gherkin 2.0.2-i386-mswin32 → 2.1.0-i386-mswin32

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.
Files changed (61) hide show
  1. data/History.txt +12 -0
  2. data/LICENSE +1 -1
  3. data/README.rdoc +2 -2
  4. data/Rakefile +2 -2
  5. data/VERSION.yml +2 -2
  6. data/features/json_formatter.feature +3 -41
  7. data/features/step_definitions/gherkin_steps.rb +5 -6
  8. data/features/step_definitions/json_formatter_steps.rb +3 -2
  9. data/features/step_definitions/json_lexer_steps.rb +5 -5
  10. data/features/step_definitions/pretty_formatter_steps.rb +9 -13
  11. data/features/support/env.rb +1 -1
  12. data/lib/gherkin/formatter/argument.rb +1 -0
  13. data/lib/gherkin/formatter/filter_formatter.rb +149 -0
  14. data/lib/gherkin/formatter/json_formatter.rb +35 -45
  15. data/lib/gherkin/formatter/line_filter.rb +26 -0
  16. data/lib/gherkin/formatter/model.rb +85 -0
  17. data/lib/gherkin/formatter/pretty_formatter.rb +36 -39
  18. data/lib/gherkin/formatter/regexp_filter.rb +17 -0
  19. data/lib/gherkin/formatter/tag_count_formatter.rb +44 -0
  20. data/lib/gherkin/i18n.rb +5 -5
  21. data/lib/gherkin/i18n.yml +13 -0
  22. data/lib/gherkin/i18n_lexer.rb +2 -2
  23. data/lib/gherkin/{json_lexer.rb → json_parser.rb} +17 -5
  24. data/lib/gherkin/{parser → listener}/event.rb +1 -1
  25. data/lib/gherkin/{parser → listener}/formatter_listener.rb +30 -23
  26. data/lib/gherkin/native/java.rb +9 -1
  27. data/lib/gherkin/parser/parser.rb +27 -14
  28. data/lib/gherkin/rubify.rb +5 -1
  29. data/lib/gherkin/tag_expression.rb +62 -0
  30. data/lib/gherkin/tools/files.rb +3 -4
  31. data/lib/gherkin/tools/reformat.rb +2 -2
  32. data/lib/gherkin/tools/stats.rb +3 -4
  33. data/lib/gherkin/tools/stats_listener.rb +1 -1
  34. data/ragel/lexer.c.rl.erb +2 -3
  35. data/ragel/lexer.java.rl.erb +1 -2
  36. data/ragel/lexer.rb.rl.erb +1 -2
  37. data/spec/gherkin/fixtures/complex_for_filtering.feature +60 -0
  38. data/spec/gherkin/fixtures/complex_with_tags.feature +61 -0
  39. data/spec/gherkin/fixtures/hantu_pisang.feature +35 -0
  40. data/spec/gherkin/formatter/filter_formatter_spec.rb +156 -0
  41. data/spec/gherkin/formatter/model_spec.rb +15 -0
  42. data/spec/gherkin/formatter/pretty_formatter_spec.rb +17 -16
  43. data/spec/gherkin/formatter/tag_count_formatter_spec.rb +31 -0
  44. data/spec/gherkin/i18n_lexer_spec.rb +3 -3
  45. data/spec/gherkin/i18n_spec.rb +2 -4
  46. data/spec/gherkin/{json_lexer_spec.rb → json_parser_spec.rb} +13 -8
  47. data/spec/gherkin/sexp_recorder.rb +10 -4
  48. data/spec/gherkin/shared/lexer_group.rb +0 -40
  49. data/spec/gherkin/shared/py_string_group.rb +0 -1
  50. data/spec/gherkin/shared/row_group.rb +1 -2
  51. data/spec/gherkin/tag_expression_spec.rb +137 -0
  52. data/spec/spec_helper.rb +5 -1
  53. data/tasks/bench.rake +5 -9
  54. metadata +33 -25
  55. data/lib/gherkin/parser/filter_listener.rb +0 -203
  56. data/lib/gherkin/parser/row.rb +0 -15
  57. data/lib/gherkin/parser/tag_expression.rb +0 -50
  58. data/spec/gherkin/parser/filter_listener_spec.rb +0 -397
  59. data/spec/gherkin/parser/formatter_listener_spec.rb +0 -134
  60. data/spec/gherkin/parser/parser_spec.rb +0 -50
  61. data/spec/gherkin/parser/tag_expression_spec.rb +0 -116
