cucumber 2.0.0 → 2.0.1

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 (74) hide show
  1. checksums.yaml +4 -4
  2. data/CONTRIBUTING.md +7 -9
  3. data/History.md +295 -265
  4. data/README.md +9 -7
  5. data/cucumber.gemspec +2 -2
  6. data/features/docs/cli/dry_run.feature +0 -3
  7. data/features/docs/cli/finding_steps.feature +28 -0
  8. data/features/docs/cli/run_specific_scenarios.feature +3 -1
  9. data/features/docs/cli/specifying_multiple_formatters.feature +22 -1
  10. data/features/docs/defining_steps/nested_steps.feature +0 -1
  11. data/features/docs/defining_steps/printing_messages.feature +4 -4
  12. data/features/docs/defining_steps/skip_scenario.feature +0 -2
  13. data/features/docs/exception_in_around_hook.feature +1 -3
  14. data/features/docs/formatters/html_formatter.feature +1 -0
  15. data/features/docs/formatters/json_formatter.feature +73 -62
  16. data/features/docs/formatters/junit_formatter.feature +130 -38
  17. data/features/docs/formatters/rerun_formatter.feature +60 -8
  18. data/features/docs/formatters/usage_formatter.feature +3 -7
  19. data/features/docs/getting_started.feature +1 -1
  20. data/features/docs/gherkin/background.feature +0 -11
  21. data/features/docs/gherkin/language_help.feature +5 -0
  22. data/features/docs/gherkin/outlines.feature +1 -3
  23. data/features/docs/gherkin/using_descriptions.feature +0 -1
  24. data/features/docs/raketask.feature +1 -1
  25. data/features/docs/writing_support_code/after_hooks.feature +22 -0
  26. data/features/lib/step_definitions/aruba_steps.rb +4 -0
  27. data/features/lib/step_definitions/junit_steps.rb +1 -1
  28. data/features/lib/support/normalise_output.rb +21 -4
  29. data/lib/cucumber/cli/configuration.rb +16 -13
  30. data/lib/cucumber/cli/main.rb +35 -10
  31. data/lib/cucumber/cli/options.rb +33 -9
  32. data/lib/cucumber/cli/rerun_file.rb +29 -0
  33. data/lib/cucumber/filters/prepare_world.rb +2 -3
  34. data/lib/cucumber/formatter/backtrace_filter.rb +40 -0
  35. data/lib/cucumber/formatter/console.rb +2 -3
  36. data/lib/cucumber/formatter/cucumber.css +1 -0
  37. data/lib/cucumber/formatter/duration_extractor.rb +28 -0
  38. data/lib/cucumber/formatter/hook_query_visitor.rb +40 -0
  39. data/lib/cucumber/formatter/html.rb +16 -1
  40. data/lib/cucumber/formatter/json.rb +287 -8
  41. data/lib/cucumber/formatter/junit.rb +92 -143
  42. data/lib/cucumber/formatter/legacy_api/adapter.rb +18 -54
  43. data/lib/cucumber/formatter/legacy_api/ast.rb +13 -0
  44. data/lib/cucumber/formatter/legacy_api/runtime_facade.rb +4 -0
  45. data/lib/cucumber/formatter/pretty.rb +2 -1
  46. data/lib/cucumber/formatter/progress.rb +20 -53
  47. data/lib/cucumber/formatter/rerun.rb +2 -1
  48. data/lib/cucumber/formatter/usage.rb +16 -22
  49. data/lib/cucumber/hooks.rb +18 -9
  50. data/lib/cucumber/multiline_argument/data_table.rb +40 -28
  51. data/lib/cucumber/platform.rb +1 -1
  52. data/lib/cucumber/rb_support/rb_hook.rb +4 -0
  53. data/lib/cucumber/running_test_case.rb +13 -4
  54. data/lib/cucumber/runtime/after_hooks.rb +7 -6
  55. data/lib/cucumber/runtime/before_hooks.rb +8 -4
  56. data/lib/cucumber/runtime/step_hooks.rb +5 -4
  57. data/lib/cucumber/runtime/support_code.rb +6 -15
  58. data/lib/cucumber/step_match.rb +1 -1
  59. data/spec/cucumber/cli/configuration_spec.rb +32 -5
  60. data/spec/cucumber/cli/main_spec.rb +3 -3
  61. data/spec/cucumber/cli/options_spec.rb +60 -1
  62. data/spec/cucumber/cli/rerun_spec.rb +89 -0
  63. data/spec/cucumber/formatter/html_spec.rb +84 -5
  64. data/spec/cucumber/formatter/json_spec.rb +757 -0
  65. data/spec/cucumber/formatter/junit_spec.rb +5 -5
  66. data/spec/cucumber/formatter/legacy_api/adapter_spec.rb +69 -8
  67. data/spec/cucumber/formatter/pretty_spec.rb +96 -0
  68. data/spec/cucumber/formatter/progress_spec.rb +85 -1
  69. data/spec/cucumber/formatter/rerun_spec.rb +3 -3
  70. data/spec/cucumber/multiline_argument/data_table_spec.rb +89 -0
  71. data/spec/cucumber/running_test_case_spec.rb +57 -1
  72. metadata +70 -60
  73. data/lib/cucumber/formatter/gherkin_formatter_adapter.rb +0 -204
  74. data/lib/cucumber/formatter/gpretty.rb +0 -24
