capybara 2.0.0.beta2 → 2.0.0.beta4
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.txt +30 -1
- data/README.md +52 -31
- data/lib/capybara.rb +1 -0
- data/lib/capybara/driver/base.rb +1 -1
- data/lib/capybara/driver/node.rb +1 -0
- data/lib/capybara/dsl.rb +12 -5
- data/lib/capybara/helpers.rb +33 -0
- data/lib/capybara/node/actions.rb +4 -2
- data/lib/capybara/node/base.rb +52 -1
- data/lib/capybara/node/element.rb +0 -12
- data/lib/capybara/node/finders.rb +1 -1
- data/lib/capybara/node/matchers.rb +57 -47
- data/lib/capybara/node/simple.rb +4 -0
- data/lib/capybara/query.rb +11 -11
- data/lib/capybara/rack_test/browser.rb +14 -15
- data/lib/capybara/rack_test/driver.rb +2 -2
- data/lib/capybara/rack_test/node.rb +15 -2
- data/lib/capybara/result.rb +7 -19
- data/lib/capybara/rspec.rb +7 -4
- data/lib/capybara/rspec/features.rb +4 -1
- data/lib/capybara/rspec/matchers.rb +8 -3
- data/lib/capybara/selector.rb +1 -2
- data/lib/capybara/selenium/driver.rb +2 -2
- data/lib/capybara/selenium/node.rb +9 -7
- data/lib/capybara/session.rb +47 -31
- data/lib/capybara/spec/fixtures/another_test_file.txt +1 -0
- data/lib/capybara/spec/public/test.js +1 -1
- data/lib/capybara/spec/session/all_spec.rb +60 -62
- data/lib/capybara/spec/session/assert_selector.rb +123 -0
- data/lib/capybara/spec/session/attach_file_spec.rb +72 -58
- data/lib/capybara/spec/session/body_spec.rb +21 -0
- data/lib/capybara/spec/session/check_spec.rb +67 -50
- data/lib/capybara/spec/session/choose_spec.rb +32 -21
- data/lib/capybara/spec/session/click_button_spec.rb +261 -221
- data/lib/capybara/spec/session/click_link_or_button_spec.rb +40 -30
- data/lib/capybara/spec/session/click_link_spec.rb +95 -81
- data/lib/capybara/spec/session/current_url_spec.rb +70 -60
- data/lib/capybara/spec/session/evaluate_script_spec.rb +6 -0
- data/lib/capybara/spec/session/execute_script_spec.rb +7 -0
- data/lib/capybara/spec/session/fill_in_spec.rb +118 -92
- data/lib/capybara/spec/session/find_button_spec.rb +16 -14
- data/lib/capybara/spec/session/find_by_id_spec.rb +16 -14
- data/lib/capybara/spec/session/find_field_spec.rb +23 -21
- data/lib/capybara/spec/session/find_link_spec.rb +15 -14
- data/lib/capybara/spec/session/find_spec.rb +96 -91
- data/lib/capybara/spec/session/first_spec.rb +53 -55
- data/lib/capybara/spec/session/has_button_spec.rb +22 -24
- data/lib/capybara/spec/session/has_css_spec.rb +190 -205
- data/lib/capybara/spec/session/has_field_spec.rb +167 -169
- data/lib/capybara/spec/session/has_link_spec.rb +26 -29
- data/lib/capybara/spec/session/has_select_spec.rb +175 -176
- data/lib/capybara/spec/session/has_selector_spec.rb +94 -100
- data/lib/capybara/spec/session/has_table_spec.rb +22 -26
- data/lib/capybara/spec/session/has_text_spec.rb +159 -132
- data/lib/capybara/spec/session/has_xpath_spec.rb +100 -96
- data/lib/capybara/spec/session/headers.rb +4 -17
- data/lib/capybara/spec/session/html_spec.rb +15 -0
- data/lib/capybara/spec/session/node_spec.rb +172 -82
- data/lib/capybara/spec/session/reset_session_spec.rb +42 -0
- data/lib/capybara/spec/session/response_code.rb +4 -17
- data/lib/capybara/spec/session/save_page_spec.rb +46 -0
- data/lib/capybara/spec/session/screenshot.rb +8 -24
- data/lib/capybara/spec/session/select_spec.rb +100 -89
- data/lib/capybara/spec/session/source_spec.rb +12 -0
- data/lib/capybara/spec/session/text_spec.rb +15 -17
- data/lib/capybara/spec/session/uncheck_spec.rb +22 -17
- data/lib/capybara/spec/session/unselect_spec.rb +57 -52
- data/lib/capybara/spec/session/visit_spec.rb +58 -60
- data/lib/capybara/spec/session/within_frame_spec.rb +24 -26
- data/lib/capybara/spec/session/within_spec.rb +119 -121
- data/lib/capybara/spec/session/within_window_spec.rb +29 -31
- data/lib/capybara/spec/spec_helper.rb +84 -0
- data/lib/capybara/spec/test_app.rb +5 -3
- data/lib/capybara/spec/views/form.erb +1 -0
- data/lib/capybara/spec/views/with_html.erb +6 -1
- data/lib/capybara/spec/views/with_js.erb +1 -0
- data/lib/capybara/version.rb +1 -1
- data/spec/basic_node_spec.rb +2 -2
- data/spec/capybara_spec.rb +9 -0
- data/spec/dsl_spec.rb +22 -10
- data/spec/rack_test_spec.rb +28 -23
- data/spec/result_spec.rb +51 -0
- data/spec/rspec/features_spec.rb +19 -0
- data/spec/rspec/matchers_spec.rb +6 -0
- data/spec/rspec_spec.rb +1 -1
- data/spec/selenium_spec.rb +11 -25
- data/spec/server_spec.rb +2 -2
- data/spec/spec_helper.rb +1 -46
- metadata +41 -98
- data/lib/capybara/spec/session.rb +0 -183
- data/lib/capybara/spec/session/javascript.rb +0 -290
- data/lib/capybara/util/save_and_open_page.rb +0 -45
- data/spec/save_and_open_page_spec.rb +0 -155
data/History.txt
CHANGED
|
@@ -2,6 +2,35 @@
|
|
|
2
2
|
|
|
3
3
|
### Changed
|
|
4
4
|
|
|
5
|
+
* `require 'capybara/rails'` will automatically enable `:respect_data_method`
|
|
6
|
+
on the RackTest driver, so the behavior matches Capybara 1.1.2 [Jo Liss]
|
|
7
|
+
* Dropped official support for Ruby 1.8.x. [Jonas Nicklas]
|
|
8
|
+
* All methods which find or manipulate fields or buttons now ignore them when
|
|
9
|
+
they are disabled. [Jonas Nicklas]
|
|
10
|
+
* Can no longer find elements by id via `find(:foo)`, use `find("#foo")` or
|
|
11
|
+
`find_by_id("foo")` instead. [Jonas Nicklas]
|
|
12
|
+
* Rename `Driver#body` to `Driver#html` (relevant only for driver authors) [Jo
|
|
13
|
+
Liss]
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
|
|
17
|
+
* Multiple files can be uploaded with `attach_file` [Jarl Friis]
|
|
18
|
+
|
|
19
|
+
### Fixed
|
|
20
|
+
|
|
21
|
+
* `has_text` (`has_content`) now accepts non-string arguments, like numbers.
|
|
22
|
+
[Jo Liss]
|
|
23
|
+
* `has_text` and `text` now correctly normalize Unicode whitespace, such as
|
|
24
|
+
` `. [Jo Liss]
|
|
25
|
+
* RackTest allows protocol relative URLs [Jonas Nicklas]
|
|
26
|
+
* Arguments are cast to string where necessary, so that e.g. `click_link(:foo)` works
|
|
27
|
+
as expected. [Jonas Nicklas]
|
|
28
|
+
* `:count => 0` now works as expected [Jarl Friis]
|
|
29
|
+
|
|
30
|
+
# Version 2.0.0.beta2
|
|
31
|
+
|
|
32
|
+
### Changed
|
|
33
|
+
|
|
5
34
|
* `respect_data_method` default to `false` for the RackTest driver, which means
|
|
6
35
|
that Capybara no longer picks up `:method => :post` et. al. from links in Rails
|
|
7
36
|
by default. [Jonas Nicklas]
|
|
@@ -77,7 +106,7 @@
|
|
|
77
106
|
session is reset [James Tucker, Jonas Nicklas]
|
|
78
107
|
* A ton of new selectors built in out of the box, like `field`, `link`, `button`,
|
|
79
108
|
etc... [Adam McCrea, Jonas Nicklas]
|
|
80
|
-
* `has_text
|
|
109
|
+
* `has_text?` has been added as an alias for `has_content?` [Jonas Nicklas]
|
|
81
110
|
* Add `Capybara.server_host` option (default: 127.0.0.1) [David Balatero]
|
|
82
111
|
* Add `:type` option for `page.has_field?` [Gonzalo Rodríguez]
|
|
83
112
|
* Custom matchers can now be specified in CSS in addition to XPath [Jonas Nicklas]
|
data/README.md
CHANGED
|
@@ -4,14 +4,23 @@
|
|
|
4
4
|
[](https://gemnasium.com/jnicklas/capybara)
|
|
5
5
|
[](https://codeclimate.com/github/jnicklas/capybara)
|
|
6
6
|
|
|
7
|
-
Capybara helps you test
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
Capybara helps you test web applications by simulating how a real user would
|
|
8
|
+
interact with your app. It is agnostic about the driver running your tests and
|
|
9
|
+
comes with Rack::Test and Selenium support built in. WebKit is supported
|
|
10
|
+
through an external gem.
|
|
11
11
|
|
|
12
12
|
**Need help?** Ask on the mailing list (please do not open an issue on
|
|
13
13
|
GitHub): http://groups.google.com/group/ruby-capybara
|
|
14
14
|
|
|
15
|
+
## Key benefits
|
|
16
|
+
|
|
17
|
+
- **No setup** necessary for Rails and Rack application. Works out of the box.
|
|
18
|
+
- **Intuitive API** which mimics the language an actual user would use.
|
|
19
|
+
- **Switch the backend** your tests run against from fast headless mode
|
|
20
|
+
to an actual browser with no changes to your tests.
|
|
21
|
+
- **Powerful synchronization** features mean you never have to manually wait
|
|
22
|
+
for asynchronous processes to complete.
|
|
23
|
+
|
|
15
24
|
## Setup
|
|
16
25
|
|
|
17
26
|
To install, type
|
|
@@ -32,6 +41,9 @@ If you are not using Rails, set Capybara.app to your rack app:
|
|
|
32
41
|
Capybara.app = MyRackApp
|
|
33
42
|
```
|
|
34
43
|
|
|
44
|
+
If you need to test JavaScript, or if your app interacts with (or is located at)
|
|
45
|
+
a remote URL, you'll need to [use a different driver](#drivers).
|
|
46
|
+
|
|
35
47
|
## Using Capybara with Cucumber
|
|
36
48
|
|
|
37
49
|
The `cucumber-rails` gem comes with Capybara support built-in. If you
|
|
@@ -126,11 +138,21 @@ feature "Signing up" do
|
|
|
126
138
|
end
|
|
127
139
|
click_link 'Sign in'
|
|
128
140
|
end
|
|
141
|
+
|
|
142
|
+
given(:other_user) { User.make(:email => 'other@example.com', :password => 'rous') }
|
|
143
|
+
|
|
144
|
+
scenario "Signing in as another user" do
|
|
145
|
+
within("#session") do
|
|
146
|
+
fill_in 'Login', :with => other_user.email
|
|
147
|
+
fill_in 'Password', :with => other_user.password
|
|
148
|
+
end
|
|
149
|
+
click_link 'Sign in'
|
|
150
|
+
end
|
|
129
151
|
end
|
|
130
152
|
```
|
|
131
153
|
|
|
132
154
|
`feature` is in fact just an alias for `describe ..., :type => :request`,
|
|
133
|
-
`background` is an alias for `before`,
|
|
155
|
+
`background` is an alias for `before`, `scenario` for `it`, and `given`/`given!` aliases for `let`/`let!`, respectively.
|
|
134
156
|
|
|
135
157
|
## Using Capybara with Test::Unit
|
|
136
158
|
|
|
@@ -217,10 +239,11 @@ Capybara uses the same DSL to drive a variety of browser and headless drivers.
|
|
|
217
239
|
|
|
218
240
|
### Selecting the Driver
|
|
219
241
|
|
|
220
|
-
By default, Capybara uses the `:rack_test` driver, which is fast but
|
|
221
|
-
support JavaScript
|
|
222
|
-
|
|
223
|
-
|
|
242
|
+
By default, Capybara uses the `:rack_test` driver, which is fast but limited: it
|
|
243
|
+
does not support JavaScript, nor is it able to access HTTP resources outside of
|
|
244
|
+
your Rack application, such as remote APIs and OAuth services. To get around
|
|
245
|
+
these limitations, you can set up a different default driver for your features.
|
|
246
|
+
For example if you'd prefer to run everything in Selenium, you could do:
|
|
224
247
|
|
|
225
248
|
```ruby
|
|
226
249
|
Capybara.default_driver = :selenium
|
|
@@ -248,15 +271,17 @@ switch in the middle of a test.
|
|
|
248
271
|
### RackTest
|
|
249
272
|
|
|
250
273
|
RackTest is Capybara's default driver. It is written in pure Ruby and does not
|
|
251
|
-
have any support for executing JavaScript. Since the RackTest driver
|
|
252
|
-
directly
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
274
|
+
have any support for executing JavaScript. Since the RackTest driver interacts
|
|
275
|
+
directly with Rack interfaces, it does not require a server to be started.
|
|
276
|
+
However, this means that if your application is not a Rack application (Rails,
|
|
277
|
+
Sinatra and most other Ruby frameworks are Rack applications) then you cannot
|
|
278
|
+
use this driver. Furthermore, you cannot use the RackTest driver to test a
|
|
279
|
+
remote application, or to access remote URLs (e.g., redirects to external
|
|
280
|
+
sites, external APIs, or OAuth services) that your application might interact
|
|
281
|
+
with.
|
|
282
|
+
|
|
257
283
|
[capybara-mechanize](https://github.com/jeroenvandijk/capybara-mechanize)
|
|
258
|
-
|
|
259
|
-
separate project.
|
|
284
|
+
provides a similar driver that can access remote servers.
|
|
260
285
|
|
|
261
286
|
RackTest can be configured with a set of headers like this:
|
|
262
287
|
|
|
@@ -474,14 +499,6 @@ that this may break with more complicated expressions:
|
|
|
474
499
|
result = page.evaluate_script('4 + 4');
|
|
475
500
|
```
|
|
476
501
|
|
|
477
|
-
### Saving screenshot
|
|
478
|
-
|
|
479
|
-
In drivers which support it, you can save screenshot:
|
|
480
|
-
|
|
481
|
-
```ruby
|
|
482
|
-
page.save_screenshot('screenshot.png')
|
|
483
|
-
```
|
|
484
|
-
|
|
485
502
|
### Debugging
|
|
486
503
|
|
|
487
504
|
It can be useful to take a snapshot of the page as it currently is and take a
|
|
@@ -501,6 +518,12 @@ print page.html
|
|
|
501
518
|
This is mostly useful for debugging. You should avoid testing against the
|
|
502
519
|
contents of `page.html` and use the more expressive finder methods instead.
|
|
503
520
|
|
|
521
|
+
Finally, in drivers that support it, you can save a screenshot:
|
|
522
|
+
|
|
523
|
+
```ruby
|
|
524
|
+
page.save_screenshot('screenshot.png')
|
|
525
|
+
```
|
|
526
|
+
|
|
504
527
|
## Transactions and database setup
|
|
505
528
|
|
|
506
529
|
Some Capybara drivers need to run against an actual HTTP server. Capybara takes
|
|
@@ -814,12 +837,6 @@ additional info about how the underlying driver can be configured.
|
|
|
814
837
|
|
|
815
838
|
## Development
|
|
816
839
|
|
|
817
|
-
If you found a _reproducible_ bug, open a [GitHub
|
|
818
|
-
Issue](http://github.com/jnicklas/capybara/issues) to submit a bug report.
|
|
819
|
-
|
|
820
|
-
Even better, send a pull request! Make sure all changes are well tested,
|
|
821
|
-
Capybara is a testing tool after all. Topic branches are good.
|
|
822
|
-
|
|
823
840
|
To set up a development environment, simply do:
|
|
824
841
|
|
|
825
842
|
```bash
|
|
@@ -827,3 +844,7 @@ git submodule update --init
|
|
|
827
844
|
bundle install
|
|
828
845
|
bundle exec rake # run the test suite
|
|
829
846
|
```
|
|
847
|
+
|
|
848
|
+
See
|
|
849
|
+
[CONTRIBUTING.md](https://github.com/jnicklas/capybara/blob/master/CONTRIBUTING.md)
|
|
850
|
+
for how to send issues and pull requests.
|
data/lib/capybara.rb
CHANGED
data/lib/capybara/driver/base.rb
CHANGED
data/lib/capybara/driver/node.rb
CHANGED
data/lib/capybara/dsl.rb
CHANGED
|
@@ -2,6 +2,15 @@ require 'capybara'
|
|
|
2
2
|
|
|
3
3
|
module Capybara
|
|
4
4
|
module DSL
|
|
5
|
+
def self.included(base)
|
|
6
|
+
warn "including Capybara::DSL in the global scope is not recommended!" if base == Object
|
|
7
|
+
super
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def self.extended(base)
|
|
11
|
+
warn "extending the main object with Capybara::DSL is not recommended!" if base == TOPLEVEL_BINDING.eval("self")
|
|
12
|
+
super
|
|
13
|
+
end
|
|
5
14
|
|
|
6
15
|
##
|
|
7
16
|
#
|
|
@@ -38,11 +47,9 @@ module Capybara
|
|
|
38
47
|
end
|
|
39
48
|
|
|
40
49
|
Session::DSL_METHODS.each do |method|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
end
|
|
45
|
-
RUBY
|
|
50
|
+
define_method method do |*args, &block|
|
|
51
|
+
page.send method, *args, &block
|
|
52
|
+
end
|
|
46
53
|
end
|
|
47
54
|
end
|
|
48
55
|
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
module Capybara
|
|
2
|
+
module Helpers
|
|
3
|
+
class << self
|
|
4
|
+
##
|
|
5
|
+
#
|
|
6
|
+
# Normalizes whitespace space by stripping leading and trailing
|
|
7
|
+
# whitespace and replacing sequences of whitespace characters
|
|
8
|
+
# with a single space.
|
|
9
|
+
#
|
|
10
|
+
# @param [String] text Text to normalize
|
|
11
|
+
# @return [String] Normalized text
|
|
12
|
+
#
|
|
13
|
+
def normalize_whitespace(text)
|
|
14
|
+
# http://en.wikipedia.org/wiki/Whitespace_character#Unicode
|
|
15
|
+
# We should have a better reference.
|
|
16
|
+
# See also http://stackoverflow.com/a/11758133/525872
|
|
17
|
+
text.to_s.gsub(/[\s\u0085\u00a0\u1680\u180e\u2000-\u200a\u2028\u2029\u202f\u205f\u3000]+/, ' ').strip
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
##
|
|
21
|
+
#
|
|
22
|
+
# Escapes any characters that would have special meaning in a regexp
|
|
23
|
+
# if text is not a regexp
|
|
24
|
+
#
|
|
25
|
+
# @param [String] text Text to escape
|
|
26
|
+
# @return [String] Escaped text
|
|
27
|
+
#
|
|
28
|
+
def to_regexp(text)
|
|
29
|
+
text.is_a?(Regexp) ? text : Regexp.escape(normalize_whitespace(text))
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -135,10 +135,12 @@ module Capybara
|
|
|
135
135
|
# page.attach_file(locator, '/path/to/file.png')
|
|
136
136
|
#
|
|
137
137
|
# @param [String] locator Which field to attach the file to
|
|
138
|
-
# @param [String] path The path of the file that will be attached
|
|
138
|
+
# @param [String] path The path of the file that will be attached, or an array of paths
|
|
139
139
|
#
|
|
140
140
|
def attach_file(locator, path)
|
|
141
|
-
|
|
141
|
+
(String === path ? [path] : path).each do |p|
|
|
142
|
+
raise Capybara::FileNotFound, "cannot attach file, #{p} does not exist" unless File.exist?(p.to_s)
|
|
143
|
+
end
|
|
142
144
|
find(:file_field, locator).set(path)
|
|
143
145
|
end
|
|
144
146
|
end
|
data/lib/capybara/node/base.rb
CHANGED
|
@@ -38,14 +38,47 @@ module Capybara
|
|
|
38
38
|
self
|
|
39
39
|
end
|
|
40
40
|
|
|
41
|
+
##
|
|
42
|
+
#
|
|
43
|
+
# This method is Capybara's primary defence agains asynchronicity
|
|
44
|
+
# problems. It works by attempting to run a given block of code until it
|
|
45
|
+
# succeeds. The exact behaviour of this method depends on a number of
|
|
46
|
+
# factors. Basically there are certain exceptions which, when raised
|
|
47
|
+
# from the block, instead of bubbling up, are caught, and the block is
|
|
48
|
+
# re-run.
|
|
49
|
+
#
|
|
50
|
+
# Certain drivers, such as RackTest, have no support for aynchronous
|
|
51
|
+
# processes, these drivers run the block, and any error raised bubbles up
|
|
52
|
+
# immediately. This allows faster turn around in the case where an
|
|
53
|
+
# expectation fails.
|
|
54
|
+
#
|
|
55
|
+
# Only exceptions that are {Capybara::ElementNotFound} or any subclass
|
|
56
|
+
# thereof cause the block to be rerun. Drivers may specify additional
|
|
57
|
+
# exceptions which also cause reruns. This usually occurs when a node is
|
|
58
|
+
# manipulated which no longer exists on the page. For example, the
|
|
59
|
+
# Selenium driver specifies
|
|
60
|
+
# `Selenium::WebDriver::Error::ObsoleteElementError`.
|
|
61
|
+
#
|
|
62
|
+
# As long as any of these exceptions are thrown, the block is re-run,
|
|
63
|
+
# until a certain amount of time passes. The amount of time defaults to
|
|
64
|
+
# {Capybara.default_wait_time} and can be overriden through the `seconds`
|
|
65
|
+
# argument. This time is compared with the system time to see how much
|
|
66
|
+
# time has passed. If the return value of {Time.now} is stubbed out,
|
|
67
|
+
# Capybara will raise `Capybara::FrozenInTime`.
|
|
68
|
+
#
|
|
69
|
+
# @param [Integer] seconds Number of seconds to retry this block
|
|
70
|
+
# @return [Object] The result of the given block
|
|
71
|
+
# @raise [Capybara::FrozenInTime] If the return value of {Time.now} appears stuck
|
|
72
|
+
#
|
|
41
73
|
def synchronize(seconds=Capybara.default_wait_time)
|
|
42
74
|
start_time = Time.now
|
|
43
75
|
|
|
44
76
|
begin
|
|
45
77
|
yield
|
|
46
78
|
rescue => e
|
|
79
|
+
raise e if @unsynchronized
|
|
47
80
|
raise e unless driver.wait?
|
|
48
|
-
raise e unless driver.invalid_element_errors.include?(e.class)
|
|
81
|
+
raise e unless driver.invalid_element_errors.include?(e.class) || e.is_a?(Capybara::ElementNotFound)
|
|
49
82
|
raise e if (Time.now - start_time) >= seconds
|
|
50
83
|
sleep(0.05)
|
|
51
84
|
raise Capybara::FrozenInTime, "time appears to be frozen, Capybara does not work with libraries which freeze time, consider using time travelling instead" if Time.now == start_time
|
|
@@ -54,6 +87,24 @@ module Capybara
|
|
|
54
87
|
end
|
|
55
88
|
end
|
|
56
89
|
|
|
90
|
+
##
|
|
91
|
+
#
|
|
92
|
+
# Within the given block, prevent synchronize from having any effect.
|
|
93
|
+
#
|
|
94
|
+
# This is an internal method which should not be called unless you are
|
|
95
|
+
# absolutely sure of what you're doing.
|
|
96
|
+
#
|
|
97
|
+
# @api private
|
|
98
|
+
# @return [Object] The result of the given block
|
|
99
|
+
#
|
|
100
|
+
def unsynchronized
|
|
101
|
+
orig = @unsynchronized
|
|
102
|
+
@unsynchronized = true
|
|
103
|
+
yield
|
|
104
|
+
ensure
|
|
105
|
+
@unsynchronized = orig
|
|
106
|
+
end
|
|
107
|
+
|
|
57
108
|
protected
|
|
58
109
|
|
|
59
110
|
def driver
|
|
@@ -177,18 +177,6 @@ module Capybara
|
|
|
177
177
|
synchronize { base.drag_to(node.base) }
|
|
178
178
|
end
|
|
179
179
|
|
|
180
|
-
def find(*args)
|
|
181
|
-
synchronize { super }
|
|
182
|
-
end
|
|
183
|
-
|
|
184
|
-
def first(*args)
|
|
185
|
-
synchronize { super }
|
|
186
|
-
end
|
|
187
|
-
|
|
188
|
-
def all(*args)
|
|
189
|
-
synchronize { super }
|
|
190
|
-
end
|
|
191
|
-
|
|
192
180
|
def reload
|
|
193
181
|
if @allow_reload
|
|
194
182
|
reloaded = parent.reload.first(@query.name, @query.locator, @query.options)
|
|
@@ -52,7 +52,7 @@ module Capybara
|
|
|
52
52
|
|
|
53
53
|
##
|
|
54
54
|
#
|
|
55
|
-
# Find a button on the page. The
|
|
55
|
+
# Find a button on the page. The button can be found by its id, name or value.
|
|
56
56
|
#
|
|
57
57
|
# @param [String] locator Which button to find
|
|
58
58
|
# @return [Capybara::Element] The found element
|
|
@@ -25,8 +25,7 @@ module Capybara
|
|
|
25
25
|
# has_selector? can also accept XPath expressions generated by the
|
|
26
26
|
# XPath gem:
|
|
27
27
|
#
|
|
28
|
-
# xpath
|
|
29
|
-
# page.has_selector?(:xpath, xpath)
|
|
28
|
+
# page.has_selector?(:xpath, XPath.descendant(:p))
|
|
30
29
|
#
|
|
31
30
|
# @param (see Capybara::Node::Finders#all)
|
|
32
31
|
# @option options [Integer] :count (nil) Number of times the expression should occur
|
|
@@ -38,14 +37,6 @@ module Capybara
|
|
|
38
37
|
return false
|
|
39
38
|
end
|
|
40
39
|
|
|
41
|
-
def assert_selector(*args)
|
|
42
|
-
synchronize do
|
|
43
|
-
result = all(*args)
|
|
44
|
-
result.matches_count? or raise Capybara::ExpectationNotMet, result.failure_message
|
|
45
|
-
end
|
|
46
|
-
return true
|
|
47
|
-
end
|
|
48
|
-
|
|
49
40
|
##
|
|
50
41
|
#
|
|
51
42
|
# Checks if a given selector is not on the page or current node.
|
|
@@ -60,6 +51,51 @@ module Capybara
|
|
|
60
51
|
return false
|
|
61
52
|
end
|
|
62
53
|
|
|
54
|
+
##
|
|
55
|
+
#
|
|
56
|
+
# Asserts that a given selector is on the page or current node.
|
|
57
|
+
#
|
|
58
|
+
# page.assert_selector('p#foo')
|
|
59
|
+
# page.assert_selector(:xpath, './/p[@id="foo"]')
|
|
60
|
+
# page.assert_selector(:foo)
|
|
61
|
+
#
|
|
62
|
+
# By default it will check if the expression occurs at least once,
|
|
63
|
+
# but a different number can be specified.
|
|
64
|
+
#
|
|
65
|
+
# page.assert_selector('p#foo', :count => 4)
|
|
66
|
+
#
|
|
67
|
+
# This will check if the expression occurs exactly 4 times.
|
|
68
|
+
#
|
|
69
|
+
# It also accepts all options that {Capybara::Node::Finders#all} accepts,
|
|
70
|
+
# such as :text and :visible.
|
|
71
|
+
#
|
|
72
|
+
# page.assert_selector('li', :text => 'Horse', :visible => true)
|
|
73
|
+
#
|
|
74
|
+
# {assert_selector} can also accept XPath expressions generated by the
|
|
75
|
+
# XPath gem:
|
|
76
|
+
#
|
|
77
|
+
# page.assert_selector(:xpath, XPath.descendant(:p))
|
|
78
|
+
#
|
|
79
|
+
# @param (see Capybara::Node::Finders#all)
|
|
80
|
+
# @option options [Integer] :count (nil) Number of times the expression should occur
|
|
81
|
+
# @raise [Capybara::ExpectationNotMet] If the selector does not exist
|
|
82
|
+
#
|
|
83
|
+
def assert_selector(*args)
|
|
84
|
+
synchronize do
|
|
85
|
+
result = all(*args)
|
|
86
|
+
result.matches_count? or raise Capybara::ExpectationNotMet, result.failure_message
|
|
87
|
+
end
|
|
88
|
+
return true
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
##
|
|
92
|
+
#
|
|
93
|
+
# Asserts that a given selector is not on the page or current node.
|
|
94
|
+
# Usage is identical to Capybara::Node::Matchers#assert_selector
|
|
95
|
+
#
|
|
96
|
+
# @param (see Capybara::Node::Finders#assert_selector)
|
|
97
|
+
# @raise [Capybara::ExpectationNotMet] If the selector exists
|
|
98
|
+
#
|
|
63
99
|
def assert_no_selector(*args)
|
|
64
100
|
synchronize do
|
|
65
101
|
result = all(*args)
|
|
@@ -157,18 +193,17 @@ module Capybara
|
|
|
157
193
|
# Checks if the page or current node has the given text content,
|
|
158
194
|
# ignoring any HTML tags and normalizing whitespace.
|
|
159
195
|
#
|
|
160
|
-
#
|
|
161
|
-
#
|
|
196
|
+
# This only matches displayable text and specifically excludes text
|
|
197
|
+
# contained within non-display nodes such as script or head tags.
|
|
162
198
|
#
|
|
163
199
|
# @param [String] content The text to check for
|
|
164
200
|
# @return [Boolean] Whether it exists
|
|
165
201
|
#
|
|
166
202
|
def has_text?(content)
|
|
167
|
-
normalized_content = normalize_whitespace(content)
|
|
168
|
-
|
|
169
203
|
synchronize do
|
|
170
|
-
normalize_whitespace(text).match(
|
|
171
|
-
|
|
204
|
+
unless Capybara::Helpers.normalize_whitespace(text).match(Capybara::Helpers.to_regexp(content))
|
|
205
|
+
raise ExpectationNotMet
|
|
206
|
+
end
|
|
172
207
|
end
|
|
173
208
|
return true
|
|
174
209
|
rescue Capybara::ExpectationNotMet
|
|
@@ -181,18 +216,17 @@ module Capybara
|
|
|
181
216
|
# Checks if the page or current node does not have the given text
|
|
182
217
|
# content, ignoring any HTML tags and normalizing whitespace.
|
|
183
218
|
#
|
|
184
|
-
#
|
|
185
|
-
#
|
|
219
|
+
# This only matches displayable text and specifically excludes text
|
|
220
|
+
# contained within non-display nodes such as script or head tags.
|
|
186
221
|
#
|
|
187
222
|
# @param [String] content The text to check for
|
|
188
|
-
# @return [Boolean] Whether it
|
|
223
|
+
# @return [Boolean] Whether it doesn't exist
|
|
189
224
|
#
|
|
190
225
|
def has_no_text?(content)
|
|
191
|
-
normalized_content = normalize_whitespace(content)
|
|
192
|
-
|
|
193
226
|
synchronize do
|
|
194
|
-
|
|
195
|
-
|
|
227
|
+
if Capybara::Helpers.normalize_whitespace(text).match(Capybara::Helpers.to_regexp(content))
|
|
228
|
+
raise ExpectationNotMet
|
|
229
|
+
end
|
|
196
230
|
end
|
|
197
231
|
return true
|
|
198
232
|
rescue Capybara::ExpectationNotMet
|
|
@@ -426,30 +460,6 @@ module Capybara
|
|
|
426
460
|
|
|
427
461
|
private
|
|
428
462
|
|
|
429
|
-
##
|
|
430
|
-
#
|
|
431
|
-
# Normalizes whitespace space by stripping leading and trailing
|
|
432
|
-
# whitespace and replacing sequences of whitespace characters
|
|
433
|
-
# with a single space.
|
|
434
|
-
#
|
|
435
|
-
# @param [String] text Text to normalize
|
|
436
|
-
# @return [String] Normalized text
|
|
437
|
-
#
|
|
438
|
-
def normalize_whitespace(text)
|
|
439
|
-
text.is_a?(Regexp) ? text : text.gsub(/\s+/, ' ').strip
|
|
440
|
-
end
|
|
441
|
-
|
|
442
|
-
##
|
|
443
|
-
#
|
|
444
|
-
# Escapes any characters that would have special meaning in a regexp
|
|
445
|
-
# if text is not a regexp
|
|
446
|
-
#
|
|
447
|
-
# @param [String] text Text to escape
|
|
448
|
-
# @return [String] Escaped text
|
|
449
|
-
#
|
|
450
|
-
def escape_regexp(text)
|
|
451
|
-
text.is_a?(Regexp) ? text : Regexp.escape(text)
|
|
452
|
-
end
|
|
453
463
|
end
|
|
454
464
|
end
|
|
455
465
|
end
|