gherkin 1.0.2-i386-mswin32 → 1.0.3-i386-mswin32

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 (76) hide show
  1. data/.gitattributes +1 -0
  2. data/History.txt +18 -0
  3. data/README.rdoc +12 -1
  4. data/Rakefile +4 -2
  5. data/VERSION.yml +1 -1
  6. data/bin/gherkin +1 -1
  7. data/dotnet/.gitignore +13 -0
  8. data/features/feature_parser.feature +22 -2
  9. data/features/native_lexer.feature +1 -1
  10. data/features/parser_with_native_lexer.feature +1 -1
  11. data/features/step_definitions/gherkin_steps.rb +2 -6
  12. data/features/step_definitions/pretty_printer_steps.rb +2 -3
  13. data/features/steps_parser.feature +1 -1
  14. data/gherkin.gemspec +40 -13
  15. data/java/Gherkin.iml +2 -4
  16. data/java/build.xml +3 -0
  17. data/java/src/gherkin/FixJava.java +6 -3
  18. data/java/src/gherkin/I18nLexer.java +48 -0
  19. data/java/src/gherkin/Listener.java +3 -1
  20. data/java/src/gherkin/Main.java +17 -0
  21. data/java/src/gherkin/Parser.java +9 -3
  22. data/java/src/gherkin/formatter/Argument.java +39 -0
  23. data/java/src/gherkin/formatter/ArgumentFormat.java +17 -0
  24. data/java/src/gherkin/formatter/Colors.java +7 -0
  25. data/java/src/gherkin/formatter/Formatter.java +15 -0
  26. data/java/src/gherkin/formatter/PrettyFormatter.java +219 -0
  27. data/java/src/gherkin/parser/StateMachineReader.java +8 -3
  28. data/java/test/gherkin/formatter/ArgumentTest.java +17 -0
  29. data/lib/gherkin/csharp_lexer.rb +15 -0
  30. data/lib/gherkin/format/argument.rb +35 -0
  31. data/lib/gherkin/format/monochrome_format.rb +9 -0
  32. data/lib/gherkin/i18n.rb +22 -0
  33. data/lib/gherkin/i18n.yml +34 -20
  34. data/lib/gherkin/i18n_lexer.rb +57 -13
  35. data/lib/gherkin/lexer.rb +9 -18
  36. data/lib/gherkin/parser.rb +3 -3
  37. data/lib/gherkin/parser/meta.txt +5 -4
  38. data/lib/gherkin/parser/root.txt +11 -9
  39. data/lib/gherkin/parser/steps.txt +4 -3
  40. data/lib/gherkin/rb_parser.rb +13 -5
  41. data/lib/gherkin/tools/colors.rb +119 -0
  42. data/lib/gherkin/tools/files.rb +6 -1
  43. data/lib/gherkin/tools/pretty_listener.rb +115 -23
  44. data/ragel/lexer.c.rl.erb +67 -51
  45. data/ragel/lexer.csharp.rl.erb +240 -0
  46. data/ragel/lexer.java.rl.erb +27 -18
  47. data/ragel/lexer.rb.rl.erb +17 -17
  48. data/ragel/lexer_common.rl.erb +8 -8
  49. data/spec/gherkin/c_lexer_spec.rb +4 -4
  50. data/spec/gherkin/csharp_lexer_spec.rb +20 -0
  51. data/spec/gherkin/fixtures/comments_in_table.feature +9 -0
  52. data/spec/gherkin/fixtures/complex.feature +2 -0
  53. data/spec/gherkin/fixtures/dos_line_endings.feature +45 -0
  54. data/spec/gherkin/fixtures/i18n_fr.feature +1 -0
  55. data/spec/gherkin/fixtures/i18n_no.feature +1 -0
  56. data/spec/gherkin/fixtures/i18n_zh-CN.feature +1 -0
  57. data/spec/gherkin/format/argument_spec.rb +28 -0
  58. data/spec/gherkin/i18n_lexer_spec.rb +4 -4
  59. data/spec/gherkin/i18n_spec.rb +31 -23
  60. data/spec/gherkin/java_lexer_spec.rb +4 -3
  61. data/spec/gherkin/parser_spec.rb +5 -0
  62. data/spec/gherkin/rb_lexer_spec.rb +4 -2
  63. data/spec/gherkin/sexp_recorder.rb +1 -1
  64. data/spec/gherkin/shared/lexer_spec.rb +169 -60
  65. data/spec/gherkin/shared/py_string_spec.rb +6 -0
  66. data/spec/gherkin/shared/row_spec.rb +107 -0
  67. data/spec/gherkin/shared/tags_spec.rb +1 -1
  68. data/spec/gherkin/tools/colors_spec.rb +19 -0
  69. data/spec/gherkin/tools/pretty_listener_spec.rb +147 -0
  70. data/spec/spec_helper.rb +31 -7
  71. data/tasks/compile.rake +81 -7
  72. data/tasks/ragel_task.rb +6 -4
  73. data/tasks/rspec.rake +2 -2
  74. metadata +86 -26
  75. data/lib/gherkin/java_lexer.rb +0 -10
  76. data/spec/gherkin/shared/table_spec.rb +0 -97
