capybara 3.4.0 → 3.5.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 +25 -0
- data/README.md +1 -1
- data/lib/capybara/node/element.rb +3 -1
- data/lib/capybara/node/matchers.rb +21 -3
- data/lib/capybara/queries/text_query.rb +2 -1
- data/lib/capybara/rspec/matchers.rb +26 -38
- data/lib/capybara/selenium/driver.rb +2 -2
- data/lib/capybara/selenium/node.rb +8 -1
- data/lib/capybara/selenium/nodes/chrome_node.rb +1 -1
- data/lib/capybara/selenium/nodes/marionette_node.rb +5 -2
- data/lib/capybara/session.rb +1 -1
- data/lib/capybara/spec/public/jquery.js +5 -5
- data/lib/capybara/spec/public/test.js +3 -0
- data/lib/capybara/spec/session/assert_selector_spec.rb +6 -2
- data/lib/capybara/spec/session/assert_text_spec.rb +6 -1
- data/lib/capybara/spec/session/attach_file_spec.rb +15 -0
- data/lib/capybara/spec/session/check_spec.rb +7 -0
- data/lib/capybara/spec/session/element/matches_selector_spec.rb +11 -0
- data/lib/capybara/spec/session/has_text_spec.rb +5 -0
- data/lib/capybara/spec/views/form.erb +6 -0
- data/lib/capybara/spec/views/with_js.erb +4 -0
- data/lib/capybara/version.rb +1 -1
- data/spec/dsl_spec.rb +2 -1
- data/spec/minitest_spec.rb +9 -1
- data/spec/rspec/shared_spec_matchers.rb +2 -2
- data/spec/selenium_spec_chrome_remote.rb +8 -2
- data/spec/selenium_spec_firefox_remote.rb +3 -0
- data/spec/selenium_spec_ie.rb +9 -1
- data/spec/selenium_spec_marionette.rb +5 -0
- data/spec/shared_selenium_session.rb +7 -3
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ccbb47ddccdce3cfd6a790bd2af929bf21f0dff5a9c284c1798fced5de3deef0
|
|
4
|
+
data.tar.gz: abcbaadffc9b324fcb05601b14a923a051471de760c6a290acd4c020f7f53428
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: dee7228b9108ed669bf8796cfe024a49594b8820f5b0899118d49a90ecd8616453ec42b5467b0a833156ae0f10ff57df3e627f2b2e164ad4edc68fcef7cc0e6e
|
|
7
|
+
data.tar.gz: 7de8b0aa5ab6b9565b17732a61e6e693b431806c33cb2d64098f3f2d6d0440383af96f2930cff0197b11e92059e48878210a4254309320eeaf73f0cf470b256f
|
data/History.md
CHANGED
|
@@ -1,3 +1,28 @@
|
|
|
1
|
+
# Version 3.5.0
|
|
2
|
+
Release date: 2018-08-01
|
|
3
|
+
|
|
4
|
+
### Added
|
|
5
|
+
|
|
6
|
+
* text predicates and matchers (`has_text?`, `has_content?`, `assert_text`, etc) now support a `normalize_ws` option
|
|
7
|
+
|
|
8
|
+
### Fixed
|
|
9
|
+
|
|
10
|
+
* `attach_file` with Selenium and local Firefox 62+ now correctly generates only one change event when attaching multiple files
|
|
11
|
+
|
|
12
|
+
# Version 3.4.2
|
|
13
|
+
Release date: 2018-07-24
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
|
|
17
|
+
* `match_xxx` selectors and `matches_xxx?` predicates work correctly with elements found using a sibling selector - Issue #2073
|
|
18
|
+
|
|
19
|
+
# Version 3.4.1
|
|
20
|
+
Release date: 2018-07-20
|
|
21
|
+
|
|
22
|
+
### Fixed
|
|
23
|
+
|
|
24
|
+
* `Session#evaluate_script` now strips the script in `Session` rather than only in the Selenium driver
|
|
25
|
+
|
|
1
26
|
# Version 3.4.0
|
|
2
27
|
Release date: 2018-07-19
|
|
3
28
|
|
data/README.md
CHANGED
|
@@ -76,7 +76,7 @@ GitHub): http://groups.google.com/group/ruby-capybara
|
|
|
76
76
|
|
|
77
77
|
## <a name="setup"></a>Setup
|
|
78
78
|
|
|
79
|
-
Capybara requires Ruby 2.
|
|
79
|
+
Capybara requires Ruby 2.3.0 or later. To install, add this line to your
|
|
80
80
|
`Gemfile` and run `bundle install`:
|
|
81
81
|
|
|
82
82
|
```ruby
|
|
@@ -344,7 +344,9 @@ module Capybara
|
|
|
344
344
|
##
|
|
345
345
|
#
|
|
346
346
|
# Trigger any event on the current element, for example mouseover or focus
|
|
347
|
-
# events.
|
|
347
|
+
# events. Not supported with the Selenium driver, and SHOULDN'T BE USED IN TESTING unless you
|
|
348
|
+
# fully understand why you're using it, that it can allow actions a user could never
|
|
349
|
+
# perform, and that it may completely invalidate your test.
|
|
348
350
|
#
|
|
349
351
|
# @param [String] event The name of the event to trigger
|
|
350
352
|
#
|
|
@@ -203,7 +203,6 @@ module Capybara
|
|
|
203
203
|
end
|
|
204
204
|
end
|
|
205
205
|
end
|
|
206
|
-
alias_method :refute_selector, :assert_no_selector
|
|
207
206
|
|
|
208
207
|
##
|
|
209
208
|
#
|
|
@@ -529,7 +528,24 @@ module Capybara
|
|
|
529
528
|
raise Capybara::ExpectationNotMet, 'Item matched the provided selector' if result.include? self
|
|
530
529
|
end
|
|
531
530
|
end
|
|
532
|
-
|
|
531
|
+
|
|
532
|
+
# Deprecated
|
|
533
|
+
# TODO: remove
|
|
534
|
+
def refute_selector(*args, &optional_filter_block)
|
|
535
|
+
warn '`refute_selector` was never meant to be in this scope unless ' \
|
|
536
|
+
'using minitest. Either replace with `assert_no_selector` ' \
|
|
537
|
+
"or require 'capybara/minitest'."
|
|
538
|
+
assert_no_selector(*args, &optional_filter_block)
|
|
539
|
+
end
|
|
540
|
+
|
|
541
|
+
# Deprecated
|
|
542
|
+
# TODO: remove
|
|
543
|
+
def refute_matches_elector(*args, &optional_filter_block)
|
|
544
|
+
warn '`refute_matches_selector` was never meant to be in this scope unless ' \
|
|
545
|
+
'using minitest. Either replace with `assert_not_matches_selector` ' \
|
|
546
|
+
"or require 'capybara/minitest'."
|
|
547
|
+
assert_not_matches_selector(*args, &optional_filter_block)
|
|
548
|
+
end
|
|
533
549
|
|
|
534
550
|
##
|
|
535
551
|
#
|
|
@@ -616,6 +632,7 @@ module Capybara
|
|
|
616
632
|
# @option options [Range] :between (nil) Range of times that is expected to contain number of times text occurs
|
|
617
633
|
# @option options [Numeric] :wait (Capybara.default_max_wait_time) Maximum time that Capybara will wait for text to eq/match given string/regexp argument
|
|
618
634
|
# @option options [Boolean] :exact (Capybara.exact_text) Whether text must be an exact match or just substring
|
|
635
|
+
# @option options [Boolean] :nomalize_ws (false) When true replace all whitespace with standard spaces and collapse consecutive whitespace to a single space
|
|
619
636
|
# @overload $0(text, **options)
|
|
620
637
|
# @param [String, Regexp] text The string/regexp to check for. If it's a string, text is expected to include it. If it's a regexp, text is expected to match it.
|
|
621
638
|
# @option options [Integer] :count (nil) Number of times the text is expected to occur
|
|
@@ -624,6 +641,7 @@ module Capybara
|
|
|
624
641
|
# @option options [Range] :between (nil) Range of times that is expected to contain number of times text occurs
|
|
625
642
|
# @option options [Numeric] :wait (Capybara.default_max_wait_time) Maximum time that Capybara will wait for text to eq/match given string/regexp argument
|
|
626
643
|
# @option options [Boolean] :exact (Capybara.exact_text) Whether text must be an exact match or just substring
|
|
644
|
+
# @option options [Boolean] :normalize_ws (false) When true replace all whitespace with standard spaces and collapse consecutive whitespace to a single space
|
|
627
645
|
# @raise [Capybara::ExpectationNotMet] if the assertion hasn't succeeded during wait time
|
|
628
646
|
# @return [true]
|
|
629
647
|
#
|
|
@@ -709,7 +727,7 @@ module Capybara
|
|
|
709
727
|
query_args = _set_query_session_options(*query_args)
|
|
710
728
|
query = Capybara::Queries::MatchQuery.new(*query_args, &optional_filter_block)
|
|
711
729
|
synchronize(query.wait) do
|
|
712
|
-
yield query.resolve_for(query_scope)
|
|
730
|
+
yield query.resolve_for(first(:xpath, './parent::*', minimum: 0) || query_scope)
|
|
713
731
|
end
|
|
714
732
|
true
|
|
715
733
|
end
|
|
@@ -24,6 +24,7 @@ module Capybara
|
|
|
24
24
|
def resolve_for(node)
|
|
25
25
|
@node = node
|
|
26
26
|
@actual_text = text(node, @type)
|
|
27
|
+
@actual_text.gsub!(/[[:space:]]+/, ' ').strip! if options[:normalize_ws]
|
|
27
28
|
@count = @actual_text.scan(@search_regexp).size
|
|
28
29
|
end
|
|
29
30
|
|
|
@@ -83,7 +84,7 @@ module Capybara
|
|
|
83
84
|
end
|
|
84
85
|
|
|
85
86
|
def valid_keys
|
|
86
|
-
COUNT_KEYS + %i[wait exact]
|
|
87
|
+
COUNT_KEYS + %i[wait exact normalize_ws]
|
|
87
88
|
end
|
|
88
89
|
|
|
89
90
|
def check_visible_text?
|
|
@@ -9,6 +9,11 @@ module Capybara
|
|
|
9
9
|
|
|
10
10
|
attr_reader :failure_message, :failure_message_when_negated
|
|
11
11
|
|
|
12
|
+
def initialize(*args, &filter_block)
|
|
13
|
+
@args = args.dup
|
|
14
|
+
@filter_block = filter_block
|
|
15
|
+
end
|
|
16
|
+
|
|
12
17
|
def wrap(actual)
|
|
13
18
|
actual = actual.to_capybara_node if actual.respond_to?(:to_capybara_node)
|
|
14
19
|
@context_el = if actual.respond_to?(:has_selector?)
|
|
@@ -56,11 +61,6 @@ module Capybara
|
|
|
56
61
|
end
|
|
57
62
|
|
|
58
63
|
class HaveSelector < Matcher
|
|
59
|
-
def initialize(*args, &filter_block)
|
|
60
|
-
@args = args
|
|
61
|
-
@filter_block = filter_block
|
|
62
|
-
end
|
|
63
|
-
|
|
64
64
|
def matches?(actual)
|
|
65
65
|
wrap_matches?(actual) { |el| el.assert_selector(*@args, &@filter_block) }
|
|
66
66
|
end
|
|
@@ -79,11 +79,6 @@ module Capybara
|
|
|
79
79
|
end
|
|
80
80
|
|
|
81
81
|
class HaveAllSelectors < Matcher
|
|
82
|
-
def initialize(*args, &filter_block)
|
|
83
|
-
@args = args
|
|
84
|
-
@filter_block = filter_block
|
|
85
|
-
end
|
|
86
|
-
|
|
87
82
|
def matches?(actual)
|
|
88
83
|
wrap_matches?(actual) { |el| el.assert_all_of_selectors(*@args, &@filter_block) }
|
|
89
84
|
end
|
|
@@ -98,11 +93,6 @@ module Capybara
|
|
|
98
93
|
end
|
|
99
94
|
|
|
100
95
|
class HaveNoSelectors < Matcher
|
|
101
|
-
def initialize(*args, &filter_block)
|
|
102
|
-
@args = args
|
|
103
|
-
@filter_block = filter_block
|
|
104
|
-
end
|
|
105
|
-
|
|
106
96
|
def matches?(actual)
|
|
107
97
|
wrap_matches?(actual) { |el| el.assert_none_of_selectors(*@args, &@filter_block) }
|
|
108
98
|
end
|
|
@@ -135,11 +125,6 @@ module Capybara
|
|
|
135
125
|
end
|
|
136
126
|
|
|
137
127
|
class HaveText < Matcher
|
|
138
|
-
def initialize(*args)
|
|
139
|
-
@args = args.dup
|
|
140
|
-
@content = args[0].is_a?(Symbol) ? args[1] : args[0]
|
|
141
|
-
end
|
|
142
|
-
|
|
143
128
|
def matches?(actual)
|
|
144
129
|
wrap_matches?(actual) { |el| el.assert_text(*@args) }
|
|
145
130
|
end
|
|
@@ -149,22 +134,21 @@ module Capybara
|
|
|
149
134
|
end
|
|
150
135
|
|
|
151
136
|
def description
|
|
152
|
-
"text #{format(
|
|
137
|
+
"text #{format(text)}"
|
|
153
138
|
end
|
|
154
139
|
|
|
155
140
|
def format(content)
|
|
156
141
|
content.inspect
|
|
157
142
|
end
|
|
158
|
-
end
|
|
159
143
|
|
|
160
|
-
|
|
161
|
-
def initialize(*args)
|
|
162
|
-
@args = args
|
|
144
|
+
private
|
|
163
145
|
|
|
164
|
-
|
|
165
|
-
@
|
|
146
|
+
def text
|
|
147
|
+
@args[0].is_a?(Symbol) ? @args[1] : @args[0]
|
|
166
148
|
end
|
|
149
|
+
end
|
|
167
150
|
|
|
151
|
+
class HaveTitle < Matcher
|
|
168
152
|
def matches?(actual)
|
|
169
153
|
wrap_matches?(actual) { |el| el.assert_title(*@args) }
|
|
170
154
|
end
|
|
@@ -174,16 +158,17 @@ module Capybara
|
|
|
174
158
|
end
|
|
175
159
|
|
|
176
160
|
def description
|
|
177
|
-
"have title #{
|
|
161
|
+
"have title #{title.inspect}"
|
|
178
162
|
end
|
|
179
|
-
end
|
|
180
163
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
@
|
|
164
|
+
private
|
|
165
|
+
|
|
166
|
+
def title
|
|
167
|
+
@args.first
|
|
185
168
|
end
|
|
169
|
+
end
|
|
186
170
|
|
|
171
|
+
class HaveCurrentPath < Matcher
|
|
187
172
|
def matches?(actual)
|
|
188
173
|
wrap_matches?(actual) { |el| el.assert_current_path(*@args) }
|
|
189
174
|
end
|
|
@@ -193,7 +178,13 @@ module Capybara
|
|
|
193
178
|
end
|
|
194
179
|
|
|
195
180
|
def description
|
|
196
|
-
"have current path #{
|
|
181
|
+
"have current path #{current_path.inspect}"
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
private
|
|
185
|
+
|
|
186
|
+
def current_path
|
|
187
|
+
@args.first
|
|
197
188
|
end
|
|
198
189
|
end
|
|
199
190
|
|
|
@@ -201,6 +192,7 @@ module Capybara
|
|
|
201
192
|
include ::Capybara::RSpecMatchers::Compound if defined?(::Capybara::RSpecMatchers::Compound)
|
|
202
193
|
|
|
203
194
|
def initialize(matcher)
|
|
195
|
+
super()
|
|
204
196
|
@matcher = matcher
|
|
205
197
|
end
|
|
206
198
|
|
|
@@ -226,10 +218,6 @@ module Capybara
|
|
|
226
218
|
end
|
|
227
219
|
|
|
228
220
|
class HaveStyle < Matcher
|
|
229
|
-
def initialize(*args)
|
|
230
|
-
@args = args
|
|
231
|
-
end
|
|
232
|
-
|
|
233
221
|
def matches?(actual)
|
|
234
222
|
wrap_matches?(actual) { |el| el.assert_style(*@args) }
|
|
235
223
|
end
|
|
@@ -99,7 +99,7 @@ class Capybara::Selenium::Driver < Capybara::Driver::Base
|
|
|
99
99
|
end
|
|
100
100
|
|
|
101
101
|
def evaluate_script(script, *args)
|
|
102
|
-
result = execute_script("return #{script
|
|
102
|
+
result = execute_script("return #{script}", *args)
|
|
103
103
|
unwrap_script_result(result)
|
|
104
104
|
end
|
|
105
105
|
|
|
@@ -312,7 +312,7 @@ private
|
|
|
312
312
|
end
|
|
313
313
|
|
|
314
314
|
def ie?
|
|
315
|
-
|
|
315
|
+
%i[internet_explorer ie].include?(browser_name)
|
|
316
316
|
end
|
|
317
317
|
|
|
318
318
|
def browser_name
|
|
@@ -176,7 +176,14 @@ class Capybara::Selenium::Node < Capybara::Driver::Node
|
|
|
176
176
|
|
|
177
177
|
if parent
|
|
178
178
|
siblings = parent.find_xpath(selector)
|
|
179
|
-
selector +=
|
|
179
|
+
selector += case siblings.size
|
|
180
|
+
when 0
|
|
181
|
+
'[ERROR]' # IE doesn't support full XPath (namespace-uri, etc)
|
|
182
|
+
when 1
|
|
183
|
+
'' # index not necessary when only one matching element
|
|
184
|
+
else
|
|
185
|
+
"[#{siblings.index(node) + 1}]"
|
|
186
|
+
end
|
|
180
187
|
end
|
|
181
188
|
result.push selector
|
|
182
189
|
end
|
|
@@ -5,7 +5,7 @@ class Capybara::Selenium::ChromeNode < Capybara::Selenium::Node
|
|
|
5
5
|
super(value)
|
|
6
6
|
rescue ::Selenium::WebDriver::Error::ExpectedError => e
|
|
7
7
|
if e.message =~ /File not found : .+\n.+/m
|
|
8
|
-
raise ArgumentError, "Selenium with remote Chrome doesn't
|
|
8
|
+
raise ArgumentError, "Selenium < 3.14 with remote Chrome doesn't support multiple file upload"
|
|
9
9
|
end
|
|
10
10
|
raise
|
|
11
11
|
end
|
|
@@ -26,8 +26,11 @@ class Capybara::Selenium::MarionetteNode < Capybara::Selenium::Node
|
|
|
26
26
|
end
|
|
27
27
|
|
|
28
28
|
def set_file(value) # rubocop:disable Naming/AccessorMethodName
|
|
29
|
+
native.clear # By default files are appended so we have to clear here
|
|
30
|
+
return super if driver.browser.capabilities[:browser_version].to_f >= 62.0
|
|
31
|
+
|
|
32
|
+
# Workaround lack of support for multiple upload by uploading one at a time
|
|
29
33
|
path_names = value.to_s.empty? ? [] : value
|
|
30
|
-
native.clear
|
|
31
34
|
Array(path_names).each do |path|
|
|
32
35
|
unless driver.browser.respond_to?(:upload)
|
|
33
36
|
if (fd = bridge.file_detector)
|
|
@@ -47,7 +50,7 @@ private
|
|
|
47
50
|
|
|
48
51
|
def upload(local_file)
|
|
49
52
|
unless File.file?(local_file)
|
|
50
|
-
raise
|
|
53
|
+
raise ArgumentError, "You may only upload files: #{local_file.inspect}"
|
|
51
54
|
end
|
|
52
55
|
|
|
53
56
|
result = bridge.http.call(:post, "session/#{bridge.session_id}/file", file: Selenium::WebDriver::Zipper.zip_file(local_file))
|
data/lib/capybara/session.rb
CHANGED
|
@@ -580,7 +580,7 @@ module Capybara
|
|
|
580
580
|
#
|
|
581
581
|
def evaluate_script(script, *args)
|
|
582
582
|
@touched = true
|
|
583
|
-
result = driver.evaluate_script(script, *driver_args(args))
|
|
583
|
+
result = driver.evaluate_script(script.strip, *driver_args(args))
|
|
584
584
|
element_script_result(result)
|
|
585
585
|
end
|
|
586
586
|
|