cucumber 0.4.3 → 0.4.4

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 (69) hide show
  1. data/History.txt +27 -0
  2. data/VERSION.yml +3 -2
  3. data/cucumber.gemspec +11 -5
  4. data/examples/watir/features/support/screenshots.rb +1 -2
  5. data/features/call_many_steps.feature +124 -0
  6. data/features/default_snippets.feature +2 -2
  7. data/features/expand.feature +13 -2
  8. data/features/language_help.feature +1 -1
  9. data/features/report_called_undefined_steps.feature +1 -1
  10. data/features/snippet.feature +2 -2
  11. data/features/support/env.rb +3 -5
  12. data/features/tag_logic.feature +32 -0
  13. data/features/wire_protocol.feature +7 -7
  14. data/lib/cucumber.rb +6 -0
  15. data/lib/cucumber/ast/background.rb +1 -1
  16. data/lib/cucumber/ast/comment.rb +1 -1
  17. data/lib/cucumber/ast/examples.rb +1 -1
  18. data/lib/cucumber/ast/feature.rb +1 -1
  19. data/lib/cucumber/ast/feature_element.rb +2 -3
  20. data/lib/cucumber/ast/features.rb +1 -1
  21. data/lib/cucumber/ast/outline_table.rb +17 -4
  22. data/lib/cucumber/ast/py_string.rb +3 -1
  23. data/lib/cucumber/ast/scenario.rb +3 -1
  24. data/lib/cucumber/ast/scenario_outline.rb +2 -2
  25. data/lib/cucumber/ast/step.rb +1 -1
  26. data/lib/cucumber/ast/step_collection.rb +1 -1
  27. data/lib/cucumber/ast/step_invocation.rb +2 -1
  28. data/lib/cucumber/ast/table.rb +3 -3
  29. data/lib/cucumber/ast/tags.rb +18 -11
  30. data/lib/cucumber/ast/tree_walker.rb +16 -0
  31. data/lib/cucumber/cli/main.rb +3 -2
  32. data/lib/cucumber/cli/options.rb +4 -6
  33. data/lib/cucumber/cli/profile_loader.rb +4 -0
  34. data/lib/cucumber/filter.rb +2 -2
  35. data/lib/cucumber/formatter/ansicolor.rb +8 -0
  36. data/lib/cucumber/formatter/pretty.rb +3 -4
  37. data/lib/cucumber/language_support/language_methods.rb +4 -3
  38. data/lib/cucumber/languages.yml +1 -1
  39. data/lib/cucumber/parser.rb +2 -0
  40. data/lib/cucumber/parser/common.rb +170 -0
  41. data/lib/cucumber/parser/common.tt +21 -0
  42. data/lib/cucumber/parser/feature.rb +7 -291
  43. data/lib/cucumber/parser/feature.tt +7 -43
  44. data/lib/cucumber/parser/i18n.tt +2 -0
  45. data/lib/cucumber/parser/natural_language.rb +9 -0
  46. data/lib/cucumber/parser/py_string.rb +276 -0
  47. data/lib/cucumber/parser/py_string.tt +45 -0
  48. data/lib/cucumber/parser/table.rb +5 -120
  49. data/lib/cucumber/parser/table.tt +2 -13
  50. data/lib/cucumber/platform.rb +3 -2
  51. data/lib/cucumber/rails/active_record.rb +2 -21
  52. data/lib/cucumber/rails/world.rb +2 -1
  53. data/lib/cucumber/rb_support/rb_hook.rb +2 -1
  54. data/lib/cucumber/rb_support/rb_language.rb +8 -6
  55. data/lib/cucumber/rb_support/rb_step_definition.rb +4 -0
  56. data/lib/cucumber/rb_support/rb_world.rb +16 -37
  57. data/lib/cucumber/step_mother.rb +86 -2
  58. data/lib/cucumber/wire_support/wire_language.rb +2 -2
  59. data/lib/cucumber/wire_support/wire_protocol.rb +1 -1
  60. data/rails_generators/cucumber/cucumber_generator.rb +3 -1
  61. data/rails_generators/cucumber/templates/cucumber.rake +4 -2
  62. data/rails_generators/cucumber/templates/webrat_steps.rb +28 -28
  63. data/spec/cucumber/ast/background_spec.rb +2 -1
  64. data/spec/cucumber/ast/scenario_spec.rb +3 -1
  65. data/spec/cucumber/formatter/console_spec.rb +1 -1
  66. data/spec/cucumber/rb_support/rb_step_definition_spec.rb +14 -5
  67. data/spec/cucumber/step_mother_spec.rb +1 -1
  68. data/spec/cucumber/world/pending_spec.rb +1 -1
  69. metadata +8 -3
