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,371 +1,207 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
-
module Capybara
|
|
3
|
-
module RSpecMatchers
|
|
4
|
-
class Matcher
|
|
5
|
-
if defined?(::RSpec::Expectations::Version) && (Gem::Version.new(RSpec::Expectations::Version::STRING) >= Gem::Version.new('3.0'))
|
|
6
|
-
require 'capybara/rspec/compound'
|
|
7
|
-
include ::Capybara::RSpecMatchers::Compound
|
|
8
|
-
end
|
|
9
|
-
|
|
10
|
-
attr_reader :failure_message, :failure_message_when_negated
|
|
11
|
-
|
|
12
|
-
def wrap(actual)
|
|
13
|
-
@context_el = if actual.respond_to?("has_selector?")
|
|
14
|
-
actual
|
|
15
|
-
else
|
|
16
|
-
Capybara.string(actual.to_s)
|
|
17
|
-
end
|
|
18
|
-
end
|
|
19
2
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
3
|
+
require 'capybara/rspec/matchers/have_selector'
|
|
4
|
+
require 'capybara/rspec/matchers/have_ancestor'
|
|
5
|
+
require 'capybara/rspec/matchers/have_sibling'
|
|
6
|
+
require 'capybara/rspec/matchers/match_selector'
|
|
7
|
+
require 'capybara/rspec/matchers/have_current_path'
|
|
8
|
+
require 'capybara/rspec/matchers/match_style'
|
|
9
|
+
require 'capybara/rspec/matchers/have_text'
|
|
10
|
+
require 'capybara/rspec/matchers/have_title'
|
|
11
|
+
require 'capybara/rspec/matchers/become_closed'
|
|
23
12
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
def wrap_does_not_match?(actual)
|
|
34
|
-
yield(wrap(actual))
|
|
35
|
-
rescue Capybara::ExpectationNotMet => e
|
|
36
|
-
@failure_message_when_negated = e.message
|
|
37
|
-
return false
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
def session_query_args
|
|
41
|
-
if @args.last.is_a? Hash
|
|
42
|
-
@args.last[:session_options] = session_options
|
|
43
|
-
else
|
|
44
|
-
@args.push(session_options: session_options)
|
|
45
|
-
end
|
|
46
|
-
@args
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
def session_options
|
|
50
|
-
@context_el ||= nil
|
|
51
|
-
if @context_el.respond_to? :session_options
|
|
52
|
-
@context_el.session_options
|
|
53
|
-
elsif @context_el.respond_to? :current_scope
|
|
54
|
-
@context_el.current_scope.session_options
|
|
55
|
-
else
|
|
56
|
-
Capybara.session_options
|
|
57
|
-
end
|
|
58
|
-
end
|
|
13
|
+
module Capybara
|
|
14
|
+
module RSpecMatchers
|
|
15
|
+
# RSpec matcher for whether the element(s) matching a given selector exist.
|
|
16
|
+
#
|
|
17
|
+
# @see Capybara::Node::Matchers#assert_selector
|
|
18
|
+
def have_selector(...)
|
|
19
|
+
Matchers::HaveSelector.new(...)
|
|
59
20
|
end
|
|
60
21
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
def matches?(actual)
|
|
68
|
-
wrap_matches?(actual){ |el| el.assert_selector(*@args, &@filter_block) }
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
def does_not_match?(actual)
|
|
72
|
-
wrap_does_not_match?(actual){ |el| el.assert_no_selector(*@args, &@filter_block) }
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
def description
|
|
76
|
-
"have #{query.description}"
|
|
77
|
-
end
|
|
78
|
-
|
|
79
|
-
def query
|
|
80
|
-
@query ||= Capybara::Queries::SelectorQuery.new(*session_query_args, &@filter_block)
|
|
81
|
-
end
|
|
22
|
+
# RSpec matcher for whether the element(s) matching a group of selectors exist.
|
|
23
|
+
#
|
|
24
|
+
# @see Capybara::Node::Matchers#assert_all_of_selectors
|
|
25
|
+
def have_all_of_selectors(...)
|
|
26
|
+
Matchers::HaveAllSelectors.new(...)
|
|
82
27
|
end
|
|
83
28
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
def matches?(actual)
|
|
91
|
-
wrap_matches?(actual){ |el| el.assert_all_of_selectors(*@args, &@filter_block) }
|
|
92
|
-
end
|
|
93
|
-
|
|
94
|
-
def does_not_match?(actual)
|
|
95
|
-
raise ArgumentError, "The have_all_selectors matcher does not support use with not_to/should_not"
|
|
96
|
-
end
|
|
97
|
-
|
|
98
|
-
def description
|
|
99
|
-
"have all selectors"
|
|
100
|
-
end
|
|
29
|
+
# RSpec matcher for whether no element(s) matching a group of selectors exist.
|
|
30
|
+
#
|
|
31
|
+
# @see Capybara::Node::Matchers#assert_none_of_selectors
|
|
32
|
+
def have_none_of_selectors(...)
|
|
33
|
+
Matchers::HaveNoSelectors.new(...)
|
|
101
34
|
end
|
|
102
35
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
def matches?(actual)
|
|
110
|
-
wrap_matches?(actual){ |el| el.assert_none_of_selectors(*@args, &@filter_block) }
|
|
111
|
-
end
|
|
112
|
-
|
|
113
|
-
def does_not_match?(actual)
|
|
114
|
-
raise ArgumentError, "The have_none_of_selectors matcher does not support use with not_to/should_not"
|
|
115
|
-
end
|
|
116
|
-
|
|
117
|
-
def description
|
|
118
|
-
"have no selectors"
|
|
119
|
-
end
|
|
36
|
+
# RSpec matcher for whether the element(s) matching any of a group of selectors exist.
|
|
37
|
+
#
|
|
38
|
+
# @see Capybara::Node::Matchers#assert_any_of_selectors
|
|
39
|
+
def have_any_of_selectors(...)
|
|
40
|
+
Matchers::HaveAnySelectors.new(...)
|
|
120
41
|
end
|
|
121
42
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
def does_not_match?(actual)
|
|
128
|
-
wrap_does_not_match?(actual) { |el| el.assert_not_matches_selector(*@args, &@filter_block) }
|
|
129
|
-
end
|
|
130
|
-
|
|
131
|
-
def description
|
|
132
|
-
"match #{query.description}"
|
|
133
|
-
end
|
|
134
|
-
|
|
135
|
-
def query
|
|
136
|
-
@query ||= Capybara::Queries::MatchQuery.new(*session_query_args, &@filter_block)
|
|
137
|
-
end
|
|
43
|
+
# RSpec matcher for whether the current element matches a given selector.
|
|
44
|
+
#
|
|
45
|
+
# @see Capybara::Node::Matchers#assert_matches_selector
|
|
46
|
+
def match_selector(...)
|
|
47
|
+
Matchers::MatchSelector.new(...)
|
|
138
48
|
end
|
|
139
49
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
def initialize(*args)
|
|
144
|
-
@args = args.dup
|
|
145
|
-
|
|
146
|
-
# are set just for backwards compatability
|
|
147
|
-
@type = args.shift if args.first.is_a?(Symbol)
|
|
148
|
-
@content = args.shift
|
|
149
|
-
@options = (args.first.is_a?(Hash))? args.first : {}
|
|
150
|
-
end
|
|
151
|
-
|
|
152
|
-
def matches?(actual)
|
|
153
|
-
wrap_matches?(actual) { |el| el.assert_text(*@args) }
|
|
154
|
-
end
|
|
155
|
-
|
|
156
|
-
def does_not_match?(actual)
|
|
157
|
-
wrap_does_not_match?(actual) { |el| el.assert_no_text(*@args) }
|
|
158
|
-
end
|
|
159
|
-
|
|
160
|
-
def description
|
|
161
|
-
"text #{format(content)}"
|
|
50
|
+
%i[css xpath].each do |selector|
|
|
51
|
+
define_method "have_#{selector}" do |expr, **options, &optional_filter_block|
|
|
52
|
+
Matchers::HaveSelector.new(selector, expr, **options, &optional_filter_block)
|
|
162
53
|
end
|
|
163
54
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
content.inspect
|
|
55
|
+
define_method "match_#{selector}" do |expr, **options, &optional_filter_block|
|
|
56
|
+
Matchers::MatchSelector.new(selector, expr, **options, &optional_filter_block)
|
|
167
57
|
end
|
|
168
58
|
end
|
|
169
59
|
|
|
170
|
-
|
|
171
|
-
|
|
60
|
+
# @!method have_xpath(xpath, **options, &optional_filter_block)
|
|
61
|
+
# RSpec matcher for whether elements(s) matching a given xpath selector exist.
|
|
62
|
+
#
|
|
63
|
+
# @see Capybara::Node::Matchers#has_xpath?
|
|
172
64
|
|
|
173
|
-
|
|
174
|
-
|
|
65
|
+
# @!method have_css(css, **options, &optional_filter_block)
|
|
66
|
+
# RSpec matcher for whether elements(s) matching a given css selector exist
|
|
67
|
+
#
|
|
68
|
+
# @see Capybara::Node::Matchers#has_css?
|
|
175
69
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
70
|
+
# @!method match_xpath(xpath, **options, &optional_filter_block)
|
|
71
|
+
# RSpec matcher for whether the current element matches a given xpath selector.
|
|
72
|
+
#
|
|
73
|
+
# @see Capybara::Node::Matchers#matches_xpath?
|
|
179
74
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
75
|
+
# @!method match_css(css, **options, &optional_filter_block)
|
|
76
|
+
# RSpec matcher for whether the current element matches a given css selector.
|
|
77
|
+
#
|
|
78
|
+
# @see Capybara::Node::Matchers#matches_css?
|
|
183
79
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
def description
|
|
189
|
-
"have title #{title.inspect}"
|
|
80
|
+
%i[link button field select table element].each do |selector|
|
|
81
|
+
define_method "have_#{selector}" do |locator = nil, **options, &optional_filter_block|
|
|
82
|
+
Matchers::HaveSelector.new(selector, locator, **options, &optional_filter_block)
|
|
190
83
|
end
|
|
191
84
|
end
|
|
192
85
|
|
|
193
|
-
|
|
194
|
-
|
|
86
|
+
# @!method have_element(locator = nil, **options, &optional_filter_block)
|
|
87
|
+
# RSpec matcher for elements.
|
|
88
|
+
#
|
|
89
|
+
# @see Capybara::Node::Matchers#has_element?
|
|
195
90
|
|
|
196
|
-
|
|
197
|
-
|
|
91
|
+
# @!method have_link(locator = nil, **options, &optional_filter_block)
|
|
92
|
+
# RSpec matcher for links.
|
|
93
|
+
#
|
|
94
|
+
# @see Capybara::Node::Matchers#has_link?
|
|
198
95
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
96
|
+
# @!method have_button(locator = nil, **options, &optional_filter_block)
|
|
97
|
+
# RSpec matcher for buttons.
|
|
98
|
+
#
|
|
99
|
+
# @see Capybara::Node::Matchers#has_button?
|
|
202
100
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
101
|
+
# @!method have_field(locator = nil, **options, &optional_filter_block)
|
|
102
|
+
# RSpec matcher for form fields.
|
|
103
|
+
#
|
|
104
|
+
# @see Capybara::Node::Matchers#has_field?
|
|
206
105
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
106
|
+
# @!method have_select(locator = nil, **options, &optional_filter_block)
|
|
107
|
+
# RSpec matcher for select elements.
|
|
108
|
+
#
|
|
109
|
+
# @see Capybara::Node::Matchers#has_select?
|
|
210
110
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
111
|
+
# @!method have_table(locator = nil, **options, &optional_filter_block)
|
|
112
|
+
# RSpec matcher for table elements.
|
|
113
|
+
#
|
|
114
|
+
# @see Capybara::Node::Matchers#has_table?
|
|
215
115
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
116
|
+
%i[checked unchecked].each do |state|
|
|
117
|
+
define_method "have_#{state}_field" do |locator = nil, **options, &optional_filter_block|
|
|
118
|
+
Matchers::HaveSelector.new(:field, locator, **options.merge(state => true), &optional_filter_block)
|
|
219
119
|
end
|
|
220
|
-
|
|
221
|
-
def matches?(window)
|
|
222
|
-
@window = window
|
|
223
|
-
@wait_time = Capybara::Queries::BaseQuery.wait(@options, window.session.config.default_max_wait_time)
|
|
224
|
-
start_time = Capybara::Helpers.monotonic_time
|
|
225
|
-
while window.exists?
|
|
226
|
-
return false if (Capybara::Helpers.monotonic_time - start_time) > @wait_time
|
|
227
|
-
sleep 0.05
|
|
228
|
-
end
|
|
229
|
-
true
|
|
230
|
-
end
|
|
231
|
-
|
|
232
|
-
def failure_message
|
|
233
|
-
"expected #{@window.inspect} to become closed after #{@wait_time} seconds"
|
|
234
|
-
end
|
|
235
|
-
|
|
236
|
-
def failure_message_when_negated
|
|
237
|
-
"expected #{@window.inspect} not to become closed after #{@wait_time} seconds"
|
|
238
|
-
end
|
|
239
|
-
|
|
240
|
-
# RSpec 2 compatibility:
|
|
241
|
-
alias_method :failure_message_for_should, :failure_message
|
|
242
|
-
alias_method :failure_message_for_should_not, :failure_message_when_negated
|
|
243
|
-
end
|
|
244
|
-
|
|
245
|
-
# RSpec matcher for whether the element(s) matching a given selector exist
|
|
246
|
-
# See {Capybara::Node::Matcher#assert_selector}
|
|
247
|
-
def have_selector(*args, &optional_filter_block)
|
|
248
|
-
HaveSelector.new(*args, &optional_filter_block)
|
|
249
|
-
end
|
|
250
|
-
|
|
251
|
-
# RSpec matcher for whether the element(s) matching a group of selectors exist
|
|
252
|
-
# See {Capybara::Node::Matcher#assert_all_of_selectors}
|
|
253
|
-
def have_all_of_selectors(*args, &optional_filter_block)
|
|
254
|
-
HaveAllSelectors.new(*args, &optional_filter_block)
|
|
255
|
-
end
|
|
256
|
-
|
|
257
|
-
# RSpec matcher for whether no element(s) matching a group of selectors exist
|
|
258
|
-
# See {Capybara::Node::Matcher#assert_none_of_selectors}
|
|
259
|
-
def have_none_of_selectors(*args, &optional_filter_block)
|
|
260
|
-
HaveNoSelectors.new(*args, &optional_filter_block)
|
|
261
|
-
end
|
|
262
|
-
|
|
263
|
-
# RSpec matcher for whether the current element matches a given selector
|
|
264
|
-
# See {Capybara::Node::Matchers#assert_matches_selector}
|
|
265
|
-
def match_selector(*args, &optional_filter_block)
|
|
266
|
-
MatchSelector.new(*args, &optional_filter_block)
|
|
267
|
-
end
|
|
268
|
-
# defined_negated_matcher was added in RSpec 3.1 - it's syntactic sugar only since a user can do
|
|
269
|
-
# expect(page).not_to match_selector, so not sure we really need to support not_match_selector for prior to RSpec 3.1
|
|
270
|
-
::RSpec::Matchers.define_negated_matcher :not_match_selector, :match_selector if defined?(::RSpec::Expectations::Version) && (Gem::Version.new(RSpec::Expectations::Version::STRING) >= Gem::Version.new('3.1'))
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
# RSpec matcher for whether elements(s) matching a given xpath selector exist
|
|
274
|
-
# See {Capybara::Node::Matchers#has_xpath?}
|
|
275
|
-
def have_xpath(xpath, options={}, &optional_filter_block)
|
|
276
|
-
HaveSelector.new(:xpath, xpath, options, &optional_filter_block)
|
|
277
|
-
end
|
|
278
|
-
|
|
279
|
-
# RSpec matcher for whether the current element matches a given xpath selector
|
|
280
|
-
def match_xpath(xpath, options={}, &optional_filter_block)
|
|
281
|
-
MatchSelector.new(:xpath, xpath, options, &optional_filter_block)
|
|
282
120
|
end
|
|
283
121
|
|
|
284
|
-
#
|
|
285
|
-
#
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
end
|
|
122
|
+
# @!method have_checked_field(locator = nil, **options, &optional_filter_block)
|
|
123
|
+
# RSpec matcher for checked fields.
|
|
124
|
+
#
|
|
125
|
+
# @see Capybara::Node::Matchers#has_checked_field?
|
|
289
126
|
|
|
290
|
-
#
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
127
|
+
# @!method have_unchecked_field(locator = nil, **options, &optional_filter_block)
|
|
128
|
+
# RSpec matcher for unchecked fields.
|
|
129
|
+
#
|
|
130
|
+
# @see Capybara::Node::Matchers#has_unchecked_field?
|
|
294
131
|
|
|
295
|
-
# RSpec matcher for text
|
|
296
|
-
#
|
|
297
|
-
|
|
298
|
-
|
|
132
|
+
# RSpec matcher for text content.
|
|
133
|
+
#
|
|
134
|
+
# @see Capybara::Node::Matchers#assert_text
|
|
135
|
+
def have_text(text_or_type, *args, **options)
|
|
136
|
+
Matchers::HaveText.new(text_or_type, *args, **options)
|
|
299
137
|
end
|
|
300
138
|
alias_method :have_content, :have_text
|
|
301
139
|
|
|
302
|
-
def have_title(title, options
|
|
303
|
-
HaveTitle.new(title, options)
|
|
140
|
+
def have_title(title, **options)
|
|
141
|
+
Matchers::HaveTitle.new(title, **options)
|
|
304
142
|
end
|
|
305
143
|
|
|
306
|
-
# RSpec matcher for the current path
|
|
307
|
-
#
|
|
308
|
-
|
|
309
|
-
|
|
144
|
+
# RSpec matcher for the current path.
|
|
145
|
+
#
|
|
146
|
+
# @see Capybara::SessionMatchers#assert_current_path
|
|
147
|
+
def have_current_path(path, **options, &optional_filter_block)
|
|
148
|
+
Matchers::HaveCurrentPath.new(path, **options, &optional_filter_block)
|
|
310
149
|
end
|
|
311
150
|
|
|
312
|
-
# RSpec matcher for
|
|
313
|
-
#
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
151
|
+
# RSpec matcher for element style.
|
|
152
|
+
#
|
|
153
|
+
# @see Capybara::Node::Matchers#matches_style?
|
|
154
|
+
def match_style(styles = nil, **options)
|
|
155
|
+
styles, options = options, {} if styles.nil?
|
|
156
|
+
Matchers::MatchStyle.new(styles, **options)
|
|
317
157
|
end
|
|
318
158
|
|
|
319
|
-
|
|
320
|
-
#
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
# RSpec matcher for links
|
|
327
|
-
# See {Capybara::Node::Matchers#has_field?}
|
|
328
|
-
def have_field(locator=nil, options={}, &optional_filter_block)
|
|
329
|
-
locator, options = nil, locator if locator.is_a? Hash
|
|
330
|
-
HaveSelector.new(:field, locator, options, &optional_filter_block)
|
|
159
|
+
##
|
|
160
|
+
# @deprecated
|
|
161
|
+
#
|
|
162
|
+
def have_style(styles = nil, **options)
|
|
163
|
+
Capybara::Helpers.warn "DEPRECATED: have_style is deprecated, please use match_style : #{Capybara::Helpers.filter_backtrace(caller)}"
|
|
164
|
+
match_style(styles, **options)
|
|
331
165
|
end
|
|
332
166
|
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
167
|
+
%w[selector css xpath text title current_path link button
|
|
168
|
+
field checked_field unchecked_field select table
|
|
169
|
+
sibling ancestor element].each do |matcher_type|
|
|
170
|
+
define_method "have_no_#{matcher_type}" do |*args, **kw_args, &optional_filter_block|
|
|
171
|
+
Matchers::NegatedMatcher.new(send("have_#{matcher_type}", *args, **kw_args, &optional_filter_block))
|
|
172
|
+
end
|
|
338
173
|
end
|
|
174
|
+
alias_method :have_no_content, :have_no_text
|
|
339
175
|
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
HaveSelector.new(:field, locator, options.merge(unchecked: true), &optional_filter_block)
|
|
176
|
+
%w[selector css xpath].each do |matcher_type|
|
|
177
|
+
define_method "not_match_#{matcher_type}" do |*args, **kw_args, &optional_filter_block|
|
|
178
|
+
Matchers::NegatedMatcher.new(send("match_#{matcher_type}", *args, **kw_args, &optional_filter_block))
|
|
179
|
+
end
|
|
345
180
|
end
|
|
346
181
|
|
|
347
|
-
# RSpec matcher for
|
|
348
|
-
#
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
182
|
+
# RSpec matcher for whether sibling element(s) matching a given selector exist.
|
|
183
|
+
#
|
|
184
|
+
# @see Capybara::Node::Matchers#assert_sibling
|
|
185
|
+
def have_sibling(...)
|
|
186
|
+
Matchers::HaveSibling.new(...)
|
|
352
187
|
end
|
|
353
188
|
|
|
354
|
-
# RSpec matcher for
|
|
355
|
-
#
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
189
|
+
# RSpec matcher for whether ancestor element(s) matching a given selector exist.
|
|
190
|
+
#
|
|
191
|
+
# @see Capybara::Node::Matchers#assert_ancestor
|
|
192
|
+
def have_ancestor(...)
|
|
193
|
+
Matchers::HaveAncestor.new(...)
|
|
359
194
|
end
|
|
360
195
|
|
|
361
196
|
##
|
|
362
197
|
# Wait for window to become closed.
|
|
198
|
+
#
|
|
363
199
|
# @example
|
|
364
200
|
# expect(window).to become_closed(wait: 0.8)
|
|
365
|
-
#
|
|
366
|
-
# @option options [Numeric] :wait
|
|
367
|
-
def become_closed(options
|
|
368
|
-
BecomeClosed.new(options)
|
|
201
|
+
#
|
|
202
|
+
# @option options [Numeric] :wait Maximum wait time. Defaults to {Capybara.configure default_max_wait_time}
|
|
203
|
+
def become_closed(**options)
|
|
204
|
+
Matchers::BecomeClosed.new(options)
|
|
369
205
|
end
|
|
370
206
|
end
|
|
371
|
-
end
|
|
207
|
+
end
|
data/lib/capybara/rspec.rb
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
+
|
|
2
3
|
require 'rspec/core'
|
|
3
4
|
require 'capybara/dsl'
|
|
4
5
|
require 'capybara/rspec/matchers'
|
|
@@ -6,14 +7,11 @@ require 'capybara/rspec/features'
|
|
|
6
7
|
require 'capybara/rspec/matcher_proxies'
|
|
7
8
|
|
|
8
9
|
RSpec.configure do |config|
|
|
9
|
-
config.include Capybara::DSL, :
|
|
10
|
-
config.include Capybara::RSpecMatchers, :
|
|
11
|
-
config.include Capybara::
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
# RSpec 2 and RSpec 3.
|
|
15
|
-
fetch_current_example = RSpec.respond_to?(:current_example) ?
|
|
16
|
-
proc { RSpec.current_example } : proc { |context| context.example }
|
|
10
|
+
config.include Capybara::DSL, type: :feature
|
|
11
|
+
config.include Capybara::RSpecMatchers, type: :feature
|
|
12
|
+
config.include Capybara::DSL, type: :system
|
|
13
|
+
config.include Capybara::RSpecMatchers, type: :system
|
|
14
|
+
config.include Capybara::RSpecMatchers, type: :view
|
|
17
15
|
|
|
18
16
|
# The before and after blocks must run instantaneously, because Capybara
|
|
19
17
|
# might not actually be used in all examples where it's included.
|
|
@@ -24,12 +22,10 @@ RSpec.configure do |config|
|
|
|
24
22
|
end
|
|
25
23
|
end
|
|
26
24
|
|
|
27
|
-
config.before do
|
|
25
|
+
config.before do |example|
|
|
28
26
|
if self.class.include?(Capybara::DSL)
|
|
29
|
-
example = fetch_current_example.call(self)
|
|
30
27
|
Capybara.current_driver = Capybara.javascript_driver if example.metadata[:js]
|
|
31
28
|
Capybara.current_driver = example.metadata[:driver] if example.metadata[:driver]
|
|
32
29
|
end
|
|
33
30
|
end
|
|
34
31
|
end
|
|
35
|
-
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'xpath'
|
|
4
|
+
|
|
5
|
+
module Capybara
|
|
6
|
+
class Selector
|
|
7
|
+
# @api private
|
|
8
|
+
class CSSBuilder
|
|
9
|
+
def initialize(expression)
|
|
10
|
+
@expression = expression || ''
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
attr_reader :expression
|
|
14
|
+
|
|
15
|
+
def add_attribute_conditions(**attributes)
|
|
16
|
+
@expression = attributes.inject(expression) do |css, (name, value)|
|
|
17
|
+
conditions = if name == :class
|
|
18
|
+
class_conditions(value)
|
|
19
|
+
elsif value.is_a? Regexp
|
|
20
|
+
regexp_conditions(name, value)
|
|
21
|
+
else
|
|
22
|
+
[attribute_conditions(name => value)]
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
::Capybara::Selector::CSS.split(css).map do |sel|
|
|
26
|
+
next sel if conditions.empty?
|
|
27
|
+
|
|
28
|
+
conditions.map { |cond| sel + cond }.join(', ')
|
|
29
|
+
end.join(', ')
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
private
|
|
34
|
+
|
|
35
|
+
def regexp_conditions(name, value)
|
|
36
|
+
Selector::RegexpDisassembler.new(value).alternated_substrings.map do |strs|
|
|
37
|
+
strs.map do |str|
|
|
38
|
+
"[#{name}*='#{str}'#{' i' if value.casefold?}]"
|
|
39
|
+
end.join
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def attribute_conditions(attributes)
|
|
44
|
+
attributes.map do |attribute, value|
|
|
45
|
+
case value
|
|
46
|
+
when XPath::Expression
|
|
47
|
+
raise ArgumentError, "XPath expressions are not supported for the :#{attribute} filter with CSS based selectors"
|
|
48
|
+
when Regexp
|
|
49
|
+
Selector::RegexpDisassembler.new(value).substrings.map do |str|
|
|
50
|
+
"[#{attribute}*='#{str}'#{' i' if value.casefold?}]"
|
|
51
|
+
end.join
|
|
52
|
+
when true
|
|
53
|
+
"[#{attribute}]"
|
|
54
|
+
when false
|
|
55
|
+
':not([attribute])'
|
|
56
|
+
else
|
|
57
|
+
if attribute == :id
|
|
58
|
+
"##{::Capybara::Selector::CSS.escape(value)}"
|
|
59
|
+
else
|
|
60
|
+
"[#{attribute}='#{value}']"
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end.join
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def class_conditions(classes)
|
|
67
|
+
case classes
|
|
68
|
+
when XPath::Expression
|
|
69
|
+
raise ArgumentError, 'XPath expressions are not supported for the :class filter with CSS based selectors'
|
|
70
|
+
when Regexp
|
|
71
|
+
Selector::RegexpDisassembler.new(classes).alternated_substrings.map do |strs|
|
|
72
|
+
strs.map do |str|
|
|
73
|
+
"[class*='#{str}'#{' i' if classes.casefold?}]"
|
|
74
|
+
end.join
|
|
75
|
+
end
|
|
76
|
+
else
|
|
77
|
+
cls = Array(classes).reject { |c| c.is_a? Regexp }.group_by { |cl| cl.match?(/^!(?!!!)/) }
|
|
78
|
+
[(cls[false].to_a.map { |cl| ".#{Capybara::Selector::CSS.escape(cl.sub(/^!!/, ''))}" } +
|
|
79
|
+
cls[true].to_a.map { |cl| ":not(.#{Capybara::Selector::CSS.escape(cl.slice(1..))})" }).join]
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|