cucumber 7.0.0 → 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 +4 -4
- data/CHANGELOG.md +329 -170
- data/CONTRIBUTING.md +2 -6
- data/README.md +7 -5
- data/lib/autotest/cucumber_mixin.rb +5 -2
- data/lib/autotest/discover.rb +3 -2
- data/lib/cucumber/cli/configuration.rb +4 -1
- data/lib/cucumber/cli/main.rb +4 -3
- data/lib/cucumber/cli/options.rb +8 -2
- data/lib/cucumber/cli/profile_loader.rb +1 -5
- data/lib/cucumber/cli/rerun_file.rb +1 -1
- data/lib/cucumber/configuration.rb +5 -4
- data/lib/cucumber/constantize.rb +1 -1
- data/lib/cucumber/deprecate.rb +2 -1
- data/lib/cucumber/errors.rb +1 -1
- data/lib/cucumber/events/hook_test_step_created.rb +1 -2
- data/lib/cucumber/events/step_activated.rb +0 -6
- data/lib/cucumber/events/step_definition_registered.rb +0 -5
- data/lib/cucumber/events/test_case_created.rb +1 -2
- data/lib/cucumber/events/test_run_finished.rb +2 -1
- data/lib/cucumber/events/test_step_created.rb +1 -2
- data/lib/cucumber/events/undefined_parameter_type.rb +1 -2
- data/lib/cucumber/events.rb +2 -2
- data/lib/cucumber/file_specs.rb +2 -1
- data/lib/cucumber/filters/activate_steps.rb +1 -0
- data/lib/cucumber/filters/tag_limits/verifier.rb +1 -3
- data/lib/cucumber/filters/tag_limits.rb +1 -3
- data/lib/cucumber/formatter/ansicolor.rb +63 -63
- data/lib/cucumber/formatter/ast_lookup.rb +2 -2
- data/lib/cucumber/formatter/backtrace_filter.rb +2 -1
- data/lib/cucumber/formatter/console.rb +10 -2
- data/lib/cucumber/formatter/console_issues.rb +6 -1
- data/lib/cucumber/formatter/duration_extractor.rb +1 -0
- data/lib/cucumber/formatter/errors.rb +1 -0
- data/lib/cucumber/formatter/fanout.rb +1 -1
- data/lib/cucumber/formatter/http_io.rb +6 -1
- data/lib/cucumber/formatter/ignore_missing_messages.rb +1 -1
- data/lib/cucumber/formatter/io.rb +5 -3
- data/lib/cucumber/formatter/json.rb +8 -6
- data/lib/cucumber/formatter/junit.rb +6 -3
- data/lib/cucumber/formatter/message_builder.rb +3 -2
- data/lib/cucumber/formatter/pretty.rb +15 -5
- data/lib/cucumber/formatter/progress.rb +1 -0
- data/lib/cucumber/formatter/query/hook_by_test_step.rb +1 -0
- data/lib/cucumber/formatter/query/test_case_started_by_test_case.rb +2 -0
- data/lib/cucumber/formatter/rerun.rb +2 -0
- data/lib/cucumber/formatter/summary.rb +1 -0
- data/lib/cucumber/formatter/unicode.rb +4 -4
- data/lib/cucumber/formatter/usage.rb +3 -3
- data/lib/cucumber/gherkin/data_table_parser.rb +1 -0
- data/lib/cucumber/gherkin/formatter/ansi_escapes.rb +2 -2
- data/lib/cucumber/glue/dsl.rb +29 -15
- data/lib/cucumber/glue/hook.rb +6 -3
- data/lib/cucumber/glue/invoke_in_world.rb +4 -4
- data/lib/cucumber/glue/proto_world.rb +10 -9
- data/lib/cucumber/glue/registry_and_more.rb +22 -7
- data/lib/cucumber/glue/registry_wrapper.rb +31 -0
- data/lib/cucumber/glue/step_definition.rb +6 -3
- data/lib/cucumber/hooks.rb +1 -0
- data/lib/cucumber/multiline_argument/data_table/diff_matrices.rb +2 -1
- data/lib/cucumber/multiline_argument/data_table.rb +58 -71
- data/lib/cucumber/platform.rb +2 -2
- data/lib/cucumber/rake/task.rb +20 -9
- data/lib/cucumber/rspec/disable_option_parser.rb +6 -3
- data/lib/cucumber/running_test_case.rb +1 -0
- data/lib/cucumber/runtime/meta_message_builder.rb +106 -0
- data/lib/cucumber/runtime/support_code.rb +3 -0
- data/lib/cucumber/runtime/user_interface.rb +5 -4
- data/lib/cucumber/runtime.rb +36 -22
- data/lib/cucumber/step_match.rb +5 -3
- data/lib/cucumber/step_match_search.rb +3 -2
- data/lib/cucumber/term/ansicolor.rb +74 -50
- data/lib/cucumber/term/banner.rb +1 -0
- data/lib/cucumber/version +1 -1
- data/lib/cucumber.rb +2 -1
- data/lib/simplecov_setup.rb +1 -1
- metadata +96 -88
@@ -3,21 +3,48 @@
|
|
3
3
|
require 'cucumber/platform'
|
4
4
|
require 'cucumber/term/ansicolor'
|
5
5
|
|
6
|
-
Cucumber::Term::ANSIColor.coloring = false if
|
6
|
+
Cucumber::Term::ANSIColor.coloring = false if !$stdout.tty? && !ENV.key?('AUTOTEST')
|
7
7
|
|
8
8
|
module Cucumber
|
9
9
|
module Formatter
|
10
|
-
#
|
11
|
-
#
|
12
|
-
#
|
13
|
-
#
|
14
|
-
#
|
10
|
+
# This module allows to format cucumber related outputs using ANSI escape sequences.
|
11
|
+
#
|
12
|
+
# For example, it provides a `passed` method which returns the string with
|
13
|
+
# the ANSI escape sequence to format it green per default.
|
14
|
+
#
|
15
|
+
# To use this, include or extend it in your class.
|
16
|
+
#
|
17
|
+
# Example:
|
18
|
+
#
|
19
|
+
# require 'cucumber/formatter/ansicolor'
|
20
|
+
#
|
21
|
+
# class MyFormatter
|
22
|
+
# extend Cucumber::Term::ANSIColor
|
23
|
+
#
|
24
|
+
# def on_test_step_finished(event)
|
25
|
+
# $stdout.puts undefined(event.test_step) if event.result.undefined?
|
26
|
+
# $stdout.puts passed(event.test_step) if event.result.passed?
|
27
|
+
# end
|
28
|
+
# end
|
29
|
+
#
|
30
|
+
# This module also allows the user to customize the format of cucumber outputs
|
31
|
+
# using environment variables.
|
32
|
+
#
|
33
|
+
# For instance, if your shell has a black background and a green font (like the
|
34
|
+
# "Homebrew" settings for OS X' Terminal.app), you may want to override passed
|
35
|
+
# steps to be white instead of green.
|
36
|
+
#
|
37
|
+
# Example:
|
38
|
+
#
|
39
|
+
# export CUCUMBER_COLORS="passed=white,bold:passed_param=white,bold,underline"
|
15
40
|
#
|
16
41
|
# The colours that you can change are:
|
17
42
|
#
|
18
43
|
# * <tt>undefined</tt> - defaults to <tt>yellow</tt>
|
19
44
|
# * <tt>pending</tt> - defaults to <tt>yellow</tt>
|
20
45
|
# * <tt>pending_param</tt> - defaults to <tt>yellow,bold</tt>
|
46
|
+
# * <tt>flaky</tt> - defaults to <tt>yellow</tt>
|
47
|
+
# * <tt>flaky_param</tt> - defaults to <tt>yellow,bold</tt>
|
21
48
|
# * <tt>failed</tt> - defaults to <tt>red</tt>
|
22
49
|
# * <tt>failed_param</tt> - defaults to <tt>red,bold</tt>
|
23
50
|
# * <tt>passed</tt> - defaults to <tt>green</tt>
|
@@ -29,26 +56,18 @@ module Cucumber
|
|
29
56
|
# * <tt>comment</tt> - defaults to <tt>grey</tt>
|
30
57
|
# * <tt>tag</tt> - defaults to <tt>cyan</tt>
|
31
58
|
#
|
32
|
-
# For instance, if your shell has a black background and a green font (like the
|
33
|
-
# "Homebrew" settings for OS X' Terminal.app), you may want to override passed
|
34
|
-
# steps to be white instead of green.
|
35
|
-
#
|
36
|
-
# Although not listed, you can also use <tt>grey</tt>.
|
37
|
-
#
|
38
|
-
# Examples: (On Windows, use SET instead of export.)
|
39
|
-
#
|
40
|
-
# export CUCUMBER_COLORS="passed=white"
|
41
|
-
# export CUCUMBER_COLORS="passed=white,bold:passed_param=white,bold,underline"
|
42
|
-
#
|
43
59
|
# To see what colours and effects are available, just run this in your shell:
|
44
60
|
#
|
45
|
-
# ruby -e "require 'rubygems'; require 'term/ansicolor'; puts Cucumber::Term::ANSIColor.attributes"
|
61
|
+
# ruby -e "require 'rubygems'; require 'cucumber/term/ansicolor'; puts Cucumber::Term::ANSIColor.attributes"
|
46
62
|
#
|
47
63
|
module ANSIColor
|
48
64
|
include Cucumber::Term::ANSIColor
|
49
65
|
|
66
|
+
# :stopdoc:
|
50
67
|
ALIASES = Hash.new do |h, k|
|
51
|
-
|
68
|
+
next unless k.to_s =~ /(.*)_param/
|
69
|
+
|
70
|
+
"#{h[Regexp.last_match(1)]},bold"
|
52
71
|
end.merge(
|
53
72
|
'undefined' => 'yellow',
|
54
73
|
'pending' => 'yellow',
|
@@ -60,15 +79,22 @@ module Cucumber
|
|
60
79
|
'comment' => 'grey',
|
61
80
|
'tag' => 'cyan'
|
62
81
|
)
|
82
|
+
# :startdoc:
|
63
83
|
|
64
|
-
|
65
|
-
|
84
|
+
# Apply the custom color scheme
|
85
|
+
#
|
86
|
+
# example:
|
87
|
+
#
|
88
|
+
# apply_custom_colors('passed=white')
|
89
|
+
def apply_custom_colors(colors)
|
90
|
+
colors.split(':').each do |pair|
|
66
91
|
a = pair.split('=')
|
67
92
|
ALIASES[a[0]] = a[1]
|
68
93
|
end
|
69
94
|
end
|
95
|
+
apply_custom_colors(ENV['CUCUMBER_COLORS']) if ENV['CUCUMBER_COLORS']
|
70
96
|
|
71
|
-
#
|
97
|
+
# Define the color-named methods required by Term::ANSIColor.
|
72
98
|
#
|
73
99
|
# Examples:
|
74
100
|
#
|
@@ -80,53 +106,18 @@ module Cucumber
|
|
80
106
|
# red(bold(string, &proc)) + red
|
81
107
|
# end
|
82
108
|
ALIASES.each_key do |method_name|
|
83
|
-
next if method_name
|
84
|
-
code = <<-COLOR
|
85
|
-
def #{method_name}(string=nil, &proc)
|
86
|
-
#{ALIASES[method_name].split(',').join('(') + '(string, &proc' + ')' * ALIASES[method_name].split(',').length}
|
87
|
-
end
|
88
|
-
# This resets the colour to the non-param colour
|
89
|
-
def #{method_name}_param(string=nil, &proc)
|
90
|
-
#{ALIASES[method_name + '_param'].split(',').join('(') + '(string, &proc' + ')' * ALIASES[method_name + '_param'].split(',').length} + #{ALIASES[method_name].split(',').join(' + ')}
|
91
|
-
end
|
92
|
-
COLOR
|
93
|
-
eval(code) # rubocop:disable Security/Eval
|
94
|
-
end
|
109
|
+
next if method_name.end_with?('_param')
|
95
110
|
|
96
|
-
|
97
|
-
|
98
|
-
require 'terminfo'
|
99
|
-
case TermInfo.default_object.tigetnum('colors')
|
100
|
-
when 0
|
101
|
-
raise "Your terminal doesn't support colours."
|
102
|
-
when 1
|
103
|
-
::Cucumber::Term::ANSIColor.coloring = false
|
104
|
-
alias_method :grey, :white
|
105
|
-
when 2..8
|
106
|
-
alias_method :grey, :white # rubocop:disable Lint/DuplicateMethods
|
107
|
-
else
|
108
|
-
define_real_grey
|
109
|
-
end
|
110
|
-
rescue Exception => e # rubocop:disable Lint/RescueException
|
111
|
-
if e.class.name == 'TermInfo::TermInfoError'
|
112
|
-
STDERR.puts '*** WARNING ***'
|
113
|
-
STDERR.puts "You have the genki-ruby-terminfo gem installed, but you haven't set your TERM variable."
|
114
|
-
STDERR.puts 'Try setting it to TERM=xterm-256color to get grey colour in output.'
|
115
|
-
STDERR.puts "\n"
|
116
|
-
alias_method :grey, :white
|
117
|
-
else
|
118
|
-
define_real_grey
|
111
|
+
define_method(method_name) do |text = nil, &proc|
|
112
|
+
apply_styles(ALIASES[method_name], text, &proc)
|
119
113
|
end
|
120
|
-
end
|
121
114
|
|
122
|
-
|
123
|
-
|
124
|
-
::Cucumber::Term::ANSIColor.coloring? ? "\e[90m#{string}\e[0m" : string
|
115
|
+
define_method("#{method_name}_param") do |text = nil, &proc|
|
116
|
+
apply_styles(ALIASES["#{method_name}_param"], text, &proc) + apply_styles(ALIASES[method_name])
|
125
117
|
end
|
126
118
|
end
|
127
119
|
|
128
|
-
|
129
|
-
|
120
|
+
# :stopdoc:
|
130
121
|
def cukes(n)
|
131
122
|
('(::) ' * n).strip
|
132
123
|
end
|
@@ -142,6 +133,15 @@ module Cucumber
|
|
142
133
|
def yellow_cukes(n)
|
143
134
|
blink(yellow(cukes(n)))
|
144
135
|
end
|
136
|
+
# :startdoc:
|
137
|
+
|
138
|
+
private
|
139
|
+
|
140
|
+
def apply_styles(styles, text = nil, &proc)
|
141
|
+
styles.split(',').reverse.reduce(text) do |result, method_name|
|
142
|
+
send(method_name, result, &proc)
|
143
|
+
end
|
144
|
+
end
|
145
145
|
end
|
146
146
|
end
|
147
147
|
end
|
@@ -45,11 +45,11 @@ module Cucumber
|
|
45
45
|
break
|
46
46
|
end
|
47
47
|
break if node.previous_node.nil?
|
48
|
+
|
48
49
|
node = node.previous_node
|
49
50
|
end
|
50
51
|
keyword = dialect.given_keywords.reject { |kw| kw == '* ' }[0] if keyword.nil?
|
51
|
-
|
52
|
-
keyword
|
52
|
+
Cucumber::Gherkin::I18n.code_keyword_for(keyword)
|
53
53
|
end
|
54
54
|
|
55
55
|
ScenarioSource = Struct.new(:type, :scenario)
|
@@ -22,6 +22,7 @@ module Cucumber
|
|
22
22
|
@backtrace_filters << RbConfig::CONFIG['rubylibdir'] if RbConfig::CONFIG['rubylibdir']
|
23
23
|
|
24
24
|
@backtrace_filters << 'org/jruby/' if ::Cucumber::JRUBY
|
25
|
+
@backtrace_filters << '<internal:' if RUBY_ENGINE == 'truffleruby'
|
25
26
|
|
26
27
|
BACKTRACE_FILTER_PATTERNS = Regexp.new(@backtrace_filters.join('|'))
|
27
28
|
|
@@ -33,7 +34,7 @@ module Cucumber
|
|
33
34
|
def exception
|
34
35
|
return @exception if ::Cucumber.use_full_backtrace
|
35
36
|
|
36
|
-
pwd_pattern = /#{::Regexp.escape(::Dir.pwd)}\//m
|
37
|
+
pwd_pattern = /#{::Regexp.escape(::Dir.pwd)}\//m
|
37
38
|
backtrace = @exception.backtrace.map { |line| line.gsub(pwd_pattern, './') }
|
38
39
|
|
39
40
|
filtered = (backtrace || []).reject do |line|
|
@@ -34,7 +34,7 @@ module Cucumber
|
|
34
34
|
|
35
35
|
def format_step(keyword, step_match, status, source_indent)
|
36
36
|
comment = if source_indent
|
37
|
-
c = indent(
|
37
|
+
c = indent("# #{step_match.location}", source_indent)
|
38
38
|
format_string(c, :comment)
|
39
39
|
else
|
40
40
|
''
|
@@ -109,7 +109,10 @@ module Cucumber
|
|
109
109
|
# http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/10655
|
110
110
|
def linebreaks(msg, max)
|
111
111
|
return msg unless max && max > 0
|
112
|
-
|
112
|
+
|
113
|
+
msg.gsub(/.{1,#{max}}(?:\s|\Z)/) do
|
114
|
+
(Regexp.last_match(0) + 5.chr).gsub(/\n\005/, "\n").gsub(/\005/, "\n")
|
115
|
+
end.rstrip
|
113
116
|
end
|
114
117
|
|
115
118
|
def collect_snippet_data(test_step, ast_lookup)
|
@@ -150,6 +153,7 @@ module Cucumber
|
|
150
153
|
|
151
154
|
def print_passing_wip(config, passed_test_cases, ast_lookup)
|
152
155
|
return unless config.wip?
|
156
|
+
|
153
157
|
messages = passed_test_cases.map do |test_case|
|
154
158
|
scenario_source = ast_lookup.scenario_source(test_case)
|
155
159
|
keyword = scenario_source.type == :Scenario ? scenario_source.scenario.keyword : scenario_source.scenario_outline.keyword
|
@@ -170,6 +174,7 @@ module Cucumber
|
|
170
174
|
def attach(src, media_type)
|
171
175
|
return unless media_type == 'text/x.cucumber.log+plain'
|
172
176
|
return unless @io
|
177
|
+
|
173
178
|
@io.puts
|
174
179
|
@io.puts(format_string(src, :tag))
|
175
180
|
@io.flush
|
@@ -177,6 +182,7 @@ module Cucumber
|
|
177
182
|
|
178
183
|
def print_profile_information
|
179
184
|
return if @options[:skip_profile_information] || @options[:profiles].nil? || @options[:profiles].empty?
|
185
|
+
|
180
186
|
do_print_profile_information(@options[:profiles])
|
181
187
|
end
|
182
188
|
|
@@ -224,6 +230,7 @@ module Cucumber
|
|
224
230
|
key = keys.join('_').to_sym
|
225
231
|
fmt = FORMATS[key]
|
226
232
|
raise "No format for #{key.inspect}: #{FORMATS.inspect}" if fmt.nil?
|
233
|
+
|
227
234
|
fmt
|
228
235
|
end
|
229
236
|
|
@@ -246,6 +253,7 @@ module Cucumber
|
|
246
253
|
|
247
254
|
class SnippetData
|
248
255
|
attr_reader :actual_keyword, :step
|
256
|
+
|
249
257
|
def initialize(actual_keyword, step)
|
250
258
|
@actual_keyword = actual_keyword
|
251
259
|
@step = step
|
@@ -23,6 +23,7 @@ module Cucumber
|
|
23
23
|
|
24
24
|
def to_s
|
25
25
|
return if @issues.empty?
|
26
|
+
|
26
27
|
result = Core::Test::Result::TYPES.map { |type| scenario_listing(type, @issues[type]) }
|
27
28
|
result.flatten.join("\n")
|
28
29
|
end
|
@@ -35,6 +36,7 @@ module Cucumber
|
|
35
36
|
|
36
37
|
def scenario_listing(type, test_cases)
|
37
38
|
return [] if test_cases.empty?
|
39
|
+
|
38
40
|
[format_string("#{type_heading(type)} Scenarios:", type)] + test_cases.map do |test_case|
|
39
41
|
scenario_source = @ast_lookup.scenario_source(test_case)
|
40
42
|
keyword = scenario_source.type == :Scenario ? scenario_source.scenario.keyword : scenario_source.scenario_outline.keyword
|
@@ -54,7 +56,10 @@ module Cucumber
|
|
54
56
|
|
55
57
|
def profiles_string
|
56
58
|
return if @config.custom_profiles.empty?
|
57
|
-
|
59
|
+
|
60
|
+
profiles = @config.custom_profiles.map { |profile| "-p #{profile}" }.join(' ')
|
61
|
+
|
62
|
+
"#{profiles} "
|
58
63
|
end
|
59
64
|
end
|
60
65
|
end
|
@@ -21,7 +21,7 @@ module Cucumber
|
|
21
21
|
end
|
22
22
|
|
23
23
|
def respond_to_missing?(name, include_private = false)
|
24
|
-
recipients.any? { |recipient| recipient.respond_to?(name, include_private) }
|
24
|
+
recipients.any? { |recipient| recipient.respond_to?(name, include_private) } || super(name, include_private)
|
25
25
|
end
|
26
26
|
end
|
27
27
|
end
|
@@ -35,6 +35,7 @@ module Cucumber
|
|
35
35
|
headers = headers.merge(parse_header(header_arg))
|
36
36
|
else
|
37
37
|
raise StandardError, "#{options} was not a valid curl command. Can't set url to #{arg} it is already set to #{url}" if url
|
38
|
+
|
38
39
|
url = arg
|
39
40
|
end
|
40
41
|
end
|
@@ -49,12 +50,14 @@ module Cucumber
|
|
49
50
|
|
50
51
|
def self.remove_arg_for(args, arg)
|
51
52
|
return args.shift unless args.empty?
|
53
|
+
|
52
54
|
raise StandardError, "Missing argument for #{arg}"
|
53
55
|
end
|
54
56
|
|
55
57
|
def self.parse_header(header_arg)
|
56
58
|
parts = header_arg.split(':', 2)
|
57
59
|
raise StandardError, "#{header_arg} was not a valid header" unless parts.length == 2
|
60
|
+
|
58
61
|
{ parts[0].strip => parts[1].strip }
|
59
62
|
end
|
60
63
|
end
|
@@ -76,6 +79,7 @@ module Cucumber
|
|
76
79
|
@reporter.report(response.body)
|
77
80
|
@write_io.close
|
78
81
|
return if response.is_a?(Net::HTTPSuccess) || response.is_a?(Net::HTTPRedirection)
|
82
|
+
|
79
83
|
raise StandardError, "request to #{uri} failed with status #{response.code}"
|
80
84
|
end
|
81
85
|
|
@@ -98,6 +102,7 @@ module Cucumber
|
|
98
102
|
http = build_client(uri, @https_verify_mode)
|
99
103
|
|
100
104
|
raise StandardError, "request to #{uri} failed (too many redirections)" if attempt <= 0
|
105
|
+
|
101
106
|
req = build_request(
|
102
107
|
uri,
|
103
108
|
method,
|
@@ -126,7 +131,7 @@ module Cucumber
|
|
126
131
|
end
|
127
132
|
|
128
133
|
def build_request(uri, method, headers)
|
129
|
-
method_class_name = "#{method[0].upcase}#{method[1
|
134
|
+
method_class_name = "#{method[0].upcase}#{method[1..].downcase}"
|
130
135
|
req = Net::HTTP.const_get(method_class_name).new(uri)
|
131
136
|
headers.each do |header, value|
|
132
137
|
req[header] = value
|
@@ -57,19 +57,21 @@ module Cucumber
|
|
57
57
|
end
|
58
58
|
|
59
59
|
def url?(path_or_url_or_io)
|
60
|
-
path_or_url_or_io.match(
|
60
|
+
path_or_url_or_io.match(/^https?:\/\//)
|
61
61
|
end
|
62
62
|
|
63
63
|
def ensure_file(path, name)
|
64
|
-
raise "You *must* specify --out FILE for the #{name} formatter" unless
|
64
|
+
raise "You *must* specify --out FILE for the #{name} formatter" unless path.instance_of? String
|
65
65
|
raise "I can't write #{name} to a directory - it has to be a file" if File.directory?(path)
|
66
66
|
raise "I can't write #{name} to a file in the non-existing directory #{File.dirname(path)}" unless File.directory?(File.dirname(path))
|
67
|
+
|
67
68
|
ensure_io(path, nil)
|
68
69
|
end
|
69
70
|
|
70
71
|
def ensure_dir(path, name)
|
71
|
-
raise "You *must* specify --out DIR for the #{name} formatter" unless
|
72
|
+
raise "You *must* specify --out DIR for the #{name} formatter" unless path.instance_of? String
|
72
73
|
raise "I can't write #{name} reports to a file - it has to be a directory" if File.file?(path)
|
74
|
+
|
73
75
|
FileUtils.mkdir_p(path) unless File.directory?(path)
|
74
76
|
File.absolute_path path
|
75
77
|
end
|
@@ -68,6 +68,7 @@ module Cucumber
|
|
68
68
|
test_step, result = *event.attributes
|
69
69
|
result = result.with_filtered_backtrace(Cucumber::Formatter::BacktraceFilter)
|
70
70
|
return if internal_hook?(test_step)
|
71
|
+
|
71
72
|
add_match_and_result(test_step, result)
|
72
73
|
@any_step_failed = true if result.failed?
|
73
74
|
end
|
@@ -81,7 +82,7 @@ module Cucumber
|
|
81
82
|
end
|
82
83
|
|
83
84
|
def on_test_run_finished(_event)
|
84
|
-
@io.write(JSON.
|
85
|
+
@io.write(JSON.pretty_generate(@feature_hashes))
|
85
86
|
end
|
86
87
|
|
87
88
|
def attach(src, mime_type)
|
@@ -105,7 +106,7 @@ module Cucumber
|
|
105
106
|
end
|
106
107
|
|
107
108
|
def first_step_after_background?(test_step)
|
108
|
-
@in_background && test_step.location.lines.max >= @test_case_hash[:line]
|
109
|
+
@in_background && test_step.location.file == @feature_hash[:uri] && test_step.location.lines.max >= @test_case_hash[:line]
|
109
110
|
end
|
110
111
|
|
111
112
|
def internal_hook?(test_step)
|
@@ -133,7 +134,7 @@ module Cucumber
|
|
133
134
|
when 'AfterStep hook'
|
134
135
|
after_step_hooks
|
135
136
|
else
|
136
|
-
raise
|
137
|
+
raise "Unknown hook type #{hook_step}"
|
137
138
|
end
|
138
139
|
end
|
139
140
|
|
@@ -175,15 +176,15 @@ module Cucumber
|
|
175
176
|
name: test_step.text,
|
176
177
|
line: test_step.location.lines.min
|
177
178
|
}
|
178
|
-
step_hash[:doc_string] = create_doc_string_hash(step_source.doc_string) unless step_source.doc_string.nil?
|
179
|
+
step_hash[:doc_string] = create_doc_string_hash(step_source.doc_string, test_step.multiline_arg.content) unless step_source.doc_string.nil?
|
179
180
|
step_hash[:rows] = create_data_table_value(step_source.data_table) unless step_source.data_table.nil?
|
180
181
|
step_hash
|
181
182
|
end
|
182
183
|
|
183
|
-
def create_doc_string_hash(doc_string)
|
184
|
+
def create_doc_string_hash(doc_string, doc_string_content)
|
184
185
|
content_type = doc_string.media_type || ''
|
185
186
|
{
|
186
|
-
value:
|
187
|
+
value: doc_string_content,
|
187
188
|
content_type: content_type,
|
188
189
|
line: doc_string.location.line
|
189
190
|
}
|
@@ -259,6 +260,7 @@ module Cucumber
|
|
259
260
|
line: feature.location.line
|
260
261
|
}
|
261
262
|
return if feature.tags.empty?
|
263
|
+
|
262
264
|
@feature_hash[:tags] = create_tags_array_from_hash_array(feature.tags)
|
263
265
|
end
|
264
266
|
|
@@ -84,6 +84,7 @@ module Cucumber
|
|
84
84
|
uri = test_case.location.file
|
85
85
|
feature = @ast_lookup.gherkin_document(uri).feature
|
86
86
|
raise UnNamedFeatureError, uri if feature.name.empty?
|
87
|
+
|
87
88
|
@current_feature_data = @features_data[uri]
|
88
89
|
@current_feature_data[:uri] = uri unless @current_feature_data[:uri]
|
89
90
|
@current_feature_data[:feature] = feature unless @current_feature_data[:feature]
|
@@ -111,6 +112,7 @@ module Cucumber
|
|
111
112
|
keyword = scenario_source.type == :Scenario ? scenario_source.scenario.keyword : scenario_source.scenario_outline.keyword
|
112
113
|
output = "#{keyword}: #{scenario}\n\n"
|
113
114
|
return output if result.ok?(@config.strict)
|
115
|
+
|
114
116
|
if scenario_source.type == :Scenario
|
115
117
|
if @failing_test_step
|
116
118
|
if @failing_test_step.hook?
|
@@ -125,7 +127,7 @@ module Cucumber
|
|
125
127
|
else
|
126
128
|
output += "Example row: #{row_name}\n"
|
127
129
|
end
|
128
|
-
output
|
130
|
+
"#{output}\nMessage:\n"
|
129
131
|
end
|
130
132
|
|
131
133
|
def build_testcase(result, scenario_designation, output)
|
@@ -191,7 +193,7 @@ module Cucumber
|
|
191
193
|
end
|
192
194
|
|
193
195
|
def basename(feature_file)
|
194
|
-
File.basename(feature_file.gsub(/[\\\/]/, '-'), '.feature')
|
196
|
+
File.basename(feature_file.gsub(/[\\\/]/, '-'), '.feature')
|
195
197
|
end
|
196
198
|
|
197
199
|
def write_file(feature_filename, data)
|
@@ -228,13 +230,14 @@ module Cucumber
|
|
228
230
|
end
|
229
231
|
|
230
232
|
def examples_table_row(row)
|
231
|
-
@row_name =
|
233
|
+
@row_name = "| #{row.cells.map(&:value).join(' | ')} |"
|
232
234
|
@name_suffix = " (outline example : #{@row_name})"
|
233
235
|
end
|
234
236
|
end
|
235
237
|
|
236
238
|
class ResultBuilder
|
237
239
|
attr_reader :test_case_duration
|
240
|
+
|
238
241
|
def initialize(result)
|
239
242
|
@test_case_duration = 0
|
240
243
|
result.describe_to(self)
|
@@ -226,10 +226,11 @@ module Cucumber
|
|
226
226
|
output_envelope(message)
|
227
227
|
end
|
228
228
|
|
229
|
-
def on_test_run_finished(
|
229
|
+
def on_test_run_finished(event)
|
230
230
|
message = Cucumber::Messages::Envelope.new(
|
231
231
|
test_run_finished: Cucumber::Messages::TestRunFinished.new(
|
232
|
-
timestamp: time_to_timestamp(Time.now)
|
232
|
+
timestamp: time_to_timestamp(Time.now),
|
233
|
+
success: event.success
|
233
234
|
)
|
234
235
|
)
|
235
236
|
|
@@ -24,11 +24,9 @@ module Cucumber
|
|
24
24
|
include Console
|
25
25
|
include Io
|
26
26
|
include Cucumber::Gherkin::Formatter::Escaping
|
27
|
-
attr_reader :config, :options
|
27
|
+
attr_reader :config, :options, :current_feature_uri, :current_scenario_outline, :current_examples, :current_test_case, :in_scenario_outline, :print_background_steps
|
28
28
|
private :config, :options
|
29
|
-
attr_reader :current_feature_uri, :current_scenario_outline, :current_examples, :current_test_case
|
30
29
|
private :current_feature_uri, :current_scenario_outline, :current_examples, :current_test_case
|
31
|
-
attr_reader :in_scenario_outline, :print_background_steps
|
32
30
|
private :in_scenario_outline, :print_background_steps
|
33
31
|
|
34
32
|
def initialize(config)
|
@@ -105,16 +103,19 @@ module Cucumber
|
|
105
103
|
|
106
104
|
def on_test_step_started(event)
|
107
105
|
return if event.test_step.hook?
|
106
|
+
|
108
107
|
print_step_header(current_test_case) if first_step_after_printing_background_steps?(event.test_step)
|
109
108
|
end
|
110
109
|
|
111
110
|
def on_test_step_finished(event)
|
112
111
|
collect_snippet_data(event.test_step, @ast_lookup) if event.result.undefined?
|
113
112
|
return if in_scenario_outline && !options[:expand]
|
113
|
+
|
114
114
|
exception_to_be_printed = find_exception_to_be_printed(event.result)
|
115
115
|
print_step_data(event.test_step, event.result) if print_step_data?(event, exception_to_be_printed)
|
116
116
|
print_step_output
|
117
117
|
return unless exception_to_be_printed
|
118
|
+
|
118
119
|
print_exception(exception_to_be_printed, event.result.to_sym, 6)
|
119
120
|
@exceptions << exception_to_be_printed
|
120
121
|
end
|
@@ -127,6 +128,7 @@ module Cucumber
|
|
127
128
|
else
|
128
129
|
exception_to_be_printed = find_exception_to_be_printed(event.result)
|
129
130
|
return unless exception_to_be_printed
|
131
|
+
|
130
132
|
print_exception(exception_to_be_printed, event.result.to_sym, 6)
|
131
133
|
@exceptions << exception_to_be_printed
|
132
134
|
end
|
@@ -140,6 +142,7 @@ module Cucumber
|
|
140
142
|
|
141
143
|
def attach(src, media_type)
|
142
144
|
return unless media_type == 'text/x.cucumber.log+plain'
|
145
|
+
|
143
146
|
@test_step_output.push src
|
144
147
|
end
|
145
148
|
|
@@ -147,9 +150,11 @@ module Cucumber
|
|
147
150
|
|
148
151
|
def find_exception_to_be_printed(result)
|
149
152
|
return nil if result.ok?(options[:strict])
|
153
|
+
|
150
154
|
result = result.with_filtered_backtrace(Cucumber::Formatter::BacktraceFilter)
|
151
155
|
exception = result.failed? ? result.exception : result
|
152
156
|
return nil if @exceptions.include?(exception)
|
157
|
+
|
153
158
|
exception
|
154
159
|
end
|
155
160
|
|
@@ -196,6 +201,7 @@ module Cucumber
|
|
196
201
|
def feature_has_background?
|
197
202
|
feature_children = gherkin_document.feature.children
|
198
203
|
return false if feature_children.empty?
|
204
|
+
|
199
205
|
!feature_children.first.background.nil?
|
200
206
|
end
|
201
207
|
|
@@ -239,6 +245,7 @@ module Cucumber
|
|
239
245
|
def first_step_after_printing_background_steps?(test_step)
|
240
246
|
return false unless print_background_steps
|
241
247
|
return false unless test_step.location.lines.max >= current_test_case.location.lines.max
|
248
|
+
|
242
249
|
@print_background_steps = false
|
243
250
|
true
|
244
251
|
end
|
@@ -262,7 +269,8 @@ module Cucumber
|
|
262
269
|
def print_comments(up_to_line, indent_amount)
|
263
270
|
comments = gherkin_document.comments
|
264
271
|
return if comments.empty? || comments.length <= @next_comment_to_be_printed
|
265
|
-
|
272
|
+
|
273
|
+
comments[@next_comment_to_be_printed..].each do |comment|
|
266
274
|
if comment.location.line <= up_to_line
|
267
275
|
@io.puts(indent(format_string(comment.text.strip, :comment), indent_amount))
|
268
276
|
@next_comment_to_be_printed += 1
|
@@ -294,6 +302,7 @@ module Cucumber
|
|
294
302
|
|
295
303
|
def print_description(description)
|
296
304
|
return unless description
|
305
|
+
|
297
306
|
description.split("\n").each do |line|
|
298
307
|
@io.puts(line)
|
299
308
|
end
|
@@ -398,6 +407,7 @@ module Cucumber
|
|
398
407
|
end
|
399
408
|
@io.puts
|
400
409
|
next if options[:no_multiline]
|
410
|
+
|
401
411
|
print_doc_string(step.doc_string.content, :skipped, 6) unless step.doc_string.nil?
|
402
412
|
print_data_table(step.data_table, :skipped, 6) unless step.data_table.nil?
|
403
413
|
end
|
@@ -445,7 +455,7 @@ module Cucumber
|
|
445
455
|
language = ::Gherkin::Dialect.for(language_code)
|
446
456
|
scenario_keyword = language.scenario_keywords[0]
|
447
457
|
row = scenario_source(test_case).row
|
448
|
-
expanded_name =
|
458
|
+
expanded_name = "| #{row.cells.map(&:value).join(' | ')} |"
|
449
459
|
@source_indent = calculate_source_indent_for_expanded_test_case(test_case, scenario_keyword, expanded_name)
|
450
460
|
@io.puts
|
451
461
|
print_keyword_name(scenario_keyword, expanded_name, 6, test_case.location)
|
@@ -58,6 +58,7 @@ module Cucumber
|
|
58
58
|
progress(result.to_sym) if !test_step.hook? || result.failed?
|
59
59
|
|
60
60
|
return if test_step.hook?
|
61
|
+
|
61
62
|
collect_snippet_data(test_step, @ast_lookup) if result.undefined?
|
62
63
|
@pending_step_matches << @matches[test_step.to_s] if result.pending?
|
63
64
|
@failed_results << result if result.failed?
|
@@ -13,6 +13,7 @@ module Cucumber
|
|
13
13
|
|
14
14
|
def hook_id(test_step)
|
15
15
|
return @hook_id_by_test_step_id[test_step.id] if @hook_id_by_test_step_id.key?(test_step.id)
|
16
|
+
|
16
17
|
raise TestStepUnknownError, "No hook found for #{test_step.id} }. Known: #{@hook_id_by_test_step_id.keys}"
|
17
18
|
end
|
18
19
|
|