@@ -76,8 +76,8 @@ module Cucumber
76
76
  steps.at_line?(line)
77
77
  end
78
78
 
79
- def matches_tags?(tag_names)
80
- Ast::Tags.matches?(self.parent.tags.tag_names, tag_names)
79
+ def matches_tags?(tag_name_lists)
80
+ Ast::Tags.matches?(self.parent.tags.tag_names, tag_name_lists)
81
81
  end
82
82
 
83
83
  def build
@@ -116,10 +116,10 @@ module Cucumber
116
116
  tags.at_line?(line)
117
117
  end
118
118
 
119
- def matches_tags?(tag_names)
119
+ def matches_tags?(tag_name_lists)
120
120
  feature_tag_names = self.parent.parent.tags.tag_names
121
121
  source_tag_names = (feature_tag_names + tags.tag_names).uniq
122
- Ast::Tags.matches?(source_tag_names, tag_names)
122
+ Ast::Tags.matches?(source_tag_names, tag_name_lists)
123
123
  end
124
124
 
125
125
  def matches_name?(regexp_to_match)
@@ -153,10 +153,10 @@ module Cucumber
153
153
  steps.at_line?(line)
154
154
  end
155
155
 
156
- def matches_tags?(tag_names)
156
+ def matches_tags?(tag_name_lists)
157
157
  feature_tag_names = self.parent.parent.tags.tag_names
158
158
  source_tag_names = (feature_tag_names + tags.tag_names).uniq
159
- Ast::Tags.matches?(source_tag_names, tag_names)
159
+ Ast::Tags.matches?(source_tag_names, tag_name_lists)
160
160
  end
161
161
 
162
162
  def matches_name?(regexp_to_match)
@@ -238,7 +238,7 @@ module Cucumber
238
238
  table.at_line?(line)
239
239
  end
240
240
 
241
- def matches_tags?(tag_names)
241
+ def matches_tags?(tag_name_lists)
242
242
  true
243
243
  end
244
244
 
@@ -276,42 +276,6 @@ module Cucumber
276
276
  (step_keyword keyword_space) / scenario_keyword / scenario_outline_keyword / table / tag / comment_line
277
277
  end
278
278
 
279
- rule py_string
280
- open_py_string s:(!close_py_string .)* close_py_string {
281
- def at_line?(line)
282
- line >= open_py_string.line && line <= close_py_string.line
283
- end
284
-
285
- def build
286
- Ast::PyString.new(open_py_string.line, close_py_string.line, s.text_value, open_py_string.indentation)
287
- end
288
- }
289
- end
290
-
291
- rule open_py_string
292
- indent:space* '"""' space* eol {
293
- def indentation
294
- indent.text_value.length
295
- end
296
-
297
- def line
298
- indent.line
299
- end
300
- }
301
- end
302
-
303
- rule close_py_string
304
- eol space* quotes:'"""' white {
305
- def line
306
- quotes.line
307
- end
308
- }
309
- end
310
-
311
- rule white
312
- (space / eol)*
313
- end
314
-
315
279
  end
316
280
  end
317
281
  end
@@ -2,8 +2,10 @@ module Cucumber
2
2
  module Parser
3
3
  module I18n
4
4
  grammar <%= keywords('grammar_name', true) %>
5
+ include Common
5
6
  include Feature
6
7
  include Table
8
+ include PyString
7
9
 
8
10
  rule feature
9
11
  feature_sub
@@ -18,6 +18,7 @@ module Cucumber
18
18
  raise "Language not supported: #{lang.inspect}" if @keywords.nil?
19
19
  @keywords['grammar_name'] = @keywords['name'].gsub(/\s/, '')
20
20
  register_adverbs(step_mother) if step_mother
21
+ @parser = nil
21
22
  end
22
23
 
23
24
  def register_adverbs(step_mother)
@@ -67,6 +68,14 @@ module Cucumber
67
68
  def and_keywords
68
69
  @keywords['and'].split('|')
69
70
  end
71
+
72
+ def step_keywords
73
+ %w{given when then and but}.map{|key| @keywords[key].split('|')}.flatten.uniq
74
+ end
75
+
76
+ def space_after_keyword
77
+ @keywords['space_after_keyword']
78
+ end
70
79
  end
71
80
  end
72
81
  end
