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.
- data/.gitattributes +2 -0
- data/.mailmap +2 -0
- data/.rbenv-gemsets +1 -0
- data/.rspec +1 -0
- data/.rvmrc +1 -0
- data/.travis.yml +16 -0
- data/.yardopts +5 -0
- data/Gemfile +5 -0
- data/History.md +788 -0
- data/LICENSE +20 -0
- data/README.md +272 -0
- data/Rakefile +26 -0
- data/build_native_gems.sh +7 -0
- data/cucumber.yml +4 -0
- data/examples/parse_and_output_json.rb +19 -0
- data/features/.cucumber/stepdefs.json +244 -0
- data/features/escaped_pipes.feature +8 -0
- data/features/feature_parser.feature +237 -0
- data/features/json_formatter.feature +498 -0
- data/features/json_parser.feature +331 -0
- data/features/native_lexer.feature +19 -0
- data/features/parser_with_native_lexer.feature +205 -0
- data/features/pretty_formatter.feature +16 -0
- data/features/step_definitions/eyeball_steps.rb +3 -0
- data/features/step_definitions/gherkin_steps.rb +29 -0
- data/features/step_definitions/json_formatter_steps.rb +30 -0
- data/features/step_definitions/json_parser_steps.rb +20 -0
- data/features/step_definitions/pretty_formatter_steps.rb +85 -0
- data/features/steps_parser.feature +46 -0
- data/features/support/env.rb +42 -0
- data/gherkin.gemspec +77 -0
- data/install_mingw_os_x.sh +7 -0
- data/js/.npmignore +1 -0
- data/js/lib/gherkin/lexer/.npmignore +0 -0
- data/lib/gherkin.rb +2 -0
- data/lib/gherkin/c_lexer.rb +17 -0
- data/lib/gherkin/formatter/ansi_escapes.rb +97 -0
- data/lib/gherkin/formatter/argument.rb +16 -0
- data/lib/gherkin/formatter/escaping.rb +15 -0
- data/lib/gherkin/formatter/filter_formatter.rb +146 -0
- data/lib/gherkin/formatter/hashable.rb +19 -0
- data/lib/gherkin/formatter/json_formatter.rb +122 -0
- data/lib/gherkin/formatter/line_filter.rb +26 -0
- data/lib/gherkin/formatter/model.rb +281 -0
- data/lib/gherkin/formatter/pretty_formatter.rb +244 -0
- data/lib/gherkin/formatter/regexp_filter.rb +21 -0
- data/lib/gherkin/formatter/step_printer.rb +21 -0
- data/lib/gherkin/formatter/tag_count_formatter.rb +47 -0
- data/lib/gherkin/formatter/tag_filter.rb +19 -0
- data/lib/gherkin/i18n.rb +180 -0
- data/lib/gherkin/i18n.yml +613 -0
- data/lib/gherkin/js_lexer.rb +20 -0
- data/lib/gherkin/json_parser.rb +177 -0
- data/lib/gherkin/lexer/i18n_lexer.rb +46 -0
- data/lib/gherkin/listener/event.rb +45 -0
- data/lib/gherkin/listener/formatter_listener.rb +143 -0
- data/lib/gherkin/native.rb +7 -0
- data/lib/gherkin/native/java.rb +72 -0
- data/lib/gherkin/native/null.rb +5 -0
- data/lib/gherkin/native/therubyracer.rb +39 -0
- data/lib/gherkin/parser/meta.txt +5 -0
- data/lib/gherkin/parser/parser.rb +164 -0
- data/lib/gherkin/parser/root.txt +11 -0
- data/lib/gherkin/parser/steps.txt +4 -0
- data/lib/gherkin/rb_lexer.rb +8 -0
- data/lib/gherkin/rb_lexer/README.rdoc +8 -0
- data/lib/gherkin/rb_lexer/ar.rb +1165 -0
- data/lib/gherkin/rb_lexer/bg.rb +1377 -0
- data/lib/gherkin/rb_lexer/bm.rb +1081 -0
- data/lib/gherkin/rb_lexer/ca.rb +1305 -0
- data/lib/gherkin/rb_lexer/cs.rb +1157 -0
- data/lib/gherkin/rb_lexer/cy_gb.rb +1027 -0
- data/lib/gherkin/rb_lexer/da.rb +1043 -0
- data/lib/gherkin/rb_lexer/de.rb +1151 -0
- data/lib/gherkin/rb_lexer/en.rb +1151 -0
- data/lib/gherkin/rb_lexer/en_au.rb +971 -0
- data/lib/gherkin/rb_lexer/en_lol.rb +929 -0
- data/lib/gherkin/rb_lexer/en_pirate.rb +1205 -0
- data/lib/gherkin/rb_lexer/en_scouse.rb +1357 -0
- data/lib/gherkin/rb_lexer/en_tx.rb +1011 -0
- data/lib/gherkin/rb_lexer/eo.rb +990 -0
- data/lib/gherkin/rb_lexer/es.rb +1135 -0
- data/lib/gherkin/rb_lexer/et.rb +985 -0
- data/lib/gherkin/rb_lexer/fi.rb +964 -0
- data/lib/gherkin/rb_lexer/fr.rb +1223 -0
- data/lib/gherkin/rb_lexer/he.rb +1113 -0
- data/lib/gherkin/rb_lexer/hr.rb +1061 -0
- data/lib/gherkin/rb_lexer/hu.rb +1113 -0
- data/lib/gherkin/rb_lexer/id.rb +958 -0
- data/lib/gherkin/rb_lexer/is.rb +1115 -0
- data/lib/gherkin/rb_lexer/it.rb +1081 -0
- data/lib/gherkin/rb_lexer/ja.rb +1413 -0
- data/lib/gherkin/rb_lexer/ko.rb +1097 -0
- data/lib/gherkin/rb_lexer/lt.rb +1040 -0
- data/lib/gherkin/rb_lexer/lu.rb +1127 -0
- data/lib/gherkin/rb_lexer/lv.rb +1161 -0
- data/lib/gherkin/rb_lexer/nl.rb +1110 -0
- data/lib/gherkin/rb_lexer/no.rb +1055 -0
- data/lib/gherkin/rb_lexer/pl.rb +1452 -0
- data/lib/gherkin/rb_lexer/pt.rb +1425 -0
- data/lib/gherkin/rb_lexer/ro.rb +1159 -0
- data/lib/gherkin/rb_lexer/ru.rb +1749 -0
- data/lib/gherkin/rb_lexer/sk.rb +1041 -0
- data/lib/gherkin/rb_lexer/sr_cyrl.rb +1798 -0
- data/lib/gherkin/rb_lexer/sr_latn.rb +1289 -0
- data/lib/gherkin/rb_lexer/sv.rb +1065 -0
- data/lib/gherkin/rb_lexer/tr.rb +1087 -0
- data/lib/gherkin/rb_lexer/uk.rb +1641 -0
- data/lib/gherkin/rb_lexer/uz.rb +1371 -0
- data/lib/gherkin/rb_lexer/vi.rb +1193 -0
- data/lib/gherkin/rb_lexer/zh_cn.rb +1053 -0
- data/lib/gherkin/rb_lexer/zh_tw.rb +1047 -0
- data/lib/gherkin/rubify.rb +24 -0
- data/lib/gherkin/tag_expression.rb +62 -0
- data/ragel/lexer.c.rl.erb +454 -0
- data/ragel/lexer.java.rl.erb +219 -0
- data/ragel/lexer.js.rl.erb +227 -0
- data/ragel/lexer.rb.rl.erb +174 -0
- data/ragel/lexer_common.rl.erb +50 -0
- data/spec/gherkin/c_lexer_spec.rb +22 -0
- data/spec/gherkin/fixtures/1.feature +8 -0
- data/spec/gherkin/fixtures/comments_in_table.feature +9 -0
- data/spec/gherkin/fixtures/complex.feature +45 -0
- data/spec/gherkin/fixtures/complex.json +139 -0
- data/spec/gherkin/fixtures/complex_for_filtering.feature +60 -0
- data/spec/gherkin/fixtures/complex_with_tags.feature +61 -0
- data/spec/gherkin/fixtures/dos_line_endings.feature +45 -0
- data/spec/gherkin/fixtures/examples_with_only_header.feature +14 -0
- data/spec/gherkin/fixtures/hantu_pisang.feature +35 -0
- data/spec/gherkin/fixtures/i18n_fr.feature +14 -0
- data/spec/gherkin/fixtures/i18n_fr2.feature +8 -0
- data/spec/gherkin/fixtures/i18n_no.feature +7 -0
- data/spec/gherkin/fixtures/i18n_pt1.feature +44 -0
- data/spec/gherkin/fixtures/i18n_pt2.feature +4 -0
- data/spec/gherkin/fixtures/i18n_pt3.feature +4 -0
- data/spec/gherkin/fixtures/i18n_pt4.feature +4 -0
- data/spec/gherkin/fixtures/i18n_zh-CN.feature +9 -0
- data/spec/gherkin/fixtures/issue_145.feature +22 -0
- data/spec/gherkin/fixtures/scenario_outline_with_tags.feature +13 -0
- data/spec/gherkin/fixtures/scenario_without_steps.feature +5 -0
- data/spec/gherkin/fixtures/simple_with_comments.feature +7 -0
- data/spec/gherkin/fixtures/simple_with_tags.feature +11 -0
- data/spec/gherkin/fixtures/with_bom.feature +3 -0
- data/spec/gherkin/formatter/ansi_escapes_spec.rb +32 -0
- data/spec/gherkin/formatter/filter_formatter_spec.rb +204 -0
- data/spec/gherkin/formatter/json_formatter_spec.rb +92 -0
- data/spec/gherkin/formatter/model_spec.rb +28 -0
- data/spec/gherkin/formatter/pretty_formatter_spec.rb +177 -0
- data/spec/gherkin/formatter/spaces.feature +9 -0
- data/spec/gherkin/formatter/step_printer_spec.rb +55 -0
- data/spec/gherkin/formatter/tabs.feature +9 -0
- data/spec/gherkin/formatter/tag_count_formatter_spec.rb +30 -0
- data/spec/gherkin/i18n_spec.rb +241 -0
- data/spec/gherkin/java_lexer_spec.rb +20 -0
- data/spec/gherkin/js_lexer_spec.rb +23 -0
- data/spec/gherkin/json_parser_spec.rb +176 -0
- data/spec/gherkin/lexer/i18n_lexer_spec.rb +43 -0
- data/spec/gherkin/output_stream_string_io.rb +20 -0
- data/spec/gherkin/parser/parser_spec.rb +16 -0
- data/spec/gherkin/rb_lexer_spec.rb +20 -0
- data/spec/gherkin/sexp_recorder.rb +59 -0
- data/spec/gherkin/shared/bom_group.rb +20 -0
- data/spec/gherkin/shared/doc_string_group.rb +163 -0
- data/spec/gherkin/shared/lexer_group.rb +591 -0
- data/spec/gherkin/shared/row_group.rb +125 -0
- data/spec/gherkin/shared/tags_group.rb +54 -0
- data/spec/gherkin/tag_expression_spec.rb +142 -0
- data/spec/spec_helper.rb +75 -0
- data/tasks/bench.rake +184 -0
- data/tasks/bench/feature_builder.rb +49 -0
- data/tasks/bench/null_listener.rb +4 -0
- data/tasks/compile.rake +120 -0
- data/tasks/cucumber.rake +22 -0
- data/tasks/gems.rake +31 -0
- data/tasks/ikvm.rake +124 -0
- data/tasks/ragel_task.rb +100 -0
- data/tasks/release.rake +49 -0
- data/tasks/rspec.rake +8 -0
- data/tasks/yard.rake +7 -0
- data/tasks/yard/default/layout/html/bubble_32x32.png +0 -0
- data/tasks/yard/default/layout/html/bubble_48x48.png +0 -0
- data/tasks/yard/default/layout/html/footer.erb +5 -0
- data/tasks/yard/default/layout/html/index.erb +1 -0
- data/tasks/yard/default/layout/html/layout.erb +25 -0
- data/tasks/yard/default/layout/html/logo.erb +1 -0
- data/tasks/yard/default/layout/html/setup.rb +4 -0
- 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
|