cucumber 2.1.0 → 2.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +10 -0
- data/Gemfile +3 -1
- data/History.md +18 -2
- data/README.md +5 -1
- data/cucumber.gemspec +3 -4
- data/cucumber.yml +2 -2
- data/features/docs/api/run_cli_main_with_existing_runtime.feature +4 -7
- data/features/docs/defining_steps/skip_scenario.feature +6 -2
- data/features/docs/formatters/api_methods.feature +36 -0
- data/features/docs/profiles.feature +2 -2
- data/features/lib/step_definitions/profile_steps.rb +1 -1
- data/lib/cucumber.rb +11 -4
- data/lib/cucumber/cli/configuration.rb +2 -2
- data/lib/cucumber/cli/options.rb +2 -2
- data/lib/cucumber/configuration.rb +25 -3
- data/lib/cucumber/deprecate.rb +29 -0
- data/lib/cucumber/filters/activate_steps.rb +39 -5
- data/lib/cucumber/formatter/console.rb +4 -4
- data/lib/cucumber/formatter/io.rb +1 -1
- data/lib/cucumber/formatter/legacy_api/adapter.rb +30 -30
- data/lib/cucumber/formatter/legacy_api/runtime_facade.rb +4 -9
- data/lib/cucumber/platform.rb +2 -7
- data/lib/cucumber/rb_support/rb_language.rb +72 -26
- data/lib/cucumber/rb_support/rb_step_definition.rb +2 -2
- data/lib/cucumber/rb_support/rb_world.rb +6 -1
- data/lib/cucumber/rb_support/snippet.rb +21 -0
- data/lib/cucumber/running_test_case.rb +5 -1
- data/lib/cucumber/runtime.rb +11 -15
- data/lib/cucumber/runtime/support_code.rb +20 -128
- data/lib/cucumber/step_argument.rb +25 -0
- data/lib/cucumber/step_match.rb +6 -12
- data/lib/cucumber/step_match_search.rb +67 -0
- data/lib/cucumber/version +1 -0
- data/spec/cucumber/configuration_spec.rb +3 -2
- data/spec/cucumber/filters/activate_steps_spec.rb +95 -3
- data/spec/cucumber/formatter/html_spec.rb +1 -1
- data/spec/cucumber/formatter/legacy_api/adapter_spec.rb +55 -28
- data/spec/cucumber/formatter/pretty_spec.rb +2 -2
- data/spec/cucumber/formatter/spec_helper.rb +22 -12
- data/spec/cucumber/rb_support/rb_language_spec.rb +9 -45
- data/spec/cucumber/rb_support/rb_step_definition_spec.rb +2 -2
- data/spec/cucumber/rb_support/rb_world_spec.rb +47 -0
- data/spec/cucumber/runtime/for_programming_languages_spec.rb +1 -1
- data/spec/cucumber/runtime/support_code_spec.rb +4 -111
- data/spec/cucumber/step_argument_spec.rb +18 -0
- data/spec/cucumber/step_match_search_spec.rb +122 -0
- data/spec/cucumber/step_match_spec.rb +8 -2
- data/spec/cucumber/world/pending_spec.rb +2 -1
- data/spec/cucumber_spec.rb +39 -0
- metadata +45 -50
- data/features/docs/wire_protocol/erb_configuration.feature +0 -56
- data/features/docs/wire_protocol/handle_unexpected_response.feature +0 -30
- data/features/docs/wire_protocol/invoke_message.feature +0 -216
- data/features/docs/wire_protocol/readme.md +0 -26
- data/features/docs/wire_protocol/snippets_message.feature +0 -51
- data/features/docs/wire_protocol/step_matches_message.feature +0 -81
- data/features/docs/wire_protocol/table_diffing.feature +0 -126
- data/features/docs/wire_protocol/tags.feature +0 -87
- data/features/docs/wire_protocol/timeouts.feature +0 -64
- data/lib/cucumber/events/bus.rb +0 -86
- data/lib/cucumber/gherkin/formatter/argument.rb +0 -17
- data/lib/cucumber/gherkin/formatter/hashable.rb +0 -27
- data/lib/cucumber/language_support.rb +0 -30
- data/lib/cucumber/language_support/language_methods.rb +0 -72
- data/lib/cucumber/rb_support/regexp_argument_matcher.rb +0 -21
- data/lib/cucumber/wire_support/configuration.rb +0 -38
- data/lib/cucumber/wire_support/connection.rb +0 -61
- data/lib/cucumber/wire_support/request_handler.rb +0 -32
- data/lib/cucumber/wire_support/wire_exception.rb +0 -32
- data/lib/cucumber/wire_support/wire_language.rb +0 -68
- data/lib/cucumber/wire_support/wire_packet.rb +0 -34
- data/lib/cucumber/wire_support/wire_protocol.rb +0 -43
- data/lib/cucumber/wire_support/wire_protocol/requests.rb +0 -133
- data/lib/cucumber/wire_support/wire_step_definition.rb +0 -21
- data/spec/cucumber/events/bus_spec.rb +0 -94
- data/spec/cucumber/rb_support/regexp_argument_matcher_spec.rb +0 -22
- data/spec/cucumber/wire_support/configuration_spec.rb +0 -64
- data/spec/cucumber/wire_support/connection_spec.rb +0 -64
- data/spec/cucumber/wire_support/wire_exception_spec.rb +0 -50
- data/spec/cucumber/wire_support/wire_language_spec.rb +0 -46
- data/spec/cucumber/wire_support/wire_packet_spec.rb +0 -44
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'delegate'
|
2
|
+
require 'cucumber/deprecate'
|
2
3
|
|
3
4
|
module Cucumber
|
4
5
|
# Represents the current status of a running test case.
|
@@ -94,7 +95,10 @@ module Cucumber
|
|
94
95
|
end
|
95
96
|
|
96
97
|
def skip_invoke!
|
97
|
-
Cucumber.deprecate(
|
98
|
+
Cucumber.deprecate(
|
99
|
+
"Just call #skip_this_scenario directly",
|
100
|
+
"skip_invoke!",
|
101
|
+
"2.9.9")
|
98
102
|
raise Cucumber::Core::Test::Result::Skipped
|
99
103
|
end
|
100
104
|
|
data/lib/cucumber/runtime.rb
CHANGED
@@ -4,13 +4,13 @@ require 'multi_json'
|
|
4
4
|
require 'multi_test'
|
5
5
|
require 'cucumber/configuration'
|
6
6
|
require 'cucumber/load_path'
|
7
|
-
require 'cucumber/language_support/language_methods'
|
8
7
|
require 'cucumber/formatter/duration'
|
9
8
|
require 'cucumber/file_specs'
|
10
9
|
require 'cucumber/filters'
|
11
10
|
require 'cucumber/formatter/fanout'
|
12
11
|
require 'cucumber/formatter/event_bus_report'
|
13
12
|
require 'cucumber/gherkin/i18n'
|
13
|
+
require 'cucumber/step_match_search'
|
14
14
|
|
15
15
|
module Cucumber
|
16
16
|
module FixRuby21Bug9285
|
@@ -57,12 +57,10 @@ module Cucumber
|
|
57
57
|
@support_code.configure(@configuration)
|
58
58
|
end
|
59
59
|
|
60
|
-
|
61
|
-
@support_code.load_programming_language(language)
|
62
|
-
end
|
63
|
-
|
60
|
+
require 'cucumber/wire/plugin'
|
64
61
|
def run!
|
65
62
|
load_step_definitions
|
63
|
+
install_wire_plugin
|
66
64
|
fire_after_configuration_hook
|
67
65
|
self.visitor = report
|
68
66
|
|
@@ -90,10 +88,6 @@ module Cucumber
|
|
90
88
|
@support_code.unmatched_step_definitions
|
91
89
|
end
|
92
90
|
|
93
|
-
def snippet_text(step_keyword, step_name, multiline_arg) #:nodoc:
|
94
|
-
@support_code.snippet_text(Cucumber::Gherkin::I18n.code_keyword_for(step_keyword).strip, step_name, multiline_arg)
|
95
|
-
end
|
96
|
-
|
97
91
|
def begin_scenario(scenario)
|
98
92
|
@support_code.fire_hook(:begin_scenario, scenario)
|
99
93
|
end
|
@@ -102,10 +96,6 @@ module Cucumber
|
|
102
96
|
@support_code.fire_hook(:end_scenario)
|
103
97
|
end
|
104
98
|
|
105
|
-
def unknown_programming_language?
|
106
|
-
@support_code.unknown_programming_language?
|
107
|
-
end
|
108
|
-
|
109
99
|
# Returns Ast::DocString for +string_without_triple_quotes+.
|
110
100
|
#
|
111
101
|
def doc_string(string_without_triple_quotes, content_type='', line_offset=0)
|
@@ -213,7 +203,7 @@ module Cucumber
|
|
213
203
|
formatter = factory.new(runtime_facade, path_or_io, options)
|
214
204
|
Formatter::LegacyApi::Adapter.new(
|
215
205
|
Formatter::IgnoreMissingMessages.new(formatter),
|
216
|
-
results, @
|
206
|
+
results, @configuration)
|
217
207
|
end
|
218
208
|
|
219
209
|
def legacy_formatter?(factory)
|
@@ -242,7 +232,9 @@ module Cucumber
|
|
242
232
|
filters << Cucumber::Core::Test::NameFilter.new(name_regexps)
|
243
233
|
filters << Cucumber::Core::Test::LocationsFilter.new(filespecs.locations)
|
244
234
|
filters << Filters::Quit.new
|
245
|
-
|
235
|
+
# TODO: can we just use RbLanguages's step definitions directly?
|
236
|
+
step_match_search = StepMatchSearch.new(@support_code.ruby.method(:step_matches), @configuration)
|
237
|
+
filters << Filters::ActivateSteps.new(step_match_search, @configuration)
|
246
238
|
@configuration.filters.each do |filter|
|
247
239
|
filters << filter
|
248
240
|
end
|
@@ -262,6 +254,10 @@ module Cucumber
|
|
262
254
|
@support_code.load_files!(files)
|
263
255
|
end
|
264
256
|
|
257
|
+
def install_wire_plugin
|
258
|
+
Cucumber::Wire::Plugin.new(@configuration).install if @configuration.all_files_to_load.any? {|f| f =~ %r{\.wire$} }
|
259
|
+
end
|
260
|
+
|
265
261
|
def log
|
266
262
|
Cucumber.logger
|
267
263
|
end
|
@@ -5,6 +5,7 @@ require 'cucumber/runtime/before_hooks'
|
|
5
5
|
require 'cucumber/runtime/after_hooks'
|
6
6
|
require 'cucumber/events/step_match'
|
7
7
|
require 'cucumber/gherkin/steps_parser'
|
8
|
+
require 'cucumber/step_match_search'
|
8
9
|
|
9
10
|
module Cucumber
|
10
11
|
|
@@ -43,12 +44,11 @@ module Cucumber
|
|
43
44
|
|
44
45
|
include Constantize
|
45
46
|
|
46
|
-
|
47
|
-
|
47
|
+
attr_reader :ruby
|
48
|
+
def initialize(user_interface, configuration=Configuration.default)
|
49
|
+
@configuration = configuration
|
48
50
|
@runtime_facade = Runtime::ForProgrammingLanguages.new(self, user_interface)
|
49
|
-
@
|
50
|
-
@programming_languages = []
|
51
|
-
@language_map = {}
|
51
|
+
@ruby = Cucumber::RbSupport::RbLanguage.new(@runtime_facade, @configuration)
|
52
52
|
end
|
53
53
|
|
54
54
|
def configure(new_configuration)
|
@@ -73,24 +73,9 @@ module Cucumber
|
|
73
73
|
#
|
74
74
|
# These are commonly called nested steps.
|
75
75
|
def invoke_dynamic_step(step_name, multiline_argument, location=nil)
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
raise UndefinedDynamicStep, step_name
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
# Loads and registers programming language implementation.
|
84
|
-
# Instances are cached, so calling with the same argument
|
85
|
-
# twice will return the same instance.
|
86
|
-
#
|
87
|
-
def load_programming_language(ext)
|
88
|
-
return @language_map[ext] if @language_map[ext]
|
89
|
-
programming_language_class = constantize("Cucumber::#{ext.capitalize}Support::#{ext.capitalize}Language")
|
90
|
-
programming_language = programming_language_class.new(@runtime_facade)
|
91
|
-
@programming_languages << programming_language
|
92
|
-
@language_map[ext] = programming_language
|
93
|
-
programming_language
|
76
|
+
matches = step_matches(step_name)
|
77
|
+
raise UndefinedDynamicStep, step_name if matches.empty?
|
78
|
+
matches.first.invoke(multiline_argument)
|
94
79
|
end
|
95
80
|
|
96
81
|
def load_files!(files)
|
@@ -102,158 +87,65 @@ module Cucumber
|
|
102
87
|
end
|
103
88
|
|
104
89
|
def load_files_from_paths(paths)
|
105
|
-
files = paths.map { |path| Dir["#{path}
|
90
|
+
files = paths.map { |path| Dir["#{path}/**/*.rb"] }.flatten
|
106
91
|
load_files! files
|
107
92
|
end
|
108
93
|
|
109
94
|
def unmatched_step_definitions
|
110
|
-
@
|
111
|
-
programming_language.unmatched_step_definitions
|
112
|
-
end.flatten
|
113
|
-
end
|
114
|
-
|
115
|
-
def snippet_text(step_keyword, step_name, multiline_arg) #:nodoc:
|
116
|
-
load_programming_language('rb') if unknown_programming_language?
|
117
|
-
@programming_languages.map do |programming_language|
|
118
|
-
programming_language.snippet_text(step_keyword, step_name, multiline_arg, @configuration.snippet_type)
|
119
|
-
end.join("\n")
|
120
|
-
end
|
121
|
-
|
122
|
-
def unknown_programming_language?
|
123
|
-
@programming_languages.empty?
|
95
|
+
@ruby.unmatched_step_definitions
|
124
96
|
end
|
125
97
|
|
126
98
|
def fire_hook(name, *args)
|
127
|
-
@
|
128
|
-
programming_language.send(name, *args)
|
129
|
-
end
|
99
|
+
@ruby.send(name, *args)
|
130
100
|
end
|
131
101
|
|
132
102
|
def step_definitions
|
133
|
-
@
|
134
|
-
programming_language.step_definitions
|
135
|
-
end.flatten
|
136
|
-
end
|
137
|
-
|
138
|
-
def find_match(test_step)
|
139
|
-
begin
|
140
|
-
match = step_match(test_step.name)
|
141
|
-
rescue Cucumber::Undefined
|
142
|
-
return NoStepMatch.new(test_step.source.last, test_step.name)
|
143
|
-
end
|
144
|
-
# TODO: move this onto Filters::ActivateSteps
|
145
|
-
@configuration.notify Events::StepMatch.new(test_step, match)
|
146
|
-
if @configuration.dry_run?
|
147
|
-
return SkippingStepMatch.new
|
148
|
-
end
|
149
|
-
match
|
103
|
+
@ruby.step_definitions
|
150
104
|
end
|
151
105
|
|
152
106
|
def find_after_step_hooks(test_case)
|
153
|
-
ruby = load_programming_language('rb')
|
154
107
|
scenario = RunningTestCase.new(test_case)
|
155
|
-
hooks = ruby.hooks_for(:after_step, scenario)
|
108
|
+
hooks = @ruby.hooks_for(:after_step, scenario)
|
156
109
|
StepHooks.new hooks
|
157
110
|
end
|
158
111
|
|
159
112
|
def apply_before_hooks(test_case)
|
160
|
-
ruby = load_programming_language('rb')
|
161
113
|
scenario = RunningTestCase.new(test_case)
|
162
|
-
hooks = ruby.hooks_for(:before, scenario)
|
114
|
+
hooks = @ruby.hooks_for(:before, scenario)
|
163
115
|
BeforeHooks.new(hooks, scenario).apply_to(test_case)
|
164
116
|
end
|
165
117
|
|
166
118
|
def apply_after_hooks(test_case)
|
167
|
-
ruby = load_programming_language('rb')
|
168
119
|
scenario = RunningTestCase.new(test_case)
|
169
|
-
hooks = ruby.hooks_for(:after, scenario)
|
120
|
+
hooks = @ruby.hooks_for(:after, scenario)
|
170
121
|
AfterHooks.new(hooks, scenario).apply_to(test_case)
|
171
122
|
end
|
172
123
|
|
173
124
|
def find_around_hooks(test_case)
|
174
|
-
ruby = load_programming_language('rb')
|
175
125
|
scenario = RunningTestCase.new(test_case)
|
176
126
|
|
177
|
-
ruby.hooks_for(:around, scenario).map do |hook|
|
127
|
+
@ruby.hooks_for(:around, scenario).map do |hook|
|
178
128
|
Hooks.around_hook(test_case.source) do |run_scenario|
|
179
129
|
hook.invoke('Around', scenario, &run_scenario)
|
180
130
|
end
|
181
131
|
end
|
182
132
|
end
|
183
133
|
|
184
|
-
def step_match(step_name, name_to_report=nil) #:nodoc:
|
185
|
-
@match_cache ||= {}
|
186
|
-
|
187
|
-
match = @match_cache[[step_name, name_to_report]]
|
188
|
-
return match if match
|
189
|
-
|
190
|
-
@match_cache[[step_name, name_to_report]] = step_match_without_cache(step_name, name_to_report)
|
191
|
-
end
|
192
|
-
|
193
134
|
private
|
194
135
|
|
195
|
-
def
|
196
|
-
|
197
|
-
raise Undefined.new(step_name) if matches.empty?
|
198
|
-
matches = best_matches(step_name, matches) if matches.size > 1 && guess_step_matches?
|
199
|
-
raise Ambiguous.new(step_name, matches, guess_step_matches?) if matches.size > 1
|
200
|
-
matches[0]
|
201
|
-
end
|
202
|
-
|
203
|
-
def guess_step_matches?
|
204
|
-
@configuration.guess?
|
205
|
-
end
|
206
|
-
|
207
|
-
def matches(step_name, name_to_report)
|
208
|
-
@programming_languages.map do |programming_language|
|
209
|
-
programming_language.step_matches(step_name, name_to_report).to_a
|
210
|
-
end.flatten
|
211
|
-
end
|
212
|
-
|
213
|
-
def best_matches(step_name, step_matches) #:nodoc:
|
214
|
-
no_groups = step_matches.select {|step_match| step_match.args.length == 0}
|
215
|
-
max_arg_length = step_matches.map {|step_match| step_match.args.length }.max
|
216
|
-
top_groups = step_matches.select {|step_match| step_match.args.length == max_arg_length }
|
217
|
-
|
218
|
-
if no_groups.any?
|
219
|
-
longest_regexp_length = no_groups.map {|step_match| step_match.text_length }.max
|
220
|
-
no_groups.select {|step_match| step_match.text_length == longest_regexp_length }
|
221
|
-
elsif top_groups.any?
|
222
|
-
shortest_capture_length = top_groups.map {|step_match| step_match.args.inject(0) {|sum, c| sum + c.to_s.length } }.min
|
223
|
-
top_groups.select {|step_match| step_match.args.inject(0) {|sum, c| sum + c.to_s.length } == shortest_capture_length }
|
224
|
-
else
|
225
|
-
top_groups
|
226
|
-
end
|
136
|
+
def step_matches(step_name)
|
137
|
+
StepMatchSearch.new(@ruby.method(:step_matches), @configuration).call(step_name)
|
227
138
|
end
|
228
139
|
|
229
140
|
def load_file(file)
|
230
|
-
|
231
|
-
|
232
|
-
programming_language.load_code_file(file)
|
233
|
-
else
|
234
|
-
log.debug(" * #{file} [NOT SUPPORTED]\n")
|
235
|
-
end
|
141
|
+
log.debug(" * #{file}\n")
|
142
|
+
@ruby.load_code_file(file)
|
236
143
|
end
|
237
144
|
|
238
145
|
def log
|
239
146
|
Cucumber.logger
|
240
147
|
end
|
241
148
|
|
242
|
-
def programming_language_for(step_def_file)
|
243
|
-
if ext = File.extname(step_def_file)[1..-1]
|
244
|
-
return nil if @unsupported_programming_languages.index(ext)
|
245
|
-
begin
|
246
|
-
load_programming_language(ext)
|
247
|
-
rescue LoadError => e
|
248
|
-
log.debug("Failed to load '#{ext}' programming language for file #{step_def_file}: #{e.message}\n")
|
249
|
-
@unsupported_programming_languages << ext
|
250
|
-
nil
|
251
|
-
end
|
252
|
-
else
|
253
|
-
nil
|
254
|
-
end
|
255
|
-
end
|
256
|
-
|
257
149
|
end
|
258
150
|
end
|
259
151
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Cucumber
|
2
|
+
# Defines the location and value of a captured argument from the step
|
3
|
+
# text
|
4
|
+
class StepArgument
|
5
|
+
def self.arguments_from(regexp, step_name)
|
6
|
+
match = regexp.match(step_name)
|
7
|
+
if match
|
8
|
+
n = 0
|
9
|
+
match.captures.map do |val|
|
10
|
+
n += 1
|
11
|
+
offset = match.offset(n)[0]
|
12
|
+
new(offset, val)
|
13
|
+
end
|
14
|
+
else
|
15
|
+
nil
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
attr_reader :offset, :val
|
20
|
+
|
21
|
+
def initialize(offset, val)
|
22
|
+
@offset, @val = offset, val
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/lib/cucumber/step_match.rb
CHANGED
@@ -1,26 +1,20 @@
|
|
1
1
|
require 'cucumber/multiline_argument'
|
2
2
|
|
3
3
|
module Cucumber
|
4
|
+
|
5
|
+
# Represents the match found between a Test Step and it's activation
|
4
6
|
class StepMatch #:nodoc:
|
5
7
|
attr_reader :step_definition, :step_arguments
|
6
8
|
|
7
|
-
|
8
|
-
# reported, unless it's is, in which case +name_to_report+ is used instead.
|
9
|
-
#
|
10
|
-
def initialize(step_definition, name_to_match, name_to_report, step_arguments)
|
11
|
-
raise "name_to_match can't be nil" if name_to_match.nil?
|
9
|
+
def initialize(step_definition, step_name, step_arguments)
|
12
10
|
raise "step_arguments can't be nil (but it can be an empty array)" if step_arguments.nil?
|
13
|
-
@step_definition, @name_to_match, @
|
11
|
+
@step_definition, @name_to_match, @step_arguments = step_definition, step_name, step_arguments
|
14
12
|
end
|
15
13
|
|
16
14
|
def args
|
17
15
|
@step_arguments.map{|g| g.val }
|
18
16
|
end
|
19
17
|
|
20
|
-
def name
|
21
|
-
@name_to_report
|
22
|
-
end
|
23
|
-
|
24
18
|
def activate(test_step)
|
25
19
|
test_step.with_action(@step_definition.location) do
|
26
20
|
invoke(MultilineArgument.from_core(test_step.source.last.multiline_arg))
|
@@ -49,7 +43,7 @@ module Cucumber
|
|
49
43
|
# lambda { |param| "[#{param}]" }
|
50
44
|
#
|
51
45
|
def format_args(format = lambda{|a| a}, &proc)
|
52
|
-
|
46
|
+
replace_arguments(@name_to_match, @step_arguments, format, &proc)
|
53
47
|
end
|
54
48
|
|
55
49
|
def location
|
@@ -90,7 +84,7 @@ module Cucumber
|
|
90
84
|
end
|
91
85
|
|
92
86
|
def inspect #:nodoc:
|
93
|
-
|
87
|
+
"#<#{self.class}: #{location}>"
|
94
88
|
end
|
95
89
|
|
96
90
|
private
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module Cucumber
|
2
|
+
module StepMatchSearch
|
3
|
+
def self.new(search, configuration)
|
4
|
+
CachesStepMatch.new(
|
5
|
+
AssertUnambiguousMatch.new(
|
6
|
+
configuration.guess? ? AttemptToGuessAmbiguousMatch.new(search) : search,
|
7
|
+
configuration
|
8
|
+
)
|
9
|
+
)
|
10
|
+
end
|
11
|
+
|
12
|
+
class AssertUnambiguousMatch
|
13
|
+
def initialize(search, configuration)
|
14
|
+
@search, @configuration = search, configuration
|
15
|
+
end
|
16
|
+
|
17
|
+
def call(step_name)
|
18
|
+
result = @search.call(step_name)
|
19
|
+
raise Cucumber::Ambiguous.new(step_name, result, @configuration.guess?) if result.length > 1
|
20
|
+
result
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
class AttemptToGuessAmbiguousMatch
|
25
|
+
def initialize(search)
|
26
|
+
@search = search
|
27
|
+
end
|
28
|
+
|
29
|
+
def call(step_name)
|
30
|
+
best_matches(step_name, @search.call(step_name))
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def best_matches(step_name, step_matches) #:nodoc:
|
36
|
+
no_groups = step_matches.select {|step_match| step_match.args.length == 0}
|
37
|
+
max_arg_length = step_matches.map {|step_match| step_match.args.length }.max
|
38
|
+
top_groups = step_matches.select {|step_match| step_match.args.length == max_arg_length }
|
39
|
+
|
40
|
+
if no_groups.any?
|
41
|
+
longest_regexp_length = no_groups.map {|step_match| step_match.text_length }.max
|
42
|
+
no_groups.select {|step_match| step_match.text_length == longest_regexp_length }
|
43
|
+
elsif top_groups.any?
|
44
|
+
shortest_capture_length = top_groups.map {|step_match| step_match.args.inject(0) {|sum, c| sum + c.to_s.length } }.min
|
45
|
+
top_groups.select {|step_match| step_match.args.inject(0) {|sum, c| sum + c.to_s.length } == shortest_capture_length }
|
46
|
+
else
|
47
|
+
top_groups
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
require 'delegate'
|
54
|
+
class CachesStepMatch < SimpleDelegator
|
55
|
+
def call(step_name) #:nodoc:
|
56
|
+
@match_cache ||= {}
|
57
|
+
|
58
|
+
matches = @match_cache[step_name]
|
59
|
+
return matches if matches
|
60
|
+
|
61
|
+
@match_cache[step_name] = super(step_name)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|