gherkin 2.2.5-x86-mswin32
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.
- data/.gitattributes +2 -0
- data/.gitignore +11 -0
- data/.mailmap +2 -0
- data/.rspec +1 -0
- data/.rvmrc +1 -0
- data/Gemfile +5 -0
- data/History.txt +306 -0
- data/LICENSE +20 -0
- data/README.rdoc +59 -0
- data/Rakefile +16 -0
- data/VERSION +1 -0
- data/bin/gherkin +5 -0
- data/build_native_gems.sh +8 -0
- data/cucumber.yml +3 -0
- data/features/escaped_pipes.feature +8 -0
- data/features/feature_parser.feature +237 -0
- data/features/json_formatter.feature +278 -0
- data/features/json_parser.feature +318 -0
- data/features/native_lexer.feature +19 -0
- data/features/parser_with_native_lexer.feature +205 -0
- data/features/pretty_formatter.feature +15 -0
- data/features/step_definitions/eyeball_steps.rb +3 -0
- data/features/step_definitions/gherkin_steps.rb +29 -0
- data/features/step_definitions/json_formatter_steps.rb +28 -0
- data/features/step_definitions/json_parser_steps.rb +20 -0
- data/features/step_definitions/pretty_formatter_steps.rb +82 -0
- data/features/steps_parser.feature +46 -0
- data/features/support/env.rb +38 -0
- data/gherkin.gemspec +59 -0
- data/ikvm/.gitignore +3 -0
- data/java/.gitignore +2 -0
- data/java/src/main/java/gherkin/lexer/i18n/.gitignore +1 -0
- data/java/src/main/resources/gherkin/.gitignore +1 -0
- data/lib/.gitignore +4 -0
- data/lib/gherkin.rb +2 -0
- data/lib/gherkin/c_lexer.rb +17 -0
- data/lib/gherkin/cli/main.rb +33 -0
- data/lib/gherkin/formatter/argument.rb +28 -0
- data/lib/gherkin/formatter/colors.rb +119 -0
- data/lib/gherkin/formatter/escaping.rb +15 -0
- data/lib/gherkin/formatter/filter_formatter.rb +136 -0
- data/lib/gherkin/formatter/json_formatter.rb +72 -0
- data/lib/gherkin/formatter/line_filter.rb +26 -0
- data/lib/gherkin/formatter/model.rb +231 -0
- data/lib/gherkin/formatter/monochrome_format.rb +9 -0
- data/lib/gherkin/formatter/pretty_formatter.rb +174 -0
- data/lib/gherkin/formatter/regexp_filter.rb +21 -0
- data/lib/gherkin/formatter/tag_count_formatter.rb +47 -0
- data/lib/gherkin/formatter/tag_filter.rb +19 -0
- data/lib/gherkin/i18n.rb +180 -0
- data/lib/gherkin/i18n.yml +601 -0
- data/lib/gherkin/json_parser.rb +88 -0
- data/lib/gherkin/lexer/i18n_lexer.rb +47 -0
- data/lib/gherkin/listener/event.rb +45 -0
- data/lib/gherkin/listener/formatter_listener.rb +113 -0
- data/lib/gherkin/native.rb +7 -0
- data/lib/gherkin/native/ikvm.rb +55 -0
- data/lib/gherkin/native/java.rb +55 -0
- data/lib/gherkin/native/null.rb +9 -0
- data/lib/gherkin/parser/meta.txt +5 -0
- data/lib/gherkin/parser/parser.rb +164 -0
- data/lib/gherkin/parser/root.txt +11 -0
- data/lib/gherkin/parser/steps.txt +4 -0
- data/lib/gherkin/rb_lexer.rb +8 -0
- data/lib/gherkin/rb_lexer/.gitignore +1 -0
- data/lib/gherkin/rb_lexer/README.rdoc +8 -0
- data/lib/gherkin/rubify.rb +24 -0
- data/lib/gherkin/tag_expression.rb +62 -0
- data/lib/gherkin/tools.rb +8 -0
- data/lib/gherkin/tools/files.rb +34 -0
- data/lib/gherkin/tools/reformat.rb +20 -0
- data/lib/gherkin/tools/stats.rb +20 -0
- data/lib/gherkin/tools/stats_listener.rb +60 -0
- data/lib/gherkin/version.rb +3 -0
- data/ragel/i18n/.gitignore +1 -0
- data/ragel/lexer.c.rl.erb +459 -0
- data/ragel/lexer.java.rl.erb +224 -0
- data/ragel/lexer.rb.rl.erb +179 -0
- data/ragel/lexer_common.rl.erb +50 -0
- data/spec/gherkin/c_lexer_spec.rb +21 -0
- data/spec/gherkin/fixtures/1.feature +8 -0
- data/spec/gherkin/fixtures/comments_in_table.feature +9 -0
- data/spec/gherkin/fixtures/complex.feature +45 -0
- data/spec/gherkin/fixtures/complex.json +143 -0
- data/spec/gherkin/fixtures/complex_for_filtering.feature +60 -0
- data/spec/gherkin/fixtures/complex_with_tags.feature +61 -0
- data/spec/gherkin/fixtures/dos_line_endings.feature +45 -0
- data/spec/gherkin/fixtures/hantu_pisang.feature +35 -0
- data/spec/gherkin/fixtures/i18n_fr.feature +14 -0
- data/spec/gherkin/fixtures/i18n_no.feature +7 -0
- data/spec/gherkin/fixtures/i18n_zh-CN.feature +9 -0
- data/spec/gherkin/fixtures/scenario_outline_with_tags.feature +13 -0
- data/spec/gherkin/fixtures/scenario_without_steps.feature +5 -0
- data/spec/gherkin/fixtures/simple_with_comments.feature +7 -0
- data/spec/gherkin/fixtures/simple_with_tags.feature +11 -0
- data/spec/gherkin/fixtures/with_bom.feature +3 -0
- data/spec/gherkin/formatter/argument_spec.rb +28 -0
- data/spec/gherkin/formatter/colors_spec.rb +18 -0
- data/spec/gherkin/formatter/filter_formatter_spec.rb +165 -0
- data/spec/gherkin/formatter/model_spec.rb +15 -0
- data/spec/gherkin/formatter/pretty_formatter_spec.rb +140 -0
- data/spec/gherkin/formatter/spaces.feature +9 -0
- data/spec/gherkin/formatter/tabs.feature +9 -0
- data/spec/gherkin/formatter/tag_count_formatter_spec.rb +30 -0
- data/spec/gherkin/i18n_spec.rb +149 -0
- data/spec/gherkin/java_lexer_spec.rb +20 -0
- data/spec/gherkin/json.rb +5 -0
- data/spec/gherkin/json_parser_spec.rb +67 -0
- data/spec/gherkin/lexer/i18n_lexer_spec.rb +43 -0
- data/spec/gherkin/output_stream_string_io.rb +24 -0
- data/spec/gherkin/parser/parser_spec.rb +16 -0
- data/spec/gherkin/rb_lexer_spec.rb +19 -0
- data/spec/gherkin/sexp_recorder.rb +56 -0
- data/spec/gherkin/shared/lexer_group.rb +592 -0
- data/spec/gherkin/shared/py_string_group.rb +153 -0
- data/spec/gherkin/shared/row_group.rb +120 -0
- data/spec/gherkin/shared/tags_group.rb +54 -0
- data/spec/gherkin/tag_expression_spec.rb +137 -0
- data/spec/spec_helper.rb +68 -0
- data/tasks/bench.rake +184 -0
- data/tasks/bench/feature_builder.rb +49 -0
- data/tasks/bench/generated/.gitignore +1 -0
- data/tasks/bench/null_listener.rb +4 -0
- data/tasks/compile.rake +102 -0
- data/tasks/cucumber.rake +18 -0
- data/tasks/gems.rake +42 -0
- data/tasks/ikvm.rake +54 -0
- data/tasks/ragel_task.rb +70 -0
- data/tasks/rdoc.rake +9 -0
- data/tasks/release.rake +30 -0
- data/tasks/rspec.rake +8 -0
- metadata +447 -0
@@ -0,0 +1,592 @@
|
|
1
|
+
#encoding: utf-8
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
module Gherkin
|
5
|
+
module Lexer
|
6
|
+
shared_examples_for "a Gherkin lexer" do
|
7
|
+
def scan(gherkin)
|
8
|
+
@lexer.scan(gherkin)
|
9
|
+
end
|
10
|
+
|
11
|
+
describe "Comments" do
|
12
|
+
it "should parse a one line comment" do
|
13
|
+
scan("# My comment\n")
|
14
|
+
@listener.to_sexp.should == [
|
15
|
+
[:comment, "# My comment", 1],
|
16
|
+
[:eof]
|
17
|
+
]
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should parse a multiline comment" do
|
21
|
+
scan("# Hello\n\n# World\n")
|
22
|
+
@listener.to_sexp.should == [
|
23
|
+
[:comment, "# Hello", 1],
|
24
|
+
[:comment, "# World", 3],
|
25
|
+
[:eof]
|
26
|
+
]
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should not consume comments as part of a multiline name" do
|
30
|
+
scan("Scenario: test\n#hello\n Scenario: another")
|
31
|
+
@listener.to_sexp.should == [
|
32
|
+
[:scenario, "Scenario", "test", "", 1],
|
33
|
+
[:comment, "#hello", 2],
|
34
|
+
[:scenario, "Scenario", "another", "", 3],
|
35
|
+
[:eof]
|
36
|
+
]
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should not consume comments as part of a multiline example name" do
|
40
|
+
scan("Examples: thing\n# ho hum\n| 1 | 2 |\n| 3 | 4 |\n")
|
41
|
+
@listener.to_sexp.should == [
|
42
|
+
[:examples, "Examples", "thing", "", 1],
|
43
|
+
[:comment, "# ho hum", 2],
|
44
|
+
[:row, ["1","2"], 3],
|
45
|
+
[:row, ["3","4"], 4],
|
46
|
+
[:eof]
|
47
|
+
]
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should allow empty comment lines" do
|
51
|
+
scan("#\n # A comment\n #\n")
|
52
|
+
@listener.to_sexp.should == [
|
53
|
+
[:comment, "#", 1],
|
54
|
+
[:comment, "# A comment", 2],
|
55
|
+
[:comment, "#", 3],
|
56
|
+
[:eof]
|
57
|
+
]
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should not allow comments within the Feature description" do
|
61
|
+
lambda {
|
62
|
+
scan("Feature: something\nAs a something\n# Comment\nI want something")
|
63
|
+
}.should raise_error(/Lexing error on line 4/)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
describe "Tags" do
|
68
|
+
it "should not take the tags as part of a multiline name feature element" do
|
69
|
+
scan("Feature: hi\n Scenario: test\n\n@hello\n Scenario: another")
|
70
|
+
@listener.to_sexp.should == [
|
71
|
+
[:feature, "Feature", "hi", "", 1],
|
72
|
+
[:scenario, "Scenario", "test", "", 2],
|
73
|
+
[:tag, "@hello", 4],
|
74
|
+
[:scenario, "Scenario", "another", "", 5],
|
75
|
+
[:eof]
|
76
|
+
]
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
describe "Background" do
|
81
|
+
it "should allow an empty background name and description" do
|
82
|
+
scan("Background:\nGiven I am a step\n")
|
83
|
+
@listener.to_sexp.should == [
|
84
|
+
[:background, "Background", "", "", 1],
|
85
|
+
[:step, "Given ", "I am a step", 2],
|
86
|
+
[:eof]
|
87
|
+
]
|
88
|
+
end
|
89
|
+
|
90
|
+
it "should allow an empty background description" do
|
91
|
+
scan("Background: Yeah\nGiven I am a step\n")
|
92
|
+
@listener.to_sexp.should == [
|
93
|
+
[:background, "Background", "Yeah", "", 1],
|
94
|
+
[:step, "Given ", "I am a step", 2],
|
95
|
+
[:eof]
|
96
|
+
]
|
97
|
+
end
|
98
|
+
|
99
|
+
it "should allow multiline names ending at eof" do
|
100
|
+
scan("Background: I have several\n Lines to look at\n None starting with Given")
|
101
|
+
@listener.to_sexp.should == [
|
102
|
+
[:background, "Background", "I have several", "Lines to look at\nNone starting with Given", 1],
|
103
|
+
[:eof]
|
104
|
+
]
|
105
|
+
end
|
106
|
+
|
107
|
+
it "should allow multiline names" do
|
108
|
+
scan(%{Feature: Hi
|
109
|
+
Background: It is my ambition to say
|
110
|
+
in ten sentences
|
111
|
+
what others say
|
112
|
+
in a whole book.
|
113
|
+
Given I am a step})
|
114
|
+
@listener.to_sexp.should == [
|
115
|
+
[:feature, "Feature", "Hi", "", 1],
|
116
|
+
[:background, "Background", "It is my ambition to say", "in ten sentences\nwhat others say\nin a whole book.",2],
|
117
|
+
[:step, "Given ", "I am a step", 6],
|
118
|
+
[:eof]
|
119
|
+
]
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
describe "Scenarios" do
|
124
|
+
it "should be parsed" do
|
125
|
+
scan("Scenario: Hello\n")
|
126
|
+
@listener.to_sexp.should == [
|
127
|
+
[:scenario, "Scenario", "Hello", "", 1],
|
128
|
+
[:eof]
|
129
|
+
]
|
130
|
+
end
|
131
|
+
|
132
|
+
it "should allow whitespace lines after the Scenario line" do
|
133
|
+
scan(%{Scenario: bar
|
134
|
+
|
135
|
+
Given baz
|
136
|
+
})
|
137
|
+
@listener.to_sexp.should == [
|
138
|
+
[:scenario, "Scenario", "bar", "", 1],
|
139
|
+
[:step, "Given ", "baz", 3],
|
140
|
+
[:eof]
|
141
|
+
]
|
142
|
+
end
|
143
|
+
|
144
|
+
it "should allow multiline names" do
|
145
|
+
scan(%{Scenario: It is my ambition to say
|
146
|
+
in ten sentences
|
147
|
+
what others say
|
148
|
+
in a whole book.
|
149
|
+
Given I am a step
|
150
|
+
})
|
151
|
+
@listener.to_sexp.should == [
|
152
|
+
[:scenario, "Scenario", "It is my ambition to say", "in ten sentences\nwhat others say\nin a whole book.", 1],
|
153
|
+
[:step, "Given ", "I am a step", 5],
|
154
|
+
[:eof]
|
155
|
+
]
|
156
|
+
end
|
157
|
+
|
158
|
+
it "should allow multiline names ending at eof" do
|
159
|
+
scan("Scenario: I have several\n Lines to look at\n None starting with Given")
|
160
|
+
@listener.to_sexp.should == [
|
161
|
+
[:scenario, "Scenario", "I have several", "Lines to look at\nNone starting with Given", 1],
|
162
|
+
[:eof]
|
163
|
+
]
|
164
|
+
end
|
165
|
+
|
166
|
+
it "should ignore gherkin keywords embedded in other words" do
|
167
|
+
scan(%{Scenario: I have a Button
|
168
|
+
Buttons are great
|
169
|
+
Given I have some
|
170
|
+
But I might not because I am a Charles Dickens character
|
171
|
+
})
|
172
|
+
@listener.to_sexp.should == [
|
173
|
+
[:scenario, "Scenario", "I have a Button", "Buttons are great", 1],
|
174
|
+
[:step, "Given ", "I have some", 3],
|
175
|
+
[:step, "But ", "I might not because I am a Charles Dickens character", 4],
|
176
|
+
[:eof]
|
177
|
+
]
|
178
|
+
end
|
179
|
+
|
180
|
+
it "should allow step keywords in Scenario names" do
|
181
|
+
scan(%{Scenario: When I have when in scenario
|
182
|
+
I should be fine
|
183
|
+
Given I am a step
|
184
|
+
})
|
185
|
+
@listener.to_sexp.should == [
|
186
|
+
[:scenario, "Scenario", "When I have when in scenario", "I should be fine", 1],
|
187
|
+
[:step, "Given ", "I am a step", 3],
|
188
|
+
[:eof]
|
189
|
+
]
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
describe "Scenario Outlines" do
|
194
|
+
it "should be parsed" do
|
195
|
+
scan(%{Scenario Outline: Hello
|
196
|
+
With a description
|
197
|
+
Given a <what> cucumber
|
198
|
+
Examples: With a name
|
199
|
+
and a description
|
200
|
+
|what|
|
201
|
+
|green|
|
202
|
+
})
|
203
|
+
@listener.to_sexp.should == [
|
204
|
+
[:scenario_outline, "Scenario Outline", "Hello", "With a description", 1],
|
205
|
+
[:step, "Given ", "a <what> cucumber", 3],
|
206
|
+
[:examples, "Examples", "With a name", "and a description", 4],
|
207
|
+
[:row, ["what"], 6],
|
208
|
+
[:row, ["green"], 7],
|
209
|
+
[:eof]
|
210
|
+
]
|
211
|
+
end
|
212
|
+
|
213
|
+
|
214
|
+
it "should parse with no steps or examples" do
|
215
|
+
scan(%{Scenario Outline: Hello
|
216
|
+
|
217
|
+
Scenario: My Scenario
|
218
|
+
})
|
219
|
+
@listener.to_sexp.should == [
|
220
|
+
[:scenario_outline, "Scenario Outline", "Hello", "", 1],
|
221
|
+
[:scenario, "Scenario", "My Scenario", "", 3],
|
222
|
+
[:eof]
|
223
|
+
]
|
224
|
+
end
|
225
|
+
|
226
|
+
it "should allow multiline description" do
|
227
|
+
scan(%{Scenario Outline: It is my ambition to say
|
228
|
+
in ten sentences
|
229
|
+
what others say
|
230
|
+
in a whole book.
|
231
|
+
Given I am a step
|
232
|
+
|
233
|
+
})
|
234
|
+
@listener.to_sexp.should == [
|
235
|
+
[:scenario_outline, "Scenario Outline", "It is my ambition to say", "in ten sentences\nwhat others say\nin a whole book.", 1],
|
236
|
+
[:step, "Given ", "I am a step", 5],
|
237
|
+
[:eof]
|
238
|
+
]
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
describe "Examples" do
|
243
|
+
it "should be parsed" do
|
244
|
+
scan(%{Examples:
|
245
|
+
|x|y|
|
246
|
+
|5|6|
|
247
|
+
})
|
248
|
+
@listener.to_sexp.should == [
|
249
|
+
[:examples, "Examples", "", "", 1],
|
250
|
+
[:row, ["x","y"], 2],
|
251
|
+
[:row, ["5","6"], 3],
|
252
|
+
[:eof]
|
253
|
+
]
|
254
|
+
end
|
255
|
+
|
256
|
+
it "should parse multiline example names" do
|
257
|
+
scan(%{Examples: I'm a multiline name
|
258
|
+
and I'm ok
|
259
|
+
f'real
|
260
|
+
|x|
|
261
|
+
|5|
|
262
|
+
})
|
263
|
+
@listener.to_sexp.should == [
|
264
|
+
[:examples, "Examples", "I'm a multiline name", "and I'm ok\nf'real", 1],
|
265
|
+
[:row, ["x"], 4],
|
266
|
+
[:row, ["5"], 5],
|
267
|
+
[:eof]
|
268
|
+
]
|
269
|
+
end
|
270
|
+
end
|
271
|
+
|
272
|
+
describe "Steps" do
|
273
|
+
it "should parse steps with inline table" do
|
274
|
+
scan(%{Given I have a table
|
275
|
+
|a|b|
|
276
|
+
})
|
277
|
+
@listener.to_sexp.should == [
|
278
|
+
[:step, "Given ", "I have a table", 1],
|
279
|
+
[:row, ['a','b'], 2],
|
280
|
+
[:eof]
|
281
|
+
]
|
282
|
+
end
|
283
|
+
|
284
|
+
it "should parse steps with inline py_string" do
|
285
|
+
scan("Given I have a string\n\"\"\"\nhello\nworld\n\"\"\"")
|
286
|
+
@listener.to_sexp.should == [
|
287
|
+
[:step, "Given ", "I have a string", 1],
|
288
|
+
[:py_string, "hello\nworld", 2],
|
289
|
+
[:eof]
|
290
|
+
]
|
291
|
+
end
|
292
|
+
end
|
293
|
+
|
294
|
+
describe "A single feature, single scenario, single step" do
|
295
|
+
it "should find the feature, scenario, and step" do
|
296
|
+
scan("Feature: Feature Text\n Scenario: Reading a Scenario\n Given there is a step\n")
|
297
|
+
@listener.to_sexp.should == [
|
298
|
+
[:feature, "Feature", "Feature Text", "", 1],
|
299
|
+
[:scenario, "Scenario", "Reading a Scenario", "", 2],
|
300
|
+
[:step, "Given ", "there is a step", 3],
|
301
|
+
[:eof]
|
302
|
+
]
|
303
|
+
end
|
304
|
+
end
|
305
|
+
|
306
|
+
describe "A feature ending in whitespace" do
|
307
|
+
it "should not raise an error when whitespace follows the Feature, Scenario, and Steps" do
|
308
|
+
scan("Feature: Feature Text\n Scenario: Reading a Scenario\n Given there is a step\n ")
|
309
|
+
@listener.to_sexp.should == [
|
310
|
+
[:feature, "Feature", "Feature Text", "", 1],
|
311
|
+
[:scenario, "Scenario", "Reading a Scenario", "", 2],
|
312
|
+
[:step, "Given ", "there is a step", 3],
|
313
|
+
[:eof]
|
314
|
+
]
|
315
|
+
end
|
316
|
+
end
|
317
|
+
|
318
|
+
describe "A single feature, single scenario, three steps" do
|
319
|
+
|
320
|
+
it "should find the feature, scenario, and three steps" do
|
321
|
+
scan("Feature: Feature Text\n Scenario: Reading a Scenario\n Given there is a step\n And another step\n And a third step\n")
|
322
|
+
@listener.to_sexp.should == [
|
323
|
+
[:feature, "Feature", "Feature Text", "", 1],
|
324
|
+
[:scenario, "Scenario", "Reading a Scenario", "", 2],
|
325
|
+
[:step, "Given ", "there is a step", 3],
|
326
|
+
[:step, "And ", "another step", 4],
|
327
|
+
[:step, "And ", "a third step", 5],
|
328
|
+
[:eof]
|
329
|
+
]
|
330
|
+
end
|
331
|
+
end
|
332
|
+
|
333
|
+
describe "A single feature with no scenario" do
|
334
|
+
it "should find the feature" do
|
335
|
+
scan("Feature: Feature Text\n")
|
336
|
+
@listener.to_sexp.should == [
|
337
|
+
[:feature, "Feature", "Feature Text", "", 1],
|
338
|
+
[:eof]
|
339
|
+
]
|
340
|
+
end
|
341
|
+
|
342
|
+
it "should parse a one line feature with no newline" do
|
343
|
+
scan("Feature: hi")
|
344
|
+
@listener.to_sexp.should == [
|
345
|
+
[:feature, "Feature", "hi", "", 1],
|
346
|
+
[:eof]
|
347
|
+
]
|
348
|
+
end
|
349
|
+
end
|
350
|
+
|
351
|
+
describe "A multi-line feature with no scenario" do
|
352
|
+
it "should find the feature" do
|
353
|
+
scan("Feature: Feature Text\n And some more text")
|
354
|
+
@listener.to_sexp.should == [
|
355
|
+
[:feature, "Feature", "Feature Text", "And some more text", 1],
|
356
|
+
[:eof]
|
357
|
+
]
|
358
|
+
end
|
359
|
+
end
|
360
|
+
|
361
|
+
describe "A feature with a scenario but no steps" do
|
362
|
+
it "should find the feature and scenario" do
|
363
|
+
scan("Feature: Feature Text\nScenario: Reading a Scenario\n")
|
364
|
+
@listener.to_sexp.should == [
|
365
|
+
[:feature, "Feature", "Feature Text", "", 1],
|
366
|
+
[:scenario, "Scenario", "Reading a Scenario", "", 2],
|
367
|
+
[:eof]
|
368
|
+
]
|
369
|
+
end
|
370
|
+
end
|
371
|
+
|
372
|
+
describe "A feature with two scenarios" do
|
373
|
+
it "should find the feature and two scenarios" do
|
374
|
+
scan("Feature: Feature Text\nScenario: Reading a Scenario\n Given a step\n\nScenario: A second scenario\n Given another step\n")
|
375
|
+
@listener.to_sexp.should == [
|
376
|
+
[:feature, "Feature", "Feature Text", "", 1],
|
377
|
+
[:scenario, "Scenario", "Reading a Scenario", "", 2],
|
378
|
+
[:step, "Given ", "a step", 3],
|
379
|
+
[:scenario, "Scenario", "A second scenario", "", 5],
|
380
|
+
[:step, "Given ", "another step", 6],
|
381
|
+
[:eof]
|
382
|
+
]
|
383
|
+
end
|
384
|
+
|
385
|
+
it "should find the feature and two scenarios without indentation" do
|
386
|
+
scan("Feature: Feature Text\nScenario: Reading a Scenario\nGiven a step\nScenario: A second scenario\nGiven another step\n")
|
387
|
+
@listener.to_sexp.should == [
|
388
|
+
[:feature, "Feature", "Feature Text", "", 1],
|
389
|
+
[:scenario, "Scenario", "Reading a Scenario", "", 2],
|
390
|
+
[:step, "Given ", "a step", 3],
|
391
|
+
[:scenario, "Scenario", "A second scenario", "", 4],
|
392
|
+
[:step, "Given ", "another step", 5],
|
393
|
+
[:eof]
|
394
|
+
]
|
395
|
+
end
|
396
|
+
end
|
397
|
+
|
398
|
+
describe "A simple feature with comments" do
|
399
|
+
it "should find the feature, scenarios, steps, and comments in the proper order" do
|
400
|
+
scan_file("simple_with_comments.feature")
|
401
|
+
@listener.to_sexp.should == [
|
402
|
+
[:comment, "# Here is a comment", 1],
|
403
|
+
[:feature, "Feature", "Feature Text", "", 2],
|
404
|
+
[:comment, "# Here is another # comment", 3],
|
405
|
+
[:scenario, "Scenario", "Reading a Scenario", "", 4],
|
406
|
+
[:comment, "# Here is a third comment", 5],
|
407
|
+
[:step, "Given ", "there is a step", 6],
|
408
|
+
[:comment, "# Here is a fourth comment", 7],
|
409
|
+
[:eof]
|
410
|
+
]
|
411
|
+
end
|
412
|
+
|
413
|
+
it "should support comments in tables" do
|
414
|
+
scan_file("comments_in_table.feature")
|
415
|
+
@listener.to_sexp.should == [
|
416
|
+
[:feature, "Feature", "x", "", 1],
|
417
|
+
[:scenario_outline, "Scenario Outline", "x", "", 3],
|
418
|
+
[:step, "Then ", "x is <state>", 4],
|
419
|
+
[:examples, "Examples", "", "", 6],
|
420
|
+
[:row, ["state"], 7],
|
421
|
+
[:comment, "# comment", 8],
|
422
|
+
[:row, ["1"], 9],
|
423
|
+
[:eof]
|
424
|
+
]
|
425
|
+
end
|
426
|
+
end
|
427
|
+
|
428
|
+
describe "A feature with tags everywhere" do
|
429
|
+
it "should find the feature, scenario, step, and tags in the proper order" do
|
430
|
+
scan_file("simple_with_tags.feature")
|
431
|
+
@listener.to_sexp.should == [
|
432
|
+
[:comment, "# FC", 1],
|
433
|
+
[:tag, "@ft",2],
|
434
|
+
[:feature, "Feature", "hi", "", 3],
|
435
|
+
[:tag, "@st1", 5],
|
436
|
+
[:tag, "@st2", 5],
|
437
|
+
[:scenario, "Scenario", "First", "", 6],
|
438
|
+
[:step, "Given ", "Pepper", 7],
|
439
|
+
[:tag, "@st3", 9],
|
440
|
+
[:tag, "@st4", 10],
|
441
|
+
[:tag, "@ST5", 10],
|
442
|
+
[:tag, "@#^%&ST6**!", 10],
|
443
|
+
[:scenario, "Scenario", "Second", "", 11],
|
444
|
+
[:eof]
|
445
|
+
]
|
446
|
+
end
|
447
|
+
end
|
448
|
+
|
449
|
+
describe "Comment or tag between Feature elements where previous narrative starts with same letter as a keyword" do
|
450
|
+
it "should lex this feature properly" do
|
451
|
+
scan_file("1.feature")
|
452
|
+
@listener.to_sexp.should == [
|
453
|
+
[:feature, "Feature", "Logging in", "So that I can be myself", 1],
|
454
|
+
[:comment, "# Comment", 3],
|
455
|
+
[:scenario, "Scenario", "Anonymous user can get a login form.", "Scenery here", 4],
|
456
|
+
[:tag, "@tag", 7],
|
457
|
+
[:scenario, "Scenario", "Another one", "", 8],
|
458
|
+
[:eof]
|
459
|
+
]
|
460
|
+
end
|
461
|
+
end
|
462
|
+
|
463
|
+
describe "A complex feature with tags, comments, multiple scenarios, and multiple steps and tables" do
|
464
|
+
it "should find things in the right order" do
|
465
|
+
scan_file("complex.feature")
|
466
|
+
@listener.to_sexp.should == [
|
467
|
+
[:comment, "#Comment on line 1", 1],
|
468
|
+
[:comment, "#Comment on line 2", 2],
|
469
|
+
[:tag, "@tag1", 3],
|
470
|
+
[:tag, "@tag2", 3],
|
471
|
+
[:feature, "Feature", "Feature Text", "In order to test multiline forms\nAs a ragel writer\nI need to check for complex combinations", 4],
|
472
|
+
[:comment, "#Comment on line 9", 9],
|
473
|
+
[:comment, "#Comment on line 11", 11],
|
474
|
+
[:background, "Background", "", "", 13],
|
475
|
+
[:step, "Given ", "this is a background step", 14],
|
476
|
+
[:step, "And ", "this is another one", 15],
|
477
|
+
[:tag, "@tag3", 17],
|
478
|
+
[:tag, "@tag4", 17],
|
479
|
+
[:scenario, "Scenario", "Reading a Scenario", "", 18],
|
480
|
+
[:step, "Given ", "there is a step", 19],
|
481
|
+
[:step, "But ", "not another step", 20],
|
482
|
+
[:tag, "@tag3", 22],
|
483
|
+
[:scenario, "Scenario", "Reading a second scenario", "With two lines of text", 23],
|
484
|
+
[:comment, "#Comment on line 24", 25],
|
485
|
+
[:step, "Given ", "a third step with a table", 26],
|
486
|
+
[:row, %w{a b}, 27],
|
487
|
+
[:row, %w{c d}, 28],
|
488
|
+
[:row, %w{e f}, 29],
|
489
|
+
[:step, "And ", "I am still testing things", 30],
|
490
|
+
[:row, %w{g h}, 31],
|
491
|
+
[:row, %w{e r}, 32],
|
492
|
+
[:row, %w{k i}, 33],
|
493
|
+
[:row, ['n', ''], 34],
|
494
|
+
[:step, "And ", "I am done testing these tables", 35],
|
495
|
+
[:comment, "#Comment on line 29", 36],
|
496
|
+
[:step, "Then ", "I am happy", 37],
|
497
|
+
[:scenario, "Scenario", "Hammerzeit", "", 39],
|
498
|
+
[:step, "Given ", "All work and no play", 40],
|
499
|
+
[:py_string, "Makes Homer something something\nAnd something else", 41 ],
|
500
|
+
[:step, "Then ", "crazy", 45],
|
501
|
+
[:eof]
|
502
|
+
]
|
503
|
+
end
|
504
|
+
end
|
505
|
+
|
506
|
+
describe "Windows stuff" do
|
507
|
+
it "should find things in the right order for CRLF features" do
|
508
|
+
scan_file("dos_line_endings.feature")
|
509
|
+
@listener.to_sexp.should == [
|
510
|
+
[:comment, "#Comment on line 1", 1],
|
511
|
+
[:comment, "#Comment on line 2", 2],
|
512
|
+
[:tag, "@tag1", 3],
|
513
|
+
[:tag, "@tag2", 3],
|
514
|
+
[:feature, "Feature", "Feature Text", "In order to test multiline forms\r\nAs a ragel writer\r\nI need to check for complex combinations", 4],
|
515
|
+
[:comment, "#Comment on line 9", 9],
|
516
|
+
[:comment, "#Comment on line 11", 11],
|
517
|
+
[:background, "Background", "", "", 13],
|
518
|
+
[:step, "Given ", "this is a background step", 14],
|
519
|
+
[:step, "And ", "this is another one", 15],
|
520
|
+
[:tag, "@tag3", 17],
|
521
|
+
[:tag, "@tag4", 17],
|
522
|
+
[:scenario, "Scenario", "Reading a Scenario", "", 18],
|
523
|
+
[:step, "Given ", "there is a step", 19],
|
524
|
+
[:step, "But ", "not another step", 20],
|
525
|
+
[:tag, "@tag3", 22],
|
526
|
+
[:scenario, "Scenario", "Reading a second scenario", "With two lines of text", 23],
|
527
|
+
[:comment, "#Comment on line 24", 25],
|
528
|
+
[:step, "Given ", "a third step with a table", 26],
|
529
|
+
[:row, %w{a b}, 27],
|
530
|
+
[:row, %w{c d}, 28],
|
531
|
+
[:row, %w{e f}, 29],
|
532
|
+
[:step, "And ", "I am still testing things", 30],
|
533
|
+
[:row, %w{g h}, 31],
|
534
|
+
[:row, %w{e r}, 32],
|
535
|
+
[:row, %w{k i}, 33],
|
536
|
+
[:row, ['n', ''], 34],
|
537
|
+
[:step, "And ", "I am done testing these tables", 35],
|
538
|
+
[:comment, "#Comment on line 29", 36],
|
539
|
+
[:step, "Then ", "I am happy", 37],
|
540
|
+
[:scenario, "Scenario", "Hammerzeit", "", 39],
|
541
|
+
[:step, "Given ", "All work and no play", 40],
|
542
|
+
[:py_string, "Makes Homer something something\r\nAnd something else", 41],
|
543
|
+
[:step, "Then ", "crazy", 45],
|
544
|
+
[:eof]
|
545
|
+
]
|
546
|
+
end
|
547
|
+
|
548
|
+
it "should cope with the retarded BOM that many Windows editors insert at the beginning of a file" do
|
549
|
+
scan_file("with_bom.feature")
|
550
|
+
@listener.to_sexp.should == [
|
551
|
+
[:feature, "Feature", "Feature Text", "", 1],
|
552
|
+
[:scenario, "Scenario", "Reading a Scenario", "", 2],
|
553
|
+
[:step, "Given ", "there is a step", 3],
|
554
|
+
[:eof]
|
555
|
+
]
|
556
|
+
end
|
557
|
+
end
|
558
|
+
|
559
|
+
describe "errors" do
|
560
|
+
it "should raise a Lexing error if an unparseable token is found" do
|
561
|
+
["Some text\nFeature: Hi",
|
562
|
+
"Feature: Hi\nBackground:\nGiven something\nScenario A scenario",
|
563
|
+
"Scenario: My scenario\nGiven foo\nAand bar\nScenario: another one\nGiven blah"].each do |text|
|
564
|
+
lambda { scan(text) }.should raise_error(/Lexing error on line/)
|
565
|
+
end
|
566
|
+
end
|
567
|
+
|
568
|
+
it "should include the line number and context of the error" do
|
569
|
+
lambda {
|
570
|
+
scan("Feature: hello\nScenario: My scenario\nGiven foo\nAand blah\nHmmm wrong\nThen something something")
|
571
|
+
}.should raise_error(/Lexing error on line 4/)
|
572
|
+
end
|
573
|
+
|
574
|
+
it "Feature keyword should terminate narratives for multiline capable tokens" do
|
575
|
+
scan("Feature:\nBackground:\nFeature:\nScenario Outline:\nFeature:\nScenario:\nFeature:\nExamples:\nFeature:\n")
|
576
|
+
@listener.to_sexp.should == [
|
577
|
+
[:feature, "Feature", "", "", 1],
|
578
|
+
[:background, "Background", "", "", 2],
|
579
|
+
[:feature, "Feature", "", "", 3],
|
580
|
+
[:scenario_outline, "Scenario Outline", "", "", 4],
|
581
|
+
[:feature, "Feature", "", "", 5],
|
582
|
+
[:scenario, "Scenario", "", "", 6],
|
583
|
+
[:feature, "Feature", "", "", 7],
|
584
|
+
[:examples, "Examples", "","", 8],
|
585
|
+
[:feature, "Feature", "", "", 9],
|
586
|
+
[:eof]
|
587
|
+
]
|
588
|
+
end
|
589
|
+
end
|
590
|
+
end
|
591
|
+
end
|
592
|
+
end
|