cucumber 4.0.0.rc.4 → 4.0.0.rc.5
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 +12 -1
- data/README.md +2 -2
- data/lib/cucumber/cli/options.rb +9 -3
- data/lib/cucumber/formatter/html.rb +24 -0
- data/lib/cucumber/formatter/http_io.rb +93 -0
- data/lib/cucumber/formatter/io.rb +14 -8
- data/lib/cucumber/formatter/json.rb +2 -2
- data/lib/cucumber/formatter/message.rb +3 -227
- data/lib/cucumber/formatter/message_builder.rb +241 -0
- data/lib/cucumber/runtime.rb +0 -1
- data/lib/cucumber/version +1 -1
- metadata +49 -66
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 388c05be14607a5aaa4acaef66d2bb5f6dab1258bc3e785e71a077fae3d366a7
|
4
|
+
data.tar.gz: 2546749fa602b12b756e0dee45ff756fc89507329504b94f633b39cd5692464e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ed762cc475552e7698cf9ebae51b00366f88f000fcbbbd9697bfa1056a2ec7a7a9d49bb946e0f785d8c1d435da443bd2cca834a2309a11403836dc11f93de169
|
7
|
+
data.tar.gz: 112fb462eb9a3bdb1056c3ad32670ad1160ad0f40a6b804bc09b5e948443073df55a8b6c2818c0cb8f7794623b8e71f04d913a1559bb0b69536cc7bf7634873c
|
data/CHANGELOG.md
CHANGED
@@ -9,9 +9,20 @@ This document is formatted according to the principles of [Keep A CHANGELOG](htt
|
|
9
9
|
Please visit [cucumber/CONTRIBUTING.md](https://github.com/cucumber/cucumber/blob/master/CONTRIBUTING.md) for more info on how to contribute to Cucumber.
|
10
10
|
|
11
11
|
----
|
12
|
+
## [4.0.0.rc.5](https://github.com/cucumber/cucumber-ruby/compare/v4.0.0.rc.4...4.0.0.rc.5)
|
12
13
|
|
13
|
-
|
14
|
+
### Added
|
15
|
+
|
16
|
+
* New html formatter enabled by option `--format html --out report.html`.
|
14
17
|
|
18
|
+
* Accept `--out URL` to POST results to a web server
|
19
|
+
If a URL is used as output, the output will be sent with a POST request.
|
20
|
+
This can be overridden by specifying e.g. `http-method=PUT` as a query parameter.
|
21
|
+
Other `http-` prefixed query parameters will be converted to request headers
|
22
|
+
(with the `http-` prefix stripped off).
|
23
|
+
|
24
|
+
|
25
|
+
## [4.0.0.rc.4](https://github.com/cucumber/cucumber-ruby/compare/v4.0.0.rc.3...4.0.0.rc.4)
|
15
26
|
|
16
27
|
### Added
|
17
28
|
|
data/README.md
CHANGED
@@ -15,7 +15,7 @@ your team.
|
|
15
15
|
|
16
16
|
Where to get more info:
|
17
17
|
|
18
|
-
* The main website: https://cucumber.io/
|
18
|
+
* The main website: https://cucumber.io/
|
19
19
|
* Documentation: https://cucumber.io/docs
|
20
20
|
* Ruby API Documentation: http://www.rubydoc.info/github/cucumber/cucumber-ruby/
|
21
21
|
* Support forum: https://groups.google.com/group/cukes
|
@@ -28,7 +28,7 @@ See [CONTRIBUTING.md](CONTRIBUTING.md) for info on contributing to Cucumber.
|
|
28
28
|
* Ruby 2.5
|
29
29
|
* Ruby 2.4
|
30
30
|
* Ruby 2.3
|
31
|
-
* JRuby 9.
|
31
|
+
* JRuby 9.2 (with [some limitations](https://github.com/cucumber/cucumber-ruby/blob/master/docs/jruby-limitations.md))
|
32
32
|
|
33
33
|
## Code of Conduct
|
34
34
|
|
data/lib/cucumber/cli/options.rb
CHANGED
@@ -24,6 +24,7 @@ module Cucumber
|
|
24
24
|
'junit' => ['Cucumber::Formatter::Junit', 'Generates a report similar to Ant+JUnit.'],
|
25
25
|
'json' => ['Cucumber::Formatter::Json', '[DEPRECATED] Prints the feature as JSON'],
|
26
26
|
'message' => ['Cucumber::Formatter::Message', 'Outputs protobuf messages'],
|
27
|
+
'html' => ['Cucumber::Formatter::HTML', 'Outputs HTML report'],
|
27
28
|
'summary' => ['Cucumber::Formatter::Summary', 'Summary output of feature and scenarios']
|
28
29
|
}.freeze
|
29
30
|
max = BUILTIN_FORMATS.keys.map(&:length).max
|
@@ -104,7 +105,7 @@ module Cucumber
|
|
104
105
|
add_option :formats, [*parse_formats(v), @out_stream]
|
105
106
|
end
|
106
107
|
opts.on('--init', *init_msg) { |_v| initialize_project }
|
107
|
-
opts.on('-o', '--out [FILE|DIR]', *out_msg) { |v| out_stream v }
|
108
|
+
opts.on('-o', '--out [FILE|DIR|URL]', *out_msg) { |v| out_stream v }
|
108
109
|
opts.on('-t TAG_EXPRESSION', '--tags TAG_EXPRESSION', *tags_msg) { |v| add_tag v }
|
109
110
|
opts.on('-n NAME', '--name NAME', *name_msg) { |v| add_option :name_regexps, /#{v}/ }
|
110
111
|
opts.on('-e', '--exclude PATTERN', *exclude_msg) { |v| add_option :excludes, Regexp.new(v) }
|
@@ -295,10 +296,15 @@ Specify SEED to reproduce the shuffling from a previous run.
|
|
295
296
|
|
296
297
|
def out_msg
|
297
298
|
[
|
298
|
-
'Write output to a file/directory instead of STDOUT. This option',
|
299
|
+
'Write output to a file/directory/URL instead of STDOUT. This option',
|
299
300
|
'applies to the previously specified --format, or the',
|
300
301
|
'default format if no format is specified. Check the specific',
|
301
|
-
"formatter's docs to see whether to pass a file or
|
302
|
+
"formatter's docs to see whether to pass a file, dir or URL.",
|
303
|
+
"\n",
|
304
|
+
'When using a URL, the output of the formatter will be sent as the HTTP request body.',
|
305
|
+
'HTTP headers and request method can be set with http- prefixed query parameters,',
|
306
|
+
'for example ?http-content-type=application/json&http-method=PUT.',
|
307
|
+
'All http- prefixed query parameters will be removed from the sent query parameters.'
|
302
308
|
]
|
303
309
|
end
|
304
310
|
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'cucumber/formatter/io'
|
2
|
+
require 'cucumber/html_formatter'
|
3
|
+
require 'cucumber/formatter/message_builder'
|
4
|
+
|
5
|
+
module Cucumber
|
6
|
+
module Formatter
|
7
|
+
class HTML < MessageBuilder
|
8
|
+
include Io
|
9
|
+
|
10
|
+
def initialize(config)
|
11
|
+
@io = ensure_io(config.out_stream)
|
12
|
+
@html_formatter = Cucumber::HTMLFormatter::Formatter.new(@io)
|
13
|
+
@html_formatter.write_pre_message
|
14
|
+
|
15
|
+
super(config)
|
16
|
+
end
|
17
|
+
|
18
|
+
def output_envelope(envelope)
|
19
|
+
@html_formatter.write_message(envelope)
|
20
|
+
@html_formatter.write_post_message if envelope.test_run_finished
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
|
3
|
+
module Cucumber
|
4
|
+
module Formatter
|
5
|
+
class HTTPIO
|
6
|
+
class << self
|
7
|
+
# Returns an IO that will write to a HTTP request's body
|
8
|
+
def open(url, https_verify_mode = nil)
|
9
|
+
@https_verify_mode = https_verify_mode
|
10
|
+
uri, method, headers = build_uri_method_headers(url)
|
11
|
+
|
12
|
+
@req = build_request(uri, method, headers)
|
13
|
+
@http = build_client(uri, https_verify_mode)
|
14
|
+
|
15
|
+
read_io, write_io = IO.pipe
|
16
|
+
@req.body_stream = read_io
|
17
|
+
|
18
|
+
class << write_io
|
19
|
+
attr_writer :request_thread
|
20
|
+
|
21
|
+
def start_request(http, req)
|
22
|
+
@req_thread = Thread.new do
|
23
|
+
begin
|
24
|
+
res = http.request(req)
|
25
|
+
raise StandardError, "request to #{req.uri} failed with status #{res.code}" if res.code.to_i >= 400
|
26
|
+
rescue StandardError => e
|
27
|
+
@http_error = e
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def close
|
33
|
+
super
|
34
|
+
begin
|
35
|
+
@req_thread.join
|
36
|
+
rescue StandardError
|
37
|
+
nil
|
38
|
+
end
|
39
|
+
raise @http_error unless @http_error.nil?
|
40
|
+
end
|
41
|
+
end
|
42
|
+
write_io.start_request(@http, @req)
|
43
|
+
|
44
|
+
write_io
|
45
|
+
end
|
46
|
+
|
47
|
+
def build_uri_method_headers(url)
|
48
|
+
uri = URI(url)
|
49
|
+
query_pairs = uri.query ? URI.decode_www_form(uri.query) : []
|
50
|
+
|
51
|
+
# Build headers from query parameters prefixed with http- and extract HTTP method
|
52
|
+
http_query_pairs = query_pairs.select { |pair| pair[0] =~ /^http-/ }
|
53
|
+
http_query_hash_without_prefix = Hash[http_query_pairs.map do |pair|
|
54
|
+
[
|
55
|
+
pair[0][5..-1].downcase, # remove http- prefix
|
56
|
+
pair[1]
|
57
|
+
]
|
58
|
+
end]
|
59
|
+
method = http_query_hash_without_prefix.delete('method') || 'POST'
|
60
|
+
headers = {
|
61
|
+
'transfer-encoding' => 'chunked'
|
62
|
+
}.merge(http_query_hash_without_prefix)
|
63
|
+
|
64
|
+
# Update the query with the http-* parameters removed
|
65
|
+
remaining_query_pairs = query_pairs - http_query_pairs
|
66
|
+
new_query_hash = Hash[remaining_query_pairs]
|
67
|
+
uri.query = URI.encode_www_form(new_query_hash) unless new_query_hash.empty?
|
68
|
+
[uri, method, headers]
|
69
|
+
end
|
70
|
+
|
71
|
+
private
|
72
|
+
|
73
|
+
def build_request(uri, method, headers)
|
74
|
+
method_class_name = "#{method[0].upcase}#{method[1..-1].downcase}"
|
75
|
+
req = Net::HTTP.const_get(method_class_name).new(uri)
|
76
|
+
headers.each do |header, value|
|
77
|
+
req[header] = value
|
78
|
+
end
|
79
|
+
req
|
80
|
+
end
|
81
|
+
|
82
|
+
def build_client(uri, https_verify_mode)
|
83
|
+
http = Net::HTTP.new(uri.hostname, uri.port)
|
84
|
+
if uri.scheme == 'https'
|
85
|
+
http.use_ssl = true
|
86
|
+
http.verify_mode = https_verify_mode if https_verify_mode
|
87
|
+
end
|
88
|
+
http
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
@@ -1,21 +1,27 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'cucumber/formatter/http_io'
|
4
|
+
|
3
5
|
module Cucumber
|
4
6
|
module Formatter
|
5
7
|
module Io
|
6
8
|
module_function
|
7
9
|
|
8
|
-
def ensure_io(
|
9
|
-
return nil if
|
10
|
-
return
|
11
|
-
|
10
|
+
def ensure_io(path_or_url_or_io)
|
11
|
+
return nil if path_or_url_or_io.nil?
|
12
|
+
return path_or_url_or_io if path_or_url_or_io.respond_to?(:write)
|
13
|
+
io = if path_or_url_or_io.match(%r{^https?://})
|
14
|
+
HTTPIO.open(path_or_url_or_io)
|
15
|
+
else
|
16
|
+
File.open(path_or_url_or_io, Cucumber.file_mode('w'))
|
17
|
+
end
|
12
18
|
at_exit do
|
13
|
-
unless
|
14
|
-
|
15
|
-
|
19
|
+
unless io.closed?
|
20
|
+
io.flush
|
21
|
+
io.close
|
16
22
|
end
|
17
23
|
end
|
18
|
-
|
24
|
+
io
|
19
25
|
end
|
20
26
|
|
21
27
|
def ensure_file(path, name)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require '
|
3
|
+
require 'json'
|
4
4
|
require 'base64'
|
5
5
|
require 'cucumber/formatter/backtrace_filter'
|
6
6
|
require 'cucumber/formatter/io'
|
@@ -86,7 +86,7 @@ module Cucumber
|
|
86
86
|
end
|
87
87
|
|
88
88
|
def on_test_run_finished(_event)
|
89
|
-
@io.write(
|
89
|
+
@io.write(JSON.generate(@feature_hashes, pretty: true))
|
90
90
|
end
|
91
91
|
|
92
92
|
def attach(src, mime_type)
|
@@ -1,246 +1,22 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'base64'
|
4
3
|
require 'cucumber/formatter/io'
|
5
|
-
require 'cucumber/formatter/
|
6
|
-
require 'cucumber/formatter/query/hook_by_test_step'
|
7
|
-
require 'cucumber/formatter/query/pickle_by_test'
|
8
|
-
require 'cucumber/formatter/query/pickle_step_by_test_step'
|
9
|
-
require 'cucumber/formatter/query/step_definitions_by_test_step'
|
10
|
-
require 'cucumber/formatter/query/test_case_started_by_test_case'
|
4
|
+
require 'cucumber/formatter/message_builder'
|
11
5
|
|
12
6
|
module Cucumber
|
13
7
|
module Formatter
|
14
8
|
# The formatter used for <tt>--format message</tt>
|
15
|
-
class Message
|
9
|
+
class Message < MessageBuilder
|
16
10
|
include Io
|
17
|
-
include Cucumber::Messages::TimeConversion
|
18
11
|
|
19
12
|
def initialize(config)
|
20
|
-
@config = config
|
21
|
-
@hook_by_test_step = Query::HookByTestStep.new(config)
|
22
|
-
@pickle_by_test = Query::PickleByTest.new(config)
|
23
|
-
@pickle_step_by_test_step = Query::PickleStepByTestStep.new(config)
|
24
|
-
@step_definitions_by_test_step = Query::StepDefinitionsByTestStep.new(config)
|
25
|
-
@test_case_started_by_test_case = Query::TestCaseStartedByTestCase.new(config)
|
26
|
-
|
27
13
|
@io = ensure_io(config.out_stream)
|
28
|
-
config
|
29
|
-
config.on_event :gherkin_source_read, &method(:on_gherkin_source_read)
|
30
|
-
config.on_event :test_case_ready, &method(:on_test_case_ready)
|
31
|
-
config.on_event :test_run_started, &method(:on_test_run_started)
|
32
|
-
config.on_event :test_case_started, &method(:on_test_case_started)
|
33
|
-
config.on_event :test_step_started, &method(:on_test_step_started)
|
34
|
-
config.on_event :test_step_finished, &method(:on_test_step_finished)
|
35
|
-
config.on_event :test_case_finished, &method(:on_test_case_finished)
|
36
|
-
config.on_event :test_run_finished, &method(:on_test_run_finished)
|
37
|
-
|
38
|
-
@test_case_by_step_id = {}
|
39
|
-
@current_test_case_started_id = nil
|
40
|
-
@current_test_step_id = nil
|
41
|
-
end
|
42
|
-
|
43
|
-
def attach(src, media_type)
|
44
|
-
attachment_data = {
|
45
|
-
test_step_id: @current_test_step_id,
|
46
|
-
test_case_started_id: @current_test_case_started_id,
|
47
|
-
media_type: media_type
|
48
|
-
}
|
49
|
-
|
50
|
-
if media_type.start_with?('text/')
|
51
|
-
attachment_data[:text] = src
|
52
|
-
elsif src.respond_to? :read
|
53
|
-
attachment_data[:binary] = Base64.encode64(src.read)
|
54
|
-
else
|
55
|
-
attachment_data[:binary] = Base64.encode64(src)
|
56
|
-
end
|
57
|
-
|
58
|
-
message = Cucumber::Messages::Envelope.new(
|
59
|
-
attachment: Cucumber::Messages::Attachment.new(**attachment_data)
|
60
|
-
)
|
61
|
-
|
62
|
-
output_envelope(message)
|
14
|
+
super(config)
|
63
15
|
end
|
64
16
|
|
65
|
-
private
|
66
|
-
|
67
17
|
def output_envelope(envelope)
|
68
18
|
envelope.write_ndjson_to(@io)
|
69
19
|
end
|
70
|
-
|
71
|
-
def on_envelope(event)
|
72
|
-
output_envelope(event.envelope)
|
73
|
-
end
|
74
|
-
|
75
|
-
def on_gherkin_source_read(event)
|
76
|
-
message = Cucumber::Messages::Envelope.new(
|
77
|
-
source: Cucumber::Messages::Source.new(
|
78
|
-
uri: event.path,
|
79
|
-
data: event.body,
|
80
|
-
media_type: 'text/x.cucumber.gherkin+plain'
|
81
|
-
)
|
82
|
-
)
|
83
|
-
|
84
|
-
output_envelope(message)
|
85
|
-
end
|
86
|
-
|
87
|
-
def on_test_case_ready(event)
|
88
|
-
event.test_case.test_steps.each do |step|
|
89
|
-
@test_case_by_step_id[step.id] = event.test_case
|
90
|
-
end
|
91
|
-
|
92
|
-
message = Cucumber::Messages::Envelope.new(
|
93
|
-
test_case: Cucumber::Messages::TestCase.new(
|
94
|
-
id: event.test_case.id,
|
95
|
-
pickle_id: @pickle_by_test.pickle_id(event.test_case),
|
96
|
-
test_steps: event.test_case.test_steps.map { |step| test_step_to_message(step) }
|
97
|
-
)
|
98
|
-
)
|
99
|
-
|
100
|
-
output_envelope(message)
|
101
|
-
end
|
102
|
-
|
103
|
-
def test_step_to_message(step)
|
104
|
-
return hook_step_to_message(step) if step.hook?
|
105
|
-
|
106
|
-
Cucumber::Messages::TestCase::TestStep.new(
|
107
|
-
id: step.id,
|
108
|
-
pickle_step_id: @pickle_step_by_test_step.pickle_step_id(step),
|
109
|
-
step_definition_ids: @step_definitions_by_test_step.step_definition_ids(step),
|
110
|
-
step_match_arguments_lists: step_match_arguments_lists(step)
|
111
|
-
)
|
112
|
-
end
|
113
|
-
|
114
|
-
def hook_step_to_message(step)
|
115
|
-
Cucumber::Messages::TestCase::TestStep.new(
|
116
|
-
id: step.id,
|
117
|
-
hook_id: @hook_by_test_step.hook_id(step)
|
118
|
-
)
|
119
|
-
end
|
120
|
-
|
121
|
-
def step_match_arguments_lists(step)
|
122
|
-
match_arguments = step_match_arguments(step)
|
123
|
-
[Cucumber::Messages::TestCase::TestStep::StepMatchArgumentsList.new(
|
124
|
-
step_match_arguments: match_arguments
|
125
|
-
)]
|
126
|
-
rescue Cucumber::Formatter::TestStepUnknownError
|
127
|
-
[]
|
128
|
-
end
|
129
|
-
|
130
|
-
def step_match_arguments(step)
|
131
|
-
@step_definitions_by_test_step.step_match_arguments(step).map do |argument|
|
132
|
-
Cucumber::Messages::StepMatchArgument.new(
|
133
|
-
group: argument_group_to_message(argument.group),
|
134
|
-
parameter_type_name: argument.parameter_type.name
|
135
|
-
)
|
136
|
-
end
|
137
|
-
end
|
138
|
-
|
139
|
-
def argument_group_to_message(group)
|
140
|
-
Cucumber::Messages::StepMatchArgument::Group.new(
|
141
|
-
start: group.start,
|
142
|
-
value: group.value,
|
143
|
-
children: group.children.map { |child| argument_group_to_message(child) }
|
144
|
-
)
|
145
|
-
end
|
146
|
-
|
147
|
-
def on_test_run_started(*)
|
148
|
-
message = Cucumber::Messages::Envelope.new(
|
149
|
-
test_run_started: Cucumber::Messages::TestRunStarted.new(
|
150
|
-
timestamp: time_to_timestamp(Time.now)
|
151
|
-
)
|
152
|
-
)
|
153
|
-
|
154
|
-
output_envelope(message)
|
155
|
-
end
|
156
|
-
|
157
|
-
def on_test_case_started(event)
|
158
|
-
@current_test_case_started_id = test_case_started_id(event.test_case)
|
159
|
-
|
160
|
-
message = Cucumber::Messages::Envelope.new(
|
161
|
-
test_case_started: Cucumber::Messages::TestCaseStarted.new(
|
162
|
-
id: test_case_started_id(event.test_case),
|
163
|
-
test_case_id: event.test_case.id,
|
164
|
-
timestamp: time_to_timestamp(Time.now),
|
165
|
-
attempt: @test_case_started_by_test_case.attempt_by_test_case(event.test_case)
|
166
|
-
)
|
167
|
-
)
|
168
|
-
|
169
|
-
output_envelope(message)
|
170
|
-
end
|
171
|
-
|
172
|
-
def on_test_step_started(event)
|
173
|
-
@current_test_step_id = event.test_step.id
|
174
|
-
test_case = @test_case_by_step_id[event.test_step.id]
|
175
|
-
|
176
|
-
message = Cucumber::Messages::Envelope.new(
|
177
|
-
test_step_started: Cucumber::Messages::TestStepStarted.new(
|
178
|
-
test_step_id: event.test_step.id,
|
179
|
-
test_case_started_id: test_case_started_id(test_case),
|
180
|
-
timestamp: time_to_timestamp(Time.now)
|
181
|
-
)
|
182
|
-
)
|
183
|
-
|
184
|
-
output_envelope(message)
|
185
|
-
end
|
186
|
-
|
187
|
-
def on_test_step_finished(event)
|
188
|
-
test_case = @test_case_by_step_id[event.test_step.id]
|
189
|
-
result = event
|
190
|
-
.result
|
191
|
-
.with_filtered_backtrace(Cucumber::Formatter::BacktraceFilter)
|
192
|
-
|
193
|
-
result_message = result.to_message
|
194
|
-
if result.failed? || result.pending?
|
195
|
-
result_message = Cucumber::Messages::TestStepResult.new(
|
196
|
-
status: result_message.status,
|
197
|
-
duration: result_message.duration,
|
198
|
-
message: create_error_message(result)
|
199
|
-
)
|
200
|
-
end
|
201
|
-
|
202
|
-
message = Cucumber::Messages::Envelope.new(
|
203
|
-
test_step_finished: Cucumber::Messages::TestStepFinished.new(
|
204
|
-
test_step_id: event.test_step.id,
|
205
|
-
test_case_started_id: test_case_started_id(test_case),
|
206
|
-
test_step_result: result_message,
|
207
|
-
timestamp: time_to_timestamp(Time.now)
|
208
|
-
)
|
209
|
-
)
|
210
|
-
|
211
|
-
output_envelope(message)
|
212
|
-
end
|
213
|
-
|
214
|
-
def create_error_message(result)
|
215
|
-
message_element = result.failed? ? result.exception : result
|
216
|
-
message = "#{message_element.message} (#{message_element.class})"
|
217
|
-
([message] + message_element.backtrace).join("\n")
|
218
|
-
end
|
219
|
-
|
220
|
-
def on_test_case_finished(event)
|
221
|
-
message = Cucumber::Messages::Envelope.new(
|
222
|
-
test_case_finished: Cucumber::Messages::TestCaseFinished.new(
|
223
|
-
test_case_started_id: test_case_started_id(event.test_case),
|
224
|
-
timestamp: time_to_timestamp(Time.now)
|
225
|
-
)
|
226
|
-
)
|
227
|
-
|
228
|
-
output_envelope(message)
|
229
|
-
end
|
230
|
-
|
231
|
-
def on_test_run_finished(*)
|
232
|
-
message = Cucumber::Messages::Envelope.new(
|
233
|
-
test_run_finished: Cucumber::Messages::TestRunFinished.new(
|
234
|
-
timestamp: time_to_timestamp(Time.now)
|
235
|
-
)
|
236
|
-
)
|
237
|
-
|
238
|
-
output_envelope(message)
|
239
|
-
end
|
240
|
-
|
241
|
-
def test_case_started_id(test_case)
|
242
|
-
@test_case_started_by_test_case.test_case_started_id_by_test_case(test_case)
|
243
|
-
end
|
244
20
|
end
|
245
21
|
end
|
246
22
|
end
|
@@ -0,0 +1,241 @@
|
|
1
|
+
require 'base64'
|
2
|
+
require 'cucumber/formatter/backtrace_filter'
|
3
|
+
require 'cucumber/formatter/query/hook_by_test_step'
|
4
|
+
require 'cucumber/formatter/query/pickle_by_test'
|
5
|
+
require 'cucumber/formatter/query/pickle_step_by_test_step'
|
6
|
+
require 'cucumber/formatter/query/step_definitions_by_test_step'
|
7
|
+
require 'cucumber/formatter/query/test_case_started_by_test_case'
|
8
|
+
|
9
|
+
module Cucumber
|
10
|
+
module Formatter
|
11
|
+
class MessageBuilder
|
12
|
+
include Cucumber::Messages::TimeConversion
|
13
|
+
|
14
|
+
def initialize(config)
|
15
|
+
@config = config
|
16
|
+
|
17
|
+
@hook_by_test_step = Query::HookByTestStep.new(config)
|
18
|
+
@pickle_by_test = Query::PickleByTest.new(config)
|
19
|
+
@pickle_step_by_test_step = Query::PickleStepByTestStep.new(config)
|
20
|
+
@step_definitions_by_test_step = Query::StepDefinitionsByTestStep.new(config)
|
21
|
+
@test_case_started_by_test_case = Query::TestCaseStartedByTestCase.new(config)
|
22
|
+
|
23
|
+
config.on_event :envelope, &method(:on_envelope)
|
24
|
+
config.on_event :gherkin_source_read, &method(:on_gherkin_source_read)
|
25
|
+
config.on_event :test_case_ready, &method(:on_test_case_ready)
|
26
|
+
config.on_event :test_run_started, &method(:on_test_run_started)
|
27
|
+
config.on_event :test_case_started, &method(:on_test_case_started)
|
28
|
+
config.on_event :test_step_started, &method(:on_test_step_started)
|
29
|
+
config.on_event :test_step_finished, &method(:on_test_step_finished)
|
30
|
+
config.on_event :test_case_finished, &method(:on_test_case_finished)
|
31
|
+
config.on_event :test_run_finished, &method(:on_test_run_finished)
|
32
|
+
|
33
|
+
@test_case_by_step_id = {}
|
34
|
+
@current_test_case_started_id = nil
|
35
|
+
@current_test_step_id = nil
|
36
|
+
end
|
37
|
+
|
38
|
+
def output_message
|
39
|
+
raise 'To be implemented'
|
40
|
+
end
|
41
|
+
|
42
|
+
def attach(src, media_type)
|
43
|
+
attachment_data = {
|
44
|
+
test_step_id: @current_test_step_id,
|
45
|
+
test_case_started_id: @current_test_case_started_id,
|
46
|
+
media_type: media_type
|
47
|
+
}
|
48
|
+
|
49
|
+
if media_type.start_with?('text/')
|
50
|
+
attachment_data[:text] = src
|
51
|
+
elsif src.respond_to? :read
|
52
|
+
attachment_data[:binary] = Base64.encode64(src.read)
|
53
|
+
else
|
54
|
+
attachment_data[:binary] = Base64.encode64(src)
|
55
|
+
end
|
56
|
+
|
57
|
+
message = Cucumber::Messages::Envelope.new(
|
58
|
+
attachment: Cucumber::Messages::Attachment.new(**attachment_data)
|
59
|
+
)
|
60
|
+
|
61
|
+
output_envelope(message)
|
62
|
+
end
|
63
|
+
|
64
|
+
private
|
65
|
+
|
66
|
+
def on_envelope(event)
|
67
|
+
output_envelope(event.envelope)
|
68
|
+
end
|
69
|
+
|
70
|
+
def on_gherkin_source_read(event)
|
71
|
+
message = Cucumber::Messages::Envelope.new(
|
72
|
+
source: Cucumber::Messages::Source.new(
|
73
|
+
uri: event.path,
|
74
|
+
data: event.body,
|
75
|
+
media_type: 'text/x.cucumber.gherkin+plain'
|
76
|
+
)
|
77
|
+
)
|
78
|
+
|
79
|
+
output_envelope(message)
|
80
|
+
end
|
81
|
+
|
82
|
+
def on_test_case_ready(event)
|
83
|
+
event.test_case.test_steps.each do |step|
|
84
|
+
@test_case_by_step_id[step.id] = event.test_case
|
85
|
+
end
|
86
|
+
|
87
|
+
message = Cucumber::Messages::Envelope.new(
|
88
|
+
test_case: Cucumber::Messages::TestCase.new(
|
89
|
+
id: event.test_case.id,
|
90
|
+
pickle_id: @pickle_by_test.pickle_id(event.test_case),
|
91
|
+
test_steps: event.test_case.test_steps.map { |step| test_step_to_message(step) }
|
92
|
+
)
|
93
|
+
)
|
94
|
+
|
95
|
+
output_envelope(message)
|
96
|
+
end
|
97
|
+
|
98
|
+
def test_step_to_message(step)
|
99
|
+
return hook_step_to_message(step) if step.hook?
|
100
|
+
|
101
|
+
Cucumber::Messages::TestCase::TestStep.new(
|
102
|
+
id: step.id,
|
103
|
+
pickle_step_id: @pickle_step_by_test_step.pickle_step_id(step),
|
104
|
+
step_definition_ids: @step_definitions_by_test_step.step_definition_ids(step),
|
105
|
+
step_match_arguments_lists: step_match_arguments_lists(step)
|
106
|
+
)
|
107
|
+
end
|
108
|
+
|
109
|
+
def hook_step_to_message(step)
|
110
|
+
Cucumber::Messages::TestCase::TestStep.new(
|
111
|
+
id: step.id,
|
112
|
+
hook_id: @hook_by_test_step.hook_id(step)
|
113
|
+
)
|
114
|
+
end
|
115
|
+
|
116
|
+
def step_match_arguments_lists(step)
|
117
|
+
match_arguments = step_match_arguments(step)
|
118
|
+
[Cucumber::Messages::TestCase::TestStep::StepMatchArgumentsList.new(
|
119
|
+
step_match_arguments: match_arguments
|
120
|
+
)]
|
121
|
+
rescue Cucumber::Formatter::TestStepUnknownError
|
122
|
+
[]
|
123
|
+
end
|
124
|
+
|
125
|
+
def step_match_arguments(step)
|
126
|
+
@step_definitions_by_test_step.step_match_arguments(step).map do |argument|
|
127
|
+
Cucumber::Messages::StepMatchArgument.new(
|
128
|
+
group: argument_group_to_message(argument.group),
|
129
|
+
parameter_type_name: argument.parameter_type.name
|
130
|
+
)
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
def argument_group_to_message(group)
|
135
|
+
Cucumber::Messages::StepMatchArgument::Group.new(
|
136
|
+
start: group.start,
|
137
|
+
value: group.value,
|
138
|
+
children: group.children.map { |child| argument_group_to_message(child) }
|
139
|
+
)
|
140
|
+
end
|
141
|
+
|
142
|
+
def on_test_run_started(*)
|
143
|
+
message = Cucumber::Messages::Envelope.new(
|
144
|
+
test_run_started: Cucumber::Messages::TestRunStarted.new(
|
145
|
+
timestamp: time_to_timestamp(Time.now)
|
146
|
+
)
|
147
|
+
)
|
148
|
+
|
149
|
+
output_envelope(message)
|
150
|
+
end
|
151
|
+
|
152
|
+
def on_test_case_started(event)
|
153
|
+
@current_test_case_started_id = test_case_started_id(event.test_case)
|
154
|
+
|
155
|
+
message = Cucumber::Messages::Envelope.new(
|
156
|
+
test_case_started: Cucumber::Messages::TestCaseStarted.new(
|
157
|
+
id: test_case_started_id(event.test_case),
|
158
|
+
test_case_id: event.test_case.id,
|
159
|
+
timestamp: time_to_timestamp(Time.now),
|
160
|
+
attempt: @test_case_started_by_test_case.attempt_by_test_case(event.test_case)
|
161
|
+
)
|
162
|
+
)
|
163
|
+
|
164
|
+
output_envelope(message)
|
165
|
+
end
|
166
|
+
|
167
|
+
def on_test_step_started(event)
|
168
|
+
@current_test_step_id = event.test_step.id
|
169
|
+
test_case = @test_case_by_step_id[event.test_step.id]
|
170
|
+
|
171
|
+
message = Cucumber::Messages::Envelope.new(
|
172
|
+
test_step_started: Cucumber::Messages::TestStepStarted.new(
|
173
|
+
test_step_id: event.test_step.id,
|
174
|
+
test_case_started_id: test_case_started_id(test_case),
|
175
|
+
timestamp: time_to_timestamp(Time.now)
|
176
|
+
)
|
177
|
+
)
|
178
|
+
|
179
|
+
output_envelope(message)
|
180
|
+
end
|
181
|
+
|
182
|
+
def on_test_step_finished(event)
|
183
|
+
test_case = @test_case_by_step_id[event.test_step.id]
|
184
|
+
result = event
|
185
|
+
.result
|
186
|
+
.with_filtered_backtrace(Cucumber::Formatter::BacktraceFilter)
|
187
|
+
|
188
|
+
result_message = result.to_message
|
189
|
+
if result.failed? || result.pending?
|
190
|
+
result_message = Cucumber::Messages::TestStepResult.new(
|
191
|
+
status: result_message.status,
|
192
|
+
duration: result_message.duration,
|
193
|
+
message: create_error_message(result)
|
194
|
+
)
|
195
|
+
end
|
196
|
+
|
197
|
+
message = Cucumber::Messages::Envelope.new(
|
198
|
+
test_step_finished: Cucumber::Messages::TestStepFinished.new(
|
199
|
+
test_step_id: event.test_step.id,
|
200
|
+
test_case_started_id: test_case_started_id(test_case),
|
201
|
+
test_step_result: result_message,
|
202
|
+
timestamp: time_to_timestamp(Time.now)
|
203
|
+
)
|
204
|
+
)
|
205
|
+
|
206
|
+
output_envelope(message)
|
207
|
+
end
|
208
|
+
|
209
|
+
def create_error_message(result)
|
210
|
+
message_element = result.failed? ? result.exception : result
|
211
|
+
message = "#{message_element.message} (#{message_element.class})"
|
212
|
+
([message] + message_element.backtrace).join("\n")
|
213
|
+
end
|
214
|
+
|
215
|
+
def on_test_case_finished(event)
|
216
|
+
message = Cucumber::Messages::Envelope.new(
|
217
|
+
test_case_finished: Cucumber::Messages::TestCaseFinished.new(
|
218
|
+
test_case_started_id: test_case_started_id(event.test_case),
|
219
|
+
timestamp: time_to_timestamp(Time.now)
|
220
|
+
)
|
221
|
+
)
|
222
|
+
|
223
|
+
output_envelope(message)
|
224
|
+
end
|
225
|
+
|
226
|
+
def on_test_run_finished(*)
|
227
|
+
message = Cucumber::Messages::Envelope.new(
|
228
|
+
test_run_finished: Cucumber::Messages::TestRunFinished.new(
|
229
|
+
timestamp: time_to_timestamp(Time.now)
|
230
|
+
)
|
231
|
+
)
|
232
|
+
|
233
|
+
output_envelope(message)
|
234
|
+
end
|
235
|
+
|
236
|
+
def test_case_started_id(test_case)
|
237
|
+
@test_case_started_by_test_case.test_case_started_id_by_test_case(test_case)
|
238
|
+
end
|
239
|
+
end
|
240
|
+
end
|
241
|
+
end
|
data/lib/cucumber/runtime.rb
CHANGED
data/lib/cucumber/version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
4.0.0.rc.
|
1
|
+
4.0.0.rc.5
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cucumber
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.0.0.rc.
|
4
|
+
version: 4.0.0.rc.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Aslak Hellesøy
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2020-
|
13
|
+
date: 2020-03-17 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: builder
|
@@ -93,65 +93,65 @@ dependencies:
|
|
93
93
|
- !ruby/object:Gem::Version
|
94
94
|
version: '10.0'
|
95
95
|
- !ruby/object:Gem::Dependency
|
96
|
-
name: cucumber-
|
96
|
+
name: cucumber-html-formatter
|
97
97
|
requirement: !ruby/object:Gem::Requirement
|
98
98
|
requirements:
|
99
99
|
- - ">="
|
100
100
|
- !ruby/object:Gem::Version
|
101
|
-
version:
|
101
|
+
version: 4.3.0
|
102
102
|
- - "~>"
|
103
103
|
- !ruby/object:Gem::Version
|
104
|
-
version: '
|
104
|
+
version: '4.3'
|
105
105
|
type: :runtime
|
106
106
|
prerelease: false
|
107
107
|
version_requirements: !ruby/object:Gem::Requirement
|
108
108
|
requirements:
|
109
109
|
- - ">="
|
110
110
|
- !ruby/object:Gem::Version
|
111
|
-
version:
|
111
|
+
version: 4.3.0
|
112
112
|
- - "~>"
|
113
113
|
- !ruby/object:Gem::Version
|
114
|
-
version: '
|
114
|
+
version: '4.3'
|
115
115
|
- !ruby/object:Gem::Dependency
|
116
|
-
name:
|
116
|
+
name: cucumber-wire
|
117
117
|
requirement: !ruby/object:Gem::Requirement
|
118
118
|
requirements:
|
119
119
|
- - ">="
|
120
120
|
- !ruby/object:Gem::Version
|
121
|
-
version:
|
121
|
+
version: 2.0.0
|
122
122
|
- - "~>"
|
123
123
|
- !ruby/object:Gem::Version
|
124
|
-
version: '
|
124
|
+
version: '2.0'
|
125
125
|
type: :runtime
|
126
126
|
prerelease: false
|
127
127
|
version_requirements: !ruby/object:Gem::Requirement
|
128
128
|
requirements:
|
129
129
|
- - ">="
|
130
130
|
- !ruby/object:Gem::Version
|
131
|
-
version:
|
131
|
+
version: 2.0.0
|
132
132
|
- - "~>"
|
133
133
|
- !ruby/object:Gem::Version
|
134
|
-
version: '
|
134
|
+
version: '2.0'
|
135
135
|
- !ruby/object:Gem::Dependency
|
136
|
-
name:
|
136
|
+
name: diff-lcs
|
137
137
|
requirement: !ruby/object:Gem::Requirement
|
138
138
|
requirements:
|
139
|
-
- - "~>"
|
140
|
-
- !ruby/object:Gem::Version
|
141
|
-
version: '1.13'
|
142
139
|
- - ">="
|
143
140
|
- !ruby/object:Gem::Version
|
144
|
-
version: 1.
|
141
|
+
version: '1.3'
|
142
|
+
- - "~>"
|
143
|
+
- !ruby/object:Gem::Version
|
144
|
+
version: '1.3'
|
145
145
|
type: :runtime
|
146
146
|
prerelease: false
|
147
147
|
version_requirements: !ruby/object:Gem::Requirement
|
148
148
|
requirements:
|
149
|
-
- - "~>"
|
150
|
-
- !ruby/object:Gem::Version
|
151
|
-
version: '1.13'
|
152
149
|
- - ">="
|
153
150
|
- !ruby/object:Gem::Version
|
154
|
-
version: 1.
|
151
|
+
version: '1.3'
|
152
|
+
- - "~>"
|
153
|
+
- !ruby/object:Gem::Version
|
154
|
+
version: '1.3'
|
155
155
|
- !ruby/object:Gem::Dependency
|
156
156
|
name: multi_test
|
157
157
|
requirement: !ruby/object:Gem::Requirement
|
@@ -176,42 +176,22 @@ dependencies:
|
|
176
176
|
name: aruba
|
177
177
|
requirement: !ruby/object:Gem::Requirement
|
178
178
|
requirements:
|
179
|
-
- - "~>"
|
180
|
-
- !ruby/object:Gem::Version
|
181
|
-
version: '0.14'
|
182
179
|
- - ">="
|
183
180
|
- !ruby/object:Gem::Version
|
184
|
-
version: 0.
|
185
|
-
type: :development
|
186
|
-
prerelease: false
|
187
|
-
version_requirements: !ruby/object:Gem::Requirement
|
188
|
-
requirements:
|
181
|
+
version: 1.0.0
|
189
182
|
- - "~>"
|
190
183
|
- !ruby/object:Gem::Version
|
191
|
-
version: '0
|
192
|
-
- - ">="
|
193
|
-
- !ruby/object:Gem::Version
|
194
|
-
version: 0.14.11
|
195
|
-
- !ruby/object:Gem::Dependency
|
196
|
-
name: json
|
197
|
-
requirement: !ruby/object:Gem::Requirement
|
198
|
-
requirements:
|
199
|
-
- - ">="
|
200
|
-
- !ruby/object:Gem::Version
|
201
|
-
version: 2.2.0
|
202
|
-
- - "~>"
|
203
|
-
- !ruby/object:Gem::Version
|
204
|
-
version: '2.2'
|
184
|
+
version: '1.0'
|
205
185
|
type: :development
|
206
186
|
prerelease: false
|
207
187
|
version_requirements: !ruby/object:Gem::Requirement
|
208
188
|
requirements:
|
209
189
|
- - ">="
|
210
190
|
- !ruby/object:Gem::Version
|
211
|
-
version:
|
191
|
+
version: 1.0.0
|
212
192
|
- - "~>"
|
213
193
|
- !ruby/object:Gem::Version
|
214
|
-
version: '
|
194
|
+
version: '1.0'
|
215
195
|
- !ruby/object:Gem::Dependency
|
216
196
|
name: nokogiri
|
217
197
|
requirement: !ruby/object:Gem::Requirement
|
@@ -292,26 +272,6 @@ dependencies:
|
|
292
272
|
- - "~>"
|
293
273
|
- !ruby/object:Gem::Version
|
294
274
|
version: '3.8'
|
295
|
-
- !ruby/object:Gem::Dependency
|
296
|
-
name: rubocop
|
297
|
-
requirement: !ruby/object:Gem::Requirement
|
298
|
-
requirements:
|
299
|
-
- - "~>"
|
300
|
-
- !ruby/object:Gem::Version
|
301
|
-
version: '0.75'
|
302
|
-
- - '='
|
303
|
-
- !ruby/object:Gem::Version
|
304
|
-
version: 0.75.1
|
305
|
-
type: :development
|
306
|
-
prerelease: false
|
307
|
-
version_requirements: !ruby/object:Gem::Requirement
|
308
|
-
requirements:
|
309
|
-
- - "~>"
|
310
|
-
- !ruby/object:Gem::Version
|
311
|
-
version: '0.75'
|
312
|
-
- - '='
|
313
|
-
- !ruby/object:Gem::Version
|
314
|
-
version: 0.75.1
|
315
275
|
- !ruby/object:Gem::Dependency
|
316
276
|
name: simplecov
|
317
277
|
requirement: !ruby/object:Gem::Requirement
|
@@ -372,6 +332,26 @@ dependencies:
|
|
372
332
|
- - ">="
|
373
333
|
- !ruby/object:Gem::Version
|
374
334
|
version: 1.2.3
|
335
|
+
- !ruby/object:Gem::Dependency
|
336
|
+
name: webrick
|
337
|
+
requirement: !ruby/object:Gem::Requirement
|
338
|
+
requirements:
|
339
|
+
- - ">="
|
340
|
+
- !ruby/object:Gem::Version
|
341
|
+
version: 1.6.0
|
342
|
+
- - "~>"
|
343
|
+
- !ruby/object:Gem::Version
|
344
|
+
version: '1.6'
|
345
|
+
type: :development
|
346
|
+
prerelease: false
|
347
|
+
version_requirements: !ruby/object:Gem::Requirement
|
348
|
+
requirements:
|
349
|
+
- - ">="
|
350
|
+
- !ruby/object:Gem::Version
|
351
|
+
version: 1.6.0
|
352
|
+
- - "~>"
|
353
|
+
- !ruby/object:Gem::Version
|
354
|
+
version: '1.6'
|
375
355
|
- !ruby/object:Gem::Dependency
|
376
356
|
name: octokit
|
377
357
|
requirement: !ruby/object:Gem::Requirement
|
@@ -522,12 +502,15 @@ files:
|
|
522
502
|
- lib/cucumber/formatter/errors.rb
|
523
503
|
- lib/cucumber/formatter/fail_fast.rb
|
524
504
|
- lib/cucumber/formatter/fanout.rb
|
505
|
+
- lib/cucumber/formatter/html.rb
|
506
|
+
- lib/cucumber/formatter/http_io.rb
|
525
507
|
- lib/cucumber/formatter/ignore_missing_messages.rb
|
526
508
|
- lib/cucumber/formatter/interceptor.rb
|
527
509
|
- lib/cucumber/formatter/io.rb
|
528
510
|
- lib/cucumber/formatter/json.rb
|
529
511
|
- lib/cucumber/formatter/junit.rb
|
530
512
|
- lib/cucumber/formatter/message.rb
|
513
|
+
- lib/cucumber/formatter/message_builder.rb
|
531
514
|
- lib/cucumber/formatter/pretty.rb
|
532
515
|
- lib/cucumber/formatter/progress.rb
|
533
516
|
- lib/cucumber/formatter/query/hook_by_test_step.rb
|
@@ -609,5 +592,5 @@ requirements: []
|
|
609
592
|
rubygems_version: 3.0.6
|
610
593
|
signing_key:
|
611
594
|
specification_version: 4
|
612
|
-
summary: cucumber-4.0.0.rc.
|
595
|
+
summary: cucumber-4.0.0.rc.5
|
613
596
|
test_files: []
|