@@ -1,8 +1,9 @@
1
1
  module Cucumber
2
2
  class Runtime
3
3
  class AfterHooks
4
- def initialize(action_blocks)
5
- @action_blocks = action_blocks
4
+ def initialize(hooks, scenario)
5
+ @hooks = hooks
6
+ @scenario = scenario
6
7
  end
7
8
 
8
9
  def apply_to(test_case)
@@ -14,11 +15,11 @@ module Cucumber
14
15
  private
15
16
 
16
17
  def after_hooks(source)
17
- @action_blocks.map do |action_block|
18
- Hooks.after_hook(source, &action_block)
19
- end
18
+ @hooks.map do |hook|
19
+ action = ->(result) { hook.invoke('After', @scenario.with_result(result)) }
20
+ Hooks.after_hook(source, Hooks.location(hook), &action)
21
+ end
20
22
  end
21
23
  end
22
24
  end
23
25
  end
24
-
@@ -1,8 +1,11 @@
1
+ require 'cucumber/hooks'
2
+
1
3
  module Cucumber
2
4
  class Runtime
3
5
  class BeforeHooks
4
- def initialize(action_blocks)
5
- @action_blocks = action_blocks
6
+ def initialize(hooks, scenario)
7
+ @hooks = hooks
8
+ @scenario = scenario
6
9
  end
7
10
 
8
11
  def apply_to(test_case)
@@ -14,8 +17,9 @@ module Cucumber
14
17
  private
15
18
 
16
19
  def before_hooks(source)
17
- @action_blocks.map do |action_block|
18
- Hooks.before_hook(source, &action_block)
20
+ @hooks.map do |hook|
21
+ action_block = ->(result) { hook.invoke('Before', @scenario.with_result(result)) }
22
+ Hooks.before_hook(source, Hooks.location(hook), &action_block)
19
23
  end
20
24
  end
21
25
  end
@@ -1,8 +1,8 @@
1
1
  module Cucumber
2
2
  class Runtime
3
3
  class StepHooks
4
- def initialize(after)
5
- @after = after
4
+ def initialize(hooks)
5
+ @hooks = hooks
6
6
  end
7
7
 
8
8
  def apply(test_steps)
@@ -13,8 +13,9 @@ module Cucumber
13
13
 
14
14
  private
15
15
  def after_step_hooks(test_step)
16
- @after.map do |action_block|
17
- Hooks.after_step_hook(test_step.source, &action_block)
16
+ @hooks.map do |hook|
17
+ action = ->(*args) { hook.invoke('AfterStep', args) }
18
+ Hooks.after_step_hook(test_step.source, Hooks.location(hook), &action)
18
19
  end
19
20
  end
20
21
  end
