gherkin 1.0.30 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.rspec +1 -0
- data/History.txt +19 -0
- data/Rakefile +4 -4
- data/VERSION.yml +2 -2
- data/features/feature_parser.feature +11 -0
- data/features/json_formatter.feature +238 -0
- data/features/pretty_formatter.feature +9 -0
- data/features/step_definitions/gherkin_steps.rb +1 -1
- data/features/step_definitions/json_formatter_steps.rb +32 -0
- data/features/step_definitions/pretty_formatter_steps.rb +24 -23
- data/features/support/env.rb +3 -3
- data/lib/gherkin/formatter/json_formatter.rb +82 -0
- data/lib/gherkin/formatter/pretty_formatter.rb +73 -78
- data/lib/gherkin/i18n.rb +22 -18
- data/lib/gherkin/i18n.yml +9 -9
- data/lib/gherkin/i18n_lexer.rb +2 -2
- data/lib/gherkin/parser/event.rb +6 -6
- data/lib/gherkin/parser/filter_listener.rb +5 -1
- data/lib/gherkin/parser/formatter_listener.rb +113 -0
- data/lib/gherkin/parser/json_parser.rb +102 -0
- data/lib/gherkin/parser/parser.rb +10 -2
- data/lib/gherkin/parser/row.rb +15 -0
- data/lib/gherkin/rubify.rb +2 -0
- data/lib/gherkin/tools/files.rb +1 -1
- data/lib/gherkin/tools/reformat.rb +1 -2
- data/lib/gherkin/tools/stats.rb +1 -1
- data/lib/gherkin/tools/stats_listener.rb +5 -5
- data/ragel/lexer.c.rl.erb +41 -12
- data/ragel/lexer.java.rl.erb +26 -17
- data/ragel/lexer.rb.rl.erb +10 -5
- data/ragel/lexer_common.rl.erb +6 -6
- data/spec/gherkin/c_lexer_spec.rb +2 -2
- data/spec/gherkin/fixtures/complex.js +105 -0
- data/spec/gherkin/formatter/argument_spec.rb +3 -3
- data/spec/gherkin/formatter/colors_spec.rb +3 -4
- data/spec/gherkin/formatter/pretty_formatter_spec.rb +21 -50
- data/spec/gherkin/i18n_lexer_spec.rb +6 -6
- data/spec/gherkin/i18n_spec.rb +16 -9
- data/spec/gherkin/java_lexer_spec.rb +1 -2
- data/spec/gherkin/output_stream_string_io.rb +24 -0
- data/spec/gherkin/parser/filter_listener_spec.rb +16 -9
- data/spec/gherkin/parser/formatter_listener_spec.rb +134 -0
- data/spec/gherkin/parser/json_parser_spec.rb +129 -0
- data/spec/gherkin/parser/parser_spec.rb +9 -9
- data/spec/gherkin/parser/tag_expression_spec.rb +8 -8
- data/spec/gherkin/rb_lexer_spec.rb +1 -1
- data/spec/gherkin/sexp_recorder.rb +21 -1
- data/spec/gherkin/shared/{lexer_spec.rb → lexer_group.rb} +172 -102
- data/spec/gherkin/shared/{py_string_spec.rb → py_string_group.rb} +21 -17
- data/spec/gherkin/shared/{row_spec.rb → row_group.rb} +36 -19
- data/spec/gherkin/shared/{tags_spec.rb → tags_group.rb} +13 -9
- data/spec/spec_helper.rb +18 -38
- data/tasks/bench.rake +3 -3
- data/tasks/compile.rake +13 -14
- data/tasks/rspec.rake +6 -11
- metadata +42 -28
- data/features/pretty_printer.feature +0 -14
- data/spec/gherkin/csharp_lexer_spec.rb +0 -20
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/History.txt
CHANGED
@@ -1,3 +1,22 @@
|
|
1
|
+
== 2.0.0
|
2
|
+
|
3
|
+
We're breaking the old listener API in this release, and added a new JSON formatter,
|
4
|
+
which calls for a new major version.
|
5
|
+
|
6
|
+
=== New Features
|
7
|
+
* New JSON formatter. (Aslak Hellesøy, Joseph Wilk)
|
8
|
+
* New synonyms for Hungarian (Bence Golda)
|
9
|
+
* Upgraded to use RSpec 2.0.0 (Aslak Hellesøy)
|
10
|
+
|
11
|
+
=== Bugfixes
|
12
|
+
* undefined method `<=>' on JRuby (#52 Aslak Hellesøy)
|
13
|
+
* Include link to explanation of LexingError (Mike Sassak)
|
14
|
+
|
15
|
+
=== Changed Features
|
16
|
+
* The formatter API has completely changed. There is a Gherkin Listener API and a Formatter API.
|
17
|
+
The FormatterListener acts as an adapter between them. (Aslak Hellesøy)
|
18
|
+
* The listener API now has an additional argument for description (text following the first line of Feature:, Scenario: etc.) (Gregroy Hnatiuk, Matt Wynne)
|
19
|
+
|
1
20
|
== 1.0.30 (2010-05-18)
|
2
21
|
|
3
22
|
=== New Features
|
data/Rakefile
CHANGED
@@ -18,10 +18,10 @@ begin
|
|
18
18
|
gem.homepage = "http://github.com/aslakhellesoy/gherkin"
|
19
19
|
gem.authors = ["Mike Sassak", "Gregory Hnatiuk", "Aslak Hellesøy"]
|
20
20
|
gem.executables = ["gherkin"]
|
21
|
-
gem.add_dependency "trollop", "
|
22
|
-
gem.add_development_dependency
|
23
|
-
gem.add_development_dependency "cucumber", "
|
24
|
-
gem.add_development_dependency "rake-compiler", "
|
21
|
+
gem.add_dependency "trollop", "~> 1.16.2"
|
22
|
+
gem.add_development_dependency 'rspec', '~> 2.0.0.beta.11'
|
23
|
+
gem.add_development_dependency "cucumber", "~> 0.8.1"
|
24
|
+
gem.add_development_dependency "rake-compiler", "~> 0.7.0" unless defined?(JRUBY_VERSION)
|
25
25
|
|
26
26
|
gem.files -= FileList['ikvm/**/*']
|
27
27
|
gem.files -= FileList['java/**/*']
|
data/VERSION.yml
CHANGED
@@ -73,6 +73,17 @@ Feature: Gherkin Feature lexer
|
|
73
73
|
"""
|
74
74
|
Then there should be parse errors on lines 1 through 3
|
75
75
|
|
76
|
+
Scenario: Multiple Features in file
|
77
|
+
Given the following text is parsed:
|
78
|
+
"""
|
79
|
+
Feature:
|
80
|
+
Scenario: Hi
|
81
|
+
Feature: Uh ohs
|
82
|
+
Scenario Outline:
|
83
|
+
Feature: This is silly
|
84
|
+
"""
|
85
|
+
Then there should be parse errors on lines 3 and 5
|
86
|
+
|
76
87
|
Scenario: Tag ends background and scenario
|
77
88
|
Given the following text is parsed:
|
78
89
|
"""
|
@@ -0,0 +1,238 @@
|
|
1
|
+
Feature: JSON formatter
|
2
|
+
In order to support greater access to features
|
3
|
+
we want JSON
|
4
|
+
|
5
|
+
Background:
|
6
|
+
Given a JSON formatter
|
7
|
+
And a "ruby" "root" parser
|
8
|
+
|
9
|
+
Scenario: Only a Feature
|
10
|
+
Given the following text is parsed:
|
11
|
+
"""
|
12
|
+
# language: no
|
13
|
+
# Another comment
|
14
|
+
Egenskap: Kjapp
|
15
|
+
"""
|
16
|
+
Then the outputted JSON should be:
|
17
|
+
"""
|
18
|
+
{
|
19
|
+
"comments": ["# language: no", "# Another comment"],
|
20
|
+
"description": "",
|
21
|
+
"keyword": "Egenskap",
|
22
|
+
"name": "Kjapp",
|
23
|
+
"tags": [],
|
24
|
+
"uri": "test.feature"
|
25
|
+
}
|
26
|
+
"""
|
27
|
+
|
28
|
+
Scenario: Feature with two scenarios
|
29
|
+
Given the following text is parsed:
|
30
|
+
"""
|
31
|
+
@one
|
32
|
+
Feature: OH HAI
|
33
|
+
|
34
|
+
Scenario: Fujin
|
35
|
+
Given wind
|
36
|
+
Then spirit
|
37
|
+
|
38
|
+
@two
|
39
|
+
Scenario: _why
|
40
|
+
Given chunky
|
41
|
+
Then bacon
|
42
|
+
|
43
|
+
@three @four
|
44
|
+
Scenario Outline: Life
|
45
|
+
Given some <boredom>
|
46
|
+
|
47
|
+
@five
|
48
|
+
Examples: Real life
|
49
|
+
|boredom|
|
50
|
+
|airport|
|
51
|
+
|meeting|
|
52
|
+
|
53
|
+
Scenario: who stole my mojo?
|
54
|
+
When I was
|
55
|
+
|asleep|
|
56
|
+
And so
|
57
|
+
\"\"\"
|
58
|
+
innocent
|
59
|
+
\"\"\"
|
60
|
+
|
61
|
+
# The
|
62
|
+
Scenario Outline: with
|
63
|
+
# all
|
64
|
+
Then nice
|
65
|
+
|
66
|
+
# comments
|
67
|
+
# everywhere
|
68
|
+
Examples: An example
|
69
|
+
# I mean
|
70
|
+
| partout |
|
71
|
+
"""
|
72
|
+
Then the outputted JSON should be:
|
73
|
+
"""
|
74
|
+
{
|
75
|
+
"comments": [],
|
76
|
+
"keyword": "Feature",
|
77
|
+
"name": "OH HAI",
|
78
|
+
"tags": ["@one"],
|
79
|
+
"uri": "test.feature",
|
80
|
+
"description": "",
|
81
|
+
"elements":[
|
82
|
+
{
|
83
|
+
"comments": [],
|
84
|
+
"tags": [],
|
85
|
+
"keyword": "Scenario",
|
86
|
+
"name": "Fujin",
|
87
|
+
"description": "",
|
88
|
+
"line": 4,
|
89
|
+
"steps": [
|
90
|
+
{
|
91
|
+
"comments": [],
|
92
|
+
"keyword": "Given ",
|
93
|
+
"name": "wind",
|
94
|
+
"line": 5,
|
95
|
+
"multiline_arg": null
|
96
|
+
},
|
97
|
+
{
|
98
|
+
"comments": [],
|
99
|
+
"keyword": "Then ",
|
100
|
+
"name": "spirit",
|
101
|
+
"line": 6,
|
102
|
+
"multiline_arg": null
|
103
|
+
}
|
104
|
+
]
|
105
|
+
},
|
106
|
+
{
|
107
|
+
"comments": [],
|
108
|
+
"tags": ["@two"],
|
109
|
+
"keyword": "Scenario",
|
110
|
+
"name": "_why",
|
111
|
+
"description": "",
|
112
|
+
"line": 9,
|
113
|
+
"steps": [
|
114
|
+
{
|
115
|
+
"comments": [],
|
116
|
+
"keyword": "Given ",
|
117
|
+
"name": "chunky",
|
118
|
+
"line": 10,
|
119
|
+
"multiline_arg": null
|
120
|
+
},
|
121
|
+
{
|
122
|
+
"comments": [],
|
123
|
+
"keyword": "Then ",
|
124
|
+
"name": "bacon",
|
125
|
+
"line": 11,
|
126
|
+
"multiline_arg": null
|
127
|
+
}
|
128
|
+
]
|
129
|
+
},
|
130
|
+
{
|
131
|
+
"comments": [],
|
132
|
+
"tags": ["@three", "@four"],
|
133
|
+
"keyword": "Scenario Outline",
|
134
|
+
"name": "Life",
|
135
|
+
"description": "",
|
136
|
+
"line": 14,
|
137
|
+
"steps": [
|
138
|
+
{
|
139
|
+
"comments": [],
|
140
|
+
"keyword": "Given ",
|
141
|
+
"name": "some <boredom>",
|
142
|
+
"line": 15,
|
143
|
+
"multiline_arg": null
|
144
|
+
}
|
145
|
+
]
|
146
|
+
},
|
147
|
+
{
|
148
|
+
"comments": [],
|
149
|
+
"tags": ["@five"],
|
150
|
+
"keyword": "Examples",
|
151
|
+
"name": "Real life",
|
152
|
+
"description": "",
|
153
|
+
"line": 18,
|
154
|
+
"examples_table": [
|
155
|
+
{
|
156
|
+
"comments": [],
|
157
|
+
"cells": ["boredom"],
|
158
|
+
"line": 19
|
159
|
+
},
|
160
|
+
{
|
161
|
+
"comments": [],
|
162
|
+
"cells": ["airport"],
|
163
|
+
"line": 20
|
164
|
+
},
|
165
|
+
{
|
166
|
+
"comments": [],
|
167
|
+
"cells": ["meeting"],
|
168
|
+
"line": 21
|
169
|
+
}
|
170
|
+
]
|
171
|
+
},
|
172
|
+
{
|
173
|
+
"comments": [],
|
174
|
+
"tags": [],
|
175
|
+
"keyword": "Scenario",
|
176
|
+
"name": "who stole my mojo?",
|
177
|
+
"description": "",
|
178
|
+
"line": 23,
|
179
|
+
"steps": [
|
180
|
+
{
|
181
|
+
"comments": [],
|
182
|
+
"keyword": "When ",
|
183
|
+
"name": "I was",
|
184
|
+
"line": 24,
|
185
|
+
"multiline_arg": [
|
186
|
+
{
|
187
|
+
"comments": [],
|
188
|
+
"line": 25,
|
189
|
+
"cells": ["asleep"]
|
190
|
+
}
|
191
|
+
]
|
192
|
+
},
|
193
|
+
{
|
194
|
+
"comments": [],
|
195
|
+
"keyword": "And ",
|
196
|
+
"name": "so",
|
197
|
+
"line": 26,
|
198
|
+
"multiline_arg": "innocent"
|
199
|
+
}
|
200
|
+
]
|
201
|
+
},
|
202
|
+
{
|
203
|
+
"comments": ["# The"],
|
204
|
+
"tags": [],
|
205
|
+
"keyword": "Scenario Outline",
|
206
|
+
"description": "",
|
207
|
+
"line": 32,
|
208
|
+
"name": "with",
|
209
|
+
"steps": [
|
210
|
+
{
|
211
|
+
"comments": ["# all"],
|
212
|
+
"keyword": "Then ",
|
213
|
+
"line": 34,
|
214
|
+
"name": "nice",
|
215
|
+
"multiline_arg": null
|
216
|
+
}
|
217
|
+
]
|
218
|
+
},
|
219
|
+
{
|
220
|
+
"comments": ["# comments", "# everywhere"],
|
221
|
+
"tags": [],
|
222
|
+
"keyword": "Examples",
|
223
|
+
"name": "An example",
|
224
|
+
// TODO - the description should now be the comment
|
225
|
+
// It should be on the first row of the examples_table!
|
226
|
+
"description": "# I mean",
|
227
|
+
"line": 38,
|
228
|
+
"examples_table": [
|
229
|
+
{
|
230
|
+
"comments": [],
|
231
|
+
"line": 40,
|
232
|
+
"cells": ["partout"]
|
233
|
+
}
|
234
|
+
]
|
235
|
+
}
|
236
|
+
]
|
237
|
+
}
|
238
|
+
"""
|
@@ -0,0 +1,9 @@
|
|
1
|
+
Feature: Pretty Formatter
|
2
|
+
In order to have pretty gherkin
|
3
|
+
I want to verify that all prettified cucumber features parse OK
|
4
|
+
|
5
|
+
Scenario: Parse all the features in Cucumber
|
6
|
+
Given I have Cucumber's source code next to Gherkin's
|
7
|
+
When I find all of the .feature files
|
8
|
+
And I parse the prettified representation of each of them
|
9
|
+
Then they should all be identical to the pretty output
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'stringio'
|
2
|
+
require 'gherkin/formatter/json_formatter'
|
3
|
+
require 'gherkin/parser/formatter_listener'
|
4
|
+
|
5
|
+
# Monkey patching so that Hash.to_json has a predictable result.
|
6
|
+
class Hash
|
7
|
+
alias orig_keys keys
|
8
|
+
def keys
|
9
|
+
orig_keys.sort
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
Given /^a JSON formatter$/ do
|
14
|
+
@io = StringIO.new
|
15
|
+
@listener = Gherkin::Parser::FormatterListener.new(Gherkin::Formatter::JSONFormatter.new(@io))
|
16
|
+
end
|
17
|
+
|
18
|
+
Then /^the outputted JSON should be:$/ do |expected_json|
|
19
|
+
require 'json'
|
20
|
+
expected = JSON.pretty_generate(JSON.parse(expected_json))
|
21
|
+
actual = JSON.pretty_generate(JSON.parse(@io.string))
|
22
|
+
begin
|
23
|
+
actual.should == expected
|
24
|
+
rescue # Haven't figured out how to order Hash on JRuby (JSON pure). Retry with possibly worse error message.
|
25
|
+
expected = JSON.parse(expected_json)
|
26
|
+
actual = JSON.parse(@io.string)
|
27
|
+
actual.should == expected
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
|
32
|
+
|
@@ -4,52 +4,53 @@ require 'gherkin/formatter/pretty_formatter'
|
|
4
4
|
|
5
5
|
module PrettyPlease
|
6
6
|
def pretty(source)
|
7
|
-
io
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
lexer.
|
12
|
-
|
13
|
-
io.
|
7
|
+
io = StringIO.new
|
8
|
+
formatter = Gherkin::Formatter::PrettyFormatter.new(io, false)
|
9
|
+
listener = Gherkin::Parser::FormatterListener.new(formatter)
|
10
|
+
parser = Gherkin::Parser::Parser.new(listener, true)
|
11
|
+
lexer = Gherkin::I18nLexer.new(parser)
|
12
|
+
lexer.scan(source, "test.feature", 0)
|
13
|
+
io.string
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
17
17
|
World(PrettyPlease)
|
18
18
|
|
19
|
-
Given /^I have Cucumber's
|
20
|
-
@cucumber_home =
|
21
|
-
raise "No
|
19
|
+
Given /^I have Cucumber's source code next to Gherkin's$/ do
|
20
|
+
@cucumber_home = File.dirname(__FILE__) + '/../../../cucumber'
|
21
|
+
raise "No Cucumber source in #{@cucumber_home}" unless File.file?(@cucumber_home + '/bin/cucumber')
|
22
22
|
end
|
23
23
|
|
24
24
|
When /^I find all of the \.feature files$/ do
|
25
|
-
@
|
25
|
+
@feature_paths = Dir["#{@cucumber_home}/**/*.feature"].sort
|
26
26
|
end
|
27
27
|
|
28
28
|
When /^I parse the prettified representation of each of them$/ do
|
29
|
-
@
|
30
|
-
@
|
29
|
+
@error = false
|
30
|
+
@feature_paths.each do |feature_path|
|
31
31
|
pretty1 = nil
|
32
32
|
pretty2 = nil
|
33
33
|
begin
|
34
|
-
pretty1 = pretty(IO.read(
|
34
|
+
pretty1 = pretty(IO.read(feature_path))
|
35
35
|
pretty2 = pretty(pretty1)
|
36
36
|
pretty2.should == pretty1
|
37
|
-
rescue
|
38
|
-
|
39
|
-
|
40
|
-
announce "========== #{feature}:"
|
37
|
+
rescue RSpec::Expectations::ExpectationNotMetError => e
|
38
|
+
announce "=========="
|
39
|
+
announce feature_path
|
41
40
|
if(e.message =~ /(@@.*)/m)
|
42
41
|
announce $1
|
42
|
+
@error = true
|
43
|
+
File.open("p1.feature", "wb") {|io| io.write(pretty1)}
|
44
|
+
File.open("p2.feature", "wb") {|io| io.write(pretty2)}
|
43
45
|
else
|
44
|
-
announce "
|
46
|
+
announce "Identical, except for newlines"
|
45
47
|
end
|
46
|
-
@errors << [feature, "See announced diff"]
|
47
48
|
rescue => e
|
48
|
-
|
49
|
+
e.message << "\nFatal error happened when parsing #{feature_path}"
|
49
50
|
end
|
50
51
|
end
|
51
52
|
end
|
52
53
|
|
53
|
-
Then /^
|
54
|
-
|
54
|
+
Then /^they should all be identical to the pretty output$/ do
|
55
|
+
raise "Some features didn't do pretty well" if @error
|
55
56
|
end
|
data/features/support/env.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
# I'm sure there's a better way than this...
|
2
|
-
%w{/../../
|
2
|
+
%w{ /../../spec /../../lib}.each do |path|
|
3
3
|
$LOAD_PATH << File.expand_path(File.dirname(__FILE__) + path)
|
4
4
|
end
|
5
|
-
|
6
5
|
require 'gherkin'
|
7
|
-
require "sexp_recorder"
|
6
|
+
require "gherkin/sexp_recorder"
|
7
|
+
require 'gherkin/output_stream_string_io'
|
8
8
|
|
9
9
|
module TransformHelpers
|
10
10
|
def tr_line_number(step_arg)
|