|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797 |
- # frozen_string_literal: true
-
- require 'spec_helper'
- require 'cucumber/formatter/spec_helper'
- require 'cucumber/formatter/json'
- require 'cucumber/cli/options'
- require 'json'
-
- module Cucumber
- module Formatter
- describe Json do
- extend SpecHelperDsl
- include SpecHelper
-
- context 'Given a single feature' do
- before(:each) do
- @out = StringIO.new
- @formatter = Json.new(actual_runtime.configuration.with_options(out_stream: @out))
- run_defined_feature
- end
-
- describe 'with a scenario with an undefined step' do
- define_feature <<-FEATURE
- Feature: Banana party
-
- Scenario: Monkey eats bananas
- Given there are bananas
- FEATURE
-
- it 'outputs the json data' do
- expect(load_normalised_json(@out)).to eq JSON.parse(%(
- [{"id": "banana-party",
- "uri": "spec.feature",
- "keyword": "Feature",
- "name": "Banana party",
- "line": 1,
- "description": "",
- "elements":
- [{"id": "banana-party;monkey-eats-bananas",
- "keyword": "Scenario",
- "name": "Monkey eats bananas",
- "line": 3,
- "description": "",
- "type": "scenario",
- "steps":
- [{"keyword": "Given ",
- "name": "there are bananas",
- "line": 4,
- "match": {"location": "spec.feature:4"},
- "result": {"status": "undefined"}}]}]}]))
- end
- end
-
- describe 'with a scenario with a passed step' do
- define_feature <<-FEATURE
- Feature: Banana party
-
- Scenario: Monkey eats bananas
- Given there are bananas
- FEATURE
-
- define_steps do
- Given(/^there are bananas$/) {}
- end
-
- it 'outputs the json data' do
- expect(load_normalised_json(@out)).to eq JSON.parse(%(
- [{"id": "banana-party",
- "uri": "spec.feature",
- "keyword": "Feature",
- "name": "Banana party",
- "line": 1,
- "description": "",
- "elements":
- [{"id": "banana-party;monkey-eats-bananas",
- "keyword": "Scenario",
- "name": "Monkey eats bananas",
- "line": 3,
- "description": "",
- "type": "scenario",
- "steps":
- [{"keyword": "Given ",
- "name": "there are bananas",
- "line": 4,
- "match": {"location": "spec/cucumber/formatter/json_spec.rb:63"},
- "result": {"status": "passed",
- "duration": 1}}]}]}]))
- end
- end
-
- describe 'with a scenario with a failed step' do
- define_feature <<-FEATURE
- Feature: Banana party
-
- Scenario: Monkey eats bananas
- Given there are bananas
- FEATURE
-
- define_steps do
- Given(/^there are bananas$/) { raise 'no bananas' }
- end
-
- it 'outputs the json data' do
- expect(load_normalised_json(@out)).to eq JSON.parse(%{
- [{"id": "banana-party",
- "uri": "spec.feature",
- "keyword": "Feature",
- "name": "Banana party",
- "line": 1,
- "description": "",
- "elements":
- [{"id": "banana-party;monkey-eats-bananas",
- "keyword": "Scenario",
- "name": "Monkey eats bananas",
- "line": 3,
- "description": "",
- "type": "scenario",
- "steps":
- [{"keyword": "Given ",
- "name": "there are bananas",
- "line": 4,
- "match": {"location": "spec/cucumber/formatter/json_spec.rb:100"},
- "result": {"status": "failed",
- "error_message": "no bananas (RuntimeError)\\n./spec/cucumber/formatter/json_spec.rb:100:in `/^there are bananas$/'\\nspec.feature:4:in `there are bananas'",
- "duration": 1}}]}]}]})
- end
- end
-
- describe 'with a scenario with a pending step' do
- define_feature <<-FEATURE
- Feature: Banana party
-
- Scenario: Monkey eats bananas
- Given there are bananas
- FEATURE
-
- define_steps do
- Given(/^there are bananas$/) { pending }
- end
-
- it 'outputs the json data' do
- expect(load_normalised_json(@out)).to eq JSON.parse(%{
- [{"id": "banana-party",
- "uri": "spec.feature",
- "keyword": "Feature",
- "name": "Banana party",
- "line": 1,
- "description": "",
- "elements":
- [{"id": "banana-party;monkey-eats-bananas",
- "keyword": "Scenario",
- "name": "Monkey eats bananas",
- "line": 3,
- "description": "",
- "type": "scenario",
- "steps":
- [{"keyword": "Given ",
- "name": "there are bananas",
- "line": 4,
- "match": {"location": "spec/cucumber/formatter/json_spec.rb:138"},
- "result": {"status": "pending",
- "error_message": "TODO (Cucumber::Pending)\\n./spec/cucumber/formatter/json_spec.rb:138:in `/^there are bananas$/'\\nspec.feature:4:in `there are bananas'",
- "duration": 1}}]}]}]})
- end
- end
-
- describe 'with a scenario outline with one example' do
- define_feature <<-FEATURE
- Feature: Banana party
-
- Scenario Outline: Monkey eats <fruit>
- Given there are <fruit>
-
- Examples: Fruit Table
- | fruit |
- | bananas |
- FEATURE
-
- define_steps do
- Given(/^there are bananas$/) {}
- end
-
- it 'outputs the json data' do
- expect(load_normalised_json(@out)).to eq JSON.parse(%(
- [{"id": "banana-party",
- "uri": "spec.feature",
- "keyword": "Feature",
- "name": "Banana party",
- "line": 1,
- "description": "",
- "elements":
- [{"id": "banana-party;monkey-eats-<fruit>;fruit-table;2",
- "keyword": "Scenario Outline",
- "name": "Monkey eats bananas",
- "line": 8,
- "description": "",
- "type": "scenario",
- "steps":
- [{"keyword": "Given ",
- "name": "there are bananas",
- "line": 4,
- "match": {"location": "spec/cucumber/formatter/json_spec.rb:180"},
- "result": {"status": "passed",
- "duration": 1}}]}]}]))
- end
- end
-
- describe 'with tags in the feature file' do
- define_feature <<-FEATURE
- @f
- Feature: Banana party
-
- @s
- Scenario: Monkey eats bananas
- Given there are bananas
-
- @so
- Scenario Outline: Monkey eats bananas
- Given there are <fruit>
-
- @ex
- Examples: Fruit Table
- | fruit |
- | bananas |
- FEATURE
-
- define_steps do
- Given(/^there are bananas$/) {}
- end
-
- it 'the tags are included in the json data' do
- expect(load_normalised_json(@out)).to eq JSON.parse(%(
- [{"id": "banana-party",
- "uri": "spec.feature",
- "keyword": "Feature",
- "name": "Banana party",
- "line": 2,
- "description": "",
- "tags": [{"name": "@f",
- "line": 1}],
- "elements":
- [{"id": "banana-party;monkey-eats-bananas",
- "keyword": "Scenario",
- "name": "Monkey eats bananas",
- "line": 5,
- "description": "",
- "tags": [{"name": "@f",
- "line": 1},
- {"name": "@s",
- "line": 4}],
- "type": "scenario",
- "steps":
- [{"keyword": "Given ",
- "name": "there are bananas",
- "line": 6,
- "match": {"location": "spec/cucumber/formatter/json_spec.rb:228"},
- "result": {"status": "passed",
- "duration": 1}}]},
- {"id": "banana-party;monkey-eats-bananas;fruit-table;2",
- "keyword": "Scenario Outline",
- "name": "Monkey eats bananas",
- "line": 15,
- "description": "",
- "tags": [{"name": "@f",
- "line": 1},
- {"name": "@so",
- "line": 8},
- {"name": "@ex",
- "line": 12}],
- "type": "scenario",
- "steps":
- [{"keyword": "Given ",
- "name": "there are bananas",
- "line": 10,
- "match": {"location": "spec/cucumber/formatter/json_spec.rb:228"},
- "result": {"status": "passed",
- "duration": 1}}]}]}]))
- end
- end
-
- describe 'with comments in the feature file' do
- define_feature <<-FEATURE
- #feature comment
- Feature: Banana party
-
- #background comment
- Background: There are bananas
- Given there are bananas
-
- #scenario comment
- Scenario: Monkey eats bananas
- #step comment1
- Then the monkey eats bananas
-
- #scenario outline comment
- Scenario Outline: Monkey eats bananas
- #step comment2
- Then the monkey eats <fruit>
-
- #examples table comment
- Examples: Fruit Table
- | fruit |
- #examples table row comment
- | bananas |
- FEATURE
-
- define_steps do
- Given(/^there are bananas$/) {}
- Then(/^the monkey eats bananas$/) {}
- end
-
- it 'the comments are not included in the json data' do
- expect(load_normalised_json(@out)).to eq JSON.parse(%(
- [{"id": "banana-party",
- "uri": "spec.feature",
- "keyword": "Feature",
- "name": "Banana party",
- "line": 2,
- "description": "",
- "elements":
- [{"keyword": "Background",
- "name": "There are bananas",
- "line": 5,
- "description": "",
- "type": "background",
- "steps":
- [{"keyword": "Given ",
- "name": "there are bananas",
- "line": 6,
- "match": {"location": "spec/cucumber/formatter/json_spec.rb:308"},
- "result": {"status": "passed",
- "duration": 1}}]},
- {"id": "banana-party;monkey-eats-bananas",
- "keyword": "Scenario",
- "name": "Monkey eats bananas",
- "line": 9,
- "description": "",
- "type": "scenario",
- "steps":
- [{"keyword": "Then ",
- "name": "the monkey eats bananas",
- "line": 11,
- "match": {"location": "spec/cucumber/formatter/json_spec.rb:309"},
- "result": {"status": "passed",
- "duration": 1}}]},
- {"keyword": "Background",
- "name": "There are bananas",
- "line": 5,
- "description": "",
- "type": "background",
- "steps":
- [{"keyword": "Given ",
- "name": "there are bananas",
- "line": 6,
- "match": {"location": "spec/cucumber/formatter/json_spec.rb:308"},
- "result": {"status": "passed",
- "duration": 1}}]},
- {"id": "banana-party;monkey-eats-bananas;fruit-table;2",
- "keyword": "Scenario Outline",
- "name": "Monkey eats bananas",
- "line": 22,
- "description": "",
- "type": "scenario",
- "steps":
- [{"keyword": "Then ",
- "name": "the monkey eats bananas",
- "line": 16,
- "match": {"location": "spec/cucumber/formatter/json_spec.rb:309"},
- "result": {"status": "passed",
- "duration": 1}}]}]}]))
- end
- end
-
- describe 'with a scenario with a step with a doc string' do
- define_feature <<-FEATURE
- Feature: Banana party
-
- Scenario: Monkey eats bananas
- Given there are bananas
- """
- the doc string
- """
- FEATURE
-
- define_steps do
- Given(/^there are bananas$/) { |s| s }
- end
-
- it 'includes the doc string in the json data' do
- expect(load_normalised_json(@out)).to eq JSON.parse(%(
- [{"id": "banana-party",
- "uri": "spec.feature",
- "keyword": "Feature",
- "name": "Banana party",
- "line": 1,
- "description": "",
- "elements":
- [{"id": "banana-party;monkey-eats-bananas",
- "keyword": "Scenario",
- "name": "Monkey eats bananas",
- "line": 3,
- "description": "",
- "type": "scenario",
- "steps":
- [{"keyword": "Given ",
- "name": "there are bananas",
- "line": 4,
- "doc_string": {"value": "the doc string",
- "content_type": "",
- "line": 5},
- "match": {"location": "spec/cucumber/formatter/json_spec.rb:386"},
- "result": {"status": "passed",
- "duration": 1}}]}]}]))
- end
- end
-
- describe 'with a scenario with a step that use puts' do
- define_feature <<-FEATURE
- Feature: Banana party
-
- Scenario: Monkey eats bananas
- Given there are bananas
- FEATURE
-
- define_steps do
- Given(/^there are bananas$/) { log 'from step' }
- end
-
- it 'includes the output from the step in the json data' do
- expect(load_normalised_json(@out)).to eq JSON.parse(%(
- [{"id": "banana-party",
- "uri": "spec.feature",
- "keyword": "Feature",
- "name": "Banana party",
- "line": 1,
- "description": "",
- "elements":
- [{"id": "banana-party;monkey-eats-bananas",
- "keyword": "Scenario",
- "name": "Monkey eats bananas",
- "line": 3,
- "description": "",
- "type": "scenario",
- "steps":
- [{"keyword": "Given ",
- "name": "there are bananas",
- "line": 4,
- "output": ["from step"],
- "match": {"location": "spec/cucumber/formatter/json_spec.rb:426"},
- "result": {"status": "passed",
- "duration": 1}}]}]}]))
- end
- end
-
- describe 'with a background' do
- define_feature <<-FEATURE
- Feature: Banana party
-
- Background: There are bananas
- Given there are bananas
-
- Scenario: Monkey eats bananas
- Then the monkey eats bananas
-
- Scenario: Monkey eats more bananas
- Then the monkey eats more bananas
- FEATURE
-
- it 'includes the background in the json data each time it is executed' do
- expect(load_normalised_json(@out)).to eq JSON.parse(%(
- [{"id": "banana-party",
- "uri": "spec.feature",
- "keyword": "Feature",
- "name": "Banana party",
- "line": 1,
- "description": "",
- "elements":
- [{"keyword": "Background",
- "name": "There are bananas",
- "line": 3,
- "description": "",
- "type": "background",
- "steps":
- [{"keyword": "Given ",
- "name": "there are bananas",
- "line": 4,
- "match": {"location": "spec.feature:4"},
- "result": {"status": "undefined"}}]},
- {"id": "banana-party;monkey-eats-bananas",
- "keyword": "Scenario",
- "name": "Monkey eats bananas",
- "line": 6,
- "description": "",
- "type": "scenario",
- "steps":
- [{"keyword": "Then ",
- "name": "the monkey eats bananas",
- "line": 7,
- "match": {"location": "spec.feature:7"},
- "result": {"status": "undefined"}}]},
- {"keyword": "Background",
- "name": "There are bananas",
- "line": 3,
- "description": "",
- "type": "background",
- "steps":
- [{"keyword": "Given ",
- "name": "there are bananas",
- "line": 4,
- "match": {"location": "spec.feature:4"},
- "result": {"status": "undefined"}}]},
- {"id": "banana-party;monkey-eats-more-bananas",
- "keyword": "Scenario",
- "name": "Monkey eats more bananas",
- "line": 9,
- "description": "",
- "type": "scenario",
- "steps":
- [{"keyword": "Then ",
- "name": "the monkey eats more bananas",
- "line": 10,
- "match": {"location": "spec.feature:10"},
- "result": {"status": "undefined"}}]}]}]))
- end
- end
-
- describe 'with a scenario with a step that embeds data directly' do
- define_feature <<-FEATURE
- Feature: Banana party
-
- Scenario: Monkey eats bananas
- Given there are bananas
- FEATURE
-
- define_steps do
- Given(/^there are bananas$/) { attach('YWJj', 'mime-type;base64') }
- end
-
- it 'includes the data from the step in the json data' do
- expect(load_normalised_json(@out)).to eq JSON.parse(%(
- [{"id": "banana-party",
- "uri": "spec.feature",
- "keyword": "Feature",
- "name": "Banana party",
- "line": 1,
- "description": "",
- "elements":
- [{"id": "banana-party;monkey-eats-bananas",
- "keyword": "Scenario",
- "name": "Monkey eats bananas",
- "line": 3,
- "description": "",
- "type": "scenario",
- "steps":
- [{"keyword": "Given ",
- "name": "there are bananas",
- "line": 4,
- "embeddings": [{"mime_type": "mime-type",
- "data": "YWJj"}],
- "match": {"location": "spec/cucumber/formatter/json_spec.rb:536"},
- "result": {"status": "passed",
- "duration": 1}}]}]}]))
- end
- end
-
- describe 'with a scenario with a step that embeds a file' do
- define_feature <<-FEATURE
- Feature: Banana party
-
- Scenario: Monkey eats bananas
- Given there are bananas
- FEATURE
-
- define_steps do
- Given(/^there are bananas$/) do
- RSpec::Mocks.allow_message(File, :file?) { true }
- RSpec::Mocks.allow_message(File, :read) { 'foo' }
- attach('out/snapshot.jpeg', 'image/png')
- end
- end
-
- it 'includes the file content in the json data' do
- expect(load_normalised_json(@out)).to eq JSON.parse(%(
- [{"id": "banana-party",
- "uri": "spec.feature",
- "keyword": "Feature",
- "name": "Banana party",
- "line": 1,
- "description": "",
- "elements":
- [{"id": "banana-party;monkey-eats-bananas",
- "keyword": "Scenario",
- "name": "Monkey eats bananas",
- "line": 3,
- "description": "",
- "type": "scenario",
- "steps":
- [{"keyword": "Given ",
- "name": "there are bananas",
- "line": 4,
- "embeddings": [{"mime_type": "image/png",
- "data": "Zm9v"}],
- "match": {"location": "spec/cucumber/formatter/json_spec.rb:575"},
- "result": {"status": "passed",
- "duration": 1}}]}]}]))
- end
- end
-
- describe 'with a scenario with hooks' do
- define_feature <<-FEATURE
- Feature: Banana party
-
- Scenario: Monkey eats bananas
- Given there are bananas
- FEATURE
-
- define_steps do
- Before() {}
- Before() {}
- After() {}
- After() {}
- AfterStep() {}
- AfterStep() {}
- Around() { |_scenario, block| block.call }
- Given(/^there are bananas$/) {}
- end
-
- it 'includes all hooks except the around hook in the json data' do
- expect(load_normalised_json(@out)).to eq JSON.parse(%(
- [{"id": "banana-party",
- "uri": "spec.feature",
- "keyword": "Feature",
- "name": "Banana party",
- "line": 1,
- "description": "",
- "elements":
- [{"id": "banana-party;monkey-eats-bananas",
- "keyword": "Scenario",
- "name": "Monkey eats bananas",
- "line": 3,
- "description": "",
- "type": "scenario",
- "before":
- [{"match": {"location": "spec/cucumber/formatter/json_spec.rb:618"},
- "result": {"status": "passed",
- "duration": 1}},
- {"match": {"location": "spec/cucumber/formatter/json_spec.rb:619"},
- "result": {"status": "passed",
- "duration": 1}}],
- "steps":
- [{"keyword": "Given ",
- "name": "there are bananas",
- "line": 4,
- "match": {"location": "spec/cucumber/formatter/json_spec.rb:625"},
- "result": {"status": "passed",
- "duration": 1},
- "after":
- [{"match": {"location": "spec/cucumber/formatter/json_spec.rb:622"},
- "result": {"status": "passed",
- "duration": 1}},
- {"match": {"location": "spec/cucumber/formatter/json_spec.rb:623"},
- "result": {"status": "passed",
- "duration": 1}}]}],
- "after":
- [{"match": {"location": "spec/cucumber/formatter/json_spec.rb:621"},
- "result": {"status": "passed",
- "duration": 1}},
- {"match": {"location": "spec/cucumber/formatter/json_spec.rb:620"},
- "result": {"status": "passed",
- "duration": 1}}]}]}]))
- end
- end
-
- describe 'with a scenario when only an around hook is failing' do
- define_feature <<-FEATURE
- Feature: Banana party
-
- Scenario: Monkey eats bananas
- Given there are bananas
- FEATURE
-
- define_steps do
- Around() do |_scenario, block|
- block.call
- raise 'error'
- end
- Given(/^there are bananas$/) {}
- end
-
- it 'includes the around hook result in the json data' do
- expect(load_normalised_json(@out)).to eq JSON.parse(%{
- [{"id": "banana-party",
- "uri": "spec.feature",
- "keyword": "Feature",
- "name": "Banana party",
- "line": 1,
- "description": "",
- "elements":
- [{"id": "banana-party;monkey-eats-bananas",
- "keyword": "Scenario",
- "name": "Monkey eats bananas",
- "line": 3,
- "description": "",
- "type": "scenario",
- "steps":
- [{"keyword": "Given ",
- "name": "there are bananas",
- "line": 4,
- "match": {"location": "spec/cucumber/formatter/json_spec.rb:687"},
- "result": {"status": "passed",
- "duration": 1}}],
- "around":
- [{"match": {"location": "unknown_hook_location:1"},
- "result": {"status": "failed",
- "error_message": "error (RuntimeError)\\n./spec/cucumber/formatter/json_spec.rb:685:in `Around'",
- "duration": 1}}]}]}]})
- end
- end
-
- describe 'with a scenario with a step with a data table' do
- define_feature <<-FEATURE
- Feature: Banana party
-
- Scenario: Monkey eats bananas
- Given there are bananas
- | aa | bb |
- | cc | dd |
- FEATURE
-
- define_steps do
- Given(/^there are bananas$/) { |s| s }
- end
-
- it 'includes the doc string in the json data' do
- expect(load_normalised_json(@out)).to eq JSON.parse(%(
- [{"id": "banana-party",
- "uri": "spec.feature",
- "keyword": "Feature",
- "name": "Banana party",
- "line": 1,
- "description": "",
- "elements":
- [{"id": "banana-party;monkey-eats-bananas",
- "keyword": "Scenario",
- "name": "Monkey eats bananas",
- "line": 3,
- "description": "",
- "type": "scenario",
- "steps":
- [{"keyword": "Given ",
- "name": "there are bananas",
- "line": 4,
- "rows":
- [{"cells": ["aa", "bb"]},
- {"cells": ["cc", "dd"]}],
- "match": {"location": "spec/cucumber/formatter/json_spec.rb:731"},
- "result": {"status": "passed",
- "duration": 1}}]}]}]))
- end
- end
- end
-
- def load_normalised_json(out)
- normalise_json(JSON.parse(out.string))
- end
-
- def normalise_json(json)
- # make sure duration was captured (should be >= 0)
- # then set it to what is "expected" since duration is dynamic
- json.each do |feature|
- elements = feature.fetch('elements') { [] }
- elements.each do |scenario|
- %w[steps before after around].each do |type|
- next unless scenario[type]
-
- scenario[type].each do |step_or_hook|
- normalise_json_step_or_hook(step_or_hook)
- next unless step_or_hook['after']
-
- step_or_hook['after'].each do |hook|
- normalise_json_step_or_hook(hook)
- end
- end
- end
- end
- end
- end
-
- def normalise_json_step_or_hook(step_or_hook)
- return unless step_or_hook['result'] && step_or_hook['result']['duration']
-
- expect(step_or_hook['result']['duration']).to be >= 0
- step_or_hook['result']['duration'] = 1
- end
- end
- end
- end
|