cucumber-core 10.1.1 → 11.1.0

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.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +203 -284
  3. data/README.md +0 -1
  4. data/lib/cucumber/core/test/case.rb +11 -1
  5. data/lib/cucumber/core/test/data_table.rb +4 -0
  6. data/lib/cucumber/core/test/doc_string.rb +4 -1
  7. data/lib/cucumber/core/test/empty_multiline_argument.rb +2 -2
  8. data/lib/cucumber/core/test/filters/locations_filter.rb +1 -1
  9. data/lib/cucumber/core/test/location.rb +15 -5
  10. data/lib/cucumber/core/test/step.rb +4 -0
  11. metadata +29 -94
  12. data/lib/cucumber/core/version.rb +0 -10
  13. data/spec/coverage.rb +0 -12
  14. data/spec/cucumber/core/compiler_spec.rb +0 -241
  15. data/spec/cucumber/core/event_bus_spec.rb +0 -163
  16. data/spec/cucumber/core/event_spec.rb +0 -40
  17. data/spec/cucumber/core/filter_spec.rb +0 -101
  18. data/spec/cucumber/core/gherkin/parser_spec.rb +0 -162
  19. data/spec/cucumber/core/gherkin/writer_spec.rb +0 -332
  20. data/spec/cucumber/core/report/summary_spec.rb +0 -178
  21. data/spec/cucumber/core/test/action_spec.rb +0 -153
  22. data/spec/cucumber/core/test/case_spec.rb +0 -125
  23. data/spec/cucumber/core/test/data_table_spec.rb +0 -79
  24. data/spec/cucumber/core/test/doc_string_spec.rb +0 -111
  25. data/spec/cucumber/core/test/duration_matcher.rb +0 -20
  26. data/spec/cucumber/core/test/empty_multiline_argument_spec.rb +0 -28
  27. data/spec/cucumber/core/test/filters/locations_filter_spec.rb +0 -271
  28. data/spec/cucumber/core/test/location_spec.rb +0 -129
  29. data/spec/cucumber/core/test/result_spec.rb +0 -504
  30. data/spec/cucumber/core/test/runner_spec.rb +0 -320
  31. data/spec/cucumber/core/test/step_spec.rb +0 -88
  32. data/spec/cucumber/core/test/timer_spec.rb +0 -25
  33. data/spec/cucumber/core_spec.rb +0 -262
  34. data/spec/report_api_spy.rb +0 -25
