gherkin 2.1.5 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. data/History.txt +16 -0
  2. data/README.rdoc +1 -0
  3. data/Rakefile +1 -1
  4. data/VERSION.yml +2 -2
  5. data/features/json_formatter.feature +3 -11
  6. data/features/json_parser.feature +2 -5
  7. data/features/step_definitions/json_lexer_steps.rb +1 -1
  8. data/features/step_definitions/pretty_formatter_steps.rb +1 -1
  9. data/features/support/env.rb +2 -1
  10. data/java/src/main/java/gherkin/lexer/{.gitignore → i18n/.gitignore} +0 -0
  11. data/json-simple-1.1.dll +0 -0
  12. data/lib/gherkin.rb +1 -1
  13. data/lib/gherkin/formatter/filter_formatter.rb +52 -61
  14. data/lib/gherkin/formatter/json_formatter.rb +26 -94
  15. data/lib/gherkin/formatter/line_filter.rb +3 -3
  16. data/lib/gherkin/formatter/model.rb +156 -19
  17. data/lib/gherkin/formatter/pretty_formatter.rb +25 -25
  18. data/lib/gherkin/formatter/regexp_filter.rb +5 -1
  19. data/lib/gherkin/formatter/tag_count_formatter.rb +15 -12
  20. data/lib/gherkin/formatter/tag_filter.rb +19 -0
  21. data/lib/gherkin/json_parser.rb +49 -65
  22. data/lib/gherkin/lexer/i18n_lexer.rb +40 -0
  23. data/lib/gherkin/listener/formatter_listener.rb +11 -18
  24. data/lib/gherkin/parser/parser.rb +4 -5
  25. data/lib/gherkin/tools/stats_listener.rb +1 -1
  26. data/ragel/lexer.c.rl.erb +3 -1
  27. data/ragel/lexer.java.rl.erb +4 -4
  28. data/ragel/lexer.rb.rl.erb +3 -1
  29. data/spec/gherkin/fixtures/complex.json +2 -3
  30. data/spec/gherkin/formatter/model_spec.rb +1 -1
  31. data/spec/gherkin/formatter/pretty_formatter_spec.rb +11 -8
  32. data/spec/gherkin/i18n_spec.rb +3 -3
  33. data/spec/gherkin/java_lexer_spec.rb +1 -1
  34. data/spec/gherkin/json.rb +5 -0
  35. data/spec/gherkin/json_parser_spec.rb +49 -73
  36. data/spec/gherkin/lexer/i18n_lexer_spec.rb +33 -0
  37. data/spec/gherkin/sexp_recorder.rb +0 -2
  38. data/spec/spec_helper.rb +1 -0
  39. data/tasks/bench.rake +2 -2
  40. data/tasks/compile.rake +1 -1
  41. data/tasks/ikvm.rake +3 -1
  42. data/tasks/ragel_task.rb +1 -1
  43. data/tasks/release.rake +13 -1
  44. data/tasks/rspec.rake +0 -1
  45. metadata +17 -13
  46. data/lib/gherkin/i18n_lexer.rb +0 -38
  47. data/spec/gherkin/i18n_lexer_spec.rb +0 -26
@@ -0,0 +1,40 @@
1
+ require 'gherkin/i18n'
2
+ require 'gherkin/native'
3
+
4
+ module Gherkin
5
+ module Lexer
6
+ I18nLexerNotFound = Class.new(LoadError)
7
+ LexingError = Class.new(StandardError)
8
+
9
+ # The main entry point to lexing Gherkin source.
10
+ class I18nLexer
11
+ native_impl('gherkin')
12
+
13
+ LANGUAGE_PATTERN = /^\s*#\s*language\s*:\s*([a-zA-Z\-]+)/ #:nodoc:
14
+ attr_reader :i18n_language
15
+
16
+ def initialize(listener, force_ruby=false)
17
+ @listener = listener
18
+ @force_ruby = force_ruby
19
+ end
20
+
21
+ def scan(source)
22
+ create_delegate(source).scan(source)
23
+ end
24
+
25
+ private
26
+
27
+ def create_delegate(source)
28
+ @i18n_language = lang(source)
29
+ @i18n_language.lexer(@listener, @force_ruby)
30
+ end
31
+
32
+ def lang(source)
33
+ line_one = source.split(/\n/)[0]
34
+ match = LANGUAGE_PATTERN.match(line_one)
35
+ I18n.get(match ? match[1] : 'en')
36
+ end
37
+
38
+ end
39
+ end
40
+ end
@@ -16,10 +16,6 @@ module Gherkin
16
16
  @table = nil
