cucumber-core 4.0.0 → 5.0.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.
@@ -0,0 +1,40 @@
1
+ require 'cucumber/core/event'
2
+
3
+ module Cucumber
4
+ module Core
5
+ describe Event do
6
+
7
+ describe ".new" do
8
+ it "generates new types of events" do
9
+ my_event_type = Event.new
10
+ my_event = my_event_type.new
11
+ expect(my_event).to be_kind_of(Core::Event)
12
+ end
13
+
14
+ it "generates events with attributes" do
15
+ my_event_type = Event.new(:foo, :bar)
16
+ my_event = my_event_type.new(1,2)
17
+ expect(my_event.attributes).to eq [1, 2]
18
+ expect(my_event.foo).to eq 1
19
+ expect(my_event.bar).to eq 2
20
+ end
21
+ end
22
+
23
+ describe "a generated event" do
24
+ class MyEventType < Event.new(:foo, :bar)
25
+ end
26
+
27
+ it "can be converted to a hash" do
28
+ my_event = MyEventType.new(1,2)
29
+ expect(my_event.to_h).to eq foo: 1, bar: 2
30
+ end
31
+
32
+ it "has an event_id" do
33
+ expect(MyEventType.event_id).to eq :my_event_type
34
+ expect(MyEventType.new(1,2).event_id).to eq :my_event_type
35
+ end
36
+ end
37
+ end
38
+
39
+ end
40
+ end
@@ -0,0 +1,101 @@
1
+ # frozen_string_literal: true
2
+ require 'cucumber/core/gherkin/writer'
3
+ require 'cucumber/core'
4
+ require 'cucumber/core/filter'
5
+
6
+ module Cucumber::Core
7
+ describe Filter do
8
+ include Cucumber::Core::Gherkin::Writer
9
+ include Cucumber::Core
10
+
11
+ describe ".new" do
12
+ let(:receiver) { double.as_null_object }
13
+
14
+ let(:doc) {
15
+ gherkin do
16
+ feature do
17
+ scenario 'x' do
18
+ step 'a step'
19
+ end
20
+
21
+ scenario 'y' do
22
+ step 'a step'
23
+ end
24
+ end
25
+ end
26
+ }
27
+
28
+ it "creates a filter class that can pass-through by default" do
29
+ my_filter_class = Filter.new
30
+ my_filter = my_filter_class.new
31
+ expect(receiver).to receive(:test_case) { |test_case|
32
+ expect(test_case.test_steps.length).to eq 1
33
+ expect(test_case.test_steps.first.text).to eq 'a step'
34
+ }.exactly(2).times
35
+ compile [doc], receiver, [my_filter]
36
+ end
37
+
38
+ context "customizing by subclassing" do
39
+
40
+ # Each filter imlicitly gets a :receiver attribute
41
+ # that you need to call with the new test case
42
+ # once you've received yours and modified it.
43
+ class BasicBlankingFilter < Filter.new
44
+ def test_case(test_case)
45
+ test_case.with_steps([]).describe_to(receiver)
46
+ end
47
+ end
48
+
49
+ # You can pass the names of attributes when building a
50
+ # filter, allowing you to have custom attributes.
51
+ class NamedBlankingFilter < Filter.new(:name_pattern)
52
+ def test_case(test_case)
53
+ if test_case.name =~ name_pattern
54
+ test_case.with_steps([]).describe_to(receiver)
55
+ else
56
+ test_case.describe_to(receiver) # or just call `super`
57
+ end
58
+ self
59
+ end
60
+ end
61
+
62
+ it "can override methods from the base class" do
63
+ expect(receiver).to receive(:test_case) { |test_case|
64
+ expect(test_case.test_steps.length).to eq 0
65
+ }.exactly(2).times
66
+ run BasicBlankingFilter.new
67
+ end
68
+
69
+ it "can take arguments" do
70
+ expect(receiver).to receive(:test_case) { |test_case|
71
+ expect(test_case.test_steps.length).to eq 0
72
+ }.once.ordered
73
+ expect(receiver).to receive(:test_case) { |test_case|
74
+ expect(test_case.test_steps.length).to eq 1
75
+ }.once.ordered
76
+ run NamedBlankingFilter.new(/x/)
77
+ end
78
+
79
+ end
80
+
81
+ context "customizing by using a block" do
82
+ BlockBlankingFilter = Filter.new do
83
+ def test_case(test_case)
84
+ test_case.with_steps([]).describe_to(receiver)
85
+ end
86
+ end
87
+
88
+ it "allows methods to be overridden" do
89
+ expect(receiver).to receive(:test_case) { |test_case|
90
+ expect(test_case.test_steps.length).to eq 0
91
+ }.exactly(2).times
92
+ run BlockBlankingFilter.new
93
+ end
94
+ end
95
+
96
+ def run(filter)
97
+ compile [doc], receiver, [filter]
98
+ end
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,95 @@
1
+ # -*- encoding: utf-8 -*-
2
+ # frozen_string_literal: true
3
+ require 'cucumber/core/gherkin/parser'
4
+ require 'cucumber/core/gherkin/writer'
5
+
6
+ module Cucumber
7
+ module Core
8
+ module Gherkin
9
+ describe Parser do
10
+ let(:receiver) { double }
11
+ let(:event_bus) { double }
12
+ let(:parser) { Parser.new(receiver, event_bus) }
13
+ let(:visitor) { double }
14
+
15
+ before do
16
+ allow( event_bus ).to receive(:gherkin_source_parsed)
17
+ end
18
+
19
+ def parse
20
+ parser.document(source)
21
+ end
22
+
23
+ context "for invalid gherkin" do
24
+ let(:source) { Gherkin::Document.new(path, "\nnot gherkin\n\nFeature: \n") }
25
+ let(:path) { 'path_to/the.feature' }
26
+
27
+ it "raises an error" do
28
+ expect { parse }.to raise_error(ParseError) do |error|
29
+ expect( error.message ).to match(/not gherkin/)
30
+ expect( error.message ).to match(/#{path}/)
31
+ end
32
+ end
33
+ end
34
+
35
+ context "for valid gherkin" do
36
+ let(:source) { Gherkin::Document.new(path, 'Feature:') }
37
+ let(:path) { 'path_to/the.feature' }
38
+
39
+ it "issues a gherkin_source_parsed event" do
40
+ expect( event_bus ).to receive(:gherkin_source_parsed)
41
+ parse
42
+ end
43
+ end
44
+
45
+ context "for empty files" do
46
+ let(:source) { Gherkin::Document.new(path, '') }
47
+ let(:path) { 'path_to/the.feature' }
48
+
49
+ it "passes on no pickles" do
50
+ expect( receiver ).not_to receive(:pickle)
51
+ parse
52
+ end
53
+ end
54
+
55
+ include Writer
56
+ def self.source(&block)
57
+ let(:source) { gherkin(&block) }
58
+ end
59
+
60
+ RSpec::Matchers.define :pickle_with_language do |language|
61
+ match { |actual| actual.language == language }
62
+ end
63
+
64
+ context "when the Gherkin has a language header" do
65
+ source do
66
+ feature(language: 'ja', keyword: '機能') do
67
+ scenario(keyword: 'シナリオ')
68
+ end
69
+ end
70
+
71
+ it "the pickles have the correct language" do
72
+ expect( receiver ).to receive(:pickle).with(pickle_with_language('ja'))
73
+ parse
74
+ end
75
+ end
76
+
77
+ context "when the Gherkin produces one pickle" do
78
+ source do
79
+ feature do
80
+ scenario do
81
+ step 'text'
82
+ end
83
+ end
84
+ end
85
+
86
+ it "passes on the pickle" do
87
+ expect( receiver ).to receive(:pickle)
88
+ parse
89
+ end
90
+ end
91
+
92
+ end
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,333 @@
1
+ # frozen_string_literal: true
2
+ require 'cucumber/core/gherkin/writer'
3
+ require 'unindent'
4
+
5
+ module Cucumber::Core::Gherkin
6
+ describe Writer do
7
+ include Writer
8
+
9
+ context 'specifying uri' do
10
+ it 'generates a uri by default' do
11
+ source = gherkin { feature }
12
+ expect( source.uri ).to eq 'features/test.feature'
13
+ end
14
+
15
+ it 'allows you to specify a URI' do
16
+ source = gherkin('features/path/to/my.feature') { feature }
17
+ expect( source.uri ).to eq 'features/path/to/my.feature'
18
+ end
19
+ end
20
+
21
+ context 'a feature' do
22
+
23
+ it 'generates the feature statement' do
24
+ source = gherkin { feature }
25
+ expect( source ).to eq "Feature:\n"
26
+ end
27
+
28
+ context 'when a name is provided' do
29
+ it 'includes the name in the feature statement' do
30
+ source = gherkin do
31
+ feature "A Feature\n"
32
+ end
33
+ expect( source ).to eq "Feature: A Feature\n"
34
+ end
35
+ end
36
+
37
+ context 'when a description is provided' do
38
+ it 'includes the description in the feature statement' do
39
+ source = gherkin do
40
+ feature "A Feature", description: <<-END
41
+ This is the description
42
+ which can span
43
+ multiple lines.
44
+ END
45
+ end
46
+ expected = <<-END
47
+ Feature: A Feature
48
+ This is the description
49
+ which can span
50
+ multiple lines.
51
+ END
52
+
53
+ expect( source ).to eq expected.unindent
54
+ end
55
+ end
56
+
57
+ context 'when a keyword is provided' do
58
+ it 'uses the supplied keyword' do
59
+ source = gherkin do
60
+ feature "A Feature", keyword: "Business Need"
61
+ end
62
+ expect( source ).to eq "Business Need: A Feature\n"
63
+ end
64
+ end
65
+
66
+ context 'when a language is supplied' do
67
+ it 'inserts a language statement' do
68
+ source = gherkin do
69
+ feature language: 'ru'
70
+ end
71
+
72
+ expect( source ).to eq "# language: ru\nFeature:\n"
73
+ end
74
+ end
75
+
76
+ context 'when a comment is supplied' do
77
+ it 'inserts a comment' do
78
+ source = gherkin do
79
+ comment 'wow'
80
+ comment 'great'
81
+ feature
82
+ end
83
+
84
+ expect( source.to_s ).to eq "# wow\n# great\nFeature:\n"
85
+ end
86
+ end
87
+
88
+ context 'with a scenario' do
89
+ it 'includes the scenario statement' do
90
+ source = gherkin do
91
+ feature "A Feature" do
92
+ scenario
93
+ end
94
+ end
95
+
96
+ expect( source.to_s ).to match(/Scenario:/)
97
+ end
98
+
99
+ context 'when a comment is provided' do
100
+ it 'includes the comment in the scenario statement' do
101
+ source = gherkin do
102
+ feature do
103
+ comment 'wow'
104
+ scenario
105
+ end
106
+ end
107
+ expect( source.to_s ).to eq <<-END.unindent
108
+ Feature:
109
+
110
+ # wow
111
+ Scenario:
112
+ END
113
+ end
114
+ end
115
+
116
+ context 'when a description is provided' do
117
+ it 'includes the description in the scenario statement' do
118
+ source = gherkin do
119
+ feature do
120
+ scenario description: <<-END
121
+ This is the description
122
+ which can span
123
+ multiple lines.
124
+ END
125
+ end
126
+ end
127
+
128
+ expect( source ).to eq <<-END.unindent
129
+ Feature:
130
+
131
+ Scenario:
132
+ This is the description
133
+ which can span
134
+ multiple lines.
135
+ END
136
+ end
137
+ end
138
+
139
+ context 'with a step' do
140
+ it 'includes the step statement' do
141
+ source = gherkin do
142
+ feature "A Feature" do
143
+ scenario do
144
+ step 'passing'
145
+ end
146
+ end
147
+ end
148
+
149
+ expect( source.to_s ).to match(/Given passing\Z/m)
150
+ end
151
+
152
+ context 'when a docstring is provided' do
153
+ it 'includes the content type when provided' do
154
+ source = gherkin do
155
+ feature do
156
+ scenario do
157
+ step 'failing' do
158
+ doc_string 'some text', 'text/plain'
159
+ end
160
+ end
161
+ end
162
+
163
+ end
164
+
165
+ expect( source ).to eq <<-END.unindent
166
+ Feature:
167
+
168
+ Scenario:
169
+ Given failing
170
+ """text/plain
171
+ some text
172
+ """
173
+ END
174
+ end
175
+ end
176
+ end
177
+ end
178
+
179
+ context 'with a background' do
180
+ it 'can have a description' do
181
+ source = gherkin do
182
+ feature do
183
+ background description: "One line,\nand two.."
184
+ end
185
+ end
186
+
187
+ expect( source ).to eq <<-END.unindent
188
+ Feature:
189
+
190
+ Background:
191
+ One line,
192
+ and two..
193
+ END
194
+ end
195
+ end
196
+
197
+ context 'with a scenario outline' do
198
+ it 'can have a description' do
199
+ source = gherkin do
200
+ feature do
201
+ scenario_outline description: "Doesn't need to be multi-line."
202
+ end
203
+ end
204
+
205
+ expect( source ).to eq <<-END.unindent
206
+ Feature:
207
+
208
+ Scenario Outline:
209
+ Doesn't need to be multi-line.
210
+ END
211
+ end
212
+
213
+ context 'and examples table' do
214
+ it 'can have a description' do
215
+ source = gherkin do
216
+ feature do
217
+ scenario_outline do
218
+ examples description: "Doesn't need to be multi-line." do
219
+
220
+ end
221
+ end
222
+ end
223
+ end
224
+
225
+ expect( source ).to eq <<-END.unindent
226
+ Feature:
227
+
228
+ Scenario Outline:
229
+
230
+ Examples:
231
+ Doesn't need to be multi-line.
232
+ END
233
+ end
234
+ end
235
+ end
236
+ end
237
+
238
+ it 'generates a complex feature' do
239
+ source = gherkin do
240
+ comment 'wow'
241
+ feature 'Fully featured', language: 'en', tags: '@always' do
242
+ comment 'cool'
243
+ background do
244
+ step 'passing'
245
+ end
246
+
247
+ scenario do
248
+ step 'passing'
249
+ end
250
+
251
+ comment 'here'
252
+ scenario 'with doc string', tags: '@first @second' do
253
+ comment 'and here'
254
+ step 'passing'
255
+ step 'failing', keyword: 'When' do
256
+ doc_string <<-END
257
+ I wish I was a little bit taller.
258
+ I wish I was a baller.
259
+ END
260
+ end
261
+ end
262
+
263
+ scenario 'with a table...' do
264
+ step 'passes:' do
265
+ table do
266
+ row 'name', 'age', 'location'
267
+ row 'Janine', '43', 'Antarctica'
268
+ end
269
+ end
270
+ end
271
+
272
+ comment 'yay'
273
+ scenario_outline 'eating' do
274
+ step 'there are <start> cucumbers'
275
+ step 'I eat <eat> cucumbers', keyword: 'When'
276
+ step 'I should have <left> cucumbers', keyword: 'Then'
277
+
278
+ comment 'hmmm'
279
+ examples do
280
+ row 'start', 'eat', 'left'
281
+ row '12', '5', '7'
282
+ row '20', '5', '15'
283
+ end
284
+ end
285
+ end
286
+ end
287
+
288
+ expect( source.to_s ).to eq <<-END.unindent
289
+ # language: en
290
+ # wow
291
+ @always
292
+ Feature: Fully featured
293
+
294
+ # cool
295
+ Background:
296
+ Given passing
297
+
298
+ Scenario:
299
+ Given passing
300
+
301
+ # here
302
+ @first @second
303
+ Scenario: with doc string
304
+ # and here
305
+ Given passing
306
+ When failing
307
+ """
308
+ I wish I was a little bit taller.
309
+ I wish I was a baller.
310
+ """
311
+
312
+ Scenario: with a table...
313
+ Given passes:
314
+ | name | age | location |
315
+ | Janine | 43 | Antarctica |
316
+
317
+ # yay
318
+ Scenario Outline: eating
319
+ Given there are <start> cucumbers
320
+ When I eat <eat> cucumbers
321
+ Then I should have <left> cucumbers
322
+
323
+ # hmmm
324
+ Examples:
325
+ | start | eat | left |
326
+ | 12 | 5 | 7 |
327
+ | 20 | 5 | 15 |
328
+ END
329
+
330
+ end
331
+ end
332
+ end
333
+