Skip to content

Commit e9851b5

Browse files
committed
Fix failure screenshots on Rails 7.1
1 parent 51e3cdc commit e9851b5

File tree

2 files changed

+93
-0
lines changed

2 files changed

+93
-0
lines changed

lib/rspec/rails/example/system_example_group.rb

+46
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,52 @@ def method_name
4444
].join("_").tr(CHARS_TO_TRANSLATE.join, "_").byteslice(0...200).scrub("") + "_#{rand(1000)}"
4545
end
4646

47+
if ::Rails::VERSION::STRING.to_f >= 7.1
48+
# @private
49+
# Allows failure screenshot to work whilst not exposing metadata
50+
class SuppressRailsScreenshotMetadata
51+
def initialize
52+
@example_data = {}
53+
end
54+
55+
def [](key)
56+
if @example_data.key?(key)
57+
@example_data[key]
58+
else
59+
raise_wrong_scope_error
60+
end
61+
end
62+
63+
def []=(key, value)
64+
if key == :failure_screenshot_path
65+
@example_data[key] = value
66+
else
67+
raise_wrong_scope_error
68+
end
69+
end
70+
71+
def method_missing(_name, *_args, &_block)
72+
raise_wrong_scope_error
73+
end
74+
75+
private
76+
77+
def raise_wrong_scope_error
78+
raise RSpec::Core::ExampleGroup::WrongScopeError,
79+
"`metadata` is not available from within an example " \
80+
"(e.g. an `it` block) or from constructs that run in the " \
81+
"scope of an example (e.g. `before`, `let`, etc). It is " \
82+
"only available on an example group (e.g. a `describe` or "\
83+
"`context` block)"
84+
end
85+
end
86+
87+
# @private
88+
def metadata
89+
@metadata ||= SuppressRailsScreenshotMetadata.new
90+
end
91+
end
92+
4793
# Delegates to `Rails.application`.
4894
def app
4995
::Rails.application

spec/rspec/rails/example/system_example_group_spec.rb

+47
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,53 @@ def take_screenshot
9292
end
9393
end
9494

95+
describe '#take_screenshot', if: ::Rails::VERSION::STRING.to_f >= 7.1 do
96+
it 'handles Rails calling metadata' do
97+
allow(Capybara::Session).to receive(:instance_created?).and_return(true)
98+
group = RSpec::Core::ExampleGroup.describe do
99+
include SystemExampleGroup
100+
101+
before do
102+
driven_by(:selenium)
103+
end
104+
105+
def page
106+
instance_double(Capybara::Session, save_screenshot: nil)
107+
end
108+
end
109+
example = group.it('fails') { raise }
110+
group.run
111+
112+
expect(example.metadata[:execution_result].exception).to be_a RuntimeError
113+
end
114+
end
115+
116+
describe '#metadata', if: ::Rails::VERSION::STRING.to_f >= 7.1 do
117+
let(:group) do
118+
RSpec::Core::ExampleGroup.describe do
119+
include SystemExampleGroup
120+
end
121+
end
122+
123+
it 'fakes out the rails expected method' do
124+
example = group.it('does nothing') {
125+
metadata[:failure_screenshot_path] = :value
126+
expect(metadata[:failure_screenshot_path]).to eq(:value)
127+
}
128+
group.run
129+
expect(example.execution_result.status).to eq :passed
130+
end
131+
132+
it 'still raises correctly if you use it for something else' do
133+
examples = []
134+
examples << group.it('fails nothing') { metadata[:other] = :value }
135+
examples << group.it('fails nothing') { metadata[:other] }
136+
examples << group.it('fails nothing') { metadata.key?(:any) }
137+
group.run
138+
expect(examples.map(&:execution_result)).to all have_attributes status: :failed
139+
end
140+
end
141+
95142
describe "hook order" do
96143
it 'calls Capybara.reset_sessions (TestUnit after_teardown) after any after hooks' do
97144
calls_in_order = []

0 commit comments

Comments
 (0)