capybara 2.0.3 → 2.1.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.
- data/History.md +82 -0
- data/README.md +57 -52
- data/lib/capybara/cucumber.rb +4 -1
- data/lib/capybara/driver/base.rb +13 -9
- data/lib/capybara/driver/node.rb +18 -6
- data/lib/capybara/helpers.rb +111 -22
- data/lib/capybara/node/actions.rb +30 -25
- data/lib/capybara/node/base.rb +25 -32
- data/lib/capybara/node/document.rb +6 -2
- data/lib/capybara/node/element.rb +44 -7
- data/lib/capybara/node/finders.rb +49 -22
- data/lib/capybara/node/matchers.rb +38 -21
- data/lib/capybara/node/simple.rb +31 -9
- data/lib/capybara/query.rb +72 -26
- data/lib/capybara/rack_test/browser.rb +11 -3
- data/lib/capybara/rack_test/css_handlers.rb +8 -0
- data/lib/capybara/rack_test/driver.rb +11 -3
- data/lib/capybara/rack_test/form.rb +8 -1
- data/lib/capybara/rack_test/node.rb +91 -35
- data/lib/capybara/rails.rb +0 -1
- data/lib/capybara/result.rb +21 -37
- data/lib/capybara/rspec/matchers.rb +60 -31
- data/lib/capybara/selector.rb +46 -13
- data/lib/capybara/selenium/driver.rb +42 -7
- data/lib/capybara/selenium/node.rb +23 -5
- data/lib/capybara/server.rb +1 -1
- data/lib/capybara/session.rb +47 -12
- data/lib/capybara/spec/public/test.js +12 -0
- data/lib/capybara/spec/session/all_spec.rb +9 -8
- data/lib/capybara/spec/session/attach_file_spec.rb +14 -0
- data/lib/capybara/spec/session/check_spec.rb +14 -0
- data/lib/capybara/spec/session/choose_spec.rb +14 -0
- data/lib/capybara/spec/session/click_button_spec.rb +77 -1
- data/lib/capybara/spec/session/click_link_or_button_spec.rb +65 -0
- data/lib/capybara/spec/session/click_link_spec.rb +24 -0
- data/lib/capybara/spec/session/current_scope_spec.rb +29 -0
- data/lib/capybara/spec/session/fill_in_spec.rb +26 -0
- data/lib/capybara/spec/session/find_button_spec.rb +12 -0
- data/lib/capybara/spec/session/find_by_id_spec.rb +12 -1
- data/lib/capybara/spec/session/find_field_spec.rb +30 -0
- data/lib/capybara/spec/session/find_link_spec.rb +12 -0
- data/lib/capybara/spec/session/find_spec.rb +264 -16
- data/lib/capybara/spec/session/first_spec.rb +25 -8
- data/lib/capybara/spec/session/has_css_spec.rb +2 -2
- data/lib/capybara/spec/session/has_field_spec.rb +10 -2
- data/lib/capybara/spec/session/has_selector_spec.rb +9 -0
- data/lib/capybara/spec/session/has_text_spec.rb +96 -0
- data/lib/capybara/spec/session/has_title_spec.rb +47 -0
- data/lib/capybara/spec/session/node_spec.rb +48 -0
- data/lib/capybara/spec/session/reset_session_spec.rb +10 -2
- data/lib/capybara/spec/session/save_page_spec.rb +30 -0
- data/lib/capybara/spec/session/select_spec.rb +65 -0
- data/lib/capybara/spec/session/text_spec.rb +31 -0
- data/lib/capybara/spec/session/title_spec.rb +16 -0
- data/lib/capybara/spec/session/uncheck_spec.rb +14 -0
- data/lib/capybara/spec/session/unselect_spec.rb +42 -0
- data/lib/capybara/spec/session/visit_spec.rb +3 -3
- data/lib/capybara/spec/session/within_frame_spec.rb +14 -0
- data/lib/capybara/spec/session/within_spec.rb +3 -3
- data/lib/capybara/spec/spec_helper.rb +7 -2
- data/lib/capybara/spec/views/form.erb +39 -2
- data/lib/capybara/spec/views/frame_child.erb +9 -0
- data/lib/capybara/spec/views/frame_parent.erb +8 -0
- data/lib/capybara/spec/views/with_base_tag.erb +10 -0
- data/lib/capybara/spec/views/with_count.erb +7 -0
- data/lib/capybara/spec/views/with_hover.erb +17 -0
- data/lib/capybara/spec/views/with_html.erb +23 -2
- data/lib/capybara/spec/views/with_js.erb +5 -0
- data/lib/capybara/spec/views/with_scope.erb +6 -1
- data/lib/capybara/spec/views/with_title.erb +1 -0
- data/lib/capybara/spec/views/within_frames.erb +1 -0
- data/lib/capybara/version.rb +1 -1
- data/lib/capybara.rb +43 -62
- data/spec/basic_node_spec.rb +75 -24
- data/spec/dsl_spec.rb +2 -1
- data/spec/rack_test_spec.rb +4 -3
- data/spec/rspec/matchers_spec.rb +105 -17
- data/spec/server_spec.rb +15 -8
- data/spec/spec_helper.rb +2 -1
- data.tar.gz.sig +0 -0
- metadata +82 -22
- metadata.gz.sig +0 -0
data/History.md
CHANGED
|
@@ -1,3 +1,85 @@
|
|
|
1
|
+
# Version 2.1.0
|
|
2
|
+
|
|
3
|
+
Release date: Unreleased
|
|
4
|
+
|
|
5
|
+
### Changed
|
|
6
|
+
|
|
7
|
+
* Hard version requirement on Ruby >= 1.9.3. Capybara will no longer install
|
|
8
|
+
on 1.8.7. [Felix Schäfer]
|
|
9
|
+
* Capybara no longer depends on the `selenium-webdriver` gem. Add it to
|
|
10
|
+
your Gemfile if you wish to use the Selenium driver. [Jonas Nicklas]
|
|
11
|
+
* `Capybara.ignore_hidden_elements` defaults to `true`. [Jonas Nicklas]
|
|
12
|
+
* In case of multiple matches `smart` matching is used by default. Set
|
|
13
|
+
`Capybara.match = :one` to revert to old behaviour. [Jonas Nicklas].
|
|
14
|
+
* Options in select boxes use smart matching and no longer need to match
|
|
15
|
+
exactly. Set `Capybara.exact_options = false` to revert to old behaviour.
|
|
16
|
+
[Jonas Nicklas].
|
|
17
|
+
* Visibility of text depends on `Capybara.ignore_hidden_elements` instead of
|
|
18
|
+
always returning only visible text. Set `Capybara.visible_text_only = true`
|
|
19
|
+
to revert to old behaviour. [Jonas Nicklas]
|
|
20
|
+
* Cucumber cleans up session after scenario instead. This is consistent with
|
|
21
|
+
RSpec and makes more sense, since we raise server errors in `reset!`.
|
|
22
|
+
[Jonas Nicklas]
|
|
23
|
+
|
|
24
|
+
### Added
|
|
25
|
+
|
|
26
|
+
* All actions (`click_link`, `fill_in`, etc...) and finders now take an options
|
|
27
|
+
hash, which is passed through to `find`. [Jonas Nicklas]
|
|
28
|
+
* CSS selectors are sent straight through to driver instead of being converted
|
|
29
|
+
to XPath first. Enables the use of some pseudo selectors, such as `invalid`
|
|
30
|
+
in some drivers. [Thomas Walpole]
|
|
31
|
+
* `Capybara.asset_host` option, which inserts a `base` tag into the page on
|
|
32
|
+
`save_and_open_page`, eases debugging with the Rails asset pipeline.
|
|
33
|
+
[Steve Hull]
|
|
34
|
+
* `exact` option, can specify whether to match substrings or entire text.
|
|
35
|
+
[Jonas Nicklas]
|
|
36
|
+
* `match` option, can specify behaviour in case of multiple matches.
|
|
37
|
+
[Jonas Nicklas]
|
|
38
|
+
* `wait` option, can specify how long to wait for a given action/finder.
|
|
39
|
+
[Jonas Nicklas]
|
|
40
|
+
* Config option which disables bubbling of errors raised inside server.
|
|
41
|
+
[Jonas Nicklas]
|
|
42
|
+
* `text` now takes a parameter which makes it possible to return either all
|
|
43
|
+
text or only visible text. The default depends on
|
|
44
|
+
`Capybara.ignore_hidden_elements`. `Capybara.visible_text_only` option is
|
|
45
|
+
available for compatibility. [Jonas Nicklas]
|
|
46
|
+
* `has_content?` and `has_text?` now take the same count options as `has_selector?`
|
|
47
|
+
[Andrey Botalov]
|
|
48
|
+
* `current_scope` is now public API, returns the current element when `within`
|
|
49
|
+
is used. [Martijn Walraven]
|
|
50
|
+
* `find("input").disabled?` returns true if a node is disabled. [Ben Lovell]
|
|
51
|
+
* Find disabled fields and buttons with `:disabled => false`. [Jonas Nicklas]
|
|
52
|
+
* `find("input").hover` moves the mouse to the element in supported drivers.
|
|
53
|
+
[Thomas Walpole]
|
|
54
|
+
* RackTest driver now support `form` attribute on form elements.
|
|
55
|
+
[Thomas Walpole]
|
|
56
|
+
* `page.title` returns the page title. [Terry Progetto]
|
|
57
|
+
* `has_title?` matcher to assert on page title. [Jonas Nicklas]
|
|
58
|
+
* The gem is now signed with a certicficate. The public key is available in the
|
|
59
|
+
repo. [Jonas Nicklas]
|
|
60
|
+
* `:select` and `:textarea` are valid options for the `:type` filter on `find_field`
|
|
61
|
+
and `has_field?`. [Yann Plancqueel]
|
|
62
|
+
|
|
63
|
+
### Fixed
|
|
64
|
+
|
|
65
|
+
* Fixed race conditions when synchronizing across multiple nodes [Jonas Nicklas]
|
|
66
|
+
* Fixed race conditions in deeply nested selectors [Jonas Nicklas]
|
|
67
|
+
* Fix issue with `within_frame`, where selecting multiple nested frames didn't
|
|
68
|
+
work as intended. [Thomas Walpole]
|
|
69
|
+
* RackTest no longer fills in readonly textareas. [Thomas Walpole]
|
|
70
|
+
* Don't use autoload to load files, require them directly instead. [Jonas Nicklas]
|
|
71
|
+
* Rescue weird exceptions when booting server [John Wilger]
|
|
72
|
+
* Non strings are now properly cast when using the maxlength attribute [Jonas Nicklas]
|
|
73
|
+
|
|
74
|
+
# Version 2.0.3
|
|
75
|
+
|
|
76
|
+
Release date: 2013-03-26
|
|
77
|
+
|
|
78
|
+
* Check against Rails version fixed to work with Rails' master branch now returning
|
|
79
|
+
a Gem::Version [Jonas Nicklas]
|
|
80
|
+
* Use posix character class for whitespace replace, solves various encoding
|
|
81
|
+
problems on Ruby 2.0.0 and JRuby. [Ben Cates]
|
|
82
|
+
|
|
1
83
|
# Version 2.0.2
|
|
2
84
|
|
|
3
85
|
Release date: 2012-12-31
|
data/README.md
CHANGED
|
@@ -23,19 +23,19 @@ GitHub): http://groups.google.com/group/ruby-capybara
|
|
|
23
23
|
|
|
24
24
|
## Setup
|
|
25
25
|
|
|
26
|
-
To install, type
|
|
26
|
+
Capybara requires Ruby 1.9.3 or later. To install, type:
|
|
27
27
|
|
|
28
28
|
```bash
|
|
29
|
-
|
|
29
|
+
gem install capybara
|
|
30
30
|
```
|
|
31
31
|
|
|
32
|
-
If you are
|
|
32
|
+
If the application that you are testing is a Rails app, add this line to your test helper file:
|
|
33
33
|
|
|
34
34
|
```ruby
|
|
35
35
|
require 'capybara/rails'
|
|
36
36
|
```
|
|
37
37
|
|
|
38
|
-
If you are not
|
|
38
|
+
If the application that you are testing is a Rack app, but not Rails, set Capybara.app to your Rack app:
|
|
39
39
|
|
|
40
40
|
```ruby
|
|
41
41
|
Capybara.app = MyRackApp
|
|
@@ -102,11 +102,13 @@ describe "the signup process", :type => :feature do
|
|
|
102
102
|
end
|
|
103
103
|
|
|
104
104
|
it "signs me in" do
|
|
105
|
+
visit '/sessions/new'
|
|
105
106
|
within("#session") do
|
|
106
107
|
fill_in 'Login', :with => 'user@example.com'
|
|
107
108
|
fill_in 'Password', :with => 'password'
|
|
108
109
|
end
|
|
109
110
|
click_link 'Sign in'
|
|
111
|
+
page.should have_content 'Success'
|
|
110
112
|
end
|
|
111
113
|
end
|
|
112
114
|
```
|
|
@@ -131,21 +133,25 @@ feature "Signing up" do
|
|
|
131
133
|
end
|
|
132
134
|
|
|
133
135
|
scenario "Signing in with correct credentials" do
|
|
136
|
+
visit '/sessions/new'
|
|
134
137
|
within("#session") do
|
|
135
138
|
fill_in 'Login', :with => 'user@example.com'
|
|
136
139
|
fill_in 'Password', :with => 'caplin'
|
|
137
140
|
end
|
|
138
141
|
click_link 'Sign in'
|
|
142
|
+
page.should have_content 'Success'
|
|
139
143
|
end
|
|
140
144
|
|
|
141
145
|
given(:other_user) { User.make(:email => 'other@example.com', :password => 'rous') }
|
|
142
146
|
|
|
143
147
|
scenario "Signing in as another user" do
|
|
148
|
+
visit '/sessions/new'
|
|
144
149
|
within("#session") do
|
|
145
150
|
fill_in 'Login', :with => other_user.email
|
|
146
151
|
fill_in 'Password', :with => other_user.password
|
|
147
152
|
end
|
|
148
153
|
click_link 'Sign in'
|
|
154
|
+
page.should have_content 'Invalid email or password'
|
|
149
155
|
end
|
|
150
156
|
end
|
|
151
157
|
```
|
|
@@ -156,36 +162,14 @@ end
|
|
|
156
162
|
|
|
157
163
|
## Using Capybara with Test::Unit
|
|
158
164
|
|
|
159
|
-
* If you are using Rails, add
|
|
160
|
-
|
|
161
|
-
```ruby
|
|
162
|
-
group :test do
|
|
163
|
-
gem 'database_cleaner'
|
|
164
|
-
end
|
|
165
|
-
```
|
|
166
|
-
|
|
167
|
-
Then add the following code in your `test_helper.rb` file to make
|
|
168
|
-
Capybara available in all test cases deriving from
|
|
165
|
+
* If you are using Rails, add the following code in your `test_helper.rb`
|
|
166
|
+
file to make Capybara available in all test cases deriving from
|
|
169
167
|
`ActionDispatch::IntegrationTest`:
|
|
170
168
|
|
|
171
169
|
```ruby
|
|
172
|
-
# Transactional fixtures do not work with Selenium tests, because Capybara
|
|
173
|
-
# uses a separate server thread, which the transactions would be hidden
|
|
174
|
-
# from. We hence use DatabaseCleaner to truncate our test database.
|
|
175
|
-
DatabaseCleaner.strategy = :truncation
|
|
176
|
-
|
|
177
170
|
class ActionDispatch::IntegrationTest
|
|
178
171
|
# Make the Capybara DSL available in all integration tests
|
|
179
172
|
include Capybara::DSL
|
|
180
|
-
|
|
181
|
-
# Stop ActiveRecord from wrapping tests in transactions
|
|
182
|
-
self.use_transactional_fixtures = false
|
|
183
|
-
|
|
184
|
-
teardown do
|
|
185
|
-
DatabaseCleaner.clean # Truncate the database
|
|
186
|
-
Capybara.reset_sessions! # Forget the (simulated) browser state
|
|
187
|
-
Capybara.use_default_driver # Revert Capybara.current_driver to Capybara.default_driver
|
|
188
|
-
end
|
|
189
173
|
end
|
|
190
174
|
```
|
|
191
175
|
|
|
@@ -401,7 +385,6 @@ certain elements, and working with and manipulating those elements.
|
|
|
401
385
|
```ruby
|
|
402
386
|
page.has_selector?('table tr')
|
|
403
387
|
page.has_selector?(:xpath, '//table/tr')
|
|
404
|
-
page.has_no_selector?(:content)
|
|
405
388
|
|
|
406
389
|
page.has_xpath?('//table/tr')
|
|
407
390
|
page.has_css?('table tr.foo')
|
|
@@ -416,7 +399,6 @@ You can use these with RSpec's magic matchers:
|
|
|
416
399
|
```ruby
|
|
417
400
|
page.should have_selector('table tr')
|
|
418
401
|
page.should have_selector(:xpath, '//table/tr')
|
|
419
|
-
page.should have_no_selector(:content)
|
|
420
402
|
|
|
421
403
|
page.should have_xpath('//table/tr')
|
|
422
404
|
page.should have_css('table tr.foo')
|
|
@@ -524,6 +506,49 @@ Finally, in drivers that support it, you can save a screenshot:
|
|
|
524
506
|
page.save_screenshot('screenshot.png')
|
|
525
507
|
```
|
|
526
508
|
|
|
509
|
+
## Matching
|
|
510
|
+
|
|
511
|
+
It is possible to customize how Capybara finds elements. At your disposal
|
|
512
|
+
are two options, `Capybara.exact` and `Capybara.match`.
|
|
513
|
+
|
|
514
|
+
### Exactness
|
|
515
|
+
|
|
516
|
+
`Capybara.exact` and the `exact` option work together with the `is` expression
|
|
517
|
+
inside the XPath gem. When `exact` is true, all `is` expressions match exactly,
|
|
518
|
+
when it is false, they allow substring matches. Many of the selectors built into
|
|
519
|
+
Capybara use the `is` expression. This way you can specify whether you want to
|
|
520
|
+
allow substring matches or not. `Capybara.exact` is false by default.
|
|
521
|
+
|
|
522
|
+
For example:
|
|
523
|
+
|
|
524
|
+
```ruby
|
|
525
|
+
click_link("Password") # also matches "Password confirmation"
|
|
526
|
+
Capybara.exact = true
|
|
527
|
+
click_link("Password") # does not match "Password confirmation"
|
|
528
|
+
click_link("Password", exact: false) # can be overridden
|
|
529
|
+
```
|
|
530
|
+
|
|
531
|
+
### Strategy
|
|
532
|
+
|
|
533
|
+
Using `Capybara.match` and the equivalent `match` option, you can control how
|
|
534
|
+
Capybara behaves when multiple elements all match a query. There are currently
|
|
535
|
+
four different strategies built into Capybara:
|
|
536
|
+
|
|
537
|
+
1. **first:** Just picks the first element that matches.
|
|
538
|
+
2. **one:** Raises an error if more than one element matches.
|
|
539
|
+
3. **smart:** If `exact` is `true`, raises an error if more than one element
|
|
540
|
+
matches, just like `one`. If `exact` is `false`, it will first try to find
|
|
541
|
+
an exact match. An error is raised if more than one element is found. If no
|
|
542
|
+
element is found, a new search is performed which allows partial matches. If
|
|
543
|
+
that search returns multiple matches, an error is raised.
|
|
544
|
+
4. **prefer_exact:** If multiple matches are found, some of which are exact,
|
|
545
|
+
and some of which are not, then the first exactly matching element is
|
|
546
|
+
returned.
|
|
547
|
+
|
|
548
|
+
The default for `Capybara.match` is `:smart`. To emulate the behaviour in
|
|
549
|
+
Capybara 2.0.x, set `Capybara.match` to `:one`. To emulate the behaviour in
|
|
550
|
+
Capybara 1.x, set `Capybara.match` to `:prefer_exact`.
|
|
551
|
+
|
|
527
552
|
## Transactions and database setup
|
|
528
553
|
|
|
529
554
|
Some Capybara drivers need to run against an actual HTTP server. Capybara takes
|
|
@@ -575,7 +600,7 @@ page.should have_content('baz')
|
|
|
575
600
|
If clicking on the *foo* link triggers an asynchronous process, such as
|
|
576
601
|
an Ajax request, which, when complete will add the *bar* link to the page,
|
|
577
602
|
clicking on the *bar* link would be expected to fail, since that link doesn't
|
|
578
|
-
exist yet. However Capybara is smart
|
|
603
|
+
exist yet. However Capybara is smart enough to retry finding the link for a
|
|
579
604
|
brief period of time before giving up and throwing an error. The same is true of
|
|
580
605
|
the next line, which looks for the content *baz* on the page; it will retry
|
|
581
606
|
looking for that content for a brief time. You can adjust how long this period
|
|
@@ -648,7 +673,7 @@ This enables its use in unsupported testing frameworks, and for general-purpose
|
|
|
648
673
|
## Calling remote servers
|
|
649
674
|
|
|
650
675
|
Normally Capybara expects to be testing an in-process Rack application, but you
|
|
651
|
-
can also use it to talk to a web server running anywhere on the
|
|
676
|
+
can also use it to talk to a web server running anywhere on the internet, by
|
|
652
677
|
setting app_host:
|
|
653
678
|
|
|
654
679
|
```ruby
|
|
@@ -737,25 +762,6 @@ find(:row, 3)
|
|
|
737
762
|
find(:flash_type, :notice)
|
|
738
763
|
```
|
|
739
764
|
|
|
740
|
-
You can specify an optional match option which will automatically use the
|
|
741
|
-
selector if it matches the argument:
|
|
742
|
-
|
|
743
|
-
```ruby
|
|
744
|
-
Capybara.add_selector(:id) do
|
|
745
|
-
xpath { |id| XPath.descendant[XPath.attr(:id) == id.to_s] }
|
|
746
|
-
match { |value| value.is_a?(Symbol) }
|
|
747
|
-
end
|
|
748
|
-
```
|
|
749
|
-
|
|
750
|
-
Now use it like this:
|
|
751
|
-
|
|
752
|
-
```ruby
|
|
753
|
-
find(:post_123)
|
|
754
|
-
```
|
|
755
|
-
|
|
756
|
-
This :id selector is already built into Capybara by default, so you don't
|
|
757
|
-
need to add it yourself.
|
|
758
|
-
|
|
759
765
|
## Beware the XPath // trap
|
|
760
766
|
|
|
761
767
|
In XPath the expression // means something very specific, and it might not be what
|
|
@@ -840,7 +846,6 @@ additional info about how the underlying driver can be configured.
|
|
|
840
846
|
To set up a development environment, simply do:
|
|
841
847
|
|
|
842
848
|
```bash
|
|
843
|
-
git submodule update --init
|
|
844
849
|
bundle install
|
|
845
850
|
bundle exec rake # run the test suite
|
|
846
851
|
```
|
data/lib/capybara/cucumber.rb
CHANGED
data/lib/capybara/driver/base.rb
CHANGED
|
@@ -7,7 +7,11 @@ class Capybara::Driver::Base
|
|
|
7
7
|
raise NotImplementedError
|
|
8
8
|
end
|
|
9
9
|
|
|
10
|
-
def
|
|
10
|
+
def find_xpath(query)
|
|
11
|
+
raise NotImplementedError
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def find_css(query)
|
|
11
15
|
raise NotImplementedError
|
|
12
16
|
end
|
|
13
17
|
|
|
@@ -16,31 +20,31 @@ class Capybara::Driver::Base
|
|
|
16
20
|
end
|
|
17
21
|
|
|
18
22
|
def execute_script(script)
|
|
19
|
-
raise Capybara::NotSupportedByDriverError
|
|
23
|
+
raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#execute_script'
|
|
20
24
|
end
|
|
21
25
|
|
|
22
26
|
def evaluate_script(script)
|
|
23
|
-
raise Capybara::NotSupportedByDriverError
|
|
27
|
+
raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#evaluate_script'
|
|
24
28
|
end
|
|
25
29
|
|
|
26
30
|
def save_screenshot(path, options={})
|
|
27
|
-
raise Capybara::NotSupportedByDriverError
|
|
31
|
+
raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#save_screenshot'
|
|
28
32
|
end
|
|
29
33
|
|
|
30
34
|
def response_headers
|
|
31
|
-
raise Capybara::NotSupportedByDriverError
|
|
35
|
+
raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#response_headers'
|
|
32
36
|
end
|
|
33
37
|
|
|
34
38
|
def status_code
|
|
35
|
-
raise Capybara::NotSupportedByDriverError
|
|
39
|
+
raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#status_code'
|
|
36
40
|
end
|
|
37
41
|
|
|
38
|
-
def within_frame(
|
|
39
|
-
raise Capybara::NotSupportedByDriverError
|
|
42
|
+
def within_frame(frame_handle)
|
|
43
|
+
raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#within_frame'
|
|
40
44
|
end
|
|
41
45
|
|
|
42
46
|
def within_window(handle)
|
|
43
|
-
raise Capybara::NotSupportedByDriverError
|
|
47
|
+
raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#within_window'
|
|
44
48
|
end
|
|
45
49
|
|
|
46
50
|
def invalid_element_errors
|
data/lib/capybara/driver/node.rb
CHANGED
|
@@ -8,7 +8,11 @@ module Capybara
|
|
|
8
8
|
@native = native
|
|
9
9
|
end
|
|
10
10
|
|
|
11
|
-
def
|
|
11
|
+
def all_text
|
|
12
|
+
raise NotImplementedError
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def visible_text
|
|
12
16
|
raise NotImplementedError
|
|
13
17
|
end
|
|
14
18
|
|
|
@@ -37,6 +41,10 @@ module Capybara
|
|
|
37
41
|
raise NotImplementedError
|
|
38
42
|
end
|
|
39
43
|
|
|
44
|
+
def hover
|
|
45
|
+
raise NotImplementedError
|
|
46
|
+
end
|
|
47
|
+
|
|
40
48
|
def drag_to(element)
|
|
41
49
|
raise NotImplementedError
|
|
42
50
|
end
|
|
@@ -57,22 +65,26 @@ module Capybara
|
|
|
57
65
|
raise NotImplementedError
|
|
58
66
|
end
|
|
59
67
|
|
|
68
|
+
def disabled?
|
|
69
|
+
raise NotImplementedError
|
|
70
|
+
end
|
|
71
|
+
|
|
60
72
|
def path
|
|
61
|
-
raise NotSupportedByDriverError
|
|
73
|
+
raise NotSupportedByDriverError, 'Capybara::Driver::Node#path'
|
|
62
74
|
end
|
|
63
|
-
|
|
75
|
+
|
|
64
76
|
def trigger(event)
|
|
65
|
-
raise NotSupportedByDriverError
|
|
77
|
+
raise NotSupportedByDriverError, 'Capybara::Driver::Node#trigger'
|
|
66
78
|
end
|
|
67
79
|
|
|
68
80
|
def inspect
|
|
69
81
|
%(#<#{self.class} tag="#{tag_name}" path="#{path}">)
|
|
70
|
-
rescue NotSupportedByDriverError
|
|
82
|
+
rescue NotSupportedByDriverError, 'Capybara::Driver::Node#inspect'
|
|
71
83
|
%(#<#{self.class} tag="#{tag_name}">)
|
|
72
84
|
end
|
|
73
85
|
|
|
74
86
|
def ==(other)
|
|
75
|
-
raise NotSupportedByDriverError
|
|
87
|
+
raise NotSupportedByDriverError, 'Capybara::Driver::Node#=='
|
|
76
88
|
end
|
|
77
89
|
end
|
|
78
90
|
end
|
data/lib/capybara/helpers.rb
CHANGED
|
@@ -1,31 +1,120 @@
|
|
|
1
1
|
# encoding: UTF-8
|
|
2
2
|
|
|
3
3
|
module Capybara
|
|
4
|
+
|
|
5
|
+
# @api private
|
|
4
6
|
module Helpers
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
7
|
+
extend self
|
|
8
|
+
|
|
9
|
+
##
|
|
10
|
+
#
|
|
11
|
+
# Normalizes whitespace space by stripping leading and trailing
|
|
12
|
+
# whitespace and replacing sequences of whitespace characters
|
|
13
|
+
# with a single space.
|
|
14
|
+
#
|
|
15
|
+
# @param [String] text Text to normalize
|
|
16
|
+
# @return [String] Normalized text
|
|
17
|
+
#
|
|
18
|
+
def normalize_whitespace(text)
|
|
19
|
+
text.to_s.gsub(/[[:space:]]+/, ' ').strip
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
##
|
|
23
|
+
#
|
|
24
|
+
# Escapes any characters that would have special meaning in a regexp
|
|
25
|
+
# if text is not a regexp
|
|
26
|
+
#
|
|
27
|
+
# @param [String] text Text to escape
|
|
28
|
+
# @return [String] Escaped text
|
|
29
|
+
#
|
|
30
|
+
def to_regexp(text)
|
|
31
|
+
text.is_a?(Regexp) ? text : Regexp.new(Regexp.escape(normalize_whitespace(text)))
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
##
|
|
35
|
+
#
|
|
36
|
+
# Injects a `<base>` tag into the given HTML code, pointing to
|
|
37
|
+
# `Capybara.asset_host`.
|
|
38
|
+
#
|
|
39
|
+
# @param [String] html HTML code to inject into
|
|
40
|
+
# @return [String] The modified HTML code
|
|
41
|
+
#
|
|
42
|
+
def inject_asset_host(html)
|
|
43
|
+
if Capybara.asset_host
|
|
44
|
+
if Nokogiri::HTML(html).css("base").empty? and match = html.match(/<head[^<]*?>/)
|
|
45
|
+
html.clone.insert match.end(0), "<base href='#{Capybara.asset_host}' />"
|
|
46
|
+
end
|
|
47
|
+
else
|
|
48
|
+
html
|
|
17
49
|
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
##
|
|
53
|
+
#
|
|
54
|
+
# Checks if the given count matches the given count options. By default,
|
|
55
|
+
# when no options are given, count should be larger than zero.
|
|
56
|
+
#
|
|
57
|
+
# @param [Integer] count The actual number. Should be coercible via Integer()
|
|
58
|
+
# @option [Range] between Count must be within the given range
|
|
59
|
+
# @option [Integer] count Count must be exactly this
|
|
60
|
+
# @option [Integer] maximum Count must be smaller than or equal to this value
|
|
61
|
+
# @option [Integer] minimum Count must be larger than or equal to this value
|
|
62
|
+
#
|
|
63
|
+
def matches_count?(count, options={})
|
|
64
|
+
case
|
|
65
|
+
when options[:between]
|
|
66
|
+
options[:between] === count
|
|
67
|
+
when options[:count]
|
|
68
|
+
Integer(options[:count]) == count
|
|
69
|
+
when options[:maximum]
|
|
70
|
+
Integer(options[:maximum]) >= count
|
|
71
|
+
when options[:minimum]
|
|
72
|
+
Integer(options[:minimum]) <= count
|
|
73
|
+
else
|
|
74
|
+
count > 0
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
##
|
|
79
|
+
#
|
|
80
|
+
# Generates a failure message given a description of the query and count
|
|
81
|
+
# options.
|
|
82
|
+
#
|
|
83
|
+
# @param [String] description Description of a query
|
|
84
|
+
# @option [Range] between Count should have been within the given range
|
|
85
|
+
# @option [Integer] count Count should have been exactly this
|
|
86
|
+
# @option [Integer] maximum Count should have been smaller than or equal to this value
|
|
87
|
+
# @option [Integer] minimum Count should have been larger than or equal to this value
|
|
88
|
+
#
|
|
89
|
+
def failure_message(description, options={})
|
|
90
|
+
message = "expected to find #{description}"
|
|
91
|
+
if options[:count]
|
|
92
|
+
message << " #{options[:count]} #{declension('time', 'times', options[:count])}"
|
|
93
|
+
elsif options[:between]
|
|
94
|
+
message << " between #{options[:between].first} and #{options[:between].last} times"
|
|
95
|
+
elsif options[:maximum]
|
|
96
|
+
message << " at most #{options[:maximum]} #{declension('time', 'times', options[:maximum])}"
|
|
97
|
+
elsif options[:minimum]
|
|
98
|
+
message << " at least #{options[:minimum]} #{declension('time', 'times', options[:minimum])}"
|
|
99
|
+
end
|
|
100
|
+
message
|
|
101
|
+
end
|
|
18
102
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
103
|
+
##
|
|
104
|
+
#
|
|
105
|
+
# A poor man's `pluralize`. Given two declensions, one singular and one
|
|
106
|
+
# plural, as well as a count, this will pick the correct declension. This
|
|
107
|
+
# way we can generate gramatically correct error message.
|
|
108
|
+
#
|
|
109
|
+
# @param [String] singular The singular form of the word
|
|
110
|
+
# @param [String] plural The plural form of the word
|
|
111
|
+
# @param [Integer] count The number of items
|
|
112
|
+
#
|
|
113
|
+
def declension(singular, plural, count)
|
|
114
|
+
if count == 1
|
|
115
|
+
singular
|
|
116
|
+
else
|
|
117
|
+
plural
|
|
29
118
|
end
|
|
30
119
|
end
|
|
31
120
|
end
|