gherkin 2.5.4-universal-dotnet → 2.6.0-universal-dotnet

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -11,15 +11,18 @@ class Hash
11
11
  end
12
12
 
13
13
  Given /^a JSON formatter$/ do
14
- @io = StringIO.new
15
- @formatter = Gherkin::Formatter::JSONFormatter.new(@io)
14
+ @out = StringIO.new
15
+ @formatter = Gherkin::Formatter::JSONFormatter.new(@out)
16
16
  end
17
17
 
18
18
  Then /^the outputted JSON should be:$/ do |expected_json|
19
19
  require 'json'
20
- puts JSON.pretty_generate(JSON.parse(@io.string))
20
+ @formatter.close
21
+ actual_json = @out.string
22
+ puts actual_json
23
+ puts JSON.pretty_generate(JSON.parse(actual_json))
21
24
  expected = JSON.parse(expected_json)
22
- actual = JSON.parse(@io.string)
25
+ actual = JSON.parse(actual_json)
23
26
  actual.should == expected
24
27
  end
25
28
 
@@ -12,7 +12,7 @@ Given /^a JSON lexer$/ do
12
12
  end
13
13
 
14
14
  Given /^the following JSON is parsed:$/ do |text|
15
- @json_parser.parse(JSON.pretty_generate(JSON.parse(text)), "unknown.json", 0)
15
+ @json_parser.parse(JSON.pretty_generate(JSON.parse(text)))
16
16
  end
17
17
 
18
18
  Then /^the outputted text should be:$/ do |expected_text|
@@ -20,11 +20,12 @@ module PrettyPlease
20
20
  json_formatter = Gherkin::Formatter::JSONFormatter.new(json)
21
21
  gherkin_parser = Gherkin::Parser::Parser.new(json_formatter, true)
22
22
  parse(gherkin_parser, gherkin, feature_path)
23
+ json_formatter.close
23
24
 
24
25
  io = StringIO.new
25
26
  pretty_formatter = Gherkin::Formatter::PrettyFormatter.new(io, true, false)
26
27
  json_parser = Gherkin::JSONParser.new(pretty_formatter, pretty_formatter)
27
- json_parser.parse(json.string, "#{feature_path}.json", 0)
28
+ json_parser.parse(json.string)
28
29
 
29
30
  io.string
30
31
  end
@@ -2,7 +2,8 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = "gherkin"
5
- s.version = "2.5.4"
5
+ # If bumping the major version here, comment out the cucumber dependency below and uncomment in the Gemfile to build against a local cucumber.
6
+ s.version = "2.6.0"
6
7
  s.authors = ["Mike Sassak", "Gregory Hnatiuk", "Aslak Hellesøy"]
7
8
  s.description = "A fast Gherkin lexer/parser based on the Ragel State Machine Compiler."
8
9
  s.summary = "#{s.name}-#{s.version}"
@@ -45,10 +46,10 @@ Gem::Specification.new do |s|
45
46
 
46
47
  s.add_runtime_dependency('json', '>= 1.4.6')
47
48
 
48
- s.add_development_dependency('cucumber', '>= 1.1.0')
49
+ s.add_development_dependency('cucumber', '>= 1.1.1')
49
50
  s.add_development_dependency('rake', '>= 0.9.2')
50
51
  s.add_development_dependency('bundler', '>= 1.0.21')
51
- s.add_development_dependency('rspec', '>= 2.6.0')
52
+ s.add_development_dependency('rspec', '>= 2.7.0')
52
53
 
53
54
  unless ENV['RUBY_CC_VERSION'] || defined?(JRUBY_VERSION)
54
55
  s.add_development_dependency('therubyracer', '>= 0.9.8') if ENV['GHERKIN_JS']
Binary file
@@ -5,26 +5,31 @@ require 'base64'
5
5
 
6
6
  module Gherkin
7
7
  module Formatter
8
+ # This class doesn't really generate JSON - instead it populates an Array that can easily
9
+ # be turned into JSON.
8
10
  class JSONFormatter
9
11
  native_impl('gherkin')
10
12
 
11
13
  include Base64
12
- attr_reader :gherkin_object
13
14
 
14
- # Creates a new instance that writes the resulting JSON to +io+.
15
- # If +io+ is nil, the JSON will not be written, but instead a Ruby
16
- # object can be retrieved with #gherkin_object
17
15
  def initialize(io)
16
+ raise "Must be writeable" unless io.respond_to?(:write)
18
17
  @io = io
18
+ @feature_hashes = []
19
+ end
20
+
21
+ def close
22
+ @io.write(@feature_hashes.to_json)
19
23
  end
