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
@@ -0,0 +1,757 @@
1
+ require 'spec_helper'
2
+ require 'cucumber/formatter/spec_helper'
3
+ require 'cucumber/formatter/json'
4
+ require 'cucumber/cli/options'
5
+ require 'multi_json'
6
+
7
+ module Cucumber
8
+ module Formatter
9
+ describe Json do
10
+ extend SpecHelperDsl
11
+ include SpecHelper
12
+
13
+ context "Given a single feature" do
14
+ before(:each) do
15
+ @out = StringIO.new
16
+ @formatter = Json.new(runtime, @out, {})
17
+ run_defined_feature
18
+ end
19
+
20
+ describe "with a scenario with no steps" do
21
+ define_feature <<-FEATURE
22
+ Feature: Banana party
23
+
24
+ Scenario: Monkey eats bananas
25
+ FEATURE
26
+
27
+ it "outputs the json data" do
28
+ expect(load_normalised_json(@out)).to eq MultiJson.load(%{
29
+ [{"id": "banana-party",
30
+ "uri": "spec.feature",
31
+ "keyword": "Feature",
32
+ "name": "Banana party",
33
+ "line": 1,
34
+ "description": "",
35
+ "elements":
36
+ [{"id": "banana-party;monkey-eats-bananas",
37
+ "keyword": "Scenario",
38
+ "name": "Monkey eats bananas",
39
+ "line": 3,
40
+ "description": "",
41
+ "type": "scenario"}]}]})
42
+ end
43
+ end
44
+
45
+ describe "with a scenario with an undefined step" do
46
+ define_feature <<-FEATURE
47
+ Feature: Banana party
48
+
49
+ Scenario: Monkey eats bananas
50
+ Given there are bananas
51
+ FEATURE
52
+
53
+ it "outputs the json data" do
54
+ expect(load_normalised_json(@out)).to eq MultiJson.load(%{
55
+ [{"id": "banana-party",
56
+ "uri": "spec.feature",
57
+ "keyword": "Feature",
58
+ "name": "Banana party",
59
+ "line": 1,
60
+ "description": "",
61
+ "elements":
62
+ [{"id": "banana-party;monkey-eats-bananas",
63
+ "keyword": "Scenario",
64
+ "name": "Monkey eats bananas",
65
+ "line": 3,
66
+ "description": "",
67
+ "type": "scenario",
68
+ "steps":
69
+ [{"keyword": "Given ",
70
+ "name": "there are bananas",
71
+ "line": 4,
72
+ "match": {"location": "spec.feature:4"},
73
+ "result": {"status": "undefined"}}]}]}]})
74
+ end
75
+ end
76
+
77
+ describe "with a scenario with a passed step" do
78
+ define_feature <<-FEATURE
79
+ Feature: Banana party
80
+
81
+ Scenario: Monkey eats bananas
82
+ Given there are bananas
83
+ FEATURE
84
+
85
+ define_steps do
86
+ Given(/^there are bananas$/) {}
87
+ end
88
+
89
+ it "outputs the json data" do
90
+ expect(load_normalised_json(@out)).to eq MultiJson.load(%{
91
+ [{"id": "banana-party",
92
+ "uri": "spec.feature",
93
+ "keyword": "Feature",
94
+ "name": "Banana party",
95
+ "line": 1,
96
+ "description": "",
97
+ "elements":
98
+ [{"id": "banana-party;monkey-eats-bananas",
99
+ "keyword": "Scenario",
100
+ "name": "Monkey eats bananas",
101
+ "line": 3,
102
+ "description": "",
103
+ "type": "scenario",
104
+ "steps":
105
+ [{"keyword": "Given ",
106
+ "name": "there are bananas",
107
+ "line": 4,
108
+ "match": {"location": "spec/cucumber/formatter/json_spec.rb:86"},
109
+ "result": {"status": "passed",
110
+ "duration": 1}}]}]}]})
111
+ end
112
+ end
113
+
114
+ describe "with a scenario with a failed step" do
115
+ define_feature <<-FEATURE
116
+ Feature: Banana party
117
+
118
+ Scenario: Monkey eats bananas
119
+ Given there are bananas
120
+ FEATURE
121
+
122
+ define_steps do
123
+ Given(/^there are bananas$/) { raise "no bananas" }
124
+ end
125
+
126
+ it "outputs the json data" do
127
+ expect(load_normalised_json(@out)).to eq MultiJson.load(%{
128
+ [{"id": "banana-party",
129
+ "uri": "spec.feature",
130
+ "keyword": "Feature",
131
+ "name": "Banana party",
132
+ "line": 1,
133
+ "description": "",
134
+ "elements":
135
+ [{"id": "banana-party;monkey-eats-bananas",
136
+ "keyword": "Scenario",
137
+ "name": "Monkey eats bananas",
138
+ "line": 3,
139
+ "description": "",
140
+ "type": "scenario",
141
+ "steps":
142
+ [{"keyword": "Given ",
143
+ "name": "there are bananas",
144
+ "line": 4,
145
+ "match": {"location": "spec/cucumber/formatter/json_spec.rb:123"},
146
+ "result": {"status": "failed",
147
+ "error_message": "no bananas (RuntimeError)\\n./spec/cucumber/formatter/json_spec.rb:123:in `/^there are bananas$/'\\nspec.feature:4:in `Given there are bananas'",
148
+ "duration": 1}}]}]}]})
149
+ end
150
+ end
151
+
152
+ describe "with a scenario with a pending step" do
153
+ define_feature <<-FEATURE
154
+ Feature: Banana party
155
+
156
+ Scenario: Monkey eats bananas
157
+ Given there are bananas
158
+ FEATURE
159
+
160
+ define_steps do
161
+ Given(/^there are bananas$/) { pending }
162
+ end
163
+
164
+ it "outputs the json data" do
165
+ expect(load_normalised_json(@out)).to eq MultiJson.load(%{
166
+ [{"id": "banana-party",
167
+ "uri": "spec.feature",
168
+ "keyword": "Feature",
169
+ "name": "Banana party",
170
+ "line": 1,
171
+ "description": "",
172
+ "elements":
173
+ [{"id": "banana-party;monkey-eats-bananas",
174
+ "keyword": "Scenario",
175
+ "name": "Monkey eats bananas",
176
+ "line": 3,
177
+ "description": "",
178
+ "type": "scenario",
179
+ "steps":
180
+ [{"keyword": "Given ",
181
+ "name": "there are bananas",
182
+ "line": 4,
183
+ "match": {"location": "spec/cucumber/formatter/json_spec.rb:161"},
184
+ "result": {"status": "pending",
185
+ "error_message": "TODO (Cucumber::Pending)\\n./spec/cucumber/formatter/json_spec.rb:161:in `/^there are bananas$/'\\nspec.feature:4:in `Given there are bananas'",
186
+ "duration": 1}}]}]}]})
187
+ end
188
+ end
189
+
190
+ describe "with a scenario outline with one example" do
191
+ define_feature <<-FEATURE
192
+ Feature: Banana party
193
+
194
+ Scenario Outline: Monkey eats bananas
195
+ Given there are <fruit>
196
+
197
+ Examples: Fruit Table
198
+ | fruit |
199
+ | bananas |
200
+ FEATURE
201
+
202
+ define_steps do
203
+ Given(/^there are bananas$/) {}
204
+ end
205
+
206
+ it "outputs the json data" do
207
+ expect(load_normalised_json(@out)).to eq MultiJson.load(%{
208
+ [{"id": "banana-party",
209
+ "uri": "spec.feature",
210
+ "keyword": "Feature",
211
+ "name": "Banana party",
212
+ "line": 1,
213
+ "description": "",
214
+ "elements":
215
+ [{"id": "banana-party;monkey-eats-bananas;fruit-table;2",
216
+ "keyword": "Scenario Outline",
217
+ "name": "Monkey eats bananas",
218
+ "line": 8,
219
+ "description": "",
220
+ "type": "scenario",
221
+ "steps":
222
+ [{"keyword": "Given ",
223
+ "name": "there are bananas",
224
+ "line": 8,
225
+ "match": {"location": "spec/cucumber/formatter/json_spec.rb:203"},
226
+ "result": {"status": "passed",
227
+ "duration": 1}}]}]}]})
228
+ end
229
+ end
230
+
231
+ describe "with tags in the feature file" do
232
+ define_feature <<-FEATURE
233
+ @f
234
+ Feature: Banana party
235
+
236
+ @s
237
+ Scenario: Monkey eats bananas
238
+ Given there are bananas
239
+
240
+ @so
241
+ Scenario Outline: Monkey eats bananas
242
+ Given there are <fruit>
243
+
244
+ @ex
245
+ Examples: Fruit Table
246
+ | fruit |
247
+ | bananas |
248
+ FEATURE
249
+
250
+ define_steps do
251
+ Given(/^there are bananas$/) {}
252
+ end
253
+
254
+ it "the tags are included in the json data" do
255
+ expect(load_normalised_json(@out)).to eq MultiJson.load(%{
256
+ [{"id": "banana-party",
257
+ "uri": "spec.feature",
258
+ "keyword": "Feature",
259
+ "name": "Banana party",
260
+ "line": 2,
261
+ "description": "",
262
+ "tags": [{"name": "@f",
263
+ "line": 1}],
264
+ "elements":
265
+ [{"id": "banana-party;monkey-eats-bananas",
266
+ "keyword": "Scenario",
267
+ "name": "Monkey eats bananas",
268
+ "line": 5,
269
+ "description": "",
270
+ "tags": [{"name": "@f",
271
+ "line": 1},
272
+ {"name": "@s",
273
+ "line": 4}],
274
+ "type": "scenario",
275
+ "steps":
276
+ [{"keyword": "Given ",
277
+ "name": "there are bananas",
278
+ "line": 6,
279
+ "match": {"location": "spec/cucumber/formatter/json_spec.rb:251"},
280
+ "result": {"status": "passed",
281
+ "duration": 1}}]},
282
+ {"id": "banana-party;monkey-eats-bananas;fruit-table;2",
283
+ "keyword": "Scenario Outline",
284
+ "name": "Monkey eats bananas",
285
+ "line": 15,
286
+ "description": "",
287
+ "tags": [{"name": "@f",
288
+ "line": 1},
289
+ {"name": "@so",
290
+ "line": 8},
291
+ {"name": "@ex",
292
+ "line": 12}],
293
+ "type": "scenario",
294
+ "steps":
295
+ [{"keyword": "Given ",
296
+ "name": "there are bananas",
297
+ "line": 15,
298
+ "match": {"location": "spec/cucumber/formatter/json_spec.rb:251"},
299
+ "result": {"status": "passed",
300
+ "duration": 1}}]}]}]})
301
+ end
302
+ end
303
+
304
+ describe "with comments in the feature file" do
305
+ define_feature <<-FEATURE
306
+ #feature comment
307
+ Feature: Banana party
308
+
309
+ #background comment
310
+ Background: There are bananas
311
+ Given there are bananas
312
+
313
+ #scenario comment
314
+ Scenario: Monkey eats bananas
315
+ #step comment1
316
+ Then the monkey eats bananas
317
+
318
+ #scenario outline comment
319
+ Scenario Outline: Monkey eats bananas
320
+ #step comment2
321
+ Then the monkey eats <fruit>
322
+
323
+ #examples table comment
324
+ Examples: Fruit Table
325
+ | fruit |
326
+ #examples table row comment
327
+ | bananas |
328
+ FEATURE
329
+
330
+ define_steps do
331
+ Given(/^there are bananas$/) {}
332
+ Then(/^the monkey eats bananas$/) {}
333
+ end
334
+
335
+ it "the comments are included in the json data" do
336
+ expect(load_normalised_json(@out)).to eq MultiJson.load(%{
337
+ [{"id": "banana-party",
338
+ "uri": "spec.feature",
339
+ "keyword": "Feature",
340
+ "name": "Banana party",
341
+ "line": 2,
342
+ "description": "",
343
+ "comments": [{"value": "#feature comment",
344
+ "line": 1}],
345
+ "elements":
346
+ [{"keyword": "Background",
347
+ "name": "There are bananas",
348
+ "line": 5,
349
+ "description": "",
350
+ "comments": [{"value": "#background comment",
351
+ "line": 4}],
352
+ "type": "background",
353
+ "steps":
354
+ [{"keyword": "Given ",
355
+ "name": "there are bananas",
356
+ "line": 6,
357
+ "match": {"location": "spec/cucumber/formatter/json_spec.rb:331"},
358
+ "result": {"status": "passed",
359
+ "duration": 1}}]},
360
+ {"id": "banana-party;monkey-eats-bananas",
361
+ "keyword": "Scenario",
362
+ "name": "Monkey eats bananas",
363
+ "line": 9,
364
+ "description": "",
365
+ "comments": [{"value": "#scenario comment",
366
+ "line": 8}],
367
+ "type": "scenario",
368
+ "steps":
369
+ [{"keyword": "Then ",
370
+ "name": "the monkey eats bananas",
371
+ "line": 11,
372
+ "comments": [{"value": "#step comment1",
373
+ "line": 10}],
374
+ "match": {"location": "spec/cucumber/formatter/json_spec.rb:332"},
375
+ "result": {"status": "passed",
376
+ "duration": 1}}]},
377
+ {"keyword": "Background",
378
+ "name": "There are bananas",
379
+ "line": 5,
380
+ "description": "",
381
+ "comments": [{"value": "#background comment",
382
+ "line": 4}],
383
+ "type": "background",
384
+ "steps":
385
+ [{"keyword": "Given ",
386
+ "name": "there are bananas",
387
+ "line": 6,
388
+ "match": {"location": "spec/cucumber/formatter/json_spec.rb:331"},
389
+ "result": {"status": "passed",
390
+ "duration": 1}}]},
391
+ {"id": "banana-party;monkey-eats-bananas;fruit-table;2",
392
+ "keyword": "Scenario Outline",
393
+ "name": "Monkey eats bananas",
394
+ "line": 22,
395
+ "description": "",
396
+ "comments": [{"value": "#scenario outline comment",
397
+ "line": 13},
398
+ {"value": "#examples table comment",
399
+ "line": 18},
400
+ {"value": "#examples table row comment",
401
+ "line": 21}],
402
+ "type": "scenario",
403
+ "steps":
404
+ [{"keyword": "Then ",
405
+ "name": "the monkey eats bananas",
406
+ "line": 22,
407
+ "comments": [{"value": "#step comment2",
408
+ "line": 15}],
409
+ "match": {"location": "spec/cucumber/formatter/json_spec.rb:332"},
410
+ "result": {"status": "passed",
411
+ "duration": 1}}]}]}]})
412
+ end
413
+ end
414
+
415
+ describe "with a scenario with a step with a doc string" do
416
+ define_feature <<-FEATURE
417
+ Feature: Banana party
418
+
419
+ Scenario: Monkey eats bananas
420
+ Given there are bananas
421
+ """
422
+ the doc string
423
+ """
424
+ FEATURE
425
+
426
+ define_steps do
427
+ Given(/^there are bananas$/) { |s| s }
428
+ end
429
+
430
+ it "includes the doc string in the json data" do
431
+ expect(load_normalised_json(@out)).to eq MultiJson.load(%{
432
+ [{"id": "banana-party",
433
+ "uri": "spec.feature",
434
+ "keyword": "Feature",
435
+ "name": "Banana party",
436
+ "line": 1,
437
+ "description": "",
438
+ "elements":
439
+ [{"id": "banana-party;monkey-eats-bananas",
440
+ "keyword": "Scenario",
441
+ "name": "Monkey eats bananas",
442
+ "line": 3,
443
+ "description": "",
444
+ "type": "scenario",
445
+ "steps":
446
+ [{"keyword": "Given ",
447
+ "name": "there are bananas",
448
+ "line": 4,
449
+ "doc_string": {"value": "the doc string",
450
+ "content_type": "",
451
+ "line": 5},
452
+ "match": {"location": "spec/cucumber/formatter/json_spec.rb:427"},
453
+ "result": {"status": "passed",
454
+ "duration": 1}}]}]}]})
455
+ end
456
+ end
457
+
458
+ describe "with a scenario with a step that use puts" do
459
+ define_feature <<-FEATURE
460
+ Feature: Banana party
461
+
462
+ Scenario: Monkey eats bananas
463
+ Given there are bananas
464
+ FEATURE
465
+
466
+ define_steps do
467
+ Given(/^there are bananas$/) { puts "from step" }
468
+ end
469
+
470
+ it "includes the output from the step in the json data" do
471
+ expect(load_normalised_json(@out)).to eq MultiJson.load(%{
472
+ [{"id": "banana-party",
473
+ "uri": "spec.feature",
474
+ "keyword": "Feature",
475
+ "name": "Banana party",
476
+ "line": 1,
477
+ "description": "",
478
+ "elements":
479
+ [{"id": "banana-party;monkey-eats-bananas",
480
+ "keyword": "Scenario",
481
+ "name": "Monkey eats bananas",
482
+ "line": 3,
483
+ "description": "",
484
+ "type": "scenario",
485
+ "steps":
486
+ [{"keyword": "Given ",
487
+ "name": "there are bananas",
488
+ "line": 4,
489
+ "output": ["from step"],
490
+ "match": {"location": "spec/cucumber/formatter/json_spec.rb:467"},
491
+ "result": {"status": "passed",
492
+ "duration": 1}}]}]}]})
493
+ end
494
+ end
495
+
496
+ describe "with a background" do
497
+ define_feature <<-FEATURE
498
+ Feature: Banana party
499
+
500
+ Background: There are bananas
501
+ Given there are bananas
502
+
503
+ Scenario: Monkey eats bananas
504
+ Then the monkey eats bananas
505
+
506
+ Scenario: Monkey eats more bananas
507
+ Then the monkey eats more bananas
508
+ FEATURE
509
+
510
+ it "includes the background in the json data each time it is executed" do
511
+ expect(load_normalised_json(@out)).to eq MultiJson.load(%{
512
+ [{"id": "banana-party",
513
+ "uri": "spec.feature",
514
+ "keyword": "Feature",
515
+ "name": "Banana party",
516
+ "line": 1,
517
+ "description": "",
518
+ "elements":
519
+ [{"keyword": "Background",
520
+ "name": "There are bananas",
521
+ "line": 3,
522
+ "description": "",
523
+ "type": "background",
524
+ "steps":
525
+ [{"keyword": "Given ",
526
+ "name": "there are bananas",
527
+ "line": 4,
528
+ "match": {"location": "spec.feature:4"},
529
+ "result": {"status": "undefined"}}]},
530
+ {"id": "banana-party;monkey-eats-bananas",
531
+ "keyword": "Scenario",
532
+ "name": "Monkey eats bananas",
533
+ "line": 6,
534
+ "description": "",
535
+ "type": "scenario",
536
+ "steps":
537
+ [{"keyword": "Then ",
538
+ "name": "the monkey eats bananas",
539
+ "line": 7,
540
+ "match": {"location": "spec.feature:7"},
541
+ "result": {"status": "undefined"}}]},
542
+ {"keyword": "Background",
543
+ "name": "There are bananas",
544
+ "line": 3,
545
+ "description": "",
546
+ "type": "background",
547
+ "steps":
548
+ [{"keyword": "Given ",
549
+ "name": "there are bananas",
550
+ "line": 4,
551
+ "match": {"location": "spec.feature:4"},
552
+ "result": {"status": "undefined"}}]},
553
+ {"id": "banana-party;monkey-eats-more-bananas",
554
+ "keyword": "Scenario",
555
+ "name": "Monkey eats more bananas",
556
+ "line": 9,
557
+ "description": "",
558
+ "type": "scenario",
559
+ "steps":
560
+ [{"keyword": "Then ",
561
+ "name": "the monkey eats more bananas",
562
+ "line": 10,
563
+ "match": {"location": "spec.feature:10"},
564
+ "result": {"status": "undefined"}}]}]}]})
565
+ end
566
+ end
567
+
568
+ describe "with a scenario with a step that embeds data directly" do
569
+ define_feature <<-FEATURE
570
+ Feature: Banana party
571
+
572
+ Scenario: Monkey eats bananas
573
+ Given there are bananas
574
+ FEATURE
575
+
576
+ define_steps do
577
+ Given(/^there are bananas$/) { data = "YWJj"
578
+ embed data, "mime-type;base64" }
579
+ end
580
+
581
+ it "includes the data from the step in the json data" do
582
+ expect(load_normalised_json(@out)).to eq MultiJson.load(%{
583
+ [{"id": "banana-party",
584
+ "uri": "spec.feature",
585
+ "keyword": "Feature",
586
+ "name": "Banana party",
587
+ "line": 1,
588
+ "description": "",
589
+ "elements":
590
+ [{"id": "banana-party;monkey-eats-bananas",
591
+ "keyword": "Scenario",
592
+ "name": "Monkey eats bananas",
593
+ "line": 3,
594
+ "description": "",
595
+ "type": "scenario",
596
+ "steps":
597
+ [{"keyword": "Given ",
598
+ "name": "there are bananas",
599
+ "line": 4,
600
+ "embeddings": [{"mime_type": "mime-type",
601
+ "data": "YWJj"}],
602
+ "match": {"location": "spec/cucumber/formatter/json_spec.rb:577"},
603
+ "result": {"status": "passed",
604
+ "duration": 1}}]}]}]})
605
+ end
606
+ end
607
+
608
+ describe "with a scenario with a step that embeds a file" do
609
+ define_feature <<-FEATURE
610
+ Feature: Banana party
611
+
612
+ Scenario: Monkey eats bananas
613
+ Given there are bananas
614
+ FEATURE
615
+
616
+ define_steps do
617
+ Given(/^there are bananas$/) {
618
+ RSpec::Mocks.allow_message(File, :file?) { true }
619
+ f1 = RSpec::Mocks::Double.new
620
+ RSpec::Mocks.allow_message(File, :open) { |&block| block.call(f1) }
621
+ RSpec::Mocks.allow_message(f1, :read) { "foo" }
622
+ embed('out/snapshot.jpeg', 'image/png')
623
+ }
624
+ end
625
+
626
+ it "includes the file content in the json data" do
627
+ expect(load_normalised_json(@out)).to eq MultiJson.load(%{
628
+ [{"id": "banana-party",
629
+ "uri": "spec.feature",
630
+ "keyword": "Feature",
631
+ "name": "Banana party",
632
+ "line": 1,
633
+ "description": "",
634
+ "elements":
635
+ [{"id": "banana-party;monkey-eats-bananas",
636
+ "keyword": "Scenario",
637
+ "name": "Monkey eats bananas",
638
+ "line": 3,
639
+ "description": "",
640
+ "type": "scenario",
641
+ "steps":
642
+ [{"keyword": "Given ",
643
+ "name": "there are bananas",
644
+ "line": 4,
645
+ "embeddings": [{"mime_type": "image/png",
646
+ "data": "Zm9v"}],
647
+ "match": {"location": "spec/cucumber/formatter/json_spec.rb:617"},
648
+ "result": {"status": "passed",
649
+ "duration": 1}}]}]}]})
650
+ end
651
+ end
652
+
653
+ describe "with a scenario with hooks" do
654
+ define_feature <<-FEATURE
655
+ Feature: Banana party
656
+
657
+ Scenario: Monkey eats bananas
658
+ Given there are bananas
659
+ FEATURE
660
+
661
+ define_steps do
662
+ Before() {}
663
+ Before() {}
664
+ After() {}
665
+ After() {}
666
+ AfterStep() {}
667
+ AfterStep() {}
668
+ Around() { |scenario, block| block.call }
669
+ Given(/^there are bananas$/) {}
670
+ end
671
+
672
+ it "includes all hooks except the around hook in the json data" do
673
+ expect(load_normalised_json(@out)).to eq MultiJson.load(%{
674
+ [{"id": "banana-party",
675
+ "uri": "spec.feature",
676
+ "keyword": "Feature",
677
+ "name": "Banana party",
678
+ "line": 1,
679
+ "description": "",
680
+ "elements":
681
+ [{"id": "banana-party;monkey-eats-bananas",
682
+ "keyword": "Scenario",
683
+ "name": "Monkey eats bananas",
684
+ "line": 3,
685
+ "description": "",
686
+ "type": "scenario",
687
+ "before":
688
+ [{"match": {"location": "spec/cucumber/formatter/json_spec.rb:662"},
689
+ "result": {"status": "passed",
690
+ "duration": 1}},
691
+ {"match": {"location": "spec/cucumber/formatter/json_spec.rb:663"},
692
+ "result": {"status": "passed",
693
+ "duration": 1}}],
694
+ "steps":
695
+ [{"keyword": "Given ",
696
+ "name": "there are bananas",
697
+ "line": 4,
698
+ "match": {"location": "spec/cucumber/formatter/json_spec.rb:669"},
699
+ "result": {"status": "passed",
700
+ "duration": 1},
701
+ "after":
702
+ [{"match": {"location": "spec/cucumber/formatter/json_spec.rb:666"},
703
+ "result": {"status": "passed",
704
+ "duration": 1}},
705
+ {"match": {"location": "spec/cucumber/formatter/json_spec.rb:667"},
706
+ "result": {"status": "passed",
707
+ "duration": 1}}]}],
708
+ "after":
709
+ [{"match": {"location": "spec/cucumber/formatter/json_spec.rb:665"},
710
+ "result": {"status": "passed",
711
+ "duration": 1}},
712
+ {"match": {"location": "spec/cucumber/formatter/json_spec.rb:664"},
713
+ "result": {"status": "passed",
714
+ "duration": 1}}]}]}]})
715
+ end
716
+ end
717
+
718
+ end
719
+
720
+ def load_normalised_json(out)
721
+ normalise_json(MultiJson.load(out.string))
722
+ end
723
+
724
+ def normalise_json(json)
725
+ #make sure duration was captured (should be >= 0)
726
+ #then set it to what is "expected" since duration is dynamic
727
+ json.each do |feature|
728
+ elements = feature.fetch('elements') { [] }
729
+ elements.each do |scenario|
730
+ ['steps', 'before', 'after'].each do |type|
731
+ if scenario[type]
732
+ scenario[type].each do |step_or_hook|
733
+ normalise_json_step_or_hook(step_or_hook)
734
+ if step_or_hook['after']
735
+ step_or_hook['after'].each do |hook|
736
+ normalise_json_step_or_hook(hook)
737
+ end
738
+ end
739
+ end
740
+ end
741
+ end
742
+ end
743
+ end
744
+ end
745
+
746
+ def normalise_json_step_or_hook(step_or_hook)
747
+ if step_or_hook['result']
748
+ if step_or_hook['result']['duration']
749
+ expect(step_or_hook['result']['duration']).to be >= 0
750
+ step_or_hook['result']['duration'] = 1
751
+ end
752
+ end
753
+ end
754
+
755
+ end
756
+ end
757
+ end