capybara 3.0.0 → 3.40.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.yardopts +1 -1
- data/History.md +891 -12
- data/License.txt +1 -1
- data/README.md +257 -84
- data/lib/capybara/config.rb +29 -10
- data/lib/capybara/cucumber.rb +1 -1
- data/lib/capybara/driver/base.rb +22 -4
- data/lib/capybara/driver/node.rb +38 -9
- data/lib/capybara/dsl.rb +9 -7
- data/lib/capybara/helpers.rb +57 -8
- data/lib/capybara/minitest/spec.rb +185 -84
- data/lib/capybara/minitest.rb +264 -145
- data/lib/capybara/node/actions.rb +248 -124
- data/lib/capybara/node/base.rb +35 -20
- data/lib/capybara/node/document.rb +14 -2
- data/lib/capybara/node/document_matchers.rb +13 -15
- data/lib/capybara/node/element.rb +350 -113
- data/lib/capybara/node/finders.rb +104 -82
- data/lib/capybara/node/matchers.rb +363 -157
- data/lib/capybara/node/simple.rb +54 -15
- data/lib/capybara/node/whitespace_normalizer.rb +81 -0
- data/lib/capybara/queries/active_element_query.rb +18 -0
- data/lib/capybara/queries/ancestor_query.rb +9 -10
- data/lib/capybara/queries/base_query.rb +25 -18
- data/lib/capybara/queries/current_path_query.rb +16 -6
- data/lib/capybara/queries/match_query.rb +11 -0
- data/lib/capybara/queries/selector_query.rb +617 -104
- data/lib/capybara/queries/sibling_query.rb +9 -7
- data/lib/capybara/queries/style_query.rb +45 -0
- data/lib/capybara/queries/text_query.rb +40 -22
- data/lib/capybara/queries/title_query.rb +2 -2
- data/lib/capybara/rack_test/browser.rb +106 -31
- data/lib/capybara/rack_test/driver.rb +16 -7
- data/lib/capybara/rack_test/errors.rb +6 -0
- data/lib/capybara/rack_test/form.rb +74 -49
- data/lib/capybara/rack_test/node.rb +120 -47
- data/lib/capybara/rails.rb +1 -1
- data/lib/capybara/registration_container.rb +41 -0
- data/lib/capybara/registrations/drivers.rb +42 -0
- data/lib/capybara/registrations/patches/puma_ssl.rb +29 -0
- data/lib/capybara/registrations/servers.rb +66 -0
- data/lib/capybara/result.rb +87 -53
- data/lib/capybara/rspec/features.rb +8 -10
- data/lib/capybara/rspec/matcher_proxies.rb +39 -18
- data/lib/capybara/rspec/matchers/base.rb +113 -0
- data/lib/capybara/rspec/matchers/become_closed.rb +33 -0
- data/lib/capybara/rspec/matchers/compound.rb +88 -0
- data/lib/capybara/rspec/matchers/count_sugar.rb +37 -0
- data/lib/capybara/rspec/matchers/have_ancestor.rb +28 -0
- data/lib/capybara/rspec/matchers/have_current_path.rb +29 -0
- data/lib/capybara/rspec/matchers/have_selector.rb +69 -0
- data/lib/capybara/rspec/matchers/have_sibling.rb +27 -0
- data/lib/capybara/rspec/matchers/have_text.rb +33 -0
- data/lib/capybara/rspec/matchers/have_title.rb +29 -0
- data/lib/capybara/rspec/matchers/match_selector.rb +27 -0
- data/lib/capybara/rspec/matchers/match_style.rb +43 -0
- data/lib/capybara/rspec/matchers/spatial_sugar.rb +39 -0
- data/lib/capybara/rspec/matchers.rb +142 -315
- data/lib/capybara/rspec.rb +3 -2
- data/lib/capybara/selector/builders/css_builder.rb +84 -0
- data/lib/capybara/selector/builders/xpath_builder.rb +71 -0
- data/lib/capybara/selector/css.rb +85 -8
- data/lib/capybara/selector/definition/button.rb +68 -0
- data/lib/capybara/selector/definition/checkbox.rb +26 -0
- data/lib/capybara/selector/definition/css.rb +10 -0
- data/lib/capybara/selector/definition/datalist_input.rb +35 -0
- data/lib/capybara/selector/definition/datalist_option.rb +25 -0
- data/lib/capybara/selector/definition/element.rb +28 -0
- data/lib/capybara/selector/definition/field.rb +40 -0
- data/lib/capybara/selector/definition/fieldset.rb +14 -0
- data/lib/capybara/selector/definition/file_field.rb +13 -0
- data/lib/capybara/selector/definition/fillable_field.rb +33 -0
- data/lib/capybara/selector/definition/frame.rb +17 -0
- data/lib/capybara/selector/definition/id.rb +6 -0
- data/lib/capybara/selector/definition/label.rb +62 -0
- data/lib/capybara/selector/definition/link.rb +55 -0
- data/lib/capybara/selector/definition/link_or_button.rb +16 -0
- data/lib/capybara/selector/definition/option.rb +27 -0
- data/lib/capybara/selector/definition/radio_button.rb +27 -0
- data/lib/capybara/selector/definition/select.rb +81 -0
- data/lib/capybara/selector/definition/table.rb +109 -0
- data/lib/capybara/selector/definition/table_row.rb +21 -0
- data/lib/capybara/selector/definition/xpath.rb +5 -0
- data/lib/capybara/selector/definition.rb +280 -0
- data/lib/capybara/selector/filter.rb +1 -0
- data/lib/capybara/selector/filter_set.rb +72 -28
- data/lib/capybara/selector/filters/base.rb +45 -2
- data/lib/capybara/selector/filters/expression_filter.rb +5 -6
- data/lib/capybara/selector/filters/locator_filter.rb +29 -0
- data/lib/capybara/selector/filters/node_filter.rb +18 -4
- data/lib/capybara/selector/regexp_disassembler.rb +211 -0
- data/lib/capybara/selector/selector.rb +89 -200
- data/lib/capybara/selector/xpath_extensions.rb +17 -0
- data/lib/capybara/selector.rb +474 -534
- data/lib/capybara/selenium/atoms/getAttribute.min.js +1 -0
- data/lib/capybara/selenium/atoms/isDisplayed.min.js +1 -0
- data/lib/capybara/selenium/atoms/src/getAttribute.js +161 -0
- data/lib/capybara/selenium/atoms/src/isDisplayed.js +454 -0
- data/lib/capybara/selenium/driver.rb +270 -245
- data/lib/capybara/selenium/driver_specializations/chrome_driver.rb +117 -0
- data/lib/capybara/selenium/driver_specializations/edge_driver.rb +128 -0
- data/lib/capybara/selenium/driver_specializations/firefox_driver.rb +84 -0
- data/lib/capybara/selenium/driver_specializations/internet_explorer_driver.rb +26 -0
- data/lib/capybara/selenium/driver_specializations/safari_driver.rb +24 -0
- data/lib/capybara/selenium/extensions/file_input_click_emulation.rb +34 -0
- data/lib/capybara/selenium/extensions/find.rb +110 -0
- data/lib/capybara/selenium/extensions/html5_drag.rb +229 -0
- data/lib/capybara/selenium/extensions/modifier_keys_stack.rb +28 -0
- data/lib/capybara/selenium/extensions/scroll.rb +76 -0
- data/lib/capybara/selenium/node.rb +460 -170
- data/lib/capybara/selenium/nodes/chrome_node.rb +125 -0
- data/lib/capybara/selenium/nodes/edge_node.rb +110 -0
- data/lib/capybara/selenium/nodes/firefox_node.rb +136 -0
- data/lib/capybara/selenium/nodes/ie_node.rb +22 -0
- data/lib/capybara/selenium/nodes/safari_node.rb +118 -0
- data/lib/capybara/selenium/patches/atoms.rb +18 -0
- data/lib/capybara/selenium/patches/is_displayed.rb +16 -0
- data/lib/capybara/selenium/patches/logs.rb +45 -0
- data/lib/capybara/selenium/patches/pause_duration_fix.rb +9 -0
- data/lib/capybara/selenium/patches/persistent_client.rb +20 -0
- data/lib/capybara/server/animation_disabler.rb +80 -0
- data/lib/capybara/server/checker.rb +44 -0
- data/lib/capybara/server/middleware.rb +71 -0
- data/lib/capybara/server.rb +58 -67
- data/lib/capybara/session/config.rb +40 -6
- data/lib/capybara/session/matchers.rb +26 -19
- data/lib/capybara/session.rb +252 -194
- data/lib/capybara/spec/public/jquery.js +5 -5
- data/lib/capybara/spec/public/offset.js +6 -0
- data/lib/capybara/spec/public/test.js +126 -8
- data/lib/capybara/spec/session/accept_alert_spec.rb +11 -11
- data/lib/capybara/spec/session/accept_confirm_spec.rb +3 -3
- data/lib/capybara/spec/session/accept_prompt_spec.rb +9 -10
- data/lib/capybara/spec/session/active_element_spec.rb +31 -0
- data/lib/capybara/spec/session/all_spec.rb +135 -44
- data/lib/capybara/spec/session/ancestor_spec.rb +24 -19
- data/lib/capybara/spec/session/assert_all_of_selectors_spec.rb +67 -38
- data/lib/capybara/spec/session/{assert_current_path.rb → assert_current_path_spec.rb} +20 -18
- data/lib/capybara/spec/session/assert_selector_spec.rb +143 -0
- data/lib/capybara/spec/session/assert_style_spec.rb +26 -0
- data/lib/capybara/spec/session/{assert_text.rb → assert_text_spec.rb} +76 -52
- data/lib/capybara/spec/session/{assert_title.rb → assert_title_spec.rb} +12 -12
- data/lib/capybara/spec/session/attach_file_spec.rb +126 -72
- data/lib/capybara/spec/session/body_spec.rb +11 -13
- data/lib/capybara/spec/session/check_spec.rb +112 -51
- data/lib/capybara/spec/session/choose_spec.rb +62 -30
- data/lib/capybara/spec/session/click_button_spec.rb +227 -161
- data/lib/capybara/spec/session/click_link_or_button_spec.rb +49 -30
- data/lib/capybara/spec/session/click_link_spec.rb +89 -55
- data/lib/capybara/spec/session/current_scope_spec.rb +8 -8
- data/lib/capybara/spec/session/current_url_spec.rb +44 -37
- data/lib/capybara/spec/session/dismiss_confirm_spec.rb +3 -3
- data/lib/capybara/spec/session/dismiss_prompt_spec.rb +2 -2
- data/lib/capybara/spec/session/element/{assert_match_selector.rb → assert_match_selector_spec.rb} +11 -9
- data/lib/capybara/spec/session/element/match_css_spec.rb +18 -10
- data/lib/capybara/spec/session/element/match_xpath_spec.rb +8 -6
- data/lib/capybara/spec/session/element/matches_selector_spec.rb +70 -56
- data/lib/capybara/spec/session/evaluate_async_script_spec.rb +7 -7
- data/lib/capybara/spec/session/evaluate_script_spec.rb +28 -8
- data/lib/capybara/spec/session/execute_script_spec.rb +8 -7
- data/lib/capybara/spec/session/fill_in_spec.rb +110 -44
- data/lib/capybara/spec/session/find_button_spec.rb +23 -23
- data/lib/capybara/spec/session/find_by_id_spec.rb +8 -8
- data/lib/capybara/spec/session/find_field_spec.rb +33 -31
- data/lib/capybara/spec/session/find_link_spec.rb +42 -14
- data/lib/capybara/spec/session/find_spec.rb +251 -142
- data/lib/capybara/spec/session/first_spec.rb +45 -44
- data/lib/capybara/spec/session/frame/frame_title_spec.rb +6 -6
- data/lib/capybara/spec/session/frame/frame_url_spec.rb +6 -6
- data/lib/capybara/spec/session/frame/switch_to_frame_spec.rb +32 -20
- data/lib/capybara/spec/session/frame/within_frame_spec.rb +46 -19
- data/lib/capybara/spec/session/go_back_spec.rb +1 -1
- data/lib/capybara/spec/session/go_forward_spec.rb +1 -1
- data/lib/capybara/spec/session/has_all_selectors_spec.rb +23 -23
- data/lib/capybara/spec/session/has_ancestor_spec.rb +46 -0
- data/lib/capybara/spec/session/has_any_selectors_spec.rb +29 -0
- data/lib/capybara/spec/session/has_button_spec.rb +98 -12
- data/lib/capybara/spec/session/has_css_spec.rb +271 -137
- data/lib/capybara/spec/session/has_current_path_spec.rb +50 -35
- data/lib/capybara/spec/session/has_element_spec.rb +47 -0
- data/lib/capybara/spec/session/has_field_spec.rb +137 -58
- data/lib/capybara/spec/session/has_link_spec.rb +46 -6
- data/lib/capybara/spec/session/has_none_selectors_spec.rb +33 -31
- data/lib/capybara/spec/session/has_select_spec.rb +84 -50
- data/lib/capybara/spec/session/has_selector_spec.rb +117 -69
- data/lib/capybara/spec/session/has_sibling_spec.rb +50 -0
- data/lib/capybara/spec/session/has_table_spec.rb +181 -4
- data/lib/capybara/spec/session/has_text_spec.rb +101 -53
- data/lib/capybara/spec/session/has_title_spec.rb +19 -14
- data/lib/capybara/spec/session/has_xpath_spec.rb +56 -38
- data/lib/capybara/spec/session/{headers.rb → headers_spec.rb} +1 -1
- data/lib/capybara/spec/session/html_spec.rb +13 -6
- data/lib/capybara/spec/session/matches_style_spec.rb +37 -0
- data/lib/capybara/spec/session/node_spec.rb +958 -122
- data/lib/capybara/spec/session/node_wrapper_spec.rb +15 -12
- data/lib/capybara/spec/session/refresh_spec.rb +9 -7
- data/lib/capybara/spec/session/reset_session_spec.rb +65 -37
- data/lib/capybara/spec/session/{response_code.rb → response_code_spec.rb} +1 -1
- data/lib/capybara/spec/session/save_and_open_page_spec.rb +2 -2
- data/lib/capybara/spec/session/save_and_open_screenshot_spec.rb +5 -4
- data/lib/capybara/spec/session/save_page_spec.rb +41 -38
- data/lib/capybara/spec/session/save_screenshot_spec.rb +13 -11
- data/lib/capybara/spec/session/screenshot_spec.rb +2 -2
- data/lib/capybara/spec/session/scroll_spec.rb +119 -0
- data/lib/capybara/spec/session/select_spec.rb +102 -76
- data/lib/capybara/spec/session/selectors_spec.rb +51 -18
- data/lib/capybara/spec/session/sibling_spec.rb +9 -9
- data/lib/capybara/spec/session/text_spec.rb +26 -24
- data/lib/capybara/spec/session/title_spec.rb +8 -6
- data/lib/capybara/spec/session/uncheck_spec.rb +41 -22
- data/lib/capybara/spec/session/unselect_spec.rb +37 -37
- data/lib/capybara/spec/session/visit_spec.rb +79 -53
- data/lib/capybara/spec/session/window/become_closed_spec.rb +22 -19
- data/lib/capybara/spec/session/window/current_window_spec.rb +4 -3
- data/lib/capybara/spec/session/window/open_new_window_spec.rb +4 -3
- data/lib/capybara/spec/session/window/switch_to_window_spec.rb +25 -21
- data/lib/capybara/spec/session/window/window_opened_by_spec.rb +10 -5
- data/lib/capybara/spec/session/window/window_spec.rb +88 -54
- data/lib/capybara/spec/session/window/windows_spec.rb +11 -8
- data/lib/capybara/spec/session/window/within_window_spec.rb +17 -16
- data/lib/capybara/spec/session/within_spec.rb +82 -44
- data/lib/capybara/spec/spec_helper.rb +46 -52
- data/lib/capybara/spec/test_app.rb +148 -41
- data/lib/capybara/spec/views/animated.erb +49 -0
- data/lib/capybara/spec/views/form.erb +156 -42
- data/lib/capybara/spec/views/frame_child.erb +4 -3
- data/lib/capybara/spec/views/frame_one.erb +2 -1
- data/lib/capybara/spec/views/frame_parent.erb +1 -1
- data/lib/capybara/spec/views/frame_two.erb +1 -1
- data/lib/capybara/spec/views/initial_alert.erb +2 -1
- data/lib/capybara/spec/views/layout.erb +10 -0
- data/lib/capybara/spec/views/obscured.erb +47 -0
- data/lib/capybara/spec/views/offset.erb +33 -0
- data/lib/capybara/spec/views/path.erb +2 -2
- data/lib/capybara/spec/views/popup_one.erb +1 -1
- data/lib/capybara/spec/views/popup_two.erb +1 -1
- data/lib/capybara/spec/views/react.erb +45 -0
- data/lib/capybara/spec/views/scroll.erb +21 -0
- data/lib/capybara/spec/views/spatial.erb +31 -0
- data/lib/capybara/spec/views/tables.erb +68 -1
- data/lib/capybara/spec/views/with_animation.erb +81 -0
- data/lib/capybara/spec/views/with_base_tag.erb +2 -2
- data/lib/capybara/spec/views/with_dragula.erb +24 -0
- data/lib/capybara/spec/views/with_fixed_header_footer.erb +2 -1
- data/lib/capybara/spec/views/with_hover.erb +3 -2
- data/lib/capybara/spec/views/with_hover1.erb +10 -0
- data/lib/capybara/spec/views/with_html.erb +46 -11
- data/lib/capybara/spec/views/with_html5_svg.erb +20 -0
- data/lib/capybara/spec/views/with_jquery_animation.erb +24 -0
- data/lib/capybara/spec/views/with_js.erb +30 -5
- data/lib/capybara/spec/views/with_jstree.erb +26 -0
- data/lib/capybara/spec/views/with_namespace.erb +21 -0
- data/lib/capybara/spec/views/with_scope.erb +2 -2
- data/lib/capybara/spec/views/with_scope_other.erb +6 -0
- data/lib/capybara/spec/views/with_shadow.erb +31 -0
- data/lib/capybara/spec/views/with_slow_unload.erb +2 -1
- data/lib/capybara/spec/views/with_sortable_js.erb +21 -0
- data/lib/capybara/spec/views/with_unload_alert.erb +1 -0
- data/lib/capybara/spec/views/with_windows.erb +1 -1
- data/lib/capybara/spec/views/within_frames.erb +1 -1
- data/lib/capybara/version.rb +1 -1
- data/lib/capybara/window.rb +32 -26
- data/lib/capybara.rb +128 -104
- data/spec/basic_node_spec.rb +59 -34
- data/spec/capybara_spec.rb +65 -51
- data/spec/counter_spec.rb +35 -0
- data/spec/css_builder_spec.rb +101 -0
- data/spec/css_splitter_spec.rb +38 -0
- data/spec/dsl_spec.rb +84 -55
- data/spec/filter_set_spec.rb +24 -7
- data/spec/fixtures/certificate.pem +25 -0
- data/spec/fixtures/key.pem +27 -0
- data/spec/fixtures/selenium_driver_rspec_failure.rb +5 -5
- data/spec/fixtures/selenium_driver_rspec_success.rb +5 -5
- data/spec/minitest_spec.rb +49 -5
- data/spec/minitest_spec_spec.rb +92 -62
- data/spec/per_session_config_spec.rb +6 -6
- data/spec/rack_test_spec.rb +183 -115
- data/spec/regexp_dissassembler_spec.rb +250 -0
- data/spec/result_spec.rb +99 -39
- data/spec/rspec/features_spec.rb +28 -25
- data/spec/rspec/scenarios_spec.rb +10 -6
- data/spec/rspec/shared_spec_matchers.rb +418 -364
- data/spec/rspec/views_spec.rb +4 -3
- data/spec/rspec_matchers_spec.rb +35 -10
- data/spec/rspec_spec.rb +109 -85
- data/spec/sauce_spec_chrome.rb +43 -0
- data/spec/selector_spec.rb +392 -62
- data/spec/selenium_spec_chrome.rb +183 -41
- data/spec/selenium_spec_chrome_remote.rb +96 -0
- data/spec/selenium_spec_edge.rb +41 -8
- data/spec/selenium_spec_firefox.rb +228 -0
- data/spec/selenium_spec_firefox_remote.rb +94 -0
- data/spec/selenium_spec_ie.rb +129 -11
- data/spec/selenium_spec_safari.rb +162 -0
- data/spec/server_spec.rb +192 -81
- data/spec/session_spec.rb +52 -16
- data/spec/shared_selenium_node.rb +79 -0
- data/spec/shared_selenium_session.rb +460 -123
- data/spec/spec_helper.rb +124 -2
- data/spec/whitespace_normalizer_spec.rb +54 -0
- data/spec/xpath_builder_spec.rb +93 -0
- metadata +344 -45
- data/.yard/templates_custom/default/class/html/selectors.erb +0 -38
- data/.yard/templates_custom/default/class/html/setup.rb +0 -17
- data/.yard/yard_extensions.rb +0 -78
- data/lib/capybara/rspec/compound.rb +0 -90
- data/lib/capybara/spec/session/assert_selector.rb +0 -149
- data/lib/capybara/spec/session/source_spec.rb +0 -0
- data/lib/capybara/spec/views/with_title.erb +0 -5
- data/spec/selenium_spec_marionette.rb +0 -143
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
|
##
|
@@ -45,7 +46,7 @@ module Capybara
|
|
45
46
|
attr_name = name.to_s
|
46
47
|
if attr_name == 'value'
|
47
48
|
value
|
48
|
-
elsif tag_name == 'input'
|
49
|
+
elsif (tag_name == 'input') && (native[:type] == 'checkbox') && (attr_name == 'checked')
|
49
50
|
native['checked'] == 'checked'
|
50
51
|
else
|
51
52
|
native[attr_name]
|
@@ -78,11 +79,11 @@ module Capybara
|
|
78
79
|
if tag_name == 'textarea'
|
79
80
|
native['_capybara_raw_value']
|
80
81
|
elsif tag_name == 'select'
|
81
|
-
|
82
|
-
|
82
|
+
selected_options = find_xpath('.//option[@selected]')
|
83
|
+
if multiple?
|
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
|
##
|
@@ -139,11 +144,19 @@ module Capybara
|
|
139
144
|
native.has_attribute?('selected')
|
140
145
|
end
|
141
146
|
|
147
|
+
def multiple?
|
148
|
+
native.has_attribute?('multiple')
|
149
|
+
end
|
150
|
+
|
151
|
+
def readonly?
|
152
|
+
native.has_attribute?('readonly')
|
153
|
+
end
|
154
|
+
|
142
155
|
def synchronize(_seconds = nil)
|
143
156
|
yield # simple nodes don't need to wait
|
144
157
|
end
|
145
158
|
|
146
|
-
def allow_reload!
|
159
|
+
def allow_reload!(*)
|
147
160
|
# no op
|
148
161
|
end
|
149
162
|
|
@@ -159,12 +172,12 @@ module Capybara
|
|
159
172
|
end
|
160
173
|
|
161
174
|
# @api private
|
162
|
-
def find_css(css)
|
175
|
+
def find_css(css, **_options)
|
163
176
|
native.css(css)
|
164
177
|
end
|
165
178
|
|
166
179
|
# @api private
|
167
|
-
def find_xpath(xpath)
|
180
|
+
def find_xpath(xpath, **_options)
|
168
181
|
native.xpath(xpath)
|
169
182
|
end
|
170
183
|
|
@@ -172,6 +185,32 @@ module Capybara
|
|
172
185
|
def session_options
|
173
186
|
Capybara.session_options
|
174
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
|
175
214
|
end
|
176
215
|
end
|
177
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
|
16
|
-
child_query = @child_node
|
20
|
+
def description(applied = false) # rubocop:disable Style/OptionalBooleanParameter
|
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
|
|
@@ -59,40 +60,46 @@ module Capybara
|
|
59
60
|
# Generates a failure message from the query description and count options.
|
60
61
|
#
|
61
62
|
def failure_message
|
62
|
-
|
63
|
+
+"expected to find #{description}" << count_message
|
63
64
|
end
|
64
65
|
|
65
66
|
def negative_failure_message
|
66
|
-
|
67
|
+
+"expected not to find #{description}" << count_message
|
67
68
|
end
|
68
69
|
|
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}"
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Capybara
|
2
4
|
module Queries
|
3
5
|
class MatchQuery < Capybara::Queries::SelectorQuery
|
@@ -7,6 +9,15 @@ module Capybara
|
|
7
9
|
|
8
10
|
private
|
9
11
|
|
12
|
+
def assert_valid_keys
|
13
|
+
invalid_options = @options.keys & COUNT_KEYS
|
14
|
+
unless invalid_options.empty?
|
15
|
+
raise ArgumentError, "Match queries don't support quantity options. Invalid keys - #{invalid_options.join(', ')}"
|
16
|
+
end
|
17
|
+
|
18
|
+
super
|
19
|
+
end
|
20
|
+
|
10
21
|
def valid_keys
|
11
22
|
super - COUNT_KEYS
|
12
23
|
end
|