cucumber-core 5.0.1 → 8.0.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.
@@ -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::TestStepFinished::TestStepResult.new(
48
+ status: Cucumber::Messages::TestStepFinished::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::TestStepFinished::TestStepResult.new(
79
+ status: Cucumber::Messages::TestStepFinished::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::TestStepFinished::TestStepResult.new(
132
+ status: Cucumber::Messages::TestStepFinished::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::TestStepFinished::TestStepResult.new(
220
+ status: Cucumber::Messages::TestStepFinished::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::TestStepFinished::TestStepResult.new(
245
+ status: Cucumber::Messages::TestStepFinished::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::TestStepFinished::TestStepResult.new(
270
+ status: Cucumber::Messages::TestStepFinished::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
@@ -8,10 +8,11 @@ module Cucumber
8
8
  module Core
9
9
  module Test
10
10
  class Step
11
- attr_reader :text, :location, :multiline_arg
11
+ attr_reader :id, :text, :location, :multiline_arg
12
12
 
13
- def initialize(text, location, multiline_arg = Test::EmptyMultilineArgument.new, action = Test::UndefinedAction.new(location))
13
+ def initialize(id, text, location, multiline_arg = Test::EmptyMultilineArgument.new, action = Test::UndefinedAction.new(location))
14
14
  raise ArgumentError if text.nil? || text.empty?
15
+ @id = id
15
16
  @text = text
16
17
  @location = location
17
18
  @multiline_arg = multiline_arg
@@ -35,7 +36,7 @@ module Cucumber
35
36
  end
36
37
 
37
38
  def with_action(action_location = nil, &block)
38
- self.class.new(text, location, multiline_arg, Test::Action.new(action_location, &block))
39
+ self.class.new(id, text, location, multiline_arg, Test::Action.new(action_location, &block))
39
40
  end
40
41
 
41
42
  def backtrace_line
@@ -56,8 +57,8 @@ module Cucumber
56
57
  end
57
58
 
58
59
  class HookStep < Step
59
- def initialize(text, location, action)
60
- super(text, location, Test::EmptyMultilineArgument.new, action)
60
+ def initialize(id, text, location, action)
61
+ super(id, text, location, Test::EmptyMultilineArgument.new, action)
61
62
  end
62
63
 
63
64
  def hook?
@@ -3,7 +3,7 @@ module Cucumber
3
3
  module Core
4
4
  class Version
5
5
  def self.to_s
6
- "5.0.1"
6
+ "8.0.1"
7
7
  end
8
8
  end
9
9
  end
@@ -1,4 +1,6 @@
1
1
  # frozen_string_literal: true
2
+ require 'rubygems'
3
+ require 'bundler/setup'
2
4
  require 'simplecov'
3
5
  formatters = [ SimpleCov::Formatter::HTMLFormatter ]
4
6
 
@@ -31,6 +31,60 @@ module Cucumber::Core
31
31
  end
32
32
  end
33
33
 
34
+ context "when the event_bus is provided" do
35
+ let(:event_bus) { double }
36
+
37
+ before do
38
+ allow( event_bus ).to receive(:envelope)
39
+ allow( event_bus ).to receive(:gherkin_source_parsed).and_return(nil)
40
+ allow( event_bus ).to receive(:test_case_created).and_return(nil)
41
+ allow( event_bus ).to receive(:test_step_created).and_return(nil)
42
+ end
43
+
44
+ it "emits a TestCaseCreated event with the created Test::Case and Pickle" do
45
+ gherkin_documents = [
46
+ gherkin do
47
+ feature do
48
+ scenario do
49
+ step 'passing'
50
+ end
51
+ end
52
+ end
53
+ ]
54
+
55
+ compile(gherkin_documents, event_bus) do | visitor |
56
+ allow( visitor ).to receive(:test_case)
57
+ allow( visitor ).to receive(:test_step)
58
+ allow( visitor ).to receive(:done)
59
+ allow( event_bus ).to receive(:envelope)
60
+
61
+ expect( event_bus ).to receive(:test_case_created).once
62
+ end
63
+ end
64
+
65
+ it "emits a TestStepCreated event with the created Test::Step and PickleStep" do
66
+ gherkin_documents = [
67
+ gherkin do
68
+ feature do
69
+ scenario do
70
+ step 'passing'
71
+ step 'passing'
72
+ end
73
+ end
74
+ end
75
+ ]
76
+
77
+ compile(gherkin_documents, event_bus) do |visitor|
78
+ allow( visitor ).to receive(:test_case)
79
+ allow( visitor ).to receive(:test_step)
80
+ allow( visitor ).to receive(:done)
81
+ allow( event_bus ).to receive(:envelope)
82
+
83
+ expect( event_bus ).to receive(:test_step_created).twice
84
+ end
85
+ end
86
+ end
87
+
34
88
  it "compiles a feature with a background" do
35
89
  gherkin_documents = [
36
90
  gherkin do
@@ -166,13 +220,22 @@ module Cucumber::Core
166
220
  end
167
221
  end
168
222
 
169
- def compile(gherkin_documents)
223
+ def compile(gherkin_documents, event_bus = nil)
170
224
  visitor = double
171
225
  allow( visitor ).to receive(:test_suite).and_yield(visitor)
172
226
  allow( visitor ).to receive(:test_case).and_yield(visitor)
227
+
228
+ if event_bus.nil?
229
+ event_bus = double
230
+ allow( event_bus ).to receive(:envelope).and_return(nil)
231
+ allow( event_bus ).to receive(:gherkin_source_parsed).and_return(nil)
232
+ allow( event_bus ).to receive(:test_case_created).and_return(nil)
233
+ allow( event_bus ).to receive(:test_step_created).and_return(nil)
234
+ allow( event_bus ).to receive(:envelope).and_return(nil)
235
+ end
236
+
173
237
  yield visitor
174
- super(gherkin_documents, visitor)
238
+ super(gherkin_documents, visitor, [], event_bus)
175
239
  end
176
-
177
240
  end
178
241
  end
@@ -9,11 +9,14 @@ module Cucumber
9
9
  describe Parser do
10
10
  let(:receiver) { double }
11
11
  let(:event_bus) { double }
12
- let(:parser) { Parser.new(receiver, event_bus) }
12
+ let(:gherkin_query) { double }
13
+ let(:parser) { Parser.new(receiver, event_bus, gherkin_query) }
13
14
  let(:visitor) { double }
14
15
 
15
16
  before do
16
17
  allow( event_bus ).to receive(:gherkin_source_parsed)
18
+ allow( event_bus).to receive(:envelope)
19
+ allow( gherkin_query ).to receive(:update)
17
20
  end
18
21
 
19
22
  def parse
@@ -40,6 +43,12 @@ module Cucumber
40
43
  expect( event_bus ).to receive(:gherkin_source_parsed)
41
44
  parse
42
45
  end
46
+
47
+ it "emits an 'envelope' event for every message produced by Gherkin" do
48
+ # Only one message emited, there's no pickles generated
49
+ expect( event_bus ).to receive(:envelope).once
50
+ parse
51
+ end
43
52
  end
44
53
 
45
54
  context "for empty files" do
@@ -87,8 +96,66 @@ module Cucumber
87
96
  expect( receiver ).to receive(:pickle)
88
97
  parse
89
98
  end
99
+
100
+ it "emits an 'envelope' event containing the pickle" do
101
+ allow( receiver ).to receive(:pickle)
102
+ # Once for the gherkin document, once with the pickle
103
+ expect( event_bus ).to receive(:envelope).twice
104
+ parse
105
+ end
106
+ end
107
+
108
+ context "when scenario is inside a rule" do
109
+ source do
110
+ feature do
111
+ rule do
112
+ scenario name: "My scenario"
113
+ end
114
+ end
115
+ end
116
+
117
+ it "passes on the pickle" do
118
+ expect( receiver ).to receive(:pickle)
119
+ parse
120
+ end
121
+ end
122
+
123
+ context "when example is inside a rule" do
124
+ source do
125
+ feature do
126
+ rule do
127
+ example name: "My example"
128
+ end
129
+ end
130
+ end
131
+
132
+ it "passes on the pickle" do
133
+ expect( receiver ).to receive(:pickle)
134
+ parse
135
+ end
90
136
  end
91
137
 
138
+ context "when there are multiple rules and scenarios or examples" do
139
+ source do
140
+ feature do
141
+ rule description: "First rule" do
142
+ scenario name: "Do not talk about the fight club" do
143
+ step 'text'
144
+ end
145
+ end
146
+ rule description: "Second rule"do
147
+ example name: "Do not talk about the fight club" do
148
+ step 'text'
149
+ end
150
+ end
151
+ end
152
+ end
153
+
154
+ it "passes on the pickles" do
155
+ expect( receiver ).to receive(:pickle).twice
156
+ parse
157
+ end
158
+ end
92
159
  end
93
160
  end
94
161
  end