cucumber 11.1.0 → 11.1.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 41a92bddb6a0e5cdf8a69b28abfc455f4d77516e3f4abd8283cd6a222d1f5bd9
4
- data.tar.gz: 743067172c8d6e732e86a2417dfa43b809ecff66ad772477460af2b1e217c234
3
+ metadata.gz: 859f6f5538d072ccaff43df1dc5e3b2f0a35ea3f755a35aedd2af1e9586e8b8e
4
+ data.tar.gz: 023a90d837722c080abc31d0e31621498225986eabe82e11231779819c47e7f2
5
5
  SHA512:
6
- metadata.gz: b26e638126d5f0d7846390ed1ddbf2b38c76d92c19e43aa859ba8432b04a017e509a018e55abb590ad523e31f295daeec9e210506b862a310e996b138cb113ab
7
- data.tar.gz: 5360ce612562f89839f87cf568f8a0adc3d732e224f99900653e8c58a0b4c51892932c9568b10e58365f2652fe867023d7bd32f05df7a95860583167b52cfd55
6
+ metadata.gz: ff9685e425c6adf6150d85218d2e1cf13e418800917cdcdf4a68f2a51b1a267a8d47735b38b5aced3b6e22a91346d081fa2412e9fd3de2f8b1c40b5411c802a4
7
+ data.tar.gz: 5af3d569e9e0ce0ced379d414c961f1fa94bd96f54e0c41dcac9b09a507c504c6e4701d2a162e326bfcfd30a4f40ae6bcdeeed8ecc45e18f1925408a78dd9f46
data/VERSION CHANGED
@@ -1 +1 @@
1
- 11.1.0
1
+ 11.1.1
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'cucumber/core/events'
4
+
5
+ module Cucumber
6
+ module Events
7
+ # Fired when attach is called in a step definition
8
+ class AttachCalled < Core::Event.new(:src, :media_type, :filename)
9
+ # The attachment body
10
+ attr_reader :src
11
+
12
+ # The content media type
13
+ attr_reader :media_type
14
+
15
+ # An optional filename
16
+ attr_reader :filename
17
+ end
18
+ end
19
+ end
@@ -24,6 +24,7 @@ module Cucumber
24
24
 
25
25
  def self.registry
