gherkin 1.0.30-i386-mingw32 → 2.0.0-i386-mingw32

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 (58) hide show
  1. data/.rspec +1 -0
  2. data/History.txt +19 -0
  3. data/Rakefile +4 -4
  4. data/VERSION.yml +2 -2
  5. data/features/feature_parser.feature +11 -0
  6. data/features/json_formatter.feature +238 -0
  7. data/features/pretty_formatter.feature +9 -0
  8. data/features/step_definitions/gherkin_steps.rb +1 -1
  9. data/features/step_definitions/json_formatter_steps.rb +32 -0
  10. data/features/step_definitions/pretty_formatter_steps.rb +24 -23
  11. data/features/support/env.rb +3 -3
  12. data/lib/gherkin/formatter/json_formatter.rb +82 -0
  13. data/lib/gherkin/formatter/pretty_formatter.rb +73 -78
  14. data/lib/gherkin/i18n.rb +22 -18
  15. data/lib/gherkin/i18n.yml +9 -9
  16. data/lib/gherkin/i18n_lexer.rb +2 -2
  17. data/lib/gherkin/parser/event.rb +6 -6
  18. data/lib/gherkin/parser/filter_listener.rb +5 -1
  19. data/lib/gherkin/parser/formatter_listener.rb +113 -0
  20. data/lib/gherkin/parser/json_parser.rb +102 -0
  21. data/lib/gherkin/parser/parser.rb +10 -2
  22. data/lib/gherkin/parser/row.rb +15 -0
  23. data/lib/gherkin/rubify.rb +2 -0
  24. data/lib/gherkin/tools/files.rb +1 -1
  25. data/lib/gherkin/tools/reformat.rb +1 -2
  26. data/lib/gherkin/tools/stats.rb +1 -1
  27. data/lib/gherkin/tools/stats_listener.rb +5 -5
  28. data/ragel/lexer.c.rl.erb +41 -12
  29. data/ragel/lexer.java.rl.erb +26 -17
  30. data/ragel/lexer.rb.rl.erb +10 -5
  31. data/ragel/lexer_common.rl.erb +6 -6
  32. data/spec/gherkin/c_lexer_spec.rb +2 -2
  33. data/spec/gherkin/fixtures/complex.js +105 -0
  34. data/spec/gherkin/formatter/argument_spec.rb +3 -3
  35. data/spec/gherkin/formatter/colors_spec.rb +3 -4
  36. data/spec/gherkin/formatter/pretty_formatter_spec.rb +21 -50
  37. data/spec/gherkin/i18n_lexer_spec.rb +6 -6
  38. data/spec/gherkin/i18n_spec.rb +16 -9
  39. data/spec/gherkin/java_lexer_spec.rb +1 -2
  40. data/spec/gherkin/output_stream_string_io.rb +24 -0
  41. data/spec/gherkin/parser/filter_listener_spec.rb +16 -9
  42. data/spec/gherkin/parser/formatter_listener_spec.rb +134 -0
  43. data/spec/gherkin/parser/json_parser_spec.rb +129 -0
  44. data/spec/gherkin/parser/parser_spec.rb +9 -9
  45. data/spec/gherkin/parser/tag_expression_spec.rb +8 -8
  46. data/spec/gherkin/rb_lexer_spec.rb +1 -1
  47. data/spec/gherkin/sexp_recorder.rb +21 -1
  48. data/spec/gherkin/shared/{lexer_spec.rb → lexer_group.rb} +172 -102
  49. data/spec/gherkin/shared/{py_string_spec.rb → py_string_group.rb} +21 -17
  50. data/spec/gherkin/shared/{row_spec.rb → row_group.rb} +36 -19
  51. data/spec/gherkin/shared/{tags_spec.rb → tags_group.rb} +13 -9
  52. data/spec/spec_helper.rb +18 -38
  53. data/tasks/bench.rake +3 -3
  54. data/tasks/compile.rake +13 -14
  55. data/tasks/rspec.rake +6 -11
  56. metadata +42 -28
  57. data/features/pretty_printer.feature +0 -14
  58. data/spec/gherkin/csharp_lexer_spec.rb +0 -20
@@ -1,4 +1,4 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
1
+ require 'spec_helper'
2
2
  require 'gherkin/parser/tag_expression'
3
3
 
4
4
  module Gherkin
@@ -6,7 +6,7 @@ module Gherkin
6
6
  describe TagExpression do
7
7
  context "no tags" do
8
8
  before(:each) do
9
- @e = TagExpression.new([])
9
+ @e = Gherkin::Parser::TagExpression.new([])
10
10
  end
11
11
 
12
12
  it "should match @foo" do
@@ -20,7 +20,7 @@ module Gherkin
20
20
 
21
21
  context "@foo" do
22
22
  before(:each) do
23
- @e = TagExpression.new(['@foo'])
23
+ @e = Gherkin::Parser::TagExpression.new(['@foo'])
24
24
  end
25
25
 
26
26
  it "should match @foo" do
@@ -38,7 +38,7 @@ module Gherkin
38
38
 
39
39
  context "!@foo" do
40
40
  before(:each) do
41
- @e = TagExpression.new(['~@foo'])
41
+ @e = Gherkin::Parser::TagExpression.new(['~@foo'])
42
42
  end
43
43
 
44
44
  it "should match @bar" do
@@ -52,7 +52,7 @@ module Gherkin
52
52
 