data/History.txt CHANGED
@@ -1,3 +1,15 @@
1
+ == 2.1.0 (2010-07-12)
2
+
3
+ === New Features
4
+ * Pirate! (anteaya)
5
+ * Tag limits for negative tags (Aslak Hellesøy)
6
+
7
+ === Changed Features
8
+ * The formatter API has changed and the listener API is now only used internally. (Aslak Hellesøy)
9
+
10
+ === Removed Features
11
+ * FilterListener has been replaced with FilterFormatter. Currently only in Ruby (no Java impl yet). (Aslak Hellesøy)
12
+
1
13
  == 2.0.2 (2010-06-16)
2
14
 
3
15
  === New Features
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2009 Mike Sassak, Gregory Hnatiuk, Aslak Hellesøy
1
+ Copyright (c) 2009-2010 Mike Sassak, Gregory Hnatiuk, Aslak Hellesøy
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/README.rdoc CHANGED
@@ -45,7 +45,7 @@ http://crossgcc.rts-software.org/doku.php - just add the bin folder to your PATH
45
45
  == Note on Patches/Pull Requests
46
46
 
47
47
  * Fork the project.
48
- * Run rake ragel:rb to generate all the I18N lexers
48
+ * Run rake ragel:rb to generate all the I18n lexers
49
49
  * Make your feature addition or bug fix.
50
50
  * Add tests for it. This is important so I don't break it in a
51
51
  future version unintentionally.
@@ -56,4 +56,4 @@ http://crossgcc.rts-software.org/doku.php - just add the bin folder to your PATH
56
56
 
57
57
  == Copyright
58
58
 
59
- Copyright (c) 2009 Mike Sassak, Gregory Hnatiuk, Aslak Hellesøy. See LICENSE for details.
59
+ Copyright (c) 2009-2010 Mike Sassak, Gregory Hnatiuk, Aslak Hellesøy. See LICENSE for details.
data/Rakefile CHANGED
@@ -19,8 +19,8 @@ begin
19
19
  gem.authors = ["Mike Sassak", "Gregory Hnatiuk", "Aslak Hellesøy"]
20
20
  gem.executables = ["gherkin"]
21
21
  gem.add_dependency "trollop", "~> 1.16.2"
22
- gem.add_development_dependency 'rspec', '~> 2.0.0.beta.11'
23
- gem.add_development_dependency "cucumber", "~> 0.8.1"
22
+ gem.add_development_dependency 'rspec', '~> 2.0.0.beta.15'
23
+ gem.add_development_dependency "cucumber", "~> 0.8.4"
24
24
  gem.add_development_dependency "rake-compiler", "~> 0.7.0" unless defined?(JRUBY_VERSION)
25
25
 
26
26
  gem.files -= FileList['ikvm/**/*']
data/VERSION.yml CHANGED
@@ -1,5 +1,5 @@
1
1
  ---
2
2
  :major: 2
3
- :minor: 0
3
+ :minor: 1
4
+ :patch: 0
4
5
  :build:
5
- :patch: 2
@@ -17,10 +17,9 @@ Feature: JSON formatter
17
17
  """
18
18
  {
19
19
  "comments": ["# language: no", "# Another comment"],
20
- "description": "",
21
20
  "keyword": "Egenskap",
22
21
  "name": "Kjapp",
23
- "tags": [],
22
+ "line": 3,
24
23
  "uri": "test.feature"
25
24
  }
26
25
  """
@@ -72,30 +71,24 @@ Feature: JSON formatter
72
71
  Then the outputted JSON should be:
