gherkin 1.0.30-universal-dotnet → 2.0.0-universal-dotnet

Sign up to get free protection for your applications and to get access to all the features.
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