bryanl-gherkin 2.11.1.1

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 (187) hide show
  1. data/.gitattributes +2 -0
  2. data/.mailmap +2 -0
  3. data/.rbenv-gemsets +1 -0
  4. data/.rspec +1 -0
  5. data/.rvmrc +1 -0
  6. data/.travis.yml +16 -0
  7. data/.yardopts +5 -0
  8. data/Gemfile +5 -0
  9. data/History.md +788 -0
  10. data/LICENSE +20 -0
  11. data/README.md +272 -0
  12. data/Rakefile +26 -0
  13. data/build_native_gems.sh +7 -0
  14. data/cucumber.yml +4 -0
  15. data/examples/parse_and_output_json.rb +19 -0
  16. data/features/.cucumber/stepdefs.json +244 -0
  17. data/features/escaped_pipes.feature +8 -0
  18. data/features/feature_parser.feature +237 -0
  19. data/features/json_formatter.feature +498 -0
  20. data/features/json_parser.feature +331 -0
  21. data/features/native_lexer.feature +19 -0
  22. data/features/parser_with_native_lexer.feature +205 -0
  23. data/features/pretty_formatter.feature +16 -0
  24. data/features/step_definitions/eyeball_steps.rb +3 -0
  25. data/features/step_definitions/gherkin_steps.rb +29 -0
  26. data/features/step_definitions/json_formatter_steps.rb +30 -0
  27. data/features/step_definitions/json_parser_steps.rb +20 -0
  28. data/features/step_definitions/pretty_formatter_steps.rb +85 -0
  29. data/features/steps_parser.feature +46 -0
  30. data/features/support/env.rb +42 -0
  31. data/gherkin.gemspec +77 -0
  32. data/install_mingw_os_x.sh +7 -0
  33. data/js/.npmignore +1 -0
  34. data/js/lib/gherkin/lexer/.npmignore +0 -0
  35. data/lib/gherkin.rb +2 -0
  36. data/lib/gherkin/c_lexer.rb +17 -0
  37. data/lib/gherkin/formatter/ansi_escapes.rb +97 -0
  38. data/lib/gherkin/formatter/argument.rb +16 -0
  39. data/lib/gherkin/formatter/escaping.rb +15 -0
  40. data/lib/gherkin/formatter/filter_formatter.rb +146 -0
  41. data/lib/gherkin/formatter/hashable.rb +19 -0
  42. data/lib/gherkin/formatter/json_formatter.rb +122 -0
  43. data/lib/gherkin/formatter/line_filter.rb +26 -0
  44. data/lib/gherkin/formatter/model.rb +281 -0
  45. data/lib/gherkin/formatter/pretty_formatter.rb +244 -0
  46. data/lib/gherkin/formatter/regexp_filter.rb +21 -0
  47. data/lib/gherkin/formatter/step_printer.rb +21 -0
  48. data/lib/gherkin/formatter/tag_count_formatter.rb +47 -0
  49. data/lib/gherkin/formatter/tag_filter.rb +19 -0
  50. data/lib/gherkin/i18n.rb +180 -0
  51. data/lib/gherkin/i18n.yml +613 -0
  52. data/lib/gherkin/js_lexer.rb +20 -0
  53. data/lib/gherkin/json_parser.rb +177 -0
  54. data/lib/gherkin/lexer/i18n_lexer.rb +46 -0
  55. data/lib/gherkin/listener/event.rb +45 -0
  56. data/lib/gherkin/listener/formatter_listener.rb +143 -0
  57. data/lib/gherkin/native.rb +7 -0
  58. data/lib/gherkin/native/java.rb +72 -0
  59. data/lib/gherkin/native/null.rb +5 -0
  60. data/lib/gherkin/native/therubyracer.rb +39 -0
  61. data/lib/gherkin/parser/meta.txt +5 -0
  62. data/lib/gherkin/parser/parser.rb +164 -0
  63. data/lib/gherkin/parser/root.txt +11 -0
  64. data/lib/gherkin/parser/steps.txt +4 -0
  65. data/lib/gherkin/rb_lexer.rb +8 -0
  66. data/lib/gherkin/rb_lexer/README.rdoc +8 -0
  67. data/lib/gherkin/rb_lexer/ar.rb +1165 -0
  68. data/lib/gherkin/rb_lexer/bg.rb +1377 -0
  69. data/lib/gherkin/rb_lexer/bm.rb +1081 -0
  70. data/lib/gherkin/rb_lexer/ca.rb +1305 -0
  71. data/lib/gherkin/rb_lexer/cs.rb +1157 -0
  72. data/lib/gherkin/rb_lexer/cy_gb.rb +1027 -0
  73. data/lib/gherkin/rb_lexer/da.rb +1043 -0
  74. data/lib/gherkin/rb_lexer/de.rb +1151 -0
  75. data/lib/gherkin/rb_lexer/en.rb +1151 -0
  76. data/lib/gherkin/rb_lexer/en_au.rb +971 -0
  77. data/lib/gherkin/rb_lexer/en_lol.rb +929 -0
  78. data/lib/gherkin/rb_lexer/en_pirate.rb +1205 -0
  79. data/lib/gherkin/rb_lexer/en_scouse.rb +1357 -0
  80. data/lib/gherkin/rb_lexer/en_tx.rb +1011 -0
  81. data/lib/gherkin/rb_lexer/eo.rb +990 -0
  82. data/lib/gherkin/rb_lexer/es.rb +1135 -0
  83. data/lib/gherkin/rb_lexer/et.rb +985 -0
  84. data/lib/gherkin/rb_lexer/fi.rb +964 -0
  85. data/lib/gherkin/rb_lexer/fr.rb +1223 -0
  86. data/lib/gherkin/rb_lexer/he.rb +1113 -0
  87. data/lib/gherkin/rb_lexer/hr.rb +1061 -0
  88. data/lib/gherkin/rb_lexer/hu.rb +1113 -0
  89. data/lib/gherkin/rb_lexer/id.rb +958 -0
  90. data/lib/gherkin/rb_lexer/is.rb +1115 -0
  91. data/lib/gherkin/rb_lexer/it.rb +1081 -0
  92. data/lib/gherkin/rb_lexer/ja.rb +1413 -0
  93. data/lib/gherkin/rb_lexer/ko.rb +1097 -0
  94. data/lib/gherkin/rb_lexer/lt.rb +1040 -0
  95. data/lib/gherkin/rb_lexer/lu.rb +1127 -0
  96. data/lib/gherkin/rb_lexer/lv.rb +1161 -0
  97. data/lib/gherkin/rb_lexer/nl.rb +1110 -0
  98. data/lib/gherkin/rb_lexer/no.rb +1055 -0
  99. data/lib/gherkin/rb_lexer/pl.rb +1452 -0
  100. data/lib/gherkin/rb_lexer/pt.rb +1425 -0
  101. data/lib/gherkin/rb_lexer/ro.rb +1159 -0
  102. data/lib/gherkin/rb_lexer/ru.rb +1749 -0
  103. data/lib/gherkin/rb_lexer/sk.rb +1041 -0
  104. data/lib/gherkin/rb_lexer/sr_cyrl.rb +1798 -0
  105. data/lib/gherkin/rb_lexer/sr_latn.rb +1289 -0
  106. data/lib/gherkin/rb_lexer/sv.rb +1065 -0
  107. data/lib/gherkin/rb_lexer/tr.rb +1087 -0
  108. data/lib/gherkin/rb_lexer/uk.rb +1641 -0
  109. data/lib/gherkin/rb_lexer/uz.rb +1371 -0
  110. data/lib/gherkin/rb_lexer/vi.rb +1193 -0
  111. data/lib/gherkin/rb_lexer/zh_cn.rb +1053 -0
  112. data/lib/gherkin/rb_lexer/zh_tw.rb +1047 -0
  113. data/lib/gherkin/rubify.rb +24 -0
  114. data/lib/gherkin/tag_expression.rb +62 -0
  115. data/ragel/lexer.c.rl.erb +454 -0
  116. data/ragel/lexer.java.rl.erb +219 -0
  117. data/ragel/lexer.js.rl.erb +227 -0
  118. data/ragel/lexer.rb.rl.erb +174 -0
  119. data/ragel/lexer_common.rl.erb +50 -0
  120. data/spec/gherkin/c_lexer_spec.rb +22 -0
  121. data/spec/gherkin/fixtures/1.feature +8 -0
  122. data/spec/gherkin/fixtures/comments_in_table.feature +9 -0
  123. data/spec/gherkin/fixtures/complex.feature +45 -0
  124. data/spec/gherkin/fixtures/complex.json +139 -0
  125. data/spec/gherkin/fixtures/complex_for_filtering.feature +60 -0
  126. data/spec/gherkin/fixtures/complex_with_tags.feature +61 -0
  127. data/spec/gherkin/fixtures/dos_line_endings.feature +45 -0
  128. data/spec/gherkin/fixtures/examples_with_only_header.feature +14 -0
  129. data/spec/gherkin/fixtures/hantu_pisang.feature +35 -0
  130. data/spec/gherkin/fixtures/i18n_fr.feature +14 -0
  131. data/spec/gherkin/fixtures/i18n_fr2.feature +8 -0
  132. data/spec/gherkin/fixtures/i18n_no.feature +7 -0
  133. data/spec/gherkin/fixtures/i18n_pt1.feature +44 -0
  134. data/spec/gherkin/fixtures/i18n_pt2.feature +4 -0
  135. data/spec/gherkin/fixtures/i18n_pt3.feature +4 -0
  136. data/spec/gherkin/fixtures/i18n_pt4.feature +4 -0
  137. data/spec/gherkin/fixtures/i18n_zh-CN.feature +9 -0
  138. data/spec/gherkin/fixtures/issue_145.feature +22 -0
  139. data/spec/gherkin/fixtures/scenario_outline_with_tags.feature +13 -0
  140. data/spec/gherkin/fixtures/scenario_without_steps.feature +5 -0
  141. data/spec/gherkin/fixtures/simple_with_comments.feature +7 -0
  142. data/spec/gherkin/fixtures/simple_with_tags.feature +11 -0
  143. data/spec/gherkin/fixtures/with_bom.feature +3 -0
  144. data/spec/gherkin/formatter/ansi_escapes_spec.rb +32 -0
  145. data/spec/gherkin/formatter/filter_formatter_spec.rb +204 -0
  146. data/spec/gherkin/formatter/json_formatter_spec.rb +92 -0
  147. data/spec/gherkin/formatter/model_spec.rb +28 -0
  148. data/spec/gherkin/formatter/pretty_formatter_spec.rb +177 -0
  149. data/spec/gherkin/formatter/spaces.feature +9 -0
  150. data/spec/gherkin/formatter/step_printer_spec.rb +55 -0
  151. data/spec/gherkin/formatter/tabs.feature +9 -0
  152. data/spec/gherkin/formatter/tag_count_formatter_spec.rb +30 -0
  153. data/spec/gherkin/i18n_spec.rb +241 -0
  154. data/spec/gherkin/java_lexer_spec.rb +20 -0
  155. data/spec/gherkin/js_lexer_spec.rb +23 -0
  156. data/spec/gherkin/json_parser_spec.rb +176 -0
  157. data/spec/gherkin/lexer/i18n_lexer_spec.rb +43 -0
  158. data/spec/gherkin/output_stream_string_io.rb +20 -0
  159. data/spec/gherkin/parser/parser_spec.rb +16 -0
  160. data/spec/gherkin/rb_lexer_spec.rb +20 -0
  161. data/spec/gherkin/sexp_recorder.rb +59 -0
  162. data/spec/gherkin/shared/bom_group.rb +20 -0
  163. data/spec/gherkin/shared/doc_string_group.rb +163 -0
  164. data/spec/gherkin/shared/lexer_group.rb +591 -0
  165. data/spec/gherkin/shared/row_group.rb +125 -0
  166. data/spec/gherkin/shared/tags_group.rb +54 -0
  167. data/spec/gherkin/tag_expression_spec.rb +142 -0
  168. data/spec/spec_helper.rb +75 -0
  169. data/tasks/bench.rake +184 -0
  170. data/tasks/bench/feature_builder.rb +49 -0
  171. data/tasks/bench/null_listener.rb +4 -0
  172. data/tasks/compile.rake +120 -0
  173. data/tasks/cucumber.rake +22 -0
  174. data/tasks/gems.rake +31 -0
  175. data/tasks/ikvm.rake +124 -0
  176. data/tasks/ragel_task.rb +100 -0
  177. data/tasks/release.rake +49 -0
  178. data/tasks/rspec.rake +8 -0
  179. data/tasks/yard.rake +7 -0
  180. data/tasks/yard/default/layout/html/bubble_32x32.png +0 -0
  181. data/tasks/yard/default/layout/html/bubble_48x48.png +0 -0
  182. data/tasks/yard/default/layout/html/footer.erb +5 -0
  183. data/tasks/yard/default/layout/html/index.erb +1 -0
  184. data/tasks/yard/default/layout/html/layout.erb +25 -0
  185. data/tasks/yard/default/layout/html/logo.erb +1 -0
  186. data/tasks/yard/default/layout/html/setup.rb +4 -0
  187. metadata +473 -0
