capybara 2.11.0 → 2.12.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 +30 -4
- data/README.md +4 -0
- data/lib/capybara.rb +4 -2
- data/lib/capybara/driver/base.rb +2 -2
- data/lib/capybara/helpers.rb +8 -2
- data/lib/capybara/node/actions.rb +52 -1
- data/lib/capybara/node/document_matchers.rb +1 -0
- data/lib/capybara/node/finders.rb +2 -1
- data/lib/capybara/node/matchers.rb +54 -0
- data/lib/capybara/node/simple.rb +1 -1
- data/lib/capybara/queries/current_path_query.rb +4 -2
- data/lib/capybara/queries/selector_query.rb +23 -3
- data/lib/capybara/queries/text_query.rb +15 -7
- data/lib/capybara/queries/title_query.rb +2 -2
- data/lib/capybara/rack_test/form.rb +1 -1
- data/lib/capybara/rack_test/node.rb +4 -4
- data/lib/capybara/result.rb +2 -2
- data/lib/capybara/selector.rb +16 -4
- data/lib/capybara/selenium/driver.rb +27 -22
- data/lib/capybara/selenium/node.rb +10 -1
- data/lib/capybara/session.rb +91 -30
- data/lib/capybara/spec/session/accept_prompt_spec.rb +3 -0
- data/lib/capybara/spec/session/assert_all_of_selectors_spec.rb +94 -0
- data/lib/capybara/spec/session/assert_current_path.rb +12 -0
- data/lib/capybara/spec/session/attach_file_spec.rb +30 -0
- data/lib/capybara/spec/session/click_link_spec.rb +12 -1
- data/lib/capybara/spec/session/current_url_spec.rb +8 -0
- data/lib/capybara/spec/session/evaluate_script_spec.rb +14 -0
- data/lib/capybara/spec/session/execute_script_spec.rb +13 -0
- data/lib/capybara/spec/session/fill_in_spec.rb +6 -0
- data/lib/capybara/spec/session/find_field_spec.rb +2 -0
- data/lib/capybara/spec/session/find_spec.rb +3 -3
- data/lib/capybara/spec/session/frame/switch_to_frame_spec.rb +103 -0
- data/lib/capybara/spec/session/{within_frame_spec.rb → frame/within_frame_spec.rb} +12 -0
- data/lib/capybara/spec/session/has_current_path_spec.rb +28 -0
- data/lib/capybara/spec/session/has_selector_spec.rb +21 -0
- data/lib/capybara/spec/session/has_text_spec.rb +13 -1
- data/lib/capybara/spec/session/has_title_spec.rb +15 -0
- data/lib/capybara/spec/session/node_spec.rb +34 -1
- data/lib/capybara/spec/session/within_spec.rb +7 -0
- data/lib/capybara/spec/spec_helper.rb +4 -0
- data/lib/capybara/spec/views/form.erb +48 -0
- data/lib/capybara/spec/views/with_js.erb +5 -0
- data/lib/capybara/spec/views/within_frames.erb +1 -1
- data/lib/capybara/version.rb +1 -1
- data/lib/capybara/window.rb +1 -1
- data/spec/capybara_spec.rb +2 -2
- data/spec/rack_test_spec.rb +10 -0
- data/spec/result_spec.rb +3 -3
- data/spec/rspec/shared_spec_matchers.rb +1 -1
- data/spec/session_spec.rb +10 -0
- data/spec/shared_selenium_session.rb +2 -1
- data/spec/spec_helper.rb +2 -0
- metadata +7 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bc177e8165f5b72a1dc1c1303b726701bc24254c
|
4
|
+
data.tar.gz: dab6b087b3ef03904d496bef6d3f66e2736b5bbd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f21cbebab1e87a9b9a411caf05acab9d912257604d6004db90af7439a692b862966e11291134424105698477b772cca46774aa95aad6ab78bdecd827ab862e83
|
7
|
+
data.tar.gz: c643a679ac6ac6cf17f03d63f74a97a20919980eead96c30b8b8c571120b19e0f94d2b7be978878580c6365483cc41476a83710b96200559e6be124dce620af0
|
data/History.md
CHANGED
@@ -1,4 +1,30 @@
|
|
1
|
-
#2.
|
1
|
+
#Version 2.12.0
|
2
|
+
Release date: 2017-01-22
|
3
|
+
|
4
|
+
### Added
|
5
|
+
|
6
|
+
* Session#switch_to_frame for manually handling frame switching - Issue #1365 [Thomas Walpole]
|
7
|
+
* Session#within_frame now accepts a selector type (defaults to :frame) and locator [Thomas Walpole]
|
8
|
+
* Session#execute_script and Session#evaluate_script now accept optional arguments that will be passed to the JS function. This may not be supported
|
9
|
+
by all drivers, and the types of arguments that may be passed is limited. If drivers opt to support this feature they should support passing page elements. [Thomas Walpole]
|
10
|
+
* :exact option for text and title matchers - Issue #1256 [Thomas Walpole]
|
11
|
+
* :exact_text option for selector finders/minders - Issue #1256 [Thomas Walpole]
|
12
|
+
* Capybara.exact_text setting that affects the text matchers and :text options passed to selector finders/matchers. Issue #1256 [Thomas Walpole]
|
13
|
+
* :make_visible option for #attach_file that allows for convenient changing of the CSS style of a file input element before attaching the file to it. Requires driver
|
14
|
+
support for passing page elements to Session#execute_script [Thomas Walpole]
|
15
|
+
* assert_all_selectors/assert_none_of_selectors assertions added
|
16
|
+
* :link selector (used by find_link/click_link) now supports finding hyperlink placeholders (no href attribute) when href: nil option is specified [Thomas Walpole]
|
17
|
+
* `within_element` as an alias of `within` due to RSpec collision
|
18
|
+
|
19
|
+
### Fixed
|
20
|
+
* Fields inside a disabled fieldset are now correctly considered disabled - Issue #1816 [Thomas Walpole]
|
21
|
+
* Lazy Capybara::Results evaluation enabled for JRuby 9.1.6.0+
|
22
|
+
* A driver returning nil for #current_url won't raise an exception when calling #current_path [Dylan Reichstadt]
|
23
|
+
* Support Ruby 2.4.0 unified Integer [Koichi ITO]
|
24
|
+
* RackTest driver no longer modifies the text content of textarea elements in order to behave more like a real browser [Thomas Walpole]
|
25
|
+
* TextQuery (assert_text/have_text/etc) now ignores errors when trying to generate more helpful errors messages so the original error isn't hidden [Thomas Walpole]
|
26
|
+
|
27
|
+
#Version 2.11.0
|
2
28
|
Release date: 2016-12-05
|
3
29
|
|
4
30
|
### Added
|
@@ -13,14 +39,14 @@ Release date: 2016-12-05
|
|
13
39
|
* Selenium driver with Chrome should support multiple file upload [Thomas Walpole]
|
14
40
|
* Fix visible: :hidden with :text option behavior [Thomas Walpole]
|
15
41
|
|
16
|
-
#2.10.2
|
42
|
+
#Version 2.10.2
|
17
43
|
Release date: 2016-11-30
|
18
44
|
|
19
45
|
### Fixed
|
20
46
|
* App exceptions with multiple parameter initializers now re-raised correctly - Issue #1785 [Michael Lutsiuk]
|
21
47
|
* Use Addressable::URI when parsing current_path since it's more lenient of technically invalid URLs - Issue #1801 [Marcos Duque, Thomas Walpole]
|
22
48
|
|
23
|
-
#2.10.1
|
49
|
+
#Version 2.10.1
|
24
50
|
Release date: 2016-10-08
|
25
51
|
|
26
52
|
### Fixed
|
@@ -28,7 +54,7 @@ Release date: 2016-10-08
|
|
28
54
|
* Capybara::Result optimization disabled in JRuby due to issue with lazy enumerator evaluation [Thomas Walpole]
|
29
55
|
See: https://github.com/jruby/jruby/issues/4212
|
30
56
|
|
31
|
-
#2.10.0
|
57
|
+
#Version 2.10.0
|
32
58
|
Release date: 2016-10-05
|
33
59
|
|
34
60
|
### Added
|
data/README.md
CHANGED
@@ -672,6 +672,10 @@ Or have it save and automatically open:
|
|
672
672
|
save_and_open_screenshot
|
673
673
|
```
|
674
674
|
|
675
|
+
Screenshots are saved to `Capybara.save_path`, relative to the app directory.
|
676
|
+
If you have required `capybara/rails`, `Capybara.save_path` will default to
|
677
|
+
`tmp/capybara`.
|
678
|
+
|
675
679
|
## <a name="matching"></a>Matching
|
676
680
|
|
677
681
|
It is possible to customize how Capybara finds elements. At your disposal
|
data/lib/capybara.rb
CHANGED
@@ -29,6 +29,7 @@ module Capybara
|
|
29
29
|
attr_accessor :raise_server_errors, :server_errors
|
30
30
|
attr_writer :default_driver, :current_driver, :javascript_driver, :session_name, :server_host
|
31
31
|
attr_reader :save_and_open_page_path
|
32
|
+
attr_accessor :exact_text
|
32
33
|
attr_accessor :app
|
33
34
|
|
34
35
|
##
|
@@ -244,7 +245,7 @@ module Capybara
|
|
244
245
|
# manually.
|
245
246
|
#
|
246
247
|
# @param [Rack Application] app The rack application to run
|
247
|
-
# @param [
|
248
|
+
# @param [Integer] port The port to run the application on
|
248
249
|
#
|
249
250
|
def run_default_server(app, port)
|
250
251
|
servers[:webrick].call(app, port, server_host)
|
@@ -368,7 +369,7 @@ module Capybara
|
|
368
369
|
def HTML(html)
|
369
370
|
Nokogiri::HTML(html).tap do |document|
|
370
371
|
document.xpath('//textarea').each do |textarea|
|
371
|
-
textarea
|
372
|
+
textarea['_capybara_raw_value'] = textarea.content.sub(/\A\n/,'')
|
372
373
|
end
|
373
374
|
end
|
374
375
|
end
|
@@ -495,6 +496,7 @@ Capybara.configure do |config|
|
|
495
496
|
config.automatic_reload = true
|
496
497
|
config.match = :smart
|
497
498
|
config.exact = false
|
499
|
+
config.exact_text = false
|
498
500
|
config.raise_server_errors = true
|
499
501
|
config.server_errors = [StandardError]
|
500
502
|
config.visible_text_only = false
|
data/lib/capybara/driver/base.rb
CHANGED
@@ -28,11 +28,11 @@ class Capybara::Driver::Base
|
|
28
28
|
raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#go_forward'
|
29
29
|
end
|
30
30
|
|
31
|
-
def execute_script(script)
|
31
|
+
def execute_script(script, *args)
|
32
32
|
raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#execute_script'
|
33
33
|
end
|
34
34
|
|
35
|
-
def evaluate_script(script)
|
35
|
+
def evaluate_script(script, *args)
|
36
36
|
raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#evaluate_script'
|
37
37
|
end
|
38
38
|
|
data/lib/capybara/helpers.rb
CHANGED
@@ -28,8 +28,14 @@ module Capybara
|
|
28
28
|
# @param [String] text Text to escape
|
29
29
|
# @return [String] Escaped text
|
30
30
|
#
|
31
|
-
def to_regexp(text,
|
32
|
-
text.is_a?(Regexp)
|
31
|
+
def to_regexp(text, regexp_options=nil, exact=false)
|
32
|
+
if text.is_a?(Regexp)
|
33
|
+
text
|
34
|
+
else
|
35
|
+
escaped = Regexp.escape(normalize_whitespace(text))
|
36
|
+
escaped = "\\A#{escaped}\\z" if exact
|
37
|
+
Regexp.new(escaped, regexp_options)
|
38
|
+
end
|
33
39
|
end
|
34
40
|
|
35
41
|
##
|
@@ -75,6 +75,7 @@ module Capybara
|
|
75
75
|
# @macro waiting_behavior
|
76
76
|
# @option options [String] :with The value to fill in - required
|
77
77
|
# @option options [Hash] :fill_options Driver specific options regarding how to fill fields
|
78
|
+
# @option options [String] :currently_with The current value property of the field to fill in
|
78
79
|
# @option options [Boolean] :multiple Match fields that can have multiple values?
|
79
80
|
# @option options [String] :id Match fields that match the id attribute
|
80
81
|
# @option options [String] :name Match fields that match the name attribute
|
@@ -87,6 +88,7 @@ module Capybara
|
|
87
88
|
raise "Must pass a hash containing 'with'" if not options.is_a?(Hash) or not options.has_key?(:with)
|
88
89
|
with = options.delete(:with)
|
89
90
|
fill_options = options.delete(:fill_options)
|
91
|
+
options[:with] = options.delete(:currently_with) if options.has_key?(:currently_with)
|
90
92
|
find(:fillable_field, locator, options).set(with, fill_options)
|
91
93
|
end
|
92
94
|
|
@@ -228,6 +230,7 @@ module Capybara
|
|
228
230
|
# @option options [String] id Match fields that match the id attribute
|
229
231
|
# @option options [String] name Match fields that match the name attribute
|
230
232
|
# @option options [String, Array<String>] :class Match links that match the class(es) provided
|
233
|
+
# @option options [true, Hash] make_visible A Hash of CSS styles to change before attempting to attach the file, if `true` { opacity: 1, display: 'block', visibility: 'visible' } is used (may not be supported by all drivers)
|
231
234
|
#
|
232
235
|
# @return [Capybara::Node::Element] The file field element
|
233
236
|
def attach_file(locator, path, options={})
|
@@ -235,10 +238,58 @@ module Capybara
|
|
235
238
|
Array(path).each do |p|
|
236
239
|
raise Capybara::FileNotFound, "cannot attach file, #{p} does not exist" unless File.exist?(p.to_s)
|
237
240
|
end
|
238
|
-
|
241
|
+
# Allow user to update the CSS style of the file input since they are so often hidden on a page
|
242
|
+
if style = options.delete(:make_visible)
|
243
|
+
style = { opacity: 1, display: 'block', visibility: 'visible' } if style == true
|
244
|
+
ff = find(:file_field, locator, options.merge({visible: :all}))
|
245
|
+
_update_style(ff, style)
|
246
|
+
if ff.visible?
|
247
|
+
begin
|
248
|
+
ff.set(path)
|
249
|
+
ensure
|
250
|
+
_reset_style(ff)
|
251
|
+
end
|
252
|
+
else
|
253
|
+
raise ExpectationNotMet, "The style changes in :make_visible did not make the file input visible"
|
254
|
+
end
|
255
|
+
else
|
256
|
+
find(:file_field, locator, options).set(path)
|
257
|
+
end
|
239
258
|
end
|
240
259
|
|
241
260
|
private
|
261
|
+
def _update_style(element, style)
|
262
|
+
script = <<-JS
|
263
|
+
var el = arguments[0];
|
264
|
+
el.capybara_style_cache = el.style.cssText;
|
265
|
+
var css = arguments[1];
|
266
|
+
for (var prop in css){
|
267
|
+
if (css.hasOwnProperty(prop)) {
|
268
|
+
el.style[prop] = css[prop]
|
269
|
+
}
|
270
|
+
}
|
271
|
+
JS
|
272
|
+
begin
|
273
|
+
session.execute_script(script, element, style)
|
274
|
+
rescue Capybara::NotSupportedByDriverError
|
275
|
+
warn "The :make_visible option is not supported by the current driver - ignoring"
|
276
|
+
end
|
277
|
+
end
|
278
|
+
|
279
|
+
def _reset_style(element)
|
280
|
+
script = <<-JS
|
281
|
+
var el = arguments[0];
|
282
|
+
if (el.hasOwnProperty('capybara_style_cache')) {
|
283
|
+
el.style.cssText = el.capybara_style_cache;
|
284
|
+
delete el.capybara_style_cache;
|
285
|
+
}
|
286
|
+
JS
|
287
|
+
begin
|
288
|
+
session.execute_script(script, element)
|
289
|
+
rescue
|
290
|
+
end
|
291
|
+
end
|
292
|
+
|
242
293
|
|
243
294
|
def _check_with_label(selector, checked, locator, options)
|
244
295
|
locator, options = nil, locator if locator.is_a? Hash
|
@@ -11,6 +11,7 @@ module Capybara
|
|
11
11
|
# @overload $0(regexp, options = {})
|
12
12
|
# @param regexp [Regexp] The regexp that title should match to
|
13
13
|
# @option options [Numeric] :wait (Capybara.default_max_wait_time) Maximum time that Capybara will wait for title to eq/match given string/regexp argument
|
14
|
+
# @option options [Boolean] :exact (false) When passed a string should the match be exact or just substring
|
14
15
|
# @raise [Capybara::ExpectationNotMet] if the assertion hasn't succeeded during wait time
|
15
16
|
# @return [true]
|
16
17
|
#
|
@@ -89,7 +89,7 @@ module Capybara
|
|
89
89
|
#
|
90
90
|
# @macro waiting_behavior
|
91
91
|
#
|
92
|
-
# @option options [String,Regexp] href Value to match against the links href
|
92
|
+
# @option options [String,Regexp,nil] href Value to match against the links href, if nil finds link placeholders (<a> elements with no href attribute)
|
93
93
|
# @option options [String] id Match links with the id provided
|
94
94
|
# @option options [String] title Match links with the title provided
|
95
95
|
# @option options [String] alt Match links with a contained img element whose alt matches
|
@@ -188,6 +188,7 @@ module Capybara
|
|
188
188
|
# @param [Symbol] kind Optional selector type (:css, :xpath, :field, etc.) - Defaults to Capybara.default_selector
|
189
189
|
# @param [String] locator The selector
|
190
190
|
# @option options [String, Regexp] text Only find elements which contain this text or match this regexp
|
191
|
+
# @option options [String, Boolean] exact_text (Capybara.exact_text) When String the string the elements contained text must match exactly, when Boolean controls whether the :text option must match exactly
|
191
192
|
# @option options [Boolean, Symbol] visible Only find elements with the specified visibility:
|
192
193
|
# * true - only finds visible elements.
|
193
194
|
# * false - finds invisible _and_ visible elements.
|
@@ -97,6 +97,58 @@ module Capybara
|
|
97
97
|
end
|
98
98
|
end
|
99
99
|
|
100
|
+
# Asserts that all of the provided selectors are present on the given page
|
101
|
+
# or descendants of the current node. If options are provided, the assertion
|
102
|
+
# will check that each locator is present with those options as well (other than :wait).
|
103
|
+
#
|
104
|
+
# page.assert_all_of_selectors(:custom, 'Tom', 'Joe', visible: all)
|
105
|
+
# page.assert_all_of_selectors(:css, '#my_div', 'a.not_clicked')
|
106
|
+
#
|
107
|
+
# It accepts all options that {Capybara::Node::Finders#all} accepts,
|
108
|
+
# such as :text and :visible.
|
109
|
+
#
|
110
|
+
# The :wait option applies to all of the selectors as a group, so all of the locators must be present
|
111
|
+
# within :wait (Defaults to Capybara.default_max_wait_time) seconds.
|
112
|
+
#
|
113
|
+
# @overload assert_all_of_selectors([kind = Capybara.default_selector], *locators, options = {})
|
114
|
+
#
|
115
|
+
def assert_all_of_selectors(*args, &optional_filter_block)
|
116
|
+
options = if args.last.is_a?(Hash) then args.pop.dup else {} end
|
117
|
+
selector = if args.first.is_a?(Symbol) then args.shift else Capybara.default_selector end
|
118
|
+
wait = options.fetch(:wait, Capybara.default_max_wait_time)
|
119
|
+
synchronize(wait) do
|
120
|
+
args.each do |locator|
|
121
|
+
assert_selector(selector, locator, options, &optional_filter_block)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
# Asserts that none of the provided selectors are present on the given page
|
127
|
+
# or descendants of the current node. If options are provided, the assertion
|
128
|
+
# will check that each locator is present with those options as well (other than :wait).
|
129
|
+
#
|
130
|
+
# page.assert_none_of_selectors(:custom, 'Tom', 'Joe', visible: all)
|
131
|
+
# page.assert_none_of_selectors(:css, '#my_div', 'a.not_clicked')
|
132
|
+
#
|
133
|
+
# It accepts all options that {Capybara::Node::Finders#all} accepts,
|
134
|
+
# such as :text and :visible.
|
135
|
+
#
|
136
|
+
# The :wait option applies to all of the selectors as a group, so none of the locators must be present
|
137
|
+
# within :wait (Defaults to Capybara.default_max_wait_time) seconds.
|
138
|
+
#
|
139
|
+
# @overload assert_none_of_selectors([kind = Capybara.default_selector], *locators, options = {})
|
140
|
+
#
|
141
|
+
def assert_none_of_selectors(*args, &optional_filter_block)
|
142
|
+
options = if args.last.is_a?(Hash) then args.pop.dup else {} end
|
143
|
+
selector = if args.first.is_a?(Symbol) then args.shift else Capybara.default_selector end
|
144
|
+
wait = options.fetch(:wait, Capybara.default_max_wait_time)
|
145
|
+
synchronize(wait) do
|
146
|
+
args.each do |locator|
|
147
|
+
assert_no_selector(selector, locator, options, &optional_filter_block)
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
100
152
|
##
|
101
153
|
#
|
102
154
|
# Asserts that a given selector is not on the page or a descendant of the current node.
|
@@ -546,6 +598,7 @@ module Capybara
|
|
546
598
|
# @option options [Integer] :maximum (nil) Maximum number of times the text is expected to occur
|
547
599
|
# @option options [Range] :between (nil) Range of times that is expected to contain number of times text occurs
|
548
600
|
# @option options [Numeric] :wait (Capybara.default_max_wait_time) Maximum time that Capybara will wait for text to eq/match given string/regexp argument
|
601
|
+
# @option options [Boolean] :exact (Capybara.exact_text) Whether text must be an exact match or just substring
|
549
602
|
# @overload $0(text, options = {})
|
550
603
|
# @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.
|
551
604
|
# @option options [Integer] :count (nil) Number of times the text is expected to occur
|
@@ -553,6 +606,7 @@ module Capybara
|
|
553
606
|
# @option options [Integer] :maximum (nil) Maximum number of times the text is expected to occur
|
554
607
|
# @option options [Range] :between (nil) Range of times that is expected to contain number of times text occurs
|
555
608
|
# @option options [Numeric] :wait (Capybara.default_max_wait_time) Maximum time that Capybara will wait for text to eq/match given string/regexp argument
|
609
|
+
# @option options [Boolean] :exact (Capybara.exact_text) Whether text must be an exact match or just substring
|
556
610
|
# @raise [Capybara::ExpectationNotMet] if the assertion hasn't succeeded during wait time
|
557
611
|
# @return [true]
|
558
612
|
#
|
data/lib/capybara/node/simple.rb
CHANGED
@@ -76,7 +76,7 @@ module Capybara
|
|
76
76
|
#
|
77
77
|
def value
|
78
78
|
if tag_name == 'textarea'
|
79
|
-
native
|
79
|
+
native['_capybara_raw_value']
|
80
80
|
elsif tag_name == 'select'
|
81
81
|
if native['multiple'] == 'multiple'
|
82
82
|
native.xpath(".//option[@selected='selected']").map { |option| option[:value] || option.content }
|
@@ -17,10 +17,12 @@ module Capybara
|
|
17
17
|
@actual_path = if options[:url]
|
18
18
|
session.current_url
|
19
19
|
else
|
20
|
+
uri = ::Addressable::URI.parse(session.current_url)
|
21
|
+
|
20
22
|
if options[:only_path]
|
21
|
-
|
23
|
+
uri.path unless uri.nil? # Ensure the parsed url isn't nil.
|
22
24
|
else
|
23
|
-
|
25
|
+
uri.request_uri unless uri.nil? # Ensure the parsed url isn't nil.
|
24
26
|
end
|
25
27
|
end
|
26
28
|
|
@@ -4,7 +4,7 @@ module Capybara
|
|
4
4
|
class SelectorQuery < Queries::BaseQuery
|
5
5
|
attr_accessor :selector, :locator, :options, :expression, :find, :negative
|
6
6
|
|
7
|
-
VALID_KEYS = COUNT_KEYS + [:text, :id, :class, :visible, :exact, :match, :wait, :filter_set]
|
7
|
+
VALID_KEYS = COUNT_KEYS + [:text, :id, :class, :visible, :exact, :exact_text, :match, :wait, :filter_set]
|
8
8
|
VALID_MATCH = [:first, :smart, :prefer_exact, :one]
|
9
9
|
|
10
10
|
def initialize(*args, &filter_block)
|
@@ -42,7 +42,8 @@ module Capybara
|
|
42
42
|
|
43
43
|
def description
|
44
44
|
@description = String.new("#{label} #{locator.inspect}")
|
45
|
-
@description << " with text #{options[:text].inspect}" if options[:text]
|
45
|
+
@description << " with#{" exact" if exact_text === true} text #{options[:text].inspect}" if options[:text]
|
46
|
+
@description << " with exact text #{options[:exact_text]}" if options[:exact_text].is_a?(String)
|
46
47
|
@description << " with id #{options[:id]}" if options[:id]
|
47
48
|
@description << " with classes #{Array(options[:class]).join(',')}]" if options[:class]
|
48
49
|
@description << selector.description(options)
|
@@ -52,7 +53,22 @@ module Capybara
|
|
52
53
|
|
53
54
|
def matches_filters?(node)
|
54
55
|
if options[:text]
|
55
|
-
regexp = options[:text].is_a?(Regexp)
|
56
|
+
regexp = if options[:text].is_a?(Regexp)
|
57
|
+
options[:text]
|
58
|
+
else
|
59
|
+
if exact_text === true
|
60
|
+
"\\A#{Regexp.escape(options[:text].to_s)}\\z"
|
61
|
+
else
|
62
|
+
Regexp.escape(options[:text].to_s)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
text_visible = visible
|
66
|
+
text_visible = :all if text_visible == :hidden
|
67
|
+
return false if not node.text(text_visible).match(regexp)
|
68
|
+
end
|
69
|
+
|
70
|
+
if exact_text.is_a?(String)
|
71
|
+
regexp = "\\A#{Regexp.escape(options[:exact_text])}\\z"
|
56
72
|
text_visible = visible
|
57
73
|
text_visible = :all if text_visible == :hidden
|
58
74
|
return false if not node.text(text_visible).match(regexp)
|
@@ -187,6 +203,10 @@ module Capybara
|
|
187
203
|
warn "The :exact option only has an effect on queries using the XPath#is method. Using it with the query \"#{expression.to_s}\" has no effect."
|
188
204
|
end
|
189
205
|
end
|
206
|
+
|
207
|
+
def exact_text
|
208
|
+
exact_text = options.fetch(:exact_text, Capybara.exact_text)
|
209
|
+
end
|
190
210
|
end
|
191
211
|
end
|
192
212
|
end
|
@@ -10,8 +10,8 @@ module Capybara
|
|
10
10
|
unless @expected_text.is_a?(Regexp)
|
11
11
|
@expected_text = Capybara::Helpers.normalize_whitespace(@expected_text)
|
12
12
|
end
|
13
|
-
@search_regexp = Capybara::Helpers.to_regexp(@expected_text)
|
14
13
|
@options ||= {}
|
14
|
+
@search_regexp = Capybara::Helpers.to_regexp(@expected_text, nil, exact?)
|
15
15
|
assert_valid_keys
|
16
16
|
end
|
17
17
|
|
@@ -33,12 +33,16 @@ module Capybara
|
|
33
33
|
if @expected_text.is_a?(Regexp)
|
34
34
|
"text matching #{@expected_text.inspect}"
|
35
35
|
else
|
36
|
-
"text #{@expected_text.inspect}"
|
36
|
+
"#{"exact " if exact?}text #{@expected_text.inspect}"
|
37
37
|
end
|
38
38
|
end
|
39
39
|
|
40
40
|
private
|
41
41
|
|
42
|
+
def exact?
|
43
|
+
options.fetch(:exact, Capybara.exact_text)
|
44
|
+
end
|
45
|
+
|
42
46
|
def build_message(report_on_invisible)
|
43
47
|
message = String.new()
|
44
48
|
unless (COUNT_KEYS & @options.keys).empty?
|
@@ -57,10 +61,14 @@ module Capybara
|
|
57
61
|
end
|
58
62
|
|
59
63
|
if @node and check_visible_text? and report_on_invisible
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
+
begin
|
65
|
+
invisible_text = text(@node, :all)
|
66
|
+
invisible_count = invisible_text.scan(@search_regexp).size
|
67
|
+
if invisible_count != @count
|
68
|
+
details_message << ". it was found #{invisible_count} #{Capybara::Helpers.declension("time", "times", invisible_count)} including non-visible text"
|
69
|
+
end
|
70
|
+
rescue
|
71
|
+
# An error getting the non-visible text (if element goes out of scope) should not affect the response
|
64
72
|
end
|
65
73
|
end
|
66
74
|
|
@@ -70,7 +78,7 @@ module Capybara
|
|
70
78
|
end
|
71
79
|
|
72
80
|
def valid_keys
|
73
|
-
COUNT_KEYS + [:wait]
|
81
|
+
COUNT_KEYS + [:wait, :exact]
|
74
82
|
end
|
75
83
|
|
76
84
|
def check_visible_text?
|