gherkin 1.0.30 → 2.0.0

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,10 +1,13 @@
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 lexing py_strings" do
7
-
7
+ def scan(gherkin)
8
+ @lexer.scan(gherkin, "test.feature", 0)
9
+ end
10
+
8
11
  def ps(content)
9
12
  '"""%s"""' % ("\n" + content + "\n")
10
13
  end
@@ -21,17 +24,17 @@ Feature: some feature
21
24
  Then bar
22
25
  EOS
23
26
  @listener.should_receive(:py_string).with(" Hello\nGoodbye", 4)
24
- @lexer.scan(str)
27
+ scan(str)
25
28
  end
26
29
 
27
30
  it "should parse a simple py_string" do
28
31
  @listener.should_receive(:py_string).with("I am a py_string", 1)
29
- @lexer.scan ps("I am a py_string")
32
+ scan ps("I am a py_string")
30
33
  end
31
34
 
32
35
  it "should parse an empty py_string" do
33
36
  @listener.should_receive(:py_string).with("", 4)
34
- @lexer.scan("Feature: Hi\nScenario: Hi\nGiven a step\n\"\"\"\n\"\"\"")
37
+ scan("Feature: Hi\nScenario: Hi\nGiven a step\n\"\"\"\n\"\"\"")
35
38
  end
36
39
 
37
40
  it "should treat a string containing only newlines as only newlines" do
@@ -43,12 +46,13 @@ py_string = <<EOS
43
46
  """
44
47
  EOS
45
48
  @listener.should_receive(:py_string).with("\n\n", 1)
46
- @lexer.scan(py_string)
49
+ scan(py_string)
47
50
  end
48
51
 
49
52
  it "should parse content separated by two newlines" do
50
- @lexer.scan ps("A\n\nB")
53
+ scan ps("A\n\nB")
51
54
  @listener.to_sexp.should == [
55
+ [:location, 'test.feature', 0],
52
56
  [:py_string, "A\n\nB", 1],
53
57
  [:eof]
54
58
  ]
@@ -56,12 +60,12 @@ EOS
56
60
 
57
61
  it "should parse a multiline string" do
58
62
  @listener.should_receive(:py_string).with("A\nB\nC\nD", 1)
59
- @lexer.scan ps("A\nB\nC\nD")
63
+ scan ps("A\nB\nC\nD")
60
64
  end
61
65
 
62
66
  it "should ignore unescaped quotes inside the string delimeters" do
63
67
  @listener.should_receive(:py_string).with("What does \"this\" mean?", 1)
64
- @lexer.scan ps('What does "this" mean?')
68
+ scan ps('What does "this" mean?')
65
69
  end
66
70
 
67
71
  it "should preserve whitespace within the triple quotes" do
@@ -72,12 +76,12 @@ str = <<EOS
72
76
  """
73
77
  EOS
74
78
  @listener.should_receive(:py_string).with(" Line one\nLine two", 1)
75
- @lexer.scan(str)
79
+ scan(str)
76
80
  end
77
81
 
78
82
  it "should preserve tabs within the content" do
79
83
  @listener.should_receive(:py_string).with("I have\tsome tabs\nInside\t\tthe content", 1)
80
- @lexer.scan ps("I have\tsome tabs\nInside\t\tthe content")
84
+ scan ps("I have\tsome tabs\nInside\t\tthe content")
81
85
  end
82
86
 
83
87
  it "should handle complex py_strings" do
@@ -96,7 +100,7 @@ Feature: Sample
96
100
  EOS
97
101
 
98
102
  @listener.should_receive(:py_string).with(py_string, 1)
99
- @lexer.scan ps(py_string)
103
+ scan ps(py_string)
100
104
  end
101
105
 
102
106
  it "should allow whitespace after the closing py_string delimiter" do
