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)