@@ -0,0 +1,276 @@
1
+ # Autogenerated from a Treetop grammar. Edits may be lost.
2
+
3
+
4
+ module Cucumber
5
+ module Parser
6
+ # TIP: When you hack on the grammar, just delete py_string.rb in this directory.
7
+ # Also make sure you have uninstalled all cucumber gems (don't forget xxx-cucumber
8
+ # github gems).
9
+ #
10
+ # Treetop will then generate the parser in-memory. When you're happy, just generate
11
+ # the rb file with tt feature.tt
12
+ module PyString
13
+ include Treetop::Runtime
14
+
15
+ def root
16
+ @root || :py_string
17
+ end
18
+
19
+ include Common
20
+
21
+ module PyString0
22
+ end
23
+
24
+ module PyString1
25
+ def open_py_string
26
+ elements[0]
27
+ end
28
+
29
+ def s
30
+ elements[1]
31
+ end
32
+
33
+ def close_py_string
34
+ elements[2]
35
+ end
36
+ end
37
+
38
+ module PyString2
39
+ def at_line?(line)
40
+ line >= open_py_string.line && line <= close_py_string.line
41
+ end
42
+
43
+ def build(filter=nil)
44
+ Ast::PyString.new(open_py_string.line, close_py_string.line, s.text_value, open_py_string.indentation)
45
+ end
46
+ end
47
+
48
+ def _nt_py_string
49
+ start_index = index
50
+ if node_cache[:py_string].has_key?(index)
51
+ cached = node_cache[:py_string][index]
52
+ @index = cached.interval.end if cached
53
+ return cached
54
+ end
55
+
56
+ i0, s0 = index, []
57
+ r1 = _nt_open_py_string
58
+ s0 << r1
59
+ if r1
60
+ s2, i2 = [], index
61
+ loop do
62
+ i3, s3 = index, []
63
+ i4 = index
64
+ r5 = _nt_close_py_string
65
+ if r5
66
+ r4 = nil
67
+ else
68
+ @index = i4
69
+ r4 = instantiate_node(SyntaxNode,input, index...index)
70
+ end
71
+ s3 << r4
72
+ if r4
73
+ if index < input_length
74
+ r6 = instantiate_node(SyntaxNode,input, index...(index + 1))
75
+ @index += 1
76
+ else
77
+ terminal_parse_failure("any character")
78
+ r6 = nil
79
+ end
80
+ s3 << r6
81
+ end
82
+ if s3.last
83
+ r3 = instantiate_node(SyntaxNode,input, i3...index, s3)
84
+ r3.extend(PyString0)
85
+ else
86
+ @index = i3
87
+ r3 = nil
88
+ end
89
+ if r3
90
+ s2 << r3
91
+ else
92
+ break
93
+ end
94
+ end
95
+ r2 = instantiate_node(SyntaxNode,input, i2...index, s2)
96
+ s0 << r2
97
+ if r2
98
+ r7 = _nt_close_py_string
99
+ s0 << r7
100
+ end
101
+ end
102
+ if s0.last
103
+ r0 = instantiate_node(SyntaxNode,input, i0...index, s0)
104
+ r0.extend(PyString1)
105
+ r0.extend(PyString2)
106
+ else
107
+ @index = i0
108
+ r0 = nil
109
+ end
110
+
111
+ node_cache[:py_string][start_index] = r0
112
+
113
+ r0
114
+ end
115
+
116
+ module OpenPyString0
117
+ def indent
118
+ elements[0]
119
+ end
120
+
121
+ def eol
122
+ elements[3]
123
+ end
124
+ end
125
+
126
+ module OpenPyString1
127
+ def indentation
128
+ indent.text_value.length
129
+ end
130
+
131
+ def line
132
+ indent.line
133
+ end
134
+ end
135
+
136
+ def _nt_open_py_string
137
+ start_index = index
138
+ if node_cache[:open_py_string].has_key?(index)
139
+ cached = node_cache[:open_py_string][index]
140
+ @index = cached.interval.end if cached
141
+ return cached
142
+ end
143
+
144
+ i0, s0 = index, []
145
+ s1, i1 = [], index
146
+ loop do
147
+ r2 = _nt_space
148
+ if r2
149
+ s1 << r2
150
+ else
151
+ break
152
+ end
153
+ end
154
+ r1 = instantiate_node(SyntaxNode,input, i1...index, s1)
155
+ s0 << r1
156
+ if r1
157
+ if has_terminal?('"""', false, index)
158
+ r3 = instantiate_node(SyntaxNode,input, index...(index + 3))
159
+ @index += 3
160
+ else
161
+ terminal_parse_failure('"""')
162
+ r3 = nil
163
+ end
164
+ s0 << r3
165
+ if r3
166
+ s4, i4 = [], index
167
+ loop do
168
+ r5 = _nt_space
169
+ if r5
170
+ s4 << r5
171
+ else
172
+ break
173
+ end
174
+ end
175
+ r4 = instantiate_node(SyntaxNode,input, i4...index, s4)
176
+ s0 << r4
177
+ if r4
178
+ r6 = _nt_eol
179
+ s0 << r6
180
+ end
181
+ end
182
+ end
183
+ if s0.last
184
+ r0 = instantiate_node(SyntaxNode,input, i0...index, s0)
185
+ r0.extend(OpenPyString0)
186
+ r0.extend(OpenPyString1)
187
+ else
188
+ @index = i0
189
+ r0 = nil
190
+ end
191
+
192
+ node_cache[:open_py_string][start_index] = r0
193
+
194
+ r0
195
+ end
196
+
197
+ module ClosePyString0
198
+ def eol
199
+ elements[0]
200
+ end
201
+
202
+ def quotes
203
+ elements[2]
204
+ end
205
+
206
+ def white
207
+ elements[3]
208
+ end
209
+ end
210
+
211
+ module ClosePyString1
212
+ def line
213
+ quotes.line
214
+ end
215
+ end
216
+
217
+ def _nt_close_py_string
218
+ start_index = index
219
+ if node_cache[:close_py_string].has_key?(index)
220
+ cached = node_cache[:close_py_string][index]
221
+ @index = cached.interval.end if cached
222
+ return cached
223
+ end
224
+
225
+ i0, s0 = index, []
226
+ r1 = _nt_eol
227
+ s0 << r1
228
+ if r1
229
+ s2, i2 = [], index
230
+ loop do
231
+ r3 = _nt_space
232
+ if r3
233
+ s2 << r3
234
+ else
235
+ break
236
+ end
237
+ end
238
+ r2 = instantiate_node(SyntaxNode,input, i2...index, s2)
239
+ s0 << r2
240
+ if r2
241
+ if has_terminal?('"""', false, index)
242
+ r4 = instantiate_node(SyntaxNode,input, index...(index + 3))
243
+ @index += 3
244
+ else
245
+ terminal_parse_failure('"""')
246
+ r4 = nil
247
+ end
248
+ s0 << r4
249
+ if r4
250
+ r5 = _nt_white
251
+ s0 << r5
252
+ end
253
+ end
254
+ end
255
+ if s0.last
256
+ r0 = instantiate_node(SyntaxNode,input, i0...index, s0)
257
+ r0.extend(ClosePyString0)
258
+ r0.extend(ClosePyString1)
259
+ else
260
+ @index = i0
261
+ r0 = nil
262
+ end
263
+
264
+ node_cache[:close_py_string][start_index] = r0
265
+
266
+ r0
267
+ end
268
+
269
+ end
270
+
271
+ class PyStringParser < Treetop::Runtime::CompiledParser
272
+ include PyString
273
+ end
274
+
275
+ end
276
+ end
@@ -0,0 +1,45 @@
1
+ module Cucumber
2
+ module Parser
3
+ # TIP: When you hack on the grammar, just delete py_string.rb in this directory.
4
+ # Also make sure you have uninstalled all cucumber gems (don't forget xxx-cucumber
5
+ # github gems).
6
+ #
7
+ # Treetop will then generate the parser in-memory. When you're happy, just generate
8
+ # the rb file with tt feature.tt
9
+ grammar PyString
10
+ include Common
11
+
12
+ rule py_string
13
+ open_py_string s:(!close_py_string .)* close_py_string {
14
+ def at_line?(line)
15
+ line >= open_py_string.line && line <= close_py_string.line
16
+ end
17
+
18
+ def build(filter=nil)
19
+ Ast::PyString.new(open_py_string.line, close_py_string.line, s.text_value, open_py_string.indentation)
20
+ end
21
+ }
22
+ end
23
+
24
+ rule open_py_string
25
+ indent:space* '"""' space* eol {
26
+ def indentation
27
+ indent.text_value.length
28
+ end
29
+
30
+ def line
31
+ indent.line
32
+ end
33
+ }
34
+ end
35
+
36
+ rule close_py_string
37
+ eol space* quotes:'"""' white {
38
+ def line
39
+ quotes.line
40
+ end
41
+ }
42
+ end
43
+ end
44
+ end
45
+ end
@@ -3,7 +3,7 @@
3
3
 
