gherkin 2.0.2 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. data/History.txt +12 -0
  2. data/LICENSE +1 -1
  3. data/README.rdoc +2 -2
  4. data/Rakefile +2 -2
  5. data/VERSION.yml +2 -2
  6. data/features/json_formatter.feature +3 -41
  7. data/features/step_definitions/gherkin_steps.rb +5 -6
  8. data/features/step_definitions/json_formatter_steps.rb +3 -2
  9. data/features/step_definitions/json_lexer_steps.rb +5 -5
  10. data/features/step_definitions/pretty_formatter_steps.rb +9 -13
  11. data/features/support/env.rb +1 -1
  12. data/lib/gherkin/formatter/argument.rb +1 -0
  13. data/lib/gherkin/formatter/filter_formatter.rb +149 -0
  14. data/lib/gherkin/formatter/json_formatter.rb +35 -45
  15. data/lib/gherkin/formatter/line_filter.rb +26 -0
  16. data/lib/gherkin/formatter/model.rb +85 -0
  17. data/lib/gherkin/formatter/pretty_formatter.rb +36 -39
  18. data/lib/gherkin/formatter/regexp_filter.rb +17 -0
  19. data/lib/gherkin/formatter/tag_count_formatter.rb +44 -0
  20. data/lib/gherkin/i18n.rb +5 -5
  21. data/lib/gherkin/i18n.yml +13 -0
  22. data/lib/gherkin/i18n_lexer.rb +2 -2
  23. data/lib/gherkin/{json_lexer.rb → json_parser.rb} +17 -5
  24. data/lib/gherkin/{parser → listener}/event.rb +1 -1
  25. data/lib/gherkin/{parser → listener}/formatter_listener.rb +30 -23
  26. data/lib/gherkin/native/java.rb +9 -1
  27. data/lib/gherkin/parser/parser.rb +27 -14
  28. data/lib/gherkin/rubify.rb +5 -1
  29. data/lib/gherkin/tag_expression.rb +62 -0
  30. data/lib/gherkin/tools/files.rb +3 -4
  31. data/lib/gherkin/tools/reformat.rb +2 -2
  32. data/lib/gherkin/tools/stats.rb +3 -4
  33. data/lib/gherkin/tools/stats_listener.rb +1 -1
  34. data/ragel/lexer.c.rl.erb +2 -3
  35. data/ragel/lexer.java.rl.erb +1 -2
  36. data/ragel/lexer.rb.rl.erb +1 -2
  37. data/spec/gherkin/fixtures/complex_for_filtering.feature +60 -0
  38. data/spec/gherkin/fixtures/complex_with_tags.feature +61 -0
  39. data/spec/gherkin/fixtures/hantu_pisang.feature +35 -0
  40. data/spec/gherkin/formatter/filter_formatter_spec.rb +156 -0
  41. data/spec/gherkin/formatter/model_spec.rb +15 -0
  42. data/spec/gherkin/formatter/pretty_formatter_spec.rb +17 -16
  43. data/spec/gherkin/formatter/tag_count_formatter_spec.rb +31 -0
  44. data/spec/gherkin/i18n_lexer_spec.rb +3 -3
  45. data/spec/gherkin/i18n_spec.rb +2 -4
  46. data/spec/gherkin/{json_lexer_spec.rb → json_parser_spec.rb} +13 -8
  47. data/spec/gherkin/sexp_recorder.rb +10 -4
  48. data/spec/gherkin/shared/lexer_group.rb +0 -40
  49. data/spec/gherkin/shared/py_string_group.rb +0 -1
  50. data/spec/gherkin/shared/row_group.rb +1 -2
  51. data/spec/gherkin/tag_expression_spec.rb +137 -0
  52. data/spec/spec_helper.rb +5 -1
  53. data/tasks/bench.rake +5 -9
  54. metadata +35 -25
  55. data/lib/gherkin/parser/filter_listener.rb +0 -203
  56. data/lib/gherkin/parser/row.rb +0 -15
  57. data/lib/gherkin/parser/tag_expression.rb +0 -50
  58. data/spec/gherkin/parser/filter_listener_spec.rb +0 -397
  59. data/spec/gherkin/parser/formatter_listener_spec.rb +0 -134
  60. data/spec/gherkin/parser/parser_spec.rb +0 -50
  61. data/spec/gherkin/parser/tag_expression_spec.rb +0 -116
