"Execution context was destroyed, most likely because of a navigation" when using `expect(page).to have_content` or `have_selector`
dtinth opened this issue · 8 comments
A common pattern in testing is to do this:
click_on 'Confirm'
expect(page).to have_content "Thank you"
However, page
sometimes refers to the previous page. This resulted in an error like this:
Playwright::Error:
Error: Execution context was destroyed, most likely because of a navigation
This is my current ugly workaround. I monkeypatched Capybara::Session
to retry assert_text
3 times:
module Capybara::Session::PlaywrightSessionHasContentHack
def assert_text(*args, **options)
attempt = 0
loop do |i|
sleep 1 if attempt > 0
attempt += 1
begin
return super
rescue => e
raise e if attempt > 3
next if e.message.include?("Execution context was destroyed")
next if e.message.include?("Cannot find context with specified id")
raise e
end
end
end
end
Capybara::Session.prepend(Capybara::Session::PlaywrightSessionHasContentHack)
Improved workaround that works with have_selectors
too
# Monkey-patch Capybara::Session#has_content? to automatically retry
# when the page changes in the middle of the check.
#
# See: https://github.com/YusukeIwaki/capybara-playwright-driver/issues/51
#
module Capybara::Session::PlaywrightSessionHasContentHack
def assert_text(*args, **options)
retry_if_execution_context_destroyed do
super
end
end
def assert_no_text(*args, **options)
retry_if_execution_context_destroyed do
super
end
end
def assert_selector(*args, **options)
retry_if_execution_context_destroyed do
super
end
end
def assert_no_selector(*args, **options)
retry_if_execution_context_destroyed do
super
end
end
def retry_if_execution_context_destroyed
attempt = 0
loop do |i|
sleep 1 if attempt > 0
attempt += 1
begin
return yield
rescue => e
raise e if attempt > 3
next if e.message.include?("Execution context was destroyed")
next if e.message.include?("Cannot find context with specified id")
next if e.message.include?("Unable to adopt element handle from a different document")
raise e
end
end
end
end
Capybara::Session.prepend(Capybara::Session::PlaywrightSessionHasContentHack)
@dtinth Thank you for bug report. Do you have a code for reproducing this issue?
I don’t have a repro yet. I’ll try to create one once I recover from covid.
Stay safe.
I’m feeling a bit better (and bored) so here’s a repro.
https://github.com/dtinth/capybara-playwright-driver-issue-51-repro
I’ve added multiple layers of redirects because the error happens intermittently, and with different error messages at different times.
@YusukeIwaki Thank you for the fix! 🙏 Looking forward to the new release 😃
v0.3.1 is deployed.
https://rubygems.org/gems/capybara-playwright-driver/versions/0.3.1
Could you try it? Thank you, and sorry for late fix.
v0.3.2 is also deployed, which just includes the fix of shadow_root
method.
@YusukeIwaki I have tried it (removed the monkey-patch workaround and bumped version), and it works perfectly. Thank you so much for building and maintaining this project 🙏.