@@ -148,31 +148,22 @@ module Cucumber
148
148
  def find_after_step_hooks(test_case)
149
149
  ruby = load_programming_language('rb')
150
150
  scenario = RunningTestCase.new(test_case)
151
-
152
- action_blocks = ruby.hooks_for(:after_step, scenario).map do |hook|
153
- ->(*args) { hook.invoke('AfterStep', args) }
154
- end
155
- StepHooks.new action_blocks
151
+ hooks = ruby.hooks_for(:after_step, scenario)
152
+ StepHooks.new hooks
156
153
  end
157
154
 
158
155
  def apply_before_hooks(test_case)
159
156
  ruby = load_programming_language('rb')
160
157
  scenario = RunningTestCase.new(test_case)
161
-
162
- action_blocks = ruby.hooks_for(:before, scenario).map do |hook|
163
- ->(result) { hook.invoke('Before', scenario.with_result(result)) }
164
- end
165
- BeforeHooks.new(action_blocks).apply_to(test_case)
158
+ hooks = ruby.hooks_for(:before, scenario)
159
+ BeforeHooks.new(hooks, scenario).apply_to(test_case)
166
160
  end
167
161
 
168
162
  def apply_after_hooks(test_case)
169
163
  ruby = load_programming_language('rb')
170
164
  scenario = RunningTestCase.new(test_case)
171
-
172
- action_blocks = ruby.hooks_for(:after, scenario).map do |hook|
173
- ->(result) { hook.invoke('After', scenario.with_result(result)) }
174
- end
175
- AfterHooks.new(action_blocks).apply_to(test_case)
165
+ hooks = ruby.hooks_for(:after, scenario)
166
+ AfterHooks.new(hooks, scenario).apply_to(test_case)
176
167
  end
177
168
 
178
169
  def find_around_hooks(test_case)
@@ -22,7 +22,7 @@ module Cucumber
22
22
  end
23
23
 
24
24
  def activate(test_step)
25
- test_step.with_action do
25
+ test_step.with_action(@step_definition.file_colon_line) do
26
26
  invoke(MultilineArgument.from_core(test_step.source.last.multiline_arg))
27
27
  end
28
28
  end
@@ -252,6 +252,12 @@ END_OF_MESSAGE
252
252
 
253
253
  expect(config.options[:dry_run]).to be true
254
254
  end
255
+
256
+ it "implies --no-duration with --dry-run option" do
257
+ config.parse!(%w{--dry-run})
258
+
259
+ expect(config.options[:duration]).to be false
260
+ end
255
261
 
256
262
  it "accepts --no-source option" do
257
263
  config.parse!(%w{--no-source})
@@ -265,11 +271,18 @@ END_OF_MESSAGE
265
271
  expect(config.options[:snippets]).to be false
266
272
  end
267
273
 
268
- it "sets snippets and source to false with --quiet option" do
274
+ it "sets snippets and source and duration to false with --quiet option" do
269
275
  config.parse!(%w{--quiet})
270
276
 
271
277
  expect(config.options[:snippets]).to be false
272
278
  expect(config.options[:source]).to be false
279
+ expect(config.options[:duration]).to be false
280
+ end
281
+
282
+ it "sets duration to false with --no-duration" do
283
+ config.parse!(%w{--no-duration})
284
+
285
+ expect(config.options[:duration]).to be false
273
286
  end
274
287
 
275
288
  it "accepts --verbose option" do
@@ -300,6 +313,11 @@ END_OF_MESSAGE
300
313
  expect(-> { config.parse!(%w{--format pretty --format progress}) }).to raise_error("All but one formatter must use --out, only one can print to each stream (or STDOUT)")
301
314
  end
302
315
 
316
+ it "does not accept multiple --format options when both use implicit STDOUT (using profile with no formatters)" do
317
+ given_cucumber_yml_defined_as({'default' => ['-q']})
318
+ expect(-> { config.parse!(%w{--format pretty --format progress}) }).to raise_error("All but one formatter must use --out, only one can print to each stream (or STDOUT)")
319
+ end
320
+
303
321
  it "accepts same --format options with implicit STDOUT, and keep only one" do