17
17
  end
18
18
 
19
- def location(feature_uri)
20
- @feature_uri = feature_uri
21
- end
22
-
23
19
  def comment(value, line)
24
20
  @comments << Formatter::Model::Comment.new(value, line)
25
21
  end
@@ -29,31 +25,31 @@ module Gherkin
29
25
  end
30
26
 
31
27
  def feature(keyword, name, description, line)
32
- @formatter.feature(statement(grab_comments!, grab_tags!, keyword, name, description, line), @feature_uri)
28
+ @formatter.feature(Formatter::Model::Feature.new(grab_comments!, grab_tags!, keyword, name, description, line))
33
29
  end
34
30
 
35
31
  def background(keyword, name, description, line)
36
- @formatter.background(statement(grab_comments!, [], keyword, name, description, line))
32
+ @formatter.background(Formatter::Model::Background.new(grab_comments!, keyword, name, description, line))
37
33
  end
38
34
 
39
35
  def scenario(keyword, name, description, line)
40
36
  replay_step_or_examples
41
- @formatter.scenario(statement(grab_comments!, grab_tags!, keyword, name, description, line))
37
+ @formatter.scenario(Formatter::Model::Scenario.new(grab_comments!, grab_tags!, keyword, name, description, line))
42
38
  end
43
39
 
44
40
  def scenario_outline(keyword, name, description, line)
45
41
  replay_step_or_examples
46
- @formatter.scenario_outline(statement(grab_comments!, grab_tags!, keyword, name, description, line))
42
+ @formatter.scenario_outline(Formatter::Model::ScenarioOutline.new(grab_comments!, grab_tags!, keyword, name, description, line))
47
43
  end
48
44
 
49
45
  def examples(keyword, name, description, line)
50
46
  replay_step_or_examples
51
- @examples_statement = statement(grab_comments!, grab_tags!, keyword, name, description, line)
47
+ @examples_statement = Formatter::Model::Examples.new(grab_comments!, grab_tags!, keyword, name, description, line)
52
48
  end
53
49
 
54
50
  def step(keyword, name, line)
55
51
  replay_step_or_examples
56
- @step_statement = statement(grab_comments!, [], keyword, name, nil, line)
52
+ @step_statement = Formatter::Model::Step.new(grab_comments!, keyword, name, nil, line)
57
53
  end
58
54
 
59
55
  def row(cells, line)
@@ -76,10 +72,6 @@ module Gherkin
76
72
 
77
73
  private
78
74
 
79
- def statement(comments, tags, keyword, name, description, line)
80
- Formatter::Model::Statement.new(comments, tags, keyword, name, description, line)
81
- end
82
-
83
75
  def grab_comments!
84
76
  comments = @comments
85
77
  @comments = []
@@ -92,7 +84,7 @@ module Gherkin
92
84
  tags
93
85
  end
94
86
 
95
- def grab_table!
87
+ def grab_rows!
96
88
  table = @table
97
89
  @table = nil
98
90
  table
@@ -106,12 +98,13 @@ module Gherkin
106
98
 
107
99
  def replay_step_or_examples
108
100
  if(@step_statement)
109
- multiline_arg = grab_py_string! || grab_table!
110
- @formatter.step(@step_statement, multiline_arg, nil)
101
+ @step_statement.multiline_arg = grab_py_string! || grab_rows!
102
+ @formatter.step(@step_statement)
111
103
  @step_statement = nil
112
104
  end
113
105
  if(@examples_statement)
114
- @formatter.examples(@examples_statement, grab_table!)
106
+ @examples_statement.rows = grab_rows!
107
+ @formatter.examples(@examples_statement)
115
108
  @examples_statement = nil
116
109
  end