20
24
 
21
25
  def uri(uri)
22
- # We're ignoring the uri - we don't want it as part of the JSON
23
- # (The pretty formatter uses it just for visual niceness - comments)
26
+ @uri = uri
24
27
  end
25
28
 
26
29
  def feature(feature)
27
- @gherkin_object = feature.to_hash
30
+ @feature_hash = feature.to_hash
31
+ @feature_hash['uri'] = @uri
32
+ @feature_hashes << @feature_hash
28
33
  end
29
34
 
30
35
  def background(background)
@@ -68,13 +73,12 @@ module Gherkin
68
73
  end
69
74
 
70
75
  def eof
71
- @io.write(@gherkin_object.to_json) if @io
72
76
  end
73
77
 
74
78
  private
75
79
 
76
80
  def feature_elements
77
- @gherkin_object['elements'] ||= []
81
+ @feature_hash['elements'] ||= []
78
82
  end
79
83
 
80
84
  def feature_element
@@ -31,11 +31,12 @@ module Gherkin
31
31
  end
32
32
 
33
33
  class TagStatement < DescribedStatement
34
- attr_reader :tags
34
+ attr_reader :tags, :id
35
35
 
36
- def initialize(comments, tags, keyword, name, description, line)
36
+ def initialize(comments, tags, keyword, name, description, line, id)
37
37
  super(comments, keyword, name, description, line)
38
38
  @tags = tags
39
+ @id = id
39
40
  end
40
41
 
41
42
  def first_non_comment_line
@@ -46,10 +47,6 @@ module Gherkin
46
47
  class Feature < TagStatement
47
48
  native_impl('gherkin')
48
49
 
49
- def initialize(comments, tags, keyword, name, description, line)
50
- super(comments, tags, keyword, name, description, line)
51
- end
52
-
53
50
  def replay(formatter)
54
51
  formatter.feature(self)
55
52
  end
@@ -71,8 +68,8 @@ module Gherkin
71
68
  class Scenario < TagStatement
72
69
  native_impl('gherkin')
73
70
 
74
- def initialize(comments, tags, keyword, name, description, line)
75
- super(comments, tags, keyword, name, description, line)
71
+ def initialize(comments, tags, keyword, name, description, line, id)
72
+ super(comments, tags, keyword, name, description, line, id)
76
73
  @type = "scenario"
77
74
  end
78
75
 
@@ -84,8 +81,8 @@ module Gherkin
84
81
  class ScenarioOutline < TagStatement
85
82
  native_impl('gherkin')
86
83
 
87
- def initialize(comments, tags, keyword, name, description, line)
88
- super(comments, tags, keyword, name, description, line)
84
+ def initialize(comments, tags, keyword, name, description, line, id)
85
+ super(comments, tags, keyword, name, description, line, id)
89
86
  @type = "scenario_outline"
90
87
  end
91
88
 
@@ -97,23 +94,47 @@ module Gherkin
97
94
  class Examples < TagStatement
98
95
  native_impl('gherkin')
99
96
 
100
- attr_accessor :rows
97
+ attr_accessor :rows # needs to remain mutable for filters
101
98
 
102
- def initialize(comments, tags, keyword, name, description, line, rows)
103
- super(comments, tags, keyword, name, description, line)
99
+ def initialize(comments, tags, keyword, name, description, line, id, rows)
100
+ super(comments, tags, keyword, name, description, line, id)
104
101
  @rows = rows
105
102
  end
106
103
 
107
104
  def replay(formatter)
108
105
  formatter.examples(self)
109
106
  end
107
+
108
+ class Builder
109
+ def initialize(*args)
110
+ @args = *args
111
+ @rows = nil
112
+ end
113
+
114
+ def row(comments, cells, line, id)
115
+ @rows ||= []
116
+ @rows << ExamplesTableRow.new(comments, cells, line, id)
117
+ end
118
+
119
+ def replay(formatter)
120
+ build.replay(formatter)
121
+ end
122
+
123
+ def build
124
+ Examples.new(*(@args << @rows))
125
+ end
126
+ end
110
127
  end
111
128
 
112
129
  class Step < BasicStatement
113
130
  native_impl('gherkin')
114
131
 
115
- attr_accessor :rows
116
- attr_accessor :doc_string
132
+ attr_reader :rows, :doc_string
133
+
134
+ def initialize(comments, keyword, name, line, rows, doc_string)
135
+ super(comments, keyword, name, line)
136
+ @rows, @doc_string = rows, doc_string
137
+ end
117
138
 
