cucumber 2.0.0.beta.2 → 2.0.0.beta.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +25 -7
  3. data/cucumber.gemspec +1 -1
  4. data/features/docs/defining_steps/nested_steps.feature +0 -1
  5. data/features/docs/defining_steps/printing_messages.feature +1 -0
  6. data/features/docs/defining_steps/table_diffing.feature +9 -4
  7. data/features/docs/exception_in_after_step_hook.feature +1 -0
  8. data/features/docs/formatters/json_formatter.feature +51 -4
  9. data/features/docs/formatters/junit_formatter.feature +1 -0
  10. data/features/docs/gherkin/outlines.feature +4 -0
  11. data/features/docs/output_from_hooks.feature +128 -0
  12. data/features/docs/wire_protocol_table_diffing.feature +6 -2
  13. data/features/docs/writing_support_code/after_hooks.feature +56 -0
  14. data/lib/cucumber/cli/configuration.rb +0 -4
  15. data/lib/cucumber/cli/main.rb +0 -1
  16. data/lib/cucumber/cli/options.rb +0 -3
  17. data/lib/cucumber/formatter/console.rb +3 -1
  18. data/lib/cucumber/formatter/debug.rb +4 -0
  19. data/lib/cucumber/formatter/gherkin_formatter_adapter.rb +26 -3
  20. data/lib/cucumber/formatter/html.rb +6 -2
  21. data/lib/cucumber/formatter/usage.rb +1 -58
  22. data/lib/cucumber/mappings.rb +25 -7
  23. data/lib/cucumber/multiline_argument.rb +40 -82
  24. data/lib/cucumber/multiline_argument/data_table.rb +719 -0
  25. data/lib/cucumber/multiline_argument/doc_string.rb +10 -0
  26. data/lib/cucumber/platform.rb +1 -1
  27. data/lib/cucumber/rb_support/rb_world.rb +2 -4
  28. data/lib/cucumber/reports/legacy_formatter.rb +69 -22
  29. data/lib/cucumber/runtime.rb +0 -39
  30. data/lib/cucumber/runtime/for_programming_languages.rb +12 -10
  31. data/lib/cucumber/runtime/support_code.rb +11 -4
  32. data/lib/cucumber/wire_support/wire_protocol/requests.rb +2 -2
  33. data/spec/cucumber/formatter/pretty_spec.rb +5 -5
  34. data/spec/cucumber/mappings_spec.rb +137 -8
  35. data/spec/cucumber/multiline_argument/data_table_spec.rb +508 -0
  36. data/spec/cucumber/rb_support/rb_step_definition_spec.rb +3 -3
  37. data/spec/cucumber/rb_support/snippet_spec.rb +1 -1
  38. data/spec/cucumber/runtime/for_programming_languages_spec.rb +16 -12
  39. metadata +13 -6
  40. data/lib/cucumber/runtime/features_loader.rb +0 -62
@@ -0,0 +1,10 @@
1
+ module Cucumber
2
+ module MultilineArgument
3
+ class DocString < SimpleDelegator
4
+ def append_to(array)
5
+ array << self
6
+ end
7
+ end
8
+ end
9
+ end
10
+
@@ -4,7 +4,7 @@ require 'rbconfig'
4
4
 
5
5
  module Cucumber
6
6
  unless defined?(Cucumber::VERSION)
7
- VERSION = '2.0.0.beta.2'
7
+ VERSION = '2.0.0.beta.3'
8
8
  BINARY = File.expand_path(File.dirname(__FILE__) + '/../../bin/cucumber')
9
9
  LIBDIR = File.expand_path(File.dirname(__FILE__) + '/../../lib')
10
10
  JRUBY = defined?(JRUBY_VERSION)
@@ -36,10 +36,8 @@ module Cucumber
36
36
  # @param [String] name The name of the step
37
37
  # @param [String,Cucumber::Ast::DocString,Cucumber::Ast::Table] multiline_argument
38
38
  def step(name, raw_multiline_arg=nil)
39
- # TODO: this argument parsing should move up out of core
40
- location = Core::Ast::Location.new(*caller[0].split(':')[0..1])
41
- core_multiline_arg = Core::Ast::MultilineArgument.from(raw_multiline_arg, location)
42
- @__cucumber_runtime.invoke(name, MultilineArgument.from(core_multiline_arg), location)
39
+ location = Core::Ast::Location.of_caller
40
+ @__cucumber_runtime.invoke(name, MultilineArgument.from(raw_multiline_arg, location))
43
41
  end