@@ -0,0 +1,20 @@
1
+ #encoding: utf-8
2
+ if defined?(RUBY_ENGINE) && RUBY_ENGINE == "ironruby"
3
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
4
+
5
+ module Gherkin
6
+ module Lexer
7
+ describe "C# Lexer" do
8
+ before do
9
+ @listener = Gherkin::SexpRecorder.new
10
+ @lexer = Gherkin::Lexer.csharp['en'].new(@listener)
11
+ end
12
+
13
+ it_should_behave_like "a Gherkin lexer"
14
+ it_should_behave_like "a Gherkin lexer lexing tags"
15
+ it_should_behave_like "a Gherkin lexer lexing py_strings"
16
+ it_should_behave_like "a Gherkin lexer lexing rows"
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,9 @@
1
+ Feature: x
2
+
3
+ Scenario Outline: x
4
+ Then x is <state>
5
+
6
+ Examples:
7
+ | state |
8
+ # comment
9
+ | 1 |
@@ -21,6 +21,7 @@ Feature: Feature Text
21
21
 
22
22
  @tag3
23
23
  Scenario: Reading a second scenario
24
+ With two lines of text
24
25
  #Comment on line 24
25
26
  Given a third step with a table
26
27
  |a|b|
@@ -39,5 +40,6 @@ Feature: Feature Text
39
40
  Given All work and no play
40
41
  """
41
42
  Makes Homer something something
43
+ And something else
42
44
  """
43
45
  Then crazy
@@ -0,0 +1,45 @@
1
+ #Comment on line 1
2
+ #Comment on line 2
3
+ @tag1 @tag2
4
+ Feature: Feature Text
5
+ In order to test multiline forms
6
+ As a ragel writer
7
+ I need to check for complex combinations
8
+
9
+ #Comment on line 9
10
+
11
+ #Comment on line 11
12
+
13
+ Background:
14
+ Given this is a background step
15
+ And this is another one
16
+
17
+ @tag3 @tag4
18
+ Scenario: Reading a Scenario
19
+ Given there is a step
20
+ But not another step
21
+
22
+ @tag3
23
+ Scenario: Reading a second scenario
24
+ With two lines of text
25
+ #Comment on line 24
26
+ Given a third step with a table
27
+ |a|b|
28
+ |c|d|
29
+ |e|f|
30
+ And I am still testing things
31
+ |g|h|
32
+ |e|r|
33
+ |k|i|
34
+ |n||
35
+ And I am done testing these tables
36
+ #Comment on line 29
37
+ Then I am happy
38
+
39
+ Scenario: Hammerzeit
40
+ Given All work and no play
41
+ """
42
+ Makes Homer something something
43
+ And something else
44
+ """
45
+ Then crazy
@@ -1,3 +1,4 @@
1
+ #language:fr
1
2
  Fonctionnalité: Addition
2
3
  Plan du scénario: Addition de produits dérivés
3
4
  Soit une calculatrice
@@ -1,3 +1,4 @@
1
+ #language:no
1
2
  Egenskap: i18n support
2
3
 
3
4
  Scenario: Parsing many languages
@@ -1,3 +1,4 @@
1
+ #language:zh-CN
1
2
  功能:加法
2
3
 
3
4
  场景: 两个数相加
@@ -0,0 +1,28 @@
1
+ # encoding: utf-8
2
+ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
3
+ require 'gherkin/format/argument'
4
+
5
+ module Gherkin
6
+ module Format
7
+ class BracketFormat
8
+ class << self
9
+ def new
10
+ defined?(JRUBY_VERSION) ? ::Java::GherkinFormatter::ArgumentFormat.new("[", "]") : super
11
+ end
12
+ end
13
+
14
+ def format_argument(s)
15
+ "[#{s}]"
16
+ end
17
+ end
18
+
19
+ describe Argument do
20
+ it "should replace one arg" do
21
+ argument_class = defined?(JRUBY_VERSION) ? ::Java::GherkinFormatter::Argument : Argument
22
+ argument_class.format("I have 10 cukes", BracketFormat.new, [Argument.new(7, '10')]).should == "I have [10] cukes"
23
+ end
24
+
25
+ # TODO: Add this spec: http://github.com/alg/cucumber/commit/33188e9db51f59ced74c4861524d7b2e69454630
26
+ end
27
+ end
28
+ end
@@ -4,19 +4,19 @@ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
4
4
  module Gherkin
5
5
  describe I18nLexer do
6
6
  before do
7
- @lexer = I18nLexer.new(SexpRecorder.new)
7
+ @lexer = I18nLexer.new(SexpRecorder.new, false)
8
8
  end
9
9
 
