How to allow testing beforeunload confirmation dialogs with modern ChromeDrivers

Updated . Posted . Visible to the public.

Starting with ChromeDriver 127, if your application displays a beforeunload confirmation dialog, ChromeDriver will immediately close it. In consequence, any automated tests which try to interact with unload prompts will fail.

This is because ChromeDriver now follows the W3C WebDriver spec Show archive.org snapshot which states that any unload prompts should be closed automatically.
However, this applies only to "HTTP" test sessions, i.e. what you're using by default. The spec also defines that bi-directional test sessions (using the " BiDi Show archive.org snapshot " WebDriver) should not automatically accept such dialogs. This means that we want to use the BiDi driver when testing beforeunload prompts.

Enabling the BiDi WebDriver

Using Capybara, simply set the :web_socket_url option to true to enable BiDi mode.
Example:

options = Selenium::WebDriver::Chrome::Options.new(
  args: ['--headless'],
  unhandled_prompt_behavior: 'ignore',
  # ...
)

if unload_confirmation
  options.add_option(:web_socket_url, true)
  options.add_option(:page_load_strategy, 'none') # required for selenium-webdriver 4.27+
end

Capybara::Selenium::Driver.new(app, browser: :chrome, options: options)

In combination with unhandled_prompt_behavior: 'ignore' (which we recommend setting) any unload alerts will now stay open until handled.

Note that you also need to set the :page_load_strategy to "none" for modern selenium-webdriver ≥ 4.27 since those follow the spec more closely than previous versions and respect the document's readiness state Show archive.org snapshot for navigation events.
If you do not specify a :page_load_strategy, selenium-webdriver defaults to "complete" which means it will wait for any beforeunload to be handled before e.g. a page.refresh statement returns. That that this also applies to wrapped calls like accept_confirm { page.refresh }.

Recommendation

We do not recommend BiDi mode as a default because it can have a negative impact on other tests.

For example, if your application shows unload confirmations for forms with unsaved changes, all tests would have to ensure they explicitly save or discard any changes before a test finishes. Otherwise, when the driver closes the page, an unload dialog appears which cannot be handled.
Also, the BiDi driver does not yet implement all features (see https://wpt.fyi/results/webdriver/tests/bidi Show archive.org snapshot ).

Instead, specify a BiDi driver and use that driver when testing unload behavior. Example:

Capybara.register_driver(:with_unload_confirmation) do |app|
  # ...
end
describe 'unsaved changes confirmation dialog', :js, driver: :with_unload_confirmation do
  # ...
end
Arne Hartherz
Last edit
Arne Hartherz
License
Source code in this card is licensed under the MIT License.
Posted by Arne Hartherz to makandra dev (2024-10-10 13:02)