cucumber 10.2.0 → 11.1.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.
Files changed (75) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +17 -8
  3. data/VERSION +1 -1
  4. data/lib/cucumber/cli/configuration.rb +1 -1
  5. data/lib/cucumber/cli/main.rb +22 -0
  6. data/lib/cucumber/cli/options.rb +3 -18
  7. data/lib/cucumber/cli/profile_loader.rb +2 -2
  8. data/lib/cucumber/cli/rerun_file.rb +1 -1
  9. data/lib/cucumber/cli.rb +3 -0
  10. data/lib/cucumber/configuration.rb +33 -24
  11. data/lib/cucumber/events/base.rb +25 -0
  12. data/lib/cucumber/events/envelope.rb +29 -2
  13. data/lib/cucumber/events/gherkin_source_parsed.rb +12 -3
  14. data/lib/cucumber/events/gherkin_source_read.rb +11 -3
  15. data/lib/cucumber/events/hook_test_step_created.rb +12 -2
  16. data/lib/cucumber/events/step_activated.rb +13 -7
  17. data/lib/cucumber/events/step_definition_registered.rb +12 -4
  18. data/lib/cucumber/events/test_case_created.rb +11 -3
  19. data/lib/cucumber/events/test_case_finished.rb +12 -4
  20. data/lib/cucumber/events/test_case_ready.rb +10 -4
  21. data/lib/cucumber/events/test_case_started.rb +11 -2
  22. data/lib/cucumber/events/test_run_finished.rb +10 -3
  23. data/lib/cucumber/events/test_run_hook_finished.rb +19 -0
  24. data/lib/cucumber/events/test_run_hook_started.rb +20 -0
  25. data/lib/cucumber/events/test_run_started.rb +11 -2
  26. data/lib/cucumber/events/test_step_created.rb +12 -2
  27. data/lib/cucumber/events/test_step_finished.rb +12 -2
  28. data/lib/cucumber/events/test_step_started.rb +11 -2
  29. data/lib/cucumber/events/undefined_parameter_type.rb +11 -3
  30. data/lib/cucumber/events.rb +2 -0
  31. data/lib/cucumber/filters/fire_before_all_hooks.rb +36 -0
  32. data/lib/cucumber/filters/randomizer.rb +5 -5
  33. data/lib/cucumber/filters/reverser.rb +41 -0
  34. data/lib/cucumber/filters.rb +1 -12
  35. data/lib/cucumber/formatter/ansicolor.rb +3 -0
  36. data/lib/cucumber/formatter/console.rb +15 -7
  37. data/lib/cucumber/formatter/console_issues.rb +5 -5
  38. data/lib/cucumber/formatter/duration_extractor.rb +2 -0
  39. data/lib/cucumber/formatter/fail_fast.rb +3 -4
  40. data/lib/cucumber/formatter/global_hooks_summary.rb +36 -0
  41. data/lib/cucumber/formatter/html.rb +1 -3
  42. data/lib/cucumber/formatter/json.rb +5 -3
  43. data/lib/cucumber/formatter/junit.rb +5 -34
  44. data/lib/cucumber/formatter/message.rb +8 -4
  45. data/lib/cucumber/formatter/message_builder.rb +249 -143
  46. data/lib/cucumber/formatter/pretty.rb +2 -5
  47. data/lib/cucumber/formatter/progress.rb +1 -2
  48. data/lib/cucumber/formatter/rerun.rb +80 -30
  49. data/lib/cucumber/formatter/usage.rb +2 -3
  50. data/lib/cucumber/formatter.rb +3 -0
  51. data/lib/cucumber/glue/proto_world.rb +6 -4
  52. data/lib/cucumber/glue/registry_and_more.rb +122 -20
  53. data/lib/cucumber/glue.rb +3 -0
  54. data/lib/cucumber/multiline_argument/data_table.rb +0 -11
  55. data/lib/cucumber/platform.rb +2 -2
  56. data/lib/cucumber/query.rb +273 -0
  57. data/lib/cucumber/rake/forked_cucumber_runner.rb +57 -0
  58. data/lib/cucumber/rake/in_process_cucumber_runner.rb +27 -0
  59. data/lib/cucumber/rake/task.rb +36 -106
  60. data/lib/cucumber/rake.rb +3 -0
  61. data/lib/cucumber/repository.rb +136 -0
  62. data/lib/cucumber/rspec/disable_option_parser.rb +3 -3
  63. data/lib/cucumber/runtime/user_interface.rb +2 -2
  64. data/lib/cucumber/runtime.rb +29 -9
  65. data/lib/cucumber/step_match.rb +1 -1
  66. data/lib/cucumber.rb +2 -13
  67. metadata +33 -30
  68. data/lib/cucumber/formatter/errors.rb +0 -9
  69. data/lib/cucumber/formatter/query/hook_by_test_step.rb +0 -34
  70. data/lib/cucumber/formatter/query/pickle_by_test.rb +0 -28
  71. data/lib/cucumber/formatter/query/pickle_step_by_test_step.rb +0 -28
  72. data/lib/cucumber/formatter/query/step_definitions_by_test_step.rb +0 -42
  73. data/lib/cucumber/formatter/query/test_case_started_by_test_case.rb +0 -44
  74. data/lib/cucumber/formatter/query/test_run_started.rb +0 -17
  75. data/lib/cucumber/step_definition_light.rb +0 -29