@@ -106,7 +110,7 @@ str = <<EOS
106
110
  """
107
111
  EOS
108
112
  @listener.should_receive(:py_string).with(" Line one", 1)
109
- @lexer.scan(str)
113
+ scan(str)
110
114
  end
111
115
 
112
116
  it "should preserve the last newline(s) at the end of a py_string" do
@@ -118,12 +122,12 @@ str = <<EOS
118
122
  """
119
123
  EOS
120
124
  @listener.should_receive(:py_string).with("PyString text\n\n",1)
121
- @lexer.scan(str)
125
+ scan(str)
122
126
  end
123
127
 
124
128
  it "should preserve CRLFs within py_strings" do
125
129
  @listener.should_receive(:py_string).with("Line one\r\nLine two\r\n", 1)
126
- @lexer.scan("\"\"\"\r\nLine one\r\nLine two\r\n\r\n\"\"\"")
130
+ scan("\"\"\"\r\nLine one\r\nLine two\r\n\r\n\"\"\"")
127
131
  end
128
132
 
129
133
  it "should unescape escaped triple quotes" do
@@ -133,7 +137,7 @@ str = <<EOS
133
137
  """
134
138
  EOS
135
139
  @listener.should_receive(:py_string).with('"""', 1)
136
- @lexer.scan(str)
140
+ scan(str)
137
141
  end
138
142
 
139
143
  it "should not unescape escaped single quotes" do
