capybara 3.32.0 → 3.35.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 +99 -15
- data/README.md +9 -4
- data/lib/capybara.rb +18 -8
- data/lib/capybara/config.rb +4 -6
- data/lib/capybara/cucumber.rb +1 -1
- data/lib/capybara/driver/base.rb +4 -0
- data/lib/capybara/helpers.rb +25 -1
- data/lib/capybara/minitest.rb +2 -3
- data/lib/capybara/minitest/spec.rb +14 -11
- data/lib/capybara/node/actions.rb +16 -21
- data/lib/capybara/node/base.rb +6 -6
- data/lib/capybara/node/element.rb +1 -5
- data/lib/capybara/node/finders.rb +7 -6
- data/lib/capybara/node/matchers.rb +12 -12
- data/lib/capybara/node/simple.rb +5 -1
- data/lib/capybara/queries/ancestor_query.rb +1 -1
- data/lib/capybara/queries/current_path_query.rb +14 -4
- data/lib/capybara/queries/selector_query.rb +40 -18
- data/lib/capybara/queries/sibling_query.rb +1 -1
- data/lib/capybara/queries/style_query.rb +1 -1
- data/lib/capybara/queries/text_query.rb +7 -1
- data/lib/capybara/rack_test/browser.rb +7 -3
- data/lib/capybara/rack_test/driver.rb +1 -0
- data/lib/capybara/rack_test/form.rb +1 -1
- data/lib/capybara/rack_test/node.rb +1 -1
- data/lib/capybara/registration_container.rb +44 -0
- data/lib/capybara/registrations/drivers.rb +18 -12
- data/lib/capybara/registrations/patches/puma_ssl.rb +3 -1
- data/lib/capybara/registrations/servers.rb +3 -2
- data/lib/capybara/result.rb +10 -11
- data/lib/capybara/rspec.rb +2 -0
- data/lib/capybara/rspec/matcher_proxies.rb +1 -1
- data/lib/capybara/rspec/matchers.rb +7 -6
- data/lib/capybara/rspec/matchers/have_current_path.rb +2 -2
- data/lib/capybara/rspec/matchers/have_text.rb +1 -1
- data/lib/capybara/rspec/matchers/match_style.rb +5 -0
- data/lib/capybara/selector.rb +12 -3
- data/lib/capybara/selector/builders/css_builder.rb +1 -1
- data/lib/capybara/selector/builders/xpath_builder.rb +3 -1
- data/lib/capybara/selector/definition.rb +11 -9
- data/lib/capybara/selector/definition/button.rb +26 -14
- data/lib/capybara/selector/definition/css.rb +1 -1
- data/lib/capybara/selector/definition/datalist_input.rb +1 -1
- data/lib/capybara/selector/definition/element.rb +2 -1
- data/lib/capybara/selector/definition/fillable_field.rb +1 -1
- data/lib/capybara/selector/definition/label.rb +1 -1
- data/lib/capybara/selector/definition/link.rb +8 -0
- data/lib/capybara/selector/definition/select.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/filter_set.rb +2 -2
- data/lib/capybara/selector/selector.rb +9 -1
- data/lib/capybara/selenium/atoms/src/isDisplayed.js +1 -1
- data/lib/capybara/selenium/driver.rb +51 -7
- data/lib/capybara/selenium/driver_specializations/chrome_driver.rb +9 -11
- data/lib/capybara/selenium/driver_specializations/edge_driver.rb +9 -11
- data/lib/capybara/selenium/driver_specializations/firefox_driver.rb +3 -3
- data/lib/capybara/selenium/extensions/find.rb +4 -4
- data/lib/capybara/selenium/extensions/scroll.rb +8 -10
- data/lib/capybara/selenium/logger_suppressor.rb +1 -1
- data/lib/capybara/selenium/node.rb +23 -6
- data/lib/capybara/selenium/nodes/chrome_node.rb +23 -5
- data/lib/capybara/selenium/nodes/firefox_node.rb +7 -2
- data/lib/capybara/selenium/nodes/safari_node.rb +1 -1
- data/lib/capybara/selenium/patches/action_pauser.rb +4 -1
- data/lib/capybara/selenium/patches/atoms.rb +4 -4
- data/lib/capybara/selenium/patches/logs.rb +7 -9
- data/lib/capybara/server/animation_disabler.rb +8 -3
- data/lib/capybara/server/middleware.rb +4 -2
- data/lib/capybara/session.rb +23 -14
- data/lib/capybara/session/config.rb +3 -1
- data/lib/capybara/session/matchers.rb +11 -11
- data/lib/capybara/spec/public/test.js +13 -1
- data/lib/capybara/spec/session/accept_alert_spec.rb +1 -1
- data/lib/capybara/spec/session/check_spec.rb +6 -0
- data/lib/capybara/spec/session/click_button_spec.rb +11 -0
- data/lib/capybara/spec/session/current_url_spec.rb +11 -1
- data/lib/capybara/spec/session/has_button_spec.rb +51 -0
- data/lib/capybara/spec/session/has_css_spec.rb +2 -1
- data/lib/capybara/spec/session/has_current_path_spec.rb +15 -2
- data/lib/capybara/spec/session/has_field_spec.rb +16 -0
- data/lib/capybara/spec/session/has_select_spec.rb +4 -4
- data/lib/capybara/spec/session/has_selector_spec.rb +4 -4
- data/lib/capybara/spec/session/has_text_spec.rb +0 -11
- 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 +29 -9
- data/lib/capybara/spec/session/refresh_spec.rb +2 -1
- data/lib/capybara/spec/session/save_page_spec.rb +4 -4
- 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 +1 -1
- data/lib/capybara/spec/session/window/windows_spec.rb +1 -1
- data/lib/capybara/spec/spec_helper.rb +12 -12
- data/lib/capybara/spec/test_app.rb +23 -21
- data/lib/capybara/spec/views/form.erb +28 -1
- data/lib/capybara/spec/views/with_animation.erb +8 -0
- data/lib/capybara/spec/views/with_dragula.erb +3 -1
- data/lib/capybara/spec/views/with_jquery_animation.erb +24 -0
- data/lib/capybara/spec/views/with_js.erb +3 -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 +9 -8
- data/spec/capybara_spec.rb +1 -1
- data/spec/dsl_spec.rb +14 -1
- data/spec/fixtures/selenium_driver_rspec_success.rb +1 -1
- data/spec/minitest_spec.rb +3 -2
- data/spec/rack_test_spec.rb +16 -5
- data/spec/result_spec.rb +1 -17
- data/spec/rspec/features_spec.rb +3 -1
- data/spec/rspec/scenarios_spec.rb +4 -0
- data/spec/rspec/shared_spec_matchers.rb +63 -51
- data/spec/rspec_spec.rb +4 -0
- data/spec/selector_spec.rb +17 -2
- data/spec/selenium_spec_chrome.rb +39 -20
- data/spec/selenium_spec_chrome_remote.rb +5 -1
- data/spec/selenium_spec_firefox.rb +15 -13
- data/spec/server_spec.rb +60 -49
- data/spec/shared_selenium_node.rb +10 -0
- data/spec/shared_selenium_session.rb +98 -7
- data/spec/spec_helper.rb +1 -1
- metadata +50 -15
- data/lib/capybara/spec/session/source_spec.rb +0 -0
@@ -209,13 +209,15 @@ module Capybara
|
|
209
209
|
# @!method wont_have_xpath
|
210
210
|
# See {Capybara::Node::Matchers#has_no_xpath?}
|
211
211
|
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
212
|
+
# This currently doesn't work for Ruby 2.8 due to Minitest not forwarding keyword args separately
|
213
|
+
# %w[text content title current_path].each do |assertion|
|
214
|
+
# infect_an_assertion "assert_#{assertion}", "must_have_#{assertion}", :reverse
|
215
|
+
# infect_an_assertion "refute_#{assertion}", "wont_have_#{assertion}", :reverse
|
216
|
+
# end
|
216
217
|
|
217
218
|
# rubocop:disable Style/MultilineBlockChain
|
218
|
-
(%w[
|
219
|
+
(%w[text content title current_path
|
220
|
+
selector xpath css link button field select table checked_field unchecked_field
|
219
221
|
ancestor sibling].flat_map do |assertion|
|
220
222
|
[%W[assert_#{assertion} must_have_#{assertion}],
|
221
223
|
%W[refute_#{assertion} wont_have_#{assertion}]]
|
@@ -228,14 +230,15 @@ module Capybara
|
|
228
230
|
%W[refute_matches_#{assertion} wont_match_#{assertion}]]
|
229
231
|
end).each do |(meth, new_name)|
|
230
232
|
class_eval <<-ASSERTION, __FILE__, __LINE__ + 1
|
231
|
-
def #{new_name} *args, &block
|
232
|
-
::Minitest::Expectation.new(self, ::Minitest::Spec.current).#{new_name}(*args, &block)
|
233
|
+
def #{new_name} *args, **kw_args, &block
|
234
|
+
::Minitest::Expectation.new(self, ::Minitest::Spec.current).#{new_name}(*args, **kw_args, &block)
|
233
235
|
end
|
234
236
|
ASSERTION
|
235
237
|
|
236
238
|
::Minitest::Expectation.class_eval <<-ASSERTION, __FILE__, __LINE__ + 1
|
237
|
-
def #{new_name} *args, &block
|
238
|
-
|
239
|
+
def #{new_name} *args, **kw_args, &block
|
240
|
+
raise "Calling ##{new_name} outside of test." unless ctx
|
241
|
+
ctx.#{meth}(target, *args, **kw_args, &block)
|
239
242
|
end
|
240
243
|
ASSERTION
|
241
244
|
end
|
@@ -243,9 +246,9 @@ module Capybara
|
|
243
246
|
|
244
247
|
##
|
245
248
|
# @deprecated
|
246
|
-
def must_have_style(*args, &block)
|
249
|
+
def must_have_style(*args, **kw_args, &block)
|
247
250
|
warn 'must_have_style is deprecated, please use must_match_style'
|
248
|
-
must_match_style(*args, &block)
|
251
|
+
must_match_style(*args, **kw_args, &block)
|
249
252
|
end
|
250
253
|
end
|
251
254
|
end
|
@@ -308,16 +308,14 @@ module Capybara
|
|
308
308
|
|
309
309
|
def find_select_or_datalist_input(from, options)
|
310
310
|
synchronize(Capybara::Queries::BaseQuery.wait(options, session_options.default_max_wait_time)) do
|
311
|
+
find(:select, from, **options)
|
312
|
+
rescue Capybara::ElementNotFound => select_error # rubocop:disable Naming/RescuedExceptionsVariableName
|
313
|
+
raise if %i[selected with_selected multiple].any? { |option| options.key?(option) }
|
314
|
+
|
311
315
|
begin
|
312
|
-
find(:
|
313
|
-
rescue Capybara::ElementNotFound =>
|
314
|
-
raise
|
315
|
-
|
316
|
-
begin
|
317
|
-
find(:datalist_input, from, **options)
|
318
|
-
rescue Capybara::ElementNotFound => dlinput_error # rubocop:disable Naming/RescuedExceptionsVariableName
|
319
|
-
raise Capybara::ElementNotFound, "#{select_error.message} and #{dlinput_error.message}"
|
320
|
-
end
|
316
|
+
find(:datalist_input, from, **options)
|
317
|
+
rescue Capybara::ElementNotFound => dlinput_error # rubocop:disable Naming/RescuedExceptionsVariableName
|
318
|
+
raise Capybara::ElementNotFound, "#{select_error.message} and #{dlinput_error.message}"
|
321
319
|
end
|
322
320
|
end
|
323
321
|
end
|
@@ -365,20 +363,17 @@ module Capybara
|
|
365
363
|
def _check_with_label(selector, checked, locator,
|
366
364
|
allow_label_click: session_options.automatic_label_click, **options)
|
367
365
|
options[:allow_self] = true if locator.nil?
|
368
|
-
|
369
366
|
synchronize(Capybara::Queries::BaseQuery.wait(options, session_options.default_max_wait_time)) do
|
367
|
+
el = find(selector, locator, **options)
|
368
|
+
el.set(checked)
|
369
|
+
rescue StandardError => e
|
370
|
+
raise unless allow_label_click && catch_error?(e)
|
371
|
+
|
370
372
|
begin
|
371
|
-
el
|
372
|
-
el.
|
373
|
-
rescue StandardError
|
374
|
-
raise
|
375
|
-
|
376
|
-
begin
|
377
|
-
el ||= find(selector, locator, **options.merge(visible: :all))
|
378
|
-
el.session.find(:label, for: el, visible: true).click unless el.checked? == checked
|
379
|
-
rescue StandardError # swallow extra errors - raise original
|
380
|
-
raise e
|
381
|
-
end
|
373
|
+
el ||= find(selector, locator, **options.merge(visible: :all))
|
374
|
+
el.session.find(:label, for: el, visible: true, match: :first).click unless el.checked? == checked
|
375
|
+
rescue StandardError # swallow extra errors - raise original
|
376
|
+
raise e
|
382
377
|
end
|
383
378
|
end
|
384
379
|
end
|
data/lib/capybara/node/base.rb
CHANGED
@@ -103,19 +103,19 @@ module Capybara
|
|
103
103
|
|
104
104
|
# @api private
|
105
105
|
def find_css(css, **options)
|
106
|
-
if base.method(:find_css).arity
|
107
|
-
base.find_css(css, **options)
|
108
|
-
else
|
106
|
+
if base.method(:find_css).arity == 1
|
109
107
|
base.find_css(css)
|
108
|
+
else
|
109
|
+
base.find_css(css, **options)
|
110
110
|
end
|
111
111
|
end
|
112
112
|
|
113
113
|
# @api private
|
114
114
|
def find_xpath(xpath, **options)
|
115
|
-
if base.method(:find_xpath).arity
|
116
|
-
base.find_xpath(xpath, **options)
|
117
|
-
else
|
115
|
+
if base.method(:find_xpath).arity == 1
|
118
116
|
base.find_xpath(xpath)
|
117
|
+
else
|
118
|
+
base.find_xpath(xpath, **options)
|
119
119
|
end
|
120
120
|
end
|
121
121
|
|
@@ -435,11 +435,7 @@ module Capybara
|
|
435
435
|
#
|
436
436
|
# @return [Capybara::Node::Element] The element
|
437
437
|
def drop(*args)
|
438
|
-
options = args.map
|
439
|
-
return arg.to_path if arg.respond_to?(:to_path)
|
440
|
-
|
441
|
-
arg
|
442
|
-
end
|
438
|
+
options = args.map { |arg| arg.respond_to?(:to_path) ? arg.to_path : arg }
|
443
439
|
synchronize { base.drop(*options) }
|
444
440
|
self
|
445
441
|
end
|
@@ -24,12 +24,13 @@ module Capybara
|
|
24
24
|
# @option options [Boolean] normalize_ws
|
25
25
|
# Whether the `text`/`exact_text` options are compared against elment text with whitespace normalized or as returned by the driver.
|
26
26
|
# Defaults to {Capybara.configure default_normalize_ws}.
|
27
|
-
# @option options [Boolean, Symbol] visible
|
28
|
-
#
|
29
|
-
#
|
30
|
-
#
|
31
|
-
#
|
32
|
-
#
|
27
|
+
# @option options [Boolean, Symbol] visible
|
28
|
+
# Only find elements with the specified visibility. Defaults to behavior indicated by {Capybara.configure ignore_hidden_elements}.
|
29
|
+
# * true - only finds visible elements.
|
30
|
+
# * false - finds invisible _and_ visible elements.
|
31
|
+
# * :all - same as false; finds visible and invisible elements.
|
32
|
+
# * :hidden - only finds invisible elements.
|
33
|
+
# * :visible - same as true; only finds visible elements.
|
33
34
|
# @option options [Boolean] obscured Only find elements with the specified obscured state:
|
34
35
|
# * true - only find elements whose centerpoint is not in the viewport or is obscured by another non-descendant element.
|
35
36
|
# * false - only find elements whose centerpoint is in the viewport and is not obscured by other non-descendant elements.
|
@@ -60,15 +60,16 @@ module Capybara
|
|
60
60
|
# @param styles [Hash]
|
61
61
|
# @return [Boolean] If the styles match
|
62
62
|
#
|
63
|
-
def matches_style?(styles, **options)
|
63
|
+
def matches_style?(styles = nil, **options)
|
64
|
+
styles, options = options, {} if styles.nil?
|
64
65
|
make_predicate(options) { assert_matches_style(styles, **options) }
|
65
66
|
end
|
66
67
|
|
67
68
|
##
|
68
69
|
# @deprecated Use {#matches_style?} instead.
|
69
70
|
#
|
70
|
-
def has_style?(styles, **options)
|
71
|
-
warn
|
71
|
+
def has_style?(styles = nil, **options)
|
72
|
+
Capybara::Helpers.warn "DEPRECATED: has_style? is deprecated, please use matches_style? : #{Capybara::Helpers.filter_backtrace(caller)}"
|
72
73
|
matches_style?(styles, **options)
|
73
74
|
end
|
74
75
|
|
@@ -122,7 +123,8 @@ module Capybara
|
|
122
123
|
# @param styles [Hash]
|
123
124
|
# @raise [Capybara::ExpectationNotMet] If the element doesn't have the specified styles
|
124
125
|
#
|
125
|
-
def assert_matches_style(styles, **options)
|
126
|
+
def assert_matches_style(styles = nil, **options)
|
127
|
+
styles, options = options, {} if styles.nil?
|
126
128
|
query_args, query_opts = _set_query_session_options(styles, options)
|
127
129
|
query = Capybara::Queries::StyleQuery.new(*query_args, **query_opts)
|
128
130
|
synchronize(query.wait) do
|
@@ -134,7 +136,7 @@ module Capybara
|
|
134
136
|
##
|
135
137
|
# @deprecated Use {#assert_matches_style} instead.
|
136
138
|
#
|
137
|
-
def assert_style(styles, **options)
|
139
|
+
def assert_style(styles = nil, **options)
|
138
140
|
warn 'assert_style is deprecated, please use assert_matches_style instead'
|
139
141
|
assert_matches_style(styles, **options)
|
140
142
|
end
|
@@ -201,12 +203,10 @@ module Capybara
|
|
201
203
|
selector = extract_selector(args)
|
202
204
|
synchronize(wait) do
|
203
205
|
res = args.map do |locator|
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
e.message
|
209
|
-
end
|
206
|
+
assert_selector(selector, locator, options, &optional_filter_block)
|
207
|
+
break nil
|
208
|
+
rescue Capybara::ExpectationNotMet => e
|
209
|
+
e.message
|
210
210
|
end
|
211
211
|
raise Capybara::ExpectationNotMet, res.join(' or ') if res
|
212
212
|
|
@@ -386,7 +386,7 @@ module Capybara
|
|
386
386
|
#
|
387
387
|
# page.has_field?('Email', type: 'email')
|
388
388
|
#
|
389
|
-
#
|
389
|
+
# NOTE: 'textarea' and 'select' are valid type values, matching the associated tag names.
|
390
390
|
#
|
391
391
|
# @param [String] locator The label, name or id of a field to check for
|
392
392
|
# @option options [String, Regexp] :with The text content of the field or a Regexp to match
|
data/lib/capybara/node/simple.rb
CHANGED
@@ -100,7 +100,7 @@ module Capybara
|
|
100
100
|
# @param [Boolean] check_ancestors Whether to inherit visibility from ancestors
|
101
101
|
# @return [Boolean] Whether the element is visible
|
102
102
|
#
|
103
|
-
def visible?(check_ancestors = true)
|
103
|
+
def visible?(check_ancestors = true) # rubocop:disable Style/OptionalBooleanParameter
|
104
104
|
return false if (tag_name == 'input') && (native[:type] == 'hidden')
|
105
105
|
return false if tag_name == 'template'
|
106
106
|
|
@@ -148,6 +148,10 @@ module Capybara
|
|
148
148
|
native.has_attribute?('multiple')
|
149
149
|
end
|
150
150
|
|
151
|
+
def readonly?
|
152
|
+
native.has_attribute?('readonly')
|
153
|
+
end
|
154
|
+
|
151
155
|
def synchronize(_seconds = nil)
|
152
156
|
yield # simple nodes don't need to wait
|
153
157
|
end
|
@@ -16,7 +16,7 @@ module Capybara
|
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
19
|
-
def description(applied = false)
|
19
|
+
def description(applied = false) # rubocop:disable Style/OptionalBooleanParameter
|
20
20
|
child_query = @child_node&.instance_variable_get(:@query)
|
21
21
|
desc = super
|
22
22
|
desc += " that is an ancestor of #{child_query.description}" if child_query
|
@@ -6,26 +6,30 @@ module Capybara
|
|
6
6
|
# @api private
|
7
7
|
module Queries
|
8
8
|
class CurrentPathQuery < BaseQuery
|
9
|
-
def initialize(expected_path, **options)
|
9
|
+
def initialize(expected_path, **options, &optional_filter_block)
|
10
10
|
super(options)
|
11
11
|
@expected_path = expected_path
|
12
12
|
@options = {
|
13
13
|
url: !@expected_path.is_a?(Regexp) && !::Addressable::URI.parse(@expected_path || '').hostname.nil?,
|
14
14
|
ignore_query: false
|
15
15
|
}.merge(options)
|
16
|
+
@filter_block = optional_filter_block
|
16
17
|
assert_valid_keys
|
17
18
|
end
|
18
19
|
|
19
20
|
def resolves_for?(session)
|
20
21
|
uri = ::Addressable::URI.parse(session.current_url)
|
21
|
-
|
22
|
-
|
22
|
+
@actual_path = (options[:ignore_query] ? uri&.omit(:query) : uri).yield_self do |u|
|
23
|
+
options[:url] ? u&.to_s : u&.request_uri
|
24
|
+
end
|
23
25
|
|
24
|
-
if @expected_path.is_a? Regexp
|
26
|
+
res = if @expected_path.is_a? Regexp
|
25
27
|
@actual_path.to_s.match?(@expected_path)
|
26
28
|
else
|
27
29
|
::Addressable::URI.parse(@expected_path) == ::Addressable::URI.parse(@actual_path)
|
28
30
|
end
|
31
|
+
|
32
|
+
res && matches_filter_block?(uri)
|
29
33
|
end
|
30
34
|
|
31
35
|
def failure_message
|
@@ -38,6 +42,12 @@ module Capybara
|
|
38
42
|
|
39
43
|
private
|
40
44
|
|
45
|
+
def matches_filter_block?(url)
|
46
|
+
return true unless @filter_block
|
47
|
+
|
48
|
+
@filter_block.call(url)
|
49
|
+
end
|
50
|
+
|
41
51
|
def failure_message_helper(negated = '')
|
42
52
|
verb = @expected_path.is_a?(Regexp) ? 'match' : 'equal'
|
43
53
|
"expected #{@actual_path.inspect}#{negated} to #{verb} #{@expected_path.inspect}"
|
@@ -6,6 +6,7 @@ module Capybara
|
|
6
6
|
module Queries
|
7
7
|
class SelectorQuery < Queries::BaseQuery
|
8
8
|
attr_reader :expression, :selector, :locator, :options
|
9
|
+
|
9
10
|
SPATIAL_KEYS = %i[above below left_of right_of near].freeze
|
10
11
|
VALID_KEYS = SPATIAL_KEYS + COUNT_KEYS +
|
11
12
|
%i[text id class style visible obscured exact exact_text normalize_ws match wait filter_set]
|
@@ -14,6 +15,7 @@ module Capybara
|
|
14
15
|
def initialize(*args,
|
15
16
|
session_options:,
|
16
17
|
enable_aria_label: session_options.enable_aria_label,
|
18
|
+
enable_aria_role: session_options.enable_aria_role,
|
17
19
|
test_id: session_options.test_id,
|
18
20
|
selector_format: nil,
|
19
21
|
order: nil,
|
@@ -30,7 +32,11 @@ module Capybara
|
|
30
32
|
|
31
33
|
@selector = Selector.new(
|
32
34
|
find_selector(args[0].is_a?(Symbol) ? args.shift : args[0]),
|
33
|
-
config: {
|
35
|
+
config: {
|
36
|
+
enable_aria_label: enable_aria_label,
|
37
|
+
enable_aria_role: enable_aria_role,
|
38
|
+
test_id: test_id
|
39
|
+
},
|
34
40
|
format: selector_format
|
35
41
|
)
|
36
42
|
|
@@ -49,7 +55,7 @@ module Capybara
|
|
49
55
|
def name; selector.name; end
|
50
56
|
def label; selector.label || selector.name; end
|
51
57
|
|
52
|
-
def description(only_applied = false)
|
58
|
+
def description(only_applied = false) # rubocop:disable Style/OptionalBooleanParameter
|
53
59
|
desc = +''
|
54
60
|
show_for = show_for_stage(only_applied)
|
55
61
|
|
@@ -89,11 +95,9 @@ module Capybara
|
|
89
95
|
desc << ' that also matches the custom filter block' if @filter_block && show_for[:node]
|
90
96
|
|
91
97
|
desc << " within #{@resolved_node.inspect}" if describe_within?
|
92
|
-
if locator.is_a?(String) && locator.start_with?('#', './/', '//')
|
93
|
-
|
94
|
-
|
95
|
-
"Please see the documentation for acceptable locator values.\n\n"
|
96
|
-
end
|
98
|
+
if locator.is_a?(String) && locator.start_with?('#', './/', '//') && !selector.raw_locator?
|
99
|
+
desc << "\nNote: It appears you may be passing a CSS selector or XPath expression rather than a locator. " \
|
100
|
+
"Please see the documentation for acceptable locator values.\n\n"
|
97
101
|
end
|
98
102
|
desc
|
99
103
|
end
|
@@ -233,17 +237,18 @@ module Capybara
|
|
233
237
|
hints[:styles] = options[:style] if use_default_style_filter?
|
234
238
|
hints[:position] = true if use_spatial_filter?
|
235
239
|
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
else
|
240
|
+
case selector_format
|
241
|
+
when :css
|
242
|
+
if node.method(:find_css).arity == 1
|
240
243
|
node.find_css(css)
|
241
|
-
end
|
242
|
-
elsif selector_format == :xpath
|
243
|
-
if node.method(:find_xpath).arity != 1
|
244
|
-
node.find_xpath(xpath(exact), **hints)
|
245
244
|
else
|
245
|
+
node.find_css(css, **hints)
|
246
|
+
end
|
247
|
+
when :xpath
|
248
|
+
if node.method(:find_xpath).arity == 1
|
246
249
|
node.find_xpath(xpath(exact))
|
250
|
+
else
|
251
|
+
node.find_xpath(xpath(exact), **hints)
|
247
252
|
end
|
248
253
|
else
|
249
254
|
raise ArgumentError, "Unknown format: #{selector_format}"
|
@@ -477,9 +482,25 @@ module Capybara
|
|
477
482
|
end
|
478
483
|
|
479
484
|
def matches_class_filter?(node)
|
480
|
-
return true unless use_default_class_filter? &&
|
485
|
+
return true unless use_default_class_filter? && need_to_process_classes?
|
481
486
|
|
482
|
-
options[:class].
|
487
|
+
if options[:class].is_a? Regexp
|
488
|
+
options[:class].match? node[:class]
|
489
|
+
else
|
490
|
+
classes = (node[:class] || '').split
|
491
|
+
options[:class].select { |c| c.is_a? Regexp }.all? do |r|
|
492
|
+
classes.any? { |cls| r.match? cls }
|
493
|
+
end
|
494
|
+
end
|
495
|
+
end
|
496
|
+
|
497
|
+
def need_to_process_classes?
|
498
|
+
case options[:class]
|
499
|
+
when Regexp then true
|
500
|
+
when Array then options[:class].any?(Regexp)
|
501
|
+
else
|
502
|
+
false
|
503
|
+
end
|
483
504
|
end
|
484
505
|
|
485
506
|
def matches_style_filter?(node)
|
@@ -575,6 +596,7 @@ module Capybara
|
|
575
596
|
|
576
597
|
class Rectangle
|
577
598
|
attr_reader :top, :bottom, :left, :right
|
599
|
+
|
578
600
|
def initialize(position)
|
579
601
|
# rubocop:disable Style/RescueModifier
|
580
602
|
@top = position['top'] rescue position['y']
|
@@ -645,7 +667,7 @@ module Capybara
|
|
645
667
|
|
646
668
|
d = u.dot w
|
647
669
|
e = v.dot w
|
648
|
-
cap_d = (a * c) - (b
|
670
|
+
cap_d = (a * c) - (b**2)
|
649
671
|
sD = tD = cap_d
|
650
672
|
|
651
673
|
# compute the line parameters of the two closest points
|
@@ -15,7 +15,7 @@ module Capybara
|
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
18
|
-
def description(applied = false)
|
18
|
+
def description(applied = false) # rubocop:disable Style/OptionalBooleanParameter
|
19
19
|
desc = super
|
20
20
|
sibling_query = @sibling_node&.instance_variable_get(:@query)
|
21
21
|
desc += " that is a sibling of #{sibling_query.description}" if sibling_query
|