@@ -1,201 +1,240 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'base64'
4
+ require 'json'
5
+
4
6
  require 'cucumber/formatter/backtrace_filter'
5
- require 'cucumber/formatter/query/hook_by_test_step'
6
- require 'cucumber/formatter/query/pickle_by_test'
7
- require 'cucumber/formatter/query/pickle_step_by_test_step'
8
- require 'cucumber/formatter/query/step_definitions_by_test_step'
9
- require 'cucumber/formatter/query/test_case_started_by_test_case'
10
- require 'cucumber/formatter/query/test_run_started'
7
+ require 'cucumber/query'
11
8
 
12
9
  module Cucumber
13
10
  module Formatter
14
11
  class MessageBuilder
15
12
  include Cucumber::Messages::Helpers::TimeConversion
13
+ include Io
14
+ include Console
16
15
 
17
16
  def initialize(config)
18
17
  @config = config
18
+ @ast_lookup = AstLookup.new(config)
19
+ @repository = Cucumber::Repository.new
19
20
 
20
- @hook_by_test_step = Query::HookByTestStep.new(config)
21
- @pickle_by_test = Query::PickleByTest.new(config)
22
- @pickle_step_by_test_step = Query::PickleStepByTestStep.new(config)
23
- @step_definitions_by_test_step = Query::StepDefinitionsByTestStep.new(config)
24
- @test_case_started_by_test_case = Query::TestCaseStartedByTestCase.new(config)
25
- @test_run_started = Query::TestRunStarted.new(config)
21
+ @test_run_started_id = config.test_run_started_id
26
22
 
27
- config.on_event :envelope, &method(:on_envelope)
28
- config.on_event :gherkin_source_read, &method(:on_gherkin_source_read)
23
+ # Fake Query objects
24
+ @test_case_by_step_id = {}
25
+ @pickle_id_by_test_case_id = {}
26
+ @pickle_id_step_by_test_step_id = {}
27
+ @hook_id_by_test_step_id = {}
28
+ @step_definition_ids_by_test_step_id = {}
29
+ @step_match_arguments_by_test_step_id = {}
30
+
31
+ # Ensure all handlers for events occur after all ivars are instantiated
32
+
33
+ config.on_event :gherkin_source_parsed, &method(:on_gherkin_source_parsed)
34
+
35
+ config.on_event :hook_test_step_created, &method(:on_hook_test_step_created)
36
+
37
+ config.on_event :step_activated, &method(:on_step_activated)
38
+
39
+ config.on_event :test_case_created, &method(:on_test_case_created)
29
40
  config.on_event :test_case_ready, &method(:on_test_case_ready)
30
- config.on_event :test_run_started, &method(:on_test_run_started)
31
41
  config.on_event :test_case_started, &method(:on_test_case_started)
32
- config.on_event :test_step_started, &method(:on_test_step_started)
33
- config.on_event :test_step_finished, &method(:on_test_step_finished)
34
42
  config.on_event :test_case_finished, &method(:on_test_case_finished)