117
110
  end
@@ -1,5 +1,5 @@
1
1
  require 'gherkin/i18n'
2
- require 'gherkin/i18n_lexer'
2
+ require 'gherkin/lexer/i18n_lexer'
3
3
  require 'gherkin/native'
4
4
  require 'gherkin/listener/formatter_listener'
5
5
 
@@ -22,13 +22,12 @@ module Gherkin
22
22
  @machine_name = machine_name
23
23
  @machines = []
24
24
  push_machine(@machine_name)
25
- @lexer = I18nLexer.new(self, force_ruby)
25
+ @lexer = Gherkin::Lexer::I18nLexer.new(self, force_ruby)
26
26
  end
27
27
 
28
28
  def parse(gherkin, feature_uri, line_offset)
29
- @feature_uri = feature_uri
29
+ @formatter.uri(feature_uri)
30
30
  @line_offset = line_offset
31
- @listener.location(feature_uri)
32
31
  @lexer.scan(gherkin)
33
32
  end
34
33
 
@@ -148,7 +147,7 @@ module Gherkin
148
147
  @rows = []
149
148
  end
150
149
 
151
- def location(uri, offset)
150
+ def uri(uri)
152
151
  end
153
152
 
154
153
  def row(row, line_number)
@@ -14,7 +14,7 @@ module Gherkin
14
14
  @steps = 0
15
15
  end
16
16
 
17
- def location(file, uri)
17
+ def location(uri)
18
18
  end
19
19
 
20
20
  def tag(name, line)
@@ -57,6 +57,7 @@ typedef struct lexer_state {
57
57
  } lexer_state;
58
58
 
59
59
  static VALUE mGherkin;
60
+ static VALUE mGherkinLexer;
60
61
  static VALUE mCLexer;
61
62
  static VALUE cI18nLexer;
62
63
  static VALUE rb_eGherkinLexingError;
@@ -442,7 +443,8 @@ static VALUE CLexer_scan(VALUE self, VALUE input)
442
443
  void Init_gherkin_lexer_<%= @i18n.underscored_iso_code %>()
