cucumber 0.2.3 → 0.3.0
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 +56 -1
- data/Manifest.txt +70 -49
- data/config/hoe.rb +1 -1
- data/cucumber.yml +1 -1
- data/examples/i18n/bg/Rakefile +6 -0
- data/examples/i18n/bg/features/addition.feature +11 -0
- data/examples/i18n/bg/features/consecutive_calculations.feature +18 -0
- data/examples/i18n/bg/features/division.feature +16 -0
- data/examples/i18n/bg/features/step_definitons/calculator_steps.rb +24 -0
- data/examples/i18n/bg/features/support/env.rb +6 -0
- data/examples/i18n/bg/features/support/world.rb +8 -0
- data/examples/i18n/bg/lib/calculator.rb +24 -0
- data/examples/i18n/ru/features/support/world.rb +4 -3
- data/examples/i18n/sk/Rakefile +6 -0
- data/examples/i18n/sk/features/addition.feature +16 -0
- data/examples/i18n/sk/features/division.feature +9 -0
- data/examples/i18n/sk/features/step_definitons/calculator_steps.rb +24 -0
- data/examples/i18n/sk/lib/calculator.rb +14 -0
- data/examples/self_test/features/background/background_with_name.feature +7 -0
- data/examples/self_test/features/background/passing_background.feature +2 -2
- data/examples/self_test/features/step_definitions/sample_steps.rb +18 -2
- data/examples/self_test/features/undefined_multiline_args.feature +12 -0
- data/examples/sinatra/features/support/env.rb +2 -6
- data/examples/test_unit/features/step_definitions/test_unit_steps.rb +1 -4
- data/examples/tickets/Rakefile +1 -1
- data/examples/tickets/features/229/tagged_hooks.feature +8 -0
- data/examples/tickets/features/229/tagged_hooks.rb +14 -0
- data/examples/tickets/features/270/back.feature +14 -0
- data/examples/tickets/features/270/back.steps.rb +14 -0
- data/examples/tickets/features/279/py_string_indent.feature +25 -0
- data/examples/tickets/features/279/py_string_indent.steps.rb +12 -0
- data/examples/tickets/features/279/wrong.feature_ +11 -0
- data/examples/tickets/features/step_definitons/tickets_steps.rb +0 -7
- data/features/background.feature +21 -3
- data/features/cucumber_cli.feature +18 -5
- data/features/cucumber_cli_outlines.feature +4 -1
- data/features/rake_task.feature +132 -0
- data/features/snippet.feature +23 -0
- data/features/step_definitions/cucumber_steps.rb +46 -15
- data/features/support/env.rb +61 -4
- data/features/usage.feature +5 -0
- data/gem_tasks/deployment.rake +1 -1
- data/lib/cucumber/ast/background.rb +14 -4
- data/lib/cucumber/ast/examples.rb +0 -12
- data/lib/cucumber/ast/feature.rb +2 -12
- data/lib/cucumber/ast/feature_element.rb +4 -8
- data/lib/cucumber/ast/features.rb +1 -1
- data/lib/cucumber/ast/outline_table.rb +20 -20
- data/lib/cucumber/ast/py_string.rb +6 -11
- data/lib/cucumber/ast/scenario.rb +1 -8
- data/lib/cucumber/ast/scenario_outline.rb +1 -11
- data/lib/cucumber/ast/step.rb +3 -9
- data/lib/cucumber/ast/step_collection.rb +0 -4
- data/lib/cucumber/ast/step_invocation.rb +5 -6
- data/lib/cucumber/ast/table.rb +5 -22
- data/lib/cucumber/ast/tags.rb +9 -9
- data/lib/cucumber/ast/visitor.rb +12 -25
- data/lib/cucumber/cli/configuration.rb +4 -4
- data/lib/cucumber/cli/main.rb +10 -3
- data/lib/cucumber/core_ext/instance_exec.rb +17 -4
- data/lib/cucumber/formatter/ansicolor.rb +1 -1
- data/lib/cucumber/formatter/console.rb +2 -1
- data/lib/cucumber/formatter/html.rb +21 -7
- data/lib/cucumber/formatter/pretty.rb +27 -20
- data/lib/cucumber/formatter/usage.rb +16 -0
- data/lib/cucumber/languages.yml +23 -5
- data/lib/cucumber/parser/feature.rb +231 -114
- data/lib/cucumber/parser/feature.tt +120 -25
- data/lib/cucumber/parser/table.rb +37 -25
- data/lib/cucumber/parser/table.tt +15 -3
- data/lib/cucumber/parser/treetop_ext.rb +48 -9
- data/lib/cucumber/rake/task.rb +29 -6
- data/lib/cucumber/step_definition.rb +4 -2
- data/lib/cucumber/step_mother.rb +143 -26
- data/lib/cucumber/version.rb +2 -2
- data/rails_generators/cucumber/templates/paths.rb +13 -4
- data/rails_generators/cucumber/templates/webrat_steps.rb +16 -0
- data/{specs → spec}/cucumber/ast/background_spec.rb +1 -0
- data/{specs → spec}/cucumber/ast/feature_factory.rb +1 -1
- data/{specs → spec}/cucumber/ast/feature_spec.rb +2 -2
- data/{specs → spec}/cucumber/ast/py_string_spec.rb +0 -0
- data/{specs → spec}/cucumber/ast/scenario_outline_spec.rb +0 -0
- data/{specs → spec}/cucumber/ast/scenario_spec.rb +0 -27
- data/{specs → spec}/cucumber/ast/step_collection_spec.rb +0 -0
- data/{specs → spec}/cucumber/ast/step_spec.rb +0 -0
- data/{specs → spec}/cucumber/ast/table_spec.rb +2 -2
- data/{specs → spec}/cucumber/broadcaster_spec.rb +0 -0
- data/{specs → spec}/cucumber/cli/configuration_spec.rb +0 -0
- data/{specs → spec}/cucumber/cli/main_spec.rb +5 -1
- data/spec/cucumber/core_ext/proc_spec.rb +54 -0
- data/{specs → spec}/cucumber/core_ext/string_spec.rb +0 -0
- data/{specs → spec}/cucumber/formatter/ansicolor_spec.rb +0 -0
- data/{specs → spec}/cucumber/formatter/color_io_spec.rb +0 -0
- data/{specs → spec}/cucumber/formatter/html/cucumber.css +0 -0
- data/{specs → spec}/cucumber/formatter/html/cucumber.js +0 -0
- data/{specs → spec}/cucumber/formatter/html/index.html +0 -0
- data/{specs → spec}/cucumber/formatter/html/jquery-1.3.min.js +0 -0
- data/{specs → spec}/cucumber/formatter/html/jquery.uitableedit.js +0 -0
- data/{specs → spec}/cucumber/formatters/profile_formatter_spec.rb +0 -0
- data/{specs → spec}/cucumber/parser/feature_parser_spec.rb +43 -41
- data/{specs → spec}/cucumber/parser/table_parser_spec.rb +0 -0
- data/{specs → spec}/cucumber/rails/stubs/mini_rails.rb +0 -0
- data/{specs → spec}/cucumber/rails/stubs/test_help.rb +0 -0
- data/{specs → spec}/cucumber/rails/world_spec.rb +0 -0
- data/{specs → spec}/cucumber/sell_cucumbers.feature +0 -0
- data/{specs → spec}/cucumber/step_definition_spec.rb +0 -0
- data/{specs → spec}/cucumber/step_mother_spec.rb +63 -4
- data/{specs → spec}/cucumber/treetop_parser/empty_feature.feature +0 -0
- data/{specs → spec}/cucumber/treetop_parser/empty_scenario.feature +0 -0
- data/{specs → spec}/cucumber/treetop_parser/empty_scenario_outline.feature +0 -0
- data/{specs → spec}/cucumber/treetop_parser/fit_scenario.feature +0 -0
- data/{specs → spec}/cucumber/treetop_parser/given_scenario.feature +0 -0
- data/{specs → spec}/cucumber/treetop_parser/invalid_scenario_outlines.feature +0 -0
- data/{specs → spec}/cucumber/treetop_parser/multiline_steps.feature +0 -0
- data/{specs → spec}/cucumber/treetop_parser/multiple_tables.feature +0 -0
- data/{specs → spec}/cucumber/treetop_parser/scenario_outline.feature +0 -0
- data/{specs → spec}/cucumber/treetop_parser/spaces.feature +0 -0
- data/{specs → spec}/cucumber/treetop_parser/test_dos.feature +0 -0
- data/{specs → spec}/cucumber/treetop_parser/with_comments.feature +0 -0
- data/{specs → spec}/cucumber/treetop_parser/with_tags.feature +0 -0
- data/{specs → spec}/cucumber/world/pending_spec.rb +0 -0
- data/{specs → spec}/spec.opts +0 -0
- data/{specs → spec}/spec_helper.rb +2 -11
- metadata +72 -51
- data/examples/tickets/cucumber.yml +0 -3
- data/lib/cucumber/parser/basic.rb +0 -0
- data/specs/cucumber/ast/tags_spec.rb +0 -19
- data/specs/cucumber/core_ext/proc_spec.rb +0 -37
|
@@ -10,18 +10,30 @@ module Cucumber
|
|
|
10
10
|
|
|
11
11
|
rule table
|
|
12
12
|
table_row+ {
|
|
13
|
-
def
|
|
13
|
+
def at_line?(line)
|
|
14
|
+
elements.detect{|table_row| table_row.at_line?(line)}
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def build(filter=nil)
|
|
14
18
|
Ast::Table.new(raw)
|
|
15
19
|
end
|
|
16
20
|
|
|
17
|
-
def raw
|
|
18
|
-
elements.map
|
|
21
|
+
def raw(filter=nil, scenario_outline=nil)
|
|
22
|
+
elements.map do |table_row|
|
|
23
|
+
if(filter.nil? || table_row == elements[0] || filter.at_line?(table_row) || (scenario_outline && filter.outline_at_line?(scenario_outline)))
|
|
24
|
+
table_row.build
|
|
25
|
+
end
|
|
26
|
+
end.compact
|
|
19
27
|
end
|
|
20
28
|
}
|
|
21
29
|
end
|
|
22
30
|
|
|
23
31
|
rule table_row
|
|
24
32
|
space* '|' cells:(cell '|')+ space* (eol+ / eof) {
|
|
33
|
+
def at_line?(line)
|
|
34
|
+
cells.line == line
|
|
35
|
+
end
|
|
36
|
+
|
|
25
37
|
def build
|
|
26
38
|
row = cells.elements.map do |elt|
|
|
27
39
|
value = elt.cell.text_value.strip
|
|
@@ -12,37 +12,76 @@ end
|
|
|
12
12
|
|
|
13
13
|
module Cucumber
|
|
14
14
|
module Parser
|
|
15
|
-
|
|
15
|
+
class Filter
|
|
16
|
+
def initialize(lines, options)
|
|
17
|
+
@lines = lines
|
|
18
|
+
@include_tags = options[:include_tags] || []
|
|
19
|
+
@exclude_tags = options[:exclude_tags] || []
|
|
20
|
+
@names = options[:scenario_names] || []
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def accept?(syntax_node)
|
|
24
|
+
at_line?(syntax_node) &&
|
|
25
|
+
matches_tags?(syntax_node) &&
|
|
26
|
+
matches_names?(syntax_node)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def at_line?(syntax_node)
|
|
30
|
+
@lines.nil? || @lines.empty? || @lines.detect{|line| syntax_node.at_line?(line)}
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def outline_at_line?(syntax_node)
|
|
34
|
+
@lines.nil? || @lines.empty? || @lines.detect{|line| syntax_node.outline_at_line?(line)}
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def matches_tags?(syntax_node)
|
|
38
|
+
!excluded_by_tags?(syntax_node) &&
|
|
39
|
+
included_by_tags?(syntax_node)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def included_by_tags?(syntax_node)
|
|
43
|
+
@include_tags.empty? || syntax_node.has_tags?(@include_tags)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def excluded_by_tags?(syntax_node)
|
|
47
|
+
@exclude_tags.any? && syntax_node.has_tags?(@exclude_tags)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def matches_names?(syntax_node)
|
|
51
|
+
@names.nil? || @names.empty? || @names.detect{|name| syntax_node.matches_name?(name)}
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
module TreetopExt
|
|
16
56
|
FILE_COLON_LINE_PATTERN = /^([\w\W]*?):([\d:]+)$/
|
|
17
57
|
|
|
18
58
|
# Parses a file and returns a Cucumber::Ast
|
|
19
|
-
def parse_file(file)
|
|
59
|
+
def parse_file(file, options)
|
|
20
60
|
_, path, lines = *FILE_COLON_LINE_PATTERN.match(file)
|
|
21
61
|
if path
|
|
22
62
|
lines = lines.split(':').map { |line| line.to_i }
|
|
23
63
|
else
|
|
24
64
|
path = file
|
|
25
|
-
lines = []
|
|
26
65
|
end
|
|
66
|
+
filter = Filter.new(lines, options)
|
|
27
67
|
|
|
28
|
-
loader = lambda { |io| parse_or_fail(io.read, path) }
|
|
68
|
+
loader = lambda { |io| parse_or_fail(io.read, filter, path) }
|
|
29
69
|
feature = if path =~ /^http/
|
|
30
70
|
require 'open-uri'
|
|
31
71
|
open(path, &loader)
|
|
32
72
|
else
|
|
33
73
|
File.open(path, Cucumber.file_mode('r'), &loader)
|
|
34
74
|
end
|
|
35
|
-
feature.lines = lines
|
|
36
75
|
feature
|
|
37
76
|
end
|
|
38
77
|
|
|
39
|
-
def parse_or_fail(
|
|
40
|
-
parse_tree = parse(
|
|
78
|
+
def parse_or_fail(string, filter=nil, file=nil, line_offset=0)
|
|
79
|
+
parse_tree = parse(string)
|
|
41
80
|
if parse_tree.nil?
|
|
42
81
|
raise Cucumber::Parser::SyntaxError.new(self, file, line_offset)
|
|
43
82
|
else
|
|
44
|
-
ast = parse_tree.build
|
|
45
|
-
ast.file = file
|
|
83
|
+
ast = parse_tree.build(filter) # may return nil if it doesn't match filter.
|
|
84
|
+
ast.file = file unless ast.nil?
|
|
46
85
|
ast
|
|
47
86
|
end
|
|
48
87
|
end
|
data/lib/cucumber/rake/task.rb
CHANGED
|
@@ -27,26 +27,45 @@ module Cucumber
|
|
|
27
27
|
class Task
|
|
28
28
|
LIB = File.expand_path(File.dirname(__FILE__) + '/../..') # :nodoc:
|
|
29
29
|
|
|
30
|
+
# TODO: remove depreated accessors for 0.4.0
|
|
31
|
+
def self.deprecate_accessor(attribute) # :nodoc:
|
|
32
|
+
attr_reader attribute
|
|
33
|
+
class_eval <<-EOF, __FILE__, __LINE__ + 1
|
|
34
|
+
def #{attribute}=(value)
|
|
35
|
+
@#{attribute} = value
|
|
36
|
+
warn("Cucumber::Rake::Task##{attribute} is deprecated and will be removed in 0.4.0. Please use profiles for complex settings: http://wiki.github.com/aslakhellesoy/cucumber/using-rake#profiles")
|
|
37
|
+
end
|
|
38
|
+
EOF
|
|
39
|
+
end
|
|
40
|
+
|
|
30
41
|
# Directories to add to the Ruby $LOAD_PATH
|
|
31
42
|
attr_accessor :libs
|
|
32
43
|
# Name of the cucumber binary to use for running features. Defaults to Cucumber::BINARY
|
|
33
44
|
attr_accessor :binary
|
|
34
45
|
# Array of paths to specific step definition files to use
|
|
35
|
-
|
|
46
|
+
deprecate_accessor :step_list
|
|
36
47
|
# File pattern for finding step definitions. Defaults to
|
|
37
48
|
# 'features/**/*.rb'.
|
|
38
|
-
|
|
49
|
+
deprecate_accessor :step_pattern
|
|
39
50
|
# Array of paths to specific features to run.
|
|
40
|
-
|
|
51
|
+
deprecate_accessor :feature_list
|
|
41
52
|
# File pattern for finding features to run. Defaults to
|
|
42
|
-
# 'features/**/*.feature'. Can be
|
|
43
|
-
|
|
53
|
+
# 'features/**/*.feature'. Can be overridden by the FEATURE environment variable.
|
|
54
|
+
deprecate_accessor :feature_pattern
|
|
44
55
|
# Extra options to pass to the cucumber binary. Can be overridden by the CUCUMBER_OPTS environment variable.
|
|
45
56
|
attr_accessor :cucumber_opts
|
|
46
57
|
# Run cucumber with RCov?
|
|
47
58
|
attr_accessor :rcov
|
|
48
59
|
# Extra options to pass to rcov
|
|
49
60
|
attr_accessor :rcov_opts
|
|
61
|
+
# Define what profile to be used. When used with cucumber_opts it is simply appended to it. Will be ignored when CUCUMBER_OPTS is used.
|
|
62
|
+
def profile=(profile)
|
|
63
|
+
@profile = profile
|
|
64
|
+
unless feature_list
|
|
65
|
+
@feature_list = [] # Don't use accessor to avoid deprecation warning.
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
attr_reader :profile
|
|
50
69
|
|
|
51
70
|
# Define a Rake
|
|
52
71
|
def initialize(task_name = "features", desc = "Run Features with Cucumber")
|
|
@@ -75,7 +94,7 @@ module Cucumber
|
|
|
75
94
|
def arguments_for_ruby_execution(task_args = nil) # :nodoc:
|
|
76
95
|
lib_args = ['"%s"' % libs.join(File::PATH_SEPARATOR)]
|
|
77
96
|
cucumber_bin = ['"%s"' % binary]
|
|
78
|
-
cuc_opts = [(ENV['CUCUMBER_OPTS'] ||
|
|
97
|
+
cuc_opts = [(ENV['CUCUMBER_OPTS'] || cucumber_opts_with_profile)]
|
|
79
98
|
|
|
80
99
|
step_files(task_args).each do |step_file|
|
|
81
100
|
cuc_opts << '--require'
|
|
@@ -92,6 +111,10 @@ module Cucumber
|
|
|
92
111
|
args
|
|
93
112
|
end
|
|
94
113
|
|
|
114
|
+
def cucumber_opts_with_profile # :nodoc:
|
|
115
|
+
@profile ? "#{cucumber_opts} --profile #{@profile}" : cucumber_opts
|
|
116
|
+
end
|
|
117
|
+
|
|
95
118
|
def feature_files(task_args = nil) # :nodoc:
|
|
96
119
|
if ENV['FEATURE']
|
|
97
120
|
FileList[ ENV['FEATURE'] ]
|
|
@@ -59,7 +59,7 @@ module Cucumber
|
|
|
59
59
|
PARAM_PATTERN = /"([^\"]*)"/
|
|
60
60
|
ESCAPED_PARAM_PATTERN = '"([^\\"]*)"'
|
|
61
61
|
|
|
62
|
-
def self.snippet_text(step_keyword, step_name)
|
|
62
|
+
def self.snippet_text(step_keyword, step_name, multiline_arg_class = nil)
|
|
63
63
|
escaped = Regexp.escape(step_name).gsub('\ ', ' ').gsub('/', '\/')
|
|
64
64
|
escaped = escaped.gsub(PARAM_PATTERN, ESCAPED_PARAM_PATTERN)
|
|
65
65
|
|
|
@@ -68,9 +68,11 @@ module Cucumber
|
|
|
68
68
|
n += 1
|
|
69
69
|
"arg#{n}"
|
|
70
70
|
end
|
|
71
|
+
block_args << multiline_arg_class.default_arg_name unless multiline_arg_class.nil?
|
|
71
72
|
block_arg_string = block_args.empty? ? "" : " |#{block_args.join(", ")}|"
|
|
73
|
+
multiline_class_string = multiline_arg_class ? "# #{multiline_arg_class.default_arg_name} is a #{multiline_arg_class.to_s}\n " : ""
|
|
72
74
|
|
|
73
|
-
"#{step_keyword} /^#{escaped}$/ do#{block_arg_string}\n pending\nend"
|
|
75
|
+
"#{step_keyword} /^#{escaped}$/ do#{block_arg_string}\n #{multiline_class_string}pending\nend"
|
|
74
76
|
end
|
|
75
77
|
|
|
76
78
|
class MissingProc < StandardError
|
data/lib/cucumber/step_mother.rb
CHANGED
|
@@ -45,11 +45,43 @@ module Cucumber
|
|
|
45
45
|
end
|
|
46
46
|
end
|
|
47
47
|
|
|
48
|
+
class NilWorld < StandardError
|
|
49
|
+
def initialize
|
|
50
|
+
super("World procs should never return nil")
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
class MultipleWorld < StandardError
|
|
55
|
+
def initialize(first_proc, second_proc)
|
|
56
|
+
message = "You can only pass a proc to #World once, but it's happening\n"
|
|
57
|
+
message << "in 2 places:\n\n"
|
|
58
|
+
message << first_proc.backtrace_line('World') << "\n"
|
|
59
|
+
message << second_proc.backtrace_line('World') << "\n\n"
|
|
60
|
+
message << "Use Ruby modules instead to extend your worlds. See the #World RDoc.\n\n"
|
|
61
|
+
super(message)
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
48
65
|
# This is the main interface for registering step definitions, which is done
|
|
49
66
|
# from <tt>*_steps.rb</tt> files. This module is included right at the top-level
|
|
50
67
|
# so #register_step_definition (and more interestingly - its aliases) are
|
|
51
68
|
# available from the top-level.
|
|
52
69
|
module StepMother
|
|
70
|
+
class Hook
|
|
71
|
+
def initialize(tag_names, proc)
|
|
72
|
+
@tag_names = tag_names.map{|tag| Ast::Tags.strip_prefix(tag)}
|
|
73
|
+
@proc = proc
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def matches_tag_names?(tag_names)
|
|
77
|
+
@tag_names.empty? || (@tag_names & tag_names).any?
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def execute_in(world, scenario, location)
|
|
81
|
+
world.cucumber_instance_exec(false, location, scenario, &@proc)
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
53
85
|
class << self
|
|
54
86
|
def alias_adverb(adverb)
|
|
55
87
|
adverb = adverb.gsub(/\s/, '')
|
|
@@ -97,18 +129,68 @@ module Cucumber
|
|
|
97
129
|
|
|
98
130
|
# Registers a Before proc. You can call this method as many times as you
|
|
99
131
|
# want (typically from ruby scripts under <tt>support</tt>).
|
|
100
|
-
def Before(&proc)
|
|
101
|
-
(
|
|
132
|
+
def Before(*tag_names, &proc)
|
|
133
|
+
register_hook(:before, tag_names, proc)
|
|
102
134
|
end
|
|
103
135
|
|
|
104
|
-
def After(&proc)
|
|
105
|
-
(
|
|
136
|
+
def After(*tag_names, &proc)
|
|
137
|
+
register_hook(:after, tag_names, proc)
|
|
106
138
|
end
|
|
107
139
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
140
|
+
def register_hook(phase, tags, proc)
|
|
141
|
+
hook = Hook.new(tags, proc)
|
|
142
|
+
hooks[phase] << hook
|
|
143
|
+
hook
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def hooks
|
|
147
|
+
@hooks ||= Hash.new {|hash, phase| hash[phase] = []}
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
def hooks_for(phase, scenario)
|
|
151
|
+
hooks[phase].select{|hook| scenario.accept_hook?(hook)}
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
# Registers any number of +world_modules+ (Ruby Modules) and/or a Proc.
|
|
155
|
+
# The +proc+ will be executed once before each scenario to create an
|
|
156
|
+
# Object that the scenario's steps will run within. Any +world_modules+
|
|
157
|
+
# will be mixed into this Object (via Object#extend).
|
|
158
|
+
#
|
|
159
|
+
# This method is typically called from one or more Ruby scripts under
|
|
160
|
+
# <tt>features/support</tt>. You can call this method as many times as you
|
|
161
|
+
# like (to register more modules), but if you try to register more than
|
|
162
|
+
# one Proc you will get an error.
|
|
163
|
+
#
|
|
164
|
+
# Cucumber will not yield anything to the +proc+ (like it used to do before v0.3).
|
|
165
|
+
#
|
|
166
|
+
# In earlier versions of Cucumber (before 0.3) you could not register
|
|
167
|
+
# any +world_modules+. Instead you would register several Proc objects (by
|
|
168
|
+
# calling the method several times). The result of each +proc+ would be yielded
|
|
169
|
+
# to the next +proc+. Example:
|
|
170
|
+
#
|
|
171
|
+
# World do |world| # NOT SUPPORTED FROM 0.3
|
|
172
|
+
# MyClass.new
|
|
173
|
+
# end
|
|
174
|
+
#
|
|
175
|
+
# World do |world| # NOT SUPPORTED FROM 0.3
|
|
176
|
+
# world.extend(MyModule)
|
|
177
|
+
# end
|
|
178
|
+
#
|
|
179
|
+
# From Cucumber 0.3 the recommended way to do this is:
|
|
180
|
+
#
|
|
181
|
+
# World do
|
|
182
|
+
# MyClass.new
|
|
183
|
+
# end
|
|
184
|
+
#
|
|
185
|
+
# World(MyModule)
|
|
186
|
+
#
|
|
187
|
+
def World(*world_modules, &proc)
|
|
188
|
+
if(proc)
|
|
189
|
+
raise MultipleWorld.new(@world_proc, proc) if @world_proc
|
|
190
|
+
@world_proc = proc
|
|
191
|
+
end
|
|
192
|
+
@world_modules ||= []
|
|
193
|
+
@world_modules += world_modules
|
|
112
194
|
end
|
|
113
195
|
|
|
114
196
|
def current_world
|
|
@@ -139,21 +221,27 @@ module Cucumber
|
|
|
139
221
|
@step_definitions ||= []
|
|
140
222
|
end
|
|
141
223
|
|
|
142
|
-
def snippet_text(step_keyword, step_name)
|
|
143
|
-
@snippet_generator.snippet_text(step_keyword, step_name)
|
|
224
|
+
def snippet_text(step_keyword, step_name, multiline_arg_class)
|
|
225
|
+
@snippet_generator.snippet_text(step_keyword, step_name, multiline_arg_class)
|
|
144
226
|
end
|
|
145
227
|
|
|
146
228
|
def before_and_after(scenario, skip=false)
|
|
147
|
-
unless
|
|
229
|
+
before(scenario) unless skip
|
|
230
|
+
yield
|
|
231
|
+
after(scenario) unless skip
|
|
232
|
+
scenario_visited(scenario)
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
def before(scenario)
|
|
236
|
+
unless current_world
|
|
148
237
|
new_world!
|
|
149
238
|
execute_before(scenario)
|
|
150
239
|
end
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
end
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
def after(scenario)
|
|
243
|
+
execute_after(scenario)
|
|
244
|
+
nil_world!
|
|
157
245
|
end
|
|
158
246
|
|
|
159
247
|
private
|
|
@@ -168,17 +256,46 @@ module Cucumber
|
|
|
168
256
|
|
|
169
257
|
# Creates a new world instance
|
|
170
258
|
def new_world!
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
259
|
+
create_world!
|
|
260
|
+
extend_world
|
|
261
|
+
connect_world
|
|
262
|
+
@current_world
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
def create_world!
|
|
266
|
+
if(@world_proc)
|
|
267
|
+
@current_world = @world_proc.call
|
|
268
|
+
check_nil(@current_world, @world_proc)
|
|
269
|
+
else
|
|
270
|
+
@current_world = Object.new
|
|
174
271
|
end
|
|
272
|
+
end
|
|
175
273
|
|
|
274
|
+
def extend_world
|
|
176
275
|
@current_world.extend(World)
|
|
276
|
+
@current_world.extend(::Spec::Matchers) if defined?(::Spec::Matchers)
|
|
277
|
+
(@world_modules || []).each do |mod|
|
|
278
|
+
@current_world.extend(mod)
|
|
279
|
+
end
|
|
280
|
+
end
|
|
281
|
+
|
|
282
|
+
def connect_world
|
|
177
283
|
@current_world.__cucumber_step_mother = self
|
|
178
284
|
@current_world.__cucumber_visitor = @visitor
|
|
285
|
+
end
|
|
179
286
|
|
|
180
|
-
|
|
181
|
-
|
|
287
|
+
def check_nil(o, proc)
|
|
288
|
+
if o.nil?
|
|
289
|
+
begin
|
|
290
|
+
raise NilWorld.new
|
|
291
|
+
rescue NilWorld => e
|
|
292
|
+
e.backtrace.clear
|
|
293
|
+
e.backtrace.push(proc.backtrace_line("World"))
|
|
294
|
+
raise e
|
|
295
|
+
end
|
|
296
|
+
else
|
|
297
|
+
o
|
|
298
|
+
end
|
|
182
299
|
end
|
|
183
300
|
|
|
184
301
|
def nil_world!
|
|
@@ -186,14 +303,14 @@ module Cucumber
|
|
|
186
303
|
end
|
|
187
304
|
|
|
188
305
|
def execute_before(scenario)
|
|
189
|
-
(
|
|
190
|
-
@current_world
|
|
306
|
+
hooks_for(:before, scenario).each do |hook|
|
|
307
|
+
hook.execute_in(@current_world, scenario, 'Before')
|
|
191
308
|
end
|
|
192
309
|
end
|
|
193
310
|
|
|
194
311
|
def execute_after(scenario)
|
|
195
|
-
(
|
|
196
|
-
@current_world
|
|
312
|
+
hooks_for(:after, scenario).each do |hook|
|
|
313
|
+
hook.execute_in(@current_world, scenario, 'After')
|
|
197
314
|
end
|
|
198
315
|
end
|
|
199
316
|
|