118
139
  def line_range
119
140
  range = super
@@ -136,6 +157,31 @@ module Gherkin
136
157
  Argument.new(offset, val)
137
158
  end
138
159
  end
160
+
161
+ class Builder
162
+ def initialize(*args)
163
+ @args = *args
164
+ @rows = nil
165
+ @doc_string = nil
166
+ end
167
+
168
+ def row(comments, cells, line, id)
169
+ @rows ||= []
170
+ @rows << DataTableRow.new(comments, cells, line)
171
+ end
172
+
173
+ def doc_string(string, content_type, line)
174
+ @doc_string = Formatter::Model::DocString.new(string, content_type, line)
175
+ end
176
+
177
+ def replay(formatter)
178
+ build.replay(formatter)
179
+ end
180
+
181
+ def build
182
+ Step.new(*(@args << @rows << @doc_string))
183
+ end
184
+ end
139
185
  end
140
186
 
141
187
  class Comment < Hashable
@@ -169,10 +215,10 @@ module Gherkin
169
215
  class DocString < Hashable
170
216
  native_impl('gherkin')
171
217
 
172
- attr_reader :content_type, :value, :line
218
+ attr_reader :value, :content_type, :line
173
219
 
174
- def initialize(content_type, value, line)
175
- @content_type, @value, @line = content_type, value, line
220
+ def initialize(value, content_type, line)
221
+ @value, @content_type, @line = value, content_type, line
176
222
  end
177
223
 
178
224
  def line_range
@@ -182,8 +228,6 @@ module Gherkin
182
228
  end
183
229
 
184
230
  class Row < Hashable
185
- native_impl('gherkin')
186
-
187
231
  attr_reader :comments, :cells, :line
188
232
 
189
233
  def initialize(comments, cells, line)
@@ -191,6 +235,20 @@ module Gherkin
191
235
  end
192
236
  end
193
237
 
238
+ class DataTableRow < Row
239
+ native_impl('gherkin')
240
+ end
241
+
242
+ class ExamplesTableRow < Row
243
+ native_impl('gherkin')
244
+ attr_reader :id
245
+
246
+ def initialize(comments, cells, line, id)
247
+ super(comments, cells, line)
248
+ @id = id
249
+ end
250
+ end
251
+
194
252
  class Match < Hashable
195
253
  native_impl('gherkin')
196
254
 
@@ -177,7 +177,7 @@ module Gherkin
177
177
 
178
178
  private
179
179
 
180
- def doc_string(doc_string)
180
+ def doc_string(doc_string)
181
181
  @io.puts " \"\"\"" + doc_string.content_type + "\n" + escape_triple_quotes(indent(doc_string.value, ' ')) + "\n \"\"\""
182
182
  end
183
183
 
@@ -16,21 +16,23 @@ module Gherkin
16
16
 
17
17
  # Parse a gherkin object +o+, which can either be a JSON String,
18
18
  # or a Hash (from a parsed JSON String).
19
- def parse(o, feature_uri='unknown.json', line_offset=0)
19
+ def parse(o)
20
20
  o = JSON.parse(o) if String === o
21
- @formatter.uri(feature_uri)
22
-
23
- Formatter::Model::Feature.new(comments(o), tags(o), keyword(o), name(o), description(o), line(o)).replay(@formatter)
24
- (o["elements"] || []).each do |feature_element|
25
- feature_element(feature_element).replay(@formatter)
26
- (feature_element["steps"] || []).each do |step|
27
- step(step).replay(@formatter)
28
- match(step)
29
- result(step)
30
- embeddings(step)
31
- end
32
- (feature_element["examples"] || []).each do |eo|
33
- Formatter::Model::Examples.new(comments(eo), tags(eo), keyword(eo), name(eo), description(eo), line(eo), rows(eo['rows'])).replay(@formatter)
21
+
22
+ o.each do |f|
23
+ @formatter.uri(f['uri'])
24
+ Formatter::Model::Feature.new(comments(f), tags(f), keyword(f), name(f), description(f), line(f), id(f)).replay(@formatter)
25
+ (f["elements"] || []).each do |feature_element|
26
+ feature_element(feature_element).replay(@formatter)
27
+ (feature_element["steps"] || []).each do |step|
28
+ step(step).replay(@formatter)
29
+ match(step)
30
+ result(step)
31
+ embeddings(step)
32
+ end
33
+ (feature_element["examples"] || []).each do |eo|
34
+ Formatter::Model::Examples.new(comments(eo), tags(eo), keyword(eo), name(eo), description(eo), line(eo), id(eo), examples_rows(eo['rows'])).replay(@formatter)
35
+ end
34
36
  end
