capybara 3.34.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 +21 -3
- data/lib/capybara/node/base.rb +6 -6
- data/lib/capybara/node/matchers.rb +1 -1
- data/lib/capybara/queries/selector_query.rb +24 -8
- data/lib/capybara/registrations/drivers.rb +18 -12
- data/lib/capybara/registrations/servers.rb +1 -1
- data/lib/capybara/result.rb +3 -3
- data/lib/capybara/selector.rb +2 -2
- 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/button.rb +23 -14
- data/lib/capybara/selector/definition/table_row.rb +1 -1
- data/lib/capybara/selenium/atoms/src/isDisplayed.js +1 -1
- data/lib/capybara/selenium/driver.rb +20 -4
- data/lib/capybara/selenium/extensions/find.rb +1 -1
- data/lib/capybara/selenium/logger_suppressor.rb +1 -1
- data/lib/capybara/selenium/nodes/chrome_node.rb +3 -3
- data/lib/capybara/selenium/nodes/firefox_node.rb +6 -1
- data/lib/capybara/server/animation_disabler.rb +6 -2
- data/lib/capybara/spec/session/has_button_spec.rb +33 -0
- data/lib/capybara/spec/session/html_spec.rb +1 -1
- data/lib/capybara/spec/session/node_spec.rb +1 -1
- data/lib/capybara/spec/session/refresh_spec.rb +1 -1
- 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/test_app.rb +1 -0
- data/lib/capybara/spec/views/form.erb +4 -0
- data/lib/capybara/spec/views/with_jquery_animation.erb +24 -0
- data/lib/capybara/spec/views/with_js.erb +1 -0
- data/lib/capybara/version.rb +1 -1
- data/spec/selector_spec.rb +15 -1
- data/spec/selenium_spec_chrome.rb +39 -18
- data/spec/selenium_spec_chrome_remote.rb +5 -1
- data/spec/selenium_spec_firefox.rb +15 -13
- data/spec/server_spec.rb +6 -2
- data/spec/shared_selenium_session.rb +14 -0
- metadata +46 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 00bf1cfd1e72093422fb61df1dae86d72948e8026d57fb00084d5bedceb0967e
|
4
|
+
data.tar.gz: 65a8c6b66d1ef91586ca39f7eabcf800019f853e33e087d1bb65f02a85140c8b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f961de052aa75cb3e3a941ea031d40d6d0f1fc2a9a80190c7dbe2f7d8e96b462fa71d4ed96d4dc45687e2baaf151579ca4508a2753a6e2073814857e2dee9bb4
|
7
|
+
data.tar.gz: 4b02c84f7bd1d9da419e3f43848da87290ba303541df516e6217fd3fc2e4cf5263e212e9a4a5329c8505b2f6111c0ce6ea17537ea3099b04f12c9b662d364088
|
data/History.md
CHANGED
@@ -1,13 +1,31 @@
|
|
1
|
+
# Version 3.35.0
|
2
|
+
Release date: 2020-01-25
|
3
|
+
|
4
|
+
### Added
|
5
|
+
|
6
|
+
* Support Regexp matching for individual class names in :class filter passed an Array
|
7
|
+
* Animation disabler now supports JQuery animation disabling when JQuery loaded from body [Chien-Wei Huang]
|
8
|
+
|
9
|
+
### Fixed
|
10
|
+
|
11
|
+
* :button selector type use with `enable_aria_role` [Sean Doyle]
|
12
|
+
* <label> elements don't associate with aria-role buttons
|
13
|
+
* Ignore Selenium::WebDriver::Error::InvalidSessionIdError when quitting driver [Robin Daugherty]
|
14
|
+
* Firefox: Don't click input when sending keys if already focused
|
15
|
+
* Miscellaneous issues with selenium-webdriver 4.0.0.alphas
|
16
|
+
* Nil return error in node details optimizations
|
17
|
+
* Animation disabler now inserts XHTML compliant content [Dale Morgan]
|
18
|
+
|
1
19
|
# Version 3.34.0
|
2
20
|
Release date: 2020-11-26
|
3
21
|
|
4
22
|
### Added
|
5
23
|
|
6
24
|
* Ability to fill in with emoji when using Chrome with selenium driver (Firefox already worked)
|
7
|
-
* Current path
|
25
|
+
* Current path assertions/expectations accept optional filter block
|
8
26
|
* Animation disabler now specifies `scroll-behavior: auto;` [Nathan Broadbent]
|
9
27
|
* :button selector can now find elements by label text [Sean Doyle]
|
10
|
-
* `Session#send_keys` to send keys to the current element with focus in drivers that support the
|
28
|
+
* `Session#send_keys` to send keys to the current element with focus in drivers that support the
|
11
29
|
concept of a current element [Sean Doyle]
|
12
30
|
|
13
31
|
### Changed
|
@@ -21,7 +39,7 @@ Release date: 2020-11-26
|
|
21
39
|
* Missing `readonly?` added to Node::Simple
|
22
40
|
* Selenium version detection when loaded via alternate method [Joel Hawksley]
|
23
41
|
* Connection count issue if REQUEST_URI value changed by app [Blake Williams]
|
24
|
-
* Maintain URI fragment when redirecting in rack-test driver
|
42
|
+
* Maintain URI fragment when redirecting in rack-test driver
|
25
43
|
* Text query error message [Wojciech Wnętrzak]
|
26
44
|
* Checking a checkbox/radio button with `allow_label_click` now works if there are multiple labels (Issue #2421)
|
27
45
|
* `drop` with `Pathname` (Issue #2424)[Máximo Mussini]
|
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
|
|
@@ -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
|
@@ -239,16 +239,16 @@ module Capybara
|
|
239
239
|
|
240
240
|
case selector_format
|
241
241
|
when :css
|
242
|
-
if node.method(:find_css).arity
|
243
|
-
node.find_css(css, **hints)
|
244
|
-
else
|
242
|
+
if node.method(:find_css).arity == 1
|
245
243
|
node.find_css(css)
|
244
|
+
else
|
245
|
+
node.find_css(css, **hints)
|
246
246
|
end
|
247
247
|
when :xpath
|
248
|
-
if node.method(:find_xpath).arity
|
249
|
-
node.find_xpath(xpath(exact), **hints)
|
250
|
-
else
|
248
|
+
if node.method(:find_xpath).arity == 1
|
251
249
|
node.find_xpath(xpath(exact))
|
250
|
+
else
|
251
|
+
node.find_xpath(xpath(exact), **hints)
|
252
252
|
end
|
253
253
|
else
|
254
254
|
raise ArgumentError, "Unknown format: #{selector_format}"
|
@@ -482,9 +482,25 @@ module Capybara
|
|
482
482
|
end
|
483
483
|
|
484
484
|
def matches_class_filter?(node)
|
485
|
-
return true unless use_default_class_filter? &&
|
485
|
+
return true unless use_default_class_filter? && need_to_process_classes?
|
486
486
|
|
487
|
-
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
|
488
504
|
end
|
489
505
|
|
490
506
|
def matches_style_filter?(node)
|
@@ -9,28 +9,34 @@ Capybara.register_driver :selenium do |app|
|
|
9
9
|
end
|
10
10
|
|
11
11
|
Capybara.register_driver :selenium_headless do |app|
|
12
|
-
Capybara::Selenium::Driver.load_selenium
|
13
|
-
|
14
|
-
browser_options.
|
15
|
-
|
12
|
+
version = Capybara::Selenium::Driver.load_selenium
|
13
|
+
options_key = Capybara::Selenium::Driver::CAPS_VERSION.satisfied_by?(version) ? :capabilities : :options
|
14
|
+
browser_options = ::Selenium::WebDriver::Firefox::Options.new.tap do |opts|
|
15
|
+
opts.add_argument '-headless'
|
16
|
+
end
|
17
|
+
Capybara::Selenium::Driver.new(app, **Hash[:browser => :firefox, options_key => browser_options])
|
16
18
|
end
|
17
19
|
|
18
20
|
Capybara.register_driver :selenium_chrome do |app|
|
19
|
-
Capybara::Selenium::Driver.load_selenium
|
21
|
+
version = Capybara::Selenium::Driver.load_selenium
|
22
|
+
options_key = Capybara::Selenium::Driver::CAPS_VERSION.satisfied_by?(version) ? :capabilities : :options
|
20
23
|
browser_options = ::Selenium::WebDriver::Chrome::Options.new.tap do |opts|
|
21
24
|
# Workaround https://bugs.chromium.org/p/chromedriver/issues/detail?id=2650&q=load&sort=-id&colspec=ID%20Status%20Pri%20Owner%20Summary
|
22
|
-
opts.
|
25
|
+
opts.add_argument('--disable-site-isolation-trials')
|
23
26
|
end
|
24
|
-
|
27
|
+
|
28
|
+
Capybara::Selenium::Driver.new(app, **Hash[:browser => :firefox, options_key => browser_options])
|
25
29
|
end
|
26
30
|
|
27
31
|
Capybara.register_driver :selenium_chrome_headless do |app|
|
28
|
-
Capybara::Selenium::Driver.load_selenium
|
32
|
+
version = Capybara::Selenium::Driver.load_selenium
|
33
|
+
options_key = Capybara::Selenium::Driver::CAPS_VERSION.satisfied_by?(version) ? :capabilities : :options
|
29
34
|
browser_options = ::Selenium::WebDriver::Chrome::Options.new.tap do |opts|
|
30
|
-
opts.
|
31
|
-
opts.
|
35
|
+
opts.add_argument('--headless')
|
36
|
+
opts.add_argument('--disable-gpu') if Gem.win_platform?
|
32
37
|
# Workaround https://bugs.chromium.org/p/chromedriver/issues/detail?id=2650&q=load&sort=-id&colspec=ID%20Status%20Pri%20Owner%20Summary
|
33
|
-
opts.
|
38
|
+
opts.add_argument('--disable-site-isolation-trials')
|
34
39
|
end
|
35
|
-
|
40
|
+
|
41
|
+
Capybara::Selenium::Driver.new(app, **Hash[:browser => :firefox, options_key => browser_options])
|
36
42
|
end
|
@@ -32,7 +32,7 @@ Capybara.register_server :puma do |app, port, host, **options|
|
|
32
32
|
events = conf.options[:Silent] ? ::Puma::Events.strings : ::Puma::Events.stdio
|
33
33
|
|
34
34
|
puma_ver = Gem::Version.new(Puma::Const::PUMA_VERSION)
|
35
|
-
require_relative 'patches/puma_ssl' if
|
35
|
+
require_relative 'patches/puma_ssl' if Gem::Requirement.new('>=4.0.0', '< 4.1.0').satisfied_by?(puma_ver)
|
36
36
|
|
37
37
|
events.log 'Capybara starting Puma...'
|
38
38
|
events.log "* Version #{Puma::Const::PUMA_VERSION} , codename: #{Puma::Const::CODE_NAME}"
|
data/lib/capybara/result.rb
CHANGED
@@ -54,10 +54,10 @@ module Capybara
|
|
54
54
|
idx, length = args
|
55
55
|
max_idx = case idx
|
56
56
|
when Integer
|
57
|
-
if
|
58
|
-
length.nil? ? idx : idx + length - 1
|
59
|
-
else
|
57
|
+
if idx.negative?
|
60
58
|
nil
|
59
|
+
else
|
60
|
+
length.nil? ? idx : idx + length - 1
|
61
61
|
end
|
62
62
|
when Range
|
63
63
|
# idx.max is broken with beginless ranges
|
data/lib/capybara/selector.rb
CHANGED
@@ -7,7 +7,7 @@ require 'capybara/selector/definition'
|
|
7
7
|
#
|
8
8
|
# All Selectors below support the listed selector specific filters in addition to the following system-wide filters
|
9
9
|
# * :id (String, Regexp, XPath::Expression) - Matches the id attribute
|
10
|
-
# * :class (String, Array<String>, Regexp, XPath::Expression) - Matches the class(es) provided
|
10
|
+
# * :class (String, Array<String | Regexp>, Regexp, XPath::Expression) - Matches the class(es) provided
|
11
11
|
# * :style (String, Regexp, Hash<String, String>) - Match on elements style
|
12
12
|
# * :above (Element) - Match elements above the passed element on the page
|
13
13
|
# * :below (Element) - Match elements below the passed element on the page
|
@@ -171,7 +171,7 @@ require 'capybara/selector/definition'
|
|
171
171
|
# * Filters:
|
172
172
|
# * :\<any> (String, Regexp) - Match on any specified element attribute
|
173
173
|
#
|
174
|
-
class Capybara::Selector; end
|
174
|
+
class Capybara::Selector; end # rubocop:disable Lint/EmptyClass
|
175
175
|
|
176
176
|
Capybara::Selector::FilterSet.add(:_field) do
|
177
177
|
node_filter(:checked, :boolean) { |node, value| !(value ^ node.checked?) }
|
@@ -74,7 +74,7 @@ module Capybara
|
|
74
74
|
end.join
|
75
75
|
end
|
76
76
|
else
|
77
|
-
cls = Array(classes).group_by { |cl| cl.match?(/^!(?!!!)/) }
|
77
|
+
cls = Array(classes).reject { |c| c.is_a? Regexp }.group_by { |cl| cl.match?(/^!(?!!!)/) }
|
78
78
|
[(cls[false].to_a.map { |cl| ".#{Capybara::Selector::CSS.escape(cl.sub(/^!!/, ''))}" } +
|
79
79
|
cls[true].to_a.map { |cl| ":not(.#{Capybara::Selector::CSS.escape(cl.slice(1..-1))})" }).join]
|
80
80
|
end
|
@@ -15,6 +15,8 @@ module Capybara
|
|
15
15
|
def add_attribute_conditions(**conditions)
|
16
16
|
@expression = conditions.inject(expression) do |xp, (name, value)|
|
17
17
|
conditions = name == :class ? class_conditions(value) : attribute_conditions(name => value)
|
18
|
+
return xp if conditions.nil?
|
19
|
+
|
18
20
|
if xp.is_a? XPath::Expression
|
19
21
|
xp[conditions]
|
20
22
|
else
|
@@ -47,7 +49,7 @@ module Capybara
|
|
47
49
|
when XPath::Expression, Regexp
|
48
50
|
attribute_conditions(class: classes)
|
49
51
|
else
|
50
|
-
Array(classes).map do |klass|
|
52
|
+
Array(classes).reject { |c| c.is_a? Regexp }.map do |klass|
|
51
53
|
if klass.match?(/^!(?!!!)/)
|
52
54
|
!XPath.attr(:class).contains_word(klass.slice(1..-1))
|
53
55
|
else
|
@@ -4,32 +4,29 @@ Capybara.add_selector(:button, locator_type: [String, Symbol]) do
|
|
4
4
|
xpath(:value, :title, :type, :name) do |locator, **options|
|
5
5
|
input_btn_xpath = XPath.descendant(:input)[XPath.attr(:type).one_of('submit', 'reset', 'image', 'button')]
|
6
6
|
btn_xpath = XPath.descendant(:button)
|
7
|
-
|
7
|
+
aria_btn_xpath = XPath.descendant[XPath.attr(:role).equals('button')]
|
8
8
|
image_btn_xpath = XPath.descendant(:input)[XPath.attr(:type) == 'image']
|
9
9
|
|
10
10
|
unless locator.nil?
|
11
11
|
locator = locator.to_s
|
12
|
-
locator_matchers =
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
(XPath.attr(:id) == XPath.anywhere(:label)[XPath.string.n.is(locator)].attr(:for))
|
17
|
-
locator_matchers |= XPath.attr(:'aria-label').is(locator) if enable_aria_label
|
18
|
-
locator_matchers |= XPath.attr(test_id) == locator if test_id
|
12
|
+
locator_matchers = combine_locators(locator, config: self)
|
13
|
+
btn_matchers = locator_matchers |
|
14
|
+
XPath.string.n.is(locator) |
|
15
|
+
XPath.descendant(:img)[XPath.attr(:alt).is(locator)]
|
19
16
|
|
20
17
|
input_btn_xpath = input_btn_xpath[locator_matchers] + locate_label(locator).descendant(input_btn_xpath)
|
21
|
-
|
22
|
-
|
23
|
-
XPath.string.n.is(locator) |
|
24
|
-
XPath.descendant(:img)[XPath.attr(:alt).is(locator)]
|
25
|
-
] + locate_label(locator).descendant(btn_xpath)
|
18
|
+
btn_xpath = btn_xpath[btn_matchers] + locate_label(locator).descendant(btn_xpath)
|
19
|
+
aria_btn_xpath = aria_btn_xpath[btn_matchers]
|
26
20
|
|
27
21
|
alt_matches = XPath.attr(:alt).is(locator)
|
28
22
|
alt_matches |= XPath.attr(:'aria-label').is(locator) if enable_aria_label
|
29
23
|
image_btn_xpath = image_btn_xpath[alt_matches] + locate_label(locator).descendant(image_btn_xpath)
|
30
24
|
end
|
31
25
|
|
32
|
-
|
26
|
+
btn_xpaths = [input_btn_xpath, btn_xpath, image_btn_xpath]
|
27
|
+
btn_xpaths << aria_btn_xpath if enable_aria_role
|
28
|
+
|
29
|
+
%i[value title type].inject(btn_xpaths.inject(&:union)) do |memo, ef|
|
33
30
|
memo.where(find_by_attr(ef, options[ef]))
|
34
31
|
end
|
35
32
|
end
|
@@ -51,4 +48,16 @@ Capybara.add_selector(:button, locator_type: [String, Symbol]) do
|
|
51
48
|
describe_node_filters do |disabled: nil, **|
|
52
49
|
' that is disabled' if disabled == true
|
53
50
|
end
|
51
|
+
|
52
|
+
def combine_locators(locator, config:)
|
53
|
+
[
|
54
|
+
XPath.attr(:id).equals(locator),
|
55
|
+
XPath.attr(:name).equals(locator),
|
56
|
+
XPath.attr(:value).is(locator),
|
57
|
+
XPath.attr(:title).is(locator),
|
58
|
+
(XPath.attr(:id) == XPath.anywhere(:label)[XPath.string.n.is(locator)].attr(:for)),
|
59
|
+
(XPath.attr(:'aria-label').is(locator) if config.enable_aria_label),
|
60
|
+
(XPath.attr(test_id) == locator if config.test_id)
|
61
|
+
].compact.inject(&:|)
|
62
|
+
end
|
54
63
|
end
|
@@ -9,7 +9,7 @@ Capybara.add_selector(:table_row, locator_type: [Array, Hash]) do
|
|
9
9
|
cell_xp = XPath.descendant(:td)[
|
10
10
|
XPath.string.n.is(cell) & XPath.position.equals(header_xp.preceding_sibling.count.plus(1))
|
11
11
|
]
|
12
|
-
xp
|
12
|
+
xp.where(cell_xp)
|
13
13
|
end
|
14
14
|
else
|
15
15
|
initial_td = XPath.descendant(:td)[XPath.string.n.is(locator.shift)]
|
@@ -158,7 +158,7 @@
|
|
158
158
|
// the overflow style of the body, and the body is really overflow:visible.
|
159
159
|
var overflowElem = e;
|
160
160
|
if (htmlOverflowStyle == "visible") {
|
161
|
-
//
|
161
|
+
// NOTE: bodyElem will be null/undefined in SVG documents.
|
162
162
|
if (e == htmlElem && bodyElem) {
|
163
163
|
overflowElem = bodyElem;
|
164
164
|
} else if (e == bodyElem) {
|
@@ -12,9 +12,13 @@ class Capybara::Selenium::Driver < Capybara::Driver::Base
|
|
12
12
|
clear_session_storage: nil
|
13
13
|
}.freeze
|
14
14
|
SPECIAL_OPTIONS = %i[browser clear_local_storage clear_session_storage timeout native_displayed].freeze
|
15
|
+
CAPS_VERSION = Gem::Requirement.new('~> 4.0.0.alpha6')
|
16
|
+
|
15
17
|
attr_reader :app, :options
|
16
18
|
|
17
19
|
class << self
|
20
|
+
attr_reader :selenium_webdriver_version
|
21
|
+
|
18
22
|
def load_selenium
|
19
23
|
require 'selenium-webdriver'
|
20
24
|
require 'capybara/selenium/logger_suppressor'
|
@@ -32,15 +36,18 @@ class Capybara::Selenium::Driver < Capybara::Driver::Base
|
|
32
36
|
# Selenium::WebDriver::VERSION. Ideally we'd
|
33
37
|
# use the constant in all cases, but earlier versions
|
34
38
|
# of `selenium-webdriver` didn't provide the constant.
|
35
|
-
selenium_webdriver_version =
|
39
|
+
@selenium_webdriver_version =
|
36
40
|
if Gem.loaded_specs['selenium-webdriver']
|
37
41
|
Gem.loaded_specs['selenium-webdriver'].version
|
38
42
|
else
|
39
43
|
Gem::Version.new(Selenium::WebDriver::VERSION)
|
40
44
|
end
|
41
|
-
|
45
|
+
|
46
|
+
unless Gem::Requirement.new('>= 3.5.0').satisfied_by? @selenium_webdriver_version
|
42
47
|
warn "Warning: You're using an unsupported version of selenium-webdriver, please upgrade."
|
43
48
|
end
|
49
|
+
|
50
|
+
@selenium_webdriver_version
|
44
51
|
rescue LoadError => e
|
45
52
|
raise e unless e.message.include?('selenium-webdriver')
|
46
53
|
|
@@ -66,7 +73,15 @@ class Capybara::Selenium::Driver < Capybara::Driver::Base
|
|
66
73
|
end
|
67
74
|
end
|
68
75
|
processed_options = options.reject { |key, _val| SPECIAL_OPTIONS.include?(key) }
|
69
|
-
|
76
|
+
|
77
|
+
@browser = if options[:browser] == :firefox &&
|
78
|
+
RUBY_VERSION >= '3.0' &&
|
79
|
+
Capybara::Selenium::Driver.selenium_webdriver_version <= Gem::Version.new('4.0.0.alpha1')
|
80
|
+
# selenium-webdriver 3.x doesn't correctly pass options through for Firefox with Ruby 3 so workaround that
|
81
|
+
Selenium::WebDriver::Firefox::Driver.new(**processed_options)
|
82
|
+
else
|
83
|
+
Selenium::WebDriver.for(options[:browser], processed_options)
|
84
|
+
end
|
70
85
|
|
71
86
|
specialize_driver
|
72
87
|
setup_exit_handler
|
@@ -265,7 +280,8 @@ class Capybara::Selenium::Driver < Capybara::Driver::Base
|
|
265
280
|
|
266
281
|
def quit
|
267
282
|
@browser&.quit
|
268
|
-
rescue Selenium::WebDriver::Error::SessionNotCreatedError, Errno::ECONNREFUSED
|
283
|
+
rescue Selenium::WebDriver::Error::SessionNotCreatedError, Errno::ECONNREFUSED,
|
284
|
+
Selenium::WebDriver::Error::InvalidSessionIdError
|
269
285
|
# Browser must have already gone
|
270
286
|
rescue Selenium::WebDriver::Error::UnknownError => e
|
271
287
|
unless silenced_unknown_error_message?(e.message) # Most likely already gone
|
@@ -28,7 +28,7 @@ module Capybara
|
|
28
28
|
hints_js, functions = build_hints_js(uses_visibility, styles, position)
|
29
29
|
return [] unless functions.any?
|
30
30
|
|
31
|
-
es_context.execute_script(hints_js, elements).map! do |results|
|
31
|
+
(es_context.execute_script(hints_js, elements) || []).map! do |results|
|
32
32
|
hint = {}
|
33
33
|
hint[:style] = results.pop if functions.include?(:style_func)
|
34
34
|
hint[:position] = results.pop if functions.include?(:position_func)
|
@@ -118,15 +118,15 @@ private
|
|
118
118
|
end
|
119
119
|
|
120
120
|
def chromedriver_fixed_actions_key_state?
|
121
|
-
Gem::
|
121
|
+
Gem::Requirement.new('>= 76.0.3809.68').satisfied_by?(chromedriver_version)
|
122
122
|
end
|
123
123
|
|
124
124
|
def chromedriver_supports_displayed_endpoint?
|
125
|
-
Gem::
|
125
|
+
Gem::Requirement.new('>= 76.0.3809.25').satisfied_by?(chromedriver_version)
|
126
126
|
end
|
127
127
|
|
128
128
|
def chromedriver_version
|
129
|
-
capabilities['chrome']['chromedriverVersion'].split(' ')[0]
|
129
|
+
Gem::Version.new(capabilities['chrome']['chromedriverVersion'].split(' ')[0]) # rubocop:disable Style/RedundantArgument
|
130
130
|
end
|
131
131
|
|
132
132
|
def native_displayed?
|
@@ -40,11 +40,16 @@ class Capybara::Selenium::FirefoxNode < Capybara::Selenium::Node
|
|
40
40
|
path_names.each { |path| native.send_keys(path) }
|
41
41
|
end
|
42
42
|
|
43
|
+
def focused?
|
44
|
+
driver.evaluate_script('arguments[0] == document.activeElement', self)
|
45
|
+
end
|
46
|
+
|
43
47
|
def send_keys(*args)
|
44
48
|
# https://github.com/mozilla/geckodriver/issues/846
|
45
49
|
return super(*args.map { |arg| arg == :space ? ' ' : arg }) if args.none?(Array)
|
46
50
|
|
47
|
-
native.click
|
51
|
+
native.click unless focused?
|
52
|
+
|
48
53
|
_send_keys(args).perform
|
49
54
|
end
|
50
55
|
|
@@ -40,11 +40,15 @@ module Capybara
|
|
40
40
|
end
|
41
41
|
|
42
42
|
def insert_disable(html)
|
43
|
-
html.sub(%r{(</
|
43
|
+
html.sub(%r{(</body>)}, "#{disable_markup}\\1")
|
44
44
|
end
|
45
45
|
|
46
46
|
DISABLE_MARKUP_TEMPLATE = <<~HTML
|
47
|
-
<script
|
47
|
+
<script>
|
48
|
+
//<![CDATA[
|
49
|
+
(typeof jQuery !== 'undefined') && (jQuery.fx.off = true);
|
50
|
+
//]]>
|
51
|
+
</script>
|
48
52
|
<style>
|
49
53
|
%<selector>s, %<selector>s::before, %<selector>s::after {
|
50
54
|
transition: none !important;
|
@@ -46,9 +46,25 @@ Capybara::SpecHelper.spec '#has_button?' do
|
|
46
46
|
expect(@session).to have_button('ARIA button', enable_aria_role: true)
|
47
47
|
end
|
48
48
|
|
49
|
+
it 'should be false for a role=button within a label when enable_aria_role: true' do
|
50
|
+
expect(@session).not_to have_button('role=button within label', enable_aria_role: true)
|
51
|
+
end
|
52
|
+
|
49
53
|
it 'should be false for role=button when enable_aria_role: false' do
|
50
54
|
expect(@session).not_to have_button('ARIA button', enable_aria_role: false)
|
51
55
|
end
|
56
|
+
|
57
|
+
it 'should be false for a role=button within a label when enable_aria_role: false' do
|
58
|
+
expect(@session).not_to have_button('role=button within label', enable_aria_role: false)
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'should not affect other selectors when enable_aria_role: true' do
|
62
|
+
expect(@session).to have_button('Click me!', enable_aria_role: true)
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'should not affect other selectors when enable_aria_role: false' do
|
66
|
+
expect(@session).to have_button('Click me!', enable_aria_role: false)
|
67
|
+
end
|
52
68
|
end
|
53
69
|
|
54
70
|
Capybara::SpecHelper.spec '#has_no_button?' do
|
@@ -81,7 +97,24 @@ Capybara::SpecHelper.spec '#has_no_button?' do
|
|
81
97
|
expect(@session).to have_no_button('ARIA button', enable_aria_role: false)
|
82
98
|
end
|
83
99
|
|
100
|
+
it 'should be true for role=button within a label when enable_aria_role: false' do
|
101
|
+
expect(@session).to have_no_button('role=button within label', enable_aria_role: false)
|
102
|
+
end
|
103
|
+
|
84
104
|
it 'should be false for role=button when enable_aria_role: true' do
|
85
105
|
expect(@session).not_to have_no_button('ARIA button', enable_aria_role: true)
|
86
106
|
end
|
107
|
+
|
108
|
+
it 'should be true for a role=button within a label when enable_aria_role: true' do
|
109
|
+
# label element does not associate with aria button
|
110
|
+
expect(@session).to have_no_button('role=button within label', enable_aria_role: true)
|
111
|
+
end
|
112
|
+
|
113
|
+
it 'should not affect other selectors when enable_aria_role: true' do
|
114
|
+
expect(@session).to have_no_button('Junk button that does not exist', enable_aria_role: true)
|
115
|
+
end
|
116
|
+
|
117
|
+
it 'should not affect other selectors when enable_aria_role: false' do
|
118
|
+
expect(@session).to have_no_button('Junk button that does not exist', enable_aria_role: false)
|
119
|
+
end
|
87
120
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
#
|
3
|
+
# NOTE: This file uses `sleep` to sync up parts of the tests. This is only implemented like this
|
4
4
|
# because of the methods being tested. In tests using Capybara this type of behavior should be implemented
|
5
5
|
# using Capybara provided assertions with builtin waiting behavior.
|
6
6
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
#
|
3
|
+
# NOTE: This file uses `sleep` to sync up parts of the tests. This is only implemented like this
|
4
4
|
# because of the methods being tested. In tests using Capybara this type of behavior should be implemented
|
5
5
|
# using Capybara provided assertions with builtin waiting behavior.
|
6
6
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
#
|
3
|
+
# NOTE: This file uses `sleep` to sync up parts of the tests. This is only implemented like this
|
4
4
|
# because of the methods being tested. In tests using Capybara this type of behavior should be implemented
|
5
5
|
# using Capybara provided assertions with builtin waiting behavior.
|
6
6
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
#
|
3
|
+
# NOTE: This file uses `sleep` to sync up parts of the tests. This is only implemented like this
|
4
4
|
# because of the methods being tested. In tests using Capybara this type of behavior should be implemented
|
5
5
|
# using Capybara provided assertions with builtin waiting behavior.
|
6
6
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
#
|
3
|
+
# NOTE: This file uses `sleep` to sync up parts of the tests. This is only implemented like this
|
4
4
|
# because of the methods being tested. In tests using Capybara this type of behavior should be implemented
|
5
5
|
# using Capybara provided assertions with builtin waiting behavior.
|
6
6
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
#
|
3
|
+
# NOTE: This file uses `sleep` to sync up parts of the tests. This is only implemented like this
|
4
4
|
# because of the methods being tested. In tests using Capybara this type of behavior should be implemented
|
5
5
|
# using Capybara provided assertions with builtin waiting behavior.
|
6
6
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
#
|
3
|
+
# NOTE: This file uses `sleep` to sync up parts of the tests. This is only implemented like this
|
4
4
|
# because of the methods being tested. In tests using Capybara this type of behavior should be implemented
|
5
5
|
# using Capybara provided assertions with builtin waiting behavior.
|
6
6
|
|
@@ -462,6 +462,10 @@ New line after and before textarea tag
|
|
462
462
|
button within label element
|
463
463
|
<button></button>
|
464
464
|
</label>
|
465
|
+
<label>
|
466
|
+
role=button within label element
|
467
|
+
<span role="button">with other text</span>
|
468
|
+
</label>
|
465
469
|
<input type="button" disabled="disabled" value="Disabled button"/>
|
466
470
|
<span role="button">ARIA button</span>
|
467
471
|
</p>
|
@@ -0,0 +1,24 @@
|
|
1
|
+
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<meta http-equiv="Content-type" content="text/html; charset=utf-8"/>
|
5
|
+
<title>with_jquery_animation</title>
|
6
|
+
<style>
|
7
|
+
body {
|
8
|
+
height: 2000px;
|
9
|
+
}
|
10
|
+
</style>
|
11
|
+
</head>
|
12
|
+
|
13
|
+
<body id="with_animation">
|
14
|
+
<a href="#" id='scroll'>scroll top 500</a>
|
15
|
+
|
16
|
+
<script src="/jquery.js" type="text/javascript" charset="utf-8"></script>
|
17
|
+
<script type='text/javascript'>
|
18
|
+
$('#scroll').click(function(e){
|
19
|
+
e.preventDefault();
|
20
|
+
$('html, body').animate({ scrollTop: 500 }, 'slow');
|
21
|
+
});
|
22
|
+
</script>
|
23
|
+
</body>
|
24
|
+
</html>
|
data/lib/capybara/version.rb
CHANGED
data/spec/selector_spec.rb
CHANGED
@@ -327,9 +327,23 @@ RSpec.describe Capybara do
|
|
327
327
|
expect(string.find(:custom_xpath_selector, './/div', class: /dOm WoR/i)[:id]).to eq 'random_words'
|
328
328
|
end
|
329
329
|
|
330
|
-
it 'accepts Regexp for CSS
|
330
|
+
it 'accepts Regexp for CSS based selectors' do
|
331
331
|
expect(string.find(:custom_css_selector, 'div', class: /random/)[:id]).to eq 'random_words'
|
332
332
|
end
|
333
|
+
|
334
|
+
it 'accepts Regexp for individual class names for XPath based selectors' do
|
335
|
+
expect(string.find(:custom_xpath_selector, './/div', class: [/random/, 'some'])[:id]).to eq 'random_words'
|
336
|
+
expect(string.find(:custom_xpath_selector, './/div', class: [/om/, /wor/])[:id]).to eq 'random_words'
|
337
|
+
expect { string.find(:custom_xpath_selector, './/div', class: [/not/, /wor/]) }.to raise_error(Capybara::ElementNotFound)
|
338
|
+
expect { string.find(:custom_xpath_selector, './/div', class: [/dom wor/]) }.to raise_error(Capybara::ElementNotFound)
|
339
|
+
end
|
340
|
+
|
341
|
+
it 'accepts Regexp for individual class names for CSS based selectors' do
|
342
|
+
expect(string.find(:custom_css_selector, 'div', class: [/random/])[:id]).to eq 'random_words'
|
343
|
+
expect(string.find(:custom_css_selector, 'div', class: [/om/, /wor/, 'some'])[:id]).to eq 'random_words'
|
344
|
+
expect { string.find(:custom_css_selector, 'div', class: [/not/, /wor/]) }.to raise_error(Capybara::ElementNotFound)
|
345
|
+
expect { string.find(:custom_css_selector, 'div', class: [/dom wor/]) }.to raise_error(Capybara::ElementNotFound)
|
346
|
+
end
|
333
347
|
end
|
334
348
|
|
335
349
|
context 'with :style option' do
|
@@ -19,39 +19,56 @@ browser_options.add_preference('download.default_directory', Capybara.save_path)
|
|
19
19
|
browser_options.add_preference(:download, default_directory: Capybara.save_path)
|
20
20
|
|
21
21
|
Capybara.register_driver :selenium_chrome do |app|
|
22
|
-
Capybara::Selenium::Driver.
|
22
|
+
version = Capybara::Selenium::Driver.load_selenium
|
23
|
+
options_key = Capybara::Selenium::Driver::CAPS_VERSION.satisfied_by?(version) ? :capabilities : :options
|
24
|
+
driver_options = { browser: :chrome, timeout: 30 }.tap do |opts|
|
25
|
+
opts[options_key] = browser_options
|
26
|
+
end
|
27
|
+
|
28
|
+
Capybara::Selenium::Driver.new(app, **driver_options).tap do |driver|
|
23
29
|
# Set download dir for Chrome < 77
|
24
30
|
driver.browser.download_path = Capybara.save_path
|
25
31
|
end
|
26
32
|
end
|
27
33
|
|
28
34
|
Capybara.register_driver :selenium_chrome_not_clear_storage do |app|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
35
|
+
version = Capybara::Selenium::Driver.load_selenium
|
36
|
+
options_key = Capybara::Selenium::Driver::CAPS_VERSION.satisfied_by?(version) ? :capabilities : :options
|
37
|
+
chrome_options = { browser: :chrome, clear_local_storage: false, clear_session_storage: false }.tap do |opts|
|
38
|
+
opts[options_key] = browser_options
|
39
|
+
end
|
40
|
+
|
41
|
+
Capybara::Selenium::Driver.new(app, **chrome_options)
|
34
42
|
end
|
35
43
|
|
36
44
|
Capybara.register_driver :selenium_chrome_not_clear_session_storage do |app|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
45
|
+
version = Capybara::Selenium::Driver.load_selenium
|
46
|
+
options_key = Capybara::Selenium::Driver::CAPS_VERSION.satisfied_by?(version) ? :capabilities : :options
|
47
|
+
chrome_options = { browser: :chrome, clear_session_storage: false }.tap do |opts|
|
48
|
+
opts[options_key] = browser_options
|
49
|
+
end
|
50
|
+
|
51
|
+
Capybara::Selenium::Driver.new(app, **chrome_options)
|
42
52
|
end
|
43
53
|
|
44
54
|
Capybara.register_driver :selenium_chrome_not_clear_local_storage do |app|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
55
|
+
version = Capybara::Selenium::Driver.load_selenium
|
56
|
+
options_key = Capybara::Selenium::Driver::CAPS_VERSION.satisfied_by?(version) ? :capabilities : :options
|
57
|
+
chrome_options = { browser: :chrome, clear_local_storage: false }.tap do |opts|
|
58
|
+
opts[options_key] = browser_options
|
59
|
+
end
|
60
|
+
Capybara::Selenium::Driver.new(app, **chrome_options)
|
50
61
|
end
|
51
62
|
|
52
63
|
Capybara.register_driver :selenium_driver_subclass_with_chrome do |app|
|
64
|
+
version = Capybara::Selenium::Driver.load_selenium
|
65
|
+
options_key = Capybara::Selenium::Driver::CAPS_VERSION.satisfied_by?(version) ? :capabilities : :options
|
53
66
|
subclass = Class.new(Capybara::Selenium::Driver)
|
54
|
-
|
67
|
+
chrome_options = { browser: :chrome, timeout: 30 }.tap do |opts|
|
68
|
+
opts[options_key] = browser_options
|
69
|
+
end
|
70
|
+
|
71
|
+
subclass.new(app, **chrome_options)
|
55
72
|
end
|
56
73
|
|
57
74
|
module TestSessions
|
@@ -171,7 +188,7 @@ RSpec.describe 'Capybara::Session with chrome' do
|
|
171
188
|
before { skip 'Only makes sense in W3C mode' if ENV['W3C'] == 'false' }
|
172
189
|
|
173
190
|
it 'does not error getting log types' do
|
174
|
-
skip if Gem::
|
191
|
+
skip if Gem::Requirement.new('< 75.0.3770.90').satisfied_by? chromedriver_version
|
175
192
|
expect do
|
176
193
|
session.driver.browser.manage.logs.available_types
|
177
194
|
end.not_to raise_error
|
@@ -183,4 +200,8 @@ RSpec.describe 'Capybara::Session with chrome' do
|
|
183
200
|
end.not_to raise_error
|
184
201
|
end
|
185
202
|
end
|
203
|
+
|
204
|
+
def chromedriver_version
|
205
|
+
Gem::Version.new(session.driver.browser.capabilities['chrome']['chromedriverVersion'].split[0])
|
206
|
+
end
|
186
207
|
end
|
@@ -81,7 +81,7 @@ RSpec.describe 'Capybara::Session with remote Chrome' do
|
|
81
81
|
before { skip 'Only makes sense in W3C mode' if ENV['W3C'] == 'false' }
|
82
82
|
|
83
83
|
it 'does not error when getting log types' do
|
84
|
-
skip
|
84
|
+
skip unless Gem::Requirement.new('>= 75.0.3770.90').satisfied_by? chromedriver_version
|
85
85
|
expect do
|
86
86
|
session.driver.browser.manage.logs.available_types
|
87
87
|
end.not_to raise_error
|
@@ -93,4 +93,8 @@ RSpec.describe 'Capybara::Session with remote Chrome' do
|
|
93
93
|
end.not_to raise_error
|
94
94
|
end
|
95
95
|
end
|
96
|
+
|
97
|
+
def chromedriver_version
|
98
|
+
Gem::Version.new(session.driver.browser.capabilities['chrome']['chromedriverVersion'].split[0])
|
99
|
+
end
|
96
100
|
end
|
@@ -14,28 +14,30 @@ browser_options.profile = Selenium::WebDriver::Firefox::Profile.new.tap do |prof
|
|
14
14
|
profile['browser.download.dir'] = Capybara.save_path
|
15
15
|
profile['browser.download.folderList'] = 2
|
16
16
|
profile['browser.helperApps.neverAsk.saveToDisk'] = 'text/csv'
|
17
|
+
profile['browser.startup.homepage'] = 'about:blank' # workaround bug in Selenium 4 alpha4-7
|
17
18
|
end
|
18
19
|
|
19
20
|
Capybara.register_driver :selenium_firefox do |app|
|
20
21
|
# ::Selenium::WebDriver.logger.level = "debug"
|
21
|
-
Capybara::Selenium::Driver.
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
timeout: 31
|
22
|
+
version = Capybara::Selenium::Driver.load_selenium
|
23
|
+
options_key = Capybara::Selenium::Driver::CAPS_VERSION.satisfied_by?(version) ? :capabilities : :options
|
24
|
+
driver_options = { browser: :firefox, timeout: 31 }.tap do |opts|
|
25
|
+
opts[options_key] = browser_options
|
26
26
|
# Get a trace level log from geckodriver
|
27
27
|
# :driver_opts => { args: ['-vv'] }
|
28
|
-
|
28
|
+
end
|
29
|
+
|
30
|
+
Capybara::Selenium::Driver.new(app, **driver_options)
|
29
31
|
end
|
30
32
|
|
31
33
|
Capybara.register_driver :selenium_firefox_not_clear_storage do |app|
|
32
|
-
Capybara::Selenium::Driver.
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
)
|
34
|
+
version = Capybara::Selenium::Driver.load_selenium
|
35
|
+
options_key = Capybara::Selenium::Driver::CAPS_VERSION.satisfied_by?(version) ? :capabilities : :options
|
36
|
+
driver_options = { browser: :firefox, clear_local_storage: false, clear_session_storage: false }.tap do |opts|
|
37
|
+
opts[options_key] = browser_options
|
38
|
+
end
|
39
|
+
|
40
|
+
Capybara::Selenium::Driver.new(app, **driver_options)
|
39
41
|
end
|
40
42
|
|
41
43
|
module TestSessions
|
data/spec/server_spec.rb
CHANGED
@@ -108,8 +108,12 @@ RSpec.describe Capybara::Server do
|
|
108
108
|
expect(options.fetch(:environment)).to be_a(String)
|
109
109
|
method.call(app, events, options)
|
110
110
|
end
|
111
|
-
described_class.new(app_proc).boot
|
112
|
-
expect(Puma::Server).to have_received(:new)
|
111
|
+
server = described_class.new(app_proc).boot
|
112
|
+
expect(Puma::Server).to have_received(:new).with(
|
113
|
+
anything,
|
114
|
+
anything,
|
115
|
+
satisfy { |opts| opts.final_options[:Port] == server.port }
|
116
|
+
)
|
113
117
|
ensure
|
114
118
|
Capybara.server = :default
|
115
119
|
end
|
@@ -411,6 +411,13 @@ RSpec.shared_examples 'Capybara::Session' do |session, mode|
|
|
411
411
|
JS
|
412
412
|
expect(scroll_y).to eq 500
|
413
413
|
end
|
414
|
+
|
415
|
+
it 'should scroll the page instantly without jquery animation', requires: [:js] do
|
416
|
+
@animation_session.visit('with_jquery_animation')
|
417
|
+
@animation_session.click_link('scroll top 500')
|
418
|
+
scroll_y = @animation_session.evaluate_script('window.scrollY')
|
419
|
+
expect(scroll_y).to eq 500
|
420
|
+
end
|
414
421
|
end
|
415
422
|
|
416
423
|
context 'when set to `false`' do
|
@@ -433,6 +440,13 @@ RSpec.shared_examples 'Capybara::Session' do |session, mode|
|
|
433
440
|
# measured over 0.5 seconds: 0, 75, 282, 478, 500
|
434
441
|
expect(scroll_y).to be < 500
|
435
442
|
end
|
443
|
+
|
444
|
+
it 'should scroll the page with jquery animation', requires: [:js] do
|
445
|
+
@animation_session.visit('with_jquery_animation')
|
446
|
+
@animation_session.click_link('scroll top 500')
|
447
|
+
scroll_y = @animation_session.evaluate_script('window.scrollY')
|
448
|
+
expect(scroll_y).to be < 500
|
449
|
+
end
|
436
450
|
end
|
437
451
|
|
438
452
|
context 'if we pass in css that matches elements' do
|
metadata
CHANGED
@@ -1,16 +1,16 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: capybara
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.35.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Thomas Walpole
|
8
8
|
- Jonas Nicklas
|
9
|
-
autorequire:
|
9
|
+
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain:
|
12
12
|
- gem-public_cert.pem
|
13
|
-
date:
|
13
|
+
date: 2021-01-26 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: addressable
|
@@ -86,16 +86,22 @@ dependencies:
|
|
86
86
|
name: regexp_parser
|
87
87
|
requirement: !ruby/object:Gem::Requirement
|
88
88
|
requirements:
|
89
|
-
- - "
|
89
|
+
- - ">="
|
90
90
|
- !ruby/object:Gem::Version
|
91
91
|
version: '1.5'
|
92
|
+
- - "<"
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
version: '3.0'
|
92
95
|
type: :runtime
|
93
96
|
prerelease: false
|
94
97
|
version_requirements: !ruby/object:Gem::Requirement
|
95
98
|
requirements:
|
96
|
-
- - "
|
99
|
+
- - ">="
|
97
100
|
- !ruby/object:Gem::Version
|
98
101
|
version: '1.5'
|
102
|
+
- - "<"
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
version: '3.0'
|
99
105
|
- !ruby/object:Gem::Dependency
|
100
106
|
name: xpath
|
101
107
|
requirement: !ruby/object:Gem::Requirement
|
@@ -270,14 +276,28 @@ dependencies:
|
|
270
276
|
requirements:
|
271
277
|
- - "~>"
|
272
278
|
- !ruby/object:Gem::Version
|
273
|
-
version: 1.1
|
279
|
+
version: '1.1'
|
274
280
|
type: :development
|
275
281
|
prerelease: false
|
276
282
|
version_requirements: !ruby/object:Gem::Requirement
|
277
283
|
requirements:
|
278
284
|
- - "~>"
|
279
285
|
- !ruby/object:Gem::Version
|
280
|
-
version: 1.1
|
286
|
+
version: '1.1'
|
287
|
+
- !ruby/object:Gem::Dependency
|
288
|
+
name: rubocop-minitest
|
289
|
+
requirement: !ruby/object:Gem::Requirement
|
290
|
+
requirements:
|
291
|
+
- - ">="
|
292
|
+
- !ruby/object:Gem::Version
|
293
|
+
version: '0'
|
294
|
+
type: :development
|
295
|
+
prerelease: false
|
296
|
+
version_requirements: !ruby/object:Gem::Requirement
|
297
|
+
requirements:
|
298
|
+
- - ">="
|
299
|
+
- !ruby/object:Gem::Version
|
300
|
+
version: '0'
|
281
301
|
- !ruby/object:Gem::Dependency
|
282
302
|
name: rubocop-performance
|
283
303
|
requirement: !ruby/object:Gem::Requirement
|
@@ -292,20 +312,34 @@ dependencies:
|
|
292
312
|
- - ">="
|
293
313
|
- !ruby/object:Gem::Version
|
294
314
|
version: '0'
|
315
|
+
- !ruby/object:Gem::Dependency
|
316
|
+
name: rubocop-rake
|
317
|
+
requirement: !ruby/object:Gem::Requirement
|
318
|
+
requirements:
|
319
|
+
- - ">="
|
320
|
+
- !ruby/object:Gem::Version
|
321
|
+
version: '0'
|
322
|
+
type: :development
|
323
|
+
prerelease: false
|
324
|
+
version_requirements: !ruby/object:Gem::Requirement
|
325
|
+
requirements:
|
326
|
+
- - ">="
|
327
|
+
- !ruby/object:Gem::Version
|
328
|
+
version: '0'
|
295
329
|
- !ruby/object:Gem::Dependency
|
296
330
|
name: rubocop-rspec
|
297
331
|
requirement: !ruby/object:Gem::Requirement
|
298
332
|
requirements:
|
299
333
|
- - "~>"
|
300
334
|
- !ruby/object:Gem::Version
|
301
|
-
version: 2.0
|
335
|
+
version: '2.0'
|
302
336
|
type: :development
|
303
337
|
prerelease: false
|
304
338
|
version_requirements: !ruby/object:Gem::Requirement
|
305
339
|
requirements:
|
306
340
|
- - "~>"
|
307
341
|
- !ruby/object:Gem::Version
|
308
|
-
version: 2.0
|
342
|
+
version: '2.0'
|
309
343
|
- !ruby/object:Gem::Dependency
|
310
344
|
name: sauce_whisk
|
311
345
|
requirement: !ruby/object:Gem::Requirement
|
@@ -672,6 +706,7 @@ files:
|
|
672
706
|
- lib/capybara/spec/views/with_html.erb
|
673
707
|
- lib/capybara/spec/views/with_html5_svg.erb
|
674
708
|
- lib/capybara/spec/views/with_html_entities.erb
|
709
|
+
- lib/capybara/spec/views/with_jquery_animation.erb
|
675
710
|
- lib/capybara/spec/views/with_js.erb
|
676
711
|
- lib/capybara/spec/views/with_jstree.erb
|
677
712
|
- lib/capybara/spec/views/with_namespace.erb
|
@@ -730,7 +765,7 @@ licenses:
|
|
730
765
|
metadata:
|
731
766
|
changelog_uri: https://github.com/teamcapybara/capybara/blob/master/History.md
|
732
767
|
source_code_uri: https://github.com/teamcapybara/capybara
|
733
|
-
post_install_message:
|
768
|
+
post_install_message:
|
734
769
|
rdoc_options: []
|
735
770
|
require_paths:
|
736
771
|
- lib
|
@@ -746,7 +781,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
746
781
|
version: '0'
|
747
782
|
requirements: []
|
748
783
|
rubygems_version: 3.1.4
|
749
|
-
signing_key:
|
784
|
+
signing_key:
|
750
785
|
specification_version: 4
|
751
786
|
summary: Capybara aims to simplify the process of integration testing Rack applications,
|
752
787
|
such as Rails, Sinatra or Merb
|