304
322
  config.parse!(%w{--format pretty --format pretty})
305
323
 
@@ -310,6 +328,11 @@ END_OF_MESSAGE
310
328
  expect(-> { config.parse!(%w{--format pretty --out file1 --format progress --out file1}) }).to raise_error("All but one formatter must use --out, only one can print to each stream (or STDOUT)")
311
329
  end
312
330
 
331
+ it "does not accept multiple --out streams pointing to the same place (one from profile, one from command line)" do
332
+ given_cucumber_yml_defined_as({'default' => ['-f','progress', '--out', 'file1']})
333
+ expect(-> { config.parse!(%w{--format pretty --out file1}) }).to raise_error("All but one formatter must use --out, only one can print to each stream (or STDOUT)")
334
+ end
335
+
313
336
  it "associates --out to previous --format" do
314
337
  config.parse!(%w{--format progress --out file1 --format profile --out file2})
315
338
 
@@ -402,15 +425,19 @@ END_OF_MESSAGE
402
425
  allow(File).to receive(:directory?).and_return(false)
403
426
  allow(File).to receive(:file?).and_return(true)
404
427
  allow(IO).to receive(:read).and_return(
405
- "cucumber.feature:1:3 cucumber space.feature:134 domain folder/cuke.feature:1 domain folder/different cuke:4:5" )
406
-
428
+ "cucumber.feature:1:3\ncucumber.feature:5 cucumber.feature:10\n"\
429
+ "domain folder/different cuke.feature:134 domain folder/cuke.feature:1\n"\
430
+ "domain folder/different cuke.feature:4:5 bar.feature")
407
431
  config.parse!(%w{@rerun.txt})
408
432
 
409
433
  expect(config.feature_files).to eq [
410
434
  "cucumber.feature:1:3",
411
- "cucumber space.feature:134",
435
+ "cucumber.feature:5",
436
+ "cucumber.feature:10",
437
+ "domain folder/different cuke.feature:134",
412
438
  "domain folder/cuke.feature:1",
413
- "domain folder/different cuke:4:5"]
439
+ "domain folder/different cuke.feature:4:5",
440
+ "bar.feature"]
414
441
  end
415
442
 
416
443
  it "should allow specifying environment variables on the command line" do
@@ -51,7 +51,7 @@ module Cucumber
51
51
  Cucumber.wants_to_quit = false
52
52
  end
53
53
 
54
- it "registers as a failure" do
54
+ it "exits with error code" do
55
55
  results = double('results', :failure? => false)
56
56
 
57
57
  allow_any_instance_of(Runtime).to receive(:run!)
@@ -59,7 +59,7 @@ module Cucumber
59
59
 
60
60
  Cucumber.wants_to_quit = true
61
61
 
62
- expect(kernel).to receive(:exit).with(1)
62
+ expect(kernel).to receive(:exit).with(2)
63
63
 
64
64
  subject.execute!
65
65
  end
@@ -93,7 +93,7 @@ module Cucumber
93
93
 
94
94
  allow(Configuration).to receive(:new) { configuration }
95
95
  allow(configuration).to receive(:parse!).and_raise(exception_klass.new("error message"))
96
- allow(kernel).to receive(:exit).with(1)
96
+ allow(kernel).to receive(:exit).with(2)
97
97
 
98
98
  subject.execute!
99
99
 
@@ -59,7 +59,7 @@ module Cucumber
59
59
  context "with LANG specified as 'help'" do
60
60
  include RSpec::WorkInProgress
61
61
 
62
- it "lists all known langues" do
62
+ it "lists all known languages" do
63
63
  when_parsing '--i18n help' do
64
64
  expect(Kernel).to receive(:exit)
65
65
  end
@@ -69,6 +69,28 @@ module Cucumber
69
69
  when_parsing('--i18n help') { expect(Kernel).to receive(:exit) }
70
70
  end
71
71
  end
