Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merge pull request #5 from codegram/feature/add_background_support

Feature/add background support
  • Loading branch information...
commit a4f74b4b20aef62a0705ecdc7c82f4c8cc2676de 2 parents fc53537 + 7aef876
@txus txus authored
View
9 Readme.md
@@ -30,6 +30,13 @@ class MyVisitor
scenario.each { |step| step.accept(self) }
end
+ def visit_Background(background)
+ # Do something nasty with the background
+ # And keep visiting its children:
+
+ background.each { |step| step.accept(self) }
+ end
+
def visit_Tag(tag)
# Do something nasty with the tag
end
@@ -47,6 +54,4 @@ visitor.visit(ast)
## Todo
-* Backgrounds
* Some optimization
-
View
22 lib/gherkin/ast.rb
@@ -10,14 +10,15 @@ def accept(visitor)
end
class Feature < Node
- attr_reader :name, :scenarios
+ attr_reader :name, :background, :scenarios
include Enumerable
- def initialize(name, scenarios=[])
+ def initialize(name, scenarios=[], background=nil)
@line, @column = name.line_and_column
@name = name.to_s
+ @background = background
@scenarios = scenarios
end
@@ -26,6 +27,23 @@ def each
end
end
+ class Background < Node
+ attr_reader :steps
+
+ include Enumerable
+
+ def initialize(steps=[])
+ @line = steps.first.line - 1
+ @column = 3
+
+ @steps = steps
+ end
+
+ def each
+ @steps.each
+ end
+ end
+
class Scenario < Node
attr_reader :name, :steps, :tags
View
5 lib/gherkin/parser.rb
@@ -14,6 +14,7 @@ def indent(num=2)
rule(:feature_line) { str('Feature:') >> space? >> text.as(:name) }
rule(:scenario_line) { indent(2) >> str('Scenario:') >> space? >> text.as(:name) }
+ rule(:background_line) { indent(2) >> str('Background:') }
rule(:step_keyword) { str('Given') | str('When') | str('Then') | str('And') | str('But') }
@@ -28,7 +29,9 @@ def indent(num=2)
rule(:scenario) { (tags.as(:tags) >> newline).maybe >> scenario_line >> newline >> steps.as(:steps) }
rule(:scenarios) { (scenario.as(:scenario) >> newline.maybe).repeat }
- rule(:feature) { feature_line >> newline >> scenarios.as(:scenarios) }
+ rule(:background) { background_line >> newline >> steps.as(:steps) }
+
+ rule(:feature) { feature_line >> newline >> background.as(:background).maybe >> scenarios.as(:scenarios) }
rule(:main) { feature.as(:feature) }
View
14 lib/gherkin/transform.rb
@@ -1,11 +1,23 @@
module Gherkin
class Transform < Parslet::Transform
+ # Match feature with background
rule(
feature: {
name: simple(:name),
+ background: {
+ steps: subtree(:background_steps)
+ },
scenarios: subtree(:scenarios)
}
- ) { AST::Feature.new(name, scenarios) }
+ ) { AST::Feature.new(name, scenarios, AST::Background.new(background_steps)) }
+
+ # Match feature without background
+ rule(
+ feature: {
+ name: simple(:name),
+ scenarios: subtree(:scenarios)
+ }
+ ) { AST::Feature.new(name, scenarios, AST::Background.new([])) }
# Match scenarios without tags
rule(
View
46 test/gherkin/ast_test.rb
@@ -44,21 +44,31 @@ def name.to_s; 'Name'; end
end
end
- [Feature, Scenario].each do |node|
- describe node do
- it 'is Enumerable' do
- name = OpenStruct.new(line_and_column: [2, 13])
- def name.to_s; 'Name'; end
+ describe Feature do
+ it 'is Enumerable' do
+ name = OpenStruct.new(line_and_column: [2, 13])
+ def name.to_s; 'Name'; end
- elements = ['foo', 'bar']
+ background = ['foo', 'bar']
+ elements = ['+foo', '+bar']
- instance = node.new(name, elements)
- instance.each.to_a.must_equal ['foo', 'bar']
- end
+ instance = Feature.new(name, elements, background )
+ instance.background.each.to_a.must_equal ['foo', 'bar']
+ instance.each.to_a.must_equal ['+foo', '+bar']
end
end
describe Scenario do
+ it 'is Enumerable' do
+ name = OpenStruct.new(line_and_column: [2, 13])
+ def name.to_s; 'Name'; end
+
+ elements = ['foo', 'bar']
+
+ instance = Scenario.new(name, elements)
+ instance.each.to_a.must_equal ['foo', 'bar']
+ end
+
it 'has tags' do
name = OpenStruct.new(line_and_column: [2, 13])
def name.to_s; 'Name'; end
@@ -70,5 +80,23 @@ def name.to_s; 'Name'; end
instance.tags.must_equal tags
end
end
+
+ describe Background do
+ it 'is a Node' do
+ Background.ancestors.must_include Node
+ end
+
+ it 'is Enumerable' do
+ steps = [
+ OpenStruct.new(line: 4),
+ OpenStruct.new(line: 5),
+ ]
+
+ instance = Background.new(steps)
+ instance.line.must_equal 3
+ instance.column.must_equal 3
+ instance.each.to_a.must_equal steps
+ end
+ end
end
end
View
40 test/gherkin/parser_test.rb
@@ -67,6 +67,15 @@ module Gherkin
end
end
+ describe 'Background parsing' do
+ it 'parses a background' do
+ background = " Background:\n When I do something\n Then blah"
+ steps = p(:background, background, :steps)
+ steps.first[:step][:name].must_equal 'I do something'
+ steps.last[:step][:name].must_equal 'blah'
+ end
+ end
+
describe 'Parses scenario objects' do
it 'parses a Scenario' do
parser = Gherkin::Parser.new
@@ -90,11 +99,11 @@ module Gherkin
end
end
- describe 'Parses feature objects' do
+ describe 'Parses feature objects without background' do
it 'parses a Feature' do
parser = Gherkin::Parser.new
scenario = """Feature: My Feature
- @javascript
+ @javascript @wip
Scenario: something happens
Given something happens
Then something cooler happens
@@ -108,6 +117,7 @@ module Gherkin
result[:feature][:name].must_equal 'My Feature'
result[:feature][:scenarios][0][:scenario][:tags].first[:tag].must_equal 'javascript'
+ result[:feature][:scenarios][0][:scenario][:tags].last[:tag].must_equal 'wip'
result[:feature][:scenarios][0][:scenario][:name].must_equal 'something happens'
result[:feature][:scenarios][0][:scenario][:steps][0][:step][:name].must_equal 'something happens'
result[:feature][:scenarios][0][:scenario][:steps][1][:step][:name].must_equal 'something cooler happens'
@@ -117,4 +127,30 @@ module Gherkin
result[:feature][:scenarios][1][:scenario][:steps][1][:step][:name].must_equal 'bar'
end
end
+
+ describe 'Parses feature objects with background' do
+ it 'parses a Feature' do
+ parser = Gherkin::Parser.new
+ scenario = """Feature: My Feature
+
+ Background:
+ Given something happens
+ And something cooler happens
+
+ Scenario: something else happens
+ Given foo
+ Then bar
+"""
+ result = parser.parse(scenario)
+
+ result[:feature][:name].must_equal 'My Feature'
+
+ result[:feature][:background][:steps][0][:step][:name].must_equal 'something happens'
+ result[:feature][:background][:steps][1][:step][:name].must_equal 'something cooler happens'
+
+ result[:feature][:scenarios][0][:scenario][:name].must_equal 'something else happens'
+ result[:feature][:scenarios][0][:scenario][:steps][0][:step][:name].must_equal 'foo'
+ result[:feature][:scenarios][0][:scenario][:steps][1][:step][:name].must_equal 'bar'
+ end
+ end
end
View
27 test/gherkin/transform_test.rb
@@ -5,6 +5,11 @@ module Gherkin
describe 'Feature parsing' do
before do
@scenario = """Feature: My Feature
+
+ Background:
+ Given something happens before anything else happens
+ And more things happens before anything else happens
+
Scenario: something happens
Given something happens
Then something cooler happens
@@ -14,6 +19,7 @@ module Gherkin
Given foo
Then bar
"""
+
parser = Gherkin::Parser.new
result = parser.parse(@scenario)
transform = Gherkin::Transform.new
@@ -24,27 +30,36 @@ module Gherkin
@result.must_be_kind_of AST::Feature
@result.line.must_equal 1
+ background = @result.background
+ background.must_be_kind_of AST::Background
+ background.line.must_equal 3
+ background.column.must_equal 3
+ background.steps.first.name.must_equal 'something happens before anything else happens'
+ background.steps.first.line.must_equal 4
+ background.steps.last.name.must_equal 'more things happens before anything else happens'
+ background.steps.last.line.must_equal 5
+
first_scenario = @result.scenarios.first
first_scenario.must_be_kind_of AST::Scenario
- first_scenario.line.must_equal 2
+ first_scenario.line.must_equal 7
first_scenario.name.must_equal 'something happens'
first_scenario.steps.first.name.must_equal 'something happens'
- first_scenario.steps.first.line.must_equal 3
+ first_scenario.steps.first.line.must_equal 8
first_scenario.steps.last.name.must_equal 'something cooler happens'
- first_scenario.steps.last.line.must_equal 4
+ first_scenario.steps.last.line.must_equal 9
last_scenario = @result.scenarios.last
last_scenario.must_be_kind_of AST::Scenario
- last_scenario.line.must_equal 7
+ last_scenario.line.must_equal 12
last_scenario.name.must_equal 'something else happens'
last_scenario.tags.first.name.must_equal 'javascript'
last_scenario.tags.last.name.must_equal 'wip'
last_scenario.steps.first.name.must_equal 'foo'
- last_scenario.steps.first.line.must_equal 8
+ last_scenario.steps.first.line.must_equal 13
last_scenario.steps.last.name.must_equal 'bar'
- last_scenario.steps.last.line.must_equal 9
+ last_scenario.steps.last.line.must_equal 14
end
end
end
Please sign in to comment.
Something went wrong with that request. Please try again.