gherkin 2.1.4 → 2.1.5
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +8 -0
- data/Rakefile +3 -2
- data/VERSION.yml +1 -1
- data/features/json_formatter.feature +62 -36
- data/features/json_parser.feature +51 -37
- data/features/step_definitions/json_formatter_steps.rb +5 -10
- data/lib/gherkin/formatter/filter_formatter.rb +4 -9
- data/lib/gherkin/formatter/json_formatter.rb +48 -23
- data/lib/gherkin/i18n.rb +1 -1
- data/lib/gherkin/json_parser.rb +36 -49
- data/spec/gherkin/fixtures/complex.json +72 -52
- data/spec/gherkin/fixtures/scenario_without_steps.feature +5 -0
- data/spec/gherkin/formatter/filter_formatter_spec.rb +5 -0
- data/spec/gherkin/json_parser_spec.rb +38 -49
- data/tasks/release.rake +1 -1
- metadata +33 -16
data/History.txt
CHANGED
@@ -1,3 +1,11 @@
|
|
1
|
+
== 2.1.5 (2010-07-17)
|
2
|
+
|
3
|
+
=== Bugfixes
|
4
|
+
* Line filter works on JRuby with Scenarios without steps. (Aslak Hellesøy)
|
5
|
+
|
6
|
+
=== Changed Features
|
7
|
+
* The JSON schema now puts background inside the "elements" Array. Makes parsing simpler. (Aslak Hellesøy)
|
8
|
+
|
1
9
|
== 2.1.4 (2010-07-14)
|
2
10
|
|
3
11
|
=== Bugfixes
|
data/Rakefile
CHANGED
@@ -19,8 +19,9 @@ begin
|
|
19
19
|
gem.authors = ["Mike Sassak", "Gregory Hnatiuk", "Aslak Hellesøy"]
|
20
20
|
gem.executables = ["gherkin"]
|
21
21
|
gem.add_dependency "trollop", "~> 1.16.2"
|
22
|
-
gem.add_development_dependency '
|
23
|
-
gem.add_development_dependency
|
22
|
+
gem.add_development_dependency 'awesome_print', '~> 0.2.1'
|
23
|
+
gem.add_development_dependency 'rspec', '~> 2.0.0.beta.17'
|
24
|
+
gem.add_development_dependency "cucumber", "~> 0.8.5"
|
24
25
|
gem.add_development_dependency "rake-compiler", "~> 0.7.0" unless defined?(JRUBY_VERSION)
|
25
26
|
|
26
27
|
gem.files -= FileList['ikvm/**/*']
|
data/VERSION.yml
CHANGED
@@ -16,9 +16,11 @@ Feature: JSON formatter
|
|
16
16
|
Then the outputted JSON should be:
|
17
17
|
"""
|
18
18
|
{
|
19
|
-
"
|
19
|
+
"type": "feature",
|
20
|
+
"comments": [{"value": "# language: no", "line": 1}, {"value": "# Another comment", "line": 2}],
|
20
21
|
"keyword": "Egenskap",
|
21
22
|
"name": "Kjapp",
|
23
|
+
"description": "",
|
22
24
|
"line": 3,
|
23
25
|
"uri": "test.feature"
|
24
26
|
}
|
@@ -71,16 +73,19 @@ Feature: JSON formatter
|
|
71
73
|
Then the outputted JSON should be:
|
72
74
|
"""
|
73
75
|
{
|
76
|
+
"type": "feature",
|
77
|
+
"tags": [{"name": "@one", "line":1}],
|
74
78
|
"keyword": "Feature",
|
75
79
|
"name": "OH HAI",
|
76
|
-
"
|
80
|
+
"description": "",
|
77
81
|
"line": 2,
|
78
82
|
"uri": "test.feature",
|
79
83
|
"elements":[
|
80
84
|
{
|
85
|
+
"type": "scenario",
|
81
86
|
"keyword": "Scenario",
|
82
87
|
"name": "Fujin",
|
83
|
-
"
|
88
|
+
"description": "",
|
84
89
|
"line": 4,
|
85
90
|
"steps": [
|
86
91
|
{
|
@@ -96,10 +101,11 @@ Feature: JSON formatter
|
|
96
101
|
]
|
97
102
|
},
|
98
103
|
{
|
99
|
-
"
|
104
|
+
"type": "scenario",
|
105
|
+
"tags": [{"name": "@two", "line":8}],
|
100
106
|
"keyword": "Scenario",
|
101
107
|
"name": "_why",
|
102
|
-
"
|
108
|
+
"description": "",
|
103
109
|
"line": 9,
|
104
110
|
"steps": [
|
105
111
|
{
|
@@ -115,10 +121,11 @@ Feature: JSON formatter
|
|
115
121
|
]
|
116
122
|
},
|
117
123
|
{
|
118
|
-
"
|
124
|
+
"type": "scenario_outline",
|
125
|
+
"tags": [{"name": "@three", "line":13}, {"name": "@four", "line":13}],
|
119
126
|
"keyword": "Scenario Outline",
|
120
127
|
"name": "Life",
|
121
|
-
"
|
128
|
+
"description": "",
|
122
129
|
"line": 14,
|
123
130
|
"steps": [
|
124
131
|
{
|
@@ -129,9 +136,11 @@ Feature: JSON formatter
|
|
129
136
|
],
|
130
137
|
"examples": [
|
131
138
|
{
|
132
|
-
"
|
139
|
+
"type": "examples",
|
140
|
+
"tags": [{"name": "@five", "line":17}],
|
133
141
|
"keyword": "Examples",
|
134
142
|
"name": "Real life",
|
143
|
+
"description": "",
|
135
144
|
"line": 18,
|
136
145
|
"table": [
|
137
146
|
{
|
@@ -151,39 +160,48 @@ Feature: JSON formatter
|
|
151
160
|
]
|
152
161
|
},
|
153
162
|
{
|
163
|
+
"type": "scenario",
|
154
164
|
"keyword": "Scenario",
|
155
165
|
"name": "who stole my mojo?",
|
156
|
-
"
|
166
|
+
"description": "",
|
157
167
|
"line": 23,
|
158
168
|
"steps": [
|
159
169
|
{
|
160
170
|
"keyword": "When ",
|
161
171
|
"name": "I was",
|
162
172
|
"line": 24,
|
163
|
-
"
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
173
|
+
"multiline_arg": {
|
174
|
+
"type": "table",
|
175
|
+
"value": [
|
176
|
+
{
|
177
|
+
"line": 25,
|
178
|
+
"cells": ["asleep"]
|
179
|
+
}
|
180
|
+
]
|
181
|
+
}
|
169
182
|
},
|
170
183
|
{
|
171
184
|
"keyword": "And ",
|
172
185
|
"name": "so",
|
173
186
|
"line": 26,
|
174
|
-
"
|
187
|
+
"multiline_arg": {
|
188
|
+
"type": "py_string",
|
189
|
+
"value": "innocent",
|
190
|
+
"line": 27
|
191
|
+
}
|
175
192
|
}
|
176
193
|
]
|
177
194
|
},
|
178
195
|
{
|
179
|
-
"comments": ["# The"],
|
180
|
-
"keyword": "Scenario Outline",
|
181
196
|
"type": "scenario_outline",
|
182
|
-
"
|
197
|
+
"comments": [{"value": "# The", "line":31}],
|
198
|
+
"keyword": "Scenario Outline",
|
183
199
|
"name": "with",
|
200
|
+
"description": "",
|
201
|
+
"line": 32,
|
184
202
|
"steps": [
|
185
203
|
{
|
186
|
-
"comments": ["# all"],
|
204
|
+
"comments": [{"value": "# all", "line":33}],
|
187
205
|
"keyword": "Then ",
|
188
206
|
"line": 34,
|
189
207
|
"name": "nice"
|
@@ -191,13 +209,15 @@ Feature: JSON formatter
|
|
191
209
|
],
|
192
210
|
"examples": [
|
193
211
|
{
|
194
|
-
"
|
212
|
+
"type": "examples",
|
213
|
+
"comments": [{"value": "# comments", "line": 36}, {"value": "# everywhere", "line": 37}],
|
195
214
|
"keyword": "Examples",
|
196
215
|
"name": "An example",
|
216
|
+
"description": "",
|
197
217
|
"line": 38,
|
198
218
|
"table": [
|
199
219
|
{
|
200
|
-
"comments": ["# I mean"],
|
220
|
+
"comments": [{"value": "# I mean", "line": 39}],
|
201
221
|
"line": 40,
|
202
222
|
"cells": ["partout"]
|
203
223
|
}
|
@@ -224,27 +244,33 @@ Feature: JSON formatter
|
|
224
244
|
Then the outputted JSON should be:
|
225
245
|
"""
|
226
246
|
{
|
247
|
+
"type": "feature",
|
227
248
|
"keyword": "Feature",
|
228
249
|
"name": "Kjapp",
|
250
|
+
"description": "",
|
229
251
|
"line": 1,
|
230
252
|
"uri": "test.feature",
|
231
|
-
"background": {
|
232
|
-
"keyword": "Background",
|
233
|
-
"line": 3,
|
234
|
-
"name": "No idea what Kjapp means",
|
235
|
-
"steps": [
|
236
|
-
{
|
237
|
-
"keyword": "Given ",
|
238
|
-
"line": 4,
|
239
|
-
"name": "I Google it"
|
240
|
-
}
|
241
|
-
]
|
242
|
-
},
|
243
253
|
"elements": [
|
244
254
|
{
|
245
|
-
"
|
246
|
-
"keyword": "
|
255
|
+
"type": "background",
|
256
|
+
"keyword": "Background",
|
257
|
+
"line": 3,
|
258
|
+
"name": "No idea what Kjapp means",
|
259
|
+
"description": "",
|
260
|
+
"steps": [
|
261
|
+
{
|
262
|
+
"keyword": "Given ",
|
263
|
+
"line": 4,
|
264
|
+
"name": "I Google it"
|
265
|
+
}
|
266
|
+
]
|
267
|
+
},
|
268
|
+
{
|
247
269
|
"type": "scenario",
|
270
|
+
"comments": [{"value": "# Writing JSON by hand sucks", "line": 6}],
|
271
|
+
"keyword": "Scenario",
|
272
|
+
"name": "",
|
273
|
+
"description": "",
|
248
274
|
"line": 7,
|
249
275
|
"steps": [
|
250
276
|
{
|
@@ -10,7 +10,11 @@ Feature: JSON lexer
|
|
10
10
|
Given the following JSON is parsed:
|
11
11
|
"""
|
12
12
|
{
|
13
|
-
"
|
13
|
+
"type": "feature",
|
14
|
+
"comments": [
|
15
|
+
{"value": "# language: no"},
|
16
|
+
{"value": "# Another comment"}
|
17
|
+
],
|
14
18
|
"description": "",
|
15
19
|
"keyword": "Egenskap",
|
16
20
|
"name": "Kjapp",
|
@@ -29,10 +33,11 @@ Feature: JSON lexer
|
|
29
33
|
Given the following JSON is parsed:
|
30
34
|
"""
|
31
35
|
{
|
36
|
+
"type": "feature",
|
32
37
|
"comments": [],
|
33
38
|
"keyword": "Feature",
|
34
39
|
"name": "OH HAI",
|
35
|
-
"tags": ["@one"],
|
40
|
+
"tags": [{"name": "@one"}],
|
36
41
|
"uri": "test.feature",
|
37
42
|
"description": "",
|
38
43
|
"elements":[
|
@@ -61,7 +66,7 @@ Feature: JSON lexer
|
|
61
66
|
},
|
62
67
|
{
|
63
68
|
"comments": [],
|
64
|
-
"tags": ["@two"],
|
69
|
+
"tags": [{"name": "@two"}],
|
65
70
|
"keyword": "Scenario",
|
66
71
|
"name": "_why",
|
67
72
|
"description": "",
|
@@ -84,7 +89,7 @@ Feature: JSON lexer
|
|
84
89
|
},
|
85
90
|
{
|
86
91
|
"comments": [],
|
87
|
-
"tags": ["@three", "@four"],
|
92
|
+
"tags": [{"name": "@three"}, {"name": "@four"}],
|
88
93
|
"keyword": "Scenario Outline",
|
89
94
|
"name": "Life",
|
90
95
|
"description": "",
|
@@ -100,8 +105,9 @@ Feature: JSON lexer
|
|
100
105
|
],
|
101
106
|
"examples": [
|
102
107
|
{
|
108
|
+
"type": "examples",
|
103
109
|
"comments": [],
|
104
|
-
"tags": ["@five"],
|
110
|
+
"tags": [{"name": "@five"}],
|
105
111
|
"keyword": "Examples",
|
106
112
|
"name": "Real life",
|
107
113
|
"description": "",
|
@@ -140,25 +146,32 @@ Feature: JSON lexer
|
|
140
146
|
"keyword": "When ",
|
141
147
|
"name": "I was",
|
142
148
|
"line": 24,
|
143
|
-
"
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
149
|
+
"multiline_arg": {
|
150
|
+
"type": "table",
|
151
|
+
"value": [
|
152
|
+
{
|
153
|
+
"comments": [],
|
154
|
+
"line": 25,
|
155
|
+
"cells": ["asleep"]
|
156
|
+
}
|
157
|
+
]
|
158
|
+
}
|
150
159
|
},
|
151
160
|
{
|
152
161
|
"comments": [],
|
153
162
|
"keyword": "And ",
|
154
163
|
"name": "so",
|
155
164
|
"line": 26,
|
156
|
-
"
|
165
|
+
"multiline_arg": {
|
166
|
+
"type": "py_string",
|
167
|
+
"value": "innocent",
|
168
|
+
"line": 27
|
169
|
+
}
|
157
170
|
}
|
158
171
|
]
|
159
172
|
},
|
160
173
|
{
|
161
|
-
"comments": ["# The"],
|
174
|
+
"comments": [{"value": "# The"}],
|
162
175
|
"tags": [],
|
163
176
|
"keyword": "Scenario Outline",
|
164
177
|
"description": "",
|
@@ -167,7 +180,7 @@ Feature: JSON lexer
|
|
167
180
|
"name": "with",
|
168
181
|
"steps": [
|
169
182
|
{
|
170
|
-
"comments": ["# all"],
|
183
|
+
"comments": [{"value": "# all"}],
|
171
184
|
"keyword": "Then ",
|
172
185
|
"line": 34,
|
173
186
|
"name": "nice"
|
@@ -175,22 +188,21 @@ Feature: JSON lexer
|
|
175
188
|
],
|
176
189
|
"examples": [
|
177
190
|
{
|
178
|
-
"
|
191
|
+
"type": "examples",
|
192
|
+
"comments": [{"value": "# comments"}, {"value": "# everywhere"}],
|
179
193
|
"tags": [],
|
180
194
|
"keyword": "Examples",
|
181
195
|
"name": "An example",
|
182
|
-
// TODO - the description should now be the comment
|
183
|
-
// It should be on the first row of the examples_table!
|
184
196
|
"description": "",
|
185
197
|
"line": 38,
|
186
198
|
"table": [
|
187
199
|
{
|
188
|
-
"comments": ["# I mean"],
|
200
|
+
"comments": [{"value": "# I mean"}],
|
189
201
|
"line": 40,
|
190
202
|
"cells": ["partout"]
|
191
203
|
},
|
192
204
|
{
|
193
|
-
"comments": ["# I really mean"],
|
205
|
+
"comments": [{"value": "# I really mean"}],
|
194
206
|
"line": 40,
|
195
207
|
"cells": ["bartout"]
|
196
208
|
}
|
@@ -251,35 +263,37 @@ Feature: JSON lexer
|
|
251
263
|
Given the following JSON is parsed:
|
252
264
|
"""
|
253
265
|
{
|
266
|
+
"type": "feature",
|
254
267
|
"comments": [],
|
255
268
|
"description": "",
|
256
269
|
"keyword": "Feature",
|
257
270
|
"name": "Kjapp",
|
258
271
|
"tags": [],
|
259
272
|
"uri": "test.feature",
|
260
|
-
"background": {
|
261
|
-
"comments": [],
|
262
|
-
"description": "",
|
263
|
-
"keyword": "Background",
|
264
|
-
"line": 2,
|
265
|
-
"name": "No idea what Kjapp means",
|
266
|
-
"steps": [
|
267
|
-
{
|
268
|
-
"comments": [],
|
269
|
-
"keyword": "Given ",
|
270
|
-
"line": 3,
|
271
|
-
"name": "I Google it"
|
272
|
-
}
|
273
|
-
]
|
274
|
-
},
|
275
273
|
"elements": [
|
276
274
|
{
|
277
|
-
"
|
275
|
+
"type": "background",
|
276
|
+
"comments": [],
|
277
|
+
"description": "",
|
278
|
+
"keyword": "Background",
|
279
|
+
"line": 2,
|
280
|
+
"name": "No idea what Kjapp means",
|
281
|
+
"steps": [
|
282
|
+
{
|
283
|
+
"comments": [],
|
284
|
+
"keyword": "Given ",
|
285
|
+
"line": 3,
|
286
|
+
"name": "I Google it"
|
287
|
+
}
|
288
|
+
]
|
289
|
+
},
|
290
|
+
{
|
291
|
+
"type": "scenario",
|
292
|
+
"comments": [{"value": "# Writing JSON by hand sucks"}],
|
278
293
|
"tags": [],
|
279
294
|
"keyword": "Scenario",
|
280
295
|
"name": "",
|
281
296
|
"description": "",
|
282
|
-
"type": "scenario",
|
283
297
|
"line": 6,
|
284
298
|
"steps": [
|
285
299
|
{
|
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'ap' # awesome_print gem
|
1
2
|
require 'stringio'
|
2
3
|
require 'gherkin/formatter/json_formatter'
|
3
4
|
require 'gherkin/listener/formatter_listener'
|
@@ -17,16 +18,10 @@ end
|
|
17
18
|
|
18
19
|
Then /^the outputted JSON should be:$/ do |expected_json|
|
19
20
|
require 'json'
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
actual.should == expected
|
25
|
-
rescue # Haven't figured out how to order Hash on JRuby (JSON pure). Retry with possibly worse error message.
|
26
|
-
expected = JSON.parse(expected_json)
|
27
|
-
actual = JSON.parse(@io.string)
|
28
|
-
actual.should == expected
|
29
|
-
end
|
21
|
+
announce JSON.pretty_generate(JSON.parse(@io.string))
|
22
|
+
expected = JSON.parse(expected_json).ai
|
23
|
+
actual = JSON.parse(@io.string).ai
|
24
|
+
actual.should == expected
|
30
25
|
end
|
31
26
|
|
32
27
|
|
@@ -109,28 +109,23 @@ module Gherkin
|
|
109
109
|
def replay!
|
110
110
|
case @filter
|
111
111
|
when TagExpression
|
112
|
-
background_ok = false
|
113
112
|
feature_element_ok = @filter.eval(tag_names(@feature_tags.to_a + @feature_element_tags.to_a))
|
114
113
|
examples_ok = @filter.eval(tag_names(@feature_tags.to_a + @feature_element_tags.to_a + @examples_tags.to_a)) if @examples_tags
|
115
114
|
when RegexpFilter
|
116
|
-
background_ok = @filter.eval([@background_name]) if @background_name
|
117
115
|
feature_element_ok = @filter.eval([@feature_element_name])
|
118
116
|
examples_ok = @filter.eval([@feature_element_name, @examples_name]) if @examples_name
|
119
117
|
when LineFilter
|
120
|
-
background_ok = @filter.eval([@background_range]) if @background_range
|
121
118
|
feature_element_ok = @filter.eval([@feature_element_range]) if @feature_element_range
|
122
119
|
examples_ok = @filter.eval([@feature_element_range, @examples_range]) if @examples_range
|
123
120
|
end
|
124
121
|
|
125
|
-
if
|
122
|
+
if feature_element_ok || examples_ok
|
126
123
|
replay_events!(@feature_events)
|
127
124
|
replay_events!(@background_events)
|
125
|
+
replay_events!(@feature_element_events)
|
128
126
|
|
129
|
-
if
|
130
|
-
replay_events!(@
|
131
|
-
if examples_ok
|
132
|
-
replay_events!(@examples_events)
|
133
|
-
end
|
127
|
+
if examples_ok
|
128
|
+
replay_events!(@examples_events)
|
134
129
|
end
|
135
130
|
end
|
136
131
|
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'json'
|
2
2
|
require 'json/pure' # Needed to make JSON.generate work.
|
3
3
|
require 'gherkin/rubify'
|
4
|
+
require 'gherkin/formatter/model'
|
4
5
|
|
5
6
|
module Gherkin
|
6
7
|
module Formatter
|
@@ -12,22 +13,19 @@ module Gherkin
|
|
12
13
|
end
|
13
14
|
|
14
15
|
def feature(statement, uri)
|
15
|
-
@json_hash = statement_hash(
|
16
|
+
@json_hash = statement_hash('feature', statement)
|
16
17
|
@json_hash['uri'] = uri
|
17
18
|
end
|
18
19
|
|
19
20
|
def background(statement)
|
20
|
-
|
21
|
-
@in_background = true
|
21
|
+
add_step_container('background', statement)
|
22
22
|
end
|
23
23
|
|
24
24
|
def scenario(statement)
|
25
|
-
@in_background = false
|
26
25
|
add_step_container('scenario', statement)
|
27
26
|
end
|
28
27
|
|
29
28
|
def scenario_outline(statement)
|
30
|
-
@in_background = false
|
31
29
|
add_step_container('scenario_outline', statement)
|
32
30
|
end
|
33
31
|
|
@@ -50,15 +48,31 @@ module Gherkin
|
|
50
48
|
|
51
49
|
def statement_hash(type, statement)
|
52
50
|
element = {
|
53
|
-
'comments' => statement.comments.map{|comment| comment.value},
|
54
|
-
'tags' => statement.tags.map{|tag| tag.name},
|
55
51
|
'keyword' => statement.keyword,
|
56
52
|
'name' => statement.name,
|
57
|
-
'description' => statement.description,
|
58
53
|
'line' => statement.line,
|
59
54
|
}
|
60
|
-
element['type'] = type
|
61
|
-
|
55
|
+
element['type'] = type if type
|
56
|
+
add_comments(element, statement)
|
57
|
+
add_tags(element, statement)
|
58
|
+
element['description'] = statement.description if statement.description
|
59
|
+
element
|
60
|
+
end
|
61
|
+
|
62
|
+
def add_comments(element, comment_holder)
|
63
|
+
if comment_holder.comments && comment_holder.comments.any?
|
64
|
+
element['comments'] = comment_holder.comments.map do |comment|
|
65
|
+
{'value' => comment.value, 'line' => comment.line}
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def add_tags(element, statement)
|
71
|
+
if statement.tags && statement.tags.any?
|
72
|
+
element['tags'] = statement.tags.map do |tag|
|
73
|
+
{'name' => tag.name, 'line' => tag.line}
|
74
|
+
end
|
75
|
+
end
|
62
76
|
end
|
63
77
|
|
64
78
|
def add_element(type, statement)
|
@@ -69,7 +83,7 @@ module Gherkin
|
|
69
83
|
end
|
70
84
|
|
71
85
|
def add_examples(statement)
|
72
|
-
element = statement_hash(
|
86
|
+
element = statement_hash('examples', statement)
|
73
87
|
last_element['examples'] ||= []
|
74
88
|
last_element['examples'] << element
|
75
89
|
element
|
@@ -81,27 +95,38 @@ module Gherkin
|
|
81
95
|
end
|
82
96
|
|
83
97
|
def last_element
|
84
|
-
|
85
|
-
@json_hash['background']
|
86
|
-
else
|
87
|
-
@json_hash['elements'][-1]
|
88
|
-
end
|
98
|
+
@json_hash['elements'][-1]
|
89
99
|
end
|
90
100
|
|
91
101
|
def to_hash_array(rows)
|
92
102
|
rows.map do |row|
|
93
|
-
|
103
|
+
e = {"cells" => row.cells.to_a, "line" => row.line}
|
104
|
+
add_comments(e, row)
|
105
|
+
e
|
94
106
|
end
|
95
107
|
end
|
96
108
|
|
97
109
|
def step_arg_to_hash(multiline_arg)
|
98
|
-
return {} if multiline_arg.nil?
|
99
110
|
multiline_arg = rubify(multiline_arg)
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
111
|
+
case multiline_arg
|
112
|
+
when Array
|
113
|
+
{
|
114
|
+
"multiline_arg" => {
|
115
|
+
"type" => "table",
|
116
|
+
"value" => to_hash_array(multiline_arg)
|
117
|
+
}
|
118
|
+
}
|
119
|
+
when Model::PyString
|
120
|
+
{
|
121
|
+
"multiline_arg" => {
|
122
|
+
"type" => "py_string",
|
123
|
+
"value" => multiline_arg.value,
|
124
|
+
"line" => multiline_arg.line
|
125
|
+
}
|
126
|
+
}
|
127
|
+
else
|
128
|
+
{}
|
129
|
+
end
|
105
130
|
end
|
106
131
|
end
|
107
132
|
end
|
data/lib/gherkin/i18n.rb
CHANGED
data/lib/gherkin/json_parser.rb
CHANGED
@@ -26,17 +26,11 @@ module Gherkin
|
|
26
26
|
|
27
27
|
comments_for(feature)
|
28
28
|
tags_for(feature)
|
29
|
-
multiline_event(
|
29
|
+
multiline_event(feature)
|
30
30
|
|
31
|
-
|
32
|
-
comments_for(feature["background"])
|
33
|
-
multiline_event(:background, feature["background"])
|
34
|
-
steps_for(feature["background"])
|
35
|
-
end
|
36
|
-
|
37
|
-
feature["elements"].each do |feature_element|
|
31
|
+
(feature["elements"] || []).each do |feature_element|
|
38
32
|
parse_element(feature_element)
|
39
|
-
end
|
33
|
+
end
|
40
34
|
|
41
35
|
@listener.eof
|
42
36
|
end
|
@@ -44,71 +38,64 @@ module Gherkin
|
|
44
38
|
def parse_element(feature_element)
|
45
39
|
comments_for(feature_element)
|
46
40
|
tags_for(feature_element)
|
47
|
-
|
48
|
-
|
49
|
-
|
41
|
+
multiline_event(feature_element)
|
42
|
+
steps_for(feature_element)
|
43
|
+
|
44
|
+
if feature_element["type"] == "scenario_outline"
|
45
|
+
(feature_element["examples"] || []).each do |examples|
|
46
|
+
comments_for(examples)
|
47
|
+
tags_for(examples)
|
48
|
+
multiline_event(examples)
|
49
|
+
rows_for(examples['table'])
|
50
|
+
end
|
50
51
|
end
|
51
52
|
end
|
52
53
|
|
53
|
-
def parse_outline(scenario_outline)
|
54
|
-
multiline_event(:scenario_outline, scenario_outline)
|
55
|
-
steps_for(scenario_outline)
|
56
|
-
scenario_outline["examples"].each do |examples|
|
57
|
-
comments_for(examples)
|
58
|
-
tags_for(examples)
|
59
|
-
multiline_event(:examples, examples)
|
60
|
-
rows_for(examples)
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
def parse_scenario(scenario)
|
65
|
-
multiline_event(:scenario, scenario)
|
66
|
-
steps_for(scenario)
|
67
|
-
end
|
68
|
-
|
69
54
|
def comments_for(element)
|
70
|
-
element["comments"].each do |comment|
|
71
|
-
@listener.comment(comment,
|
72
|
-
end
|
55
|
+
(element["comments"] || []).each do |comment|
|
56
|
+
@listener.comment(comment['value'], comment['line'])
|
57
|
+
end
|
73
58
|
end
|
74
59
|
|
75
60
|
def tags_for(element)
|
76
|
-
element["tags"].each do |tag|
|
77
|
-
@listener.tag(tag,
|
78
|
-
end
|
61
|
+
(element["tags"] || []).each do |tag|
|
62
|
+
@listener.tag(tag['name'], tag['line'])
|
63
|
+
end
|
79
64
|
end
|
80
65
|
|
81
66
|
def steps_for(element)
|
82
67
|
element["steps"].each do |step|
|
83
68
|
comments_for(step)
|
84
|
-
@listener.step(step["keyword"], step["name"],
|
85
|
-
|
86
|
-
rows_for(step)
|
69
|
+
@listener.step(step["keyword"], step["name"], step['line'])
|
70
|
+
multiline_arg_for(step)
|
87
71
|
end
|
88
72
|
end
|
89
73
|
|
90
|
-
def
|
91
|
-
|
74
|
+
def multiline_arg_for(element)
|
75
|
+
if ma = element["multiline_arg"]
|
76
|
+
case ma["type"]
|
77
|
+
when "py_string"
|
78
|
+
@listener.py_string(ma["value"], ma["line"])
|
79
|
+
when "table"
|
80
|
+
rows_for(ma["value"])
|
81
|
+
end
|
82
|
+
end
|
92
83
|
end
|
93
84
|
|
94
|
-
def rows_for(
|
95
|
-
|
85
|
+
def rows_for(rows)
|
86
|
+
(rows || []).each do |row|
|
96
87
|
comments_for(row)
|
97
|
-
@listener.row(cells_for(row),
|
98
|
-
end
|
88
|
+
@listener.row(cells_for(row), row['line'])
|
89
|
+
end
|
99
90
|
end
|
100
91
|
|
101
92
|
def cells_for(row)
|
102
93
|
row["cells"]
|
103
94
|
end
|
104
95
|
|
105
|
-
def
|
106
|
-
element["line"].to_i || 0
|
107
|
-
end
|
108
|
-
|
109
|
-
def multiline_event(type, element)
|
96
|
+
def multiline_event(element)
|
110
97
|
if element["keyword"]
|
111
|
-
@listener.__send__(type, element["keyword"], element["name"] || "", element["description"] || "",
|
98
|
+
@listener.__send__(element['type'].to_sym, element["keyword"], element["name"] || "", element["description"] || "", element['line'])
|
112
99
|
end
|
113
100
|
end
|
114
101
|
end
|
@@ -1,40 +1,48 @@
|
|
1
|
-
{
|
1
|
+
{
|
2
|
+
"type": "feature",
|
3
|
+
"name": "Feature Text",
|
2
4
|
"keyword": "Feature",
|
3
5
|
"description": "In order to test multiline forms",
|
4
6
|
"tags": [
|
5
|
-
"@tag1",
|
6
|
-
"@tag2"
|
7
|
+
{"name": "@tag1"},
|
8
|
+
{"name": "@tag2"}
|
7
9
|
],
|
8
|
-
"background" : {
|
9
|
-
"description": "",
|
10
|
-
"name": "",
|
11
|
-
"keyword": "Background",
|
12
|
-
"steps": [
|
13
|
-
{ "name": "this is a background step",
|
14
|
-
"keyword": "Given " },
|
15
|
-
{ "name": "this is another one",
|
16
|
-
"keyword": "When ",
|
17
|
-
"line": 412 }
|
18
|
-
]
|
19
|
-
},
|
20
10
|
"elements": [
|
11
|
+
{ "type": "background",
|
12
|
+
"description": "",
|
13
|
+
"name": "",
|
14
|
+
"keyword": "Background",
|
15
|
+
"steps": [
|
16
|
+
{ "name": "this is a background step",
|
17
|
+
"keyword": "Given " },
|
18
|
+
{ "name": "this is another one",
|
19
|
+
"keyword": "When ",
|
20
|
+
"line": 412 }
|
21
|
+
]
|
22
|
+
},
|
21
23
|
{ "type": "scenario_outline",
|
22
24
|
"keyword": "Scenario Outline",
|
23
25
|
"name": "An Scenario Outline",
|
24
26
|
"description": "",
|
25
|
-
"tags": [
|
27
|
+
"tags": [
|
28
|
+
{"name": "@foo"}
|
29
|
+
],
|
26
30
|
"steps": [
|
27
31
|
{ "name": "A step with a table",
|
28
32
|
"keyword": "Given ",
|
29
|
-
"
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
33
|
+
"multiline_arg": {
|
34
|
+
"type": "table",
|
35
|
+
"value" : [
|
36
|
+
{"cells":
|
37
|
+
[ "a","row","for","a","step" ]
|
38
|
+
}
|
39
|
+
]
|
40
|
+
}
|
34
41
|
}
|
35
42
|
],
|
36
43
|
"examples": [
|
37
|
-
{ "
|
44
|
+
{ "type": "examples",
|
45
|
+
"name": "Sweet Example",
|
38
46
|
"keyword": "Examples",
|
39
47
|
"description": "",
|
40
48
|
"table" : [
|
@@ -45,7 +53,7 @@
|
|
45
53
|
[ "The","Blanks" ]
|
46
54
|
}
|
47
55
|
],
|
48
|
-
"tags" : [ "@exampletag" ]
|
56
|
+
"tags" : [ {"name": "@exampletag"} ]
|
49
57
|
}
|
50
58
|
]
|
51
59
|
},
|
@@ -54,8 +62,8 @@
|
|
54
62
|
"name" : "Reading a Scenario",
|
55
63
|
"description": "",
|
56
64
|
"tags" : [
|
57
|
-
"@tag3",
|
58
|
-
"@tag4"
|
65
|
+
{"name": "@tag3"},
|
66
|
+
{"name": "@tag4"}
|
59
67
|
],
|
60
68
|
"steps" : [
|
61
69
|
{ "name" : "there is a step",
|
@@ -68,38 +76,45 @@
|
|
68
76
|
"keyword": "Scenario",
|
69
77
|
"name" : "Reading a second scenario",
|
70
78
|
"description": "With two lines of text",
|
71
|
-
"tags" : [ "@tag3" ],
|
79
|
+
"tags" : [ {"name": "@tag3"} ],
|
72
80
|
"steps" : [
|
73
81
|
{ "name" : "a third step with a table",
|
74
82
|
"keyword": "Given ",
|
75
|
-
"
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
83
|
+
"multiline_arg": {
|
84
|
+
"type": "table",
|
85
|
+
"value": [
|
86
|
+
{
|
87
|
+
"cells" : [ "a","b" ],
|
88
|
+
"line" : 987
|
89
|
+
},
|
90
|
+
{ "cells" :
|
91
|
+
[ "c","d" ]
|
92
|
+
},
|
93
|
+
{ "cells" :
|
94
|
+
[ "e", "f" ]
|
95
|
+
}
|
96
|
+
]
|
97
|
+
}
|
86
98
|
},
|
87
99
|
{ "name" : "I am still testing things",
|
88
100
|
"keyword": "Given ",
|
89
|
-
"
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
101
|
+
"multiline_arg": {
|
102
|
+
"type": "table",
|
103
|
+
"value": [
|
104
|
+
{ "cells" :
|
105
|
+
[ "g","h" ]
|
106
|
+
},
|
107
|
+
{ "cells" :
|
108
|
+
[ "e","r" ]
|
109
|
+
},
|
110
|
+
{ "cells" :
|
111
|
+
[ "k", "i" ]
|
112
|
+
},
|
113
|
+
{ "cells" :
|
114
|
+
[ "n", "" ]
|
115
|
+
}
|
116
|
+
]
|
117
|
+
}
|
103
118
|
},
|
104
119
|
{ "name" : "I am done testing these tables",
|
105
120
|
"keyword": "Given " },
|
@@ -114,7 +129,12 @@
|
|
114
129
|
"steps" : [
|
115
130
|
{ "name" : "All work and no play",
|
116
131
|
"keyword": "Given ",
|
117
|
-
"
|
132
|
+
"multiline_arg": {
|
133
|
+
"type": "py_string",
|
134
|
+
"value": "Makes Homer something something\nAnd something else",
|
135
|
+
"line": 777
|
136
|
+
}
|
137
|
+
},
|
118
138
|
{ "name" : "crazy",
|
119
139
|
"keyword": "Given " }
|
120
140
|
]
|
@@ -92,6 +92,11 @@ module Gherkin
|
|
92
92
|
|
93
93
|
context "lines" do
|
94
94
|
context "on the same line as feature element keyword" do
|
95
|
+
it "should filter on scenario without line" do
|
96
|
+
self.file = 'scenario_without_steps.feature'
|
97
|
+
verify_filter([3], 1..4)
|
98
|
+
end
|
99
|
+
|
95
100
|
it "should filter on scenario line" do
|
96
101
|
verify_filter([16], 1..19)
|
97
102
|
end
|
@@ -22,7 +22,7 @@ module Gherkin
|
|
22
22
|
|
23
23
|
describe "A barely empty feature" do
|
24
24
|
it "should scan a feature with no elements" do
|
25
|
-
@parser.parse_with_listener('{ "keyword": "Feature", "name": "One", "description": "", "line" : 3 }', @listener)
|
25
|
+
@parser.parse_with_listener('{ "type": "feature", "keyword": "Feature", "name": "One", "description": "", "line" : 3 }', @listener)
|
26
26
|
@listener.to_sexp.should == [
|
27
27
|
[:location, "unknown.json"],
|
28
28
|
[:feature, "Feature", "One", "", 3],
|
@@ -31,23 +31,12 @@ module Gherkin
|
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
34
|
-
describe "Missing line numbers" do
|
35
|
-
it "should indicate a line number of 0 if a line attribute doesn't exist" do
|
36
|
-
@parser.parse_with_listener('{ "name": "My Sweet Featur", "keyword": "Feature", "description": "" }', @listener)
|
37
|
-
@listener.to_sexp.should == [
|
38
|
-
[:location, "unknown.json"],
|
39
|
-
[:feature, "Feature", "My Sweet Featur", "", 0],
|
40
|
-
[:eof]
|
41
|
-
]
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
34
|
describe "Keywords" do
|
46
35
|
it "should use the keyword from the source when provided" do
|
47
|
-
@parser.parse_with_listener('{ "name" : "My Sweet Featur", "language": "fr", "keyword": "Feature", "description": "" }', @listener)
|
36
|
+
@parser.parse_with_listener('{ "type": "feature", "name" : "My Sweet Featur", "language": "fr", "keyword": "Feature", "description": "" }', @listener)
|
48
37
|
@listener.to_sexp.should == [
|
49
38
|
[:location, "unknown.json"],
|
50
|
-
[:feature, "Feature", "My Sweet Featur", "",
|
39
|
+
[:feature, "Feature", "My Sweet Featur", "", nil],
|
51
40
|
[:eof]
|
52
41
|
]
|
53
42
|
end
|
@@ -58,42 +47,42 @@ module Gherkin
|
|
58
47
|
@parser.parse_with_listener(fixture("complex.json"), @listener)
|
59
48
|
@listener.to_sexp.should == [
|
60
49
|
[:location, "unknown.json"],
|
61
|
-
[:tag, "@tag1",
|
62
|
-
[:tag, "@tag2",
|
63
|
-
[:feature, "Feature", "Feature Text","In order to test multiline forms",
|
64
|
-
[:background, "Background", "", "",
|
65
|
-
[:step, "Given ", "this is a background step",
|
50
|
+
[:tag, "@tag1", nil],
|
51
|
+
[:tag, "@tag2", nil],
|
52
|
+
[:feature, "Feature", "Feature Text","In order to test multiline forms", nil],
|
53
|
+
[:background, "Background", "", "", nil],
|
54
|
+
[:step, "Given ", "this is a background step", nil],
|
66
55
|
[:step, "When ", "this is another one", 412],
|
67
|
-
[:tag, "@foo",
|
68
|
-
[:scenario_outline, "Scenario Outline", "An Scenario Outline","",
|
69
|
-
[:step, "Given ", "A step with a table",
|
70
|
-
[:row, %w{a row for a step},
|
71
|
-
[:tag, "@exampletag",
|
72
|
-
[:examples, "Examples", "Sweet Example", "",
|
73
|
-
[:row, %w{Fill In},
|
74
|
-
[:row, %w{The Blanks},
|
75
|
-
[:tag, "@tag3",
|
76
|
-
[:tag, "@tag4",
|
77
|
-
[:scenario, "Scenario", "Reading a Scenario", "",
|
78
|
-
[:step, "Given ", "there is a step",
|
79
|
-
[:step, "But ", "not another step",
|
80
|
-
[:tag, "@tag3",
|
81
|
-
[:scenario, "Scenario", "Reading a second scenario", "With two lines of text",
|
82
|
-
[:step, "Given ", "a third step with a table",
|
83
|
-
[:row, %w{a b},
|
84
|
-
[:row, %w{c d},
|
85
|
-
[:row, %w{e f},
|
86
|
-
[:step, "Given ", "I am still testing things",
|
87
|
-
[:row, %w{g h},
|
88
|
-
[:row, %w{e r},
|
89
|
-
[:row, %w{k i},
|
90
|
-
[:row, ['n', ''],
|
91
|
-
[:step, "Given ", "I am done testing these tables",
|
92
|
-
[:step, "Given ", "I am happy",
|
93
|
-
[:scenario, "Scenario", "Hammerzeit", "",
|
94
|
-
[:step, "Given ", "All work and no play",
|
95
|
-
[:py_string, "Makes Homer something something\nAnd something else",
|
96
|
-
[:step, "Given ", "crazy",
|
56
|
+
[:tag, "@foo", nil],
|
57
|
+
[:scenario_outline, "Scenario Outline", "An Scenario Outline","", nil],
|
58
|
+
[:step, "Given ", "A step with a table", nil],
|
59
|
+
[:row, %w{a row for a step}, nil],
|
60
|
+
[:tag, "@exampletag", nil],
|
61
|
+
[:examples, "Examples", "Sweet Example", "", nil],
|
62
|
+
[:row, %w{Fill In}, nil],
|
63
|
+
[:row, %w{The Blanks}, nil],
|
64
|
+
[:tag, "@tag3", nil],
|
65
|
+
[:tag, "@tag4", nil],
|
66
|
+
[:scenario, "Scenario", "Reading a Scenario", "", nil],
|
67
|
+
[:step, "Given ", "there is a step", nil],
|
68
|
+
[:step, "But ", "not another step", nil],
|
69
|
+
[:tag, "@tag3", nil],
|
70
|
+
[:scenario, "Scenario", "Reading a second scenario", "With two lines of text", nil],
|
71
|
+
[:step, "Given ", "a third step with a table", nil],
|
72
|
+
[:row, %w{a b}, 987],
|
73
|
+
[:row, %w{c d}, nil],
|
74
|
+
[:row, %w{e f}, nil],
|
75
|
+
[:step, "Given ", "I am still testing things", nil],
|
76
|
+
[:row, %w{g h}, nil],
|
77
|
+
[:row, %w{e r}, nil],
|
78
|
+
[:row, %w{k i}, nil],
|
79
|
+
[:row, ['n', ''], nil],
|
80
|
+
[:step, "Given ", "I am done testing these tables", nil],
|
81
|
+
[:step, "Given ", "I am happy", nil],
|
82
|
+
[:scenario, "Scenario", "Hammerzeit", "", nil],
|
83
|
+
[:step, "Given ", "All work and no play", nil],
|
84
|
+
[:py_string, "Makes Homer something something\nAnd something else", 777],
|
85
|
+
[:step, "Given ", "crazy", nil],
|
97
86
|
[:eof]
|
98
87
|
]
|
99
88
|
end
|
data/tasks/release.rake
CHANGED
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gherkin
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 1
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 2
|
8
8
|
- 1
|
9
|
-
-
|
10
|
-
version: 2.1.
|
9
|
+
- 5
|
10
|
+
version: 2.1.5
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Mike Sassak
|
@@ -17,7 +17,7 @@ autorequire:
|
|
17
17
|
bindir: bin
|
18
18
|
cert_chain: []
|
19
19
|
|
20
|
-
date: 2010-07-
|
20
|
+
date: 2010-07-17 00:00:00 +02:00
|
21
21
|
default_executable: gherkin
|
22
22
|
dependencies:
|
23
23
|
- !ruby/object:Gem::Dependency
|
@@ -37,43 +37,59 @@ dependencies:
|
|
37
37
|
type: :runtime
|
38
38
|
version_requirements: *id001
|
39
39
|
- !ruby/object:Gem::Dependency
|
40
|
-
name:
|
40
|
+
name: awesome_print
|
41
41
|
prerelease: false
|
42
42
|
requirement: &id002 !ruby/object:Gem::Requirement
|
43
43
|
none: false
|
44
44
|
requirements:
|
45
45
|
- - ~>
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
hash:
|
47
|
+
hash: 21
|
48
|
+
segments:
|
49
|
+
- 0
|
50
|
+
- 2
|
51
|
+
- 1
|
52
|
+
version: 0.2.1
|
53
|
+
type: :development
|
54
|
+
version_requirements: *id002
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec
|
57
|
+
prerelease: false
|
58
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
59
|
+
none: false
|
60
|
+
requirements:
|
61
|
+
- - ~>
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
hash: 62196417
|
48
64
|
segments:
|
49
65
|
- 2
|
50
66
|
- 0
|
51
67
|
- 0
|
52
68
|
- beta
|
53
|
-
-
|
54
|
-
version: 2.0.0.beta.
|
69
|
+
- 17
|
70
|
+
version: 2.0.0.beta.17
|
55
71
|
type: :development
|
56
|
-
version_requirements: *
|
72
|
+
version_requirements: *id003
|
57
73
|
- !ruby/object:Gem::Dependency
|
58
74
|
name: cucumber
|
59
75
|
prerelease: false
|
60
|
-
requirement: &
|
76
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
61
77
|
none: false
|
62
78
|
requirements:
|
63
79
|
- - ~>
|
64
80
|
- !ruby/object:Gem::Version
|
65
|
-
hash:
|
81
|
+
hash: 53
|
66
82
|
segments:
|
67
83
|
- 0
|
68
84
|
- 8
|
69
|
-
-
|
70
|
-
version: 0.8.
|
85
|
+
- 5
|
86
|
+
version: 0.8.5
|
71
87
|
type: :development
|
72
|
-
version_requirements: *
|
88
|
+
version_requirements: *id004
|
73
89
|
- !ruby/object:Gem::Dependency
|
74
90
|
name: rake-compiler
|
75
91
|
prerelease: false
|
76
|
-
requirement: &
|
92
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
77
93
|
none: false
|
78
94
|
requirements:
|
79
95
|
- - ~>
|
@@ -85,7 +101,7 @@ dependencies:
|
|
85
101
|
- 0
|
86
102
|
version: 0.7.0
|
87
103
|
type: :development
|
88
|
-
version_requirements: *
|
104
|
+
version_requirements: *id005
|
89
105
|
description: A fast Gherkin lexer/parser based on the Ragel State Machine Compiler.
|
90
106
|
email: cukes@googlegroups.com
|
91
107
|
executables:
|
@@ -316,6 +332,7 @@ files:
|
|
316
332
|
- spec/gherkin/fixtures/i18n_no.feature
|
317
333
|
- spec/gherkin/fixtures/i18n_zh-CN.feature
|
318
334
|
- spec/gherkin/fixtures/scenario_outline_with_tags.feature
|
335
|
+
- spec/gherkin/fixtures/scenario_without_steps.feature
|
319
336
|
- spec/gherkin/fixtures/simple_with_comments.feature
|
320
337
|
- spec/gherkin/fixtures/simple_with_tags.feature
|
321
338
|
- spec/gherkin/fixtures/with_bom.feature
|