ChromeDriver 135 started following the W3C spec more closely, which broke testing beforeunload confirmations again. To get working confirmations in a testing browser again, unhandled_prompt_behavior
needs to be set to the hash { default: :ignore }
.
Selenium doesn't currently support setting this option to a hash, so a monkey patch is needed.
Changes
- 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](https://w3c.github.io/webdriver/#user-prompts) 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](https://w3c.github.io/webdriver-bidi/)" 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:
- ```ruby
- options = Selenium::WebDriver::Chrome::Options.new(
- args: ['--headless'],
- unhandled_prompt_behavior: 'ignore',- + unhandled_prompt_behavior: { default: '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](https://makandracards.com/makandra/617366-configure-selenium-webdriver-automatically-close-alerts)) any unload alerts will now stay open until handled.- +In combination with `unhandled_prompt_behavior: { default: 'ignore' }` ([which we recommend setting](https://makandracards.com/makandra/617366-configure-selenium-webdriver-automatically-close-alerts)) 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](https://www.w3.org/TR/webdriver-bidi/#type-browsingContext-ReadinessState) 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 }`.
- +### Setting `unhandled_prompt_behavior` to a hash
- +The [W3C spec](https://w3c.github.io/webdriver/#user-prompt-handler) allows setting the `unhandledPromptBehavior` option to a hash. This allows users to specify different behaviors for different types of alerts (e.g. `alert`, `confirm`, `beforeUnload`). Setting the option to a string is still supported, but doesn't affect `beforeUnload` prompts anymore.
- +
- +Currently, Selenium [doesn't support setting the `unhandledPromptBehavior` option to a hash](https://github.com/SeleniumHQ/selenium/issues/16159) and converts the option to a string. The following monkey patch is needed:
- +```rb
- +module FixUnhandledPromptBehaviorOption
- + def process_w3c_options(options)
- + w3c_options = options.select { |key, val| w3c?(key) && !val.nil? }
- + options.delete_if { |key, _val| w3c?(key) }
- + w3c_options
- + end
- +end
- +
- +Selenium::WebDriver::Options.prepend(FixUnhandledPromptBehaviorOption)
- +```
- +
- ## 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>).
- Instead, specify a BiDi driver and use that driver when testing unload behavior. Example:
- ```ruby
- Capybara.register_driver(:with_unload_confirmation) do |app|
- # ...
- end
- ```
- ```ruby
- describe 'unsaved changes confirmation dialog', :js, driver: :with_unload_confirmation do
- # ...
- end
- ```
Posted by Niklas Hasselmeyer to makandra dev (2025-08-12 10:25)