@@ -1,15 +0,0 @@
1
- require 'gherkin/native'
2
-
3
- module Gherkin
4
- module Parser
5
- class Row
6
- native_impl('gherkin')
7
-
8
- attr_reader :cells, :comments, :line
9
-
10
- def initialize(cells, comments, line)
11
- @cells, @comments, @line = cells, comments, line
12
- end
13
- end
14
- end
15
- end
@@ -1,50 +0,0 @@
1
- require 'gherkin/native'
2
-
3
- module Gherkin
4
- module Parser
5
- class TagExpression
6
- native_impl('gherkin')
7
-
8
- attr_reader :limits
9
-
10
- def initialize(tag_expressions)
11
- @ands = []
12
- @limits = {}
13
- tag_expressions.each do |expr|
14
- add(expr.strip.split(/\s*,\s*/))
15
- end
16
- end
17
-
18
- def empty?
19
- @ands.empty?
20
- end
21
-
22
- def eval(tags)
23
- return true if @ands.flatten.empty?
24
- vars = Hash[*tags.map{|tag| [tag, true]}.flatten]
25
- !!Kernel.eval(ruby_expression)
26
- end
27
-
28
- private
29
-
30
- def add(tags)
31
- negatives, positives = tags.partition{|tag| tag =~ /^~/}
32
- positive_limits = Hash[*positives.map{|positive| tag, limit = positive.split(':'); [tag, limit ? limit.to_i : nil]}.flatten]
33
- @limits.merge!(positive_limits)
34
- @ands << (negatives + positive_limits.keys)
35
- end
36
-
37
- def ruby_expression
38
- "(" + @ands.map do |ors|
39
- ors.map do |tag|
40
- if tag =~ /^~(.*)/
41
- "!vars['#{$1}']"
42
- else
43
- "vars['#{tag}']"
44
- end
45
- end.join("||")
46
- end.join(")&&(") + ")"
47
- end
48
- end
49
- end
50
- end
@@ -1,397 +0,0 @@
1
- # encoding: utf-8
2
- require 'spec_helper'
3
- require 'gherkin/parser/filter_listener'
4
- require 'gherkin/parser/formatter_listener'
5
- require 'gherkin/formatter/pretty_formatter'
6
- require 'stringio'
7
-
8
- module Gherkin
9
- module Parser
10
- describe FilterListener do
11
-
12
- class LineListener
13
- attr_reader :lines
14
-
15
- def location(uri, offset)
16
- end
17
-
18
- def method_missing(*sexp_args)
19
- @lines ||= []
20
- raise "Hmm" if sexp_args == [:eof, []]
21
- @lines << sexp_args[-1]
22
- end
23
- end
24
-
25
- def verify_filters(expected_lines, filters)
26
- line_listener = LineListener.new
27
- scan(line_listener, filters)
28
- line_listener.lines.should == expected_lines
29
- end
30
-
31
- def verify_output(expected_output, filters)
32
- io = StringIO.new
33
- formatter = Gherkin::Formatter::PrettyFormatter.new(io, true)
34
- listener = Gherkin::Parser::FormatterListener.new(formatter)
35
- scan(listener, filters)
36
- io.string.should == expected_output
37
- end
38
-
39
- def scan(listener, filters)
40
- filter_listener = Gherkin::Parser::FilterListener.new(listener, filters)
41
- parser = Gherkin::Parser::Parser.new(filter_listener, true, "root")
42
- lexer = Gherkin::I18nLexer.new(parser, true)
43
- lexer.scan(@input, "test.feature", 0)
44
- end
45
-
46
- context "Scenario" do
47
- before do
48
- @input = %{Feature: 1
49
- Scenario: 2
50
- Given 3
51
-
52
- Scenario: 5
53
- Given 6
54
- }
55
- end
56
-
57
- it "should not replay anything if no lines match" do
58
- verify_filters([:eof], [90])
59
- end
60
-
61
- it "should not replay anything if no names match" do
62
- verify_filters([:eof], [/pudding/])
63
- end
64
-
65
- it "should replay identically when there is no filter" do
66
- verify_filters([1,2,3,5,6,:eof], [])
67
- end
68
-
69
- it "should replay identically when line filter is feature line" do
70
- verify_filters([1,2,3,5,6,:eof], [1])
71
- end
72
-
73
- it "should match scenario line of first scenario" do
74
- verify_filters([1,2,3,:eof], [2])
75
- end
76
-
77
- it "should match name of first scenario" do
78
- verify_filters([1,2,3,:eof], [/2/])
79
- end
80
-
81
- it "should match step line of first scenario" do
82
- verify_filters([1,2,3,:eof], [3])
83
- end
84
-
85
- it "should match step line of second scenario" do
86
- verify_filters([1,5,6,:eof], [6])
87
- end
88
-
89
- it "should replay identically (except newlines) when the filter matches both scenarios" do
90
- verify_filters([1,2,3,5,6,:eof], [3,6])
91
- end
92
- end
93
-
94
- context "Scenario with py_string" do
95
- before do
96
- @input = %{Feature: 1
97
- Scenario: 2
98
- Given 3
99
- """
100
- 5
101
- """
102
-
103
- Scenario: 8
104
- Given 9
105
- }
106
- end
107
-
108
- it "should replay identically when there is no filter" do
109
- verify_filters([1,2,3,4,8,9,:eof], {})
110
- end
111
-
112
- it "should filter on py_string line" do
113
- verify_filters([1,2,3,4,:eof], [4])
114
- end
115
- end
116
-
117
- context "Scenario with Table and Comment and Tag" do
118
- before do
119
- @input = %{#language:en
120
- Feature: 2
121
- # 3
122
- Scenario: 4
123
- Given 5
124
- When 6
125
-
126
- @tag8
127
- Scenario: 9
128
- Given 10
129
- When 11
130
- | 12 | 12 |
131
- | 13 | 13 |
132
- }
133
- end
134
-
135
- it "should replay identically when there is no filter" do
136
- verify_filters([1,2,3,4,5,6,8,9,10,11,12,13,:eof], [])
137
- end
138
-
139
- it "should match step line of first scenario" do
140
- verify_filters([1,2,3,4,5,6,:eof], [5])
141
- end
142
-
143
- it "should match scenario line of second scenario" do
144
- verify_filters([1,2,8,9,10,11,12,13,:eof], [9])
145
- end
146
-
147
- it "should match tag of second scenario" do
148
- verify_filters([1,2,8,9,10,11,12,13,:eof], ['@tag8'])
149
- end
150
-
151
- it "should return everything when a line is given in each scenario" do
152
- verify_filters([1,2,3,4,5,6,8,9,10,11,12,13,:eof], [6,9])
153
- end
154
-
155
- it "should return a scenario when a line is given for its tag" do
156
- verify_filters([1,2,8,9,10,11,12,13,:eof], [8])
157
- end
158
-
159
- it "should return a scenario when a line is given for its comment" do
160
- verify_filters([1,2,3,4,5,6,:eof], [3])
161
- end
162
- end
163
-
164
- context "Scenario with Background and Comment" do
165
- before do
166
- @input = %{#language:en
167
- Feature: 2
168
- # 3
169
- Background: 4
170
- Given 5
171
-
172
- # 7
173
- Scenario: 8
174
- Given 9
175
- When 10
176
-
177
- Scenario: 12
178
- Given 13
179
- When 14
180
- | 15 | 16 |
181
- | 15 | 16 |
182
- }
183
- end
184
-
185
- it "should replay identically when there is no filter" do
186
- verify_filters([1,2,3,4,5,7,8,9,10,12,13,14,15,16,:eof], [])
187
- end
188
-
189
- it "should not replay any scenarios when filtering on the line of a background step" do
190
- verify_filters([1,2,3,4,5,:eof], [5])
191
- end
192
-
193
- it "should not replay any scenarios when filtering on the line of the background" do
194
- verify_filters([1,2,3,4,5,:eof], [4])
195
- end
196
-
197
- it "should replay the background on step line of first scenario" do
198
- verify_filters([1,2,3,4,5,7,8,9,10,:eof], [9])
199
- end
200
- end
201
-
202
- context "Scenario Outline" do
203
- before do
204
- @input = %{Feature: Fname
205
- Fdesc
206
- @tag3
207
- Scenario Outline: 4
208
- Given <foo> 5
209
- When <bar> 6
210
-
211
- @tag8
212
- Examples: 9
213
- | foo | bar |
214
- | 11 | 11 |
215
- | 12 | 12 |
216
- | 13 | 13 |
217
- | 14 | 14 |
218
- | 15 | 15 |
219
-
220
- @tag17
221
- Examples: 18
222
- | snip | snap |
223
- | 20 | 20 |
224
- | 21 | 21 |
225
-
226
- Scenario: 23
227
- Given 24
228
- When 25
229
- }
230
- end
231
-
232
- it "should match step line of first scenario outline" do
233
- verify_filters([1,3,4,5,6,8,9,10,11,12,13,14,15,17,18,19,20,21,:eof], [6])
234
- end
235
-
236
- it "should match examples line of second scenario outline" do
237
- verify_filters([1,3,4,5,6,17,18,19,20,21,:eof], [18])
238
- end
239
-
240
- it "should match examples name of second scenario outline" do
241
- verify_filters([1,3,4,5,6,17,18,19,20,21,:eof], [/18/])
242
- end
243
-
244
- it "should match header row line of second scenario outline" do
245
- verify_filters([1,3,4,5,6,17,18,19,20,21,:eof], [19])
246
- end
247
-
248
- it "should match an example row of first scenario outline" do
249
- verify_filters([1,3,4,5,6,8,9,10,13,:eof], [13])
250
- end
251
-
252
- it "should match an example row of second scenario outline" do
253
- verify_filters([1,3,4,5,6,17,18,19,20,:eof], [20])
254
- end
255
-
256
- it "should match 2 example rows of first scenario outline" do
257
- verify_filters([1,3,4,5,6,8,9,10,12,14,:eof], [12,14])
258
- end
259
-
260
- it "should replay itself properly" do
261
- filtered = %{Feature: Fname
262
- Fdesc
263
-
264
- @tag3
265
- Scenario Outline: 4
266
- Given <foo> 5
267
- When <bar> 6
268
-
269
- @tag8
270
- Examples: 9
271
- | foo | bar |
272
- | 12 | 12 |
273
- | 14 | 14 |
274
- }
275
-
276
- verify_output(filtered, [12,14])
277
- end
278
- end
279
-
280
- context "Scenarios with tags on both feature and scenarios" do
281
- before do
282
- # Lines with more than one tag per line will be repeated
283
- @input = %{#language:en
284
- @a @b
285
- Feature: 3
286
- @c @d
287
- Scenario: 5
288
- Given 6
289
-
290
- @c @e
291
- Scenario: 9
292
- Given 10
293
-
294
- Scenario: 12
295
- Given 13
296
- }
297
- end
298
-
299
- it "should match @d" do
300
- verify_filters([1,2,2,3,4,4,5,6,:eof], ['@d'])
301
- end
302
-
303
- it "should match everything when feature tag matches" do
304
- verify_filters([1,2,2,3,4,4,5,6,8,8,9,10,12,13,:eof], ['@a'])
305
- end
306
-
307
- it "should match @a && !@d" do
308
- verify_filters([1,2,2,3,8,8,9,10,12,13,:eof], ['@a','~@d'])
309
- end
310
-
311
- it "should match @d || @e" do
312
- verify_filters([1,2,2,3,4,4,5,6,8,8,9,10,:eof], ['@d,@e'])
313
- end
314
- end
315
-
316
- context "Scenario Outlines with tags on examples" do
317
- before do
318
- # Lines with more than one tag per line will be repeated
319
- @input = %{#language:en
320
- @a @b
321
- Feature: 3
322
- @d
323
- Scenario Outline: 5
324
- Given 6
325
-
326
- @c @e
327
- Examples: 9
328
- | foo | bar |
329
- | 11 | 11 |
330
-
331
- @d @f
332
- Examples: 14
333
- | foo | bar |
334
- | 16 | 16 |
335
- | 17 | 17 |
336
-
337
- Scenario: 19
338
- Given 20
339
- }
340
- end
341
-
342
- it "should match @c" do
343
- verify_filters([1,2,2,3,4,5,6,8,8,9,10,11,:eof], ['@c'])
344
- end
345
-
346
- it "should match @d" do
347
- verify_filters([1,2,2,3,4,5,6,8,8,9,10,11,13,13,14,15,16,17,:eof], ['@d'])
348
- end
349
-
350
- it "should match @f" do
351
- verify_filters([1,2,2,3,4,5,6,13,13,14,15,16,17,:eof], ['@f'])
352
- end
353
-
354
- it "should match @a and not @c" do
355
- verify_filters([1,2,2,3,4,5,6,13,13,14,15,16,17,19,20,:eof], ['@a','~@c'])
356
- end
357
-
358
- it "should match @c or @d" do
359
- verify_filters([1,2,2,3,4,5,6,8,8,9,10,11,13,13,14,15,16,17,:eof], ['@c,@d'])
360
- end
361
-
362
- it "should not match @m" do
363
- verify_filters([:eof], ['@m'])
364
- end
365
- end
366
-
367
- context "Background with PyString" do
368
- before do
369
- @input = %{#language:en
370
- Feature: 2
371
- Background: 3
372
- Given 4
373
- """
374
- 6
375
- """
376
-
377
- Scenario: 9
378
- Given 10
379
- """
380
- 12
381
- """
382
-
383
- Scenario: 15
384
- Given 16
385
- """
386
- 18
387
- """
388
- }
389
- end
390
-
391
- it "should replay itself properly" do
392
- verify_filters([1,2,3,4,5,15,16,17,:eof], [15])
393
- end
394
- end
395
- end
396
- end
397
- end