kosmas58-cucumber 0.2.2.1 → 0.2.3.3

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.
Files changed (101) hide show
  1. data/History.txt +57 -5
  2. data/Manifest.txt +21 -4
  3. data/bin/cucumber +1 -1
  4. data/config/hoe.rb +2 -2
  5. data/examples/i18n/Rakefile +6 -8
  6. data/examples/i18n/ar/features/step_definitons/calculator_steps.rb +1 -1
  7. data/examples/i18n/ar/lib/calculator.rb +1 -0
  8. data/examples/i18n/da/features/step_definitons/kalkulator_steps.rb +1 -1
  9. data/examples/i18n/de/features/step_definitons/calculator_steps.rb +1 -1
  10. data/examples/i18n/en/features/step_definitons/calculator_steps.rb +1 -1
  11. data/examples/i18n/es/features/step_definitons/calculador_steps.rb +1 -1
  12. data/examples/i18n/et/features/step_definitions/kalkulaator_steps.rb +1 -1
  13. data/examples/i18n/fi/features/step_definitons/laskin_steps.rb +1 -1
  14. data/examples/i18n/fr/features/step_definitions/calculatrice_steps.rb +1 -1
  15. data/examples/i18n/id/features/step_definitons/calculator_steps.rb +1 -1
  16. data/examples/i18n/it/features/step_definitons/calcolatrice_steps.rb +1 -1
  17. data/examples/i18n/ja/features/step_definitons/calculator_steps.rb +1 -1
  18. data/examples/i18n/ko/features/addition.feature +1 -1
  19. data/examples/i18n/ko/features/step_definitons/calculator_steps.rb +1 -1
  20. data/examples/i18n/lt/features/step_definitons/calculator_steps.rb +1 -1
  21. data/examples/i18n/no/features/support/env.rb +1 -1
  22. data/examples/i18n/pt/features/step_definitions/calculadora_steps.rb +1 -1
  23. data/examples/i18n/ro/features/step_definitons/calculator_steps.rb +1 -1
  24. data/examples/i18n/ru/features/support/env.rb +1 -1
  25. data/examples/i18n/ru/features/support/world.rb +4 -3
  26. data/examples/i18n/se/features/step_definitons/kalkulator_steps.rb +1 -1
  27. data/examples/i18n/sk/Rakefile +6 -0
  28. data/examples/i18n/sk/features/addition.feature +16 -0
  29. data/examples/i18n/sk/features/division.feature +9 -0
  30. data/examples/i18n/sk/features/step_definitons/calculator_steps.rb +24 -0
  31. data/examples/i18n/sk/lib/calculator.rb +14 -0
  32. data/examples/i18n/zh-CN/features/step_definitons/calculator_steps.rb +1 -1
  33. data/examples/i18n/zh-TW/features/step_definitons/calculator_steps.rb +1 -1
  34. data/examples/self_test/features/background/background_with_name.feature +7 -0
  35. data/examples/self_test/features/step_definitions/sample_steps.rb +8 -2
  36. data/examples/self_test/features/undefined_multiline_args.feature +12 -0
  37. data/examples/sinatra/features/support/env.rb +2 -6
  38. data/examples/test_unit/features/step_definitions/test_unit_steps.rb +1 -4
  39. data/examples/tickets/Rakefile +1 -1
  40. data/examples/tickets/features/246.feature +4 -0
  41. data/examples/tickets/features/270/back.feature +14 -0
  42. data/examples/tickets/features/270/back.steps.rb +14 -0
  43. data/examples/tickets/features/step_definitons/246_steps.rb +3 -0
  44. data/features/background.feature +21 -4
  45. data/features/cucumber_cli.feature +18 -5
  46. data/features/cucumber_cli_outlines.feature +5 -2
  47. data/features/snippet.feature +23 -0
  48. data/features/step_definitions/cucumber_steps.rb +6 -2
  49. data/features/usage.feature +5 -0
  50. data/gem_tasks/rspec.rake +3 -2
  51. data/lib/cucumber/ast/background.rb +3 -3
  52. data/lib/cucumber/ast/examples.rb +0 -12
  53. data/lib/cucumber/ast/feature.rb +2 -12
  54. data/lib/cucumber/ast/feature_element.rb +0 -8
  55. data/lib/cucumber/ast/features.rb +1 -1
  56. data/lib/cucumber/ast/outline_table.rb +14 -22
  57. data/lib/cucumber/ast/py_string.rb +6 -11
  58. data/lib/cucumber/ast/scenario.rb +1 -8
  59. data/lib/cucumber/ast/scenario_outline.rb +1 -11
  60. data/lib/cucumber/ast/step.rb +3 -9
  61. data/lib/cucumber/ast/step_collection.rb +0 -4
  62. data/lib/cucumber/ast/step_invocation.rb +5 -6
  63. data/lib/cucumber/ast/table.rb +26 -22
  64. data/lib/cucumber/ast/tags.rb +0 -8
  65. data/lib/cucumber/ast/visitor.rb +12 -25
  66. data/lib/cucumber/cli/configuration.rb +2 -2
  67. data/lib/cucumber/cli/main.rb +5 -2
  68. data/lib/cucumber/core_ext/instance_exec.rb +17 -4
  69. data/lib/cucumber/formatter/ansicolor.rb +10 -2
  70. data/lib/cucumber/formatter/console.rb +2 -1
  71. data/lib/cucumber/formatter/html.rb +21 -7
  72. data/lib/cucumber/formatter/pretty.rb +27 -20
  73. data/lib/cucumber/formatter/usage.rb +16 -0
  74. data/lib/cucumber/languages.yml +68 -7
  75. data/lib/cucumber/parser/feature.rb +238 -135
  76. data/lib/cucumber/parser/feature.tt +117 -22
  77. data/lib/cucumber/parser/i18n.tt +4 -0
  78. data/lib/cucumber/parser/table.rb +37 -25
  79. data/lib/cucumber/parser/table.tt +15 -3
  80. data/lib/cucumber/parser/treetop_ext.rb +48 -9
  81. data/lib/cucumber/parser.rb +2 -7
  82. data/lib/cucumber/step_definition.rb +13 -14
  83. data/lib/cucumber/step_mother.rb +93 -11
  84. data/lib/cucumber/version.rb +2 -2
  85. data/rails_generators/cucumber/templates/env.rb +1 -1
  86. data/rails_generators/cucumber/templates/paths.rb +15 -5
  87. data/rails_generators/cucumber/templates/webrat_steps.rb +8 -0
  88. data/spec/cucumber/ast/background_spec.rb +1 -0
  89. data/spec/cucumber/ast/feature_factory.rb +1 -1
  90. data/spec/cucumber/ast/feature_spec.rb +2 -2
  91. data/spec/cucumber/ast/scenario_spec.rb +0 -27
  92. data/spec/cucumber/ast/table_spec.rb +23 -2
  93. data/spec/cucumber/core_ext/proc_spec.rb +25 -8
  94. data/spec/cucumber/parser/feature_parser_spec.rb +43 -41
  95. data/spec/cucumber/step_definition_spec.rb +8 -0
  96. data/spec/cucumber/step_mother_spec.rb +48 -0
  97. data/spec/spec_helper.rb +2 -11
  98. metadata +17 -6
  99. data/examples/tickets/cucumber.yml +0 -3
  100. data/lib/cucumber/parser/basic.rb +0 -0
  101. data/spec/cucumber/ast/tags_spec.rb +0 -19