@@ -0,0 +1,20 @@
1
+ #encoding: utf-8
2
+ if defined?(JRUBY_VERSION)
3
+ require 'spec_helper'
4
+
5
+ module Gherkin
6
+ module JavaLexer
7
+ describe "Java Lexer" do
8
+ before do
9
+ @listener = Gherkin::SexpRecorder.new
10
+ @lexer = Java::GherkinLexer::I18nLexer.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 doc_strings"
16
+ it_should_behave_like "a Gherkin lexer lexing rows"
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,23 @@
1
+ #encoding: utf-8
2
+ if !defined?(JRUBY_VERSION) && ENV['GHERKIN_JS']
3
+ require 'spec_helper'
4
+ require 'gherkin/js_lexer'
5
+
6
+ module Gherkin
7
+ module Lexer
8
+ describe "JavaScript Lexer" do
9
+ before do
10
+ @listener = Gherkin::SexpRecorder.new
11
+ @lexer = Gherkin::JsLexer['en'].new(@listener)
12
+ end
13
+
14
+ it_should_behave_like "a Gherkin lexer"
15
+ it_should_behave_like "a Gherkin lexer lexing tags"
16
+ it_should_behave_like "a Gherkin lexer lexing doc_strings"
17
+ it_should_behave_like "a Gherkin lexer lexing rows"
18
+ # TODO - make this pass!
19
+ # it_should_behave_like "parsing windows files"
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,176 @@
1
+ #encoding: utf-8
2
+ require 'stringio'
3
+ require 'spec_helper'
4
+ require 'gherkin/json_parser'
5
+ require 'gherkin/formatter/json_formatter'
6
+
7
+ module Gherkin
8
+ describe JSONParser do
9
+
10
+ def check_json(json)
11
+ io = StringIO.new
12
+ f = Formatter::JSONFormatter.new(io)
13
+ p = JSONParser.new(f, f)
14
+ p.parse(json)
15
+ f.done
16
+ expected = JSON.parse(json)
17
+ actual = JSON.parse(io.string)
18
+
19
+ begin
20
+ actual.should == expected
21
+ rescue
22
+ puts "EXPECTED"
23
+ puts json
24
+ puts "ACTUAL"
25
+ puts io.string
26
+ puts "======"
27
+
28
+ raise
29
+ end
30
+ end
31
+
32
+ it "should parse a barely empty feature" do
33
+ check_json(%{[
34
+ {
35
+ "id": "one",
36
+ "uri": "test.feature",
37
+ "keyword": "Feature",
38
+ "name": "One",
39
+ "description": "",
40
+ "line" : 3
41
+ }
42
+ ]})
43
+ end
44
+
45
+ it "should parse feature with tags and one scenario" do
46
+ check_json(%{[
47
+ {
48
+ "id": "one",
49
+ "uri": "test.feature",
50
+ "tags": [
51
+ {
52
+ "name": "@foo",
53
+ "line": 22
54
+ }
55
+ ],
56
+ "keyword": "Feature",
57
+ "name": "One",
58
+ "description": "",
59
+ "line": 3,
60
+ "elements": [
61
+ {
62
+ "id": "one/two",
63
+ "type": "scenario",
64
+ "steps": [
65
+ {
66
+ "name": "Hello",
67
+ "rows": [
68
+ {
69
+ "cells": ["foo", "bar"]
70
+ }
71
+ ]
72
+ }
73
+ ]
74
+ }
75
+ ]
76
+ }
77
+ ]})
78
+ end
79
+
80
+ it "should parse feature with match, result and embedding" do
81
+ check_json(%{
82
+ [
83
+ {
84
+ "id":"one",
85
+ "uri":"test.feature",
86
+ "tags":[
87
+ {
88
+ "name":"@foo",
89
+ "line":22
90
+ }
91
+ ],
92
+ "keyword":"Feature",
93
+ "name":"One",
94
+ "description":"",
95
+ "line":3,
96
+ "elements":[
97
+ {
98
+ "id":"one/a-scenario",
99
+ "type":"scenario",
100
+ "before": [
101
+ {
102
+ "match":{
103
+ "location":"features/step_definitions/hooks.rb:1"
104
+ },
105
+ "result":{
106
+ "status":"passed",
107
+ "error_message":"Passed hook",
108
+ "duration": 3
109
+ }
110
+ },
111
+ {
112
+ "match":{
113
+ "location":"features/step_definitions/hooks.rb:2"
114
+ },
115
+ "result":{
116
+ "status":"failed",
117
+ "error_message":"Failed hook",
118
+ "duration": 22
119
+ }
120
+ }
121
+ ],
122
+ "steps":[
123
+ {
124
+ "keyword":"Given ",
125
+ "name":"a passing step",
126
+ "line":6,
127
+ "match":{
128
+ "arguments":[
129
+ {
130
+ "offset":22,
131
+ "val":"cukes"
132
+ }
133
+ ],
134
+ "location":"features/step_definitions/steps.rb:1"
135
+ },
136
+ "result":{
137
+ "status":"failed",
138
+ "error_message":"You suck",
139
+ "duration":-1
140
+ },
141
+ "embeddings":[
142
+ {
143
+ "mime_type":"text/plain",
144
+ "data":"Tm8sIEknbSBub3QgaW50ZXJlc3RlZCBpbiBkZXZlbG9waW5nIGEgcG93ZXJmdWwgYnJhaW4uIEFsbCBJJ20gYWZ0ZXIgaXMganVzdCBhIG1lZGlvY3JlIGJyYWluLCBzb21ldGhpbmcgbGlrZSB0aGUgUHJlc2lkZW50IG9mIHRoZSBBbWVyaWNhbiBUZWxlcGhvbmUgYW5kIFRlbGVncmFwaCBDb21wYW55Lg=="
145
+ }
146
+ ],
147
+ "output":[
148
+ "Hello",
149
+ "World"
150
+ ]
151
+ }
152
+ ],
153
+ "after": [
154
+ {
155
+ "match":{
156
+ "location":"features/step_definitions/hooks.rb:3"
157
+ },
158
+ "result":{
159
+ "status":"failed",
160
+ "error_message":"Failed After",
161
+ "duration": 22
162
+ }
163
+ }
164
+ ]
165
+ }
166
+ ]
167
+ }
168
+ ]
169
+ })
170
+ end
171
+
172
+ it "shoud parse a complex feature" do
173
+ check_json('[' + fixture("complex.json") + ']')
174
+ end
175
+ end
176
+ end
@@ -0,0 +1,43 @@
1
+ #encoding: utf-8
2
+ require 'spec_helper'
3
+
4
+ module Gherkin
5
+ module Lexer
6
+ describe I18nLexer do
7
+ before do
8
+ @lexer = Gherkin::Lexer::I18nLexer.new(Gherkin::SexpRecorder.new, false)
9
+ end
10
+
11
+ it "should store the i18n language of the last scanned feature" do
12
+ @lexer.scan("# language: fr\n")
13
+ @lexer.i18n_language.iso_code.should == "fr"
14
+ @lexer.scan("# language: no\n")
15
+ @lexer.i18n_language.iso_code.should == "no"
16
+ end
17
+
18
+ it "should detect language when there are spaces and CRLF" do
19
+ @lexer.scan("# language: da \r\n")
20
+ @lexer.i18n_language.iso_code.should == "da"
21
+ end
22
+
23
+ it "should detect language when the language comment is not the first line" do
24
+ @lexer.scan("# hello\n# language: no\n")
25
+ @lexer.i18n_language.iso_code.should == "no"
26
+ end
27
+
28
+ it "should detect language when the language is on the third line, and there are empty lines above" do
29
+ @lexer.scan("# hello\n\n# language: no\n")
30
+ @lexer.i18n_language.iso_code.should == "no"
31
+ end
32
+
33
+ it "should use English i18n by default" do
34
+ @lexer.scan("Feature: foo\n")
35
+ @lexer.i18n_language.iso_code.should == "en"
36
+ end
37
+
38
+ it "should === its ruby class, even when the impl is Java" do
39
+ Gherkin::Lexer::I18nLexer.should === Gherkin::Lexer::I18nLexer.new(Gherkin::SexpRecorder.new, true)
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,20 @@
1
+ if defined?(JRUBY_VERSION)
2
+ class WriterStringIO < Java.java.io.StringWriter
3
+ def write(what)
4
+ super(Java.java.lang.String.new(what.to_s))
5
+ end
6
+
7
+ def string
8
+ toString()
9
+ end
10
+ end
11
+
12
+ require 'stringio'
13
+ class StringIO
14
+ class << self
15
+ def new
16
+ WriterStringIO.new
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,16 @@
1
+ require 'spec_helper'
2
+
3
+ module Gherkin
4
+ module Parser
5
+ describe Parser do
6
+ unless defined?(JRUBY_VERSION)
7
+ it "should raise when feature doesn't parse" do
8
+ p = Parser.new(mock('formatter').as_null_object)
9
+ lambda do
10
+ p.parse("Feature: f\nFeature: f", __FILE__, __LINE__-1)
11
+ end.should raise_error(/Parse error at/)
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,20 @@
1
+ #encoding: utf-8
2
+ require 'spec_helper'
3
+ require 'gherkin/rb_lexer/en'
4
+
5
+ module Gherkin
6
+ module Lexer
7
+ describe "Ruby Lexer" do
8
+ before do
9
+ @listener = Gherkin::SexpRecorder.new
10
+ @lexer = Gherkin::RbLexer::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 doc_strings"
16
+ it_should_behave_like "a Gherkin lexer lexing rows"
17
+ it_should_behave_like "parsing windows files"
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,59 @@
1
+ require 'gherkin/rubify'
2
+ require 'gherkin/formatter/model'
3
+
4
+ module Gherkin
5
+ class SexpRecorder
6
+ include Rubify
7
+
8
+ def initialize
9
+ @sexps = []
10
+ end
11
+
12
+ # We can't use method_missing - therubyracer isn't able to invoke methods like that.
13
+ [:comment, :tag, :feature, :background, :scenario, :scenario_outline, :examples, :step, :doc_string, :row, :eof, :uri, :syntax_error].each do |event|
14
+ define_method(event) do |*args|
15
+ args = rubify(args)
16
+ args = sexpify(args)
17
+ @sexps << [event] + args
18
+ end
19
+ end
20
+
21
+ def to_sexp
22
+ @sexps
23
+ end
24
+
25
+ # Useful in IRB
26
+ def reset!
27
+ @sexps = []
28
+ end
29
+
30
+ def errors
31
+ @sexps.select { |sexp| sexp[0] == :syntax_error }
32
+ end
33
+
34
+ def line(number)
35
+ @sexps.find { |sexp| sexp.last == number }
36
+ end
37
+
38
+ def sexpify(o)
39
+ array = (defined?(JRUBY_VERSION) && Java.java.util.Collection === o) ||
40
+ (defined?(V8) && V8::Array === o) ||
41
+ Array === o
42
+ if array
43
+ o.map{|e| sexpify(e)}
44
+ elsif(Formatter::Model::Row === o)
45
+ {
46
+ "cells" => sexpify(o.cells),
47
+ "comments" => sexpify(o.comments),
48
+ "line" => o.line,
49
+ }
50
+ elsif(Formatter::Model::Comment === o)
51
+ o.value
52
+ elsif(Formatter::Model::Tag === o)
53
+ o.name
54
+ else
55
+ o
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,20 @@
1
+ #encoding: utf-8
2
+ require 'spec_helper'
3
+
4
+ module Gherkin
5
+ module Lexer
6
+ shared_examples_for "parsing windows files" do
7
+ describe "with BOM" do
8
+ it "should work just fine" do
9
+ scan_file("with_bom.feature")
10
+ @listener.to_sexp.should == [
11
+ [:feature, "Feature", "Feature Text", "", 1],
12
+ [:scenario, "Scenario", "Reading a Scenario", "", 2],
13
+ [:step, "Given ", "there is a step", 3],
14
+ [:eof]
15
+ ]
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,163 @@
1
+ # encoding: utf-8
2
+ require 'spec_helper'
3
+
4
+ module Gherkin
5
+ module Lexer
6
+ shared_examples_for "a Gherkin lexer lexing doc_strings" do
7
+ def scan(gherkin)
8
+ @lexer.scan(gherkin)
9
+ end
10
+
11
+ def ps(content)
12
+ '"""%s"""' % ("\n" + content + "\n")
13
+ end
14
+
15
+ it "should provide the amount of indentation of the triple quotes to the listener" do
16
+ str = <<EOS
17
+ Feature: some feature
18
+ Scenario: some scenario
19
+ Given foo
20
+ """
21
+ Hello
22
+ Goodbye
23
+ """
24
+ Then bar
25
+ EOS
26
+ @listener.should_receive(:doc_string).with('', " Hello\nGoodbye", 4)
27
+ scan(str)
28
+ end
29
+
30
+ it "should parse a simple doc_string" do
31
+ @listener.should_receive(:doc_string).with('', "I am a doc_string", 1)
32
+ scan ps("I am a doc_string")
33
+ end
34
+
35
+ it "should parse an empty doc_string" do
36
+ @listener.should_receive(:doc_string).with('', '', 4)
37
+ scan("Feature: Hi\nScenario: Hi\nGiven a step\n\"\"\"\n\"\"\"")
38
+ end
39
+
40
+ it "should treat a string containing only newlines as only newlines" do
41
+ doc_string = <<EOS
42
+ """
43
+
44
+
45
+
46
+ """
47
+ EOS
48
+ @listener.should_receive(:doc_string).with('', "\n\n", 1)
49
+ scan(doc_string)
50
+ end
51
+
52
+ it "should parse content separated by two newlines" do
53
+ scan ps("A\n\nB")
54
+ @listener.to_sexp.should == [
55
+ [:doc_string, '', "A\n\nB", 1],
56
+ [:eof]
57
+ ]
58
+ end
59
+
60
+ it "should parse a multiline string" do
61
+ @listener.should_receive(:doc_string).with('', "A\nB\nC\nD", 1)
62
+ scan ps("A\nB\nC\nD")
63
+ end
64
+
65
+ it "should ignore unescaped quotes inside the string delimeters" do
66
+ @listener.should_receive(:doc_string).with('', "What does \"this\" mean?", 1)
67
+ scan ps('What does "this" mean?')
68
+ end
69
+
70
+ it "should preserve whitespace within the triple quotes" do
71
+ str = <<EOS
72
+ """
73
+ Line one
74
+ Line two
75
+ """
76
+ EOS
77
+ @listener.should_receive(:doc_string).with('', " Line one\nLine two", 1)
78
+ scan(str)
79
+ end
80
+
81
+ it "should preserve tabs within the content" do
82
+ @listener.should_receive(:doc_string).with('', "I have\tsome tabs\nInside\t\tthe content", 1)
83
+ scan ps("I have\tsome tabs\nInside\t\tthe content")
84
+ end
85
+
86
+ it "should handle complex doc_strings" do
87
+ doc_string = <<EOS
88
+ # Feature comment
89
+ @one
90
+ Feature: Sample
91
+
92
+ @two @three
93
+ Scenario: Missing
94
+ Given missing
95
+
96
+ 1 scenario (1 passed)
97
+ 1 step (1 passed)
98
+
99
+ EOS
100
+
101
+ @listener.should_receive(:doc_string).with('', doc_string, 1)
102
+ scan ps(doc_string)
103
+ end
104
+
105
+ it "should allow whitespace after the closing doc_string delimiter" do
106
+ str = <<EOS
107
+ """
108
+ Line one
109
+ """
110
+ EOS
111
+ @listener.should_receive(:doc_string).with('', " Line one", 1)
112
+ scan(str)
113
+ end
114
+
115
+ it "should preserve the last newline(s) at the end of a doc_string" do
116
+ str = <<EOS
117
+ """
118
+ DocString text
119
+
120
+
121
+ """
122
+ EOS
123
+ @listener.should_receive(:doc_string).with('', "DocString text\n\n", 1)
124
+ scan(str)
125
+ end
126
+
127
+ it "should preserve CRLFs within doc_strings" do
128
+ @listener.should_receive(:doc_string).with('', "Line one\r\nLine two\r\n", 1)
129
+ scan("\"\"\"\r\nLine one\r\nLine two\r\n\r\n\"\"\"")
130
+ end
131
+
132
+ it "should unescape escaped triple quotes" do
133
+ str = <<EOS
134
+ """
135
+ \\"\\"\\"
136
+ """
137
+ EOS
138
+ @listener.should_receive(:doc_string).with('', '"""', 1)
139
+ scan(str)
140
+ end
141
+
142
+ it "should not unescape escaped single quotes" do
143
+ str = <<EOS
144
+ """
145
+ \\" \\"\\"
146
+ """
147
+ EOS
148
+ @listener.should_receive(:doc_string).with('', '\" \"\"', 1)
149
+ scan(str)
150
+ end
151
+
152
+ it "should lex doc_string content_types" do
153
+ str = <<EOS
154
+ """gherkin type
155
+ Feature: Doc String Types
156
+ """
157
+ EOS
158
+ @listener.should_receive(:doc_string).with('gherkin type', 'Feature: Doc String Types', 1)
159
+ scan(str)
160
+ end
161
+ end
162
+ end
163
+ end