capybara 3.30.0 → 3.31.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 +21 -0
- data/README.md +1 -1
- data/lib/capybara/dsl.rb +10 -2
- data/lib/capybara/minitest.rb +18 -4
- data/lib/capybara/node/element.rb +11 -8
- data/lib/capybara/node/finders.rb +5 -1
- data/lib/capybara/node/matchers.rb +24 -15
- data/lib/capybara/node/simple.rb +1 -1
- data/lib/capybara/queries/base_query.rb +2 -1
- data/lib/capybara/rack_test/node.rb +34 -9
- data/lib/capybara/result.rb +24 -4
- data/lib/capybara/rspec/matchers.rb +27 -27
- data/lib/capybara/rspec/matchers/base.rb +12 -6
- data/lib/capybara/rspec/matchers/count_sugar.rb +2 -1
- data/lib/capybara/rspec/matchers/have_ancestor.rb +4 -3
- data/lib/capybara/rspec/matchers/have_current_path.rb +2 -2
- data/lib/capybara/rspec/matchers/have_selector.rb +15 -7
- data/lib/capybara/rspec/matchers/have_sibling.rb +3 -3
- data/lib/capybara/rspec/matchers/have_text.rb +2 -2
- data/lib/capybara/rspec/matchers/have_title.rb +2 -2
- data/lib/capybara/rspec/matchers/match_selector.rb +3 -3
- data/lib/capybara/rspec/matchers/match_style.rb +2 -2
- data/lib/capybara/rspec/matchers/spatial_sugar.rb +2 -1
- data/lib/capybara/selector.rb +2 -0
- data/lib/capybara/selector/definition/label.rb +1 -1
- data/lib/capybara/selector/definition/select.rb +31 -12
- data/lib/capybara/selenium/driver_specializations/chrome_driver.rb +1 -1
- data/lib/capybara/selenium/extensions/html5_drag.rb +24 -8
- data/lib/capybara/selenium/node.rb +23 -6
- data/lib/capybara/selenium/nodes/chrome_node.rb +4 -2
- data/lib/capybara/selenium/nodes/edge_node.rb +1 -1
- data/lib/capybara/selenium/nodes/firefox_node.rb +1 -1
- data/lib/capybara/session.rb +30 -15
- data/lib/capybara/spec/public/test.js +40 -6
- data/lib/capybara/spec/session/all_spec.rb +45 -5
- data/lib/capybara/spec/session/assert_text_spec.rb +5 -5
- data/lib/capybara/spec/session/fill_in_spec.rb +20 -0
- data/lib/capybara/spec/session/has_css_spec.rb +3 -3
- data/lib/capybara/spec/session/has_select_spec.rb +28 -0
- data/lib/capybara/spec/session/has_text_spec.rb +5 -1
- data/lib/capybara/spec/session/node_spec.rb +92 -3
- data/lib/capybara/spec/views/form.erb +6 -1
- data/lib/capybara/version.rb +1 -1
- data/spec/rack_test_spec.rb +0 -1
- data/spec/result_spec.rb +4 -0
- data/spec/selenium_spec_chrome.rb +2 -1
- 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: dd31d35629d475d7fdaba1d6e415599d995a08f27b28fa619a3a4449b61b91d8
|
4
|
+
data.tar.gz: 27c812629e2d99e8f4c62fa7961df9b499c5346b1c61092faf487f592356033d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 946e3f2de0137ddaa6e3a2febba2c87244997737c54a10024133de110ca41b8aeddcb66e0437bef5d826e9fe21d4c42701674c3864bd578d24c30c7b1f90e2a9
|
7
|
+
data.tar.gz: f9409de3e2e0ea44e0bb6b6f77cce7e0e8f5a4d95c43fb62af2eb63d11e755d6a8c00b9b9b4d2bbe2729538d0d1038e92468e0a7994d1578b50e05b5227b87f4
|
data/History.md
CHANGED
@@ -1,3 +1,24 @@
|
|
1
|
+
# Version 3.31.0
|
2
|
+
Release date: 2020-01-26
|
3
|
+
|
4
|
+
### Added
|
5
|
+
|
6
|
+
* Support setting range inputs with the selenium driver [Andrew White]
|
7
|
+
* Support setting range inputs with the rack driver
|
8
|
+
* Support drop modifier keys in drag & drop [Elliot Crosby-McCullough]
|
9
|
+
* `enabled_options` and `disabled options` filters for select selector
|
10
|
+
* Support beginless ranges
|
11
|
+
* Optionally allow `all` results to be reloaded when stable - Beta feature - may be removed in
|
12
|
+
future version if problems occur
|
13
|
+
|
14
|
+
### Fixed
|
15
|
+
|
16
|
+
* Fix Ruby 2.7 deprecation notices around keyword arguments. I have tried to do this without
|
17
|
+
any breaking changes, but due to the nature of the 2.7 changes and some selector types accepting
|
18
|
+
Hashes as locators there are a lot of edge cases. If you find any broken cases please report
|
19
|
+
them and I'll see if they're fixable.
|
20
|
+
* Clicking on details/summary element behavior in rack_test driver_
|
21
|
+
|
1
22
|
# Version 3.30.0
|
2
23
|
Release date: 2019-12-24
|
3
24
|
|
data/README.md
CHANGED
@@ -7,7 +7,7 @@
|
|
7
7
|
[](https://gitter.im/jnicklas/capybara?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
8
8
|
[](https://dependabot.com/compatibility-score.html?dependency-name=capybara&package-manager=bundler&version-scheme=semver)
|
9
9
|
|
10
|
-
**Note** You are viewing the README for the 3.
|
10
|
+
**Note** You are viewing the README for the 3.31.x stable branch of Capybara.
|
11
11
|
|
12
12
|
Capybara helps you test web applications by simulating how a real user would
|
13
13
|
interact with your app. It is agnostic about the driver running your tests and
|
data/lib/capybara/dsl.rb
CHANGED
@@ -47,8 +47,16 @@ module Capybara
|
|
47
47
|
end
|
48
48
|
|
49
49
|
Session::DSL_METHODS.each do |method|
|
50
|
-
|
51
|
-
|
50
|
+
if RUBY_VERSION >= '2.7'
|
51
|
+
class_eval <<~METHOD, __FILE__, __LINE__ + 1
|
52
|
+
def #{method}(...)
|
53
|
+
page.method("#{method}").call(...)
|
54
|
+
end
|
55
|
+
METHOD
|
56
|
+
else
|
57
|
+
define_method method do |*args, &block|
|
58
|
+
page.send method, *args, &block
|
59
|
+
end
|
52
60
|
end
|
53
61
|
end
|
54
62
|
end
|
data/lib/capybara/minitest.rb
CHANGED
@@ -52,6 +52,7 @@ module Capybara
|
|
52
52
|
raise ::Minitest::Assertion, e.message
|
53
53
|
end
|
54
54
|
ASSERTION
|
55
|
+
ruby2_keywords "assert_#{assertion_name}" if respond_to?(:ruby2_keywords)
|
55
56
|
end
|
56
57
|
|
57
58
|
alias_method :refute_title, :assert_no_title
|
@@ -109,6 +110,7 @@ module Capybara
|
|
109
110
|
raise ::Minitest::Assertion, e.message
|
110
111
|
end
|
111
112
|
ASSERTION
|
113
|
+
ruby2_keywords "assert_#{assertion_name}" if respond_to?(:ruby2_keywords)
|
112
114
|
end
|
113
115
|
|
114
116
|
alias_method :refute_selector, :assert_no_selector
|
@@ -120,14 +122,16 @@ module Capybara
|
|
120
122
|
define_method "assert_#{selector_type}" do |*args, &optional_filter_block|
|
121
123
|
subject, args = determine_subject(args)
|
122
124
|
locator, options = extract_locator(args)
|
123
|
-
assert_selector(subject, selector_type.to_sym, locator, options, &optional_filter_block)
|
125
|
+
assert_selector(subject, selector_type.to_sym, locator, **options, &optional_filter_block)
|
124
126
|
end
|
127
|
+
ruby2_keywords "assert_#{selector_type}" if respond_to?(:ruby2_keywords)
|
125
128
|
|
126
129
|
define_method "assert_no_#{selector_type}" do |*args, &optional_filter_block|
|
127
130
|
subject, args = determine_subject(args)
|
128
131
|
locator, options = extract_locator(args)
|
129
|
-
assert_no_selector(subject, selector_type.to_sym, locator, options, &optional_filter_block)
|
132
|
+
assert_no_selector(subject, selector_type.to_sym, locator, **options, &optional_filter_block)
|
130
133
|
end
|
134
|
+
ruby2_keywords "assert_no_#{selector_type}" if respond_to?(:ruby2_keywords)
|
131
135
|
alias_method "refute_#{selector_type}", "assert_no_#{selector_type}"
|
132
136
|
end
|
133
137
|
|
@@ -135,14 +139,22 @@ module Capybara
|
|
135
139
|
define_method "assert_#{field_type}_field" do |*args, &optional_filter_block|
|
136
140
|
subject, args = determine_subject(args)
|
137
141
|
locator, options = extract_locator(args)
|
138
|
-
assert_selector(subject, :field, locator, options.merge(field_type.to_sym => true), &optional_filter_block)
|
142
|
+
assert_selector(subject, :field, locator, **options.merge(field_type.to_sym => true), &optional_filter_block)
|
139
143
|
end
|
144
|
+
ruby2_keywords "assert_#{field_type}_field" if respond_to?(:ruby2_keywords)
|
140
145
|
|
141
146
|
define_method "assert_no_#{field_type}_field" do |*args, &optional_filter_block|
|
142
147
|
subject, args = determine_subject(args)
|
143
148
|
locator, options = extract_locator(args)
|
144
|
-
assert_no_selector(
|
149
|
+
assert_no_selector(
|
150
|
+
subject,
|
151
|
+
:field,
|
152
|
+
locator,
|
153
|
+
**options.merge(field_type.to_sym => true),
|
154
|
+
&optional_filter_block
|
155
|
+
)
|
145
156
|
end
|
157
|
+
ruby2_keywords "assert_no_#{field_type}_field" if respond_to?(:ruby2_keywords)
|
146
158
|
alias_method "refute_#{field_type}_field", "assert_no_#{field_type}_field"
|
147
159
|
end
|
148
160
|
|
@@ -151,11 +163,13 @@ module Capybara
|
|
151
163
|
subject, args = determine_subject(args)
|
152
164
|
assert_matches_selector(subject, selector_type.to_sym, *args, &optional_filter_block)
|
153
165
|
end
|
166
|
+
ruby2_keywords "assert_matches_#{selector_type}" if respond_to?(:ruby2_keywords)
|
154
167
|
|
155
168
|
define_method "assert_not_matches_#{selector_type}" do |*args, &optional_filter_block|
|
156
169
|
subject, args = determine_subject(args)
|
157
170
|
assert_not_matches_selector(subject, selector_type.to_sym, *args, &optional_filter_block)
|
158
171
|
end
|
172
|
+
ruby2_keywords "assert_not_matches_#{selector_type}" if respond_to?(:ruby2_keywords)
|
159
173
|
alias_method "refute_matches_#{selector_type}", "assert_not_matches_#{selector_type}"
|
160
174
|
end
|
161
175
|
|
@@ -27,9 +27,11 @@ module Capybara
|
|
27
27
|
@query_scope = query_scope
|
28
28
|
@query = query
|
29
29
|
@allow_reload = false
|
30
|
+
@query_idx = nil
|
30
31
|
end
|
31
32
|
|
32
|
-
def allow_reload!
|
33
|
+
def allow_reload!(idx = nil)
|
34
|
+
@query_idx = idx
|
33
35
|
@allow_reload = true
|
34
36
|
end
|
35
37
|
|
@@ -407,6 +409,8 @@ module Capybara
|
|
407
409
|
# @option options [Boolean] :html5 When using Chrome/Firefox with Selenium enables to force the use of HTML5
|
408
410
|
# (true) or legacy (false) dragging. If not specified the driver will attempt to
|
409
411
|
# detect the correct method to use.
|
412
|
+
# @option options [Array<Symbol>,Symbol] :drop_modifiers Modifier keys which should be held while the dragged element is dropped.
|
413
|
+
#
|
410
414
|
#
|
411
415
|
# @return [Capybara::Node::Element] The dragged element
|
412
416
|
def drag_to(node, **options)
|
@@ -545,14 +549,13 @@ module Capybara
|
|
545
549
|
|
546
550
|
# @api private
|
547
551
|
def reload
|
548
|
-
|
549
|
-
begin
|
550
|
-
reloaded = @query.resolve_for(query_scope.reload)&.first
|
552
|
+
return self unless @allow_reload
|
551
553
|
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
554
|
+
begin
|
555
|
+
reloaded = @query.resolve_for(query_scope.reload)[@query_idx.to_i]
|
556
|
+
@base = reloaded.base if reloaded
|
557
|
+
rescue StandardError => e
|
558
|
+
raise e unless catch_error?(e)
|
556
559
|
end
|
557
560
|
self
|
558
561
|
end
|
@@ -235,13 +235,16 @@ module Capybara
|
|
235
235
|
# @option options [Integer] maximum Maximum number of matches that are expected to be found
|
236
236
|
# @option options [Integer] minimum Minimum number of matches that are expected to be found
|
237
237
|
# @option options [Range] between Number of matches found must be within the given range
|
238
|
+
# @option options [Boolean] allow_reload Beta feature - May be removed in any version.
|
239
|
+
# When `true` allows elements to be reloaded if they become stale. This is an advanced behavior and should only be used
|
240
|
+
# if you fully understand the potential ramifications. The results can be confusing on dynamic pages. Defaults to `false`
|
238
241
|
# @overload all([kind = Capybara.default_selector], locator = nil, **options)
|
239
242
|
# @overload all([kind = Capybara.default_selector], locator = nil, **options, &filter_block)
|
240
243
|
# @yieldparam element [Capybara::Node::Element] The element being considered for inclusion in the results
|
241
244
|
# @yieldreturn [Boolean] Should the element be considered in the results?
|
242
245
|
# @return [Capybara::Result] A collection of found elements
|
243
246
|
# @raise [Capybara::ExpectationNotMet] The number of elements found doesn't match the specified conditions
|
244
|
-
def all(*args, **options, &optional_filter_block)
|
247
|
+
def all(*args, allow_reload: false, **options, &optional_filter_block)
|
245
248
|
minimum_specified = options_include_minimum?(options)
|
246
249
|
options = { minimum: 1 }.merge(options) unless minimum_specified
|
247
250
|
options[:session_options] = session_options
|
@@ -250,6 +253,7 @@ module Capybara
|
|
250
253
|
begin
|
251
254
|
synchronize(query.wait) do
|
252
255
|
result = query.resolve_for(self)
|
256
|
+
result.allow_reload! if allow_reload
|
253
257
|
raise Capybara::ExpectationNotMet, result.failure_message unless result.matches_count?
|
254
258
|
|
255
259
|
result
|
@@ -61,7 +61,7 @@ module Capybara
|
|
61
61
|
# @return [Boolean] If the styles match
|
62
62
|
#
|
63
63
|
def matches_style?(styles, **options)
|
64
|
-
make_predicate(options) { assert_matches_style(styles, options) }
|
64
|
+
make_predicate(options) { assert_matches_style(styles, **options) }
|
65
65
|
end
|
66
66
|
|
67
67
|
##
|
@@ -123,8 +123,8 @@ module Capybara
|
|
123
123
|
# @raise [Capybara::ExpectationNotMet] If the element doesn't have the specified styles
|
124
124
|
#
|
125
125
|
def assert_matches_style(styles, **options)
|
126
|
-
query_args = _set_query_session_options(styles,
|
127
|
-
query = Capybara::Queries::StyleQuery.new(*query_args)
|
126
|
+
query_args, query_opts = _set_query_session_options(styles, options)
|
127
|
+
query = Capybara::Queries::StyleQuery.new(*query_args, **query_opts)
|
128
128
|
synchronize(query.wait) do
|
129
129
|
raise Capybara::ExpectationNotMet, query.failure_message unless query.resolves_for?(self)
|
130
130
|
end
|
@@ -672,8 +672,8 @@ module Capybara
|
|
672
672
|
# @raise [Capybara::ExpectationNotMet] if the assertion hasn't succeeded during wait time
|
673
673
|
# @return [true]
|
674
674
|
#
|
675
|
-
def assert_text(*args)
|
676
|
-
_verify_text(*args) do |count, query|
|
675
|
+
def assert_text(type_or_text, *args, **opts)
|
676
|
+
_verify_text(type_or_text, *args, **opts) do |count, query|
|
677
677
|
unless query.matches_count?(count) && (count.positive? || query.expects_none?)
|
678
678
|
raise Capybara::ExpectationNotMet, query.failure_message
|
679
679
|
end
|
@@ -688,8 +688,8 @@ module Capybara
|
|
688
688
|
# @raise [Capybara::ExpectationNotMet] if the assertion hasn't succeeded during wait time
|
689
689
|
# @return [true]
|
690
690
|
#
|
691
|
-
def assert_no_text(*args)
|
692
|
-
_verify_text(*args) do |count, query|
|
691
|
+
def assert_no_text(type_or_text, *args, **opts)
|
692
|
+
_verify_text(type_or_text, *args, **opts) do |count, query|
|
693
693
|
if query.matches_count?(count) && (count.positive? || query.expects_none?)
|
694
694
|
raise Capybara::ExpectationNotMet, query.negative_failure_message
|
695
695
|
end
|
@@ -711,7 +711,7 @@ module Capybara
|
|
711
711
|
# @return [Boolean] Whether it exists
|
712
712
|
#
|
713
713
|
def has_text?(*args, **options)
|
714
|
-
make_predicate(options) { assert_text(*args, options) }
|
714
|
+
make_predicate(options) { assert_text(*args, **options) }
|
715
715
|
end
|
716
716
|
alias_method :has_content?, :has_text?
|
717
717
|
|
@@ -723,7 +723,7 @@ module Capybara
|
|
723
723
|
# @return [Boolean] Whether it doesn't exist
|
724
724
|
#
|
725
725
|
def has_no_text?(*args, **options)
|
726
|
-
make_predicate(options) { assert_no_text(*args, options) }
|
726
|
+
make_predicate(options) { assert_no_text(*args, **options) }
|
727
727
|
end
|
728
728
|
alias_method :has_no_content?, :has_no_text?
|
729
729
|
|
@@ -832,8 +832,14 @@ module Capybara
|
|
832
832
|
end
|
833
833
|
|
834
834
|
def _verify_selector_result(query_args, optional_filter_block, query_type = Capybara::Queries::SelectorQuery)
|
835
|
-
query_args =
|
836
|
-
|
835
|
+
# query_args, query_opts = if query_args[0].is_a? Symbol
|
836
|
+
# a,o = _set_query_session_options(*query_args.slice(2..))
|
837
|
+
# [query_args.slice(0..1).concat(a), o]
|
838
|
+
# else
|
839
|
+
# _set_query_session_options(*query_args)
|
840
|
+
# end
|
841
|
+
query_args, query_opts = _set_query_session_options(*query_args)
|
842
|
+
query = query_type.new(*query_args, **query_opts, &optional_filter_block)
|
837
843
|
synchronize(query.wait) do
|
838
844
|
yield query.resolve_for(self), query
|
839
845
|
end
|
@@ -841,8 +847,8 @@ module Capybara
|
|
841
847
|
end
|
842
848
|
|
843
849
|
def _verify_match_result(query_args, optional_filter_block)
|
844
|
-
query_args = _set_query_session_options(*query_args)
|
845
|
-
query = Capybara::Queries::MatchQuery.new(*query_args, &optional_filter_block)
|
850
|
+
query_args, query_opts = _set_query_session_options(*query_args)
|
851
|
+
query = Capybara::Queries::MatchQuery.new(*query_args, **query_opts, &optional_filter_block)
|
846
852
|
synchronize(query.wait) do
|
847
853
|
yield query.resolve_for(parent || session&.document || query_scope)
|
848
854
|
end
|
@@ -858,9 +864,12 @@ module Capybara
|
|
858
864
|
true
|
859
865
|
end
|
860
866
|
|
861
|
-
def _set_query_session_options(*query_args
|
867
|
+
def _set_query_session_options(*query_args)
|
868
|
+
query_args, query_options = query_args.dup, {}
|
869
|
+
# query_options = query_args.pop if query_options.empty? && query_args.last.is_a?(Hash)
|
870
|
+
query_options = query_args.pop if query_args.last.is_a?(Hash)
|
862
871
|
query_options[:session_options] = session_options
|
863
|
-
query_args
|
872
|
+
[query_args, query_options]
|
864
873
|
end
|
865
874
|
|
866
875
|
def make_predicate(options)
|
data/lib/capybara/node/simple.rb
CHANGED
@@ -79,7 +79,8 @@ module Capybara
|
|
79
79
|
if count
|
80
80
|
message << " #{occurrences count}"
|
81
81
|
elsif between
|
82
|
-
message << " between #{between.
|
82
|
+
message << " between #{between.begin ? between.first : 1} and" \
|
83
|
+
" #{between.end ? between.last : 'infinite'} times"
|
83
84
|
elsif maximum
|
84
85
|
message << " at most #{occurrences maximum}"
|
85
86
|
elsif minimum
|
@@ -45,6 +45,7 @@ class Capybara::RackTest::Node < Capybara::Driver::Node
|
|
45
45
|
|
46
46
|
if radio? then set_radio(value)
|
47
47
|
elsif checkbox? then set_checkbox(value)
|
48
|
+
elsif range? then set_range(value)
|
48
49
|
elsif input_field? then set_input(value)
|
49
50
|
elsif textarea? then native['_capybara_raw_value'] = value.to_s
|
50
51
|
end
|
@@ -76,8 +77,8 @@ class Capybara::RackTest::Node < Capybara::Driver::Node
|
|
76
77
|
set(!checked?)
|
77
78
|
elsif tag_name == 'label'
|
78
79
|
click_label
|
79
|
-
elsif
|
80
|
-
toggle_details
|
80
|
+
elsif (details = native.xpath('.//ancestor-or-self::details').last)
|
81
|
+
toggle_details(details)
|
81
82
|
end
|
82
83
|
end
|
83
84
|
|
@@ -123,9 +124,18 @@ class Capybara::RackTest::Node < Capybara::Driver::Node
|
|
123
124
|
alias_method "unchecked_#{meth_name}", meth_name
|
124
125
|
private "unchecked_#{meth_name}" # rubocop:disable Style/AccessModifierDeclarations
|
125
126
|
|
126
|
-
|
127
|
-
|
128
|
-
|
127
|
+
if RUBY_VERSION >= '2.7'
|
128
|
+
class_eval <<~METHOD, __FILE__, __LINE__ + 1
|
129
|
+
def #{meth_name}(...)
|
130
|
+
stale_check
|
131
|
+
method(:"unchecked_#{meth_name}").call(...)
|
132
|
+
end
|
133
|
+
METHOD
|
134
|
+
else
|
135
|
+
define_method meth_name do |*args|
|
136
|
+
stale_check
|
137
|
+
send("unchecked_#{meth_name}", *args)
|
138
|
+
end
|
129
139
|
end
|
130
140
|
end
|
131
141
|
|
@@ -199,6 +209,14 @@ private
|
|
199
209
|
end
|
200
210
|
end
|
201
211
|
|
212
|
+
def set_range(value) # rubocop:disable Naming/AccessorMethodName
|
213
|
+
min, max, step = (native['min'] || 0).to_f, (native['max'] || 100).to_f, (native['step'] || 1).to_f
|
214
|
+
value = value.to_f
|
215
|
+
value = value.clamp(min, max)
|
216
|
+
value = ((value - min) / step).round * step + min
|
217
|
+
native['value'] = value.clamp(min, max)
|
218
|
+
end
|
219
|
+
|
202
220
|
def set_input(value) # rubocop:disable Naming/AccessorMethodName
|
203
221
|
if text_or_password? && attribute_is_not_blank?(:maxlength)
|
204
222
|
# Browser behavior for maxlength="0" is inconsistent, so we stick with
|
@@ -238,11 +256,14 @@ private
|
|
238
256
|
labelled_control.set(!labelled_control.checked?) if checkbox_or_radio?(labelled_control)
|
239
257
|
end
|
240
258
|
|
241
|
-
def toggle_details
|
242
|
-
|
243
|
-
|
259
|
+
def toggle_details(details = nil)
|
260
|
+
details ||= native.xpath('.//ancestor-or-self::details').last
|
261
|
+
return unless details
|
262
|
+
|
263
|
+
if details.has_attribute?('open')
|
264
|
+
details.remove_attribute('open')
|
244
265
|
else
|
245
|
-
|
266
|
+
details.set_attribute('open', 'open')
|
246
267
|
end
|
247
268
|
end
|
248
269
|
|
@@ -284,6 +305,10 @@ protected
|
|
284
305
|
tag_name == 'textarea'
|
285
306
|
end
|
286
307
|
|
308
|
+
def range?
|
309
|
+
input_field? && type == 'range'
|
310
|
+
end
|
311
|
+
|
287
312
|
OPTION_OWNER_XPATH = XPath.parent(:optgroup, :select, :datalist).to_s.freeze
|
288
313
|
DISABLED_BY_FIELDSET_XPATH = XPath.generate do |x|
|
289
314
|
x.parent(:fieldset)[
|
data/lib/capybara/result.rb
CHANGED
@@ -31,6 +31,7 @@ module Capybara
|
|
31
31
|
@filter_errors = []
|
32
32
|
@results_enum = lazy_select_elements { |node| query.matches_filters?(node, @filter_errors) }
|
33
33
|
@query = query
|
34
|
+
@allow_reload = false
|
34
35
|
end
|
35
36
|
|
36
37
|
def_delegators :full_results, :size, :length, :last, :values_at, :inspect, :sample
|
@@ -43,7 +44,7 @@ module Capybara
|
|
43
44
|
@result_cache.each(&block)
|
44
45
|
loop do
|
45
46
|
next_result = @results_enum.next
|
46
|
-
|
47
|
+
add_to_cache(next_result)
|
47
48
|
yield next_result
|
48
49
|
end
|
49
50
|
self
|
@@ -59,7 +60,11 @@ module Capybara
|
|
59
60
|
nil
|
60
61
|
end
|
61
62
|
when Range
|
62
|
-
|
63
|
+
# idx.max is broken with beginless ranges
|
64
|
+
# idx.end && idx.max # endless range will have end == nil
|
65
|
+
max = idx.end
|
66
|
+
max -= 1 if max && idx.exclude_end?
|
67
|
+
max
|
63
68
|
end
|
64
69
|
|
65
70
|
if max_idx.nil?
|
@@ -94,7 +99,9 @@ module Capybara
|
|
94
99
|
end
|
95
100
|
|
96
101
|
if between
|
97
|
-
min, max = between.
|
102
|
+
min, max = (between.begin && between.min) || 1, between.end
|
103
|
+
max -= 1 if max && between.exclude_end?
|
104
|
+
|
98
105
|
size = load_up_to(max ? max + 1 : min)
|
99
106
|
return size <=> min unless between.include?(size)
|
100
107
|
end
|
@@ -130,13 +137,26 @@ module Capybara
|
|
130
137
|
@elements.length
|
131
138
|
end
|
132
139
|
|
140
|
+
##
|
141
|
+
# @api private
|
142
|
+
#
|
143
|
+
def allow_reload!
|
144
|
+
@allow_reload = true
|
145
|
+
self
|
146
|
+
end
|
147
|
+
|
133
148
|
private
|
134
149
|
|
150
|
+
def add_to_cache(elem)
|
151
|
+
elem.allow_reload!(@result_cache.size) if @allow_reload
|
152
|
+
@result_cache << elem
|
153
|
+
end
|
154
|
+
|
135
155
|
def load_up_to(num)
|
136
156
|
loop do
|
137
157
|
break if @result_cache.size >= num
|
138
158
|
|
139
|
-
@
|
159
|
+
add_to_cache(@results_enum.next)
|
140
160
|
end
|
141
161
|
@result_cache.size
|
142
162
|
end
|