cucumber-core 0.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.
- checksums.yaml +7 -0
- data/.coveralls.yml +1 -0
- data/.rspec +1 -0
- data/.ruby-gemset +1 -0
- data/.travis.yml +16 -0
- data/Gemfile +2 -0
- data/LICENSE +20 -0
- data/README.md +9 -0
- data/Rakefile +24 -0
- data/cucumber-core.gemspec +32 -0
- data/lib/cucumber/core.rb +37 -0
- data/lib/cucumber/core/ast.rb +13 -0
- data/lib/cucumber/core/ast/background.rb +33 -0
- data/lib/cucumber/core/ast/comment.rb +17 -0
- data/lib/cucumber/core/ast/data_table.rb +326 -0
- data/lib/cucumber/core/ast/describes_itself.rb +16 -0
- data/lib/cucumber/core/ast/doc_string.rb +83 -0
- data/lib/cucumber/core/ast/empty_background.rb +12 -0
- data/lib/cucumber/core/ast/examples_table.rb +95 -0
- data/lib/cucumber/core/ast/feature.rb +62 -0
- data/lib/cucumber/core/ast/location.rb +140 -0
- data/lib/cucumber/core/ast/multiline_argument.rb +33 -0
- data/lib/cucumber/core/ast/names.rb +19 -0
- data/lib/cucumber/core/ast/outline_step.rb +51 -0
- data/lib/cucumber/core/ast/scenario.rb +43 -0
- data/lib/cucumber/core/ast/scenario_outline.rb +44 -0
- data/lib/cucumber/core/ast/step.rb +38 -0
- data/lib/cucumber/core/ast/tag.rb +14 -0
- data/lib/cucumber/core/compiler.rb +136 -0
- data/lib/cucumber/core/gherkin/ast_builder.rb +315 -0
- data/lib/cucumber/core/gherkin/document.rb +20 -0
- data/lib/cucumber/core/gherkin/parser.rb +45 -0
- data/lib/cucumber/core/gherkin/writer.rb +220 -0
- data/lib/cucumber/core/gherkin/writer/helpers.rb +178 -0
- data/lib/cucumber/core/platform.rb +30 -0
- data/lib/cucumber/core/test/case.rb +143 -0
- data/lib/cucumber/core/test/filters.rb +48 -0
- data/lib/cucumber/core/test/filters/tag_filter.rb +110 -0
- data/lib/cucumber/core/test/hook_compiler.rb +109 -0
- data/lib/cucumber/core/test/mapper.rb +56 -0
- data/lib/cucumber/core/test/mapping.rb +67 -0
- data/lib/cucumber/core/test/result.rb +191 -0
- data/lib/cucumber/core/test/runner.rb +149 -0
- data/lib/cucumber/core/test/step.rb +69 -0
- data/lib/cucumber/core/test/timer.rb +31 -0
- data/lib/cucumber/core/version.rb +9 -0
- data/lib/cucumber/initializer.rb +18 -0
- data/spec/capture_warnings.rb +68 -0
- data/spec/coverage.rb +10 -0
- data/spec/cucumber/core/ast/data_table_spec.rb +139 -0
- data/spec/cucumber/core/ast/doc_string_spec.rb +77 -0
- data/spec/cucumber/core/ast/examples_table_spec.rb +87 -0
- data/spec/cucumber/core/ast/location_spec.rb +105 -0
- data/spec/cucumber/core/ast/outline_step_spec.rb +77 -0
- data/spec/cucumber/core/ast/step_spec.rb +44 -0
- data/spec/cucumber/core/compiler_spec.rb +249 -0
- data/spec/cucumber/core/gherkin/parser_spec.rb +182 -0
- data/spec/cucumber/core/gherkin/writer_spec.rb +332 -0
- data/spec/cucumber/core/test/case_spec.rb +416 -0
- data/spec/cucumber/core/test/hook_compiler_spec.rb +78 -0
- data/spec/cucumber/core/test/mapper_spec.rb +68 -0
- data/spec/cucumber/core/test/mapping_spec.rb +103 -0
- data/spec/cucumber/core/test/result_spec.rb +178 -0
- data/spec/cucumber/core/test/runner_spec.rb +265 -0
- data/spec/cucumber/core/test/step_spec.rb +58 -0
- data/spec/cucumber/core/test/timer_spec.rb +13 -0
- data/spec/cucumber/core_spec.rb +419 -0
- data/spec/cucumber/initializer_spec.rb +49 -0
- metadata +221 -0
@@ -0,0 +1,182 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require 'cucumber/initializer'
|
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(:parser) { Parser.new(receiver) }
|
12
|
+
let(:visitor) { double }
|
13
|
+
|
14
|
+
def parse
|
15
|
+
parser.document(source)
|
16
|
+
end
|
17
|
+
|
18
|
+
context "for invalid gherkin" do
|
19
|
+
let(:source) { Gherkin::Document.new(path, 'not gherkin') }
|
20
|
+
let(:path) { 'path_to/the.feature' }
|
21
|
+
|
22
|
+
it "raises an error" do
|
23
|
+
expect { parse }.to raise_error(ParseError) do |error|
|
24
|
+
expect( error.message ).to match(/not gherkin/)
|
25
|
+
expect( error.message ).to match(/#{path}/)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
include Writer
|
31
|
+
def self.source(&block)
|
32
|
+
let(:source) { gherkin(&block) }
|
33
|
+
end
|
34
|
+
|
35
|
+
def feature
|
36
|
+
result = nil
|
37
|
+
receiver.stub(:feature) { |feature| result = feature }
|
38
|
+
parse
|
39
|
+
result
|
40
|
+
end
|
41
|
+
|
42
|
+
context "when the Gherkin has a language header" do
|
43
|
+
source do
|
44
|
+
feature(language: 'ja', keyword: '機能')
|
45
|
+
end
|
46
|
+
|
47
|
+
it "sets the language from the Gherkin" do
|
48
|
+
feature.language.iso_code.should == 'ja'
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
context "a Scenario with a DocString" do
|
53
|
+
source do
|
54
|
+
feature do
|
55
|
+
scenario do
|
56
|
+
step do
|
57
|
+
doc_string("content")
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
it "parses doc strings without error" do
|
64
|
+
visitor.stub(:feature).and_yield
|
65
|
+
visitor.stub(:scenario).and_yield
|
66
|
+
visitor.stub(:step).and_yield
|
67
|
+
|
68
|
+
location = double
|
69
|
+
expected = Ast::DocString.new("content", "", location)
|
70
|
+
expect( visitor ).to receive(:doc_string).with(expected)
|
71
|
+
feature.describe_to(visitor)
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
context "a Scenario with a DataTable" do
|
77
|
+
source do
|
78
|
+
feature do
|
79
|
+
scenario do
|
80
|
+
step do
|
81
|
+
table do
|
82
|
+
row "name", "surname"
|
83
|
+
row "rob", "westgeest"
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
it "parses the DataTable" do
|
91
|
+
visitor = double
|
92
|
+
visitor.stub(:feature).and_yield
|
93
|
+
visitor.stub(:scenario).and_yield
|
94
|
+
visitor.stub(:step).and_yield
|
95
|
+
|
96
|
+
expected = Ast::DataTable.new([['name', 'surname'], ['rob', 'westgeest']], Ast::Location.new('foo.feature', 23))
|
97
|
+
expect( visitor ).to receive(:table).with(expected)
|
98
|
+
feature.describe_to(visitor)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
context "a Scenario with a Comment" do
|
103
|
+
source do
|
104
|
+
feature do
|
105
|
+
comment 'wow'
|
106
|
+
scenario
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
it "parses the comment into the AST" do
|
111
|
+
visitor = double
|
112
|
+
visitor.stub(:feature).and_yield
|
113
|
+
expect( visitor ).to receive(:scenario) do |scenario|
|
114
|
+
expect( scenario.comments.join ).to eq "# wow"
|
115
|
+
end
|
116
|
+
feature.describe_to(visitor)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
context "a Scenario Outline" do
|
121
|
+
source do
|
122
|
+
feature do
|
123
|
+
scenario_outline 'outline name' do
|
124
|
+
step 'passing <arg>'
|
125
|
+
|
126
|
+
examples do
|
127
|
+
row 'arg'
|
128
|
+
row '1'
|
129
|
+
row '2'
|
130
|
+
end
|
131
|
+
|
132
|
+
examples do
|
133
|
+
row 'arg'
|
134
|
+
row 'a'
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
it "creates a scenario outline node" do
|
141
|
+
visitor.stub(:feature).and_yield
|
142
|
+
expect( visitor ).to receive(:scenario_outline) do |outline|
|
143
|
+
expect( outline.name ).to eq 'outline name'
|
144
|
+
end
|
145
|
+
feature.describe_to(visitor)
|
146
|
+
end
|
147
|
+
|
148
|
+
it "creates a step node for each step of the scenario outline" do
|
149
|
+
visitor.stub(:feature).and_yield
|
150
|
+
visitor.stub(:scenario_outline).and_yield
|
151
|
+
visitor.stub(:examples_table)
|
152
|
+
expect( visitor ).to receive(:outline_step) do |step|
|
153
|
+
expect( step.name ).to eq 'passing <arg>'
|
154
|
+
end
|
155
|
+
feature.describe_to(visitor)
|
156
|
+
end
|
157
|
+
|
158
|
+
it "creates an examples table node for each examples table" do
|
159
|
+
visitor.stub(:feature).and_yield
|
160
|
+
visitor.stub(:scenario_outline).and_yield
|
161
|
+
visitor.stub(:outline_step)
|
162
|
+
expect( visitor ).to receive(:examples_table).exactly(2).times.and_yield
|
163
|
+
expect( visitor ).to receive(:examples_table_row) do |row|
|
164
|
+
expect( row.number ).to eq 1
|
165
|
+
expect( row.values ).to eq ['1']
|
166
|
+
end.once.ordered
|
167
|
+
expect( visitor ).to receive(:examples_table_row) do |row|
|
168
|
+
expect( row.number ).to eq 2
|
169
|
+
expect( row.values ).to eq ['2']
|
170
|
+
end.once.ordered
|
171
|
+
expect( visitor ).to receive(:examples_table_row) do |row|
|
172
|
+
expect( row.number ).to eq 1
|
173
|
+
expect( row.values ).to eq ['a']
|
174
|
+
end.once.ordered
|
175
|
+
feature.describe_to(visitor)
|
176
|
+
end
|
177
|
+
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
@@ -0,0 +1,332 @@
|
|
1
|
+
require 'cucumber/core/gherkin/writer'
|
2
|
+
require 'unindent'
|
3
|
+
|
4
|
+
module Cucumber::Core::Gherkin
|
5
|
+
describe Writer do
|
6
|
+
include Writer
|
7
|
+
|
8
|
+
context 'specifying uri' do
|
9
|
+
it 'generates a uri by default' do
|
10
|
+
source = gherkin { feature }
|
11
|
+
expect( source.uri ).to eq 'features/test.feature'
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'allows you to specify a URI' do
|
15
|
+
source = gherkin('features/path/to/my.feature') { feature }
|
16
|
+
expect( source.uri ).to eq 'features/path/to/my.feature'
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
context 'a feature' do
|
21
|
+
|
22
|
+
it 'generates the feature statement' do
|
23
|
+
source = gherkin { feature }
|
24
|
+
expect( source ).to eq "Feature:\n"
|
25
|
+
end
|
26
|
+
|
27
|
+
context 'when a name is provided' do
|
28
|
+
it 'includes the name in the feature statement' do
|
29
|
+
source = gherkin do
|
30
|
+
feature "A Feature\n"
|
31
|
+
end
|
32
|
+
expect( source ).to eq "Feature: A Feature\n"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
context 'when a description is provided' do
|
37
|
+
it 'includes the description in the feature statement' do
|
38
|
+
source = gherkin do
|
39
|
+
feature "A Feature", description: <<-END
|
40
|
+
This is the description
|
41
|
+
which can span
|
42
|
+
multiple lines.
|
43
|
+
END
|
44
|
+
end
|
45
|
+
expected = <<-END
|
46
|
+
Feature: A Feature
|
47
|
+
This is the description
|
48
|
+
which can span
|
49
|
+
multiple lines.
|
50
|
+
END
|
51
|
+
|
52
|
+
expect( source ).to eq expected.unindent
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
context 'when a keyword is provided' do
|
57
|
+
it 'uses the supplied keyword' do
|
58
|
+
source = gherkin do
|
59
|
+
feature "A Feature", keyword: "Business Need"
|
60
|
+
end
|
61
|
+
expect( source ).to eq "Business Need: A Feature\n"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
context 'when a language is supplied' do
|
66
|
+
it 'inserts a language statement' do
|
67
|
+
source = gherkin do
|
68
|
+
feature language: 'ru'
|
69
|
+
end
|
70
|
+
|
71
|
+
expect( source ).to eq "# language: ru\nFeature:\n"
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
context 'when a comment is supplied' do
|
76
|
+
it 'inserts a comment' do
|
77
|
+
source = gherkin do
|
78
|
+
comment 'wow'
|
79
|
+
comment 'great'
|
80
|
+
feature
|
81
|
+
end
|
82
|
+
|
83
|
+
expect( source.to_s ).to eq "# wow\n# great\nFeature:\n"
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
context 'with a scenario' do
|
88
|
+
it 'includes the scenario statement' do
|
89
|
+
source = gherkin do
|
90
|
+
feature "A Feature" do
|
91
|
+
scenario
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
expect( source.to_s ).to match(/Scenario:/)
|
96
|
+
end
|
97
|
+
|
98
|
+
context 'when a comment is provided' do
|
99
|
+
it 'includes the comment in the scenario statement' do
|
100
|
+
source = gherkin do
|
101
|
+
feature do
|
102
|
+
comment 'wow'
|
103
|
+
scenario
|
104
|
+
end
|
105
|
+
end
|
106
|
+
expect( source.to_s ).to eq <<-END.unindent
|
107
|
+
Feature:
|
108
|
+
|
109
|
+
# wow
|
110
|
+
Scenario:
|
111
|
+
END
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
context 'when a description is provided' do
|
116
|
+
it 'includes the description in the scenario statement' do
|
117
|
+
source = gherkin do
|
118
|
+
feature do
|
119
|
+
scenario description: <<-END
|
120
|
+
This is the description
|
121
|
+
which can span
|
122
|
+
multiple lines.
|
123
|
+
END
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
expect( source ).to eq <<-END.unindent
|
128
|
+
Feature:
|
129
|
+
|
130
|
+
Scenario:
|
131
|
+
This is the description
|
132
|
+
which can span
|
133
|
+
multiple lines.
|
134
|
+
END
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
context 'with a step' do
|
139
|
+
it 'includes the step statement' do
|
140
|
+
source = gherkin do
|
141
|
+
feature "A Feature" do
|
142
|
+
scenario do
|
143
|
+
step 'passing'
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
expect( source.to_s ).to match(/Given passing\Z/m)
|
149
|
+
end
|
150
|
+
|
151
|
+
context 'when a docstring is provided' do
|
152
|
+
it 'includes the content type when provided' do
|
153
|
+
source = gherkin do
|
154
|
+
feature do
|
155
|
+
scenario do
|
156
|
+
step 'failing' do
|
157
|
+
doc_string 'some text', 'text/plain'
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
end
|
163
|
+
|
164
|
+
expect( source ).to eq <<-END.unindent
|
165
|
+
Feature:
|
166
|
+
|
167
|
+
Scenario:
|
168
|
+
Given failing
|
169
|
+
"""text/plain
|
170
|
+
some text
|
171
|
+
"""
|
172
|
+
END
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
context 'with a background' do
|
179
|
+
it 'can have a description' do
|
180
|
+
source = gherkin do
|
181
|
+
feature do
|
182
|
+
background description: "One line,\nand two.."
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
expect( source ).to eq <<-END.unindent
|
187
|
+
Feature:
|
188
|
+
|
189
|
+
Background:
|
190
|
+
One line,
|
191
|
+
and two..
|
192
|
+
END
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
context 'with a scenario outline' do
|
197
|
+
it 'can have a description' do
|
198
|
+
source = gherkin do
|
199
|
+
feature do
|
200
|
+
scenario_outline description: "Doesn't need to be multi-line."
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
expect( source ).to eq <<-END.unindent
|
205
|
+
Feature:
|
206
|
+
|
207
|
+
Scenario Outline:
|
208
|
+
Doesn't need to be multi-line.
|
209
|
+
END
|
210
|
+
end
|
211
|
+
|
212
|
+
context 'and examples table' do
|
213
|
+
it 'can have a description' do
|
214
|
+
source = gherkin do
|
215
|
+
feature do
|
216
|
+
scenario_outline do
|
217
|
+
examples description: "Doesn't need to be multi-line." do
|
218
|
+
|
219
|
+
end
|
220
|
+
end
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
expect( source ).to eq <<-END.unindent
|
225
|
+
Feature:
|
226
|
+
|
227
|
+
Scenario Outline:
|
228
|
+
|
229
|
+
Examples:
|
230
|
+
Doesn't need to be multi-line.
|
231
|
+
END
|
232
|
+
end
|
233
|
+
end
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
it 'generates a complex feature' do
|
238
|
+
source = gherkin do
|
239
|
+
comment 'wow'
|
240
|
+
feature 'Fully featured', language: 'en', tags: '@always' do
|
241
|
+
comment 'cool'
|
242
|
+
background do
|
243
|
+
step 'passing'
|
244
|
+
end
|
245
|
+
|
246
|
+
scenario do
|
247
|
+
step 'passing'
|
248
|
+
end
|
249
|
+
|
250
|
+
comment 'here'
|
251
|
+
scenario 'with doc string', tags: '@first @second' do
|
252
|
+
comment 'and here'
|
253
|
+
step 'passing'
|
254
|
+
step 'failing', keyword: 'When' do
|
255
|
+
doc_string <<-END
|
256
|
+
I wish I was a little bit taller.
|
257
|
+
I wish I was a baller.
|
258
|
+
END
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
scenario 'with a table...' do
|
263
|
+
step 'passes:' do
|
264
|
+
table do
|
265
|
+
row 'name', 'age', 'location'
|
266
|
+
row 'Janine', '43', 'Antarctica'
|
267
|
+
end
|
268
|
+
end
|
269
|
+
end
|
270
|
+
|
271
|
+
comment 'yay'
|
272
|
+
scenario_outline 'eating' do
|
273
|
+
step 'there are <start> cucumbers'
|
274
|
+
step 'I eat <eat> cucumbers', keyword: 'When'
|
275
|
+
step 'I should have <left> cucumbers', keyword: 'Then'
|
276
|
+
|
277
|
+
comment 'hmmm'
|
278
|
+
examples do
|
279
|
+
row 'start', 'eat', 'left'
|
280
|
+
row '12', '5', '7'
|
281
|
+
row '20', '5', '15'
|
282
|
+
end
|
283
|
+
end
|
284
|
+
end
|
285
|
+
end
|
286
|
+
|
287
|
+
expect( source.to_s ).to eq <<-END.unindent
|
288
|
+
# language: en
|
289
|
+
# wow
|
290
|
+
@always
|
291
|
+
Feature: Fully featured
|
292
|
+
|
293
|
+
# cool
|
294
|
+
Background:
|
295
|
+
Given passing
|
296
|
+
|
297
|
+
Scenario:
|
298
|
+
Given passing
|
299
|
+
|
300
|
+
# here
|
301
|
+
@first @second
|
302
|
+
Scenario: with doc string
|
303
|
+
# and here
|
304
|
+
Given passing
|
305
|
+
When failing
|
306
|
+
"""
|
307
|
+
I wish I was a little bit taller.
|
308
|
+
I wish I was a baller.
|
309
|
+
"""
|
310
|
+
|
311
|
+
Scenario: with a table...
|
312
|
+
Given passes:
|
313
|
+
| name | age | location |
|
314
|
+
| Janine | 43 | Antarctica |
|
315
|
+
|
316
|
+
# yay
|
317
|
+
Scenario Outline: eating
|
318
|
+
Given there are <start> cucumbers
|
319
|
+
When I eat <eat> cucumbers
|
320
|
+
Then I should have <left> cucumbers
|
321
|
+
|
322
|
+
# hmmm
|
323
|
+
Examples:
|
324
|
+
| start | eat | left |
|
325
|
+
| 12 | 5 | 7 |
|
326
|
+
| 20 | 5 | 15 |
|
327
|
+
END
|
328
|
+
|
329
|
+
end
|
330
|
+
end
|
331
|
+
end
|
332
|
+
|