Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix failure screenshots on Rails 7.1 #2704

Merged
merged 1 commit into from Nov 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
46 changes: 46 additions & 0 deletions lib/rspec/rails/example/system_example_group.rb
Expand Up @@ -44,6 +44,52 @@ def method_name
].join("_").tr(CHARS_TO_TRANSLATE.join, "_").byteslice(0...200).scrub("") + "_#{rand(1000)}"
end

if ::Rails::VERSION::STRING.to_f >= 7.1
# @private
# Allows failure screenshot to work whilst not exposing metadata
class SuppressRailsScreenshotMetadata
def initialize
@example_data = {}
end

def [](key)
if @example_data.key?(key)
@example_data[key]
else
raise_wrong_scope_error
end
end

def []=(key, value)
if key == :failure_screenshot_path
@example_data[key] = value
else
raise_wrong_scope_error
end
end

def method_missing(_name, *_args, &_block)
raise_wrong_scope_error
end

private

def raise_wrong_scope_error
raise RSpec::Core::ExampleGroup::WrongScopeError,
"`metadata` is not available from within an example " \
"(e.g. an `it` block) or from constructs that run in the " \
"scope of an example (e.g. `before`, `let`, etc). It is " \
"only available on an example group (e.g. a `describe` or "\
"`context` block)"
end
end

# @private
def metadata
@metadata ||= SuppressRailsScreenshotMetadata.new
end
end

# Delegates to `Rails.application`.
def app
::Rails.application
Expand Down
47 changes: 47 additions & 0 deletions spec/rspec/rails/example/system_example_group_spec.rb
Expand Up @@ -92,6 +92,53 @@ def take_screenshot
end
end

describe '#take_screenshot', if: ::Rails::VERSION::STRING.to_f >= 7.1 do
it 'handles Rails calling metadata' do
allow(Capybara::Session).to receive(:instance_created?).and_return(true)
group = RSpec::Core::ExampleGroup.describe do
include SystemExampleGroup

before do
driven_by(:selenium)
end

def page
instance_double(Capybara::Session, save_screenshot: nil)
end
end
example = group.it('fails') { raise }
group.run

expect(example.metadata[:execution_result].exception).to be_a RuntimeError
end
end

describe '#metadata', if: ::Rails::VERSION::STRING.to_f >= 7.1 do
let(:group) do
RSpec::Core::ExampleGroup.describe do
include SystemExampleGroup
end
end

it 'fakes out the rails expected method' do
example = group.it('does nothing') {
metadata[:failure_screenshot_path] = :value
expect(metadata[:failure_screenshot_path]).to eq(:value)
}
group.run
expect(example.execution_result.status).to eq :passed
end

it 'still raises correctly if you use it for something else' do
examples = []
examples << group.it('fails nothing') { metadata[:other] = :value }
examples << group.it('fails nothing') { metadata[:other] }
examples << group.it('fails nothing') { metadata.key?(:any) }
group.run
expect(examples.map(&:execution_result)).to all have_attributes status: :failed
end
end

describe "hook order" do
it 'calls Capybara.reset_sessions (TestUnit after_teardown) after any after hooks' do
calls_in_order = []
Expand Down