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