443
444
  {
444
445
  mGherkin = rb_define_module("Gherkin");
445
- rb_eGherkinLexingError = rb_const_get(mGherkin, rb_intern("LexingError"));
446
+ mGherkinLexer = rb_define_module_under(mGherkin, "Lexer");
447
+ rb_eGherkinLexingError = rb_const_get(mGherkinLexer, rb_intern("LexingError"));
446
448
 
447
449
  mCLexer = rb_define_module_under(mGherkin, "CLexer");
448
450
  cI18nLexer = rb_define_class_under(mCLexer, "<%= @i18n.underscored_iso_code.capitalize %>", rb_cObject);
@@ -1,13 +1,13 @@
1
- package gherkin.lexer;
1
+ package gherkin.lexer.i18n;
2
2
 
3
3
  import java.io.UnsupportedEncodingException;
4
4
  import java.util.List;
5
5
  import java.util.ArrayList;
6
6
  import java.util.regex.Pattern;
7
7
  import java.util.regex.Matcher;
8
- import gherkin.Lexer;
9
- import gherkin.Listener;
10
- import gherkin.LexingError;
8
+ import gherkin.lexer.Lexer;
9
+ import gherkin.lexer.Listener;
10
+ import gherkin.lexer.LexingError;
11
11
 
12
12
  public class <%= @i18n.underscored_iso_code.upcase %> implements Lexer {
13
13
  %%{
@@ -1,3 +1,5 @@
1
+ require 'gherkin/lexer/i18n_lexer'
2
+
1
3
  module Gherkin
2
4
  module RbLexer
3
5
  class <%= @i18n.underscored_iso_code.capitalize %> #:nodoc:
@@ -113,7 +115,7 @@ module Gherkin
113
115
  action end_feature {
114
116
  if cs < lexer_first_final
115
117
  content = current_line_content(data, p)
116
- raise LexingError.new("Lexing error on line %d: '%s'. See http://wiki.github.com/aslakhellesoy/gherkin/lexingerror for more information." % [@line_number, content])
118
+ raise Gherkin::Lexer::LexingError.new("Lexing error on line %d: '%s'. See http://wiki.github.com/aslakhellesoy/gherkin/lexingerror for more information." % [@line_number, content])
117
119
  else
118
120
  @listener.eof
119
121
  end
@@ -1,5 +1,4 @@
1
1
  {
2
- "type": "feature",
3
2
  "name": "Feature Text",
4
3
  "keyword": "Feature",
5
4
  "description": "In order to test multiline forms",
@@ -41,11 +40,11 @@
41
40
  }
42
41
  ],
43
42
  "examples": [
44
- { "type": "examples",
43
+ {
45
44
  "name": "Sweet Example",
46
45
  "keyword": "Examples",
47
46
  "description": "",
48
- "table" : [
47
+ "rows" : [
49
48
  {"cells" :
50
49
  [ "Fill","In" ]
51
50
  },
@@ -7,7 +7,7 @@ module Gherkin
7
7
  describe Tag do
8
8
  it "should be equal when name is equal" do
9
9
  tags = [Tag.new('@x', 1), Tag.new('@y', 2), Tag.new('@x', 3)]
10
- tags.uniq.length.should == 2
10
+ tags.to_a.uniq.length.should == 2
11
11
  end
12
12
  end
13
13
  end
@@ -35,14 +35,15 @@ module Gherkin
35
35
  end
36
36
 
37
37
  it "should print comments when scenario is longer" do
38
- @l.feature(Model::Statement.new([], [], "Feature", "Hello", "World", 1), "features/foo.feature")
38
+ @l.uri("features/foo.feature")
39
+ @l.feature(Model::Feature.new([], [], "Feature", "Hello", "World", 1))
39
40
  @l.steps([
40
41
  ['Given ', 'some stuff'],
41
42
  ['When ', 'foo']
42
43
  ])
43
- @l.scenario(Model::Statement.new([], [], "Scenario", "The scenario", "", 4))
44
- @l.step(Model::Statement.new([], [], "Given ", "some stuff", "", 5), nil, result('passed', nil, nil, "features/step_definitions/bar.rb:56"))
45
- @l.step(Model::Statement.new([], [], "When ", "foo", "", 6), nil, result('passed', nil, nil, "features/step_definitions/bar.rb:96"))
44
+ @l.scenario(Model::Scenario.new([], [], "Scenario", "The scenario", "", 4))
45
+ @l.step(Model::Step.new([], "Given ", "some stuff", "", 5, nil, result('passed', nil, nil, "features/step_definitions/bar.rb:56")))
46
+ @l.step(Model::Step.new([], "When ", "foo", "", 6, nil, result('passed', nil, nil, "features/step_definitions/bar.rb:96")))
46
47
 
47
48
  assert_io(%{Feature: Hello
48
49
  World
@@ -54,12 +55,13 @@ module Gherkin
54
55
  end
55
56
 
56
57
  it "should print comments when step is longer" do
57
- @l.feature(Model::Statement.new([], [], "Feature", "Hello", "World", 1), "features/foo.feature")
58
+ @l.uri("features/foo.feature")
59
+ @l.feature(Model::Feature.new([], [], "Feature", "Hello", "World", 1))
58
60
  @l.steps([
59
61
  ['Given ', 'some stuff that is longer']
60
62
  ])
61
- @l.scenario(Model::Statement.new([], [], "Scenario", "The scenario", "", 4))
62
- @l.step(Model::Statement.new([], [], "Given ", "some stuff that is longer", "", 5), nil, result('passed', nil, nil, "features/step_definitions/bar.rb:56"))
63
+ @l.scenario(Model::Scenario.new([], [], "Scenario", "The scenario", "", 4))
64
+ @l.step(Model::Step.new([], "Given ", "some stuff that is longer", "", 5, nil, result('passed', nil, nil, "features/step_definitions/bar.rb:56")))
63
65
 
64
66
  assert_io(%{Feature: Hello
65
67
  World
@@ -70,7 +72,8 @@ module Gherkin
70
72
  end
71
73
 
72
74
  it "should highlight arguments for regular steps" do
73
- @l.step(Model::Statement.new([], [], "Given ", "I have 999 cukes in my belly", "", 3), nil, result('passed', nil, [Gherkin::Formatter::Argument.new(7, '999')], nil))
75
+ step = Model::Step.new([], "Given ", "I have 999 cukes in my belly", "", 3, nil, result('passed', nil, [Gherkin::Formatter::Argument.new(7, '999')], nil))
76
+ @l.step(step)
74
77
  assert_io(" Given I have 999 cukes in my belly\n")
75
78
  end
76
79
 
@@ -13,7 +13,7 @@ module Gherkin
13
13
  end
14
14
 
15
15
  it "should recognize keywords in the language of the lexer" do
16
- lexer = Gherkin::I18nLexer.new(@listener, false)
16
+ lexer = Gherkin::Lexer::I18nLexer.new(@listener, false)
17
17
  scan_file(lexer, "i18n_no.feature")
18
18
  @listener.to_sexp.should == [
19
19
  [:comment, "#language:no", 1],
@@ -27,7 +27,7 @@ module Gherkin
27
27
  end
28
28
 
29
29
  it "should parse languages without a space after keywords" do
30
- lexer = Gherkin::I18nLexer.new(@listener, false)
30
+ lexer = Gherkin::Lexer::I18nLexer.new(@listener, false)
31
31
  scan_file(lexer, "i18n_zh-CN.feature")
32
32
  @listener.to_sexp.should == [
33
33
  [:comment, "#language:zh-CN", 1],
@@ -42,7 +42,7 @@ module Gherkin
42
42
  end
43
43
 
44
44
  it "should parse languages with spaces after some keywords but not others" do
45
- lexer = Gherkin::I18nLexer.new(@listener, false)
45
+ lexer = Gherkin::Lexer::I18nLexer.new(@listener, false)
46
46
  scan_file(lexer, "i18n_fr.feature")
47
47
  @listener.to_sexp.should == [
48
48
  [:comment, "#language:fr", 1],
@@ -7,7 +7,7 @@ module Gherkin
7
7
  describe "Java Lexer" do
8
8
  before do
9
9
  @listener = Gherkin::SexpRecorder.new
10
- @lexer = Java::Gherkin::I18nLexer.new(@listener)
10
+ @lexer = Java::GherkinLexer::I18nLexer.new(@listener)
11
11
  end
12
12
 
13
13
  it_should_behave_like "a Gherkin lexer"
@@ -0,0 +1,5 @@
1
+ JSON_SIMPLE_JAR = ENV['HOME'] + '/.m2/repository/com/googlecode/json-simple/json-simple/1.1/json-simple-1.1.jar'
2
+
3
+ if defined?(JRUBY_VERSION)
4
+ require JSON_SIMPLE_JAR
5
+ end
@@ -1,91 +1,67 @@
1
1
  #encoding: utf-8
2
+ require 'ap'
2
3
  require 'spec_helper'
3
4
  require 'gherkin/json_parser'
5
+ require 'gherkin/formatter/json_formatter'
4
6
 
5
7
  module Gherkin
6
8
  describe JSONParser do
7
9
 
8
- before do
9
- @listener = Gherkin::SexpRecorder.new
10
- @parser = Gherkin::JSONParser.new(nil)
11
- end
10
+ def check_json(json)
11
+ io = StringIO.new
12
+ f = Formatter::JSONFormatter.new(io)
13
+ p = JSONParser.new(f)
14
+ p.parse(json, 'unknown.json')
15
+ expected = JSON.parse(json)
16
+ actual = JSON.parse(io.string)
12
17
 
13
- describe "An empty feature" do
14
- it "should scan empty features" do
15
- @parser.parse_with_listener('{}', @listener)
16
- @listener.to_sexp.should == [
17
- [:location, "unknown.json"],
18
- [:eof]
19
- ]
20
- end
18
+ actual.should == expected
21
19
  end
22
20
 
23
- describe "A barely empty feature" do
24
- it "should scan a feature with no elements" do
25
- @parser.parse_with_listener('{ "type": "feature", "keyword": "Feature", "name": "One", "description": "", "line" : 3 }', @listener)
26
- @listener.to_sexp.should == [
27
- [:location, "unknown.json"],
28
- [:feature, "Feature", "One", "", 3],
29
- [:eof]
30
- ]
31
- end
21
+ it "should parse a barely empty feature" do
22
+ check_json(%{{
23
+ "keyword": "Feature",
24
+ "name": "One",
25
+ "description": "",
26
+ "line" : 3
27
+ }})
32
28
  end
33
29
 
34
- describe "Keywords" do
35
- it "should use the keyword from the source when provided" do
36
- @parser.parse_with_listener('{ "type": "feature", "name" : "My Sweet Featur", "language": "fr", "keyword": "Feature", "description": "" }', @listener)
37
- @listener.to_sexp.should == [
38
- [:location, "unknown.json"],
39
- [:feature, "Feature", "My Sweet Featur", "", nil],
40
- [:eof]
30
+ it "should parse feature with tags and one scenario" do
31
+ check_json(%{{
32
+ "tags": [
33
+ {
34
+ "name": "@foo",
35
+ "line": 22
36
+ }
37
+ ],
38
+ "keyword": "Feature",
39
+ "name": "One",
40
+ "description": "",
41
+ "line": 3,
42
+ "elements": [
43
+ {
44
+ "type": "scenario",
45
+ "steps": [
46
+ {
47
+ "name": "Hello",
48
+ "multiline_arg": {
49
+ "type": "table",
50
+ "value": [
51
+ {
52
+ "cells": ["foo", "bar"]
53
+ }
54
+ ]
55
+ }
56
+ }
57
+ ]
58
+ }
41
59
  ]
42
- end
60
+ }})
43
61
  end
44
62
 
45
- describe "A complex feature with tags, comments, multiple scenarios, and multiple steps and tables" do
46
- it "should find things in the right order" do
47
- @parser.parse_with_listener(fixture("complex.json"), @listener)
48
- @listener.to_sexp.should == [
49
- [:location, "unknown.json"],
50
- [:tag, "@tag1", nil],
51
- [:tag, "@tag2", nil],
52
- [:feature, "Feature", "Feature Text","In order to test multiline forms", nil],
53
- [:background, "Background", "", "", nil],
54
- [:step, "Given ", "this is a background step", nil],
55
- [:step, "When ", "this is another one", 412],
56
- [:tag, "@foo", nil],
57
- [:scenario_outline, "Scenario Outline", "An Scenario Outline","", nil],
58
- [:step, "Given ", "A step with a table", nil],
59
- [:row, %w{a row for a step}, nil],
60
- [:tag, "@exampletag", nil],
61
- [:examples, "Examples", "Sweet Example", "", nil],
62
- [:row, %w{Fill In}, nil],
63
- [:row, %w{The Blanks}, nil],
64
- [:tag, "@tag3", nil],
65
- [:tag, "@tag4", nil],
66
- [:scenario, "Scenario", "Reading a Scenario", "", nil],
67
- [:step, "Given ", "there is a step", nil],
68
- [:step, "But ", "not another step", nil],
69
- [:tag, "@tag3", nil],
70
- [:scenario, "Scenario", "Reading a second scenario", "With two lines of text", nil],
71
- [:step, "Given ", "a third step with a table", nil],
72
- [:row, %w{a b}, 987],
73
- [:row, %w{c d}, nil],
74
- [:row, %w{e f}, nil],
75
- [:step, "Given ", "I am still testing things", nil],
76
- [:row, %w{g h}, nil],
77
- [:row, %w{e r}, nil],
78
- [:row, %w{k i}, nil],
79
- [:row, ['n', ''], nil],
80
- [:step, "Given ", "I am done testing these tables", nil],
81
- [:step, "Given ", "I am happy", nil],
82
- [:scenario, "Scenario", "Hammerzeit", "", nil],
83
- [:step, "Given ", "All work and no play", nil],
84
- [:py_string, "Makes Homer something something\nAnd something else", 777],
85
- [:step, "Given ", "crazy", nil],
86
- [:eof]
87
- ]
88
- end
63
+ it "shoud parse a complex feature" do
64
+ check_json(fixture("complex.json"))
89
65
  end
90
66
  end
91
67
  end