cucumber 3.1.2 → 8.0.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 +5 -5
- data/CHANGELOG.md +1880 -1146
- data/CONTRIBUTING.md +220 -61
- data/README.md +143 -22
- data/bin/cucumber +1 -1
- data/lib/autotest/cucumber_mixin.rb +49 -53
- data/lib/autotest/discover.rb +3 -2
- data/lib/cucumber/cli/configuration.rb +32 -7
- data/lib/cucumber/cli/main.rb +16 -15
- data/lib/cucumber/cli/options.rb +111 -79
- data/lib/cucumber/cli/profile_loader.rb +45 -26
- data/lib/cucumber/cli/rerun_file.rb +1 -1
- data/lib/cucumber/configuration.rb +47 -31
- data/lib/cucumber/constantize.rb +3 -6
- data/lib/cucumber/deprecate.rb +32 -7
- data/lib/cucumber/errors.rb +5 -7
- data/lib/cucumber/events/envelope.rb +9 -0
- data/lib/cucumber/events/gherkin_source_parsed.rb +11 -0
- data/lib/cucumber/events/hook_test_step_created.rb +12 -0
- data/lib/cucumber/events/step_activated.rb +0 -5
- data/lib/cucumber/events/step_definition_registered.rb +0 -5
- data/lib/cucumber/events/test_case_created.rb +12 -0
- data/lib/cucumber/events/test_case_ready.rb +12 -0
- data/lib/cucumber/events/test_run_finished.rb +2 -1
- data/lib/cucumber/events/test_step_created.rb +12 -0
- data/lib/cucumber/events/undefined_parameter_type.rb +9 -0
- data/lib/cucumber/events.rb +15 -8
- data/lib/cucumber/file_specs.rb +8 -7
- data/lib/cucumber/filters/activate_steps.rb +6 -3
- data/lib/cucumber/filters/broadcast_test_case_ready_event.rb +12 -0
- data/lib/cucumber/filters/prepare_world.rb +5 -9
- data/lib/cucumber/filters/quit.rb +1 -3
- data/lib/cucumber/filters/tag_limits/verifier.rb +3 -7
- data/lib/cucumber/filters/tag_limits.rb +1 -3
- data/lib/cucumber/filters.rb +1 -0
- data/lib/cucumber/formatter/ansicolor.rb +74 -86
- data/lib/cucumber/formatter/ast_lookup.rb +163 -0
- data/lib/cucumber/formatter/backtrace_filter.rb +10 -7
- data/lib/cucumber/formatter/console.rb +76 -68
- data/lib/cucumber/formatter/console_counts.rb +4 -9
- data/lib/cucumber/formatter/console_issues.rb +12 -4
- data/lib/cucumber/formatter/duration.rb +1 -1
- data/lib/cucumber/formatter/duration_extractor.rb +4 -1
- data/lib/cucumber/formatter/errors.rb +7 -0
- data/lib/cucumber/formatter/fanout.rb +3 -1
- data/lib/cucumber/formatter/html.rb +11 -598
- data/lib/cucumber/formatter/http_io.rb +152 -0
- data/lib/cucumber/formatter/ignore_missing_messages.rb +2 -2
- data/lib/cucumber/formatter/interceptor.rb +11 -30
- data/lib/cucumber/formatter/io.rb +57 -13
- data/lib/cucumber/formatter/json.rb +119 -124
- data/lib/cucumber/formatter/junit.rb +75 -55
- data/lib/cucumber/formatter/message.rb +23 -0
- data/lib/cucumber/formatter/message_builder.rb +256 -0
- data/lib/cucumber/formatter/pretty.rb +370 -153
- data/lib/cucumber/formatter/progress.rb +31 -32
- data/lib/cucumber/formatter/publish_banner_printer.rb +77 -0
- data/lib/cucumber/formatter/query/hook_by_test_step.rb +32 -0
- data/lib/cucumber/formatter/query/pickle_by_test.rb +26 -0
- data/lib/cucumber/formatter/query/pickle_step_by_test_step.rb +26 -0
- data/lib/cucumber/formatter/query/step_definitions_by_test_step.rb +40 -0
- data/lib/cucumber/formatter/query/test_case_started_by_test_case.rb +42 -0
- data/lib/cucumber/formatter/rerun.rb +24 -4
- data/lib/cucumber/formatter/stepdefs.rb +1 -2
- data/lib/cucumber/formatter/steps.rb +8 -6
- data/lib/cucumber/formatter/summary.rb +17 -8
- data/lib/cucumber/formatter/unicode.rb +18 -20
- data/lib/cucumber/formatter/url_reporter.rb +17 -0
- data/lib/cucumber/formatter/usage.rb +18 -15
- data/lib/cucumber/gherkin/data_table_parser.rb +18 -6
- data/lib/cucumber/gherkin/formatter/ansi_escapes.rb +14 -18
- data/lib/cucumber/gherkin/formatter/escaping.rb +2 -2
- data/lib/cucumber/gherkin/steps_parser.rb +17 -8
- data/lib/cucumber/glue/dsl.rb +29 -15
- data/lib/cucumber/glue/hook.rb +37 -11
- data/lib/cucumber/glue/invoke_in_world.rb +17 -22
- data/lib/cucumber/glue/proto_world.rb +47 -53
- data/lib/cucumber/glue/registry_and_more.rb +62 -17
- data/lib/cucumber/glue/registry_wrapper.rb +31 -0
- data/lib/cucumber/glue/snippet.rb +23 -22
- data/lib/cucumber/glue/step_definition.rb +48 -23
- data/lib/cucumber/glue/world_factory.rb +1 -1
- data/lib/cucumber/hooks.rb +12 -11
- data/lib/cucumber/multiline_argument/data_table/diff_matrices.rb +4 -3
- data/lib/cucumber/multiline_argument/data_table.rb +143 -123
- data/lib/cucumber/multiline_argument/doc_string.rb +1 -1
- data/lib/cucumber/multiline_argument.rb +4 -6
- data/lib/cucumber/platform.rb +5 -5
- data/lib/cucumber/rake/task.rb +34 -25
- data/lib/cucumber/rspec/disable_option_parser.rb +15 -11
- data/lib/cucumber/rspec/doubles.rb +3 -5
- data/lib/cucumber/running_test_case.rb +3 -53
- data/lib/cucumber/runtime/after_hooks.rb +8 -4
- data/lib/cucumber/runtime/before_hooks.rb +8 -4
- data/lib/cucumber/runtime/for_programming_languages.rb +4 -2
- data/lib/cucumber/runtime/meta_message_builder.rb +106 -0
- data/lib/cucumber/runtime/step_hooks.rb +6 -2
- data/lib/cucumber/runtime/support_code.rb +16 -15
- data/lib/cucumber/runtime/user_interface.rb +10 -19
- data/lib/cucumber/runtime.rb +78 -76
- data/lib/cucumber/step_definition_light.rb +4 -3
- data/lib/cucumber/step_definitions.rb +2 -2
- data/lib/cucumber/step_match.rb +17 -20
- data/lib/cucumber/step_match_search.rb +5 -3
- data/lib/cucumber/term/ansicolor.rb +72 -48
- data/lib/cucumber/term/banner.rb +57 -0
- data/lib/cucumber/version +1 -1
- data/lib/cucumber.rb +3 -2
- data/lib/simplecov_setup.rb +1 -1
- metadata +279 -81
- data/lib/cucumber/core_ext/string.rb +0 -11
- data/lib/cucumber/events/gherkin_source_parsed.rb~ +0 -14
- data/lib/cucumber/formatter/ast_lookup.rb~ +0 -9
- data/lib/cucumber/formatter/cucumber.css +0 -286
- data/lib/cucumber/formatter/cucumber.sass +0 -247
- data/lib/cucumber/formatter/hook_query_visitor.rb +0 -42
- data/lib/cucumber/formatter/html_builder.rb +0 -121
- data/lib/cucumber/formatter/inline-js.js +0 -30
- data/lib/cucumber/formatter/jquery-min.js +0 -154
- data/lib/cucumber/formatter/json_pretty.rb +0 -11
- data/lib/cucumber/formatter/legacy_api/adapter.rb +0 -1028
- data/lib/cucumber/formatter/legacy_api/ast.rb +0 -394
- data/lib/cucumber/formatter/legacy_api/results.rb +0 -50
- data/lib/cucumber/formatter/legacy_api/runtime_facade.rb +0 -32
- data/lib/cucumber/step_argument.rb +0 -25
data/lib/cucumber/runtime.rb
CHANGED
@@ -1,16 +1,19 @@
|
|
1
|
-
# -*- coding: utf-8 -*-
|
2
1
|
# frozen_string_literal: true
|
3
2
|
|
4
3
|
require 'fileutils'
|
5
|
-
require 'multi_json'
|
6
4
|
require 'cucumber/configuration'
|
5
|
+
require 'cucumber/deprecate'
|
7
6
|
require 'cucumber/load_path'
|
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/gherkin/i18n'
|
12
|
+
require 'cucumber/glue/registry_wrapper'
|
13
13
|
require 'cucumber/step_match_search'
|
14
|
+
require 'cucumber/messages'
|
15
|
+
require 'cucumber/runtime/meta_message_builder'
|
16
|
+
require 'sys/uname'
|
14
17
|
|
15
18
|
module Cucumber
|
16
19
|
module FixRuby21Bug9285
|
@@ -19,21 +22,22 @@ module Cucumber
|
|
19
22
|
end
|
20
23
|
end
|
21
24
|
|
22
|
-
class FileException <
|
23
|
-
|
25
|
+
class FileException < RuntimeError
|
26
|
+
attr_reader :path
|
24
27
|
|
25
28
|
def initialize(original_exception, path)
|
26
|
-
super(original_exception)
|
27
29
|
@path = path
|
30
|
+
super(original_exception)
|
28
31
|
end
|
29
32
|
end
|
30
33
|
|
31
34
|
class FileNotFoundException < FileException
|
32
35
|
end
|
33
36
|
|
34
|
-
class FeatureFolderNotFoundException <
|
37
|
+
class FeatureFolderNotFoundException < RuntimeError
|
35
38
|
def initialize(path)
|
36
39
|
@path = path
|
40
|
+
super
|
37
41
|
end
|
38
42
|
|
39
43
|
def message
|
@@ -54,7 +58,6 @@ module Cucumber
|
|
54
58
|
def initialize(configuration = Configuration.default)
|
55
59
|
@configuration = Configuration.new(configuration)
|
56
60
|
@support_code = SupportCode.new(self, @configuration)
|
57
|
-
@results = Formatter::LegacyApi::Results.new
|
58
61
|
end
|
59
62
|
|
60
63
|
# Allows you to take an existing runtime and change its configuration
|
@@ -63,17 +66,22 @@ module Cucumber
|
|
63
66
|
@support_code.configure(@configuration)
|
64
67
|
end
|
65
68
|
|
66
|
-
require 'cucumber/wire/plugin'
|
67
69
|
def run!
|
70
|
+
@configuration.notify :envelope, Cucumber::Messages::Envelope.new(
|
71
|
+
meta: MetaMessageBuilder.build_meta_message
|
72
|
+
)
|
73
|
+
|
68
74
|
load_step_definitions
|
69
|
-
|
70
|
-
|
75
|
+
fire_install_plugin_hook
|
76
|
+
fire_before_all_hook unless dry_run?
|
71
77
|
# TODO: can we remove this state?
|
72
78
|
self.visitor = report
|
73
79
|
|
74
80
|
receiver = Test::Runner.new(@configuration.event_bus)
|
75
|
-
compile features, receiver, filters
|
76
|
-
@configuration.notify :test_run_finished
|
81
|
+
compile features, receiver, filters, @configuration.event_bus
|
82
|
+
@configuration.notify :test_run_finished, !failure?
|
83
|
+
|
84
|
+
fire_after_all_hook unless dry_run?
|
77
85
|
end
|
78
86
|
|
79
87
|
def features_paths
|
@@ -84,14 +92,6 @@ module Cucumber
|
|
84
92
|
@configuration.dry_run?
|
85
93
|
end
|
86
94
|
|
87
|
-
def scenarios(status = nil)
|
88
|
-
@results.scenarios(status)
|
89
|
-
end
|
90
|
-
|
91
|
-
def steps(status = nil)
|
92
|
-
@results.steps(status)
|
93
|
-
end
|
94
|
-
|
95
95
|
def unmatched_step_definitions
|
96
96
|
@support_code.unmatched_step_definitions
|
97
97
|
end
|
@@ -107,14 +107,29 @@ module Cucumber
|
|
107
107
|
# Returns Ast::DocString for +string_without_triple_quotes+.
|
108
108
|
#
|
109
109
|
def doc_string(string_without_triple_quotes, content_type = '', _line_offset = 0)
|
110
|
-
|
111
|
-
|
110
|
+
Core::Test::DocString.new(string_without_triple_quotes, content_type)
|
111
|
+
end
|
112
|
+
|
113
|
+
def failure?
|
114
|
+
if @configuration.wip?
|
115
|
+
summary_report.test_cases.total_passed > 0
|
116
|
+
else
|
117
|
+
!summary_report.ok?(@configuration.strict)
|
118
|
+
end
|
112
119
|
end
|
113
120
|
|
114
121
|
private
|
115
122
|
|
116
|
-
def
|
117
|
-
@support_code.fire_hook(:
|
123
|
+
def fire_install_plugin_hook # :nodoc:
|
124
|
+
@support_code.fire_hook(:install_plugin, @configuration, registry_wrapper)
|
125
|
+
end
|
126
|
+
|
127
|
+
def fire_before_all_hook # :nodoc:
|
128
|
+
@support_code.fire_hook(:before_all)
|
129
|
+
end
|
130
|
+
|
131
|
+
def fire_after_all_hook # :nodoc:
|
132
|
+
@support_code.fire_hook(:after_all)
|
118
133
|
end
|
119
134
|
|
120
135
|
require 'cucumber/core/gherkin/document'
|
@@ -135,22 +150,20 @@ module Cucumber
|
|
135
150
|
end
|
136
151
|
|
137
152
|
class NormalisedEncodingFile
|
138
|
-
COMMENT_OR_EMPTY_LINE_PATTERN = /^\s*#|^\s*$/
|
139
|
-
ENCODING_PATTERN = /^\s*#\s*encoding\s*:\s*([^\s]+)/
|
153
|
+
COMMENT_OR_EMPTY_LINE_PATTERN = /^\s*#|^\s*$/ # :nodoc:
|
154
|
+
ENCODING_PATTERN = /^\s*#\s*encoding\s*:\s*([^\s]+)/ # :nodoc:
|
140
155
|
|
141
156
|
def self.read(path)
|
142
157
|
new(path).read
|
143
158
|
end
|
144
159
|
|
145
160
|
def initialize(path)
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
raise FeatureFolderNotFoundException.new(path)
|
153
|
-
end
|
161
|
+
@file = File.new(path)
|
162
|
+
set_encoding
|
163
|
+
rescue Errno::EACCES => e
|
164
|
+
raise FileNotFoundException.new(e, File.expand_path(path))
|
165
|
+
rescue Errno::ENOENT
|
166
|
+
raise FeatureFolderNotFoundException, path
|
154
167
|
end
|
155
168
|
|
156
169
|
def read
|
@@ -162,7 +175,7 @@ module Cucumber
|
|
162
175
|
def set_encoding
|
163
176
|
@file.each do |line|
|
164
177
|
if ENCODING_PATTERN =~ line
|
165
|
-
@file.set_encoding
|
178
|
+
@file.set_encoding Regexp.last_match(1)
|
166
179
|
break
|
167
180
|
end
|
168
181
|
break unless COMMENT_OR_EMPTY_LINE_PATTERN =~ line
|
@@ -171,16 +184,17 @@ module Cucumber
|
|
171
184
|
end
|
172
185
|
end
|
173
186
|
|
174
|
-
require 'cucumber/formatter/legacy_api/adapter'
|
175
|
-
require 'cucumber/formatter/legacy_api/runtime_facade'
|
176
|
-
require 'cucumber/formatter/legacy_api/results'
|
177
187
|
require 'cucumber/formatter/ignore_missing_messages'
|
178
188
|
require 'cucumber/formatter/fail_fast'
|
189
|
+
require 'cucumber/formatter/publish_banner_printer'
|
179
190
|
require 'cucumber/core/report/summary'
|
191
|
+
|
180
192
|
def report
|
181
193
|
return @report if @report
|
194
|
+
|
182
195
|
reports = [summary_report] + formatters
|
183
196
|
reports << fail_fast_report if @configuration.fail_fast?
|
197
|
+
reports << publish_banner_printer unless @configuration.publish_quiet?
|
184
198
|
@report ||= Formatter::Fanout.new(reports)
|
185
199
|
end
|
186
200
|
|
@@ -192,52 +206,36 @@ module Cucumber
|
|
192
206
|
@fail_fast_report ||= Formatter::FailFast.new(@configuration)
|
193
207
|
end
|
194
208
|
|
209
|
+
def publish_banner_printer
|
210
|
+
@publish_banner_printer ||= Formatter::PublishBannerPrinter.new(@configuration)
|
211
|
+
end
|
212
|
+
|
195
213
|
def formatters
|
196
214
|
@formatters ||=
|
197
|
-
@configuration.formatter_factories do |factory, formatter_options, path_or_io
|
198
|
-
create_formatter(factory, formatter_options, path_or_io
|
215
|
+
@configuration.formatter_factories do |factory, formatter_options, path_or_io|
|
216
|
+
create_formatter(factory, formatter_options, path_or_io)
|
199
217
|
end
|
200
218
|
end
|
201
219
|
|
202
|
-
def create_formatter(factory, formatter_options, path_or_io
|
203
|
-
if
|
204
|
-
if
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
220
|
+
def create_formatter(factory, formatter_options, path_or_io)
|
221
|
+
if accept_options?(factory)
|
222
|
+
return factory.new(@configuration, formatter_options) if path_or_io.nil?
|
223
|
+
|
224
|
+
factory.new(@configuration.with_options(out_stream: path_or_io),
|
225
|
+
formatter_options)
|
226
|
+
else
|
227
|
+
return factory.new(@configuration) if path_or_io.nil?
|
228
|
+
|
229
|
+
factory.new(@configuration.with_options(out_stream: path_or_io))
|
212
230
|
end
|
213
|
-
results = Formatter::LegacyApi::Results.new
|
214
|
-
runtime_facade = Formatter::LegacyApi::RuntimeFacade.new(results, @support_code, @configuration)
|
215
|
-
formatter = factory.new(runtime_facade, path_or_io, cli_options)
|
216
|
-
Formatter::LegacyApi::Adapter.new(
|
217
|
-
Formatter::IgnoreMissingMessages.new(formatter),
|
218
|
-
results, @configuration
|
219
|
-
)
|
220
231
|
end
|
221
232
|
|
222
233
|
def accept_options?(factory)
|
223
234
|
factory.instance_method(:initialize).arity > 1
|
224
235
|
end
|
225
236
|
|
226
|
-
def legacy_formatter?(factory)
|
227
|
-
factory.instance_method(:initialize).arity > 2
|
228
|
-
end
|
229
|
-
|
230
|
-
def failure?
|
231
|
-
if @configuration.wip?
|
232
|
-
summary_report.test_cases.total_passed > 0
|
233
|
-
else
|
234
|
-
!summary_report.ok?(@configuration.strict)
|
235
|
-
end
|
236
|
-
end
|
237
|
-
public :failure?
|
238
|
-
|
239
237
|
require 'cucumber/core/test/filters'
|
240
|
-
def filters
|
238
|
+
def filters # rubocop:disable Metrics/AbcSize
|
241
239
|
tag_expressions = @configuration.tag_expressions
|
242
240
|
name_regexps = @configuration.name_regexps
|
243
241
|
tag_limits = @configuration.tag_limits
|
@@ -250,14 +248,18 @@ module Cucumber
|
|
250
248
|
# TODO: can we just use Glue::RegistryAndMore's step definitions directly?
|
251
249
|
step_match_search = StepMatchSearch.new(@support_code.registry.method(:step_matches), @configuration)
|
252
250
|
filters << Filters::ActivateSteps.new(step_match_search, @configuration)
|
253
|
-
@configuration.filters.each
|
254
|
-
|
255
|
-
end
|
251
|
+
@configuration.filters.each { |filter| filters << filter }
|
252
|
+
|
256
253
|
unless configuration.dry_run?
|
257
254
|
filters << Filters::ApplyAfterStepHooks.new(@support_code)
|
258
255
|
filters << Filters::ApplyBeforeHooks.new(@support_code)
|
259
256
|
filters << Filters::ApplyAfterHooks.new(@support_code)
|
260
257
|
filters << Filters::ApplyAroundHooks.new(@support_code)
|
258
|
+
end
|
259
|
+
|
260
|
+
filters << Filters::BroadcastTestCaseReadyEvent.new(@configuration)
|
261
|
+
|
262
|
+
unless configuration.dry_run?
|
261
263
|
filters << Filters::BroadcastTestRunStartedEvent.new(@configuration)
|
262
264
|
filters << Filters::Quit.new
|
263
265
|
filters << Filters::Retry.new(@configuration)
|
@@ -272,8 +274,8 @@ module Cucumber
|
|
272
274
|
@support_code.load_files!(files)
|
273
275
|
end
|
274
276
|
|
275
|
-
def
|
276
|
-
Cucumber::
|
277
|
+
def registry_wrapper
|
278
|
+
Cucumber::Glue::RegistryWrapper.new(@support_code.registry)
|
277
279
|
end
|
278
280
|
|
279
281
|
def log
|
@@ -9,11 +9,12 @@ module Cucumber
|
|
9
9
|
attr_reader :regexp_source, :location
|
10
10
|
|
11
11
|
def initialize(regexp_source, location)
|
12
|
-
@regexp_source
|
12
|
+
@regexp_source = regexp_source
|
13
|
+
@location = location
|
13
14
|
end
|
14
15
|
|
15
|
-
def eql?(
|
16
|
-
regexp_source ==
|
16
|
+
def eql?(other)
|
17
|
+
regexp_source == other.regexp_source && location == other.location
|
17
18
|
end
|
18
19
|
|
19
20
|
def hash
|
@@ -8,8 +8,8 @@ module Cucumber
|
|
8
8
|
@support_code.load_files_from_paths(configuration.autoload_code_paths)
|
9
9
|
end
|
10
10
|
|
11
|
-
def to_json
|
12
|
-
@support_code.step_definitions.map(&:to_hash).to_json
|
11
|
+
def to_json(obj = nil)
|
12
|
+
@support_code.step_definitions.map(&:to_hash).to_json(obj)
|
13
13
|
end
|
14
14
|
end
|
15
15
|
end
|
data/lib/cucumber/step_match.rb
CHANGED
@@ -4,12 +4,15 @@ require 'cucumber/multiline_argument'
|
|
4
4
|
|
5
5
|
module Cucumber
|
6
6
|
# Represents the match found between a Test Step and its activation
|
7
|
-
class StepMatch
|
7
|
+
class StepMatch # :nodoc:
|
8
8
|
attr_reader :step_definition, :step_arguments
|
9
9
|
|
10
10
|
def initialize(step_definition, step_name, step_arguments)
|
11
11
|
raise "step_arguments can't be nil (but it can be an empty array)" if step_arguments.nil?
|
12
|
-
|
12
|
+
|
13
|
+
@step_definition = step_definition
|
14
|
+
@name_to_match = step_name
|
15
|
+
@step_arguments = step_arguments
|
13
16
|
end
|
14
17
|
|
15
18
|
def args
|
@@ -21,12 +24,12 @@ module Cucumber
|
|
21
24
|
|
22
25
|
def activate(test_step)
|
23
26
|
test_step.with_action(@step_definition.location) do
|
24
|
-
invoke(MultilineArgument.from_core(test_step.
|
27
|
+
invoke(MultilineArgument.from_core(test_step.multiline_arg))
|
25
28
|
end
|
26
29
|
end
|
27
30
|
|
28
31
|
def invoke(multiline_arg)
|
29
|
-
all_args =
|
32
|
+
all_args = args
|
30
33
|
multiline_arg.append_to(all_args)
|
31
34
|
@step_definition.invoke(all_args)
|
32
35
|
end
|
@@ -46,7 +49,7 @@ module Cucumber
|
|
46
49
|
#
|
47
50
|
# lambda { |param| "[#{param}]" }
|
48
51
|
#
|
49
|
-
def format_args(format =
|
52
|
+
def format_args(format = ->(a) { a }, &proc)
|
50
53
|
replace_arguments(@name_to_match, @step_arguments, format, &proc)
|
51
54
|
end
|
52
55
|
|
@@ -75,7 +78,7 @@ module Cucumber
|
|
75
78
|
|
76
79
|
replacement = if block_given?
|
77
80
|
yield(group.value)
|
78
|
-
elsif Proc
|
81
|
+
elsif Proc == format.class
|
79
82
|
format.call(group.value)
|
80
83
|
else
|
81
84
|
format % group.value
|
@@ -88,24 +91,18 @@ module Cucumber
|
|
88
91
|
s
|
89
92
|
end
|
90
93
|
|
91
|
-
def inspect
|
94
|
+
def inspect # :nodoc:
|
92
95
|
"#<#{self.class}: #{location}>"
|
93
96
|
end
|
94
|
-
|
95
|
-
private
|
96
|
-
|
97
|
-
def deep_clone_args
|
98
|
-
Marshal.load( Marshal.dump( args ) )
|
99
|
-
end
|
100
97
|
end
|
101
98
|
|
102
99
|
class SkippingStepMatch
|
103
100
|
def activate(test_step)
|
104
|
-
|
101
|
+
test_step.with_action { raise Core::Test::Result::Skipped }
|
105
102
|
end
|
106
103
|
end
|
107
104
|
|
108
|
-
class NoStepMatch
|
105
|
+
class NoStepMatch # :nodoc:
|
109
106
|
attr_reader :step_definition, :name
|
110
107
|
|
111
108
|
def initialize(step, name)
|
@@ -119,12 +116,12 @@ module Cucumber
|
|
119
116
|
|
120
117
|
def location
|
121
118
|
raise "No location for #{@step}" unless @step.location
|
119
|
+
|
122
120
|
@step.location
|
123
121
|
end
|
124
122
|
|
125
123
|
def file_colon_line
|
126
|
-
|
127
|
-
@step.file_colon_line
|
124
|
+
location.to_s
|
128
125
|
end
|
129
126
|
|
130
127
|
def backtrace_line
|
@@ -132,7 +129,7 @@ module Cucumber
|
|
132
129
|
end
|
133
130
|
|
134
131
|
def text_length
|
135
|
-
@step.
|
132
|
+
@step.text.length
|
136
133
|
end
|
137
134
|
|
138
135
|
def step_arguments
|
@@ -141,7 +138,7 @@ module Cucumber
|
|
141
138
|
|
142
139
|
def activate(test_step)
|
143
140
|
# noop
|
144
|
-
|
141
|
+
test_step
|
145
142
|
end
|
146
143
|
end
|
147
144
|
|
@@ -151,7 +148,7 @@ module Cucumber
|
|
151
148
|
end
|
152
149
|
|
153
150
|
def activate(test_step)
|
154
|
-
|
151
|
+
test_step.with_action { raise @error }
|
155
152
|
end
|
156
153
|
end
|
157
154
|
end
|
@@ -13,12 +13,14 @@ module Cucumber
|
|
13
13
|
|
14
14
|
class AssertUnambiguousMatch
|
15
15
|
def initialize(search, configuration)
|
16
|
-
@search
|
16
|
+
@search = search
|
17
|
+
@configuration = configuration
|
17
18
|
end
|
18
19
|
|
19
20
|
def call(step_name)
|
20
21
|
result = @search.call(step_name)
|
21
22
|
raise Cucumber::Ambiguous.new(step_name, result, @configuration.guess?) if result.length > 1
|
23
|
+
|
22
24
|
result
|
23
25
|
end
|
24
26
|
end
|
@@ -34,7 +36,7 @@ module Cucumber
|
|
34
36
|
|
35
37
|
private
|
36
38
|
|
37
|
-
def best_matches(_step_name, step_matches)
|
39
|
+
def best_matches(_step_name, step_matches) # :nodoc:
|
38
40
|
no_groups = step_matches.select { |step_match| step_match.args.empty? }
|
39
41
|
max_arg_length = step_matches.map { |step_match| step_match.args.length }.max
|
40
42
|
top_groups = step_matches.select { |step_match| step_match.args.length == max_arg_length }
|
@@ -53,7 +55,7 @@ module Cucumber
|
|
53
55
|
|
54
56
|
require 'delegate'
|
55
57
|
class CachesStepMatch < SimpleDelegator
|
56
|
-
def call(step_name)
|
58
|
+
def call(step_name) # :nodoc:
|
57
59
|
@match_cache ||= {}
|
58
60
|
|
59
61
|
matches = @match_cache[step_name]
|
@@ -2,8 +2,28 @@
|
|
2
2
|
|
3
3
|
module Cucumber
|
4
4
|
module Term
|
5
|
-
#
|
6
|
-
#
|
5
|
+
# This module allows to colorize text using ANSI escape sequences.
|
6
|
+
#
|
7
|
+
# Include the module in your class and use its methods to colorize text.
|
8
|
+
#
|
9
|
+
# Example:
|
10
|
+
#
|
11
|
+
# require 'cucumber/term/ansicolor'
|
12
|
+
#
|
13
|
+
# class MyFormatter
|
14
|
+
# include Cucumber::Term::ANSIColor
|
15
|
+
#
|
16
|
+
# def initialize(config)
|
17
|
+
# $stdout.puts yellow("Initializing formatter")
|
18
|
+
# $stdout.puts green("Coloring is active \o/") if Cucumber::Term::ANSIColor.coloring?
|
19
|
+
# $stdout.puts grey("Feature path:") + blue(bold(config.feature_dirs))
|
20
|
+
# end
|
21
|
+
# end
|
22
|
+
#
|
23
|
+
# To see what colours and effects are available, just run this in your shell:
|
24
|
+
#
|
25
|
+
# ruby -e "require 'rubygems'; require 'cucumber/term/ansicolor'; puts Cucumber::Term::ANSIColor.attributes"
|
26
|
+
#
|
7
27
|
module ANSIColor
|
8
28
|
# :stopdoc:
|
9
29
|
ATTRIBUTES = [
|
@@ -27,6 +47,7 @@ module Cucumber
|
|
27
47
|
[:magenta, 35],
|
28
48
|
[:cyan, 36],
|
29
49
|
[:white, 37],
|
50
|
+
[:grey, 90],
|
30
51
|
[:on_black, 40],
|
31
52
|
[:on_red, 41],
|
32
53
|
[:on_green, 42],
|
@@ -35,77 +56,80 @@ module Cucumber
|
|
35
56
|
[:on_magenta, 45],
|
36
57
|
[:on_cyan, 46],
|
37
58
|
[:on_white, 47]
|
38
|
-
]
|
59
|
+
].freeze
|
39
60
|
|
40
61
|
ATTRIBUTE_NAMES = ATTRIBUTES.transpose.first
|
41
62
|
# :startdoc:
|
42
63
|
|
43
|
-
# Returns true, if the coloring function of this module
|
44
|
-
# is switched on, false otherwise.
|
45
|
-
def self.coloring?
|
46
|
-
@coloring
|
47
|
-
end
|
48
|
-
|
49
|
-
# Turns the coloring on or off globally, so you can easily do
|
50
|
-
# this for example:
|
51
|
-
# Cucumber::Term::ANSIColor::coloring = STDOUT.isatty
|
52
|
-
def self.coloring=(val)
|
53
|
-
@coloring = val
|
54
|
-
end
|
55
|
-
self.coloring = true
|
56
|
-
|
57
|
-
ATTRIBUTES.each do |c, v|
|
58
|
-
eval %Q{
|
59
|
-
def #{c}(string = nil)
|
60
|
-
result = String.new
|
61
|
-
result << "\e[#{v}m" if Cucumber::Term::ANSIColor.coloring?
|
62
|
-
if block_given?
|
63
|
-
result << yield
|
64
|
-
elsif string
|
65
|
-
result << string
|
66
|
-
elsif respond_to?(:to_str)
|
67
|
-
result << to_str
|
68
|
-
else
|
69
|
-
return result #only switch on
|
70
|
-
end
|
71
|
-
result << "\e[0m" if Cucumber::Term::ANSIColor.coloring?
|
72
|
-
result
|
73
|
-
end
|
74
|
-
}
|
75
|
-
end
|
76
|
-
|
77
64
|
# Regular expression that is used to scan for ANSI-sequences while
|
78
65
|
# uncoloring strings.
|
79
66
|
COLORED_REGEXP = /\e\[(?:[34][0-7]|[0-9])?m/
|
80
67
|
|
81
|
-
|
82
|
-
|
68
|
+
@coloring = true
|
69
|
+
|
70
|
+
class << self
|
71
|
+
# Turns the coloring on or off globally, so you can easily do
|
72
|
+
# this for example:
|
73
|
+
# Cucumber::Term::ANSIColor::coloring = $stdout.isatty
|
74
|
+
attr_accessor :coloring
|
75
|
+
|
76
|
+
# Returns true, if the coloring function of this module
|
77
|
+
# is switched on, false otherwise.
|
78
|
+
alias coloring? :coloring
|
79
|
+
|
80
|
+
def included(klass)
|
81
|
+
return unless klass == String
|
82
|
+
|
83
83
|
ATTRIBUTES.delete(:clear)
|
84
84
|
ATTRIBUTE_NAMES.delete(:clear)
|
85
85
|
end
|
86
86
|
end
|
87
87
|
|
88
|
-
|
88
|
+
ATTRIBUTES.each do |color_name, color_code|
|
89
|
+
define_method(color_name) do |text = nil, &block|
|
90
|
+
if block
|
91
|
+
colorize(block.call, color_code)
|
92
|
+
elsif text
|
93
|
+
colorize(text, color_code)
|
94
|
+
elsif respond_to?(:to_str)
|
95
|
+
colorize(to_str, color_code)
|
96
|
+
else
|
97
|
+
colorize(nil, color_code) # switch coloration on
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
# Returns an uncolored version of the string
|
89
103
|
# ANSI-sequences are stripped from the string.
|
90
|
-
def uncolored(
|
104
|
+
def uncolored(text = nil)
|
91
105
|
if block_given?
|
92
|
-
yield
|
93
|
-
elsif
|
94
|
-
|
106
|
+
uncolorize(yield)
|
107
|
+
elsif text
|
108
|
+
uncolorize(text)
|
95
109
|
elsif respond_to?(:to_str)
|
96
|
-
to_str
|
110
|
+
uncolorize(to_str)
|
97
111
|
else
|
98
112
|
''
|
99
113
|
end
|
100
114
|
end
|
101
115
|
|
102
|
-
module_function
|
103
|
-
|
104
116
|
# Returns an array of all Cucumber::Term::ANSIColor attributes as symbols.
|
105
117
|
def attributes
|
106
118
|
ATTRIBUTE_NAMES
|
107
119
|
end
|
108
|
-
|
120
|
+
|
121
|
+
private
|
122
|
+
|
123
|
+
def colorize(text, color_code)
|
124
|
+
return String.new(text || '') unless Cucumber::Term::ANSIColor.coloring?
|
125
|
+
return "\e[#{color_code}m" unless text
|
126
|
+
|
127
|
+
"\e[#{color_code}m#{text}\e[0m"
|
128
|
+
end
|
129
|
+
|
130
|
+
def uncolorize(string)
|
131
|
+
string.gsub(COLORED_REGEXP, '')
|
132
|
+
end
|
109
133
|
end
|
110
134
|
end
|
111
135
|
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'cucumber/term/ansicolor'
|
2
|
+
|
3
|
+
module Cucumber
|
4
|
+
module Term
|
5
|
+
module Banner
|
6
|
+
def display_banner(lines, io, border_modifiers = nil)
|
7
|
+
BannerMaker.new.display_banner(lines, io, border_modifiers || %i[green bold])
|
8
|
+
end
|
9
|
+
|
10
|
+
class BannerMaker
|
11
|
+
include Term::ANSIColor
|
12
|
+
|
13
|
+
def display_banner(lines, io, border_modifiers)
|
14
|
+
lines = lines.split("\n") if lines.is_a? String
|
15
|
+
longest_line_length = lines.map { |line| line_length(line) }.max
|
16
|
+
|
17
|
+
io.puts apply_modifiers("┌#{'─' * (longest_line_length + 2)}┐", border_modifiers)
|
18
|
+
lines.map do |line|
|
19
|
+
padding = ' ' * (longest_line_length - line_length(line))
|
20
|
+
io.puts "#{apply_modifiers('│', border_modifiers)} #{display_line(line)}#{padding} #{apply_modifiers('│', border_modifiers)}"
|
21
|
+
end
|
22
|
+
io.puts apply_modifiers("└#{'─' * (longest_line_length + 2)}┘", border_modifiers)
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def display_line(line)
|
28
|
+
line.is_a?(Array) ? line.map { |span| display_span(span) }.join : line
|
29
|
+
end
|
30
|
+
|
31
|
+
def display_span(span)
|
32
|
+
return apply_modifiers(span.shift, span) if span.is_a?(Array)
|
33
|
+
|
34
|
+
span
|
35
|
+
end
|
36
|
+
|
37
|
+
def apply_modifiers(str, modifiers)
|
38
|
+
display = str
|
39
|
+
modifiers.each { |modifier| display = send(modifier, display) }
|
40
|
+
display
|
41
|
+
end
|
42
|
+
|
43
|
+
def line_length(line)
|
44
|
+
if line.is_a?(Array)
|
45
|
+
line.map { |span| span_length(span) }.sum
|
46
|
+
else
|
47
|
+
line.length
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def span_length(span)
|
52
|
+
span.is_a?(Array) ? span[0].length : span.length
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|