cucumber 2.1.0 → 2.2.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.
- 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
|
+
|