capybara 3.35.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/History.md +168 -5
- data/README.md +199 -39
- data/lib/capybara/config.rb +16 -4
- data/lib/capybara/driver/base.rb +4 -0
- data/lib/capybara/driver/node.rb +5 -1
- data/lib/capybara/dsl.rb +4 -10
- data/lib/capybara/helpers.rb +9 -14
- data/lib/capybara/minitest/spec.rb +18 -6
- data/lib/capybara/minitest.rb +14 -1
- data/lib/capybara/node/actions.rb +14 -9
- data/lib/capybara/node/base.rb +2 -1
- data/lib/capybara/node/document.rb +2 -2
- data/lib/capybara/node/element.rb +13 -2
- data/lib/capybara/node/finders.rb +11 -2
- data/lib/capybara/node/matchers.rb +25 -0
- data/lib/capybara/node/simple.rb +5 -1
- 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 +2 -1
- data/lib/capybara/queries/base_query.rb +2 -2
- data/lib/capybara/queries/current_path_query.rb +1 -1
- data/lib/capybara/queries/selector_query.rb +40 -11
- data/lib/capybara/queries/sibling_query.rb +2 -1
- data/lib/capybara/queries/text_query.rb +1 -1
- data/lib/capybara/rack_test/browser.rb +64 -8
- data/lib/capybara/rack_test/driver.rb +4 -4
- data/lib/capybara/rack_test/form.rb +29 -7
- data/lib/capybara/rack_test/node.rb +32 -33
- data/lib/capybara/registration_container.rb +2 -5
- data/lib/capybara/registrations/drivers.rb +7 -7
- data/lib/capybara/registrations/servers.rb +37 -16
- data/lib/capybara/result.rb +2 -2
- data/lib/capybara/rspec/matcher_proxies.rb +6 -6
- data/lib/capybara/rspec/matchers/base.rb +8 -6
- data/lib/capybara/rspec/matchers/compound.rb +1 -1
- data/lib/capybara/rspec/matchers/have_selector.rb +9 -17
- data/lib/capybara/rspec/matchers.rb +21 -16
- data/lib/capybara/selector/builders/css_builder.rb +1 -1
- data/lib/capybara/selector/builders/xpath_builder.rb +1 -1
- data/lib/capybara/selector/css.rb +6 -6
- data/lib/capybara/selector/definition/button.rb +10 -5
- data/lib/capybara/selector/definition/checkbox.rb +1 -1
- data/lib/capybara/selector/definition/file_field.rb +1 -1
- data/lib/capybara/selector/definition/fillable_field.rb +1 -1
- data/lib/capybara/selector/definition/link.rb +2 -1
- data/lib/capybara/selector/definition/radio_button.rb +1 -1
- data/lib/capybara/selector/definition/table.rb +1 -1
- data/lib/capybara/selector/definition/table_row.rb +2 -2
- data/lib/capybara/selector/definition.rb +4 -2
- data/lib/capybara/selector/filter_set.rb +4 -7
- data/lib/capybara/selector/regexp_disassembler.rb +2 -5
- data/lib/capybara/selector/selector.rb +5 -1
- data/lib/capybara/selector.rb +252 -0
- data/lib/capybara/selenium/driver.rb +31 -54
- data/lib/capybara/selenium/driver_specializations/chrome_driver.rb +1 -1
- data/lib/capybara/selenium/driver_specializations/edge_driver.rb +9 -5
- data/lib/capybara/selenium/driver_specializations/firefox_driver.rb +2 -7
- data/lib/capybara/selenium/extensions/html5_drag.rb +5 -4
- data/lib/capybara/selenium/node.rb +60 -38
- data/lib/capybara/selenium/nodes/chrome_node.rb +4 -16
- data/lib/capybara/selenium/nodes/edge_node.rb +19 -13
- data/lib/capybara/selenium/nodes/firefox_node.rb +3 -3
- data/lib/capybara/selenium/nodes/safari_node.rb +4 -4
- data/lib/capybara/selenium/patches/atoms.rb +1 -1
- data/lib/capybara/selenium/patches/pause_duration_fix.rb +1 -1
- data/lib/capybara/server/animation_disabler.rb +40 -23
- data/lib/capybara/server/middleware.rb +1 -1
- data/lib/capybara/server.rb +1 -1
- data/lib/capybara/session/config.rb +4 -2
- data/lib/capybara/session.rb +34 -34
- data/lib/capybara/spec/public/test.js +4 -0
- data/lib/capybara/spec/session/active_element_spec.rb +31 -0
- data/lib/capybara/spec/session/all_spec.rb +11 -15
- data/lib/capybara/spec/session/assert_text_spec.rb +17 -17
- data/lib/capybara/spec/session/attach_file_spec.rb +6 -0
- data/lib/capybara/spec/session/check_spec.rb +10 -0
- data/lib/capybara/spec/session/choose_spec.rb +6 -0
- data/lib/capybara/spec/session/click_link_or_button_spec.rb +9 -0
- data/lib/capybara/spec/session/click_link_spec.rb +12 -1
- data/lib/capybara/spec/session/current_scope_spec.rb +1 -1
- data/lib/capybara/spec/session/fill_in_spec.rb +6 -0
- data/lib/capybara/spec/session/find_link_spec.rb +10 -0
- data/lib/capybara/spec/session/find_spec.rb +15 -1
- data/lib/capybara/spec/session/first_spec.rb +1 -1
- data/lib/capybara/spec/session/frame/within_frame_spec.rb +2 -0
- data/lib/capybara/spec/session/has_all_selectors_spec.rb +5 -5
- data/lib/capybara/spec/session/has_ancestor_spec.rb +2 -2
- data/lib/capybara/spec/session/has_any_selectors_spec.rb +6 -2
- data/lib/capybara/spec/session/has_button_spec.rb +30 -0
- data/lib/capybara/spec/session/has_current_path_spec.rb +3 -3
- data/lib/capybara/spec/session/has_element_spec.rb +47 -0
- data/lib/capybara/spec/session/has_field_spec.rb +25 -1
- data/lib/capybara/spec/session/has_link_spec.rb +40 -0
- data/lib/capybara/spec/session/has_none_selectors_spec.rb +7 -7
- data/lib/capybara/spec/session/has_select_spec.rb +10 -4
- data/lib/capybara/spec/session/has_selector_spec.rb +15 -0
- data/lib/capybara/spec/session/has_table_spec.rb +13 -2
- data/lib/capybara/spec/session/has_text_spec.rb +6 -14
- data/lib/capybara/spec/session/matches_style_spec.rb +2 -0
- data/lib/capybara/spec/session/node_spec.rb +88 -1
- data/lib/capybara/spec/session/node_wrapper_spec.rb +1 -1
- data/lib/capybara/spec/session/reset_session_spec.rb +13 -0
- data/lib/capybara/spec/session/scroll_spec.rb +7 -5
- data/lib/capybara/spec/session/uncheck_spec.rb +1 -1
- data/lib/capybara/spec/session/visit_spec.rb +20 -0
- data/lib/capybara/spec/session/window/window_spec.rb +1 -1
- data/lib/capybara/spec/session/window/windows_spec.rb +1 -1
- data/lib/capybara/spec/session/within_spec.rb +13 -0
- data/lib/capybara/spec/spec_helper.rb +12 -5
- data/lib/capybara/spec/test_app.rb +91 -14
- data/lib/capybara/spec/views/animated.erb +1 -1
- data/lib/capybara/spec/views/form.erb +34 -4
- data/lib/capybara/spec/views/frame_child.erb +1 -1
- data/lib/capybara/spec/views/frame_one.erb +1 -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 +1 -1
- data/lib/capybara/spec/views/offset.erb +2 -1
- 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 +2 -2
- data/lib/capybara/spec/views/scroll.erb +2 -1
- data/lib/capybara/spec/views/spatial.erb +1 -1
- data/lib/capybara/spec/views/with_animation.erb +2 -3
- data/lib/capybara/spec/views/with_base_tag.erb +2 -2
- data/lib/capybara/spec/views/with_dragula.erb +2 -2
- data/lib/capybara/spec/views/with_fixed_header_footer.erb +2 -1
- data/lib/capybara/spec/views/with_hover.erb +2 -2
- data/lib/capybara/spec/views/with_html.erb +5 -3
- data/lib/capybara/spec/views/with_jquery_animation.erb +1 -1
- data/lib/capybara/spec/views/with_js.erb +2 -3
- data/lib/capybara/spec/views/with_jstree.erb +1 -1
- 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_shadow.erb +31 -0
- data/lib/capybara/spec/views/with_slow_unload.erb +2 -1
- data/lib/capybara/spec/views/with_sortable_js.erb +2 -2
- 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 +1 -1
- data/lib/capybara.rb +30 -30
- data/spec/basic_node_spec.rb +16 -3
- data/spec/capybara_spec.rb +12 -0
- data/spec/counter_spec.rb +35 -0
- data/spec/css_builder_spec.rb +1 -1
- data/spec/css_splitter_spec.rb +1 -1
- data/spec/dsl_spec.rb +5 -3
- data/spec/fixtures/selenium_driver_rspec_failure.rb +2 -2
- data/spec/fixtures/selenium_driver_rspec_success.rb +2 -2
- data/spec/minitest_spec.rb +12 -1
- data/spec/minitest_spec_spec.rb +4 -0
- data/spec/per_session_config_spec.rb +1 -1
- data/spec/rack_test_spec.rb +30 -12
- data/spec/result_spec.rb +41 -35
- data/spec/rspec/features_spec.rb +3 -3
- data/spec/rspec/scenarios_spec.rb +2 -2
- data/spec/rspec/shared_spec_matchers.rb +27 -3
- data/spec/rspec_matchers_spec.rb +25 -0
- data/spec/rspec_spec.rb +3 -3
- data/spec/sauce_spec_chrome.rb +5 -5
- data/spec/selector_spec.rb +4 -4
- data/spec/selenium_spec_chrome.rb +20 -18
- data/spec/selenium_spec_chrome_remote.rb +15 -19
- data/spec/selenium_spec_edge.rb +19 -6
- data/spec/selenium_spec_firefox.rb +26 -8
- data/spec/selenium_spec_firefox_remote.rb +18 -4
- data/spec/selenium_spec_ie.rb +7 -8
- data/spec/selenium_spec_safari.rb +34 -20
- data/spec/server_spec.rb +19 -7
- data/spec/shared_selenium_node.rb +0 -4
- data/spec/shared_selenium_session.rb +22 -14
- data/spec/spec_helper.rb +36 -3
- data/spec/whitespace_normalizer_spec.rb +54 -0
- data/spec/xpath_builder_spec.rb +1 -1
- metadata +49 -30
- data/lib/capybara/selenium/logger_suppressor.rb +0 -34
- data/lib/capybara/selenium/patches/action_pauser.rb +0 -26
- data/lib/capybara/spec/views/with_title.erb +0 -5
@@ -15,36 +15,36 @@ module Capybara
|
|
15
15
|
# RSpec matcher for whether the element(s) matching a given selector exist.
|
16
16
|
#
|
17
17
|
# @see Capybara::Node::Matchers#assert_selector
|
18
|
-
def have_selector(
|
19
|
-
Matchers::HaveSelector.new(
|
18
|
+
def have_selector(...)
|
19
|
+
Matchers::HaveSelector.new(...)
|
20
20
|
end
|
21
21
|
|
22
22
|
# RSpec matcher for whether the element(s) matching a group of selectors exist.
|
23
23
|
#
|
24
24
|
# @see Capybara::Node::Matchers#assert_all_of_selectors
|
25
|
-
def have_all_of_selectors(
|
26
|
-
Matchers::HaveAllSelectors.new(
|
25
|
+
def have_all_of_selectors(...)
|
26
|
+
Matchers::HaveAllSelectors.new(...)
|
27
27
|
end
|
28
28
|
|
29
29
|
# RSpec matcher for whether no element(s) matching a group of selectors exist.
|
30
30
|
#
|
31
31
|
# @see Capybara::Node::Matchers#assert_none_of_selectors
|
32
|
-
def have_none_of_selectors(
|
33
|
-
Matchers::HaveNoSelectors.new(
|
32
|
+
def have_none_of_selectors(...)
|
33
|
+
Matchers::HaveNoSelectors.new(...)
|
34
34
|
end
|
35
35
|
|
36
36
|
# RSpec matcher for whether the element(s) matching any of a group of selectors exist.
|
37
37
|
#
|
38
38
|
# @see Capybara::Node::Matchers#assert_any_of_selectors
|
39
|
-
def have_any_of_selectors(
|
40
|
-
Matchers::HaveAnySelectors.new(
|
39
|
+
def have_any_of_selectors(...)
|
40
|
+
Matchers::HaveAnySelectors.new(...)
|
41
41
|
end
|
42
42
|
|
43
43
|
# RSpec matcher for whether the current element matches a given selector.
|
44
44
|
#
|
45
45
|
# @see Capybara::Node::Matchers#assert_matches_selector
|
46
|
-
def match_selector(
|
47
|
-
Matchers::MatchSelector.new(
|
46
|
+
def match_selector(...)
|
47
|
+
Matchers::MatchSelector.new(...)
|
48
48
|
end
|
49
49
|
|
50
50
|
%i[css xpath].each do |selector|
|
@@ -77,12 +77,17 @@ module Capybara
|
|
77
77
|
#
|
78
78
|
# @see Capybara::Node::Matchers#matches_css?
|
79
79
|
|
80
|
-
%i[link button field select table].each do |selector|
|
80
|
+
%i[link button field select table element].each do |selector|
|
81
81
|
define_method "have_#{selector}" do |locator = nil, **options, &optional_filter_block|
|
82
82
|
Matchers::HaveSelector.new(selector, locator, **options, &optional_filter_block)
|
83
83
|
end
|
84
84
|
end
|
85
85
|
|
86
|
+
# @!method have_element(locator = nil, **options, &optional_filter_block)
|
87
|
+
# RSpec matcher for elements.
|
88
|
+
#
|
89
|
+
# @see Capybara::Node::Matchers#has_element?
|
90
|
+
|
86
91
|
# @!method have_link(locator = nil, **options, &optional_filter_block)
|
87
92
|
# RSpec matcher for links.
|
88
93
|
#
|
@@ -161,7 +166,7 @@ module Capybara
|
|
161
166
|
|
162
167
|
%w[selector css xpath text title current_path link button
|
163
168
|
field checked_field unchecked_field select table
|
164
|
-
sibling ancestor].each do |matcher_type|
|
169
|
+
sibling ancestor element].each do |matcher_type|
|
165
170
|
define_method "have_no_#{matcher_type}" do |*args, **kw_args, &optional_filter_block|
|
166
171
|
Matchers::NegatedMatcher.new(send("have_#{matcher_type}", *args, **kw_args, &optional_filter_block))
|
167
172
|
end
|
@@ -177,15 +182,15 @@ module Capybara
|
|
177
182
|
# RSpec matcher for whether sibling element(s) matching a given selector exist.
|
178
183
|
#
|
179
184
|
# @see Capybara::Node::Matchers#assert_sibling
|
180
|
-
def have_sibling(
|
181
|
-
Matchers::HaveSibling.new(
|
185
|
+
def have_sibling(...)
|
186
|
+
Matchers::HaveSibling.new(...)
|
182
187
|
end
|
183
188
|
|
184
189
|
# RSpec matcher for whether ancestor element(s) matching a given selector exist.
|
185
190
|
#
|
186
191
|
# @see Capybara::Node::Matchers#assert_ancestor
|
187
|
-
def have_ancestor(
|
188
|
-
Matchers::HaveAncestor.new(
|
192
|
+
def have_ancestor(...)
|
193
|
+
Matchers::HaveAncestor.new(...)
|
189
194
|
end
|
190
195
|
|
191
196
|
##
|
@@ -76,7 +76,7 @@ module Capybara
|
|
76
76
|
else
|
77
77
|
cls = Array(classes).reject { |c| c.is_a? Regexp }.group_by { |cl| cl.match?(/^!(?!!!)/) }
|
78
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
|
79
|
+
cls[true].to_a.map { |cl| ":not(.#{Capybara::Selector::CSS.escape(cl.slice(1..))})" }).join]
|
80
80
|
end
|
81
81
|
end
|
82
82
|
end
|
@@ -51,7 +51,7 @@ module Capybara
|
|
51
51
|
else
|
52
52
|
Array(classes).reject { |c| c.is_a? Regexp }.map do |klass|
|
53
53
|
if klass.match?(/^!(?!!!)/)
|
54
|
-
!XPath.attr(:class).contains_word(klass.slice(1
|
54
|
+
!XPath.attr(:class).contains_word(klass.slice(1..))
|
55
55
|
else
|
56
56
|
XPath.attr(:class).contains_word(klass.sub(/^!!/, ''))
|
57
57
|
end
|
@@ -23,11 +23,11 @@ module Capybara
|
|
23
23
|
end
|
24
24
|
|
25
25
|
S = '\u{80}-\u{D7FF}\u{E000}-\u{FFFD}\u{10000}-\u{10FFFF}'
|
26
|
-
H = /[0-9a-fA-F]
|
27
|
-
UNICODE = /\\#{H}{1,6}[ \t\r\n\f]
|
28
|
-
NONASCII = /[#{S}]
|
29
|
-
ESCAPE = /#{UNICODE}|\\[ -~#{S}]
|
30
|
-
NMSTART = /[_a-zA-Z]|#{NONASCII}|#{ESCAPE}
|
26
|
+
H = /[0-9a-fA-F]/
|
27
|
+
UNICODE = /\\#{H}{1,6}[ \t\r\n\f]?/
|
28
|
+
NONASCII = /[#{S}]/
|
29
|
+
ESCAPE = /#{UNICODE}|\\[ -~#{S}]/
|
30
|
+
NMSTART = /[_a-zA-Z]|#{NONASCII}|#{ESCAPE}/
|
31
31
|
|
32
32
|
class Splitter
|
33
33
|
def split(css)
|
@@ -43,7 +43,7 @@ module Capybara
|
|
43
43
|
when '"', "'"
|
44
44
|
selector << parse_string(char, str)
|
45
45
|
when '\\'
|
46
|
-
selector << char + str.getc
|
46
|
+
selector << (char + str.getc)
|
47
47
|
when ','
|
48
48
|
selectors << selector.strip
|
49
49
|
selector.clear
|
@@ -14,16 +14,17 @@ Capybara.add_selector(:button, locator_type: [String, Symbol]) do
|
|
14
14
|
XPath.string.n.is(locator) |
|
15
15
|
XPath.descendant(:img)[XPath.attr(:alt).is(locator)]
|
16
16
|
|
17
|
-
|
18
|
-
|
17
|
+
label_contains_xpath = locate_label(locator).descendant[labellable_elements]
|
18
|
+
input_btn_xpath = input_btn_xpath[locator_matchers]
|
19
|
+
btn_xpath = btn_xpath[btn_matchers]
|
19
20
|
aria_btn_xpath = aria_btn_xpath[btn_matchers]
|
20
21
|
|
21
22
|
alt_matches = XPath.attr(:alt).is(locator)
|
22
23
|
alt_matches |= XPath.attr(:'aria-label').is(locator) if enable_aria_label
|
23
|
-
image_btn_xpath = image_btn_xpath[alt_matches]
|
24
|
+
image_btn_xpath = image_btn_xpath[alt_matches]
|
24
25
|
end
|
25
26
|
|
26
|
-
btn_xpaths = [input_btn_xpath, btn_xpath, image_btn_xpath]
|
27
|
+
btn_xpaths = [input_btn_xpath, btn_xpath, image_btn_xpath, label_contains_xpath].compact
|
27
28
|
btn_xpaths << aria_btn_xpath if enable_aria_role
|
28
29
|
|
29
30
|
%i[value title type].inject(btn_xpaths.inject(&:union)) do |memo, ef|
|
@@ -57,7 +58,11 @@ Capybara.add_selector(:button, locator_type: [String, Symbol]) do
|
|
57
58
|
XPath.attr(:title).is(locator),
|
58
59
|
(XPath.attr(:id) == XPath.anywhere(:label)[XPath.string.n.is(locator)].attr(:for)),
|
59
60
|
(XPath.attr(:'aria-label').is(locator) if config.enable_aria_label),
|
60
|
-
(XPath.attr(test_id) == locator if config.test_id)
|
61
|
+
(XPath.attr(config.test_id) == locator if config.test_id)
|
61
62
|
].compact.inject(&:|)
|
62
63
|
end
|
64
|
+
|
65
|
+
def labellable_elements
|
66
|
+
(XPath.self(:input) & XPath.attr(:type).one_of('submit', 'reset', 'image', 'button')) | XPath.self(:button)
|
67
|
+
end
|
63
68
|
end
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
Capybara.add_selector(:checkbox, locator_type: [String, Symbol]) do
|
4
4
|
xpath do |locator, allow_self: nil, **options|
|
5
|
-
xpath = XPath.axis(allow_self ? :
|
5
|
+
xpath = XPath.axis(allow_self ? :'descendant-or-self' : :descendant, :input)[
|
6
6
|
XPath.attr(:type) == 'checkbox'
|
7
7
|
]
|
8
8
|
locate_field(xpath, locator, **options)
|
@@ -3,7 +3,7 @@
|
|
3
3
|
Capybara.add_selector(:file_field, locator_type: [String, Symbol]) do
|
4
4
|
label 'file field'
|
5
5
|
xpath do |locator, allow_self: nil, **options|
|
6
|
-
xpath = XPath.axis(allow_self ? :
|
6
|
+
xpath = XPath.axis(allow_self ? :'descendant-or-self' : :descendant, :input)[
|
7
7
|
XPath.attr(:type) == 'file'
|
8
8
|
]
|
9
9
|
locate_field(xpath, locator, **options)
|
@@ -3,7 +3,7 @@
|
|
3
3
|
Capybara.add_selector(:fillable_field, locator_type: [String, Symbol]) do
|
4
4
|
label 'field'
|
5
5
|
xpath do |locator, allow_self: nil, **options|
|
6
|
-
xpath = XPath.axis(allow_self ? :
|
6
|
+
xpath = XPath.axis(allow_self ? :'descendant-or-self' : :descendant, :input, :textarea)[
|
7
7
|
!XPath.attr(:type).one_of('submit', 'image', 'radio', 'checkbox', 'hidden', 'file')
|
8
8
|
]
|
9
9
|
locate_field(xpath, locator, **options)
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
Capybara.add_selector(:link, locator_type: [String, Symbol]) do
|
4
|
-
xpath do |locator, href: true, alt: nil, title: nil, **|
|
4
|
+
xpath do |locator, href: true, alt: nil, title: nil, target: nil, **|
|
5
5
|
xpath = XPath.descendant(:a)
|
6
6
|
xpath = builder(xpath).add_attribute_conditions(href: href) unless href == false
|
7
7
|
|
@@ -25,6 +25,7 @@ Capybara.add_selector(:link, locator_type: [String, Symbol]) do
|
|
25
25
|
|
26
26
|
xpath = xpath[find_by_attr(:title, title)]
|
27
27
|
xpath = xpath[XPath.descendant(:img)[XPath.attr(:alt) == alt]] if alt
|
28
|
+
xpath = xpath[find_by_attr(:target, target)] if target
|
28
29
|
|
29
30
|
xpath
|
30
31
|
end
|
@@ -3,7 +3,7 @@
|
|
3
3
|
Capybara.add_selector(:radio_button, locator_type: [String, Symbol]) do
|
4
4
|
label 'radio button'
|
5
5
|
xpath do |locator, allow_self: nil, **options|
|
6
|
-
xpath = XPath.axis(allow_self ? :
|
6
|
+
xpath = XPath.axis(allow_self ? :'descendant-or-self' : :descendant, :input)[
|
7
7
|
XPath.attr(:type) == 'radio'
|
8
8
|
]
|
9
9
|
locate_field(xpath, locator, **options)
|
@@ -93,7 +93,7 @@ Capybara.add_selector(:table, locator_type: [String, Symbol]) do
|
|
93
93
|
row.map do |header, cell|
|
94
94
|
header_xp = XPath.ancestor(:table)[1].descendant(:tr)[1].descendant(:th)[XPath.string.n.is(header)]
|
95
95
|
XPath.descendant(:td)[
|
96
|
-
XPath.string.n.is(cell) & XPath.position.equals(header_xp.preceding_sibling.count.plus(1))
|
96
|
+
XPath.string.n.is(cell) & header_xp.boolean & XPath.position.equals(header_xp.preceding_sibling.count.plus(1))
|
97
97
|
]
|
98
98
|
end.reduce(:&)
|
99
99
|
end
|
@@ -7,14 +7,14 @@ Capybara.add_selector(:table_row, locator_type: [Array, Hash]) do
|
|
7
7
|
locator.reduce(xpath) do |xp, (header, cell)|
|
8
8
|
header_xp = XPath.ancestor(:table)[1].descendant(:tr)[1].descendant(:th)[XPath.string.n.is(header)]
|
9
9
|
cell_xp = XPath.descendant(:td)[
|
10
|
-
XPath.string.n.is(cell) & XPath.position.equals(header_xp.preceding_sibling.count.plus(1))
|
10
|
+
XPath.string.n.is(cell) & header_xp.boolean & XPath.position.equals(header_xp.preceding_sibling.count.plus(1))
|
11
11
|
]
|
12
12
|
xp.where(cell_xp)
|
13
13
|
end
|
14
14
|
else
|
15
15
|
initial_td = XPath.descendant(:td)[XPath.string.n.is(locator.shift)]
|
16
16
|
tds = locator.reverse.map { |cell| XPath.following_sibling(:td)[XPath.string.n.is(cell)] }
|
17
|
-
.reduce { |xp, cell|
|
17
|
+
.reduce { |xp, cell| cell.where(xp) }
|
18
18
|
xpath[initial_td[tds]]
|
19
19
|
end
|
20
20
|
end
|
@@ -203,7 +203,7 @@ module Capybara
|
|
203
203
|
|
204
204
|
##
|
205
205
|
#
|
206
|
-
# Set the default visibility mode that
|
206
|
+
# Set the default visibility mode that should be used if no visible option is passed when using the selector.
|
207
207
|
# If not specified will default to the behavior indicated by Capybara.ignore_hidden_elements
|
208
208
|
#
|
209
209
|
# @param [Symbol] default_visibility Only find elements with the specified visibility:
|
@@ -260,7 +260,9 @@ module Capybara
|
|
260
260
|
|
261
261
|
def parameter_names(block)
|
262
262
|
key_types = %i[key keyreq]
|
263
|
-
|
263
|
+
# user filter_map when we drop dupport for 2.6
|
264
|
+
# block.parameters.select { |(type, _name)| key_types.include? type }.map { |(_, name)| name }
|
265
|
+
block.parameters.filter_map { |(type, name)| name if key_types.include? type }
|
264
266
|
end
|
265
267
|
|
266
268
|
def expression(type, allowed_filters, &block)
|
@@ -101,13 +101,10 @@ module Capybara
|
|
101
101
|
private
|
102
102
|
|
103
103
|
def options_with_defaults(options)
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
end
|
109
|
-
end
|
110
|
-
options
|
104
|
+
expression_filters
|
105
|
+
.chain(node_filters)
|
106
|
+
.filter_map { |name, filter| [name, filter.default] if filter.default? }
|
107
|
+
.to_h.merge!(options)
|
111
108
|
end
|
112
109
|
|
113
110
|
def add_filter(name, filter_class, *types, matcher: nil, **options, &block)
|
@@ -69,11 +69,8 @@ module Capybara
|
|
69
69
|
suffixes = [[]]
|
70
70
|
strs.reverse_each do |str|
|
71
71
|
if str.is_a? Set
|
72
|
-
prefixes = str.
|
73
|
-
|
74
|
-
result = []
|
75
|
-
prefixes.product(suffixes) { |pair| result << pair.flatten(1) }
|
76
|
-
suffixes = result
|
72
|
+
prefixes = str.flat_map { |s| combine(s) }
|
73
|
+
suffixes = prefixes.product(suffixes).map { |pair| pair.flatten(1) }
|
77
74
|
else
|
78
75
|
suffixes.each { |arr| arr.unshift str }
|
79
76
|
end
|
@@ -66,7 +66,11 @@ module Capybara
|
|
66
66
|
end
|
67
67
|
ensure
|
68
68
|
unless locator_valid?(locator)
|
69
|
-
|
69
|
+
Capybara::Helpers.warn(
|
70
|
+
"Locator #{locator.class}:#{locator.inspect} for selector #{name.inspect} must #{locator_description}. " \
|
71
|
+
'This will raise an error in a future version of Capybara. ' \
|
72
|
+
"Called from: #{Capybara::Helpers.filter_backtrace(caller)}"
|
73
|
+
)
|
70
74
|
end
|
71
75
|
end
|
72
76
|
|