Skip to content

Commit d914b5e

Browse files
authored
Merge pull request #24629 from opf/fix/selenium-rack-session-login-flake
Retry rack session login on stale inspector node
2 parents a280390 + 381fa85 commit d914b5e

1 file changed

Lines changed: 26 additions & 1 deletion

File tree

spec/support/authentication_helpers.rb

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#++
3030

3131
require "rack_session_access/capybara"
32+
require "retriable"
3233

3334
module AuthenticationHelpers
3435
def self.included(base)
@@ -47,7 +48,7 @@ def login_as(user)
4748
session_value_for(user).to_s
4849
)
4950
else
50-
page.set_rack_session(session_value_for(user))
51+
set_rack_session_with_retry(session_value_for(user))
5152
end
5253
end
5354

@@ -86,8 +87,32 @@ def logout
8687
allow(RequestStore).to receive(:[]).and_call_original
8788
end
8889

90+
# Chrome reports a node that went stale mid-command as an unhandled
91+
# inspector error, which selenium-webdriver surfaces as UnknownError
92+
# rather than StaleElementReferenceError, so Capybara's synchronize
93+
# does not retry it.
94+
STALE_PAGE_ERRORS = {
95+
Selenium::WebDriver::Error::StaleElementReferenceError => nil,
96+
Selenium::WebDriver::Error::UnknownError => /Node with given id does not belong to the document/
97+
}.freeze
98+
private_constant :STALE_PAGE_ERRORS
99+
89100
private
90101

102+
# set_rack_session drives a real form on /rack_session: it submits the
103+
# form and immediately reads the page text to confirm the update. Under
104+
# Selenium that read can resolve the body node just before the submit's
105+
# navigation lands and then read it just after, hitting a stale node.
106+
# Writing the session data again is idempotent, so the whole call is
107+
# retried a bounded number of times. Retriable is called directly rather
108+
# than through retry_block because the latter no-ops under
109+
# RSPEC_RETRY_RETRY_COUNT=0, which is where this race bites most.
110+
def set_rack_session_with_retry(session_value)
111+
Retriable.retriable(tries: 3, on: STALE_PAGE_ERRORS) do
112+
page.set_rack_session(session_value)
113+
end
114+
end
115+
91116
def js_enabled?
92117
RSpec.current_example.metadata[:js]
93118
end

0 commit comments

Comments
 (0)