How to configure Selenium WebDriver to not automatically close alerts or other browser dialogs

Updated . Posted . Visible to the public. Repeats.

tl;dr

We recommend configuring Selenium's unhandled prompt behavior to { default: 'ignore' } with the monkey patch below.

When running tests in a real browser, we use Selenium. Each browser is controlled by a specific driver, e.g. Selenium::WebDriver::Chrome for Chrome.

There is one quirk to all drivers (at least those following the W3C webdriver spec) that can be impractical:
When any user prompt Show archive.org snapshot (like an alert) is encountered when trying to perform an action, they will dismiss the dialog by default Show archive.org snapshot and raise an error (dismiss and notify mode).

You maybe encountered this in the past, when an Selenium::WebDriver::Error::UnexpectedAlertOpenError was raised.
However, when the error is raised in from the Selenium driver, the user prompt will have been closed already and can not be brought back. Also, any JavaScript code placed after the alert will be executed.

Automatically closing user prompts happens when performing most options, like a simple visit or execute_script from Capybara.

Different behaviors

While drivers default to dismissing user prompts, you can change that. Specifically, the specification Show archive.org snapshot describes these possible behaviors:

Keyword Description
'dismiss' All simple dialogs encountered should be dismissed.
'accept' All simple dialogs encountered should be accepted.
'dismiss and notify' All simple dialogs encountered should be dismissed, and an error returned that the dialog was handled. (default)
'accept and notify' All simple dialogs encountered should be accepted, and an error returned that the dialog was handled.
'ignore' All simple dialogs encountered should be left to the user to handle. (recommended)

While the description of ignore does not say if errors would be raised, they are. When a user prompt is open, the driver cannot perform actions like Capybara's visit or execute_script, and you will still receive a Selenium::WebDriver::Error::UnexpectedAlertOpenError. This is probably what you want for running tests.

Different types of prompts

It is possible to handle different types of prompt separately. For example, if you want to accept every prompt except alerts, you can use { default: 'accept', alert: 'ignore' }. The supported prompt types are alert, prompt, confirm, beforeUnload and file.

It is also possible to set the unhandled prompt behavior to a string. That setting is respected for every alert type except before unload prompts.

How to configure Selenium WebDriver

Configuring the unhandled prompt behavior is fairly simple. You need to specify the webdriver option unhandled_prompt_behavior when building your Capybara driver.

For example, the Chrome driver can be configured like this:

Capybara.register_driver(:selenium) do |app|
  options = Selenium::WebDriver::Chrome::Options.new(
    unhandled_prompt_behavior: { default: 'ignore' },
    # ...
  )
  Capybara::Selenium::Driver.new(app, browser: :chrome, options: options)
end

Ruby-Selenium doesn't support setting the beforeUnload capability to a hash yet. The following monkey patch removes the unnecessary conversation to a string:

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)
Arne Hartherz
Last edit
Niklas Hasselmeyer
License
Source code in this card is licensed under the MIT License.
Posted by Arne Hartherz to makandra dev (2024-01-31 08:29)