cucumber-core 5.0.1 → 8.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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