require 'cucumber/core_ext/string' require 'cucumber/core_ext/proc' module Cucumber # 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 def self.snippet_text(step_keyword, step_name) escaped = Regexp.escape(step_name).gsub('\ ', ' ').gsub('/', '\/') "#{step_keyword} /^#{escaped}$/ do\nend" end class MissingProc < StandardError def message "Step definitions must always have a proc" end end attr_reader :regexp def initialize(pattern, &proc) raise MissingProc if proc.nil? if String === pattern p = pattern.gsub(/\$\w+/, '(.*)') pattern = Regexp.new("^#{p}$") end @regexp, @proc = pattern, proc end #:stopdoc: def match(step_name) case step_name when String then @regexp.match(step_name) when Regexp then @regexp == step_name end end # Formats the matched arguments of the associated Step. This method # is usually called from visitors, which render output. # # The +format+ 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 matched_args(step_name) step_name.match(@regexp).captures end def execute(step_name, 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.to_backtrace_line) raise e end end def to_backtrace_line "#{file_colon_line}:in `#{@regexp.inspect}'" end def file_colon_line @proc.file_colon_line end end end