@@ -20,25 +20,42 @@ module Cucumber
20
20
  bg:background?
21
21
  feature_elements
22
22
  comment? {
23
- def build
24
- background = bg.respond_to?(:build) ? bg.build : nil
25
- Ast::Feature.new(
26
- background,
27
- comment.build,
28
- tags.build,
29
- header.text_value,
30
- feature_elements.build(background)
31
- )
23
+ def has_tags?(tag_names)
24
+ tags.has_tags?(tag_names)
25
+ end
26
+
27
+ def build(filter)
28
+ if(filter.nil? || feature_elements.accept?(filter))
29
+ background = bg.respond_to?(:build) ? bg.build : nil
30
+ Ast::Feature.new(
31
+ background,
32
+ comment.build,
33
+ tags.build,
34
+ header.text_value,
35
+ feature_elements.build(background, filter)
36
+ )
37
+ end
32
38
  end
33
39
  }
34
40
  end
35
41
 
36
42
  rule tags
37
43
  white ts:(tag (space/eol)+)* {
44
+ def at_line?(line)
45
+ ts.elements.detect{|e| e.tag.line == line}
46
+ end
47
+
48
+ def has_tags?(tags)
49
+ tag_names.detect{|tag_name| tags.index(tag_name)}
50
+ end
51
+
38
52
  def build
39
- tag_names = ts.elements.map{|e| e.tag.tag_name.text_value}
40
53
  Ast::Tags.new(ts.line, tag_names)
41
54
  end
55
+
56
+ def tag_names
57
+ ts.elements.map{|e| e.tag.tag_name.text_value}
58
+ end
42
59
  }