44
42
 
45
43
  # Run a snippet of Gherkin
@@ -1,6 +1,7 @@
1
1
  require 'forwardable'
2
2
  require 'delegate'
3
3
  require 'cucumber/errors'
4
+ require 'cucumber/multiline_argument'
4
5
 
5
6
  module Cucumber
6
7
  module Reports
@@ -220,29 +221,41 @@ module Cucumber
220
221
  def after_test_case(*args)
221
222
  if current_test_step_source.step_result.nil?
222
223
  switch_step_container
223
- @delayed_messages = []
224
- @delayed_embeddings = []
225
224
  end
225
+
226
+ # messages and embedding should already have been handled, but just in case...
227
+ @delayed_messages.each { |message| formatter.puts(message) }
228
+ @delayed_embeddings.each { |embedding| embedding.send_to_formatter(formatter) }
229
+ @delayed_messages = []
230
+ @delayed_embeddings = []
231
+
226
232
  @child.after_test_case
227
233
  @previous_test_case_background = @current_test_case_background
228
234
  @previous_test_case_scenario_outline = current_test_step_source.scenario_outline
229
235
  end
230
236
 
231
237
  def before_hook(location, result)
232
- @before_hook_results << Legacy::Ast::HookResult.new(LegacyResultBuilder.new(result))
238
+ @before_hook_results << Legacy::Ast::HookResult.new(LegacyResultBuilder.new(result), @delayed_messages, @delayed_embeddings)
239
+ @delayed_messages = []
240
+ @delayed_embeddings = []
233
241
  end
234
242
 
235
243
  def after_hook(location, result)
236
244
  # if the scenario has no steps, we can hit this before we've created the scenario printer
237
245
  # ideally we should call switch_step_container in before_step_step
238
246
  switch_step_container if !@child
239
- @child.after_hook Legacy::Ast::HookResult.new(LegacyResultBuilder.new(result))
247
+ @child.after_hook Legacy::Ast::HookResult.new(LegacyResultBuilder.new(result), @delayed_messages, @delayed_embeddings)
248
+ @delayed_messages = []
249
+ @delayed_embeddings = []
240
250
  end
241
251
 
242
252
  def after_step_hook(hook, result)
243
253
  line = StepBacktraceLine.new(current_test_step_source.step)
244
- @child.after_step_hook LegacyResultBuilder.new(result).
245
- append_to_exception_backtrace(line)
254
+ @child.after_step_hook Legacy::Ast::HookResult.new(LegacyResultBuilder.new(result).
255
+ append_to_exception_backtrace(line), @delayed_messages, @delayed_embeddings)
256
+ @delayed_messages = []
257
+ @delayed_embeddings = []
258
+
246
259
  end
247
260
 
248
261
  def background(node, *)
@@ -417,7 +430,7 @@ module Cucumber
417
430
  end
418
431
 
419
432
  def after_step_hook(result)
420
- result.describe_exception_to formatter
433
+ result.accept formatter
421
434
  end
422
435
 
423
436
  def step_invocation(step_invocation, source)
@@ -485,7 +498,7 @@ module Cucumber
485
498
  end
486
499
 
487
500
  def after_step_hook(result)
488
- result.describe_exception_to formatter
501
+ result.accept formatter
489
502
  end
490
503
 
491
504
  def after_test_case(*args)
@@ -726,7 +739,8 @@ module Cucumber
726
739
  include PrintsAfterHooks
727
740
 
728
741
  def after_step_hook(result)
729
- @after_step_hook_result = result
742
+ @after_step_hook_result ||= []
743
+ @after_step_hook_result.push result
730
744
  end
731
745
 
732
746
  def after_test_case(*args)
@@ -791,7 +805,7 @@ module Cucumber
791
805
  formatter.after_table_cell(value)
792
806
  end
793
807
  formatter.after_table_row(legacy_table_row)
794
- @after_step_hook_result.describe_exception_to formatter if @after_step_hook_result
808
+ @after_step_hook_result.each { |result| result.accept formatter } if @after_step_hook_result
795
809
  after_hook_results.accept(formatter)
796
810
  @done = true
797
811
  self
@@ -826,7 +840,7 @@ module Cucumber
826
840
  def after