53
53
  context "@foo || @bar" do
54
54
  before(:each) do
55
- @e = TagExpression.new(['@foo,@bar'])
55
+ @e = Gherkin::Parser::TagExpression.new(['@foo,@bar'])
56
56
  end
57
57
 
58
58
  it "should match @foo" do
@@ -70,7 +70,7 @@ module Gherkin
70
70
 
71
71
  context "(@foo || @bar) && !@zap" do
72
72
  before(:each) do
73
- @e = TagExpression.new(['@foo,@bar', '~@zap'])
73
+ @e = Gherkin::Parser::TagExpression.new(['@foo,@bar', '~@zap'])
74
74
  end
75
75
 
76
76
  it "should match @foo" do
@@ -84,7 +84,7 @@ module Gherkin
84
84
 
85
85
  context "(@foo:3 || !@bar:4) && @zap:5" do
86
86
  before(:each) do
87
- @e = TagExpression.new(['@foo:3,~@bar','@zap:5'])
87
+ @e = Gherkin::Parser::TagExpression.new(['@foo:3,~@bar','@zap:5'])
88
88
  end
89
89
 
90
90
  it "should count tags for positive tags" do
@@ -98,7 +98,7 @@ module Gherkin
98
98
 
99
99
  context "Parsing '@foo:3,~@bar', '@zap:5'" do
100
100
  before(:each) do
101
- @e = TagExpression.new([' @foo:3 , ~@bar ', ' @zap:5 '])
101
+ @e = Gherkin::Parser::TagExpression.new([' @foo:3 , ~@bar ', ' @zap:5 '])
102
102
  end
103
103
 
104
104
  unless defined?(JRUBY_VERSION)
@@ -1,5 +1,5 @@
1
1
  #encoding: utf-8
2
- require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+ require 'spec_helper'
3
3
  require 'gherkin/rb_lexer/en'
4
4
 
5
5
  module Gherkin
@@ -1,5 +1,10 @@
1
+ require 'gherkin/rubify'
2
+ require 'gherkin/parser/row'
3
+
1
4
  module Gherkin
2
5
  class SexpRecorder
6
+ include Rubify
7
+
3
8
  def initialize
4
9
  @sexps = []
5
10
  end
@@ -8,7 +13,8 @@ module Gherkin
8
13
  event = :scenario_outline if event == :scenarioOutline # Special Java Lexer handling
9
14
  event = :py_string if event == :pyString # Special Java Lexer handling
10
15
  event = :syntax_error if event == :syntaxError # Special Java Lexer handling
11
- args[0] = args[0].to_a if event == :row # Special JRuby handling
16
+ args = rubify(args)
17
+ args = sexpify(args)
12
18
  @sexps << [event] + args
13
19
  end
14
20
 
@@ -28,5 +34,19 @@ module Gherkin
28
34
  def line(number)
29
35
  @sexps.find { |sexp| sexp.last == number }
30
36
  end
37
+
38
+ def sexpify(o)
39
+ if (defined?(JRUBY_VERSION) && Java.java.util.Collection === o) || Array === o
40
+ o.map{|e| sexpify(e)}
41
+ elsif(Parser::Row === o)
42
+ {
43
+ "cells" => rubify(o.cells),
44
+ "comments" => rubify(o.comments),
45
+ "line" => o.line,
46
+ }
47
+ else
48
+ o
49
+ end
50
+ end
31
51
  end
32
52
  end
@@ -1,22 +1,27 @@
1
1
  #encoding: utf-8
2
- require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
+ require 'spec_helper'
3
3
 
4
4
  module Gherkin
5
5
  module Lexer
6
6
  shared_examples_for "a Gherkin lexer" do
7
+ def scan(gherkin)
8
+ @lexer.scan(gherkin, "test.feature", 0)
9
+ end
7
10
 
8
11
  describe "Comments" do
9
12
  it "should parse a one line comment" do
10
- @lexer.scan("# My comment\n")
13
+ scan("# My comment\n")
11
14
  @listener.to_sexp.should == [
15
+ [:location, 'test.feature', 0],
12
16
  [:comment, "# My comment", 1],
13
17
  [:eof]
14
18
  ]
15
19
  end
16
20
 
17
21
  it "should parse a multiline comment" do
