capybara 2.5.0 → 2.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/History.md +22 -1
- data/License.txt +1 -1
- data/README.md +21 -28
- data/lib/capybara.rb +44 -19
- data/lib/capybara/cucumber.rb +1 -1
- data/lib/capybara/node/finders.rb +8 -2
- data/lib/capybara/queries/current_path_query.rb +3 -3
- data/lib/capybara/rack_test/form.rb +28 -9
- data/lib/capybara/rails.rb +0 -1
- data/lib/capybara/rspec.rb +0 -1
- data/lib/capybara/rspec/features.rb +2 -0
- data/lib/capybara/selector.rb +54 -22
- data/lib/capybara/selenium/node.rb +18 -2
- data/lib/capybara/session.rb +35 -47
- data/lib/capybara/spec/public/jquery-ui.js +13 -791
- data/lib/capybara/spec/public/jquery.js +4 -9045
- data/lib/capybara/spec/public/test.js +15 -6
- data/lib/capybara/spec/session/accept_confirm_spec.rb +11 -0
- data/lib/capybara/spec/session/find_button_spec.rb +22 -0
- data/lib/capybara/spec/session/find_field_spec.rb +9 -1
- data/lib/capybara/spec/session/has_button_spec.rb +8 -0
- data/lib/capybara/spec/session/has_current_path_spec.rb +10 -0
- data/lib/capybara/spec/session/has_field_spec.rb +8 -0
- data/lib/capybara/spec/session/has_select_spec.rb +14 -0
- data/lib/capybara/spec/session/node_spec.rb +22 -4
- data/lib/capybara/spec/session/visit_spec.rb +19 -0
- data/lib/capybara/spec/session/window/window_opened_by_spec.rb +1 -0
- data/lib/capybara/spec/views/form.erb +20 -0
- data/lib/capybara/spec/views/with_js.erb +6 -0
- data/lib/capybara/version.rb +1 -1
- data/spec/rspec/features_spec.rb +17 -5
- data/spec/rspec/scenarios_spec.rb +20 -0
- data/spec/selector_spec.rb +53 -0
- data/spec/selenium_spec.rb +19 -0
- data/spec/selenium_spec_chrome.rb +2 -0
- data/spec/server_spec.rb +1 -1
- metadata +22 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b7503b0ca48f7ee15c40c1baacb2e4147aeda674
|
4
|
+
data.tar.gz: 0da9283932e38baf19334f06cb94cd3eeaf5acdf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 388e135a8d62498ae35e0f0ae289a0f78cef7ebd2f522197926a3c0a4fa68e67f548aba020ff513dde67dba3ef899685ce7cac49246a647be432f43cdd6bf697
|
7
|
+
data.tar.gz: b31b4c8ee11655e952d746ccd44ac228b8d0f739bb684c2e5bbbc80c961219bbbb380570e1adc0e4dc272d7c6081df5f74ab03f5bdf5ca7df8b3b14df7f63d60
|
data/History.md
CHANGED
@@ -1,3 +1,22 @@
|
|
1
|
+
# Version 2.6.0
|
2
|
+
Relase date: 2016-01-17
|
3
|
+
|
4
|
+
### Fixed
|
5
|
+
* Fixed path escaping issue with current_path matchers [Tom Walpole, Luke Rollans] (Issue #1611)
|
6
|
+
* Fixed circular require [David Rodríguez]
|
7
|
+
* Capybara::RackTest::Form no longer overrides Object#method [David Rodriguez]
|
8
|
+
* options and with_options filter for :select selector have more intuitive visibility behavior [Nathan]
|
9
|
+
* Test for nested modal API method support [Tom Walpole]
|
10
|
+
|
11
|
+
|
12
|
+
### Added
|
13
|
+
* Capybara.modify_selector [Tom Walpole]
|
14
|
+
* xfeature and ffeature aliases added when using RSpec [Filip Bartuzi]
|
15
|
+
* Selenium driver supports a :clear option to #set to handle different strategies for clearing a field [Tom Walpole]
|
16
|
+
* Support the use of rack 2.0 with the rack_test driver [Travis Grathwell, Tom Walpole]
|
17
|
+
* Disabled option for default selectors now supports true, false, or :all [Jillian Rosile, Tom Walpole]
|
18
|
+
* Modal API methods now default wait time to Capybara.max_default_wait_time [Tom Walpole]
|
19
|
+
|
1
20
|
# Version 2.5.0
|
2
21
|
Release date: 2015-08-25
|
3
22
|
|
@@ -12,7 +31,6 @@ Release date: 2015-08-25
|
|
12
31
|
* Implement Node#path in selenium driver [Soutaro Matsumoto]
|
13
32
|
* 'using_session' is now nestable [Tom Walpole]
|
14
33
|
* 'switch_to_window' will now use waiting behavior for a matching window to appear [Tom Walpole]
|
15
|
-
* Capybara.default_wait_time deprecated in favor of Capybara.default_max_wait_time to more clearly explain its purpose [Paul Pettengill]
|
16
34
|
* Warning when attempting to select a disabled option
|
17
35
|
* Capybara matchers are now available in RSpec view specs by default [Joshua Clayton]
|
18
36
|
* 'have_link' and 'click_link' now accept Regexp for href matching [Yaniv Savir]
|
@@ -25,6 +43,9 @@ Release date: 2015-08-25
|
|
25
43
|
* 'formmethod' attribute support in RackTest driver [Emilia Andrzejewska]
|
26
44
|
* Clear field using backspaces in Selenium driver by using `:fill_options => { :clear => :backspace }` [Joe Lencioni]
|
27
45
|
|
46
|
+
### Deprecated
|
47
|
+
* Capybara.default_wait_time deprecated in favor of Capybara.default_max_wait_time to more clearly explain its purpose [Paul Pettengill]
|
48
|
+
|
28
49
|
#Version 2.4.4
|
29
50
|
Release date: 2014-10-13
|
30
51
|
|
data/License.txt
CHANGED
data/README.md
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
# Capybara
|
2
2
|
|
3
|
-
[![Build Status](https://secure.travis-ci.org/jnicklas/capybara.
|
4
|
-
[![Dependency Status](https://gemnasium.com/jnicklas/capybara.
|
5
|
-
[![Code Climate](https://codeclimate.com/github/jnicklas/capybara.
|
3
|
+
[![Build Status](https://secure.travis-ci.org/jnicklas/capybara.svg)](https://travis-ci.org/jnicklas/capybara)
|
4
|
+
[![Dependency Status](https://gemnasium.com/jnicklas/capybara.svg)](https://gemnasium.com/jnicklas/capybara)
|
5
|
+
[![Code Climate](https://codeclimate.com/github/jnicklas/capybara.svg)](https://codeclimate.com/github/jnicklas/capybara)
|
6
6
|
|
7
7
|
Capybara helps you test web applications by simulating how a real user would
|
8
8
|
interact with your app. It is agnostic about the driver running your tests and
|
@@ -69,6 +69,8 @@ Capybara requires Ruby 1.9.3 or later. To install, add this line to your
|
|
69
69
|
gem 'capybara'
|
70
70
|
```
|
71
71
|
|
72
|
+
**Note:** If using Ruby < 2.0 you will also need to limit the version of mime-types to < 3.0
|
73
|
+
|
72
74
|
If the application that you are testing is a Rails app, add this line to your test helper file:
|
73
75
|
|
74
76
|
```ruby
|
@@ -131,7 +133,11 @@ Load RSpec 2.x support by adding the following line (typically to your
|
|
131
133
|
require 'capybara/rspec'
|
132
134
|
```
|
133
135
|
|
134
|
-
If you are using Rails, put your Capybara specs in `spec/features
|
136
|
+
If you are using Rails, put your Capybara specs in `spec/features` (only works
|
137
|
+
if [you have it configured in
|
138
|
+
rpsec](https://www.relishapp.com/rspec/rspec-rails/docs/upgrade#file-type-inference-disabled))
|
139
|
+
and if you have your Capybara specs in a different directory, then tag the
|
140
|
+
example groups with `:type => :feature`.
|
135
141
|
|
136
142
|
If you are not using Rails, tag all the example groups in which you want to use
|
137
143
|
Capybara with `:type => :feature`.
|
@@ -367,7 +373,7 @@ Capybara.javascript_driver = :webkit
|
|
367
373
|
|
368
374
|
### Poltergeist
|
369
375
|
|
370
|
-
[Poltergeist](https://github.com/
|
376
|
+
[Poltergeist](https://github.com/teampoltergeist/poltergeist) is another
|
371
377
|
headless driver which integrates Capybara with
|
372
378
|
[PhantomJS](http://phantomjs.org/). It is truly headless, so doesn't
|
373
379
|
require Xvfb to run on your CI server. It will also detect and report
|
@@ -399,12 +405,17 @@ The visit method only takes a single parameter, the request method is **always**
|
|
399
405
|
GET.
|
400
406
|
|
401
407
|
You can get the [current path](http://rubydoc.info/github/jnicklas/capybara/master/Capybara/Session#current_path-instance_method)
|
402
|
-
of the browsing session
|
408
|
+
of the browsing session, and test it using the [`have_current_path`](http://www.rubydoc.info/github/jnicklas/capybara/master/Capybara/RSpecMatchers#have_current_path-instance_method) matcher:
|
403
409
|
|
404
410
|
```ruby
|
405
|
-
expect(
|
411
|
+
expect(page).to have_current_path(post_comments_path(post))
|
406
412
|
```
|
407
413
|
|
414
|
+
**Note**: You can also assert the current path by testing the value of
|
415
|
+
`current_path` directly. However, using the `have_current_path` matcher is
|
416
|
+
safer since it uses Capybara's [waiting behaviour](#asynchronous-javascript-ajax-and-friends)
|
417
|
+
to ensure that preceding actions (such as a `click_link`) have completed.
|
418
|
+
|
408
419
|
### Clicking links and buttons
|
409
420
|
|
410
421
|
*Full reference: [Capybara::Node::Actions](http://rubydoc.info/github/jnicklas/capybara/master/Capybara/Node/Actions)*
|
@@ -682,24 +693,7 @@ your test code to be invisible to Capybara.
|
|
682
693
|
|
683
694
|
Cucumber handles this by using truncation instead of transactions, i.e. they
|
684
695
|
empty out the entire database after each test. You can get the same behaviour
|
685
|
-
by using a gem such as [database_cleaner](https://github.com/
|
686
|
-
|
687
|
-
It is also possible to force your ORM to use the same transaction for all
|
688
|
-
threads. This may have thread safety implications and could cause strange
|
689
|
-
failures, so use caution with this approach. It can be implemented in
|
690
|
-
ActiveRecord through the following monkey patch:
|
691
|
-
|
692
|
-
```ruby
|
693
|
-
class ActiveRecord::Base
|
694
|
-
mattr_accessor :shared_connection
|
695
|
-
@@shared_connection = nil
|
696
|
-
|
697
|
-
def self.connection
|
698
|
-
@@shared_connection || retrieve_connection
|
699
|
-
end
|
700
|
-
end
|
701
|
-
ActiveRecord::Base.shared_connection = ActiveRecord::Base.connection
|
702
|
-
```
|
696
|
+
by using a gem such as [database_cleaner](https://github.com/DatabaseCleaner/database_cleaner).
|
703
697
|
|
704
698
|
## Asynchronous JavaScript (Ajax and friends)
|
705
699
|
|
@@ -769,7 +763,6 @@ You can mix the DSL into any context by including <tt>Capybara::DSL</tt>:
|
|
769
763
|
|
770
764
|
|
771
765
|
```ruby
|
772
|
-
require 'capybara'
|
773
766
|
require 'capybara/dsl'
|
774
767
|
|
775
768
|
Capybara.default_driver = :webkit
|
@@ -938,7 +931,7 @@ Whatever is returned from the block should conform to the API described by
|
|
938
931
|
Capybara::Driver::Base, it does not however have to inherit from this class.
|
939
932
|
Gems can use this API to add their own drivers to Capybara.
|
940
933
|
|
941
|
-
The [Selenium wiki](
|
934
|
+
The [Selenium wiki](https://github.com/SeleniumHQ/selenium/wiki/Ruby-Bindings) has
|
942
935
|
additional info about how the underlying driver can be configured.
|
943
936
|
|
944
937
|
## Gotchas:
|
@@ -957,7 +950,7 @@ additional info about how the underlying driver can be configured.
|
|
957
950
|
since Capybara's Ajax timing uses the system time, resulting in Capybara
|
958
951
|
never timing out and just hanging when a failure occurs. It's still possible to
|
959
952
|
use gems which allow you to travel in time, rather than freeze time.
|
960
|
-
One such gem is [Timecop](
|
953
|
+
One such gem is [Timecop](https://github.com/travisjeffery/timecop).
|
961
954
|
|
962
955
|
* When using Rack::Test, beware if attempting to visit absolute URLs. For
|
963
956
|
example, a session might not be shared between visits to `posts_path`
|
data/lib/capybara.rb
CHANGED
@@ -37,24 +37,24 @@ module Capybara
|
|
37
37
|
#
|
38
38
|
# === Configurable options
|
39
39
|
#
|
40
|
-
# [app_host = String] The default host to use when giving a relative URL to visit
|
41
|
-
# [always_include_port = Boolean] Whether the Rack server's port should automatically be inserted into every visited URL (Default: false)
|
42
|
-
# [asset_host = String] Where dynamic assets are hosted - will be prepended to relative asset locations if present (Default: nil)
|
43
|
-
# [run_server = Boolean] Whether to start a Rack server for the given Rack app (Default: true)
|
44
|
-
# [raise_server_errors = Boolean] Should errors raised in the server be raised in the tests? (Default: true)
|
45
|
-
# [server_errors = Array\<Class\>] Error classes that should be raised in the tests if they are raised in the server and Capybara.raise_server_errors is true (Default: [StandardError])
|
46
|
-
# [default_selector = :css/:xpath] Methods which take a selector use the given type by default (Default: :css)
|
47
|
-
# [default_max_wait_time = Numeric] The maximum number of seconds to wait for asynchronous processes to finish (Default: 2)
|
48
|
-
# [ignore_hidden_elements = Boolean] Whether to ignore hidden elements on the page (Default: true)
|
49
|
-
# [automatic_reload = Boolean] Whether to automatically reload elements as Capybara is waiting (Default: true)
|
50
|
-
# [save_and_open_page_path = String] Where to put pages saved through save_and_open_page (Default: Dir.pwd)
|
51
|
-
# [wait_on_first_by_default = Boolean] Whether Node#first defaults to Capybara waiting behavior for at least 1 element to match (Default: false)
|
40
|
+
# [app_host = String] The default host to use when giving a relative URL to visit
|
41
|
+
# [always_include_port = Boolean] Whether the Rack server's port should automatically be inserted into every visited URL (Default: false)
|
42
|
+
# [asset_host = String] Where dynamic assets are hosted - will be prepended to relative asset locations if present (Default: nil)
|
43
|
+
# [run_server = Boolean] Whether to start a Rack server for the given Rack app (Default: true)
|
44
|
+
# [raise_server_errors = Boolean] Should errors raised in the server be raised in the tests? (Default: true)
|
45
|
+
# [server_errors = Array\<Class\>] Error classes that should be raised in the tests if they are raised in the server and Capybara.raise_server_errors is true (Default: [StandardError])
|
46
|
+
# [default_selector = :css/:xpath] Methods which take a selector use the given type by default (Default: :css)
|
47
|
+
# [default_max_wait_time = Numeric] The maximum number of seconds to wait for asynchronous processes to finish (Default: 2)
|
48
|
+
# [ignore_hidden_elements = Boolean] Whether to ignore hidden elements on the page (Default: true)
|
49
|
+
# [automatic_reload = Boolean] Whether to automatically reload elements as Capybara is waiting (Default: true)
|
50
|
+
# [save_and_open_page_path = String] Where to put pages saved through save_and_open_page (Default: Dir.pwd)
|
51
|
+
# [wait_on_first_by_default = Boolean] Whether Node#first defaults to Capybara waiting behavior for at least 1 element to match (Default: false)
|
52
52
|
# === DSL Options
|
53
53
|
#
|
54
54
|
# when using capybara/dsl, the following options are also available:
|
55
55
|
#
|
56
|
-
# [default_driver = Symbol] The name of the driver to use by default. (Default: :rack_test)
|
57
|
-
# [javascript_driver = Symbol] The name of a driver to use for JavaScript enabled tests. (Default: :selenium)
|
56
|
+
# [default_driver = Symbol] The name of the driver to use by default. (Default: :rack_test)
|
57
|
+
# [javascript_driver = Symbol] The name of a driver to use for JavaScript enabled tests. (Default: :selenium)
|
58
58
|
#
|
59
59
|
def configure
|
60
60
|
yield self
|
@@ -109,6 +109,23 @@ module Capybara
|
|
109
109
|
Capybara::Selector.add(name, &block)
|
110
110
|
end
|
111
111
|
|
112
|
+
##
|
113
|
+
#
|
114
|
+
# Modify a selector previously craeated by {Capybara.add_selector}.
|
115
|
+
# For example modifying the :button selector to also find divs styled
|
116
|
+
# to look like buttons might look like this
|
117
|
+
#
|
118
|
+
# Capybara.modfiy_selector(:button) do
|
119
|
+
# xpath { |locator| XPath::HTML.button(locator).or(XPath::css('div.btn')[XPath::string.n.is(locator)]) }
|
120
|
+
# end
|
121
|
+
#
|
122
|
+
# @param [Symbol] name The name of the selector to modify
|
123
|
+
# @yield A block executed in the context of the existing {Capybara::Selector}
|
124
|
+
#
|
125
|
+
def modify_selector(name, &block)
|
126
|
+
Capybara::Selector.update(name, &block)
|
127
|
+
end
|
128
|
+
|
112
129
|
def drivers
|
113
130
|
@drivers ||= {}
|
114
131
|
end
|
@@ -140,7 +157,16 @@ module Capybara
|
|
140
157
|
# in a {Capybara::Node::Simple} which exposes all {Capybara::Node::Matchers},
|
141
158
|
# {Capybara::Node::Finders} and {Capybara::Node::DocumentMatchers}. This allows you to query
|
142
159
|
# any string containing HTML in the exact same way you would query the current document in a Capybara
|
143
|
-
# session.
|
160
|
+
# session.
|
161
|
+
#
|
162
|
+
# Example: A single element
|
163
|
+
#
|
164
|
+
# node = Capybara.string('<a href="foo">bar</a>')
|
165
|
+
# anchor = node.first('a')
|
166
|
+
# anchor[:href] #=> 'foo'
|
167
|
+
# anchor.text #=> 'bar'
|
168
|
+
#
|
169
|
+
# Example: Multiple elements
|
144
170
|
#
|
145
171
|
# node = Capybara.string <<-HTML
|
146
172
|
# <ul>
|
@@ -296,13 +322,13 @@ module Capybara
|
|
296
322
|
end
|
297
323
|
end
|
298
324
|
end
|
299
|
-
|
325
|
+
|
300
326
|
# @deprecated Use default_max_wait_time instead
|
301
327
|
def default_wait_time
|
302
328
|
deprecate('default_wait_time', 'default_max_wait_time', true)
|
303
329
|
default_max_wait_time
|
304
330
|
end
|
305
|
-
|
331
|
+
|
306
332
|
# @deprecated Use default_max_wait_time= instead
|
307
333
|
def default_wait_time=(t)
|
308
334
|
deprecate('default_wait_time=', 'default_max_wait_time=')
|
@@ -337,7 +363,6 @@ module Capybara
|
|
337
363
|
|
338
364
|
require 'capybara/helpers'
|
339
365
|
require 'capybara/session'
|
340
|
-
require 'capybara/dsl'
|
341
366
|
require 'capybara/window'
|
342
367
|
require 'capybara/server'
|
343
368
|
require 'capybara/selector'
|
@@ -349,7 +374,7 @@ module Capybara
|
|
349
374
|
require 'capybara/queries/text_query'
|
350
375
|
require 'capybara/queries/title_query'
|
351
376
|
require 'capybara/queries/current_path_query'
|
352
|
-
|
377
|
+
|
353
378
|
require 'capybara/node/finders'
|
354
379
|
require 'capybara/node/matchers'
|
355
380
|
require 'capybara/node/actions'
|
data/lib/capybara/cucumber.rb
CHANGED
@@ -56,7 +56,10 @@ module Capybara
|
|
56
56
|
#
|
57
57
|
# @option options [Boolean] checked Match checked field?
|
58
58
|
# @option options [Boolean] unchecked Match unchecked field?
|
59
|
-
# @option options [Boolean] disabled (false) Match disabled field?
|
59
|
+
# @option options [Boolean, Symbol] disabled (false) Match disabled field?
|
60
|
+
# * true - only finds a disabled field
|
61
|
+
# * false - only finds an enabled field
|
62
|
+
# * :all - finds either an enabled or disabled field
|
60
63
|
# @option options [Boolean] readonly Match readonly field?
|
61
64
|
# @option options [String] with Value of field to match on
|
62
65
|
# @option options [String] type Type of field to match on
|
@@ -91,7 +94,10 @@ module Capybara
|
|
91
94
|
# @macro waiting_behavior
|
92
95
|
#
|
93
96
|
# @param [String] locator Which button to find
|
94
|
-
# @option options [Boolean] disabled (false) Match disabled button?
|
97
|
+
# @option options [Boolean, Symbol] disabled (false) Match disabled button?
|
98
|
+
# * true - only finds a disabled button
|
99
|
+
# * false - only finds an enabled button
|
100
|
+
# * :all - finds either an enabled or disabled button
|
95
101
|
# @return [Capybara::Node::Element] The found element
|
96
102
|
#
|
97
103
|
def find_button(locator, options={})
|
@@ -15,16 +15,16 @@ module Capybara
|
|
15
15
|
session.current_url
|
16
16
|
else
|
17
17
|
if options[:only_path]
|
18
|
-
URI.parse(session.current_url).path
|
18
|
+
Addressable::URI.parse(session.current_url).path
|
19
19
|
else
|
20
|
-
URI.parse(session.current_url).request_uri
|
20
|
+
Addressable::URI.parse(session.current_url).request_uri
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
24
24
|
if @expected_path.is_a? Regexp
|
25
25
|
@actual_path.match(@expected_path)
|
26
26
|
else
|
27
|
-
@expected_path == @actual_path
|
27
|
+
Addressable::URI.parse(@expected_path) == Addressable::URI.parse(@actual_path)
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
@@ -15,15 +15,15 @@ class Capybara::RackTest::Form < Capybara::RackTest::Node
|
|
15
15
|
end
|
16
16
|
|
17
17
|
def params(button)
|
18
|
-
params =
|
18
|
+
params = make_params
|
19
19
|
|
20
20
|
form_element_types=[:input, :select, :textarea]
|
21
|
-
form_elements_xpath=XPath.generate do |x|
|
21
|
+
form_elements_xpath=XPath.generate do |x|
|
22
22
|
xpath=x.descendant(*form_element_types).where(~x.attr(:form))
|
23
23
|
xpath=xpath.union(x.anywhere(*form_element_types).where(x.attr(:form) == native[:id])) if native[:id]
|
24
24
|
xpath.where(~x.attr(:disabled))
|
25
25
|
end.to_s
|
26
|
-
|
26
|
+
|
27
27
|
native.xpath(form_elements_xpath).map do |field|
|
28
28
|
case field.name
|
29
29
|
when 'input'
|
@@ -31,7 +31,7 @@ class Capybara::RackTest::Form < Capybara::RackTest::Node
|
|
31
31
|
if field['checked']
|
32
32
|
node=Capybara::RackTest::Node.new(self.driver, field)
|
33
33
|
merge_param!(params, field['name'].to_s, node.value.to_s)
|
34
|
-
end
|
34
|
+
end
|
35
35
|
elsif %w(submit image).include? field['type']
|
36
36
|
# TO DO identify the click button here (in document order, rather
|
37
37
|
# than leaving until the end of the params)
|
@@ -67,13 +67,14 @@ class Capybara::RackTest::Form < Capybara::RackTest::Node
|
|
67
67
|
end
|
68
68
|
end
|
69
69
|
merge_param!(params, button[:name], button[:value] || "") if button[:name]
|
70
|
-
|
70
|
+
|
71
|
+
params.to_params_hash
|
71
72
|
end
|
72
73
|
|
73
74
|
def submit(button)
|
74
75
|
action = (button && button['formaction']) || native['action']
|
75
|
-
|
76
|
-
driver.submit(
|
76
|
+
method = (button && button['formmethod']) || request_method
|
77
|
+
driver.submit(method, action.to_s, params(button))
|
77
78
|
end
|
78
79
|
|
79
80
|
def multipart?
|
@@ -82,11 +83,29 @@ class Capybara::RackTest::Form < Capybara::RackTest::Node
|
|
82
83
|
|
83
84
|
private
|
84
85
|
|
85
|
-
|
86
|
+
class ParamsHash < Hash
|
87
|
+
def to_params_hash
|
88
|
+
self
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def request_method
|
86
93
|
self[:method] =~ /post/i ? :post : :get
|
87
94
|
end
|
88
95
|
|
89
96
|
def merge_param!(params, key, value)
|
90
|
-
Rack::Utils.
|
97
|
+
if Rack::Utils.respond_to?(:default_query_parser)
|
98
|
+
Rack::Utils.default_query_parser.normalize_params(params, key, value, Rack::Utils.param_depth_limit)
|
99
|
+
else
|
100
|
+
Rack::Utils.normalize_params(params, key, value)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def make_params
|
105
|
+
if Rack::Utils.respond_to?(:default_query_parser)
|
106
|
+
Rack::Utils.default_query_parser.make_params
|
107
|
+
else
|
108
|
+
ParamsHash.new
|
109
|
+
end
|
91
110
|
end
|
92
111
|
end
|
data/lib/capybara/rails.rb
CHANGED
data/lib/capybara/rspec.rb
CHANGED
@@ -9,6 +9,8 @@ if RSpec::Core::Version::STRING.to_f >= 3.0
|
|
9
9
|
|
10
10
|
RSpec.configure do |config|
|
11
11
|
config.alias_example_group_to :feature, :capybara_feature => true, :type => :feature
|
12
|
+
config.alias_example_group_to :xfeature, :capybara_feature => true, :type => :feature, :skip => "Temporarily disabled with xfeature"
|
13
|
+
config.alias_example_group_to :ffeature, :capybara_feature => true, :type => :feature, :focus => true
|
12
14
|
config.alias_example_to :scenario
|
13
15
|
config.alias_example_to :xscenario, :skip => "Temporarily disabled with xscenario"
|
14
16
|
config.alias_example_to :fscenario, :focus => true
|
data/lib/capybara/selector.rb
CHANGED
@@ -17,11 +17,25 @@ module Capybara
|
|
17
17
|
end
|
18
18
|
|
19
19
|
def matches?(node, value)
|
20
|
+
return true if skip?(value)
|
21
|
+
|
20
22
|
if @options.has_key?(:valid_values) && !Array(@options[:valid_values]).include?(value)
|
21
|
-
|
23
|
+
msg = "Invalid value #{value.inspect} passed to filter #{@name} - "
|
24
|
+
if default?
|
25
|
+
warn msg + "defaulting to #{default}"
|
26
|
+
value = default
|
27
|
+
else
|
28
|
+
warn msg + "skipping"
|
29
|
+
return true
|
30
|
+
end
|
22
31
|
end
|
32
|
+
|
23
33
|
@block.call(node, value)
|
24
34
|
end
|
35
|
+
|
36
|
+
def skip?(value)
|
37
|
+
@options.has_key?(:skip_if) && value == @options[:skip_if]
|
38
|
+
end
|
25
39
|
end
|
26
40
|
|
27
41
|
attr_reader :name, :custom_filters, :format
|
@@ -35,6 +49,10 @@ module Capybara
|
|
35
49
|
all[name.to_sym] = Capybara::Selector.new(name.to_sym, &block)
|
36
50
|
end
|
37
51
|
|
52
|
+
def update(name, &block)
|
53
|
+
all[name.to_sym].instance_eval(&block)
|
54
|
+
end
|
55
|
+
|
38
56
|
def remove(name)
|
39
57
|
all.delete(name.to_sym)
|
40
58
|
end
|
@@ -51,15 +69,19 @@ module Capybara
|
|
51
69
|
end
|
52
70
|
|
53
71
|
def xpath(&block)
|
54
|
-
|
55
|
-
|
72
|
+
if block
|
73
|
+
@format = :xpath
|
74
|
+
@xpath, @css = block, nil
|
75
|
+
end
|
56
76
|
@xpath
|
57
77
|
end
|
58
78
|
|
59
79
|
# Same as xpath, but wrap in XPath.css().
|
60
80
|
def css(&block)
|
61
|
-
|
62
|
-
|
81
|
+
if block
|
82
|
+
@format = :css
|
83
|
+
@css, @xpath = block, nil
|
84
|
+
end
|
63
85
|
@css
|
64
86
|
end
|
65
87
|
|
@@ -115,7 +137,7 @@ Capybara.add_selector(:field) do
|
|
115
137
|
xpath { |locator| XPath::HTML.field(locator) }
|
116
138
|
filter(:checked, boolean: true) { |node, value| not(value ^ node.checked?) }
|
117
139
|
filter(:unchecked, boolean: true) { |node, value| (value ^ node.checked?) }
|
118
|
-
filter(:disabled, default: false, boolean: true) { |node, value| not(value ^ node.disabled?) }
|
140
|
+
filter(:disabled, default: false, boolean: true, skip_if: :all) { |node, value| not(value ^ node.disabled?) }
|
119
141
|
filter(:readonly, boolean: true) { |node, value| not(value ^ node[:readonly]) }
|
120
142
|
filter(:with) { |node, with| node.value == with.to_s }
|
121
143
|
filter(:type) do |node, type|
|
@@ -131,7 +153,7 @@ Capybara.add_selector(:field) do
|
|
131
153
|
desc << " with value #{options[:with].to_s.inspect}" if options.has_key?(:with)
|
132
154
|
states << 'checked' if options[:checked] || (options.has_key?(:unchecked) && !options[:unchecked])
|
133
155
|
states << 'not checked' if options[:unchecked] || (options.has_key?(:checked) && !options[:checked])
|
134
|
-
states << 'disabled' if options[:disabled]
|
156
|
+
states << 'disabled' if options[:disabled] == true
|
135
157
|
desc << " that is #{states.join(' and ')}" unless states.empty?
|
136
158
|
desc
|
137
159
|
end
|
@@ -162,15 +184,15 @@ end
|
|
162
184
|
|
163
185
|
Capybara.add_selector(:button) do
|
164
186
|
xpath { |locator| XPath::HTML.button(locator) }
|
165
|
-
filter(:disabled, default: false, boolean: true) { |node, value| not(value ^ node.disabled?) }
|
166
|
-
describe { |options| " that is disabled" if options[:disabled] }
|
187
|
+
filter(:disabled, default: false, boolean: true, skip_if: :all) { |node, value| not(value ^ node.disabled?) }
|
188
|
+
describe { |options| " that is disabled" if options[:disabled] == true }
|
167
189
|
end
|
168
190
|
|
169
191
|
Capybara.add_selector(:fillable_field) do
|
170
192
|
label "field"
|
171
193
|
xpath { |locator| XPath::HTML.fillable_field(locator) }
|
172
|
-
filter(:disabled, default: false, boolean: true) { |node, value| not(value ^ node.disabled?) }
|
173
|
-
describe { |options| " that is disabled" if options[:disabled] }
|
194
|
+
filter(:disabled, default: false, boolean: true, skip_if: :all) { |node, value| not(value ^ node.disabled?) }
|
195
|
+
describe { |options| " that is disabled" if options[:disabled] == true }
|
174
196
|
end
|
175
197
|
|
176
198
|
Capybara.add_selector(:radio_button) do
|
@@ -179,13 +201,13 @@ Capybara.add_selector(:radio_button) do
|
|
179
201
|
filter(:checked, boolean: true) { |node, value| not(value ^ node.checked?) }
|
180
202
|
filter(:unchecked, boolean: true) { |node, value| (value ^ node.checked?) }
|
181
203
|
filter(:option) { |node, value| node.value == value.to_s }
|
182
|
-
filter(:disabled, default: false, boolean: true) { |node, value| not(value ^ node.disabled?) }
|
204
|
+
filter(:disabled, default: false, boolean: true, skip_if: :all) { |node, value| not(value ^ node.disabled?) }
|
183
205
|
describe do |options|
|
184
206
|
desc, states = "", []
|
185
207
|
desc << " with value #{options[:option].inspect}" if options[:option]
|
186
208
|
states << 'checked' if options[:checked] || (options.has_key?(:unchecked) && !options[:unchecked])
|
187
209
|
states << 'not checked' if options[:unchecked] || (options.has_key?(:checked) && !options[:checked])
|
188
|
-
states << 'disabled' if options[:disabled]
|
210
|
+
states << 'disabled' if options[:disabled] == true
|
189
211
|
desc << " that is #{states.join(' and ')}" unless states.empty?
|
190
212
|
desc
|
191
213
|
end
|
@@ -196,13 +218,13 @@ Capybara.add_selector(:checkbox) do
|
|
196
218
|
filter(:checked, boolean: true) { |node, value| not(value ^ node.checked?) }
|
197
219
|
filter(:unchecked, boolean: true) { |node, value| (value ^ node.checked?) }
|
198
220
|
filter(:option) { |node, value| node.value == value.to_s }
|
199
|
-
filter(:disabled, default: false, boolean: true) { |node, value| not(value ^ node.disabled?) }
|
221
|
+
filter(:disabled, default: false, boolean: true, skip_if: :all) { |node, value| not(value ^ node.disabled?) }
|
200
222
|
describe do |options|
|
201
223
|
desc, states = "", []
|
202
224
|
desc << " with value #{options[:option].inspect}" if options[:option]
|
203
225
|
states << 'checked' if options[:checked] || (options.has_key?(:unchecked) && !options[:unchecked])
|
204
226
|
states << 'not checked' if options[:unchecked] || (options.has_key?(:checked) && !options[:checked])
|
205
|
-
states << 'disabled' if options[:disabled]
|
227
|
+
states << 'disabled' if options[:disabled] == true
|
206
228
|
desc << " that is #{states.join(' and ')}" unless states.empty?
|
207
229
|
desc
|
208
230
|
end
|
@@ -212,21 +234,31 @@ Capybara.add_selector(:select) do
|
|
212
234
|
label "select box"
|
213
235
|
xpath { |locator| XPath::HTML.select(locator) }
|
214
236
|
filter(:options) do |node, options|
|
215
|
-
|
237
|
+
if node.visible?
|
238
|
+
actual = node.all(:xpath, './/option').map { |option| option.text }
|
239
|
+
else
|
240
|
+
actual = node.all(:xpath, './/option', visible: false).map { |option| option.text(:all) }
|
241
|
+
end
|
216
242
|
options.sort == actual.sort
|
217
243
|
end
|
218
|
-
filter(:with_options)
|
244
|
+
filter(:with_options) do |node, options|
|
245
|
+
finder_settings = { minimum: 0 }
|
246
|
+
if !node.visible?
|
247
|
+
finder_settings[:visible] = false
|
248
|
+
end
|
249
|
+
options.all? { |option| node.first(:option, option, finder_settings) }
|
250
|
+
end
|
219
251
|
filter(:selected) do |node, selected|
|
220
|
-
actual = node.all(:xpath, './/option').select { |option| option.selected? }.map { |option| option.text }
|
252
|
+
actual = node.all(:xpath, './/option', visible: false).select { |option| option.selected? }.map { |option| option.text(:all) }
|
221
253
|
[selected].flatten.sort == actual.sort
|
222
254
|
end
|
223
|
-
filter(:disabled, default: false, boolean: true) { |node, value| not(value ^ node.disabled?) }
|
255
|
+
filter(:disabled, default: false, boolean: true, skip_if: :all) { |node, value| not(value ^ node.disabled?) }
|
224
256
|
describe do |options|
|
225
257
|
desc = ""
|
226
258
|
desc << " with options #{options[:options].inspect}" if options[:options]
|
227
259
|
desc << " with at least options #{options[:with_options].inspect}" if options[:with_options]
|
228
260
|
desc << " with #{options[:selected].inspect} selected" if options[:selected]
|
229
|
-
desc << " that is disabled" if options[:disabled]
|
261
|
+
desc << " that is disabled" if options[:disabled] == true
|
230
262
|
desc
|
231
263
|
end
|
232
264
|
end
|
@@ -238,8 +270,8 @@ end
|
|
238
270
|
Capybara.add_selector(:file_field) do
|
239
271
|
label "file field"
|
240
272
|
xpath { |locator| XPath::HTML.file_field(locator) }
|
241
|
-
filter(:disabled, default: false, boolean: true) { |node, value| not(value ^ node.disabled?) }
|
242
|
-
describe { |options| " that is disabled" if options[:disabled] }
|
273
|
+
filter(:disabled, default: false, boolean: true, skip_if: :all) { |node, value| not(value ^ node.disabled?) }
|
274
|
+
describe { |options| " that is disabled" if options[:disabled] == true}
|
243
275
|
end
|
244
276
|
|
245
277
|
Capybara.add_selector(:table) do
|