10
10
  it "should store the i18n language of the last scanned feature" do
11
11
  @lexer.scan("# language: fr\n")
12
- @lexer.language.key.should == "fr"
12
+ @lexer.i18n_language.should == "fr"
13
13
  @lexer.scan("# language: no\n")
14
- @lexer.language.key.should == "no"
14
+ @lexer.i18n_language.should == "no"
15
15
  end
16
16
 
17
17
  it "should use English i18n by default" do
18
18
  @lexer.scan("Feature: foo\n")
19
- @lexer.language.key.should == "en"
19
+ @lexer.i18n_language.should == "en"
20
20
  end
21
21
  end
22
22
  end
@@ -13,43 +13,51 @@ module Gherkin
13
13
  end
14
14
 
15
15
  it "should recognize keywords in the language of the lexer" do
16
- lexer = Gherkin::Lexer['no'].new(@listener)
16
+ lexer = Gherkin::I18nLexer.new(@listener, false)
17
17
  scan_file(lexer, "i18n_no.feature")
18
18
  @listener.to_sexp.should == [
19
- [:feature, "Egenskap", "i18n support", 1],
20
- [:scenario, "Scenario", "Parsing many languages", 3],
21
- [:step, "Gitt", "Gherkin supports many languages", 4],
22
- [:step, "Når", "Norwegian keywords are parsed", 5],
23
- [:step, "", "they should be recognized", 6]
19
+ [:comment, "#language:no", 1],
20
+ [:feature, "Egenskap", "i18n support", 2],
21
+ [:scenario, "Scenario", "Parsing many languages", 4],
22
+ [:step, "Gitt ", "Gherkin supports many languages", 5],
23
+ [:step, "Når ", "Norwegian keywords are parsed", 6],
24
+ [:step, "Så ", "they should be recognized", 7],
25
+ [:eof]
24
26
  ]
25
27
  end
26
28
 
27
29
  it "should parse languages without a space after keywords" do
28
- lexer = Gherkin::Lexer['zh-CN'].new(@listener)
30
+ lexer = Gherkin::I18nLexer.new(@listener, false)
29
31
  scan_file(lexer, "i18n_zh-CN.feature")
30
32
  @listener.to_sexp.should == [
31
- [:feature, "功能", "加法", 1],
32
- [:scenario, "场景", "两个数相加", 3],
33
- [:step, "假如", "我已经在计算器里输入6", 4],
34
- [:step, "而且", "我已经在计算器里输入7", 5],
35
- [:step, "", "我按相加按钮", 6],
36
- [:step, "那么", "我应该在屏幕上看到的结果是13", 7]
33
+ [:comment, "#language:zh-CN", 1],
34
+ [:feature, "功能", "加法", 2],
35
+ [:scenario, "场景", "两个数相加", 4],
36
+ [:step, "假如", "我已经在计算器里输入6", 5],
37
+ [:step, "而且", "我已经在计算器里输入7", 6],
38
+ [:step, "", "我按相加按钮", 7],
39
+ [:step, "那么", "我应该在屏幕上看到的结果是13", 8],
40
+ [:eof]
37
41
  ]
38
42
  end
39
43
 
40
44
  it "should parse languages with spaces after some keywords but not others" do
41
- lexer = Gherkin::Lexer['fr'].new(@listener)
45
+ lexer = Gherkin::I18nLexer.new(@listener, false)
42
46
  scan_file(lexer, "i18n_fr.feature")
43
47
  @listener.to_sexp.should == [
44
- [:feature, "Fonctionnalité", "Addition", 1],
45
- [:scenario_outline, "Plan du scénario", "Addition de produits dérivés", 2],
46
- [:step, "Soit", "une calculatrice", 3],
47
- [:step, "Etant donné", "qu'on tape <a>", 4],
48
- [:step, "Et", "qu'on tape <b>", 5],
49
- [:step, "Lorsqu'", "on tape additionner", 6],
50
- [:step, "Alors", "le résultat doit être <somme>", 7],
51
- [:examples, "Exemples", "", 9],
52
- [:table, [["a","b","somme"],["2","2","4"],["2","3","5"]], 10]
48
+ [:comment, "#language:fr", 1],
49
+ [:feature, "Fonctionnalité", "Addition", 2],
50
+ [:scenario_outline, "Plan du scénario", "Addition de produits dérivés", 3],
51
+ [:step, "Soit ", "une calculatrice", 4],
52
+ [:step, "Etant donné ", "qu'on tape <a>", 5],
53
+ [:step, "Et ", "qu'on tape <b>", 6],
54
+ [:step, "Lorsqu'", "on tape additionner", 7],
55
+ [:step, "Alors ", "le résultat doit être <somme>", 8],
56
+ [:examples, "Exemples", "", 10],
57
+ [:row, %w{a b somme}, 11],
58
+ [:row, %w{2 2 4}, 12],
59
+ [:row, %w{2 3 5}, 13],
60
+ [:eof]
53
61
  ]
