aslakhellesoy-cucumber 0.3.95 → 0.3.96
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.txt +21 -0
- data/Manifest.txt +9 -3
- data/examples/sinatra/features/support/env.rb +1 -3
- data/features/cucumber_cli.feature +1 -0
- data/features/drb_server_integration.feature +56 -3
- data/features/junit_formatter.feature +23 -12
- data/features/step_definitions/cucumber_steps.rb +13 -2
- data/features/support/env.rb +19 -3
- data/lib/cucumber/ast/feature_element.rb +1 -1
- data/lib/cucumber/ast/step.rb +1 -1
- data/lib/cucumber/ast/step_invocation.rb +3 -2
- data/lib/cucumber/cli/configuration.rb +9 -25
- data/lib/cucumber/cli/drb_client.rb +7 -3
- data/lib/cucumber/cli/language_help_formatter.rb +4 -4
- data/lib/cucumber/cli/main.rb +26 -46
- data/lib/cucumber/cli/options.rb +3 -0
- data/lib/cucumber/constantize.rb +28 -0
- data/lib/cucumber/feature_file.rb +3 -3
- data/lib/cucumber/formatter/junit.rb +13 -9
- data/lib/cucumber/formatter/pretty.rb +2 -2
- data/lib/cucumber/language_support/hook_methods.rb +9 -0
- data/lib/cucumber/language_support/language_methods.rb +47 -0
- data/lib/cucumber/language_support/step_definition_methods.rb +44 -0
- data/lib/cucumber/parser/natural_language.rb +72 -0
- data/lib/cucumber/rb_support/rb_dsl.rb +73 -0
- data/lib/cucumber/rb_support/rb_hook.rb +19 -0
- data/lib/cucumber/rb_support/rb_language.rb +129 -0
- data/lib/cucumber/rb_support/rb_step_definition.rb +56 -0
- data/lib/cucumber/step_match.rb +2 -2
- data/lib/cucumber/step_mother.rb +87 -206
- data/lib/cucumber/version.rb +1 -1
- data/lib/cucumber/webrat/element_locator.rb +7 -7
- data/lib/cucumber/world.rb +28 -8
- data/rails_generators/cucumber/templates/cucumber_environment.rb +2 -2
- data/rails_generators/cucumber/templates/spork_env.rb +0 -2
- data/rails_generators/cucumber/templates/webrat_steps.rb +17 -0
- data/spec/cucumber/ast/background_spec.rb +8 -5
- data/spec/cucumber/ast/feature_factory.rb +4 -5
- data/spec/cucumber/ast/feature_spec.rb +7 -1
- data/spec/cucumber/ast/scenario_outline_spec.rb +10 -6
- data/spec/cucumber/ast/scenario_spec.rb +8 -3
- data/spec/cucumber/ast/step_collection_spec.rb +2 -2
- data/spec/cucumber/cli/configuration_spec.rb +15 -0
- data/spec/cucumber/cli/drb_client_spec.rb +35 -1
- data/spec/cucumber/cli/main_spec.rb +5 -4
- data/spec/cucumber/cli/options_spec.rb +6 -0
- data/spec/cucumber/parser/feature_parser_spec.rb +6 -5
- data/spec/cucumber/parser/table_parser_spec.rb +1 -1
- data/spec/cucumber/step_definition_spec.rb +26 -25
- data/spec/cucumber/step_mother_spec.rb +46 -41
- data/spec/cucumber/world/pending_spec.rb +4 -5
- metadata +11 -5
- data/lib/cucumber/cli/rb_step_def_loader.rb +0 -14
- data/lib/cucumber/parser/i18n/language.rb +0 -87
- data/lib/cucumber/step_definition.rb +0 -122
data/lib/cucumber/cli/options.rb
CHANGED
@@ -218,6 +218,9 @@ module Cucumber
|
|
218
218
|
opts.on(DRB_FLAG, "Run features against a DRb server. (i.e. with the spork gem)") do
|
219
219
|
@options[:drb] = true
|
220
220
|
end
|
221
|
+
opts.on("--port PORT", "Specify DRb port. Ignored without --drb") do |port|
|
222
|
+
@options[:drb_port] = port
|
223
|
+
end
|
221
224
|
opts.on_tail("--version", "Show version.") do
|
222
225
|
@out_stream.puts VERSION::STRING
|
223
226
|
Kernel.exit
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Cucumber
|
2
|
+
module Constantize
|
3
|
+
def constantize(camel_cased_word)
|
4
|
+
begin
|
5
|
+
names = camel_cased_word.split('::')
|
6
|
+
names.shift if names.empty? || names.first.empty?
|
7
|
+
|
8
|
+
constant = Object
|
9
|
+
names.each do |name|
|
10
|
+
constant = constant.const_defined?(name) ? constant.const_get(name) : constant.const_missing(name)
|
11
|
+
end
|
12
|
+
constant
|
13
|
+
rescue NameError
|
14
|
+
require underscore(camel_cased_word)
|
15
|
+
retry
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
# Snagged from active_support
|
20
|
+
def underscore(camel_cased_word)
|
21
|
+
camel_cased_word.to_s.gsub(/::/, '/').
|
22
|
+
gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
|
23
|
+
gsub(/([a-z\d])([A-Z])/,'\1_\2').
|
24
|
+
tr("-", "_").
|
25
|
+
downcase
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require 'cucumber/parser/
|
1
|
+
require 'cucumber/parser/natural_language'
|
2
2
|
require 'cucumber/filter'
|
3
3
|
|
4
4
|
module Cucumber
|
@@ -20,9 +20,9 @@ module Cucumber
|
|
20
20
|
# Parses a file and returns a Cucumber::Ast
|
21
21
|
# If +options+ contains tags, the result will
|
22
22
|
# be filtered.
|
23
|
-
def parse(options
|
23
|
+
def parse(step_mother, options)
|
24
24
|
filter = Filter.new(@lines, options)
|
25
|
-
language = Parser::
|
25
|
+
language = Parser::NaturalLanguage.get(step_mother, (lang || options[:lang] || 'en'))
|
26
26
|
language.parse(source, @path, filter)
|
27
27
|
end
|
28
28
|
|
@@ -45,8 +45,8 @@ module Cucumber
|
|
45
45
|
end
|
46
46
|
|
47
47
|
def visit_scenario_name(keyword, name, file_colon_line, source_indent)
|
48
|
-
scenario_name = name.strip
|
49
|
-
scenario_name = "Unnamed scenario" if name
|
48
|
+
scenario_name = name.strip.delete(".\r\n")
|
49
|
+
scenario_name = "Unnamed scenario" if name.blank?
|
50
50
|
@scenario = scenario_name
|
51
51
|
@outline = keyword.include?('Scenario Outline')
|
52
52
|
@output = "Scenario#{ " outline" if @outline}: #{@scenario}\n\n"
|
@@ -96,16 +96,20 @@ module Cucumber
|
|
96
96
|
@time += duration
|
97
97
|
classname = "#{@feature_name}.#{@scenario}"
|
98
98
|
name = "#{@scenario}#{suffix}"
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
99
|
+
failed = (status == :failed || (status == :pending && @options[:strict]))
|
100
|
+
#puts "FAILED:!!#{failed}"
|
101
|
+
if status == :passed || failed
|
102
|
+
@builder.testcase(:classname => classname, :name => name, :time => "%.6f" % duration) do
|
103
|
+
if failed
|
104
|
+
@builder.failure(:message => "#{status.to_s} #{name}", :type => status.to_s) do
|
105
|
+
@builder.text! @output
|
106
|
+
@builder.text!(format_exception(exception)) if exception
|
107
|
+
end
|
108
|
+
@failures += 1
|
104
109
|
end
|
105
|
-
@failures += 1
|
106
110
|
end
|
111
|
+
@tests += 1
|
107
112
|
end
|
108
|
-
@tests += 1
|
109
113
|
end
|
110
114
|
|
111
115
|
def format_exception(exception)
|
@@ -97,9 +97,9 @@ module Cucumber
|
|
97
97
|
end
|
98
98
|
|
99
99
|
def visit_examples_name(keyword, name)
|
100
|
-
names = name.empty? ? [name] : name.split("\n")
|
100
|
+
names = name.strip.empty? ? [name.strip] : name.split("\n")
|
101
101
|
@io.puts("\n #{keyword} #{names[0]}")
|
102
|
-
names[1..-1].each {|s| @io.puts " #{s}" }
|
102
|
+
names[1..-1].each {|s| @io.puts " #{s}" } unless names.empty?
|
103
103
|
@io.flush
|
104
104
|
@indent = 6
|
105
105
|
@scenario_indent = 6
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module Cucumber
|
2
|
+
module LanguageSupport
|
3
|
+
module LanguageMethods
|
4
|
+
def before(scenario)
|
5
|
+
step_mother.begin_scenario
|
6
|
+
execute_before(scenario)
|
7
|
+
end
|
8
|
+
|
9
|
+
def after(scenario)
|
10
|
+
execute_after(scenario)
|
11
|
+
step_mother.end_scenario
|
12
|
+
end
|
13
|
+
|
14
|
+
def execute_before(scenario)
|
15
|
+
step_mother.hooks_for(:before, scenario).each do |hook|
|
16
|
+
invoke(hook, 'Before', scenario, true)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def execute_after(scenario)
|
21
|
+
step_mother.hooks_for(:after, scenario).each do |hook|
|
22
|
+
invoke(hook, 'After', scenario, true)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def execute_after_step(scenario)
|
27
|
+
step_mother.hooks_for(:after_step, scenario).each do |hook|
|
28
|
+
invoke(hook, 'AfterStep', scenario, false)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def invoke(hook, location, scenario, exception_fails_scenario)
|
35
|
+
begin
|
36
|
+
hook.invoke(location, scenario)
|
37
|
+
rescue Exception => exception
|
38
|
+
if exception_fails_scenario
|
39
|
+
scenario.fail!(exception)
|
40
|
+
else
|
41
|
+
raise
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Cucumber
|
2
|
+
module LanguageSupport
|
3
|
+
module StepDefinitionMethods
|
4
|
+
def step_match(name_to_match, name_to_report)
|
5
|
+
if(match = regexp.match(name_to_match))
|
6
|
+
StepMatch.new(self, name_to_match, name_to_report, match.captures)
|
7
|
+
else
|
8
|
+
nil
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
# Formats the matched arguments of the associated Step. This method
|
13
|
+
# is usually called from visitors, which render output.
|
14
|
+
#
|
15
|
+
# The +format+ can either be a String or a Proc.
|
16
|
+
#
|
17
|
+
# If it is a String it should be a format string according to
|
18
|
+
# <tt>Kernel#sprinf</tt>, for example:
|
19
|
+
#
|
20
|
+
# '<span class="param">%s</span></tt>'
|
21
|
+
#
|
22
|
+
# If it is a Proc, it should take one argument and return the formatted
|
23
|
+
# argument, for example:
|
24
|
+
#
|
25
|
+
# lambda { |param| "[#{param}]" }
|
26
|
+
#
|
27
|
+
def format_args(step_name, format)
|
28
|
+
step_name.gzub(regexp, format)
|
29
|
+
end
|
30
|
+
|
31
|
+
def same_regexp?(regexp)
|
32
|
+
self.regexp == regexp
|
33
|
+
end
|
34
|
+
|
35
|
+
def backtrace_line
|
36
|
+
"#{file_colon_line}:in `#{regexp.inspect}'"
|
37
|
+
end
|
38
|
+
|
39
|
+
def text_length
|
40
|
+
regexp.inspect.jlength
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
module Cucumber
|
2
|
+
module Parser
|
3
|
+
class NaturalLanguage
|
4
|
+
KEYWORD_KEYS = %w{name native encoding feature background scenario scenario_outline examples given when then but}
|
5
|
+
|
6
|
+
class << self
|
7
|
+
def get(step_mother, lang)
|
8
|
+
languages[lang] ||= new(step_mother, lang)
|
9
|
+
end
|
10
|
+
|
11
|
+
def languages
|
12
|
+
@languages ||= {}
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def initialize(step_mother, lang)
|
17
|
+
@keywords = Cucumber::LANGUAGES[lang]
|
18
|
+
raise "Language not supported: #{lang.inspect}" if @keywords.nil?
|
19
|
+
@keywords['grammar_name'] = @keywords['name'].gsub(/\s/, '')
|
20
|
+
register_adverbs(step_mother) if step_mother
|
21
|
+
end
|
22
|
+
|
23
|
+
def register_adverbs(step_mother)
|
24
|
+
adverbs = %w{given when then and but}.map{|keyword| @keywords[keyword].split('|').map{|w| w.gsub(/\s/, '')}}.flatten
|
25
|
+
step_mother.register_adverbs(adverbs)
|
26
|
+
end
|
27
|
+
|
28
|
+
def parser
|
29
|
+
return @parser if @parser
|
30
|
+
i18n_tt = File.expand_path(File.dirname(__FILE__) + '/i18n.tt')
|
31
|
+
template = File.open(i18n_tt, Cucumber.file_mode('r')).read
|
32
|
+
erb = ERB.new(template)
|
33
|
+
grammar = erb.result(binding)
|
34
|
+
Treetop.load_from_string(grammar)
|
35
|
+
@parser = Parser::I18n.const_get("#{@keywords['grammar_name']}Parser").new
|
36
|
+
def @parser.inspect
|
37
|
+
"#<#{self.class.name}>"
|
38
|
+
end
|
39
|
+
@parser
|
40
|
+
end
|
41
|
+
|
42
|
+
def parse(source, path, filter)
|
43
|
+
feature = parser.parse_or_fail(source, path, filter)
|
44
|
+
feature.language = self if feature
|
45
|
+
feature
|
46
|
+
end
|
47
|
+
|
48
|
+
def keywords(key, raw=false)
|
49
|
+
return @keywords[key] if raw
|
50
|
+
return nil unless @keywords[key]
|
51
|
+
values = @keywords[key].split('|')
|
52
|
+
values.map{|value| "'#{value}'"}.join(" / ")
|
53
|
+
end
|
54
|
+
|
55
|
+
def incomplete?
|
56
|
+
KEYWORD_KEYS.detect{|key| @keywords[key].nil?}
|
57
|
+
end
|
58
|
+
|
59
|
+
def scenario_keyword
|
60
|
+
@keywords['scenario'].split('|')[0] + ':'
|
61
|
+
end
|
62
|
+
|
63
|
+
def but_keywords
|
64
|
+
@keywords['but'].split('|')
|
65
|
+
end
|
66
|
+
|
67
|
+
def and_keywords
|
68
|
+
@keywords['and'].split('|')
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require 'cucumber/rb_support/rb_hook'
|
2
|
+
|
3
|
+
module Cucumber
|
4
|
+
module RbSupport
|
5
|
+
# This module defines the methods you can use to define pure Ruby
|
6
|
+
# Step Definitions and Hooks. This module is mixed into the toplevel
|
7
|
+
# object.
|
8
|
+
module RbDsl
|
9
|
+
class << self
|
10
|
+
attr_accessor :step_mother, :rb_language
|
11
|
+
|
12
|
+
def alias_adverb(adverb)
|
13
|
+
alias_method adverb, :register_rb_step_definition
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
# Registers any number of +world_modules+ (Ruby Modules) and/or a Proc.
|
18
|
+
# The +proc+ will be executed once before each scenario to create an
|
19
|
+
# Object that the scenario's steps will run within. Any +world_modules+
|
20
|
+
# will be mixed into this Object (via Object#extend).
|
21
|
+
#
|
22
|
+
# This method is typically called from one or more Ruby scripts under
|
23
|
+
# <tt>features/support</tt>. You can call this method as many times as you
|
24
|
+
# like (to register more modules), but if you try to register more than
|
25
|
+
# one Proc you will get an error.
|
26
|
+
#
|
27
|
+
# Cucumber will not yield anything to the +proc+. Examples:
|
28
|
+
#
|
29
|
+
# World do
|
30
|
+
# MyClass.new
|
31
|
+
# end
|
32
|
+
#
|
33
|
+
# World(MyModule)
|
34
|
+
#
|
35
|
+
def World(*world_modules, &proc)
|
36
|
+
RbDsl.rb_language.build_world_factory(*world_modules, &proc)
|
37
|
+
end
|
38
|
+
|
39
|
+
# Registers a Before proc. You can call this method as many times as you
|
40
|
+
# want (typically from ruby scripts under <tt>support</tt>).
|
41
|
+
def Before(*tag_names, &proc)
|
42
|
+
RbDsl.step_mother.register_hook(:before, RbHook.new(RbDsl.rb_language, tag_names, proc))
|
43
|
+
end
|
44
|
+
|
45
|
+
def After(*tag_names, &proc)
|
46
|
+
RbDsl.step_mother.register_hook(:after, RbHook.new(RbDsl.rb_language, tag_names, proc))
|
47
|
+
end
|
48
|
+
|
49
|
+
def AfterStep(*tag_names, &proc)
|
50
|
+
RbDsl.step_mother.register_hook(:after_step, RbHook.new(RbDsl.rb_language, tag_names, proc))
|
51
|
+
end
|
52
|
+
|
53
|
+
# Registers a new Ruby StepDefinition.
|
54
|
+
# This method is aliased
|
55
|
+
# to <tt>Given</tt>, <tt>When</tt> and <tt>Then</tt>, and
|
56
|
+
# also to the i18n translations whenever a feature of a
|
57
|
+
# new language is loaded.
|
58
|
+
#
|
59
|
+
# See Cucumber#alias_steps for details on how to
|
60
|
+
# create your own aliases.
|
61
|
+
#
|
62
|
+
# The +&proc+ gets executed in the context of a <tt>world</tt>
|
63
|
+
# object, which is defined by #World. A new <tt>world</tt>
|
64
|
+
# object is created for each scenario and is shared across
|
65
|
+
# step definitions within that scenario.
|
66
|
+
def register_rb_step_definition(regexp, &proc)
|
67
|
+
RbDsl.step_mother.register_step_definition(RbStepDefinition.new(RbDsl.rb_language, regexp, &proc))
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
extend(Cucumber::RbSupport::RbDsl)
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Cucumber
|
2
|
+
module RbSupport
|
3
|
+
class RbHook
|
4
|
+
include LanguageSupport::HookMethods
|
5
|
+
|
6
|
+
attr_reader :tag_names
|
7
|
+
|
8
|
+
def initialize(rb_language, tag_names, proc)
|
9
|
+
@rb_language = rb_language
|
10
|
+
@tag_names = tag_names
|
11
|
+
@proc = proc
|
12
|
+
end
|
13
|
+
|
14
|
+
def invoke(location, scenario)
|
15
|
+
@rb_language.current_world.cucumber_instance_exec(false, location, scenario, &@proc)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,129 @@
|
|
1
|
+
require 'cucumber/rb_support/rb_dsl'
|
2
|
+
require 'cucumber/rb_support/rb_step_definition'
|
3
|
+
|
4
|
+
module Cucumber
|
5
|
+
module RbSupport
|
6
|
+
class NilWorld < StandardError
|
7
|
+
def initialize
|
8
|
+
super("World procs should never return nil")
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
class MultipleWorld < StandardError
|
13
|
+
def initialize(first_proc, second_proc)
|
14
|
+
message = "You can only pass a proc to #World once, but it's happening\n"
|
15
|
+
message << "in 2 places:\n\n"
|
16
|
+
message << first_proc.backtrace_line('World') << "\n"
|
17
|
+
message << second_proc.backtrace_line('World') << "\n\n"
|
18
|
+
message << "Use Ruby modules instead to extend your worlds. See the Cucumber::StepMother#World RDoc\n"
|
19
|
+
message << "or http://wiki.github.com/aslakhellesoy/cucumber/a-whole-new-world.\n\n"
|
20
|
+
super(message)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
class RbLanguage
|
25
|
+
include LanguageSupport::LanguageMethods
|
26
|
+
attr_reader :current_world, :step_mother
|
27
|
+
|
28
|
+
def initialize(step_mother)
|
29
|
+
@step_mother = step_mother
|
30
|
+
RbDsl.step_mother = step_mother
|
31
|
+
RbDsl.rb_language = self
|
32
|
+
end
|
33
|
+
|
34
|
+
def load_step_def_file(step_def_file)
|
35
|
+
begin
|
36
|
+
require step_def_file
|
37
|
+
rescue LoadError => e
|
38
|
+
e.message << "\nFailed to load #{step_def_file}"
|
39
|
+
raise e
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def build_world_factory(*world_modules, &proc)
|
44
|
+
if(proc)
|
45
|
+
raise MultipleWorld.new(@world_proc, proc) if @world_proc
|
46
|
+
@world_proc = proc
|
47
|
+
end
|
48
|
+
@world_modules ||= []
|
49
|
+
@world_modules += world_modules
|
50
|
+
end
|
51
|
+
|
52
|
+
def begin_scenario
|
53
|
+
create_world
|
54
|
+
extend_world
|
55
|
+
connect_world(@step_mother)
|
56
|
+
end
|
57
|
+
|
58
|
+
def end_scenario
|
59
|
+
@current_world = nil
|
60
|
+
end
|
61
|
+
|
62
|
+
def snippet_text(step_keyword, step_name, multiline_arg_class = nil)
|
63
|
+
escaped = Regexp.escape(step_name).gsub('\ ', ' ').gsub('/', '\/')
|
64
|
+
escaped = escaped.gsub(PARAM_PATTERN, ESCAPED_PARAM_PATTERN)
|
65
|
+
|
66
|
+
n = 0
|
67
|
+
block_args = escaped.scan(ESCAPED_PARAM_PATTERN).map do |a|
|
68
|
+
n += 1
|
69
|
+
"arg#{n}"
|
70
|
+
end
|
71
|
+
block_args << multiline_arg_class.default_arg_name unless multiline_arg_class.nil?
|
72
|
+
block_arg_string = block_args.empty? ? "" : " |#{block_args.join(", ")}|"
|
73
|
+
multiline_class_comment = ""
|
74
|
+
if(multiline_arg_class == Ast::Table)
|
75
|
+
multiline_class_comment = "# #{multiline_arg_class.default_arg_name} is a #{multiline_arg_class.to_s}\n "
|
76
|
+
end
|
77
|
+
|
78
|
+
"#{step_keyword} /^#{escaped}$/ do#{block_arg_string}\n #{multiline_class_comment}pending\nend"
|
79
|
+
end
|
80
|
+
|
81
|
+
def alias_adverbs(adverbs)
|
82
|
+
adverbs.each do |adverb|
|
83
|
+
RbDsl.alias_adverb(adverb)
|
84
|
+
World.alias_adverb(adverb)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
private
|
89
|
+
|
90
|
+
PARAM_PATTERN = /"([^\"]*)"/
|
91
|
+
ESCAPED_PARAM_PATTERN = '"([^\\"]*)"'
|
92
|
+
|
93
|
+
def create_world
|
94
|
+
if(@world_proc)
|
95
|
+
@current_world = @world_proc.call
|
96
|
+
check_nil(@current_world, @world_proc)
|
97
|
+
else
|
98
|
+
@current_world = Object.new
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def extend_world
|
103
|
+
@current_world.extend(World)
|
104
|
+
@current_world.extend(::Spec::Matchers) if defined?(::Spec::Matchers)
|
105
|
+
(@world_modules || []).each do |mod|
|
106
|
+
@current_world.extend(mod)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def connect_world(step_mother)
|
111
|
+
@current_world.__cucumber_step_mother = step_mother
|
112
|
+
end
|
113
|
+
|
114
|
+
def check_nil(o, proc)
|
115
|
+
if o.nil?
|
116
|
+
begin
|
117
|
+
raise NilWorld.new
|
118
|
+
rescue NilWorld => e
|
119
|
+
e.backtrace.clear
|
120
|
+
e.backtrace.push(proc.backtrace_line("World"))
|
121
|
+
raise e
|
122
|
+
end
|
123
|
+
else
|
124
|
+
o
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'cucumber/step_match'
|
2
|
+
require 'cucumber/core_ext/string'
|
3
|
+
require 'cucumber/core_ext/proc'
|
4
|
+
|
5
|
+
module Cucumber
|
6
|
+
# A Step Definition holds a Regexp and a Proc, and is created
|
7
|
+
# by calling <tt>Given</tt>, <tt>When</tt> or <tt>Then</tt>
|
8
|
+
# in the <tt>step_definitions</tt> ruby files - for example:
|
9
|
+
#
|
10
|
+
# Given /I have (\d+) cucumbers in my belly/ do
|
11
|
+
# # some code here
|
12
|
+
# end
|
13
|
+
#
|
14
|
+
class RbStepDefinition
|
15
|
+
include LanguageSupport::StepDefinitionMethods
|
16
|
+
|
17
|
+
class MissingProc < StandardError
|
18
|
+
def message
|
19
|
+
"Step definitions must always have a proc"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
attr_reader :proc
|
24
|
+
|
25
|
+
def initialize(rb_language, pattern, &proc)
|
26
|
+
raise MissingProc if proc.nil?
|
27
|
+
if String === pattern
|
28
|
+
p = pattern.gsub(/\$\w+/, '(.*)') # Replace $var with (.*)
|
29
|
+
pattern = Regexp.new("^#{p}$")
|
30
|
+
end
|
31
|
+
@rb_language, @regexp, @proc = rb_language, pattern, proc
|
32
|
+
end
|
33
|
+
|
34
|
+
def regexp
|
35
|
+
@regexp
|
36
|
+
end
|
37
|
+
|
38
|
+
def invoke(args)
|
39
|
+
args = args.map{|arg| Ast::PyString === arg ? arg.to_s : arg}
|
40
|
+
begin
|
41
|
+
@rb_language.current_world.cucumber_instance_exec(true, regexp.inspect, *args, &@proc)
|
42
|
+
rescue Cucumber::ArityMismatchError => e
|
43
|
+
e.backtrace.unshift(self.backtrace_line)
|
44
|
+
raise e
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def file_colon_line
|
49
|
+
@proc.file_colon_line
|
50
|
+
end
|
51
|
+
|
52
|
+
def file
|
53
|
+
@file ||= file_colon_line.split(':')[0]
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
data/lib/cucumber/step_match.rb
CHANGED
@@ -10,10 +10,10 @@ module Cucumber
|
|
10
10
|
@formatted_step_name
|
11
11
|
end
|
12
12
|
|
13
|
-
def invoke(
|
13
|
+
def invoke(multiline_arg)
|
14
14
|
all_args = @args.dup
|
15
15
|
all_args << multiline_arg if multiline_arg
|
16
|
-
@step_definition.invoke(
|
16
|
+
@step_definition.invoke(all_args)
|
17
17
|
end
|
18
18
|
|
19
19
|
def format_args(format = lambda{|a| a})
|