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.
@@ -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.2"
6
+ "6.0.0"
7
7
  end
8
8
  end
9
9
  end
@@ -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,6 +96,13 @@ 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
90
106
  end
91
107
 
92
108
  context "when scenario is inside a rule" do
@@ -13,11 +13,12 @@ module Cucumber
13
13
  include Core
14
14
  include Core::Gherkin::Writer
15
15
 
16
+ let(:id) { double }
16
17
  let(:name) { double }
17
18
  let(:location) { double }
18
19
  let(:tags) { double }
19
20
  let(:language) { double }
20
- let(:test_case) { Test::Case.new(name, test_steps, location, tags, language) }
21
+ let(:test_case) { Test::Case.new(id, name, test_steps, location, tags, language) }
21
22
  let(:test_steps) { [double, double] }
22
23
 
23
24
  context 'describing itself' do
@@ -45,7 +46,7 @@ module Cucumber
45
46
  expect( first_hook ).to receive(:describe_to).ordered.and_yield
46
47
  expect( second_hook ).to receive(:describe_to).ordered.and_yield
47
48
  around_hooks = [first_hook, second_hook]
48
- Test::Case.new(name, [], location, tags, language, around_hooks).describe_to(visitor, double)
49
+ Test::Case.new(id, name, [], location, tags, language, around_hooks).describe_to(visitor, double)
49
50
  end
50
51
 
51
52
  end
@@ -6,31 +6,29 @@ module Cucumber
6
6
  module Core
7
7
  module Test
8
8
  describe DataTable do
9
- let(:location) { Test::Location.new('foo.feature', 9..12) }
10
-
11
9
  before do
12
10
  @table = DataTable.new([
13
11
  %w{one four seven},
14
12
  %w{4444 55555 666666}
15
- ], location)
13
+ ])
16
14
  end
17
15
 
18
16
  describe "equality" do
19
17
  it "is equal to another table with the same data" do
20
- expect( DataTable.new([[1,2],[3,4]], location) ).to eq DataTable.new([[1,2],[3,4]], location)
18
+ expect( DataTable.new([[1,2],[3,4]]) ).to eq DataTable.new([[1,2],[3,4]])
21
19
  end
22
20
 
23
21
  it "is not equal to another table with different data" do
24
- expect( DataTable.new([[1,2],[3,4]], location) ).not_to eq DataTable.new([[1,2]], location)
22
+ expect( DataTable.new([[1,2],[3,4]]) ).not_to eq DataTable.new([[1,2]])
25
23
  end
26
24
 
27
25
  it "is not equal to a non table" do
28
- expect( DataTable.new([[1,2],[3,4]], location) ).not_to eq Object.new
26
+ expect( DataTable.new([[1,2],[3,4]]) ).not_to eq Object.new
29
27
  end
30
28
  end
31
29
 
32
30
  describe "#data_table?" do
33
- let(:table) { DataTable.new([[1,2],[3,4]], location) }
31
+ let(:table) { DataTable.new([[1,2],[3,4]]) }
34
32
 
35
33
  it "returns true" do
36
34
  expect(table).to be_data_table
@@ -38,7 +36,7 @@ module Cucumber
38
36
  end
39
37
 
40
38
  describe "#doc_string" do
41
- let(:table) { DataTable.new([[1,2],[3,4]], location) }
39
+ let(:table) { DataTable.new([[1,2],[3,4]]) }
42
40
 
43
41
  it "returns false" do
44
42
  expect(table).not_to be_doc_string
@@ -46,7 +44,7 @@ module Cucumber
46
44
  end
47
45
 
48
46
  describe "#map" do
49
- let(:table) { DataTable.new([ %w{foo bar}, %w{1 2} ], location) }
47
+ let(:table) { DataTable.new([ %w{foo bar}, %w{1 2} ]) }
50
48
 
51
49
  it 'yields the contents of each cell to the block' do
52
50
 
@@ -54,7 +52,7 @@ module Cucumber
54
52
  end
55
53
 
56
54
  it 'returns a new table with the cells modified by the block' do
57
- expect( table.map { |cell| "*#{cell}*" } ).to eq DataTable.new([%w{*foo* *bar*}, %w{*1* *2*}], location)
55
+ expect( table.map { |cell| "*#{cell}*" } ).to eq DataTable.new([%w{*foo* *bar*}, %w{*1* *2*}])
58
56
  end
59
57
  end
60
58
 
@@ -63,14 +61,14 @@ module Cucumber
63
61
  @table = DataTable.new([
64
62
  %w{one 1111},
65
63
  %w{two 22222}
66
- ], location)
64
+ ])
67
65
  end