54
62
  end
55
63
  end
@@ -1,20 +1,21 @@
1
1
  #encoding: utf-8
2
2
  if defined?(JRUBY_VERSION)
3
3
  require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
4
+ require 'gherkin.jar'
4
5
 
5
6
  module Gherkin
6
7
  module JavaLexer
7
8
  describe "Java Lexer" do
8
9
  before do
9
10
  @listener = Gherkin::SexpRecorder.new
10
- @lexer = Gherkin::Lexer.java['en'].new(@listener)
11
+ @lexer = Java::Gherkin::I18nLexer.new(@listener)
11
12
  end
12
13
 
13
14
  it_should_behave_like "a Gherkin lexer"
14
15
  it_should_behave_like "a Gherkin lexer lexing tags"
15
16
  it_should_behave_like "a Gherkin lexer lexing py_strings"
16
- it_should_behave_like "a Gherkin lexer lexing tables"
17
+ it_should_behave_like "a Gherkin lexer lexing rows"
17
18
  end
18
19
  end
19
20
  end
20
- end
21
+ end
@@ -19,6 +19,11 @@ module Gherkin
19
19
  }.should raise_error(/Parse error on line 12\. Found scenario when expecting one of: comment, feature, tag\. \(Current state: root\)\.$/)
20
20
  end
21
21
 
22
+ it "should allow empty files" do
23
+ @listener.should_receive(:eof)
24
+ @parser.eof
25
+ end
26
+
22
27
  it "should delegate an error message when raise on error is false" do
23
28
  @listener.should_receive(:syntax_error).with(sym(:root), sym(:background), a([:comment, :feature, :tag]), 1)
24
29
  @parser = Parser.new(@listener, false)
@@ -1,18 +1,20 @@
1
1
  #encoding: utf-8
2
2
  require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
3
+ require 'gherkin/rb_lexer'
4
+ require 'gherkin/rb_lexer/en'
3
5
 
4
6
  module Gherkin
5
7
  module Lexer
6
8
  describe "Ruby Lexer" do
7
9
  before do
8
10
  @listener = Gherkin::SexpRecorder.new
9
- @lexer = Gherkin::Lexer.rb['en'].new(@listener)
11
+ @lexer = Gherkin::RbLexer::En.new(@listener)
10
12
  end
11
13
 
12
14
  it_should_behave_like "a Gherkin lexer"
13
15
  it_should_behave_like "a Gherkin lexer lexing tags"
14
16
  it_should_behave_like "a Gherkin lexer lexing py_strings"
15
- it_should_behave_like "a Gherkin lexer lexing tables"
17
+ it_should_behave_like "a Gherkin lexer lexing rows"
16
18
  end
17
19
  end
18
20
  end
@@ -5,7 +5,7 @@ module Gherkin
5
5
  end
6
6
 
7
7
  def method_missing(m, *args)
8
- args[0] = args[0].map{|row| row.map{|cell| cell}} if m == :table
8
+ args[0] = args[0].map{|cell| cell} if m == :row
9
9
  @sexps << [m] + args
10
10
  end
11
11
 
@@ -8,14 +8,18 @@ module Gherkin
8
8
  describe "Comments" do
9
9
  it "should parse a one line comment" do
10
10
  @lexer.scan("# My comment\n")
11
- @listener.to_sexp.should == [[:comment, "# My comment", 1]]
11
+ @listener.to_sexp.should == [
12
+ [:comment, "# My comment", 1],
13
+ [:eof]
14
+ ]
12
15
  end
13
16
 
14
17
  it "should parse a multiline comment" do
15
18
  @lexer.scan("# Hello\n\n# World\n")
16
19
  @listener.to_sexp.should == [
17
20
  [:comment, "# Hello", 1],
18
- [:comment, "# World", 3]
21
+ [:comment, "# World", 3],
22
+ [:eof]
19
23
  ]
20
24
  end
21
25
 
@@ -24,7 +28,8 @@ module Gherkin
24
28
  @listener.to_sexp.should == [
25
29
  [:scenario, "Scenario", "test", 1],
26
30
  [:comment, "#hello", 2],
27
- [:scenario, "Scenario", "another", 3]
31
+ [:scenario, "Scenario", "another", 3],
32
+ [:eof]
28
33
  ]
29
34
  end
30
35
 
@@ -33,7 +38,8 @@ module Gherkin
33
38
  @listener.to_sexp.should == [
34
39
  [:comment, "#", 1],
35
40
  [:comment, "# A comment", 2],
36
- [:comment, "#", 3]
41
+ [:comment, "#", 3],
42
+ [:eof]
37
43
  ]
38
44
  end
39
45
 
@@ -51,7 +57,8 @@ module Gherkin
51
57
  [:feature, "Feature", "hi", 1],
52
58
  [:scenario, "Scenario", "test", 2],
53
59
  [:tag, "hello", 4],
