gherkin-ruby 0.0.2 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/Rakefile +19 -1
- data/Readme.md +2 -2
- data/gherkin-ruby.gemspec +2 -1
- data/lib/gherkin/ast.rb +18 -17
- data/lib/gherkin/parser/gherkin.rex +44 -0
- data/lib/gherkin/parser/gherkin.y +100 -0
- data/lib/gherkin/parser/lexer.rb +120 -0
- data/lib/gherkin/parser/parser.rb +359 -0
- data/lib/gherkin/parser.rb +1 -43
- data/lib/gherkin/version.rb +1 -1
- data/lib/gherkin.rb +2 -7
- data/test/gherkin/ast_test.rb +19 -32
- data/test/gherkin/parser/lexer_test.rb +43 -0
- data/test/gherkin/parser/parser_test.rb +96 -0
- data/test/gherkin/parser_test.rb +52 -148
- metadata +85 -40
- data/lib/gherkin/transform.rb +0 -50
- data/test/gherkin/transform_test.rb +0 -74
data/test/gherkin/parser_test.rb
CHANGED
@@ -1,169 +1,73 @@
|
|
1
1
|
require_relative '../test_helper'
|
2
|
-
require 'parslet'
|
3
|
-
|
4
|
-
def p(rule, input, tag=nil)
|
5
|
-
tag ||= rule
|
6
|
-
parser = Gherkin::Parser.new
|
7
|
-
parser.send(rule).parse(input)[tag]
|
8
|
-
end
|
9
2
|
|
10
3
|
module Gherkin
|
11
4
|
describe 'Feature parsing' do
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
it 'parses the Scenario name' do
|
17
|
-
p(:scenario_line, " Scenario: Formal greeting", :name).must_equal "Formal greeting"
|
18
|
-
end
|
19
|
-
|
20
|
-
describe 'Steps' do
|
21
|
-
it 'parses a Given step' do
|
22
|
-
step = " Given I have an empty array"
|
23
|
-
p(:step, step, :name).must_equal "I have an empty array"
|
24
|
-
p(:step, step, :keyword).must_equal "Given"
|
25
|
-
end
|
26
|
-
|
27
|
-
it 'parses a When step' do
|
28
|
-
step = " When I have an empty array"
|
29
|
-
p(:step, step, :name).must_equal "I have an empty array"
|
30
|
-
p(:step, step, :keyword).must_equal "When"
|
31
|
-
end
|
32
|
-
|
33
|
-
it 'parses a Then step' do
|
34
|
-
step = " Then I have an empty array"
|
35
|
-
p(:step, step, :name).must_equal "I have an empty array"
|
36
|
-
p(:step, step, :keyword).must_equal "Then"
|
37
|
-
end
|
38
|
-
|
39
|
-
it 'parses an And step' do
|
40
|
-
step = " And I have an empty array"
|
41
|
-
p(:step, step, :name).must_equal "I have an empty array"
|
42
|
-
p(:step, step, :keyword).must_equal "And"
|
43
|
-
end
|
44
|
-
|
45
|
-
it 'parses a But step' do
|
46
|
-
step = " But I have an empty array"
|
47
|
-
p(:step, step, :name).must_equal "I have an empty array"
|
48
|
-
p(:step, step, :keyword).must_equal "But"
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
describe 'Comment parsing' do
|
54
|
-
it 'parses a comment ignoring its content' do
|
55
|
-
p(:comment, "# My comment").size.must_be :>, 0
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
describe 'Description parsing' do
|
60
|
-
it 'parses multiline descriptions' do
|
61
|
-
description = """ In order to know what the heck is Gherkin
|
5
|
+
before do
|
6
|
+
@scenario = """Feature: My Feature
|
7
|
+
In order to do something #w000t peoeple
|
62
8
|
As a developer
|
63
|
-
I want
|
64
|
-
"""
|
65
|
-
parser = Gherkin::Parser.new
|
66
|
-
parser.description.parse(description)
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
describe 'Tags parsing' do
|
71
|
-
it 'parses many tags' do
|
72
|
-
javascript = p(:tags, " @javascript @wip", 0)
|
73
|
-
wip = p(:tags, " @javascript @wip", 1)
|
74
|
-
javascript[:tag].must_equal 'javascript'
|
75
|
-
wip[:tag].must_equal 'wip'
|
76
|
-
end
|
9
|
+
I want to be happy #yeah
|
77
10
|
|
78
|
-
|
79
|
-
p(:tags, " @javascript", 0)[:tag].must_equal 'javascript'
|
80
|
-
end
|
81
|
-
end
|
11
|
+
# Attend people. This is going to be fun
|
82
12
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
steps.first[:step][:name].must_equal 'I do something'
|
88
|
-
steps.last[:step][:name].must_equal 'blah'
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
describe 'Parses scenario objects' do
|
93
|
-
it 'parses a Scenario' do
|
94
|
-
parser = Gherkin::Parser.new
|
95
|
-
scenario = " Scenario: Parse a scenario\n Given something happens\n Then something cooler happens"
|
96
|
-
result = parser.scenario.parse(scenario)
|
97
|
-
|
98
|
-
result[:name].must_equal 'Parse a scenario'
|
99
|
-
result[:steps][0][:step][:name].must_equal 'something happens'
|
100
|
-
result[:steps][1][:step][:name].must_equal 'something cooler happens'
|
101
|
-
end
|
102
|
-
|
103
|
-
it 'parses a Scenario with a tag' do
|
104
|
-
parser = Gherkin::Parser.new
|
105
|
-
scenario = " @javascript\n Scenario: Parse a scenario\n Given something happens\n Then something cooler happens"
|
106
|
-
result = parser.scenario.parse(scenario)
|
107
|
-
|
108
|
-
result[:tags].first[:tag].must_equal 'javascript'
|
109
|
-
result[:name].must_equal 'Parse a scenario'
|
110
|
-
result[:steps][0][:step][:name].must_equal 'something happens'
|
111
|
-
result[:steps][1][:step][:name].must_equal 'something cooler happens'
|
112
|
-
end
|
113
|
-
end
|
13
|
+
Background:
|
14
|
+
Given something happens before anything else happens
|
15
|
+
And more things happens before anything else happens
|
16
|
+
# And I wipe the hard drive
|
114
17
|
|
115
|
-
|
116
|
-
it 'parses a Feature' do
|
117
|
-
parser = Gherkin::Parser.new
|
118
|
-
scenario = """Feature: My Feature
|
119
|
-
@javascript @wip
|
120
|
-
Scenario: something happens
|
18
|
+
Scenario: something happens # yeah
|
121
19
|
Given something happens
|
122
20
|
Then something cooler happens
|
123
21
|
|
22
|
+
@javascript @wip #@destroy
|
124
23
|
Scenario: something else happens
|
125
24
|
Given foo
|
126
25
|
Then bar
|
127
26
|
"""
|
128
|
-
result = parser.parse(scenario)
|
129
27
|
|
130
|
-
|
131
|
-
|
132
|
-
result[:feature][:scenarios][0][:scenario][:tags].first[:tag].must_equal 'javascript'
|
133
|
-
result[:feature][:scenarios][0][:scenario][:tags].last[:tag].must_equal 'wip'
|
134
|
-
result[:feature][:scenarios][0][:scenario][:name].must_equal 'something happens'
|
135
|
-
result[:feature][:scenarios][0][:scenario][:steps][0][:step][:name].must_equal 'something happens'
|
136
|
-
result[:feature][:scenarios][0][:scenario][:steps][1][:step][:name].must_equal 'something cooler happens'
|
137
|
-
|
138
|
-
result[:feature][:scenarios][1][:scenario][:name].must_equal 'something else happens'
|
139
|
-
result[:feature][:scenarios][1][:scenario][:steps][0][:step][:name].must_equal 'foo'
|
140
|
-
result[:feature][:scenarios][1][:scenario][:steps][1][:step][:name].must_equal 'bar'
|
28
|
+
parser = Gherkin::Parser.new
|
29
|
+
@result = parser.parse(@scenario)
|
141
30
|
end
|
142
|
-
end
|
143
|
-
|
144
|
-
describe 'Parses feature objects with background' do
|
145
|
-
it 'parses a Feature' do
|
146
|
-
parser = Gherkin::Parser.new
|
147
|
-
scenario = """Feature: My Feature
|
148
|
-
|
149
|
-
Background:
|
150
|
-
Given something happens
|
151
|
-
And something cooler happens
|
152
|
-
|
153
|
-
Scenario: something else happens
|
154
|
-
Given foo
|
155
|
-
Then bar
|
156
|
-
"""
|
157
|
-
result = parser.parse(scenario)
|
158
|
-
|
159
|
-
result[:feature][:name].must_equal 'My Feature'
|
160
|
-
|
161
|
-
result[:feature][:background][:steps][0][:step][:name].must_equal 'something happens'
|
162
|
-
result[:feature][:background][:steps][1][:step][:name].must_equal 'something cooler happens'
|
163
31
|
|
164
|
-
|
165
|
-
result
|
166
|
-
result
|
32
|
+
it 'generates a nice tree' do
|
33
|
+
@result.must_be_kind_of AST::Feature
|
34
|
+
@result.line.must_equal 1
|
35
|
+
|
36
|
+
background = @result.background
|
37
|
+
background.must_be_kind_of AST::Background
|
38
|
+
background.line.must_equal 8
|
39
|
+
background.steps.first.keyword.must_equal 'Given'
|
40
|
+
background.steps.first.name.must_equal 'something happens before anything else happens'
|
41
|
+
background.steps.first.line.must_equal 9
|
42
|
+
background.steps.last.keyword.must_equal 'And'
|
43
|
+
background.steps.last.name.must_equal 'more things happens before anything else happens'
|
44
|
+
background.steps.last.line.must_equal 10
|
45
|
+
|
46
|
+
first_scenario = @result.scenarios.first
|
47
|
+
first_scenario.must_be_kind_of AST::Scenario
|
48
|
+
first_scenario.line.must_equal 13
|
49
|
+
first_scenario.name.must_equal 'something happens'
|
50
|
+
first_scenario.steps.first.keyword.must_equal 'Given'
|
51
|
+
first_scenario.steps.first.name.must_equal 'something happens'
|
52
|
+
first_scenario.steps.first.line.must_equal 14
|
53
|
+
first_scenario.steps.last.keyword.must_equal 'Then'
|
54
|
+
first_scenario.steps.last.name.must_equal 'something cooler happens'
|
55
|
+
first_scenario.steps.last.line.must_equal 15
|
56
|
+
|
57
|
+
last_scenario = @result.scenarios.last
|
58
|
+
last_scenario.must_be_kind_of AST::Scenario
|
59
|
+
last_scenario.line.must_equal 18
|
60
|
+
last_scenario.name.must_equal 'something else happens'
|
61
|
+
|
62
|
+
last_scenario.tags.first.name.must_equal 'javascript'
|
63
|
+
last_scenario.tags.last.name.must_equal 'wip'
|
64
|
+
|
65
|
+
last_scenario.steps.first.keyword.must_equal 'Given'
|
66
|
+
last_scenario.steps.first.name.must_equal 'foo'
|
67
|
+
last_scenario.steps.first.line.must_equal 19
|
68
|
+
last_scenario.steps.last.keyword.must_equal 'Then'
|
69
|
+
last_scenario.steps.last.name.must_equal 'bar'
|
70
|
+
last_scenario.steps.last.line.must_equal 20
|
167
71
|
end
|
168
72
|
end
|
169
73
|
end
|
metadata
CHANGED
@@ -1,47 +1,77 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: gherkin-ruby
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 1322991910812937300
|
5
5
|
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
- 0
|
10
|
+
version: 0.1.0
|
6
11
|
platform: ruby
|
7
|
-
authors:
|
12
|
+
authors:
|
8
13
|
- Marc Divins
|
9
14
|
- Josep M. Bach
|
10
15
|
autorequire:
|
11
16
|
bindir: bin
|
12
17
|
cert_chain: []
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
+
|
19
|
+
date: 2011-11-30 00:00:00 +01:00
|
20
|
+
default_executable:
|
21
|
+
dependencies:
|
22
|
+
- !ruby/object:Gem::Dependency
|
23
|
+
name: rexical
|
24
|
+
prerelease: false
|
25
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
18
26
|
none: false
|
19
|
-
requirements:
|
20
|
-
- -
|
21
|
-
- !ruby/object:Gem::Version
|
22
|
-
|
27
|
+
requirements:
|
28
|
+
- - ">="
|
29
|
+
- !ruby/object:Gem::Version
|
30
|
+
hash: 2002549777813010636
|
31
|
+
segments:
|
32
|
+
- 0
|
33
|
+
version: "0"
|
23
34
|
type: :runtime
|
35
|
+
version_requirements: *id001
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: racc
|
24
38
|
prerelease: false
|
25
|
-
|
26
|
-
|
39
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
40
|
+
none: false
|
41
|
+
requirements:
|
42
|
+
- - ">="
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
hash: 2002549777813010636
|
45
|
+
segments:
|
46
|
+
- 0
|
47
|
+
version: "0"
|
48
|
+
type: :runtime
|
49
|
+
version_requirements: *id002
|
50
|
+
- !ruby/object:Gem::Dependency
|
27
51
|
name: minitest
|
28
|
-
|
52
|
+
prerelease: false
|
53
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
29
54
|
none: false
|
30
|
-
requirements:
|
31
|
-
- -
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
|
55
|
+
requirements:
|
56
|
+
- - ">="
|
57
|
+
- !ruby/object:Gem::Version
|
58
|
+
hash: 2002549777813010636
|
59
|
+
segments:
|
60
|
+
- 0
|
61
|
+
version: "0"
|
34
62
|
type: :development
|
35
|
-
|
36
|
-
version_requirements: *2156943540
|
63
|
+
version_requirements: *id003
|
37
64
|
description: Gherkin-ruby is a Gherkin parser in pure Ruby using Parslet
|
38
|
-
email:
|
65
|
+
email:
|
39
66
|
- marcdivc@gmail.com
|
40
67
|
- josep.m.bach@gmail.com
|
41
68
|
executables: []
|
69
|
+
|
42
70
|
extensions: []
|
71
|
+
|
43
72
|
extra_rdoc_files: []
|
44
|
-
|
73
|
+
|
74
|
+
files:
|
45
75
|
- .gitignore
|
46
76
|
- .travis.yml
|
47
77
|
- Gemfile
|
@@ -51,38 +81,53 @@ files:
|
|
51
81
|
- lib/gherkin.rb
|
52
82
|
- lib/gherkin/ast.rb
|
53
83
|
- lib/gherkin/parser.rb
|
54
|
-
- lib/gherkin/
|
84
|
+
- lib/gherkin/parser/gherkin.rex
|
85
|
+
- lib/gherkin/parser/gherkin.y
|
86
|
+
- lib/gherkin/parser/lexer.rb
|
87
|
+
- lib/gherkin/parser/parser.rb
|
55
88
|
- lib/gherkin/version.rb
|
56
89
|
- test/gherkin/ast_test.rb
|
90
|
+
- test/gherkin/parser/lexer_test.rb
|
91
|
+
- test/gherkin/parser/parser_test.rb
|
57
92
|
- test/gherkin/parser_test.rb
|
58
|
-
- test/gherkin/transform_test.rb
|
59
93
|
- test/test_helper.rb
|
94
|
+
has_rdoc: true
|
60
95
|
homepage: http://github.com/codegram/gherkin
|
61
96
|
licenses: []
|
97
|
+
|
62
98
|
post_install_message:
|
63
99
|
rdoc_options: []
|
64
|
-
|
100
|
+
|
101
|
+
require_paths:
|
65
102
|
- lib
|
66
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
103
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
67
104
|
none: false
|
68
|
-
requirements:
|
69
|
-
- -
|
70
|
-
- !ruby/object:Gem::Version
|
71
|
-
|
72
|
-
|
105
|
+
requirements:
|
106
|
+
- - ">="
|
107
|
+
- !ruby/object:Gem::Version
|
108
|
+
hash: 2002549777813010636
|
109
|
+
segments:
|
110
|
+
- 0
|
111
|
+
version: "0"
|
112
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
73
113
|
none: false
|
74
|
-
requirements:
|
75
|
-
- -
|
76
|
-
- !ruby/object:Gem::Version
|
77
|
-
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
hash: 2002549777813010636
|
118
|
+
segments:
|
119
|
+
- 0
|
120
|
+
version: "0"
|
78
121
|
requirements: []
|
122
|
+
|
79
123
|
rubyforge_project: gherkin-ruby
|
80
|
-
rubygems_version: 1.
|
124
|
+
rubygems_version: 1.5.2
|
81
125
|
signing_key:
|
82
126
|
specification_version: 3
|
83
127
|
summary: Gherkin-ruby is a Gherkin parser in pure Ruby using Parslet
|
84
|
-
test_files:
|
128
|
+
test_files:
|
85
129
|
- test/gherkin/ast_test.rb
|
130
|
+
- test/gherkin/parser/lexer_test.rb
|
131
|
+
- test/gherkin/parser/parser_test.rb
|
86
132
|
- test/gherkin/parser_test.rb
|
87
|
-
- test/gherkin/transform_test.rb
|
88
133
|
- test/test_helper.rb
|
data/lib/gherkin/transform.rb
DELETED
@@ -1,50 +0,0 @@
|
|
1
|
-
module Gherkin
|
2
|
-
class Transform < Parslet::Transform
|
3
|
-
# Match feature with background
|
4
|
-
rule(
|
5
|
-
feature: {
|
6
|
-
name: simple(:name),
|
7
|
-
background: {
|
8
|
-
steps: subtree(:background_steps)
|
9
|
-
},
|
10
|
-
scenarios: subtree(:scenarios)
|
11
|
-
}
|
12
|
-
) { AST::Feature.new(name, scenarios, AST::Background.new(background_steps)) }
|
13
|
-
|
14
|
-
# Match feature without background
|
15
|
-
rule(
|
16
|
-
feature: {
|
17
|
-
name: simple(:name),
|
18
|
-
scenarios: subtree(:scenarios)
|
19
|
-
}
|
20
|
-
) { AST::Feature.new(name, scenarios, AST::Background.new([])) }
|
21
|
-
|
22
|
-
# Match scenarios without tags
|
23
|
-
rule(
|
24
|
-
scenario: {
|
25
|
-
name: simple(:name),
|
26
|
-
steps: subtree(:steps)
|
27
|
-
}
|
28
|
-
) { AST::Scenario.new(name, steps, []) }
|
29
|
-
|
30
|
-
# Match scenarios with tags
|
31
|
-
rule(
|
32
|
-
scenario: {
|
33
|
-
name: simple(:name),
|
34
|
-
steps: subtree(:steps),
|
35
|
-
tags: subtree(:tags)
|
36
|
-
}
|
37
|
-
) { AST::Scenario.new(name, steps, tags) }
|
38
|
-
|
39
|
-
rule(
|
40
|
-
step: {
|
41
|
-
name: simple(:name),
|
42
|
-
keyword: simple(:keyword),
|
43
|
-
}
|
44
|
-
) { AST::Step.new(name, keyword) }
|
45
|
-
|
46
|
-
rule(
|
47
|
-
tag: simple(:name)
|
48
|
-
) { AST::Tag.new(name) }
|
49
|
-
end
|
50
|
-
end
|
@@ -1,74 +0,0 @@
|
|
1
|
-
require_relative '../test_helper'
|
2
|
-
require 'parslet'
|
3
|
-
|
4
|
-
module Gherkin
|
5
|
-
describe 'Feature parsing' do
|
6
|
-
before do
|
7
|
-
@scenario = """Feature: My Feature
|
8
|
-
In order to do something
|
9
|
-
As a developer
|
10
|
-
I want to be happy
|
11
|
-
|
12
|
-
Background:
|
13
|
-
Given something happens before anything else happens
|
14
|
-
And more things happens before anything else happens
|
15
|
-
|
16
|
-
Scenario: something happens
|
17
|
-
Given something happens
|
18
|
-
Then something cooler happens
|
19
|
-
|
20
|
-
@javascript @wip
|
21
|
-
Scenario: something else happens
|
22
|
-
Given foo
|
23
|
-
Then bar
|
24
|
-
"""
|
25
|
-
|
26
|
-
parser = Gherkin::Parser.new
|
27
|
-
result = parser.parse(@scenario)
|
28
|
-
transform = Gherkin::Transform.new
|
29
|
-
@result = transform.apply(result)
|
30
|
-
end
|
31
|
-
|
32
|
-
it 'generates a nice tree' do
|
33
|
-
@result.must_be_kind_of AST::Feature
|
34
|
-
@result.line.must_equal 1
|
35
|
-
|
36
|
-
background = @result.background
|
37
|
-
background.must_be_kind_of AST::Background
|
38
|
-
background.line.must_equal 6
|
39
|
-
background.column.must_equal 3
|
40
|
-
background.steps.first.keyword.must_equal 'Given'
|
41
|
-
background.steps.first.name.must_equal 'something happens before anything else happens'
|
42
|
-
background.steps.first.line.must_equal 7
|
43
|
-
background.steps.last.keyword.must_equal 'And'
|
44
|
-
background.steps.last.name.must_equal 'more things happens before anything else happens'
|
45
|
-
background.steps.last.line.must_equal 8
|
46
|
-
|
47
|
-
first_scenario = @result.scenarios.first
|
48
|
-
first_scenario.must_be_kind_of AST::Scenario
|
49
|
-
first_scenario.line.must_equal 10
|
50
|
-
first_scenario.name.must_equal 'something happens'
|
51
|
-
first_scenario.steps.first.keyword.must_equal 'Given'
|
52
|
-
first_scenario.steps.first.name.must_equal 'something happens'
|
53
|
-
first_scenario.steps.first.line.must_equal 11
|
54
|
-
first_scenario.steps.last.keyword.must_equal 'Then'
|
55
|
-
first_scenario.steps.last.name.must_equal 'something cooler happens'
|
56
|
-
first_scenario.steps.last.line.must_equal 12
|
57
|
-
|
58
|
-
last_scenario = @result.scenarios.last
|
59
|
-
last_scenario.must_be_kind_of AST::Scenario
|
60
|
-
last_scenario.line.must_equal 15
|
61
|
-
last_scenario.name.must_equal 'something else happens'
|
62
|
-
|
63
|
-
last_scenario.tags.first.name.must_equal 'javascript'
|
64
|
-
last_scenario.tags.last.name.must_equal 'wip'
|
65
|
-
|
66
|
-
last_scenario.steps.first.keyword.must_equal 'Given'
|
67
|
-
last_scenario.steps.first.name.must_equal 'foo'
|
68
|
-
last_scenario.steps.first.line.must_equal 16
|
69
|
-
last_scenario.steps.last.keyword.must_equal 'Then'
|
70
|
-
last_scenario.steps.last.name.must_equal 'bar'
|
71
|
-
last_scenario.steps.last.line.must_equal 17
|
72
|
-
end
|
73
|
-
end
|
74
|
-
end
|