capybara 3.3.0 → 3.40.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.yardopts +1 -0
- data/History.md +803 -13
- data/License.txt +1 -1
- data/README.md +257 -84
- data/lib/capybara/config.rb +25 -9
- data/lib/capybara/cucumber.rb +1 -1
- data/lib/capybara/driver/base.rb +17 -3
- data/lib/capybara/driver/node.rb +31 -6
- data/lib/capybara/dsl.rb +9 -7
- data/lib/capybara/helpers.rb +31 -7
- data/lib/capybara/minitest/spec.rb +180 -88
- data/lib/capybara/minitest.rb +262 -149
- data/lib/capybara/node/actions.rb +202 -116
- data/lib/capybara/node/base.rb +34 -19
- data/lib/capybara/node/document.rb +14 -2
- data/lib/capybara/node/document_matchers.rb +10 -12
- data/lib/capybara/node/element.rb +269 -115
- data/lib/capybara/node/finders.rb +99 -77
- data/lib/capybara/node/matchers.rb +327 -151
- data/lib/capybara/node/simple.rb +48 -13
- data/lib/capybara/node/whitespace_normalizer.rb +81 -0
- data/lib/capybara/queries/active_element_query.rb +18 -0
- data/lib/capybara/queries/ancestor_query.rb +8 -9
- data/lib/capybara/queries/base_query.rb +23 -16
- data/lib/capybara/queries/current_path_query.rb +16 -6
- data/lib/capybara/queries/match_query.rb +1 -0
- data/lib/capybara/queries/selector_query.rb +587 -130
- data/lib/capybara/queries/sibling_query.rb +8 -6
- data/lib/capybara/queries/style_query.rb +6 -2
- data/lib/capybara/queries/text_query.rb +28 -14
- data/lib/capybara/queries/title_query.rb +2 -2
- data/lib/capybara/rack_test/browser.rb +92 -25
- data/lib/capybara/rack_test/driver.rb +16 -7
- data/lib/capybara/rack_test/errors.rb +6 -0
- data/lib/capybara/rack_test/form.rb +68 -41
- data/lib/capybara/rack_test/node.rb +106 -39
- data/lib/capybara/rails.rb +1 -1
- data/lib/capybara/registration_container.rb +41 -0
- data/lib/capybara/registrations/drivers.rb +42 -0
- data/lib/capybara/registrations/patches/puma_ssl.rb +29 -0
- data/lib/capybara/registrations/servers.rb +66 -0
- data/lib/capybara/result.rb +75 -52
- data/lib/capybara/rspec/features.rb +7 -7
- data/lib/capybara/rspec/matcher_proxies.rb +39 -18
- data/lib/capybara/rspec/matchers/base.rb +113 -0
- data/lib/capybara/rspec/matchers/become_closed.rb +33 -0
- data/lib/capybara/rspec/matchers/compound.rb +88 -0
- data/lib/capybara/rspec/matchers/count_sugar.rb +37 -0
- data/lib/capybara/rspec/matchers/have_ancestor.rb +28 -0
- data/lib/capybara/rspec/matchers/have_current_path.rb +29 -0
- data/lib/capybara/rspec/matchers/have_selector.rb +69 -0
- data/lib/capybara/rspec/matchers/have_sibling.rb +27 -0
- data/lib/capybara/rspec/matchers/have_text.rb +33 -0
- data/lib/capybara/rspec/matchers/have_title.rb +29 -0
- data/lib/capybara/rspec/matchers/match_selector.rb +27 -0
- data/lib/capybara/rspec/matchers/match_style.rb +43 -0
- data/lib/capybara/rspec/matchers/spatial_sugar.rb +39 -0
- data/lib/capybara/rspec/matchers.rb +141 -339
- data/lib/capybara/rspec.rb +2 -0
- data/lib/capybara/selector/builders/css_builder.rb +84 -0
- data/lib/capybara/selector/builders/xpath_builder.rb +71 -0
- data/lib/capybara/selector/css.rb +27 -25
- data/lib/capybara/selector/definition/button.rb +68 -0
- data/lib/capybara/selector/definition/checkbox.rb +26 -0
- data/lib/capybara/selector/definition/css.rb +10 -0
- data/lib/capybara/selector/definition/datalist_input.rb +35 -0
- data/lib/capybara/selector/definition/datalist_option.rb +25 -0
- data/lib/capybara/selector/definition/element.rb +28 -0
- data/lib/capybara/selector/definition/field.rb +40 -0
- data/lib/capybara/selector/definition/fieldset.rb +14 -0
- data/lib/capybara/selector/definition/file_field.rb +13 -0
- data/lib/capybara/selector/definition/fillable_field.rb +33 -0
- data/lib/capybara/selector/definition/frame.rb +17 -0
- data/lib/capybara/selector/definition/id.rb +6 -0
- data/lib/capybara/selector/definition/label.rb +62 -0
- data/lib/capybara/selector/definition/link.rb +55 -0
- data/lib/capybara/selector/definition/link_or_button.rb +16 -0
- data/lib/capybara/selector/definition/option.rb +27 -0
- data/lib/capybara/selector/definition/radio_button.rb +27 -0
- data/lib/capybara/selector/definition/select.rb +81 -0
- data/lib/capybara/selector/definition/table.rb +109 -0
- data/lib/capybara/selector/definition/table_row.rb +21 -0
- data/lib/capybara/selector/definition/xpath.rb +5 -0
- data/lib/capybara/selector/definition.rb +280 -0
- data/lib/capybara/selector/filter.rb +1 -0
- data/lib/capybara/selector/filter_set.rb +73 -25
- data/lib/capybara/selector/filters/base.rb +24 -5
- data/lib/capybara/selector/filters/expression_filter.rb +3 -3
- data/lib/capybara/selector/filters/locator_filter.rb +29 -0
- data/lib/capybara/selector/filters/node_filter.rb +16 -2
- data/lib/capybara/selector/regexp_disassembler.rb +211 -0
- data/lib/capybara/selector/selector.rb +85 -348
- data/lib/capybara/selector/xpath_extensions.rb +17 -0
- data/lib/capybara/selector.rb +474 -447
- data/lib/capybara/selenium/atoms/getAttribute.min.js +1 -0
- data/lib/capybara/selenium/atoms/isDisplayed.min.js +1 -0
- data/lib/capybara/selenium/atoms/src/getAttribute.js +161 -0
- data/lib/capybara/selenium/atoms/src/isDisplayed.js +454 -0
- data/lib/capybara/selenium/driver.rb +255 -143
- data/lib/capybara/selenium/driver_specializations/chrome_driver.rb +93 -11
- data/lib/capybara/selenium/driver_specializations/edge_driver.rb +128 -0
- data/lib/capybara/selenium/driver_specializations/firefox_driver.rb +84 -0
- data/lib/capybara/selenium/driver_specializations/internet_explorer_driver.rb +26 -0
- data/lib/capybara/selenium/driver_specializations/safari_driver.rb +24 -0
- data/lib/capybara/selenium/extensions/file_input_click_emulation.rb +34 -0
- data/lib/capybara/selenium/extensions/find.rb +110 -0
- data/lib/capybara/selenium/extensions/html5_drag.rb +229 -0
- data/lib/capybara/selenium/extensions/modifier_keys_stack.rb +28 -0
- data/lib/capybara/selenium/extensions/scroll.rb +76 -0
- data/lib/capybara/selenium/node.rb +436 -134
- data/lib/capybara/selenium/nodes/chrome_node.rb +125 -0
- data/lib/capybara/selenium/nodes/edge_node.rb +110 -0
- data/lib/capybara/selenium/nodes/firefox_node.rb +136 -0
- data/lib/capybara/selenium/nodes/ie_node.rb +22 -0
- data/lib/capybara/selenium/nodes/safari_node.rb +118 -0
- data/lib/capybara/selenium/patches/atoms.rb +18 -0
- data/lib/capybara/selenium/patches/is_displayed.rb +16 -0
- data/lib/capybara/selenium/patches/logs.rb +45 -0
- data/lib/capybara/selenium/patches/pause_duration_fix.rb +9 -0
- data/lib/capybara/selenium/patches/persistent_client.rb +20 -0
- data/lib/capybara/server/animation_disabler.rb +56 -19
- data/lib/capybara/server/checker.rb +9 -3
- data/lib/capybara/server/middleware.rb +28 -12
- data/lib/capybara/server.rb +33 -10
- data/lib/capybara/session/config.rb +34 -10
- data/lib/capybara/session/matchers.rb +23 -16
- data/lib/capybara/session.rb +230 -170
- data/lib/capybara/spec/public/jquery.js +5 -5
- data/lib/capybara/spec/public/offset.js +6 -0
- data/lib/capybara/spec/public/test.js +121 -8
- data/lib/capybara/spec/session/accept_alert_spec.rb +11 -11
- data/lib/capybara/spec/session/accept_confirm_spec.rb +3 -3
- data/lib/capybara/spec/session/accept_prompt_spec.rb +9 -10
- data/lib/capybara/spec/session/active_element_spec.rb +31 -0
- data/lib/capybara/spec/session/all_spec.rb +127 -40
- data/lib/capybara/spec/session/ancestor_spec.rb +24 -19
- data/lib/capybara/spec/session/assert_all_of_selectors_spec.rb +67 -38
- data/lib/capybara/spec/session/assert_current_path_spec.rb +21 -18
- data/lib/capybara/spec/session/assert_selector_spec.rb +52 -58
- data/lib/capybara/spec/session/assert_style_spec.rb +7 -7
- data/lib/capybara/spec/session/assert_text_spec.rb +74 -50
- data/lib/capybara/spec/session/assert_title_spec.rb +12 -12
- data/lib/capybara/spec/session/attach_file_spec.rb +126 -72
- data/lib/capybara/spec/session/body_spec.rb +6 -6
- data/lib/capybara/spec/session/check_spec.rb +102 -47
- data/lib/capybara/spec/session/choose_spec.rb +58 -32
- data/lib/capybara/spec/session/click_button_spec.rb +219 -163
- data/lib/capybara/spec/session/click_link_or_button_spec.rb +49 -23
- data/lib/capybara/spec/session/click_link_spec.rb +77 -54
- data/lib/capybara/spec/session/current_scope_spec.rb +8 -8
- data/lib/capybara/spec/session/current_url_spec.rb +38 -29
- data/lib/capybara/spec/session/dismiss_confirm_spec.rb +3 -3
- data/lib/capybara/spec/session/dismiss_prompt_spec.rb +2 -2
- data/lib/capybara/spec/session/element/assert_match_selector_spec.rb +8 -8
- data/lib/capybara/spec/session/element/match_css_spec.rb +16 -10
- data/lib/capybara/spec/session/element/match_xpath_spec.rb +6 -6
- data/lib/capybara/spec/session/element/matches_selector_spec.rb +68 -56
- data/lib/capybara/spec/session/evaluate_async_script_spec.rb +7 -7
- data/lib/capybara/spec/session/evaluate_script_spec.rb +28 -8
- data/lib/capybara/spec/session/execute_script_spec.rb +8 -7
- data/lib/capybara/spec/session/fill_in_spec.rb +101 -46
- data/lib/capybara/spec/session/find_button_spec.rb +23 -23
- data/lib/capybara/spec/session/find_by_id_spec.rb +7 -7
- data/lib/capybara/spec/session/find_field_spec.rb +32 -30
- data/lib/capybara/spec/session/find_link_spec.rb +31 -21
- data/lib/capybara/spec/session/find_spec.rb +244 -141
- data/lib/capybara/spec/session/first_spec.rb +43 -43
- data/lib/capybara/spec/session/frame/frame_title_spec.rb +5 -5
- data/lib/capybara/spec/session/frame/frame_url_spec.rb +5 -5
- data/lib/capybara/spec/session/frame/switch_to_frame_spec.rb +30 -18
- data/lib/capybara/spec/session/frame/within_frame_spec.rb +45 -18
- data/lib/capybara/spec/session/go_back_spec.rb +1 -1
- data/lib/capybara/spec/session/go_forward_spec.rb +1 -1
- data/lib/capybara/spec/session/has_all_selectors_spec.rb +23 -23
- data/lib/capybara/spec/session/has_ancestor_spec.rb +46 -0
- data/lib/capybara/spec/session/has_any_selectors_spec.rb +29 -0
- data/lib/capybara/spec/session/has_button_spec.rb +94 -13
- data/lib/capybara/spec/session/has_css_spec.rb +272 -132
- data/lib/capybara/spec/session/has_current_path_spec.rb +50 -35
- data/lib/capybara/spec/session/has_element_spec.rb +47 -0
- data/lib/capybara/spec/session/has_field_spec.rb +137 -58
- data/lib/capybara/spec/session/has_link_spec.rb +44 -4
- data/lib/capybara/spec/session/has_none_selectors_spec.rb +31 -31
- data/lib/capybara/spec/session/has_select_spec.rb +84 -50
- data/lib/capybara/spec/session/has_selector_spec.rb +111 -71
- data/lib/capybara/spec/session/has_sibling_spec.rb +50 -0
- data/lib/capybara/spec/session/has_table_spec.rb +181 -4
- data/lib/capybara/spec/session/has_text_spec.rb +101 -53
- data/lib/capybara/spec/session/has_title_spec.rb +19 -14
- data/lib/capybara/spec/session/has_xpath_spec.rb +56 -38
- data/lib/capybara/spec/session/headers_spec.rb +1 -1
- data/lib/capybara/spec/session/html_spec.rb +13 -6
- data/lib/capybara/spec/session/matches_style_spec.rb +37 -0
- data/lib/capybara/spec/session/node_spec.rb +894 -142
- data/lib/capybara/spec/session/node_wrapper_spec.rb +10 -7
- data/lib/capybara/spec/session/refresh_spec.rb +9 -7
- data/lib/capybara/spec/session/reset_session_spec.rb +63 -35
- data/lib/capybara/spec/session/response_code_spec.rb +1 -1
- data/lib/capybara/spec/session/save_and_open_page_spec.rb +2 -2
- data/lib/capybara/spec/session/save_and_open_screenshot_spec.rb +2 -2
- data/lib/capybara/spec/session/save_page_spec.rb +37 -37
- data/lib/capybara/spec/session/save_screenshot_spec.rb +10 -10
- data/lib/capybara/spec/session/screenshot_spec.rb +2 -2
- data/lib/capybara/spec/session/scroll_spec.rb +119 -0
- data/lib/capybara/spec/session/select_spec.rb +85 -85
- data/lib/capybara/spec/session/selectors_spec.rb +49 -18
- data/lib/capybara/spec/session/sibling_spec.rb +9 -9
- data/lib/capybara/spec/session/text_spec.rb +25 -24
- data/lib/capybara/spec/session/title_spec.rb +7 -6
- data/lib/capybara/spec/session/uncheck_spec.rb +33 -21
- data/lib/capybara/spec/session/unselect_spec.rb +37 -37
- data/lib/capybara/spec/session/visit_spec.rb +68 -49
- data/lib/capybara/spec/session/window/become_closed_spec.rb +20 -17
- data/lib/capybara/spec/session/window/current_window_spec.rb +1 -1
- data/lib/capybara/spec/session/window/switch_to_window_spec.rb +20 -16
- data/lib/capybara/spec/session/window/window_opened_by_spec.rb +6 -2
- data/lib/capybara/spec/session/window/window_spec.rb +62 -63
- data/lib/capybara/spec/session/window/windows_spec.rb +5 -1
- data/lib/capybara/spec/session/window/within_window_spec.rb +14 -14
- data/lib/capybara/spec/session/within_spec.rb +79 -42
- data/lib/capybara/spec/spec_helper.rb +41 -53
- data/lib/capybara/spec/test_app.rb +132 -43
- data/lib/capybara/spec/views/animated.erb +49 -0
- data/lib/capybara/spec/views/form.erb +139 -42
- data/lib/capybara/spec/views/frame_child.erb +4 -3
- data/lib/capybara/spec/views/frame_one.erb +2 -1
- data/lib/capybara/spec/views/frame_parent.erb +1 -1
- data/lib/capybara/spec/views/frame_two.erb +1 -1
- data/lib/capybara/spec/views/initial_alert.erb +2 -1
- data/lib/capybara/spec/views/layout.erb +10 -0
- data/lib/capybara/spec/views/obscured.erb +47 -0
- data/lib/capybara/spec/views/offset.erb +33 -0
- data/lib/capybara/spec/views/path.erb +2 -2
- data/lib/capybara/spec/views/popup_one.erb +1 -1
- data/lib/capybara/spec/views/popup_two.erb +1 -1
- data/lib/capybara/spec/views/react.erb +45 -0
- data/lib/capybara/spec/views/scroll.erb +21 -0
- data/lib/capybara/spec/views/spatial.erb +31 -0
- data/lib/capybara/spec/views/tables.erb +67 -0
- data/lib/capybara/spec/views/with_animation.erb +39 -4
- data/lib/capybara/spec/views/with_base_tag.erb +2 -2
- data/lib/capybara/spec/views/with_dragula.erb +24 -0
- data/lib/capybara/spec/views/with_fixed_header_footer.erb +2 -1
- data/lib/capybara/spec/views/with_hover.erb +3 -2
- data/lib/capybara/spec/views/with_hover1.erb +10 -0
- data/lib/capybara/spec/views/with_html.erb +37 -9
- data/lib/capybara/spec/views/with_html5_svg.erb +20 -0
- data/lib/capybara/spec/views/with_jquery_animation.erb +24 -0
- data/lib/capybara/spec/views/with_js.erb +26 -5
- data/lib/capybara/spec/views/with_jstree.erb +26 -0
- data/lib/capybara/spec/views/with_namespace.erb +1 -0
- data/lib/capybara/spec/views/with_scope.erb +2 -2
- data/lib/capybara/spec/views/with_scope_other.erb +6 -0
- data/lib/capybara/spec/views/with_shadow.erb +31 -0
- data/lib/capybara/spec/views/with_slow_unload.erb +2 -1
- data/lib/capybara/spec/views/with_sortable_js.erb +21 -0
- data/lib/capybara/spec/views/with_unload_alert.erb +1 -0
- data/lib/capybara/spec/views/with_windows.erb +1 -1
- data/lib/capybara/spec/views/within_frames.erb +1 -1
- data/lib/capybara/version.rb +1 -1
- data/lib/capybara/window.rb +19 -25
- data/lib/capybara.rb +126 -111
- data/spec/basic_node_spec.rb +59 -34
- data/spec/capybara_spec.rb +56 -44
- data/spec/counter_spec.rb +35 -0
- data/spec/css_builder_spec.rb +101 -0
- data/spec/css_splitter_spec.rb +8 -8
- data/spec/dsl_spec.rb +79 -52
- data/spec/filter_set_spec.rb +9 -9
- data/spec/fixtures/selenium_driver_rspec_failure.rb +4 -4
- data/spec/fixtures/selenium_driver_rspec_success.rb +4 -4
- data/spec/minitest_spec.rb +45 -7
- data/spec/minitest_spec_spec.rb +87 -64
- data/spec/per_session_config_spec.rb +6 -6
- data/spec/rack_test_spec.rb +172 -116
- data/spec/regexp_dissassembler_spec.rb +250 -0
- data/spec/result_spec.rb +80 -72
- data/spec/rspec/features_spec.rb +21 -16
- data/spec/rspec/scenarios_spec.rb +10 -6
- data/spec/rspec/shared_spec_matchers.rb +407 -365
- data/spec/rspec/views_spec.rb +3 -3
- data/spec/rspec_matchers_spec.rb +35 -10
- data/spec/rspec_spec.rb +63 -41
- data/spec/sauce_spec_chrome.rb +43 -0
- data/spec/selector_spec.rb +334 -89
- data/spec/selenium_spec_chrome.rb +176 -62
- data/spec/selenium_spec_chrome_remote.rb +54 -14
- data/spec/selenium_spec_edge.rb +41 -8
- data/spec/selenium_spec_firefox.rb +228 -0
- data/spec/selenium_spec_firefox_remote.rb +94 -0
- data/spec/selenium_spec_ie.rb +129 -11
- data/spec/selenium_spec_safari.rb +162 -0
- data/spec/server_spec.rb +171 -97
- data/spec/session_spec.rb +34 -18
- data/spec/shared_selenium_node.rb +79 -0
- data/spec/shared_selenium_session.rb +344 -80
- data/spec/spec_helper.rb +124 -2
- data/spec/whitespace_normalizer_spec.rb +54 -0
- data/spec/xpath_builder_spec.rb +93 -0
- metadata +326 -28
- data/lib/capybara/rspec/compound.rb +0 -94
- data/lib/capybara/selenium/driver_specializations/marionette_driver.rb +0 -31
- data/lib/capybara/selenium/nodes/marionette_node.rb +0 -31
- data/lib/capybara/spec/session/has_style_spec.rb +0 -25
- data/lib/capybara/spec/session/source_spec.rb +0 -0
- data/lib/capybara/spec/views/with_title.erb +0 -5
- data/spec/selenium_spec_marionette.rb +0 -167
data/spec/selector_spec.rb
CHANGED
|
@@ -3,21 +3,22 @@
|
|
|
3
3
|
require 'spec_helper'
|
|
4
4
|
|
|
5
5
|
RSpec.describe Capybara do
|
|
6
|
+
include Capybara::RSpecMatchers
|
|
6
7
|
describe 'Selectors' do
|
|
7
8
|
let :string do
|
|
8
|
-
|
|
9
|
+
described_class.string <<-STRING
|
|
9
10
|
<html>
|
|
10
11
|
<head>
|
|
11
12
|
<title>selectors</title>
|
|
12
13
|
</head>
|
|
13
14
|
<body>
|
|
14
|
-
<div class="
|
|
15
|
-
<div class="
|
|
16
|
-
<h1 class="
|
|
15
|
+
<div class="aa" id="page">
|
|
16
|
+
<div class="bb" id="content">
|
|
17
|
+
<h1 class="aa">Totally awesome</h1>
|
|
17
18
|
<p>Yes it is</p>
|
|
18
19
|
</div>
|
|
19
|
-
<p class="
|
|
20
|
-
<p class="
|
|
20
|
+
<p class="bb cc">Some Content</p>
|
|
21
|
+
<p class="bb dd !mine"></p>
|
|
21
22
|
</div>
|
|
22
23
|
<div id="#special">
|
|
23
24
|
</div>
|
|
@@ -31,6 +32,7 @@ RSpec.describe Capybara do
|
|
|
31
32
|
<input type="file" id="file" class=".special file"/>
|
|
32
33
|
<input type="hidden" id="hidden_field" value="this is hidden"/>
|
|
33
34
|
<input type="submit" value="click me" title="submit button"/>
|
|
35
|
+
<input type="button" value="don't click me" title="Other button 1" style="line-height: 30px;"/>
|
|
34
36
|
<a href="#">link</a>
|
|
35
37
|
<fieldset></fieldset>
|
|
36
38
|
<select id="select">
|
|
@@ -41,83 +43,212 @@ RSpec.describe Capybara do
|
|
|
41
43
|
<table>
|
|
42
44
|
<tr><td></td></tr>
|
|
43
45
|
</table>
|
|
46
|
+
<table id="rows">
|
|
47
|
+
<tr>
|
|
48
|
+
<td>A</td><td>B</td><td>C</td>
|
|
49
|
+
</tr>
|
|
50
|
+
<tr>
|
|
51
|
+
<td>D</td><td>E</td><td>F</td>
|
|
52
|
+
</tr>
|
|
53
|
+
</table>
|
|
54
|
+
<table id="cols">
|
|
55
|
+
<tbody>
|
|
56
|
+
<tr>
|
|
57
|
+
<td>A</td><td>D</td>
|
|
58
|
+
</tr>
|
|
59
|
+
<tr>
|
|
60
|
+
<td>B</td><td>E</td>
|
|
61
|
+
</tr>
|
|
62
|
+
<tr>
|
|
63
|
+
<td>C</td><td>F</td>
|
|
64
|
+
</tr>
|
|
65
|
+
</tbody>
|
|
66
|
+
</table>
|
|
44
67
|
</body>
|
|
45
68
|
</html>
|
|
46
69
|
STRING
|
|
47
70
|
end
|
|
48
71
|
|
|
49
72
|
before do
|
|
50
|
-
|
|
73
|
+
described_class.add_selector :custom_selector do
|
|
51
74
|
css { |css_class| "div.#{css_class}" }
|
|
52
75
|
node_filter(:not_empty, boolean: true, default: true, skip_if: :all) { |node, value| value ^ (node.text == '') }
|
|
53
76
|
end
|
|
54
77
|
|
|
55
|
-
|
|
56
|
-
css
|
|
78
|
+
described_class.add_selector :custom_css_selector do
|
|
79
|
+
css(:name, :other_name) do |selector, name: nil, **|
|
|
80
|
+
selector ||= ''
|
|
81
|
+
selector += "[name='#{name}']" if name
|
|
82
|
+
selector
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
expression_filter(:placeholder) do |expr, val|
|
|
86
|
+
expr + "[placeholder='#{val}']"
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
expression_filter(:value) do |expr, val|
|
|
90
|
+
expr + "[value='#{val}']"
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
expression_filter(:title) do |expr, val|
|
|
94
|
+
expr + "[title='#{val}']"
|
|
95
|
+
end
|
|
57
96
|
end
|
|
58
97
|
|
|
59
|
-
|
|
60
|
-
xpath { |selector| selector }
|
|
98
|
+
described_class.add_selector :custom_xpath_selector do
|
|
99
|
+
xpath(:valid1, :valid2) { |selector| selector }
|
|
100
|
+
match { |value| value == 'match_me' }
|
|
61
101
|
end
|
|
62
102
|
end
|
|
63
103
|
|
|
64
|
-
it
|
|
104
|
+
it 'supports `filter` as an alias for `node_filter`' do
|
|
65
105
|
expect do
|
|
66
|
-
|
|
67
|
-
css { |_unused|
|
|
106
|
+
described_class.add_selector :filter_alias_selector do
|
|
107
|
+
css { |_unused| 'div' }
|
|
68
108
|
filter(:something) { |_node, _value| true }
|
|
69
109
|
end
|
|
70
110
|
end.not_to raise_error
|
|
71
111
|
end
|
|
72
112
|
|
|
73
|
-
describe
|
|
74
|
-
it
|
|
75
|
-
|
|
113
|
+
describe 'adding a selector' do
|
|
114
|
+
it 'can set default visibility' do
|
|
115
|
+
described_class.add_selector :hidden_field do
|
|
76
116
|
visible :hidden
|
|
77
117
|
css { |_sel| 'input[type="hidden"]' }
|
|
78
118
|
end
|
|
79
119
|
|
|
80
|
-
expect(string).to have_no_css('input[type="hidden"]')
|
|
120
|
+
expect(string).to have_no_css('input[type="hidden"]') # rubocop:disable Capybara/SpecificMatcher
|
|
81
121
|
expect(string).to have_selector(:hidden_field)
|
|
82
122
|
end
|
|
83
123
|
end
|
|
84
124
|
|
|
85
|
-
describe
|
|
86
|
-
it
|
|
87
|
-
el = string.find(:custom_selector, '
|
|
125
|
+
describe 'modify_selector' do
|
|
126
|
+
it 'allows modifying a selector' do
|
|
127
|
+
el = string.find(:custom_selector, 'aa')
|
|
88
128
|
expect(el.tag_name).to eq 'div'
|
|
89
|
-
|
|
129
|
+
described_class.modify_selector :custom_selector do
|
|
90
130
|
css { |css_class| "h1.#{css_class}" }
|
|
91
131
|
end
|
|
92
|
-
el = string.find(:custom_selector, '
|
|
132
|
+
el = string.find(:custom_selector, 'aa')
|
|
93
133
|
expect(el.tag_name).to eq 'h1'
|
|
94
134
|
end
|
|
95
135
|
|
|
96
136
|
it "doesn't change existing filters" do
|
|
97
|
-
|
|
137
|
+
described_class.modify_selector :custom_selector do
|
|
98
138
|
css { |css_class| "p.#{css_class}" }
|
|
99
139
|
end
|
|
100
|
-
expect(string).to have_selector(:custom_selector, '
|
|
101
|
-
expect(string).to have_selector(:custom_selector, '
|
|
102
|
-
expect(string).to have_selector(:custom_selector, '
|
|
140
|
+
expect(string).to have_selector(:custom_selector, 'bb', count: 1)
|
|
141
|
+
expect(string).to have_selector(:custom_selector, 'bb', not_empty: false, count: 1)
|
|
142
|
+
expect(string).to have_selector(:custom_selector, 'bb', not_empty: :all, count: 2)
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
describe '::[]' do
|
|
147
|
+
it 'can find a selector' do
|
|
148
|
+
expect(Capybara::Selector[:field]).not_to be_nil
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
it 'raises if no selector found' do
|
|
152
|
+
expect { Capybara::Selector[:no_exist] }.to raise_error(ArgumentError, /Unknown selector type/)
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
describe '::for' do
|
|
157
|
+
it 'finds selector that matches the locator' do
|
|
158
|
+
expect(Capybara::Selector.for('match_me').name).to eq :custom_xpath_selector
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
it 'returns nil if no match' do
|
|
162
|
+
expect(Capybara::Selector.for('nothing')).to be_nil
|
|
103
163
|
end
|
|
104
164
|
end
|
|
105
165
|
|
|
106
|
-
describe
|
|
107
|
-
|
|
108
|
-
|
|
166
|
+
describe 'xpath' do
|
|
167
|
+
it 'uses filter names passed in' do
|
|
168
|
+
described_class.add_selector :test do
|
|
169
|
+
xpath(:something, :other) { |_locator| XPath.descendant }
|
|
170
|
+
end
|
|
171
|
+
selector = Capybara::Selector.new :test, config: nil, format: nil
|
|
172
|
+
|
|
173
|
+
expect(selector.expression_filters.keys).to include(:something, :other)
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
it 'gets filter names from block if none passed to xpath method' do
|
|
177
|
+
described_class.add_selector :test do
|
|
178
|
+
xpath { |_locator, valid3:, valid4: nil| "#{valid3} #{valid4}" }
|
|
179
|
+
end
|
|
180
|
+
selector = Capybara::Selector.new :test, config: nil, format: nil
|
|
181
|
+
|
|
182
|
+
expect(selector.expression_filters.keys).to include(:valid3, :valid4)
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
it 'ignores block parameters if names passed in' do
|
|
186
|
+
described_class.add_selector :test do
|
|
187
|
+
xpath(:valid1) { |_locator, valid3:, valid4: nil| "#{valid3} #{valid4}" }
|
|
188
|
+
end
|
|
189
|
+
selector = Capybara::Selector.new :test, config: nil, format: nil
|
|
190
|
+
|
|
191
|
+
expect(selector.expression_filters.keys).to include(:valid1)
|
|
192
|
+
expect(selector.expression_filters.keys).not_to include(:valid3, :valid4)
|
|
193
|
+
end
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
describe 'css' do
|
|
197
|
+
it "supports filters specified in 'css' definition" do
|
|
198
|
+
expect(string).to have_selector(:custom_css_selector, 'input', name: 'form[my_text_input]')
|
|
199
|
+
expect(string).to have_no_selector(:custom_css_selector, 'input', name: 'form[not_my_text_input]')
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
it 'supports explicitly defined expression filters' do
|
|
203
|
+
expect(string).to have_selector(:custom_css_selector, placeholder: 'my text')
|
|
204
|
+
expect(string).to have_no_selector(:custom_css_selector, placeholder: 'not my text')
|
|
205
|
+
expect(string).to have_selector(:custom_css_selector, value: 'click me', title: 'submit button')
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
it 'uses filter names passed in' do
|
|
209
|
+
described_class.add_selector :test do
|
|
210
|
+
css(:name, :other_name) { |_locator| '' }
|
|
211
|
+
end
|
|
212
|
+
selector = Capybara::Selector.new :test, config: nil, format: nil
|
|
213
|
+
|
|
214
|
+
expect(selector.expression_filters.keys).to include(:name, :other_name)
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
it 'gets filter names from block if none passed to css method' do
|
|
218
|
+
described_class.add_selector :test do
|
|
219
|
+
css { |_locator, valid3:, valid4: nil| "#{valid3} #{valid4}" }
|
|
220
|
+
end
|
|
221
|
+
selector = Capybara::Selector.new :test, config: nil, format: nil
|
|
222
|
+
|
|
223
|
+
expect(selector.expression_filters.keys).to include(:valid3, :valid4)
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
it 'ignores block parameters if names passed in' do
|
|
227
|
+
described_class.add_selector :test do
|
|
228
|
+
css(:valid1) { |_locator, valid3:, valid4: nil| "#{valid3} #{valid4}" }
|
|
229
|
+
end
|
|
230
|
+
selector = Capybara::Selector.new :test, config: nil, format: nil
|
|
231
|
+
|
|
232
|
+
expect(selector.expression_filters.keys).to include(:valid1)
|
|
233
|
+
expect(selector.expression_filters.keys).not_to include(:valid3, :valid4)
|
|
234
|
+
end
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
describe 'builtin selectors' do
|
|
238
|
+
context 'when locator is nil' do
|
|
239
|
+
it 'devolves to just finding element types' do
|
|
109
240
|
selectors = {
|
|
110
241
|
field: ".//*[self::input | self::textarea | self::select][not(./@type = 'submit' or ./@type = 'image' or ./@type = 'hidden')]",
|
|
111
|
-
fieldset:
|
|
112
|
-
link:
|
|
242
|
+
fieldset: './/fieldset',
|
|
243
|
+
link: './/a[./@href]',
|
|
113
244
|
link_or_button: ".//a[./@href] | .//input[./@type = 'submit' or ./@type = 'reset' or ./@type = 'image' or ./@type = 'button'] | .//button",
|
|
114
245
|
fillable_field: ".//*[self::input | self::textarea][not(./@type = 'submit' or ./@type = 'image' or ./@type = 'radio' or ./@type = 'checkbox' or ./@type = 'hidden' or ./@type = 'file')]",
|
|
115
246
|
radio_button: ".//input[./@type = 'radio']",
|
|
116
247
|
checkbox: ".//input[./@type = 'checkbox']",
|
|
117
|
-
select:
|
|
118
|
-
option:
|
|
248
|
+
select: './/select',
|
|
249
|
+
option: './/option',
|
|
119
250
|
file_field: ".//input[./@type = 'file']",
|
|
120
|
-
table:
|
|
251
|
+
table: './/table'
|
|
121
252
|
}
|
|
122
253
|
selectors.each do |selector, xpath|
|
|
123
254
|
results = string.all(selector, nil).to_a.map(&:native)
|
|
@@ -127,155 +258,269 @@ RSpec.describe Capybara do
|
|
|
127
258
|
end
|
|
128
259
|
end
|
|
129
260
|
|
|
130
|
-
context
|
|
131
|
-
it
|
|
132
|
-
expect(string.all(:custom_css_selector,
|
|
133
|
-
expect(string.all(:custom_css_selector,
|
|
261
|
+
context 'with :id option' do
|
|
262
|
+
it 'works with compound css selectors' do
|
|
263
|
+
expect(string.all(:custom_css_selector, 'div, h1', id: 'page').size).to eq 1
|
|
264
|
+
expect(string.all(:custom_css_selector, 'h1, div', id: 'page').size).to eq 1
|
|
134
265
|
end
|
|
135
266
|
|
|
136
267
|
it "works with 'special' characters" do
|
|
137
|
-
expect(string.find(:custom_css_selector,
|
|
138
|
-
expect(string.find(:custom_css_selector,
|
|
268
|
+
expect(string.find(:custom_css_selector, 'div', id: '#special')[:id]).to eq '#special'
|
|
269
|
+
expect(string.find(:custom_css_selector, 'input', id: '2checkbox')[:id]).to eq '2checkbox'
|
|
139
270
|
end
|
|
140
271
|
|
|
141
|
-
it
|
|
272
|
+
it 'accepts XPath expression for xpath based selectors' do
|
|
142
273
|
expect(string.find(:custom_xpath_selector, './/div', id: XPath.contains('peci'))[:id]).to eq '#special'
|
|
143
274
|
expect(string.find(:custom_xpath_selector, './/input', id: XPath.ends_with('box'))[:id]).to eq '2checkbox'
|
|
144
275
|
end
|
|
145
276
|
|
|
146
|
-
it
|
|
147
|
-
expect { string.find(:custom_css_selector,
|
|
277
|
+
it 'errors XPath expression for CSS based selectors' do
|
|
278
|
+
expect { string.find(:custom_css_selector, 'div', id: XPath.contains('peci')) }
|
|
148
279
|
.to raise_error(ArgumentError, /not supported/)
|
|
149
280
|
end
|
|
281
|
+
|
|
282
|
+
it 'accepts Regexp for xpath based selectors' do
|
|
283
|
+
expect(string.find(:custom_xpath_selector, './/div', id: /peci/)[:id]).to eq '#special'
|
|
284
|
+
expect(string.find(:custom_xpath_selector, './/div', id: /pEcI/i)[:id]).to eq '#special'
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
it 'accepts Regexp for css based selectors' do
|
|
288
|
+
expect(string.find(:custom_css_selector, 'div', id: /sp.*al/)[:id]).to eq '#special'
|
|
289
|
+
end
|
|
150
290
|
end
|
|
151
291
|
|
|
152
|
-
context
|
|
153
|
-
it
|
|
154
|
-
expect(string.all(:custom_css_selector,
|
|
155
|
-
expect(string.all(:custom_css_selector,
|
|
292
|
+
context 'with :class option' do
|
|
293
|
+
it 'works with compound css selectors' do
|
|
294
|
+
expect(string.all(:custom_css_selector, 'div, h1', class: 'aa').size).to eq 2
|
|
295
|
+
expect(string.all(:custom_css_selector, 'h1, div', class: 'aa').size).to eq 2
|
|
156
296
|
end
|
|
157
297
|
|
|
158
|
-
it
|
|
159
|
-
expect(string.all(:custom_css_selector,
|
|
160
|
-
expect(string.all(:custom_css_selector,
|
|
161
|
-
expect(string.all(:custom_xpath_selector, XPath.descendant(:div, :p), class: ['
|
|
162
|
-
expect(string.all(:custom_xpath_selector, XPath.descendant(:div, :p), class: ['!
|
|
298
|
+
it 'handles negated classes' do
|
|
299
|
+
expect(string.all(:custom_css_selector, 'div, p', class: ['bb', '!cc']).size).to eq 2
|
|
300
|
+
expect(string.all(:custom_css_selector, 'div, p', class: ['!cc', '!dd', 'bb']).size).to eq 1
|
|
301
|
+
expect(string.all(:custom_xpath_selector, XPath.descendant(:div, :p), class: ['bb', '!cc']).size).to eq 2
|
|
302
|
+
expect(string.all(:custom_xpath_selector, XPath.descendant(:div, :p), class: ['!cc', '!dd', 'bb']).size).to eq 1
|
|
303
|
+
end
|
|
304
|
+
|
|
305
|
+
it 'handles classes starting with ! by requiring negated negated first' do
|
|
306
|
+
expect(string.all(:custom_css_selector, 'div, p', class: ['!!!mine']).size).to eq 1
|
|
307
|
+
expect(string.all(:custom_xpath_selector, XPath.descendant(:div, :p), class: ['!!!mine']).size).to eq 1
|
|
163
308
|
end
|
|
164
309
|
|
|
165
310
|
it "works with 'special' characters" do
|
|
166
|
-
expect(string.find(:custom_css_selector,
|
|
167
|
-
expect(string.find(:custom_css_selector,
|
|
311
|
+
expect(string.find(:custom_css_selector, 'input', class: '.special')[:id]).to eq 'file'
|
|
312
|
+
expect(string.find(:custom_css_selector, 'input', class: '2checkbox')[:id]).to eq '2checkbox'
|
|
168
313
|
end
|
|
169
314
|
|
|
170
|
-
it
|
|
315
|
+
it 'accepts XPath expression for xpath based selectors' do
|
|
171
316
|
expect(string.find(:custom_xpath_selector, './/div', class: XPath.contains('dom wor'))[:id]).to eq 'random_words'
|
|
172
317
|
expect(string.find(:custom_xpath_selector, './/div', class: XPath.ends_with('words'))[:id]).to eq 'random_words'
|
|
173
318
|
end
|
|
174
319
|
|
|
175
|
-
it
|
|
176
|
-
expect { string.find(:custom_css_selector,
|
|
320
|
+
it 'errors XPath expression for CSS based selectors' do
|
|
321
|
+
expect { string.find(:custom_css_selector, 'div', class: XPath.contains('random')) }
|
|
177
322
|
.to raise_error(ArgumentError, /not supported/)
|
|
178
323
|
end
|
|
324
|
+
|
|
325
|
+
it 'accepts Regexp for XPath based selectors' do
|
|
326
|
+
expect(string.find(:custom_xpath_selector, './/div', class: /dom wor/)[:id]).to eq 'random_words'
|
|
327
|
+
expect(string.find(:custom_xpath_selector, './/div', class: /dOm WoR/i)[:id]).to eq 'random_words'
|
|
328
|
+
end
|
|
329
|
+
|
|
330
|
+
it 'accepts Regexp for CSS based selectors' do
|
|
331
|
+
expect(string.find(:custom_css_selector, 'div', class: /random/)[:id]).to eq 'random_words'
|
|
332
|
+
end
|
|
333
|
+
|
|
334
|
+
it 'accepts Regexp for individual class names for XPath based selectors' do
|
|
335
|
+
expect(string.find(:custom_xpath_selector, './/div', class: [/random/, 'some'])[:id]).to eq 'random_words'
|
|
336
|
+
expect(string.find(:custom_xpath_selector, './/div', class: [/om/, /wor/])[:id]).to eq 'random_words'
|
|
337
|
+
expect { string.find(:custom_xpath_selector, './/div', class: [/not/, /wor/]) }.to raise_error(Capybara::ElementNotFound)
|
|
338
|
+
expect { string.find(:custom_xpath_selector, './/div', class: [/dom wor/]) }.to raise_error(Capybara::ElementNotFound)
|
|
339
|
+
end
|
|
340
|
+
|
|
341
|
+
it 'accepts Regexp for individual class names for CSS based selectors' do
|
|
342
|
+
expect(string.find(:custom_css_selector, 'div', class: [/random/])[:id]).to eq 'random_words'
|
|
343
|
+
expect(string.find(:custom_css_selector, 'div', class: [/om/, /wor/, 'some'])[:id]).to eq 'random_words'
|
|
344
|
+
expect { string.find(:custom_css_selector, 'div', class: [/not/, /wor/]) }.to raise_error(Capybara::ElementNotFound)
|
|
345
|
+
expect { string.find(:custom_css_selector, 'div', class: [/dom wor/]) }.to raise_error(Capybara::ElementNotFound)
|
|
346
|
+
end
|
|
347
|
+
end
|
|
348
|
+
|
|
349
|
+
context 'with :style option' do
|
|
350
|
+
it 'accepts string for CSS based selectors' do
|
|
351
|
+
expect(string.find(:custom_css_selector, 'input', style: 'line-height: 30px;')[:title]).to eq 'Other button 1'
|
|
352
|
+
end
|
|
353
|
+
|
|
354
|
+
it 'accepts Regexp for CSS base selectors' do
|
|
355
|
+
expect(string.find(:custom_css_selector, 'input', style: /30px/)[:title]).to eq 'Other button 1'
|
|
356
|
+
end
|
|
179
357
|
end
|
|
180
358
|
|
|
181
359
|
# :css, :xpath, :id, :field, :fieldset, :link, :button, :link_or_button, :fillable_field, :radio_button, :checkbox, :select,
|
|
182
360
|
# :option, :file_field, :label, :table, :frame
|
|
183
361
|
|
|
184
|
-
describe
|
|
185
|
-
it
|
|
186
|
-
expect(string.find(:css,
|
|
362
|
+
describe ':css selector' do
|
|
363
|
+
it 'finds by CSS locator' do
|
|
364
|
+
expect(string.find(:css, 'input#my_text_input')[:name]).to eq 'form[my_text_input]'
|
|
187
365
|
end
|
|
188
366
|
end
|
|
189
367
|
|
|
190
|
-
describe
|
|
191
|
-
it
|
|
368
|
+
describe ':xpath selector' do
|
|
369
|
+
it 'finds by XPath locator' do
|
|
192
370
|
expect(string.find(:xpath, './/input[@id="my_text_input"]')[:name]).to eq 'form[my_text_input]'
|
|
193
371
|
end
|
|
194
372
|
end
|
|
195
373
|
|
|
196
|
-
describe
|
|
197
|
-
it
|
|
198
|
-
expect(string.find(:id,
|
|
374
|
+
describe ':id selector' do
|
|
375
|
+
it 'finds by locator' do
|
|
376
|
+
expect(string.find(:id, 'my_text_input')[:name]).to eq 'form[my_text_input]'
|
|
377
|
+
expect(string.find(:id, /my_text_input/)[:name]).to eq 'form[my_text_input]'
|
|
378
|
+
expect(string.find(:id, /_text_/)[:name]).to eq 'form[my_text_input]'
|
|
379
|
+
expect(string.find(:id, /i[nmo]/)[:name]).to eq 'form[my_text_input]'
|
|
199
380
|
end
|
|
200
381
|
end
|
|
201
382
|
|
|
202
|
-
describe
|
|
203
|
-
it
|
|
383
|
+
describe ':field selector' do
|
|
384
|
+
it 'finds by locator' do
|
|
204
385
|
expect(string.find(:field, 'My Text Input')[:id]).to eq 'my_text_input'
|
|
205
386
|
expect(string.find(:field, 'my_text_input')[:id]).to eq 'my_text_input'
|
|
206
387
|
expect(string.find(:field, 'form[my_text_input]')[:id]).to eq 'my_text_input'
|
|
207
388
|
end
|
|
208
389
|
|
|
209
|
-
it
|
|
390
|
+
it 'finds by id string' do
|
|
210
391
|
expect(string.find(:field, id: 'my_text_input')[:name]).to eq 'form[my_text_input]'
|
|
211
392
|
end
|
|
212
393
|
|
|
213
|
-
it
|
|
394
|
+
it 'finds by id regexp' do
|
|
395
|
+
expect(string.find(:field, id: /my_text_inp/)[:name]).to eq 'form[my_text_input]'
|
|
396
|
+
end
|
|
397
|
+
|
|
398
|
+
it 'finds by name' do
|
|
214
399
|
expect(string.find(:field, name: 'form[my_text_input]')[:id]).to eq 'my_text_input'
|
|
215
400
|
end
|
|
216
401
|
|
|
217
|
-
it
|
|
402
|
+
it 'finds by placeholder' do
|
|
218
403
|
expect(string.find(:field, placeholder: 'my text')[:id]).to eq 'my_text_input'
|
|
219
404
|
end
|
|
220
405
|
|
|
221
|
-
it
|
|
406
|
+
it 'finds by type' do
|
|
222
407
|
expect(string.find(:field, type: 'file')[:id]).to eq 'file'
|
|
223
408
|
expect(string.find(:field, type: 'select')[:id]).to eq 'select'
|
|
224
409
|
end
|
|
225
410
|
end
|
|
226
411
|
|
|
227
|
-
describe
|
|
228
|
-
it
|
|
412
|
+
describe ':option selector' do
|
|
413
|
+
it 'finds disabled options' do
|
|
229
414
|
expect(string.find(:option, disabled: true).value).to eq 'b'
|
|
230
415
|
end
|
|
231
416
|
|
|
232
|
-
it
|
|
417
|
+
it 'finds selected options' do
|
|
233
418
|
expect(string.find(:option, selected: true).value).to eq 'c'
|
|
234
419
|
end
|
|
235
420
|
|
|
236
|
-
it
|
|
421
|
+
it 'finds not selected and not disabled options' do
|
|
237
422
|
expect(string.find(:option, disabled: false, selected: false).value).to eq 'a'
|
|
238
423
|
end
|
|
239
424
|
end
|
|
240
425
|
|
|
241
|
-
describe
|
|
242
|
-
it
|
|
426
|
+
describe ':button selector' do
|
|
427
|
+
it 'finds by value' do
|
|
243
428
|
expect(string.find(:button, 'click me').value).to eq 'click me'
|
|
244
429
|
end
|
|
245
430
|
|
|
246
|
-
it
|
|
431
|
+
it 'finds by title' do
|
|
247
432
|
expect(string.find(:button, 'submit button').value).to eq 'click me'
|
|
248
433
|
end
|
|
249
434
|
|
|
250
|
-
it
|
|
435
|
+
it 'includes non-matching parameters in failure message' do
|
|
251
436
|
expect { string.find(:button, 'click me', title: 'click me') }.to raise_error(/with title click me/)
|
|
252
437
|
end
|
|
253
438
|
end
|
|
254
439
|
|
|
255
|
-
describe
|
|
256
|
-
it
|
|
440
|
+
describe ':element selector' do
|
|
441
|
+
it 'finds by any attributes' do
|
|
257
442
|
expect(string.find(:element, 'input', type: 'submit').value).to eq 'click me'
|
|
258
443
|
end
|
|
259
444
|
|
|
260
|
-
it
|
|
445
|
+
it 'supports regexp matching' do
|
|
446
|
+
expect(string.find(:element, 'input', type: /sub/).value).to eq 'click me'
|
|
447
|
+
expect(string.find(:element, 'input', title: /sub\w.*button/).value).to eq 'click me'
|
|
448
|
+
expect(string.find(:element, 'input', title: /sub.* b.*ton/).value).to eq 'click me'
|
|
449
|
+
expect(string.find(:element, 'input', title: /sub.*mit.*/).value).to eq 'click me'
|
|
450
|
+
expect(string.find(:element, 'input', title: /^submit button$/).value).to eq 'click me'
|
|
451
|
+
expect(string.find(:element, 'input', title: /^(?:submit|other) button$/).value).to eq 'click me'
|
|
452
|
+
expect(string.find(:element, 'input', title: /SuB.*mIt/i).value).to eq 'click me'
|
|
453
|
+
expect(string.find(:element, 'input', title: /^Su.*Bm.*It/i).value).to eq 'click me'
|
|
454
|
+
expect(string.find(:element, 'input', title: /^Ot.*he.*r b.*\d/i).value).to eq "don't click me"
|
|
455
|
+
end
|
|
456
|
+
|
|
457
|
+
it 'still works with system keys' do
|
|
261
458
|
expect { string.all(:element, 'input', type: 'submit', count: 1) }.not_to raise_error
|
|
262
459
|
end
|
|
263
460
|
|
|
264
|
-
it
|
|
265
|
-
expect
|
|
461
|
+
it 'works without element type' do
|
|
462
|
+
expect(string.find(:element, type: 'submit').value).to eq 'click me'
|
|
463
|
+
end
|
|
464
|
+
|
|
465
|
+
it 'validates attribute presence when true' do
|
|
466
|
+
expect(string.find(:element, name: true)[:id]).to eq 'my_text_input'
|
|
467
|
+
end
|
|
468
|
+
|
|
469
|
+
it 'validates attribute absence when false' do
|
|
470
|
+
expect(string.find(:element, 'option', disabled: false, selected: false).value).to eq 'a'
|
|
471
|
+
end
|
|
472
|
+
|
|
473
|
+
it 'includes wildcarded keys in description' do
|
|
474
|
+
expect { string.all(:element, 'input', not_there: 'bad', presence: true, absence: false, count: 1) }
|
|
266
475
|
.to(raise_error do |e|
|
|
267
476
|
expect(e).to be_a(Capybara::ElementNotFound)
|
|
268
|
-
expect(e.message).to include
|
|
269
|
-
expect(e.message).
|
|
477
|
+
expect(e.message).to include 'not_there => bad'
|
|
478
|
+
expect(e.message).to include 'with presence attribute'
|
|
479
|
+
expect(e.message).to include 'without absence attribute'
|
|
480
|
+
expect(e.message).not_to include 'count 1'
|
|
270
481
|
end)
|
|
271
482
|
end
|
|
272
483
|
|
|
273
|
-
it
|
|
484
|
+
it 'accepts XPath::Expression' do
|
|
274
485
|
expect(string.find(:element, 'input', type: XPath.starts_with('subm')).value).to eq 'click me'
|
|
275
486
|
expect(string.find(:element, 'input', type: XPath.ends_with('ext'))[:type]).to eq 'text'
|
|
276
487
|
expect(string.find(:element, 'input', type: XPath.contains('ckb'))[:type]).to eq 'checkbox'
|
|
277
488
|
expect(string.find(:element, 'input', title: XPath.contains_word('submit'))[:type]).to eq 'submit'
|
|
278
|
-
expect(string.find(:element, 'input', title: XPath.contains_word('button'))[:type]).to eq '
|
|
489
|
+
expect(string.find(:element, 'input', title: XPath.contains_word('button 1'))[:type]).to eq 'button'
|
|
490
|
+
end
|
|
491
|
+
end
|
|
492
|
+
|
|
493
|
+
describe ':link_or_button selector' do
|
|
494
|
+
around do |example|
|
|
495
|
+
described_class.modify_selector(:link_or_button) do
|
|
496
|
+
expression_filter(:random) { |xpath, _| xpath } # do nothing filter
|
|
497
|
+
end
|
|
498
|
+
example.run
|
|
499
|
+
Capybara::Selector[:link_or_button].expression_filters.delete(:random)
|
|
500
|
+
end
|
|
501
|
+
|
|
502
|
+
it 'should not find links when disabled == true' do
|
|
503
|
+
expect(string.all(:link_or_button, disabled: true).size).to eq 0
|
|
504
|
+
end
|
|
505
|
+
|
|
506
|
+
context 'when modified' do
|
|
507
|
+
it 'should still work' do
|
|
508
|
+
filter = Capybara::Selector[:link_or_button].expression_filters[:random]
|
|
509
|
+
allow(filter).to receive(:apply_filter).and_call_original
|
|
510
|
+
|
|
511
|
+
expect(string.find(:link_or_button, 'click me', random: 'blah').value).to eq 'click me'
|
|
512
|
+
expect(filter).to have_received(:apply_filter).with(anything, :random, 'blah', anything)
|
|
513
|
+
end
|
|
514
|
+
end
|
|
515
|
+
end
|
|
516
|
+
|
|
517
|
+
describe ':table selector' do
|
|
518
|
+
it 'finds by rows' do
|
|
519
|
+
expect(string.find(:table, with_rows: [%w[D E F]])[:id]).to eq 'rows'
|
|
520
|
+
end
|
|
521
|
+
|
|
522
|
+
it 'finds by columns' do
|
|
523
|
+
expect(string.find(:table, with_cols: [%w[A B C]])[:id]).to eq 'cols'
|
|
279
524
|
end
|
|
280
525
|
end
|
|
281
526
|
end
|