# cucumber/cucumber

### Subversion checkout URL

You can clone with
or
.

Merge branch 'v8' of git://github.com/josephwilk/cucumber into v8

commit 8a6b1911c6585d13252237d1241dc61e20143782 2 parents fe84167 + 63ef261
aslakhellesoy authored
11 examples/javascript/features/fibonacci.feature
 @@ -18,10 +18,12 @@ Feature: Fibonacci | 100 | [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89] | Scenario: Single series tested via a PyString - When I ask Javascript to calculate fibonacci up to 2 + When I ask Javascript to calculate fibonacci up to 2 with formatting Then it should give me: """ - [1, 1] + + '[1, 1]' + """ Scenario: Single series tested via a Step Table @@ -33,4 +35,7 @@ Feature: Fibonacci @do-fibonnacci-in-before-hook Scenario: Single series with Before hook with a tag label - Then it should give me [1, 1, 2] + Then it should give me [1, 1, 2] + + Scenario: Single series by calling a step from within a step + Then it should give me [1, 1] via calling another step definition
4 examples/javascript/features/lib/fibonacci.js
 @@ -12,4 +12,8 @@ var fibonacciSeries = function(fibonacciLimit) { i++; } return "[" + result.join(", ") + "]"; +} + +var fibonacciSeriesFormatted = function(fibonacciLimit){ + return "\n'" + fibonacciSeries(fibonacciLimit) + "'\n" }
18 examples/javascript/features/step_definitions/fib_steps.js
 @@ -10,9 +10,18 @@ After(function(){ //throw 'Sabotage scenario'; }); +Transform(/^(\d+)\$/, function(n){ + return parseInt(n); +}); + When(/^I ask Javascript to calculate fibonacci up to (\d+)\$/, function(n){ assertEqual(0, fibResult) - fibResult = fibonacciSeries(parseInt(n)); + fibResult = fibonacciSeries(n); +}); + +When(/^I ask Javascript to calculate fibonacci up to (\d+) with formatting\$/, function(n){ + assertEqual(0, fibResult) + fibResult = fibonacciSeriesFormatted(n); }); Then(/^it should give me (\[.*\])\$/, function(expectedResult){ @@ -28,3 +37,10 @@ Then(/^it should contain:\$/, function(table){ assertMatches(hashes[0]['cell 1'], fibResult); assertMatches(hashes[0]['cell 2'], fibResult); }); + + +Then(/^it should give me (\[.*\]) via calling another step definition\$/, function(expectedResult){ + Given("I ask Javascript to calculate fibonacci up to 2"); + assertEqual(expectedResult, fibResult); +}); +
20 lib/cucumber/js_support/js_dsl.js
 @@ -1,14 +1,23 @@ var CucumberJsDsl = { registerStepDefinition: function(regexp, func) { - jsLanguage.addStepDefinition(regexp, func); + if(func == null){ + jsLanguage.executeStepDefinition(regexp); + } + else{ + jsLanguage.addStepDefinition(regexp, func); + } + }, + + registerTransform: function(regexp, func){ + jsLanguage.registerJsTransform(regexp, func); }, beforeHook: function(tag_or_func, func){ - CucumberJsDsl.__registerJsHook('before', tag_or_func, func) + CucumberJsDsl.__registerJsHook('before', tag_or_func, func); }, afterHook: function(tag_or_func, func){ - CucumberJsDsl.__registerJsHook('after', tag_or_func, func) + CucumberJsDsl.__registerJsHook('after', tag_or_func, func); }, Table: function(raw_table){ @@ -17,8 +26,8 @@ var CucumberJsDsl = { __registerJsHook: function(label, tag_or_func, func){ if(func != null){ - var hook_func = func - var tag = tag_or_func + var hook_func = func; + var tag = tag_or_func; } else{ var hook_func = tag_or_func; @@ -58,3 +67,4 @@ var Then = CucumberJsDsl.registerStepDefinition; var Before = CucumberJsDsl.beforeHook; var After = CucumberJsDsl.afterHook; +var Transform = CucumberJsDsl.registerTransform;
34 lib/cucumber/js_support/js_language.rb
 @@ -5,6 +5,11 @@ module Cucumber module JsSupport + def self.argument_safe_string(string) + arg_string = string.to_s.gsub(/[']/, '\\\\\'') + "'#{arg_string.gsub("\n", '\n')}'" + end + class JsWorld def initialize @world = V8::Context.new @@ -15,7 +20,7 @@ def execute(js_function, args=[]) if arg.is_a?(Ast::Table) "new CucumberJsDsl.Table(#{arg.raw.inspect})" else - "'#{arg}'" + JsSupport.argument_safe_string(arg) end end @@ -33,6 +38,7 @@ def initialize(js_language, regexp, js_function) end def invoke(args) + args = @js_language.execute_transforms(args) @js_language.current_world.execute(@js_function, args) end @@ -65,6 +71,22 @@ def invoke(location, scenario) end end + class JsTransform + def initialize(js_language, regexp, js_function) + @js_language, @regexp, @js_function = js_language, regexp.ToString, js_function + end + + def match(arg) + arg = JsSupport.argument_safe_string(arg) + matches = eval_js "#{@regexp}.exec(#{arg});" + matches ? matches[1..-1] : nil + end + + def invoke(arg) + @js_language.current_world.execute(@js_function, [arg]) + end + end + class JsArg def initialize(arg) @arg = arg @@ -85,6 +107,7 @@ class JsLanguage def initialize(step_mother) @step_definitions = [] @world = JsWorld.new + @step_mother = step_mother @world["jsLanguage"] = self @world.load(File.dirname(__FILE__) + '/js_dsl.js') @@ -117,12 +140,21 @@ def add_step_definition(regexp, js_function) @step_definitions << JsStepDefinition.new(self, regexp, js_function) end + #TODO: support multiline arguments when calling steps from within steps + def execute_step_definition(name, multiline_argument = nil) + @step_mother.step_match(name).invoke(multiline_argument) + end + #TODO: support multiple tag_names def register_js_hook(phase, js_function, tag_name = nil) tag_names = tag_name ? [tag_name] : [] add_hook(phase, JsHook.new(self, tag_names, js_function)) end + def register_js_transform(regexp, js_function) + add_transform(JsTransform.new(self, regexp, js_function)) + end + def current_world @world end