72
+
73
+ context "with invalid LANG" do
74
+ include RSpec::WorkInProgress
75
+
76
+ it "exits" do
77
+ when_parsing '--i18n foo' do
78
+ expect(Kernel).to receive(:exit)
79
+ end
80
+ end
81
+
82
+ it "says the language was invalid" do
83
+ after_parsing '--i18n foo' do
84
+ expect(@output_stream.string).to include("Invalid language 'foo'. Available languages are:")
85
+ end
86
+ end
87
+
88
+ it "displays the language table" do
89
+ after_parsing '--i18n foo' do
90
+ expect(@output_stream.string).to include(Gherkin::I18n.language_table);
91
+ end
92
+ end
93
+ end
72
94
  end
73
95
 
74
96
  context '-f FORMAT or --format FORMAT' do
@@ -88,6 +110,35 @@ module Cucumber
88
110
  end
89
111
  end
90
112
 
113
+ context 'handling multiple formatters' do
114
+ it "catches multiple command line formatters using the same stream" do
115
+ expect{ options.parse!(prepare_args('-f pretty -f progress')) }.to raise_error("All but one formatter must use --out, only one can print to each stream (or STDOUT)")
116
+ end
117
+
118
+ it "catches multiple profile formatters using the same stream" do
119
+ given_cucumber_yml_defined_as({'default' => '-f progress -f pretty'})
120
+ options = Options.new(output_stream, error_stream, :default_profile => 'default')
121
+
122
+ expect{ options.parse!(%w{}) }.to raise_error("All but one formatter must use --out, only one can print to each stream (or STDOUT)")
123
+ end
124
+
125
+ it "profiles does not affect the catching of multiple command line formatters using the same stream" do
126
+ given_cucumber_yml_defined_as({'default' => '-q'})
127
+ options = Options.new(output_stream, error_stream, :default_profile => 'default')
128
+
129
+ expect{ options.parse!(%w{-f progress -f pretty}) }.to raise_error("All but one formatter must use --out, only one can print to each stream (or STDOUT)")
130
+ end
131
+
132
+ it "merges profile formatters and command line formatters" do
133
+ given_cucumber_yml_defined_as({'default' => '-f junit -o result.xml'})
134
+ options = Options.new(output_stream, error_stream, :default_profile => 'default')
135
+
136
+ options.parse!(%w{-f pretty})
137
+
138
+ expect(options[:formats]).to eq [['pretty', output_stream], ["junit", "result.xml"]]
139
+ end
140
+ end
141
+
91
142
  context '-t TAGS --tags TAGS' do
92
143
  it "designates tags prefixed with ~ as tags to be excluded" do
93
144
  after_parsing('--tags ~@foo,@bar') { expect(options[:tag_expressions]).to eq ['~@foo,@bar'] }
@@ -238,6 +289,14 @@ module Cucumber
238
289
 
239
290
  expect(options[:snippets]).to be false
240
291
  expect(options[:source]).to be false
292
+ expect(options[:duration]).to be false
293
+ end
294
+
295
+ it "uses --no-duration when defined in the profile" do
296
+ given_cucumber_yml_defined_as('foo' => '--no-duration')
297
+ options.parse!(%w[-p foo])
298
+
299
+ expect(options[:duration]).to be false
241
300
  end
242
301
  end
243
302
 
