capybara 2.18.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 +945 -12
- data/License.txt +1 -1
- data/README.md +264 -90
- data/lib/capybara/config.rb +29 -57
- data/lib/capybara/cucumber.rb +2 -3
- data/lib/capybara/driver/base.rb +35 -18
- data/lib/capybara/driver/node.rb +40 -10
- data/lib/capybara/dsl.rb +10 -7
- data/lib/capybara/helpers.rb +70 -31
- data/lib/capybara/minitest/spec.rb +185 -83
- data/lib/capybara/minitest.rb +232 -112
- data/lib/capybara/node/actions.rb +274 -171
- data/lib/capybara/node/base.rb +42 -34
- data/lib/capybara/node/document.rb +15 -3
- data/lib/capybara/node/document_matchers.rb +19 -21
- data/lib/capybara/node/element.rb +362 -135
- data/lib/capybara/node/finders.rb +151 -137
- data/lib/capybara/node/matchers.rb +394 -209
- data/lib/capybara/node/simple.rb +59 -26
- 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 +12 -9
- data/lib/capybara/queries/base_query.rb +39 -28
- data/lib/capybara/queries/current_path_query.rb +21 -27
- data/lib/capybara/queries/match_query.rb +14 -7
- data/lib/capybara/queries/selector_query.rb +659 -149
- data/lib/capybara/queries/sibling_query.rb +11 -9
- data/lib/capybara/queries/style_query.rb +45 -0
- data/lib/capybara/queries/text_query.rb +56 -38
- data/lib/capybara/queries/title_query.rb +8 -11
- data/lib/capybara/rack_test/browser.rb +114 -42
- data/lib/capybara/rack_test/css_handlers.rb +6 -4
- data/lib/capybara/rack_test/driver.rb +22 -17
- data/lib/capybara/rack_test/errors.rb +6 -0
- data/lib/capybara/rack_test/form.rb +93 -58
- data/lib/capybara/rack_test/node.rb +184 -81
- data/lib/capybara/rails.rb +3 -7
- 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 +97 -63
- data/lib/capybara/rspec/features.rb +17 -50
- data/lib/capybara/rspec/matcher_proxies.rb +52 -15
- 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 +146 -310
- data/lib/capybara/rspec.rb +7 -11
- 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 -13
- 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 +2 -17
- data/lib/capybara/selector/filter_set.rb +80 -33
- data/lib/capybara/selector/filters/base.rb +50 -6
- data/lib/capybara/selector/filters/expression_filter.rb +8 -26
- data/lib/capybara/selector/filters/locator_filter.rb +29 -0
- data/lib/capybara/selector/filters/node_filter.rb +16 -12
- data/lib/capybara/selector/regexp_disassembler.rb +211 -0
- data/lib/capybara/selector/selector.rb +93 -210
- data/lib/capybara/selector/xpath_extensions.rb +17 -0
- data/lib/capybara/selector.rb +475 -523
- 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 +298 -267
- 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 +517 -145
- 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 +59 -67
- data/lib/capybara/session/config.rb +81 -67
- data/lib/capybara/session/matchers.rb +28 -20
- data/lib/capybara/session.rb +337 -365
- 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 +151 -12
- data/lib/capybara/spec/session/accept_alert_spec.rb +12 -11
- data/lib/capybara/spec/session/accept_confirm_spec.rb +6 -5
- data/lib/capybara/spec/session/accept_prompt_spec.rb +10 -10
- data/lib/capybara/spec/session/active_element_spec.rb +31 -0
- data/lib/capybara/spec/session/all_spec.rb +161 -57
- data/lib/capybara/spec/session/ancestor_spec.rb +27 -24
- data/lib/capybara/spec/session/assert_all_of_selectors_spec.rb +68 -38
- 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.rb → assert_title_spec.rb} +22 -12
- data/lib/capybara/spec/session/attach_file_spec.rb +144 -69
- data/lib/capybara/spec/session/body_spec.rb +12 -13
- data/lib/capybara/spec/session/check_spec.rb +117 -55
- data/lib/capybara/spec/session/choose_spec.rb +64 -31
- data/lib/capybara/spec/session/click_button_spec.rb +231 -173
- data/lib/capybara/spec/session/click_link_or_button_spec.rb +55 -35
- data/lib/capybara/spec/session/click_link_spec.rb +93 -58
- data/lib/capybara/spec/session/current_scope_spec.rb +12 -11
- data/lib/capybara/spec/session/current_url_spec.rb +57 -39
- data/lib/capybara/spec/session/dismiss_confirm_spec.rb +4 -4
- data/lib/capybara/spec/session/dismiss_prompt_spec.rb +3 -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 +9 -7
- data/lib/capybara/spec/session/element/matches_selector_spec.rb +71 -57
- data/lib/capybara/spec/session/evaluate_async_script_spec.rb +8 -7
- data/lib/capybara/spec/session/evaluate_script_spec.rb +29 -8
- data/lib/capybara/spec/session/execute_script_spec.rb +10 -8
- data/lib/capybara/spec/session/fill_in_spec.rb +134 -43
- data/lib/capybara/spec/session/find_button_spec.rb +25 -24
- data/lib/capybara/spec/session/find_by_id_spec.rb +10 -9
- data/lib/capybara/spec/session/find_field_spec.rb +37 -41
- data/lib/capybara/spec/session/find_link_spec.rb +46 -17
- data/lib/capybara/spec/session/find_spec.rb +260 -145
- data/lib/capybara/spec/session/first_spec.rb +80 -52
- 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 +33 -20
- data/lib/capybara/spec/session/frame/within_frame_spec.rb +52 -32
- data/lib/capybara/spec/session/go_back_spec.rb +2 -1
- data/lib/capybara/spec/session/go_forward_spec.rb +2 -1
- data/lib/capybara/spec/session/has_all_selectors_spec.rb +31 -31
- 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 +100 -13
- data/lib/capybara/spec/session/has_css_spec.rb +272 -137
- data/lib/capybara/spec/session/has_current_path_spec.rb +60 -61
- data/lib/capybara/spec/session/has_element_spec.rb +47 -0
- data/lib/capybara/spec/session/has_field_spec.rb +139 -59
- data/lib/capybara/spec/session/has_link_spec.rb +47 -6
- data/lib/capybara/spec/session/has_none_selectors_spec.rb +42 -40
- data/lib/capybara/spec/session/has_select_spec.rb +107 -72
- data/lib/capybara/spec/session/has_selector_spec.rb +120 -71
- data/lib/capybara/spec/session/has_sibling_spec.rb +50 -0
- data/lib/capybara/spec/session/has_table_spec.rb +183 -5
- data/lib/capybara/spec/session/has_text_spec.rb +106 -62
- data/lib/capybara/spec/session/has_title_spec.rb +20 -14
- data/lib/capybara/spec/session/has_xpath_spec.rb +57 -38
- 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 +37 -0
- data/lib/capybara/spec/session/node_spec.rb +1024 -153
- data/lib/capybara/spec/session/node_wrapper_spec.rb +39 -0
- data/lib/capybara/spec/session/refresh_spec.rb +12 -6
- data/lib/capybara/spec/session/reset_session_spec.rb +82 -35
- 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 +8 -12
- 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 +119 -0
- data/lib/capybara/spec/session/select_spec.rb +107 -81
- data/lib/capybara/spec/session/selectors_spec.rb +52 -19
- data/lib/capybara/spec/session/sibling_spec.rb +10 -10
- data/lib/capybara/spec/session/text_spec.rb +37 -21
- data/lib/capybara/spec/session/title_spec.rb +17 -5
- data/lib/capybara/spec/session/uncheck_spec.rb +43 -23
- data/lib/capybara/spec/session/unselect_spec.rb +39 -38
- data/lib/capybara/spec/session/visit_spec.rb +85 -53
- data/lib/capybara/spec/session/window/become_closed_spec.rb +24 -20
- 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 +27 -22
- data/lib/capybara/spec/session/window/window_opened_by_spec.rb +12 -6
- data/lib/capybara/spec/session/window/window_spec.rb +97 -63
- data/lib/capybara/spec/session/window/windows_spec.rb +12 -10
- data/lib/capybara/spec/session/window/within_window_spec.rb +31 -86
- data/lib/capybara/spec/session/within_spec.rb +83 -44
- data/lib/capybara/spec/spec_helper.rb +54 -44
- data/lib/capybara/spec/test_app.rb +158 -43
- data/lib/capybara/spec/views/animated.erb +49 -0
- data/lib/capybara/spec/views/form.erb +163 -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 +69 -12
- 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 +5 -2
- data/lib/capybara/version.rb +2 -1
- data/lib/capybara/window.rb +36 -34
- data/lib/capybara.rb +134 -107
- data/spec/basic_node_spec.rb +60 -34
- data/spec/capybara_spec.rb +63 -88
- 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 +85 -64
- data/spec/filter_set_spec.rb +27 -9
- data/spec/fixtures/certificate.pem +25 -0
- data/spec/fixtures/key.pem +27 -0
- data/spec/fixtures/selenium_driver_rspec_failure.rb +6 -5
- data/spec/fixtures/selenium_driver_rspec_success.rb +6 -5
- data/spec/minitest_spec.rb +52 -7
- data/spec/minitest_spec_spec.rb +94 -63
- data/spec/per_session_config_spec.rb +14 -13
- data/spec/rack_test_spec.rb +194 -125
- data/spec/regexp_dissassembler_spec.rb +250 -0
- data/spec/result_spec.rb +111 -50
- data/spec/rspec/features_spec.rb +37 -31
- data/spec/rspec/scenarios_spec.rb +10 -8
- data/spec/rspec/shared_spec_matchers.rb +473 -422
- data/spec/rspec/views_spec.rb +5 -3
- data/spec/rspec_matchers_spec.rb +52 -11
- data/spec/rspec_spec.rb +109 -89
- data/spec/sauce_spec_chrome.rb +43 -0
- data/spec/selector_spec.rb +397 -68
- data/spec/selenium_spec_chrome.rb +187 -40
- data/spec/selenium_spec_chrome_remote.rb +96 -0
- data/spec/selenium_spec_edge.rb +60 -0
- data/spec/selenium_spec_firefox.rb +201 -41
- data/spec/selenium_spec_firefox_remote.rb +94 -0
- data/spec/selenium_spec_ie.rb +149 -0
- data/spec/selenium_spec_safari.rb +162 -0
- data/spec/server_spec.rb +213 -102
- data/spec/session_spec.rb +53 -16
- data/spec/shared_selenium_node.rb +79 -0
- data/spec/shared_selenium_session.rb +473 -122
- data/spec/spec_helper.rb +126 -7
- data/spec/whitespace_normalizer_spec.rb +54 -0
- data/spec/xpath_builder_spec.rb +93 -0
- metadata +355 -73
- 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/query.rb +0 -7
- data/lib/capybara/rspec/compound.rb +0 -95
- data/lib/capybara/spec/session/assert_current_path.rb +0 -72
- data/lib/capybara/spec/session/assert_selector.rb +0 -148
- data/lib/capybara/spec/session/assert_text.rb +0 -234
- 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 -127
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
+
|
|
2
3
|
module Capybara
|
|
3
4
|
module Node
|
|
4
|
-
|
|
5
5
|
##
|
|
6
6
|
#
|
|
7
7
|
# A {Capybara::Node::Element} represents a single element on the page. It is possible
|
|
@@ -22,15 +22,16 @@ module Capybara
|
|
|
22
22
|
# @see Capybara::Node
|
|
23
23
|
#
|
|
24
24
|
class Element < Base
|
|
25
|
-
|
|
26
25
|
def initialize(session, base, query_scope, query)
|
|
27
26
|
super(session, base)
|
|
28
27
|
@query_scope = query_scope
|
|
29
28
|
@query = query
|
|
30
29
|
@allow_reload = false
|
|
30
|
+
@query_idx = nil
|
|
31
31
|
end
|
|
32
32
|
|
|
33
|
-
def allow_reload!
|
|
33
|
+
def allow_reload!(idx = nil)
|
|
34
|
+
@query_idx = idx
|
|
34
35
|
@allow_reload = true
|
|
35
36
|
end
|
|
36
37
|
|
|
@@ -44,30 +45,25 @@ module Capybara
|
|
|
44
45
|
|
|
45
46
|
##
|
|
46
47
|
#
|
|
47
|
-
# Retrieve the text of the element. If
|
|
48
|
+
# Retrieve the text of the element. If {Capybara.configure ignore_hidden_elements}
|
|
48
49
|
# is `true`, which it is by default, then this will return only text
|
|
49
50
|
# which is visible. The exact semantics of this may differ between
|
|
50
51
|
# drivers, but generally any text within elements with `display:none` is
|
|
51
52
|
# ignored. This behaviour can be overridden by passing `:all` to this
|
|
52
53
|
# method.
|
|
53
54
|
#
|
|
54
|
-
# @param [:all, :visible]
|
|
55
|
+
# @param type [:all, :visible] Whether to return only visible or all text
|
|
55
56
|
# @return [String] The text of the element
|
|
56
57
|
#
|
|
57
|
-
def text(type=nil)
|
|
58
|
-
type ||= :all unless session_options.ignore_hidden_elements
|
|
59
|
-
synchronize
|
|
60
|
-
|
|
61
|
-
base.all_text
|
|
62
|
-
else
|
|
63
|
-
base.visible_text
|
|
64
|
-
end
|
|
65
|
-
end
|
|
58
|
+
def text(type = nil, normalize_ws: false)
|
|
59
|
+
type ||= :all unless session_options.ignore_hidden_elements || session_options.visible_text_only
|
|
60
|
+
txt = synchronize { type == :all ? base.all_text : base.visible_text }
|
|
61
|
+
normalize_ws ? txt.gsub(/[[:space:]]+/, ' ').strip : txt
|
|
66
62
|
end
|
|
67
63
|
|
|
68
64
|
##
|
|
69
65
|
#
|
|
70
|
-
# Retrieve the given attribute
|
|
66
|
+
# Retrieve the given attribute.
|
|
71
67
|
#
|
|
72
68
|
# element[:title] # => HTML title attribute
|
|
73
69
|
#
|
|
@@ -78,6 +74,30 @@ module Capybara
|
|
|
78
74
|
synchronize { base[attribute] }
|
|
79
75
|
end
|
|
80
76
|
|
|
77
|
+
##
|
|
78
|
+
#
|
|
79
|
+
# Retrieve the given CSS styles.
|
|
80
|
+
#
|
|
81
|
+
# element.style('color', 'font-size') # => Computed values of CSS 'color' and 'font-size' styles
|
|
82
|
+
#
|
|
83
|
+
# @param [Array<String>] styles Names of the desired CSS properties
|
|
84
|
+
# @return [Hash] Hash of the CSS property names to computed values
|
|
85
|
+
#
|
|
86
|
+
def style(*styles)
|
|
87
|
+
styles = styles.flatten.map(&:to_s)
|
|
88
|
+
raise ArgumentError, 'You must specify at least one CSS style' if styles.empty?
|
|
89
|
+
|
|
90
|
+
begin
|
|
91
|
+
synchronize { base.style(styles) }
|
|
92
|
+
rescue NotImplementedError => e
|
|
93
|
+
begin
|
|
94
|
+
evaluate_script(STYLE_SCRIPT, *styles)
|
|
95
|
+
rescue Capybara::NotSupportedByDriverError
|
|
96
|
+
raise e
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
81
101
|
##
|
|
82
102
|
#
|
|
83
103
|
# @return [String] The value of the form element
|
|
@@ -91,163 +111,179 @@ module Capybara
|
|
|
91
111
|
# Set the value of the form element to the given value.
|
|
92
112
|
#
|
|
93
113
|
# @param [String] value The new value
|
|
94
|
-
# @param [Hash
|
|
114
|
+
# @param [Hash] options Driver specific options for how to set the value. Take default values from {Capybara.configure default_set_options}.
|
|
95
115
|
#
|
|
96
116
|
# @return [Capybara::Node::Element] The element
|
|
97
|
-
def set(value, options
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
driver_supports_options = (base.method(:set).arity != 1)
|
|
101
|
-
|
|
102
|
-
unless options.empty? || driver_supports_options
|
|
103
|
-
warn "Options passed to Capybara::Node#set but the driver doesn't support them"
|
|
117
|
+
def set(value, **options)
|
|
118
|
+
if ENV.fetch('CAPYBARA_THOROUGH', nil) && readonly?
|
|
119
|
+
raise Capybara::ReadOnlyElementError, "Attempt to set readonly element with value: #{value}"
|
|
104
120
|
end
|
|
105
121
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
else
|
|
110
|
-
base.set(value)
|
|
111
|
-
end
|
|
112
|
-
end
|
|
113
|
-
return self
|
|
122
|
+
options = session_options.default_set_options.to_h.merge(options)
|
|
123
|
+
synchronize { base.set(value, **options) }
|
|
124
|
+
self
|
|
114
125
|
end
|
|
115
126
|
|
|
116
127
|
##
|
|
117
128
|
#
|
|
118
|
-
# Select this node if is an option element inside a select tag
|
|
129
|
+
# Select this node if it is an option element inside a select tag.
|
|
119
130
|
#
|
|
131
|
+
# @!macro action_waiting_behavior
|
|
132
|
+
# If the driver dynamic pages (JS) and the element is currently non-interactable, this method will
|
|
133
|
+
# continuously retry the action until either the element becomes interactable or the maximum
|
|
134
|
+
# wait time expires.
|
|
135
|
+
#
|
|
136
|
+
# @param [false, Numeric] wait
|
|
137
|
+
# Maximum time to wait for the action to succeed. Defaults to {Capybara.configure default_max_wait_time}.
|
|
120
138
|
# @return [Capybara::Node::Element] The element
|
|
121
|
-
def select_option
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
return self
|
|
139
|
+
def select_option(wait: nil)
|
|
140
|
+
synchronize(wait) { base.select_option }
|
|
141
|
+
self
|
|
125
142
|
end
|
|
126
143
|
|
|
127
144
|
##
|
|
128
145
|
#
|
|
129
|
-
# Unselect this node if is an option element inside a multiple select tag
|
|
146
|
+
# Unselect this node if it is an option element inside a multiple select tag.
|
|
130
147
|
#
|
|
148
|
+
# @macro action_waiting_behavior
|
|
131
149
|
# @return [Capybara::Node::Element] The element
|
|
132
|
-
def unselect_option
|
|
133
|
-
synchronize { base.unselect_option }
|
|
134
|
-
|
|
150
|
+
def unselect_option(wait: nil)
|
|
151
|
+
synchronize(wait) { base.unselect_option }
|
|
152
|
+
self
|
|
135
153
|
end
|
|
136
154
|
|
|
137
155
|
##
|
|
138
156
|
#
|
|
139
|
-
# Click the Element
|
|
140
|
-
#
|
|
157
|
+
# Click the Element.
|
|
158
|
+
#
|
|
159
|
+
# @macro action_waiting_behavior
|
|
160
|
+
# @!macro click_modifiers
|
|
161
|
+
# Both x: and y: must be specified if an offset is wanted, if not specified the click will occur at the middle of the element.
|
|
162
|
+
# @overload $0(*modifier_keys, wait: nil, **offset)
|
|
163
|
+
# @param *modifier_keys [:alt, :control, :meta, :shift] ([]) Keys to be held down when clicking
|
|
164
|
+
# @option options [Integer] x X coordinate to offset the click location. If {Capybara.configure w3c_click_offset} is `true` the
|
|
165
|
+
# offset will be from the element center, otherwise it will be from the top left corner of the element
|
|
166
|
+
# @option options [Integer] y Y coordinate to offset the click location. If {Capybara.configure w3c_click_offset} is `true` the
|
|
167
|
+
# offset will be from the element center, otherwise it will be from the top left corner of the element
|
|
168
|
+
# @option options [Float] delay Delay between the mouse down and mouse up events in seconds (0)
|
|
141
169
|
# @return [Capybara::Node::Element] The element
|
|
142
|
-
def click
|
|
143
|
-
|
|
144
|
-
|
|
170
|
+
def click(*keys, **options)
|
|
171
|
+
perform_click_action(keys, **options) do |k, opts|
|
|
172
|
+
base.click(k, **opts)
|
|
173
|
+
end
|
|
145
174
|
end
|
|
146
175
|
|
|
147
176
|
##
|
|
148
177
|
#
|
|
149
|
-
# Right Click the Element
|
|
178
|
+
# Right Click the Element.
|
|
150
179
|
#
|
|
180
|
+
# @macro action_waiting_behavior
|
|
181
|
+
# @macro click_modifiers
|
|
182
|
+
# @option options [Float] delay Delay between the mouse down and mouse up events in seconds (0)
|
|
151
183
|
# @return [Capybara::Node::Element] The element
|
|
152
|
-
def right_click
|
|
153
|
-
|
|
154
|
-
|
|
184
|
+
def right_click(*keys, **options)
|
|
185
|
+
perform_click_action(keys, **options) do |k, opts|
|
|
186
|
+
base.right_click(k, **opts)
|
|
187
|
+
end
|
|
155
188
|
end
|
|
156
189
|
|
|
157
190
|
##
|
|
158
191
|
#
|
|
159
|
-
# Double Click the Element
|
|
192
|
+
# Double Click the Element.
|
|
160
193
|
#
|
|
194
|
+
# @macro action_waiting_behavior
|
|
195
|
+
# @macro click_modifiers
|
|
161
196
|
# @return [Capybara::Node::Element] The element
|
|
162
|
-
def double_click
|
|
163
|
-
|
|
164
|
-
|
|
197
|
+
def double_click(*keys, **options)
|
|
198
|
+
perform_click_action(keys, **options) do |k, opts|
|
|
199
|
+
base.double_click(k, **opts)
|
|
200
|
+
end
|
|
165
201
|
end
|
|
166
202
|
|
|
167
203
|
##
|
|
168
204
|
#
|
|
169
|
-
# Send Keystrokes to the Element
|
|
205
|
+
# Send Keystrokes to the Element.
|
|
170
206
|
#
|
|
171
207
|
# @overload send_keys(keys, ...)
|
|
172
|
-
# @param [String, Symbol, Array<String,Symbol>]
|
|
208
|
+
# @param keys [String, Symbol, Array<String,Symbol>]
|
|
173
209
|
#
|
|
174
210
|
# Examples:
|
|
175
211
|
#
|
|
176
212
|
# element.send_keys "foo" #=> value: 'foo'
|
|
177
|
-
# element.send_keys "tet", :left, "s"
|
|
213
|
+
# element.send_keys "tet", :left, "s" #=> value: 'test'
|
|
178
214
|
# element.send_keys [:control, 'a'], :space #=> value: ' ' - assuming ctrl-a selects all contents
|
|
179
215
|
#
|
|
180
|
-
# Symbols supported for keys
|
|
181
|
-
# :cancel
|
|
182
|
-
# :help
|
|
183
|
-
# :backspace
|
|
184
|
-
# :tab
|
|
185
|
-
# :clear
|
|
186
|
-
# :return
|
|
187
|
-
# :enter
|
|
188
|
-
# :shift
|
|
189
|
-
# :control
|
|
190
|
-
# :alt
|
|
191
|
-
# :pause
|
|
192
|
-
# :escape
|
|
193
|
-
# :space
|
|
194
|
-
# :page_up
|
|
195
|
-
# :page_down
|
|
196
|
-
# :end
|
|
197
|
-
# :home
|
|
198
|
-
# :left
|
|
199
|
-
# :up
|
|
200
|
-
# :right
|
|
201
|
-
# :down
|
|
202
|
-
# :insert
|
|
203
|
-
# :delete
|
|
204
|
-
# :semicolon
|
|
205
|
-
# :equals
|
|
206
|
-
# :numpad0
|
|
207
|
-
# :numpad1
|
|
208
|
-
# :numpad2
|
|
209
|
-
# :numpad3
|
|
210
|
-
# :numpad4
|
|
211
|
-
# :numpad5
|
|
212
|
-
# :numpad6
|
|
213
|
-
# :numpad7
|
|
214
|
-
# :numpad8
|
|
215
|
-
# :numpad9
|
|
216
|
-
# :multiply - numeric keypad *
|
|
217
|
-
# :add - numeric keypad +
|
|
218
|
-
# :separator - numeric keypad 'separator' key ??
|
|
219
|
-
# :subtract - numeric keypad -
|
|
220
|
-
# :decimal - numeric keypad .
|
|
221
|
-
# :divide - numeric keypad /
|
|
222
|
-
# :f1
|
|
223
|
-
# :f2
|
|
224
|
-
# :f3
|
|
225
|
-
# :f4
|
|
226
|
-
# :f5
|
|
227
|
-
# :f6
|
|
228
|
-
# :f7
|
|
229
|
-
# :f8
|
|
230
|
-
# :f9
|
|
231
|
-
# :f10
|
|
232
|
-
# :f11
|
|
233
|
-
# :f12
|
|
234
|
-
# :meta
|
|
235
|
-
# :command - alias of :meta
|
|
216
|
+
# Symbols supported for keys:
|
|
217
|
+
# * :cancel
|
|
218
|
+
# * :help
|
|
219
|
+
# * :backspace
|
|
220
|
+
# * :tab
|
|
221
|
+
# * :clear
|
|
222
|
+
# * :return
|
|
223
|
+
# * :enter
|
|
224
|
+
# * :shift
|
|
225
|
+
# * :control
|
|
226
|
+
# * :alt
|
|
227
|
+
# * :pause
|
|
228
|
+
# * :escape
|
|
229
|
+
# * :space
|
|
230
|
+
# * :page_up
|
|
231
|
+
# * :page_down
|
|
232
|
+
# * :end
|
|
233
|
+
# * :home
|
|
234
|
+
# * :left
|
|
235
|
+
# * :up
|
|
236
|
+
# * :right
|
|
237
|
+
# * :down
|
|
238
|
+
# * :insert
|
|
239
|
+
# * :delete
|
|
240
|
+
# * :semicolon
|
|
241
|
+
# * :equals
|
|
242
|
+
# * :numpad0
|
|
243
|
+
# * :numpad1
|
|
244
|
+
# * :numpad2
|
|
245
|
+
# * :numpad3
|
|
246
|
+
# * :numpad4
|
|
247
|
+
# * :numpad5
|
|
248
|
+
# * :numpad6
|
|
249
|
+
# * :numpad7
|
|
250
|
+
# * :numpad8
|
|
251
|
+
# * :numpad9
|
|
252
|
+
# * :multiply - numeric keypad *
|
|
253
|
+
# * :add - numeric keypad +
|
|
254
|
+
# * :separator - numeric keypad 'separator' key ??
|
|
255
|
+
# * :subtract - numeric keypad -
|
|
256
|
+
# * :decimal - numeric keypad .
|
|
257
|
+
# * :divide - numeric keypad /
|
|
258
|
+
# * :f1
|
|
259
|
+
# * :f2
|
|
260
|
+
# * :f3
|
|
261
|
+
# * :f4
|
|
262
|
+
# * :f5
|
|
263
|
+
# * :f6
|
|
264
|
+
# * :f7
|
|
265
|
+
# * :f8
|
|
266
|
+
# * :f9
|
|
267
|
+
# * :f10
|
|
268
|
+
# * :f11
|
|
269
|
+
# * :f12
|
|
270
|
+
# * :meta
|
|
271
|
+
# * :command - alias of :meta
|
|
236
272
|
#
|
|
237
273
|
# @return [Capybara::Node::Element] The element
|
|
238
274
|
def send_keys(*args)
|
|
239
275
|
synchronize { base.send_keys(*args) }
|
|
240
|
-
|
|
276
|
+
self
|
|
241
277
|
end
|
|
242
278
|
|
|
243
279
|
##
|
|
244
280
|
#
|
|
245
|
-
# Hover on the Element
|
|
281
|
+
# Hover on the Element.
|
|
246
282
|
#
|
|
247
283
|
# @return [Capybara::Node::Element] The element
|
|
248
284
|
def hover
|
|
249
285
|
synchronize { base.hover }
|
|
250
|
-
|
|
286
|
+
self
|
|
251
287
|
end
|
|
252
288
|
|
|
253
289
|
##
|
|
@@ -255,7 +291,8 @@ module Capybara
|
|
|
255
291
|
# @return [String] The tag name of the element
|
|
256
292
|
#
|
|
257
293
|
def tag_name
|
|
258
|
-
|
|
294
|
+
# Element type is immutable so cache it
|
|
295
|
+
@tag_name ||= initial_cache[:tag_name] || synchronize { base.tag_name }
|
|
259
296
|
end
|
|
260
297
|
|
|
261
298
|
##
|
|
@@ -269,6 +306,17 @@ module Capybara
|
|
|
269
306
|
synchronize { base.visible? }
|
|
270
307
|
end
|
|
271
308
|
|
|
309
|
+
##
|
|
310
|
+
#
|
|
311
|
+
# Whether or not the element is currently in the viewport and it (or descendants)
|
|
312
|
+
# would be considered clickable at the elements center point.
|
|
313
|
+
#
|
|
314
|
+
# @return [Boolean] Whether the elements center is obscured.
|
|
315
|
+
#
|
|
316
|
+
def obscured?
|
|
317
|
+
synchronize { base.obscured? }
|
|
318
|
+
end
|
|
319
|
+
|
|
272
320
|
##
|
|
273
321
|
#
|
|
274
322
|
# Whether or not the element is checked.
|
|
@@ -321,7 +369,7 @@ module Capybara
|
|
|
321
369
|
|
|
322
370
|
##
|
|
323
371
|
#
|
|
324
|
-
# An XPath expression describing where on the page the element can be found
|
|
372
|
+
# An XPath expression describing where on the page the element can be found.
|
|
325
373
|
#
|
|
326
374
|
# @return [String] An XPath expression
|
|
327
375
|
#
|
|
@@ -329,17 +377,23 @@ module Capybara
|
|
|
329
377
|
synchronize { base.path }
|
|
330
378
|
end
|
|
331
379
|
|
|
380
|
+
def rect
|
|
381
|
+
synchronize { base.rect }
|
|
382
|
+
end
|
|
383
|
+
|
|
332
384
|
##
|
|
333
385
|
#
|
|
334
386
|
# Trigger any event on the current element, for example mouseover or focus
|
|
335
|
-
# events.
|
|
387
|
+
# events. Not supported with the Selenium driver, and SHOULDN'T BE USED IN TESTING unless you
|
|
388
|
+
# fully understand why you're using it, that it can allow actions a user could never
|
|
389
|
+
# perform, and that it may completely invalidate your test.
|
|
336
390
|
#
|
|
337
391
|
# @param [String] event The name of the event to trigger
|
|
338
392
|
#
|
|
339
393
|
# @return [Capybara::Node::Element] The element
|
|
340
394
|
def trigger(event)
|
|
341
395
|
synchronize { base.trigger(event) }
|
|
342
|
-
|
|
396
|
+
self
|
|
343
397
|
end
|
|
344
398
|
|
|
345
399
|
##
|
|
@@ -351,35 +405,208 @@ module Capybara
|
|
|
351
405
|
# source.drag_to(target)
|
|
352
406
|
#
|
|
353
407
|
# @param [Capybara::Node::Element] node The element to drag to
|
|
408
|
+
# @param [Hash] options Driver specific options for dragging. May not be supported by all drivers.
|
|
409
|
+
# @option options [Numeric] :delay (0.05) When using Chrome/Firefox with Selenium and HTML5 dragging this is the number
|
|
410
|
+
# of seconds between each stage of the drag.
|
|
411
|
+
# @option options [Boolean] :html5 When using Chrome/Firefox with Selenium enables to force the use of HTML5
|
|
412
|
+
# (true) or legacy (false) dragging. If not specified the driver will attempt to
|
|
413
|
+
# detect the correct method to use.
|
|
414
|
+
# @option options [Array<Symbol>,Symbol] :drop_modifiers Modifier keys which should be held while the dragged element is dropped.
|
|
415
|
+
#
|
|
416
|
+
#
|
|
417
|
+
# @return [Capybara::Node::Element] The dragged element
|
|
418
|
+
def drag_to(node, **options)
|
|
419
|
+
synchronize { base.drag_to(node.base, **options) }
|
|
420
|
+
self
|
|
421
|
+
end
|
|
422
|
+
|
|
423
|
+
##
|
|
424
|
+
#
|
|
425
|
+
# Drop items on the current element.
|
|
426
|
+
#
|
|
427
|
+
# target = page.find('#foo')
|
|
428
|
+
# target.drop('/some/path/file.csv')
|
|
429
|
+
#
|
|
430
|
+
# @overload drop(path, ...)
|
|
431
|
+
# @param [String, #to_path] path Location of the file to drop on the element
|
|
432
|
+
#
|
|
433
|
+
# @overload drop(strings, ...)
|
|
434
|
+
# @param [Hash] strings A hash of type to data to be dropped - `{ "text/url" => "https://www.google.com" }`
|
|
435
|
+
#
|
|
436
|
+
# @return [Capybara::Node::Element] The element
|
|
437
|
+
def drop(*args)
|
|
438
|
+
options = args.map { |arg| arg.respond_to?(:to_path) ? arg.to_path : arg }
|
|
439
|
+
synchronize { base.drop(*options) }
|
|
440
|
+
self
|
|
441
|
+
end
|
|
442
|
+
|
|
443
|
+
##
|
|
444
|
+
#
|
|
445
|
+
# Scroll the page or element.
|
|
446
|
+
#
|
|
447
|
+
# @overload scroll_to(position, offset: [0,0])
|
|
448
|
+
# Scroll the page or element to its top, bottom or middle.
|
|
449
|
+
# @param [:top, :bottom, :center, :current] position
|
|
450
|
+
# @param [[Integer, Integer]] offset
|
|
451
|
+
#
|
|
452
|
+
# @overload scroll_to(element, align: :top)
|
|
453
|
+
# Scroll the page or current element until the given element is aligned at the top, bottom, or center of it.
|
|
454
|
+
# @param [Capybara::Node::Element] element The element to be scrolled into view
|
|
455
|
+
# @param [:top, :bottom, :center] align Where to align the element being scrolled into view with relation to the current page/element if possible
|
|
456
|
+
#
|
|
457
|
+
# @overload scroll_to(x,y)
|
|
458
|
+
# @param [Integer] x Horizontal scroll offset
|
|
459
|
+
# @param [Integer] y Vertical scroll offset
|
|
460
|
+
#
|
|
461
|
+
# @return [Capybara::Node::Element] The element
|
|
462
|
+
def scroll_to(pos_or_el_or_x, y = nil, align: :top, offset: nil)
|
|
463
|
+
case pos_or_el_or_x
|
|
464
|
+
when Symbol
|
|
465
|
+
synchronize { base.scroll_to(nil, pos_or_el_or_x) } unless pos_or_el_or_x == :current
|
|
466
|
+
when Capybara::Node::Element
|
|
467
|
+
synchronize { base.scroll_to(pos_or_el_or_x.base, align) }
|
|
468
|
+
else
|
|
469
|
+
synchronize { base.scroll_to(nil, nil, [pos_or_el_or_x, y]) }
|
|
470
|
+
end
|
|
471
|
+
synchronize { base.scroll_by(*offset) } unless offset.nil?
|
|
472
|
+
self
|
|
473
|
+
end
|
|
474
|
+
|
|
475
|
+
##
|
|
476
|
+
#
|
|
477
|
+
# Return the shadow_root for the current element
|
|
478
|
+
#
|
|
479
|
+
# @return [Capybara::Node::Element] The shadow root
|
|
480
|
+
|
|
481
|
+
def shadow_root
|
|
482
|
+
root = synchronize { base.shadow_root }
|
|
483
|
+
root && Capybara::Node::Element.new(session, root, nil, nil)
|
|
484
|
+
end
|
|
485
|
+
|
|
486
|
+
##
|
|
487
|
+
#
|
|
488
|
+
# Execute the given JS in the context of the element not returning a result. This is useful for scripts that return
|
|
489
|
+
# complex objects, such as jQuery statements. {#execute_script} should be used over
|
|
490
|
+
# {#evaluate_script} whenever a result is not expected or needed. `this` in the script will refer to the element this is called on.
|
|
491
|
+
#
|
|
492
|
+
# @param [String] script A string of JavaScript to execute
|
|
493
|
+
# @param args Optional arguments that will be passed to the script. Driver support for this is optional and types of objects supported may differ between drivers
|
|
494
|
+
#
|
|
495
|
+
def execute_script(script, *args)
|
|
496
|
+
session.execute_script(<<~JS, self, *args)
|
|
497
|
+
(function (){
|
|
498
|
+
#{script}
|
|
499
|
+
}).apply(arguments[0], Array.prototype.slice.call(arguments,1));
|
|
500
|
+
JS
|
|
501
|
+
end
|
|
502
|
+
|
|
503
|
+
##
|
|
504
|
+
#
|
|
505
|
+
# Evaluate the given JS in the context of the element and return the result. Be careful when using this with
|
|
506
|
+
# scripts that return complex objects, such as jQuery statements. {#execute_script} might
|
|
507
|
+
# be a better alternative. `this` in the script will refer to the element this is called on.
|
|
508
|
+
#
|
|
509
|
+
# @param [String] script A string of JavaScript to evaluate
|
|
510
|
+
# @return [Object] The result of the evaluated JavaScript (may be driver specific)
|
|
511
|
+
#
|
|
512
|
+
def evaluate_script(script, *args)
|
|
513
|
+
session.evaluate_script(<<~JS, self, *args)
|
|
514
|
+
(function(){
|
|
515
|
+
return #{script.strip}
|
|
516
|
+
}).apply(arguments[0], Array.prototype.slice.call(arguments,1));
|
|
517
|
+
JS
|
|
518
|
+
end
|
|
519
|
+
|
|
520
|
+
##
|
|
521
|
+
#
|
|
522
|
+
# Evaluate the given JavaScript in the context of the element and obtain the result from a
|
|
523
|
+
# callback function which will be passed as the last argument to the script. `this` in the
|
|
524
|
+
# script will refer to the element this is called on.
|
|
525
|
+
#
|
|
526
|
+
# @param [String] script A string of JavaScript to evaluate
|
|
527
|
+
# @return [Object] The result of the evaluated JavaScript (may be driver specific)
|
|
528
|
+
#
|
|
529
|
+
def evaluate_async_script(script, *args)
|
|
530
|
+
session.evaluate_async_script(<<~JS, self, *args)
|
|
531
|
+
(function (){
|
|
532
|
+
#{script}
|
|
533
|
+
}).apply(arguments[0], Array.prototype.slice.call(arguments,1));
|
|
534
|
+
JS
|
|
535
|
+
end
|
|
536
|
+
|
|
537
|
+
##
|
|
538
|
+
#
|
|
539
|
+
# Toggle the elements background color between white and black for a period of time.
|
|
354
540
|
#
|
|
355
541
|
# @return [Capybara::Node::Element] The element
|
|
356
|
-
def
|
|
357
|
-
|
|
358
|
-
|
|
542
|
+
def flash
|
|
543
|
+
execute_script(<<~JS, 100)
|
|
544
|
+
async function flash(el, delay){
|
|
545
|
+
var old_bg = el.style.backgroundColor;
|
|
546
|
+
var colors = ["black", "white"];
|
|
547
|
+
for(var i=0; i<20; i++){
|
|
548
|
+
el.style.backgroundColor = colors[i % colors.length];
|
|
549
|
+
await new Promise(resolve => setTimeout(resolve, delay));
|
|
550
|
+
}
|
|
551
|
+
el.style.backgroundColor = old_bg;
|
|
552
|
+
}
|
|
553
|
+
flash(this, arguments[0]);
|
|
554
|
+
JS
|
|
555
|
+
|
|
556
|
+
self
|
|
359
557
|
end
|
|
360
558
|
|
|
559
|
+
# @api private
|
|
361
560
|
def reload
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
561
|
+
return self unless @allow_reload
|
|
562
|
+
|
|
563
|
+
begin
|
|
564
|
+
reloaded = @query.resolve_for(query_scope ? query_scope.reload : session)[@query_idx.to_i]
|
|
565
|
+
@base = reloaded.base if reloaded
|
|
566
|
+
rescue StandardError => e
|
|
567
|
+
raise e unless catch_error?(e)
|
|
369
568
|
end
|
|
370
569
|
self
|
|
371
570
|
end
|
|
372
571
|
|
|
572
|
+
##
|
|
573
|
+
#
|
|
574
|
+
# A human-readable representation of the element.
|
|
575
|
+
#
|
|
576
|
+
# @return [String] A string representation
|
|
373
577
|
def inspect
|
|
374
578
|
%(#<Capybara::Node::Element tag="#{base.tag_name}" path="#{base.path}">)
|
|
375
579
|
rescue NotSupportedByDriverError
|
|
376
580
|
%(#<Capybara::Node::Element tag="#{base.tag_name}">)
|
|
377
|
-
rescue
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
581
|
+
rescue *session.driver.invalid_element_errors
|
|
582
|
+
%(Obsolete #<Capybara::Node::Element>)
|
|
583
|
+
end
|
|
584
|
+
|
|
585
|
+
# @api private
|
|
586
|
+
def initial_cache
|
|
587
|
+
base.respond_to?(:initial_cache) ? base.initial_cache : {}
|
|
588
|
+
end
|
|
589
|
+
|
|
590
|
+
STYLE_SCRIPT = <<~JS
|
|
591
|
+
(function(){
|
|
592
|
+
var s = window.getComputedStyle(this);
|
|
593
|
+
var result = {};
|
|
594
|
+
for (var i = arguments.length; i--; ) {
|
|
595
|
+
var property_name = arguments[i];
|
|
596
|
+
result[property_name] = s.getPropertyValue(property_name);
|
|
597
|
+
}
|
|
598
|
+
return result;
|
|
599
|
+
}).apply(this, arguments)
|
|
600
|
+
JS
|
|
601
|
+
|
|
602
|
+
private
|
|
603
|
+
|
|
604
|
+
def perform_click_action(keys, wait: nil, **options)
|
|
605
|
+
raise ArgumentError, 'You must specify both x: and y: for a click offset' if nil ^ options[:x] ^ options[:y]
|
|
606
|
+
|
|
607
|
+
options[:offset] ||= :center if session_options.w3c_click_offset
|
|
608
|
+
synchronize(wait) { yield keys, options }
|
|
609
|
+
self
|
|
383
610
|
end
|
|
384
611
|
end
|
|
385
612
|
end
|