4
4
  module Cucumber
5
5
  module Parser
6
- # TIP: When you hack on the grammar, just delete feature.rb in this directory.
6
+ # TIP: When you hack on the grammar, just delete table.rb in this directory.
7
7
  # Also make sure you have uninstalled all cucumber gems (don't forget xxx-cucumber
8
8
  # github gems).
9
9
  #
@@ -16,6 +16,8 @@ module Cucumber
16
16
  @root || :table
17
17
  end
18
18
 
19
+ include Common
20
+
19
21
  module Table0
20
22
  def at_line?(line)
21
23
  elements.detect{|table_row| table_row.at_line?(line)}
@@ -265,9 +267,8 @@ module Cucumber
265
267
  s1 << r2
266
268
  if r2
267
269
  if index < input_length
268
- next_character = index + input[index..-1].match(/\A(.)/um).end(1)
269
- r6 = instantiate_node(SyntaxNode,input, index...next_character)
270
- @index = next_character
270
+ r6 = instantiate_node(SyntaxNode,input, index...(index + 1))
271
+ @index += 1
271
272
  else
272
273
  terminal_parse_failure("any character")
273
274
  r6 = nil
@@ -294,122 +295,6 @@ module Cucumber
294
295
  r0
295
296
  end
296
297
 
297
- def _nt_space
298
- start_index = index
299
- if node_cache[:space].has_key?(index)
300
- cached = node_cache[:space][index]
301
- @index = cached.interval.end if cached
302
- return cached
303
- end
304
-
305
- if has_terminal?('\G[ \\t]', true, index)
306
- next_character = index + input[index..-1].match(/\A(.)/um).end(1)
307
- r0 = instantiate_node(SyntaxNode, input, index...next_character)
308
- @index = next_character
309
- else
310
- r0 = nil
311
- end
312
-
313
- node_cache[:space][start_index] = r0
314
-
315
- r0
316
- end
317
-
318
- module Eol0
319
- end
320
-
321
- def _nt_eol
322
- start_index = index
323
- if node_cache[:eol].has_key?(index)
324
- cached = node_cache[:eol][index]
325
- @index = cached.interval.end if cached
326
- return cached
327
- end
328
-
329
- i0 = index
330
- if has_terminal?("\n", false, index)
331
- r1 = instantiate_node(SyntaxNode,input, index...(index + 1))
332
- @index += 1
333
- else
334
- terminal_parse_failure("\n")
335
- r1 = nil
336
- end
337
- if r1
338
- r0 = r1
339
- else
340
- i2, s2 = index, []
341
- if has_terminal?("\r", false, index)
342
- r3 = instantiate_node(SyntaxNode,input, index...(index + 1))
343
- @index += 1
344
- else
345
- terminal_parse_failure("\r")
346
- r3 = nil
347
- end
348
- s2 << r3
349
- if r3
350
- if has_terminal?("\n", false, index)
351
- r5 = instantiate_node(SyntaxNode,input, index...(index + 1))
352
- @index += 1
353
- else
354
- terminal_parse_failure("\n")
355
- r5 = nil
356
- end
357
- if r5
358
- r4 = r5
359
- else
360
- r4 = instantiate_node(SyntaxNode,input, index...index)
361
- end
362
- s2 << r4
363
- end
364
- if s2.last
365
- r2 = instantiate_node(SyntaxNode,input, i2...index, s2)
366
- r2.extend(Eol0)
367
- else
368
- @index = i2
369
- r2 = nil
370
- end
371
- if r2
372
- r0 = r2
373
- else
374
- @index = i0
375
- r0 = nil
376
- end
377
- end
378
-
379
- node_cache[:eol][start_index] = r0
380
-
381
- r0
382
- end
383
-
384
- def _nt_eof
385
- start_index = index
386
- if node_cache[:eof].has_key?(index)
387
- cached = node_cache[:eof][index]
388
- @index = cached.interval.end if cached
389
- return cached
390
- end
391
-
392
- i0 = index
393
- if index < input_length
394
- next_character = index + input[index..-1].match(/\A(.)/um).end(1)
395
- r1 = instantiate_node(SyntaxNode,input, index...next_character)
396
- @index = next_character
397
- else
398
- terminal_parse_failure("any character")
399
- r1 = nil
400
- end
401
- if r1
402
- r0 = nil
403
- else
404
- @index = i0
405
- r0 = instantiate_node(SyntaxNode,input, index...index)
406
- end
407
-
408
- node_cache[:eof][start_index] = r0
409
-
410
- r0
411
- end
412
-
413
298
  end
414
299
 
415
300
  class TableParser < Treetop::Runtime::CompiledParser