2016-03-07 16:52:19 -08:00
# frozen_string_literal: true
2018-01-08 12:23:54 -08:00
2018-06-21 13:13:53 -07:00
require 'uri'
require 'English'
2013-10-20 19:29:22 +02:00
2011-04-11 06:24:00 +01:00
class Capybara :: Selenium :: Driver < Capybara :: Driver :: Base
2019-01-03 13:00:38 -08:00
include Capybara :: Selenium :: Find
2011-02-22 15:53:14 +01:00
DEFAULT_OPTIONS = {
2018-01-09 14:05:50 -08:00
browser : :firefox ,
2018-11-20 09:44:52 -08:00
clear_local_storage : nil ,
clear_session_storage : nil
2018-01-08 12:23:54 -08:00
} . freeze
2019-07-22 15:24:49 -07:00
SPECIAL_OPTIONS = % i [ browser clear_local_storage clear_session_storage timeout native_displayed ] . freeze
2021-12-31 07:35:20 +09:00
CAPS_VERSION = Gem :: Requirement . new ( '>= 4.0.0.alpha6' )
2021-01-20 11:37:49 -08:00
2012-07-13 13:29:02 +02:00
attr_reader :app , :options
2009-11-07 16:30:16 +01:00
2019-04-17 13:08:33 -07:00
class << self
2021-01-19 23:42:29 -08:00
attr_reader :selenium_webdriver_version
2019-04-17 13:08:33 -07:00
def load_selenium
require 'selenium-webdriver'
2019-04-17 18:04:03 -07:00
require 'capybara/selenium/logger_suppressor'
2019-05-02 18:57:14 -07:00
require 'capybara/selenium/patches/atoms'
2019-07-18 09:56:36 -07:00
require 'capybara/selenium/patches/is_displayed'
2020-03-29 11:22:56 -07:00
require 'capybara/selenium/patches/action_pauser'
2020-09-05 11:39:05 -06:00
# Look up the version of `selenium-webdriver` to
# see if it's a version we support.
#
# By default, we use Gem.loaded_specs to determine
# the version number. However, in some cases, such
# as when loading `selenium-webdriver` outside of
# Rubygems, we fall back to referencing
# Selenium::WebDriver::VERSION. Ideally we'd
# use the constant in all cases, but earlier versions
# of `selenium-webdriver` didn't provide the constant.
2021-01-19 23:42:29 -08:00
@selenium_webdriver_version =
2020-09-05 11:54:25 -07:00
if Gem . loaded_specs [ 'selenium-webdriver' ]
2020-09-05 11:39:05 -06:00
Gem . loaded_specs [ 'selenium-webdriver' ] . version
else
Gem :: Version . new ( Selenium :: WebDriver :: VERSION )
end
2021-01-19 16:00:52 -08:00
2021-10-23 13:28:25 -07:00
unless Gem :: Requirement . new ( '>= 3.142.7' ) . satisfied_by? @selenium_webdriver_version
2019-10-15 18:02:35 -07:00
warn " Warning: You're using an unsupported version of selenium-webdriver, please upgrade. "
end
2021-01-19 16:00:52 -08:00
2021-01-19 23:42:29 -08:00
@selenium_webdriver_version
2019-04-17 13:08:33 -07:00
rescue LoadError = > e
2020-07-06 22:34:20 -07:00
raise e unless e . message . include? ( 'selenium-webdriver' )
2019-04-17 13:08:33 -07:00
raise LoadError , " Capybara's selenium driver is unable to load `selenium-webdriver`, please install the gem and add `gem 'selenium-webdriver'` to your Gemfile if you are using bundler. "
end
attr_reader :specializations
2018-09-24 09:43:46 -07:00
2019-04-17 13:08:33 -07:00
def register_specialization ( browser_name , specialization )
@specializations || = { }
@specializations [ browser_name ] = specialization
end
2018-04-16 12:05:25 -07:00
end
2010-08-30 09:19:44 +02:00
def browser
2019-04-17 13:08:33 -07:00
unless @browser
2019-03-28 10:40:35 -07:00
options [ :http_client ] || = begin
2019-03-30 09:02:59 -07:00
require 'capybara/selenium/patches/persistent_client'
2019-03-28 10:40:35 -07:00
if options [ :timeout ]
:: Capybara :: Selenium :: PersistentClient . new ( read_timeout : options [ :timeout ] )
else
:: Capybara :: Selenium :: PersistentClient . new
end
2018-11-20 14:20:46 -08:00
end
2018-08-24 11:32:55 -07:00
processed_options = options . reject { | key , _val | SPECIAL_OPTIONS . include? ( key ) }
2021-01-19 23:42:29 -08:00
@browser = if options [ :browser ] == :firefox &&
RUBY_VERSION > = '3.0' &&
Capybara :: Selenium :: Driver . selenium_webdriver_version < = Gem :: Version . new ( '4.0.0.alpha1' )
# selenium-webdriver 3.x doesn't correctly pass options through for Firefox with Ruby 3 so workaround that
Selenium :: WebDriver :: Firefox :: Driver . new ( ** processed_options )
else
Selenium :: WebDriver . for ( options [ :browser ] , processed_options )
end
2019-04-17 13:08:33 -07:00
specialize_driver
setup_exit_handler
2009-11-14 10:44:46 +01:00
end
2018-09-16 11:50:56 -07:00
@browser
2009-11-07 16:30:16 +01:00
end
2016-08-17 16:14:39 -07:00
def initialize ( app , ** options )
2020-09-05 12:24:43 -07:00
super ( )
2018-04-16 12:05:25 -07:00
self . class . load_selenium
2009-11-07 16:30:16 +01:00
@app = app
2012-01-08 23:01:46 +09:00
@browser = nil
2012-01-08 23:02:24 +09:00
@exit_status = nil
2018-08-17 13:57:12 -07:00
@frame_handles = Hash . new { | hash , handle | hash [ handle ] = [ ] }
2011-02-22 15:53:14 +01:00
@options = DEFAULT_OPTIONS . merge ( options )
2018-06-06 16:11:47 -07:00
@node_class = :: Capybara :: Selenium :: Node
2009-11-07 16:30:16 +01:00
end
2009-11-14 10:44:46 +01:00
2009-11-07 16:30:16 +01:00
def visit ( path )
2012-07-13 13:29:02 +02:00
browser . navigate . to ( path )
2009-11-07 16:30:16 +01:00
end
2009-11-14 10:44:46 +01:00
2017-07-04 15:14:55 -07:00
def refresh
2018-02-15 14:34:06 -08:00
browser . navigate . refresh
2017-07-04 15:14:55 -07:00
end
2013-10-05 21:23:51 +03:00
def go_back
browser . navigate . back
end
def go_forward
browser . navigate . forward
end
2012-09-10 03:05:17 +02:00
def html
2010-01-01 20:13:54 +01:00
browser . page_source
2020-05-23 11:28:24 -07:00
rescue Selenium :: WebDriver :: Error :: JavascriptError = > e
2020-07-06 22:34:20 -07:00
raise unless e . message . include? ( 'documentElement is null' )
2009-11-07 16:30:16 +01:00
end
2009-11-14 10:44:46 +01:00
2013-02-06 21:36:55 +02:00
def title
browser . title
end
2013-02-24 18:54:39 +01:00
2009-12-16 15:16:52 +01:00
def current_url
2010-01-01 20:13:54 +01:00
browser . current_url
2009-12-16 15:16:52 +01:00
end
2009-12-12 21:46:08 +01:00
def wait? ; true ; end
2012-07-13 13:29:02 +02:00
def needs_server? ; true ; end
2009-11-07 16:30:16 +01:00
2016-12-22 16:22:46 -08:00
def execute_script ( script , * args )
2018-05-11 09:42:15 -07:00
browser . execute_script ( script , * native_args ( args ) )
2010-06-29 22:41:33 +02:00
end
2016-12-22 16:22:46 -08:00
def evaluate_script ( script , * args )
2018-07-20 00:07:30 -07:00
result = execute_script ( " return #{ script } " , * args )
2017-01-28 14:34:44 -08:00
unwrap_script_result ( result )
2010-01-01 20:13:54 +01:00
end
2010-01-01 22:46:05 +01:00
2017-10-20 15:18:00 -07:00
def evaluate_async_script ( script , * args )
browser . manage . timeouts . script_timeout = Capybara . default_max_wait_time
2018-05-11 09:42:15 -07:00
result = browser . execute_async_script ( script , * native_args ( args ) )
2017-10-20 15:18:00 -07:00
unwrap_script_result ( result )
end
2021-01-31 21:08:43 -05:00
def active_element
2021-08-15 12:34:15 -07:00
build_node ( native_active_element )
2021-01-31 21:08:43 -05:00
end
2020-11-16 20:26:59 -05:00
def send_keys ( * args )
2021-08-15 12:34:15 -07:00
# Should this call the specialized nodes rather than native???
native_active_element . send_keys ( * args )
2020-11-16 20:26:59 -05:00
end
2016-08-17 16:14:39 -07:00
def save_screenshot ( path , ** _options )
2012-07-10 13:50:15 +09:00
browser . save_screenshot ( path )
end
2010-07-29 15:25:45 +02:00
def reset!
2010-09-07 18:35:09 +02:00
# Use instance variable directly so we avoid starting the browser just to reset the session
2018-01-09 14:05:50 -08:00
return unless @browser
2016-03-30 14:55:29 -07:00
2018-01-09 14:05:50 -08:00
navigated = false
2018-06-06 10:51:25 -07:00
timer = Capybara :: Helpers . timer ( expire_in : 10 )
2018-01-09 14:05:50 -08:00
begin
2018-10-11 10:59:17 -07:00
# Only trigger a navigation if we haven't done it already, otherwise it
# can trigger an endless series of unload modals
reset_browser_state unless navigated
2018-01-09 14:05:50 -08:00
navigated = true
# Ensure the page is empty and trigger an UnhandledAlertError for any modals that appear during unload
2018-10-11 10:59:17 -07:00
wait_for_empty_page ( timer )
2019-04-17 18:04:03 -07:00
rescue * unhandled_alert_errors
2018-01-09 14:05:50 -08:00
# This error is thrown if an unhandled alert is on the page
# Firefox appears to automatically dismiss this alert, chrome does not
# We'll try to accept it
2018-10-11 10:59:17 -07:00
accept_unhandled_reset_alert
2018-01-09 14:05:50 -08:00
# try cleaning up the browser again
retry
2011-04-07 17:08:32 +02:00
end
2010-01-23 12:58:30 +01:00
end
2019-05-10 08:07:57 -07:00
def frame_obscured_at? ( x : , y : )
frame = @frame_handles [ current_window_handle ] . last
return false unless frame
switch_to_frame ( :parent )
begin
2019-11-28 12:19:37 -08:00
frame . base . obscured? ( x : x , y : y )
2019-05-10 08:07:57 -07:00
ensure
switch_to_frame ( frame )
end
end
2016-07-15 11:00:14 -07:00
def switch_to_frame ( frame )
2018-08-17 13:57:12 -07:00
handles = @frame_handles [ current_window_handle ]
2016-07-15 11:00:14 -07:00
case frame
when :top
2018-08-17 13:57:12 -07:00
handles . clear
2016-07-15 11:00:14 -07:00
browser . switch_to . default_content
when :parent
2018-08-17 13:57:12 -07:00
handles . pop
2018-09-11 11:15:07 -07:00
browser . switch_to . parent_frame
2016-07-15 11:00:14 -07:00
else
2019-05-10 08:07:57 -07:00
handles << frame
2016-07-15 11:00:14 -07:00
browser . switch_to . frame ( frame . native )
end
2010-01-12 11:40:10 -08:00
end
2010-04-28 16:03:13 -07:00
2014-04-09 00:28:16 +03:00
def current_window_handle
browser . window_handle
end
2014-04-25 01:38:42 +03:00
def window_size ( handle )
within_given_window ( handle ) do
size = browser . manage . window . size
[ size . width , size . height ]
end
2014-04-09 00:28:16 +03:00
end
2014-04-25 01:38:42 +03:00
def resize_window_to ( handle , width , height )
within_given_window ( handle ) do
2018-06-21 13:13:53 -07:00
browser . manage . window . resize_to ( width , height )
2014-04-25 01:38:42 +03:00
end
2014-04-09 00:28:16 +03:00
end
2014-04-25 01:38:42 +03:00
def maximize_window ( handle )
within_given_window ( handle ) do
browser . manage . window . maximize
end
2014-05-28 22:34:31 +03:00
sleep 0 . 1 # work around for https://code.google.com/p/selenium/issues/detail?id=7405
2014-04-10 10:20:27 +03:00
end
2018-06-21 11:30:26 -07:00
def fullscreen_window ( handle )
within_given_window ( handle ) do
2018-06-21 13:13:53 -07:00
browser . manage . window . full_screen
2018-06-21 11:30:26 -07:00
end
end
2014-04-25 01:38:42 +03:00
def close_window ( handle )
2018-07-10 14:18:39 -07:00
raise ArgumentError , 'Not allowed to close the primary window' if handle == window_handles . first
2018-09-24 09:43:46 -07:00
2014-04-25 01:38:42 +03:00
within_given_window ( handle ) do
browser . close
end
2014-04-09 00:28:16 +03:00
end
def window_handles
browser . window_handles
end
2019-03-26 12:05:21 -07:00
def open_new_window ( kind = :tab )
2021-10-20 21:08:46 -04:00
if browser . switch_to . respond_to? ( :new_window )
2021-10-23 17:48:56 -07:00
handle = current_window_handle
2021-10-20 21:08:46 -04:00
browser . switch_to . new_window ( kind )
2021-10-23 17:48:56 -07:00
switch_to_window ( handle )
2021-10-20 21:08:46 -04:00
else
browser . manage . new_window ( kind )
end
2019-03-26 12:05:21 -07:00
rescue NoMethodError , Selenium :: WebDriver :: Error :: WebDriverError
# If not supported by the driver or browser default to using JS
2014-04-09 00:28:16 +03:00
browser . execute_script ( 'window.open();' )
end
def switch_to_window ( handle )
browser . switch_to . window handle
end
2016-08-17 16:14:39 -07:00
def accept_modal ( _type , ** options )
2018-02-12 10:07:06 -08:00
yield if block_given?
2019-11-28 14:41:13 -08:00
modal = find_modal ( ** options )
2017-10-09 01:37:45 -07:00
2018-02-12 10:07:06 -08:00
modal . send_keys options [ :with ] if options [ :with ]
2017-10-09 01:37:45 -07:00
2018-02-12 10:07:06 -08:00
message = modal . text
modal . accept
message
2013-04-01 16:41:55 -06:00
end
2016-08-17 16:14:39 -07:00
def dismiss_modal ( _type , ** options )
2018-02-12 10:07:06 -08:00
yield if block_given?
2019-11-28 14:41:13 -08:00
modal = find_modal ( ** options )
2018-02-12 10:07:06 -08:00
message = modal . text
modal . dismiss
message
2013-04-01 16:41:55 -06:00
end
2011-05-13 13:22:50 +01:00
def quit
2018-05-10 13:20:23 -07:00
@browser & . quit
2021-01-13 09:23:00 -05:00
rescue Selenium :: WebDriver :: Error :: SessionNotCreatedError , Errno :: ECONNREFUSED ,
Selenium :: WebDriver :: Error :: InvalidSessionIdError
2011-05-13 13:22:50 +01:00
# Browser must have already gone
2019-04-29 11:11:01 -07:00
rescue Selenium :: WebDriver :: Error :: UnknownError = > e
unless silenced_unknown_error_message? ( e . message ) # Most likely already gone
2016-11-23 11:53:57 -08:00
# probably already gone but not sure - so warn
2019-04-29 11:11:01 -07:00
warn " Ignoring Selenium UnknownError during driver quit: #{ e . message } "
2016-11-23 11:53:57 -08:00
end
2013-11-22 15:59:51 -08:00
ensure
@browser = nil
2011-05-13 13:22:50 +01:00
end
2011-07-13 15:39:17 +02:00
def invalid_element_errors
2021-03-27 12:11:45 -07:00
@invalid_element_errors || =
2019-04-18 09:19:16 -07:00
[
:: Selenium :: WebDriver :: Error :: StaleElementReferenceError ,
:: Selenium :: WebDriver :: Error :: ElementNotInteractableError ,
:: Selenium :: WebDriver :: Error :: InvalidSelectorError , # Work around chromedriver go_back/go_forward race condition
:: Selenium :: WebDriver :: Error :: ElementClickInterceptedError ,
:: Selenium :: WebDriver :: Error :: NoSuchElementError , # IE
:: Selenium :: WebDriver :: Error :: InvalidArgumentError # IE
] . tap do | errors |
unless selenium_4?
:: Selenium :: WebDriver . logger . suppress_deprecations do
errors . concat [
:: Selenium :: WebDriver :: Error :: UnhandledError ,
:: Selenium :: WebDriver :: Error :: ElementNotVisibleError ,
:: Selenium :: WebDriver :: Error :: InvalidElementStateError ,
:: Selenium :: WebDriver :: Error :: ElementNotSelectableError
]
end
end
2019-04-17 18:04:03 -07:00
end
2011-07-13 15:39:17 +02:00
end
2013-02-24 18:54:39 +01:00
2014-04-09 00:28:16 +03:00
def no_such_window_error
Selenium :: WebDriver :: Error :: NoSuchWindowError
end
2014-04-25 01:38:42 +03:00
2018-06-06 16:11:47 -07:00
private
2019-04-17 23:29:48 -07:00
def selenium_4?
defined? ( Selenium :: WebDriver :: VERSION ) && ( Selenium :: WebDriver :: VERSION . to_f > = 4 )
end
2018-05-11 09:42:15 -07:00
def native_args ( args )
args . map { | arg | arg . is_a? ( Capybara :: Selenium :: Node ) ? arg . native : arg }
end
2021-08-15 12:34:15 -07:00
def native_active_element
browser . switch_to . active_element
end
2018-08-22 17:15:16 -07:00
def clear_browser_state
2018-10-02 12:23:19 -07:00
delete_all_cookies
2018-08-22 17:15:16 -07:00
clear_storage
2020-04-02 18:05:16 -07:00
rescue * clear_browser_state_errors
2018-08-22 17:15:16 -07:00
# delete_all_cookies fails when we've previously gone
# to about:blank, so we rescue this error and do nothing
# instead.
end
2019-04-17 18:04:03 -07:00
def clear_browser_state_errors
2019-05-07 15:15:38 -07:00
@clear_browser_state_errors || = [ Selenium :: WebDriver :: Error :: UnknownError ]
2019-04-17 18:04:03 -07:00
end
def unhandled_alert_errors
2019-06-24 16:55:36 -07:00
@unhandled_alert_errors || = with_legacy_error (
[ Selenium :: WebDriver :: Error :: UnexpectedAlertOpenError ] ,
'UnhandledAlertError'
)
2019-04-17 18:04:03 -07:00
end
2018-10-02 12:23:19 -07:00
def delete_all_cookies
@browser . manage . delete_all_cookies
end
2017-11-13 13:04:47 -08:00
def clear_storage
2018-11-20 09:44:52 -08:00
clear_session_storage unless options [ :clear_session_storage ] == false
clear_local_storage unless options [ :clear_local_storage ] == false
2020-04-02 18:05:16 -07:00
rescue Selenium :: WebDriver :: Error :: JavascriptError
2018-11-20 09:44:52 -08:00
# session/local storage may not be available if on non-http pages (e.g. about:blank)
2018-08-24 04:45:19 -07:00
end
def clear_session_storage
if @browser . respond_to? :session_storage
@browser . session_storage . clear
else
2019-03-13 18:21:53 -07:00
begin
@browser & . execute_script ( 'window.sessionStorage.clear()' )
rescue # rubocop:disable Style/RescueStandardError
2019-10-15 18:02:35 -07:00
unless options [ :clear_session_storage ] . nil?
warn 'sessionStorage clear requested but is not supported by this driver'
end
2019-03-13 18:21:53 -07:00
end
2017-11-13 13:04:47 -08:00
end
2018-08-24 04:45:19 -07:00
end
2018-05-14 14:30:34 -07:00
2018-08-24 04:45:19 -07:00
def clear_local_storage
if @browser . respond_to? :local_storage
@browser . local_storage . clear
else
2019-03-13 18:21:53 -07:00
begin
@browser & . execute_script ( 'window.localStorage.clear()' )
rescue # rubocop:disable Style/RescueStandardError
2019-10-15 18:02:35 -07:00
unless options [ :clear_local_storage ] . nil?
warn 'localStorage clear requested but is not supported by this driver'
end
2019-03-13 18:21:53 -07:00
end
2017-11-13 13:04:47 -08:00
end
end
2018-08-22 17:15:16 -07:00
def navigate_with_accept ( url )
@browser . navigate . to ( url )
sleep 0 . 1 # slight wait for alert
@browser . switch_to . alert . accept
2020-04-02 18:05:16 -07:00
rescue modal_error
2018-08-22 17:15:16 -07:00
# alert now gone, should mean navigation happened
end
2017-11-03 13:31:35 -07:00
def modal_error
2018-06-22 14:53:28 -07:00
Selenium :: WebDriver :: Error :: NoSuchAlertError
2017-11-03 13:31:35 -07:00
end
2014-04-25 01:38:42 +03:00
def within_given_window ( handle )
2018-01-09 14:05:50 -08:00
original_handle = current_window_handle
2014-04-25 01:38:42 +03:00
if handle == original_handle
yield
else
switch_to_window ( handle )
result = yield
switch_to_window ( original_handle )
result
end
end
2013-04-01 16:41:55 -06:00
2016-08-17 16:14:39 -07:00
def find_modal ( text : nil , ** options )
2014-06-03 12:18:14 -07:00
# Selenium has its own built in wait (2 seconds)for a modal to show up, so this wait is really the minimum time
# Actual wait time may be longer than specified
wait = Selenium :: WebDriver :: Wait . new (
2018-01-09 14:05:50 -08:00
timeout : options . fetch ( :wait , session_options . default_max_wait_time ) || 0 ,
2018-01-08 12:23:54 -08:00
ignore : modal_error
)
2014-06-03 12:18:14 -07:00
begin
2015-02-06 16:13:41 +01:00
wait . until do
2014-06-03 12:18:14 -07:00
alert = @browser . switch_to . alert
2019-07-13 14:37:12 -07:00
regexp = text . is_a? ( Regexp ) ? text : Regexp . new ( Regexp . escape ( text . to_s ) )
matched = alert . text . match? ( regexp )
2019-10-15 18:02:35 -07:00
unless matched
raise Capybara :: ModalNotFound , " Unable to find modal dialog with #{ text } - found ' #{ alert . text } ' instead. "
end
2019-07-13 14:37:12 -07:00
alert
2014-06-03 12:18:14 -07:00
end
2019-04-17 18:04:03 -07:00
rescue * find_modal_errors
2018-01-09 14:05:50 -08:00
raise Capybara :: ModalNotFound , " Unable to find modal dialog #{ " with #{ text } " if text } "
2014-06-03 12:18:14 -07:00
end
2013-04-01 16:41:55 -06:00
end
2019-04-17 18:04:03 -07:00
def find_modal_errors
2019-06-24 16:55:36 -07:00
@find_modal_errors || = with_legacy_error ( [ Selenium :: WebDriver :: Error :: TimeoutError ] , 'TimeOutError' )
end
def with_legacy_error ( errors , legacy_error )
errors . tap do | errs |
2019-04-18 09:19:16 -07:00
unless selenium_4?
:: Selenium :: WebDriver . logger . suppress_deprecations do
2019-06-24 16:55:36 -07:00
errs << Selenium :: WebDriver :: Error . const_get ( legacy_error )
2019-04-18 09:19:16 -07:00
end
2019-04-17 23:29:48 -07:00
end
2019-04-17 18:04:03 -07:00
end
end
2016-11-23 11:53:57 -08:00
def silenced_unknown_error_message? ( msg )
2019-04-04 14:15:27 -07:00
silenced_unknown_error_messages . any? { | regex | msg . match? regex }
2016-11-23 11:53:57 -08:00
end
def silenced_unknown_error_messages
2018-01-08 12:23:54 -08:00
[ / Error communicating with the remote browser / ]
2016-11-23 11:53:57 -08:00
end
2017-01-28 14:34:44 -08:00
def unwrap_script_result ( arg )
2022-05-07 16:52:01 -07:00
# TODO: move into the case when we drop support for Selenium < 4.1
2022-05-05 11:32:50 -07:00
element_types = [ Selenium :: WebDriver :: Element ]
element_types . push ( Selenium :: WebDriver :: ShadowRoot ) if defined? ( Selenium :: WebDriver :: ShadowRoot )
2017-01-28 14:34:44 -08:00
case arg
when Array
2018-08-20 16:46:31 -07:00
arg . map { | arr | unwrap_script_result ( arr ) }
2017-01-28 14:34:44 -08:00
when Hash
2019-03-25 09:37:25 -07:00
arg . transform_values! { | value | unwrap_script_result ( value ) }
2022-05-05 11:32:50 -07:00
when * element_types
2018-06-06 16:11:47 -07:00
build_node ( arg )
2017-01-28 14:34:44 -08:00
else
arg
end
end
2018-06-06 16:11:47 -07:00
2019-01-03 13:00:38 -08:00
def find_context
browser
end
2019-01-08 15:51:05 -08:00
def build_node ( native_node , initial_cache = { } )
:: Capybara :: Selenium :: Node . new ( self , native_node , initial_cache )
2018-06-06 16:11:47 -07:00
end
2018-08-24 11:32:55 -07:00
2019-08-01 12:36:39 -07:00
def bridge
browser . send ( :bridge )
end
2020-09-10 12:18:59 -07:00
2019-04-17 13:08:33 -07:00
def specialize_driver
browser_type = browser . browser
2019-05-11 12:07:16 +01:00
Capybara :: Selenium :: Driver . specializations . select { | k , _v | k === browser_type } . each_value do | specialization | # rubocop:disable Style/CaseEquality
2019-04-17 13:08:33 -07:00
extend specialization
2018-08-24 11:32:55 -07:00
end
end
def setup_exit_handler
main = Process . pid
at_exit do
# Store the exit status of the test run since it goes away after calling the at_exit proc...
@exit_status = $ERROR_INFO . status if $ERROR_INFO . is_a? ( SystemExit )
quit if Process . pid == main
exit @exit_status if @exit_status # Force exit with stored status
end
end
2018-10-11 10:59:17 -07:00
def reset_browser_state
clear_browser_state
@browser . navigate . to ( 'about:blank' )
end
def wait_for_empty_page ( timer )
until find_xpath ( '/html/body/*' ) . empty?
raise Capybara :: ExpectationNotMet , 'Timed out waiting for Selenium session reset' if timer . expired?
2019-01-15 11:05:35 -08:00
sleep 0 . 01
2019-02-24 07:45:49 +11:00
# It has been observed that it is possible that asynchronous JS code in
# the application under test can navigate the browser away from about:blank
2019-02-24 15:32:07 -08:00
# if the timing is just right. Ensure we are still at about:blank...
2019-02-24 07:45:49 +11:00
@browser . navigate . to ( 'about:blank' ) unless current_url == 'about:blank'
2018-10-11 10:59:17 -07:00
end
end
def accept_unhandled_reset_alert
@browser . switch_to . alert . accept
sleep 0 . 25 # allow time for the modal to be handled
rescue modal_error
# The alert is now gone.
# If navigation has not occurred attempt again and accept alert
# since FF may have dismissed the alert at first attempt.
navigate_with_accept ( 'about:blank' ) if current_url != 'about:blank'
end
2009-11-07 16:30:16 +01:00
end
2018-06-21 13:13:53 -07:00
require 'capybara/selenium/driver_specializations/chrome_driver'
2018-11-18 13:27:00 -08:00
require 'capybara/selenium/driver_specializations/firefox_driver'
2018-12-20 12:37:14 -08:00
require 'capybara/selenium/driver_specializations/internet_explorer_driver'
2019-03-13 18:21:53 -07:00
require 'capybara/selenium/driver_specializations/safari_driver'
2019-06-01 18:17:59 -07:00
require 'capybara/selenium/driver_specializations/edge_driver'