35
37
  end
36
38
 
@@ -44,23 +46,25 @@ module Gherkin
44
46
  when 'background'
45
47
  Formatter::Model::Background.new(comments(o), keyword(o), name(o), description(o), line(o))
46
48
  when 'scenario'
47
- Formatter::Model::Scenario.new(comments(o), tags(o), keyword(o), name(o), description(o), line(o))
49
+ Formatter::Model::Scenario.new(comments(o), tags(o), keyword(o), name(o), description(o), line(o), id(o))
48
50
  when 'scenario_outline'
49
- Formatter::Model::ScenarioOutline.new(comments(o), tags(o), keyword(o), name(o), description(o), line(o))
51
+ Formatter::Model::ScenarioOutline.new(comments(o), tags(o), keyword(o), name(o), description(o), line(o), id(o))
50
52
  end
51
53
  end
52
54
 
53
55
  def step(o)
54
- step = Formatter::Model::Step.new(comments(o), keyword(o), name(o), line(o))
56
+ builder = Formatter::Model::Step::Builder.new(comments(o), keyword(o), name(o), line(o))
57
+
58
+ (o['rows'] || []).each do |row|
59
+ builder.row comments(row), row['cells'], row['line'], nil
60
+ end
55
61
 
56
- if(o['rows'])
57
- step.rows = rows(o['rows'])
58
- elsif(o['doc_string'])
62
+ if(o['doc_string'])
59
63
  ds = o['doc_string']
60
- step.doc_string = Formatter::Model::DocString.new(ds['content_type'].to_s, ds['value'], ds['line'])
64
+ builder.doc_string ds['value'], ds['content_type'].to_s, ds['line']
61
65
  end
62
66
 
63
- step
67
+ builder.build
64
68
  end
65
69
 
66
70
  def match(o)
@@ -81,8 +85,8 @@ module Gherkin
81
85
  end
82
86
  end
83
87
 
84
- def rows(o)
85
- o.map{|row| Formatter::Model::Row.new(comments(row), row['cells'], row['line'])}
88
+ def examples_rows(o)
89
+ o.map{|row| Formatter::Model::ExamplesTableRow.new(comments(row), row['cells'], row['line'], row['id'])}
86
90
  end
87
91
 
88
92
  def comments(o)
@@ -113,6 +117,10 @@ module Gherkin
113
117
  o['line']
114
118
  end
115
119
 
120
+ def id(o)
121
+ o['id']
122
+ end
123
+
116
124
  def arguments(m)
117
125
  m['arguments'].map{|a| Formatter::Argument.new(a['offset'], a['val'])}
118
126
  end
@@ -11,54 +11,65 @@ module Gherkin
11
11
 
12
12
  def initialize(formatter)
13
13
  @formatter = formatter
14
- @comments = []
15
- @tags = []
16
- @table = nil
14
+ @stash = Stash.new
17
15
  end
18
16
 
19
17
  def comment(value, line)
20
- @comments << Formatter::Model::Comment.new(value, line)
18
+ @stash.comment Formatter::Model::Comment.new(value, line)
21
19
  end
22
20
 
23
21
  def tag(name, line)
24
- @tags << Formatter::Model::Tag.new(name, line)
22
+ @stash.tag Formatter::Model::Tag.new(name, line)
25
23
  end
26
24
 
27
25
  def feature(keyword, name, description, line)
28
- @formatter.feature(Formatter::Model::Feature.new(grab_comments!, grab_tags!, keyword, name, description, line))
26
+ @stash.feature(name) do |comments, tags, id|
27
+ replay Formatter::Model::Feature.new(comments, tags, keyword, name, description, line, id)
28
+ end
29
29
  end
30
30
 
31
31
  def background(keyword, name, description, line)
32
- @formatter.background(Formatter::Model::Background.new(grab_comments!, keyword, name, description, line))
32
+ @stash.feature_element(name) do |comments, tags, id|
33
+ replay Formatter::Model::Background.new(comments, keyword, name, description, line)
34
+ end
33
35
  end
34
36
 
35
37
  def scenario(keyword, name, description, line)
36
38
  replay_step_or_examples
37
- @formatter.scenario(Formatter::Model::Scenario.new(grab_comments!, grab_tags!, keyword, name, description, line))
39
+ @stash.feature_element(name) do |comments, tags, id|
40
+ replay Formatter::Model::Scenario.new(comments, tags, keyword, name, description, line, id)
41
+ end
38
42
  end
39
43
 