827
841
  return if @done
828
842
  @child.after if @child
829
- @after_step_hook_result.describe_exception_to formatter if @after_step_hook_result
843
+ @after_step_hook_result.each { |result| result.accept formatter } if @after_step_hook_result
830
844
  after_hook_results.accept(formatter)
831
845
  @done = true
832
846
  self
@@ -977,7 +991,7 @@ module Cucumber
977
991
 
978
992
  class StepBacktraceLine < Struct.new(:step)
979
993
  def to_s
980
- "#{step.location}:in `#{step.keyword}#{step.gherkin_statement.name}'"
994
+ step.backtrace_line
981
995
  end
982
996
  end
983
997
 
@@ -1057,13 +1071,15 @@ module Cucumber
1057
1071
  end
1058
1072
 
1059
1073
  class HookResult
1060
- def initialize(result)
1061
- @result = result
1074
+ def initialize(result, messages, embeddings)
1075
+ @result, @messages, @embeddings = result, messages, embeddings
1062
1076
  @already_accepted = false
1063
1077
  end
1064
1078
 
1065
1079
  def accept(formatter)
1066
1080
  unless @already_accepted
1081
+ @messages.each { |message| formatter.puts(message) }
1082
+ @embeddings.each { |embedding| embedding.send_to_formatter(formatter) }
1067
1083
  @result.describe_exception_to(formatter)
1068
1084
  @already_accepted = true
1069
1085
  end
@@ -1179,9 +1195,9 @@ module Cucumber
1179
1195
  end
1180
1196
 
1181
1197
  class DataTableRow
1182
- def initialize(row)
1183
- @values = row.map(&:value)
1184
- @line = row.line
1198
+ def initialize(row, line)
1199
+ @values = row
1200
+ @line = line
1185
1201
  end
1186
1202
 
1187
1203
  def dom_id
@@ -1210,6 +1226,18 @@ module Cucumber
1210
1226
  private :values, :line
1211
1227
  end
1212
1228
 
1229
+ class LegacyTableRow < DataTableRow
1230
+ def accept(formatter)
1231
+ formatter.before_table_row(self)
1232
+ values.each do |value|
1233
+ formatter.before_table_cell(value.value)
1234
+ formatter.table_cell_value(value.value, value.status)
1235
+ formatter.after_table_cell(value.value)
1236
+ end
1237
+ formatter.after_table_row(self)
1238
+ end
1239
+ end
1240
+
1213
1241
  Tags = Struct.new(:tags) do
1214
1242
  def accept(formatter)
1215
1243
  formatter.before_tags tags
@@ -1268,6 +1296,10 @@ module Cucumber
1268
1296
  @result = DataTable.new(node)
1269
1297
  end
1270
1298
 
1299
+ def legacy_table(node)
1300
+ @result = LegacyTable.new(node)
1301
+ end
1302
+
1271
1303
  def result
1272
1304
  @result || Node.new(nil)
1273
1305
  end
@@ -1281,16 +1313,31 @@ module Cucumber
1281
1313
  end
1282
1314
  end
1283
1315
 
1284
- class DataTable < Node
1316
+ class DataTable < Cucumber::MultilineArgument::DataTable
1317
+ def node
1318
+ @ast_table
1319
+ end
1320
+
1285
1321
  def accept(formatter)
1286
- formatter.before_multiline_arg node
1287
- node.cells_rows.each do |row|
1288
- Legacy::Ast::DataTableRow.new(row).accept(formatter)
1322
+ formatter.before_multiline_arg self
1323
+ node.raw.each_with_index do |row, index|
1324
+ line = node.location.line + index
1325
+ Legacy::Ast::DataTableRow.new(row, line).accept(formatter)
1289
1326
  end
1290
- formatter.after_multiline_arg node
1327
+ formatter.after_multiline_arg self
1291
1328
  end
1292
1329
  end
1330
+ end
1293
1331
 
1332
+ class LegacyTable < SimpleDelegator
1333
+ def accept(formatter)
1334
+ formatter.before_multiline_arg self
1335
+ cells_rows.each_with_index do |row, index|
1336
+ line = location.line + index
1337
+ Legacy::Ast::LegacyTableRow.new(row, line).accept(formatter)
1338
+ end
1339
+ formatter.after_multiline_arg self
1340
+ end
1294
1341
  end
