capybara 3.39.2 → 3.40.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 +22 -0
- data/README.md +173 -29
- data/lib/capybara/helpers.rb +1 -1
- data/lib/capybara/minitest/spec.rb +16 -4
- data/lib/capybara/minitest.rb +14 -1
- data/lib/capybara/node/matchers.rb +25 -0
- data/lib/capybara/node/whitespace_normalizer.rb +5 -5
- data/lib/capybara/queries/selector_query.rb +2 -1
- data/lib/capybara/rack_test/browser.rb +3 -2
- data/lib/capybara/rack_test/node.rb +5 -12
- data/lib/capybara/registration_container.rb +2 -2
- data/lib/capybara/registrations/drivers.rb +1 -1
- data/lib/capybara/registrations/servers.rb +8 -7
- data/lib/capybara/result.rb +2 -2
- data/lib/capybara/rspec/matchers/have_selector.rb +4 -12
- data/lib/capybara/rspec/matchers.rb +7 -2
- data/lib/capybara/selector/css.rb +5 -5
- data/lib/capybara/selector/definition/table.rb +1 -1
- data/lib/capybara/selector/definition/table_row.rb +2 -2
- data/lib/capybara/selector.rb +251 -0
- data/lib/capybara/selenium/driver.rb +11 -51
- data/lib/capybara/selenium/driver_specializations/firefox_driver.rb +1 -6
- data/lib/capybara/selenium/node.rb +4 -31
- data/lib/capybara/selenium/nodes/chrome_node.rb +3 -19
- data/lib/capybara/selenium/nodes/edge_node.rb +0 -16
- data/lib/capybara/server/animation_disabler.rb +1 -1
- data/lib/capybara/server.rb +1 -1
- data/lib/capybara/session.rb +3 -2
- data/lib/capybara/spec/session/all_spec.rb +1 -1
- data/lib/capybara/spec/session/click_link_spec.rb +1 -1
- data/lib/capybara/spec/session/find_spec.rb +8 -0
- data/lib/capybara/spec/session/has_element_spec.rb +47 -0
- data/lib/capybara/spec/session/has_table_spec.rb +13 -2
- data/lib/capybara/spec/session/node_spec.rb +6 -0
- data/lib/capybara/spec/session/node_wrapper_spec.rb +1 -1
- data/lib/capybara/spec/session/uncheck_spec.rb +1 -1
- data/lib/capybara/spec/spec_helper.rb +2 -2
- data/lib/capybara/spec/test_app.rb +1 -1
- data/lib/capybara/spec/views/form.erb +5 -0
- data/lib/capybara/spec/views/with_html.erb +2 -0
- data/lib/capybara/version.rb +1 -1
- data/lib/capybara.rb +7 -6
- data/spec/minitest_spec.rb +8 -1
- data/spec/result_spec.rb +9 -0
- data/spec/rspec/shared_spec_matchers.rb +26 -2
- data/spec/rspec_spec.rb +1 -1
- data/spec/sauce_spec_chrome.rb +1 -1
- data/spec/selector_spec.rb +1 -1
- data/spec/selenium_spec_chrome.rb +7 -5
- data/spec/selenium_spec_chrome_remote.rb +0 -5
- data/spec/selenium_spec_edge.rb +11 -4
- data/spec/selenium_spec_firefox.rb +4 -3
- data/spec/selenium_spec_firefox_remote.rb +2 -3
- data/spec/server_spec.rb +12 -0
- data/spec/shared_selenium_session.rb +0 -2
- data/spec/spec_helper.rb +2 -2
- metadata +25 -32
- data/lib/capybara/selenium/logger_suppressor.rb +0 -44
- data/lib/capybara/selenium/patches/action_pauser.rb +0 -26
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e0537a83e6809595a8e15b9c450f4f4b0976c5ebf1327cc0611ae20a05b3574b
|
|
4
|
+
data.tar.gz: c3035e7a05874cc93ab27c6aea26e529dea4c3b63bd5d3281deaaf34c45a91b0
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 48c7bc5cbfc8e3324ea09d937a207299ad91ffc2e255dbbb7ed13265e4541c3672271ccb2f19b3902588d5c649cb6f561b7c483e7b815b824ccf37df8bbb5075
|
|
7
|
+
data.tar.gz: 5b3a9cc9a6ba6ed67a54ef381c00ed9cc94027d26bdfc98ba1c509a097c9dc123d39bd72a6a5728e5b5b4e503202e475889d22cf47c07ce88eb7afedf604ed83
|
data/History.md
CHANGED
|
@@ -1,3 +1,25 @@
|
|
|
1
|
+
#Version 3.40.0
|
|
2
|
+
Release date: 2024-01-26
|
|
3
|
+
|
|
4
|
+
### Changned
|
|
5
|
+
|
|
6
|
+
* Dropped support for Ruby 2.7, 3.0+ is now required
|
|
7
|
+
* Dropped support for Selenium < 4.8
|
|
8
|
+
* Use the new headless option on chromedriver with registered selenium driver [Neil Carvalho]
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
* `Capybara::Result#to_ary` to support multiple assignment [Sean Doyle]
|
|
13
|
+
* `has_element?` and related matchers [Sean Doyle]
|
|
14
|
+
* Rack 3 support
|
|
15
|
+
|
|
16
|
+
### Fixed
|
|
17
|
+
|
|
18
|
+
* Forward save_screenshot options to selenium - Issue 2738
|
|
19
|
+
* Rack test - don't auto submit forms with multiple inputs [Mitchell Henke]
|
|
20
|
+
* Table row selector matches cell values in order - Issue 2686 [Jeff Parr]
|
|
21
|
+
* Table row selector fixes for first column - Issue 2685 [Jeff Par]
|
|
22
|
+
|
|
1
23
|
# Version 3.39.2
|
|
2
24
|
Release date: 2023-06-10
|
|
3
25
|
|
data/README.md
CHANGED
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
# Capybara
|
|
2
2
|
|
|
3
|
-
[](https://ci.appveyor.com/api/projects/github/teamcapybara/capybara)
|
|
3
|
+
[](https://github.com/teamcapybara/capybara/actions/workflows/build.yml)
|
|
5
4
|
[](https://codeclimate.com/github/teamcapybara/capybara)
|
|
6
5
|
[](https://coveralls.io/github/teamcapybara/capybara?branch=master)
|
|
7
|
-
[](https://gitter.im/jnicklas/capybara?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
|
8
|
-
[](https://dependabot.com/compatibility-score.html?dependency-name=capybara&package-manager=bundler&version-scheme=semver)
|
|
9
6
|
|
|
10
7
|
Capybara helps you test web applications by simulating how a real user would
|
|
11
8
|
interact with your app. It is agnostic about the driver running your tests and
|
|
@@ -18,8 +15,7 @@ If you and/or your company find value in Capybara and would like to contribute f
|
|
|
18
15
|
<a href="https://www.patreon.com/capybara">Patreon</a>
|
|
19
16
|
|
|
20
17
|
|
|
21
|
-
**Need help?** Ask on the
|
|
22
|
-
GitHub): http://groups.google.com/group/ruby-capybara
|
|
18
|
+
**Need help?** Ask on the discussions (please do not open an issue): https://github.com/orgs/teamcapybara/discussions/categories/q-a
|
|
23
19
|
|
|
24
20
|
## Table of contents
|
|
25
21
|
|
|
@@ -34,7 +30,6 @@ GitHub): http://groups.google.com/group/ruby-capybara
|
|
|
34
30
|
- [Selecting the Driver](#selecting-the-driver)
|
|
35
31
|
- [RackTest](#racktest)
|
|
36
32
|
- [Selenium](#selenium)
|
|
37
|
-
- [Apparition](#apparition)
|
|
38
33
|
- [The DSL](#the-dsl)
|
|
39
34
|
- [Navigating](#navigating)
|
|
40
35
|
- [Clicking links and buttons](#clicking-links-and-buttons)
|
|
@@ -46,6 +41,10 @@ GitHub): http://groups.google.com/group/ruby-capybara
|
|
|
46
41
|
- [Scripting](#scripting)
|
|
47
42
|
- [Modals](#modals)
|
|
48
43
|
- [Debugging](#debugging)
|
|
44
|
+
- [Selectors](#selectors)
|
|
45
|
+
- [Name](#selectors-name)
|
|
46
|
+
- [Locator](#selectors-locator)
|
|
47
|
+
- [Filters](#selectors-filters)
|
|
49
48
|
- [Matching](#matching)
|
|
50
49
|
- [Exactness](#exactness)
|
|
51
50
|
- [Strategy](#strategy)
|
|
@@ -74,7 +73,7 @@ GitHub): http://groups.google.com/group/ruby-capybara
|
|
|
74
73
|
|
|
75
74
|
## <a name="setup"></a>Setup
|
|
76
75
|
|
|
77
|
-
Capybara requires Ruby
|
|
76
|
+
Capybara requires Ruby 3.0.0 or later. To install, add this line to your
|
|
78
77
|
`Gemfile` and run `bundle install`:
|
|
79
78
|
|
|
80
79
|
```ruby
|
|
@@ -145,13 +144,13 @@ Load RSpec 3.5+ support by adding the following line (typically to your
|
|
|
145
144
|
require 'capybara/rspec'
|
|
146
145
|
```
|
|
147
146
|
|
|
148
|
-
If you are using Rails, put your Capybara specs in `spec/features` or `spec/system` (only works
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
example groups with `type: :feature` or `type: :system` depending on which type of test you're writing.
|
|
147
|
+
If you are using Rails, put your Capybara specs in `spec/features` or `spec/system` (only works if
|
|
148
|
+
[you have it configured in RSpec](https://rspec.info/features/6-0/rspec-rails/directory-structure/))
|
|
149
|
+
and if you have your Capybara specs in a different directory, then tag the example groups with
|
|
150
|
+
`type: :feature` or `type: :system` depending on which type of test you're writing.
|
|
153
151
|
|
|
154
|
-
If you are using Rails system specs please see [their documentation](https://
|
|
152
|
+
If you are using Rails system specs please see [their documentation](https://rspec.info/features/6-0/rspec-rails/system-specs/system-specs)
|
|
153
|
+
for selecting the driver you wish to use.
|
|
155
154
|
|
|
156
155
|
If you are not using Rails, tag all the example groups in which you want to use
|
|
157
156
|
Capybara with `type: :feature`.
|
|
@@ -183,7 +182,7 @@ to one specific driver. For example:
|
|
|
183
182
|
```ruby
|
|
184
183
|
describe 'some stuff which requires js', js: true do
|
|
185
184
|
it 'will use the default js driver'
|
|
186
|
-
it 'will switch to one specific driver', driver: :
|
|
185
|
+
it 'will switch to one specific driver', driver: :selenium
|
|
187
186
|
end
|
|
188
187
|
```
|
|
189
188
|
|
|
@@ -353,7 +352,7 @@ You can also change the driver temporarily (typically in the Before/setup and
|
|
|
353
352
|
After/teardown blocks):
|
|
354
353
|
|
|
355
354
|
```ruby
|
|
356
|
-
Capybara.current_driver = :
|
|
355
|
+
Capybara.current_driver = :selenium # temporarily select different driver
|
|
357
356
|
# tests here
|
|
358
357
|
Capybara.use_default_driver # switch back to default driver
|
|
359
358
|
```
|
|
@@ -409,15 +408,6 @@ to the browsers. See the section on adding and configuring drivers.
|
|
|
409
408
|
same transaction as your tests, causing data not to be shared between your test
|
|
410
409
|
and test server, see [Transactions and database setup](#transactions-and-database-setup) below.
|
|
411
410
|
|
|
412
|
-
### <a name="apparition"></a>Apparition
|
|
413
|
-
|
|
414
|
-
The [apparition driver](https://github.com/twalpole/apparition) is a new driver that allows you to run tests using Chrome in a headless
|
|
415
|
-
or headed configuration. It attempts to provide backwards compatibility with the [Poltergeist driver API](https://github.com/teampoltergeist/poltergeist)
|
|
416
|
-
and [capybara-webkit API](https://github.com/thoughtbot/capybara-webkit) while allowing for the use of modern JS/CSS. It
|
|
417
|
-
uses CDP to communicate with Chrome, thereby obviating the need for chromedriver. This driver is being developed by the
|
|
418
|
-
current developer of Capybara and will attempt to keep up to date with new Capybara releases. It will probably be moved into the
|
|
419
|
-
teamcapybara repo once it reaches v1.0.
|
|
420
|
-
|
|
421
411
|
## <a name="the-dsl"></a>The DSL
|
|
422
412
|
|
|
423
413
|
*A complete reference is available at
|
|
@@ -632,10 +622,10 @@ JS
|
|
|
632
622
|
|
|
633
623
|
In drivers which support it, you can accept, dismiss and respond to alerts, confirms, and prompts.
|
|
634
624
|
|
|
635
|
-
You can accept
|
|
625
|
+
You can accept alert messages by wrapping the code that produces an alert in a block:
|
|
636
626
|
|
|
637
627
|
```ruby
|
|
638
|
-
accept_alert do
|
|
628
|
+
accept_alert 'optional text or regex' do
|
|
639
629
|
click_link('Show Alert')
|
|
640
630
|
end
|
|
641
631
|
```
|
|
@@ -643,7 +633,13 @@ end
|
|
|
643
633
|
You can accept or dismiss a confirmation by wrapping it in a block, as well:
|
|
644
634
|
|
|
645
635
|
```ruby
|
|
646
|
-
|
|
636
|
+
accept_confirm 'optional text' do
|
|
637
|
+
click_link('Show Confirm')
|
|
638
|
+
end
|
|
639
|
+
```
|
|
640
|
+
|
|
641
|
+
```ruby
|
|
642
|
+
dismiss_confirm 'optional text' do
|
|
647
643
|
click_link('Show Confirm')
|
|
648
644
|
end
|
|
649
645
|
```
|
|
@@ -651,7 +647,13 @@ end
|
|
|
651
647
|
You can accept or dismiss prompts as well, and also provide text to fill in for the response:
|
|
652
648
|
|
|
653
649
|
```ruby
|
|
654
|
-
accept_prompt(with: 'Linus Torvalds') do
|
|
650
|
+
accept_prompt('optional text', with: 'Linus Torvalds') do
|
|
651
|
+
click_link('Show Prompt About Linux')
|
|
652
|
+
end
|
|
653
|
+
```
|
|
654
|
+
|
|
655
|
+
```ruby
|
|
656
|
+
dismiss_prompt('optional text') do
|
|
655
657
|
click_link('Show Prompt About Linux')
|
|
656
658
|
end
|
|
657
659
|
```
|
|
@@ -701,6 +703,148 @@ Screenshots are saved to `Capybara.save_path`, relative to the app directory.
|
|
|
701
703
|
If you have required `capybara/rails`, `Capybara.save_path` will default to
|
|
702
704
|
`tmp/capybara`.
|
|
703
705
|
|
|
706
|
+
## <a name="selectors"></a>Selectors
|
|
707
|
+
|
|
708
|
+
Helpers and matchers that accept Selectors share a common method signature that
|
|
709
|
+
includes:
|
|
710
|
+
|
|
711
|
+
1. a positional Name argument
|
|
712
|
+
2. a positional Locator argument
|
|
713
|
+
3. keyword Filter arguments
|
|
714
|
+
4. a predicate Filter block argument
|
|
715
|
+
|
|
716
|
+
These arguments are usually optional in one way or another.
|
|
717
|
+
|
|
718
|
+
### <a name="selectors-name"></a>Name
|
|
719
|
+
|
|
720
|
+
The name argument determines the Selector to use. The argument is optional when
|
|
721
|
+
a helper explicitly conveys the selector name (for example, [`find_field`][]
|
|
722
|
+
uses `:field`, [`find_link`][] uses `:link`, etc):
|
|
723
|
+
|
|
724
|
+
```ruby
|
|
725
|
+
page.html # => '<a href="/">Home</a>'
|
|
726
|
+
|
|
727
|
+
page.find(:link) == page.find_link
|
|
728
|
+
|
|
729
|
+
page.html # => '<input>'
|
|
730
|
+
|
|
731
|
+
page.find(:field) == page.find_field
|
|
732
|
+
```
|
|
733
|
+
|
|
734
|
+
### <a name="selectors-locator"></a>Locator
|
|
735
|
+
|
|
736
|
+
The locator argument usually represents information that can most meaningfully
|
|
737
|
+
distinguish an element that matches the selector from an element that does not:
|
|
738
|
+
|
|
739
|
+
```ruby
|
|
740
|
+
page.html # => '<div id="greeting">Hello world</div>'
|
|
741
|
+
|
|
742
|
+
page.find(:css, 'div').text # => 'Hello world'
|
|
743
|
+
page.find(:xpath, './/div').text # => 'Hello world'
|
|
744
|
+
```
|
|
745
|
+
|
|
746
|
+
General purpose finder methods like [`find`][] and [`all`][] can accept the
|
|
747
|
+
locator as their first positional argument when the method can infer the default
|
|
748
|
+
value from the [`Capybara.default_selector`][] configuration:
|
|
749
|
+
|
|
750
|
+
```ruby
|
|
751
|
+
page.html # => '<div id="greeting">Hello world</div>'
|
|
752
|
+
|
|
753
|
+
Capybara.default_selector = :css
|
|
754
|
+
|
|
755
|
+
page.find('div').text # => 'Hello world'
|
|
756
|
+
|
|
757
|
+
Capybara.default_selector = :xpath
|
|
758
|
+
|
|
759
|
+
page.find('.//div').text # => 'Hello world'
|
|
760
|
+
```
|
|
761
|
+
|
|
762
|
+
The locator argument's semantics are context-specific, and depend on the
|
|
763
|
+
selector. The types of arguments are varied. Some selectors support `String` or
|
|
764
|
+
`Regexp` arguments, while others like `:table_row` support `Array<String>` and
|
|
765
|
+
`Hash<String, String>`:
|
|
766
|
+
|
|
767
|
+
```ruby
|
|
768
|
+
page.html # => '<label for="greeting">Greeting</label>
|
|
769
|
+
<input id="greeting" name="content">'
|
|
770
|
+
|
|
771
|
+
# find by the <input> element's [id] attribute
|
|
772
|
+
page.find(:id, 'greeting') == page.find_by_id('greeting') # => true
|
|
773
|
+
|
|
774
|
+
# find by the <input> element's [id] attribute
|
|
775
|
+
page.find(:field, 'greeting') == page.find_field('greeting') # => true
|
|
776
|
+
|
|
777
|
+
# find by the <input> element's [name] attribute
|
|
778
|
+
page.find(:field, 'content') == page.find_field('content') # => true
|
|
779
|
+
|
|
780
|
+
# find by the <label> element's text
|
|
781
|
+
page.find(:field, 'Greeting') == page.find_field('Greeting') # => true
|
|
782
|
+
|
|
783
|
+
page.html # => '<table>
|
|
784
|
+
<tr>
|
|
785
|
+
<th>A</th>
|
|
786
|
+
<th>B</th>
|
|
787
|
+
</tr>
|
|
788
|
+
<tr>
|
|
789
|
+
<td>1</td>
|
|
790
|
+
<td>2</td>
|
|
791
|
+
</tr>
|
|
792
|
+
</table>'
|
|
793
|
+
|
|
794
|
+
# find by <td> content
|
|
795
|
+
page.find(:table_row, ['1', '2']) == page.find(:css, 'tr:last-of-type') # => true
|
|
796
|
+
|
|
797
|
+
# find by <th> content paired with corresponding <td> content
|
|
798
|
+
page.find(:table_row, 'A' => '1') == page.find(:table_row, 'B' => '2') # => true
|
|
799
|
+
```
|
|
800
|
+
|
|
801
|
+
### <a name="selectors-filters"></a> Filters
|
|
802
|
+
|
|
803
|
+
All filters are optional. The supported set of keys is a mixture of both global
|
|
804
|
+
and context-specific filters.The supported types of values depend on the
|
|
805
|
+
context:
|
|
806
|
+
|
|
807
|
+
```ruby
|
|
808
|
+
page.html # => '<a href="/">Home</a>'
|
|
809
|
+
|
|
810
|
+
# find by the [href] attribute
|
|
811
|
+
page.find_link(href: '/') == page.find_link(text: 'Home') # => true
|
|
812
|
+
|
|
813
|
+
page.html # => '<div id="element" data-attribute="value">Content</div>'
|
|
814
|
+
|
|
815
|
+
# find by the [id] attribute
|
|
816
|
+
page.find(id: 'element') == page.find(text: 'Content') # => true
|
|
817
|
+
|
|
818
|
+
# find by the [data-attribute] attribute
|
|
819
|
+
page.find(:element, 'data-attribute': /value/) == page.find(text: 'Content') # => true
|
|
820
|
+
|
|
821
|
+
page.html # => '<input type="checkbox">'
|
|
822
|
+
|
|
823
|
+
# find by the absence of the [checked] attribute
|
|
824
|
+
page.find_field(checked: false) == page.find_field(unchecked: true) # => true
|
|
825
|
+
```
|
|
826
|
+
|
|
827
|
+
The predicate block is always optional. When there are results for a selector
|
|
828
|
+
query, the block is called with each item in the result set. When the block
|
|
829
|
+
evaluates to true, the item is included from the result set. Otherwise, the item
|
|
830
|
+
is excluded:
|
|
831
|
+
|
|
832
|
+
```ruby
|
|
833
|
+
page.html # => '<input role="switch" type="checkbox" checked>'
|
|
834
|
+
|
|
835
|
+
switch = page.find_field { |input| input["role"] == "switch" }
|
|
836
|
+
field = page.find_field(checked: true)
|
|
837
|
+
|
|
838
|
+
switch == field # => true
|
|
839
|
+
```
|
|
840
|
+
|
|
841
|
+
[`find`]: https://rubydoc.info/github/teamcapybara/capybara/master/Capybara/Node/Finders:find
|
|
842
|
+
[`all`]: https://rubydoc.info/github/teamcapybara/capybara/master/Capybara/Node/Finders:all
|
|
843
|
+
[`Capybara.default_selector`]: https://rubydoc.info/github/teamcapybara/capybara/master/Capybara%2Econfigure
|
|
844
|
+
[`find_by_id`]: https://rubydoc.info/github/teamcapybara/capybara/master/Capybara/Node/Finders:find_by_id
|
|
845
|
+
[`find_field`]: https://rubydoc.info/github/teamcapybara/capybara/master/Capybara/Node/Finders:find_field
|
|
846
|
+
[`find_link`]: https://rubydoc.info/github/teamcapybara/capybara/master/Capybara/Node/Finders:find_link
|
|
847
|
+
|
|
704
848
|
## <a name="matching"></a>Matching
|
|
705
849
|
|
|
706
850
|
It is possible to customize how Capybara finds elements. At your disposal
|
data/lib/capybara/helpers.rb
CHANGED
|
@@ -95,6 +95,18 @@ module Capybara
|
|
|
95
95
|
# @!method wont_have_field
|
|
96
96
|
# See {Capybara::Node::Matchers#has_no_field?}
|
|
97
97
|
|
|
98
|
+
##
|
|
99
|
+
# Expectation that there is element
|
|
100
|
+
#
|
|
101
|
+
# @!method must_have_element
|
|
102
|
+
# See {Capybara::Node::Matchers#has_element?}
|
|
103
|
+
|
|
104
|
+
##
|
|
105
|
+
# Expectation that there is no element
|
|
106
|
+
#
|
|
107
|
+
# @!method wont_have_element
|
|
108
|
+
# See {Capybara::Node::Matchers#has_no_element?}
|
|
109
|
+
|
|
98
110
|
##
|
|
99
111
|
# Expectation that there is link
|
|
100
112
|
#
|
|
@@ -230,15 +242,15 @@ module Capybara
|
|
|
230
242
|
%W[refute_matches_#{assertion} wont_match_#{assertion}]]
|
|
231
243
|
end).each do |(meth, new_name)|
|
|
232
244
|
class_eval <<-ASSERTION, __FILE__, __LINE__ + 1
|
|
233
|
-
def #{new_name}
|
|
234
|
-
::Minitest::Expectation.new(self, ::Minitest::Spec.current).#{new_name}(
|
|
245
|
+
def #{new_name}(...)
|
|
246
|
+
::Minitest::Expectation.new(self, ::Minitest::Spec.current).#{new_name}(...)
|
|
235
247
|
end
|
|
236
248
|
ASSERTION
|
|
237
249
|
|
|
238
250
|
::Minitest::Expectation.class_eval <<-ASSERTION, __FILE__, __LINE__ + 1
|
|
239
|
-
def #{new_name}
|
|
251
|
+
def #{new_name}(...)
|
|
240
252
|
raise "Calling ##{new_name} outside of test." unless ctx
|
|
241
|
-
ctx.#{meth}(target,
|
|
253
|
+
ctx.#{meth}(target, ...)
|
|
242
254
|
end
|
|
243
255
|
ASSERTION
|
|
244
256
|
end
|
data/lib/capybara/minitest.rb
CHANGED
|
@@ -190,6 +190,19 @@ module Capybara
|
|
|
190
190
|
# @!method assert_no_css
|
|
191
191
|
# See {Capybara::Node::Matchers#has_no_css?}
|
|
192
192
|
|
|
193
|
+
##
|
|
194
|
+
# Assert that provided element exists
|
|
195
|
+
#
|
|
196
|
+
# @!method assert_element
|
|
197
|
+
# See {Capybara::Node::Matchers#has_element?}
|
|
198
|
+
|
|
199
|
+
##
|
|
200
|
+
# Assert that provided element does not exist
|
|
201
|
+
#
|
|
202
|
+
# @!method assert_no_element
|
|
203
|
+
# @!method refute_element
|
|
204
|
+
# See {Capybara::Node::Matchers#has_no_element?}
|
|
205
|
+
|
|
193
206
|
##
|
|
194
207
|
# Assert that provided link exists
|
|
195
208
|
#
|
|
@@ -281,7 +294,7 @@ module Capybara
|
|
|
281
294
|
# @!method assert_no_table
|
|
282
295
|
# See {Capybara::Node::Matchers#has_no_table?}
|
|
283
296
|
|
|
284
|
-
%w[xpath css link button field select table].each do |selector_type|
|
|
297
|
+
%w[xpath css element link button field select table].each do |selector_type|
|
|
285
298
|
define_method "assert_#{selector_type}" do |*args, &optional_filter_block|
|
|
286
299
|
subject, args = determine_subject(args)
|
|
287
300
|
locator, options = extract_locator(args)
|
|
@@ -322,6 +322,31 @@ module Capybara
|
|
|
322
322
|
has_no_selector?(:css, path, **options, &optional_filter_block)
|
|
323
323
|
end
|
|
324
324
|
|
|
325
|
+
##
|
|
326
|
+
#
|
|
327
|
+
# Checks if the page or current node has a element with the given
|
|
328
|
+
# local name.
|
|
329
|
+
#
|
|
330
|
+
# @param [String] locator The local name of a element to check for
|
|
331
|
+
# @option options [String, Regexp] The attributes values of matching elements
|
|
332
|
+
# @return [Boolean] Whether it exists
|
|
333
|
+
#
|
|
334
|
+
def has_element?(locator = nil, **options, &optional_filter_block)
|
|
335
|
+
has_selector?(:element, locator, **options, &optional_filter_block)
|
|
336
|
+
end
|
|
337
|
+
|
|
338
|
+
##
|
|
339
|
+
#
|
|
340
|
+
# Checks if the page or current node has no element with the given
|
|
341
|
+
# local name.
|
|
342
|
+
#
|
|
343
|
+
# @param (see #has_element?)
|
|
344
|
+
# @return [Boolean] Whether it doesn't exist
|
|
345
|
+
#
|
|
346
|
+
def has_no_element?(locator = nil, **options, &optional_filter_block)
|
|
347
|
+
has_no_selector?(:element, locator, **options, &optional_filter_block)
|
|
348
|
+
end
|
|
349
|
+
|
|
325
350
|
##
|
|
326
351
|
#
|
|
327
352
|
# Checks if the page or current node has a link with the given
|
|
@@ -16,16 +16,16 @@ module Capybara
|
|
|
16
16
|
PARAGRAPH_SEPERATOR = "\u2029"
|
|
17
17
|
|
|
18
18
|
# All spaces except for NBSP
|
|
19
|
-
BREAKING_SPACES = "[[:space:]&&[^#{NON_BREAKING_SPACE}]]"
|
|
19
|
+
BREAKING_SPACES = "[[:space:]&&[^#{NON_BREAKING_SPACE}]]".freeze
|
|
20
20
|
|
|
21
21
|
# Whitespace we want to substitute with plain spaces
|
|
22
|
-
SQUEEZED_SPACES = " \n\f\t\v#{LINE_SEPERATOR}#{PARAGRAPH_SEPERATOR}"
|
|
22
|
+
SQUEEZED_SPACES = " \n\f\t\v#{LINE_SEPERATOR}#{PARAGRAPH_SEPERATOR}".freeze
|
|
23
23
|
|
|
24
24
|
# Any whitespace at the front of text
|
|
25
|
-
LEADING_SPACES = /\A#{BREAKING_SPACES}
|
|
25
|
+
LEADING_SPACES = /\A#{BREAKING_SPACES}+/
|
|
26
26
|
|
|
27
27
|
# Any whitespace at the end of text
|
|
28
|
-
TRAILING_SPACES = /#{BREAKING_SPACES}+\z
|
|
28
|
+
TRAILING_SPACES = /#{BREAKING_SPACES}+\z/
|
|
29
29
|
|
|
30
30
|
# "Invisible" space character
|
|
31
31
|
ZERO_WIDTH_SPACE = "\u200b"
|
|
@@ -40,7 +40,7 @@ module Capybara
|
|
|
40
40
|
REMOVED_CHARACTERS = [ZERO_WIDTH_SPACE, LEFT_TO_RIGHT_MARK, RIGHT_TO_LEFT_MARK].join
|
|
41
41
|
|
|
42
42
|
# Matches multiple empty lines
|
|
43
|
-
EMPTY_LINES = /[\ \n]*\n[\ \n]
|
|
43
|
+
EMPTY_LINES = /[\ \n]*\n[\ \n]*/
|
|
44
44
|
|
|
45
45
|
##
|
|
46
46
|
#
|
|
@@ -70,7 +70,8 @@ module Capybara
|
|
|
70
70
|
desc << 'non-visible ' if visible == :hidden
|
|
71
71
|
end
|
|
72
72
|
|
|
73
|
-
desc <<
|
|
73
|
+
desc << label.to_s
|
|
74
|
+
desc << " #{locator.inspect}" unless locator.nil?
|
|
74
75
|
|
|
75
76
|
if show_for[:any]
|
|
76
77
|
desc << " with#{' exact' if exact_text == true} text #{options[:text].inspect}" if options[:text]
|
|
@@ -35,12 +35,13 @@ class Capybara::RackTest::Browser
|
|
|
35
35
|
path = request_path if path.nil? || path.empty?
|
|
36
36
|
uri = build_uri(path)
|
|
37
37
|
uri.query = '' if method.to_s.casecmp('get').zero?
|
|
38
|
+
env = { 'HTTP_REFERER' => referer_url }
|
|
39
|
+
env['CONTENT_TYPE'] = content_type if content_type
|
|
38
40
|
process_and_follow_redirects(
|
|
39
41
|
method,
|
|
40
42
|
uri.to_s,
|
|
41
43
|
attributes,
|
|
42
|
-
|
|
43
|
-
'CONTENT_TYPE' => content_type
|
|
44
|
+
env
|
|
44
45
|
)
|
|
45
46
|
end
|
|
46
47
|
|
|
@@ -125,19 +125,12 @@ class Capybara::RackTest::Node < Capybara::Driver::Node
|
|
|
125
125
|
alias_method "unchecked_#{meth_name}", meth_name
|
|
126
126
|
private "unchecked_#{meth_name}" # rubocop:disable Style/AccessModifierDeclarations
|
|
127
127
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
def #{meth_name}(...)
|
|
131
|
-
stale_check
|
|
132
|
-
method(:"unchecked_#{meth_name}").call(...)
|
|
133
|
-
end
|
|
134
|
-
METHOD
|
|
135
|
-
else
|
|
136
|
-
define_method meth_name do |*args|
|
|
128
|
+
class_eval <<~METHOD, __FILE__, __LINE__ + 1
|
|
129
|
+
def #{meth_name}(...)
|
|
137
130
|
stale_check
|
|
138
|
-
|
|
131
|
+
method(:"unchecked_#{meth_name}").call(...)
|
|
139
132
|
end
|
|
140
|
-
|
|
133
|
+
METHOD
|
|
141
134
|
end
|
|
142
135
|
|
|
143
136
|
protected
|
|
@@ -232,7 +225,7 @@ private
|
|
|
232
225
|
native.remove
|
|
233
226
|
else
|
|
234
227
|
value.to_s.tap do |set_value|
|
|
235
|
-
if set_value.end_with?("\n") && form&.css('input, textarea')&.count
|
|
228
|
+
if set_value.end_with?("\n") && form&.css('input, textarea')&.count == 1
|
|
236
229
|
native['value'] = set_value.to_s.chop
|
|
237
230
|
Capybara::RackTest::Form.new(driver, form).submit(self)
|
|
238
231
|
else
|
|
@@ -16,10 +16,10 @@ module Capybara
|
|
|
16
16
|
@registered[name] = value
|
|
17
17
|
end
|
|
18
18
|
|
|
19
|
-
def method_missing(method_name,
|
|
19
|
+
def method_missing(method_name, ...)
|
|
20
20
|
if @registered.respond_to?(method_name)
|
|
21
21
|
Capybara::Helpers.warn "DEPRECATED: Calling '#{method_name}' on the drivers/servers container is deprecated without replacement"
|
|
22
|
-
return @registered.public_send(method_name,
|
|
22
|
+
return @registered.public_send(method_name, ...)
|
|
23
23
|
end
|
|
24
24
|
super
|
|
25
25
|
end
|
|
@@ -32,7 +32,7 @@ Capybara.register_driver :selenium_chrome_headless do |app|
|
|
|
32
32
|
version = Capybara::Selenium::Driver.load_selenium
|
|
33
33
|
options_key = Capybara::Selenium::Driver::CAPS_VERSION.satisfied_by?(version) ? :capabilities : :options
|
|
34
34
|
browser_options = Selenium::WebDriver::Chrome::Options.new.tap do |opts|
|
|
35
|
-
opts.add_argument('--headless')
|
|
35
|
+
opts.add_argument('--headless=new')
|
|
36
36
|
opts.add_argument('--disable-gpu') if Gem.win_platform?
|
|
37
37
|
# Workaround https://bugs.chromium.org/p/chromedriver/issues/detail?id=2650&q=load&sort=-id&colspec=ID%20Status%20Pri%20Owner%20Summary
|
|
38
38
|
opts.add_argument('--disable-site-isolation-trials')
|
|
@@ -27,19 +27,20 @@ Capybara.register_server :puma do |app, port, host, **options| # rubocop:disable
|
|
|
27
27
|
require 'rack/handler/puma'
|
|
28
28
|
rescue LoadError
|
|
29
29
|
raise LoadError, 'Capybara is unable to load `puma` for its server, please add `puma` to your project or specify a different server via something like `Capybara.server = :webrick`.'
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
30
|
+
end
|
|
31
|
+
puma_rack_handler = defined?(Rackup::Handler::Puma) ? Rackup::Handler::Puma : Rack::Handler::Puma
|
|
32
|
+
|
|
33
|
+
unless puma_rack_handler.respond_to?(:config)
|
|
34
|
+
raise LoadError, 'Capybara requires `puma` version 3.8.0 or higher, please upgrade `puma` or register and specify your own server block'
|
|
34
35
|
end
|
|
35
36
|
|
|
36
37
|
# If we just run the Puma Rack handler it installs signal handlers which prevent us from being able to interrupt tests.
|
|
37
38
|
# Therefore construct and run the Server instance ourselves.
|
|
38
|
-
#
|
|
39
|
+
# puma_rack_handler.run(app, { Host: host, Port: port, Threads: "0:4", workers: 0, daemon: false }.merge(options))
|
|
39
40
|
default_options = { Host: host, Port: port, Threads: '0:4', workers: 0, daemon: false }
|
|
40
41
|
options = default_options.merge(options)
|
|
41
42
|
|
|
42
|
-
conf =
|
|
43
|
+
conf = puma_rack_handler.config(app, options)
|
|
43
44
|
conf.clamp
|
|
44
45
|
|
|
45
46
|
puma_ver = Gem::Version.new(Puma::Const::PUMA_VERSION)
|
|
@@ -51,7 +52,7 @@ Capybara.register_server :puma do |app, port, host, **options| # rubocop:disable
|
|
|
51
52
|
conf.options[:log_writer] = logger
|
|
52
53
|
|
|
53
54
|
logger.log 'Capybara starting Puma...'
|
|
54
|
-
logger.log "* Version #{Puma::Const::PUMA_VERSION}
|
|
55
|
+
logger.log "* Version #{Puma::Const::PUMA_VERSION}, codename: #{Puma::Const::CODE_NAME}"
|
|
55
56
|
logger.log "* Min threads: #{conf.options[:min_threads]}, max threads: #{conf.options[:max_threads]}"
|
|
56
57
|
|
|
57
58
|
Puma::Server.new(
|
data/lib/capybara/result.rb
CHANGED
|
@@ -34,7 +34,7 @@ module Capybara
|
|
|
34
34
|
@allow_reload = false
|
|
35
35
|
end
|
|
36
36
|
|
|
37
|
-
def_delegators :full_results, :size, :length, :last, :values_at, :inspect, :sample
|
|
37
|
+
def_delegators :full_results, :size, :length, :last, :values_at, :inspect, :sample, :to_ary
|
|
38
38
|
|
|
39
39
|
alias index find_index
|
|
40
40
|
|
|
@@ -116,7 +116,7 @@ module Capybara
|
|
|
116
116
|
message << ' but there were no matches'
|
|
117
117
|
else
|
|
118
118
|
message << ", found #{count} #{Capybara::Helpers.declension('match', 'matches', count)}: " \
|
|
119
|
-
<< full_results.map
|
|
119
|
+
<< full_results.map { |r| r.text.inspect }.join(', ')
|
|
120
120
|
end
|
|
121
121
|
unless rest.empty?
|
|
122
122
|
elements = rest.map { |el| el.text rescue '<<ERROR>>' }.map(&:inspect).join(', ') # rubocop:disable Style/RescueModifier
|
|
@@ -22,9 +22,7 @@ module Capybara
|
|
|
22
22
|
el.assert_no_selector(*@args, **session_query_options, &@filter_block)
|
|
23
23
|
end
|
|
24
24
|
|
|
25
|
-
def description
|
|
26
|
-
"have #{query.description}"
|
|
27
|
-
end
|
|
25
|
+
def description = "have #{query.description}"
|
|
28
26
|
|
|
29
27
|
def query
|
|
30
28
|
@query ||= Capybara::Queries::SelectorQuery.new(*session_query_args, **session_query_options, &@filter_block)
|
|
@@ -40,9 +38,7 @@ module Capybara
|
|
|
40
38
|
raise ArgumentError, 'The have_all_selectors matcher does not support use with not_to/should_not'
|
|
41
39
|
end
|
|
42
40
|
|
|
43
|
-
def description
|
|
44
|
-
'have all selectors'
|
|
45
|
-
end
|
|
41
|
+
def description = 'have all selectors'
|
|
46
42
|
end
|
|
47
43
|
|
|
48
44
|
class HaveNoSelectors < WrappedElementMatcher
|
|
@@ -54,9 +50,7 @@ module Capybara
|
|
|
54
50
|
raise ArgumentError, 'The have_none_of_selectors matcher does not support use with not_to/should_not'
|
|
55
51
|
end
|
|
56
52
|
|
|
57
|
-
def description
|
|
58
|
-
'have no selectors'
|
|
59
|
-
end
|
|
53
|
+
def description = 'have no selectors'
|
|
60
54
|
end
|
|
61
55
|
|
|
62
56
|
class HaveAnySelectors < WrappedElementMatcher
|
|
@@ -68,9 +62,7 @@ module Capybara
|
|
|
68
62
|
el.assert_none_of_selectors(*@args, **session_query_options, &@filter_block)
|
|
69
63
|
end
|
|
70
64
|
|
|
71
|
-
def description
|
|
72
|
-
'have any selectors'
|
|
73
|
-
end
|
|
65
|
+
def description = 'have any selectors'
|
|
74
66
|
end
|
|
75
67
|
end
|
|
76
68
|
end
|