54
- [:scenario, "Scenario", "another", 5]
60
+ [:scenario, "Scenario", "another", 5],
61
+ [:eof]
55
62
  ]
56
63
  end
57
64
  end
@@ -61,14 +68,16 @@ module Gherkin
61
68
  @lexer.scan("Background:\nGiven I am a step\n")
62
69
  @listener.to_sexp.should == [
63
70
  [:background, "Background", "", 1],
64
- [:step, "Given", "I am a step", 2]
71
+ [:step, "Given ", "I am a step", 2],
72
+ [:eof]
65
73
  ]
66
74
  end
67
75
 
68
76
  it "should allow multiline names ending at eof" do
69
77
  @lexer.scan("Background: I have several\n Lines to look at\n None starting with Given")
70
78
  @listener.to_sexp.should == [
71
- [:background, "Background", "I have several\nLines to look at\nNone starting with Given", 1]
79
+ [:background, "Background", "I have several\nLines to look at\nNone starting with Given", 1],
80
+ [:eof]
72
81
  ]
73
82
  end
74
83
 
@@ -82,7 +91,8 @@ Given I am a step})
82
91
  @listener.to_sexp.should == [
83
92
  [:feature, "Feature", "Hi", 1],
84
93
  [:background, "Background", "It is my ambition to say\nin ten sentences\nwhat others say\nin a whole book.",2],
85
- [:step, "Given", "I am a step", 6]
94
+ [:step, "Given ", "I am a step", 6],
95
+ [:eof]
86
96
  ]
87
97
  end
88
98
  end
@@ -91,7 +101,8 @@ Given I am a step})
91
101
  it "should be parsed" do
92
102
  @lexer.scan("Scenario: Hello\n")
93
103
  @listener.to_sexp.should == [
94
- [:scenario, "Scenario", "Hello", 1]
104
+ [:scenario, "Scenario", "Hello", 1],
105
+ [:eof]
95
106
  ]
96
107
  end
97
108
 
@@ -102,7 +113,8 @@ Given I am a step})
102
113
  })
103
114
  @listener.to_sexp.should == [
104
115
  [:scenario, "Scenario", "bar", 1],
105
- [:step, "Given", "baz", 3]
116
+ [:step, "Given ", "baz", 3],
117
+ [:eof]
106
118
  ]
107
119
  end
108
120
 
@@ -115,14 +127,16 @@ Given I am a step})
115
127
  })
116
128
  @listener.to_sexp.should == [
117
129
  [:scenario, "Scenario", "It is my ambition to say\nin ten sentences\nwhat others say\nin a whole book.", 1],
118
- [:step, "Given", "I am a step", 5]
130
+ [:step, "Given ", "I am a step", 5],
131
+ [:eof]
119
132
  ]
120
133
  end
121
134
 
122
135
  it "should allow multiline names ending at eof" do
123
136
  @lexer.scan("Scenario: I have several\n Lines to look at\n None starting with Given")
124
137
  @listener.to_sexp.should == [
125
- [:scenario, "Scenario", "I have several\nLines to look at\nNone starting with Given", 1]
138
+ [:scenario, "Scenario", "I have several\nLines to look at\nNone starting with Given", 1],
139
+ [:eof]
126
140
  ]
127
141
  end
128
142
 
@@ -134,8 +148,9 @@ Given I am a step})
134
148
  })
135
149
  @listener.to_sexp.should == [
136
150
  [:scenario, "Scenario", "I have a Button\nButtons are great", 1],
137
- [:step, "Given", "I have some", 3],
138
- [:step, "But", "I might not because I am a Charles Dickens character", 4]
151
+ [:step, "Given ", "I have some", 3],
152
+ [:step, "But ", "I might not because I am a Charles Dickens character", 4],
153
+ [:eof]
139
154
  ]
140
155
  end
141
156
 
@@ -146,7 +161,8 @@ Given I am a step
146
161
  })
147
162
  @listener.to_sexp.should == [
148
163
  [:scenario, "Scenario", "When I have when in scenario\nI should be fine", 1],
149
- [:step, "Given", "I am a step", 3]
164
+ [:step, "Given ", "I am a step", 3],
165
+ [:eof]
150
166
  ]
151
167
  end
152
168
  end
@@ -161,9 +177,11 @@ Given I am a step
161
177
  })
162
178
  @listener.to_sexp.should == [
163
179
  [:scenario_outline, "Scenario Outline", "Hello", 1],
164
- [:step, "Given", "a <what> cucumber", 2],
180
+ [:step, "Given ", "a <what> cucumber", 2],
165
181
  [:examples, "Examples", "", 3],
166
- [:table, [["what"],["green"]], 4]
182
+ [:row, ["what"], 4],
183
+ [:row, ["green"], 5],
184
+ [:eof]
167
185
  ]
168
186
  end
169
187
 
@@ -174,7 +192,8 @@ Given I am a step
174
192
  })