43
60
  end
44
61
 
@@ -59,12 +76,13 @@ module Cucumber
59
76
  end
60
77
 
61
78
  rule background
62
- comment white background_keyword space* (eol+ / eof) steps {
79
+ comment white background_keyword space* name:line_to_eol? (eol+ / eof) steps {
63
80
  def build
64
81
  Ast::Background.new(
65
82
  comment.build,
66
83
  background_keyword.line,
67
- background_keyword.text_value,
84
+ background_keyword.text_value,
85
+ name.text_value,
68
86
  steps.build
69
87
  )
70
88
  end
@@ -73,15 +91,38 @@ module Cucumber
73
91
 
74
92
  rule feature_elements
75
93
  (scenario / scenario_outline)* {
76
- def build(background)
77
- elements.map{|s| s.build(background)}
94
+ def accept?(filter)
95
+ filter.nil? || elements.empty? || elements.detect{|feature_element| filter.accept?(feature_element)}
96
+ end
97
+
98
+ def build(background, filter)
99
+ elements.map do |feature_element|
100
+ if filter.nil? || filter.accept?(feature_element)
101
+ feature_element.build(background, filter)
102
+ end
103
+ end.compact
78
104
  end
79
105
  }
80
106
  end
81
107
 
82
108
  rule scenario
83
109
  comment tags white scenario_keyword space* name:line_to_eol white steps white {
84
- def build(background)
110
+ def at_line?(line)
111
+ scenario_keyword.line == line ||
112
+ steps.at_line?(line) ||
113
+ tags.at_line?(line)
114
+ end
115
+
116
+ def has_tags?(tag_names)
117
+ feature_tags = self.parent.parent.tags
118
+ tags.has_tags?(tag_names) || feature_tags.has_tags?(tag_names)
119
+ end
120
+
121
+ def matches_name?(name_to_match)
122
+ name.text_value == name_to_match
123
+ end
124
+
125
+ def build(background, filter)
85
126
  Ast::Scenario.new(
86
127
  background,
87
128
  comment.build,
@@ -97,7 +138,27 @@ module Cucumber
97
138
 
98
139
  rule scenario_outline
99
140
  comment tags white scenario_outline_keyword space* name:line_to_eol white steps examples_sections white {
100
- def build(background)
141
+ def at_line?(line)
142
+ outline_at_line?(line) ||
143
+ examples_sections.at_line?(line) ||
144
+ tags.at_line?(line)
145
+ end
146
+
147
+ def outline_at_line?(line)
148
+ scenario_outline_keyword.line == line ||
149
+ steps.at_line?(line)
150
+ end
151
+
152
+ def has_tags?(tag_names)
153
+ feature_tags = self.parent.parent.tags
154
+ tags.has_tags?(tag_names) || feature_tags.has_tags?(tag_names)
155
+ end
156
+
157
+ def matches_name?(name_to_match)
158
+ name.text_value == name_to_match
159
+ end
160
+
161
+ def build(background, filter)
101
162
  Ast::ScenarioOutline.new(
102
163
  background,
103
164
  comment.build,
@@ -106,7 +167,7 @@ module Cucumber
106
167
  scenario_outline_keyword.text_value,
107
168
  name.text_value,
108
169
  steps.build,
109
- examples_sections.build
170
+ examples_sections.build(filter, self)
110
171
  )
111
172
  end
112
173
  }
@@ -114,6 +175,10 @@ module Cucumber
114
175
 
115
176
  rule steps
116
177
  step* {
178
+ def at_line?(line)
179
+ elements.detect{|e| e.at_line?(line)}
180
+ end
181
+
117
182
  def build
118
183
  elements.map{|e| e.build}
119
184
  end
@@ -121,7 +186,12 @@ module Cucumber
121
186
  end
122
187
 
123
188
  rule step
124
- comment space* step_keyword space* name:line_to_eol (eol+ / eof) multi:multiline_arg? white {
189
+ comment space* step_keyword keyword_space name:line_to_eol (eol+ / eof) multi:multiline_arg? white {
190
+ def at_line?(line)
191
+ step_keyword.line == line ||
192
+ (multi.respond_to?(:at_line?) && multi.at_line?(line))
193
+ end
194
+
125
195
  def build
126
196
  if multi.respond_to?(:build)
127
197
  Ast::Step.new(step_keyword.line, step_keyword.text_value, name.text_value.strip, multi.build)
@@ -134,16 +204,37 @@ module Cucumber
134
204
 
135
205
  rule examples_sections
136
206
  examples* {
137
- def build
138
- elements.map{|e| e.build}
207
+ def at_line?(line)
208
+ elements.detect { |e| e.at_line?(line) }
209
+ end
210
+
211
+ def build(filter, scenario_outline)
212
+ elements.map do |e|
213
+ if(filter.nil? || filter.accept?(e) || filter.outline_at_line?(scenario_outline))
214
+ e.build(filter, scenario_outline)
215
+ end
216
+ end.compact
139
217
  end
140
218
  }
141
219
  end
142
220
 
143
221
  rule examples
144
222
  space* examples_keyword space* name:line_to_eol? eol table white {
145
- def build
146
- [examples_keyword.line, examples_keyword.text_value, name.text_value, table.raw]
223
+ def at_line?(line)
224
+ examples_keyword.line == line ||
225
+ table.at_line?(line)
226
+ end
227
+
228
+ def has_tags?(tag_names)
229
+ true
230
+ end
231
+
232
+ def outline_at_line?(line)
233
+ true
234
+ end
235
+
236
+ def build(filter, scenario_outline)
237
+ [examples_keyword.line, examples_keyword.text_value, name.text_value, table.raw(filter, scenario_outline)]
147
238
  end
148
239
  }
149
240
  end
@@ -158,6 +249,10 @@ module Cucumber
158
249
 
159
250
  rule py_string
160
251
  open_py_string s:(!close_py_string .)* close_py_string {
252
+ def at_line?(line)
253
+ line >= open_py_string.line && line <= close_py_string.line
254
+ end
255
+
161
256
  def build
162
257
  Ast::PyString.new(open_py_string.line, close_py_string.line, s.text_value, open_py_string.indentation)
163
258
  end
@@ -22,6 +22,10 @@ module Cucumber
22
22
  (<%= keywords('but') %>)
23
23
  end
24
24
 
25
+ rule keyword_space
26
+ <%= keywords('space_after_keyword', true) ? 'space+' : 'space*' %>
27
+ end
28
+
25
29
  rule examples_keyword
26
30
  (<%= keywords('examples') %>) ':'?
27
31
  end
@@ -14,12 +14,20 @@ module Cucumber
14
14
  end
15
15
 
16
16
  module Table0
17
- def build
17
+ def at_line?(line)
18
+ elements.detect{|table_row| table_row.at_line?(line)}
19
+ end
20
+
21
+ def build(filter=nil)
18
22
  Ast::Table.new(raw)
19
23
  end
20
24
 
21
- def raw
22
- elements.map{|e| e.build}
25
+ def raw(filter=nil, scenario_outline=nil)
26
+ elements.map do |table_row|
27
+ if(filter.nil? || table_row == elements[0] || filter.at_line?(table_row) || (scenario_outline && filter.outline_at_line?(scenario_outline)))
28
+ table_row.build
29
+ end
30
+ end.compact
23
31
  end
24
32
  end
25
33
 
@@ -44,7 +52,7 @@ module Cucumber
44
52
  self.index = i0
45
53
  r0 = nil
46
54
  else
47
- r0 = SyntaxNode.new(input, i0...index, s0)
55
+ r0 = instantiate_node(SyntaxNode,input, i0...index, s0)
48
56
  r0.extend(Table0)
49
57
  end
50
58
 
@@ -68,6 +76,10 @@ module Cucumber
68
76
  end
69
77
 
70
78
  module TableRow2
79
+ def at_line?(line)
80
+ cells.line == line
81
+ end
82
+
71
83
  def build
72
84
  row = cells.elements.map do |elt|
73
85
  value = elt.cell.text_value.strip
@@ -101,11 +113,11 @@ module Cucumber
101
113
  break
102
114
  end
103
115
  end
104
- r1 = SyntaxNode.new(input, i1...index, s1)
116
+ r1 = instantiate_node(SyntaxNode,input, i1...index, s1)
105
117
  s0 << r1
106
118
  if r1
107
119
  if input.index('|', index) == index
108
- r3 = (SyntaxNode).new(input, index...(index + 1))
120
+ r3 = instantiate_node(SyntaxNode,input, index...(index + 1))
109
121
  @index += 1
110
122
  else
111
123
  terminal_parse_failure('|')
@@ -120,7 +132,7 @@ module Cucumber
120
132
  s5 << r6
121
133
  if r6
122
134
  if input.index('|', index) == index
123
- r7 = (SyntaxNode).new(input, index...(index + 1))
135
+ r7 = instantiate_node(SyntaxNode,input, index...(index + 1))
124
136
  @index += 1
125
137
  else
126
138
  terminal_parse_failure('|')
@@ -129,7 +141,7 @@ module Cucumber
129
141
  s5 << r7
130
142
  end
131
143
  if s5.last
132
- r5 = (SyntaxNode).new(input, i5...index, s5)
144
+ r5 = instantiate_node(SyntaxNode,input, i5...index, s5)
133
145
  r5.extend(TableRow0)
134
146
  else
135
147
  self.index = i5
@@ -145,7 +157,7 @@ module Cucumber
145
157
  self.index = i4
146
158
  r4 = nil
147
159
  else
148
- r4 = SyntaxNode.new(input, i4...index, s4)
160
+ r4 = instantiate_node(SyntaxNode,input, i4...index, s4)
149
161
  end
150
162
  s0 << r4
151
163
  if r4
@@ -158,7 +170,7 @@ module Cucumber
158
170
  break
159
171
  end
160
172
  end
161
- r8 = SyntaxNode.new(input, i8...index, s8)
173
+ r8 = instantiate_node(SyntaxNode,input, i8...index, s8)
162
174
  s0 << r8
163
175
  if r8
164
176
  i10 = index
@@ -175,7 +187,7 @@ module Cucumber
175
187
  self.index = i11
176
188
  r11 = nil
177
189
  else
178
- r11 = SyntaxNode.new(input, i11...index, s11)
190
+ r11 = instantiate_node(SyntaxNode,input, i11...index, s11)
179
191
  end
180
192
  if r11
181
193
  r10 = r11
@@ -194,7 +206,7 @@ module Cucumber
194
206
  end
195
207
  end
196
208
  if s0.last
197
- r0 = (SyntaxNode).new(input, i0...index, s0)
209
+ r0 = instantiate_node(SyntaxNode,input, i0...index, s0)
198
210
  r0.extend(TableRow1)
199
211
  r0.extend(TableRow2)
200
212
  else
@@ -224,7 +236,7 @@ module Cucumber
224
236
  i2 = index
225
237
  i3 = index
226
238
  if input.index('|', index) == index
227
- r4 = (SyntaxNode).new(input, index...(index + 1))
239
+ r4 = instantiate_node(SyntaxNode,input, index...(index + 1))
228
240
  @index += 1
229
241
  else
230
242
  terminal_parse_failure('|')
@@ -245,12 +257,12 @@ module Cucumber
245
257
  r2 = nil
246
258
  else
247
259
  self.index = i2
248
- r2 = SyntaxNode.new(input, index...index)
260
+ r2 = instantiate_node(SyntaxNode,input, index...index)
249
261
  end
250
262
  s1 << r2
251
263
  if r2
252
264
  if index < input_length
253
- r6 = (SyntaxNode).new(input, index...(index + 1))
265
+ r6 = instantiate_node(SyntaxNode,input, index...(index + 1))
254
266
  @index += 1
255
267
  else
256
268
  terminal_parse_failure("any character")
@@ -259,7 +271,7 @@ module Cucumber
259
271
  s1 << r6
260
272
  end
261
273
  if s1.last
262
- r1 = (SyntaxNode).new(input, i1...index, s1)
274
+ r1 = instantiate_node(SyntaxNode,input, i1...index, s1)
263
275
  r1.extend(Cell0)
264
276
  else
265
277
  self.index = i1
@@ -271,7 +283,7 @@ module Cucumber
271
283
  break
272
284
  end
273
285
  end
274
- r0 = SyntaxNode.new(input, i0...index, s0)
286
+ r0 = instantiate_node(SyntaxNode,input, i0...index, s0)
275
287
 
276
288
  node_cache[:cell][start_index] = r0
277
289
 
@@ -287,7 +299,7 @@ module Cucumber
287
299
  end
288
300
 
289
301
  if input.index(Regexp.new('[ \\t]'), index) == index
290
- r0 = (SyntaxNode).new(input, index...(index + 1))
302
+ r0 = instantiate_node(SyntaxNode,input, index...(index + 1))
291
303
  @index += 1
292
304
  else
293
305
  r0 = nil
@@ -311,7 +323,7 @@ module Cucumber
311
323
 
312
324
  i0 = index
313
325
  if input.index("\n", index) == index
314
- r1 = (SyntaxNode).new(input, index...(index + 1))
326
+ r1 = instantiate_node(SyntaxNode,input, index...(index + 1))
315
327
  @index += 1
316
328
  else
317
329
  terminal_parse_failure("\n")
@@ -322,7 +334,7 @@ module Cucumber
322
334
  else
323
335
  i2, s2 = index, []
324
336
  if input.index("\r", index) == index
325
- r3 = (SyntaxNode).new(input, index...(index + 1))
337
+ r3 = instantiate_node(SyntaxNode,input, index...(index + 1))
326
338
  @index += 1
327
339
  else
328
340
  terminal_parse_failure("\r")
@@ -331,7 +343,7 @@ module Cucumber
331
343
  s2 << r3
332
344
  if r3
333
345
  if input.index("\n", index) == index
334
- r5 = (SyntaxNode).new(input, index...(index + 1))
346
+ r5 = instantiate_node(SyntaxNode,input, index...(index + 1))
335
347
  @index += 1
336
348
  else
337
349
  terminal_parse_failure("\n")
@@ -340,12 +352,12 @@ module Cucumber
340
352
  if r5
341
353
  r4 = r5
342
354
  else
343
- r4 = SyntaxNode.new(input, index...index)
355
+ r4 = instantiate_node(SyntaxNode,input, index...index)
344
356
  end
345
357
  s2 << r4
346
358
  end
347
359
  if s2.last
348
- r2 = (SyntaxNode).new(input, i2...index, s2)
360
+ r2 = instantiate_node(SyntaxNode,input, i2...index, s2)
349
361
  r2.extend(Eol0)
350
362
  else
351
363
  self.index = i2
@@ -374,7 +386,7 @@ module Cucumber
374
386
 
375
387
  i0 = index
376
388
  if index < input_length
377
- r1 = (SyntaxNode).new(input, index...(index + 1))
389
+ r1 = instantiate_node(SyntaxNode,input, index...(index + 1))
378
390
  @index += 1
379
391
  else
380
392
  terminal_parse_failure("any character")
@@ -384,7 +396,7 @@ module Cucumber
384
396
  r0 = nil
385
397
  else
386
398
  self.index = i0
387
- r0 = SyntaxNode.new(input, index...index)
399
+ r0 = instantiate_node(SyntaxNode,input, index...index)
388
400
  end
389
401
 
390
402
  node_cache[:eof][start_index] = r0
@@ -10,18 +10,30 @@ module Cucumber
10
10
 
11
11
  rule table
12
12
  table_row+ {
13
- def build
13
+ def at_line?(line)
14
+ elements.detect{|table_row| table_row.at_line?(line)}
15
+ end
16
+
17
+ def build(filter=nil)
14
18
  Ast::Table.new(raw)
15
19
  end
16
20
 
17
- def raw
18
- elements.map{|e| e.build}
21
+ def raw(filter=nil, scenario_outline=nil)
22
+ elements.map do |table_row|
23
+ if(filter.nil? || table_row == elements[0] || filter.at_line?(table_row) || (scenario_outline && filter.outline_at_line?(scenario_outline)))
24
+ table_row.build
25
+ end
26
+ end.compact
19
27
  end
20
28
  }
21
29
  end
22
30
 
23
31
  rule table_row
24
32
  space* '|' cells:(cell '|')+ space* (eol+ / eof) {
33
+ def at_line?(line)
34
+ cells.line == line
35
+ end
36
+
25
37
  def build
26
38
  row = cells.elements.map do |elt|
27
39
  value = elt.cell.text_value.strip
@@ -12,37 +12,76 @@ end
12
12
 
13
13
  module Cucumber
14
14
  module Parser
15
- module TreetopExt
15
+ class Filter
16
+ def initialize(lines, options)
17
+ @lines = lines
18
+ @include_tags = options[:include_tags] || []
19
+ @exclude_tags = options[:exclude_tags] || []
20
+ @names = options[:scenario_names] || []
21
+ end
22
+
23
+ def accept?(syntax_node)
24
+ at_line?(syntax_node) &&
25
+ matches_tags?(syntax_node) &&
26
+ matches_names?(syntax_node)
27
+ end
28
+
29
+ def at_line?(syntax_node)
30
+ @lines.nil? || @lines.empty? || @lines.detect{|line| syntax_node.at_line?(line)}
31
+ end
32
+
33
+ def outline_at_line?(syntax_node)
34
+ @lines.nil? || @lines.empty? || @lines.detect{|line| syntax_node.outline_at_line?(line)}
35
+ end
36
+
37
+ def matches_tags?(syntax_node)
38
+ !excluded_by_tags?(syntax_node) &&
39
+ included_by_tags?(syntax_node)
40
+ end
41
+
42
+ def included_by_tags?(syntax_node)
43
+ @include_tags.empty? || syntax_node.has_tags?(@include_tags)
44
+ end
45
+
46
+ def excluded_by_tags?(syntax_node)
47
+ @exclude_tags.any? && syntax_node.has_tags?(@exclude_tags)
48
+ end
49
+
50
+ def matches_names?(syntax_node)
51
+ @names.nil? || @names.empty? || @names.detect{|name| syntax_node.matches_name?(name)}
52
+ end
53
+ end
54
+
55
+ module TreetopExt
16
56
  FILE_COLON_LINE_PATTERN = /^([\w\W]*?):([\d:]+)$/
17
57
 
18
58
  # Parses a file and returns a Cucumber::Ast
19
- def parse_file(file)
59
+ def parse_file(file, options)
20
60
  _, path, lines = *FILE_COLON_LINE_PATTERN.match(file)
21
61
  if path
22
62
  lines = lines.split(':').map { |line| line.to_i }
23
63
  else
24
64
  path = file
25
- lines = []
26
65
  end
66
+ filter = Filter.new(lines, options)
27
67
 
28
- loader = lambda { |io| parse_or_fail(io.read, path) }
68
+ loader = lambda { |io| parse_or_fail(io.read, filter, path) }
29
69
  feature = if path =~ /^http/
30
70
  require 'open-uri'
31
71
  open(path, &loader)
32
72
  else
33
73
  File.open(path, Cucumber.file_mode('r'), &loader)
34
74
  end
35
- feature.lines = lines
36
75
  feature
37
76
  end
38
77
 
39
- def parse_or_fail(s, file=nil, line_offset=0)
40
- parse_tree = parse(s)
78
+ def parse_or_fail(string, filter=nil, file=nil, line_offset=0)
79
+ parse_tree = parse(string)
41
80
  if parse_tree.nil?
42
81
  raise Cucumber::Parser::SyntaxError.new(self, file, line_offset)
43
82
  else
44
- ast = parse_tree.build
45
- ast.file = file
83
+ ast = parse_tree.build(filter) # may return nil if it doesn't match filter.
84
+ ast.file = file unless ast.nil?
46
85
  ast
47
86
  end
48
87
  end
@@ -13,12 +13,6 @@ module Cucumber
13
13
  #
14
14
  # The AST classes are defined in the Cucumber::Ast module.
15
15
  module Parser
16
- translator = Module.new do
17
- def keywordz(key)
18
- 'Scenario'
19
- end
20
- end
21
-
22
16
  def self.load_parser(keywords)
23
17
  Loader.new(keywords)
24
18
  end
@@ -34,7 +28,8 @@ module Cucumber
34
28
  require 'cucumber/parser/feature'
35
29
  end
36
30
 
37
- def keywords(key)
31
+ def keywords(key, raw=false)
32
+ return @keywords[key] if raw
38
33
  values = @keywords[key].split('|')
39
34
  values.map{|value| "'#{value}'"}.join(" / ")
40
35
  end
@@ -56,24 +56,23 @@ module Cucumber
56
56
  # end
57
57
  #
58
58
  class StepDefinition
59
- def self.snippet_text(step_keyword, step_name)
59
+ PARAM_PATTERN = /"([^\"]*)"/
60
+ ESCAPED_PARAM_PATTERN = '"([^\\"]*)"'
61
+
62
+ def self.snippet_text(step_keyword, step_name, multiline_arg_class = nil)
60
63
  escaped = Regexp.escape(step_name).gsub('\ ', ' ').gsub('/', '\/')
61
- param_pattern = /"([^\"]*)"/
64
+ escaped = escaped.gsub(PARAM_PATTERN, ESCAPED_PARAM_PATTERN)
62
65
 
63
- match = escaped.match(param_pattern)
64
- if match
65
- n = 0
66
- block_args = match.captures.map do |a|
67
- n += 1
68
- "arg#{n}"
69
- end
70
- block_arg_string = " |#{block_args.join(", ")}|"
71
- else
72
- block_arg_string = ""
66
+ n = 0
67
+ block_args = escaped.scan(ESCAPED_PARAM_PATTERN).map do |a|
68
+ n += 1
69
+ "arg#{n}"
73
70
  end
71
+ block_args << multiline_arg_class.default_arg_name unless multiline_arg_class.nil?
72
+ block_arg_string = block_args.empty? ? "" : " |#{block_args.join(", ")}|"
73
+ multiline_class_string = multiline_arg_class ? "# #{multiline_arg_class.default_arg_name} is a #{multiline_arg_class.to_s}\n " : ""
74
74
 
75
- escaped = escaped.gsub(param_pattern, '"([^\\"]*)"')
76
- "#{step_keyword} /^#{escaped}$/ do#{block_arg_string}\n pending\nend"
75
+ "#{step_keyword} /^#{escaped}$/ do#{block_arg_string}\n #{multiline_class_string}pending\nend"
77
76
  end
78
77
 
79
78
  class MissingProc < StandardError