1295
1342
 
1296
1343
  Features = Struct.new(:duration)
@@ -35,7 +35,6 @@ module Cucumber
35
35
 
36
36
  require 'cucumber/core'
37
37
  require 'cucumber/runtime/user_interface'
38
- require 'cucumber/runtime/features_loader'
39
38
  require 'cucumber/runtime/results'
40
39
  require 'cucumber/runtime/support_code'
41
40
  require 'cucumber/runtime/tag_limits'
@@ -157,44 +156,6 @@ module Cucumber
157
156
  @support_code.unknown_programming_language?
158
157
  end
159
158
 
160
- # TODO: this code is untested
161
- def write_stepdefs_json
162
- if(@configuration.dotcucumber)
163
- stepdefs = []
164
- @support_code.step_definitions.sort{|a,b| a.to_hash['source'] <=> a.to_hash['source']}.each do |stepdef|
165
- stepdef_hash = stepdef.to_hash
166
- steps = []
167
- features.each do |feature|
168
- feature.feature_elements.each do |feature_element|
169
- feature_element.raw_steps.each do |step|
170
- args = stepdef.arguments_from(step.name)
171
- if(args)
172
- steps << {
173
- 'name' => step.name,
174
- 'args' => args.map do |arg|
175
- {
176
- 'offset' => arg.offset,
177
- 'val' => arg.val
178
- }
179
- end
180
- }
181
- end
182
- end
183
- end
184
- end
185
- stepdef_hash['file_colon_line'] = stepdef.file_colon_line
186
- stepdef_hash['steps'] = steps.uniq.sort {|a,b| a['name'] <=> b['name']}
187
- stepdefs << stepdef_hash
188
- end
189
- if !File.directory?(@configuration.dotcucumber)
190
- FileUtils.mkdir_p(@configuration.dotcucumber)
191
- end
192
- File.open(File.join(@configuration.dotcucumber, 'stepdefs.json'), 'w') do |io|
193
- io.write(MultiJson.dump(stepdefs, :pretty => true))
194
- end
195
- end
196
- end
197
-
198
159
  # Returns Ast::DocString for +string_without_triple_quotes+.
199
160
  #
200
161
  def doc_string(string_without_triple_quotes, content_type='', line_offset=0)
@@ -27,7 +27,7 @@ module Cucumber
27
27
  :invoke,
28
28
  :load_programming_language
29
29
 
30
- # Returns a Cucumber::Core::Ast::DataTable for +text_or_table+, which can either
30
+ # Returns a Cucumber::MultilineArgument::DataTable for +text_or_table+, which can either
31
31
  # be a String:
32
32
  #
33
33
  # table(%{
@@ -45,21 +45,23 @@ module Cucumber
45
45
  # ])
46
46
  #
47
47
  def table(text_or_table, file=nil, line_offset=0)
48
- file, line = *caller[0].split(':')[0..1]
49
- location = Core::Ast::Location.new(file, line)
48
+ if !file
49
+ location = Core::Ast::Location.of_caller
50
+ else
51
+ location = Core::Ast::Location.new(file, line)
52
+ end
50
53
  if Array === text_or_table
51
- Core::Ast::DataTable.new(text_or_table, location)
54
+ MultilineArgument::DataTable.new(text_or_table, location)
52
55
  else
53
- Core::Ast::DataTable.parse(text_or_table, file, location)
56
+ MultilineArgument::DataTable.parse(text_or_table, file, location)
54
57
  end
55
58
  end
56
59
 
57
- # Returns Ast::DocString for +string_without_triple_quotes+.
60
+ # Returns a Cucumber::MultilineArgument::DocString for +body+.
58
61
  #
59
- def doc_string(string_without_triple_quotes, content_type='', line_offset=0)
60
- file, line = *caller[0].split(':')[0..1]
61
- location = Core::Ast::Location.new(file, line)
62
- Core::Ast::DocString.new(string_without_triple_quotes,content_type, location)
62
+ def doc_string(body, content_type='', line_offset=0)
63
+ location = Core::Ast::Location.of_caller
64
+ MultilineArgument.doc_string(body, content_type, location)
63
65
  end
64
66
  end
65
67
  end
@@ -1,5 +1,4 @@
1
1
  require 'cucumber/constantize'
2
- require 'cucumber/core/ast/multiline_argument'
3
2
  require 'cucumber/runtime/for_programming_languages'