175
193
  @listener.to_sexp.should == [
176
194
  [:scenario_outline, "Scenario Outline", "Hello", 1],
177
- [:scenario, "Scenario", "My Scenario", 3]
195
+ [:scenario, "Scenario", "My Scenario", 3],
196
+ [:eof]
178
197
  ]
179
198
  end
180
199
 
@@ -188,7 +207,8 @@ Given I am a step
188
207
  })
189
208
  @listener.to_sexp.should == [
190
209
  [:scenario_outline, "Scenario Outline", "It is my ambition to say\nin ten sentences\nwhat others say\nin a whole book.", 1],
191
- [:step, "Given", "I am a step", 5]
210
+ [:step, "Given ", "I am a step", 5],
211
+ [:eof]
192
212
  ]
193
213
  end
194
214
  end
@@ -201,7 +221,9 @@ Given I am a step
201
221
  })
202
222
  @listener.to_sexp.should == [
203
223
  [:examples, "Examples", "", 1],
204
- [:table, [["x","y"],["5","6"]], 2]
224
+ [:row, ["x","y"], 2],
225
+ [:row, ["5","6"], 3],
226
+ [:eof]
205
227
  ]
206
228
  end
207
229
 
@@ -214,7 +236,9 @@ Given I am a step
214
236
  })
215
237
  @listener.to_sexp.should == [
216
238
  [:examples, "Examples", "I'm a multiline name\nand I'm ok\nf'real", 1],
217
- [:table, [["x"],["5"]], 4]
239
+ [:row, ["x"], 4],
240
+ [:row, ["5"], 5],
241
+ [:eof]
218
242
  ]
219
243
  end
220
244
  end
@@ -225,16 +249,18 @@ Given I am a step
225
249
  |a|b|
226
250
  })
227
251
  @listener.to_sexp.should == [
228
- [:step, "Given", "I have a table", 1],
229
- [:table, [['a','b']], 2]
252
+ [:step, "Given ", "I have a table", 1],
253
+ [:row, ['a','b'], 2],
254
+ [:eof]
230
255
  ]
231
256
  end
232
257
 
233
258
  it "should parse steps with inline py_string" do
234
259
  @lexer.scan("Given I have a string\n\"\"\"\nhello\nworld\n\"\"\"")
235
260
  @listener.to_sexp.should == [
236
- [:step, "Given", "I have a string", 1],
237
- [:py_string, "hello\nworld", 2]
261
+ [:step, "Given ", "I have a string", 1],
262
+ [:py_string, "hello\nworld", 2],
263
+ [:eof]
238
264
  ]
239
265
  end
240
266
  end
@@ -245,7 +271,8 @@ Given I am a step
245
271
  @listener.to_sexp.should == [
246
272
  [:feature, "Feature", "Feature Text", 1],
247
273
  [:scenario, "Scenario", "Reading a Scenario", 2],
248
- [:step, "Given", "there is a step", 3]
274
+ [:step, "Given ", "there is a step", 3],
275
+ [:eof]
249
276
  ]
250
277
  end
251
278
  end
@@ -256,7 +283,8 @@ Given I am a step
256
283
  @listener.to_sexp.should == [
257
284
  [:feature, "Feature", "Feature Text", 1],
258
285
  [:scenario, "Scenario", "Reading a Scenario", 2],
259
- [:step, "Given", "there is a step", 3]
286
+ [:step, "Given ", "there is a step", 3],
287
+ [:eof]
260
288
  ]
261
289
  end
262
290
  end
@@ -268,9 +296,10 @@ Given I am a step
268
296
  @listener.to_sexp.should == [
269
297
  [:feature, "Feature", "Feature Text", 1],
270
298
  [:scenario, "Scenario", "Reading a Scenario", 2],
271
- [:step, "Given", "there is a step", 3],
272
- [:step, "And", "another step", 4],
273
- [:step, "And", "a third step", 5]
299
+ [:step, "Given ", "there is a step", 3],
300
+ [:step, "And ", "another step", 4],
301
+ [:step, "And ", "a third step", 5],
302
+ [:eof]
274
303
  ]
275
304
  end
276
305
  end
@@ -278,19 +307,28 @@ Given I am a step
278
307
  describe "A single feature with no scenario" do
279
308
  it "should find the feature" do
280
309
  @lexer.scan("Feature: Feature Text\n")
281
- @listener.to_sexp.should == [[:feature, "Feature", "Feature Text", 1]]
310
+ @listener.to_sexp.should == [
311
+ [:feature, "Feature", "Feature Text", 1],
312
+ [:eof]
313
+ ]
282
314
  end
283
315
 
284
316
  it "should parse a one line feature with no newline" do
285
317
  @lexer.scan("Feature: hi")
286
- @listener.to_sexp.should == [[:feature, "Feature", "hi", 1]]
318
+ @listener.to_sexp.should == [
319
+ [:feature, "Feature", "hi", 1],
320
+ [:eof]
321
+ ]
287
322
  end