40
44
  def scenario_outline(keyword, name, description, line)
41
45
  replay_step_or_examples
42
- @formatter.scenario_outline(Formatter::Model::ScenarioOutline.new(grab_comments!, grab_tags!, keyword, name, description, line))
46
+ @stash.feature_element(name) do |comments, tags, id|
47
+ replay Formatter::Model::ScenarioOutline.new(comments, tags, keyword, name, description, line, id)
48
+ end
43
49
  end
44
50
 
45
51
  def examples(keyword, name, description, line)
46
52
  replay_step_or_examples
47
- @examples_statement = Formatter::Model::Examples.new(grab_comments!, grab_tags!, keyword, name, description, line, nil)
53
+ @stash.examples(name) do |comments, tags, id|
54
+ @current_builder = Formatter::Model::Examples::Builder.new(comments, tags, keyword, name, description, line, id)
55
+ end
48
56
  end
49
57
 
50
58
  def step(keyword, name, line)
51
59
  replay_step_or_examples
52
- @step_statement = Formatter::Model::Step.new(grab_comments!, keyword, name, line)
60
+ @stash.basic_statement do |comments|
61
+ @current_builder = Formatter::Model::Step::Builder.new(comments, keyword, name, line)
62
+ end
53
63
  end
54
64
 
55
65
  def row(cells, line)
56
- @table ||= []
57
- @table << Formatter::Model::Row.new(grab_comments!, cells, line)
66
+ @stash.basic_statement do |comments, id|
67
+ @current_builder.row(comments, cells, line, id)
68
+ end
58
69
  end
59
70
 
60
- def doc_string(string, content_type, line)
61
- @doc_string = Formatter::Model::DocString.new(string, content_type, line)
71
+ def doc_string(content_type, value, line)
72
+ @current_builder.doc_string(value, content_type, line)
62
73
  end
63
74
 
64
75
  def eof
@@ -71,46 +82,61 @@ module Gherkin
71
82
  end
72
83
 
73
84
  private
85
+
86
+ def replay(element)
87
+ element.replay(@formatter)
88
+ end
89
+
90
+ class Stash
91
+ attr_reader :comments, :tags, :ids
92
+
93
+ def initialize
94
+ @comments, @tags, @ids = [], [], []
95
+ @row_index = 0
96
+ end
97
+
98
+ def comment(comment)
99
+ @comments << comment
100
+ end
101
+
102
+ def feature(name)
103
+ @feature_id = id(name)
104
+ yield @comments, @tags, @feature_id
105
+ @comments, @tags = [], []
106
+ end
74
107
 
75
- def grab_comments!
76
- comments = @comments
77
- @comments = []
78
- comments
79
- end
80
-
81
- def grab_tags!
82
- tags = @tags
83
- @tags = []
84
- tags
85
- end
86
-
87
- def grab_rows!
88
- table = @table
89
- @table = nil
90
- table
91
- end
108
+ def feature_element(name)
109
+ @feature_element_id = "#{@feature_id};#{id(name)}"
110
+ yield @comments, @tags, @feature_element_id
111
+ @comments, @tags = [], []
112
+ end
113
+
114
+ def examples(name)
115
+ @examples_id = "#{@feature_element_id};#{id(name)}"
116
+ @row_index = 0
117
+ yield @comments, @tags, @examples_id
118
+ @comments, @tags = [], []
119
+ end
120
+
121
+ def basic_statement
122
+ @row_index += 1
123
+ yield @comments, "#{@examples_id};#{@row_index}"
124
+ @comments = []
125
+ end
126
+
127
+ def tag(tag)
128
+ @tags << tag
129
+ end
92
130
 
93
- def grab_doc_string!
94
- doc_string = @doc_string
95
- @doc_string = nil
96
- doc_string
131
+ def id(name)
132
+ (name || '').gsub(/[\s_]/, '-').downcase
133
+ end
97
134
  end
98
135
 
99
136
  def replay_step_or_examples
100
- if(@step_statement)
101
- if(doc_string = grab_doc_string!)
102
- @step_statement.doc_string = doc_string
103
- elsif(rows = grab_rows!)
104
- @step_statement.rows = rows
105
- end
106
- @formatter.step(@step_statement)
107
- @step_statement = nil
108
- end
109
- if(@examples_statement)
110
- @examples_statement.rows = grab_rows!
111
- @formatter.examples(@examples_statement)
112
- @examples_statement = nil
113
- end
137
+ return unless @current_builder
138
+ replay(@current_builder)
139
+ @current_builder = nil
114
140
  end
115
141
  end
116
142
  end