require 'cucumber/step_match' require 'cucumber/core_ext/string' require 'cucumber/core_ext/proc' module Cucumber module StepDefinitionMethods def step_match(name_to_match, name_to_report) if(match = name_to_match.match(regexp)) StepMatch.new(self, name_to_match, name_to_report, match.captures) else nil end end # Formats the matched arguments of the associated Step. This method # is usually called from visitors, which render output. # # The +format+ can either be a String or a Proc. # # If it is a String it should be a format string according to # Kernel#sprinf, for example: # # '%s' # # If it is a Proc, it should take one argument and return the formatted # argument, for example: # # lambda { |param| "[#{param}]" } # def format_args(step_name, format) step_name.gzub(regexp, format) end def match(step_name) case step_name when String then regexp.match(step_name) when Regexp then regexp == step_name end end def backtrace_line "#{file_colon_line}:in `#{regexp.inspect}'" end def text_length regexp.inspect.jlength end end # A Step Definition holds a Regexp and a Proc, and is created # by calling Given, When or Then # in the step_definitions ruby files - for example: # # Given /I have (\d+) cucumbers in my belly/ do # # some code here # end # class StepDefinition PARAM_PATTERN = /"([^\"]*)"/ ESCAPED_PARAM_PATTERN = '"([^\\"]*)"' def self.snippet_text(step_keyword, step_name, multiline_arg_class = nil) escaped = Regexp.escape(step_name).gsub('\ ', ' ').gsub('/', '\/') escaped = escaped.gsub(PARAM_PATTERN, ESCAPED_PARAM_PATTERN) n = 0 block_args = escaped.scan(ESCAPED_PARAM_PATTERN).map do |a| n += 1 "arg#{n}" end block_args << multiline_arg_class.default_arg_name unless multiline_arg_class.nil? block_arg_string = block_args.empty? ? "" : " |#{block_args.join(", ")}|" multiline_class_string = multiline_arg_class ? "# #{multiline_arg_class.default_arg_name} is a #{multiline_arg_class.to_s}\n " : "" "#{step_keyword} /^#{escaped}$/ do#{block_arg_string}\n #{multiline_class_string}pending\nend" end class MissingProc < StandardError def message "Step definitions must always have a proc" end end include StepDefinitionMethods def initialize(pattern, &proc) raise MissingProc if proc.nil? if String === pattern p = pattern.gsub(/\$\w+/, '(.*)') # Replace $var with (.*) pattern = Regexp.new("^#{p}$") end @regexp, @proc = pattern, proc end def regexp @regexp end def invoke(world, args) args = args.map{|arg| Ast::PyString === arg ? arg.to_s : arg} begin world.cucumber_instance_exec(true, regexp.inspect, *args, &@proc) rescue Cucumber::ArityMismatchError => e e.backtrace.unshift(self.backtrace_line) raise e end end def file_colon_line @proc.file_colon_line end end end