68
66
 
69
67
  it "should transpose the table" do
70
68
  transposed = DataTable.new([
71
69
  %w{one two},
72
70
  %w{1111 22222}
73
- ], location)
71
+ ])
74
72
  expect( @table.transpose ).to eq( transposed )
75
73
  end
76
74
  end
@@ -1,5 +1,4 @@
1
1
  # frozen_string_literal: true
2
- require 'cucumber/core/test/location'
3
2
  require 'cucumber/core/test/doc_string'
4
3
  require 'unindent'
5
4
 
@@ -7,11 +6,10 @@ module Cucumber
7
6
  module Core
8
7
  module Test
9
8
  describe DocString do
10
- let(:location) { double }
11
- let(:doc_string) { DocString.new(content, content_type, location) }
9
+ let(:doc_string) { DocString.new(content, content_type) }
12
10
 
13
11
  describe "#data_table?" do
14
- let(:doc_string) { DocString.new("test", "text/plain" , location) }
12
+ let(:doc_string) { DocString.new("test", "text/plain" ) }
15
13
 
16
14
  it "returns false" do
17
15
  expect(doc_string).not_to be_data_table
@@ -19,7 +17,7 @@ module Cucumber
19
17
  end
20
18
 
21
19
  describe "#doc_string" do
22
- let(:doc_string) { DocString.new("test", "text/plain" , location) }
20
+ let(:doc_string) { DocString.new("test", "text/plain" ) }
23
21
 
24
22
  it "returns true" do
25
23
  expect(doc_string).to be_doc_string
@@ -48,15 +46,15 @@ module Cucumber
48
46
  let(:content_type) { 'text/plain' }
49
47
 
50
48
  it 'is equal to another DocString with the same content and content_type' do
51
- expect( doc_string ).to eq DocString.new(content, content_type, location)
49
+ expect( doc_string ).to eq DocString.new(content, content_type)
52
50
  end
53
51
 
54
52
  it 'is not equal to another DocString with different content' do
55
- expect( doc_string ).not_to eq DocString.new('bar', content_type, location)
53
+ expect( doc_string ).not_to eq DocString.new('bar', content_type)
56
54
  end
57
55
 
58
56
  it 'is not equal to another DocString with different content_type' do
59
- expect( doc_string ).not_to eq DocString.new(content, 'text/html', location)
57
+ expect( doc_string ).not_to eq DocString.new(content, 'text/html')
60
58
  end
61
59
 
62
60
  it 'is equal to a string with the same content' do
@@ -96,13 +94,12 @@ module Cucumber
96
94
  end
97
95
 
98
96
  context "inspect" do
99
- let(:location) { Test::Location.new("features/feature.feature", 8) }
100
97
  let(:content_type) { 'text/plain' }
101
98
 
102
99
  it "provides a useful inspect method" do
103
- doc_string = DocString.new("some text", content_type, location)
100
+ doc_string = DocString.new("some text", content_type)
104
101
  expect(doc_string.inspect).to eq <<-END.chomp.unindent
105
- #<Cucumber::Core::Test::DocString (features/feature.feature:8)
102
+ #<Cucumber::Core::Test::DocString
106
103
  """text/plain
107
104
  some text
108
105
  """>
@@ -23,6 +23,11 @@ module Cucumber::Core::Test
23
23
  expect( result.to_s ).to eq "✓"
24
24
  end
25
25
 
26
+ it "converts to a Cucumber::Message::TestResult" do
27
+ message = result.to_message
28
+ expect(message.status).to eq(Cucumber::Messages::TestStepResult::Status::PASSED)
29
+ end
30
+
26
31
  it "has a duration" do
27
32
  expect( result.duration ).to eq duration
28
33
  end
@@ -68,6 +73,11 @@ module Cucumber::Core::Test
68
73
  expect( result.duration ).to eq duration
69
74
  end
70
75
 
76
+ it "converts to a Cucumber::Message::TestResult" do
77
+ message = result.to_message
78
+ expect(message.status).to eq(Cucumber::Messages::TestStepResult::Status::FAILED)
79
+ end
80
+
71
81
  it "requires both constructor arguments" do
72
82
  expect { Result::Failed.new }.to raise_error(ArgumentError)
73
83
  expect { Result::Failed.new(duration) }.to raise_error(ArgumentError)
@@ -131,6 +141,11 @@ module Cucumber::Core::Test
131
141
  specify { expect( result ).to be_unknown }
132
142
  specify { expect( result ).not_to be_skipped }
133
143
  specify { expect( result ).not_to be_flaky }