26
26
  Core::Events.build_registry(
27
+ AttachCalled,
27
28
  GherkinSourceParsed,
28
29
  GherkinSourceRead,
29
30
  HookTestStepCreated,
@@ -169,15 +169,15 @@ module Cucumber
169
169
  end
170
170
  end
171
171
 
172
- def attach(src, media_type, filename, _streamed_file)
173
- return unless media_type == 'text/x.cucumber.log+plain'
172
+ def on_attach_called(event)
173
+ return unless event.media_type == 'text/x.cucumber.log+plain'
174
174
  return unless @io
175
175
 
176
176
  @io.puts
177
- if filename
178
- @io.puts("#{filename}: #{format_string(src, :tag)}")
177
+ if event.filename
178
+ @io.puts("#{event.filename}: #{format_string(event.src, :tag)}")
179
179
  else
180
- @io.puts(format_string(src, :tag))
180
+ @io.puts(format_string(event.src, :tag))
181
181
  end
182
182
 
183
183
  @io.flush
@@ -27,8 +27,6 @@ module Cucumber
27
27
  def duration(duration, *)
28
28
  duration.tap { |dur| @result_duration = dur.nanoseconds / 10**9.0 }
29
29
  end
30
-
31
- def attach(*) end
32
30
  end
33
31
  end
34
32
  end
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'cucumber/formatter/io'
4
3
  require 'cucumber/html_formatter'
5
- require 'cucumber/formatter/message_builder'
4
+
5
+ require_relative 'message_builder'
6
6
 
7
7
  module Cucumber
8
8
  module Formatter
@@ -14,9 +14,11 @@ module Cucumber
14
14
  super(config)
15
15
  end
16
16
 
17
- def output_envelope(envelope)
18
- @repository.update(envelope)
17
+ def on_envelope(event)
18
+ super(event)
19
+ envelope = event.envelope
19
20
  @html_formatter.write_message(envelope)
21
+ # TODO: Move this conditional logic into the HTML formatter proper
20
22
  @html_formatter.write_post_message if envelope.test_run_finished
21
23
  end
22
24
  end
@@ -22,6 +22,7 @@ module Cucumber
22
22
  config.on_event :test_step_started, &method(:on_test_step_started)
23
23
  config.on_event :test_step_finished, &method(:on_test_step_finished)
24
24
  config.on_event :test_run_finished, &method(:on_test_run_finished)
25
+ config.on_event :attach_called, &method(:on_attach_called)
25
26
  end
26
27
 
27
28
  def on_test_case_started(event)
@@ -87,18 +88,19 @@ module Cucumber
87
88
  @io.write(JSON.pretty_generate(@feature_hashes))
88
89
  end
89
90
 
90
- def attach(src, mime_type, _filename, _streamed_file)
91
- if mime_type == 'text/x.cucumber.log+plain'
92
- test_step_output << src
91
+ def on_attach_called(event)
92
+ if event.media_type == 'text/x.cucumber.log+plain'
93
+ test_step_output << event.src
93
94
  return
94
95
  end
95
- if mime_type =~ /;base64$/
96
- mime_type = mime_type[0..-8]
97
- data = src
96
+ if event.media_type =~ /;base64$/
97
+ media_type = event.media_type[0..-8]
98
+ data = event.src
98
99
  else
99
- data = encode64(src)
100
+ data = encode64(event.src)
101
+ media_type = event.media_type
100
102
  end
101
- test_step_embeddings << { mime_type: mime_type, data: data }
103
+ test_step_embeddings << { mime_type: media_type, data: data }
102
104
  end
103
105
 
104
106
  private
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'cucumber/formatter/io'
4
- require 'cucumber/query'
3
+ require_relative 'io'
5
4
 
6
5
  module Cucumber
7
6
  module Formatter
@@ -11,14 +10,11 @@ module Cucumber
11
10
 
12
11
  def initialize(config)
13
12
  @io = ensure_io(config.out_stream, config.error_stream)
14
- @repository = Cucumber::Repository.new
15
- @query = Cucumber::Query.new(@repository)
16
13
  config.on_event :envelope, &method(:output_envelope)
17
14
  end
18
15
 
19
16
  def output_envelope(event)
20
17
  envelope = event.envelope
21
- @repository.update(envelope)
22
18
  @io.write(envelope.to_json)
23
19
  @io.write("\n")
24
20
  end
@@ -6,11 +6,14 @@ require 'json'
6
6
  require 'cucumber/formatter/backtrace_filter'
7
7
  require 'cucumber/query'
8
8
 
9
+ require_relative 'message_handlers'
10
+
9
11
  module Cucumber
10
12
  module Formatter
11
13
  class MessageBuilder
12
14
  include Cucumber::Messages::Helpers::TimeConversion
13
15
  include Io
16
+ include MessageHandlers
14
17
  include Console
15
18
 
16
19
  def initialize(config)
@@ -48,38 +51,41 @@ module Cucumber
48
51
  config.on_event :test_step_started, &method(:on_test_step_started)
49
52
  config.on_event :test_step_finished, &method(:on_test_step_finished)
50
53
 
54
+ config.on_event :attach_called, &method(:on_attach_called)
51
55
  config.on_event :envelope, &method(:on_envelope)
52
56
  end
53
57
 
54
58
  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
59
+ store_current_test_run_hook_started_id(event)
56
60
  end
57
61
 
58
- def attach(src, media_type, filename, streamed_file)
62
+ def on_attach_called(event)
59
63
  attachment_data =
60
64
  if @current_test_run_hook_started_id.nil?
61
65
  {
62
66
  test_step_id: @current_test_step_id,
63
67
  test_case_started_id: @current_test_case_started_id,
64
- media_type: media_type,
65
- file_name: filename,
68
+ media_type: event.media_type,
69
+ file_name: event.filename,
66
70
  timestamp: time_to_timestamp(Time.now)
67
71
  }
68
72
  else
69
73
  {
70
74
  test_run_hook_started_id: @current_test_run_hook_started_id,
71
- media_type: media_type,
72
- file_name: filename,
75
+ media_type: event.media_type,
76
+ file_name: event.filename,
73
77
  timestamp: time_to_timestamp(Time.now)
74
78
  }
75
79
  end
76
80
 
81
+ streamed_file = event.src.encoding == Encoding::BINARY
82
+
77
83
  if streamed_file
78
84
  attachment_data[:content_encoding] = Cucumber::Messages::AttachmentContentEncoding::BASE64
79
- attachment_data[:body] = Base64.strict_encode64(src)
85
+ attachment_data[:body] = Base64.strict_encode64(event.src)
80
86
  else
81
87
  attachment_data[:content_encoding] = Cucumber::Messages::AttachmentContentEncoding::IDENTITY
82
- attachment_data[:body] = src.is_a?(Hash) ? src.to_json : src
88
+ attachment_data[:body] = event.src.is_a?(Hash) ? event.src.to_json : event.src
83
89
  end
84
90
 
85
91
  message = Cucumber::Messages::Envelope.new(attachment: Cucumber::Messages::Attachment.new(**attachment_data))
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cucumber
4
+ module Formatter
5
+ # Common Message Handlers to be used across all message-based formatters
6
+ # Designed to work solely with events of type `Envelope`
7
+ module MessageHandlers
8
+ def store_current_test_run_hook_started_id(event)
9
+ @current_test_run_hook_started_id = event.envelope.test_run_hook_started.id if event.envelope.test_run_hook_started
10
+ end
11
+ end
12
+ end
13
+ end
@@ -64,6 +64,7 @@ module Cucumber
64
64
  config.on_event :test_case_finished, &method(:on_test_case_finished)
65
65
  config.on_event :test_run_finished, &method(:on_test_run_finished)
66
66
  config.on_event :undefined_parameter_type, &method(:collect_undefined_parameter_type_names)
67
+ config.on_event :attach_called, &method(:on_attach_called)
67
68
  end
68
69
 
69
70
  def on_gherkin_source_read(event)
@@ -137,13 +138,13 @@ module Cucumber
137
138
  print_summary
138
139
  end
139
140
 
140
- def attach(src, media_type, filename, _streamed_file)
141
- return unless media_type == 'text/x.cucumber.log+plain'
141
+ def on_attach_called(event)
142
+ return unless event.media_type == 'text/x.cucumber.log+plain'
142
143
 
143
- if filename
144
- @test_step_output.push("#{filename}: #{src}")
144
+ if event.filename
145
+ @test_step_output.push("#{event.filename}: #{event.src}")
145
146
  else
146
- @test_step_output.push(src)
147
+ @test_step_output.push(event.src)
147
148
  end
148
149
  end
149
150
 
@@ -36,6 +36,7 @@ module Cucumber
36
36
  config.on_event :test_case_finished, &method(:on_test_case_finished)
37
37
  config.on_event :test_run_finished, &method(:on_test_run_finished)
38
38
  config.on_event :undefined_parameter_type, &method(:collect_undefined_parameter_type_names)
39
+ config.on_event :attach_called, &method(:on_attach_called)
39
40
  end
40
41
 
41
42
  def on_step_activated(event)
@@ -1,8 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'cucumber/formatter/io'
4
3
  require 'cucumber/query'
5
4
 
5
+ require_relative 'io'
6
+
6
7
  module Cucumber
7
8
  module Formatter
8
9
  class Rerun
@@ -4,12 +4,13 @@ require 'cucumber/formatter/io'
4
4
  require 'cucumber/formatter/console'
5
5
  require 'cucumber/formatter/console_counts'
6
6
  require 'cucumber/formatter/console_issues'
7
+ require 'cucumber/formatter/backtrace_filter'
7
8
  require 'cucumber/core/test/result'
8
9
  require 'cucumber/formatter/ast_lookup'
9
10
 
10
11
  module Cucumber
11
12
  module Formatter
12
- # Summary formatter, outputting only feature / scenario titles
13
+ # Summary formatter, outputting feature / scenario titles plus failure details
13
14
  class Summary
14
15
  include Io
15
16
  include Console
@@ -20,6 +21,7 @@ module Cucumber
20
21
  @ast_lookup = AstLookup.new(config)
21
22
  @counts = ConsoleCounts.new(@config)
22
23
  @issues = ConsoleIssues.new(@config, @ast_lookup)
24
+ @failed_results = []
23
25
  @start_time = Time.now
24
26
 
25
27
  @config.on_event :test_case_started do |event|
@@ -31,9 +33,14 @@ module Cucumber
31
33
  print_result event.result
32
34
  end
33
35
 
36
+ @config.on_event :test_step_finished do |event|
37
+ collect_failed_result(event.test_step, event.result)
38
+ end
39
+
34
40
  @config.on_event :test_run_finished do |_event|
35
41
  duration = Time.now - @start_time
36
42
  @io.puts
43
+ print_elements(@failed_results, :failed, 'steps')
37
44
  print_statistics(duration, @config, @counts, @issues)
38
45
  end
39
46
  end
@@ -61,6 +68,13 @@ module Cucumber
61
68
  def print_result(result)
62
69
  @io.puts format_string(result, result.to_sym)
63
70
  end
71
+
72
+ def collect_failed_result(test_step, result)
73
+ return if test_step.hook?
74
+
75
+ result = result.with_filtered_backtrace(Cucumber::Formatter::BacktraceFilter)
76
+ @failed_results << result if result.failed?
77
+ end
64
78
  end
65
79
  end
66
80
  end
@@ -93,12 +93,11 @@ module Cucumber
93
93
  if File.file?(file)
94
94
  media_type = MiniMime.lookup_by_filename(file)&.content_type if media_type.nil?
95
95
  file = File.read(file, mode: 'rb')
96
- streamed_file = true
97
96
  end
98
97
  # We pass in the concept of whether the file is streamed to ensure that the envelope encoding is correct
99
- super(file, media_type, filename, streamed_file)
98
+ super(file, media_type, filename)
100
99
  rescue StandardError
101
- super(file, media_type, filename, streamed_file)
100
+ super(file, media_type, filename)
102
101
  end
103
102
 
104
103
  # Mark the matched step as pending.
@@ -155,8 +154,8 @@ module Cucumber
155
154
  runtime.ask(question, timeout_seconds)
156
155
  end
157
156
 
158
- define_method(:attach) do |file, media_type, filename, streamed_file|
159
- runtime.attach(file, media_type, filename, streamed_file)
157
+ define_method(:attach) do |file, media_type, filename|
158
+ runtime.attach(file, media_type, filename)
160
159
  end
161
160
 
162
161
  # Prints the list of modules that are included in the World
@@ -1,11 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'timeout'
4
+ require 'cucumber/events/attach_called'
4
5
 
5
6
  module Cucumber
6
7
  class Runtime
7
8
  module UserInterface
8
- attr_writer :visitor
9
+ attr_writer :configuration
9
10
 
10
11
  # Suspends execution and prompts +question+ to the console (STDOUT).
11
12
  # An operator (manual tester) can then enter a line of text and hit
@@ -41,8 +42,9 @@ module Cucumber
41
42
  # be a path to a file, or if it's an image it may also be a Base64 encoded image.
42
43
  # The embedded data may or may not be ignored, depending on what kind of formatter(s) are active.
43
44
  #
44
- def attach(src, media_type, filename, streamed_file)
45
- @visitor.attach(src, media_type, filename, streamed_file)
45
+ def attach(src, media_type, filename)
46
+ @configuration.notify(:attach_called, src, media_type, filename)
47
+ self
46
48
  end
47
49
 
48
50
  private
@@ -6,7 +6,6 @@ require 'cucumber/load_path'
6
6
  require 'cucumber/formatter/duration'
7
7
  require 'cucumber/file_specs'
8
8
  require 'cucumber/filters'
9
- require 'cucumber/formatter/fanout'
10
9
  require 'cucumber/gherkin/i18n'
11
10
  require 'cucumber/glue/registry_wrapper'
12
11
  require 'cucumber/step_match_search'
@@ -72,8 +71,7 @@ module Cucumber
72
71
 
73
72
  load_step_definitions
74
73
  fire_install_plugin_hook
75
- # TODO: can we remove this state?
76
- self.visitor = report
74
+ create_formatters
77
75
 
78
76
  receiver = Test::Runner.new(@configuration.event_bus)
79
77
  compile features, receiver, filters, @configuration.event_bus
@@ -198,13 +196,17 @@ module Cucumber
198
196
  require 'cucumber/formatter/publish_banner_printer'
199
197
  require 'cucumber/core/report/summary'
200
198
 
201
- def report
202
- return @report if @report
203
-
204
- reports = [message_builder, summary_report, global_hooks_summary_report] + formatters
205
- reports << fail_fast_report if @configuration.fail_fast?
206
- reports << publish_banner_printer unless @configuration.publish_quiet?
207
- @report ||= Formatter::Fanout.new(reports)
199
+ def create_formatters
200
+ # Define all formatters which are specified via cli options
201
+ formatters
202
+ # Define the MessageBuilder formatter - Required until all messages are generated at the source
203
+ # Skip when a user formatter already inherits from MessageBuilder (e.g. HTML) to avoid sending every event twice.
204
+ message_builder unless formatters.any? { |f| f.is_a?(Formatter::MessageBuilder) }
205
+ # `summary_report` and `global_hooks_summary_report` are used to determine the exit code
206
+ summary_report
207
+ global_hooks_summary_report
208
+ fail_fast_report if @configuration.fail_fast?
209
+ publish_banner_printer unless @configuration.publish_quiet?
208
210
  end
209
211
 
210
212
  def message_builder
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: 11.1.0
4
+ version: 11.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aslak Hellesøy
@@ -353,6 +353,7 @@ files:
353
353
  - lib/cucumber/encoding.rb
354
354
  - lib/cucumber/errors.rb
355
355
  - lib/cucumber/events.rb
356
+ - lib/cucumber/events/attach_called.rb
356
357
  - lib/cucumber/events/base.rb
357
358
  - lib/cucumber/events/envelope.rb
358
359
  - lib/cucumber/events/gherkin_source_parsed.rb
@@ -402,7 +403,6 @@ files:
402
403
  - lib/cucumber/formatter/duration.rb
403
404
  - lib/cucumber/formatter/duration_extractor.rb
404
405
  - lib/cucumber/formatter/fail_fast.rb
405
- - lib/cucumber/formatter/fanout.rb
406
406
  - lib/cucumber/formatter/global_hooks_summary.rb
407
407
  - lib/cucumber/formatter/html.rb
408
408
  - lib/cucumber/formatter/http_io.rb
@@ -414,6 +414,7 @@ files:
414
414
  - lib/cucumber/formatter/junit.rb
415
415
  - lib/cucumber/formatter/message.rb
416
416
  - lib/cucumber/formatter/message_builder.rb
417
+ - lib/cucumber/formatter/message_handlers.rb
417
418
  - lib/cucumber/formatter/pretty.rb
418
419
  - lib/cucumber/formatter/progress.rb
419
420
  - lib/cucumber/formatter/publish_banner_printer.rb
@@ -498,5 +499,5 @@ required_rubygems_version: !ruby/object:Gem::Requirement
498
499
  requirements: []
499
500
  rubygems_version: 4.0.10
500
501
  specification_version: 4
501
- summary: cucumber-11.1.0
502
+ summary: cucumber-11.1.1
502
503
  test_files: []
@@ -1,28 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Cucumber
4
- module Formatter
5
- # Forwards any messages sent to this object to all recipients
6
- # that respond to that message.
7
- class Fanout < BasicObject
8
- attr_reader :recipients
9
- private :recipients
10
-
11
- def initialize(recipients)
12
- @recipients = recipients
13
- end
14
-
15
- def method_missing(message, *args)
16
- super unless recipients
17
-
18
- recipients.each do |recipient|
19
- recipient.send(message, *args) if recipient.respond_to?(message)
20
- end
21
- end
22
-
23
- def respond_to_missing?(name, include_private = false)
24
- recipients.any? { |recipient| recipient.respond_to?(name, include_private) } || super(name, include_private)
25
- end
26
- end
27
- end
28
- end