4
3
 
5
4
  module Cucumber
@@ -8,6 +7,7 @@ module Cucumber
8
7
 
9
8
  class SupportCode
10
9
 
10
+ # TODO: figure out a way to move this to the core. We'd need to have access to the mappings to pass those in.
11
11
  require 'forwardable'
12
12
  class StepInvoker
13
13
  include Gherkin::Rubify
@@ -20,13 +20,20 @@ module Cucumber
20
20
  end
21
21
 
22
22
  def step(step)
23
- location = Cucumber::Core::Ast::Location.new(*caller[0].split(':')[0..1])
24
- core_multiline_arg = Core::Ast::MultilineArgument.from(step.doc_string || step.rows, location)
25
- @support_code.invoke(step.name, MultilineArgument.from(core_multiline_arg), location)
23
+ location = Core::Ast::Location.of_caller
24
+ @support_code.invoke(step.name, multiline_arg(step, location))
26
25
  end
27
26
 
28
27
  def eof
29
28
  end
29
+
30
+ def multiline_arg(step, location)
31
+ if argument = step.doc_string
32
+ MultilineArgument.doc_string(argument.value, argument.content_type, location.on_line(argument.line_range))
33
+ else
34
+ MultilineArgument.from(step.rows, location)
35
+ end
36
+ end
30
37
  end
31
38
 
32
39
  include Constantize
@@ -69,7 +69,7 @@ module Cucumber
69
69
 
70
70
  def handle_diff!(tables)
71
71
  # TODO: figure out if / how we could get a location for a table from the wire (or make a null location)
72
- location = Core::Ast::Location.new('??', '??')
72
+ location = Core::Ast::Location.new(__FILE__, __LINE__)
73
73
  table1 = table(tables[0], location)
74
74
  table2 = table(tables[1], location)
75
75
  table1.diff!(table2)
@@ -89,7 +89,7 @@ module Cucumber
89
89
  private
90
90
 
91
91
  def table(data, location)
92
- Cucumber::MultilineArgument.from(Core::Ast::DataTable.new(data, location))
92
+ Cucumber::MultilineArgument.from_core(Core::Ast::DataTable.new(data, location))
93
93
  end
94
94
  end
95
95
 
@@ -531,14 +531,14 @@ OUTPUT
531
531
  Given there are <Things> # spec.feature:4
532
532
  Examples: Fruit
533
533
  Scenario: | apples | # spec.feature:8
534
- Given there are apples # spec.feature:4
534
+ Given there are apples # spec.feature:8
535
535
  Scenario: | bananas | # spec.feature:9
536
- Given there are bananas # spec.feature:4
536
+ Given there are bananas # spec.feature:9
537
537
  Examples: Vegetables
538
538
  Scenario: | broccoli | # spec.feature:12
539
- Given there are broccoli # spec.feature:4
539
+ Given there are broccoli # spec.feature:12
540
540
  Scenario: | carrots | # spec.feature:13
541
- Given there are carrots # spec.feature:4
541
+ Given there are carrots # spec.feature:13
542
542
  OUTPUT
543
543
  lines.split("\n").each do |line|
544
544
  expect(@out.string).to include line.strip
@@ -561,7 +561,7 @@ OUTPUT
561
561
  lines = <<-OUTPUT
562
562
  Examples:
563
563
  Scenario: | Hominidae | Very long cell content | # spec.feature:8
564
- Given there are Hominidae # spec.feature:4
564
+ Given there are Hominidae # spec.feature:8
565
565
 
566
566
  OUTPUT
567
567
  lines.split("\n").each do |line|
@@ -10,7 +10,7 @@ module Cucumber
10
10
  let(:ruby) { double.as_null_object }
11
11
  let(:runtime) do
12
12
  double(
13
- load_programming_language: ruby,
13
+ load_programming_language: ruby,
14
14
  step_match: double
15
15
  )
16
16
  end
@@ -18,16 +18,129 @@ module Cucumber
18
18
  let(:report) { double.as_null_object }
19
19
 
20
20
  it "responds to #source_tag_names" do
