capybara 3.32.2 → 3.33.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 +21 -1
- data/README.md +10 -3
- data/lib/capybara.rb +17 -7
- data/lib/capybara/cucumber.rb +1 -1
- data/lib/capybara/minitest.rb +2 -3
- data/lib/capybara/node/actions.rb +16 -20
- data/lib/capybara/node/matchers.rb +4 -6
- data/lib/capybara/queries/selector_query.rb +8 -1
- data/lib/capybara/queries/style_query.rb +1 -1
- data/lib/capybara/queries/text_query.rb +6 -0
- data/lib/capybara/registration_container.rb +44 -0
- data/lib/capybara/selector.rb +10 -1
- data/lib/capybara/selector/definition.rb +5 -4
- data/lib/capybara/selector/definition/button.rb +1 -0
- data/lib/capybara/selector/definition/fillable_field.rb +1 -1
- data/lib/capybara/selector/definition/link.rb +8 -0
- data/lib/capybara/selector/definition/table.rb +1 -1
- data/lib/capybara/selector/selector.rb +4 -0
- data/lib/capybara/selenium/driver.rb +2 -0
- data/lib/capybara/selenium/driver_specializations/chrome_driver.rb +7 -9
- data/lib/capybara/selenium/driver_specializations/edge_driver.rb +7 -9
- data/lib/capybara/selenium/node.rb +3 -2
- data/lib/capybara/selenium/nodes/firefox_node.rb +1 -1
- data/lib/capybara/selenium/patches/logs.rb +3 -5
- data/lib/capybara/session.rb +3 -3
- data/lib/capybara/session/config.rb +3 -1
- data/lib/capybara/spec/public/test.js +7 -0
- data/lib/capybara/spec/session/click_button_spec.rb +11 -0
- data/lib/capybara/spec/session/has_button_spec.rb +16 -0
- data/lib/capybara/spec/session/has_current_path_spec.rb +2 -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/node_spec.rb +6 -6
- data/lib/capybara/spec/spec_helper.rb +1 -0
- data/lib/capybara/spec/test_app.rb +14 -18
- data/lib/capybara/spec/views/form.erb +2 -1
- data/lib/capybara/spec/views/with_dragula.erb +3 -1
- data/lib/capybara/spec/views/with_js.erb +1 -0
- data/lib/capybara/version.rb +1 -1
- data/spec/capybara_spec.rb +1 -1
- data/spec/dsl_spec.rb +14 -1
- data/spec/minitest_spec.rb +1 -1
- data/spec/rack_test_spec.rb +1 -0
- data/spec/rspec/shared_spec_matchers.rb +63 -51
- data/spec/selector_spec.rb +1 -1
- data/spec/selenium_spec_chrome.rb +0 -2
- data/spec/server_spec.rb +41 -49
- data/spec/shared_selenium_session.rb +10 -1
- data/spec/spec_helper.rb +1 -1
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ab64d9d47c6374c4f203945be70b868fb9e4c48d3fdca087ba4e66498e40b91c
|
4
|
+
data.tar.gz: 451c97390c148b5b0fad1b06107a4f0de87f17f7b8cef7156fb76ad2ee503f76
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b0ca3fd8a4535e1df696ddc7f547e066b873d3f4be2b54655fdbb0b6588c5086a87b93500e241e0da031b586c0b6a30cdd8522f209309cf6729c683226bfcf7f
|
7
|
+
data.tar.gz: d295dcd733856816a1c89810f4d54304a52c251d585afcc62b986a66d63e080e03ddc81bdc46cf51a044e29d2849ccce9bb3cb307a0757746e662394f648a717
|
data/History.md
CHANGED
@@ -1,10 +1,30 @@
|
|
1
|
+
# Version 3.33.0
|
2
|
+
Release date: 2020-06-21
|
3
|
+
|
4
|
+
### Added
|
5
|
+
|
6
|
+
* Block passed to `within_session` now receives the new and old session
|
7
|
+
* Support for aria-role button when enabled [Seiei Miyagi]
|
8
|
+
* Support for aria-role link when enabled
|
9
|
+
* Support for `validation_message` filter with :field and :fillable_field selectors
|
10
|
+
|
11
|
+
### Changed
|
12
|
+
|
13
|
+
* Ruby 2.5.0+ is now required
|
14
|
+
* Deprecated direct manupulation of the driver and server registries
|
15
|
+
|
16
|
+
### Fixed
|
17
|
+
|
18
|
+
* Ruby 2.7 warning in minitest `assert_text` [Eileen M. Uchitelle]
|
19
|
+
|
20
|
+
|
1
21
|
# Version 3.32.2
|
2
22
|
Release date: 2020-05-16
|
3
23
|
|
4
24
|
### Fixed
|
5
25
|
|
6
26
|
* Don't use lazy enumerator with JRuby due to leaking threads
|
7
|
-
* Ruby 2
|
27
|
+
* Ruby 2.7 deprecation warning when registering Webrick [Jon Zeppieri]
|
8
28
|
* `have_text` description [Juan Pablo Rinaldi]
|
9
29
|
|
10
30
|
# Version 3.32.1
|
data/README.md
CHANGED
@@ -7,7 +7,7 @@
|
|
7
7
|
[](https://gitter.im/jnicklas/capybara?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
8
8
|
[](https://dependabot.com/compatibility-score.html?dependency-name=capybara&package-manager=bundler&version-scheme=semver)
|
9
9
|
|
10
|
-
**Note** You are viewing the README for the 3.
|
10
|
+
**Note** You are viewing the README for the 3.33.x release of Capybara.
|
11
11
|
|
12
12
|
Capybara helps you test web applications by simulating how a real user would
|
13
13
|
interact with your app. It is agnostic about the driver running your tests and
|
@@ -76,7 +76,7 @@ GitHub): http://groups.google.com/group/ruby-capybara
|
|
76
76
|
|
77
77
|
## <a name="setup"></a>Setup
|
78
78
|
|
79
|
-
Capybara requires Ruby 2.
|
79
|
+
Capybara requires Ruby 2.5.0 or later. To install, add this line to your
|
80
80
|
`Gemfile` and run `bundle install`:
|
81
81
|
|
82
82
|
```ruby
|
@@ -149,7 +149,7 @@ require 'capybara/rspec'
|
|
149
149
|
|
150
150
|
If you are using Rails, put your Capybara specs in `spec/features` or `spec/system` (only works
|
151
151
|
if [you have it configured in
|
152
|
-
RSpec](https://
|
152
|
+
RSpec](https://relishapp.com/rspec/rspec-rails/v/4-0/docs/directory-structure))
|
153
153
|
and if you have your Capybara specs in a different directory, then tag the
|
154
154
|
example groups with `type: :feature` or `type: :system` depending on which type of test you're writing.
|
155
155
|
|
@@ -1055,6 +1055,13 @@ additional info about how the underlying driver can be configured.
|
|
1055
1055
|
are testing for specific server errors and using multiple sessions make sure to test for the
|
1056
1056
|
errors using the initial session (usually :default)
|
1057
1057
|
|
1058
|
+
* If WebMock is enabled, you may encounter a "Too many open files"
|
1059
|
+
error. A simple `page.find` call may cause thousands of HTTP requests
|
1060
|
+
until the timeout occurs. By default, WebMock will cause each of these
|
1061
|
+
requests to spawn a new connection. To work around this problem, you
|
1062
|
+
may need to [enable WebMock's `net_http_connect_on_start: true`
|
1063
|
+
parameter](https://github.com/bblimke/webmock/blob/master/README.md#connecting-on-nethttpstart).
|
1064
|
+
|
1058
1065
|
## <a name="threadsafe"></a>"Threadsafe" mode
|
1059
1066
|
|
1060
1067
|
In normal mode most of Capybara's configuration options are global settings which can cause issues
|
data/lib/capybara.rb
CHANGED
@@ -5,6 +5,7 @@ require 'nokogiri'
|
|
5
5
|
require 'xpath'
|
6
6
|
require 'forwardable'
|
7
7
|
require 'capybara/config'
|
8
|
+
require 'capybara/registration_container'
|
8
9
|
|
9
10
|
module Capybara
|
10
11
|
class CapybaraError < StandardError; end
|
@@ -81,6 +82,7 @@ module Capybara
|
|
81
82
|
# - **default_selector** (`:css`, `:xpath` = `:css`) - Methods which take a selector use the given type by default. See also {Capybara::Selector}.
|
82
83
|
# - **default_set_options** (Hash = `{}`) - The default options passed to {Capybara::Node::Element#set Element#set}.
|
83
84
|
# - **enable_aria_label** (Boolean = `false`) - Whether fields, links, and buttons will match against `aria-label` attribute.
|
85
|
+
# - **enable_aria_role** (Boolean = `false`) - Selectors will check for relevant aria role (currently only `button`).
|
84
86
|
# - **exact** (Boolean = `false`) - Whether locators are matched exactly or with substrings. Only affects selector conditions
|
85
87
|
# written using the `XPath#is` method.
|
86
88
|
# - **exact_text** (Boolean = `false`) - Whether the text matchers and `:text` filter match exactly or on substrings.
|
@@ -93,6 +95,7 @@ module Capybara
|
|
93
95
|
# - **save_path** (String = `Dir.pwd`) - Where to put pages saved through {Capybara::Session#save_page save_page}, {Capybara::Session#save_screenshot save_screenshot},
|
94
96
|
# {Capybara::Session#save_and_open_page save_and_open_page}, or {Capybara::Session#save_and_open_screenshot save_and_open_screenshot}.
|
95
97
|
# - **server** (Symbol = `:default` (which uses puma)) - The name of the registered server to use when running the app under test.
|
98
|
+
# - **server_port** (Integer) - The port Capybara will run the application server on, if not specified a random port will be used.
|
96
99
|
# - **server_errors** (Array\<Class> = `[Exception]`) - Error classes that should be raised in the tests if they are raised in the server
|
97
100
|
# and {configure raise_server_errors} is `true`.
|
98
101
|
# - **test_id** (Symbol, String, `nil` = `nil`) - Optional attribute to match locator against with built-in selectors along with id.
|
@@ -124,7 +127,7 @@ module Capybara
|
|
124
127
|
# @yieldreturn [Capybara::Driver::Base] A Capybara driver instance
|
125
128
|
#
|
126
129
|
def register_driver(name, &block)
|
127
|
-
drivers
|
130
|
+
drivers.send(:register, name, block)
|
128
131
|
end
|
129
132
|
|
130
133
|
##
|
@@ -143,7 +146,7 @@ module Capybara
|
|
143
146
|
# @yieldparam host The host/ip to bind to
|
144
147
|
#
|
145
148
|
def register_server(name, &block)
|
146
|
-
servers
|
149
|
+
servers.send(:register, name.to_sym, block)
|
147
150
|
end
|
148
151
|
|
149
152
|
##
|
@@ -197,11 +200,11 @@ module Capybara
|
|
197
200
|
end
|
198
201
|
|
199
202
|
def drivers
|
200
|
-
@drivers ||=
|
203
|
+
@drivers ||= RegistrationContainer.new
|
201
204
|
end
|
202
205
|
|
203
206
|
def servers
|
204
|
-
@servers ||=
|
207
|
+
@servers ||= RegistrationContainer.new
|
205
208
|
end
|
206
209
|
|
207
210
|
# Wraps the given string, which should contain an HTML document or fragment
|
@@ -349,7 +352,8 @@ module Capybara
|
|
349
352
|
#
|
350
353
|
# Yield a block using a specific session name or {Capybara::Session} instance.
|
351
354
|
#
|
352
|
-
def using_session(name_or_session)
|
355
|
+
def using_session(name_or_session, &block)
|
356
|
+
previous_session = current_session
|
353
357
|
previous_session_info = {
|
354
358
|
specified_session: specified_session,
|
355
359
|
session_name: session_name,
|
@@ -362,7 +366,12 @@ module Capybara
|
|
362
366
|
else
|
363
367
|
self.session_name = name_or_session
|
364
368
|
end
|
365
|
-
|
369
|
+
|
370
|
+
if block.arity.zero?
|
371
|
+
yield
|
372
|
+
else
|
373
|
+
yield current_session, previous_session
|
374
|
+
end
|
366
375
|
ensure
|
367
376
|
self.session_name, self.specified_session = previous_session_info.values_at(:session_name, :specified_session)
|
368
377
|
self.current_driver, self.app = previous_session_info.values_at(:current_driver, :app) if threadsafe
|
@@ -394,7 +403,7 @@ module Capybara
|
|
394
403
|
template.inner_html = ''
|
395
404
|
end
|
396
405
|
document.xpath('//textarea').each do |textarea|
|
397
|
-
textarea['_capybara_raw_value'] = textarea.content.
|
406
|
+
textarea['_capybara_raw_value'] = textarea.content.delete_prefix("\n")
|
398
407
|
end
|
399
408
|
end
|
400
409
|
end
|
@@ -501,6 +510,7 @@ Capybara.configure do |config|
|
|
501
510
|
config.visible_text_only = false
|
502
511
|
config.automatic_label_click = false
|
503
512
|
config.enable_aria_label = false
|
513
|
+
config.enable_aria_role = false
|
504
514
|
config.reuse_server = true
|
505
515
|
config.default_set_options = {}
|
506
516
|
config.test_id = nil
|
data/lib/capybara/cucumber.rb
CHANGED
@@ -22,6 +22,6 @@ end
|
|
22
22
|
Before do |scenario|
|
23
23
|
scenario.source_tag_names.each do |tag|
|
24
24
|
driver_name = tag.sub(/^@/, '').to_sym
|
25
|
-
Capybara.current_driver = driver_name if Capybara.drivers
|
25
|
+
Capybara.current_driver = driver_name if Capybara.drivers[driver_name]
|
26
26
|
end
|
27
27
|
end
|
data/lib/capybara/minitest.rb
CHANGED
@@ -50,15 +50,14 @@ module Capybara
|
|
50
50
|
|
51
51
|
%w[text no_text title no_title current_path no_current_path].each do |assertion_name|
|
52
52
|
class_eval <<-ASSERTION, __FILE__, __LINE__ + 1
|
53
|
-
def assert_#{assertion_name}
|
53
|
+
def assert_#{assertion_name}(*args, **kwargs)
|
54
54
|
self.assertions +=1
|
55
55
|
subject, args = determine_subject(args)
|
56
|
-
subject.assert_#{assertion_name}(*args)
|
56
|
+
subject.assert_#{assertion_name}(*args, **kwargs)
|
57
57
|
rescue Capybara::ExpectationNotMet => e
|
58
58
|
raise ::Minitest::Assertion, e.message
|
59
59
|
end
|
60
60
|
ASSERTION
|
61
|
-
ruby2_keywords "assert_#{assertion_name}" if respond_to?(:ruby2_keywords)
|
62
61
|
end
|
63
62
|
|
64
63
|
alias_method :refute_title, :assert_no_title
|
@@ -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
|
@@ -367,18 +365,16 @@ module Capybara
|
|
367
365
|
options[:allow_self] = true if locator.nil?
|
368
366
|
|
369
367
|
synchronize(Capybara::Queries::BaseQuery.wait(options, session_options.default_max_wait_time)) do
|
368
|
+
el = find(selector, locator, **options)
|
369
|
+
el.set(checked)
|
370
|
+
rescue StandardError => e
|
371
|
+
raise unless allow_label_click && catch_error?(e)
|
372
|
+
|
370
373
|
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
|
374
|
+
el ||= find(selector, locator, **options.merge(visible: :all))
|
375
|
+
el.session.find(:label, for: el, visible: true).click unless el.checked? == checked
|
376
|
+
rescue StandardError # swallow extra errors - raise original
|
377
|
+
raise e
|
382
378
|
end
|
383
379
|
end
|
384
380
|
end
|
@@ -201,12 +201,10 @@ module Capybara
|
|
201
201
|
selector = extract_selector(args)
|
202
202
|
synchronize(wait) do
|
203
203
|
res = args.map do |locator|
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
e.message
|
209
|
-
end
|
204
|
+
assert_selector(selector, locator, options, &optional_filter_block)
|
205
|
+
break nil
|
206
|
+
rescue Capybara::ExpectationNotMet => e
|
207
|
+
e.message
|
210
208
|
end
|
211
209
|
raise Capybara::ExpectationNotMet, res.join(' or ') if res
|
212
210
|
|
@@ -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
|
|
@@ -575,6 +581,7 @@ module Capybara
|
|
575
581
|
|
576
582
|
class Rectangle
|
577
583
|
attr_reader :top, :bottom, :left, :right
|
584
|
+
|
578
585
|
def initialize(position)
|
579
586
|
# rubocop:disable Style/RescueModifier
|
580
587
|
@top = position['top'] rescue position['y']
|
@@ -6,6 +6,8 @@ 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, '${@type} is not a valid type for a text query' unless valid_types.include?(@type)
|
10
|
+
|
9
11
|
@options = options
|
10
12
|
super(@options)
|
11
13
|
self.session_options = session_options
|
@@ -89,6 +91,10 @@ module Capybara
|
|
89
91
|
COUNT_KEYS + %i[wait exact normalize_ws]
|
90
92
|
end
|
91
93
|
|
94
|
+
def valid_types
|
95
|
+
%i[all visible]
|
96
|
+
end
|
97
|
+
|
92
98
|
def check_visible_text?
|
93
99
|
@type == :visible
|
94
100
|
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Capybara
|
4
|
+
# @api private
|
5
|
+
class RegistrationContainer
|
6
|
+
def names
|
7
|
+
@registered.keys
|
8
|
+
end
|
9
|
+
|
10
|
+
def [](name)
|
11
|
+
@registered[name]
|
12
|
+
end
|
13
|
+
|
14
|
+
def []=(name, value)
|
15
|
+
warn 'DEPRECATED: Directly setting drivers/servers is deprecated, please use Capybara.register_driver/register_server instead'
|
16
|
+
@registered[name] = value
|
17
|
+
end
|
18
|
+
|
19
|
+
def method_missing(method_name, *args, **options, &block)
|
20
|
+
if @registered.respond_to?(method_name)
|
21
|
+
warn "DEPRECATED: Calling '#{method_name}' on the drivers/servers container is deprecated without replacement"
|
22
|
+
# RUBY 2.6 will send an empty hash rather than nothing with **options so fix that
|
23
|
+
return @registered.public_send(method_name, *args, &block) if options.empty?
|
24
|
+
|
25
|
+
return @registered.public_send(method_name, *args, **options, &block)
|
26
|
+
end
|
27
|
+
super
|
28
|
+
end
|
29
|
+
|
30
|
+
def respond_to_missing?(method_name, include_private = false)
|
31
|
+
@registered.respond_to?(method_name) || super
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def initialize
|
37
|
+
@registered = {}
|
38
|
+
end
|
39
|
+
|
40
|
+
def register(name, block)
|
41
|
+
@registered[name] = block
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
data/lib/capybara/selector.rb
CHANGED
@@ -40,6 +40,7 @@ require 'capybara/selector/definition'
|
|
40
40
|
# * :disabled (Boolean, :all) - Match disabled field? (Default: false)
|
41
41
|
# * :multiple (Boolean) - Match fields that accept multiple values
|
42
42
|
# * :valid (Boolean) - Match fields that are valid/invalid according to HTML5 form validation
|
43
|
+
# * :validation_message (String, Regexp) - Matches the elements current validationMessage
|
43
44
|
#
|
44
45
|
# * **:fieldset** - Select fieldset elements
|
45
46
|
# * Locator: Matches id, {Capybara.configure test_id}, or contents of wrapped legend
|
@@ -79,6 +80,7 @@ require 'capybara/selector/definition'
|
|
79
80
|
# * :disabled (Boolean, :all) - Match disabled field? (Default: false)
|
80
81
|
# * :multiple (Boolean) - Match fields that accept multiple values
|
81
82
|
# * :valid (Boolean) - Match fields that are valid/invalid according to HTML5 form validation
|
83
|
+
# * :validation_message (String, Regexp) - Matches the elements current validationMessage
|
82
84
|
#
|
83
85
|
# * **:radio_button** - Find radio buttons
|
84
86
|
# * Locator: Match id, {Capybara.configure test_id} attribute, name, or associated label text
|
@@ -178,6 +180,12 @@ Capybara::Selector::FilterSet.add(:_field) do
|
|
178
180
|
node_filter(:valid, :boolean) { |node, value| node.evaluate_script('this.validity.valid') == value }
|
179
181
|
node_filter(:name) { |node, value| !value.is_a?(Regexp) || value.match?(node[:name]) }
|
180
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
|
181
189
|
|
182
190
|
expression_filter(:name) do |xpath, val|
|
183
191
|
builder(xpath).add_attribute_conditions(name: val)
|
@@ -198,7 +206,7 @@ Capybara::Selector::FilterSet.add(:_field) do
|
|
198
206
|
desc
|
199
207
|
end
|
200
208
|
|
201
|
-
describe(:node_filters) do |checked: nil, unchecked: nil, disabled: nil, valid: nil, **|
|
209
|
+
describe(:node_filters) do |checked: nil, unchecked: nil, disabled: nil, valid: nil, validation_message: nil, **|
|
202
210
|
desc, states = +'', []
|
203
211
|
states << 'checked' if checked || (unchecked == false)
|
204
212
|
states << 'not checked' if unchecked || (checked == false)
|
@@ -206,6 +214,7 @@ Capybara::Selector::FilterSet.add(:_field) do
|
|
206
214
|
desc << " that is #{states.join(' and ')}" unless states.empty?
|
207
215
|
desc << ' that is valid' if valid == true
|
208
216
|
desc << ' that is invalid' if valid == false
|
217
|
+
desc << " with validation message #{validation_message.to_s.inspect}" if validation_message
|
209
218
|
desc
|
210
219
|
end
|
211
220
|
end
|
@@ -10,6 +10,7 @@ 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)
|
@@ -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
|
@@ -251,9 +252,9 @@ 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
|
|