gherkin-ruby 0.0.2 → 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.
- data/.gitignore +1 -0
- data/Rakefile +19 -1
- data/Readme.md +2 -2
- data/gherkin-ruby.gemspec +2 -1
- data/lib/gherkin/ast.rb +18 -17
- data/lib/gherkin/parser/gherkin.rex +44 -0
- data/lib/gherkin/parser/gherkin.y +100 -0
- data/lib/gherkin/parser/lexer.rb +120 -0
- data/lib/gherkin/parser/parser.rb +359 -0
- data/lib/gherkin/parser.rb +1 -43
- data/lib/gherkin/version.rb +1 -1
- data/lib/gherkin.rb +2 -7
- data/test/gherkin/ast_test.rb +19 -32
- data/test/gherkin/parser/lexer_test.rb +43 -0
- data/test/gherkin/parser/parser_test.rb +96 -0
- data/test/gherkin/parser_test.rb +52 -148
- metadata +85 -40
- data/lib/gherkin/transform.rb +0 -50
- data/test/gherkin/transform_test.rb +0 -74
@@ -0,0 +1,359 @@
|
|
1
|
+
#
|
2
|
+
# DO NOT MODIFY!!!!
|
3
|
+
# This file is automatically generated by Racc 1.4.7
|
4
|
+
# from Racc grammer file "".
|
5
|
+
#
|
6
|
+
|
7
|
+
require 'racc/parser.rb'
|
8
|
+
|
9
|
+
require_relative "lexer"
|
10
|
+
require_relative "../ast"
|
11
|
+
|
12
|
+
module Gherkin
|
13
|
+
class Parser < Racc::Parser
|
14
|
+
|
15
|
+
module_eval(<<'...end gherkin.y/module_eval...', 'gherkin.y', 97)
|
16
|
+
|
17
|
+
def parse(input)
|
18
|
+
scan_str(input)
|
19
|
+
end
|
20
|
+
...end gherkin.y/module_eval...
|
21
|
+
##### State transition tables begin ###
|
22
|
+
|
23
|
+
racc_action_table = [
|
24
|
+
14, 3, 14, 15, 14, 26, 14, 11, 13, 3,
|
25
|
+
38, 31, 32, 33, 34, 35, 14, 14, 11, 13,
|
26
|
+
41, 31, 32, 33, 34, 35, 31, 32, 33, 34,
|
27
|
+
35, 31, 32, 33, 34, 35, 31, 32, 33, 34,
|
28
|
+
35, 3, 3, 7, 11, 13, 31, 32, 33, 34,
|
29
|
+
35, 3, 3, 3, 18, 3, 44, 14, 45, 20,
|
30
|
+
21, 48, 3, 14, 3, 14, 27, 3, 14, 14,
|
31
|
+
8, 24 ]
|
32
|
+
|
33
|
+
racc_action_check = [
|
34
|
+
19, 12, 4, 4, 22, 12, 51, 22, 22, 38,
|
35
|
+
19, 51, 51, 51, 51, 51, 40, 25, 2, 2,
|
36
|
+
25, 40, 40, 40, 40, 40, 47, 47, 47, 47,
|
37
|
+
47, 52, 52, 52, 52, 52, 17, 17, 17, 17,
|
38
|
+
17, 9, 0, 0, 9, 9, 28, 28, 28, 28,
|
39
|
+
28, 6, 24, 18, 5, 29, 30, 36, 37, 7,
|
40
|
+
8, 41, 42, 43, 45, 46, 15, 48, 49, 50,
|
41
|
+
1, 11 ]
|
42
|
+
|
43
|
+
racc_action_pointer = [
|
44
|
+
40, 70, 13, nil, 0, 50, 49, 47, 60, 39,
|
45
|
+
nil, 59, -1, nil, nil, 54, nil, 29, 51, -2,
|
46
|
+
nil, nil, 2, nil, 50, 15, nil, nil, 39, 53,
|
47
|
+
44, nil, nil, nil, nil, nil, 55, 46, 7, nil,
|
48
|
+
14, 49, 60, 61, nil, 62, 63, 19, 65, 66,
|
49
|
+
67, 4, 24 ]
|
50
|
+
|
51
|
+
racc_action_default = [
|
52
|
+
-31, -31, -1, -3, -31, -5, -7, -31, -31, -2,
|
53
|
+
-24, -31, -31, -29, -4, -31, -6, -31, -31, -8,
|
54
|
+
-10, 53, -31, -25, -31, -31, -30, -11, -14, -31,
|
55
|
+
-31, -19, -20, -21, -22, -23, -15, -9, -31, -26,
|
56
|
+
-31, -31, -31, -16, -18, -31, -12, -27, -31, -17,
|
57
|
+
-13, -31, -28 ]
|
58
|
+
|
59
|
+
racc_goto_table = [
|
60
|
+
4, 10, 28, 42, 6, 16, 19, 5, 23, 22,
|
61
|
+
37, 17, 25, 9, 2, 1, nil, nil, 36, nil,
|
62
|
+
nil, 39, 42, nil, 40, 47, nil, 42, nil, 43,
|
63
|
+
nil, nil, nil, nil, nil, nil, 52, nil, 46, nil,
|
64
|
+
nil, nil, 49, nil, nil, 50, nil, nil, 51 ]
|
65
|
+
|
66
|
+
racc_goto_check = [
|
67
|
+
4, 13, 10, 11, 7, 6, 4, 5, 13, 4,
|
68
|
+
8, 9, 4, 3, 2, 1, nil, nil, 4, nil,
|
69
|
+
nil, 13, 11, nil, 4, 10, nil, 11, nil, 4,
|
70
|
+
nil, nil, nil, nil, nil, nil, 10, nil, 4, nil,
|
71
|
+
nil, nil, 4, nil, nil, 4, nil, nil, 4 ]
|
72
|
+
|
73
|
+
racc_goto_pointer = [
|
74
|
+
nil, 15, 14, 11, 0, 7, 0, 4, -9, 6,
|
75
|
+
-15, -25, nil, -1, nil ]
|
76
|
+
|
77
|
+
racc_goto_default = [
|
78
|
+
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
|
79
|
+
nil, 29, 30, nil, 12 ]
|
80
|
+
|
81
|
+
racc_reduce_table = [
|
82
|
+
0, 0, :racc_error,
|
83
|
+
1, 14, :_reduce_1,
|
84
|
+
2, 14, :_reduce_2,
|
85
|
+
1, 17, :_reduce_none,
|
86
|
+
2, 17, :_reduce_none,
|
87
|
+
1, 15, :_reduce_5,
|
88
|
+
2, 15, :_reduce_6,
|
89
|
+
1, 18, :_reduce_7,
|
90
|
+
2, 18, :_reduce_8,
|
91
|
+
3, 18, :_reduce_9,
|
92
|
+
2, 20, :_reduce_10,
|
93
|
+
3, 20, :_reduce_11,
|
94
|
+
2, 21, :_reduce_none,
|
95
|
+
3, 21, :_reduce_none,
|
96
|
+
2, 19, :_reduce_14,
|
97
|
+
2, 22, :_reduce_15,
|
98
|
+
2, 23, :_reduce_16,
|
99
|
+
3, 23, :_reduce_17,
|
100
|
+
2, 24, :_reduce_18,
|
101
|
+
1, 25, :_reduce_none,
|
102
|
+
1, 25, :_reduce_none,
|
103
|
+
1, 25, :_reduce_none,
|
104
|
+
1, 25, :_reduce_none,
|
105
|
+
1, 25, :_reduce_none,
|
106
|
+
1, 16, :_reduce_24,
|
107
|
+
2, 16, :_reduce_25,
|
108
|
+
3, 16, :_reduce_26,
|
109
|
+
4, 26, :_reduce_27,
|
110
|
+
6, 26, :_reduce_28,
|
111
|
+
1, 27, :_reduce_29,
|
112
|
+
2, 27, :_reduce_30 ]
|
113
|
+
|
114
|
+
racc_reduce_n = 31
|
115
|
+
|
116
|
+
racc_shift_n = 53
|
117
|
+
|
118
|
+
racc_token_table = {
|
119
|
+
false => 0,
|
120
|
+
:error => 1,
|
121
|
+
:NEWLINE => 2,
|
122
|
+
:FEATURE => 3,
|
123
|
+
:BACKGROUND => 4,
|
124
|
+
:SCENARIO => 5,
|
125
|
+
:TAG => 6,
|
126
|
+
:GIVEN => 7,
|
127
|
+
:WHEN => 8,
|
128
|
+
:THEN => 9,
|
129
|
+
:AND => 10,
|
130
|
+
:BUT => 11,
|
131
|
+
:TEXT => 12 }
|
132
|
+
|
133
|
+
racc_nt_base = 13
|
134
|
+
|
135
|
+
racc_use_result_var = true
|
136
|
+
|
137
|
+
Racc_arg = [
|
138
|
+
racc_action_table,
|
139
|
+
racc_action_check,
|
140
|
+
racc_action_default,
|
141
|
+
racc_action_pointer,
|
142
|
+
racc_goto_table,
|
143
|
+
racc_goto_check,
|
144
|
+
racc_goto_default,
|
145
|
+
racc_goto_pointer,
|
146
|
+
racc_nt_base,
|
147
|
+
racc_reduce_table,
|
148
|
+
racc_token_table,
|
149
|
+
racc_shift_n,
|
150
|
+
racc_reduce_n,
|
151
|
+
racc_use_result_var ]
|
152
|
+
|
153
|
+
Racc_token_to_s_table = [
|
154
|
+
"$end",
|
155
|
+
"error",
|
156
|
+
"NEWLINE",
|
157
|
+
"FEATURE",
|
158
|
+
"BACKGROUND",
|
159
|
+
"SCENARIO",
|
160
|
+
"TAG",
|
161
|
+
"GIVEN",
|
162
|
+
"WHEN",
|
163
|
+
"THEN",
|
164
|
+
"AND",
|
165
|
+
"BUT",
|
166
|
+
"TEXT",
|
167
|
+
"$start",
|
168
|
+
"Root",
|
169
|
+
"Feature",
|
170
|
+
"Scenarios",
|
171
|
+
"Newline",
|
172
|
+
"FeatureHeader",
|
173
|
+
"Background",
|
174
|
+
"FeatureName",
|
175
|
+
"Description",
|
176
|
+
"BackgroundHeader",
|
177
|
+
"Steps",
|
178
|
+
"Step",
|
179
|
+
"Keyword",
|
180
|
+
"Scenario",
|
181
|
+
"Tags" ]
|
182
|
+
|
183
|
+
Racc_debug_parser = false
|
184
|
+
|
185
|
+
##### State transition tables end #####
|
186
|
+
|
187
|
+
# reduce 0 omitted
|
188
|
+
|
189
|
+
module_eval(<<'.,.,', 'gherkin.y', 14)
|
190
|
+
def _reduce_1(val, _values, result)
|
191
|
+
result = val[0];
|
192
|
+
result
|
193
|
+
end
|
194
|
+
.,.,
|
195
|
+
|
196
|
+
module_eval(<<'.,.,', 'gherkin.y', 17)
|
197
|
+
def _reduce_2(val, _values, result)
|
198
|
+
result = val[0]; result.scenarios = val[1]
|
199
|
+
result
|
200
|
+
end
|
201
|
+
.,.,
|
202
|
+
|
203
|
+
# reduce 3 omitted
|
204
|
+
|
205
|
+
# reduce 4 omitted
|
206
|
+
|
207
|
+
module_eval(<<'.,.,', 'gherkin.y', 26)
|
208
|
+
def _reduce_5(val, _values, result)
|
209
|
+
result = val[0]
|
210
|
+
result
|
211
|
+
end
|
212
|
+
.,.,
|
213
|
+
|
214
|
+
module_eval(<<'.,.,', 'gherkin.y', 28)
|
215
|
+
def _reduce_6(val, _values, result)
|
216
|
+
result = val[0]; result.background = val[1]
|
217
|
+
result
|
218
|
+
end
|
219
|
+
.,.,
|
220
|
+
|
221
|
+
module_eval(<<'.,.,', 'gherkin.y', 32)
|
222
|
+
def _reduce_7(val, _values, result)
|
223
|
+
result = val[0]
|
224
|
+
result
|
225
|
+
end
|
226
|
+
.,.,
|
227
|
+
|
228
|
+
module_eval(<<'.,.,', 'gherkin.y', 33)
|
229
|
+
def _reduce_8(val, _values, result)
|
230
|
+
result = val[0]
|
231
|
+
result
|
232
|
+
end
|
233
|
+
.,.,
|
234
|
+
|
235
|
+
module_eval(<<'.,.,', 'gherkin.y', 35)
|
236
|
+
def _reduce_9(val, _values, result)
|
237
|
+
result = val[0]
|
238
|
+
result
|
239
|
+
end
|
240
|
+
.,.,
|
241
|
+
|
242
|
+
module_eval(<<'.,.,', 'gherkin.y', 39)
|
243
|
+
def _reduce_10(val, _values, result)
|
244
|
+
result = AST::Feature.new(val[1]); result.pos(filename, lineno)
|
245
|
+
result
|
246
|
+
end
|
247
|
+
.,.,
|
248
|
+
|
249
|
+
module_eval(<<'.,.,', 'gherkin.y', 40)
|
250
|
+
def _reduce_11(val, _values, result)
|
251
|
+
result = AST::Feature.new(val[2]); result.pos(filename, lineno)
|
252
|
+
result
|
253
|
+
end
|
254
|
+
.,.,
|
255
|
+
|
256
|
+
# reduce 12 omitted
|
257
|
+
|
258
|
+
# reduce 13 omitted
|
259
|
+
|
260
|
+
module_eval(<<'.,.,', 'gherkin.y', 50)
|
261
|
+
def _reduce_14(val, _values, result)
|
262
|
+
result = val[0]; result.steps = val[1]
|
263
|
+
result
|
264
|
+
end
|
265
|
+
.,.,
|
266
|
+
|
267
|
+
module_eval(<<'.,.,', 'gherkin.y', 54)
|
268
|
+
def _reduce_15(val, _values, result)
|
269
|
+
result = AST::Background.new; result.pos(filename, lineno)
|
270
|
+
result
|
271
|
+
end
|
272
|
+
.,.,
|
273
|
+
|
274
|
+
module_eval(<<'.,.,', 'gherkin.y', 58)
|
275
|
+
def _reduce_16(val, _values, result)
|
276
|
+
result = [val[0]]
|
277
|
+
result
|
278
|
+
end
|
279
|
+
.,.,
|
280
|
+
|
281
|
+
module_eval(<<'.,.,', 'gherkin.y', 59)
|
282
|
+
def _reduce_17(val, _values, result)
|
283
|
+
result = val[0] << val[1]
|
284
|
+
result
|
285
|
+
end
|
286
|
+
.,.,
|
287
|
+
|
288
|
+
module_eval(<<'.,.,', 'gherkin.y', 63)
|
289
|
+
def _reduce_18(val, _values, result)
|
290
|
+
result = AST::Step.new(val[1], val[0]); result.pos(filename, lineno)
|
291
|
+
result
|
292
|
+
end
|
293
|
+
.,.,
|
294
|
+
|
295
|
+
# reduce 19 omitted
|
296
|
+
|
297
|
+
# reduce 20 omitted
|
298
|
+
|
299
|
+
# reduce 21 omitted
|
300
|
+
|
301
|
+
# reduce 22 omitted
|
302
|
+
|
303
|
+
# reduce 23 omitted
|
304
|
+
|
305
|
+
module_eval(<<'.,.,', 'gherkin.y', 71)
|
306
|
+
def _reduce_24(val, _values, result)
|
307
|
+
result = [val[0]]
|
308
|
+
result
|
309
|
+
end
|
310
|
+
.,.,
|
311
|
+
|
312
|
+
module_eval(<<'.,.,', 'gherkin.y', 72)
|
313
|
+
def _reduce_25(val, _values, result)
|
314
|
+
result = val[0] << val[1]
|
315
|
+
result
|
316
|
+
end
|
317
|
+
.,.,
|
318
|
+
|
319
|
+
module_eval(<<'.,.,', 'gherkin.y', 73)
|
320
|
+
def _reduce_26(val, _values, result)
|
321
|
+
result = val[0] << val[2]
|
322
|
+
result
|
323
|
+
end
|
324
|
+
.,.,
|
325
|
+
|
326
|
+
module_eval(<<'.,.,', 'gherkin.y', 78)
|
327
|
+
def _reduce_27(val, _values, result)
|
328
|
+
result = AST::Scenario.new(val[1], val[3]); result.pos(filename, lineno - 1)
|
329
|
+
result
|
330
|
+
end
|
331
|
+
.,.,
|
332
|
+
|
333
|
+
module_eval(<<'.,.,', 'gherkin.y', 81)
|
334
|
+
def _reduce_28(val, _values, result)
|
335
|
+
result = AST::Scenario.new(val[3], val[5], val[0]); result.pos(filename, lineno - 2)
|
336
|
+
result
|
337
|
+
end
|
338
|
+
.,.,
|
339
|
+
|
340
|
+
module_eval(<<'.,.,', 'gherkin.y', 85)
|
341
|
+
def _reduce_29(val, _values, result)
|
342
|
+
result = [AST::Tag.new(val[0])]
|
343
|
+
result
|
344
|
+
end
|
345
|
+
.,.,
|
346
|
+
|
347
|
+
module_eval(<<'.,.,', 'gherkin.y', 86)
|
348
|
+
def _reduce_30(val, _values, result)
|
349
|
+
result = val[0] << AST::Tag.new(val[1])
|
350
|
+
result
|
351
|
+
end
|
352
|
+
.,.,
|
353
|
+
|
354
|
+
def _reduce_none(val, _values, result)
|
355
|
+
val[0]
|
356
|
+
end
|
357
|
+
|
358
|
+
end # class Parser
|
359
|
+
end # module Gherkin
|
data/lib/gherkin/parser.rb
CHANGED
@@ -1,43 +1 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
module Gherkin
|
4
|
-
class Parser < Parslet::Parser
|
5
|
-
def indent(num=2)
|
6
|
-
str(' ' * num)
|
7
|
-
end
|
8
|
-
|
9
|
-
rule(:space) { match('\s').repeat }
|
10
|
-
rule(:space?) { space.maybe }
|
11
|
-
rule(:newline) { match('\n').repeat }
|
12
|
-
rule(:text) { match('[^\n]').repeat }
|
13
|
-
rule(:identifier) { match('\w').repeat }
|
14
|
-
|
15
|
-
rule(:feature_line) { str('Feature:') >> space? >> text.as(:name) }
|
16
|
-
rule(:scenario_line) { indent(2) >> str('Scenario:') >> space? >> text.as(:name) }
|
17
|
-
|
18
|
-
rule(:step_keyword) { str('Given') | str('When') | str('Then') | str('And') | str('But') }
|
19
|
-
|
20
|
-
rule(:comment) { str('#') >> text.as(:comment) }
|
21
|
-
|
22
|
-
rule(:description_text) { (str('Background:') | str('Scenario:') | str('@')).absent? >> text }
|
23
|
-
rule(:description) { (indent(2) >> description_text >> newline).repeat }
|
24
|
-
|
25
|
-
rule(:background_line) { indent(2) >> str('Background:') }
|
26
|
-
|
27
|
-
rule(:step) { indent(4) >> step_keyword.as(:keyword) >> space? >> text.as(:name) }
|
28
|
-
rule(:steps) { (step.as(:step) >> newline.maybe).repeat }
|
29
|
-
|
30
|
-
rule(:tags) { indent(2) >> (str('@') >> identifier.as(:tag) >> str(' ').maybe).repeat(1) }
|
31
|
-
|
32
|
-
rule(:scenario) { (tags.as(:tags) >> newline).maybe >> scenario_line >> newline >> steps.as(:steps) }
|
33
|
-
rule(:scenarios) { (scenario.as(:scenario) >> newline.maybe).repeat }
|
34
|
-
|
35
|
-
rule(:background) { background_line >> newline >> steps.as(:steps) }
|
36
|
-
|
37
|
-
rule(:feature) { feature_line >> newline >> description >> background.as(:background).maybe >> scenarios.as(:scenarios) }
|
38
|
-
|
39
|
-
rule(:main) { feature.as(:feature) }
|
40
|
-
|
41
|
-
root :main
|
42
|
-
end
|
43
|
-
end
|
1
|
+
require_relative 'parser/parser'
|
data/lib/gherkin/version.rb
CHANGED
data/lib/gherkin.rb
CHANGED
@@ -1,15 +1,10 @@
|
|
1
|
-
require 'parslet'
|
2
1
|
require_relative "gherkin/version"
|
3
2
|
require_relative 'gherkin/ast'
|
4
3
|
require_relative 'gherkin/parser'
|
5
|
-
require_relative 'gherkin/transform'
|
6
4
|
|
7
5
|
module Gherkin
|
8
6
|
def self.parse(input)
|
9
|
-
parser
|
10
|
-
|
11
|
-
|
12
|
-
parsed = parser.parse input
|
13
|
-
transform.apply(parsed)
|
7
|
+
parser = Parser.new
|
8
|
+
parser.parse(input)
|
14
9
|
end
|
15
10
|
end
|
data/test/gherkin/ast_test.rb
CHANGED
@@ -32,51 +32,42 @@ module Gherkin
|
|
32
32
|
node.ancestors.must_include Node
|
33
33
|
end
|
34
34
|
|
35
|
-
it 'has a line
|
36
|
-
|
37
|
-
def name.to_s; 'Name'; end
|
38
|
-
|
39
|
-
instance = node.new(name)
|
35
|
+
it 'has a line' do
|
36
|
+
instance = node.new("Name")
|
40
37
|
instance.name.must_equal 'Name'
|
41
|
-
instance.line
|
42
|
-
instance.column.must_equal 13
|
38
|
+
instance.must_respond_to :line
|
43
39
|
end
|
44
40
|
end
|
45
41
|
end
|
46
42
|
|
47
43
|
describe Feature do
|
48
44
|
it 'is Enumerable' do
|
49
|
-
name = OpenStruct.new(line_and_column: [2, 13])
|
50
|
-
def name.to_s; 'Name'; end
|
51
|
-
|
52
45
|
background = ['foo', 'bar']
|
53
46
|
elements = ['+foo', '+bar']
|
54
47
|
|
55
|
-
instance = Feature.new(
|
48
|
+
instance = Feature.new("My feature", elements, background )
|
56
49
|
instance.background.each.to_a.must_equal ['foo', 'bar']
|
57
50
|
instance.each.to_a.must_equal ['+foo', '+bar']
|
58
51
|
end
|
59
52
|
end
|
60
53
|
|
61
54
|
describe Scenario do
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
55
|
+
let(:steps) do
|
56
|
+
steps = [
|
57
|
+
OpenStruct.new(line: 4),
|
58
|
+
OpenStruct.new(line: 5),
|
59
|
+
]
|
60
|
+
end
|
67
61
|
|
68
|
-
|
69
|
-
instance.
|
62
|
+
it 'is Enumerable' do
|
63
|
+
instance = Scenario.new("Name", steps)
|
64
|
+
instance.each.to_a.must_equal steps
|
70
65
|
end
|
71
66
|
|
72
67
|
it 'has tags' do
|
73
|
-
name = OpenStruct.new(line_and_column: [2, 13])
|
74
|
-
def name.to_s; 'Name'; end
|
75
|
-
|
76
|
-
steps = ['foo', 'bar']
|
77
68
|
tags = ['javascript', 'wip']
|
78
69
|
|
79
|
-
instance = Scenario.new(
|
70
|
+
instance = Scenario.new("Name", steps, tags)
|
80
71
|
instance.tags.must_equal tags
|
81
72
|
end
|
82
73
|
end
|
@@ -99,10 +90,10 @@ module Gherkin
|
|
99
90
|
end
|
100
91
|
|
101
92
|
describe 'when there are background steps' do
|
102
|
-
it 'records line
|
93
|
+
it 'records line' do
|
103
94
|
instance = Background.new(steps)
|
95
|
+
instance.pos("file", 3)
|
104
96
|
instance.line.must_equal 3
|
105
|
-
instance.column.must_equal 3
|
106
97
|
end
|
107
98
|
end
|
108
99
|
|
@@ -110,7 +101,6 @@ module Gherkin
|
|
110
101
|
it 'does not' do
|
111
102
|
instance = Background.new([])
|
112
103
|
instance.line.must_equal nil
|
113
|
-
instance.column.must_equal nil
|
114
104
|
end
|
115
105
|
end
|
116
106
|
end
|
@@ -120,15 +110,12 @@ module Gherkin
|
|
120
110
|
Step.ancestors.must_include Node
|
121
111
|
end
|
122
112
|
|
123
|
-
it 'has a line
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
instance = Step.new(name, 'Given')
|
113
|
+
it 'has a line' do
|
114
|
+
instance = Step.new("Name", 'Given')
|
115
|
+
instance.pos("file", 2)
|
128
116
|
instance.name.must_equal 'Name'
|
129
117
|
instance.keyword.must_equal 'Given'
|
130
118
|
instance.line.must_equal 2
|
131
|
-
instance.column.must_equal 13
|
132
119
|
end
|
133
120
|
end
|
134
121
|
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module Gherkin
|
4
|
+
describe Parser do
|
5
|
+
let(:lexer) { Parser.new }
|
6
|
+
|
7
|
+
it 'ignores commments' do
|
8
|
+
lexer.tokenize("# this is a comment").must_equal []
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'parses newlines' do
|
12
|
+
lexer.tokenize("\n\n").must_equal [[:NEWLINE, "\n"], [:NEWLINE, "\n"]]
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'parses text and strips it' do
|
16
|
+
lexer.tokenize(" Arbitrary text ").must_equal [[:TEXT, "Arbitrary text"]]
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'parses tags' do
|
20
|
+
lexer.tokenize("@javascript @wip").must_equal [
|
21
|
+
[:TAG, "javascript"],
|
22
|
+
[:TAG, "wip"],
|
23
|
+
]
|
24
|
+
end
|
25
|
+
|
26
|
+
describe 'Keywords' do
|
27
|
+
%w(Feature: Background: Scenario:).each do |keyword|
|
28
|
+
it "parses #{keyword}:" do
|
29
|
+
name = keyword[0..-2]
|
30
|
+
lexer.tokenize(keyword).must_equal [[name.upcase.to_sym, name]]
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe 'Step keywords' do
|
36
|
+
%w(Given When Then And But).each do |keyword|
|
37
|
+
it "parses #{keyword}" do
|
38
|
+
lexer.tokenize(keyword).must_equal [[keyword.upcase.to_sym, keyword]]
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module Gherkin
|
4
|
+
describe Parser do
|
5
|
+
def parse(input)
|
6
|
+
parser = Parser.new
|
7
|
+
parser.parse(input)
|
8
|
+
end
|
9
|
+
|
10
|
+
describe 'Feature name and description' do
|
11
|
+
it 'parses feature header without description' do
|
12
|
+
feature = parse(
|
13
|
+
"Feature: my feature"
|
14
|
+
)
|
15
|
+
feature.must_be_kind_of AST::Feature
|
16
|
+
feature.name.must_equal "my feature"
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'parses feature header with description' do
|
20
|
+
feature = parse(
|
21
|
+
"Feature: my feature\n In order to do something\n As a user\n"
|
22
|
+
)
|
23
|
+
feature.must_be_kind_of AST::Feature
|
24
|
+
feature.name.must_equal "my feature"
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'parses feature with background' do
|
28
|
+
feature = parse("""
|
29
|
+
Feature: Do something
|
30
|
+
|
31
|
+
Background:
|
32
|
+
Given blah foo bar
|
33
|
+
Then something else
|
34
|
+
""")
|
35
|
+
feature.name.must_equal "Do something"
|
36
|
+
feature.background.must_be_kind_of AST::Background
|
37
|
+
steps = feature.background.steps
|
38
|
+
|
39
|
+
given_step = steps.first
|
40
|
+
then_step = steps.last
|
41
|
+
|
42
|
+
given_step.keyword.must_equal "Given"
|
43
|
+
given_step.name.must_equal "blah foo bar"
|
44
|
+
then_step.keyword.must_equal "Then"
|
45
|
+
then_step.name.must_equal "something else"
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'parses feature with scenarios' do
|
49
|
+
feature = parse("""
|
50
|
+
Feature: Do something
|
51
|
+
|
52
|
+
Scenario: Foo bar baz
|
53
|
+
Given blah foo bar
|
54
|
+
Then something else
|
55
|
+
|
56
|
+
Scenario: Foo bar baz blah
|
57
|
+
Given blah foo bar
|
58
|
+
Then something else
|
59
|
+
""")
|
60
|
+
scenarios = feature.scenarios
|
61
|
+
|
62
|
+
first_scenario = scenarios.first
|
63
|
+
last_scenario = scenarios.last
|
64
|
+
|
65
|
+
first_scenario.name.must_equal "Foo bar baz"
|
66
|
+
first_scenario.steps.first.name.must_equal "blah foo bar"
|
67
|
+
first_scenario.steps.last.name.must_equal "something else"
|
68
|
+
|
69
|
+
last_scenario.name.must_equal "Foo bar baz blah"
|
70
|
+
last_scenario.steps.first.name.must_equal "blah foo bar"
|
71
|
+
last_scenario.steps.last.name.must_equal "something else"
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'parses feature with scenarios with tags' do
|
75
|
+
feature = parse("""
|
76
|
+
Feature: Do something
|
77
|
+
|
78
|
+
Scenario: Foo bar baz
|
79
|
+
Given blah foo bar
|
80
|
+
Then something else
|
81
|
+
|
82
|
+
@javascript @wip
|
83
|
+
Scenario: Foo bar baz blah
|
84
|
+
Given blah foo bar
|
85
|
+
Then something else
|
86
|
+
""")
|
87
|
+
scenarios = feature.scenarios
|
88
|
+
|
89
|
+
last_scenario = scenarios.last
|
90
|
+
|
91
|
+
last_scenario.tags.first.name.must_equal "javascript"
|
92
|
+
last_scenario.tags.last.name.must_equal "wip"
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|