capybara 3.29.0 → 3.30.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 +19 -1
- data/README.md +1 -1
- data/lib/capybara/config.rb +7 -3
- data/lib/capybara/helpers.rb +3 -1
- data/lib/capybara/node/actions.rb +23 -19
- data/lib/capybara/node/document.rb +2 -2
- data/lib/capybara/node/document_matchers.rb +3 -3
- data/lib/capybara/node/element.rb +10 -8
- data/lib/capybara/node/finders.rb +12 -10
- data/lib/capybara/node/matchers.rb +39 -33
- data/lib/capybara/node/simple.rb +3 -1
- data/lib/capybara/queries/ancestor_query.rb +1 -1
- data/lib/capybara/queries/selector_query.rb +17 -4
- data/lib/capybara/queries/sibling_query.rb +1 -1
- data/lib/capybara/rack_test/browser.rb +4 -1
- data/lib/capybara/rack_test/driver.rb +1 -1
- data/lib/capybara/rack_test/form.rb +1 -1
- data/lib/capybara/selector.rb +22 -16
- data/lib/capybara/selector/css.rb +1 -1
- data/lib/capybara/selector/definition.rb +2 -2
- data/lib/capybara/selector/definition/button.rb +7 -2
- 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 +1 -1
- data/lib/capybara/selector/definition/datalist_option.rb +1 -1
- data/lib/capybara/selector/definition/element.rb +1 -1
- 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 +1 -1
- data/lib/capybara/selector/definition/label.rb +3 -1
- data/lib/capybara/selector/definition/radio_button.rb +2 -2
- data/lib/capybara/selector/definition/select.rb +1 -1
- data/lib/capybara/selector/definition/table.rb +5 -2
- data/lib/capybara/selector/filter_set.rb +11 -9
- data/lib/capybara/selector/filters/base.rb +6 -1
- data/lib/capybara/selector/filters/locator_filter.rb +1 -1
- data/lib/capybara/selector/selector.rb +4 -2
- data/lib/capybara/selenium/driver.rb +19 -11
- data/lib/capybara/selenium/driver_specializations/firefox_driver.rb +2 -2
- data/lib/capybara/selenium/extensions/html5_drag.rb +6 -5
- data/lib/capybara/selenium/node.rb +6 -4
- data/lib/capybara/selenium/nodes/chrome_node.rb +7 -3
- data/lib/capybara/selenium/nodes/edge_node.rb +3 -1
- data/lib/capybara/selenium/nodes/firefox_node.rb +1 -1
- data/lib/capybara/server.rb +15 -3
- data/lib/capybara/server/checker.rb +1 -1
- data/lib/capybara/server/middleware.rb +20 -10
- data/lib/capybara/session.rb +10 -8
- data/lib/capybara/session/config.rb +6 -2
- data/lib/capybara/session/matchers.rb +6 -6
- data/lib/capybara/spec/public/test.js +11 -0
- data/lib/capybara/spec/session/all_spec.rb +15 -0
- data/lib/capybara/spec/session/ancestor_spec.rb +5 -0
- data/lib/capybara/spec/session/assert_text_spec.rb +4 -0
- data/lib/capybara/spec/session/click_button_spec.rb +5 -0
- data/lib/capybara/spec/session/find_spec.rb +20 -0
- data/lib/capybara/spec/session/has_table_spec.rb +51 -5
- data/lib/capybara/spec/session/has_text_spec.rb +31 -0
- data/lib/capybara/spec/session/node_spec.rb +15 -0
- data/lib/capybara/spec/session/save_and_open_screenshot_spec.rb +2 -2
- data/lib/capybara/spec/session/save_screenshot_spec.rb +4 -4
- data/lib/capybara/spec/session/selectors_spec.rb +15 -2
- data/lib/capybara/spec/views/form.erb +5 -0
- data/lib/capybara/version.rb +1 -1
- data/spec/dsl_spec.rb +2 -2
- data/spec/minitest_spec_spec.rb +46 -46
- data/spec/regexp_dissassembler_spec.rb +45 -37
- data/spec/result_spec.rb +3 -3
- data/spec/rspec/features_spec.rb +1 -0
- data/spec/rspec/shared_spec_matchers.rb +3 -3
- data/spec/rspec_spec.rb +4 -4
- data/spec/selenium_spec_chrome.rb +3 -3
- data/spec/selenium_spec_firefox.rb +7 -2
- data/spec/server_spec.rb +42 -0
- data/spec/session_spec.rb +1 -1
- data/spec/shared_selenium_node.rb +3 -3
- data/spec/shared_selenium_session.rb +8 -7
- metadata +3 -3
data/lib/capybara/node/simple.rb
CHANGED
@@ -108,7 +108,9 @@ module Capybara
|
|
108
108
|
!find_xpath(VISIBILITY_XPATH)
|
109
109
|
else
|
110
110
|
# No need for an xpath if only checking the current element
|
111
|
-
!(native.key?('hidden') ||
|
111
|
+
!(native.key?('hidden') ||
|
112
|
+
/display:\s?none/.match?(native[:style] || '') ||
|
113
|
+
%w[script head].include?(tag_name))
|
112
114
|
end
|
113
115
|
end
|
114
116
|
|
@@ -12,7 +12,7 @@ module Capybara
|
|
12
12
|
ancestors = node.find_xpath(XPath.ancestor.to_s)
|
13
13
|
.map(&method(:to_element))
|
14
14
|
.select { |el| match_results.include?(el) }
|
15
|
-
Capybara::Result.new(ancestors, self)
|
15
|
+
Capybara::Result.new(ordered_results(ancestors), self)
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
@@ -16,11 +16,13 @@ module Capybara
|
|
16
16
|
enable_aria_label: session_options.enable_aria_label,
|
17
17
|
test_id: session_options.test_id,
|
18
18
|
selector_format: nil,
|
19
|
+
order: nil,
|
19
20
|
**options,
|
20
21
|
&filter_block)
|
21
22
|
@resolved_node = nil
|
22
23
|
@resolved_count = 0
|
23
24
|
@options = options.dup
|
25
|
+
@order = order
|
24
26
|
@filter_cache = Hash.new { |hsh, key| hsh[key] = {} }
|
25
27
|
|
26
28
|
super(@options)
|
@@ -37,7 +39,7 @@ module Capybara
|
|
37
39
|
|
38
40
|
raise ArgumentError, "Unused parameters passed to #{self.class.name} : #{args}" unless args.empty?
|
39
41
|
|
40
|
-
@expression = selector.call(@locator,
|
42
|
+
@expression = selector.call(@locator, **@options)
|
41
43
|
|
42
44
|
warn_exact_usage
|
43
45
|
|
@@ -77,7 +79,9 @@ module Capybara
|
|
77
79
|
end
|
78
80
|
|
79
81
|
%i[above below left_of right_of near].each do |spatial_filter|
|
80
|
-
|
82
|
+
if options[spatial_filter] && show_for[:spatial]
|
83
|
+
desc << " #{spatial_filter} #{options[spatial_filter] rescue '<ERROR>'}" # rubocop:disable Style/RescueModifier
|
84
|
+
end
|
81
85
|
end
|
82
86
|
|
83
87
|
desc << selector.description(node_filters: show_for[:node], **options)
|
@@ -148,7 +152,7 @@ module Capybara
|
|
148
152
|
|
149
153
|
node.synchronize do
|
150
154
|
children = find_nodes_by_selector_format(node, exact).map(&method(:to_element))
|
151
|
-
Capybara::Result.new(children, self)
|
155
|
+
Capybara::Result.new(ordered_results(children), self)
|
152
156
|
end
|
153
157
|
end
|
154
158
|
|
@@ -311,6 +315,15 @@ module Capybara
|
|
311
315
|
filters
|
312
316
|
end
|
313
317
|
|
318
|
+
def ordered_results(results)
|
319
|
+
case @order
|
320
|
+
when :reverse
|
321
|
+
results.reverse
|
322
|
+
else
|
323
|
+
results
|
324
|
+
end
|
325
|
+
end
|
326
|
+
|
314
327
|
def custom_keys
|
315
328
|
@custom_keys ||= node_filters.keys + expression_filters.keys
|
316
329
|
end
|
@@ -338,7 +351,7 @@ module Capybara
|
|
338
351
|
conditions[:id] = options[:id] if use_default_id_filter?
|
339
352
|
conditions[:class] = options[:class] if use_default_class_filter?
|
340
353
|
conditions[:style] = options[:style] if use_default_style_filter? && !options[:style].is_a?(Hash)
|
341
|
-
builder(expr).add_attribute_conditions(conditions)
|
354
|
+
builder(expr).add_attribute_conditions(**conditions)
|
342
355
|
end
|
343
356
|
|
344
357
|
def use_default_id_filter?
|
@@ -11,7 +11,7 @@ module Capybara
|
|
11
11
|
siblings = node.find_xpath((XPath.preceding_sibling + XPath.following_sibling).to_s)
|
12
12
|
.map(&method(:to_element))
|
13
13
|
.select { |el| match_results.include?(el) }
|
14
|
-
Capybara::Result.new(siblings, self)
|
14
|
+
Capybara::Result.new(ordered_results(siblings), self)
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
@@ -53,7 +53,10 @@ class Capybara::RackTest::Browser
|
|
53
53
|
end
|
54
54
|
end
|
55
55
|
end
|
56
|
-
|
56
|
+
|
57
|
+
if last_response.redirect? # rubocop:disable Style/GuardClause
|
58
|
+
raise Capybara::InfiniteRedirectError, "redirected more than #{driver.redirect_limit} times, check for infinite redirects."
|
59
|
+
end
|
57
60
|
end
|
58
61
|
|
59
62
|
def process(method, path, attributes = {}, env = {})
|
data/lib/capybara/selector.rb
CHANGED
@@ -30,8 +30,8 @@ require 'capybara/selector/definition'
|
|
30
30
|
# * Locator: Matches against the id, {Capybara.configure test_id} attribute, name, placeholder, or
|
31
31
|
# associated label text
|
32
32
|
# * Filters:
|
33
|
-
# * :name (String) - Matches the name attribute
|
34
|
-
# * :placeholder (String) - Matches the placeholder attribute
|
33
|
+
# * :name (String, Regexp) - Matches the name attribute
|
34
|
+
# * :placeholder (String, Regexp) - Matches the placeholder attribute
|
35
35
|
# * :type (String) - Matches the type attribute of the field or element type for 'textarea' and 'select'
|
36
36
|
# * :readonly (Boolean) - Match on the element being readonly
|
37
37
|
# * :with (String, Regexp) - Matches the current value of the field
|
@@ -58,7 +58,7 @@ require 'capybara/selector/definition'
|
|
58
58
|
# * **:button** - Find buttons ( input [of type submit, reset, image, button] or button elements )
|
59
59
|
# * 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
|
60
60
|
# * Filters:
|
61
|
-
# * :name (String) - Matches the name attribute
|
61
|
+
# * :name (String, Regexp) - Matches the name attribute
|
62
62
|
# * :title (String) - Matches the title attribute
|
63
63
|
# * :value (String) - Matches the value of an input button
|
64
64
|
# * :type (String) - Matches the type attribute
|
@@ -72,8 +72,8 @@ require 'capybara/selector/definition'
|
|
72
72
|
# * **:fillable_field** - Find text fillable fields ( textarea, input [not of type submit, image, radio, checkbox, hidden, file] )
|
73
73
|
# * Locator: Matches against the id, {Capybara.configure test_id} attribute, name, placeholder, or associated label text
|
74
74
|
# * Filters:
|
75
|
-
# * :name (String) - Matches the name attribute
|
76
|
-
# * :placeholder (String) - Matches the placeholder attribute
|
75
|
+
# * :name (String, Regexp) - Matches the name attribute
|
76
|
+
# * :placeholder (String, Regexp) - Matches the placeholder attribute
|
77
77
|
# * :with (String, Regexp) - Matches the current value of the field
|
78
78
|
# * :type (String) - Matches the type attribute of the field or element type for 'textarea'
|
79
79
|
# * :disabled (Boolean, :all) - Match disabled field? (Default: false)
|
@@ -83,7 +83,7 @@ require 'capybara/selector/definition'
|
|
83
83
|
# * **:radio_button** - Find radio buttons
|
84
84
|
# * Locator: Match id, {Capybara.configure test_id} attribute, name, or associated label text
|
85
85
|
# * Filters:
|
86
|
-
# * :name (String) - Matches the name attribute
|
86
|
+
# * :name (String, Regexp) - Matches the name attribute
|
87
87
|
# * :checked (Boolean) - Match checked fields?
|
88
88
|
# * :unchecked (Boolean) - Match unchecked fields?
|
89
89
|
# * :disabled (Boolean, :all) - Match disabled field? (Default: false)
|
@@ -93,18 +93,18 @@ require 'capybara/selector/definition'
|
|
93
93
|
# * **:checkbox** - Find checkboxes
|
94
94
|
# * Locator: Match id, {Capybara.configure test_id} attribute, name, or associated label text
|
95
95
|
# * Filters:
|
96
|
-
# * :name (String) - Matches the name attribute
|
96
|
+
# * :name (String, Regexp) - Matches the name attribute
|
97
97
|
# * :checked (Boolean) - Match checked fields?
|
98
98
|
# * :unchecked (Boolean) - Match unchecked fields?
|
99
99
|
# * :disabled (Boolean, :all) - Match disabled field? (Default: false)
|
100
|
-
# * :
|
101
|
-
# * :
|
100
|
+
# * :with (String, Regexp) - Match the current value
|
101
|
+
# * :option - Alias of :with
|
102
102
|
#
|
103
103
|
# * **:select** - Find select elements
|
104
104
|
# * Locator: Match id, {Capybara.configure test_id} attribute, name, placeholder, or associated label text
|
105
105
|
# * Filters:
|
106
|
-
# * :name (String) - Matches the name attribute
|
107
|
-
# * :placeholder (String) - Matches the placeholder attribute
|
106
|
+
# * :name (String, Regexp) - Matches the name attribute
|
107
|
+
# * :placeholder (String, Placeholder) - Matches the placeholder attribute
|
108
108
|
# * :disabled (Boolean, :all) - Match disabled field? (Default: false)
|
109
109
|
# * :multiple (Boolean) - Match fields that accept multiple values
|
110
110
|
# * :options (Array<String>) - Exact match options
|
@@ -122,8 +122,8 @@ require 'capybara/selector/definition'
|
|
122
122
|
# * Locator: Matches against the id, {Capybara.configure test_id} attribute, name,
|
123
123
|
# placeholder, or associated label text
|
124
124
|
# * Filters:
|
125
|
-
# * :name (String) - Matches the name attribute
|
126
|
-
# * :placeholder (String) - Matches the placeholder attribute
|
125
|
+
# * :name (String, Regexp) - Matches the name attribute
|
126
|
+
# * :placeholder (String, Regexp) - Matches the placeholder attribute
|
127
127
|
# * :disabled (Boolean, :all) - Match disabled field? (Default: false)
|
128
128
|
# * :options (Array<String>) - Exact match options
|
129
129
|
# * :with_options (Array<String>) - Partial match options
|
@@ -136,7 +136,7 @@ require 'capybara/selector/definition'
|
|
136
136
|
# * **:file_field** - Find file input elements
|
137
137
|
# * Locator: Match id, {Capybara.configure test_id} attribute, name, or associated label text
|
138
138
|
# * Filters:
|
139
|
-
# * :name (String) - Matches the name attribute
|
139
|
+
# * :name (String, Regexp) - Matches the name attribute
|
140
140
|
# * :disabled (Boolean, :all) - Match disabled field? (Default: false)
|
141
141
|
# * :multiple (Boolean) - Match field that accepts multiple values
|
142
142
|
#
|
@@ -174,9 +174,15 @@ Capybara::Selector::FilterSet.add(:_field) do
|
|
174
174
|
node_filter(:unchecked, :boolean) { |node, value| (value ^ node.checked?) }
|
175
175
|
node_filter(:disabled, :boolean, default: false, skip_if: :all) { |node, value| !(value ^ node.disabled?) }
|
176
176
|
node_filter(:valid, :boolean) { |node, value| node.evaluate_script('this.validity.valid') == value }
|
177
|
+
node_filter(:name) { |node, value| !value.is_a?(Regexp) || value.match?(node[:name]) }
|
178
|
+
node_filter(:placeholder) { |node, value| !value.is_a?(Regexp) || value.match?(node[:placeholder]) }
|
177
179
|
|
178
|
-
expression_filter(:name)
|
179
|
-
|
180
|
+
expression_filter(:name) do |xpath, val|
|
181
|
+
builder(xpath).add_attribute_conditions(name: val)
|
182
|
+
end
|
183
|
+
expression_filter(:placeholder) do |xpath, val|
|
184
|
+
builder(xpath).add_attribute_conditions(placeholder: val)
|
185
|
+
end
|
180
186
|
expression_filter(:disabled) { |xpath, val| val ? xpath : xpath[~XPath.attr(:disabled)] }
|
181
187
|
expression_filter(:multiple) { |xpath, val| xpath[val ? XPath.attr(:multiple) : ~XPath.attr(:multiple)] }
|
182
188
|
|
@@ -166,7 +166,7 @@ module Capybara
|
|
166
166
|
|
167
167
|
def locator_filter(*types, **options, &block)
|
168
168
|
types.each { |type| options[type] = true }
|
169
|
-
@locator_filter = Capybara::Selector::Filters::LocatorFilter.new(block, options) if block
|
169
|
+
@locator_filter = Capybara::Selector::Filters::LocatorFilter.new(block, **options) if block
|
170
170
|
@locator_filter
|
171
171
|
end
|
172
172
|
|
@@ -181,7 +181,7 @@ module Capybara
|
|
181
181
|
describe(:expression_filters, &block)
|
182
182
|
else
|
183
183
|
describe(:expression_filters) do |**options|
|
184
|
-
describe_all_expression_filters(options)
|
184
|
+
describe_all_expression_filters(**options)
|
185
185
|
end
|
186
186
|
end
|
187
187
|
end
|
@@ -26,7 +26,7 @@ Capybara.add_selector(:button, locator_type: [String, Symbol]) do
|
|
26
26
|
image_btn_xpath = image_btn_xpath[alt_matches]
|
27
27
|
end
|
28
28
|
|
29
|
-
%i[value title type
|
29
|
+
%i[value title type].inject(input_btn_xpath.union(btn_xpath).union(image_btn_xpath)) do |memo, ef|
|
30
30
|
memo[find_by_attr(ef, options[ef])]
|
31
31
|
end
|
32
32
|
end
|
@@ -34,10 +34,15 @@ Capybara.add_selector(:button, locator_type: [String, Symbol]) do
|
|
34
34
|
node_filter(:disabled, :boolean, default: false, skip_if: :all) { |node, value| !(value ^ node.disabled?) }
|
35
35
|
expression_filter(:disabled) { |xpath, val| val ? xpath : xpath[~XPath.attr(:disabled)] }
|
36
36
|
|
37
|
+
node_filter(:name) { |node, value| !value.is_a?(Regexp) || value.match?(node[:name]) }
|
38
|
+
expression_filter(:name) do |xpath, val|
|
39
|
+
builder(xpath).add_attribute_conditions(name: val)
|
40
|
+
end
|
41
|
+
|
37
42
|
describe_expression_filters do |disabled: nil, **options|
|
38
43
|
desc = +''
|
39
44
|
desc << ' that is not disabled' if disabled == false
|
40
|
-
desc << describe_all_expression_filters(options)
|
45
|
+
desc << describe_all_expression_filters(**options)
|
41
46
|
end
|
42
47
|
|
43
48
|
describe_node_filters do |disabled: nil, **|
|
@@ -5,7 +5,7 @@ Capybara.add_selector(:checkbox, locator_type: [String, Symbol]) do
|
|
5
5
|
xpath = XPath.axis(allow_self ? :"descendant-or-self" : :descendant, :input)[
|
6
6
|
XPath.attr(:type) == 'checkbox'
|
7
7
|
]
|
8
|
-
locate_field(xpath, locator, options)
|
8
|
+
locate_field(xpath, locator, **options)
|
9
9
|
end
|
10
10
|
|
11
11
|
filter_set(:_field, %i[checked unchecked disabled name])
|
@@ -20,7 +20,7 @@ Capybara.add_selector(:checkbox, locator_type: [String, Symbol]) do
|
|
20
20
|
describe_node_filters do |option: nil, with: nil, **|
|
21
21
|
desc = +''
|
22
22
|
desc << " with value #{option.inspect}" if option
|
23
|
-
desc << " with value #{with.
|
23
|
+
desc << " with value #{with.inspect}" if with
|
24
24
|
desc
|
25
25
|
end
|
26
26
|
end
|
@@ -2,7 +2,9 @@
|
|
2
2
|
|
3
3
|
Capybara.add_selector(:css, locator_type: [String, Symbol], raw_locator: true) do
|
4
4
|
css do |css|
|
5
|
-
|
5
|
+
if css.is_a? Symbol
|
6
|
+
warn "DEPRECATED: Passing a symbol (#{css.inspect}) as the CSS locator is deprecated - please pass a string instead."
|
7
|
+
end
|
6
8
|
css
|
7
9
|
end
|
8
10
|
end
|
@@ -5,7 +5,7 @@ Capybara.add_selector(:datalist_input, locator_type: [String, Symbol]) do
|
|
5
5
|
|
6
6
|
xpath do |locator, **options|
|
7
7
|
xpath = XPath.descendant(:input)[XPath.attr(:list)]
|
8
|
-
locate_field(xpath, locator, options)
|
8
|
+
locate_field(xpath, locator, **options)
|
9
9
|
end
|
10
10
|
|
11
11
|
filter_set(:_field, %i[disabled name placeholder])
|
@@ -16,7 +16,7 @@ Capybara.add_selector(:datalist_option, locator_type: [String, Symbol]) do
|
|
16
16
|
describe_expression_filters do |disabled: nil, **options|
|
17
17
|
desc = +''
|
18
18
|
desc << ' that is not disabled' if disabled == false
|
19
|
-
desc << describe_all_expression_filters(options)
|
19
|
+
desc << describe_all_expression_filters(**options)
|
20
20
|
end
|
21
21
|
|
22
22
|
describe_node_filters do |**options|
|
@@ -19,7 +19,7 @@ Capybara.add_selector(:element, locator_type: [String, Symbol]) do
|
|
19
19
|
|
20
20
|
describe_expression_filters do |**options|
|
21
21
|
booleans, values = options.partition { |_k, v| [true, false].include? v }.map(&:to_h)
|
22
|
-
desc = describe_all_expression_filters(values)
|
22
|
+
desc = describe_all_expression_filters(**values)
|
23
23
|
desc + booleans.map do |k, v|
|
24
24
|
v ? " with #{k} attribute" : "without #{k} attribute"
|
25
25
|
end.join
|
@@ -7,7 +7,7 @@ Capybara.add_selector(:field, locator_type: [String, Symbol]) do
|
|
7
7
|
invalid_types = %w[submit image]
|
8
8
|
invalid_types << 'hidden' unless options[:type].to_s == 'hidden'
|
9
9
|
xpath = XPath.descendant(:input, :textarea, :select)[!XPath.attr(:type).one_of(*invalid_types)]
|
10
|
-
locate_field(xpath, locator, options)
|
10
|
+
locate_field(xpath, locator, **options)
|
11
11
|
end
|
12
12
|
|
13
13
|
expression_filter(:type) do |expr, type|
|
@@ -6,7 +6,7 @@ Capybara.add_selector(:file_field, locator_type: [String, Symbol]) do
|
|
6
6
|
xpath = XPath.axis(allow_self ? :"descendant-or-self" : :descendant, :input)[
|
7
7
|
XPath.attr(:type) == 'file'
|
8
8
|
]
|
9
|
-
locate_field(xpath, locator, options)
|
9
|
+
locate_field(xpath, locator, **options)
|
10
10
|
end
|
11
11
|
|
12
12
|
filter_set(:_field, %i[disabled multiple name])
|
@@ -6,7 +6,7 @@ Capybara.add_selector(:fillable_field, locator_type: [String, Symbol]) do
|
|
6
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
|
-
locate_field(xpath, locator, options)
|
9
|
+
locate_field(xpath, locator, **options)
|
10
10
|
end
|
11
11
|
|
12
12
|
expression_filter(:type) do |expr, type|
|
@@ -10,7 +10,9 @@ Capybara.add_selector(:label, locator_type: [String, Symbol]) do
|
|
10
10
|
xpath = xpath[locator_matchers]
|
11
11
|
end
|
12
12
|
if options.key?(:for)
|
13
|
-
|
13
|
+
for_option = options[:for]
|
14
|
+
for_option = for_option[:id] if for_option.is_a?(Capybara::Node::Element)
|
15
|
+
if for_option && (for_option != '')
|
14
16
|
with_attr = builder(XPath.self).add_attribute_conditions(for: for_option)
|
15
17
|
wrapped = !XPath.attr(:for) &
|
16
18
|
builder(XPath.self.descendant(*labelable_elements)).add_attribute_conditions(id: for_option)
|
@@ -6,7 +6,7 @@ Capybara.add_selector(:radio_button, locator_type: [String, Symbol]) do
|
|
6
6
|
xpath = XPath.axis(allow_self ? :"descendant-or-self" : :descendant, :input)[
|
7
7
|
XPath.attr(:type) == 'radio'
|
8
8
|
]
|
9
|
-
locate_field(xpath, locator, options)
|
9
|
+
locate_field(xpath, locator, **options)
|
10
10
|
end
|
11
11
|
|
12
12
|
filter_set(:_field, %i[checked unchecked disabled name])
|
@@ -21,7 +21,7 @@ Capybara.add_selector(:radio_button, locator_type: [String, Symbol]) do
|
|
21
21
|
describe_node_filters do |option: nil, with: nil, **|
|
22
22
|
desc = +''
|
23
23
|
desc << " with value #{option.inspect}" if option
|
24
|
-
desc << " with value #{with.
|
24
|
+
desc << " with value #{with.inspect}" if with
|
25
25
|
desc
|
26
26
|
end
|
27
27
|
end
|
@@ -5,7 +5,7 @@ Capybara.add_selector(:select, locator_type: [String, Symbol]) do
|
|
5
5
|
|
6
6
|
xpath do |locator, **options|
|
7
7
|
xpath = XPath.descendant(:select)
|
8
|
-
locate_field(xpath, locator, options)
|
8
|
+
locate_field(xpath, locator, **options)
|
9
9
|
end
|
10
10
|
|
11
11
|
filter_set(:_field, %i[disabled multiple name placeholder])
|
@@ -19,7 +19,10 @@ Capybara.add_selector(:table, locator_type: [String, Symbol]) do
|
|
19
19
|
header = XPath.descendant(:th)[XPath.string.n.is(header)]
|
20
20
|
td = XPath.descendant(:tr)[header].descendant(:td)
|
21
21
|
cell_condition = XPath.string.n.is(cell_str)
|
22
|
-
|
22
|
+
if xp
|
23
|
+
prev_cell = XPath.ancestor(:table)[1].join(xp)
|
24
|
+
cell_condition &= (prev_cell & prev_col_position?(prev_cell))
|
25
|
+
end
|
23
26
|
td[cell_condition]
|
24
27
|
end
|
25
28
|
else
|
@@ -28,7 +31,7 @@ Capybara.add_selector(:table, locator_type: [String, Symbol]) do
|
|
28
31
|
|
29
32
|
if prev_cell
|
30
33
|
prev_cell = XPath.ancestor(:tr)[1].preceding_sibling(:tr).join(prev_cell)
|
31
|
-
cell_condition &= prev_col_position?(prev_cell)
|
34
|
+
cell_condition &= (prev_cell & prev_col_position?(prev_cell))
|
32
35
|
end
|
33
36
|
|
34
37
|
XPath.descendant(:td)[cell_condition]
|
@@ -15,15 +15,15 @@ module Capybara
|
|
15
15
|
instance_eval(&block)
|
16
16
|
end
|
17
17
|
|
18
|
-
def node_filter(names, *
|
18
|
+
def node_filter(names, *types, **options, &block)
|
19
19
|
Array(names).each do |name|
|
20
|
-
add_filter(name, Filters::NodeFilter, *
|
20
|
+
add_filter(name, Filters::NodeFilter, *types, **options, &block)
|
21
21
|
end
|
22
22
|
end
|
23
23
|
alias_method :filter, :node_filter
|
24
24
|
|
25
|
-
def expression_filter(name, *
|
26
|
-
add_filter(name, Filters::ExpressionFilter, *
|
25
|
+
def expression_filter(name, *types, **options, &block)
|
26
|
+
add_filter(name, Filters::ExpressionFilter, *types, **options, &block)
|
27
27
|
end
|
28
28
|
|
29
29
|
def describe(what = nil, &block)
|
@@ -42,9 +42,9 @@ module Capybara
|
|
42
42
|
def description(node_filters: true, expression_filters: true, **options)
|
43
43
|
opts = options_with_defaults(options)
|
44
44
|
description = +''
|
45
|
-
description << undeclared_descriptions.map { |desc| desc.call(opts).to_s }.join
|
46
|
-
description << expression_filter_descriptions.map { |desc| desc.call(opts).to_s }.join if expression_filters
|
47
|
-
description << node_filter_descriptions.map { |desc| desc.call(opts).to_s }.join if node_filters
|
45
|
+
description << undeclared_descriptions.map { |desc| desc.call(**opts).to_s }.join
|
46
|
+
description << expression_filter_descriptions.map { |desc| desc.call(**opts).to_s }.join if expression_filters
|
47
|
+
description << node_filter_descriptions.map { |desc| desc.call(**opts).to_s }.join if node_filters
|
48
48
|
description
|
49
49
|
end
|
50
50
|
|
@@ -112,9 +112,11 @@ module Capybara
|
|
112
112
|
|
113
113
|
def add_filter(name, filter_class, *types, matcher: nil, **options, &block)
|
114
114
|
types.each { |type| options[type] = true }
|
115
|
-
|
115
|
+
if matcher && options[:default]
|
116
|
+
raise 'ArgumentError', ':default option is not supported for filters with a :matcher option'
|
117
|
+
end
|
116
118
|
|
117
|
-
filter = filter_class.new(name, matcher, block, options)
|
119
|
+
filter = filter_class.new(name, matcher, block, **options)
|
118
120
|
(filter_class <= Filters::ExpressionFilter ? @expression_filters : @node_filters)[name] = filter
|
119
121
|
end
|
120
122
|
end
|