capybara 3.23.0 → 3.35.3
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 +264 -11
- data/README.md +10 -6
- data/lib/capybara.rb +20 -8
- data/lib/capybara/config.rb +10 -8
- data/lib/capybara/cucumber.rb +1 -1
- data/lib/capybara/driver/base.rb +4 -0
- data/lib/capybara/driver/node.rb +4 -0
- data/lib/capybara/dsl.rb +10 -2
- data/lib/capybara/helpers.rb +28 -2
- data/lib/capybara/minitest.rb +232 -144
- data/lib/capybara/minitest/spec.rb +156 -97
- data/lib/capybara/node/actions.rb +36 -36
- data/lib/capybara/node/base.rb +6 -6
- data/lib/capybara/node/document.rb +2 -2
- data/lib/capybara/node/document_matchers.rb +3 -3
- data/lib/capybara/node/element.rb +77 -33
- data/lib/capybara/node/finders.rb +24 -17
- data/lib/capybara/node/matchers.rb +79 -64
- data/lib/capybara/node/simple.rb +11 -4
- data/lib/capybara/queries/ancestor_query.rb +6 -10
- data/lib/capybara/queries/base_query.rb +2 -1
- data/lib/capybara/queries/current_path_query.rb +14 -4
- data/lib/capybara/queries/selector_query.rb +259 -23
- data/lib/capybara/queries/sibling_query.rb +5 -11
- data/lib/capybara/queries/style_query.rb +1 -1
- data/lib/capybara/queries/text_query.rb +13 -1
- data/lib/capybara/rack_test/browser.rb +13 -4
- data/lib/capybara/rack_test/driver.rb +2 -1
- data/lib/capybara/rack_test/form.rb +2 -2
- data/lib/capybara/rack_test/node.rb +42 -6
- data/lib/capybara/registration_container.rb +44 -0
- data/lib/capybara/registrations/drivers.rb +18 -12
- data/lib/capybara/registrations/patches/puma_ssl.rb +29 -0
- data/lib/capybara/registrations/servers.rb +9 -2
- data/lib/capybara/result.rb +39 -19
- data/lib/capybara/rspec.rb +2 -0
- data/lib/capybara/rspec/matcher_proxies.rb +5 -5
- data/lib/capybara/rspec/matchers.rb +97 -74
- data/lib/capybara/rspec/matchers/base.rb +19 -6
- data/lib/capybara/rspec/matchers/count_sugar.rb +2 -1
- data/lib/capybara/rspec/matchers/have_ancestor.rb +5 -7
- data/lib/capybara/rspec/matchers/have_current_path.rb +2 -2
- data/lib/capybara/rspec/matchers/have_selector.rb +15 -10
- data/lib/capybara/rspec/matchers/have_sibling.rb +4 -7
- data/lib/capybara/rspec/matchers/have_text.rb +4 -7
- data/lib/capybara/rspec/matchers/have_title.rb +2 -2
- data/lib/capybara/rspec/matchers/match_selector.rb +3 -3
- data/lib/capybara/rspec/matchers/match_style.rb +7 -2
- data/lib/capybara/rspec/matchers/spatial_sugar.rb +39 -0
- data/lib/capybara/selector.rb +46 -19
- data/lib/capybara/selector/builders/css_builder.rb +10 -6
- data/lib/capybara/selector/builders/xpath_builder.rb +4 -2
- data/lib/capybara/selector/css.rb +1 -1
- data/lib/capybara/selector/definition.rb +13 -11
- data/lib/capybara/selector/definition/button.rb +32 -15
- data/lib/capybara/selector/definition/checkbox.rb +2 -2
- data/lib/capybara/selector/definition/css.rb +3 -1
- data/lib/capybara/selector/definition/datalist_input.rb +2 -2
- data/lib/capybara/selector/definition/datalist_option.rb +1 -1
- data/lib/capybara/selector/definition/element.rb +3 -2
- data/lib/capybara/selector/definition/field.rb +1 -1
- data/lib/capybara/selector/definition/file_field.rb +1 -1
- data/lib/capybara/selector/definition/fillable_field.rb +2 -2
- data/lib/capybara/selector/definition/label.rb +5 -3
- data/lib/capybara/selector/definition/link.rb +8 -0
- data/lib/capybara/selector/definition/option.rb +1 -1
- data/lib/capybara/selector/definition/radio_button.rb +2 -2
- data/lib/capybara/selector/definition/select.rb +33 -14
- data/lib/capybara/selector/definition/table.rb +6 -3
- data/lib/capybara/selector/definition/table_row.rb +2 -2
- data/lib/capybara/selector/filter_set.rb +13 -11
- data/lib/capybara/selector/filters/base.rb +6 -1
- data/lib/capybara/selector/filters/locator_filter.rb +1 -1
- data/lib/capybara/selector/regexp_disassembler.rb +7 -0
- data/lib/capybara/selector/selector.rb +13 -3
- data/lib/capybara/selenium/atoms/getAttribute.min.js +1 -1
- data/lib/capybara/selenium/atoms/isDisplayed.min.js +1 -1
- data/lib/capybara/selenium/atoms/src/getAttribute.js +1 -1
- data/lib/capybara/selenium/atoms/src/isDisplayed.js +10 -10
- data/lib/capybara/selenium/driver.rb +86 -24
- data/lib/capybara/selenium/driver_specializations/chrome_driver.rb +24 -21
- data/lib/capybara/selenium/driver_specializations/edge_driver.rb +21 -19
- data/lib/capybara/selenium/driver_specializations/firefox_driver.rb +17 -1
- data/lib/capybara/selenium/driver_specializations/safari_driver.rb +0 -4
- data/lib/capybara/selenium/extensions/file_input_click_emulation.rb +34 -0
- data/lib/capybara/selenium/extensions/find.rb +37 -26
- data/lib/capybara/selenium/extensions/html5_drag.rb +55 -11
- data/lib/capybara/selenium/extensions/modifier_keys_stack.rb +28 -0
- data/lib/capybara/selenium/extensions/scroll.rb +8 -10
- data/lib/capybara/selenium/logger_suppressor.rb +8 -2
- data/lib/capybara/selenium/node.rb +160 -40
- data/lib/capybara/selenium/nodes/chrome_node.rb +72 -12
- data/lib/capybara/selenium/nodes/edge_node.rb +32 -14
- data/lib/capybara/selenium/nodes/firefox_node.rb +28 -32
- data/lib/capybara/selenium/nodes/safari_node.rb +5 -29
- data/lib/capybara/selenium/patches/action_pauser.rb +26 -0
- data/lib/capybara/selenium/patches/atoms.rb +4 -4
- data/lib/capybara/selenium/patches/is_displayed.rb +16 -0
- data/lib/capybara/selenium/patches/logs.rb +32 -7
- data/lib/capybara/server.rb +19 -3
- data/lib/capybara/server/animation_disabler.rb +8 -3
- data/lib/capybara/server/checker.rb +1 -1
- data/lib/capybara/server/middleware.rb +22 -10
- data/lib/capybara/session.rb +66 -40
- data/lib/capybara/session/config.rb +11 -3
- data/lib/capybara/session/matchers.rb +11 -11
- data/lib/capybara/spec/public/offset.js +6 -0
- data/lib/capybara/spec/public/test.js +75 -7
- data/lib/capybara/spec/session/accept_alert_spec.rb +1 -1
- data/lib/capybara/spec/session/all_spec.rb +60 -5
- data/lib/capybara/spec/session/ancestor_spec.rb +5 -0
- data/lib/capybara/spec/session/assert_text_spec.rb +9 -5
- data/lib/capybara/spec/session/check_spec.rb +6 -0
- data/lib/capybara/spec/session/click_button_spec.rb +16 -0
- data/lib/capybara/spec/session/click_link_or_button_spec.rb +9 -0
- data/lib/capybara/spec/session/current_url_spec.rb +11 -1
- data/lib/capybara/spec/session/fill_in_spec.rb +29 -0
- data/lib/capybara/spec/session/find_spec.rb +55 -0
- data/lib/capybara/spec/session/has_ancestor_spec.rb +2 -0
- data/lib/capybara/spec/session/has_button_spec.rb +51 -0
- data/lib/capybara/spec/session/has_css_spec.rb +26 -4
- data/lib/capybara/spec/session/has_current_path_spec.rb +15 -2
- data/lib/capybara/spec/session/has_field_spec.rb +34 -0
- data/lib/capybara/spec/session/has_select_spec.rb +32 -4
- data/lib/capybara/spec/session/has_selector_spec.rb +4 -4
- data/lib/capybara/spec/session/has_table_spec.rb +51 -5
- data/lib/capybara/spec/session/has_text_spec.rb +30 -0
- data/lib/capybara/spec/session/html_spec.rb +1 -1
- data/lib/capybara/spec/session/matches_style_spec.rb +2 -2
- data/lib/capybara/spec/session/node_spec.rb +394 -9
- data/lib/capybara/spec/session/refresh_spec.rb +2 -1
- data/lib/capybara/spec/session/save_and_open_screenshot_spec.rb +2 -2
- data/lib/capybara/spec/session/save_page_spec.rb +4 -4
- data/lib/capybara/spec/session/save_screenshot_spec.rb +4 -15
- data/lib/capybara/spec/session/selectors_spec.rb +16 -3
- data/lib/capybara/spec/session/window/switch_to_window_spec.rb +1 -1
- data/lib/capybara/spec/session/window/window_opened_by_spec.rb +1 -1
- data/lib/capybara/spec/session/window/window_spec.rb +8 -8
- data/lib/capybara/spec/session/window/windows_spec.rb +1 -1
- data/lib/capybara/spec/spec_helper.rb +14 -14
- data/lib/capybara/spec/test_app.rb +27 -21
- data/lib/capybara/spec/views/form.erb +47 -4
- data/lib/capybara/spec/views/offset.erb +32 -0
- data/lib/capybara/spec/views/spatial.erb +31 -0
- data/lib/capybara/spec/views/with_animation.erb +37 -1
- data/lib/capybara/spec/views/with_dragula.erb +24 -0
- data/lib/capybara/spec/views/with_html.erb +24 -2
- data/lib/capybara/spec/views/with_jquery_animation.erb +24 -0
- data/lib/capybara/spec/views/with_js.erb +4 -1
- data/lib/capybara/spec/views/with_jstree.erb +26 -0
- data/lib/capybara/spec/views/with_sortable_js.erb +1 -1
- data/lib/capybara/version.rb +1 -1
- data/lib/capybara/window.rb +3 -7
- data/spec/basic_node_spec.rb +15 -14
- data/spec/capybara_spec.rb +28 -28
- data/spec/dsl_spec.rb +16 -3
- data/spec/filter_set_spec.rb +5 -5
- data/spec/fixtures/selenium_driver_rspec_failure.rb +1 -1
- data/spec/fixtures/selenium_driver_rspec_success.rb +1 -1
- data/spec/minitest_spec.rb +3 -2
- data/spec/minitest_spec_spec.rb +46 -46
- data/spec/rack_test_spec.rb +38 -15
- data/spec/regexp_dissassembler_spec.rb +52 -38
- data/spec/result_spec.rb +43 -32
- data/spec/rspec/features_spec.rb +4 -1
- data/spec/rspec/scenarios_spec.rb +4 -0
- data/spec/rspec/shared_spec_matchers.rb +68 -56
- data/spec/rspec_spec.rb +9 -5
- data/spec/selector_spec.rb +32 -17
- data/spec/selenium_spec_chrome.rb +78 -11
- data/spec/selenium_spec_chrome_remote.rb +23 -6
- data/spec/selenium_spec_edge.rb +15 -12
- data/spec/selenium_spec_firefox.rb +24 -19
- data/spec/selenium_spec_firefox_remote.rb +0 -8
- data/spec/selenium_spec_ie.rb +1 -6
- data/spec/server_spec.rb +106 -44
- data/spec/session_spec.rb +5 -5
- data/spec/shared_selenium_node.rb +56 -2
- data/spec/shared_selenium_session.rb +122 -15
- data/spec/spec_helper.rb +2 -2
- metadata +63 -17
- data/lib/capybara/spec/session/source_spec.rb +0 -0
@@ -1,20 +1,17 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'capybara/rspec/matchers/base'
|
4
|
-
require 'capybara/rspec/matchers/count_sugar'
|
5
4
|
|
6
5
|
module Capybara
|
7
6
|
module RSpecMatchers
|
8
7
|
module Matchers
|
9
|
-
class HaveSibling <
|
10
|
-
include CountSugar
|
11
|
-
|
8
|
+
class HaveSibling < CountableWrappedElementMatcher
|
12
9
|
def element_matches?(el)
|
13
|
-
el.assert_sibling(*@args, &@filter_block)
|
10
|
+
el.assert_sibling(*@args, **session_query_options, &@filter_block)
|
14
11
|
end
|
15
12
|
|
16
13
|
def element_does_not_match?(el)
|
17
|
-
el.assert_no_sibling(*@args, &@filter_block)
|
14
|
+
el.assert_no_sibling(*@args, **session_query_options, &@filter_block)
|
18
15
|
end
|
19
16
|
|
20
17
|
def description
|
@@ -22,7 +19,7 @@ module Capybara
|
|
22
19
|
end
|
23
20
|
|
24
21
|
def query
|
25
|
-
@query ||= Capybara::Queries::SiblingQuery.new(*session_query_args, &@filter_block)
|
22
|
+
@query ||= Capybara::Queries::SiblingQuery.new(*session_query_args, **session_query_options, &@filter_block)
|
26
23
|
end
|
27
24
|
end
|
28
25
|
end
|
@@ -1,24 +1,21 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'capybara/rspec/matchers/base'
|
4
|
-
require 'capybara/rspec/matchers/count_sugar'
|
5
4
|
|
6
5
|
module Capybara
|
7
6
|
module RSpecMatchers
|
8
7
|
module Matchers
|
9
|
-
class HaveText <
|
10
|
-
include CountSugar
|
11
|
-
|
8
|
+
class HaveText < CountableWrappedElementMatcher
|
12
9
|
def element_matches?(el)
|
13
|
-
el.assert_text(*@args)
|
10
|
+
el.assert_text(*@args, **@kw_args)
|
14
11
|
end
|
15
12
|
|
16
13
|
def element_does_not_match?(el)
|
17
|
-
el.assert_no_text(*@args)
|
14
|
+
el.assert_no_text(*@args, **@kw_args)
|
18
15
|
end
|
19
16
|
|
20
17
|
def description
|
21
|
-
"text #{format(text)}"
|
18
|
+
"have text #{format(text)}"
|
22
19
|
end
|
23
20
|
|
24
21
|
def format(content)
|
@@ -7,11 +7,11 @@ module Capybara
|
|
7
7
|
module Matchers
|
8
8
|
class HaveTitle < WrappedElementMatcher
|
9
9
|
def element_matches?(el)
|
10
|
-
el.assert_title(*@args)
|
10
|
+
el.assert_title(*@args, **@kw_args)
|
11
11
|
end
|
12
12
|
|
13
13
|
def element_does_not_match?(el)
|
14
|
-
el.assert_no_title(*@args)
|
14
|
+
el.assert_no_title(*@args, **@kw_args)
|
15
15
|
end
|
16
16
|
|
17
17
|
def description
|
@@ -7,11 +7,11 @@ module Capybara
|
|
7
7
|
module Matchers
|
8
8
|
class MatchSelector < HaveSelector
|
9
9
|
def element_matches?(el)
|
10
|
-
el.assert_matches_selector(*@args, &@filter_block)
|
10
|
+
el.assert_matches_selector(*@args, **session_query_options, &@filter_block)
|
11
11
|
end
|
12
12
|
|
13
13
|
def element_does_not_match?(el)
|
14
|
-
el.assert_not_matches_selector(*@args, &@filter_block)
|
14
|
+
el.assert_not_matches_selector(*@args, **session_query_options, &@filter_block)
|
15
15
|
end
|
16
16
|
|
17
17
|
def description
|
@@ -19,7 +19,7 @@ module Capybara
|
|
19
19
|
end
|
20
20
|
|
21
21
|
def query
|
22
|
-
@query ||= Capybara::Queries::MatchQuery.new(*session_query_args, &@filter_block)
|
22
|
+
@query ||= Capybara::Queries::MatchQuery.new(*session_query_args, **session_query_options, &@filter_block)
|
23
23
|
end
|
24
24
|
end
|
25
25
|
end
|
@@ -6,8 +6,13 @@ module Capybara
|
|
6
6
|
module RSpecMatchers
|
7
7
|
module Matchers
|
8
8
|
class MatchStyle < WrappedElementMatcher
|
9
|
+
def initialize(styles = nil, **kw_args, &filter_block)
|
10
|
+
styles, kw_args = kw_args, {} if styles.nil?
|
11
|
+
super(styles, **kw_args, &filter_block)
|
12
|
+
end
|
13
|
+
|
9
14
|
def element_matches?(el)
|
10
|
-
el.assert_matches_style(*@args)
|
15
|
+
el.assert_matches_style(*@args, **@kw_args)
|
11
16
|
end
|
12
17
|
|
13
18
|
def does_not_match?(_actual)
|
@@ -28,7 +33,7 @@ module Capybara
|
|
28
33
|
##
|
29
34
|
# @deprecated
|
30
35
|
class HaveStyle < MatchStyle
|
31
|
-
def initialize(*args, &filter_block)
|
36
|
+
def initialize(*args, **kw_args, &filter_block)
|
32
37
|
warn 'HaveStyle matcher is deprecated, please use the MatchStyle matcher instead'
|
33
38
|
super
|
34
39
|
end
|
@@ -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
|
data/lib/capybara/selector.rb
CHANGED
@@ -7,8 +7,13 @@ require 'capybara/selector/definition'
|
|
7
7
|
#
|
8
8
|
# All Selectors below support the listed selector specific filters in addition to the following system-wide filters
|
9
9
|
# * :id (String, Regexp, XPath::Expression) - Matches the id attribute
|
10
|
-
# * :class (String, Array<String>, Regexp, XPath::Expression) - Matches the class(es) provided
|
10
|
+
# * :class (String, Array<String | Regexp>, Regexp, XPath::Expression) - Matches the class(es) provided
|
11
11
|
# * :style (String, Regexp, Hash<String, String>) - Match on elements style
|
12
|
+
# * :above (Element) - Match elements above the passed element on the page
|
13
|
+
# * :below (Element) - Match elements below the passed element on the page
|
14
|
+
# * :left_of (Element) - Match elements left of the passed element on the page
|
15
|
+
# * :right_of (Element) - Match elements right of the passed element on the page
|
16
|
+
# * :near (Element) - Match elements near (within 50px) the passed element on the page
|
12
17
|
#
|
13
18
|
# ### Built-in Selectors
|
14
19
|
#
|
@@ -25,8 +30,8 @@ require 'capybara/selector/definition'
|
|
25
30
|
# * Locator: Matches against the id, {Capybara.configure test_id} attribute, name, placeholder, or
|
26
31
|
# associated label text
|
27
32
|
# * Filters:
|
28
|
-
# * :name (String) - Matches the name attribute
|
29
|
-
# * :placeholder (String) - Matches the placeholder attribute
|
33
|
+
# * :name (String, Regexp) - Matches the name attribute
|
34
|
+
# * :placeholder (String, Regexp) - Matches the placeholder attribute
|
30
35
|
# * :type (String) - Matches the type attribute of the field or element type for 'textarea' and 'select'
|
31
36
|
# * :readonly (Boolean) - Match on the element being readonly
|
32
37
|
# * :with (String, Regexp) - Matches the current value of the field
|
@@ -34,6 +39,8 @@ require 'capybara/selector/definition'
|
|
34
39
|
# * :unchecked (Boolean) - Match unchecked fields?
|
35
40
|
# * :disabled (Boolean, :all) - Match disabled field? (Default: false)
|
36
41
|
# * :multiple (Boolean) - Match fields that accept multiple values
|
42
|
+
# * :valid (Boolean) - Match fields that are valid/invalid according to HTML5 form validation
|
43
|
+
# * :validation_message (String, Regexp) - Matches the elements current validationMessage
|
37
44
|
#
|
38
45
|
# * **:fieldset** - Select fieldset elements
|
39
46
|
# * Locator: Matches id, {Capybara.configure test_id}, or contents of wrapped legend
|
@@ -52,7 +59,7 @@ require 'capybara/selector/definition'
|
|
52
59
|
# * **:button** - Find buttons ( input [of type submit, reset, image, button] or button elements )
|
53
60
|
# * Locator: Matches the id, {Capybara.configure test_id} attribute, name, value, or title attributes, string content of a button, or the alt attribute of an image type button or of a descendant image of a button
|
54
61
|
# * Filters:
|
55
|
-
# * :name (String) - Matches the name attribute
|
62
|
+
# * :name (String, Regexp) - Matches the name attribute
|
56
63
|
# * :title (String) - Matches the title attribute
|
57
64
|
# * :value (String) - Matches the value of an input button
|
58
65
|
# * :type (String) - Matches the type attribute
|
@@ -66,17 +73,19 @@ require 'capybara/selector/definition'
|
|
66
73
|
# * **:fillable_field** - Find text fillable fields ( textarea, input [not of type submit, image, radio, checkbox, hidden, file] )
|
67
74
|
# * Locator: Matches against the id, {Capybara.configure test_id} attribute, name, placeholder, or associated label text
|
68
75
|
# * Filters:
|
69
|
-
# * :name (String) - Matches the name attribute
|
70
|
-
# * :placeholder (String) - Matches the placeholder attribute
|
76
|
+
# * :name (String, Regexp) - Matches the name attribute
|
77
|
+
# * :placeholder (String, Regexp) - Matches the placeholder attribute
|
71
78
|
# * :with (String, Regexp) - Matches the current value of the field
|
72
79
|
# * :type (String) - Matches the type attribute of the field or element type for 'textarea'
|
73
80
|
# * :disabled (Boolean, :all) - Match disabled field? (Default: false)
|
74
81
|
# * :multiple (Boolean) - Match fields that accept multiple values
|
82
|
+
# * :valid (Boolean) - Match fields that are valid/invalid according to HTML5 form validation
|
83
|
+
# * :validation_message (String, Regexp) - Matches the elements current validationMessage
|
75
84
|
#
|
76
85
|
# * **:radio_button** - Find radio buttons
|
77
86
|
# * Locator: Match id, {Capybara.configure test_id} attribute, name, or associated label text
|
78
87
|
# * Filters:
|
79
|
-
# * :name (String) - Matches the name attribute
|
88
|
+
# * :name (String, Regexp) - Matches the name attribute
|
80
89
|
# * :checked (Boolean) - Match checked fields?
|
81
90
|
# * :unchecked (Boolean) - Match unchecked fields?
|
82
91
|
# * :disabled (Boolean, :all) - Match disabled field? (Default: false)
|
@@ -86,21 +95,23 @@ require 'capybara/selector/definition'
|
|
86
95
|
# * **:checkbox** - Find checkboxes
|
87
96
|
# * Locator: Match id, {Capybara.configure test_id} attribute, name, or associated label text
|
88
97
|
# * Filters:
|
89
|
-
# * :name (String) - Matches the name attribute
|
98
|
+
# * :name (String, Regexp) - Matches the name attribute
|
90
99
|
# * :checked (Boolean) - Match checked fields?
|
91
100
|
# * :unchecked (Boolean) - Match unchecked fields?
|
92
101
|
# * :disabled (Boolean, :all) - Match disabled field? (Default: false)
|
93
|
-
# * :
|
94
|
-
# * :
|
102
|
+
# * :with (String, Regexp) - Match the current value
|
103
|
+
# * :option - Alias of :with
|
95
104
|
#
|
96
105
|
# * **:select** - Find select elements
|
97
106
|
# * Locator: Match id, {Capybara.configure test_id} attribute, name, placeholder, or associated label text
|
98
107
|
# * Filters:
|
99
|
-
# * :name (String) - Matches the name attribute
|
100
|
-
# * :placeholder (String) - Matches the placeholder attribute
|
108
|
+
# * :name (String, Regexp) - Matches the name attribute
|
109
|
+
# * :placeholder (String, Placeholder) - Matches the placeholder attribute
|
101
110
|
# * :disabled (Boolean, :all) - Match disabled field? (Default: false)
|
102
111
|
# * :multiple (Boolean) - Match fields that accept multiple values
|
103
112
|
# * :options (Array<String>) - Exact match options
|
113
|
+
# * :enabled_options (Array<String>) - Exact match enabled options
|
114
|
+
# * :disabled_options (Array<String>) - Exact match disabled options
|
104
115
|
# * :with_options (Array<String>) - Partial match options
|
105
116
|
# * :selected (String, Array<String>) - Match the selection(s)
|
106
117
|
# * :with_selected (String, Array<String>) - Partial match the selection(s)
|
@@ -115,8 +126,8 @@ require 'capybara/selector/definition'
|
|
115
126
|
# * Locator: Matches against the id, {Capybara.configure test_id} attribute, name,
|
116
127
|
# placeholder, or associated label text
|
117
128
|
# * Filters:
|
118
|
-
# * :name (String) - Matches the name attribute
|
119
|
-
# * :placeholder (String) - Matches the placeholder attribute
|
129
|
+
# * :name (String, Regexp) - Matches the name attribute
|
130
|
+
# * :placeholder (String, Regexp) - Matches the placeholder attribute
|
120
131
|
# * :disabled (Boolean, :all) - Match disabled field? (Default: false)
|
121
132
|
# * :options (Array<String>) - Exact match options
|
122
133
|
# * :with_options (Array<String>) - Partial match options
|
@@ -129,7 +140,7 @@ require 'capybara/selector/definition'
|
|
129
140
|
# * **:file_field** - Find file input elements
|
130
141
|
# * Locator: Match id, {Capybara.configure test_id} attribute, name, or associated label text
|
131
142
|
# * Filters:
|
132
|
-
# * :name (String) - Matches the name attribute
|
143
|
+
# * :name (String, Regexp) - Matches the name attribute
|
133
144
|
# * :disabled (Boolean, :all) - Match disabled field? (Default: false)
|
134
145
|
# * :multiple (Boolean) - Match field that accepts multiple values
|
135
146
|
#
|
@@ -160,15 +171,28 @@ require 'capybara/selector/definition'
|
|
160
171
|
# * Filters:
|
161
172
|
# * :\<any> (String, Regexp) - Match on any specified element attribute
|
162
173
|
#
|
163
|
-
class Capybara::Selector; end
|
174
|
+
class Capybara::Selector; end # rubocop:disable Lint/EmptyClass
|
164
175
|
|
165
176
|
Capybara::Selector::FilterSet.add(:_field) do
|
166
177
|
node_filter(:checked, :boolean) { |node, value| !(value ^ node.checked?) }
|
167
178
|
node_filter(:unchecked, :boolean) { |node, value| (value ^ node.checked?) }
|
168
179
|
node_filter(:disabled, :boolean, default: false, skip_if: :all) { |node, value| !(value ^ node.disabled?) }
|
180
|
+
node_filter(:valid, :boolean) { |node, value| node.evaluate_script('this.validity.valid') == value }
|
181
|
+
node_filter(:name) { |node, value| !value.is_a?(Regexp) || value.match?(node[:name]) }
|
182
|
+
node_filter(:placeholder) { |node, value| !value.is_a?(Regexp) || value.match?(node[:placeholder]) }
|
183
|
+
node_filter(:validation_message) do |node, msg|
|
184
|
+
vm = node[:validationMessage]
|
185
|
+
(msg.is_a?(Regexp) ? msg.match?(vm) : vm == msg.to_s).tap do |res|
|
186
|
+
add_error("Expected validation message to be #{msg.inspect} but was #{vm}") unless res
|
187
|
+
end
|
188
|
+
end
|
169
189
|
|
170
|
-
expression_filter(:name)
|
171
|
-
|
190
|
+
expression_filter(:name) do |xpath, val|
|
191
|
+
builder(xpath).add_attribute_conditions(name: val)
|
192
|
+
end
|
193
|
+
expression_filter(:placeholder) do |xpath, val|
|
194
|
+
builder(xpath).add_attribute_conditions(placeholder: val)
|
195
|
+
end
|
172
196
|
expression_filter(:disabled) { |xpath, val| val ? xpath : xpath[~XPath.attr(:disabled)] }
|
173
197
|
expression_filter(:multiple) { |xpath, val| xpath[val ? XPath.attr(:multiple) : ~XPath.attr(:multiple)] }
|
174
198
|
|
@@ -182,12 +206,15 @@ Capybara::Selector::FilterSet.add(:_field) do
|
|
182
206
|
desc
|
183
207
|
end
|
184
208
|
|
185
|
-
describe(:node_filters) do |checked: nil, unchecked: nil, disabled: nil, **|
|
209
|
+
describe(:node_filters) do |checked: nil, unchecked: nil, disabled: nil, valid: nil, validation_message: nil, **|
|
186
210
|
desc, states = +'', []
|
187
211
|
states << 'checked' if checked || (unchecked == false)
|
188
212
|
states << 'not checked' if unchecked || (checked == false)
|
189
213
|
states << 'disabled' if disabled == true
|
190
214
|
desc << " that is #{states.join(' and ')}" unless states.empty?
|
215
|
+
desc << ' that is valid' if valid == true
|
216
|
+
desc << ' that is invalid' if valid == false
|
217
|
+
desc << " with validation message #{validation_message.to_s.inspect}" if validation_message
|
191
218
|
desc
|
192
219
|
end
|
193
220
|
end
|
@@ -17,11 +17,7 @@ module Capybara
|
|
17
17
|
conditions = if name == :class
|
18
18
|
class_conditions(value)
|
19
19
|
elsif value.is_a? Regexp
|
20
|
-
|
21
|
-
strs.map do |str|
|
22
|
-
"[#{name}*='#{str}'#{' i' if value.casefold?}]"
|
23
|
-
end.join
|
24
|
-
end
|
20
|
+
regexp_conditions(name, value)
|
25
21
|
else
|
26
22
|
[attribute_conditions(name => value)]
|
27
23
|
end
|
@@ -36,6 +32,14 @@ module Capybara
|
|
36
32
|
|
37
33
|
private
|
38
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
|
+
|
39
43
|
def attribute_conditions(attributes)
|
40
44
|
attributes.map do |attribute, value|
|
41
45
|
case value
|
@@ -70,7 +74,7 @@ module Capybara
|
|
70
74
|
end.join
|
71
75
|
end
|
72
76
|
else
|
73
|
-
cls = Array(classes).
|
77
|
+
cls = Array(classes).reject { |c| c.is_a? Regexp }.group_by { |cl| cl.match?(/^!(?!!!)/) }
|
74
78
|
[(cls[false].to_a.map { |cl| ".#{Capybara::Selector::CSS.escape(cl.sub(/^!!/, ''))}" } +
|
75
79
|
cls[true].to_a.map { |cl| ":not(.#{Capybara::Selector::CSS.escape(cl.slice(1..-1))})" }).join]
|
76
80
|
end
|
@@ -15,6 +15,8 @@ module Capybara
|
|
15
15
|
def add_attribute_conditions(**conditions)
|
16
16
|
@expression = conditions.inject(expression) do |xp, (name, value)|
|
17
17
|
conditions = name == :class ? class_conditions(value) : attribute_conditions(name => value)
|
18
|
+
return xp if conditions.nil?
|
19
|
+
|
18
20
|
if xp.is_a? XPath::Expression
|
19
21
|
xp[conditions]
|
20
22
|
else
|
@@ -47,8 +49,8 @@ module Capybara
|
|
47
49
|
when XPath::Expression, Regexp
|
48
50
|
attribute_conditions(class: classes)
|
49
51
|
else
|
50
|
-
Array(classes).map do |klass|
|
51
|
-
if klass.
|
52
|
+
Array(classes).reject { |c| c.is_a? Regexp }.map do |klass|
|
53
|
+
if klass.match?(/^!(?!!!)/)
|
52
54
|
!XPath.attr(:class).contains_word(klass.slice(1..-1))
|
53
55
|
else
|
54
56
|
XPath.attr(:class).contains_word(klass.sub(/^!!/, ''))
|
@@ -10,11 +10,12 @@ module Capybara
|
|
10
10
|
class Selector
|
11
11
|
class Definition
|
12
12
|
attr_reader :name, :expressions
|
13
|
+
|
13
14
|
extend Forwardable
|
14
15
|
|
15
16
|
def initialize(name, locator_type: nil, raw_locator: false, supports_exact: nil, &block)
|
16
17
|
@name = name
|
17
|
-
@filter_set = Capybara::Selector::FilterSet.add(name)
|
18
|
+
@filter_set = Capybara::Selector::FilterSet.add(name)
|
18
19
|
@match = nil
|
19
20
|
@label = nil
|
20
21
|
@failure_message = nil
|
@@ -82,7 +83,7 @@ module Capybara
|
|
82
83
|
# Automatic selector detection
|
83
84
|
#
|
84
85
|
# @yield [locator] This block takes the passed in locator string and returns whether or not it matches the selector
|
85
|
-
# @yieldparam [String], locator The locator string used to
|
86
|
+
# @yieldparam [String], locator The locator string used to determine if it matches the selector
|
86
87
|
# @yieldreturn [Boolean] Whether this selector matches the locator string
|
87
88
|
# @return [#call] The block that will be used to detect selector match
|
88
89
|
#
|
@@ -166,7 +167,7 @@ module Capybara
|
|
166
167
|
|
167
168
|
def locator_filter(*types, **options, &block)
|
168
169
|
types.each { |type| options[type] = true }
|
169
|
-
@locator_filter = Capybara::Selector::Filters::LocatorFilter.new(block, options) if block
|
170
|
+
@locator_filter = Capybara::Selector::Filters::LocatorFilter.new(block, **options) if block
|
170
171
|
@locator_filter
|
171
172
|
end
|
172
173
|
|
@@ -177,11 +178,11 @@ module Capybara
|
|
177
178
|
def_delegator :@filter_set, :describe
|
178
179
|
|
179
180
|
def describe_expression_filters(&block)
|
180
|
-
if
|
181
|
+
if block
|
181
182
|
describe(:expression_filters, &block)
|
182
183
|
else
|
183
184
|
describe(:expression_filters) do |**options|
|
184
|
-
describe_all_expression_filters(options)
|
185
|
+
describe_all_expression_filters(**options)
|
185
186
|
end
|
186
187
|
end
|
187
188
|
end
|
@@ -189,7 +190,7 @@ module Capybara
|
|
189
190
|
def describe_all_expression_filters(**opts)
|
190
191
|
expression_filters.map do |ef_name, ef|
|
191
192
|
if ef.matcher?
|
192
|
-
|
193
|
+
handled_custom_options(ef, opts).map { |option, value| " with #{ef_name}[#{option} => #{value}]" }.join
|
193
194
|
elsif opts.key?(ef_name)
|
194
195
|
" with #{ef_name} #{opts[ef_name]}"
|
195
196
|
end
|
@@ -214,7 +215,7 @@ module Capybara
|
|
214
215
|
end
|
215
216
|
|
216
217
|
def default_visibility(fallback = Capybara.ignore_hidden_elements, options = {})
|
217
|
-
vis = if @default_visibility
|
218
|
+
vis = if @default_visibility.respond_to?(:call)
|
218
219
|
@default_visibility.call(options)
|
219
220
|
else
|
220
221
|
@default_visibility
|
@@ -251,14 +252,15 @@ module Capybara
|
|
251
252
|
|
252
253
|
private
|
253
254
|
|
254
|
-
def
|
255
|
-
|
256
|
-
filter.handles_option?(
|
255
|
+
def handled_custom_options(filter, options)
|
256
|
+
options.select do |option, _|
|
257
|
+
filter.handles_option?(option) && !::Capybara::Queries::SelectorQuery::VALID_KEYS.include?(option)
|
257
258
|
end
|
258
259
|
end
|
259
260
|
|
260
261
|
def parameter_names(block)
|
261
|
-
|
262
|
+
key_types = %i[key keyreq]
|
263
|
+
block.parameters.select { |(type, _name)| key_types.include? type }.map { |(_type, name)| name }
|
262
264
|
end
|
263
265
|
|
264
266
|
def expression(type, allowed_filters, &block)
|