capybara 3.33.0 → 3.34.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 +44 -15
- data/README.md +0 -2
- data/lib/capybara.rb +1 -1
- data/lib/capybara/config.rb +4 -6
- data/lib/capybara/driver/base.rb +4 -0
- data/lib/capybara/helpers.rb +25 -1
- data/lib/capybara/minitest.rb +2 -2
- data/lib/capybara/minitest/spec.rb +14 -11
- data/lib/capybara/node/actions.rb +1 -2
- data/lib/capybara/node/element.rb +1 -5
- data/lib/capybara/node/finders.rb +7 -6
- data/lib/capybara/node/matchers.rb +7 -5
- 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 +8 -9
- data/lib/capybara/queries/sibling_query.rb +1 -1
- data/lib/capybara/queries/text_query.rb +2 -2
- 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 +3 -3
- data/lib/capybara/registrations/patches/puma_ssl.rb +3 -1
- data/lib/capybara/registrations/servers.rb +1 -0
- data/lib/capybara/result.rb +3 -7
- 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/match_style.rb +5 -0
- data/lib/capybara/selector/definition.rb +6 -5
- data/lib/capybara/selector/definition/button.rb +7 -5
- 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/label.rb +1 -1
- data/lib/capybara/selector/definition/select.rb +1 -1
- data/lib/capybara/selector/definition/table_row.rb +1 -1
- data/lib/capybara/selector/filter_set.rb +2 -2
- data/lib/capybara/selector/selector.rb +5 -1
- data/lib/capybara/selenium/driver.rb +29 -3
- data/lib/capybara/selenium/driver_specializations/chrome_driver.rb +3 -3
- data/lib/capybara/selenium/driver_specializations/edge_driver.rb +3 -3
- data/lib/capybara/selenium/driver_specializations/firefox_driver.rb +1 -1
- data/lib/capybara/selenium/extensions/find.rb +3 -3
- data/lib/capybara/selenium/extensions/scroll.rb +8 -10
- data/lib/capybara/selenium/node.rb +6 -3
- data/lib/capybara/selenium/nodes/chrome_node.rb +20 -2
- data/lib/capybara/selenium/nodes/safari_node.rb +1 -1
- data/lib/capybara/selenium/patches/atoms.rb +4 -4
- data/lib/capybara/selenium/patches/logs.rb +4 -4
- data/lib/capybara/server/animation_disabler.rb +3 -2
- data/lib/capybara/server/middleware.rb +4 -2
- data/lib/capybara/session.rb +20 -11
- data/lib/capybara/session/matchers.rb +11 -11
- data/lib/capybara/spec/public/test.js +6 -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/current_url_spec.rb +11 -1
- data/lib/capybara/spec/session/has_button_spec.rb +2 -0
- data/lib/capybara/spec/session/has_css_spec.rb +2 -1
- data/lib/capybara/spec/session/has_current_path_spec.rb +13 -0
- data/lib/capybara/spec/session/has_text_spec.rb +0 -11
- data/lib/capybara/spec/session/matches_style_spec.rb +2 -2
- data/lib/capybara/spec/session/node_spec.rb +22 -2
- data/lib/capybara/spec/session/refresh_spec.rb +1 -0
- data/lib/capybara/spec/session/save_page_spec.rb +4 -4
- data/lib/capybara/spec/spec_helper.rb +11 -12
- data/lib/capybara/spec/test_app.rb +8 -3
- data/lib/capybara/spec/views/form.erb +18 -0
- data/lib/capybara/spec/views/with_animation.erb +8 -0
- data/lib/capybara/spec/views/with_js.erb +1 -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/dsl_spec.rb +1 -1
- data/spec/fixtures/selenium_driver_rspec_success.rb +1 -1
- data/spec/minitest_spec.rb +2 -1
- data/spec/rack_test_spec.rb +15 -5
- data/spec/rspec/features_spec.rb +3 -1
- data/spec/rspec/scenarios_spec.rb +4 -0
- data/spec/rspec/shared_spec_matchers.rb +2 -2
- data/spec/rspec_spec.rb +4 -0
- data/spec/selector_spec.rb +1 -0
- data/spec/server_spec.rb +15 -0
- data/spec/shared_selenium_session.rb +60 -1
- metadata +22 -23
- data/lib/capybara/spec/session/source_spec.rb +0 -0
@@ -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}"
|
@@ -55,7 +55,7 @@ module Capybara
|
|
55
55
|
def name; selector.name; end
|
56
56
|
def label; selector.label || selector.name; end
|
57
57
|
|
58
|
-
def description(only_applied = false)
|
58
|
+
def description(only_applied = false) # rubocop:disable Style/OptionalBooleanParameter
|
59
59
|
desc = +''
|
60
60
|
show_for = show_for_stage(only_applied)
|
61
61
|
|
@@ -95,11 +95,9 @@ module Capybara
|
|
95
95
|
desc << ' that also matches the custom filter block' if @filter_block && show_for[:node]
|
96
96
|
|
97
97
|
desc << " within #{@resolved_node.inspect}" if describe_within?
|
98
|
-
if locator.is_a?(String) && locator.start_with?('#', './/', '//')
|
99
|
-
|
100
|
-
|
101
|
-
"Please see the documentation for acceptable locator values.\n\n"
|
102
|
-
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"
|
103
101
|
end
|
104
102
|
desc
|
105
103
|
end
|
@@ -239,13 +237,14 @@ module Capybara
|
|
239
237
|
hints[:styles] = options[:style] if use_default_style_filter?
|
240
238
|
hints[:position] = true if use_spatial_filter?
|
241
239
|
|
242
|
-
|
240
|
+
case selector_format
|
241
|
+
when :css
|
243
242
|
if node.method(:find_css).arity != 1
|
244
243
|
node.find_css(css, **hints)
|
245
244
|
else
|
246
245
|
node.find_css(css)
|
247
246
|
end
|
248
|
-
|
247
|
+
when :xpath
|
249
248
|
if node.method(:find_xpath).arity != 1
|
250
249
|
node.find_xpath(xpath(exact), **hints)
|
251
250
|
else
|
@@ -652,7 +651,7 @@ module Capybara
|
|
652
651
|
|
653
652
|
d = u.dot w
|
654
653
|
e = v.dot w
|
655
|
-
cap_d = (a * c) - (b
|
654
|
+
cap_d = (a * c) - (b**2)
|
656
655
|
sD = tD = cap_d
|
657
656
|
|
658
657
|
# 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
|
@@ -6,7 +6,7 @@ module Capybara
|
|
6
6
|
class TextQuery < BaseQuery
|
7
7
|
def initialize(type = nil, expected_text, session_options:, **options) # rubocop:disable Style/OptionalArguments
|
8
8
|
@type = type.nil? ? default_type : type
|
9
|
-
raise ArgumentError,
|
9
|
+
raise ArgumentError, "#{@type} is not a valid type for a text query" unless valid_types.include?(@type)
|
10
10
|
|
11
11
|
@options = options
|
12
12
|
super(@options)
|
@@ -14,7 +14,7 @@ module Capybara
|
|
14
14
|
|
15
15
|
if expected_text.nil? && !exact?
|
16
16
|
warn 'Checking for expected text of nil is confusing and/or pointless since it will always match. '\
|
17
|
-
|
17
|
+
"Please specify a string or regexp instead. #{Capybara::Helpers.filter_backtrace(caller)}"
|
18
18
|
end
|
19
19
|
|
20
20
|
@expected_text = expected_text.is_a?(Regexp) ? expected_text : expected_text.to_s
|
@@ -8,6 +8,7 @@ class Capybara::RackTest::Browser
|
|
8
8
|
|
9
9
|
def initialize(driver)
|
10
10
|
@driver = driver
|
11
|
+
@current_fragment = nil
|
11
12
|
end
|
12
13
|
|
13
14
|
def app
|
@@ -31,7 +32,7 @@ class Capybara::RackTest::Browser
|
|
31
32
|
def submit(method, path, attributes)
|
32
33
|
path = request_path if path.nil? || path.empty?
|
33
34
|
uri = build_uri(path)
|
34
|
-
uri.query = '' if method
|
35
|
+
uri.query = '' if method.to_s.casecmp('get').zero?
|
35
36
|
process_and_follow_redirects(method, uri.to_s, attributes, 'HTTP_REFERER' => current_url)
|
36
37
|
end
|
37
38
|
|
@@ -42,6 +43,7 @@ class Capybara::RackTest::Browser
|
|
42
43
|
end
|
43
44
|
|
44
45
|
def process_and_follow_redirects(method, path, attributes = {}, env = {})
|
46
|
+
@current_fragment = build_uri(path).fragment
|
45
47
|
process(method, path, attributes, env)
|
46
48
|
|
47
49
|
return unless driver.follow_redirects?
|
@@ -65,7 +67,7 @@ class Capybara::RackTest::Browser
|
|
65
67
|
method = method.downcase
|
66
68
|
new_uri = build_uri(path)
|
67
69
|
@current_scheme, @current_host, @current_port = new_uri.select(:scheme, :host, :port)
|
68
|
-
|
70
|
+
@current_fragment = new_uri.fragment || @current_fragment
|
69
71
|
reset_cache!
|
70
72
|
send(method, new_uri.to_s, attributes, env.merge(options[:headers] || {}))
|
71
73
|
end
|
@@ -83,7 +85,9 @@ class Capybara::RackTest::Browser
|
|
83
85
|
end
|
84
86
|
|
85
87
|
def current_url
|
86
|
-
last_request.url
|
88
|
+
uri = build_uri(last_request.url)
|
89
|
+
uri.fragment = @current_fragment if @current_fragment
|
90
|
+
uri.to_s
|
87
91
|
rescue Rack::Test::Error
|
88
92
|
''
|
89
93
|
end
|
@@ -17,6 +17,7 @@ class Capybara::RackTest::Driver < Capybara::Driver::Base
|
|
17
17
|
def initialize(app, **options)
|
18
18
|
raise ArgumentError, 'rack-test requires a rack application, but none was given' unless app
|
19
19
|
|
20
|
+
super()
|
20
21
|
@app = app
|
21
22
|
@options = DEFAULT_OPTIONS.merge(options)
|
22
23
|
end
|
@@ -6,7 +6,7 @@ class Capybara::RackTest::Form < Capybara::RackTest::Node
|
|
6
6
|
# That check should be based solely on the form element's 'enctype' attribute value,
|
7
7
|
# which should probably be provided to Rack::Test in its non-GET request methods.
|
8
8
|
class NilUploadedFile < Rack::Test::UploadedFile
|
9
|
-
def initialize
|
9
|
+
def initialize # rubocop:disable Lint/MissingSuper
|
10
10
|
@empty_file = Tempfile.new('nil_uploaded_file')
|
11
11
|
@empty_file.close
|
12
12
|
end
|
@@ -15,7 +15,7 @@ class Capybara::RackTest::Node < Capybara::Driver::Node
|
|
15
15
|
end
|
16
16
|
|
17
17
|
def visible_text
|
18
|
-
displayed_text.
|
18
|
+
displayed_text.squeeze(' ')
|
19
19
|
.gsub(/[\ \n]*\n[\ \n]*/, "\n")
|
20
20
|
.gsub(/\A[[:space:]&&[^\u00a0]]+/, '')
|
21
21
|
.gsub(/[[:space:]&&[^\u00a0]]+\z/, '')
|
@@ -12,13 +12,13 @@ module Capybara
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def []=(name, value)
|
15
|
-
warn 'DEPRECATED: Directly setting drivers/servers is deprecated, please use Capybara.register_driver/register_server instead'
|
15
|
+
Capybara::Helpers.warn 'DEPRECATED: Directly setting drivers/servers is deprecated, please use Capybara.register_driver/register_server instead'
|
16
16
|
@registered[name] = value
|
17
17
|
end
|
18
18
|
|
19
19
|
def method_missing(method_name, *args, **options, &block)
|
20
20
|
if @registered.respond_to?(method_name)
|
21
|
-
warn "DEPRECATED: Calling '#{method_name}' on the drivers/servers container is deprecated without replacement"
|
21
|
+
Capybara::Helpers.warn "DEPRECATED: Calling '#{method_name}' on the drivers/servers container is deprecated without replacement"
|
22
22
|
# RUBY 2.6 will send an empty hash rather than nothing with **options so fix that
|
23
23
|
return @registered.public_send(method_name, *args, &block) if options.empty?
|
24
24
|
|
@@ -27,7 +27,7 @@ module Capybara
|
|
27
27
|
super
|
28
28
|
end
|
29
29
|
|
30
|
-
def respond_to_missing?(method_name,
|
30
|
+
def respond_to_missing?(method_name, include_all)
|
31
31
|
@registered.respond_to?(method_name) || super
|
32
32
|
end
|
33
33
|
|
@@ -4,12 +4,14 @@ module Puma
|
|
4
4
|
module MiniSSL
|
5
5
|
class Socket
|
6
6
|
def read_nonblock(size, *_)
|
7
|
+
wait_states = %i[wait_readable wait_writable]
|
8
|
+
|
7
9
|
loop do
|
8
10
|
output = engine_read_all
|
9
11
|
return output if output
|
10
12
|
|
11
13
|
data = @socket.read_nonblock(size, exception: false)
|
12
|
-
raise IO::EAGAINWaitReadable if
|
14
|
+
raise IO::EAGAINWaitReadable if wait_states.include? data
|
13
15
|
return nil if data.nil?
|
14
16
|
|
15
17
|
@engine.inject(data)
|
@@ -28,6 +28,7 @@ Capybara.register_server :puma do |app, port, host, **options|
|
|
28
28
|
options = default_options.merge(options)
|
29
29
|
|
30
30
|
conf = Rack::Handler::Puma.config(app, options)
|
31
|
+
conf.clamp
|
31
32
|
events = conf.options[:Silent] ? ::Puma::Events.strings : ::Puma::Events.stdio
|
32
33
|
|
33
34
|
puma_ver = Gem::Version.new(Puma::Const::PUMA_VERSION)
|
data/lib/capybara/result.rb
CHANGED
@@ -39,7 +39,7 @@ module Capybara
|
|
39
39
|
alias index find_index
|
40
40
|
|
41
41
|
def each(&block)
|
42
|
-
return enum_for(:each) unless
|
42
|
+
return enum_for(:each) unless block
|
43
43
|
|
44
44
|
@result_cache.each(&block)
|
45
45
|
loop do
|
@@ -91,13 +91,9 @@ module Capybara
|
|
91
91
|
return load_up_to(count + 1) <=> count
|
92
92
|
end
|
93
93
|
|
94
|
-
if min && (min = Integer(min))
|
95
|
-
return -1 if load_up_to(min) < min
|
96
|
-
end
|
94
|
+
return -1 if min && (min = Integer(min)) && (load_up_to(min) < min)
|
97
95
|
|
98
|
-
if max && (max = Integer(max))
|
99
|
-
return 1 if load_up_to(max + 1) > max
|
100
|
-
end
|
96
|
+
return 1 if max && (max = Integer(max)) && (load_up_to(max + 1) > max)
|
101
97
|
|
102
98
|
if between
|
103
99
|
min, max = (between.begin && between.min) || 1, between.end
|
data/lib/capybara/rspec.rb
CHANGED
@@ -9,6 +9,8 @@ require 'capybara/rspec/matcher_proxies'
|
|
9
9
|
RSpec.configure do |config|
|
10
10
|
config.include Capybara::DSL, type: :feature
|
11
11
|
config.include Capybara::RSpecMatchers, type: :feature
|
12
|
+
config.include Capybara::DSL, type: :system
|
13
|
+
config.include Capybara::RSpecMatchers, type: :system
|
12
14
|
config.include Capybara::RSpecMatchers, type: :view
|
13
15
|
|
14
16
|
# The before and after blocks must run instantaneously, because Capybara
|
@@ -94,7 +94,7 @@ module Capybara
|
|
94
94
|
# @see Capybara::Node::Matchers#has_button?
|
95
95
|
|
96
96
|
# @!method have_field(locator = nil, **options, &optional_filter_block)
|
97
|
-
# RSpec matcher for
|
97
|
+
# RSpec matcher for form fields.
|
98
98
|
#
|
99
99
|
# @see Capybara::Node::Matchers#has_field?
|
100
100
|
|
@@ -139,22 +139,23 @@ module Capybara
|
|
139
139
|
# RSpec matcher for the current path.
|
140
140
|
#
|
141
141
|
# @see Capybara::SessionMatchers#assert_current_path
|
142
|
-
def have_current_path(path, **options)
|
143
|
-
Matchers::HaveCurrentPath.new(path, **options)
|
142
|
+
def have_current_path(path, **options, &optional_filter_block)
|
143
|
+
Matchers::HaveCurrentPath.new(path, **options, &optional_filter_block)
|
144
144
|
end
|
145
145
|
|
146
146
|
# RSpec matcher for element style.
|
147
147
|
#
|
148
148
|
# @see Capybara::Node::Matchers#matches_style?
|
149
|
-
def match_style(styles, **options)
|
149
|
+
def match_style(styles = nil, **options)
|
150
|
+
styles, options = options, {} if styles.nil?
|
150
151
|
Matchers::MatchStyle.new(styles, **options)
|
151
152
|
end
|
152
153
|
|
153
154
|
##
|
154
155
|
# @deprecated
|
155
156
|
#
|
156
|
-
def have_style(styles, **options)
|
157
|
-
warn
|
157
|
+
def have_style(styles = nil, **options)
|
158
|
+
Capybara::Helpers.warn "DEPRECATED: have_style is deprecated, please use match_style : #{Capybara::Helpers.filter_backtrace(caller)}"
|
158
159
|
match_style(styles, **options)
|
159
160
|
end
|
160
161
|
|
@@ -7,11 +7,11 @@ module Capybara
|
|
7
7
|
module Matchers
|
8
8
|
class HaveCurrentPath < WrappedElementMatcher
|
9
9
|
def element_matches?(el)
|
10
|
-
el.assert_current_path(current_path, **@kw_args)
|
10
|
+
el.assert_current_path(current_path, **@kw_args, &@filter_block)
|
11
11
|
end
|
12
12
|
|
13
13
|
def element_does_not_match?(el)
|
14
|
-
el.assert_no_current_path(current_path, **@kw_args)
|
14
|
+
el.assert_no_current_path(current_path, **@kw_args, &@filter_block)
|
15
15
|
end
|
16
16
|
|
17
17
|
def description
|
@@ -6,6 +6,11 @@ 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
15
|
el.assert_matches_style(*@args, **@kw_args)
|
11
16
|
end
|
@@ -15,7 +15,7 @@ module Capybara
|
|
15
15
|
|
16
16
|
def initialize(name, locator_type: nil, raw_locator: false, supports_exact: nil, &block)
|
17
17
|
@name = name
|
18
|
-
@filter_set = Capybara::Selector::FilterSet.add(name)
|
18
|
+
@filter_set = Capybara::Selector::FilterSet.add(name)
|
19
19
|
@match = nil
|
20
20
|
@label = nil
|
21
21
|
@failure_message = nil
|
@@ -83,7 +83,7 @@ module Capybara
|
|
83
83
|
# Automatic selector detection
|
84
84
|
#
|
85
85
|
# @yield [locator] This block takes the passed in locator string and returns whether or not it matches the selector
|
86
|
-
# @yieldparam [String], locator The locator string used to
|
86
|
+
# @yieldparam [String], locator The locator string used to determine if it matches the selector
|
87
87
|
# @yieldreturn [Boolean] Whether this selector matches the locator string
|
88
88
|
# @return [#call] The block that will be used to detect selector match
|
89
89
|
#
|
@@ -178,7 +178,7 @@ module Capybara
|
|
178
178
|
def_delegator :@filter_set, :describe
|
179
179
|
|
180
180
|
def describe_expression_filters(&block)
|
181
|
-
if
|
181
|
+
if block
|
182
182
|
describe(:expression_filters, &block)
|
183
183
|
else
|
184
184
|
describe(:expression_filters) do |**options|
|
@@ -215,7 +215,7 @@ module Capybara
|
|
215
215
|
end
|
216
216
|
|
217
217
|
def default_visibility(fallback = Capybara.ignore_hidden_elements, options = {})
|
218
|
-
vis = if @default_visibility
|
218
|
+
vis = if @default_visibility.respond_to?(:call)
|
219
219
|
@default_visibility.call(options)
|
220
220
|
else
|
221
221
|
@default_visibility
|
@@ -259,7 +259,8 @@ module Capybara
|
|
259
259
|
end
|
260
260
|
|
261
261
|
def parameter_names(block)
|
262
|
-
|
262
|
+
key_types = %i[key keyreq]
|
263
|
+
block.parameters.select { |(type, _name)| key_types.include? type }.map { |(_type, name)| name }
|
263
264
|
end
|
264
265
|
|
265
266
|
def expression(type, allowed_filters, &block)
|
@@ -12,23 +12,25 @@ Capybara.add_selector(:button, locator_type: [String, Symbol]) do
|
|
12
12
|
locator_matchers = XPath.attr(:id).equals(locator) |
|
13
13
|
XPath.attr(:name).equals(locator) |
|
14
14
|
XPath.attr(:value).is(locator) |
|
15
|
-
XPath.attr(:title).is(locator)
|
15
|
+
XPath.attr(:title).is(locator) |
|
16
|
+
(XPath.attr(:id) == XPath.anywhere(:label)[XPath.string.n.is(locator)].attr(:for))
|
16
17
|
locator_matchers |= XPath.attr(:'aria-label').is(locator) if enable_aria_label
|
17
18
|
locator_matchers |= XPath.attr(test_id) == locator if test_id
|
18
19
|
|
19
|
-
input_btn_xpath = input_btn_xpath[locator_matchers]
|
20
|
+
input_btn_xpath = input_btn_xpath[locator_matchers] + locate_label(locator).descendant(input_btn_xpath)
|
20
21
|
|
21
22
|
btn_xpath = btn_xpath[locator_matchers |
|
22
23
|
XPath.string.n.is(locator) |
|
23
|
-
XPath.descendant(:img)[XPath.attr(:alt).is(locator)]
|
24
|
+
XPath.descendant(:img)[XPath.attr(:alt).is(locator)]
|
25
|
+
] + locate_label(locator).descendant(btn_xpath)
|
24
26
|
|
25
27
|
alt_matches = XPath.attr(:alt).is(locator)
|
26
28
|
alt_matches |= XPath.attr(:'aria-label').is(locator) if enable_aria_label
|
27
|
-
image_btn_xpath = image_btn_xpath[alt_matches]
|
29
|
+
image_btn_xpath = image_btn_xpath[alt_matches] + locate_label(locator).descendant(image_btn_xpath)
|
28
30
|
end
|
29
31
|
|
30
32
|
%i[value title type].inject(input_btn_xpath.union(btn_xpath).union(image_btn_xpath)) do |memo, ef|
|
31
|
-
memo
|
33
|
+
memo.where(find_by_attr(ef, options[ef]))
|
32
34
|
end
|
33
35
|
end
|
34
36
|
|
@@ -3,7 +3,7 @@
|
|
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."
|
6
|
+
Capybara::Helpers.warn "DEPRECATED: Passing a symbol (#{css.inspect}) as the CSS locator is deprecated - please pass a string instead : #{Capybara::Helpers.filter_backtrace(caller)}"
|
7
7
|
end
|
8
8
|
css
|
9
9
|
end
|
@@ -19,7 +19,7 @@ Capybara.add_selector(:datalist_input, locator_type: [String, Symbol]) do
|
|
19
19
|
|
20
20
|
expression_filter(:with_options) do |expr, options|
|
21
21
|
options.inject(expr) do |xpath, option|
|
22
|
-
xpath
|
22
|
+
xpath.where(XPath.attr(:list) == XPath.anywhere(:datalist)[expression_for(:datalist_option, option)].attr(:id))
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|