gherkin-ruby 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,8 @@
1
+ env:
2
+ - RBXOPT=-X19 JRUBY_OPTS="--1.9"
3
+ rvm:
4
+ - 1.9.2
5
+ - 1.9.3
6
+ - ruby-head
7
+ - rbx-head
8
+ - jruby
data/Gemfile CHANGED
@@ -2,3 +2,4 @@ source "http://rubygems.org"
2
2
 
3
3
  # Specify your gem's dependencies in gherkin.gemspec
4
4
  gemspec
5
+ gem 'rake'
data/Readme.md CHANGED
@@ -1,6 +1,25 @@
1
1
  # gherkin-ruby
2
2
  Gherkin-ruby is a pure Ruby implementation of a [Gherkin](http://github.com/cucumber/gherkin) parser, using [Parslet](http://github.com/kschiess/parslet).
3
3
 
4
+ ## Why this one over the official, fast, Ragel-based Gherkin parser?
5
+
6
+ * Less than 200 LOC.
7
+ * No C-exts
8
+ * No Java/.NET crap.
9
+ * Fast enough for our purposes (using it for the [Spinach](http://github.com/codegram/spinach) project)
10
+
11
+ ## Install
12
+
13
+ $ gem install gherkin-ruby
14
+
15
+ Or in your Gemfile:
16
+
17
+ ```ruby
18
+ # Gemfile
19
+
20
+ gem 'gherkin-ruby'
21
+ ```
22
+
4
23
  ## Usage
5
24
  You can easily implement your own visitors to traverse the Abstract Syntax Tree. The following example just prints the step names to standard output:
6
25
 
@@ -33,8 +33,10 @@ module Gherkin
33
33
  include Enumerable
34
34
 
35
35
  def initialize(steps=[])
36
- @line = steps.first.line - 1
37
- @column = 3
36
+ if steps.any?
37
+ @line = steps.first.line - 1
38
+ @column = 3
39
+ end
38
40
 
39
41
  @steps = steps
40
42
  end
@@ -63,11 +65,12 @@ module Gherkin
63
65
  end
64
66
 
65
67
  class Step < Node
66
- attr_reader :name
67
- def initialize(name)
68
+ attr_reader :name, :keyword
69
+ def initialize(name, keyword)
68
70
  @line, @column = name.line_and_column
69
71
 
70
- @name = name.to_s
72
+ @name = name.to_s
73
+ @keyword = keyword.to_s
71
74
  end
72
75
  end
73
76
 
@@ -14,14 +14,17 @@ module Gherkin
14
14
 
15
15
  rule(:feature_line) { str('Feature:') >> space? >> text.as(:name) }
16
16
  rule(:scenario_line) { indent(2) >> str('Scenario:') >> space? >> text.as(:name) }
17
- rule(:background_line) { indent(2) >> str('Background:') }
18
17
 
19
18
  rule(:step_keyword) { str('Given') | str('When') | str('Then') | str('And') | str('But') }
20
19
 
21
20
  rule(:comment) { str('#') >> text.as(:comment) }
22
- rule(:description) { indent(2) >> text.as(:description) }
23
21
 
24
- rule(:step) { indent(4) >> step_keyword >> space? >> text.as(:name) }
22
+ rule(:description_text) { (str('Background:') | str('Scenario:') | str('@')).absent? >> text }
23
+ rule(:description) { (indent(2) >> description_text >> newline).repeat }
24
+
25
+ rule(:background_line) { indent(2) >> str('Background:') }
26
+
27
+ rule(:step) { indent(4) >> step_keyword.as(:keyword) >> space? >> text.as(:name) }
25
28
  rule(:steps) { (step.as(:step) >> newline.maybe).repeat }
26
29
 
27
30
  rule(:tags) { indent(2) >> (str('@') >> identifier.as(:tag) >> str(' ').maybe).repeat(1) }
@@ -31,7 +34,7 @@ module Gherkin
31
34
 
32
35
  rule(:background) { background_line >> newline >> steps.as(:steps) }
33
36
 
34
- rule(:feature) { feature_line >> newline >> background.as(:background).maybe >> scenarios.as(:scenarios) }
37
+ rule(:feature) { feature_line >> newline >> description >> background.as(:background).maybe >> scenarios.as(:scenarios) }
35
38
 
36
39
  rule(:main) { feature.as(:feature) }
37
40
 
@@ -39,8 +39,9 @@ module Gherkin
39
39
  rule(
40
40
  step: {
41
41
  name: simple(:name),
42
+ keyword: simple(:keyword),
42
43
  }
43
- ) { AST::Step.new(name) }
44
+ ) { AST::Step.new(name, keyword) }
44
45
 
45
46
  rule(
46
47
  tag: simple(:name)
@@ -1,3 +1,3 @@
1
1
  module Gherkin
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
@@ -26,7 +26,7 @@ module Gherkin
26
26
  end
27
27
  end
28
28
 
29
- [Feature, Scenario, Step, Tag].each do |node|
29
+ [Feature, Scenario, Tag].each do |node|
30
30
  describe node do
31
31
  it 'is a Node' do
32
32
  node.ancestors.must_include Node
@@ -82,21 +82,54 @@ module Gherkin
82
82
  end
83
83
 
84
84
  describe Background do
85
- it 'is a Node' do
86
- Background.ancestors.must_include Node
87
- end
88
-
89
- it 'is Enumerable' do
85
+ let(:steps) do
90
86
  steps = [
91
87
  OpenStruct.new(line: 4),
92
88
  OpenStruct.new(line: 5),
93
89
  ]
90
+ end
94
91
 
92
+ it 'is a Node' do
93
+ Background.ancestors.must_include Node
94
+ end
95
+
96
+ it 'is Enumerable' do
95
97
  instance = Background.new(steps)
96
- instance.line.must_equal 3
97
- instance.column.must_equal 3
98
98
  instance.each.to_a.must_equal steps
99
99
  end
100
+
101
+ describe 'when there are background steps' do
102
+ it 'records line and column' do
103
+ instance = Background.new(steps)
104
+ instance.line.must_equal 3
105
+ instance.column.must_equal 3
106
+ end
107
+ end
108
+
109
+ describe 'otherwise' do
110
+ it 'does not' do
111
+ instance = Background.new([])
112
+ instance.line.must_equal nil
113
+ instance.column.must_equal nil
114
+ end
115
+ end
116
+ end
117
+
118
+ describe Step do
119
+ it 'is a Node' do
120
+ Step.ancestors.must_include Node
121
+ end
122
+
123
+ it 'has a line and column' do
124
+ name = OpenStruct.new(line_and_column: [2, 13])
125
+ def name.to_s; 'Name'; end
126
+
127
+ instance = Step.new(name, 'Given')
128
+ instance.name.must_equal 'Name'
129
+ instance.keyword.must_equal 'Given'
130
+ instance.line.must_equal 2
131
+ instance.column.must_equal 13
132
+ end
100
133
  end
101
134
  end
102
135
  end
@@ -19,23 +19,33 @@ module Gherkin
19
19
 
20
20
  describe 'Steps' do
21
21
  it 'parses a Given step' do
22
- p(:step, " Given I have an empty array", :name).must_equal "I have an empty array"
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"
23
25
  end
24
26
 
25
27
  it 'parses a When step' do
26
- p(:step, " When I have an empty array", :name).must_equal "I have an empty array"
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"
27
31
  end
28
32
 
29
33
  it 'parses a Then step' do
30
- p(:step, " Then I have an empty array", :name).must_equal "I have an empty array"
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"
31
37
  end
32
38
 
33
39
  it 'parses an And step' do
34
- p(:step, " And I have an empty array", :name).must_equal "I have an empty array"
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"
35
43
  end
36
44
 
37
45
  it 'parses a But step' do
38
- p(:step, " But I have an empty array", :name).must_equal "I have an empty array"
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"
39
49
  end
40
50
  end
41
51
  end
@@ -47,10 +57,13 @@ module Gherkin
47
57
  end
48
58
 
49
59
  describe 'Description parsing' do
50
- it 'parses descriptions ignoring their content' do
51
- p(:description, " In order to know what the heck is Gherkin").size.must_be :>, 0
52
- p(:description, " As a developer").size.must_be :>, 0
53
- p(:description, " I want it to behave in an expected way").size.must_be :>, 0
60
+ it 'parses multiline descriptions' do
61
+ description = """ In order to know what the heck is Gherkin
62
+ As a developer
63
+ I want it to behave in an expected way
64
+ """
65
+ parser = Gherkin::Parser.new
66
+ parser.description.parse(description)
54
67
  end
55
68
  end
56
69
 
@@ -5,6 +5,9 @@ module Gherkin
5
5
  describe 'Feature parsing' do
6
6
  before do
7
7
  @scenario = """Feature: My Feature
8
+ In order to do something
9
+ As a developer
10
+ I want to be happy
8
11
 
9
12
  Background:
10
13
  Given something happens before anything else happens
@@ -32,34 +35,40 @@ module Gherkin
32
35
 
33
36
  background = @result.background
34
37
  background.must_be_kind_of AST::Background
35
- background.line.must_equal 3
38
+ background.line.must_equal 6
36
39
  background.column.must_equal 3
40
+ background.steps.first.keyword.must_equal 'Given'
37
41
  background.steps.first.name.must_equal 'something happens before anything else happens'
38
- background.steps.first.line.must_equal 4
42
+ background.steps.first.line.must_equal 7
43
+ background.steps.last.keyword.must_equal 'And'
39
44
  background.steps.last.name.must_equal 'more things happens before anything else happens'
40
- background.steps.last.line.must_equal 5
45
+ background.steps.last.line.must_equal 8
41
46
 
42
47
  first_scenario = @result.scenarios.first
43
48
  first_scenario.must_be_kind_of AST::Scenario
44
- first_scenario.line.must_equal 7
49
+ first_scenario.line.must_equal 10
45
50
  first_scenario.name.must_equal 'something happens'
51
+ first_scenario.steps.first.keyword.must_equal 'Given'
46
52
  first_scenario.steps.first.name.must_equal 'something happens'
47
- first_scenario.steps.first.line.must_equal 8
53
+ first_scenario.steps.first.line.must_equal 11
54
+ first_scenario.steps.last.keyword.must_equal 'Then'
48
55
  first_scenario.steps.last.name.must_equal 'something cooler happens'
49
- first_scenario.steps.last.line.must_equal 9
56
+ first_scenario.steps.last.line.must_equal 12
50
57
 
51
58
  last_scenario = @result.scenarios.last
52
59
  last_scenario.must_be_kind_of AST::Scenario
53
- last_scenario.line.must_equal 12
60
+ last_scenario.line.must_equal 15
54
61
  last_scenario.name.must_equal 'something else happens'
55
62
 
56
63
  last_scenario.tags.first.name.must_equal 'javascript'
57
64
  last_scenario.tags.last.name.must_equal 'wip'
58
65
 
66
+ last_scenario.steps.first.keyword.must_equal 'Given'
59
67
  last_scenario.steps.first.name.must_equal 'foo'
60
- last_scenario.steps.first.line.must_equal 13
68
+ last_scenario.steps.first.line.must_equal 16
69
+ last_scenario.steps.last.keyword.must_equal 'Then'
61
70
  last_scenario.steps.last.name.must_equal 'bar'
62
- last_scenario.steps.last.line.must_equal 14
71
+ last_scenario.steps.last.line.must_equal 17
63
72
  end
64
73
  end
65
74
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gherkin-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -10,11 +10,11 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2011-11-09 00:00:00.000000000 Z
13
+ date: 2011-11-11 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: parslet
17
- requirement: &2160498080 !ruby/object:Gem::Requirement
17
+ requirement: &2156944000 !ruby/object:Gem::Requirement
18
18
  none: false
19
19
  requirements:
20
20
  - - ! '>='
@@ -22,10 +22,10 @@ dependencies:
22
22
  version: '0'
23
23
  type: :runtime
24
24
  prerelease: false
25
- version_requirements: *2160498080
25
+ version_requirements: *2156944000
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: minitest
28
- requirement: &2160497620 !ruby/object:Gem::Requirement
28
+ requirement: &2156943540 !ruby/object:Gem::Requirement
29
29
  none: false
30
30
  requirements:
31
31
  - - ! '>='
@@ -33,7 +33,7 @@ dependencies:
33
33
  version: '0'
34
34
  type: :development
35
35
  prerelease: false
36
- version_requirements: *2160497620
36
+ version_requirements: *2156943540
37
37
  description: Gherkin-ruby is a Gherkin parser in pure Ruby using Parslet
38
38
  email:
39
39
  - marcdivc@gmail.com
@@ -43,6 +43,7 @@ extensions: []
43
43
  extra_rdoc_files: []
44
44
  files:
45
45
  - .gitignore
46
+ - .travis.yml
46
47
  - Gemfile
47
48
  - Rakefile
48
49
  - Readme.md