73
72
  """
74
73
  {
75
- "comments": [],
76
74
  "keyword": "Feature",
77
75
  "name": "OH HAI",
78
76
  "tags": ["@one"],
77
+ "line": 2,
79
78
  "uri": "test.feature",
80
- "description": "",
81
79
  "elements":[
82
80
  {
83
- "comments": [],
84
- "tags": [],
85
81
  "keyword": "Scenario",
86
82
  "name": "Fujin",
87
- "description": "",
88
83
  "type": "scenario",
89
84
  "line": 4,
90
85
  "steps": [
91
86
  {
92
- "comments": [],
93
87
  "keyword": "Given ",
94
88
  "name": "wind",
95
89
  "line": 5
96
90
  },
97
91
  {
98
- "comments": [],
99
92
  "keyword": "Then ",
100
93
  "name": "spirit",
101
94
  "line": 6
@@ -103,22 +96,18 @@ Feature: JSON formatter
103
96
  ]
104
97
  },
105
98
  {
106
- "comments": [],
107
99
  "tags": ["@two"],
108
100
  "keyword": "Scenario",
109
101
  "name": "_why",
110
- "description": "",
111
102
  "type": "scenario",
112
103
  "line": 9,
113
104
  "steps": [
114
105
  {
115
- "comments": [],
116
106
  "keyword": "Given ",
117
107
  "name": "chunky",
118
108
  "line": 10
119
109
  },
120
110
  {
121
- "comments": [],
122
111
  "keyword": "Then ",
123
112
  "name": "bacon",
124
113
  "line": 11
@@ -126,16 +115,13 @@ Feature: JSON formatter
126
115
  ]
127
116
  },
128
117
  {
129
- "comments": [],
130
118
  "tags": ["@three", "@four"],
131
119
  "keyword": "Scenario Outline",
132
120
  "name": "Life",
133
- "description": "",
134
121
  "type": "scenario_outline",
135
122
  "line": 14,
136
123
  "steps": [
137
124
  {
138
- "comments": [],
139
125
  "keyword": "Given ",
140
126
  "name": "some <boredom>",
141
127
  "line": 15
@@ -143,25 +129,20 @@ Feature: JSON formatter
143
129
  ],
144
130
  "examples": [
145
131
  {
146
- "comments": [],
147
132
  "tags": ["@five"],
148
133
  "keyword": "Examples",
149
134
  "name": "Real life",
150
- "description": "",
151
135
  "line": 18,
152
136
  "table": [
153
137
  {
154
- "comments": [],
155
138
  "cells": ["boredom"],
156
139
  "line": 19
157
140
  },
158
141
  {
159
- "comments": [],
160
142
  "cells": ["airport"],
161
143
  "line": 20
162
144
  },
163
145
  {
164
- "comments": [],
165
146
  "cells": ["meeting"],
166
147
  "line": 21
167
148
  }
@@ -170,29 +151,23 @@ Feature: JSON formatter
170
151
  ]
171
152
  },
172
153
  {
173
- "comments": [],
174
- "tags": [],
175
154
  "keyword": "Scenario",
176
155
  "name": "who stole my mojo?",
177
- "description": "",
178
156
  "type": "scenario",
179
157
  "line": 23,
180
158
  "steps": [
181
159
  {
182
- "comments": [],
183
160
  "keyword": "When ",
184
161
  "name": "I was",
185
162
  "line": 24,
186
163
  "table": [
187
164
  {
188
- "comments": [],
189
165
  "line": 25,
190
166
  "cells": ["asleep"]
191
167
  }
192
168
  ]
193
169
  },
194
170
  {
195
- "comments": [],
196
171
  "keyword": "And ",
197
172
  "name": "so",
198
173
  "line": 26,
@@ -202,9 +177,7 @@ Feature: JSON formatter
202
177
  },
203
178
  {
204
179
  "comments": ["# The"],
205
- "tags": [],
206
180
  "keyword": "Scenario Outline",
207
- "description": "",
208
181
  "type": "scenario_outline",
209
182
  "line": 32,
210
183
  "name": "with",
@@ -219,10 +192,8 @@ Feature: JSON formatter
219
192
  "examples": [
220
193
  {
221
194
  "comments": ["# comments", "# everywhere"],
222
- "tags": [],
223
195
  "keyword": "Examples",
224
196
  "name": "An example",
225
- "description": "",
226
197
  "line": 38,
227
198
  "table": [
228
199
  {
@@ -253,21 +224,16 @@ Feature: JSON formatter
253
224
  Then the outputted JSON should be:
254
225
  """
