require 'cucumber/step_match'
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\n pending\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+/, '(.*)') # Replace $var with (.*)
pattern = Regexp.new("^#{p}$")
end
@regexp, @proc = pattern, proc
end
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
def invoke(world, args, step_name)
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
#: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+ 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 matched_args(step_name)
step_name.match(@regexp).captures
end
def backtrace_line
"#{file_colon_line}:in `#{@regexp.inspect}'"
end
def file_colon_line
@proc.file_colon_line
end
def text_length
@regexp.inspect.jlength
end
def to_s(indent = 0)
@regexp.inspect + (' # ').indent(indent) + file_colon_line
end
end
end