capybara 3.3.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 -0
- data/History.md +803 -13
- data/License.txt +1 -1
- data/README.md +257 -84
- data/lib/capybara/config.rb +25 -9
- data/lib/capybara/cucumber.rb +1 -1
- data/lib/capybara/driver/base.rb +17 -3
- data/lib/capybara/driver/node.rb +31 -6
- data/lib/capybara/dsl.rb +9 -7
- data/lib/capybara/helpers.rb +31 -7
- data/lib/capybara/minitest/spec.rb +180 -88
- data/lib/capybara/minitest.rb +262 -149
- data/lib/capybara/node/actions.rb +202 -116
- data/lib/capybara/node/base.rb +34 -19
- data/lib/capybara/node/document.rb +14 -2
- data/lib/capybara/node/document_matchers.rb +10 -12
- data/lib/capybara/node/element.rb +269 -115
- data/lib/capybara/node/finders.rb +99 -77
- data/lib/capybara/node/matchers.rb +327 -151
- data/lib/capybara/node/simple.rb +48 -13
- 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 +8 -9
- data/lib/capybara/queries/base_query.rb +23 -16
- data/lib/capybara/queries/current_path_query.rb +16 -6
- data/lib/capybara/queries/match_query.rb +1 -0
- data/lib/capybara/queries/selector_query.rb +587 -130
- data/lib/capybara/queries/sibling_query.rb +8 -6
- data/lib/capybara/queries/style_query.rb +6 -2
- data/lib/capybara/queries/text_query.rb +28 -14
- data/lib/capybara/queries/title_query.rb +2 -2
- data/lib/capybara/rack_test/browser.rb +92 -25
- 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 +68 -41
- data/lib/capybara/rack_test/node.rb +106 -39
- 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 +75 -52
- data/lib/capybara/rspec/features.rb +7 -7
- 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 +141 -339
- data/lib/capybara/rspec.rb +2 -0
- 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 +27 -25
- 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 +73 -25
- data/lib/capybara/selector/filters/base.rb +24 -5
- data/lib/capybara/selector/filters/expression_filter.rb +3 -3
- data/lib/capybara/selector/filters/locator_filter.rb +29 -0
- data/lib/capybara/selector/filters/node_filter.rb +16 -2
- data/lib/capybara/selector/regexp_disassembler.rb +211 -0
- data/lib/capybara/selector/selector.rb +85 -348
- data/lib/capybara/selector/xpath_extensions.rb +17 -0
- data/lib/capybara/selector.rb +474 -447
- 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 +255 -143
- data/lib/capybara/selenium/driver_specializations/chrome_driver.rb +93 -11
- 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 +436 -134
- 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 +56 -19
- data/lib/capybara/server/checker.rb +9 -3
- data/lib/capybara/server/middleware.rb +28 -12
- data/lib/capybara/server.rb +33 -10
- data/lib/capybara/session/config.rb +34 -10
- data/lib/capybara/session/matchers.rb +23 -16
- data/lib/capybara/session.rb +230 -170
- 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 +121 -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 +127 -40
- 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_spec.rb +21 -18
- data/lib/capybara/spec/session/assert_selector_spec.rb +52 -58
- data/lib/capybara/spec/session/assert_style_spec.rb +7 -7
- data/lib/capybara/spec/session/assert_text_spec.rb +74 -50
- data/lib/capybara/spec/session/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 +6 -6
- data/lib/capybara/spec/session/check_spec.rb +102 -47
- data/lib/capybara/spec/session/choose_spec.rb +58 -32
- data/lib/capybara/spec/session/click_button_spec.rb +219 -163
- data/lib/capybara/spec/session/click_link_or_button_spec.rb +49 -23
- data/lib/capybara/spec/session/click_link_spec.rb +77 -54
- data/lib/capybara/spec/session/current_scope_spec.rb +8 -8
- data/lib/capybara/spec/session/current_url_spec.rb +38 -29
- 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_spec.rb +8 -8
- data/lib/capybara/spec/session/element/match_css_spec.rb +16 -10
- data/lib/capybara/spec/session/element/match_xpath_spec.rb +6 -6
- data/lib/capybara/spec/session/element/matches_selector_spec.rb +68 -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 +101 -46
- data/lib/capybara/spec/session/find_button_spec.rb +23 -23
- data/lib/capybara/spec/session/find_by_id_spec.rb +7 -7
- data/lib/capybara/spec/session/find_field_spec.rb +32 -30
- data/lib/capybara/spec/session/find_link_spec.rb +31 -21
- data/lib/capybara/spec/session/find_spec.rb +244 -141
- data/lib/capybara/spec/session/first_spec.rb +43 -43
- data/lib/capybara/spec/session/frame/frame_title_spec.rb +5 -5
- data/lib/capybara/spec/session/frame/frame_url_spec.rb +5 -5
- data/lib/capybara/spec/session/frame/switch_to_frame_spec.rb +30 -18
- data/lib/capybara/spec/session/frame/within_frame_spec.rb +45 -18
- 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 +94 -13
- data/lib/capybara/spec/session/has_css_spec.rb +272 -132
- 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 +44 -4
- data/lib/capybara/spec/session/has_none_selectors_spec.rb +31 -31
- data/lib/capybara/spec/session/has_select_spec.rb +84 -50
- data/lib/capybara/spec/session/has_selector_spec.rb +111 -71
- 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_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 +894 -142
- data/lib/capybara/spec/session/node_wrapper_spec.rb +10 -7
- data/lib/capybara/spec/session/refresh_spec.rb +9 -7
- data/lib/capybara/spec/session/reset_session_spec.rb +63 -35
- data/lib/capybara/spec/session/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 +2 -2
- data/lib/capybara/spec/session/save_page_spec.rb +37 -37
- data/lib/capybara/spec/session/save_screenshot_spec.rb +10 -10
- 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 +85 -85
- data/lib/capybara/spec/session/selectors_spec.rb +49 -18
- data/lib/capybara/spec/session/sibling_spec.rb +9 -9
- data/lib/capybara/spec/session/text_spec.rb +25 -24
- data/lib/capybara/spec/session/title_spec.rb +7 -6
- data/lib/capybara/spec/session/uncheck_spec.rb +33 -21
- data/lib/capybara/spec/session/unselect_spec.rb +37 -37
- data/lib/capybara/spec/session/visit_spec.rb +68 -49
- data/lib/capybara/spec/session/window/become_closed_spec.rb +20 -17
- data/lib/capybara/spec/session/window/current_window_spec.rb +1 -1
- data/lib/capybara/spec/session/window/switch_to_window_spec.rb +20 -16
- data/lib/capybara/spec/session/window/window_opened_by_spec.rb +6 -2
- data/lib/capybara/spec/session/window/window_spec.rb +62 -63
- data/lib/capybara/spec/session/window/windows_spec.rb +5 -1
- data/lib/capybara/spec/session/window/within_window_spec.rb +14 -14
- data/lib/capybara/spec/session/within_spec.rb +79 -42
- data/lib/capybara/spec/spec_helper.rb +41 -53
- data/lib/capybara/spec/test_app.rb +132 -43
- data/lib/capybara/spec/views/animated.erb +49 -0
- data/lib/capybara/spec/views/form.erb +139 -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 +67 -0
- data/lib/capybara/spec/views/with_animation.erb +39 -4
- 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 +37 -9
- 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 +26 -5
- data/lib/capybara/spec/views/with_jstree.erb +26 -0
- data/lib/capybara/spec/views/with_namespace.erb +1 -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 +19 -25
- data/lib/capybara.rb +126 -111
- data/spec/basic_node_spec.rb +59 -34
- data/spec/capybara_spec.rb +56 -44
- data/spec/counter_spec.rb +35 -0
- data/spec/css_builder_spec.rb +101 -0
- data/spec/css_splitter_spec.rb +8 -8
- data/spec/dsl_spec.rb +79 -52
- data/spec/filter_set_spec.rb +9 -9
- data/spec/fixtures/selenium_driver_rspec_failure.rb +4 -4
- data/spec/fixtures/selenium_driver_rspec_success.rb +4 -4
- data/spec/minitest_spec.rb +45 -7
- data/spec/minitest_spec_spec.rb +87 -64
- data/spec/per_session_config_spec.rb +6 -6
- data/spec/rack_test_spec.rb +172 -116
- data/spec/regexp_dissassembler_spec.rb +250 -0
- data/spec/result_spec.rb +80 -72
- data/spec/rspec/features_spec.rb +21 -16
- data/spec/rspec/scenarios_spec.rb +10 -6
- data/spec/rspec/shared_spec_matchers.rb +407 -365
- data/spec/rspec/views_spec.rb +3 -3
- data/spec/rspec_matchers_spec.rb +35 -10
- data/spec/rspec_spec.rb +63 -41
- data/spec/sauce_spec_chrome.rb +43 -0
- data/spec/selector_spec.rb +334 -89
- data/spec/selenium_spec_chrome.rb +176 -62
- data/spec/selenium_spec_chrome_remote.rb +54 -14
- 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 +171 -97
- data/spec/session_spec.rb +34 -18
- data/spec/shared_selenium_node.rb +79 -0
- data/spec/shared_selenium_session.rb +344 -80
- data/spec/spec_helper.rb +124 -2
- data/spec/whitespace_normalizer_spec.rb +54 -0
- data/spec/xpath_builder_spec.rb +93 -0
- metadata +326 -28
- data/lib/capybara/rspec/compound.rb +0 -94
- data/lib/capybara/selenium/driver_specializations/marionette_driver.rb +0 -31
- data/lib/capybara/selenium/nodes/marionette_node.rb +0 -31
- data/lib/capybara/spec/session/has_style_spec.rb +0 -25
- 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 -167
data/lib/capybara/node/simple.rb
CHANGED
|
@@ -28,8 +28,9 @@ module Capybara
|
|
|
28
28
|
#
|
|
29
29
|
# @return [String] The text of the element
|
|
30
30
|
#
|
|
31
|
-
def text(_type = nil)
|
|
32
|
-
native.text
|
|
31
|
+
def text(_type = nil, normalize_ws: false)
|
|
32
|
+
txt = native.text
|
|
33
|
+
normalize_ws ? txt.gsub(/[[:space:]]+/, ' ').strip : txt
|
|
33
34
|
end
|
|
34
35
|
|
|
35
36
|
##
|
|
@@ -78,11 +79,11 @@ module Capybara
|
|
|
78
79
|
if tag_name == 'textarea'
|
|
79
80
|
native['_capybara_raw_value']
|
|
80
81
|
elsif tag_name == 'select'
|
|
82
|
+
selected_options = find_xpath('.//option[@selected]')
|
|
81
83
|
if multiple?
|
|
82
|
-
|
|
84
|
+
selected_options.map(&method(:option_value))
|
|
83
85
|
else
|
|
84
|
-
|
|
85
|
-
option[:value] || option.content if option
|
|
86
|
+
option_value(selected_options.first || find_xpath('.//option').first)
|
|
86
87
|
end
|
|
87
88
|
elsif tag_name == 'input' && %w[radio checkbox].include?(native[:type])
|
|
88
89
|
native[:value] || 'on'
|
|
@@ -99,14 +100,17 @@ module Capybara
|
|
|
99
100
|
# @param [Boolean] check_ancestors Whether to inherit visibility from ancestors
|
|
100
101
|
# @return [Boolean] Whether the element is visible
|
|
101
102
|
#
|
|
102
|
-
def visible?(check_ancestors = true)
|
|
103
|
-
return false if (tag_name == 'input') && (native[:type] ==
|
|
103
|
+
def visible?(check_ancestors = true) # rubocop:disable Style/OptionalBooleanParameter
|
|
104
|
+
return false if (tag_name == 'input') && (native[:type] == 'hidden')
|
|
105
|
+
return false if tag_name == 'template'
|
|
104
106
|
|
|
105
107
|
if check_ancestors
|
|
106
|
-
!
|
|
108
|
+
!find_xpath(VISIBILITY_XPATH)
|
|
107
109
|
else
|
|
108
110
|
# No need for an xpath if only checking the current element
|
|
109
|
-
!(native.
|
|
111
|
+
!(native.key?('hidden') ||
|
|
112
|
+
/display:\s?none/.match?(native[:style] || '') ||
|
|
113
|
+
%w[script head style].include?(tag_name))
|
|
110
114
|
end
|
|
111
115
|
end
|
|
112
116
|
|
|
@@ -126,7 +130,8 @@ module Capybara
|
|
|
126
130
|
#
|
|
127
131
|
# @return [Boolean] Whether the element is disabled
|
|
128
132
|
def disabled?
|
|
129
|
-
native.has_attribute?('disabled')
|
|
133
|
+
native.has_attribute?('disabled') &&
|
|
134
|
+
%w[button input select textarea optgroup option menuitem fieldset].include?(tag_name)
|
|
130
135
|
end
|
|
131
136
|
|
|
132
137
|
##
|
|
@@ -143,11 +148,15 @@ module Capybara
|
|
|
143
148
|
native.has_attribute?('multiple')
|
|
144
149
|
end
|
|
145
150
|
|
|
151
|
+
def readonly?
|
|
152
|
+
native.has_attribute?('readonly')
|
|
153
|
+
end
|
|
154
|
+
|
|
146
155
|
def synchronize(_seconds = nil)
|
|
147
156
|
yield # simple nodes don't need to wait
|
|
148
157
|
end
|
|
149
158
|
|
|
150
|
-
def allow_reload!
|
|
159
|
+
def allow_reload!(*)
|
|
151
160
|
# no op
|
|
152
161
|
end
|
|
153
162
|
|
|
@@ -163,12 +172,12 @@ module Capybara
|
|
|
163
172
|
end
|
|
164
173
|
|
|
165
174
|
# @api private
|
|
166
|
-
def find_css(css)
|
|
175
|
+
def find_css(css, **_options)
|
|
167
176
|
native.css(css)
|
|
168
177
|
end
|
|
169
178
|
|
|
170
179
|
# @api private
|
|
171
|
-
def find_xpath(xpath)
|
|
180
|
+
def find_xpath(xpath, **_options)
|
|
172
181
|
native.xpath(xpath)
|
|
173
182
|
end
|
|
174
183
|
|
|
@@ -176,6 +185,32 @@ module Capybara
|
|
|
176
185
|
def session_options
|
|
177
186
|
Capybara.session_options
|
|
178
187
|
end
|
|
188
|
+
|
|
189
|
+
# @api private
|
|
190
|
+
def initial_cache
|
|
191
|
+
{}
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
def ==(other)
|
|
195
|
+
eql?(other) || (other.respond_to?(:native) && native == other.native)
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
private
|
|
199
|
+
|
|
200
|
+
def option_value(option)
|
|
201
|
+
return nil if option.nil?
|
|
202
|
+
|
|
203
|
+
option[:value] || option.content
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
VISIBILITY_XPATH = XPath.generate do |x|
|
|
207
|
+
x.ancestor_or_self[
|
|
208
|
+
x.attr(:style)[x.contains('display:none') | x.contains('display: none')] |
|
|
209
|
+
x.attr(:hidden) |
|
|
210
|
+
x.qname.one_of('script', 'head') |
|
|
211
|
+
(~x.self(:summary) & XPath.parent(:details)[!XPath.attr(:open)])
|
|
212
|
+
].boolean
|
|
213
|
+
end.to_s.freeze
|
|
179
214
|
end
|
|
180
215
|
end
|
|
181
216
|
end
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Capybara
|
|
4
|
+
module Node
|
|
5
|
+
##
|
|
6
|
+
#
|
|
7
|
+
# {Capybara::Node::WhitespaceNormalizer} provides methods that
|
|
8
|
+
# help to normalize the spacing of text content inside of
|
|
9
|
+
# {Capybara::Node::Element}s by removing various unicode
|
|
10
|
+
# spacing and directional markings.
|
|
11
|
+
#
|
|
12
|
+
module WhitespaceNormalizer
|
|
13
|
+
# Unicode for NBSP, or
|
|
14
|
+
NON_BREAKING_SPACE = "\u00a0"
|
|
15
|
+
LINE_SEPERATOR = "\u2028"
|
|
16
|
+
PARAGRAPH_SEPERATOR = "\u2029"
|
|
17
|
+
|
|
18
|
+
# All spaces except for NBSP
|
|
19
|
+
BREAKING_SPACES = "[[:space:]&&[^#{NON_BREAKING_SPACE}]]".freeze
|
|
20
|
+
|
|
21
|
+
# Whitespace we want to substitute with plain spaces
|
|
22
|
+
SQUEEZED_SPACES = " \n\f\t\v#{LINE_SEPERATOR}#{PARAGRAPH_SEPERATOR}".freeze
|
|
23
|
+
|
|
24
|
+
# Any whitespace at the front of text
|
|
25
|
+
LEADING_SPACES = /\A#{BREAKING_SPACES}+/
|
|
26
|
+
|
|
27
|
+
# Any whitespace at the end of text
|
|
28
|
+
TRAILING_SPACES = /#{BREAKING_SPACES}+\z/
|
|
29
|
+
|
|
30
|
+
# "Invisible" space character
|
|
31
|
+
ZERO_WIDTH_SPACE = "\u200b"
|
|
32
|
+
|
|
33
|
+
# Signifies text is read left to right
|
|
34
|
+
LEFT_TO_RIGHT_MARK = "\u200e"
|
|
35
|
+
|
|
36
|
+
# Signifies text is read right to left
|
|
37
|
+
RIGHT_TO_LEFT_MARK = "\u200f"
|
|
38
|
+
|
|
39
|
+
# Characters we want to truncate from text
|
|
40
|
+
REMOVED_CHARACTERS = [ZERO_WIDTH_SPACE, LEFT_TO_RIGHT_MARK, RIGHT_TO_LEFT_MARK].join
|
|
41
|
+
|
|
42
|
+
# Matches multiple empty lines
|
|
43
|
+
EMPTY_LINES = /[\ \n]*\n[\ \n]*/
|
|
44
|
+
|
|
45
|
+
##
|
|
46
|
+
#
|
|
47
|
+
# Normalizes the spacing of a node's text to be similar to
|
|
48
|
+
# what matchers might expect.
|
|
49
|
+
#
|
|
50
|
+
# @param text [String]
|
|
51
|
+
# @return [String]
|
|
52
|
+
#
|
|
53
|
+
def normalize_spacing(text)
|
|
54
|
+
text
|
|
55
|
+
.delete(REMOVED_CHARACTERS)
|
|
56
|
+
.tr(SQUEEZED_SPACES, ' ')
|
|
57
|
+
.squeeze(' ')
|
|
58
|
+
.sub(LEADING_SPACES, '')
|
|
59
|
+
.sub(TRAILING_SPACES, '')
|
|
60
|
+
.tr(NON_BREAKING_SPACE, ' ')
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
##
|
|
64
|
+
#
|
|
65
|
+
# Variant on {Capybara::Node::Normalizer#normalize_spacing} that
|
|
66
|
+
# targets the whitespace of visible elements only.
|
|
67
|
+
#
|
|
68
|
+
# @param text [String]
|
|
69
|
+
# @return [String]
|
|
70
|
+
#
|
|
71
|
+
def normalize_visible_spacing(text)
|
|
72
|
+
text
|
|
73
|
+
.squeeze(' ')
|
|
74
|
+
.gsub(EMPTY_LINES, "\n")
|
|
75
|
+
.sub(LEADING_SPACES, '')
|
|
76
|
+
.sub(TRAILING_SPACES, '')
|
|
77
|
+
.tr(NON_BREAKING_SPACE, ' ')
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Capybara
|
|
4
|
+
# @api private
|
|
5
|
+
module Queries
|
|
6
|
+
class ActiveElementQuery < BaseQuery
|
|
7
|
+
def initialize(**options)
|
|
8
|
+
@options = options
|
|
9
|
+
super(@options)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def resolve_for(session)
|
|
13
|
+
node = session.driver.active_element
|
|
14
|
+
[Capybara::Node::Element.new(session, node, nil, self)]
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -6,24 +6,23 @@ module Capybara
|
|
|
6
6
|
# @api private
|
|
7
7
|
def resolve_for(node, exact = nil)
|
|
8
8
|
@child_node = node
|
|
9
|
+
|
|
9
10
|
node.synchronize do
|
|
10
|
-
|
|
11
|
-
|
|
11
|
+
scope = node.respond_to?(:session) ? node.session.current_scope : node.find(:xpath, '/*')
|
|
12
|
+
match_results = super(scope, exact)
|
|
13
|
+
ancestors = node.find_xpath(XPath.ancestor.to_s)
|
|
14
|
+
.map(&method(:to_element))
|
|
15
|
+
.select { |el| match_results.include?(el) }
|
|
16
|
+
Capybara::Result.new(ordered_results(ancestors), self)
|
|
12
17
|
end
|
|
13
18
|
end
|
|
14
19
|
|
|
15
|
-
def description
|
|
20
|
+
def description(applied = false) # rubocop:disable Style/OptionalBooleanParameter
|
|
16
21
|
child_query = @child_node&.instance_variable_get(:@query)
|
|
17
22
|
desc = super
|
|
18
23
|
desc += " that is an ancestor of #{child_query.description}" if child_query
|
|
19
24
|
desc
|
|
20
25
|
end
|
|
21
|
-
|
|
22
|
-
private
|
|
23
|
-
|
|
24
|
-
def valid_keys
|
|
25
|
-
super - COUNT_KEYS
|
|
26
|
-
end
|
|
27
26
|
end
|
|
28
27
|
end
|
|
29
28
|
end
|
|
@@ -23,9 +23,9 @@ module Capybara
|
|
|
23
23
|
|
|
24
24
|
def self.wait(options, default = Capybara.default_max_wait_time)
|
|
25
25
|
# if no value or nil for the :wait option is passed it should default to the default
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
26
|
+
wait = options.fetch(:wait, nil)
|
|
27
|
+
wait = default if wait.nil?
|
|
28
|
+
wait || 0
|
|
29
29
|
end
|
|
30
30
|
|
|
31
31
|
##
|
|
@@ -51,6 +51,7 @@ module Capybara
|
|
|
51
51
|
return false if options[:maximum] && (Integer(options[:maximum]) < count)
|
|
52
52
|
return false if options[:minimum] && (Integer(options[:minimum]) > count)
|
|
53
53
|
return false if options[:between] && !options[:between].include?(count)
|
|
54
|
+
|
|
54
55
|
true
|
|
55
56
|
end
|
|
56
57
|
|
|
@@ -69,30 +70,36 @@ module Capybara
|
|
|
69
70
|
private
|
|
70
71
|
|
|
71
72
|
def count_specified?
|
|
72
|
-
COUNT_KEYS.any? { |
|
|
73
|
+
COUNT_KEYS.any? { |key| options.key? key }
|
|
73
74
|
end
|
|
74
75
|
|
|
75
76
|
def count_message
|
|
76
|
-
message = +
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
elsif
|
|
84
|
-
message << " at
|
|
77
|
+
message = +''
|
|
78
|
+
count, between, maximum, minimum = options.values_at(:count, :between, :maximum, :minimum)
|
|
79
|
+
if count
|
|
80
|
+
message << " #{occurrences count}"
|
|
81
|
+
elsif between
|
|
82
|
+
message << " between #{between.begin ? between.first : 1} and " \
|
|
83
|
+
"#{between.end ? between.last : 'infinite'} times"
|
|
84
|
+
elsif maximum
|
|
85
|
+
message << " at most #{occurrences maximum}"
|
|
86
|
+
elsif minimum
|
|
87
|
+
message << " at least #{occurrences minimum}"
|
|
85
88
|
end
|
|
86
89
|
message
|
|
87
90
|
end
|
|
88
91
|
|
|
92
|
+
def occurrences(count)
|
|
93
|
+
"#{count} #{Capybara::Helpers.declension('time', 'times', count)}"
|
|
94
|
+
end
|
|
95
|
+
|
|
89
96
|
def assert_valid_keys
|
|
90
97
|
invalid_keys = @options.keys - valid_keys
|
|
91
98
|
return if invalid_keys.empty?
|
|
92
99
|
|
|
93
|
-
invalid_names = invalid_keys.map(&:inspect).join(
|
|
94
|
-
valid_names = valid_keys.map(&:inspect).join(
|
|
95
|
-
raise ArgumentError, "
|
|
100
|
+
invalid_names = invalid_keys.map(&:inspect).join(', ')
|
|
101
|
+
valid_names = valid_keys.map(&:inspect).join(', ')
|
|
102
|
+
raise ArgumentError, "Invalid option(s) #{invalid_names}, should be one of #{valid_names}"
|
|
96
103
|
end
|
|
97
104
|
end
|
|
98
105
|
end
|
|
@@ -6,26 +6,30 @@ module Capybara
|
|
|
6
6
|
# @api private
|
|
7
7
|
module Queries
|
|
8
8
|
class CurrentPathQuery < BaseQuery
|
|
9
|
-
def initialize(expected_path, **options)
|
|
9
|
+
def initialize(expected_path, **options, &optional_filter_block)
|
|
10
10
|
super(options)
|
|
11
11
|
@expected_path = expected_path
|
|
12
12
|
@options = {
|
|
13
|
-
url: !@expected_path.is_a?(Regexp) && !::Addressable::URI.parse(@expected_path ||
|
|
13
|
+
url: !@expected_path.is_a?(Regexp) && !::Addressable::URI.parse(@expected_path || '').hostname.nil?,
|
|
14
14
|
ignore_query: false
|
|
15
15
|
}.merge(options)
|
|
16
|
+
@filter_block = optional_filter_block
|
|
16
17
|
assert_valid_keys
|
|
17
18
|
end
|
|
18
19
|
|
|
19
20
|
def resolves_for?(session)
|
|
20
21
|
uri = ::Addressable::URI.parse(session.current_url)
|
|
21
|
-
|
|
22
|
-
|
|
22
|
+
@actual_path = (options[:ignore_query] ? uri&.omit(:query) : uri).then do |u|
|
|
23
|
+
options[:url] ? u&.to_s : u&.request_uri
|
|
24
|
+
end
|
|
23
25
|
|
|
24
|
-
if @expected_path.is_a? Regexp
|
|
25
|
-
@actual_path.to_s.match(@expected_path)
|
|
26
|
+
res = if @expected_path.is_a? Regexp
|
|
27
|
+
@actual_path.to_s.match?(@expected_path)
|
|
26
28
|
else
|
|
27
29
|
::Addressable::URI.parse(@expected_path) == ::Addressable::URI.parse(@actual_path)
|
|
28
30
|
end
|
|
31
|
+
|
|
32
|
+
res && matches_filter_block?(uri)
|
|
29
33
|
end
|
|
30
34
|
|
|
31
35
|
def failure_message
|
|
@@ -38,6 +42,12 @@ module Capybara
|
|
|
38
42
|
|
|
39
43
|
private
|
|
40
44
|
|
|
45
|
+
def matches_filter_block?(url)
|
|
46
|
+
return true unless @filter_block
|
|
47
|
+
|
|
48
|
+
@filter_block.call(url)
|
|
49
|
+
end
|
|
50
|
+
|
|
41
51
|
def failure_message_helper(negated = '')
|
|
42
52
|
verb = @expected_path.is_a?(Regexp) ? 'match' : 'equal'
|
|
43
53
|
"expected #{@actual_path.inspect}#{negated} to #{verb} #{@expected_path.inspect}"
|