# frozen_string_literal: true require 'spec_helper' require 'cucumber/formatter/spec_helper' require 'cucumber/formatter/html' require 'nokogiri' require 'cucumber/glue/registry_and_more' require 'rspec/mocks' module Cucumber module Formatter describe Html do extend SpecHelperDsl include SpecHelper RSpec::Matchers.define :have_css_node do |css, regexp| match do |doc| nodes = doc.css(css) nodes.detect{ |node| node.text =~ regexp } end end before(:each) do @out = StringIO.new @formatter = Html.new(runtime, @out, {}) end it 'does not raise an error when visiting a blank feature name' do expect(-> { @formatter.feature_name('Feature', '') }).not_to raise_error end describe 'when writing the report to a file' do before(:each) do allow(@out).to receive(:respond_to?).with(:path).and_return(true) expect(@out).to receive(:path).and_return('out/file.html') run_defined_feature @doc = Nokogiri.HTML(@out.string) end describe 'with a step that embeds a snapshot' do define_steps do Given(/snap/) { RSpec::Mocks.allow_message(File, :file?) { true } embed('out/snapshot.jpeg', 'image/jpeg') } end define_feature(<<-FEATURE) Feature: Scenario: Given snap FEATURE it 'converts the snapshot path to a relative path' do expect(@doc.css('.embed img').first.attributes['src'].to_s).to eq 'snapshot.jpeg' end end end describe 'given a single feature' do before(:each) do run_defined_feature @doc = Nokogiri.HTML(@out.string) end describe 'basic feature' do define_feature <<-FEATURE Feature: Bananas In order to find my inner monkey As a human I must eat bananas FEATURE it 'should output a main container div' do expect(@out.string).to match(/\
# Healthy}) end end describe 'with a comment at scenario level' do define_feature <<-FEATURE Feature: Foo # Healthy Scenario Scenario: Given passing FEATURE it { expect(@doc).to have_css_node('.scenario .comment', /Healthy Scenario/) } end describe 'with a tag' do define_feature <<-FEATURE @foo Feature: can't have standalone tag :) Scenario: Given passing FEATURE it { expect(@doc).to have_css_node('.feature .tag', /foo/) } end describe 'with a narrative' do define_feature <<-FEATURE Feature: Bananas In order to find my inner monkey As a human I must eat bananas Scenario: Given passing FEATURE it { expect(@doc).to have_css_node('.feature h2', /Bananas/) } it { expect(@doc).to have_css_node('.feature .narrative', /must eat bananas/) } end describe 'with a background' do define_feature <<-FEATURE Feature: Bananas Background: Given there are bananas Scenario: When the monkey eats a banana FEATURE it { expect(@doc).to have_css_node('.feature .background', /there are bananas/) } end describe 'with a scenario' do define_feature <<-FEATURE Feature: Banana party Scenario: Monkey eats banana Given there are bananas FEATURE it { expect(@doc).to have_css_node('.feature h3', /Monkey eats banana/) } it { expect(@doc).to have_css_node('.feature .scenario .step', /there are bananas/) } end describe 'with a scenario outline' do define_feature <<-FEATURE Feature: Fud Pyramid Scenario Outline: Monkey eats a balanced diet Given there are
}m) expect(html_str).to match(%r{}m) end end describe 'with a step that fails in the background' do define_steps do Given(/boo/) { raise 'eek' } end define_feature(<<-FEATURE) Feature: shouting Background: Given boo Scenario: Given yay FEATURE it { expect(@doc).to have_css_node('.feature .background .step.failed', /eek/) } it { expect(@out.string).not_to include('makeRed(\'scenario_0\')') } it { expect(@out.string).to include('makeRed(\'background_0\')') } it { expect(@doc).not_to have_css_node('.feature .scenario .step.failed', //) } it { expect(@doc).to have_css_node('.feature .scenario .step.undefined', /yay/) } it { expect(@doc).to have_css_node('.feature .background .backtrace', //) } it { expect(@doc).not_to have_css_node('.feature .scenario .backtrace', //) } end context 'with a before hook that fails' do describe 'in a scenario' do define_steps do Before { raise 'eek' } Given(/yay/) {} end define_feature(<<-FEATURE) Feature: shouting Scenario: Given yay FEATURE it { expect(@out.string).to include('makeRed(\'scenario_1\')') } it { expect(@doc).not_to have_css_node('.feature .scenario .step.failed', //) } it { expect(@doc).to have_css_node('.feature .scenario .step.skipped', /yay/) } end describe 'in a scenario outline' do define_steps do Before { raise 'eek' } Given(/yay/) {} end define_feature(<<-FEATURE) Feature: shouting Scenario Outline: GivenExamples: | step | | yay | FEATURE it { expect(@out.string).to include('makeRed(\'scenario_1\')') } it { expect(@doc).not_to have_css_node('.feature .scenario .step.failed', //) } it { expect(@doc).to have_css_node('.feature .scenario .step.skipped', /yay/) } end end describe 'with a step that embeds a snapshot' do define_steps do Given(/snap/) { RSpec::Mocks.allow_message(File, :file?) { true } embed('snapshot.jpeg', 'image/jpeg') } end define_feature(<<-FEATURE) Feature: Scenario: Given snap FEATURE it { expect(@doc.css('.embed img').first.attributes['src'].to_s).to eq 'snapshot.jpeg' } end describe 'with a step that embeds a text' do define_steps do Given(/log/) { embed('log.txt', 'text/plain', 'foo') } end define_feature(<<-FEATURE) Feature: Scenario: Given log FEATURE it { expect(@doc.at('a#text_0')['href'].to_s).to eq 'log.txt' } end describe 'with a step that embeds a snapshot content manually' do define_steps do Given(/snap/) { embed('data:image/png;base64,YWJj', 'image/png') } end define_feature(<<-FEATURE) Feature: Scenario: Given snap FEATURE it { expect(@doc.css('.embed img').first.attributes['src'].to_s).to eq 'data:image/png;base64,YWJj' } end describe 'with a step that embeds a snapshot content' do define_steps do Given(/snap/) { embed('YWJj', 'image/png;base64') } end define_feature(<<-FEATURE) Feature: Scenario: Given snap FEATURE it { expect(@doc.css('.embed img').first.attributes['src'].to_s).to eq 'data:image/png;base64,YWJj' } end describe 'with an undefined Given step then an undefined And step' do define_feature(<<-FEATURE) Feature: Scenario: Given some undefined step And another undefined step FEATURE it { expect(@doc.css('pre').map { |pre| /^(Given|And)/.match(pre.text)[1] }).to eq %w(Given Given) } end describe 'with an undefined When step then an undefined And step' do define_feature(<<-FEATURE) Feature: Scenario: Given some undefined step When a different undefined step And another undefined step FEATURE it { expect(@doc.css('pre').map { |pre| /^(Given|When|And)/.match(pre.text)[1] }).to eq %w(Given When When) } end describe 'with an passing Then step and an undefined And step' do define_feature <<-FEATURE Feature: Scenario: Given this step passes Then this step passes And this step is undefined FEATURE define_steps do Given(/^this step passes$/) {} end it { expect(@doc.css('pre').map { |pre| /^(Given|Then)/.match(pre.text)[1] }).to eq ['Then'] } end describe 'with a output from hooks' do describe 'in a scenario' do define_feature <<-FEATURE Feature: Scenario: Given this step passes FEATURE define_steps do Before do puts 'Before hook' end AfterStep do puts 'AfterStep hook' end After do puts 'After hook' end Given(/^this step passes$/) {} end it 'should have ccs nodes ".step.message" for all the hooks' do expect(@doc.css('.step.message').length).to eq 3 expect(@doc.css('.step.message')[0].text).to eq 'Before hook' expect(@doc.css('.step.message')[1].text).to eq 'AfterStep hook' expect(@doc.css('.step.message')[2].text).to eq 'After hook' end end describe 'in a scenario outline' do define_feature <<-FEATURE Feature: Scenario Outline: Given this step Examples: | status | | passes | FEATURE define_steps do Before do puts 'Before hook' end AfterStep do puts 'AfterStep hook' end After do puts 'After hook' end Given(/^this step passes$/) {} end it { expect(@doc).to have_css_node('.message', /Before hook, AfterStep hook, After hook/) } end end end context 'in --expand mode' do let(:options) { { expand: true } } before(:each) do @out = StringIO.new @formatter = Html.new(runtime, @out, {:expand => true}) run_defined_feature @doc = Nokogiri.HTML(@out.string) end describe 'with undefined * steps in a Scenario Outline' do define_feature <<-FEATURE Feature: Scenario Outline: * this step is Then this step passes Examples: | status | | undefined | | undefined | FEATURE define_steps do Given(/^this step passes$/) {} end it { expect(@doc.css('pre').map { |pre| /^(Given|Then|When)/.match(pre.text)[1] }).to eq %w(Given Given) } end describe 'with a scenario outline and a before hook that fails' do define_steps do Before { raise 'eek' } Given(/yay/) {} end define_feature(<<-FEATURE) Feature: shouting Scenario Outline: Given Examples: | step | | yay | FEATURE it { expect(@out.string).to include('makeRed(\'scenario_1\')') } it { expect(@out.string).to include('makeRed(\'scenario_1_1\')') } it { expect(@doc).not_to have_css_node('.feature .scenario .step.failed', //) } it { expect(@doc).to have_css_node('.feature .scenario .step.skipped', /yay/) } end end end end end