43
+
44
+ config.on_event :test_run_started, &method(:on_test_run_started)
35
45
  config.on_event :test_run_finished, &method(:on_test_run_finished)
36
- config.on_event :undefined_parameter_type, &method(:on_undefined_parameter_type)
37
46
 
38
- @test_case_by_step_id = {}
39
- @current_test_run_started_id = nil
40
- @current_test_case_started_id = nil
41
- @current_test_step_id = nil
42
- end
47
+ config.on_event :test_step_created, &method(:on_test_step_created)
48
+ config.on_event :test_step_started, &method(:on_test_step_started)
49
+ config.on_event :test_step_finished, &method(:on_test_step_finished)
43
50
 
44
- def output_message
45
- raise 'To be implemented'
51
+ config.on_event :envelope, &method(:on_envelope)
46
52
  end
47
53
 
48
- def attach(src, media_type, filename)
49
- attachment_data = {
50
- test_step_id: @current_test_step_id,
51
- test_case_started_id: @current_test_case_started_id,
52
- media_type: media_type,
53
- file_name: filename
54
- }
54
+ def on_envelope(event)
55
+ @current_test_run_hook_started_id = event.envelope.test_run_hook_started.id if event.envelope.test_run_hook_started
56
+ end
55
57
 
56
- if media_type&.start_with?('text/')
57
- attachment_data[:content_encoding] = Cucumber::Messages::AttachmentContentEncoding::IDENTITY
58
- attachment_data[:body] = src
59
- else
60
- body = src.respond_to?(:read) ? src.read : src
58
+ def attach(src, media_type, filename, streamed_file)
59
+ attachment_data =
60
+ if @current_test_run_hook_started_id.nil?
61
+ {
62
+ test_step_id: @current_test_step_id,
63
+ test_case_started_id: @current_test_case_started_id,
64
+ media_type: media_type,
65
+ file_name: filename,
66
+ timestamp: time_to_timestamp(Time.now)
67
+ }
68
+ else
69
+ {
70
+ test_run_hook_started_id: @current_test_run_hook_started_id,
71
+ media_type: media_type,
72
+ file_name: filename,
73
+ timestamp: time_to_timestamp(Time.now)
74
+ }
75
+ end
76
+
77
+ if streamed_file
61
78
  attachment_data[:content_encoding] = Cucumber::Messages::AttachmentContentEncoding::BASE64
62
- attachment_data[:body] = Base64.strict_encode64(body)
79
+ attachment_data[:body] = Base64.strict_encode64(src)
80
+ else
81
+ attachment_data[:content_encoding] = Cucumber::Messages::AttachmentContentEncoding::IDENTITY
82
+ attachment_data[:body] = src.is_a?(Hash) ? src.to_json : src
63
83
  end
64
84
 
65
85
  message = Cucumber::Messages::Envelope.new(attachment: Cucumber::Messages::Attachment.new(**attachment_data))
66
- output_envelope(message)
86
+ @config.event_bus.envelope(message)
67
87
  end
68
88
 
69
89
  private
70
90
 
71
- def on_envelope(event)
72
- output_envelope(event.envelope)
91
+ def on_gherkin_source_parsed(_event)
92
+ # TODO: Handle GherkinSourceParsed
73
93
  end
74
94
 
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
- )
95
+ def on_hook_test_step_created(event)
96
+ @hook_id_by_test_step_id[event.test_step.id] = event.hook.id
97
+ end
83
98
 
84
- output_envelope(message)
99
+ def on_step_activated(event)
100
+ @step_definition_ids_by_test_step_id[event.test_step.id] << event.step_match.step_definition.id
101
+ @step_match_arguments_by_test_step_id[event.test_step.id] = event.step_match.step_arguments
85
102
  end
86
103
 
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
104
+ def on_test_case_created(event)
105
+ @pickle_id_by_test_case_id[event.test_case.id] = event.pickle.id
106
+ end
91
107
 
