capybara 2.5.0 → 2.6.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 -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
|
-
[](https://travis-ci.org/jnicklas/capybara)
|
4
|
+
[](https://gemnasium.com/jnicklas/capybara)
|
5
|
+
[](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
|