@@ -143,7 +147,7 @@ str = <<EOS
143
147
  """
144
148
  EOS
145
149
  @listener.should_receive(:py_string).with('\" \"\"', 1)
146
- @lexer.scan(str)
150
+ scan(str)
147
151
  end
148
152
  end
149
153
  end
@@ -1,9 +1,13 @@
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 lexing rows" do
7
+ def scan(gherkin)
8
+ @lexer.scan(gherkin, "test.feature", 0)
9
+ end
10
+
7
11
  rows = {
8
12
  "|a|b|\n" => %w{a b},
9
13
  "|a|b|c|\n" => %w{a b c},
@@ -12,33 +16,34 @@ module Gherkin
12
16
  rows.each do |text, expected|
13
17
  it "should parse #{text}" do
14
18
  @listener.should_receive(:row).with(r(expected), 1)
15
- @lexer.scan(text.dup)
19
+ scan(text.dup)
16
20
  end
17
21
  end
18
22
 
19
23
  it "should parse a row with many cells" do
20
24
  @listener.should_receive(:row).with(r(%w{a b c d e f g h i j k l m n o p}), 1)
21
- @lexer.scan("|a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|\n")
25
+ scan("|a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|\n")
22
26
  end
23
27
 
24
28
  it "should parse multicharacter cell content" do
25
29
  @listener.should_receive(:row).with(r(%w{foo bar}), 1)
26
- @lexer.scan("| foo | bar |\n")
30
+ scan("| foo | bar |\n")
27
31
  end
28
32
 
29
33
  it "should escape backslashed pipes" do
30
34
  @listener.should_receive(:row).with(r(['|', 'the', '\a', '\\', '|\\|']), 1)
31
- @lexer.scan('| \| | the | \a | \\ | \|\\\| |' + "\n")
35
+ scan('| \| | the | \a | \\ | \|\\\| |' + "\n")
32
36
  end
33
37
 
34
38
  it "should parse cells with spaces within the content" do
35
39
  @listener.should_receive(:row).with(r(["Dill pickle", "Valencia orange"]), 1)
36
- @lexer.scan("| Dill pickle | Valencia orange |\n")
40
+ scan("| Dill pickle | Valencia orange |\n")
37
41
  end
38
42
 
39
43
  it "should allow utf-8" do
40
- @lexer.scan(" | ůﻚ | 2 | \n")
44
+ scan(" | ůﻚ | 2 | \n")
41
45
  @listener.to_sexp.should == [
46
+ [:location, 'test.feature', 0],
42
47
  [:row, ["ůﻚ", "2"], 1],
43
48
  [:eof]
44
49
  ]
@@ -46,58 +51,70 @@ module Gherkin
46
51
 
47
52
  it "should allow utf-8 using should_receive" do
48
53
  @listener.should_receive(:row).with(r(['繁體中文 而且','並且','繁體中文 而且','並且']), 1)
49
- @lexer.scan("| 繁體中文 而且|並且| 繁體中文 而且|並且|\n")
54
+ scan("| 繁體中文 而且|並且| 繁體中文 而且|並且|\n")
50
55
  end
51
56
 
52
57
  it "should parse a 2x2 table" do
53
58
  @listener.should_receive(:row).with(r(%w{1 2}), 1)
54
59
  @listener.should_receive(:row).with(r(%w{3 4}), 2)
55
- @lexer.scan("| 1 | 2 |\n| 3 | 4 |\n")
60
+ scan("| 1 | 2 |\n| 3 | 4 |\n")
56
61
  end
57
62
 
58
63
  it "should parse a 2x2 table with empty cells" do
59
64
  @listener.should_receive(:row).with(r(['1', '']), 1)
60
65
  @listener.should_receive(:row).with(r(['', '4']), 2)
61
- @lexer.scan("| 1 | |\n|| 4 |\n")
66
+ scan("| 1 | |\n|| 4 |\n")
62
67
  end
63
68
 
64
69
  it "should parse a row with empty cells" do
65
70
  @listener.should_receive(:row).with(r(['1', '']), 1).twice
66
- @lexer.scan("| 1 | |\n")
67
- @lexer.scan("|1||\n")
71
+ scan("| 1 | |\n")
72
+ scan("|1||\n")
68
73
  end
69
74
 
70
75
  it "should parse a 1x2 table that does not end in a newline" do
71
76
  @listener.should_receive(:row).with(r(%w{1 2}), 1)
72
- @lexer.scan("| 1 | 2 |")
77
+ scan("| 1 | 2 |")
73
78
  end
74
79
 
75
80
  it "should parse a row without spaces and with a newline" do
76
81
  @listener.should_receive(:row).with(r(%w{1 2}), 1)
77
- @lexer.scan("|1|2|\n")
82
+ scan("|1|2|\n")
78
83
  end
79
84
 
80
85
  it "should parse a row with whitespace after the rows" do
81
86
  @listener.should_receive(:row).with(r(%w{1 2}), 1)
82
- @lexer.scan("| 1 | 2 | \n ")
87
+ scan("| 1 | 2 | \n ")
83
88
  end
84
89
 
85
90
  it "should parse a row with lots of whitespace" do
86
91
  @listener.should_receive(:row).with(r(["abc", "123"]), 1)
87
- @lexer.scan(" \t| \t abc\t| \t123\t \t\t| \t\t \t \t\n ")
92
+ scan(" \t| \t abc\t| \t123\t \t\t| \t\t \t \t\n ")
88
93
  end
89
94
 
90
95
  it "should parse a table with a commented-out row" do
91
96
  @listener.should_receive(:row).with(r(["abc"]), 1)
92
97
  @listener.should_receive(:comment).with("#|123|", 2)
93
98
  @listener.should_receive(:row).with(r(["def"]), 3)
94
- @lexer.scan("|abc|\n#|123|\n|def|\n")
99
+ scan("|abc|\n#|123|\n|def|\n")
95
100
  end
96
101
 
97
102
  it "should raise LexingError for rows that aren't closed" do
98
103
  lambda {
99
- @lexer.scan("|| oh hello \n")
100
- }.should raise_error(/Parsing error on line 1: '|| oh hello/)
104
+ scan("|| oh hello \n")
105
+ }.should raise_error(/Lexing error on line 1: '\|\| oh hello/)
106
+ end
107
+
108
+ it "should raise LexingError for rows that are followed by a comment" do
109
+ lambda {
110
+ scan("|hi| # oh hello \n")
111
+ }.should raise_error(/Lexing error on line 1: '\|hi\| # oh hello/)
112
+ end
113
+
114
+ it "should raise LexingError for rows that aren't closed" do
115
+ lambda {
116
+ scan("|| oh hello \n |Shoudn't Get|Here|")
117
+ }.should raise_error(/Lexing error on line 1: '\|\| oh hello/)
101
118
  end
102
119
  end
103
120
  end
@@ -1,49 +1,53 @@
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 lexing tags" do
7
+ def scan(gherkin)
8
+ @lexer.scan(gherkin, "test.feature", 0)
9
+ end
10
+
7
11
  it "should lex a single tag" do
8
12
  @listener.should_receive(:tag).with("@dog", 1)
9
- @lexer.scan("@dog\n")
13
+ scan("@dog\n")
10
14
  end
11
15
 
12
16
  it "should lex multiple tags" do
13
17
  @listener.should_receive(:tag).twice
14
- @lexer.scan("@dog @cat\n")
18
+ scan("@dog @cat\n")
15
19
  end
16
20
 
17
21
  it "should lex UTF-8 tags" do
18
22
  @listener.should_receive(:tag).with("@シナリオテンプレート", 1)
19
- @lexer.scan("@シナリオテンプレート\n")
23
+ scan("@シナリオテンプレート\n")
20
24
  end
21
25
 
22
26
  it "should lex mixed tags" do
23
27
  @listener.should_receive(:tag).with("@wip", 1).ordered
24
28
  @listener.should_receive(:tag).with("@Значения", 1).ordered
25
- @lexer.scan("@wip @Значения\n")
29
+ scan("@wip @Значения\n")
26
30
  end
27
31
 
28
32
  it "should lex wacky identifiers" do
29
33
  @listener.should_receive(:tag).exactly(4).times
30
- @lexer.scan("@BJ-x98.77 @BJ-z12.33 @O_o" "@#not_a_comment\n")
34
+ scan("@BJ-x98.77 @BJ-z12.33 @O_o" "@#not_a_comment\n")
31
35
  end
32
36
 
33
37
  # TODO: Ask on ML for opinions about this one
34
38
  it "should lex tags without spaces between them?" do
35
39
  @listener.should_receive(:tag).twice
36
- @lexer.scan("@one@two\n")
40
+ scan("@one@two\n")
37
41
  end
38
42
 
39
43
  it "should not lex tags beginning with two @@ signs" do
40
44
  @listener.should_not_receive(:tag)
41
- lambda { @lexer.scan("@@test\n") }.should raise_error(/Lexing error on line 1/)
45
+ lambda { scan("@@test\n") }.should raise_error(/Lexing error on line 1/)
42
46
  end
43
47
 
44
48
  it "should not lex a lone @ sign" do
45
49
  @listener.should_not_receive(:tag)
46
- lambda { @lexer.scan("@\n") }.should raise_error(/Lexing error on line 1/)
50
+ lambda { scan("@\n") }.should raise_error(/Lexing error on line 1/)
47
51
  end
48
52
  end
49
53
  end
@@ -1,43 +1,23 @@
1
- $LOAD_PATH.unshift(File.dirname(__FILE__))
2
- $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
- $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'spec/gherkin'))
4
1
  require 'gherkin'
5
2
  require 'stringio'
6
3
  require 'gherkin/sexp_recorder'
4
+ require 'gherkin/output_stream_string_io'
7
5
  require 'rubygems'
8
- require 'spec'
9
- require 'spec/autorun'
10
- require 'shared/lexer_spec'
11
- require 'shared/tags_spec'
12
- require 'shared/py_string_spec'
13
- require 'shared/row_spec'
14
-
15
- if defined?(JRUBY_VERSION)
16
- class OutputStreamStringIO < Java.java.io.ByteArrayOutputStream
17
- def rewind
18
- end
19
-
20
- def read
21
- toString("UTF-8")
22
- end
23
- end
24
- end
25
-
26
- class StringIO
27
- class << self
28
- def new
29
- if defined?(JRUBY_VERSION)
30
- OutputStreamStringIO.new
31
- else
32
- super
33
- end
34
- end
35
- end
36
- end
6
+ require 'rspec/autorun'
7
+ require 'gherkin/shared/lexer_group'
8
+ require 'gherkin/shared/tags_group'
9
+ require 'gherkin/shared/py_string_group'
10
+ require 'gherkin/shared/row_group'
37
11
 
38
12
  module GherkinSpecHelper
13
+ # TODO: Rename to gherkin_scan_file
39
14
  def scan_file(file)
40
- @lexer.scan(File.new(File.dirname(__FILE__) + "/gherkin/fixtures/" + file).read)
15
+ @lexer.scan(File.new(File.dirname(__FILE__) + "/gherkin/fixtures/" + file).read, file, 0)
16
+ end
17
+
18
+ # TODO: Remove
19
+ def parse_file(file)
20
+ @parser.parse(File.new(File.dirname(__FILE__) + "/gherkin/fixtures/" + file).read)
41
21
  end
42
22
 
43
23
  def rubify_hash(hash)
@@ -51,12 +31,12 @@ module GherkinSpecHelper
51
31
  end
52
32
  end
53
33
 
54
- Spec::Runner.configure do |c|
34
+ RSpec.configure do |c|
55
35
  c.include(GherkinSpecHelper)
56
36
  end
57
37
 
58
38
  # Allows comparison of Java List with Ruby Array (rows)
59
- Spec::Matchers.define :r do |expected|
39
+ RSpec::Matchers.define :r do |expected|
60
40
  match do |row|
61
41
  def row.inspect
62
42
  "r " + self.map{|cell| cell}.inspect
@@ -65,7 +45,7 @@ Spec::Matchers.define :r do |expected|
65
45
  end
66
46
  end
67
47
 
68
- Spec::Matchers.define :a do |expected|
48
+ RSpec::Matchers.define :a do |expected|
69
49
  match do |array|
70
50
  def array.inspect
71
51
  "a " + self.map{|e| e.to_sym}.inspect
@@ -74,13 +54,13 @@ Spec::Matchers.define :a do |expected|
74
54
  end
75
55
  end
76
56
 
77
- Spec::Matchers.define :sym do |expected|
57
+ RSpec::Matchers.define :sym do |expected|
78
58
  match do |actual|
79
59
  expected.to_s == actual.to_s
80
60
  end
81
61
  end
82
62
 
83
- Spec::Matchers.define :allow do |event|
63
+ RSpec::Matchers.define :allow do |event|
84
64
  match do |parser|
85
65
  parser.expected.index(event)
86
66
  end
@@ -111,7 +111,7 @@ class Benchmarker
111
111
  parser = Gherkin::Parser::Parser.new(NullListener.new, true, "root")
112
112
  lexer = Gherkin::I18nLexer.new(parser, true)
113
113
  @features.each do |feature|
114
- lexer.scan(File.read(feature))
114
+ lexer.scan(File.read(feature), feature, 0)
115
115
  end
116
116
  end
117
117
 
@@ -122,7 +122,7 @@ class Benchmarker
122
122
  parser = Gherkin::Parser::Parser.new(NullListener.new, true, "root")
123
123
  lexer = Gherkin::I18nLexer.new(parser, false)
124
124
  @features.each do |feature|
125
- lexer.scan(File.read(feature))
125
+ lexer.scan(File.read(feature), feature, 0)
126
126
  end
127
127
  end
128
128
 
@@ -132,7 +132,7 @@ class Benchmarker
132
132
  require 'null_listener'
133
133
  lexer = Gherkin::I18nLexer.new(NullListener.new, false)
134
134
  @features.each do |feature|
135
- lexer.scan(File.read(feature))
135
+ lexer.scan(File.read(feature), feature, 0)
136
136
  end
137
137
  end
138
138
  end