@@ -0,0 +1,89 @@
1
+ require 'spec_helper'
2
+
3
+ module Cucumber
4
+ module Cli
5
+ describe RerunFile do
6
+
7
+ let(:rerun_file) { RerunFile.new('@rerun.txt') }
8
+
9
+ it "expects rerun files to have a leading @" do
10
+ allow(File).to receive(:file?) { true }
11
+ expect(RerunFile.can_read?('rerun.txt')).to eq false
12
+ expect(RerunFile.can_read?('@rerun.txt')).to eq true
13
+ end
14
+
15
+ it "does not treat directories as rerun files" do
16
+ allow(File).to receive(:file?) { false }
17
+ expect(RerunFile.can_read?('@rerun.txt')).to eq false
18
+ end
19
+
20
+ it "removes leading @ character from filename" do
21
+ expect(rerun_file.path).to eq 'rerun.txt'
22
+ end
23
+
24
+ context "rerun file containing single feature" do
25
+ before(:each) do
26
+ allow(IO).to receive(:read).and_return("cucumber.feature")
27
+ end
28
+
29
+ it "produces an array containing a single feature file path" do
30
+ expect(rerun_file.features).to eq %w(cucumber.feature)
31
+ end
32
+ end
33
+
34
+ context "contains multiple features on multiple lines" do
35
+ before(:each) do
36
+ allow(IO).to receive(:read).and_return("cucumber.feature\nfoo.feature")
37
+ end
38
+
39
+ it "produces an array containing multiple feature file paths" do
40
+ expect(rerun_file.features).to eq %w(cucumber.feature foo.feature)
41
+ end
42
+ end
43
+
44
+ context "contains multiple features on same line" do
45
+ before(:each) do
46
+ allow(IO).to receive(:read).and_return("cucumber.feature foo.feature")
47
+ end
48
+
49
+ it "produces an array containing multiple feature file paths" do
50
+ expect(rerun_file.features).to eq %w(cucumber.feature foo.feature)
51
+ end
52
+ end
53
+
54
+ context "contains multiple scenarios on same line" do
55
+ before(:each) do
56
+ allow(IO).to receive(:read).and_return("cucumber.feature:8 foo.feature:8:16")
57
+ end
58
+
59
+ it "produces an array containing multiple feature file paths with scenario lines" do
60
+ expect(rerun_file.features).to eq %w(cucumber.feature:8 foo.feature:8:16)
61
+ end
62
+ end
63
+
64
+ context "contains features with spaces in file names" do
65
+ before(:each) do
66
+ allow(IO).to receive(:read).and_return("cucumber test.feature:8 foo.feature:8:16")
67
+ end
68
+
69
+ it "produces an array containing multiple feature file paths with scenario lines" do
70
+ expect(rerun_file.features).to eq ['cucumber test.feature:8', 'foo.feature:8:16']
71
+ end
72
+ end
73
+
74
+ context "contains features and scenarios with and without spaces same line and across lines" do
75
+ before(:each) do
76
+ allow(IO).to receive(:read).and_return(
77
+ "cucumber.feature:1:3\ncucumber.feature:5 cucumber.feature:10\n"\
78
+ "cucumber space.feature:134 domain folder/cuke.feature\n")
79
+ end
80
+
81
+ it "produces an array containing multiple feature file paths with scenario lines" do
82
+ feature_files = ['cucumber.feature:1:3', 'cucumber.feature:5', 'cucumber.feature:10',
83
+ 'cucumber space.feature:134', 'domain folder/cuke.feature']
84
+ expect(rerun_file.features).to eq feature_files
85
+ end
86
+ end
87
+ end
88
+ end
89
+ end
@@ -40,7 +40,7 @@ module Cucumber
40
40
 
41
41
  describe "with a step that embeds a snapshot" do
42
42
  define_steps do
