cucumber-core 5.0.2 → 6.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3ab18c1635eeda0fbd575d01a83bafc96a0073a1ec0ba1249e4bf26b9c60f914
4
- data.tar.gz: 1dccc021f15d75d76c2c3974049f768ee926e0dd7ced151cc9b46a2b422b6906
3
+ metadata.gz: 1b9ecd1991c28bb04a27496f473972f9da886f102c94ac5a6176d4167773afb3
4
+ data.tar.gz: f833220cdb22fd26e68b3457c0c8ced6cc574227c8dc6dd30a540680a09ea8d2
5
5
  SHA512:
6
- metadata.gz: 81461cf45c9616e3e36fc70a25da1b3c0e30e709cc12e675994e6fd0f730ff4e68f9680453e31ecb4814d69a9a79a98ceeb0691a7365fc660fe9e4cad7462092
7
- data.tar.gz: 3a8cc3c74351d91f90c36f509a813b56cab9a333057de9b3b596de4b1feaa8dc912d87827d2682f1fc3f2b2eca2f82c75f38bd2f75204119eb21bcbcf0b8507a
6
+ metadata.gz: d720066139dee301d46a5bb64e2c9e630d599d4750ca5026a40e70cb5c547b14301aee31bdbe12627f043d9df0b427c87444adfa24b2d01c463e484feba2e724
7
+ data.tar.gz: 9d7e4f57de2b4c84c2e8a94bf68bc22aea34d058c8ef6bead5e975866a0bcaed53d5d987c0884d6db42e496eddf46273a946aba13565f78ba34b2eb9d22df265
data/CHANGELOG.md CHANGED
@@ -1,5 +1,27 @@
1
1
  Please see [CONTRIBUTING.md](https://github.com/cucumber/cucumber/blob/master/CONTRIBUTING.md) on how to contribute to Cucumber.
2
2
 
3
+ ## [6.0.0](https://github.com/cucumber/cucumber-ruby-core/compare/v5.0.2...v6.0.0)
4
+
5
+ ### Changed
6
+
7
+ * Update to Gherkin 10
8
+
9
+ ### Added
10
+
11
+ * Add `envelope` event, which are used when emitting `Cucumber::Messages`
12
+ * Add `TestCaseCreated` and `TestStepCreated` events, emitted when compiling a `Pickle`
13
+ * Add `Id` field to `TestCase` and `TestStep`
14
+ * Added rubocop (with todo file), and removed backports gems
15
+ ([#186](https://github.com/cucumber/cucumber-ruby-core/pull/186),
16
+ [#182](https://github.com/cucumber/cucumber-ruby-core/issues/182)
17
+ [tas50](https://github.com/tas50),
18
+ [luke-hill](https://github.com/luke-hill))
19
+
20
+ ### Removed
21
+
22
+ * Remove location for MultiLine arguments
23
+
24
+
3
25
  ## [5.0.2](https://github.com/cucumber/cucumber-ruby-core/compare/v5.0.1...v5.0.2)
4
26
 
5
27
  ### Changed
data/lib/cucumber/core.rb CHANGED
@@ -4,6 +4,8 @@ require 'cucumber/core/gherkin/parser'
4
4
  require 'cucumber/core/gherkin/document'
5
5
  require 'cucumber/core/compiler'
6
6
  require 'cucumber/core/test/runner'
7
+ require 'cucumber/messages'
8
+ require 'gherkin/query'
7
9
 
8
10
  module Cucumber
9
11
  module Core
@@ -11,21 +13,22 @@ module Cucumber
11
13
  def execute(gherkin_documents, filters = [], event_bus = EventBus.new)
12
14
  yield event_bus if block_given?
13
15
  receiver = Test::Runner.new(event_bus)
14
- compile gherkin_documents, receiver, filters
16
+ compile gherkin_documents, receiver, filters, event_bus
15
17
  self
16
18
  end
17
19
 
18
20
  def compile(gherkin_documents, last_receiver, filters = [], event_bus = EventBus.new)
19
21
  first_receiver = compose(filters, last_receiver)
20
- compiler = Compiler.new(first_receiver)
21
- parse gherkin_documents, compiler, event_bus
22
+ gherkin_query = ::Gherkin::Query.new
23
+ compiler = Compiler.new(first_receiver, gherkin_query, event_bus)
24
+ parse gherkin_documents, compiler, event_bus, gherkin_query
22
25
  self
23
26
  end
24
27
 
25
28
  private
26
29
 
27
- def parse(gherkin_documents, compiler, event_bus)
28
- parser = Core::Gherkin::Parser.new(compiler, event_bus)
30
+ def parse(gherkin_documents, compiler, event_bus, gherkin_query)
31
+ parser = Core::Gherkin::Parser.new(compiler, event_bus, gherkin_query)
29
32
  gherkin_documents.each do |document|
30
33
  parser.document document
31
34
  end
@@ -38,6 +41,5 @@ module Cucumber
38
41
  filter.with_receiver(receiver)
39
42
  end
40
43
  end
41
-
42
44
  end
43
45
  end
@@ -6,16 +6,20 @@ require 'cucumber/core/test/tag'
6
6
  require 'cucumber/core/test/doc_string'
7
7
  require 'cucumber/core/test/data_table'
8
8
  require 'cucumber/core/test/empty_multiline_argument'
9
+ require 'cucumber/messages'
9
10
 
10
11
  module Cucumber
11
12
  module Core
12
13
  # Compiles the Pickles into test cases
13
14
  class Compiler
14
- attr_reader :receiver
15
- private :receiver
15
+ attr_reader :receiver, :gherkin_query, :id_generator
16
+ private :receiver, :gherkin_query, :id_generator
16
17
 
17
- def initialize(receiver)
18
+ def initialize(receiver, gherkin_query, event_bus = nil)
18
19
  @receiver = receiver
20
+ @id_generator = Cucumber::Messages::IdGenerator::UUID.new
21
+ @gherkin_query = gherkin_query
22
+ @event_bus = event_bus
19
23
  end
20
24
 
21
25
  def pickle(pickle)
@@ -33,15 +37,19 @@ module Cucumber
33
37
  def create_test_case(pickle)
34
38
  uri = pickle.uri
35
39
  test_steps = pickle.steps.map { |step| create_test_step(step, uri) }
36
- lines = pickle.locations.map { |location| location.line }.sort.reverse
37
- tags = pickle.tags.map { |tag| Test::Tag.new(Test::Location.new(uri, tag.location.line), tag.name) }
38
- Test::Case.new(pickle.name, test_steps, Test::Location.new(uri, lines), tags, pickle.language)
40
+ lines = source_lines_for_pickle(pickle).sort.reverse
41
+ tags = pickle.tags.map { |tag| Test::Tag.new(Test::Location.new(uri, source_line_for_pickle_tag(tag)), tag.name) }
42
+ test_case = Test::Case.new(id_generator.new_id, pickle.name, test_steps, Test::Location.new(uri, lines), tags, pickle.language)
43
+ @event_bus.test_case_created(test_case, pickle) unless @event_bus.nil?
44
+ test_case
39
45
  end
40
46
 
41
47
  def create_test_step(pickle_step, uri)
42
- lines = pickle_step.locations.map { |location| location.line }.sort.reverse
48
+ lines = source_lines_for_pickle_step(pickle_step).sort.reverse
43
49
  multiline_arg = create_multiline_arg(pickle_step, uri)
44
- Test::Step.new(pickle_step.text, Test::Location.new(uri, lines), multiline_arg)
50
+ step = Test::Step.new(id_generator.new_id, pickle_step.text, Test::Location.new(uri, lines), multiline_arg)
51
+ @event_bus.test_step_created(step, pickle_step) unless @event_bus.nil?
52
+ step
45
53
  end
46
54
 
47
55
  def create_multiline_arg(pickle_step, uri)
@@ -50,21 +58,34 @@ module Cucumber
50
58
  doc_string = pickle_step.argument.doc_string
51
59
  Test::DocString.new(
52
60
  doc_string.content,
53
- doc_string.contentType,
54
- Test::Location.new(uri, doc_string.location.line)
61
+ doc_string.media_type
55
62
  )
56
63
  elsif pickle_step.argument.data_table
57
64
  data_table = pickle_step.argument.data_table
58
- first_cell = data_table.rows.first.cells.first
59
65
  Test::DataTable.new(
60
- data_table.rows.map { |row| row.cells.map { |cell| cell.value } },
61
- Test::Location.new(uri, first_cell.location.line)
66
+ data_table.rows.map { |row| row.cells.map { |cell| cell.value } }
62
67
  )
63
68
  end
64
69
  else
65
70
  Test::EmptyMultilineArgument.new
66
71
  end
67
72
  end
73
+
74
+ def source_lines_for_pickle(pickle)
75
+ pickle.ast_node_ids.map { |id| source_line(id) }
76
+ end
77
+
78
+ def source_lines_for_pickle_step(pickle_step)
79
+ pickle_step.ast_node_ids.map { |id| source_line(id) }
80
+ end
81
+
82
+ def source_line_for_pickle_tag(tag)
83
+ source_line(tag.ast_node_id)
84
+ end
85
+
86
+ def source_line(id)
87
+ gherkin_query.location(id).line
88
+ end
68
89
  end
69
90
  end
70
91
  end
@@ -1,5 +1,3 @@
1
- require 'backports/2.1.0/array/to_h'
2
-
3
1
  module Cucumber
4
2
  module Core
5
3
  class Event
@@ -5,6 +5,10 @@ module Cucumber
5
5
  module Core
6
6
  module Events
7
7
 
8
+ class Envelope < Event.new(:envelope)
9
+ attr_reader :envelope
10
+ end
11
+
8
12
  # Signals that a gherkin source has been parsed
9
13
  class GherkinSourceParsed < Event.new(:gherkin_document)
10
14
  # @return [GherkinDocument] the GherkinDocument Ast Node
@@ -12,6 +16,24 @@ module Cucumber
12
16
 
13
17
  end
14
18
 
19
+ # Signals that a Test::Step was created from a PickleStep
20
+ class TestStepCreated < Event.new(:test_step, :pickle_step)
21
+ # The created test step
22
+ attr_reader :test_step
23
+
24
+ # The source pickle step
25
+ attr_reader :pickle_step
26
+ end
27
+
28
+ # Signals that a Test::Case was created from a Pickle
29
+ class TestCaseCreated < Event.new(:test_case, :pickle)
30
+ # The created test step
31
+ attr_reader :test_case
32
+
33
+ # The source pickle step
34
+ attr_reader :pickle
35
+ end
36
+
15
37
  # Signals that a {Test::Case} is about to be executed
16
38
  class TestCaseStarted < Event.new(:test_case)
17
39
 
@@ -55,7 +77,10 @@ module Cucumber
55
77
  # that will be used by the {EventBus} by default.
56
78
  def self.registry
57
79
  build_registry(
80
+ Envelope,
58
81
  GherkinSourceParsed,
82
+ TestStepCreated,
83
+ TestCaseCreated,
59
84
  TestCaseStarted,
60
85
  TestStepStarted,
61
86
  TestStepFinished,
@@ -7,24 +7,27 @@ module Cucumber
7
7
  ParseError = Class.new(StandardError)
8
8
 
9
9
  class Parser
10
- attr_reader :receiver, :event_bus
11
- private :receiver, :event_bus
10
+ attr_reader :receiver, :event_bus, :gherkin_query
11
+ private :receiver, :event_bus, :gherkin_query
12
12
 
13
- def initialize(receiver, event_bus)
13
+ def initialize(receiver, event_bus, gherkin_query)
14
14
  @receiver = receiver
15
15
  @event_bus = event_bus
16
+ @gherkin_query = gherkin_query
16
17
  end
17
18
 
18
19
  def document(document)
19
20
  messages = ::Gherkin.from_source(document.uri, document.body, gherkin_options(document))
20
21
  messages.each do |message|
21
- if !message.gherkinDocument.nil?
22
- event_bus.gherkin_source_parsed(message.gherkinDocument)
22
+ event_bus.envelope(message)
23
+ gherkin_query.update(message)
24
+ if !message.gherkin_document.nil?
25
+ event_bus.gherkin_source_parsed(message.gherkin_document)
23
26
  elsif !message.pickle.nil?
24
27
  receiver.pickle(message.pickle)
25
28
  elsif !message.attachment.nil?
26
29
  # Parse error
27
- raise Core::Gherkin::ParseError.new("#{document.uri}: #{message.attachment.data}")
30
+ raise Core::Gherkin::ParseError.new("#{document.uri}: #{message.attachment.text}")
28
31
  else
29
32
  raise "Unknown message: #{message.to_hash}"
30
33
  end
@@ -7,10 +7,11 @@ module Cucumber
7
7
  module Core
8
8
  module Test
9
9
  class Case
10
- attr_reader :name, :test_steps, :location, :tags, :language, :around_hooks
10
+ attr_reader :id, :name, :test_steps, :location, :tags, :language, :around_hooks
11
11
 
12
- def initialize(name, test_steps, location, tags, language, around_hooks = [])
12
+ def initialize(id, name, test_steps, location, tags, language, around_hooks = [])
13
13
  raise ArgumentError.new("test_steps should be an Array but is a #{test_steps.class}") unless test_steps.is_a?(Array)
14
+ @id = id
14
15
  @name = name
15
16
  @test_steps = test_steps
16
17
  @location = location
@@ -35,11 +36,11 @@ module Cucumber
35
36
  end
36
37
 
37
38
  def with_steps(test_steps)
38
- self.class.new(name, test_steps, location, tags, language, around_hooks)
39
+ self.class.new(id, name, test_steps, location, tags, language, around_hooks)
39
40
  end
40
41
 
41
42
  def with_around_hooks(around_hooks)
42
- self.class.new(name, test_steps, location, tags, language, around_hooks)
43
+ self.class.new(id, name, test_steps, location, tags, language, around_hooks)
43
44
  end
44
45
 
45
46
  def match_tags?(*expressions)
@@ -1,5 +1,4 @@
1
1
  # frozen_string_literal: true
2
- require 'cucumber/core/test/location'
3
2
 
4
3
  module Cucumber
5
4
  module Core
@@ -24,18 +23,15 @@ module Cucumber
24
23
  # This will store <tt>[['a', 'b'], ['c', 'd']]</tt> in the <tt>data</tt> variable.
25
24
  #
26
25
  class DataTable
27
- include HasLocation
28
-
29
26
  # Creates a new instance. +raw+ should be an Array of Array of String
30
27
  # or an Array of Hash
31
28
  # You don't typically create your own DataTable objects - Cucumber will do
32
29
  # it internally and pass them to your Step Definitions.
33
30
  #
34
- def initialize(rows, location)
31
+ def initialize(rows)
35
32
  raw = ensure_array_of_array(rows)
36
33
  verify_rows_are_same_length(raw)
37
34
  @raw = raw.freeze
38
- @location = location
39
35
  end
40
36
  attr_reader :raw
41
37
 
@@ -58,7 +54,7 @@ module Cucumber
58
54
  # Creates a copy of this table
59
55
  #
60
56
  def dup
61
- self.class.new(raw.dup, location)
57
+ self.class.new(raw.dup)
62
58
  end
63
59
 
64
60
  # Returns a new, transposed table. Example:
@@ -73,7 +69,7 @@ module Cucumber
73
69
  # | 4 | 2 |
74
70
  #
75
71
  def transpose
76
- self.class.new(raw.transpose, location)
72
+ self.class.new(raw.transpose)
77
73
  end
78
74
 
79
75
  def map(&block)
@@ -81,7 +77,7 @@ module Cucumber
81
77
  row.map(&block)
82
78
  end
83
79
 
84
- self.class.new(new_raw, location)
80
+ self.class.new(new_raw)
85
81
  end
86
82
 
87
83
  def ==(other)
@@ -89,7 +85,7 @@ module Cucumber
89
85
  end
90
86
 
91
87
  def inspect
92
- %{#<#{self.class} #{raw.inspect} (#{location})>}
88
+ %{#<#{self.class} #{raw.inspect})>}
93
89
  end
94
90
 
95
91
  private
@@ -20,14 +20,11 @@ module Cucumber
20
20
  # Note how the indentation from the source is stripped away.
21
21
  #
22
22
  class DocString < SimpleDelegator
23
- include HasLocation
24
-
25
23
  attr_reader :content_type, :content
26
24
 
27
- def initialize(content, content_type, location)
25
+ def initialize(content, content_type)
28
26
  @content = content
29
27
  @content_type = content_type
30
- @location = location
31
28
  super @content
32
29
  end
33
30
 
@@ -46,7 +43,7 @@ module Cucumber
46
43
  def map
47
44
  raise ArgumentError, "No block given" unless block_given?
48
45
  new_content = yield content
49
- self.class.new(new_content, content_type, location)
46
+ self.class.new(new_content, content_type)
50
47
  end
51
48
 
52
49
  def to_step_definition_arg
@@ -65,7 +62,7 @@ module Cucumber
65
62
 
66
63
  def inspect
67
64
  [
68
- %{#<#{self.class} (#{location})},
65
+ %{#<#{self.class}},
69
66
  %{ """#{content_type}},
70
67
  %{ #{@content}},
71
68
  %{ """>}
@@ -9,7 +9,6 @@ module Cucumber
9
9
  STRICT_AFFECTED_TYPES = [:flaky, :undefined, :pending].freeze
10
10
 
11
11
  def self.ok?(type, be_strict = StrictConfiguration.new)
12
- private
13
12
  class_name = type.to_s.slice(0, 1).capitalize + type.to_s.slice(1..-1)
14
13
  const_get(class_name).ok?(be_strict.strict?(type))
15
14
  end
@@ -43,6 +42,13 @@ module Cucumber
43
42
  def with_filtered_backtrace(filter)
44
43
  self
45
44
  end
45
+
46
+ def to_message
47
+ Cucumber::Messages::TestStepResult.new(
48
+ status: Cucumber::Messages::TestStepResult::Status::UNKNOWN,
49
+ duration: UnknownDuration.new.to_message_duration
50
+ )
51
+ end
46
52
  end
47
53
 
48
54
  class Passed
@@ -68,6 +74,13 @@ module Cucumber
68
74
  "✓"
69
75
  end
70
76
 
77
+ def to_message
78
+ Cucumber::Messages::TestStepResult.new(
79
+ status: Cucumber::Messages::TestStepResult::Status::PASSED,
80
+ duration: duration.to_message_duration
81
+ )
82
+ end
83
+
71
84
  def ok?(be_strict = nil)
72
85
  self.class.ok?
73
86
  end
@@ -83,6 +96,7 @@ module Cucumber
83
96
 
84
97
  class Failed
85
98
  include Result.query_methods :failed
99
+
86
100
  attr_reader :duration, :exception
87
101
 
88
102
  def self.ok?(be_strict = false)
@@ -107,6 +121,20 @@ module Cucumber
107
121
  "✗"
108
122
  end
109
123
 
124
+ def to_message
125
+ begin
126
+ message = exception.backtrace.join("\n")
127
+ rescue NoMethodError
128
+ message = ""
129
+ end
130
+
131
+ Cucumber::Messages::TestStepResult.new(
132
+ status: Cucumber::Messages::TestStepResult::Status::FAILED,
133
+ duration: duration.to_message_duration,
134
+ message: message
135
+ )
136
+ end
137
+
110
138
  def ok?(be_strict = nil)
111
139
  self.class.ok?
112
140
  end
@@ -186,6 +214,13 @@ module Cucumber
186
214
  def to_s
187
215
  "?"
188
216
  end
217
+
218
+ def to_message
219
+ Cucumber::Messages::TestStepResult.new(
220
+ status: Cucumber::Messages::TestStepResult::Status::UNDEFINED,
221
+ duration: duration.to_message_duration
222
+ )
223
+ end
189
224
  end
190
225
 
191
226
  class Skipped < Raisable
@@ -204,6 +239,13 @@ module Cucumber
204
239
  def to_s
205
240
  "-"
206
241
  end
242
+
243
+ def to_message
244
+ Cucumber::Messages::TestStepResult.new(
245
+ status: Cucumber::Messages::TestStepResult::Status::SKIPPED,
246
+ duration: duration.to_message_duration
247
+ )
248
+ end
207
249
  end
208
250
 
209
251
  class Pending < Raisable
@@ -222,6 +264,13 @@ module Cucumber
222
264
  def to_s
223
265
  "P"
224
266
  end
267
+
268
+ def to_message
269
+ Cucumber::Messages::TestStepResult.new(
270
+ status: Cucumber::Messages::TestStepResult::Status::PENDING,
271
+ duration: duration.to_message_duration
272
+ )
273
+ end
225
274
  end
226
275
 
227
276
  # Handles the strict settings for the result types that are
@@ -229,7 +278,7 @@ module Cucumber
229
278
  class StrictConfiguration
230
279
  attr_accessor :settings
231
280
  private :settings
232
-
281
+
233
282
  def initialize(strict_types = [])
234
283
  @settings = Hash[STRICT_AFFECTED_TYPES.map { |t| [t, :default] }]
235
284
  strict_types.each do |type|
@@ -329,7 +378,7 @@ module Cucumber
329
378
  def decrement_failed
330
379
  @totals[:failed] -= 1
331
380
  end
332
-
381
+
333
382
  private
334
383
 
335
384
  def get_total(method_name)
@@ -344,14 +393,22 @@ module Cucumber
344
393
  end
345
394
 
346
395
  class Duration
396
+ include Cucumber::Messages::TimeConversion
397
+
347
398
  attr_reader :nanoseconds
348
399
 
349
400
  def initialize(nanoseconds)
350
401
  @nanoseconds = nanoseconds
351
402
  end
403
+
404
+ def to_message_duration
405
+ seconds_to_duration(nanoseconds.to_f / NANOSECONDS_PER_SECOND)
406
+ end
352
407
  end
353
408
 
354
409
  class UnknownDuration
410
+ include Cucumber::Messages::TimeConversion
411
+
355
412
  def tap(&block)
356
413
  self
357
414
  end
@@ -359,6 +416,10 @@ module Cucumber
359
416
  def nanoseconds
360
417
  raise "#nanoseconds only allowed to be used in #tap block"
361
418
  end
419
+
420
+ def to_message_duration
421
+ seconds_to_duration(0)
422
+ end
362
423
  end
363
424
  end
364
425
  end