cucumber 2.0.0 → 2.0.1

Sign up to get free protection for your applications and to get access to all the features.
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