capybara 2.16.1 → 2.17.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 +14 -1
- data/lib/capybara/minitest.rb +3 -1
- data/lib/capybara/minitest/spec.rb +3 -1
- data/lib/capybara/queries/current_path_query.rb +1 -1
- data/lib/capybara/queries/text_query.rb +1 -1
- data/lib/capybara/rspec/matchers.rb +50 -1
- data/lib/capybara/selenium/node.rb +27 -4
- data/lib/capybara/session.rb +4 -6
- data/lib/capybara/session/config.rb +8 -0
- data/lib/capybara/spec/public/test.js +2 -2
- data/lib/capybara/spec/session/assert_text.rb +8 -0
- data/lib/capybara/spec/session/has_all_selectors_spec.rb +69 -0
- data/lib/capybara/spec/session/has_current_path_spec.rb +6 -0
- data/lib/capybara/spec/session/has_link_spec.rb +4 -4
- data/lib/capybara/spec/session/has_none_selectors_spec.rb +76 -0
- data/lib/capybara/spec/session/has_select_spec.rb +2 -2
- data/lib/capybara/spec/session/node_spec.rb +19 -5
- data/lib/capybara/spec/session/select_spec.rb +1 -0
- data/lib/capybara/spec/spec_helper.rb +5 -3
- data/lib/capybara/spec/views/with_hover.erb +5 -0
- data/lib/capybara/spec/views/with_html.erb +4 -0
- data/lib/capybara/spec/views/with_js.erb +7 -0
- data/lib/capybara/version.rb +1 -1
- data/spec/capybara_spec.rb +1 -1
- data/spec/minitest_spec.rb +9 -1
- data/spec/minitest_spec_spec.rb +9 -1
- data/spec/selenium_spec_chrome.rb +8 -4
- metadata +13 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5f913df68a0c00ede749cba87a0b229ff28e9e6b8f8f45bbbbd07577729f1c6a
|
4
|
+
data.tar.gz: 37a3fdfec9dc3cab859eae2300819d4691c1f20ccb05acf98807e7e287796c98
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1edbf3df7b7357bbb96937c10eecffa5afa6ead2c119b0607bae820973702197de1536ec540968100d00355d07227c1f531f793156d645124d9f1a0250802996
|
7
|
+
data.tar.gz: e5a51fbceb1d26ddf7a101712bb407bc835ab701038b6e103c9f25c7677308fbda93ec515701862b297810b962dffac3b0e3ed35032296a6cf1f78c4adb4b79e
|
data/History.md
CHANGED
@@ -1,5 +1,18 @@
|
|
1
|
+
# Version 2.17.0
|
2
|
+
Release date: 2018-01-02
|
3
|
+
|
4
|
+
### Added
|
5
|
+
|
6
|
+
* `have_all_of_selectors`, `have_none_of_selectors` RSpec matchers for parity with minitest assertions [Thomas Walpole]
|
7
|
+
|
8
|
+
### Fixed
|
9
|
+
|
10
|
+
* Allow xpath 3.x gem [Thomas Walpole]
|
11
|
+
* Issue when drivers returned nil for `current_path` and a matcher was used with a Regexp [Thomas Walpole]
|
12
|
+
* Error message when visible element not found, but non-visible was [Andy Klimczak]
|
13
|
+
|
1
14
|
# Version 2.16.1
|
2
|
-
Release
|
15
|
+
Release date: 2017-11-20
|
3
16
|
|
4
17
|
### Fixed
|
5
18
|
|
data/lib/capybara/minitest.rb
CHANGED
@@ -81,7 +81,9 @@ module Capybara
|
|
81
81
|
# @!method assert_xpath
|
82
82
|
# see {Capybara::Node::Matchers#assert_not_matches_selector}
|
83
83
|
|
84
|
-
%w(assert_selector assert_no_selector
|
84
|
+
%w(assert_selector assert_no_selector
|
85
|
+
assert_all_of_selectors assert_none_of_selectors
|
86
|
+
assert_matches_selector assert_not_matches_selector).each do |assertion_name|
|
85
87
|
self.class_eval <<-EOM, __FILE__, __LINE__ + 1
|
86
88
|
def #{assertion_name} *args, &optional_filter_block
|
87
89
|
self.assertions +=1
|
@@ -11,7 +11,9 @@ module Capybara
|
|
11
11
|
(%w(selector xpath css link button field select table checked_field unchecked_field).flat_map do |assertion|
|
12
12
|
[["assert_#{assertion}", "must_have_#{assertion}"],
|
13
13
|
["refute_#{assertion}", "wont_have_#{assertion}"]]
|
14
|
-
end +
|
14
|
+
end + [["assert_all_of_selectors", "must_have_all_of_selectors"],
|
15
|
+
["assert_none_of_selectors", "must_have_none_of_selectors"]] +
|
16
|
+
%w(selector xpath css).flat_map do |assertion|
|
15
17
|
[["assert_matches_#{assertion}", "must_match_#{assertion}"],
|
16
18
|
["refute_matches_#{assertion}", "wont_match_#{assertion}"]]
|
17
19
|
end).each do |(meth, new_name)|
|
@@ -70,7 +70,7 @@ module Capybara
|
|
70
70
|
invisible_text = text(@node, :all)
|
71
71
|
invisible_count = invisible_text.scan(@search_regexp).size
|
72
72
|
if invisible_count != @count
|
73
|
-
details_message << "
|
73
|
+
details_message << "it was found #{invisible_count} #{Capybara::Helpers.declension("time", "times", invisible_count)} including non-visible text"
|
74
74
|
end
|
75
75
|
rescue
|
76
76
|
# An error getting the non-visible text (if element goes out of scope) should not affect the response
|
@@ -59,7 +59,6 @@ module Capybara
|
|
59
59
|
end
|
60
60
|
|
61
61
|
class HaveSelector < Matcher
|
62
|
-
|
63
62
|
def initialize(*args, &filter_block)
|
64
63
|
@args = args
|
65
64
|
@filter_block = filter_block
|
@@ -82,6 +81,44 @@ module Capybara
|
|
82
81
|
end
|
83
82
|
end
|
84
83
|
|
84
|
+
class HaveAllSelectors < Matcher
|
85
|
+
def initialize(*args, &filter_block)
|
86
|
+
@args = args
|
87
|
+
@filter_block = filter_block
|
88
|
+
end
|
89
|
+
|
90
|
+
def matches?(actual)
|
91
|
+
wrap_matches?(actual){ |el| el.assert_all_of_selectors(*@args, &@filter_block) }
|
92
|
+
end
|
93
|
+
|
94
|
+
def does_not_match?(actual)
|
95
|
+
raise ArgumentError, "The have_all_selectors matcher does not support use with not_to/should_not"
|
96
|
+
end
|
97
|
+
|
98
|
+
def description
|
99
|
+
"have all selectors"
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
class HaveNoSelectors < Matcher
|
104
|
+
def initialize(*args, &filter_block)
|
105
|
+
@args = args
|
106
|
+
@filter_block = filter_block
|
107
|
+
end
|
108
|
+
|
109
|
+
def matches?(actual)
|
110
|
+
wrap_matches?(actual){ |el| el.assert_none_of_selectors(*@args, &@filter_block) }
|
111
|
+
end
|
112
|
+
|
113
|
+
def does_not_match?(actual)
|
114
|
+
raise ArgumentError, "The have_none_of_selectors matcher does not support use with not_to/should_not"
|
115
|
+
end
|
116
|
+
|
117
|
+
def description
|
118
|
+
"have no selectors"
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
85
122
|
class MatchSelector < HaveSelector
|
86
123
|
def matches?(actual)
|
87
124
|
wrap_matches?(actual) { |el| el.assert_matches_selector(*@args, &@filter_block) }
|
@@ -211,6 +248,18 @@ module Capybara
|
|
211
248
|
HaveSelector.new(*args, &optional_filter_block)
|
212
249
|
end
|
213
250
|
|
251
|
+
# RSpec matcher for whether the element(s) matching a group of selectors exist
|
252
|
+
# See {Capybara::Node::Matcher#assert_all_of_selectors}
|
253
|
+
def have_all_of_selectors(*args, &optional_filter_block)
|
254
|
+
HaveAllSelectors.new(*args, &optional_filter_block)
|
255
|
+
end
|
256
|
+
|
257
|
+
# RSpec matcher for whether no element(s) matching a group of selectors exist
|
258
|
+
# See {Capybara::Node::Matcher#assert_none_of_selectors}
|
259
|
+
def have_none_of_selectors(*args, &optional_filter_block)
|
260
|
+
HaveNoSelectors.new(*args, &optional_filter_block)
|
261
|
+
end
|
262
|
+
|
214
263
|
# RSpec matcher for whether the current element matches a given selector
|
215
264
|
# See {Capybara::Node::Matchers#assert_matches_selector}
|
216
265
|
def match_selector(*args, &optional_filter_block)
|
@@ -1,5 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
class Capybara::Selenium::Node < Capybara::Driver::Node
|
3
|
+
|
3
4
|
def visible_text
|
4
5
|
# Selenium doesn't normalize Unicode whitespace.
|
5
6
|
Capybara::Helpers.normalize_whitespace(native.text)
|
@@ -112,11 +113,15 @@ class Capybara::Selenium::Node < Capybara::Driver::Node
|
|
112
113
|
end
|
113
114
|
|
114
115
|
def right_click
|
115
|
-
|
116
|
+
scroll_if_needed do
|
117
|
+
driver.browser.action.context_click(native).perform
|
118
|
+
end
|
116
119
|
end
|
117
120
|
|
118
121
|
def double_click
|
119
|
-
|
122
|
+
scroll_if_needed do
|
123
|
+
driver.browser.action.double_click(native).perform
|
124
|
+
end
|
120
125
|
end
|
121
126
|
|
122
127
|
def send_keys(*args)
|
@@ -124,11 +129,15 @@ class Capybara::Selenium::Node < Capybara::Driver::Node
|
|
124
129
|
end
|
125
130
|
|
126
131
|
def hover
|
127
|
-
|
132
|
+
scroll_if_needed do
|
133
|
+
driver.browser.action.move_to(native).perform
|
134
|
+
end
|
128
135
|
end
|
129
136
|
|
130
137
|
def drag_to(element)
|
131
|
-
|
138
|
+
scroll_if_needed do
|
139
|
+
driver.browser.action.drag_and_drop(native, element.native).perform
|
140
|
+
end
|
132
141
|
end
|
133
142
|
|
134
143
|
def tag_name
|
@@ -238,4 +247,18 @@ private
|
|
238
247
|
end
|
239
248
|
end
|
240
249
|
end
|
250
|
+
|
251
|
+
def scroll_if_needed(&block)
|
252
|
+
block.call
|
253
|
+
rescue ::Selenium::WebDriver::Error::MoveTargetOutOfBoundsError
|
254
|
+
script = <<-JS
|
255
|
+
try {
|
256
|
+
arguments[0].scrollIntoView({behavior: 'instant', block: 'center', inline: 'center'});
|
257
|
+
} catch(e) {
|
258
|
+
arguments[0].scrollIntoView(true);
|
259
|
+
}
|
260
|
+
JS
|
261
|
+
driver.execute_script(script, self)
|
262
|
+
block.call
|
263
|
+
end
|
241
264
|
end
|
data/lib/capybara/session.rb
CHANGED
@@ -261,10 +261,8 @@ module Capybara
|
|
261
261
|
|
262
262
|
visit_uri_parts = visit_uri.to_hash.delete_if { |k,v| v.nil? }
|
263
263
|
|
264
|
-
#
|
265
|
-
#
|
266
|
-
# @abotalov brought up a good point about this behavior potentially being useful to people
|
267
|
-
# deploying to a subdirectory and/or single page apps where only the url fragment changes
|
264
|
+
# Useful to people deploying to a subdirectory
|
265
|
+
# and/or single page apps where only the url fragment changes
|
268
266
|
visit_uri_parts[:path] = uri_base.path + visit_uri.path
|
269
267
|
|
270
268
|
visit_uri = uri_base.merge(visit_uri_parts)
|
@@ -488,7 +486,7 @@ module Capybara
|
|
488
486
|
# @raise [Capybara::WindowError] if no window matches given block
|
489
487
|
# @overload switch_to_window(window)
|
490
488
|
# @param window [Capybara::Window] window that should be switched to
|
491
|
-
# @raise [Capybara::Driver::Base#no_such_window_error] if
|
489
|
+
# @raise [Capybara::Driver::Base#no_such_window_error] if nonexistent (e.g. closed) window was passed
|
492
490
|
#
|
493
491
|
# @return [Capybara::Window] window that has been switched to
|
494
492
|
# @raise [Capybara::ScopeError] if this method is invoked inside `within` or
|
@@ -521,7 +519,7 @@ module Capybara
|
|
521
519
|
# @overload within_window(window) { do_something }
|
522
520
|
# @param window [Capybara::Window] instance of `Capybara::Window` class
|
523
521
|
# that will be switched to
|
524
|
-
# @raise [driver#no_such_window_error] if
|
522
|
+
# @raise [driver#no_such_window_error] if nonexistent (e.g. closed) window was passed
|
525
523
|
# @overload within_window(proc_or_lambda) { do_something }
|
526
524
|
# @param lambda [Proc] lambda. First window for which lambda
|
527
525
|
# returns a value other than false or nil will be switched to.
|
@@ -39,6 +39,7 @@ module Capybara
|
|
39
39
|
# See {Capybara.configure}
|
40
40
|
#@!method save_path
|
41
41
|
# See {Capybara.configure}
|
42
|
+
#@deprecated
|
42
43
|
#@!method exact_options
|
43
44
|
# See {Capybara.configure}
|
44
45
|
#@!method asset_host
|
@@ -90,6 +91,13 @@ module Capybara
|
|
90
91
|
@save_and_open_page_path = path
|
91
92
|
end
|
92
93
|
|
94
|
+
remove_method :exact_options=
|
95
|
+
def exact_options=(opt)
|
96
|
+
@exact_options = opt
|
97
|
+
warn "DEPRECATED: #exact_options is deprecated, please scope your findes/actions and use the `:exact` "\
|
98
|
+
"option if similar functionality is needed."
|
99
|
+
end
|
100
|
+
|
93
101
|
def initialize_copy(other)
|
94
102
|
super
|
95
103
|
@server_errors = @server_errors.dup
|
@@ -1,8 +1,8 @@
|
|
1
1
|
var activeRequests = 0;
|
2
2
|
$(function() {
|
3
3
|
$('#change').text('I changed it');
|
4
|
-
$('#drag').draggable();
|
5
|
-
$('#drop').droppable({
|
4
|
+
$('#drag, #drag_scroll').draggable();
|
5
|
+
$('#drop, #drop_scroll').droppable({
|
6
6
|
drop: function(event, ui) {
|
7
7
|
ui.draggable.remove();
|
8
8
|
$(this).html('Dropped!');
|
@@ -52,6 +52,14 @@ Capybara::SpecHelper.spec '#assert_text' do
|
|
52
52
|
end.to raise_error(Capybara::ExpectationNotMet, /it was found 1 time using a case insensitive search/)
|
53
53
|
end
|
54
54
|
|
55
|
+
it "should raise error with helpful message if requested text is present but invisible and with incorrect case", requires: [:js] do
|
56
|
+
@session.visit('/with_html')
|
57
|
+
el = @session.find(:css, '#uppercase')
|
58
|
+
expect do
|
59
|
+
el.assert_text('text here')
|
60
|
+
end.to raise_error(Capybara::ExpectationNotMet, /it was found 1 time using a case insensitive search and it was found 1 time including non-visible text/)
|
61
|
+
end
|
62
|
+
|
55
63
|
it "should raise the correct error if requested text is missing but contains regex special characters" do
|
56
64
|
@session.visit('/with_html')
|
57
65
|
expect do
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
Capybara::SpecHelper.spec '#have_all_selectors' do
|
3
|
+
before do
|
4
|
+
@session.visit('/with_html')
|
5
|
+
end
|
6
|
+
|
7
|
+
it "should be true if the given selectors are on the page" do
|
8
|
+
expect(@session).to have_all_of_selectors(:css, "p a#foo", "h2#h2one", "h2#h2two" )
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should be false if any of the given selectors are not on the page" do
|
12
|
+
expect {
|
13
|
+
expect(@session).to have_all_of_selectors(:css, "p a#foo", "h2#h2three", "h2#h2one")
|
14
|
+
}.to raise_error ::RSpec::Expectations::ExpectationNotMetError
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should use default selector" do
|
18
|
+
Capybara.default_selector = :css
|
19
|
+
expect(@session).to have_all_of_selectors("p a#foo", "h2#h2two", "h2#h2one" )
|
20
|
+
expect {
|
21
|
+
expect(@session).to have_all_of_selectors("p a#foo", "h2#h2three", "h2#h2one")
|
22
|
+
}.to raise_error ::RSpec::Expectations::ExpectationNotMetError
|
23
|
+
end
|
24
|
+
|
25
|
+
context "should respect scopes" do
|
26
|
+
it "when used with `within`" do
|
27
|
+
@session.within "//p[@id='first']" do
|
28
|
+
expect(@session).to have_all_of_selectors(".//a[@id='foo']")
|
29
|
+
expect {
|
30
|
+
expect(@session).to have_all_of_selectors(".//a[@id='red']")
|
31
|
+
}.to raise_error ::RSpec::Expectations::ExpectationNotMetError
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
it "when called on elements" do
|
36
|
+
el = @session.find "//p[@id='first']"
|
37
|
+
expect(el).to have_all_of_selectors(".//a[@id='foo']")
|
38
|
+
expect {
|
39
|
+
expect(el).to have_all_of_selectors(".//a[@id='red']")
|
40
|
+
}.to raise_error ::RSpec::Expectations::ExpectationNotMetError
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
context "with options" do
|
45
|
+
it "should apply options to all locators" do
|
46
|
+
expect(@session).to have_all_of_selectors(:field, 'normal', 'additional_newline', type: :textarea)
|
47
|
+
expect {
|
48
|
+
expect(@session).to have_all_of_selectors(:field, 'normal', 'test_field', 'additional_newline', type: :textarea)
|
49
|
+
}.to raise_error ::RSpec::Expectations::ExpectationNotMetError
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
context "with wait", requires: [:js] do
|
54
|
+
it "should not raise error if all the elements appear before given wait duration" do
|
55
|
+
Capybara.using_wait_time(0.1) do
|
56
|
+
@session.visit('/with_js')
|
57
|
+
@session.click_link('Click me')
|
58
|
+
expect(@session).to have_all_of_selectors(:css, "a#clickable", "a#has-been-clicked", '#drag', wait: 0.9)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
it "cannot be negated" do
|
64
|
+
expect {
|
65
|
+
expect(@session).not_to have_all_of_selectors(:css, "p a#foo", "h2#h2one", "h2#h2two")
|
66
|
+
}.to raise_error ArgumentError
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
@@ -13,6 +13,12 @@ Capybara::SpecHelper.spec '#has_current_path?' do
|
|
13
13
|
expect(@session).not_to have_current_path(/monkey/)
|
14
14
|
end
|
15
15
|
|
16
|
+
it "should not raise an error when non-http" do
|
17
|
+
@session.reset_session!
|
18
|
+
expect(@session.has_current_path?(/monkey/)).to eq false
|
19
|
+
expect(@session.has_current_path?("/with_js")).to eq false
|
20
|
+
end
|
21
|
+
|
16
22
|
it "should handle non-escaped query options" do
|
17
23
|
@session.click_link("Non-escaped query options")
|
18
24
|
expect(@session).to have_current_path("/with_html?options[]=things")
|
@@ -14,8 +14,8 @@ Capybara::SpecHelper.spec '#has_link?' do
|
|
14
14
|
|
15
15
|
it "should be false if the given link is not on the page" do
|
16
16
|
expect(@session).not_to have_link('monkey')
|
17
|
-
expect(@session).not_to have_link('A link', href: '/
|
18
|
-
expect(@session).not_to have_link('A link', href: /
|
17
|
+
expect(@session).not_to have_link('A link', href: '/nonexistent-href')
|
18
|
+
expect(@session).not_to have_link('A link', href: /nonexistent/)
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
@@ -32,7 +32,7 @@ Capybara::SpecHelper.spec '#has_no_link?' do
|
|
32
32
|
|
33
33
|
it "should be true if the given link is not on the page" do
|
34
34
|
expect(@session).to have_no_link('monkey')
|
35
|
-
expect(@session).to have_no_link('A link', href: '/
|
36
|
-
expect(@session).to have_no_link('A link', href: /\/
|
35
|
+
expect(@session).to have_no_link('A link', href: '/nonexistent-href')
|
36
|
+
expect(@session).to have_no_link('A link', href: /\/nonexistent-href/)
|
37
37
|
end
|
38
38
|
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
Capybara::SpecHelper.spec '#have_none_of_selectors' do
|
2
|
+
before do
|
3
|
+
@session.visit('/with_html')
|
4
|
+
end
|
5
|
+
|
6
|
+
it "should be false if any of the given locators are on the page" do
|
7
|
+
expect {
|
8
|
+
expect(@session).to have_none_of_selectors(:xpath, "//p", "//a")
|
9
|
+
}.to raise_error ::RSpec::Expectations::ExpectationNotMetError
|
10
|
+
expect {
|
11
|
+
expect(@session).to have_none_of_selectors(:css, "p a#foo")
|
12
|
+
}.to raise_error ::RSpec::Expectations::ExpectationNotMetError
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should be true if none of the given locators are on the page" do
|
16
|
+
expect(@session).to have_none_of_selectors(:xpath, "//abbr", "//td" )
|
17
|
+
expect(@session).to have_none_of_selectors(:css, "p a#doesnotexist", "abbr")
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should use default selector" do
|
21
|
+
Capybara.default_selector = :css
|
22
|
+
expect(@session).to have_none_of_selectors("p a#doesnotexist", "abbr")
|
23
|
+
expect {
|
24
|
+
expect(@session).to have_none_of_selectors("abbr", "p a#foo")
|
25
|
+
}.to raise_error ::RSpec::Expectations::ExpectationNotMetError
|
26
|
+
end
|
27
|
+
|
28
|
+
context "should respect scopes" do
|
29
|
+
it "when used with `within`" do
|
30
|
+
@session.within "//p[@id='first']" do
|
31
|
+
expect {
|
32
|
+
expect(@session).to have_none_of_selectors(".//a[@id='foo']")
|
33
|
+
}.to raise_error ::RSpec::Expectations::ExpectationNotMetError
|
34
|
+
expect(@session).to have_none_of_selectors(".//a[@id='red']")
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
it "when called on an element" do
|
39
|
+
el = @session.find "//p[@id='first']"
|
40
|
+
expect {
|
41
|
+
expect(el).to have_none_of_selectors(".//a[@id='foo']")
|
42
|
+
}.to raise_error ::RSpec::Expectations::ExpectationNotMetError
|
43
|
+
expect(el).to have_none_of_selectors(".//a[@id='red']")
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
context "with options" do
|
48
|
+
it "should apply the options to all locators" do
|
49
|
+
expect {
|
50
|
+
expect(@session).to have_none_of_selectors("//p//a", text: "Redirect")
|
51
|
+
}.to raise_error ::RSpec::Expectations::ExpectationNotMetError
|
52
|
+
expect(@session).to have_none_of_selectors("//p", text: "Doesnotexist")
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should discard all matches where the given regexp is matched" do
|
56
|
+
expect {
|
57
|
+
expect(@session).to have_none_of_selectors("//p//a", text: /re[dab]i/i, count: 1)
|
58
|
+
}.to raise_error ::RSpec::Expectations::ExpectationNotMetError
|
59
|
+
expect(@session).to have_none_of_selectors("//p//a", text: /Red$/)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
context "with wait", requires: [:js] do
|
64
|
+
it "should not find elements if they appear after given wait duration" do
|
65
|
+
@session.visit('/with_js')
|
66
|
+
@session.click_link('Click me')
|
67
|
+
expect(@session).to have_none_of_selectors(:css, "#new_field", "a#has-been-clicked", wait: 0.1)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
it "cannot be negated" do
|
72
|
+
expect {
|
73
|
+
expect(@session).not_to have_none_of_selectors(:css, "p a#foo", "h2#h2one", "h2#h2two")
|
74
|
+
}.to raise_error ArgumentError
|
75
|
+
end
|
76
|
+
end
|
@@ -27,7 +27,7 @@ Capybara::SpecHelper.spec '#has_select?' do
|
|
27
27
|
expect(@session).not_to have_select('Does not exist', selected: 'John')
|
28
28
|
expect(@session).not_to have_select('City', selected: 'Not there')
|
29
29
|
expect(@session).not_to have_select('Underwear', selected: [
|
30
|
-
'Boxerbriefs', 'Briefs', 'Commando', "Frenchman's Pantalons", 'Long Johns', '
|
30
|
+
'Boxerbriefs', 'Briefs', 'Commando', "Frenchman's Pantalons", 'Long Johns', 'Nonexistent'
|
31
31
|
])
|
32
32
|
expect(@session).not_to have_select('Underwear', selected: [
|
33
33
|
'Boxerbriefs', 'Briefs', 'Boxers', 'Commando', "Frenchman's Pantalons", 'Long Johns'
|
@@ -185,7 +185,7 @@ Capybara::SpecHelper.spec '#has_no_select?' do
|
|
185
185
|
expect(@session).to have_no_select('Does not exist', selected: 'John')
|
186
186
|
expect(@session).to have_no_select('City', selected: 'Not there')
|
187
187
|
expect(@session).to have_no_select('Underwear', selected: [
|
188
|
-
'Boxerbriefs', 'Briefs', 'Commando', "Frenchman's Pantalons", 'Long Johns', '
|
188
|
+
'Boxerbriefs', 'Briefs', 'Commando', "Frenchman's Pantalons", 'Long Johns', 'Nonexistent'
|
189
189
|
])
|
190
190
|
expect(@session).to have_no_select('Underwear', selected: [
|
191
191
|
'Boxerbriefs', 'Briefs', 'Boxers', 'Commando', "Frenchman's Pantalons", 'Long Johns'
|
@@ -297,14 +297,29 @@ Capybara::SpecHelper.spec "node" do
|
|
297
297
|
element.drag_to(target)
|
298
298
|
expect(@session.find('//div[contains(., "Dropped!")]')).not_to be_nil
|
299
299
|
end
|
300
|
+
|
301
|
+
it "should drag and drop if scrolling is needed" do
|
302
|
+
@session.visit('/with_js')
|
303
|
+
element = @session.find('//div[@id="drag_scroll"]')
|
304
|
+
target = @session.find('//div[@id="drop_scroll"]')
|
305
|
+
element.drag_to(target)
|
306
|
+
expect(@session.find('//div[contains(., "Dropped!")]')).not_to be_nil
|
307
|
+
end
|
300
308
|
end
|
301
309
|
|
302
310
|
describe '#hover', requires: [:hover] do
|
303
311
|
it "should allow hovering on an element" do
|
304
312
|
@session.visit('/with_hover')
|
305
|
-
expect(@session.find(:css,'.hidden_until_hover', visible: false)).not_to be_visible
|
306
|
-
@session.find(:css,'.wrapper').hover
|
307
|
-
expect(@session.find(:css, '.hidden_until_hover', visible: false)).to be_visible
|
313
|
+
expect(@session.find(:css, '.wrapper:not(.scroll_needed) .hidden_until_hover', visible: false)).not_to be_visible
|
314
|
+
@session.find(:css,'.wrapper:not(.scroll_needed)').hover
|
315
|
+
expect(@session.find(:css, '.wrapper:not(.scroll_needed) .hidden_until_hover', visible: false)).to be_visible
|
316
|
+
end
|
317
|
+
|
318
|
+
it "should allow hovering on an element that needs to be scrolled into view" do
|
319
|
+
@session.visit('/with_hover')
|
320
|
+
expect(@session.find(:css, '.wrapper.scroll_needed .hidden_until_hover', visible: false)).not_to be_visible
|
321
|
+
@session.find(:css,'.wrapper.scroll_needed').hover
|
322
|
+
expect(@session.find(:css, '.wrapper.scroll_needed .hidden_until_hover', visible: false)).to be_visible
|
308
323
|
end
|
309
324
|
end
|
310
325
|
|
@@ -347,7 +362,7 @@ Capybara::SpecHelper.spec "node" do
|
|
347
362
|
|
348
363
|
describe '#double_click', requires: [:js] do
|
349
364
|
it "should double click an element" do
|
350
|
-
pending "selenium-webdriver/geckodriver doesn't
|
365
|
+
pending "selenium-webdriver/geckodriver doesn't generate double click event" if marionette?(@session)
|
351
366
|
@session.visit('/with_js')
|
352
367
|
@session.find(:css, '#click-test').double_click
|
353
368
|
expect(@session.find(:css, '#has-been-double-clicked')).to be
|
@@ -356,7 +371,6 @@ Capybara::SpecHelper.spec "node" do
|
|
356
371
|
|
357
372
|
describe '#right_click', requires: [:js] do
|
358
373
|
it "should right click an element" do
|
359
|
-
pending "selenium-webdriver/geckodriver doesn't support mouse move_to" if marionette?(@session)
|
360
374
|
@session.visit('/with_js')
|
361
375
|
@session.find(:css, '#click-test').right_click
|
362
376
|
expect(@session.find(:css, '#has-been-right-clicked')).to be
|
@@ -24,6 +24,7 @@ Capybara::SpecHelper.spec "#select" do
|
|
24
24
|
end
|
25
25
|
|
26
26
|
it "should not allow selecting options where they are the only inexact match if `Capybara.exact_options = true`" do
|
27
|
+
expect_any_instance_of(Kernel).to receive(:warn).with(/^DEPRECATED:/)
|
27
28
|
Capybara.exact_options = true
|
28
29
|
expect do
|
29
30
|
@session.select("Mis", from: 'Title')
|
@@ -33,7 +33,9 @@ module Capybara
|
|
33
33
|
Capybara.default_max_wait_time = 1
|
34
34
|
Capybara.ignore_hidden_elements = true
|
35
35
|
Capybara.exact = false
|
36
|
-
|
36
|
+
# `exact_options` is deprecated - set instancce var directly so we
|
37
|
+
# don't generate message every reset
|
38
|
+
Capybara.send(:config).session_options.instance_variable_set('@exact_options', false)
|
37
39
|
Capybara.raise_server_errors = true
|
38
40
|
Capybara.visible_text_only = false
|
39
41
|
Capybara.match = :smart
|
@@ -52,7 +54,7 @@ module Capybara
|
|
52
54
|
end
|
53
55
|
end
|
54
56
|
|
55
|
-
def spec(name, options
|
57
|
+
def spec(name, *options, &block)
|
56
58
|
@specs ||= []
|
57
59
|
@specs << [name, options, block]
|
58
60
|
end
|
@@ -79,7 +81,7 @@ module Capybara
|
|
79
81
|
end
|
80
82
|
|
81
83
|
specs.each do |spec_name, spec_options, block|
|
82
|
-
describe spec_name, spec_options do
|
84
|
+
describe spec_name, *spec_options do
|
83
85
|
class_eval(&block)
|
84
86
|
end
|
85
87
|
end
|
@@ -14,5 +14,10 @@
|
|
14
14
|
Some text here so the wrapper has size
|
15
15
|
<div class="hidden_until_hover">Here I am</div>
|
16
16
|
</div>
|
17
|
+
<div style="display: block; height: 1000px; width: 100%"></div>
|
18
|
+
<div class="wrapper scroll_needed" >
|
19
|
+
Some text here so the wrapper has size
|
20
|
+
<div class="hidden_until_hover">Here I am</div>
|
21
|
+
</div>
|
17
22
|
</body>
|
18
23
|
</html>
|
@@ -121,6 +121,13 @@
|
|
121
121
|
<input type="file" id="hidden_file" style="opacity:0; display: none;">
|
122
122
|
</p>
|
123
123
|
|
124
|
+
<div id="drag_scroll">
|
125
|
+
<p>This is a draggable element.</p>
|
126
|
+
</div>
|
127
|
+
<div id="drop_scroll">
|
128
|
+
<p>It should be dropped here.</p>
|
129
|
+
</div>
|
130
|
+
|
124
131
|
<script type="text/javascript">
|
125
132
|
// a javascript comment
|
126
133
|
var aVar = 123;
|
data/lib/capybara/version.rb
CHANGED
data/spec/capybara_spec.rb
CHANGED
@@ -139,7 +139,7 @@ RSpec.describe Capybara do
|
|
139
139
|
end
|
140
140
|
|
141
141
|
RSpec.describe Capybara::Session do
|
142
|
-
context 'with
|
142
|
+
context 'with nonexistent driver' do
|
143
143
|
it "should raise an error" do
|
144
144
|
expect {
|
145
145
|
Capybara::Session.new(:quox, TestApp).driver
|
data/spec/minitest_spec.rb
CHANGED
@@ -88,6 +88,14 @@ class MinitestTest < Minitest::Test
|
|
88
88
|
refute_table('not_on_form')
|
89
89
|
end
|
90
90
|
|
91
|
+
def test_assert_all_of_selectors
|
92
|
+
assert_all_of_selectors(:css, 'select#form_other_title', 'input#form_last_name')
|
93
|
+
end
|
94
|
+
|
95
|
+
def test_assert_none_of_selectors
|
96
|
+
assert_none_of_selectors(:css, 'input#not_on_page', 'input#also_not_on_page')
|
97
|
+
end
|
98
|
+
|
91
99
|
def test_assert_matches_selector
|
92
100
|
assert_matches_selector(find(:field, 'customer_email'), :field, 'customer_email')
|
93
101
|
assert_not_matches_selector(find(:select, 'form_title'), :field, 'customer_email')
|
@@ -117,6 +125,6 @@ RSpec.describe 'capybara/minitest' do
|
|
117
125
|
reporter.start
|
118
126
|
MinitestTest.run reporter, {}
|
119
127
|
reporter.report
|
120
|
-
expect(output.string).to include("
|
128
|
+
expect(output.string).to include("17 runs, 44 assertions, 0 failures, 0 errors, 0 skips")
|
121
129
|
end
|
122
130
|
end
|
data/spec/minitest_spec_spec.rb
CHANGED
@@ -88,6 +88,14 @@ class MinitestSpecTest < Minitest::Spec
|
|
88
88
|
page.wont_have_table('not_on_form')
|
89
89
|
end
|
90
90
|
|
91
|
+
it "supports all_of_selectors expectations" do
|
92
|
+
page.must_have_all_of_selectors(:css, 'select#form_other_title', 'input#form_last_name')
|
93
|
+
end
|
94
|
+
|
95
|
+
it "supports none_of_selectors expectations" do
|
96
|
+
page.must_have_none_of_selectors(:css, 'input#not_on_page', 'input#also_not_on_page')
|
97
|
+
end
|
98
|
+
|
91
99
|
it "supports match_selector expectations" do
|
92
100
|
find(:field, 'customer_email').must_match_selector(:field, 'customer_email')
|
93
101
|
find(:select, 'form_title').wont_match_selector(:field, 'customer_email')
|
@@ -120,7 +128,7 @@ RSpec.describe 'capybara/minitest/spec' do
|
|
120
128
|
reporter.start
|
121
129
|
MinitestSpecTest.run reporter, {}
|
122
130
|
reporter.report
|
123
|
-
expect(output.string).to include("
|
131
|
+
expect(output.string).to include("18 runs, 41 assertions, 1 failures, 0 errors, 0 skips")
|
124
132
|
#Make sure error messages are displayed
|
125
133
|
expect(output.string).to include('expected to find visible select box "non_existing_form_title" that is not disabled but there were no matches')
|
126
134
|
end
|
@@ -40,8 +40,10 @@ RSpec.describe "Capybara::Session with chrome" do
|
|
40
40
|
@session.find(:css, '#set-storage').click
|
41
41
|
@session.reset!
|
42
42
|
@session.visit('/with_js')
|
43
|
-
expect(@session.driver.browser.local_storage.keys).not_to be_empty
|
44
|
-
expect(@session.driver.browser.session_storage.keys).not_to be_empty
|
43
|
+
# expect(@session.driver.browser.local_storage.keys).not_to be_empty
|
44
|
+
# expect(@session.driver.browser.session_storage.keys).not_to be_empty
|
45
|
+
expect(@session.evaluate_script('Object.keys(localStorage)')).not_to be_empty
|
46
|
+
expect(@session.evaluate_script('Object.keys(sessionStorage)')).not_to be_empty
|
45
47
|
end
|
46
48
|
|
47
49
|
it "clears storage when set" do
|
@@ -50,8 +52,10 @@ RSpec.describe "Capybara::Session with chrome" do
|
|
50
52
|
@session.find(:css, '#set-storage').click
|
51
53
|
@session.reset!
|
52
54
|
@session.visit('/with_js')
|
53
|
-
expect(@session.driver.browser.local_storage.keys).to be_empty
|
54
|
-
expect(@session.driver.browser.session_storage.keys).to be_empty
|
55
|
+
# expect(@session.driver.browser.local_storage.keys).to be_empty
|
56
|
+
# expect(@session.driver.browser.session_storage.keys).to be_empty
|
57
|
+
expect(@session.evaluate_script('Object.keys(localStorage)')).to be_empty
|
58
|
+
expect(@session.evaluate_script('Object.keys(sessionStorage)')).to be_empty
|
55
59
|
end
|
56
60
|
end
|
57
61
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: capybara
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.17.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Thomas Walpole
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain:
|
12
12
|
- gem-public_cert.pem
|
13
|
-
date:
|
13
|
+
date: 2018-01-02 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: nokogiri
|
@@ -72,16 +72,22 @@ dependencies:
|
|
72
72
|
name: xpath
|
73
73
|
requirement: !ruby/object:Gem::Requirement
|
74
74
|
requirements:
|
75
|
-
- - "
|
75
|
+
- - ">="
|
76
76
|
- !ruby/object:Gem::Version
|
77
77
|
version: '2.0'
|
78
|
+
- - "<"
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: '4.0'
|
78
81
|
type: :runtime
|
79
82
|
prerelease: false
|
80
83
|
version_requirements: !ruby/object:Gem::Requirement
|
81
84
|
requirements:
|
82
|
-
- - "
|
85
|
+
- - ">="
|
83
86
|
- !ruby/object:Gem::Version
|
84
87
|
version: '2.0'
|
88
|
+
- - "<"
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: '4.0'
|
85
91
|
- !ruby/object:Gem::Dependency
|
86
92
|
name: addressable
|
87
93
|
requirement: !ruby/object:Gem::Requirement
|
@@ -390,11 +396,13 @@ files:
|
|
390
396
|
- lib/capybara/spec/session/frame/within_frame_spec.rb
|
391
397
|
- lib/capybara/spec/session/go_back_spec.rb
|
392
398
|
- lib/capybara/spec/session/go_forward_spec.rb
|
399
|
+
- lib/capybara/spec/session/has_all_selectors_spec.rb
|
393
400
|
- lib/capybara/spec/session/has_button_spec.rb
|
394
401
|
- lib/capybara/spec/session/has_css_spec.rb
|
395
402
|
- lib/capybara/spec/session/has_current_path_spec.rb
|
396
403
|
- lib/capybara/spec/session/has_field_spec.rb
|
397
404
|
- lib/capybara/spec/session/has_link_spec.rb
|
405
|
+
- lib/capybara/spec/session/has_none_selectors_spec.rb
|
398
406
|
- lib/capybara/spec/session/has_select_spec.rb
|
399
407
|
- lib/capybara/spec/session/has_selector_spec.rb
|
400
408
|
- lib/capybara/spec/session/has_table_spec.rb
|
@@ -508,7 +516,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
508
516
|
version: '0'
|
509
517
|
requirements: []
|
510
518
|
rubyforge_project:
|
511
|
-
rubygems_version: 2.7.
|
519
|
+
rubygems_version: 2.7.3
|
512
520
|
signing_key:
|
513
521
|
specification_version: 4
|
514
522
|
summary: Capybara aims to simplify the process of integration testing Rack applications,
|