18
- @lexer.scan("# Hello\n\n# World\n")
22
+ scan("# Hello\n\n# World\n")
19
23
  @listener.to_sexp.should == [
24
+ [:location, 'test.feature', 0],
20
25
  [:comment, "# Hello", 1],
21
26
  [:comment, "# World", 3],
22
27
  [:eof]
@@ -24,18 +29,20 @@ module Gherkin
24
29
  end
25
30
 
26
31
  it "should not consume comments as part of a multiline name" do
27
- @lexer.scan("Scenario: test\n#hello\n Scenario: another")
32
+ scan("Scenario: test\n#hello\n Scenario: another")
28
33
  @listener.to_sexp.should == [
29
- [:scenario, "Scenario", "test", 1],
34
+ [:location, 'test.feature', 0],
35
+ [:scenario, "Scenario", "test", "", 1],
30
36
  [:comment, "#hello", 2],
31
- [:scenario, "Scenario", "another", 3],
37
+ [:scenario, "Scenario", "another", "", 3],
32
38
  [:eof]
33
39
  ]
34
40
  end
35
41
 
36
42
  it "should allow empty comment lines" do
37
- @lexer.scan("#\n # A comment\n #\n")
43
+ scan("#\n # A comment\n #\n")
38
44
  @listener.to_sexp.should == [
45
+ [:location, 'test.feature', 0],
39
46
  [:comment, "#", 1],
40
47
  [:comment, "# A comment", 2],
41
48
  [:comment, "#", 3],
@@ -45,52 +52,66 @@ module Gherkin
45
52
 
46
53
  it "should not allow comments within the Feature description" do
47
54
  lambda {
48
- @lexer.scan("Feature: something\nAs a something\n# Comment\nI want something")
55
+ scan("Feature: something\nAs a something\n# Comment\nI want something")
49
56
  }.should raise_error(/Lexing error on line 4/)
50
57
  end
51
58
  end
52
59
 
53
60
  describe "Tags" do
54
61
  it "should not take the tags as part of a multiline name feature element" do
55
- @lexer.scan("Feature: hi\n Scenario: test\n\n@hello\n Scenario: another")
62
+ scan("Feature: hi\n Scenario: test\n\n@hello\n Scenario: another")
56
63
  @listener.to_sexp.should == [
57
- [:feature, "Feature", "hi", 1],
58
- [:scenario, "Scenario", "test", 2],
64
+ [:location, 'test.feature', 0],
65
+ [:feature, "Feature", "hi", "", 1],
66
+ [:scenario, "Scenario", "test", "", 2],
59
67
  [:tag, "@hello", 4],
60
- [:scenario, "Scenario", "another", 5],
68
+ [:scenario, "Scenario", "another", "", 5],
61
69
  [:eof]
62
70
  ]
63
71
  end
64
72
  end
65
73
 
66
74
  describe "Background" do
75
+ it "should allow an empty background name and description" do
76
+ scan("Background:\nGiven I am a step\n")
77
+ @listener.to_sexp.should == [
78
+ [:location, 'test.feature', 0],
79
+ [:background, "Background", "", "", 1],
80
+ [:step, "Given ", "I am a step", 2],
81
+ [:eof]
82
+ ]
83
+ end
84
+
67
85
  it "should allow an empty background description" do
68
- @lexer.scan("Background:\nGiven I am a step\n")
86
+ scan("Background: Yeah\nGiven I am a step\n")
69
87
  @listener.to_sexp.should == [
70
- [:background, "Background", "", 1],
88
+ [:location, 'test.feature', 0],
89
+ [:background, "Background", "Yeah", "", 1],
71
90
  [:step, "Given ", "I am a step", 2],
72
91
  [:eof]
73
92
  ]
74
93
  end
75
94
 
76
95
  it "should allow multiline names ending at eof" do
77
- @lexer.scan("Background: I have several\n Lines to look at\n None starting with Given")
96
+ scan("Background: I have several\n Lines to look at\n None starting with Given")
78
97
  @listener.to_sexp.should == [
79
- [:background, "Background", "I have several\nLines to look at\nNone starting with Given", 1],
98
+ [:location, 'test.feature', 0],
99
+ [:background, "Background", "I have several", "Lines to look at\nNone starting with Given", 1],
80
100
  [:eof]
81
101
  ]
82
102
  end
83
103
 
84
104
  it "should allow multiline names" do
85
- @lexer.scan(%{Feature: Hi
105
+ scan(%{Feature: Hi
86
106
  Background: It is my ambition to say
87
107
  in ten sentences
88
108
  what others say
89
109
  in a whole book.
90
110
  Given I am a step})
91
111
  @listener.to_sexp.should == [
92
- [:feature, "Feature", "Hi", 1],
93
- [:background, "Background", "It is my ambition to say\nin ten sentences\nwhat others say\nin a whole book.",2],
112
+ [:location, 'test.feature', 0],
113
+ [:feature, "Feature", "Hi", "", 1],
114
+ [:background, "Background", "It is my ambition to say", "in ten sentences\nwhat others say\nin a whole book.",2],
94
115
  [:step, "Given ", "I am a step", 6],
95
116
  [:eof]
96
117
  ]
@@ -99,68 +120,74 @@ Given I am a step})
99
120
 
100
121
  describe "Scenarios" do
101
122
  it "should be parsed" do
102
- @lexer.scan("Scenario: Hello\n")
123
+ scan("Scenario: Hello\n")
103
124
  @listener.to_sexp.should == [
104
- [:scenario, "Scenario", "Hello", 1],
125
+ [:location, 'test.feature', 0],
126
+ [:scenario, "Scenario", "Hello", "", 1],
105
127
  [:eof]
106
128
  ]
107
129
  end
108
130
 
109
131
  it "should allow whitespace lines after the Scenario line" do
110
- @lexer.scan(%{Scenario: bar
132
+ scan(%{Scenario: bar
111
133
 
112
134
  Given baz
113
135
  })
114
136
  @listener.to_sexp.should == [
115
- [:scenario, "Scenario", "bar", 1],
137
+ [:location, 'test.feature', 0],
138
+ [:scenario, "Scenario", "bar", "", 1],
116
139
  [:step, "Given ", "baz", 3],
117
140
  [:eof]
118
141
  ]
119
142
  end
120
143
 
121
144
  it "should allow multiline names" do
122
- @lexer.scan(%{Scenario: It is my ambition to say
145
+ scan(%{Scenario: It is my ambition to say
123
146
  in ten sentences
124
147
  what others say
125
148
  in a whole book.
126
149
  Given I am a step
127
150
  })
128
151
  @listener.to_sexp.should == [
129
- [:scenario, "Scenario", "It is my ambition to say\nin ten sentences\nwhat others say\nin a whole book.", 1],
152
+ [:location, 'test.feature', 0],
153
+ [:scenario, "Scenario", "It is my ambition to say", "in ten sentences\nwhat others say\nin a whole book.", 1],
130
154
  [:step, "Given ", "I am a step", 5],
131
155
  [:eof]
132
156
  ]
133
157
  end
134
158
 
135
159
  it "should allow multiline names ending at eof" do
136
- @lexer.scan("Scenario: I have several\n Lines to look at\n None starting with Given")
160
+ scan("Scenario: I have several\n Lines to look at\n None starting with Given")
137
161
  @listener.to_sexp.should == [
138
- [:scenario, "Scenario", "I have several\nLines to look at\nNone starting with Given", 1],
162
+ [:location, 'test.feature', 0],
163
+ [:scenario, "Scenario", "I have several", "Lines to look at\nNone starting with Given", 1],
139
164
  [:eof]
140
165
  ]
141
166
  end
142
167
 
143
168
  it "should ignore gherkin keywords embedded in other words" do
144
- @lexer.scan(%{Scenario: I have a Button
169
+ scan(%{Scenario: I have a Button
145
170
  Buttons are great
146
171
  Given I have some
147
172
  But I might not because I am a Charles Dickens character
148
173
  })
149
174
  @listener.to_sexp.should == [
150
- [:scenario, "Scenario", "I have a Button\nButtons are great", 1],
175
+ [:location, 'test.feature', 0],
176
+ [:scenario, "Scenario", "I have a Button", "Buttons are great", 1],
151
177
  [:step, "Given ", "I have some", 3],
152
178
  [:step, "But ", "I might not because I am a Charles Dickens character", 4],
153
179
  [:eof]
154
180
  ]
155
181
  end
156
182
 
157
- it "should allow step names in Scenario descriptions" do
158
- @lexer.scan(%{Scenario: When I have when in scenario
183
+ it "should allow step keywords in Scenario names" do
184
+ scan(%{Scenario: When I have when in scenario
159
185
  I should be fine
160
186
  Given I am a step
161
187
  })
162
188
  @listener.to_sexp.should == [
163
- [:scenario, "Scenario", "When I have when in scenario\nI should be fine", 1],
189
+ [:location, 'test.feature', 0],
190
+ [:scenario, "Scenario", "When I have when in scenario", "I should be fine", 1],
164
191
  [:step, "Given ", "I am a step", 3],
165
192
  [:eof]
166
193
  ]
@@ -169,36 +196,41 @@ Given I am a step
169
196
 
170
197
  describe "Scenario Outlines" do
171
198
  it "should be parsed" do
172
- @lexer.scan(%{Scenario Outline: Hello
199
+ scan(%{Scenario Outline: Hello
200
+ With a description
173
201
  Given a <what> cucumber
174
- Examples:
202
+ Examples: With a name
203
+ and a description
175
204
  |what|
176
205
  |green|
177
206
  })
178
207
  @listener.to_sexp.should == [
179
- [:scenario_outline, "Scenario Outline", "Hello", 1],
180
- [:step, "Given ", "a <what> cucumber", 2],
181
- [:examples, "Examples", "", 3],
182
- [:row, ["what"], 4],
183
- [:row, ["green"], 5],
208
+ [:location, 'test.feature', 0],
209
+ [:scenario_outline, "Scenario Outline", "Hello", "With a description", 1],
210
+ [:step, "Given ", "a <what> cucumber", 3],
211
+ [:examples, "Examples", "With a name", "and a description", 4],
212
+ [:row, ["what"], 6],
213
+ [:row, ["green"], 7],
184
214
  [:eof]
185
215
  ]
186
216
  end
187
217
 
218
+
188
219
  it "should parse with no steps or examples" do
189
- @lexer.scan(%{Scenario Outline: Hello
220
+ scan(%{Scenario Outline: Hello
190
221
 
191
222
  Scenario: My Scenario
192
223
  })
193
224
  @listener.to_sexp.should == [
194
- [:scenario_outline, "Scenario Outline", "Hello", 1],
195
- [:scenario, "Scenario", "My Scenario", 3],
225
+ [:location, 'test.feature', 0],
226
+ [:scenario_outline, "Scenario Outline", "Hello", "", 1],
227
+ [:scenario, "Scenario", "My Scenario", "", 3],
196
228
  [:eof]
197
229
  ]
198
230
  end
199
231
 
200
- it "should allow multiline names" do
201
- @lexer.scan(%{Scenario Outline: It is my ambition to say
232
+ it "should allow multiline description" do
233
+ scan(%{Scenario Outline: It is my ambition to say
202
234
  in ten sentences
203
235
  what others say
204
236
  in a whole book.
@@ -206,7 +238,8 @@ Given I am a step
206
238
 
207
239
  })
208
240
  @listener.to_sexp.should == [
209
- [:scenario_outline, "Scenario Outline", "It is my ambition to say\nin ten sentences\nwhat others say\nin a whole book.", 1],
241
+ [:location, 'test.feature', 0],
242
+ [:scenario_outline, "Scenario Outline", "It is my ambition to say", "in ten sentences\nwhat others say\nin a whole book.", 1],
210
243
  [:step, "Given ", "I am a step", 5],
211
244
  [:eof]
212
245
  ]
@@ -215,12 +248,13 @@ Given I am a step
215
248
 
216
249
  describe "Examples" do
217
250
  it "should be parsed" do
218
- @lexer.scan(%{Examples:
251
+ scan(%{Examples:
219
252
  |x|y|
220
253
  |5|6|
221
254
  })
222
255
  @listener.to_sexp.should == [
223
- [:examples, "Examples", "", 1],
256
+ [:location, 'test.feature', 0],
257
+ [:examples, "Examples", "", "", 1],
224
258
  [:row, ["x","y"], 2],
225
259
  [:row, ["5","6"], 3],
226
260
  [:eof]
@@ -228,14 +262,15 @@ Given I am a step
228
262
  end
229
263
 
230
264
  it "should parse multiline example names" do
231
- @lexer.scan(%{Examples: I'm a multiline name
265
+ scan(%{Examples: I'm a multiline name
232
266
  and I'm ok
233
267
  f'real
234
268
  |x|
235
269
  |5|
236
270
  })
237
271
  @listener.to_sexp.should == [
238
- [:examples, "Examples", "I'm a multiline name\nand I'm ok\nf'real", 1],
272
+ [:location, 'test.feature', 0],
273
+ [:examples, "Examples", "I'm a multiline name", "and I'm ok\nf'real", 1],
239
274
  [:row, ["x"], 4],
240
275
  [:row, ["5"], 5],
241
276
  [:eof]
@@ -245,10 +280,11 @@ Given I am a step
245
280
 
246
281
  describe "Steps" do
247
282
  it "should parse steps with inline table" do
248
- @lexer.scan(%{Given I have a table
283
+ scan(%{Given I have a table
249
284
  |a|b|
250
285
  })
251
286
  @listener.to_sexp.should == [
287
+ [:location, 'test.feature', 0],
252
288
  [:step, "Given ", "I have a table", 1],
253
289
  [:row, ['a','b'], 2],
254
290
  [:eof]
@@ -256,8 +292,9 @@ Given I am a step
256
292
  end
257
293
 
258
294
  it "should parse steps with inline py_string" do
259
- @lexer.scan("Given I have a string\n\"\"\"\nhello\nworld\n\"\"\"")
295
+ scan("Given I have a string\n\"\"\"\nhello\nworld\n\"\"\"")
260
296
  @listener.to_sexp.should == [
297
+ [:location, 'test.feature', 0],
261
298
  [:step, "Given ", "I have a string", 1],
262
299
  [:py_string, "hello\nworld", 2],
263
300
  [:eof]
@@ -267,10 +304,11 @@ Given I am a step
267
304
 
268
305
  describe "A single feature, single scenario, single step" do
269
306
  it "should find the feature, scenario, and step" do
270
- @lexer.scan("Feature: Feature Text\n Scenario: Reading a Scenario\n Given there is a step\n")
307
+ scan("Feature: Feature Text\n Scenario: Reading a Scenario\n Given there is a step\n")
271
308
  @listener.to_sexp.should == [
272
- [:feature, "Feature", "Feature Text", 1],
273
- [:scenario, "Scenario", "Reading a Scenario", 2],
309
+ [:location, 'test.feature', 0],
310
+ [:feature, "Feature", "Feature Text", "", 1],
311
+ [:scenario, "Scenario", "Reading a Scenario", "", 2],
274
312
  [:step, "Given ", "there is a step", 3],
275
313
  [:eof]
276
314
  ]
@@ -279,10 +317,11 @@ Given I am a step
279
317
 
280
318
  describe "A feature ending in whitespace" do
281
319
  it "should not raise an error when whitespace follows the Feature, Scenario, and Steps" do
282
- @lexer.scan("Feature: Feature Text\n Scenario: Reading a Scenario\n Given there is a step\n ")
320
+ scan("Feature: Feature Text\n Scenario: Reading a Scenario\n Given there is a step\n ")
283
321
  @listener.to_sexp.should == [
284
- [:feature, "Feature", "Feature Text", 1],
285
- [:scenario, "Scenario", "Reading a Scenario", 2],
322
+ [:location, 'test.feature', 0],
323
+ [:feature, "Feature", "Feature Text", "", 1],
324
+ [:scenario, "Scenario", "Reading a Scenario", "", 2],
286
325
  [:step, "Given ", "there is a step", 3],
287
326
  [:eof]
288
327
  ]
@@ -292,10 +331,11 @@ Given I am a step
292
331
  describe "A single feature, single scenario, three steps" do
293
332
 
294
333
  it "should find the feature, scenario, and three steps" do
295
- @lexer.scan("Feature: Feature Text\n Scenario: Reading a Scenario\n Given there is a step\n And another step\n And a third step\n")
334
+ scan("Feature: Feature Text\n Scenario: Reading a Scenario\n Given there is a step\n And another step\n And a third step\n")
296
335
  @listener.to_sexp.should == [
297
- [:feature, "Feature", "Feature Text", 1],
298
- [:scenario, "Scenario", "Reading a Scenario", 2],
336
+ [:location, 'test.feature', 0],
337
+ [:feature, "Feature", "Feature Text", "", 1],
338
+ [:scenario, "Scenario", "Reading a Scenario", "", 2],
299
339
  [:step, "Given ", "there is a step", 3],
300
340
  [:step, "And ", "another step", 4],
301
341
  [:step, "And ", "a third step", 5],
@@ -306,17 +346,19 @@ Given I am a step
306
346
 
307
347
  describe "A single feature with no scenario" do
308
348
  it "should find the feature" do
309
- @lexer.scan("Feature: Feature Text\n")
349
+ scan("Feature: Feature Text\n")
310
350
  @listener.to_sexp.should == [
311
- [:feature, "Feature", "Feature Text", 1],
351
+ [:location, 'test.feature', 0],
352
+ [:feature, "Feature", "Feature Text", "", 1],
312
353
  [:eof]
313
354
  ]
314
355
  end
315
356
 
316
357
  it "should parse a one line feature with no newline" do
317
- @lexer.scan("Feature: hi")
358
+ scan("Feature: hi")
318
359
  @listener.to_sexp.should == [
319
- [:feature, "Feature", "hi", 1],
360
+ [:location, 'test.feature', 0],
361
+ [:feature, "Feature", "hi", "", 1],
320
362
  [:eof]
321
363
  ]
322
364
  end
@@ -324,9 +366,10 @@ Given I am a step
324
366
 
325
367
  describe "A multi-line feature with no scenario" do
326
368
  it "should find the feature" do
327
- @lexer.scan("Feature: Feature Text\n And some more text")
369
+ scan("Feature: Feature Text\n And some more text")
328
370
  @listener.to_sexp.should == [
329
- [:feature, "Feature", "Feature Text\nAnd some more text", 1],
371
+ [:location, 'test.feature', 0],
372
+ [:feature, "Feature", "Feature Text", "And some more text", 1],
330
373
  [:eof]
331
374
  ]
332
375
  end
@@ -334,10 +377,11 @@ Given I am a step
334
377
 
335
378
  describe "A feature with a scenario but no steps" do
336
379
  it "should find the feature and scenario" do
337
- @lexer.scan("Feature: Feature Text\nScenario: Reading a Scenario\n")
380
+ scan("Feature: Feature Text\nScenario: Reading a Scenario\n")
338
381
  @listener.to_sexp.should == [
339
- [:feature, "Feature", "Feature Text", 1],
340
- [:scenario, "Scenario", "Reading a Scenario", 2],
382
+ [:location, 'test.feature', 0],
383
+ [:feature, "Feature", "Feature Text", "", 1],
384
+ [:scenario, "Scenario", "Reading a Scenario", "", 2],
341
385
  [:eof]
342
386
  ]
343
387
  end
@@ -345,24 +389,26 @@ Given I am a step
345
389
 
346
390
  describe "A feature with two scenarios" do
347
391
  it "should find the feature and two scenarios" do
348
- @lexer.scan("Feature: Feature Text\nScenario: Reading a Scenario\n Given a step\n\nScenario: A second scenario\n Given another step\n")
392
+ scan("Feature: Feature Text\nScenario: Reading a Scenario\n Given a step\n\nScenario: A second scenario\n Given another step\n")
349
393
  @listener.to_sexp.should == [
350
- [:feature, "Feature", "Feature Text", 1],
351
- [:scenario, "Scenario", "Reading a Scenario", 2],
394
+ [:location, 'test.feature', 0],
395
+ [:feature, "Feature", "Feature Text", "", 1],
396
+ [:scenario, "Scenario", "Reading a Scenario", "", 2],
352
397
  [:step, "Given ", "a step", 3],
353
- [:scenario, "Scenario", "A second scenario", 5],
398
+ [:scenario, "Scenario", "A second scenario", "", 5],
354
399
  [:step, "Given ", "another step", 6],
355
400
  [:eof]
356
401
  ]
357
402
  end
358
403
 
359
404
  it "should find the feature and two scenarios without indentation" do
360
- @lexer.scan("Feature: Feature Text\nScenario: Reading a Scenario\nGiven a step\nScenario: A second scenario\nGiven another step\n")
405
+ scan("Feature: Feature Text\nScenario: Reading a Scenario\nGiven a step\nScenario: A second scenario\nGiven another step\n")
361
406
  @listener.to_sexp.should == [
362
- [:feature, "Feature", "Feature Text", 1],
363
- [:scenario, "Scenario", "Reading a Scenario", 2],
407
+ [:location, 'test.feature', 0],
408
+ [:feature, "Feature", "Feature Text", "", 1],
409
+ [:scenario, "Scenario", "Reading a Scenario", "", 2],
364
410
  [:step, "Given ", "a step", 3],
365
- [:scenario, "Scenario", "A second scenario", 4],
411
+ [:scenario, "Scenario", "A second scenario", "", 4],
366
412
  [:step, "Given ", "another step", 5],
367
413
  [:eof]
368
414
  ]
@@ -373,10 +419,11 @@ Given I am a step
373
419
  it "should find the feature, scenarios, steps, and comments in the proper order" do
374
420
  scan_file("simple_with_comments.feature")
375
421
  @listener.to_sexp.should == [
422
+ [:location, 'simple_with_comments.feature', 0],
376
423
  [:comment, "# Here is a comment", 1],
377
- [:feature, "Feature", "Feature Text", 2],
424
+ [:feature, "Feature", "Feature Text", "", 2],
378
425
  [:comment, "# Here is another # comment", 3],
379
- [:scenario, "Scenario", "Reading a Scenario", 4],
426
+ [:scenario, "Scenario", "Reading a Scenario", "", 4],
380
427
  [:comment, "# Here is a third comment", 5],
381
428
  [:step, "Given ", "there is a step", 6],
382
429
  [:comment, "# Here is a fourth comment", 7],
@@ -387,10 +434,11 @@ Given I am a step
387
434
  it "should support comments in tables" do
388
435
  scan_file("comments_in_table.feature")
389
436
  @listener.to_sexp.should == [
390
- [:feature, "Feature", "x", 1],
391
- [:scenario_outline, "Scenario Outline", "x", 3],
437
+ [:location, 'comments_in_table.feature', 0],
438
+ [:feature, "Feature", "x", "", 1],
439
+ [:scenario_outline, "Scenario Outline", "x", "", 3],
392
440
  [:step, "Then ", "x is <state>", 4],
393
- [:examples, "Examples", "", 6],
441
+ [:examples, "Examples", "", "", 6],
394
442
  [:row, ["state"], 7],
395
443
  [:comment, "# comment", 8],
396
444
  [:row, ["1"], 9],
@@ -403,18 +451,19 @@ Given I am a step
403
451
  it "should find the feature, scenario, step, and tags in the proper order" do
404
452
  scan_file("simple_with_tags.feature")
405
453
  @listener.to_sexp.should == [
454
+ [:location, 'simple_with_tags.feature', 0],
406
455
  [:comment, "# FC", 1],
407
456
  [:tag, "@ft",2],
408
- [:feature, "Feature", "hi", 3],
457
+ [:feature, "Feature", "hi", "", 3],
409
458
  [:tag, "@st1", 5],
410
459
  [:tag, "@st2", 5],
411
- [:scenario, "Scenario", "First", 6],
460
+ [:scenario, "Scenario", "First", "", 6],
412
461
  [:step, "Given ", "Pepper", 7],
413
462
  [:tag, "@st3", 9],
414
463
  [:tag, "@st4", 10],
415
464
  [:tag, "@ST5", 10],
416
465
  [:tag, "@#^%&ST6**!", 10],
417
- [:scenario, "Scenario", "Second", 11],
466
+ [:scenario, "Scenario", "Second", "", 11],
418
467
  [:eof]
419
468
  ]
420
469
  end
@@ -424,11 +473,12 @@ Given I am a step
424
473
  it "should lex this feature properly" do
425
474
  scan_file("1.feature")
426
475
  @listener.to_sexp.should == [
427
- [:feature, "Feature", "Logging in\nSo that I can be myself", 1],
476
+ [:location, '1.feature', 0],
477
+ [:feature, "Feature", "Logging in", "So that I can be myself", 1],
428
478
  [:comment, "# Comment", 3],
429
- [:scenario, "Scenario", "Anonymous user can get a login form.\nScenery here", 4],
479
+ [:scenario, "Scenario", "Anonymous user can get a login form.", "Scenery here", 4],
430
480
  [:tag, "@tag", 7],
431
- [:scenario, "Scenario", "Another one", 8],
481
+ [:scenario, "Scenario", "Another one", "", 8],
432
482
  [:eof]
433
483
  ]
434
484
  end
@@ -438,23 +488,24 @@ Given I am a step
438
488
  it "should find things in the right order" do
439
489
  scan_file("complex.feature")
440
490
  @listener.to_sexp.should == [
491
+ [:location, 'complex.feature', 0],
441
492
  [:comment, "#Comment on line 1", 1],
442
493
  [:comment, "#Comment on line 2", 2],
443
494
  [:tag, "@tag1", 3],
444
495
  [:tag, "@tag2", 3],
445
- [:feature, "Feature", "Feature Text\nIn order to test multiline forms\nAs a ragel writer\nI need to check for complex combinations", 4],
496
+ [:feature, "Feature", "Feature Text", "In order to test multiline forms\nAs a ragel writer\nI need to check for complex combinations", 4],
446
497
  [:comment, "#Comment on line 9", 9],
447
498
  [:comment, "#Comment on line 11", 11],
448
- [:background, "Background", "", 13],
499
+ [:background, "Background", "", "", 13],
449
500
  [:step, "Given ", "this is a background step", 14],
450
501
  [:step, "And ", "this is another one", 15],
451
502
  [:tag, "@tag3", 17],
452
503
  [:tag, "@tag4", 17],
453
- [:scenario, "Scenario", "Reading a Scenario", 18],
504
+ [:scenario, "Scenario", "Reading a Scenario", "", 18],
454
505
  [:step, "Given ", "there is a step", 19],
455
506
  [:step, "But ", "not another step", 20],
456
507
  [:tag, "@tag3", 22],
457
- [:scenario, "Scenario", "Reading a second scenario\nWith two lines of text", 23],
508
+ [:scenario, "Scenario", "Reading a second scenario", "With two lines of text", 23],
458
509
  [:comment, "#Comment on line 24", 25],
459
510
  [:step, "Given ", "a third step with a table", 26],
460
511
  [:row, %w{a b}, 27],
@@ -468,7 +519,7 @@ Given I am a step
468
519
  [:step, "And ", "I am done testing these tables", 35],
469
520
  [:comment, "#Comment on line 29", 36],
470
521
  [:step, "Then ", "I am happy", 37],
471
- [:scenario, "Scenario", "Hammerzeit", 39],
522
+ [:scenario, "Scenario", "Hammerzeit", "", 39],
472
523
  [:step, "Given ", "All work and no play", 40],
473
524
  [:py_string, "Makes Homer something something\nAnd something else", 41 ],
474
525
  [:step, "Then ", "crazy", 45],
@@ -481,23 +532,24 @@ Given I am a step
481
532
  it "should find things in the right order for CRLF features" do
482
533
  scan_file("dos_line_endings.feature")
483
534
  @listener.to_sexp.should == [
535
+ [:location, 'dos_line_endings.feature', 0],
484
536
  [:comment, "#Comment on line 1", 1],
485
537
  [:comment, "#Comment on line 2", 2],
486
538
  [:tag, "@tag1", 3],
487
539
  [:tag, "@tag2", 3],
488
- [:feature, "Feature", "Feature Text\r\nIn order to test multiline forms\r\nAs a ragel writer\r\nI need to check for complex combinations", 4],
540
+ [:feature, "Feature", "Feature Text", "In order to test multiline forms\r\nAs a ragel writer\r\nI need to check for complex combinations", 4],
489
541
  [:comment, "#Comment on line 9", 9],
490
542
  [:comment, "#Comment on line 11", 11],
491
- [:background, "Background", "", 13],
543
+ [:background, "Background", "", "", 13],
492
544
  [:step, "Given ", "this is a background step", 14],
493
545
  [:step, "And ", "this is another one", 15],
494
546
  [:tag, "@tag3", 17],
495
547
  [:tag, "@tag4", 17],
496
- [:scenario, "Scenario", "Reading a Scenario", 18],
548
+ [:scenario, "Scenario", "Reading a Scenario", "", 18],
497
549
  [:step, "Given ", "there is a step", 19],
498
550
  [:step, "But ", "not another step", 20],
499
551
  [:tag, "@tag3", 22],
500
- [:scenario, "Scenario", "Reading a second scenario\r\nWith two lines of text", 23],
552
+ [:scenario, "Scenario", "Reading a second scenario", "With two lines of text", 23],
501
553
  [:comment, "#Comment on line 24", 25],
502
554
  [:step, "Given ", "a third step with a table", 26],
503
555
  [:row, %w{a b}, 27],
@@ -511,7 +563,7 @@ Given I am a step
511
563
  [:step, "And ", "I am done testing these tables", 35],
512
564
  [:comment, "#Comment on line 29", 36],
513
565
  [:step, "Then ", "I am happy", 37],
514
- [:scenario, "Scenario", "Hammerzeit", 39],
566
+ [:scenario, "Scenario", "Hammerzeit", "", 39],
515
567
  [:step, "Given ", "All work and no play", 40],
516
568
  [:py_string, "Makes Homer something something\r\nAnd something else", 41],
517
569
  [:step, "Then ", "crazy", 45],
@@ -522,8 +574,9 @@ Given I am a step
522
574
  it "should cope with the retarded BOM that many Windows editors insert at the beginning of a file" do
523
575
  scan_file("with_bom.feature")
524
576
  @listener.to_sexp.should == [
525
- [:feature, "Feature", "Feature Text", 1],
526
- [:scenario, "Scenario", "Reading a Scenario", 2],
577
+ [:location, 'with_bom.feature', 0],
578
+ [:feature, "Feature", "Feature Text", "", 1],
579
+ [:scenario, "Scenario", "Reading a Scenario", "", 2],
527
580
  [:step, "Given ", "there is a step", 3],
528
581
  [:eof]
529
582
  ]
@@ -535,15 +588,32 @@ Given I am a step
535
588
  ["Some text\nFeature: Hi",
536
589
  "Feature: Hi\nBackground:\nGiven something\nScenario A scenario",
537
590
  "Scenario: My scenario\nGiven foo\nAand bar\nScenario: another one\nGiven blah"].each do |text|
538
- lambda { @lexer.scan(text) }.should raise_error(/Lexing error on line/)
591
+ lambda { scan(text) }.should raise_error(/Lexing error on line/)
539
592
  end
540
593
  end
541
594
 
542
595
  it "should include the line number and context of the error" do
543
596
  lambda {
544
- @lexer.scan("Feature: hello\nScenario: My scenario\nGiven foo\nAand blah\nHmmm wrong\nThen something something")
597
+ scan("Feature: hello\nScenario: My scenario\nGiven foo\nAand blah\nHmmm wrong\nThen something something")
545
598
  }.should raise_error(/Lexing error on line 4/)
546
599
  end
600
+
601
+ it "Feature keyword should terminate narratives for multiline capable tokens" do
602
+ scan("Feature:\nBackground:\nFeature:\nScenario Outline:\nFeature:\nScenario:\nFeature:\nExamples:\nFeature:\n")
603
+ @listener.to_sexp.should == [
604
+ [:location, 'test.feature', 0],
605
+ [:feature, "Feature", "", "", 1],
606
+ [:background, "Background", "", "", 2],
607
+ [:feature, "Feature", "", "", 3],
608
+ [:scenario_outline, "Scenario Outline", "", "", 4],
609
+ [:feature, "Feature", "", "", 5],
610
+ [:scenario, "Scenario", "", "", 6],
611
+ [:feature, "Feature", "", "", 7],
612
+ [:examples, "Examples", "","", 8],
613
+ [:feature, "Feature", "", "", 9],
614
+ [:eof]
615
+ ]
616
+ end
547
617
  end
548
618
  end
549
619
  end