288
323
  end
289
324
 
290
325
  describe "A multi-line feature with no scenario" do
291
326
  it "should find the feature" do
292
327
  @lexer.scan("Feature: Feature Text\n And some more text")
293
- @listener.to_sexp.should == [[:feature, "Feature", "Feature Text\nAnd some more text", 1]]
328
+ @listener.to_sexp.should == [
329
+ [:feature, "Feature", "Feature Text\nAnd some more text", 1],
330
+ [:eof]
331
+ ]
294
332
  end
295
333
  end
296
334
 
@@ -299,7 +337,8 @@ Given I am a step
299
337
  @lexer.scan("Feature: Feature Text\nScenario: Reading a Scenario\n")
300
338
  @listener.to_sexp.should == [
301
339
  [:feature, "Feature", "Feature Text", 1],
302
- [:scenario, "Scenario", "Reading a Scenario", 2]
340
+ [:scenario, "Scenario", "Reading a Scenario", 2],
341
+ [:eof]
303
342
  ]
304
343
  end
305
344
  end
@@ -310,9 +349,10 @@ Given I am a step
310
349
  @listener.to_sexp.should == [
311
350
  [:feature, "Feature", "Feature Text", 1],
312
351
  [:scenario, "Scenario", "Reading a Scenario", 2],
313
- [:step, "Given", "a step", 3],
352
+ [:step, "Given ", "a step", 3],
314
353
  [:scenario, "Scenario", "A second scenario", 5],
315
- [:step, "Given", "another step", 6]
354
+ [:step, "Given ", "another step", 6],
355
+ [:eof]
316
356
  ]
317
357
  end
318
358
 
@@ -321,9 +361,10 @@ Given I am a step
321
361
  @listener.to_sexp.should == [
322
362
  [:feature, "Feature", "Feature Text", 1],
323
363
  [:scenario, "Scenario", "Reading a Scenario", 2],
324
- [:step, "Given", "a step", 3],
364
+ [:step, "Given ", "a step", 3],
325
365
  [:scenario, "Scenario", "A second scenario", 4],
326
- [:step, "Given", "another step", 5]
366
+ [:step, "Given ", "another step", 5],
367
+ [:eof]
327
368
  ]
328
369
  end
329
370
  end
@@ -337,8 +378,23 @@ Given I am a step
337
378
  [:comment, "# Here is another # comment", 3],
338
379
  [:scenario, "Scenario", "Reading a Scenario", 4],
339
380
  [:comment, "# Here is a third comment", 5],
340
- [:step, "Given", "there is a step", 6],
341
- [:comment, "# Here is a fourth comment", 7]
381
+ [:step, "Given ", "there is a step", 6],
382
+ [:comment, "# Here is a fourth comment", 7],
383
+ [:eof]
384
+ ]
385
+ end
386
+
387
+ it "should support comments in tables" do
388
+ scan_file("comments_in_table.feature")
389
+ @listener.to_sexp.should == [
390
+ [:feature, "Feature", "x", 1],
391
+ [:scenario_outline, "Scenario Outline", "x", 3],
392
+ [:step, "Then ", "x is <state>", 4],
393
+ [:examples, "Examples", "", 6],
394
+ [:row, ["state"], 7],
395
+ [:comment, "# comment", 8],
396
+ [:row, ["1"], 9],
397
+ [:eof]
342
398
  ]
343
399
  end
344
400
  end
@@ -353,12 +409,13 @@ Given I am a step
353
409
  [:tag, "st1", 5],
354
410
  [:tag, "st2", 5],
355
411
  [:scenario, "Scenario", "First", 6],
356
- [:step, "Given", "Pepper", 7],
412
+ [:step, "Given ", "Pepper", 7],
357
413
  [:tag, "st3", 9],
358
414
  [:tag, "st4", 10],
359
415
  [:tag, "ST5", 10],
360
416
  [:tag, "#^%&ST6**!", 10],
361
- [:scenario, "Scenario", "Second", 11]
417
+ [:scenario, "Scenario", "Second", 11],
418
+ [:eof]
362
419
  ]
363
420
  end
364
421
  end
@@ -371,7 +428,8 @@ Given I am a step
371
428
  [:comment, "# Comment", 3],
372
429
  [:scenario, "Scenario", "Anonymous user can get a login form.\nScenery here", 4],
373
430
  [:tag, "tag", 7],
374
- [:scenario, "Scenario", "Another one", 8]
431
+ [:scenario, "Scenario", "Another one", 8],
432
+ [:eof]
375
433
  ]
376
434
  end
377
435
  end
@@ -388,30 +446,81 @@ Given I am a step
388
446
  [:comment, "#Comment on line 9", 9],
389
447
  [:comment, "#Comment on line 11", 11],
390
448
  [:background, "Background", "", 13],