@@ -1,125 +0,0 @@
1
- # frozen_string_literal: true
2
- require 'cucumber/core'
3
- require 'cucumber/core/gherkin/writer'
4
- require 'cucumber/core/platform'
5
- require 'cucumber/core/test/case'
6
- require 'unindent'
7
-
8
- module Cucumber
9
- module Core
10
- module Test
11
- describe Case do
12
- include Core
13
- include Core::Gherkin::Writer
14
-
15
- let(:id) { double }
16
- let(:name) { double }
17
- let(:location) { double }
18
- let(:tags) { double }
19
- let(:language) { double }
20
- let(:test_case) { Test::Case.new(id, name, test_steps, location, tags, language) }
21
- let(:test_steps) { [double, double] }
22
-
23
- context 'describing itself' do
24
- it "describes itself to a visitor" do
25
- visitor = double
26
- args = double
27
- expect(visitor).to receive(:test_case).with(test_case, args)
28
- test_case.describe_to(visitor, args)
29
- end
30
-
31
- it "asks each test_step to describe themselves to the visitor" do
32
- visitor = double
33
- args = double
34
- test_steps.each do |test_step|
35
- expect(test_step).to receive(:describe_to).with(visitor, args)
36
- end
37
- allow(visitor).to receive(:test_case).and_yield(visitor)
38
- test_case.describe_to(visitor, args)
39
- end
40
-
41
- it "describes around hooks in order" do
42
- visitor = double
43
- allow(visitor).to receive(:test_case).and_yield(visitor)
44
- first_hook = double
45
- second_hook = double
46
- expect(first_hook).to receive(:describe_to).ordered.and_yield
47
- expect(second_hook).to receive(:describe_to).ordered.and_yield
48
- around_hooks = [first_hook, second_hook]
49
- Test::Case.new(id, name, [], location, tags, language, around_hooks).describe_to(visitor, double)
50
- end
51
- end
52
-
53
- describe "#name" do
54
- it "the name is passed when creating the test case" do
55
- expect(test_case.name).to eq(name)
56
- end
57
- end
58
-
59
- describe "#location" do
60
- it "the location is passed when creating the test case" do
61
- expect(test_case.location).to eq(location)
62
- end
63
- end
64
-
65
- describe "#tags" do
66
- it "the tags are passed when creating the test case" do
67
- expect(test_case.tags).to eq(tags)
68
- end
69
- end
70
-
71
- describe "matching tags" do
72
- let(:tags) { ['@a', '@b', '@c'].map { |value| Tag.new(location, value) } }
73
- it "matches tags using tag expressions" do
74
- expect(test_case.match_tags?(['@a and @b'])).to be_truthy
75
- expect(test_case.match_tags?(['@a or @d'])).to be_truthy
76
- expect(test_case.match_tags?(['not @d'])).to be_truthy
77
- expect(test_case.match_tags?(['@a and @d'])).to be_falsy
78
- end
79
-
80
- it "matches handles multiple expressions" do
81
- expect(test_case.match_tags?(['@a and @b', 'not @d'])).to be_truthy
82
- expect(test_case.match_tags?(['@a and @b', 'not @c'])).to be_falsy
83
- end
84
- end
85
-
86
- describe "matching names" do
87
- let(:name) { 'scenario' }
88
- it "matches names against regexp" do
89
- expect(test_case.match_name?(/scenario/)).to be_truthy
90
- end
91
- end
92
-
93
- describe "#language" do
94
- let(:language) { 'en-pirate' }
95
- it "the language is passed when creating the test case" do
96
- expect(test_case.language).to eq 'en-pirate'
97
- end
98
- end
99
-
100
- describe "equality" do
101
- it "is equal to another test case at the same location" do
102
- gherkin = gherkin('features/foo.feature') do
103
- feature do
104
- scenario do
105
- step 'text'
106
- end
107
- end
108
- end
109
- test_case_instances = []
110
- receiver = double.as_null_object
111
- allow(receiver).to receive(:test_case) do |test_case|
112
- test_case_instances << test_case
113
- end
114
- 2.times { compile([gherkin], receiver) }
115
- expect(test_case_instances.length).to eq 2
116
- expect(test_case_instances.uniq.length).to eq 1
117
- expect(test_case_instances[0]).to be_eql test_case_instances[1]
118
- expect(test_case_instances[0]).to eq test_case_instances[1]
119
- expect(test_case_instances[0]).not_to equal test_case_instances[1]
120
- end
121
- end
122
- end
123
- end
124
- end
125
- end
@@ -1,79 +0,0 @@
1
- # encoding: utf-8
2
- # frozen_string_literal: true
3
- require 'cucumber/core/test/data_table'
4
-
5
- module Cucumber
6
- module Core
7
- module Test
8
- describe DataTable do
9
- before do
10
- @table = DataTable.new([
11
- %w{one four seven},
12
- %w{4444 55555 666666}
13
- ])
14
- end
15
-
16
- describe "equality" do
17
- it "is equal to another table with the same data" do
18
- expect( DataTable.new([[1, 2], [3, 4]]) ).to eq DataTable.new([[1, 2], [3, 4]])
19
- end
20
-
21
- it "is not equal to another table with different data" do
22
- expect( DataTable.new([[1, 2], [3, 4]]) ).not_to eq DataTable.new([[1, 2]])
23
- end
24
-
25
- it "is not equal to a non table" do
26
- expect( DataTable.new([[1, 2], [3, 4]]) ).not_to eq Object.new
27
- end
28
- end
29
-
30
- describe "#data_table?" do
31
- let(:table) { DataTable.new([[1, 2], [3, 4]]) }
32
-
33
- it "returns true" do
34
- expect(table).to be_data_table
35
- end
36
- end
37
-
38
- describe "#doc_string" do
39
- let(:table) { DataTable.new([[1, 2], [3, 4]]) }
40
-
41
- it "returns false" do
42
- expect(table).not_to be_doc_string
43
- end
44
- end
45
-
46
- describe "#map" do
47
- let(:table) { DataTable.new([ %w{foo bar}, %w{1 2} ]) }
48
-
49
- it 'yields the contents of each cell to the block' do
50
-
51
- expect { |b| table.map(&b) }.to yield_successive_args('foo', 'bar', '1', '2')
52
- end
53
-
54
- it 'returns a new table with the cells modified by the block' do
55
- expect( table.map { |cell| "*#{cell}*" } ).to eq DataTable.new([%w{*foo* *bar*}, %w{*1* *2*}])
56
- end
57
- end
58
-
59
- describe "#transpose" do
60
- before(:each) do
61
- @table = DataTable.new([
62
- %w{one 1111},
63
- %w{two 22222}
64
- ])
65
- end
66
-
67
- it "should transpose the table" do
68
- transposed = DataTable.new([
69
- %w{one two},
70
- %w{1111 22222}
71
- ])
72
- expect( @table.transpose ).to eq( transposed )
73
- end
74
- end
75
-
76
- end
77
- end
78
- end
79
- end
@@ -1,111 +0,0 @@
1
- # frozen_string_literal: true
2
- require 'cucumber/core/test/doc_string'
3
- require 'unindent'
4
-
5
- module Cucumber
6
- module Core
7
- module Test
8
- describe DocString do
9
- let(:doc_string) { DocString.new(content, content_type) }
10
-
11
- describe "#data_table?" do
12
- let(:doc_string) { DocString.new("test", "text/plain" ) }
13
-
14
- it "returns false" do
15
- expect(doc_string).not_to be_data_table
16
- end
17
- end
18
-
19
- describe "#doc_string" do
20
- let(:doc_string) { DocString.new("test", "text/plain" ) }
21
-
22
- it "returns true" do
23
- expect(doc_string).to be_doc_string
24
- end
25
- end
26
-
27
- context '#map' do
28
- let(:content) { 'original content' }
29
- let(:content_type) { double }
30
-
31
- it 'yields with the content' do
32
- expect { |b| doc_string.map(&b) }.to yield_with_args(content)
33
- end
34
-
35
- it 'returns a new docstring with new content' do
36
- expect( doc_string.map { 'foo' }.content ).to eq 'foo'
37
- end
38
-
39
- it 'raises an error if no block is given' do
40
- expect { doc_string.map }.to raise_error ArgumentError
41
- end
42
- end
43
-
44
- context 'equality' do
45
- let(:content) { 'foo' }
46
- let(:content_type) { 'text/plain' }
47
-
48
- it 'is equal to another DocString with the same content and content_type' do
49
- expect( doc_string ).to eq DocString.new(content, content_type)
50
- end
51
-
52
- it 'is not equal to another DocString with different content' do
53
- expect( doc_string ).not_to eq DocString.new('bar', content_type)
54
- end
55
-
56
- it 'is not equal to another DocString with different content_type' do
57
- expect( doc_string ).not_to eq DocString.new(content, 'text/html')
58
- end
59
-
60
- it 'is equal to a string with the same content' do
61
- expect( doc_string ).to eq 'foo'
62
- end
63
-
64
- it 'returns false when compared with something odd' do
65
- expect( doc_string ).not_to eq 5
66
- end
67
- end
68
-
69
- context 'quacking like a String' do
70
- let(:content) { String.new('content') }
71
- let(:content_type) { 'text/plain' }
72
-
73
- it 'delegates #encoding to the content string' do
74
- content.force_encoding('us-ascii')
75
- expect( doc_string.encoding ).to eq Encoding.find('US-ASCII')
76
- end
77
-
78
- it 'allows implicit conversion to a String' do
79
- expect( 'expected content' ).to include(doc_string)
80
- end
81
-
82
- it 'allows explicit conversion to a String' do
83
- expect( doc_string.to_s ).to eq 'content'
84
- end
85
-
86
- it 'delegates #gsub to the content string' do
87
- expect( doc_string.gsub(/n/, '_') ).to eq 'co_te_t'
88
- end
89
-
90
- it 'delegates #split to the content string' do
91
- expect(doc_string.split('n')).to eq ['co', 'te', 't']
92
- end
93
- end
94
- end
95
-
96
- context "inspect" do
97
- let(:content_type) { 'text/plain' }
98
-
99
- it "provides a useful inspect method" do
100
- doc_string = DocString.new("some text", content_type)
101
- expect(doc_string.inspect).to eq <<-END.chomp.unindent
102
- #<Cucumber::Core::Test::DocString
103
- """text/plain
104
- some text
105
- """>
106
- END
107
- end
108
- end
109
- end
110
- end
111
- end
@@ -1,20 +0,0 @@
1
- # -*- encoding: utf-8 -*-
2
- # frozen_string_literal: true
3
- require 'cucumber/core/test/result'
4
- require 'rspec/expectations'
5
-
6
- module Cucumber::Core::Test
7
- RSpec::Matchers.define :be_duration do |expected|
8
- match do |actual|
9
- actual.tap { |duration| @nanoseconds = duration.nanoseconds }
10
- @nanoseconds == expected
11
- end
12
- end
13
-
14
- RSpec::Matchers.define :an_unknown_duration do
15
- match do |actual|
16
- actual.tap { raise "#tap block was executed, not an UnknownDuration" }
17
- expect(actual).to respond_to(:nanoseconds)
18
- end
19
- end
20
- end
@@ -1,28 +0,0 @@
1
- # frozen_string_literal: true
2
- require 'cucumber/core/test/location'
3
- require 'cucumber/core/test/empty_multiline_argument'
4
-
5
- module Cucumber
6
- module Core
7
- module Test
8
- describe EmptyMultilineArgument do
9
-
10
- let(:location) { double }
11
- let(:arg) { EmptyMultilineArgument.new }
12
-
13
- describe "#data_table?" do
14
- it "returns false" do
15
- expect(arg).not_to be_data_table
16
- end
17
- end
18
-
19
- describe "#doc_string" do
20
- it "returns false" do
21
- expect(arg).not_to be_doc_string
22
- end
23
- end
24
-
25
- end
26
- end
27
- end
28
- end
@@ -1,271 +0,0 @@
1
- # encoding: utf-8
2
- # frozen_string_literal: true
3
- require 'cucumber/core/gherkin/writer'
4
- require 'cucumber/core'
5
- require 'cucumber/core/test/filters/locations_filter'
6
- require 'timeout'
7
- require 'cucumber/core/test/location'
8
-
9
- module Cucumber::Core
10
- describe Test::LocationsFilter do
11
- include Cucumber::Core::Gherkin::Writer
12
- include Cucumber::Core
13
-
14
- let(:receiver) { SpyReceiver.new }
15
-
16
- let(:doc) do
17
- gherkin('features/test.feature') do
18
- feature do
19
- scenario 'x' do
20
- step 'a step'
21
- end
22
-
23
- scenario 'y' do
24
- step 'a step'
25
- end
26
- end
27
- end
28
- end
29
-
30
- it "sorts by the given locations" do
31
- locations = [
32
- Test::Location.new('features/test.feature', 6),
33
- Test::Location.new('features/test.feature', 3)
34
- ]
35
- filter = Test::LocationsFilter.new(locations)
36
- compile [doc], receiver, [filter]
37
- expect(receiver.test_case_locations).to eq locations
38
- end
39
-
40
- it "works with wildcard locations" do
41
- locations = [
42
- Test::Location.new('features/test.feature')
43
- ]
44
- filter = Test::LocationsFilter.new(locations)
45
- compile [doc], receiver, [filter]
46
- expect(receiver.test_case_locations).to eq [
47
- Test::Location.new('features/test.feature', 3),
48
- Test::Location.new('features/test.feature', 6)
49
- ]
50
- end
51
-
52
- it "filters out scenarios that don't match" do
53
- locations = [
54
- Test::Location.new('features/test.feature', 3)
55
- ]
56
- filter = Test::LocationsFilter.new(locations)
57
- compile [doc], receiver, [filter]
58
- expect(receiver.test_case_locations).to eq locations
59
- end
60
-
61
- describe "matching location" do
62
- let(:file) { 'features/path/to/the.feature' }
63
-
64
- let(:test_cases) do
65
- receiver = double.as_null_object
66
- result = []
67
- allow(receiver).to receive(:test_case) { |test_case| result << test_case }
68
- compile [doc], receiver
69
- result
70
- end
71
-
72
- context "for a scenario" do
73
- let(:doc) do
74
- Gherkin::Document.new(file, <<-END)
75
- Feature:
76
-
77
- Scenario: one
78
- Given one a
79
-
80
- # comment
81
- @tags
82
- Scenario: two
83
- Given two a
84
- And two b
85
-
86
- Scenario: three
87
- Given three b
88
-
89
- Scenario: with docstring
90
- Given a docstring
91
- """
92
- this is a docstring
93
- """
94
-
95
- Scenario: with a table
96
- Given a table
97
- | a | b |
98
- | 1 | 2 |
99
- | 3 | 4 |
100
-
101
- END
102
- end
103
-
104
- def test_case_named(name)
105
- test_cases.find { |c| c.name == name }
106
- end
107
-
108
- it 'matches the precise location of the scenario' do
109
- location = test_case_named('two').location
110
- filter = Test::LocationsFilter.new([location])
111
- compile [doc], receiver, [filter]
112
- expect(receiver.test_case_locations).to eq [test_case_named('two').location]
113
- end
114
-
115
- it 'matches multiple locations' do
116
- good_location = Test::Location.new(file, 8)
117
- bad_location = Test::Location.new(file, 5)
118
- filter = Test::LocationsFilter.new([good_location, bad_location])
119
- compile [doc], receiver, [filter]
120
- expect(receiver.test_case_locations).to eq [test_case_named('two').location]
121
- end
122
-
123
- it "doesn't match a location after the scenario line" do
124
- location = Test::Location.new(file, 9)
125
- filter = Test::LocationsFilter.new([location])
126
- compile [doc], receiver, [filter]
127
- expect(receiver.test_case_locations).to eq []
128
- end
129
-
130
- it "doesn't match a location before the scenario line" do
131
- location = Test::Location.new(file, 7)
132
- filter = Test::LocationsFilter.new([location])
133
- compile [doc], receiver, [filter]
134
- expect(receiver.test_case_locations).to eq []
135
- end
136
-
137
- context "with duplicate locations in the filter" do
138
- it "matches each test case only once" do
139
- location_tc_two = test_case_named('two').location
140
- location_tc_one = test_case_named('one').location
141
- location_last_step_tc_two = Test::Location.new(file, 10)
142
- filter = Test::LocationsFilter.new([location_tc_two, location_tc_one, location_last_step_tc_two])
143
- compile [doc], receiver, [filter]
144
- expect(receiver.test_case_locations).to eq [test_case_named('two').location, location_tc_one = test_case_named('one').location]
145
- end
146
- end
147
- end
148
-
149
- context "for a scenario outline" do
150
- let(:doc) do
151
- Gherkin::Document.new(file, <<-END)
152
- Feature:
153
-
154
- Scenario: one
155
- Given one a
156
-
157
- # comment on line 6
158
- @tags-on-line-7
159
- Scenario Outline: two <arg>
160
- Given two a
161
- And two <arg>
162
- """
163
- docstring
164
- """
165
-
166
- # comment on line 15
167
- @tags-on-line-16
168
- Examples: x1
169
- | arg |
170
- | b |
171
-
172
- Examples: x2
173
- | arg |
174
- | c |
175
- | d |
176
-
177
- Scenario: three
178
- Given three b
179
- END
180
- end
181
-
182
- let(:test_case) do
183
- test_cases.find { |c| c.name == "two b" }
184
- end
185
-
186
- it "matches row location to the test case of the row" do
187
- locations = [
188
- Test::Location.new(file, 19),
189
- ]
190
- filter = Test::LocationsFilter.new(locations)
191
- compile [doc], receiver, [filter]
192
- expect(receiver.test_case_locations).to eq [test_case.location]
193
- end
194
-
195
- it "matches outline location with the all test cases of all the tables" do
196
- locations = [
197
- Test::Location.new(file, 8),
198
- ]
199
- filter = Test::LocationsFilter.new(locations)
200
- compile [doc], receiver, [filter]
201
- expect(receiver.test_case_locations.map(&:line)).to eq [19, 23, 24]
202
- end
203
-
204
- it "doesn't match the location of the examples line" do
205
- location = Test::Location.new(file, 17)
206
- filter = Test::LocationsFilter.new([location])
207
- compile [doc], receiver, [filter]
208
- expect(receiver.test_case_locations).to eq []
209
- end
210
- end
211
- end
212
-
213
- context "under load", slow: true do
214
- num_features = 50
215
- num_scenarios_per_feature = 50
216
-
217
- let(:docs) do
218
- (1..num_features).map do |i|
219
- gherkin("features/test_#{i}.feature") do
220
- feature do
221
- (1..num_scenarios_per_feature).each do |j|
222
- scenario "scenario #{j}" do
223
- step 'text'
224
- end
225
- end
226
- end
227
- end
228
- end
229
- end
230
-
231
- num_locations = num_features
232
- let(:locations) do
233
- (1..num_locations).map do |i|
234
- (1..num_scenarios_per_feature).map do |j|
235
- line = 3 + ((j - 1) * 3)
236
- Test::Location.new("features/test_#{i}.feature", line)
237
- end
238
- end.flatten
239
- end
240
-
241
- max_duration_ms = 10000
242
- max_duration_ms *= 2.5 if defined?(JRUBY_VERSION)
243
- it "filters #{num_features * num_scenarios_per_feature} test cases within #{max_duration_ms}ms" do
244
- filter = Test::LocationsFilter.new(locations)
245
- Timeout.timeout(max_duration_ms / 1000.0) do
246
- compile docs, receiver, [filter]
247
- end
248
- expect(receiver.test_cases.length).to eq num_features * num_scenarios_per_feature
249
- end
250
-
251
- end
252
- end
253
-
254
- class SpyReceiver
255
- def test_case(test_case)
256
- test_cases << test_case
257
- end
258
-
259
- def done
260
- end
261
-
262
- def test_case_locations
263
- test_cases.map(&:location)
264
- end
265
-
266
- def test_cases
267
- @test_cases ||= []
268
- end
269
-
270
- end
271
- end