255
226
  {
256
- "comments": [],
257
- "description": "",
258
227
  "keyword": "Feature",
259
228
  "name": "Kjapp",
260
- "tags": [],
229
+ "line": 1,
261
230
  "uri": "test.feature",
262
231
  "background": {
263
- "comments": [],
264
- "description": "",
265
232
  "keyword": "Background",
266
233
  "line": 3,
267
234
  "name": "No idea what Kjapp means",
268
235
  "steps": [
269
236
  {
270
- "comments": [],
271
237
  "keyword": "Given ",
272
238
  "line": 4,
273
239
  "name": "I Google it"
@@ -277,15 +243,11 @@ Feature: JSON formatter
277
243
  "elements": [
278
244
  {
279
245
  "comments": ["# Writing JSON by hand sucks"],
280
- "tags": [],
281
246
  "keyword": "Scenario",
282
- "name": "",
283
- "description": "",
284
247
  "type": "scenario",
285
248
  "line": 7,
286
249
  "steps": [
287
250
  {
288
- "comments": [],
289
251
  "keyword": "Then ",
290
252
  "name": "I think it means \"fast\"",
291
253
  "line": 8
@@ -1,18 +1,17 @@
1
- Given /^a "([^\"]*)" "([^\"]*)" parser$/ do |ruby_or_native, parser_name|
2
- parser = Gherkin::Parser::Parser.new(@listener, false, parser_name)
3
- @lexer = Gherkin::I18nLexer.new(parser, ruby_or_native == "ruby")
1
+ Given /^a "(ruby|native)" "([^\"]*)" parser$/ do |ruby_or_native, parser_name|
2
+ @parser = Gherkin::Parser::Parser.new(@formatter, false, parser_name, ruby_or_native=="ruby")
4
3
  end
5
4
 
6
5
  Given "the following text is parsed:" do |text|
7
- @lexer.scan(text, "test.feature", 0)
6
+ @parser.parse(text, "test.feature", 0)
8
7
  end
9
8
 
10
9
  Then "there should be no parse errors" do
11
- @listener.errors.should == []
10
+ @formatter.errors.should == []
12
11
  end
13
12
 
14
13
  Then /^there should be a parse error on (line \d+)$/ do |line|
15
- @listener.line(line).should include(:syntax_error, line)
14
+ @formatter.line(line).should include(:syntax_error, line)
16
15
  end
17
16
 
18
17
  Then /^there should be parse errors on (lines .*)$/ do |lines|
@@ -1,6 +1,6 @@
1
1
  require 'stringio'
2
2
  require 'gherkin/formatter/json_formatter'
3
- require 'gherkin/parser/formatter_listener'
3
+ require 'gherkin/listener/formatter_listener'
4
4
 
5
5
  # Monkey patching so that Hash.to_json has a predictable result.
6
6
  class Hash
@@ -12,13 +12,14 @@ end
12
12
 
13
13
  Given /^a JSON formatter$/ do
14
14
  @io = StringIO.new
15
- @listener = Gherkin::Parser::FormatterListener.new(Gherkin::Formatter::JSONFormatter.new(@io))
15
+ @formatter = Gherkin::Formatter::JSONFormatter.new(@io)
16
16
  end
17
17
 
18
18
  Then /^the outputted JSON should be:$/ do |expected_json|
19
19
  require 'json'
20
20
  expected = JSON.pretty_generate(JSON.parse(expected_json))
21
21
  actual = JSON.pretty_generate(JSON.parse(@io.string))
22
+ announce actual
22
23
  begin
23
24
  actual.should == expected
24
25
  rescue # Haven't figured out how to order Hash on JRuby (JSON pure). Retry with possibly worse error message.
@@ -1,20 +1,20 @@
1
1
  require 'stringio'
2
2
  require 'gherkin/formatter/pretty_formatter'
3
- require 'gherkin/json_lexer'
3
+ require 'gherkin/json_parser'
4
4
 
5
5
  Given /^a PrettyFormatter$/ do
6
6
  @io = StringIO.new
7
- @formatter = Gherkin::Parser::FormatterListener.new(Gherkin::Formatter::PrettyFormatter.new(@io, true))
7
+ @formatter = Gherkin::Formatter::PrettyFormatter.new(@io, true)
8
8
  end
9
9
 
10
10
  Given /^a JSON lexer$/ do
11
- @json_parser = Gherkin::JSONLexer.new(@formatter)
11
+ @json_parser = Gherkin::JSONParser.new(@formatter)
12
12
  end
13
13
 
14
14
  Given /^the following JSON is parsed:$/ do |text|
15
- @json_parser.scan(JSON.pretty_generate(JSON.parse(text)))
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|
19
- expected_text.should == @io.string.strip
19
+ @io.string.strip.should == expected_text
20
20
  end
@@ -3,38 +3,34 @@ require 'fileutils'
3
3
  require 'gherkin'
4
4
  require 'gherkin/formatter/pretty_formatter'
5
5
  require 'gherkin/formatter/json_formatter'
6
- require 'gherkin/json_lexer'
6
+ require 'gherkin/json_parser'
7
7
 
8
8
  module PrettyPlease
9
9
  def pretty_machinery(gherkin, feature_path)
10
10
  io = StringIO.new
11
11
  formatter = Gherkin::Formatter::PrettyFormatter.new(io, false)
12
- listener = Gherkin::Parser::FormatterListener.new(formatter)
13
- parser = Gherkin::Parser::Parser.new(listener, true)
14
- lexer = Gherkin::I18nLexer.new(parser)
15
- scan(lexer, gherkin, feature_path)
12
+ parser = Gherkin::Parser::Parser.new(formatter, true)
13
+ parse(parser, gherkin, feature_path)
16
14
  io.string
17
15
  end
18
16
 
19
17
  def json_machinery(gherkin, feature_path)
20
18
  json = StringIO.new
21
19
  json_formatter = Gherkin::Formatter::JSONFormatter.new(json)
22
- formatter_listener = Gherkin::Parser::FormatterListener.new(json_formatter)
23
- gherkin_lexer = Gherkin::I18nLexer.new(formatter_listener)
24
- scan(gherkin_lexer, gherkin, feature_path)
20
+ gherkin_parser = Gherkin::Parser::Parser.new(json_formatter, true)
21
+ parse(gherkin_parser, gherkin, feature_path)
25
22
 
26
23
  result = StringIO.new
27
24
  pretty_formatter = Gherkin::Formatter::PrettyFormatter.new(result, false)
28
- formatter_listener = Gherkin::Parser::FormatterListener.new(pretty_formatter)
29
- json_lexer = Gherkin::JSONLexer.new(formatter_listener)
30
- json_lexer.scan(json.string)
25
+ json_parser = Gherkin::JSONParser.new(pretty_formatter)
26
+ json_parser.parse(json.string)
31
27
 
32
28
  result.string
33
29
  end
34
30
 
35
- def scan(lexer, gherkin, feature_path)
31
+ def parse(parser, gherkin, feature_path)
36
32
  begin
37
- lexer.scan(gherkin, feature_path, 0)
33
+ parser.parse(gherkin, feature_path, 0)
38
34
  rescue => e
39
35
  if e.message =~ /Lexing error/
40
36
  FileUtils.mkdir "tmp" unless File.directory?("tmp")
@@ -24,7 +24,7 @@ class GherkinWorld
24
24
  include TransformHelpers
25
25
 
26
26
  def initialize
27
- @listener = Gherkin::SexpRecorder.new
27
+ @formatter = Gherkin::SexpRecorder.new
28
28
  end
29
29
  end
30
30
 
@@ -11,6 +11,7 @@ module Gherkin
11
11
  end
12
12
 
13
13
  def self.format(string, argument_format, arguments)
14
+ arguments ||= []
14
15
  s = string.dup
15
16
  offset = past_offset = 0
16
17
  arguments.each do |arg|
@@ -0,0 +1,149 @@
1
+ require 'gherkin/rubify'
2
+ require 'gherkin/tag_expression'
3
+ require 'gherkin/formatter/regexp_filter'
4
+ require 'gherkin/formatter/line_filter'
5
+ require 'gherkin/formatter/model'
6
+
7
+ module Gherkin
8
+ module Formatter
9
+ class FilterFormatter
10
+ include Rubify
11
+
12
+ def initialize(formatter, filters)
13
+ @formatter = formatter
14
+ @filter = detect_filter(filters)
15
+
16
+
17
+ @feature_tags = []
18
+ @feature_element_tags = []
19
+ @examples_tags = []
20
+
21
+ @feature_events = []
22
+ @background_events = []
23
+ @feature_element_events = []
24
+ @examples_events = []
25
+ end
26
+
27
+ def feature(statement, uri)
28
+ @feature_tags = statement.tags
29
+ @feature_name = statement.name
30
+ @feature_events = [[:feature, statement, uri]]
31
+ end
32
+
33
+ def background(statement)
34
+ @feature_element_name = statement.name
35
+ @feature_element_range = statement.line_range
36
+ @background_events = [[:background, statement]]
37
+ end
38
+
39
+ def scenario(statement)
40
+ replay!
41
+ @feature_element_tags = statement.tags
42
+ @feature_element_name = statement.name
43
+ @feature_element_range = statement.line_range
44
+ @feature_element_events = [[:scenario, statement]]
45
+ end
46
+
47
+ def scenario_outline(statement)
48
+ replay!
49
+ @feature_element_tags = statement.tags
50
+ @feature_element_name = statement.name
51
+ @feature_element_range = statement.line_range
52
+ @feature_element_events = [[:scenario_outline, statement]]
53
+ @examples_events.clear
54
+ end
55
+
56
+ def examples(statement, examples_rows)
57
+ replay!
58
+ @examples_tags = statement.tags
59
+ @examples_name = statement.name
60
+
61
+ table_body_range = examples_rows.to_a[1].line..examples_rows.to_a[-1].line
62
+ @examples_range = statement.line_range.first..table_body_range.last
63
+ if(LineFilter === @filter && @filter.eval([table_body_range]))
64
+ examples_rows = @filter.filter_table_body_rows(examples_rows)
65
+ end
66
+ @examples_events = [[:examples, statement, examples_rows]]
67
+ end
68
+
69
+ def step(statement, multiline_arg, result)
70
+ args = [:step, statement, multiline_arg, result]
71
+ if @feature_element_events.any?
72
+ @feature_element_events << args
73
+ else
74
+ @background_events << args
75
+ end
76
+
77
+ if LineFilter === @filter
78
+ step_range = statement.line_range
79
+ case rubify(multiline_arg)
80
+ when Model::PyString
81
+ step_range = step_range.first..multiline_arg.line_range.last
82
+ when Array
83
+ step_range = step_range.first..multiline_arg.to_a[-1].line
84
+ end
85
+ @feature_element_range = @feature_element_range.first..step_range.last
86
+ end
87
+ end
88
+
89
+ def eof
90
+ replay!
91
+ @formatter.eof
92
+ end
93
+
94
+ private
95
+
96
+ def detect_filter(filters)
97
+ raise "Inconsistent filters: #{filters.inspect}" if filters.map{|filter| filter.class}.uniq.length > 1
98
+ case(filters[0])
99
+ when Fixnum
100
+ LineFilter.new(filters)
101
+ when Regexp
102
+ RegexpFilter.new(filters)
103
+ when String
104
+ TagExpression.new(filters)
105
+ end
106
+ end
107
+
108
+ def replay!
109
+ case @filter
110
+ when TagExpression
111
+ background_ok = false
112
+ feature_element_ok = @filter.eval(tag_names(@feature_tags.to_a + @feature_element_tags.to_a))
113
+ examples_ok = @filter.eval(tag_names(@feature_tags.to_a + @feature_element_tags.to_a + @examples_tags.to_a)) if @examples_tags
114
+ when RegexpFilter
115
+ background_ok = @filter.eval([@background_name]) if @background_name
116
+ feature_element_ok = @filter.eval([@feature_element_name])
117
+ examples_ok = @filter.eval([@feature_element_name, @examples_name]) if @examples_name
118
+ when LineFilter
119
+ background_ok = @filter.eval([@background_range]) if @background_range
120
+ feature_element_ok = @filter.eval([@feature_element_range]) if @feature_element_range
121
+ examples_ok = @filter.eval([@feature_element_range, @examples_range]) if @examples_range
122
+ end
123
+
124
+ if background_ok || feature_element_ok || examples_ok
125
+ replay_events!(@feature_events)
126
+ replay_events!(@background_events)
127
+
128
+ if feature_element_ok || examples_ok
129
+ replay_events!(@feature_element_events)
130
+ if examples_ok
131
+ replay_events!(@examples_events)
132
+ end
133
+ end
134
+ end
135
+ end
136
+
137
+ def tag_names(tags)
138
+ tags.to_a.uniq.map{|tag| tag.name}
139
+ end
140
+
141
+ def replay_events!(events)
142
+ events.each do |event|
143
+ @formatter.__send__(*event)
144
+ end
145
+ events.clear
146
+ end
147
+ end
148
+ end
149
+ end