capybara 3.35.3 → 3.38.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 +90 -4
- data/README.md +28 -12
- data/lib/capybara/config.rb +16 -4
- data/lib/capybara/driver/base.rb +4 -0
- data/lib/capybara/driver/node.rb +5 -1
- data/lib/capybara/dsl.rb +4 -10
- data/lib/capybara/helpers.rb +8 -13
- data/lib/capybara/minitest/spec.rb +2 -2
- data/lib/capybara/node/actions.rb +10 -5
- data/lib/capybara/node/base.rb +2 -1
- data/lib/capybara/node/document.rb +2 -2
- data/lib/capybara/node/element.rb +13 -2
- data/lib/capybara/node/finders.rb +9 -2
- data/lib/capybara/node/simple.rb +5 -1
- data/lib/capybara/queries/active_element_query.rb +18 -0
- data/lib/capybara/queries/ancestor_query.rb +2 -1
- data/lib/capybara/queries/base_query.rb +2 -2
- data/lib/capybara/queries/current_path_query.rb +1 -1
- data/lib/capybara/queries/selector_query.rb +38 -10
- data/lib/capybara/queries/sibling_query.rb +2 -1
- data/lib/capybara/queries/text_query.rb +1 -1
- data/lib/capybara/rack_test/browser.rb +63 -8
- data/lib/capybara/rack_test/driver.rb +4 -4
- data/lib/capybara/rack_test/form.rb +29 -7
- data/lib/capybara/rack_test/node.rb +10 -7
- data/lib/capybara/registration_container.rb +0 -3
- data/lib/capybara/registrations/drivers.rb +3 -3
- data/lib/capybara/registrations/servers.rb +17 -9
- data/lib/capybara/rspec/matcher_proxies.rb +3 -3
- data/lib/capybara/rspec/matchers/have_selector.rb +5 -5
- data/lib/capybara/rspec/matchers.rb +14 -14
- data/lib/capybara/selector/builders/css_builder.rb +1 -1
- data/lib/capybara/selector/builders/xpath_builder.rb +1 -1
- data/lib/capybara/selector/css.rb +1 -1
- data/lib/capybara/selector/definition/button.rb +9 -4
- data/lib/capybara/selector/definition/checkbox.rb +1 -1
- data/lib/capybara/selector/definition/file_field.rb +1 -1
- data/lib/capybara/selector/definition/fillable_field.rb +1 -1
- data/lib/capybara/selector/definition/radio_button.rb +1 -1
- data/lib/capybara/selector/definition.rb +4 -2
- data/lib/capybara/selector/filter_set.rb +4 -7
- data/lib/capybara/selector/regexp_disassembler.rb +2 -5
- data/lib/capybara/selector/selector.rb +5 -1
- data/lib/capybara/selector.rb +1 -0
- data/lib/capybara/selenium/driver.rb +28 -11
- data/lib/capybara/selenium/driver_specializations/chrome_driver.rb +1 -1
- data/lib/capybara/selenium/driver_specializations/edge_driver.rb +1 -1
- data/lib/capybara/selenium/driver_specializations/firefox_driver.rb +1 -1
- data/lib/capybara/selenium/extensions/html5_drag.rb +2 -4
- data/lib/capybara/selenium/logger_suppressor.rb +4 -0
- data/lib/capybara/selenium/node.rb +74 -23
- data/lib/capybara/selenium/nodes/chrome_node.rb +1 -1
- data/lib/capybara/selenium/nodes/edge_node.rb +1 -1
- data/lib/capybara/selenium/nodes/firefox_node.rb +3 -3
- data/lib/capybara/selenium/nodes/safari_node.rb +4 -4
- data/lib/capybara/server/animation_disabler.rb +41 -23
- data/lib/capybara/server/middleware.rb +1 -1
- data/lib/capybara/session/config.rb +4 -2
- data/lib/capybara/session.rb +31 -32
- data/lib/capybara/spec/session/active_element_spec.rb +31 -0
- data/lib/capybara/spec/session/all_spec.rb +9 -13
- data/lib/capybara/spec/session/assert_text_spec.rb +17 -17
- data/lib/capybara/spec/session/attach_file_spec.rb +6 -0
- data/lib/capybara/spec/session/check_spec.rb +10 -0
- data/lib/capybara/spec/session/choose_spec.rb +6 -0
- data/lib/capybara/spec/session/current_scope_spec.rb +1 -1
- data/lib/capybara/spec/session/fill_in_spec.rb +6 -0
- data/lib/capybara/spec/session/find_spec.rb +6 -0
- data/lib/capybara/spec/session/has_ancestor_spec.rb +2 -2
- data/lib/capybara/spec/session/has_any_selectors_spec.rb +4 -0
- data/lib/capybara/spec/session/has_button_spec.rb +30 -0
- data/lib/capybara/spec/session/has_current_path_spec.rb +2 -2
- data/lib/capybara/spec/session/has_field_spec.rb +25 -1
- data/lib/capybara/spec/session/has_link_spec.rb +36 -0
- data/lib/capybara/spec/session/has_select_spec.rb +10 -4
- data/lib/capybara/spec/session/has_selector_spec.rb +15 -0
- data/lib/capybara/spec/session/has_text_spec.rb +6 -14
- data/lib/capybara/spec/session/node_spec.rb +66 -1
- data/lib/capybara/spec/session/reset_session_spec.rb +13 -0
- data/lib/capybara/spec/session/scroll_spec.rb +4 -4
- data/lib/capybara/spec/session/visit_spec.rb +20 -0
- data/lib/capybara/spec/session/window/window_spec.rb +1 -1
- data/lib/capybara/spec/session/within_spec.rb +13 -0
- data/lib/capybara/spec/spec_helper.rb +12 -5
- data/lib/capybara/spec/test_app.rb +91 -14
- data/lib/capybara/spec/views/animated.erb +1 -1
- data/lib/capybara/spec/views/form.erb +24 -3
- data/lib/capybara/spec/views/frame_child.erb +1 -1
- data/lib/capybara/spec/views/frame_one.erb +1 -1
- data/lib/capybara/spec/views/frame_parent.erb +1 -1
- data/lib/capybara/spec/views/frame_two.erb +1 -1
- data/lib/capybara/spec/views/initial_alert.erb +2 -1
- data/lib/capybara/spec/views/layout.erb +10 -0
- data/lib/capybara/spec/views/obscured.erb +1 -1
- data/lib/capybara/spec/views/offset.erb +2 -1
- data/lib/capybara/spec/views/path.erb +2 -2
- data/lib/capybara/spec/views/popup_one.erb +1 -1
- data/lib/capybara/spec/views/popup_two.erb +1 -1
- data/lib/capybara/spec/views/react.erb +2 -2
- data/lib/capybara/spec/views/scroll.erb +2 -1
- data/lib/capybara/spec/views/spatial.erb +1 -1
- data/lib/capybara/spec/views/with_animation.erb +2 -3
- data/lib/capybara/spec/views/with_base_tag.erb +2 -2
- data/lib/capybara/spec/views/with_dragula.erb +2 -2
- data/lib/capybara/spec/views/with_fixed_header_footer.erb +2 -1
- data/lib/capybara/spec/views/with_hover.erb +2 -2
- data/lib/capybara/spec/views/with_html.erb +3 -3
- data/lib/capybara/spec/views/with_jquery_animation.erb +1 -1
- data/lib/capybara/spec/views/with_js.erb +2 -3
- data/lib/capybara/spec/views/with_jstree.erb +1 -1
- data/lib/capybara/spec/views/with_namespace.erb +1 -0
- data/lib/capybara/spec/views/with_scope.erb +2 -2
- data/lib/capybara/spec/views/with_shadow.erb +31 -0
- data/lib/capybara/spec/views/with_slow_unload.erb +2 -1
- data/lib/capybara/spec/views/with_sortable_js.erb +2 -2
- data/lib/capybara/spec/views/with_unload_alert.erb +1 -0
- data/lib/capybara/spec/views/with_windows.erb +1 -1
- data/lib/capybara/spec/views/within_frames.erb +1 -1
- data/lib/capybara/version.rb +1 -1
- data/lib/capybara/window.rb +1 -1
- data/lib/capybara.rb +23 -24
- data/spec/basic_node_spec.rb +16 -3
- data/spec/capybara_spec.rb +12 -0
- data/spec/counter_spec.rb +35 -0
- data/spec/dsl_spec.rb +5 -3
- data/spec/fixtures/selenium_driver_rspec_failure.rb +2 -2
- data/spec/fixtures/selenium_driver_rspec_success.rb +2 -2
- data/spec/minitest_spec.rb +4 -0
- data/spec/minitest_spec_spec.rb +4 -0
- data/spec/per_session_config_spec.rb +1 -1
- data/spec/rack_test_spec.rb +28 -10
- data/spec/result_spec.rb +32 -35
- data/spec/rspec/features_spec.rb +3 -3
- data/spec/rspec/scenarios_spec.rb +1 -1
- data/spec/rspec/shared_spec_matchers.rb +3 -3
- data/spec/rspec_spec.rb +2 -2
- data/spec/sauce_spec_chrome.rb +3 -3
- data/spec/selector_spec.rb +4 -4
- data/spec/selenium_spec_chrome.rb +11 -10
- data/spec/selenium_spec_chrome_remote.rb +11 -8
- data/spec/selenium_spec_edge.rb +2 -0
- data/spec/selenium_spec_firefox.rb +15 -4
- data/spec/selenium_spec_firefox_remote.rb +4 -2
- data/spec/selenium_spec_ie.rb +6 -7
- data/spec/selenium_spec_safari.rb +33 -19
- data/spec/server_spec.rb +5 -5
- data/spec/shared_selenium_node.rb +0 -4
- data/spec/shared_selenium_session.rb +23 -14
- data/spec/spec_helper.rb +1 -1
- metadata +38 -14
- data/lib/capybara/spec/views/with_title.erb +0 -5
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 163cb499d23bf17278c9912462fb3fb337b2d28b764a95c5ed3f9c4af3f1c317
|
|
4
|
+
data.tar.gz: 7010ef4e7f6af6c4d78ae58a05846c2607864d6fe24d05c49747fc1e1ded8675
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 66ac2676f22d83ec1a4478f68a8f7f095c9c9f9396eb1b5c1bf34803e15e19ed02c1f1342731d55787219ddd2d9d0829eb0c76ef702c4e07ac3a0b19a9c2aaec
|
|
7
|
+
data.tar.gz: f35c37f9ccdcdd58c1c76c80cf58eb8c62b0878bb40ff1dd6191978978409b41adabbc34013868e30a5ec4f33d077532ad8c1a90fdf0138dd524703c5168a001
|
data/History.md
CHANGED
|
@@ -1,7 +1,94 @@
|
|
|
1
|
+
# Version 3.38.0
|
|
2
|
+
Release date: 2022-11-03
|
|
3
|
+
|
|
4
|
+
### Changed
|
|
5
|
+
|
|
6
|
+
* Capybara.w3c_click_offset now defaults to true. If you need click offsets to be from the elements top left corner set it to false in your config
|
|
7
|
+
|
|
8
|
+
### Added
|
|
9
|
+
|
|
10
|
+
* Support Selenium 4.3 changes to click offset calculations
|
|
11
|
+
* `click`, `double_click`, `right_click` can now be called on the session to click the currently scoped element (or document)
|
|
12
|
+
* `Session#within` now passes the scoped element to the block
|
|
13
|
+
* Support rack-test 2+
|
|
14
|
+
* Retry interval is now configurable [Masahiro NOMOTO]
|
|
15
|
+
* Support Puma 6 - Issue #2590
|
|
16
|
+
* Selenium: DetachedShadowRootError is treated as an invalid element error [Perryn Fowler]
|
|
17
|
+
* Selenium: When inspected shadow roots will have a tag name of "ShadowRoot"
|
|
18
|
+
* `evaluate_async_script` added to Session::DSL_METHODS [Henry Blyth]
|
|
19
|
+
|
|
20
|
+
### Fixed
|
|
21
|
+
|
|
22
|
+
* Use higher precision clock in Capybara::Helpers::Timer if available
|
|
23
|
+
* rack-test driver behavior with \r\n - Issue #2547 [Stefan Hoffmann]
|
|
24
|
+
* Updated for deprecation of positional parameters in Selenium::WebDriver::ActionBuilder#pause
|
|
25
|
+
* Explicitly set cause on server raised errors
|
|
26
|
+
* Options no longer duplicated in have_xxx invalid option error message [Yudai Takada]
|
|
27
|
+
* Animation disabler is now threadsafe [Daniel Sheppard]
|
|
28
|
+
* Server connection count tracking [Oleksandr K.]
|
|
29
|
+
* Ensure scopes are reset when session is [Henry Blyth]
|
|
30
|
+
|
|
31
|
+
# Version 3.37.1
|
|
32
|
+
Release date: 2022-05-09
|
|
33
|
+
|
|
34
|
+
### Fixed
|
|
35
|
+
|
|
36
|
+
* Regression in rack-test visit - Issue #2548
|
|
37
|
+
|
|
38
|
+
# Version 3.37.0
|
|
39
|
+
Release date: 2022-05-07
|
|
40
|
+
|
|
41
|
+
### Changed
|
|
42
|
+
|
|
43
|
+
* Ruby 2.7.0+ is now required
|
|
44
|
+
|
|
45
|
+
### Added
|
|
46
|
+
|
|
47
|
+
* [Beta] CSP nonces inserted into animation disabler additions - Issue #2542
|
|
48
|
+
* Support `<base>` element in rack-test driver - ISsue #2544
|
|
49
|
+
* [Beta] `Element#shadow_root` support. Requires selenium-webdriver 4.1+. Only currently supported with Chrome when using the selenium driver. Note: only CSS can be used to find elements from the shadow root. Therefore you won't be able to use most Capybara helper methods (`fill_in`, `click_link`, `find_field`, etc) directly from the shadow root since those locators are built using XPath. If you first locate a descendant from the shadow root using CSS then you should be able to use all the Capybara methods from there.
|
|
50
|
+
* Regexp now supported for `exact_text` finder option
|
|
51
|
+
|
|
52
|
+
### Fixed
|
|
53
|
+
|
|
54
|
+
* Fragments in referer headers in rack-test driver - Issue #2525
|
|
55
|
+
* Selenium v4.1 deprecation notice
|
|
56
|
+
|
|
57
|
+
# Version 3.36.0
|
|
58
|
+
Release date: 2021-10-24
|
|
59
|
+
|
|
60
|
+
### Changed
|
|
61
|
+
|
|
62
|
+
* Ruby 2.6.0+ is now required
|
|
63
|
+
* Minimum selenium-webdriver supported is now 3.142.7
|
|
64
|
+
|
|
65
|
+
### Added
|
|
66
|
+
|
|
67
|
+
* Support for selenium-webdriver 4.x
|
|
68
|
+
* `allow_label_click` accepts click options to be used when clicking an associated label
|
|
69
|
+
* Deprecated `allow_gumbo=` in favor of `use_html5_parsing=` to enable use of Nokogiri::HTML5 when available
|
|
70
|
+
* `Session#active_element` returns the element with focus - Not supported by the `RackTest` driver [Sean Doyle]
|
|
71
|
+
* Support `focused:` filter for finding interactive elements - Not supported by the `RackTest` driver [Sean Doyle]
|
|
72
|
+
|
|
73
|
+
### Fixed
|
|
74
|
+
|
|
75
|
+
* Sibling and ancestor queries now work with Simple::Node - Issue #2452
|
|
76
|
+
* rack_test correctly ignores readonly attribute on specific input element types
|
|
77
|
+
* `Node#all_text` always returns a string - Issue #2477
|
|
78
|
+
* `have_any_of_selectors` negated match - Issue #2473
|
|
79
|
+
* `Document#scroll_to` fixed for standards behavior - pass quirks: true if you need the older behavior [Eric Anderson]
|
|
80
|
+
* Use capture on attach file event listener for better React compatibility [Jeff Way]
|
|
81
|
+
* Animation disabler produces valid HTML [Javi Martin]
|
|
82
|
+
|
|
83
|
+
### Removed
|
|
84
|
+
|
|
85
|
+
* References to non-w3c mode in drivers/tests. Non-w3c mode is obsolete and no one should be using it anymore. Capybara hasn't been testing/supporting it in a while
|
|
86
|
+
|
|
1
87
|
# Version 3.35.3
|
|
2
88
|
Release date: 2021-01-29
|
|
3
89
|
|
|
4
90
|
### Fixed
|
|
91
|
+
|
|
5
92
|
* Just a release to have the correct dates in the History.md in released gem
|
|
6
93
|
|
|
7
94
|
# Version 3.35.2
|
|
@@ -753,7 +840,7 @@ Release date: 2018-03-23
|
|
|
753
840
|
|
|
754
841
|
### Changed
|
|
755
842
|
|
|
756
|
-
*
|
|
843
|
+
* Visible text whitespace is no longer fully normalized in favor of being more in line with the WebDriver spec for visible text
|
|
757
844
|
* Drivers are expected to close extra windows when resetting the session
|
|
758
845
|
* Selenium driver supports Date/Time when filling in date/time/datetime-local inputs
|
|
759
846
|
* `current_url` returns the url for the top level browsing context
|
|
@@ -1159,7 +1246,7 @@ Release date: 2016-01-27
|
|
|
1159
1246
|
|
|
1160
1247
|
# Version 2.6.0
|
|
1161
1248
|
|
|
1162
|
-
|
|
1249
|
+
Release date: 2016-01-17
|
|
1163
1250
|
|
|
1164
1251
|
### Fixed
|
|
1165
1252
|
|
|
@@ -1223,7 +1310,7 @@ Release date: 2014-10-13
|
|
|
1223
1310
|
|
|
1224
1311
|
# Version 2.4.3
|
|
1225
1312
|
|
|
1226
|
-
|
|
1313
|
+
Release date: 2014-09-21
|
|
1227
1314
|
|
|
1228
1315
|
### Fixed
|
|
1229
1316
|
|
|
@@ -1898,4 +1985,3 @@ too many users, please read the release notes carefully!
|
|
|
1898
1985
|
* clicking links where the image's alt attribute contains the text is now possible
|
|
1899
1986
|
* within_fieldset and within_table work when the default selector is CSS
|
|
1900
1987
|
* boolean attributes work the same across drivers (return true/false)
|
|
1901
|
-
|
data/README.md
CHANGED
|
@@ -74,7 +74,7 @@ GitHub): http://groups.google.com/group/ruby-capybara
|
|
|
74
74
|
|
|
75
75
|
## <a name="setup"></a>Setup
|
|
76
76
|
|
|
77
|
-
Capybara requires Ruby 2.
|
|
77
|
+
Capybara requires Ruby 2.7.0 or later. To install, add this line to your
|
|
78
78
|
`Gemfile` and run `bundle install`:
|
|
79
79
|
|
|
80
80
|
```ruby
|
|
@@ -151,6 +151,8 @@ RSpec](https://relishapp.com/rspec/rspec-rails/v/4-0/docs/directory-structure))
|
|
|
151
151
|
and if you have your Capybara specs in a different directory, then tag the
|
|
152
152
|
example groups with `type: :feature` or `type: :system` depending on which type of test you're writing.
|
|
153
153
|
|
|
154
|
+
If you are using Rails system specs please see [their documentation](https://relishapp.com/rspec/rspec-rails/docs/system-specs/system-spec#system-specs-driven-by-selenium-chrome-headless) for selecting the driver you wish to use.
|
|
155
|
+
|
|
154
156
|
If you are not using Rails, tag all the example groups in which you want to use
|
|
155
157
|
Capybara with `type: :feature`.
|
|
156
158
|
|
|
@@ -159,7 +161,7 @@ You can now write your specs like so:
|
|
|
159
161
|
```ruby
|
|
160
162
|
describe "the signin process", type: :feature do
|
|
161
163
|
before :each do
|
|
162
|
-
User.
|
|
164
|
+
User.create(email: 'user@example.com', password: 'password')
|
|
163
165
|
end
|
|
164
166
|
|
|
165
167
|
it "signs me in" do
|
|
@@ -190,7 +192,7 @@ Capybara also comes with a built in DSL for creating descriptive acceptance test
|
|
|
190
192
|
```ruby
|
|
191
193
|
feature "Signing in" do
|
|
192
194
|
background do
|
|
193
|
-
User.
|
|
195
|
+
User.create(email: 'user@example.com', password: 'caplin')
|
|
194
196
|
end
|
|
195
197
|
|
|
196
198
|
scenario "Signing in with correct credentials" do
|
|
@@ -203,7 +205,7 @@ feature "Signing in" do
|
|
|
203
205
|
expect(page).to have_content 'Success'
|
|
204
206
|
end
|
|
205
207
|
|
|
206
|
-
given(:other_user) { User.
|
|
208
|
+
given(:other_user) { User.create(email: 'other@example.com', password: 'rous') }
|
|
207
209
|
|
|
208
210
|
scenario "Signing in as another user" do
|
|
209
211
|
visit '/sessions/new'
|
|
@@ -258,6 +260,8 @@ end
|
|
|
258
260
|
|
|
259
261
|
## <a name="using-capybara-with-minitest"></a>Using Capybara with Minitest
|
|
260
262
|
|
|
263
|
+
* If you are using Rails system tests please see their documentation for information on selecting the driver you wish to use.
|
|
264
|
+
|
|
261
265
|
* If you are using Rails, but not using Rails system tests, add the following code in your `test_helper.rb`
|
|
262
266
|
file to make Capybara available in all test cases deriving from
|
|
263
267
|
`ActionDispatch::IntegrationTest`:
|
|
@@ -332,7 +336,7 @@ By default, Capybara uses the `:rack_test` driver, which is fast but limited: it
|
|
|
332
336
|
does not support JavaScript, nor is it able to access HTTP resources outside of
|
|
333
337
|
your Rack application, such as remote APIs and OAuth services. To get around
|
|
334
338
|
these limitations, you can set up a different default driver for your features.
|
|
335
|
-
For example if you'd prefer to run everything in Selenium, you could do:
|
|
339
|
+
For example, if you'd prefer to run everything in Selenium, you could do:
|
|
336
340
|
|
|
337
341
|
```ruby
|
|
338
342
|
Capybara.default_driver = :selenium # :selenium_chrome and :selenium_chrome_headless are also registered
|
|
@@ -626,7 +630,7 @@ JS
|
|
|
626
630
|
|
|
627
631
|
### <a name="modals"></a>Modals
|
|
628
632
|
|
|
629
|
-
In drivers which support it, you can accept, dismiss and respond to alerts, confirms and prompts.
|
|
633
|
+
In drivers which support it, you can accept, dismiss and respond to alerts, confirms, and prompts.
|
|
630
634
|
|
|
631
635
|
You can accept or dismiss alert messages by wrapping the code that produces an alert in a block:
|
|
632
636
|
|
|
@@ -777,7 +781,7 @@ expect(page).to have_content('baz')
|
|
|
777
781
|
If clicking on the *foo* link triggers an asynchronous process, such as
|
|
778
782
|
an Ajax request, which, when complete will add the *bar* link to the page,
|
|
779
783
|
clicking on the *bar* link would be expected to fail, since that link doesn't
|
|
780
|
-
exist yet. However Capybara is smart enough to retry finding the link for a
|
|
784
|
+
exist yet. However, Capybara is smart enough to retry finding the link for a
|
|
781
785
|
brief period of time before giving up and throwing an error. The same is true of
|
|
782
786
|
the next line, which looks for the content *baz* on the page; it will retry
|
|
783
787
|
looking for that content for a brief time. You can adjust how long this period
|
|
@@ -791,13 +795,25 @@ Be aware that because of this behaviour, the following two statements are **not*
|
|
|
791
795
|
equivalent, and you should **always** use the latter!
|
|
792
796
|
|
|
793
797
|
```ruby
|
|
794
|
-
|
|
795
|
-
|
|
798
|
+
# Given use of a driver where the page is loaded when visit returns
|
|
799
|
+
# and that Capybara.predicates_wait is `true`
|
|
800
|
+
# consider a page where the `a` tag is removed through AJAX after 1s
|
|
801
|
+
visit(some_path)
|
|
802
|
+
!page.has_xpath?('a') # is false
|
|
803
|
+
page.has_no_xpath?('a') # is true
|
|
796
804
|
```
|
|
797
805
|
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
806
|
+
First expression:
|
|
807
|
+
- `has_xpath?('a')` is called right after `visit` returns. It is `true` because the link has not yet been removed
|
|
808
|
+
- Capybara does not wait upon successful predicates/assertions, therefore **has_xpath? returns `true` immediately**
|
|
809
|
+
- The expression returns `false` (because it is negated with the leading `!`)
|
|
810
|
+
|
|
811
|
+
Second expression:
|
|
812
|
+
- `has_no_xpath?('a')` is called right after `visit` returns. It is `false` because the link has not yet been removed.
|
|
813
|
+
- Capybara waits upon failed predicates/assertions, therefore **has_no_xpath? does not return `false` immediately**
|
|
814
|
+
- Capybara will periodically re-check the predicate/assertion up to the `default_max_wait_time` defined
|
|
815
|
+
- after 1s, the predicate becomes `true` (because the link has been removed)
|
|
816
|
+
- The expression returns `true`
|
|
801
817
|
|
|
802
818
|
Capybara's RSpec matchers, however, are smart enough to handle either form.
|
|
803
819
|
The two following statements are functionally equivalent:
|
data/lib/capybara/config.rb
CHANGED
|
@@ -7,10 +7,12 @@ module Capybara
|
|
|
7
7
|
class Config
|
|
8
8
|
extend Forwardable
|
|
9
9
|
|
|
10
|
-
OPTIONS = %i[
|
|
10
|
+
OPTIONS = %i[
|
|
11
|
+
app reuse_server threadsafe server default_driver javascript_driver use_html5_parsing allow_gumbo
|
|
12
|
+
].freeze
|
|
11
13
|
|
|
12
|
-
attr_accessor :app, :
|
|
13
|
-
attr_reader :reuse_server, :threadsafe, :session_options
|
|
14
|
+
attr_accessor :app, :use_html5_parsing
|
|
15
|
+
attr_reader :reuse_server, :threadsafe, :session_options # rubocop:disable Style/BisectedAttrAccessor
|
|
14
16
|
attr_writer :default_driver, :javascript_driver
|
|
15
17
|
|
|
16
18
|
SessionConfig::OPTIONS.each do |method|
|
|
@@ -22,7 +24,7 @@ module Capybara
|
|
|
22
24
|
@javascript_driver = nil
|
|
23
25
|
end
|
|
24
26
|
|
|
25
|
-
attr_writer :reuse_server
|
|
27
|
+
attr_writer :reuse_server # rubocop:disable Style/BisectedAttrAccessor
|
|
26
28
|
|
|
27
29
|
def threadsafe=(bool)
|
|
28
30
|
if (bool != threadsafe) && Session.instance_created?
|
|
@@ -88,5 +90,15 @@ module Capybara
|
|
|
88
90
|
end
|
|
89
91
|
@deprecation_notified[method] = true
|
|
90
92
|
end
|
|
93
|
+
|
|
94
|
+
def allow_gumbo=(val)
|
|
95
|
+
deprecate('allow_gumbo=', 'use_html5_parsing=')
|
|
96
|
+
self.use_html5_parsing = val
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def allow_gumbo
|
|
100
|
+
deprecate('allow_gumbo', 'use_html5_parsing')
|
|
101
|
+
use_html5_parsing
|
|
102
|
+
end
|
|
91
103
|
end
|
|
92
104
|
end
|
data/lib/capybara/driver/base.rb
CHANGED
|
@@ -63,6 +63,10 @@ class Capybara::Driver::Base
|
|
|
63
63
|
raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#send_keys'
|
|
64
64
|
end
|
|
65
65
|
|
|
66
|
+
def active_element
|
|
67
|
+
raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#active_element'
|
|
68
|
+
end
|
|
69
|
+
|
|
66
70
|
##
|
|
67
71
|
#
|
|
68
72
|
# @param frame [Capybara::Node::Element, :parent, :top] The iframe element to switch to
|
data/lib/capybara/driver/node.rb
CHANGED
|
@@ -125,6 +125,10 @@ module Capybara
|
|
|
125
125
|
raise NotSupportedByDriverError, 'Capybara::Driver::Node#trigger'
|
|
126
126
|
end
|
|
127
127
|
|
|
128
|
+
def shadow_root
|
|
129
|
+
raise NotSupportedByDriverError, 'Capybara::Driver::Node#shadow_root'
|
|
130
|
+
end
|
|
131
|
+
|
|
128
132
|
def inspect
|
|
129
133
|
%(#<#{self.class} tag="#{tag_name}" path="#{path}">)
|
|
130
134
|
rescue NotSupportedByDriverError
|
|
@@ -132,7 +136,7 @@ module Capybara
|
|
|
132
136
|
end
|
|
133
137
|
|
|
134
138
|
def ==(other)
|
|
135
|
-
|
|
139
|
+
eql?(other) || (other.respond_to?(:native) && native == other.native)
|
|
136
140
|
end
|
|
137
141
|
end
|
|
138
142
|
end
|
data/lib/capybara/dsl.rb
CHANGED
|
@@ -47,17 +47,11 @@ module Capybara
|
|
|
47
47
|
end
|
|
48
48
|
|
|
49
49
|
Session::DSL_METHODS.each do |method|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
page.method("#{method}").call(...)
|
|
54
|
-
end
|
|
55
|
-
METHOD
|
|
56
|
-
else
|
|
57
|
-
define_method method do |*args, &block|
|
|
58
|
-
page.send method, *args, &block
|
|
50
|
+
class_eval <<~METHOD, __FILE__, __LINE__ + 1
|
|
51
|
+
def #{method}(...)
|
|
52
|
+
page.method("#{method}").call(...)
|
|
59
53
|
end
|
|
60
|
-
|
|
54
|
+
METHOD
|
|
61
55
|
end
|
|
62
56
|
end
|
|
63
57
|
|
data/lib/capybara/helpers.rb
CHANGED
|
@@ -73,28 +73,23 @@ module Capybara
|
|
|
73
73
|
def filter_backtrace(trace)
|
|
74
74
|
return 'No backtrace' unless trace
|
|
75
75
|
|
|
76
|
-
filter = %r{lib/capybara/|lib/rspec/|lib/minitest
|
|
76
|
+
filter = %r{lib/capybara/|lib/rspec/|lib/minitest/|delegate.rb}
|
|
77
77
|
new_trace = trace.take_while { |line| line !~ filter }
|
|
78
|
-
new_trace = trace.
|
|
78
|
+
new_trace = trace.grep_v(filter) if new_trace.empty?
|
|
79
79
|
new_trace = trace.dup if new_trace.empty?
|
|
80
80
|
|
|
81
81
|
new_trace.first.split(/:in /, 2).first
|
|
82
82
|
end
|
|
83
83
|
|
|
84
84
|
def warn(message, uplevel: 1)
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
# TODO: Remove when we drop support for Ruby 2.5
|
|
88
|
-
# Workaround for emulating `warn '...', uplevel: n` in Ruby 2.5 or lower.
|
|
89
|
-
if (match = /^(?<file>.+?):(?<line>\d+)(?::in `.*')?/.match(caller[uplevel]))
|
|
90
|
-
location = [match[:file], match[:line]].join(':')
|
|
91
|
-
Kernel.warn "#{location}: #{message}"
|
|
92
|
-
else
|
|
93
|
-
Kernel.warn message
|
|
94
|
-
end
|
|
85
|
+
Kernel.warn(message, uplevel: uplevel)
|
|
95
86
|
end
|
|
96
87
|
|
|
97
|
-
if defined?(Process::
|
|
88
|
+
if defined?(Process::CLOCK_MONOTONIC_RAW)
|
|
89
|
+
def monotonic_time; Process.clock_gettime Process::CLOCK_MONOTONIC_RAW; end
|
|
90
|
+
elsif defined?(Process::CLOCK_MONOTONIC_PRECISE)
|
|
91
|
+
def monotonic_time; Process.clock_gettime Process::CLOCK_MONOTONIC_PRECISE; end
|
|
92
|
+
elsif defined?(Process::CLOCK_MONOTONIC)
|
|
98
93
|
def monotonic_time; Process.clock_gettime Process::CLOCK_MONOTONIC; end
|
|
99
94
|
else
|
|
100
95
|
def monotonic_time; Time.now.to_f; end
|
|
@@ -246,9 +246,9 @@ module Capybara
|
|
|
246
246
|
|
|
247
247
|
##
|
|
248
248
|
# @deprecated
|
|
249
|
-
def must_have_style(
|
|
249
|
+
def must_have_style(...)
|
|
250
250
|
warn 'must_have_style is deprecated, please use must_match_style'
|
|
251
|
-
must_match_style(
|
|
251
|
+
must_match_style(...)
|
|
252
252
|
end
|
|
253
253
|
end
|
|
254
254
|
end
|
|
@@ -92,8 +92,9 @@ module Capybara
|
|
|
92
92
|
end
|
|
93
93
|
|
|
94
94
|
# @!macro label_click
|
|
95
|
-
# @option options [Boolean] allow_label_click
|
|
95
|
+
# @option options [Boolean, Hash] allow_label_click
|
|
96
96
|
# Attempt to click the label to toggle state if element is non-visible. Defaults to {Capybara.configure automatic_label_click}.
|
|
97
|
+
# If set to a Hash it is passed as options to the `click` on the label
|
|
97
98
|
|
|
98
99
|
##
|
|
99
100
|
#
|
|
@@ -277,7 +278,7 @@ module Capybara
|
|
|
277
278
|
# @return [Capybara::Node::Element] The file field element
|
|
278
279
|
def attach_file(locator = nil, paths, make_visible: nil, **options) # rubocop:disable Style/OptionalArguments
|
|
279
280
|
if locator && block_given?
|
|
280
|
-
raise ArgumentError, '
|
|
281
|
+
raise ArgumentError, '`#attach_file` does not support passing both a locator and a block'
|
|
281
282
|
end
|
|
282
283
|
|
|
283
284
|
Array(paths).each do |path|
|
|
@@ -314,7 +315,7 @@ module Capybara
|
|
|
314
315
|
|
|
315
316
|
begin
|
|
316
317
|
find(:datalist_input, from, **options)
|
|
317
|
-
rescue Capybara::ElementNotFound => dlinput_error
|
|
318
|
+
rescue Capybara::ElementNotFound => dlinput_error
|
|
318
319
|
raise Capybara::ElementNotFound, "#{select_error.message} and #{dlinput_error.message}"
|
|
319
320
|
end
|
|
320
321
|
end
|
|
@@ -371,7 +372,11 @@ module Capybara
|
|
|
371
372
|
|
|
372
373
|
begin
|
|
373
374
|
el ||= find(selector, locator, **options.merge(visible: :all))
|
|
374
|
-
|
|
375
|
+
unless el.checked? == checked
|
|
376
|
+
el.session
|
|
377
|
+
.find(:label, for: el, visible: true, match: :first)
|
|
378
|
+
.click(**(Hash.try_convert(allow_label_click) || {}))
|
|
379
|
+
end
|
|
375
380
|
rescue StandardError # swallow extra errors - raise original
|
|
376
381
|
raise e
|
|
377
382
|
end
|
|
@@ -408,7 +413,7 @@ module Capybara
|
|
|
408
413
|
this.removeEventListener('click', file_catcher);
|
|
409
414
|
e.preventDefault();
|
|
410
415
|
}
|
|
411
|
-
})
|
|
416
|
+
}, {capture: true})
|
|
412
417
|
JS
|
|
413
418
|
end
|
|
414
419
|
end
|
data/lib/capybara/node/base.rb
CHANGED
|
@@ -77,6 +77,7 @@ module Capybara
|
|
|
77
77
|
return yield if session.synchronized
|
|
78
78
|
|
|
79
79
|
seconds = session_options.default_max_wait_time if [nil, true].include? seconds
|
|
80
|
+
interval = session_options.default_retry_interval
|
|
80
81
|
session.synchronized = true
|
|
81
82
|
timer = Capybara::Helpers.timer(expire_in: seconds)
|
|
82
83
|
begin
|
|
@@ -88,7 +89,7 @@ module Capybara
|
|
|
88
89
|
if driver.wait?
|
|
89
90
|
raise e if timer.expired?
|
|
90
91
|
|
|
91
|
-
sleep
|
|
92
|
+
sleep interval
|
|
92
93
|
reload if session_options.automatic_reload
|
|
93
94
|
else
|
|
94
95
|
old_base = @base
|
|
@@ -40,8 +40,8 @@ module Capybara
|
|
|
40
40
|
find(:xpath, '/html').evaluate_script(*args)
|
|
41
41
|
end
|
|
42
42
|
|
|
43
|
-
def scroll_to(*args, **options)
|
|
44
|
-
find(:xpath, '//body').scroll_to(*args, **options)
|
|
43
|
+
def scroll_to(*args, quirks: false, **options)
|
|
44
|
+
find(:xpath, quirks ? '//body' : '/html').scroll_to(*args, **options)
|
|
45
45
|
end
|
|
46
46
|
end
|
|
47
47
|
end
|
|
@@ -115,7 +115,7 @@ module Capybara
|
|
|
115
115
|
#
|
|
116
116
|
# @return [Capybara::Node::Element] The element
|
|
117
117
|
def set(value, **options)
|
|
118
|
-
if ENV
|
|
118
|
+
if ENV.fetch('CAPYBARA_THOROUGH', nil) && readonly?
|
|
119
119
|
raise Capybara::ReadOnlyElementError, "Attempt to set readonly element with value: #{value}"
|
|
120
120
|
end
|
|
121
121
|
|
|
@@ -472,6 +472,17 @@ module Capybara
|
|
|
472
472
|
self
|
|
473
473
|
end
|
|
474
474
|
|
|
475
|
+
##
|
|
476
|
+
#
|
|
477
|
+
# Return the shadow_root for the current element
|
|
478
|
+
#
|
|
479
|
+
# @return [Capybara::Node::Element] The shadow root
|
|
480
|
+
|
|
481
|
+
def shadow_root
|
|
482
|
+
root = synchronize { base.shadow_root }
|
|
483
|
+
root && Capybara::Node::Element.new(session, root, nil, nil)
|
|
484
|
+
end
|
|
485
|
+
|
|
475
486
|
##
|
|
476
487
|
#
|
|
477
488
|
# Execute the given JS in the context of the element not returning a result. This is useful for scripts that return
|
|
@@ -550,7 +561,7 @@ module Capybara
|
|
|
550
561
|
return self unless @allow_reload
|
|
551
562
|
|
|
552
563
|
begin
|
|
553
|
-
reloaded = @query.resolve_for(query_scope.reload)[@query_idx.to_i]
|
|
564
|
+
reloaded = @query.resolve_for(query_scope ? query_scope.reload : session)[@query_idx.to_i]
|
|
554
565
|
@base = reloaded.base if reloaded
|
|
555
566
|
rescue StandardError => e
|
|
556
567
|
raise e unless catch_error?(e)
|
|
@@ -18,11 +18,11 @@ module Capybara
|
|
|
18
18
|
#
|
|
19
19
|
# @!macro system_filters
|
|
20
20
|
# @option options [String, Regexp] text Only find elements which contain this text or match this regexp
|
|
21
|
-
# @option options [String,
|
|
21
|
+
# @option options [String, Regexp, String] exact_text
|
|
22
22
|
# When String the elements contained text must match exactly, when Boolean controls whether the `text` option must match exactly.
|
|
23
23
|
# Defaults to {Capybara.configure exact_text}.
|
|
24
24
|
# @option options [Boolean] normalize_ws
|
|
25
|
-
# Whether the `text`/`exact_text` options are compared against
|
|
25
|
+
# Whether the `text`/`exact_text` options are compared against element text with whitespace normalized or as returned by the driver.
|
|
26
26
|
# Defaults to {Capybara.configure default_normalize_ws}.
|
|
27
27
|
# @option options [Boolean, Symbol] visible
|
|
28
28
|
# Only find elements with the specified visibility. Defaults to behavior indicated by {Capybara.configure ignore_hidden_elements}.
|
|
@@ -50,6 +50,13 @@ module Capybara
|
|
|
50
50
|
#
|
|
51
51
|
def find(*args, **options, &optional_filter_block)
|
|
52
52
|
options[:session_options] = session_options
|
|
53
|
+
count_options = options.slice(*Capybara::Queries::BaseQuery::COUNT_KEYS)
|
|
54
|
+
unless count_options.empty?
|
|
55
|
+
Capybara::Helpers.warn(
|
|
56
|
+
"'find' does not support count options (#{count_options}) ignoring. " \
|
|
57
|
+
"Called from: #{Capybara::Helpers.filter_backtrace(caller)}"
|
|
58
|
+
)
|
|
59
|
+
end
|
|
53
60
|
synced_resolve Capybara::Queries::SelectorQuery.new(*args, **options, &optional_filter_block)
|
|
54
61
|
end
|
|
55
62
|
|
data/lib/capybara/node/simple.rb
CHANGED
|
@@ -110,7 +110,7 @@ module Capybara
|
|
|
110
110
|
# No need for an xpath if only checking the current element
|
|
111
111
|
!(native.key?('hidden') ||
|
|
112
112
|
/display:\s?none/.match?(native[:style] || '') ||
|
|
113
|
-
%w[script head].include?(tag_name))
|
|
113
|
+
%w[script head style].include?(tag_name))
|
|
114
114
|
end
|
|
115
115
|
end
|
|
116
116
|
|
|
@@ -191,6 +191,10 @@ module Capybara
|
|
|
191
191
|
{}
|
|
192
192
|
end
|
|
193
193
|
|
|
194
|
+
def ==(other)
|
|
195
|
+
eql?(other) || (other.respond_to?(:native) && native == other.native)
|
|
196
|
+
end
|
|
197
|
+
|
|
194
198
|
private
|
|
195
199
|
|
|
196
200
|
def option_value(option)
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Capybara
|
|
4
|
+
# @api private
|
|
5
|
+
module Queries
|
|
6
|
+
class ActiveElementQuery < BaseQuery
|
|
7
|
+
def initialize(**options)
|
|
8
|
+
@options = options
|
|
9
|
+
super(@options)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def resolve_for(session)
|
|
13
|
+
node = session.driver.active_element
|
|
14
|
+
[Capybara::Node::Element.new(session, node, nil, self)]
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -8,7 +8,8 @@ module Capybara
|
|
|
8
8
|
@child_node = node
|
|
9
9
|
|
|
10
10
|
node.synchronize do
|
|
11
|
-
|
|
11
|
+
scope = node.respond_to?(:session) ? node.session.current_scope : node.find(:xpath, '/*')
|
|
12
|
+
match_results = super(scope, exact)
|
|
12
13
|
ancestors = node.find_xpath(XPath.ancestor.to_s)
|
|
13
14
|
.map(&method(:to_element))
|
|
14
15
|
.select { |el| match_results.include?(el) }
|
|
@@ -79,8 +79,8 @@ module Capybara
|
|
|
79
79
|
if count
|
|
80
80
|
message << " #{occurrences count}"
|
|
81
81
|
elsif between
|
|
82
|
-
message << " between #{between.begin ? between.first : 1} and" \
|
|
83
|
-
"
|
|
82
|
+
message << " between #{between.begin ? between.first : 1} and " \
|
|
83
|
+
"#{between.end ? between.last : 'infinite'} times"
|
|
84
84
|
elsif maximum
|
|
85
85
|
message << " at most #{occurrences maximum}"
|
|
86
86
|
elsif minimum
|
|
@@ -19,7 +19,7 @@ module Capybara
|
|
|
19
19
|
|
|
20
20
|
def resolves_for?(session)
|
|
21
21
|
uri = ::Addressable::URI.parse(session.current_url)
|
|
22
|
-
@actual_path = (options[:ignore_query] ? uri&.omit(:query) : uri).
|
|
22
|
+
@actual_path = (options[:ignore_query] ? uri&.omit(:query) : uri).then do |u|
|
|
23
23
|
options[:url] ? u&.to_s : u&.request_uri
|
|
24
24
|
end
|
|
25
25
|
|