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
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Capybara
|
|
4
|
+
module RSpecMatchers
|
|
5
|
+
module SpatialSugar
|
|
6
|
+
def above(el)
|
|
7
|
+
options[:above] = el
|
|
8
|
+
self
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def below(el)
|
|
12
|
+
options[:below] = el
|
|
13
|
+
self
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def left_of(el)
|
|
17
|
+
options[:left_of] = el
|
|
18
|
+
self
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def right_of(el)
|
|
22
|
+
options[:right_of] = el
|
|
23
|
+
self
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def near(el)
|
|
27
|
+
options[:near] = el
|
|
28
|
+
self
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
private
|
|
32
|
+
|
|
33
|
+
def options
|
|
34
|
+
# (@args.last.is_a?(Hash) ? @args : @args.push({})).last
|
|
35
|
+
@kw_args
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -1,405 +1,207 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require 'capybara/rspec/
|
|
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'
|
|
4
12
|
|
|
5
13
|
module Capybara
|
|
6
14
|
module RSpecMatchers
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
def wrap(actual)
|
|
13
|
-
actual = actual.to_capybara_node if actual.respond_to?(:to_capybara_node)
|
|
14
|
-
@context_el = if actual.respond_to?(:has_selector?)
|
|
15
|
-
actual
|
|
16
|
-
else
|
|
17
|
-
Capybara.string(actual.to_s)
|
|
18
|
-
end
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
private
|
|
22
|
-
|
|
23
|
-
def wrap_matches?(actual)
|
|
24
|
-
yield(wrap(actual))
|
|
25
|
-
rescue Capybara::ExpectationNotMet => e
|
|
26
|
-
@failure_message = e.message
|
|
27
|
-
false
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
def wrap_does_not_match?(actual)
|
|
31
|
-
yield(wrap(actual))
|
|
32
|
-
rescue Capybara::ExpectationNotMet => e
|
|
33
|
-
@failure_message_when_negated = e.message
|
|
34
|
-
false
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
def session_query_args
|
|
38
|
-
if @args.last.is_a? Hash
|
|
39
|
-
@args.last[:session_options] = session_options
|
|
40
|
-
else
|
|
41
|
-
@args.push(session_options: session_options)
|
|
42
|
-
end
|
|
43
|
-
@args
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
def session_options
|
|
47
|
-
@context_el ||= nil
|
|
48
|
-
if @context_el.respond_to? :session_options
|
|
49
|
-
@context_el.session_options
|
|
50
|
-
elsif @context_el.respond_to? :current_scope
|
|
51
|
-
@context_el.current_scope.session_options
|
|
52
|
-
else
|
|
53
|
-
Capybara.session_options
|
|
54
|
-
end
|
|
55
|
-
end
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
class HaveSelector < Matcher
|
|
59
|
-
def initialize(*args, &filter_block)
|
|
60
|
-
@args = args
|
|
61
|
-
@filter_block = filter_block
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
def matches?(actual)
|
|
65
|
-
wrap_matches?(actual) { |el| el.assert_selector(*@args, &@filter_block) }
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
def does_not_match?(actual)
|
|
69
|
-
wrap_does_not_match?(actual) { |el| el.assert_no_selector(*@args, &@filter_block) }
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
def description
|
|
73
|
-
"have #{query.description}"
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
def query
|
|
77
|
-
@query ||= Capybara::Queries::SelectorQuery.new(*session_query_args, &@filter_block)
|
|
78
|
-
end
|
|
79
|
-
end
|
|
80
|
-
|
|
81
|
-
class HaveAllSelectors < Matcher
|
|
82
|
-
def initialize(*args, &filter_block)
|
|
83
|
-
@args = args
|
|
84
|
-
@filter_block = filter_block
|
|
85
|
-
end
|
|
86
|
-
|
|
87
|
-
def matches?(actual)
|
|
88
|
-
wrap_matches?(actual) { |el| el.assert_all_of_selectors(*@args, &@filter_block) }
|
|
89
|
-
end
|
|
90
|
-
|
|
91
|
-
def does_not_match?(_actual)
|
|
92
|
-
raise ArgumentError, "The have_all_selectors matcher does not support use with not_to/should_not"
|
|
93
|
-
end
|
|
94
|
-
|
|
95
|
-
def description
|
|
96
|
-
"have all selectors"
|
|
97
|
-
end
|
|
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(...)
|
|
98
20
|
end
|
|
99
21
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
def matches?(actual)
|
|
107
|
-
wrap_matches?(actual) { |el| el.assert_none_of_selectors(*@args, &@filter_block) }
|
|
108
|
-
end
|
|
109
|
-
|
|
110
|
-
def does_not_match?(_actual)
|
|
111
|
-
raise ArgumentError, "The have_none_of_selectors matcher does not support use with not_to/should_not"
|
|
112
|
-
end
|
|
113
|
-
|
|
114
|
-
def description
|
|
115
|
-
"have no selectors"
|
|
116
|
-
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(...)
|
|
117
27
|
end
|
|
118
28
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
def does_not_match?(actual)
|
|
125
|
-
wrap_does_not_match?(actual) { |el| el.assert_not_matches_selector(*@args, &@filter_block) }
|
|
126
|
-
end
|
|
127
|
-
|
|
128
|
-
def description
|
|
129
|
-
"match #{query.description}"
|
|
130
|
-
end
|
|
131
|
-
|
|
132
|
-
def query
|
|
133
|
-
@query ||= Capybara::Queries::MatchQuery.new(*session_query_args, &@filter_block)
|
|
134
|
-
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(...)
|
|
135
34
|
end
|
|
136
35
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
def matches?(actual)
|
|
144
|
-
wrap_matches?(actual) { |el| el.assert_text(*@args) }
|
|
145
|
-
end
|
|
146
|
-
|
|
147
|
-
def does_not_match?(actual)
|
|
148
|
-
wrap_does_not_match?(actual) { |el| el.assert_no_text(*@args) }
|
|
149
|
-
end
|
|
150
|
-
|
|
151
|
-
def description
|
|
152
|
-
"text #{format(@content)}"
|
|
153
|
-
end
|
|
154
|
-
|
|
155
|
-
def format(content)
|
|
156
|
-
content.inspect
|
|
157
|
-
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(...)
|
|
158
41
|
end
|
|
159
42
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
@title = args.first
|
|
166
|
-
end
|
|
167
|
-
|
|
168
|
-
def matches?(actual)
|
|
169
|
-
wrap_matches?(actual) { |el| el.assert_title(*@args) }
|
|
170
|
-
end
|
|
171
|
-
|
|
172
|
-
def does_not_match?(actual)
|
|
173
|
-
wrap_does_not_match?(actual) { |el| el.assert_no_title(*@args) }
|
|
174
|
-
end
|
|
175
|
-
|
|
176
|
-
def description
|
|
177
|
-
"have title #{@title.inspect}"
|
|
178
|
-
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(...)
|
|
179
48
|
end
|
|
180
49
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
@current_path = args.first
|
|
185
|
-
end
|
|
186
|
-
|
|
187
|
-
def matches?(actual)
|
|
188
|
-
wrap_matches?(actual) { |el| el.assert_current_path(*@args) }
|
|
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)
|
|
189
53
|
end
|
|
190
54
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
end
|
|
194
|
-
|
|
195
|
-
def description
|
|
196
|
-
"have current path #{@current_path.inspect}"
|
|
55
|
+
define_method "match_#{selector}" do |expr, **options, &optional_filter_block|
|
|
56
|
+
Matchers::MatchSelector.new(selector, expr, **options, &optional_filter_block)
|
|
197
57
|
end
|
|
198
58
|
end
|
|
199
59
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
@matcher = matcher
|
|
205
|
-
end
|
|
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?
|
|
206
64
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
def does_not_match?(actual)
|
|
212
|
-
@matcher.matches?(actual)
|
|
213
|
-
end
|
|
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?
|
|
214
69
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
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?
|
|
218
74
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
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?
|
|
222
79
|
|
|
223
|
-
|
|
224
|
-
|
|
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)
|
|
225
83
|
end
|
|
226
84
|
end
|
|
227
85
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
86
|
+
# @!method have_element(locator = nil, **options, &optional_filter_block)
|
|
87
|
+
# RSpec matcher for elements.
|
|
88
|
+
#
|
|
89
|
+
# @see Capybara::Node::Matchers#has_element?
|
|
232
90
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
91
|
+
# @!method have_link(locator = nil, **options, &optional_filter_block)
|
|
92
|
+
# RSpec matcher for links.
|
|
93
|
+
#
|
|
94
|
+
# @see Capybara::Node::Matchers#has_link?
|
|
236
95
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
def description
|
|
242
|
-
"have style"
|
|
243
|
-
end
|
|
244
|
-
end
|
|
96
|
+
# @!method have_button(locator = nil, **options, &optional_filter_block)
|
|
97
|
+
# RSpec matcher for buttons.
|
|
98
|
+
#
|
|
99
|
+
# @see Capybara::Node::Matchers#has_button?
|
|
245
100
|
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
101
|
+
# @!method have_field(locator = nil, **options, &optional_filter_block)
|
|
102
|
+
# RSpec matcher for form fields.
|
|
103
|
+
#
|
|
104
|
+
# @see Capybara::Node::Matchers#has_field?
|
|
250
105
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
while window.exists?
|
|
256
|
-
return false if timer.expired?
|
|
257
|
-
sleep 0.05
|
|
258
|
-
end
|
|
259
|
-
true
|
|
260
|
-
end
|
|
106
|
+
# @!method have_select(locator = nil, **options, &optional_filter_block)
|
|
107
|
+
# RSpec matcher for select elements.
|
|
108
|
+
#
|
|
109
|
+
# @see Capybara::Node::Matchers#has_select?
|
|
261
110
|
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
111
|
+
# @!method have_table(locator = nil, **options, &optional_filter_block)
|
|
112
|
+
# RSpec matcher for table elements.
|
|
113
|
+
#
|
|
114
|
+
# @see Capybara::Node::Matchers#has_table?
|
|
265
115
|
|
|
266
|
-
|
|
267
|
-
|
|
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)
|
|
268
119
|
end
|
|
269
120
|
end
|
|
270
121
|
|
|
271
|
-
#
|
|
272
|
-
#
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
end
|
|
276
|
-
|
|
277
|
-
# RSpec matcher for whether the element(s) matching a group of selectors exist
|
|
278
|
-
# See {Capybara::Node::Matcher#assert_all_of_selectors}
|
|
279
|
-
def have_all_of_selectors(*args, &optional_filter_block)
|
|
280
|
-
HaveAllSelectors.new(*args, &optional_filter_block)
|
|
281
|
-
end
|
|
282
|
-
|
|
283
|
-
# RSpec matcher for whether no element(s) matching a group of selectors exist
|
|
284
|
-
# See {Capybara::Node::Matcher#assert_none_of_selectors}
|
|
285
|
-
def have_none_of_selectors(*args, &optional_filter_block)
|
|
286
|
-
HaveNoSelectors.new(*args, &optional_filter_block)
|
|
287
|
-
end
|
|
288
|
-
|
|
289
|
-
# RSpec matcher for whether the current element matches a given selector
|
|
290
|
-
# See {Capybara::Node::Matchers#assert_matches_selector}
|
|
291
|
-
def match_selector(*args, &optional_filter_block)
|
|
292
|
-
MatchSelector.new(*args, &optional_filter_block)
|
|
293
|
-
end
|
|
294
|
-
|
|
295
|
-
# RSpec matcher for whether elements(s) matching a given xpath selector exist
|
|
296
|
-
# See {Capybara::Node::Matchers#has_xpath?}
|
|
297
|
-
def have_xpath(xpath, **options, &optional_filter_block)
|
|
298
|
-
HaveSelector.new(:xpath, xpath, options, &optional_filter_block)
|
|
299
|
-
end
|
|
300
|
-
|
|
301
|
-
# RSpec matcher for whether the current element matches a given xpath selector
|
|
302
|
-
def match_xpath(xpath, **options, &optional_filter_block)
|
|
303
|
-
MatchSelector.new(:xpath, xpath, options, &optional_filter_block)
|
|
304
|
-
end
|
|
305
|
-
|
|
306
|
-
# RSpec matcher for whether elements(s) matching a given css selector exist
|
|
307
|
-
# See {Capybara::Node::Matchers#has_css?}
|
|
308
|
-
def have_css(css, **options, &optional_filter_block)
|
|
309
|
-
HaveSelector.new(:css, css, options, &optional_filter_block)
|
|
310
|
-
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?
|
|
311
126
|
|
|
312
|
-
#
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
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?
|
|
316
131
|
|
|
317
|
-
# RSpec matcher for text content
|
|
318
|
-
#
|
|
319
|
-
|
|
320
|
-
|
|
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)
|
|
321
137
|
end
|
|
322
138
|
alias_method :have_content, :have_text
|
|
323
139
|
|
|
324
140
|
def have_title(title, **options)
|
|
325
|
-
HaveTitle.new(title, options)
|
|
326
|
-
end
|
|
327
|
-
|
|
328
|
-
# RSpec matcher for the current path
|
|
329
|
-
# See {Capybara::SessionMatchers#assert_current_path}
|
|
330
|
-
def have_current_path(path, **options)
|
|
331
|
-
HaveCurrentPath.new(path, options)
|
|
332
|
-
end
|
|
333
|
-
|
|
334
|
-
# RSpec matcher for links
|
|
335
|
-
# See {Capybara::Node::Matchers#has_link?}
|
|
336
|
-
def have_link(locator = nil, **options, &optional_filter_block)
|
|
337
|
-
HaveSelector.new(:link, locator, options, &optional_filter_block)
|
|
338
|
-
end
|
|
339
|
-
|
|
340
|
-
# RSpec matcher for buttons
|
|
341
|
-
# See {Capybara::Node::Matchers#has_button?}
|
|
342
|
-
def have_button(locator = nil, **options, &optional_filter_block)
|
|
343
|
-
HaveSelector.new(:button, locator, options, &optional_filter_block)
|
|
344
|
-
end
|
|
345
|
-
|
|
346
|
-
# RSpec matcher for links
|
|
347
|
-
# See {Capybara::Node::Matchers#has_field?}
|
|
348
|
-
def have_field(locator = nil, **options, &optional_filter_block)
|
|
349
|
-
HaveSelector.new(:field, locator, options, &optional_filter_block)
|
|
350
|
-
end
|
|
351
|
-
|
|
352
|
-
# RSpec matcher for checked fields
|
|
353
|
-
# See {Capybara::Node::Matchers#has_checked_field?}
|
|
354
|
-
def have_checked_field(locator = nil, **options, &optional_filter_block)
|
|
355
|
-
HaveSelector.new(:field, locator, options.merge(checked: true), &optional_filter_block)
|
|
141
|
+
Matchers::HaveTitle.new(title, **options)
|
|
356
142
|
end
|
|
357
143
|
|
|
358
|
-
# RSpec matcher for
|
|
359
|
-
#
|
|
360
|
-
|
|
361
|
-
|
|
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)
|
|
362
149
|
end
|
|
363
150
|
|
|
364
|
-
# RSpec matcher for
|
|
365
|
-
#
|
|
366
|
-
|
|
367
|
-
|
|
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)
|
|
368
157
|
end
|
|
369
158
|
|
|
370
|
-
|
|
371
|
-
#
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
# RSpec matcher for element style
|
|
377
|
-
# See {Capybara::Node::Matchers#has_style?}
|
|
378
|
-
def have_style(styles, **options)
|
|
379
|
-
HaveStyle.new(styles, options)
|
|
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)
|
|
380
165
|
end
|
|
381
166
|
|
|
382
|
-
%w[selector css xpath text title current_path link button
|
|
383
|
-
|
|
384
|
-
|
|
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))
|
|
385
172
|
end
|
|
386
173
|
end
|
|
387
174
|
alias_method :have_no_content, :have_no_text
|
|
388
175
|
|
|
389
176
|
%w[selector css xpath].each do |matcher_type|
|
|
390
|
-
define_method "not_match_#{matcher_type}" do |*args, &optional_filter_block|
|
|
391
|
-
NegatedMatcher.new(send("match_#{matcher_type}", *args, &optional_filter_block))
|
|
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))
|
|
392
179
|
end
|
|
393
180
|
end
|
|
394
181
|
|
|
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(...)
|
|
187
|
+
end
|
|
188
|
+
|
|
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(...)
|
|
194
|
+
end
|
|
195
|
+
|
|
395
196
|
##
|
|
396
197
|
# Wait for window to become closed.
|
|
198
|
+
#
|
|
397
199
|
# @example
|
|
398
200
|
# expect(window).to become_closed(wait: 0.8)
|
|
399
|
-
#
|
|
400
|
-
# @option options [Numeric] :wait
|
|
201
|
+
#
|
|
202
|
+
# @option options [Numeric] :wait Maximum wait time. Defaults to {Capybara.configure default_max_wait_time}
|
|
401
203
|
def become_closed(**options)
|
|
402
|
-
BecomeClosed.new(options)
|
|
204
|
+
Matchers::BecomeClosed.new(options)
|
|
403
205
|
end
|
|
404
206
|
end
|
|
405
207
|
end
|
data/lib/capybara/rspec.rb
CHANGED
|
@@ -9,6 +9,8 @@ require 'capybara/rspec/matcher_proxies'
|
|
|
9
9
|
RSpec.configure do |config|
|
|
10
10
|
config.include Capybara::DSL, type: :feature
|
|
11
11
|
config.include Capybara::RSpecMatchers, type: :feature
|
|
12
|
+
config.include Capybara::DSL, type: :system
|
|
13
|
+
config.include Capybara::RSpecMatchers, type: :system
|
|
12
14
|
config.include Capybara::RSpecMatchers, type: :view
|
|
13
15
|
|
|
14
16
|
# The before and after blocks must run instantaneously, because Capybara
|
|
@@ -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
|