144
+
145
+ it "converts to a Cucumber::Message::TestResult" do
146
+ message = result.to_message
147
+ expect(message.status).to eq(Cucumber::Messages::TestStepResult::Status::UNKNOWN)
148
+ end
134
149
  end
135
150
 
136
151
  describe Result::Raisable do
@@ -190,6 +205,11 @@ module Cucumber::Core::Test
190
205
  result.describe_to(visitor, args)
191
206
  end
192
207
 
208
+ it "converts to a Cucumber::Message::TestResult" do
209
+ message = result.to_message
210
+ expect(message.status).to eq(Cucumber::Messages::TestStepResult::Status::UNDEFINED)
211
+ end
212
+
193
213
  specify { expect( result.to_sym ).to eq :undefined }
194
214
 
195
215
  specify { expect( result ).not_to be_passed }
@@ -214,6 +234,11 @@ module Cucumber::Core::Test
214
234
  result.describe_to(visitor, args)
215
235
  end
216
236
 
237
+ it "converts to a Cucumber::Message::TestResult" do
238
+ message = result.to_message
239
+ expect(message.status).to eq(Cucumber::Messages::TestStepResult::Status::SKIPPED)
240
+ end
241
+
217
242
  specify { expect( result.to_sym ).to eq :skipped }
218
243
 
219
244
  specify { expect( result ).not_to be_passed }
@@ -236,6 +261,11 @@ module Cucumber::Core::Test
236
261
  result.describe_to(visitor, args)
237
262
  end
238
263
 
264
+ it "converts to a Cucumber::Message::TestResult" do
265
+ message = result.to_message
266
+ expect(message.status).to eq(Cucumber::Messages::TestStepResult::Status::PENDING)
267
+ end
268
+
239
269
  specify { expect( result.to_sym ).to eq :pending }
240
270
 
241
271
  specify { expect( result ).not_to be_passed }
@@ -259,7 +289,7 @@ module Cucumber::Core::Test
259
289
 
260
290
  describe Result::StrictConfiguration do
261
291
  subject(:strict_configuration) { Result::StrictConfiguration.new}
262
-
292
+
263
293
  describe '#set_strict' do
264
294
  context 'no type argument' do
265
295
  it 'sets all result types to the setting argument' do
@@ -7,19 +7,21 @@ require 'cucumber/core/test/duration_matcher'
7
7
  module Cucumber::Core::Test
8
8
  describe Runner do
9
9
 
10
+ let(:step_id) { double }
11
+ let(:test_id) { double }
10
12
  let(:name) { double }
11
13
  let(:location) { double }
12
14
  let(:tags) { double }
13
15
  let(:language) { double }
14
- let(:test_case) { Case.new(name, test_steps, location, tags, language) }
16
+ let(:test_case) { Case.new(test_id, name, test_steps, location, tags, language) }
15
17
  let(:text) { double }
16
18
  let(:runner) { Runner.new(event_bus) }
17
19
  let(:event_bus) { double.as_null_object }
18
- let(:passing) { Step.new(text, location, location).with_action {} }
19
- let(:failing) { Step.new(text, location, location).with_action { raise exception } }
20
- let(:pending) { Step.new(text, location, location).with_action { raise Result::Pending.new("TODO") } }
21
- let(:skipping) { Step.new(text, location, location).with_action { raise Result::Skipped.new } }
22
- let(:undefined) { Step.new(text, location, location) }
20
+ let(:passing) { Step.new(step_id, text, location, location).with_action {} }
21
+ let(:failing) { Step.new(step_id, text, location, location).with_action { raise exception } }
22
+ let(:pending) { Step.new(step_id, text, location, location).with_action { raise Result::Pending.new("TODO") } }
23
+ let(:skipping) { Step.new(step_id, text, location, location).with_action { raise Result::Skipped.new } }
24
+ let(:undefined) { Step.new(step_id, text, location, location) }
23
25
  let(:exception) { StandardError.new('test error') }
24
26
 
25
27
  before do
@@ -223,8 +225,8 @@ module Cucumber::Core::Test
223
225
 
224
226
  context 'with multiple test cases' do
225
227
  context 'when the first test case fails' do
226
- let(:first_test_case) { Case.new(name, [failing], location, tags, language) }
227
- let(:last_test_case) { Case.new(name, [passing], location, tags, language) }
228
+ let(:first_test_case) { Case.new(test_id, name, [failing], location, tags, language) }
229
+ let(:last_test_case) { Case.new(test_id, name, [passing], location, tags, language) }
228
230
  let(:test_cases) { [first_test_case, last_test_case] }
229
231
 