43
- Given(/snap/) {
43
+ Given(/snap/) {
44
44
  RSpec::Mocks.allow_message(File, :file?) { true }
45
45
  embed('out/snapshot.jpeg', 'image/jpeg')
46
46
  }
@@ -87,7 +87,25 @@ module Cucumber
87
87
 
88
88
  it { expect(@out.string).to match(/^\<!DOCTYPE/) }
89
89
  it { expect(@out.string).to match(/\<\/html\>$/) }
90
- it { expect(@doc).to have_css_node('.feature .comment', /Healthy/) }
90
+
91
+ it "nests the comment within the feature" do
92
+ expect(@doc).to have_css_node('.feature .comment', /Healthy/)
93
+ end
94
+
95
+ it "properly closes the comment" do
96
+ expect(@out.string).to match(%r{<pre class="comment"># Healthy<br/></pre>})
97
+ end
98
+ end
99
+
100
+ describe "with a comment at scenario level" do
101
+ define_feature <<-FEATURE
102
+ Feature: Foo
103
+ # Healthy Scenario
104
+ Scenario:
105
+ Given passing
106
+ FEATURE
107
+
108
+ it { expect(@doc).to have_css_node('.scenario .comment', /Healthy Scenario/) }
91
109
  end
92
110
 
93
111
  describe "with a tag" do
@@ -273,9 +291,49 @@ module Cucumber
273
291
  it { expect(@doc).not_to have_css_node('.feature .scenario .backtrace', //) }
274
292
  end
275
293
 
294
+ context "with a before hook that fails" do
295
+ describe "in a scenario" do
296
+ define_steps do
297
+ Before { raise 'eek' }
298
+ Given(/yay/) {}
299
+ end
300
+
301
+ define_feature(<<-FEATURE)
302
+ Feature: shouting
303
+ Scenario:
304
+ Given yay
305
+ FEATURE
306
+
307
+ it { expect(@out.string).to include('makeRed(\'scenario_1\')') }
308
+ it { expect(@doc).not_to have_css_node('.feature .scenario .step.failed', //) }
309
+ it { expect(@doc).to have_css_node('.feature .scenario .step.skipped', /yay/) }
310
+ end
311
+
312
+ describe "in a scenario outline" do
313
+ define_steps do
314
+ Before { raise 'eek' }
315
+ Given(/yay/) {}
316
+ end
317
+
318
+ define_feature(<<-FEATURE)
319
+ Feature: shouting
320
+ Scenario Outline:
321
+ Given <step>
322
+ Examples:
323
+ | step |
324
+ | yay |
325
+ FEATURE
326
+
327
+ it { expect(@out.string).to include('makeRed(\'scenario_1\')') }
328
+ it { expect(@doc).not_to have_css_node('.feature .scenario .step.failed', //) }
329
+ it { expect(@doc).to have_css_node('.feature .scenario .step.skipped', /yay/) }
330
+ end
331
+
332
+ end
333
+
276
334
  describe "with a step that embeds a snapshot" do
277
335
  define_steps do
278
- Given(/snap/) {
336
+ Given(/snap/) {
279
337
  RSpec::Mocks.allow_message(File, :file?) { true }
280
338
  embed('snapshot.jpeg', 'image/jpeg')
281
339
  }
@@ -289,7 +347,7 @@ module Cucumber
289
347
 
290
348
  it { expect(@doc.css('.embed img').first.attributes['src'].to_s).to eq "snapshot.jpeg" }
291
349
  end
292
-
350
+
293
351
  describe "with a step that embeds a text" do
294
352
  define_steps do
295
353
  Given(/log/) { embed('log.txt', 'text/plain') }
@@ -431,7 +489,7 @@ module Cucumber
431
489
  let(:runtime) { Runtime.new({:expand => true})}
432
490
  before(:each) do
433
491
  @out = StringIO.new
434
- @formatter = Html.new(runtime, @out, {})
492
+ @formatter = Html.new(runtime, @out, {:expand => true})
435
493
  run_defined_feature
436
494
  @doc = Nokogiri.HTML(@out.string)
437
495
  end
@@ -453,6 +511,27 @@ module Cucumber
453
511
 
454
512
  it { expect(@doc.css('pre').map { |pre| /^(Given|Then|When)/.match(pre.text)[1] }).to eq ["Given", "Given"] }
455
513
  end
514
+
515
+ describe "with a scenario outline and a before hook that fails" do
516
+ define_steps do
517
+ Before { raise 'eek' }
518
+ Given(/yay/) {}
519
+ end
520
+
521
+ define_feature(<<-FEATURE)
522
+ Feature: shouting
523
+ Scenario Outline:
524
+ Given <step>
525
+ Examples:
526
+ | step |
527
+ | yay |
528
+ FEATURE
529
+
530
+ it { expect(@out.string).to include('makeRed(\'scenario_1\')') }
531
+ it { expect(@out.string).to include('makeRed(\'scenario_1_1\')') }
532
+ it { expect(@doc).not_to have_css_node('.feature .scenario .step.failed', //) }
533
+ it { expect(@doc).to have_css_node('.feature .scenario .step.skipped', /yay/) }
534
+ end
456
535
  end
457
536
  end
458
537
  end