391
- [:step, "Given", "this is a background step", 14],
392
- [:step, "And", "this is another one", 15],
449
+ [:step, "Given ", "this is a background step", 14],
450
+ [:step, "And ", "this is another one", 15],
393
451
  [:tag, "tag3", 17],
394
452
  [:tag, "tag4", 17],
395
453
  [:scenario, "Scenario", "Reading a Scenario", 18],
396
- [:step, "Given", "there is a step", 19],
397
- [:step, "But", "not another step", 20],
454
+ [:step, "Given ", "there is a step", 19],
455
+ [:step, "But ", "not another step", 20],
398
456
  [:tag, "tag3", 22],
399
- [:scenario, "Scenario", "Reading a second scenario", 23],
400
- [:comment, "#Comment on line 24", 24],
401
- [:step, "Given", "a third step with a table", 25],
402
- [:table, [['a','b'],['c','d'],['e','f']], 26],
403
- [:step, "And", "I am still testing things", 29],
404
- [:table, [['g','h'],['e','r'],['k','i'],['n','']], 30],
405
- [:step, "And", "I am done testing these tables", 34],
406
- [:comment, "#Comment on line 29", 35],
407
- [:step, "Then", "I am happy", 36],
408
- [:scenario, "Scenario", "Hammerzeit", 38],
409
- [:step, "Given", "All work and no play", 39],
410
- [:py_string, "Makes Homer something something", 40],
411
- [:step, "Then", "crazy", 43]
457
+ [:scenario, "Scenario", "Reading a second scenario\nWith two lines of text", 23],
458
+ [:comment, "#Comment on line 24", 25],
459
+ [:step, "Given ", "a third step with a table", 26],
460
+ [:row, %w{a b}, 27],
461
+ [:row, %w{c d}, 28],
462
+ [:row, %w{e f}, 29],
463
+ [:step, "And ", "I am still testing things", 30],
464
+ [:row, %w{g h}, 31],
465
+ [:row, %w{e r}, 32],
466
+ [:row, %w{k i}, 33],
467
+ [:row, ['n', ''], 34],
468
+ [:step, "And ", "I am done testing these tables", 35],
469
+ [:comment, "#Comment on line 29", 36],
470
+ [:step, "Then ", "I am happy", 37],
471
+ [:scenario, "Scenario", "Hammerzeit", 39],
472
+ [:step, "Given ", "All work and no play", 40],
473
+ [:py_string, "Makes Homer something something\nAnd something else", 41 ],
474
+ [:step, "Then ", "crazy", 45],
475
+ [:eof]
412
476
  ]
413
477
  end
414
478
  end
479
+
480
+ context "DOS line endings" do
481
+ describe "A complex feature with tags, comments, multiple scenarios, and multiple steps and tables" do
482
+ it "should find things in the right order" do
483
+ scan_file("dos_line_endings.feature")
484
+ @listener.to_sexp.should == [
485
+ [:comment, "#Comment on line 1", 1],
486
+ [:comment, "#Comment on line 2", 2],
487
+ [:tag, "tag1", 3],
488
+ [:tag, "tag2", 3],
489
+ [: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],
490
+ [:comment, "#Comment on line 9", 9],
491
+ [:comment, "#Comment on line 11", 11],
492
+ [:background, "Background", "", 13],
493
+ [:step, "Given ", "this is a background step", 14],
494
+ [:step, "And ", "this is another one", 15],
495
+ [:tag, "tag3", 17],
496
+ [:tag, "tag4", 17],
497
+ [:scenario, "Scenario", "Reading a Scenario", 18],
498
+ [:step, "Given ", "there is a step", 19],
499
+ [:step, "But ", "not another step", 20],
500
+ [:tag, "tag3", 22],
501
+ [:scenario, "Scenario", "Reading a second scenario\r\nWith two lines of text", 23],
502
+ [:comment, "#Comment on line 24", 25],
503
+ [:step, "Given ", "a third step with a table", 26],
504
+ [:row, %w{a b}, 27],
505
+ [:row, %w{c d}, 28],
506
+ [:row, %w{e f}, 29],
507
+ [:step, "And ", "I am still testing things", 30],
508
+ [:row, %w{g h}, 31],
509
+ [:row, %w{e r}, 32],
510
+ [:row, %w{k i}, 33],
511
+ [:row, ['n', ''], 34],
512
+ [:step, "And ", "I am done testing these tables", 35],
513
+ [:comment, "#Comment on line 29", 36],
514
+ [:step, "Then ", "I am happy", 37],
515
+ [:scenario, "Scenario", "Hammerzeit", 39],
516
+ [:step, "Given ", "All work and no play", 40],
517
+ [:py_string, "Makes Homer something something\r\nAnd something else", 41],
518
+ [:step, "Then ", "crazy", 45],
519
+ [:eof]
520
+ ]
521
+ end
522
+ end
523
+ end
415
524
 
416
525
  describe "errors" do
417
526
  it "should raise a Lexing error if an unparseable token is found" do