230
232
  it 'reports the results correctly for the following test case' do
@@ -244,9 +246,9 @@ module Cucumber::Core::Test
244
246
  hook_mapping = UnskippableAction.new do |last_result|
245
247
  result_spy = last_result
246
248
  end
247
- after_hook = HookStep.new(text, location, hook_mapping)
248
- failing_step = Step.new(text, location).with_action { fail }
249
- test_case = Case.new(name, [failing_step, after_hook], location, tags, language)
249
+ after_hook = HookStep.new(step_id, text, location, hook_mapping)
250
+ failing_step = Step.new(step_id, text, location).with_action { fail }
251
+ test_case = Case.new(test_id, name, [failing_step, after_hook], location, tags, language)
250
252
  test_case.describe_to runner
251
253
  expect(result_spy).to be_failed
252
254
  end
@@ -256,8 +258,8 @@ module Cucumber::Core::Test
256
258
  context "with around hooks" do
257
259
  it "passes normally when around hooks don't fail" do
258
260
  around_hook = AroundHook.new { |block| block.call }
259
- passing_step = Step.new(text, location, location).with_action {}
260
- test_case = Case.new(name, [passing_step], location, tags, language, [around_hook])
261
+ passing_step = Step.new(step_id, text, location, location).with_action {}
262
+ test_case = Case.new(test_id, name, [passing_step], location, tags, language, [around_hook])
261
263
  expect(event_bus).to receive(:test_case_finished).with(test_case, anything) do |reported_test_case, result|
262
264
  expect(result).to be_passed
263
265
  end
@@ -266,8 +268,8 @@ module Cucumber::Core::Test
266
268
 
267
269
  it "gets a failed result if the Around hook fails before the test case is run" do
268
270
  around_hook = AroundHook.new { |block| raise exception }
269
- passing_step = Step.new(text, location, location).with_action {}
270
- test_case = Case.new(name, [passing_step], location, tags, language, [around_hook])
271
+ passing_step = Step.new(step_id, text, location, location).with_action {}
272
+ test_case = Case.new(test_id, name, [passing_step], location, tags, language, [around_hook])
271
273
  expect(event_bus).to receive(:test_case_finished).with(test_case, anything) do |reported_test_case, result|
272
274
  expect(result).to be_failed
273
275
  expect(result.exception).to eq exception
@@ -277,8 +279,8 @@ module Cucumber::Core::Test
277
279
 
278
280
  it "gets a failed result if the Around hook fails after the test case is run" do
279
281
  around_hook = AroundHook.new { |block| block.call; raise exception }
280
- passing_step = Step.new(text, location, location).with_action {}
281
- test_case = Case.new(name, [passing_step], location, tags, language, [around_hook])
282
+ passing_step = Step.new(step_id, text, location, location).with_action {}
283
+ test_case = Case.new(test_id, name, [passing_step], location, tags, language, [around_hook])
282
284
  expect(event_bus).to receive(:test_case_finished).with(test_case, anything) do |reported_test_case, result|
283
285
  expect(result).to be_failed
284
286
  expect(result.exception).to eq exception
@@ -288,8 +290,8 @@ module Cucumber::Core::Test
288
290
 
289
291
  it "fails when a step fails if the around hook works" do
290
292
  around_hook = AroundHook.new { |block| block.call }
291
- failing_step = Step.new(text, location, location).with_action { raise exception }
292
- test_case = Case.new(name, [failing_step], location, tags, language, [around_hook])
293
+ failing_step = Step.new(step_id, text, location, location).with_action { raise exception }
294
+ test_case = Case.new(test_id, name, [failing_step], location, tags, language, [around_hook])
293
295
  expect(event_bus).to receive(:test_case_finished).with(test_case, anything) do |reported_test_case, result|
294
296
  expect(result).to be_failed
295
297
  expect(result.exception).to eq exception
@@ -299,8 +301,8 @@ module Cucumber::Core::Test
299
301
 
300
302
  it "sends after_test_step for a step interrupted by (a timeout in) the around hook" do
301
303
  around_hook = AroundHook.new { |block| block.call; raise exception }
302
- passing_step = Step.new(text, location, location).with_action {}
303
- test_case = Case.new(name, [], location, tags, language, [around_hook])
304
+ passing_step = Step.new(step_id, text, location, location).with_action {}
305
+ test_case = Case.new(test_id, name, [], location, tags, language, [around_hook])
304
306
  allow(runner).to receive(:running_test_step).and_return(passing_step)
305
307
  expect(event_bus).to receive(:test_step_finished).with(passing_step, anything) do |reported_test_case, result|
306
308
  expect(result).to be_failed