capybara 3.0.0 → 3.40.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.yardopts +1 -1
- data/History.md +891 -12
- data/License.txt +1 -1
- data/README.md +257 -84
- data/lib/capybara/config.rb +29 -10
- data/lib/capybara/cucumber.rb +1 -1
- data/lib/capybara/driver/base.rb +22 -4
- data/lib/capybara/driver/node.rb +38 -9
- data/lib/capybara/dsl.rb +9 -7
- data/lib/capybara/helpers.rb +57 -8
- data/lib/capybara/minitest/spec.rb +185 -84
- data/lib/capybara/minitest.rb +264 -145
- data/lib/capybara/node/actions.rb +248 -124
- data/lib/capybara/node/base.rb +35 -20
- data/lib/capybara/node/document.rb +14 -2
- data/lib/capybara/node/document_matchers.rb +13 -15
- data/lib/capybara/node/element.rb +350 -113
- data/lib/capybara/node/finders.rb +104 -82
- data/lib/capybara/node/matchers.rb +363 -157
- data/lib/capybara/node/simple.rb +54 -15
- data/lib/capybara/node/whitespace_normalizer.rb +81 -0
- data/lib/capybara/queries/active_element_query.rb +18 -0
- data/lib/capybara/queries/ancestor_query.rb +9 -10
- data/lib/capybara/queries/base_query.rb +25 -18
- data/lib/capybara/queries/current_path_query.rb +16 -6
- data/lib/capybara/queries/match_query.rb +11 -0
- data/lib/capybara/queries/selector_query.rb +617 -104
- data/lib/capybara/queries/sibling_query.rb +9 -7
- data/lib/capybara/queries/style_query.rb +45 -0
- data/lib/capybara/queries/text_query.rb +40 -22
- data/lib/capybara/queries/title_query.rb +2 -2
- data/lib/capybara/rack_test/browser.rb +106 -31
- data/lib/capybara/rack_test/driver.rb +16 -7
- data/lib/capybara/rack_test/errors.rb +6 -0
- data/lib/capybara/rack_test/form.rb +74 -49
- data/lib/capybara/rack_test/node.rb +120 -47
- data/lib/capybara/rails.rb +1 -1
- data/lib/capybara/registration_container.rb +41 -0
- data/lib/capybara/registrations/drivers.rb +42 -0
- data/lib/capybara/registrations/patches/puma_ssl.rb +29 -0
- data/lib/capybara/registrations/servers.rb +66 -0
- data/lib/capybara/result.rb +87 -53
- data/lib/capybara/rspec/features.rb +8 -10
- data/lib/capybara/rspec/matcher_proxies.rb +39 -18
- data/lib/capybara/rspec/matchers/base.rb +113 -0
- data/lib/capybara/rspec/matchers/become_closed.rb +33 -0
- data/lib/capybara/rspec/matchers/compound.rb +88 -0
- data/lib/capybara/rspec/matchers/count_sugar.rb +37 -0
- data/lib/capybara/rspec/matchers/have_ancestor.rb +28 -0
- data/lib/capybara/rspec/matchers/have_current_path.rb +29 -0
- data/lib/capybara/rspec/matchers/have_selector.rb +69 -0
- data/lib/capybara/rspec/matchers/have_sibling.rb +27 -0
- data/lib/capybara/rspec/matchers/have_text.rb +33 -0
- data/lib/capybara/rspec/matchers/have_title.rb +29 -0
- data/lib/capybara/rspec/matchers/match_selector.rb +27 -0
- data/lib/capybara/rspec/matchers/match_style.rb +43 -0
- data/lib/capybara/rspec/matchers/spatial_sugar.rb +39 -0
- data/lib/capybara/rspec/matchers.rb +142 -315
- data/lib/capybara/rspec.rb +3 -2
- data/lib/capybara/selector/builders/css_builder.rb +84 -0
- data/lib/capybara/selector/builders/xpath_builder.rb +71 -0
- data/lib/capybara/selector/css.rb +85 -8
- data/lib/capybara/selector/definition/button.rb +68 -0
- data/lib/capybara/selector/definition/checkbox.rb +26 -0
- data/lib/capybara/selector/definition/css.rb +10 -0
- data/lib/capybara/selector/definition/datalist_input.rb +35 -0
- data/lib/capybara/selector/definition/datalist_option.rb +25 -0
- data/lib/capybara/selector/definition/element.rb +28 -0
- data/lib/capybara/selector/definition/field.rb +40 -0
- data/lib/capybara/selector/definition/fieldset.rb +14 -0
- data/lib/capybara/selector/definition/file_field.rb +13 -0
- data/lib/capybara/selector/definition/fillable_field.rb +33 -0
- data/lib/capybara/selector/definition/frame.rb +17 -0
- data/lib/capybara/selector/definition/id.rb +6 -0
- data/lib/capybara/selector/definition/label.rb +62 -0
- data/lib/capybara/selector/definition/link.rb +55 -0
- data/lib/capybara/selector/definition/link_or_button.rb +16 -0
- data/lib/capybara/selector/definition/option.rb +27 -0
- data/lib/capybara/selector/definition/radio_button.rb +27 -0
- data/lib/capybara/selector/definition/select.rb +81 -0
- data/lib/capybara/selector/definition/table.rb +109 -0
- data/lib/capybara/selector/definition/table_row.rb +21 -0
- data/lib/capybara/selector/definition/xpath.rb +5 -0
- data/lib/capybara/selector/definition.rb +280 -0
- data/lib/capybara/selector/filter.rb +1 -0
- data/lib/capybara/selector/filter_set.rb +72 -28
- data/lib/capybara/selector/filters/base.rb +45 -2
- data/lib/capybara/selector/filters/expression_filter.rb +5 -6
- data/lib/capybara/selector/filters/locator_filter.rb +29 -0
- data/lib/capybara/selector/filters/node_filter.rb +18 -4
- data/lib/capybara/selector/regexp_disassembler.rb +211 -0
- data/lib/capybara/selector/selector.rb +89 -200
- data/lib/capybara/selector/xpath_extensions.rb +17 -0
- data/lib/capybara/selector.rb +474 -534
- data/lib/capybara/selenium/atoms/getAttribute.min.js +1 -0
- data/lib/capybara/selenium/atoms/isDisplayed.min.js +1 -0
- data/lib/capybara/selenium/atoms/src/getAttribute.js +161 -0
- data/lib/capybara/selenium/atoms/src/isDisplayed.js +454 -0
- data/lib/capybara/selenium/driver.rb +270 -245
- data/lib/capybara/selenium/driver_specializations/chrome_driver.rb +117 -0
- data/lib/capybara/selenium/driver_specializations/edge_driver.rb +128 -0
- data/lib/capybara/selenium/driver_specializations/firefox_driver.rb +84 -0
- data/lib/capybara/selenium/driver_specializations/internet_explorer_driver.rb +26 -0
- data/lib/capybara/selenium/driver_specializations/safari_driver.rb +24 -0
- data/lib/capybara/selenium/extensions/file_input_click_emulation.rb +34 -0
- data/lib/capybara/selenium/extensions/find.rb +110 -0
- data/lib/capybara/selenium/extensions/html5_drag.rb +229 -0
- data/lib/capybara/selenium/extensions/modifier_keys_stack.rb +28 -0
- data/lib/capybara/selenium/extensions/scroll.rb +76 -0
- data/lib/capybara/selenium/node.rb +460 -170
- data/lib/capybara/selenium/nodes/chrome_node.rb +125 -0
- data/lib/capybara/selenium/nodes/edge_node.rb +110 -0
- data/lib/capybara/selenium/nodes/firefox_node.rb +136 -0
- data/lib/capybara/selenium/nodes/ie_node.rb +22 -0
- data/lib/capybara/selenium/nodes/safari_node.rb +118 -0
- data/lib/capybara/selenium/patches/atoms.rb +18 -0
- data/lib/capybara/selenium/patches/is_displayed.rb +16 -0
- data/lib/capybara/selenium/patches/logs.rb +45 -0
- data/lib/capybara/selenium/patches/pause_duration_fix.rb +9 -0
- data/lib/capybara/selenium/patches/persistent_client.rb +20 -0
- data/lib/capybara/server/animation_disabler.rb +80 -0
- data/lib/capybara/server/checker.rb +44 -0
- data/lib/capybara/server/middleware.rb +71 -0
- data/lib/capybara/server.rb +58 -67
- data/lib/capybara/session/config.rb +40 -6
- data/lib/capybara/session/matchers.rb +26 -19
- data/lib/capybara/session.rb +252 -194
- data/lib/capybara/spec/public/jquery.js +5 -5
- data/lib/capybara/spec/public/offset.js +6 -0
- data/lib/capybara/spec/public/test.js +126 -8
- data/lib/capybara/spec/session/accept_alert_spec.rb +11 -11
- data/lib/capybara/spec/session/accept_confirm_spec.rb +3 -3
- data/lib/capybara/spec/session/accept_prompt_spec.rb +9 -10
- data/lib/capybara/spec/session/active_element_spec.rb +31 -0
- data/lib/capybara/spec/session/all_spec.rb +135 -44
- data/lib/capybara/spec/session/ancestor_spec.rb +24 -19
- data/lib/capybara/spec/session/assert_all_of_selectors_spec.rb +67 -38
- data/lib/capybara/spec/session/{assert_current_path.rb → assert_current_path_spec.rb} +20 -18
- data/lib/capybara/spec/session/assert_selector_spec.rb +143 -0
- data/lib/capybara/spec/session/assert_style_spec.rb +26 -0
- data/lib/capybara/spec/session/{assert_text.rb → assert_text_spec.rb} +76 -52
- data/lib/capybara/spec/session/{assert_title.rb → assert_title_spec.rb} +12 -12
- data/lib/capybara/spec/session/attach_file_spec.rb +126 -72
- data/lib/capybara/spec/session/body_spec.rb +11 -13
- data/lib/capybara/spec/session/check_spec.rb +112 -51
- data/lib/capybara/spec/session/choose_spec.rb +62 -30
- data/lib/capybara/spec/session/click_button_spec.rb +227 -161
- data/lib/capybara/spec/session/click_link_or_button_spec.rb +49 -30
- data/lib/capybara/spec/session/click_link_spec.rb +89 -55
- data/lib/capybara/spec/session/current_scope_spec.rb +8 -8
- data/lib/capybara/spec/session/current_url_spec.rb +44 -37
- data/lib/capybara/spec/session/dismiss_confirm_spec.rb +3 -3
- data/lib/capybara/spec/session/dismiss_prompt_spec.rb +2 -2
- data/lib/capybara/spec/session/element/{assert_match_selector.rb → assert_match_selector_spec.rb} +11 -9
- data/lib/capybara/spec/session/element/match_css_spec.rb +18 -10
- data/lib/capybara/spec/session/element/match_xpath_spec.rb +8 -6
- data/lib/capybara/spec/session/element/matches_selector_spec.rb +70 -56
- data/lib/capybara/spec/session/evaluate_async_script_spec.rb +7 -7
- data/lib/capybara/spec/session/evaluate_script_spec.rb +28 -8
- data/lib/capybara/spec/session/execute_script_spec.rb +8 -7
- data/lib/capybara/spec/session/fill_in_spec.rb +110 -44
- data/lib/capybara/spec/session/find_button_spec.rb +23 -23
- data/lib/capybara/spec/session/find_by_id_spec.rb +8 -8
- data/lib/capybara/spec/session/find_field_spec.rb +33 -31
- data/lib/capybara/spec/session/find_link_spec.rb +42 -14
- data/lib/capybara/spec/session/find_spec.rb +251 -142
- data/lib/capybara/spec/session/first_spec.rb +45 -44
- data/lib/capybara/spec/session/frame/frame_title_spec.rb +6 -6
- data/lib/capybara/spec/session/frame/frame_url_spec.rb +6 -6
- data/lib/capybara/spec/session/frame/switch_to_frame_spec.rb +32 -20
- data/lib/capybara/spec/session/frame/within_frame_spec.rb +46 -19
- data/lib/capybara/spec/session/go_back_spec.rb +1 -1
- data/lib/capybara/spec/session/go_forward_spec.rb +1 -1
- data/lib/capybara/spec/session/has_all_selectors_spec.rb +23 -23
- data/lib/capybara/spec/session/has_ancestor_spec.rb +46 -0
- data/lib/capybara/spec/session/has_any_selectors_spec.rb +29 -0
- data/lib/capybara/spec/session/has_button_spec.rb +98 -12
- data/lib/capybara/spec/session/has_css_spec.rb +271 -137
- data/lib/capybara/spec/session/has_current_path_spec.rb +50 -35
- data/lib/capybara/spec/session/has_element_spec.rb +47 -0
- data/lib/capybara/spec/session/has_field_spec.rb +137 -58
- data/lib/capybara/spec/session/has_link_spec.rb +46 -6
- data/lib/capybara/spec/session/has_none_selectors_spec.rb +33 -31
- data/lib/capybara/spec/session/has_select_spec.rb +84 -50
- data/lib/capybara/spec/session/has_selector_spec.rb +117 -69
- data/lib/capybara/spec/session/has_sibling_spec.rb +50 -0
- data/lib/capybara/spec/session/has_table_spec.rb +181 -4
- data/lib/capybara/spec/session/has_text_spec.rb +101 -53
- data/lib/capybara/spec/session/has_title_spec.rb +19 -14
- data/lib/capybara/spec/session/has_xpath_spec.rb +56 -38
- data/lib/capybara/spec/session/{headers.rb → headers_spec.rb} +1 -1
- data/lib/capybara/spec/session/html_spec.rb +13 -6
- data/lib/capybara/spec/session/matches_style_spec.rb +37 -0
- data/lib/capybara/spec/session/node_spec.rb +958 -122
- data/lib/capybara/spec/session/node_wrapper_spec.rb +15 -12
- data/lib/capybara/spec/session/refresh_spec.rb +9 -7
- data/lib/capybara/spec/session/reset_session_spec.rb +65 -37
- data/lib/capybara/spec/session/{response_code.rb → response_code_spec.rb} +1 -1
- data/lib/capybara/spec/session/save_and_open_page_spec.rb +2 -2
- data/lib/capybara/spec/session/save_and_open_screenshot_spec.rb +5 -4
- data/lib/capybara/spec/session/save_page_spec.rb +41 -38
- data/lib/capybara/spec/session/save_screenshot_spec.rb +13 -11
- data/lib/capybara/spec/session/screenshot_spec.rb +2 -2
- data/lib/capybara/spec/session/scroll_spec.rb +119 -0
- data/lib/capybara/spec/session/select_spec.rb +102 -76
- data/lib/capybara/spec/session/selectors_spec.rb +51 -18
- data/lib/capybara/spec/session/sibling_spec.rb +9 -9
- data/lib/capybara/spec/session/text_spec.rb +26 -24
- data/lib/capybara/spec/session/title_spec.rb +8 -6
- data/lib/capybara/spec/session/uncheck_spec.rb +41 -22
- data/lib/capybara/spec/session/unselect_spec.rb +37 -37
- data/lib/capybara/spec/session/visit_spec.rb +79 -53
- data/lib/capybara/spec/session/window/become_closed_spec.rb +22 -19
- data/lib/capybara/spec/session/window/current_window_spec.rb +4 -3
- data/lib/capybara/spec/session/window/open_new_window_spec.rb +4 -3
- data/lib/capybara/spec/session/window/switch_to_window_spec.rb +25 -21
- data/lib/capybara/spec/session/window/window_opened_by_spec.rb +10 -5
- data/lib/capybara/spec/session/window/window_spec.rb +88 -54
- data/lib/capybara/spec/session/window/windows_spec.rb +11 -8
- data/lib/capybara/spec/session/window/within_window_spec.rb +17 -16
- data/lib/capybara/spec/session/within_spec.rb +82 -44
- data/lib/capybara/spec/spec_helper.rb +46 -52
- data/lib/capybara/spec/test_app.rb +148 -41
- data/lib/capybara/spec/views/animated.erb +49 -0
- data/lib/capybara/spec/views/form.erb +156 -42
- data/lib/capybara/spec/views/frame_child.erb +4 -3
- data/lib/capybara/spec/views/frame_one.erb +2 -1
- data/lib/capybara/spec/views/frame_parent.erb +1 -1
- data/lib/capybara/spec/views/frame_two.erb +1 -1
- data/lib/capybara/spec/views/initial_alert.erb +2 -1
- data/lib/capybara/spec/views/layout.erb +10 -0
- data/lib/capybara/spec/views/obscured.erb +47 -0
- data/lib/capybara/spec/views/offset.erb +33 -0
- data/lib/capybara/spec/views/path.erb +2 -2
- data/lib/capybara/spec/views/popup_one.erb +1 -1
- data/lib/capybara/spec/views/popup_two.erb +1 -1
- data/lib/capybara/spec/views/react.erb +45 -0
- data/lib/capybara/spec/views/scroll.erb +21 -0
- data/lib/capybara/spec/views/spatial.erb +31 -0
- data/lib/capybara/spec/views/tables.erb +68 -1
- data/lib/capybara/spec/views/with_animation.erb +81 -0
- data/lib/capybara/spec/views/with_base_tag.erb +2 -2
- data/lib/capybara/spec/views/with_dragula.erb +24 -0
- data/lib/capybara/spec/views/with_fixed_header_footer.erb +2 -1
- data/lib/capybara/spec/views/with_hover.erb +3 -2
- data/lib/capybara/spec/views/with_hover1.erb +10 -0
- data/lib/capybara/spec/views/with_html.erb +46 -11
- data/lib/capybara/spec/views/with_html5_svg.erb +20 -0
- data/lib/capybara/spec/views/with_jquery_animation.erb +24 -0
- data/lib/capybara/spec/views/with_js.erb +30 -5
- data/lib/capybara/spec/views/with_jstree.erb +26 -0
- data/lib/capybara/spec/views/with_namespace.erb +21 -0
- data/lib/capybara/spec/views/with_scope.erb +2 -2
- data/lib/capybara/spec/views/with_scope_other.erb +6 -0
- data/lib/capybara/spec/views/with_shadow.erb +31 -0
- data/lib/capybara/spec/views/with_slow_unload.erb +2 -1
- data/lib/capybara/spec/views/with_sortable_js.erb +21 -0
- data/lib/capybara/spec/views/with_unload_alert.erb +1 -0
- data/lib/capybara/spec/views/with_windows.erb +1 -1
- data/lib/capybara/spec/views/within_frames.erb +1 -1
- data/lib/capybara/version.rb +1 -1
- data/lib/capybara/window.rb +32 -26
- data/lib/capybara.rb +128 -104
- data/spec/basic_node_spec.rb +59 -34
- data/spec/capybara_spec.rb +65 -51
- data/spec/counter_spec.rb +35 -0
- data/spec/css_builder_spec.rb +101 -0
- data/spec/css_splitter_spec.rb +38 -0
- data/spec/dsl_spec.rb +84 -55
- data/spec/filter_set_spec.rb +24 -7
- data/spec/fixtures/certificate.pem +25 -0
- data/spec/fixtures/key.pem +27 -0
- data/spec/fixtures/selenium_driver_rspec_failure.rb +5 -5
- data/spec/fixtures/selenium_driver_rspec_success.rb +5 -5
- data/spec/minitest_spec.rb +49 -5
- data/spec/minitest_spec_spec.rb +92 -62
- data/spec/per_session_config_spec.rb +6 -6
- data/spec/rack_test_spec.rb +183 -115
- data/spec/regexp_dissassembler_spec.rb +250 -0
- data/spec/result_spec.rb +99 -39
- data/spec/rspec/features_spec.rb +28 -25
- data/spec/rspec/scenarios_spec.rb +10 -6
- data/spec/rspec/shared_spec_matchers.rb +418 -364
- data/spec/rspec/views_spec.rb +4 -3
- data/spec/rspec_matchers_spec.rb +35 -10
- data/spec/rspec_spec.rb +109 -85
- data/spec/sauce_spec_chrome.rb +43 -0
- data/spec/selector_spec.rb +392 -62
- data/spec/selenium_spec_chrome.rb +183 -41
- data/spec/selenium_spec_chrome_remote.rb +96 -0
- data/spec/selenium_spec_edge.rb +41 -8
- data/spec/selenium_spec_firefox.rb +228 -0
- data/spec/selenium_spec_firefox_remote.rb +94 -0
- data/spec/selenium_spec_ie.rb +129 -11
- data/spec/selenium_spec_safari.rb +162 -0
- data/spec/server_spec.rb +192 -81
- data/spec/session_spec.rb +52 -16
- data/spec/shared_selenium_node.rb +79 -0
- data/spec/shared_selenium_session.rb +460 -123
- data/spec/spec_helper.rb +124 -2
- data/spec/whitespace_normalizer_spec.rb +54 -0
- data/spec/xpath_builder_spec.rb +93 -0
- metadata +344 -45
- data/.yard/templates_custom/default/class/html/selectors.erb +0 -38
- data/.yard/templates_custom/default/class/html/setup.rb +0 -17
- data/.yard/yard_extensions.rb +0 -78
- data/lib/capybara/rspec/compound.rb +0 -90
- data/lib/capybara/spec/session/assert_selector.rb +0 -149
- data/lib/capybara/spec/session/source_spec.rb +0 -0
- data/lib/capybara/spec/views/with_title.erb +0 -5
- data/spec/selenium_spec_marionette.rb +0 -143
@@ -1,50 +1,94 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
3
|
+
require 'uri'
|
4
|
+
require 'English'
|
5
5
|
|
6
6
|
class Capybara::Selenium::Driver < Capybara::Driver::Base
|
7
|
+
include Capybara::Selenium::Find
|
8
|
+
|
7
9
|
DEFAULT_OPTIONS = {
|
8
10
|
browser: :firefox,
|
9
|
-
clear_local_storage:
|
10
|
-
clear_session_storage:
|
11
|
+
clear_local_storage: nil,
|
12
|
+
clear_session_storage: nil
|
11
13
|
}.freeze
|
12
|
-
SPECIAL_OPTIONS = %i[browser clear_local_storage clear_session_storage].freeze
|
14
|
+
SPECIAL_OPTIONS = %i[browser clear_local_storage clear_session_storage timeout native_displayed].freeze
|
15
|
+
CAPS_VERSION = Gem::Requirement.new('< 4.8.0')
|
13
16
|
|
14
17
|
attr_reader :app, :options
|
15
18
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
19
|
+
class << self
|
20
|
+
attr_reader :selenium_webdriver_version
|
21
|
+
|
22
|
+
def load_selenium
|
23
|
+
require 'selenium-webdriver'
|
24
|
+
require 'capybara/selenium/patches/atoms'
|
25
|
+
require 'capybara/selenium/patches/is_displayed'
|
26
|
+
|
27
|
+
# Look up the version of `selenium-webdriver` to
|
28
|
+
# see if it's a version we support.
|
29
|
+
#
|
30
|
+
# By default, we use Gem.loaded_specs to determine
|
31
|
+
# the version number. However, in some cases, such
|
32
|
+
# as when loading `selenium-webdriver` outside of
|
33
|
+
# Rubygems, we fall back to referencing
|
34
|
+
# Selenium::WebDriver::VERSION. Ideally we'd
|
35
|
+
# use the constant in all cases, but earlier versions
|
36
|
+
# of `selenium-webdriver` didn't provide the constant.
|
37
|
+
@selenium_webdriver_version =
|
38
|
+
if Gem.loaded_specs['selenium-webdriver']
|
39
|
+
Gem.loaded_specs['selenium-webdriver'].version
|
40
|
+
else
|
41
|
+
Gem::Version.new(Selenium::WebDriver::VERSION)
|
42
|
+
end
|
43
|
+
|
44
|
+
unless Gem::Requirement.new('>= 4.8').satisfied_by? @selenium_webdriver_version
|
45
|
+
warn "Warning: You're using an unsupported version of selenium-webdriver, please upgrade to 4.8+."
|
21
46
|
end
|
22
47
|
|
23
|
-
@
|
24
|
-
|
48
|
+
@selenium_webdriver_version
|
49
|
+
rescue LoadError => e
|
50
|
+
raise e unless e.message.include?('selenium-webdriver')
|
51
|
+
|
52
|
+
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."
|
53
|
+
end
|
25
54
|
|
26
|
-
|
27
|
-
(defined?(Selenium::WebDriver::Remote::W3C::Capabilities) && @browser.capabilities.is_a?(Selenium::WebDriver::Remote::W3C::Capabilities)))
|
28
|
-
main = Process.pid
|
55
|
+
attr_reader :specializations
|
29
56
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
57
|
+
def register_specialization(browser_name, specialization)
|
58
|
+
@specializations ||= {}
|
59
|
+
@specializations[browser_name] = specialization
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def browser
|
64
|
+
unless @browser
|
65
|
+
options[:http_client] ||= begin
|
66
|
+
require 'capybara/selenium/patches/persistent_client'
|
67
|
+
if options[:timeout]
|
68
|
+
::Capybara::Selenium::PersistentClient.new(read_timeout: options[:timeout])
|
69
|
+
else
|
70
|
+
::Capybara::Selenium::PersistentClient.new
|
71
|
+
end
|
35
72
|
end
|
73
|
+
processed_options = options.except(*SPECIAL_OPTIONS)
|
74
|
+
|
75
|
+
@browser = Selenium::WebDriver.for(options[:browser], processed_options)
|
76
|
+
|
77
|
+
specialize_driver
|
78
|
+
setup_exit_handler
|
36
79
|
end
|
37
80
|
@browser
|
38
81
|
end
|
39
82
|
|
40
83
|
def initialize(app, **options)
|
41
|
-
|
42
|
-
|
84
|
+
super()
|
85
|
+
self.class.load_selenium
|
43
86
|
@app = app
|
44
87
|
@browser = nil
|
45
88
|
@exit_status = nil
|
46
|
-
@frame_handles = {}
|
89
|
+
@frame_handles = Hash.new { |hash, handle| hash[handle] = [] }
|
47
90
|
@options = DEFAULT_OPTIONS.merge(options)
|
91
|
+
@node_class = ::Capybara::Selenium::Node
|
48
92
|
end
|
49
93
|
|
50
94
|
def visit(path)
|
@@ -65,6 +109,8 @@ class Capybara::Selenium::Driver < Capybara::Driver::Base
|
|
65
109
|
|
66
110
|
def html
|
67
111
|
browser.page_source
|
112
|
+
rescue Selenium::WebDriver::Error::JavascriptError => e
|
113
|
+
raise unless e.message.include?('documentElement is null')
|
68
114
|
end
|
69
115
|
|
70
116
|
def title
|
@@ -75,19 +121,11 @@ class Capybara::Selenium::Driver < Capybara::Driver::Base
|
|
75
121
|
browser.current_url
|
76
122
|
end
|
77
123
|
|
78
|
-
def find_xpath(selector)
|
79
|
-
browser.find_elements(:xpath, selector).map { |node| Capybara::Selenium::Node.new(self, node) }
|
80
|
-
end
|
81
|
-
|
82
|
-
def find_css(selector)
|
83
|
-
browser.find_elements(:css, selector).map { |node| Capybara::Selenium::Node.new(self, node) }
|
84
|
-
end
|
85
|
-
|
86
124
|
def wait?; true; end
|
87
125
|
def needs_server?; true; end
|
88
126
|
|
89
127
|
def execute_script(script, *args)
|
90
|
-
browser.execute_script(script, *args
|
128
|
+
browser.execute_script(script, *native_args(args))
|
91
129
|
end
|
92
130
|
|
93
131
|
def evaluate_script(script, *args)
|
@@ -97,86 +135,69 @@ class Capybara::Selenium::Driver < Capybara::Driver::Base
|
|
97
135
|
|
98
136
|
def evaluate_async_script(script, *args)
|
99
137
|
browser.manage.timeouts.script_timeout = Capybara.default_max_wait_time
|
100
|
-
result = browser.execute_async_script(script, *args
|
138
|
+
result = browser.execute_async_script(script, *native_args(args))
|
101
139
|
unwrap_script_result(result)
|
102
140
|
end
|
103
141
|
|
104
|
-
def
|
105
|
-
|
142
|
+
def active_element
|
143
|
+
build_node(native_active_element)
|
144
|
+
end
|
145
|
+
|
146
|
+
def send_keys(*args)
|
147
|
+
# Should this call the specialized nodes rather than native???
|
148
|
+
native_active_element.send_keys(*args)
|
149
|
+
end
|
150
|
+
|
151
|
+
def save_screenshot(path, **options)
|
152
|
+
browser.save_screenshot(path, **options)
|
106
153
|
end
|
107
154
|
|
108
155
|
def reset!
|
109
156
|
# Use instance variable directly so we avoid starting the browser just to reset the session
|
110
157
|
return unless @browser
|
111
158
|
|
112
|
-
if firefox? || chrome?
|
113
|
-
switch_to_window(window_handles.first)
|
114
|
-
window_handles.slice(1..-1).each { |win| close_window(win) }
|
115
|
-
end
|
116
|
-
|
117
159
|
navigated = false
|
118
|
-
|
160
|
+
timer = Capybara::Helpers.timer(expire_in: 10)
|
119
161
|
begin
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
begin
|
124
|
-
@browser.manage.delete_all_cookies
|
125
|
-
clear_storage
|
126
|
-
rescue Selenium::WebDriver::Error::UnhandledError
|
127
|
-
# delete_all_cookies fails when we've previously gone
|
128
|
-
# to about:blank, so we rescue this error and do nothing
|
129
|
-
# instead.
|
130
|
-
end
|
131
|
-
@browser.navigate.to("about:blank")
|
132
|
-
end
|
162
|
+
# Only trigger a navigation if we haven't done it already, otherwise it
|
163
|
+
# can trigger an endless series of unload modals
|
164
|
+
reset_browser_state unless navigated
|
133
165
|
navigated = true
|
134
|
-
|
135
166
|
# Ensure the page is empty and trigger an UnhandledAlertError for any modals that appear during unload
|
136
|
-
|
137
|
-
|
138
|
-
sleep 0.05
|
139
|
-
end
|
140
|
-
rescue Selenium::WebDriver::Error::UnhandledAlertError, Selenium::WebDriver::Error::UnexpectedAlertOpenError
|
167
|
+
wait_for_empty_page(timer)
|
168
|
+
rescue *unhandled_alert_errors
|
141
169
|
# This error is thrown if an unhandled alert is on the page
|
142
170
|
# Firefox appears to automatically dismiss this alert, chrome does not
|
143
171
|
# We'll try to accept it
|
144
|
-
|
145
|
-
@browser.switch_to.alert.accept
|
146
|
-
sleep 0.25 # allow time for the modal to be handled
|
147
|
-
rescue modal_error
|
148
|
-
# The alert is now gone
|
149
|
-
if current_url != "about:blank"
|
150
|
-
begin
|
151
|
-
# If navigation has not occurred attempt again and accept alert
|
152
|
-
# since FF may have dismissed the alert at first attempt
|
153
|
-
@browser.navigate.to("about:blank")
|
154
|
-
sleep 0.1 # slight wait for alert
|
155
|
-
@browser.switch_to.alert.accept
|
156
|
-
rescue modal_error # rubocop:disable Metrics/BlockNesting
|
157
|
-
# alert now gone, should mean navigation happened
|
158
|
-
end
|
159
|
-
end
|
160
|
-
end
|
172
|
+
accept_unhandled_reset_alert
|
161
173
|
# try cleaning up the browser again
|
162
174
|
retry
|
163
175
|
end
|
164
176
|
end
|
165
177
|
|
178
|
+
def frame_obscured_at?(x:, y:)
|
179
|
+
frame = @frame_handles[current_window_handle].last
|
180
|
+
return false unless frame
|
181
|
+
|
182
|
+
switch_to_frame(:parent)
|
183
|
+
begin
|
184
|
+
frame.base.obscured?(x: x, y: y)
|
185
|
+
ensure
|
186
|
+
switch_to_frame(frame)
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
166
190
|
def switch_to_frame(frame)
|
191
|
+
handles = @frame_handles[current_window_handle]
|
167
192
|
case frame
|
168
193
|
when :top
|
169
|
-
|
194
|
+
handles.clear
|
170
195
|
browser.switch_to.default_content
|
171
196
|
when :parent
|
172
|
-
|
173
|
-
|
174
|
-
@frame_handles[browser.window_handle].pop
|
175
|
-
browser.switch_to.default_content
|
176
|
-
@frame_handles[browser.window_handle].each { |fh| browser.switch_to.frame(fh) }
|
197
|
+
handles.pop
|
198
|
+
browser.switch_to.parent_frame
|
177
199
|
else
|
178
|
-
|
179
|
-
@frame_handles[browser.window_handle] << frame.native
|
200
|
+
handles << frame
|
180
201
|
browser.switch_to.frame(frame.native)
|
181
202
|
end
|
182
203
|
end
|
@@ -194,12 +215,7 @@ class Capybara::Selenium::Driver < Capybara::Driver::Base
|
|
194
215
|
|
195
216
|
def resize_window_to(handle, width, height)
|
196
217
|
within_given_window(handle) do
|
197
|
-
|
198
|
-
if marionette? && (window_size(handle) == [width, height])
|
199
|
-
{}
|
200
|
-
else
|
201
|
-
browser.manage.window.resize_to(width, height)
|
202
|
-
end
|
218
|
+
browser.manage.window.resize_to(width, height)
|
203
219
|
end
|
204
220
|
end
|
205
221
|
|
@@ -210,8 +226,15 @@ class Capybara::Selenium::Driver < Capybara::Driver::Base
|
|
210
226
|
sleep 0.1 # work around for https://code.google.com/p/selenium/issues/detail?id=7405
|
211
227
|
end
|
212
228
|
|
229
|
+
def fullscreen_window(handle)
|
230
|
+
within_given_window(handle) do
|
231
|
+
browser.manage.window.full_screen
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
213
235
|
def close_window(handle)
|
214
|
-
raise ArgumentError,
|
236
|
+
raise ArgumentError, 'Not allowed to close the primary window' if handle == window_handles.first
|
237
|
+
|
215
238
|
within_given_window(handle) do
|
216
239
|
browser.close
|
217
240
|
end
|
@@ -221,7 +244,16 @@ class Capybara::Selenium::Driver < Capybara::Driver::Base
|
|
221
244
|
browser.window_handles
|
222
245
|
end
|
223
246
|
|
224
|
-
def open_new_window
|
247
|
+
def open_new_window(kind = :tab)
|
248
|
+
if browser.switch_to.respond_to?(:new_window)
|
249
|
+
handle = current_window_handle
|
250
|
+
browser.switch_to.new_window(kind)
|
251
|
+
switch_to_window(handle)
|
252
|
+
else
|
253
|
+
browser.manage.new_window(kind)
|
254
|
+
end
|
255
|
+
rescue NoMethodError, Selenium::WebDriver::Error::WebDriverError
|
256
|
+
# If not supported by the driver or browser default to using JS
|
225
257
|
browser.execute_script('window.open();')
|
226
258
|
end
|
227
259
|
|
@@ -231,7 +263,7 @@ class Capybara::Selenium::Driver < Capybara::Driver::Base
|
|
231
263
|
|
232
264
|
def accept_modal(_type, **options)
|
233
265
|
yield if block_given?
|
234
|
-
modal = find_modal(options)
|
266
|
+
modal = find_modal(**options)
|
235
267
|
|
236
268
|
modal.send_keys options[:with] if options[:with]
|
237
269
|
|
@@ -242,15 +274,16 @@ class Capybara::Selenium::Driver < Capybara::Driver::Base
|
|
242
274
|
|
243
275
|
def dismiss_modal(_type, **options)
|
244
276
|
yield if block_given?
|
245
|
-
modal = find_modal(options)
|
277
|
+
modal = find_modal(**options)
|
246
278
|
message = modal.text
|
247
279
|
modal.dismiss
|
248
280
|
message
|
249
281
|
end
|
250
282
|
|
251
283
|
def quit
|
252
|
-
@browser
|
253
|
-
rescue Selenium::WebDriver::Error::SessionNotCreatedError, Errno::ECONNREFUSED
|
284
|
+
@browser&.quit
|
285
|
+
rescue Selenium::WebDriver::Error::SessionNotCreatedError, Errno::ECONNREFUSED,
|
286
|
+
Selenium::WebDriver::Error::InvalidSessionIdError
|
254
287
|
# Browser must have already gone
|
255
288
|
rescue Selenium::WebDriver::Error::UnknownError => e
|
256
289
|
unless silenced_unknown_error_message?(e.message) # Most likely already gone
|
@@ -262,133 +295,101 @@ class Capybara::Selenium::Driver < Capybara::Driver::Base
|
|
262
295
|
end
|
263
296
|
|
264
297
|
def invalid_element_errors
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
298
|
+
@invalid_element_errors ||=
|
299
|
+
[
|
300
|
+
::Selenium::WebDriver::Error::StaleElementReferenceError,
|
301
|
+
::Selenium::WebDriver::Error::ElementNotInteractableError,
|
302
|
+
::Selenium::WebDriver::Error::InvalidSelectorError, # Work around chromedriver go_back/go_forward race condition
|
303
|
+
::Selenium::WebDriver::Error::ElementClickInterceptedError,
|
304
|
+
::Selenium::WebDriver::Error::NoSuchElementError, # IE
|
305
|
+
::Selenium::WebDriver::Error::InvalidArgumentError # IE
|
306
|
+
].tap do |errors|
|
307
|
+
if defined?(::Selenium::WebDriver::Error::DetachedShadowRootError)
|
308
|
+
errors.push(::Selenium::WebDriver::Error::DetachedShadowRootError)
|
309
|
+
end
|
310
|
+
end
|
278
311
|
end
|
279
312
|
|
280
313
|
def no_such_window_error
|
281
314
|
Selenium::WebDriver::Error::NoSuchWindowError
|
282
315
|
end
|
283
316
|
|
284
|
-
|
285
|
-
def marionette?
|
286
|
-
firefox? && browser && @w3c
|
287
|
-
end
|
317
|
+
private
|
288
318
|
|
289
|
-
|
290
|
-
|
291
|
-
browser_name == "firefox"
|
319
|
+
def native_args(args)
|
320
|
+
args.map { |arg| arg.is_a?(Capybara::Selenium::Node) ? arg.native : arg }
|
292
321
|
end
|
293
322
|
|
294
|
-
|
295
|
-
|
296
|
-
browser_name == "chrome"
|
323
|
+
def native_active_element
|
324
|
+
browser.switch_to.active_element
|
297
325
|
end
|
298
326
|
|
299
|
-
|
300
|
-
|
301
|
-
|
327
|
+
def clear_browser_state
|
328
|
+
delete_all_cookies
|
329
|
+
clear_storage
|
330
|
+
rescue *clear_browser_state_errors
|
331
|
+
# delete_all_cookies fails when we've previously gone
|
332
|
+
# to about:blank, so we rescue this error and do nothing
|
333
|
+
# instead.
|
302
334
|
end
|
303
335
|
|
304
|
-
|
305
|
-
|
306
|
-
browser_name == "ie"
|
336
|
+
def clear_browser_state_errors
|
337
|
+
@clear_browser_state_errors ||= [Selenium::WebDriver::Error::UnknownError]
|
307
338
|
end
|
308
339
|
|
309
|
-
|
340
|
+
def unhandled_alert_errors
|
341
|
+
@unhandled_alert_errors ||= [Selenium::WebDriver::Error::UnexpectedAlertOpenError]
|
342
|
+
end
|
310
343
|
|
311
|
-
def
|
312
|
-
|
344
|
+
def delete_all_cookies
|
345
|
+
@browser.manage.delete_all_cookies
|
313
346
|
end
|
314
347
|
|
315
348
|
def clear_storage
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
warn "sessionStorage clear requested but is not available for this driver"
|
321
|
-
end
|
322
|
-
end
|
323
|
-
if options[:clear_local_storage]
|
324
|
-
if @browser.respond_to? :local_storage
|
325
|
-
@browser.local_storage.clear
|
326
|
-
else
|
327
|
-
warn "localStorage clear requested but is not available for this driver"
|
328
|
-
end
|
329
|
-
end
|
349
|
+
clear_session_storage unless options[:clear_session_storage] == false
|
350
|
+
clear_local_storage unless options[:clear_local_storage] == false
|
351
|
+
rescue Selenium::WebDriver::Error::JavascriptError
|
352
|
+
# session/local storage may not be available if on non-http pages (e.g. about:blank)
|
330
353
|
end
|
331
354
|
|
332
|
-
def
|
333
|
-
if
|
334
|
-
|
355
|
+
def clear_session_storage
|
356
|
+
if @browser.respond_to? :session_storage
|
357
|
+
@browser.session_storage.clear
|
335
358
|
else
|
336
|
-
|
359
|
+
begin
|
360
|
+
@browser&.execute_script('window.sessionStorage.clear()')
|
361
|
+
rescue # rubocop:disable Style/RescueStandardError
|
362
|
+
unless options[:clear_session_storage].nil?
|
363
|
+
warn 'sessionStorage clear requested but is not supported by this driver'
|
364
|
+
end
|
365
|
+
end
|
337
366
|
end
|
338
367
|
end
|
339
368
|
|
340
|
-
def
|
341
|
-
|
342
|
-
|
343
|
-
"default_text"
|
344
|
-
else
|
345
|
-
"'#{response_text.gsub("\\", "\\\\\\").gsub("'", "\\\\'")}'"
|
346
|
-
end
|
369
|
+
def clear_local_storage
|
370
|
+
if @browser.respond_to? :local_storage
|
371
|
+
@browser.local_storage.clear
|
347
372
|
else
|
348
|
-
|
373
|
+
begin
|
374
|
+
@browser&.execute_script('window.localStorage.clear()')
|
375
|
+
rescue # rubocop:disable Style/RescueStandardError
|
376
|
+
unless options[:clear_local_storage].nil?
|
377
|
+
warn 'localStorage clear requested but is not supported by this driver'
|
378
|
+
end
|
379
|
+
end
|
349
380
|
end
|
381
|
+
end
|
350
382
|
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
remove_handler: function(handler) {
|
362
|
-
window.alert = handler.alert;
|
363
|
-
window.confirm = handler.confirm;
|
364
|
-
window.prompt = handler.prompt;
|
365
|
-
},
|
366
|
-
handler_called: function(handler, str) {
|
367
|
-
handler.called = true;
|
368
|
-
handler.modal_text = str;
|
369
|
-
this.remove_handler(handler);
|
370
|
-
}
|
371
|
-
};
|
372
|
-
};
|
373
|
-
|
374
|
-
var modal_handler = {
|
375
|
-
prompt: window.prompt,
|
376
|
-
confirm: window.confirm,
|
377
|
-
alert: window.alert,
|
378
|
-
called: false
|
379
|
-
}
|
380
|
-
window.capybara.add_handler(modal_handler);
|
381
|
-
|
382
|
-
window.alert = window.confirm = function(str = "") {
|
383
|
-
window.capybara.handler_called(modal_handler, str.toString());
|
384
|
-
return #{accept ? 'true' : 'false'};
|
385
|
-
}
|
386
|
-
window.prompt = function(str = "", default_text = "") {
|
387
|
-
window.capybara.handler_called(modal_handler, str.toString());
|
388
|
-
return #{prompt_response};
|
389
|
-
}
|
390
|
-
JS
|
391
|
-
execute_script script
|
383
|
+
def navigate_with_accept(url)
|
384
|
+
@browser.navigate.to(url)
|
385
|
+
sleep 0.1 # slight wait for alert
|
386
|
+
@browser.switch_to.alert.accept
|
387
|
+
rescue modal_error
|
388
|
+
# alert now gone, should mean navigation happened
|
389
|
+
end
|
390
|
+
|
391
|
+
def modal_error
|
392
|
+
Selenium::WebDriver::Error::NoSuchAlertError
|
392
393
|
end
|
393
394
|
|
394
395
|
def within_given_window(handle)
|
@@ -413,47 +414,25 @@ private
|
|
413
414
|
begin
|
414
415
|
wait.until do
|
415
416
|
alert = @browser.switch_to.alert
|
416
|
-
regexp = text.is_a?(Regexp) ? text : Regexp.escape(text.to_s)
|
417
|
-
alert.text.match(regexp)
|
417
|
+
regexp = text.is_a?(Regexp) ? text : Regexp.new(Regexp.escape(text.to_s))
|
418
|
+
matched = alert.text.match?(regexp)
|
419
|
+
unless matched
|
420
|
+
raise Capybara::ModalNotFound, "Unable to find modal dialog with #{text} - found '#{alert.text}' instead."
|
421
|
+
end
|
422
|
+
|
423
|
+
alert
|
418
424
|
end
|
419
|
-
rescue
|
425
|
+
rescue *find_modal_errors
|
420
426
|
raise Capybara::ModalNotFound, "Unable to find modal dialog#{" with #{text}" if text}"
|
421
427
|
end
|
422
428
|
end
|
423
429
|
|
424
|
-
def
|
425
|
-
|
426
|
-
# Actual wait time may be longer than specified
|
427
|
-
wait = Selenium::WebDriver::Wait.new(
|
428
|
-
timeout: options.fetch(:wait, session_options.default_max_wait_time) || 0,
|
429
|
-
ignore: modal_error
|
430
|
-
)
|
431
|
-
begin
|
432
|
-
wait.until do
|
433
|
-
called, alert_text = evaluate_script('window.capybara && window.capybara.current_modal_status()')
|
434
|
-
if called
|
435
|
-
execute_script('window.capybara && window.capybara.modal_handlers.shift()')
|
436
|
-
regexp = text.is_a?(Regexp) ? text : Regexp.escape(text.to_s)
|
437
|
-
if alert_text.match(regexp)
|
438
|
-
alert_text
|
439
|
-
else
|
440
|
-
raise Capybara::ModalNotFound, "Unable to find modal dialog#{" with #{text}" if text}"
|
441
|
-
end
|
442
|
-
elsif called.nil?
|
443
|
-
# page changed so modal_handler data has gone away
|
444
|
-
warn "Can't verify modal text when page change occurs - ignoring" if options[:text]
|
445
|
-
""
|
446
|
-
else
|
447
|
-
nil
|
448
|
-
end
|
449
|
-
end
|
450
|
-
rescue Selenium::WebDriver::Error::TimeOutError
|
451
|
-
raise Capybara::ModalNotFound, "Unable to find modal dialog#{" with #{options[:text]}" if options[:text]}"
|
452
|
-
end
|
430
|
+
def find_modal_errors
|
431
|
+
@find_modal_errors ||= [Selenium::WebDriver::Error::TimeoutError]
|
453
432
|
end
|
454
433
|
|
455
434
|
def silenced_unknown_error_message?(msg)
|
456
|
-
silenced_unknown_error_messages.any? { |
|
435
|
+
silenced_unknown_error_messages.any? { |regex| msg.match? regex }
|
457
436
|
end
|
458
437
|
|
459
438
|
def silenced_unknown_error_messages
|
@@ -463,30 +442,76 @@ private
|
|
463
442
|
def unwrap_script_result(arg)
|
464
443
|
case arg
|
465
444
|
when Array
|
466
|
-
arg.map { |
|
445
|
+
arg.map { |arr| unwrap_script_result(arr) }
|
467
446
|
when Hash
|
468
|
-
arg.
|
469
|
-
when Selenium::WebDriver::Element
|
470
|
-
|
447
|
+
arg.transform_values! { |value| unwrap_script_result(value) }
|
448
|
+
when Selenium::WebDriver::Element, Selenium::WebDriver::ShadowRoot
|
449
|
+
build_node(arg)
|
471
450
|
else
|
472
451
|
arg
|
473
452
|
end
|
474
453
|
end
|
475
454
|
|
476
|
-
def
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
455
|
+
def find_context
|
456
|
+
browser
|
457
|
+
end
|
458
|
+
|
459
|
+
def build_node(native_node, initial_cache = {})
|
460
|
+
::Capybara::Selenium::Node.new(self, native_node, initial_cache)
|
461
|
+
end
|
462
|
+
|
463
|
+
def bridge
|
464
|
+
browser.send(:bridge)
|
465
|
+
end
|
466
|
+
|
467
|
+
def specialize_driver
|
468
|
+
browser_type = browser.browser
|
469
|
+
Capybara::Selenium::Driver.specializations.select { |k, _v| k === browser_type }.each_value do |specialization| # rubocop:disable Style/CaseEquality
|
470
|
+
extend specialization
|
481
471
|
end
|
482
|
-
|
483
|
-
|
472
|
+
end
|
473
|
+
|
474
|
+
def setup_exit_handler
|
475
|
+
main = Process.pid
|
476
|
+
at_exit do
|
477
|
+
# Store the exit status of the test run since it goes away after calling the at_exit proc...
|
478
|
+
@exit_status = $ERROR_INFO.status if $ERROR_INFO.is_a?(SystemExit)
|
479
|
+
quit if Process.pid == main
|
480
|
+
exit @exit_status if @exit_status # Force exit with stored status
|
484
481
|
end
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
482
|
+
end
|
483
|
+
|
484
|
+
def reset_browser_state
|
485
|
+
clear_browser_state
|
486
|
+
@browser.navigate.to('about:blank')
|
487
|
+
end
|
488
|
+
|
489
|
+
def wait_for_empty_page(timer)
|
490
|
+
until find_xpath('/html/body/*').empty?
|
491
|
+
raise Capybara::ExpectationNotMet, 'Timed out waiting for Selenium session reset' if timer.expired?
|
492
|
+
|
493
|
+
sleep 0.01
|
494
|
+
|
495
|
+
# It has been observed that it is possible that asynchronous JS code in
|
496
|
+
# the application under test can navigate the browser away from about:blank
|
497
|
+
# if the timing is just right. Ensure we are still at about:blank...
|
498
|
+
@browser.navigate.to('about:blank') unless current_url == 'about:blank'
|
490
499
|
end
|
491
500
|
end
|
501
|
+
|
502
|
+
def accept_unhandled_reset_alert
|
503
|
+
@browser.switch_to.alert.accept
|
504
|
+
sleep 0.25 # allow time for the modal to be handled
|
505
|
+
rescue modal_error
|
506
|
+
# The alert is now gone.
|
507
|
+
# If navigation has not occurred attempt again and accept alert
|
508
|
+
# since FF may have dismissed the alert at first attempt.
|
509
|
+
navigate_with_accept('about:blank') if current_url != 'about:blank'
|
510
|
+
end
|
492
511
|
end
|
512
|
+
|
513
|
+
require 'capybara/selenium/driver_specializations/chrome_driver'
|
514
|
+
require 'capybara/selenium/driver_specializations/firefox_driver'
|
515
|
+
require 'capybara/selenium/driver_specializations/internet_explorer_driver'
|
516
|
+
require 'capybara/selenium/driver_specializations/safari_driver'
|
517
|
+
require 'capybara/selenium/driver_specializations/edge_driver'
|