diff --git a/lib/cucumber/rb_support/rb_dsl.rb b/lib/cucumber/rb_support/rb_dsl.rb index d6889ca76f..ff0b2b407f 100644 --- a/lib/cucumber/rb_support/rb_dsl.rb +++ b/lib/cucumber/rb_support/rb_dsl.rb @@ -23,8 +23,8 @@ def register_rb_transform(regexp, proc) @rb_language.register_rb_transform(regexp, proc) end - def register_rb_step_definition(regexp, proc) - @rb_language.register_rb_step_definition(regexp, proc) + def register_rb_step_definition(regexp, proc_or_sym, options = {}) + @rb_language.register_rb_step_definition(regexp, proc_or_sym, options) end end @@ -98,12 +98,19 @@ def AfterConfiguration(&proc) # also to the i18n translations whenever a feature of a # new language is loaded. # - # The +&proc+ gets executed in the context of a World - # object, which is defined by #World. A new World - # object is created for each scenario and is shared across - # step definitions within that scenario. - def register_rb_step_definition(regexp, &proc) - RbDsl.register_rb_step_definition(regexp, proc) + # If provided, the +symbol+ is sent to the World object + # as defined by #World. A new World object is created + # for each scenario and is shared across step definitions within + # that scenario. If the +options+ hash contains an :on + # key, the value for this is assumed to be a proc. This proc + # will be executed in the context of the World object + # and then sent the +symbol+. + # + # If no +symbol+ if provided then the +&proc+ gets executed in + # the context of the World object. + def register_rb_step_definition(regexp, symbol = nil, options = {}, &proc) + proc_or_sym = symbol || proc + RbDsl.register_rb_step_definition(regexp, proc_or_sym, options) end end end diff --git a/lib/cucumber/rb_support/rb_language.rb b/lib/cucumber/rb_support/rb_language.rb index bb59050f52..bce857783d 100644 --- a/lib/cucumber/rb_support/rb_language.rb +++ b/lib/cucumber/rb_support/rb_language.rb @@ -124,8 +124,8 @@ def register_rb_transform(regexp, proc) add_transform(RbTransform.new(self, regexp, proc)) end - def register_rb_step_definition(regexp, proc) - step_definition = RbStepDefinition.new(self, regexp, proc) + def register_rb_step_definition(regexp, proc_or_sym, options) + step_definition = RbStepDefinition.new(self, regexp, proc_or_sym, options) @step_definitions << step_definition step_definition end diff --git a/lib/cucumber/rb_support/rb_step_definition.rb b/lib/cucumber/rb_support/rb_step_definition.rb index 72d4e4bf2c..cc2e168a70 100644 --- a/lib/cucumber/rb_support/rb_step_definition.rb +++ b/lib/cucumber/rb_support/rb_step_definition.rb @@ -19,18 +19,25 @@ class RbStepDefinition class MissingProc < StandardError def message - "Step definitions must always have a proc" + "Step definitions must always have a proc or symbol" end end - def initialize(rb_language, regexp, proc) - raise MissingProc if proc.nil? + def initialize(rb_language, regexp, proc_or_sym, options) + raise MissingProc if proc_or_sym.nil? if String === regexp p = Regexp.escape(regexp) p = p.gsub(/\\\$\w+/, '(.*)') # Replace $var with (.*) regexp = Regexp.new("^#{p}$") end - @rb_language, @regexp, @proc = rb_language, regexp, proc + @rb_language, @regexp, @proc = rb_language, regexp, proc_or_sym + if @proc.kind_of? Symbol + @proc = lambda do |*args| + target = options[:on] ? instance_exec(&options[:on]) : self + target.send(proc_or_sym, *args) + end + end + @rb_language.available_step_definition(regexp_source, file_colon_line) end @@ -71,7 +78,12 @@ def backtrace_line end def file_colon_line - @proc.file_colon_line + case @proc + when Proc + @proc.file_colon_line + when Symbol + ":#{@proc}" + end end def file diff --git a/spec/cucumber/rb_support/rb_step_definition_spec.rb b/spec/cucumber/rb_support/rb_step_definition_spec.rb index 805bc63d9c..2825c50c22 100644 --- a/spec/cucumber/rb_support/rb_step_definition_spec.rb +++ b/spec/cucumber/rb_support/rb_step_definition_spec.rb @@ -44,6 +44,22 @@ module RbSupport $inside.should == 'inside' end + it "should call a method on the world when specified with a symbol" do + rb.current_world.should_receive(:with_symbol) + dsl.Given /With symbol/, :with_symbol + + support_code.step_match("With symbol").invoke(nil) + end + + it "should call a method on a specified object" do + target = double('target') + target.should_receive(:with_symbol) + rb.current_world.stub!(:target).and_return(target) + dsl.Given /With symbol on block/, :with_symbol, :on => lambda { target } + + support_code.step_match("With symbol on block").invoke(nil) + end + it "should raise Undefined when inside step is not defined" do dsl.Given /Outside/ do step 'Inside' @@ -91,7 +107,7 @@ module RbSupport end it "should have a JSON representation of the signature" do - RbStepDefinition.new(rb, /I CAN HAZ (\d+) CUKES/i, lambda{}).to_hash.should == {'source' => "I CAN HAZ (\\d+) CUKES", 'flags' => 'i'} + RbStepDefinition.new(rb, /I CAN HAZ (\d+) CUKES/i, lambda{}, {}).to_hash.should == {'source' => "I CAN HAZ (\\d+) CUKES", 'flags' => 'i'} end end end diff --git a/spec/cucumber/step_match_spec.rb b/spec/cucumber/step_match_spec.rb index a6c24fe314..fdfacf4ae9 100644 --- a/spec/cucumber/step_match_spec.rb +++ b/spec/cucumber/step_match_spec.rb @@ -12,7 +12,7 @@ module Cucumber end def stepdef(regexp) - RbSupport::RbStepDefinition.new(@rb_language, regexp, lambda{}) + RbSupport::RbStepDefinition.new(@rb_language, regexp, lambda{}, {}) end def step_match(regexp, name) @@ -66,4 +66,4 @@ def step_match(regexp, name) m.format_args("%s").should == "running 5 times 10 meters" end end -end \ No newline at end of file +end