aslakhellesoy-cucumber 0.3.95 → 0.3.96
Sign up to get free protection for your applications and to get access to all the features.
- 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})
|