21
- gherkin_docs = [
22
- gherkin do
23
- feature 'test', tags: '@foo @bar' do
24
- scenario 'test', tags: '@baz' do
21
+ define_gherkin do
22
+ feature 'test', tags: '@foo @bar' do
23
+ scenario 'test', tags: '@baz' do
24
+ step 'passing'
25
+ end
26
+ end
27
+ end
28
+
29
+ before do |scenario|
30
+ expect(scenario.source_tag_names).to eq %w(@foo @bar @baz)
31
+ end
32
+ end
33
+
34
+ describe "#failed?" do
35
+
36
+ it "is true if the test case is in a failed state" do
37
+ define_gherkin do
38
+ feature do
39
+ scenario do
40
+ step 'failing'
41
+ end
42
+ end
43
+ end
44
+
45
+ allow(runtime).to receive(:step_match) do |step_name|
46
+ if step_name == 'failing'
47
+ step_match = double
48
+ allow(step_match).to receive(:invoke) { fail }
49
+ step_match
50
+ else
51
+ raise Cucumber::Undefined
52
+ end
53
+ end
54
+
55
+ after do |test_case|
56
+ expect(test_case).to be_failed
57
+ end
58
+ end
59
+
60
+ end
61
+
62
+ describe "#scenario_outline" do
63
+
64
+ # TODO: is this actually desired behaviour?
65
+ it "throws a NoMethodError when the test case is from a scenario" do
66
+ define_gherkin do
67
+ feature do
68
+ scenario do
69
+ step 'passing'
70
+ end
71
+ end
72
+ end
73
+
74
+ before do |test_case|
75
+ expect{ test_case.scenario_outline }.to raise_error(NoMethodError)
76
+ end
77
+ end
78
+
79
+ it "points to self when the test case is from a scenario outline" do
80
+ define_gherkin do
81
+ feature do
82
+ scenario_outline 'outline' do
83
+ step 'passing'
84
+
85
+ examples 'examples' do
86
+ row 'a'
87
+ row '1'
88
+ end
89
+ end
90
+ end
91
+ end
92
+
93
+ before do |test_case|
94
+ expect(test_case.scenario_outline).to_not be_nil
95
+ expect(test_case.scenario_outline.name).to eq "Scenario Outline: outline, examples (row 1)"
96
+ end
97
+ end
98
+
99
+ end
100
+
101
+ describe "#outline?" do
102
+
103
+ it "returns false when the test case is from a scenario" do
104
+ define_gherkin do
105
+ feature do
106
+ scenario do
107
+ step 'passing'
108
+ end
109
+ end
110
+ end
111
+
112
+ before do |test_case|
113
+ expect(test_case).to_not be_an_outline
114
+ end
115
+ end
116
+
117
+ it "returns true when the test case is from a scenario" do
118
+ define_gherkin do
119
+ feature do
120
+ scenario_outline do
25
121
  step 'passing'
122
+
123
+ examples 'examples' do
124
+ row 'a'
125
+ row '1'
126
+ end
26
127
  end
27
128
  end
28
129
  end
29
- ]
30
130
 
131
+ before do |test_case|
132
+ expect(test_case).to be_an_outline
133
+ end
134
+ end
135
+
136
+ end
137
+ attr_accessor :gherkin_docs
138
+
139
+ def define_gherkin(&block)
140
+ self.gherkin_docs = [gherkin(&block)]
141
+ end
142
+
143
+ def before
31
144
  # TODO: the complexity of this stubbing shows we need to clean up the interface
32
145
  scenario_spy = nil
33
146
  allow(ruby).to receive(:hooks_for) do |phase, scenario|
@@ -41,10 +154,26 @@ module Cucumber
41
154
  []
42
155
  end
43
156
  end
44
-
45
157
  execute gherkin_docs, mappings, report
158
+ yield scenario_spy
159
+ end
46
160
 
47
- expect(scenario_spy.source_tag_names).to eq %w(@foo @bar @baz)
161
+ def after
162
+ # TODO: the complexity of this stubbing shows we need to clean up the interface
163
+ scenario_spy = nil
164
+ allow(ruby).to receive(:hooks_for) do |phase, scenario|
165
+ if phase == :after
166
+ hook = double
167
+ expect(hook).to receive(:invoke) do |phase, scenario|
168
+ scenario_spy = scenario
169
+ end
170
+ [hook]
171
+ else
172
+ []
173
+ end
174
+ end
175
+ execute gherkin_docs, mappings, report
176
+ yield scenario_spy
48
177
  end
49
178
  end
50
179
  end