108
+ def on_test_case_ready(event)
92
109
  message = Cucumber::Messages::Envelope.new(
93
110
  test_case: Cucumber::Messages::TestCase.new(
94
111
  id: event.test_case.id,
95
- pickle_id: @pickle_by_test.pickle_id(event.test_case),
112
+ pickle_id: fake_query_pickle_id(event.test_case),
96
113
  test_steps: event.test_case.test_steps.map { |step| test_step_to_message(step) },
97
- test_run_started_id: @current_test_run_started_id
114
+ test_run_started_id: @test_run_started_id
98
115
  )
99
116
  )
100
117
 
101
- output_envelope(message)
118
+ # TODO: This may be a redundant update. But for now we're leaving this in whilst we're in the transitory phase
119
+ @repository.update(message)
120
+
121
+ @config.event_bus.envelope(message)
102
122
  end
103
123
 
104
- def test_step_to_message(step)
105
- return hook_step_to_message(step) if step.hook?
124
+ def on_test_case_started(event)
125
+ # For any new test_case_started events, we must ALWAYS generate a new id for a new run
126
+ @current_test_case_started_id = @config.id_generator.new_id
127
+ @current_test_run_hook_started_id = nil
106
128
 
107
- Cucumber::Messages::TestStep.new(
108
- id: step.id,
109
- pickle_step_id: @pickle_step_by_test_step.pickle_step_id(step),
110
- step_definition_ids: @step_definitions_by_test_step.step_definition_ids(step),
111
- step_match_arguments_lists: step_match_arguments_lists(step)
112
- )
113
- end
129
+ find_all_test_case_started_by_test_case_id =
130
+ @repository.test_case_started_by_id
131
+ .values
132
+ .select { |test_case_started| test_case_started.test_case_id == event.test_case.id }
114
133
 
115
- def hook_step_to_message(step)
116
- Cucumber::Messages::TestStep.new(
117
- id: step.id,
118
- hook_id: @hook_by_test_step.hook_id(step)
134
+ # If no TestCaseStarted messages exist. We must be on attempt 1 (Hence the .to_i casting for a `nil` value)
135
+ attempts_previously_made = find_all_test_case_started_by_test_case_id.map(&:attempt).max.to_i
136
+
137
+ message = Cucumber::Messages::Envelope.new(
138
+ test_case_started: Cucumber::Messages::TestCaseStarted.new(
139
+ id: @current_test_case_started_id,
140
+ test_case_id: event.test_case.id,
141
+ timestamp: time_to_timestamp(Time.now),
142
+ attempt: attempts_previously_made + 1
143
+ )
119
144
  )
120
- end
121
145
 
122
- def step_match_arguments_lists(step)
123
- match_arguments = step_match_arguments(step)
124
- [Cucumber::Messages::StepMatchArgumentsList.new(
125
- step_match_arguments: match_arguments
126
- )]
127
- rescue Cucumber::Formatter::TestStepUnknownError
128
- []
146
+ @config.event_bus.envelope(message)
147
+ @repository.update(message)
129
148
  end
130
149
 
131
- def step_match_arguments(step)
132
- @step_definitions_by_test_step.step_match_arguments(step).map do |argument|
133
- Cucumber::Messages::StepMatchArgument.new(
134
- group: argument_group_to_message(argument.group),
135
- parameter_type_name: parameter_type_name(argument)
136
- )
137
- end
138
- end
150
+ def on_test_case_finished(event)
151
+ test_case_started_id =
152
+ @repository.test_case_started_by_id
153
+ .values
154
+ .detect { |test_case_started_message| test_case_started_message.test_case_id == event.test_case.id }
155
+ .id
139
156
 
140
- def argument_group_to_message(group)
141
- Cucumber::Messages::Group.new(
142
- start: group.start,
143
- value: group.value,
144
- children: group.children.map { |child| argument_group_to_message(child) }
157
+ test_case_started_message = @repository.test_case_started_by_id[test_case_started_id]
158
+ max_attempts = @config.retry_attempts
159
+ retries_attempted = test_case_started_message.attempt - 1
160
+ will_be_retried = event.result.failed? && (retries_attempted < max_attempts)
161
+
162
+ message = Cucumber::Messages::Envelope.new(
163
+ test_case_finished: Cucumber::Messages::TestCaseFinished.new(
164
+ test_case_started_id: test_case_started_id,
165
+ timestamp: time_to_timestamp(Time.now),
166
+ will_be_retried: will_be_retried
167
+ )
145
168
  )
146
- end
147
169
 
148
- def parameter_type_name(step_match_argument)
149
- step_match_argument.parameter_type&.name if step_match_argument.respond_to?(:parameter_type)
170
+ @config.event_bus.envelope(message)
150
171
  end
151
172
 
152
173
  def on_test_run_started(*)
153
- @current_test_run_started_id = @test_run_started.id
154
-
155
174
  message = Cucumber::Messages::Envelope.new(
156
175
  test_run_started: Cucumber::Messages::TestRunStarted.new(
157
176
  timestamp: time_to_timestamp(Time.now),
158
- id: @current_test_run_started_id
177
+ id: @test_run_started_id
159
178
  )
160
179
  )
161
180
 
162
- output_envelope(message)
181
+ @config.event_bus.envelope(message)
163
182
  end
164
183
 
165
- def on_test_case_started(event)
166
- @current_test_case_started_id = test_case_started_id(event.test_case)
167
-
184
+ def on_test_run_finished(event)
168
185
  message = Cucumber::Messages::Envelope.new(
169
- test_case_started: Cucumber::Messages::TestCaseStarted.new(
170
- id: test_case_started_id(event.test_case),
171
- test_case_id: event.test_case.id,
186
+ test_run_finished: Cucumber::Messages::TestRunFinished.new(
172
187
  timestamp: time_to_timestamp(Time.now),
173
- attempt: @test_case_started_by_test_case.attempt_by_test_case(event.test_case)
188
+ success: event.success,
189
+ test_run_started_id: @test_run_started_id
174
190
  )
175
191
  )
176
192
 
177
- output_envelope(message)
193
+ @config.event_bus.envelope(message)
194
+ end
195
+
196
+ def on_test_step_created(event)
197
+ @pickle_id_step_by_test_step_id[event.test_step.id] = event.pickle_step.id
198
+ @step_definition_ids_by_test_step_id[event.test_step.id] = []
178
199
  end
179
200
 
180
201
  def on_test_step_started(event)
181
202
  @current_test_step_id = event.test_step.id
182
- test_case = @test_case_by_step_id[event.test_step.id]
203
+ find_test_case_by_step_id =
204
+ @repository.test_case_by_id
205
+ .values
206
+ .detect { |test_case_message| test_case_message.test_steps.any? { |step_message| step_message.id == event.test_step.id } }
207
+
208
+ find_test_case_started_by_test_case =
209
+ @repository.test_case_started_by_id
210
+ .values
211
+ .select { |test_case_started_message| test_case_started_message.test_case_id == find_test_case_by_step_id.id }
212
+ .max_by(&:attempt)
183
213
 
184
214
  message = Cucumber::Messages::Envelope.new(
185
215
  test_step_started: Cucumber::Messages::TestStepStarted.new(
186
216
  test_step_id: event.test_step.id,
187
- test_case_started_id: test_case_started_id(test_case),
217
+ test_case_started_id: find_test_case_started_by_test_case.id,
188
218
  timestamp: time_to_timestamp(Time.now)
189
219
  )
190
220
  )
191
221
 
192
- output_envelope(message)
222
+ @config.event_bus.envelope(message)
193
223
  end
194
224
 
195
225
  def on_test_step_finished(event)
196
- test_case = @test_case_by_step_id[event.test_step.id]
197
- result = event.result.with_filtered_backtrace(Cucumber::Formatter::BacktraceFilter)
226
+ find_test_case_by_step_id =
227
+ @repository.test_case_by_id
228
+ .values
229
+ .detect { |test_case_message| test_case_message.test_steps.any? { |step_message| step_message.id == event.test_step.id } }
198
230
 
231
+ find_test_case_started_by_test_case =
232
+ @repository.test_case_started_by_id
233
+ .values
234
+ .select { |test_case_started_message| test_case_started_message.test_case_id == find_test_case_by_step_id.id }
235
+ .max_by(&:attempt)
236
+
237
+ result = event.result.with_filtered_backtrace(Cucumber::Formatter::BacktraceFilter)
199
238
  result_message = result.to_message
200
239
  if result.failed? || result.pending?
201
240
  message_element = result.failed? ? result.exception : result
@@ -208,16 +247,105 @@ module Cucumber
208
247
  )
209
248
  end
210
249
 
250
+ output_snippet_envelope(event)
251
+
211
252
  message = Cucumber::Messages::Envelope.new(
212
253
  test_step_finished: Cucumber::Messages::TestStepFinished.new(
213
254
  test_step_id: event.test_step.id,
214
- test_case_started_id: test_case_started_id(test_case),
255
+ test_case_started_id: find_test_case_started_by_test_case.id,
215
256
  test_step_result: result_message,
216
257
  timestamp: time_to_timestamp(Time.now)
217
258
  )
218
259
  )
219
260
 
220
- output_envelope(message)
261
+ @config.event_bus.envelope(message)
262
+ end
263
+
264
+ def output_snippet_envelope(event)
265
+ return unless event.result.undefined?
266
+
267
+ collect_snippet_data(event.test_step, @ast_lookup)
268
+ snippet_text_proc = lambda do |step_keyword, step_name, multiline_arg|
269
+ snippet_text(step_keyword, step_name, multiline_arg)
270
+ end
271
+
272
+ message = generate_snippet_envelope(snippet_text_proc, event)
273
+ @config.event_bus.envelope(message)
274
+ # To ensure we don't redistribute the "same" snippets over and over again
275
+ snippets_input.clear
276
+ end
277
+
278
+ def generate_snippet_envelope(snippet_text_proc, event)
279
+ snippets_array = snippets_input.map do |data|
280
+ snippet_text_proc.call(data.actual_keyword, data.step.text, data.step.multiline_arg)
281
+ end.uniq
282
+
283
+ Cucumber::Messages::Envelope.new(
284
+ suggestion: Cucumber::Messages::Suggestion.new(
285
+ id: @config.id_generator.new_id,
286
+ pickle_step_id: @repository.test_step_by_id[event.test_step.id].pickle_step_id,
287
+ snippets: snippets_array.map { |code_snippet| Cucumber::Messages::Snippet.new(language: 'ruby', code: code_snippet) }
288
+ )
289
+ )
290
+ end
291
+
292
+ def on_undefined_parameter_type(event)
293
+ message = Cucumber::Messages::Envelope.new(
294
+ undefined_parameter_type: Cucumber::Messages::UndefinedParameterType.new(
295
+ name: event.type_name,
296
+ expression: event.expression
297
+ )
298
+ )
299
+
300
+ @config.event_bus.envelope(message)
301
+ end
302
+
303
+ def test_step_to_message(step)
304
+ return hook_step_to_message(step) if step.hook?
305
+
306
+ Cucumber::Messages::TestStep.new(
307
+ id: step.id,
308
+ pickle_step_id: @pickle_id_step_by_test_step_id[step.id],
309
+ step_definition_ids: fake_query_step_definition_ids(step),
310
+ step_match_arguments_lists: step_match_arguments_lists(step)
311
+ )
312
+ end
313
+
314
+ def hook_step_to_message(step)
315
+ Cucumber::Messages::TestStep.new(
316
+ id: step.id,
317
+ hook_id: @hook_id_by_test_step_id[step.id]
318
+ )
319
+ end
320
+
321
+ def step_match_arguments_lists(step)
322
+ match_arguments = step_match_arguments(step)
323
+ if match_arguments.nil?
324
+ []
325
+ else
326
+ [Cucumber::Messages::StepMatchArgumentsList.new(step_match_arguments: match_arguments)]
327
+ end
328
+ end
329
+
330
+ def step_match_arguments(step)
331
+ fake_query_step_match_arguments(step)&.map do |argument|
332
+ Cucumber::Messages::StepMatchArgument.new(
333
+ group: argument_group_to_message(argument.group),
334
+ parameter_type_name: parameter_type_name(argument)
335
+ )
336
+ end
337
+ end
338
+
339
+ def argument_group_to_message(group)
340
+ Cucumber::Messages::Group.new(
341
+ start: group.start,
342
+ value: group.value,
343
+ children: group.children&.map { |child| argument_group_to_message(child) }
344
+ )
345
+ end
346
+
347
+ def parameter_type_name(step_match_argument)
348
+ step_match_argument.parameter_type&.name if step_match_argument.respond_to?(:parameter_type)
221
349
  end
222
350
 
223
351
  def create_error_message(message_element)
@@ -237,42 +365,20 @@ module Cucumber
237
365
  )
238
366
  end
239
367
 
240
- def on_test_case_finished(event)
241
- message = Cucumber::Messages::Envelope.new(
242
- test_case_finished: Cucumber::Messages::TestCaseFinished.new(
243
- test_case_started_id: test_case_started_id(event.test_case),
244
- timestamp: time_to_timestamp(Time.now)
245
- )
246
- )
247
-
248
- output_envelope(message)
368
+ def fake_query_hook_id(test_step)
369
+ @hook_id_by_test_step_id.fetch(test_step.id)
249
370
  end
250
371
 
251
- def on_test_run_finished(event)
252
- message = Cucumber::Messages::Envelope.new(
253
- test_run_finished: Cucumber::Messages::TestRunFinished.new(
254
- timestamp: time_to_timestamp(Time.now),
255
- success: event.success,
256
- test_run_started_id: @current_test_run_started_id
257
- )
258
- )
259
-
260
- output_envelope(message)
372
+ def fake_query_pickle_id(test_case)
373
+ @pickle_id_by_test_case_id.fetch(test_case.id)
261
374
  end
262
375
 
263
- def on_undefined_parameter_type(event)
264
- message = Cucumber::Messages::Envelope.new(
265
- undefined_parameter_type: Cucumber::Messages::UndefinedParameterType.new(
266
- name: event.type_name,
267
- expression: event.expression
268
- )
269
- )
270
-
271
- output_envelope(message)
376
+ def fake_query_step_definition_ids(test_step)
377
+ @step_definition_ids_by_test_step_id.fetch(test_step.id)
272
378
  end
273
379
 
274
- def test_case_started_id(test_case)
275
- @test_case_started_by_test_case.test_case_started_id_by_test_case(test_case)
380
+ def fake_query_step_match_arguments(test_step)
381
+ @step_match_arguments_by_test_step_id.fetch(test_step.id, nil)
276
382
  end
277
383
  end
278
384
  end
@@ -33,8 +33,6 @@ module Cucumber
33
33
  @io = ensure_io(config.out_stream, config.error_stream)
34
34
  @config = config
35
35
  @options = config.to_hash
36
- @snippets_input = []
37
- @undefined_parameter_types = []
38
36
  @total_duration = 0
39
37
  @exceptions = []
40
38
  @gherkin_sources = {}
@@ -73,8 +71,7 @@ module Cucumber
73
71
  end
74
72
 
75
73
  def on_step_activated(event)
76
- test_step, step_match = *event.attributes
77
- @step_matches[test_step.to_s] = step_match
74
+ @step_matches[event.test_step.to_s] = event.step_match
78
75
  end
79
76
 
80
77
  def on_test_case_started(event)
@@ -140,7 +137,7 @@ module Cucumber
140
137
  print_summary
141
138
  end
142
139
 
143
- def attach(src, media_type, filename)
140
+ def attach(src, media_type, filename, _streamed_file)
144
141
  return unless media_type == 'text/x.cucumber.log+plain'
145
142
 
146
143
  if filename
@@ -20,8 +20,6 @@ module Cucumber
20
20
  def initialize(config)
21
21
  @config = config
22
22
  @io = ensure_io(config.out_stream, config.error_stream)
23
- @snippets_input = []
24
- @undefined_parameter_types = []
25
23
  @total_duration = 0
26
24
  @matches = {}
27
25
  @pending_step_matches = []
@@ -94,6 +92,7 @@ module Cucumber
94
92
  CHARS = {
95
93
  passed: '.',
96
94
  failed: 'F',
95
+ ambiguous: 'A',
97
96
  undefined: 'U',
98
97
  pending: 'P',
99
98
  skipped: '-'