capybara 2.18.0 → 3.0.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 +55 -1
- data/README.md +18 -17
- data/lib/capybara/config.rb +11 -58
- data/lib/capybara/cucumber.rb +2 -3
- data/lib/capybara/driver/base.rb +15 -16
- data/lib/capybara/driver/node.rb +5 -4
- data/lib/capybara/dsl.rb +1 -0
- data/lib/capybara/helpers.rb +19 -29
- data/lib/capybara/minitest/spec.rb +15 -14
- data/lib/capybara/minitest.rb +139 -138
- data/lib/capybara/node/actions.rb +60 -81
- data/lib/capybara/node/base.rb +11 -18
- data/lib/capybara/node/document.rb +2 -2
- data/lib/capybara/node/document_matchers.rb +8 -8
- data/lib/capybara/node/element.rb +30 -40
- data/lib/capybara/node/finders.rb +62 -70
- data/lib/capybara/node/matchers.rb +50 -71
- data/lib/capybara/node/simple.rb +11 -17
- data/lib/capybara/queries/ancestor_query.rb +11 -7
- data/lib/capybara/queries/base_query.rb +22 -18
- data/lib/capybara/queries/current_path_query.rb +8 -24
- data/lib/capybara/queries/match_query.rb +3 -7
- data/lib/capybara/queries/selector_query.rb +92 -95
- data/lib/capybara/queries/sibling_query.rb +4 -4
- data/lib/capybara/queries/text_query.rb +35 -35
- data/lib/capybara/queries/title_query.rb +8 -11
- data/lib/capybara/rack_test/browser.rb +15 -18
- data/lib/capybara/rack_test/css_handlers.rb +6 -4
- data/lib/capybara/rack_test/driver.rb +6 -10
- data/lib/capybara/rack_test/form.rb +50 -40
- data/lib/capybara/rack_test/node.rb +93 -63
- data/lib/capybara/rails.rb +2 -6
- data/lib/capybara/result.rb +22 -22
- data/lib/capybara/rspec/compound.rb +5 -10
- data/lib/capybara/rspec/features.rb +17 -48
- data/lib/capybara/rspec/matcher_proxies.rb +31 -15
- data/lib/capybara/rspec/matchers.rb +70 -61
- data/lib/capybara/rspec.rb +5 -10
- data/lib/capybara/selector/css.rb +6 -11
- data/lib/capybara/selector/filter.rb +1 -17
- data/lib/capybara/selector/filter_set.rb +18 -15
- data/lib/capybara/selector/filters/base.rb +7 -6
- data/lib/capybara/selector/filters/expression_filter.rb +6 -23
- data/lib/capybara/selector/filters/node_filter.rb +2 -12
- data/lib/capybara/selector/selector.rb +28 -34
- data/lib/capybara/selector.rb +129 -117
- data/lib/capybara/selenium/driver.rb +131 -125
- data/lib/capybara/selenium/node.rb +197 -115
- data/lib/capybara/server.rb +3 -2
- data/lib/capybara/session/config.rb +47 -67
- data/lib/capybara/session/matchers.rb +8 -7
- data/lib/capybara/session.rb +138 -224
- data/lib/capybara/spec/public/test.js +25 -4
- data/lib/capybara/spec/session/accept_alert_spec.rb +1 -0
- data/lib/capybara/spec/session/accept_confirm_spec.rb +3 -2
- data/lib/capybara/spec/session/accept_prompt_spec.rb +1 -0
- data/lib/capybara/spec/session/all_spec.rb +31 -18
- data/lib/capybara/spec/session/ancestor_spec.rb +6 -8
- data/lib/capybara/spec/session/assert_all_of_selectors_spec.rb +6 -5
- data/lib/capybara/spec/session/assert_current_path.rb +12 -11
- data/lib/capybara/spec/session/assert_selector.rb +1 -0
- data/lib/capybara/spec/session/assert_text.rb +23 -23
- data/lib/capybara/spec/session/assert_title.rb +13 -3
- data/lib/capybara/spec/session/attach_file_spec.rb +51 -30
- data/lib/capybara/spec/session/body_spec.rb +1 -0
- data/lib/capybara/spec/session/check_spec.rb +7 -6
- data/lib/capybara/spec/session/choose_spec.rb +5 -4
- data/lib/capybara/spec/session/click_button_spec.rb +24 -32
- data/lib/capybara/spec/session/click_link_or_button_spec.rb +8 -7
- data/lib/capybara/spec/session/click_link_spec.rb +8 -7
- data/lib/capybara/spec/session/current_scope_spec.rb +4 -3
- data/lib/capybara/spec/session/current_url_spec.rb +17 -6
- data/lib/capybara/spec/session/dismiss_confirm_spec.rb +1 -1
- data/lib/capybara/spec/session/dismiss_prompt_spec.rb +1 -0
- data/lib/capybara/spec/session/element/assert_match_selector.rb +1 -1
- data/lib/capybara/spec/session/element/match_xpath_spec.rb +1 -1
- data/lib/capybara/spec/session/element/matches_selector_spec.rb +5 -5
- data/lib/capybara/spec/session/evaluate_async_script_spec.rb +3 -2
- data/lib/capybara/spec/session/evaluate_script_spec.rb +4 -3
- data/lib/capybara/spec/session/execute_script_spec.rb +4 -3
- data/lib/capybara/spec/session/fill_in_spec.rb +30 -5
- data/lib/capybara/spec/session/find_button_spec.rb +4 -3
- data/lib/capybara/spec/session/find_by_id_spec.rb +2 -1
- data/lib/capybara/spec/session/find_field_spec.rb +9 -15
- data/lib/capybara/spec/session/find_link_spec.rb +6 -5
- data/lib/capybara/spec/session/find_spec.rb +37 -31
- data/lib/capybara/spec/session/first_spec.rb +60 -33
- data/lib/capybara/spec/session/frame/frame_title_spec.rb +23 -0
- data/lib/capybara/spec/session/frame/frame_url_spec.rb +23 -0
- data/lib/capybara/spec/session/frame/switch_to_frame_spec.rb +2 -1
- data/lib/capybara/spec/session/frame/within_frame_spec.rb +9 -16
- data/lib/capybara/spec/session/go_back_spec.rb +1 -0
- data/lib/capybara/spec/session/go_forward_spec.rb +1 -0
- data/lib/capybara/spec/session/has_all_selectors_spec.rb +15 -15
- data/lib/capybara/spec/session/has_button_spec.rb +2 -1
- data/lib/capybara/spec/session/has_css_spec.rb +3 -2
- data/lib/capybara/spec/session/has_current_path_spec.rb +12 -28
- data/lib/capybara/spec/session/has_field_spec.rb +4 -3
- data/lib/capybara/spec/session/has_link_spec.rb +1 -0
- data/lib/capybara/spec/session/has_none_selectors_spec.rb +17 -17
- data/lib/capybara/spec/session/has_select_spec.rb +30 -29
- data/lib/capybara/spec/session/has_selector_spec.rb +5 -4
- data/lib/capybara/spec/session/has_table_spec.rb +2 -1
- data/lib/capybara/spec/session/has_text_spec.rb +9 -13
- data/lib/capybara/spec/session/has_title_spec.rb +1 -0
- data/lib/capybara/spec/session/has_xpath_spec.rb +1 -0
- data/lib/capybara/spec/session/headers.rb +2 -1
- data/lib/capybara/spec/session/html_spec.rb +1 -0
- data/lib/capybara/spec/session/node_spec.rb +91 -56
- data/lib/capybara/spec/session/node_wrapper_spec.rb +36 -0
- data/lib/capybara/spec/session/refresh_spec.rb +6 -2
- data/lib/capybara/spec/session/reset_session_spec.rb +19 -0
- data/lib/capybara/spec/session/response_code.rb +1 -0
- data/lib/capybara/spec/session/save_and_open_page_spec.rb +1 -0
- data/lib/capybara/spec/session/save_and_open_screenshot_spec.rb +6 -11
- data/lib/capybara/spec/session/save_page_spec.rb +1 -17
- data/lib/capybara/spec/session/save_screenshot_spec.rb +3 -3
- data/lib/capybara/spec/session/select_spec.rb +20 -20
- data/lib/capybara/spec/session/selectors_spec.rb +2 -2
- data/lib/capybara/spec/session/sibling_spec.rb +1 -1
- data/lib/capybara/spec/session/text_spec.rb +17 -3
- data/lib/capybara/spec/session/title_spec.rb +11 -1
- data/lib/capybara/spec/session/uncheck_spec.rb +4 -3
- data/lib/capybara/spec/session/unselect_spec.rb +6 -5
- data/lib/capybara/spec/session/visit_spec.rb +9 -3
- data/lib/capybara/spec/session/window/become_closed_spec.rb +2 -1
- data/lib/capybara/spec/session/window/current_window_spec.rb +1 -0
- data/lib/capybara/spec/session/window/open_new_window_spec.rb +1 -0
- data/lib/capybara/spec/session/window/switch_to_window_spec.rb +2 -1
- data/lib/capybara/spec/session/window/window_opened_by_spec.rb +2 -1
- data/lib/capybara/spec/session/window/window_spec.rb +12 -12
- data/lib/capybara/spec/session/window/windows_spec.rb +2 -3
- data/lib/capybara/spec/session/window/within_window_spec.rb +15 -71
- data/lib/capybara/spec/session/within_spec.rb +1 -0
- data/lib/capybara/spec/spec_helper.rb +34 -18
- data/lib/capybara/spec/test_app.rb +17 -9
- data/lib/capybara/spec/views/form.erb +7 -0
- data/lib/capybara/spec/views/with_html.erb +23 -1
- data/lib/capybara/spec/views/within_frames.erb +4 -1
- data/lib/capybara/version.rb +2 -1
- data/lib/capybara/window.rb +6 -10
- data/lib/capybara.rb +28 -25
- data/spec/basic_node_spec.rb +1 -0
- data/spec/capybara_spec.rb +11 -50
- data/spec/dsl_spec.rb +5 -13
- data/spec/filter_set_spec.rb +5 -4
- data/spec/fixtures/selenium_driver_rspec_failure.rb +2 -1
- data/spec/fixtures/selenium_driver_rspec_success.rb +3 -2
- data/spec/minitest_spec.rb +4 -3
- data/spec/minitest_spec_spec.rb +3 -2
- data/spec/per_session_config_spec.rb +9 -8
- data/spec/rack_test_spec.rb +21 -20
- data/spec/result_spec.rb +17 -16
- data/spec/rspec/features_spec.rb +17 -14
- data/spec/rspec/scenarios_spec.rb +5 -7
- data/spec/rspec/shared_spec_matchers.rb +96 -99
- data/spec/rspec/views_spec.rb +2 -1
- data/spec/rspec_matchers_spec.rb +18 -2
- data/spec/rspec_spec.rb +11 -15
- data/spec/selector_spec.rb +5 -6
- data/spec/selenium_spec_chrome.rb +9 -4
- data/spec/selenium_spec_edge.rb +27 -0
- data/spec/selenium_spec_ie.rb +31 -0
- data/spec/selenium_spec_marionette.rb +28 -12
- data/spec/server_spec.rb +33 -33
- data/spec/session_spec.rb +2 -1
- data/spec/shared_selenium_session.rb +36 -22
- data/spec/spec_helper.rb +3 -6
- metadata +68 -85
- data/lib/capybara/query.rb +0 -7
- data/spec/selenium_spec_firefox.rb +0 -68
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module Capybara
|
3
4
|
module Node
|
4
|
-
|
5
5
|
##
|
6
6
|
#
|
7
7
|
# A {Capybara::Document} represents an HTML document. Any operation
|
@@ -20,7 +20,7 @@ module Capybara
|
|
20
20
|
#
|
21
21
|
# @return [String] The text of the document
|
22
22
|
#
|
23
|
-
def text(type=nil)
|
23
|
+
def text(type = nil)
|
24
24
|
find(:xpath, '/html').text(type)
|
25
25
|
end
|
26
26
|
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module Capybara
|
3
4
|
module Node
|
4
5
|
module DocumentMatchers
|
@@ -15,8 +16,8 @@ module Capybara
|
|
15
16
|
# @raise [Capybara::ExpectationNotMet] if the assertion hasn't succeeded during wait time
|
16
17
|
# @return [true]
|
17
18
|
#
|
18
|
-
def assert_title(title, options
|
19
|
-
_verify_title(title,options) { |query| raise Capybara::ExpectationNotMet, query.failure_message unless query.resolves_for?(self) }
|
19
|
+
def assert_title(title, **options)
|
20
|
+
_verify_title(title, options) { |query| raise Capybara::ExpectationNotMet, query.failure_message unless query.resolves_for?(self) }
|
20
21
|
end
|
21
22
|
|
22
23
|
##
|
@@ -26,8 +27,8 @@ module Capybara
|
|
26
27
|
# @raise [Capybara::ExpectationNotMet] if the assertion hasn't succeeded during wait time
|
27
28
|
# @return [true]
|
28
29
|
#
|
29
|
-
def assert_no_title(title, options
|
30
|
-
_verify_title(title,options) { |query| raise Capybara::ExpectationNotMet, query.negative_failure_message if query.resolves_for?(self) }
|
30
|
+
def assert_no_title(title, **options)
|
31
|
+
_verify_title(title, options) { |query| raise Capybara::ExpectationNotMet, query.negative_failure_message if query.resolves_for?(self) }
|
31
32
|
end
|
32
33
|
|
33
34
|
##
|
@@ -36,7 +37,7 @@ module Capybara
|
|
36
37
|
# @macro title_query_params
|
37
38
|
# @return [Boolean]
|
38
39
|
#
|
39
|
-
def has_title?(title, options
|
40
|
+
def has_title?(title, **options)
|
40
41
|
assert_title(title, options)
|
41
42
|
rescue Capybara::ExpectationNotMet
|
42
43
|
return false
|
@@ -48,13 +49,13 @@ module Capybara
|
|
48
49
|
# @macro title_query_params
|
49
50
|
# @return [Boolean]
|
50
51
|
#
|
51
|
-
def has_no_title?(title, options
|
52
|
+
def has_no_title?(title, **options)
|
52
53
|
assert_no_title(title, options)
|
53
54
|
rescue Capybara::ExpectationNotMet
|
54
55
|
return false
|
55
56
|
end
|
56
57
|
|
57
|
-
|
58
|
+
private
|
58
59
|
|
59
60
|
def _verify_title(title, options)
|
60
61
|
query = Capybara::Queries::TitleQuery.new(title, options)
|
@@ -63,7 +64,6 @@ module Capybara
|
|
63
64
|
end
|
64
65
|
return true
|
65
66
|
end
|
66
|
-
|
67
67
|
end
|
68
68
|
end
|
69
69
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module Capybara
|
3
4
|
module Node
|
4
|
-
|
5
5
|
##
|
6
6
|
#
|
7
7
|
# A {Capybara::Node::Element} represents a single element on the page. It is possible
|
@@ -22,7 +22,6 @@ module Capybara
|
|
22
22
|
# @see Capybara::Node
|
23
23
|
#
|
24
24
|
class Element < Base
|
25
|
-
|
26
25
|
def initialize(session, base, query_scope, query)
|
27
26
|
super(session, base)
|
28
27
|
@query_scope = query_scope
|
@@ -54,7 +53,7 @@ module Capybara
|
|
54
53
|
# @param [:all, :visible] type Whether to return only visible or all text
|
55
54
|
# @return [String] The text of the element
|
56
55
|
#
|
57
|
-
def text(type=nil)
|
56
|
+
def text(type = nil)
|
58
57
|
type ||= :all unless session_options.ignore_hidden_elements or session_options.visible_text_only
|
59
58
|
synchronize do
|
60
59
|
if type == :all
|
@@ -94,23 +93,10 @@ module Capybara
|
|
94
93
|
# @param [Hash{}] options Driver specific options for how to set the value
|
95
94
|
#
|
96
95
|
# @return [Capybara::Node::Element] The element
|
97
|
-
def set(value, options
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
unless options.empty? || driver_supports_options
|
103
|
-
warn "Options passed to Capybara::Node#set but the driver doesn't support them"
|
104
|
-
end
|
105
|
-
|
106
|
-
synchronize do
|
107
|
-
if driver_supports_options
|
108
|
-
base.set(value, options)
|
109
|
-
else
|
110
|
-
base.set(value)
|
111
|
-
end
|
112
|
-
end
|
113
|
-
return self
|
96
|
+
def set(value, **options)
|
97
|
+
raise Capybara::ReadOnlyElementError, "Attempt to set readonly element with value: #{value}" if readonly?
|
98
|
+
synchronize { base.set(value, options) }
|
99
|
+
self
|
114
100
|
end
|
115
101
|
|
116
102
|
##
|
@@ -121,7 +107,7 @@ module Capybara
|
|
121
107
|
def select_option
|
122
108
|
warn "Attempt to select disabled option: #{value || text}" if disabled?
|
123
109
|
synchronize { base.select_option }
|
124
|
-
|
110
|
+
self
|
125
111
|
end
|
126
112
|
|
127
113
|
##
|
@@ -131,37 +117,43 @@ module Capybara
|
|
131
117
|
# @return [Capybara::Node::Element] The element
|
132
118
|
def unselect_option
|
133
119
|
synchronize { base.unselect_option }
|
134
|
-
|
120
|
+
self
|
135
121
|
end
|
136
122
|
|
137
123
|
##
|
138
124
|
#
|
139
125
|
# Click the Element
|
140
126
|
#
|
127
|
+
# @!macro click_modifiers
|
128
|
+
# @overload $0(*key_modifiers=[], offset={x: nil, y: nil})
|
129
|
+
# @param [Array<:alt, :control, :meta, :shift>] *key_modifiers Keys to be held down when clicking
|
130
|
+
# @param [Hash] offset x and y coordinates to offset the click location from the top left corner of the element. If not specified will click the middle of the element.
|
141
131
|
# @return [Capybara::Node::Element] The element
|
142
|
-
def click
|
143
|
-
synchronize { base.click }
|
144
|
-
|
132
|
+
def click(*keys, **offset)
|
133
|
+
synchronize { base.click(keys, offset) }
|
134
|
+
self
|
145
135
|
end
|
146
136
|
|
147
137
|
##
|
148
138
|
#
|
149
139
|
# Right Click the Element
|
150
140
|
#
|
141
|
+
# @macro click_modifiers
|
151
142
|
# @return [Capybara::Node::Element] The element
|
152
|
-
def right_click
|
153
|
-
synchronize { base.right_click }
|
154
|
-
|
143
|
+
def right_click(*keys, **offset)
|
144
|
+
synchronize { base.right_click(keys, offset) }
|
145
|
+
self
|
155
146
|
end
|
156
147
|
|
157
148
|
##
|
158
149
|
#
|
159
150
|
# Double Click the Element
|
160
151
|
#
|
152
|
+
# @macro click_modifiers
|
161
153
|
# @return [Capybara::Node::Element] The element
|
162
|
-
def double_click
|
163
|
-
synchronize { base.double_click }
|
164
|
-
|
154
|
+
def double_click(*keys, **offset)
|
155
|
+
synchronize { base.double_click(keys, offset) }
|
156
|
+
self
|
165
157
|
end
|
166
158
|
|
167
159
|
##
|
@@ -237,7 +229,7 @@ module Capybara
|
|
237
229
|
# @return [Capybara::Node::Element] The element
|
238
230
|
def send_keys(*args)
|
239
231
|
synchronize { base.send_keys(*args) }
|
240
|
-
|
232
|
+
self
|
241
233
|
end
|
242
234
|
|
243
235
|
##
|
@@ -247,7 +239,7 @@ module Capybara
|
|
247
239
|
# @return [Capybara::Node::Element] The element
|
248
240
|
def hover
|
249
241
|
synchronize { base.hover }
|
250
|
-
|
242
|
+
self
|
251
243
|
end
|
252
244
|
|
253
245
|
##
|
@@ -339,7 +331,7 @@ module Capybara
|
|
339
331
|
# @return [Capybara::Node::Element] The element
|
340
332
|
def trigger(event)
|
341
333
|
synchronize { base.trigger(event) }
|
342
|
-
|
334
|
+
self
|
343
335
|
end
|
344
336
|
|
345
337
|
##
|
@@ -355,7 +347,7 @@ module Capybara
|
|
355
347
|
# @return [Capybara::Node::Element] The element
|
356
348
|
def drag_to(node)
|
357
349
|
synchronize { base.drag_to(node.base) }
|
358
|
-
|
350
|
+
self
|
359
351
|
end
|
360
352
|
|
361
353
|
def reload
|
@@ -375,11 +367,9 @@ module Capybara
|
|
375
367
|
rescue NotSupportedByDriverError
|
376
368
|
%(#<Capybara::Node::Element tag="#{base.tag_name}">)
|
377
369
|
rescue => e
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
raise
|
382
|
-
end
|
370
|
+
raise unless session.driver.invalid_element_errors.any? { |et| e.is_a?(et) }
|
371
|
+
|
372
|
+
%(Obsolete #<Capybara::Node::Element>)
|
383
373
|
end
|
384
374
|
end
|
385
375
|
end
|
@@ -1,8 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module Capybara
|
3
4
|
module Node
|
4
5
|
module Finders
|
5
|
-
|
6
6
|
##
|
7
7
|
#
|
8
8
|
# Find an {Capybara::Node::Element} based on the given arguments. +find+ will raise an error if the element
|
@@ -28,13 +28,9 @@ module Capybara
|
|
28
28
|
# @return [Capybara::Node::Element] The found element
|
29
29
|
# @raise [Capybara::ElementNotFound] If the element can't be found before time expires
|
30
30
|
#
|
31
|
-
def find(*args, &optional_filter_block)
|
32
|
-
|
33
|
-
|
34
|
-
else
|
35
|
-
args.push(session_options: session_options)
|
36
|
-
end
|
37
|
-
synced_resolve Capybara::Queries::SelectorQuery.new(*args, &optional_filter_block)
|
31
|
+
def find(*args, **options, &optional_filter_block)
|
32
|
+
options[:session_options] = session_options
|
33
|
+
synced_resolve Capybara::Queries::SelectorQuery.new(*args, options, &optional_filter_block)
|
38
34
|
end
|
39
35
|
|
40
36
|
##
|
@@ -57,13 +53,9 @@ module Capybara
|
|
57
53
|
# @return [Capybara::Node::Element] The found element
|
58
54
|
# @raise [Capybara::ElementNotFound] If the element can't be found before time expires
|
59
55
|
#
|
60
|
-
def ancestor(*args, &optional_filter_block)
|
61
|
-
|
62
|
-
|
63
|
-
else
|
64
|
-
args.push(session_options: session_options)
|
65
|
-
end
|
66
|
-
synced_resolve Capybara::Queries::AncestorQuery.new(*args, &optional_filter_block)
|
56
|
+
def ancestor(*args, **options, &optional_filter_block)
|
57
|
+
options[:session_options] = session_options
|
58
|
+
synced_resolve Capybara::Queries::AncestorQuery.new(*args, **options, &optional_filter_block)
|
67
59
|
end
|
68
60
|
|
69
61
|
##
|
@@ -87,13 +79,9 @@ module Capybara
|
|
87
79
|
# @return [Capybara::Node::Element] The found element
|
88
80
|
# @raise [Capybara::ElementNotFound] If the element can't be found before time expires
|
89
81
|
#
|
90
|
-
def sibling(*args, &optional_filter_block)
|
91
|
-
|
92
|
-
|
93
|
-
else
|
94
|
-
args.push(session_options: session_options)
|
95
|
-
end
|
96
|
-
synced_resolve Capybara::Queries::SiblingQuery.new(*args, &optional_filter_block)
|
82
|
+
def sibling(*args, **options, &optional_filter_block)
|
83
|
+
options[:session_options] = session_options
|
84
|
+
synced_resolve Capybara::Queries::SiblingQuery.new(*args, **options, &optional_filter_block)
|
97
85
|
end
|
98
86
|
|
99
87
|
##
|
@@ -123,11 +111,9 @@ module Capybara
|
|
123
111
|
# @return [Capybara::Node::Element] The found element
|
124
112
|
#
|
125
113
|
|
126
|
-
def find_field(locator=nil, options
|
127
|
-
locator, options = nil, locator if locator.is_a? Hash
|
114
|
+
def find_field(locator = nil, **options, &optional_filter_block)
|
128
115
|
find(:field, locator, options, &optional_filter_block)
|
129
116
|
end
|
130
|
-
alias_method :field_labeled, :find_field
|
131
117
|
|
132
118
|
##
|
133
119
|
#
|
@@ -145,8 +131,7 @@ module Capybara
|
|
145
131
|
# @option options [String, Array<String>] class Match links that match the class(es) provided
|
146
132
|
# @return [Capybara::Node::Element] The found element
|
147
133
|
#
|
148
|
-
def find_link(locator=nil, options
|
149
|
-
locator, options = nil, locator if locator.is_a? Hash
|
134
|
+
def find_link(locator = nil, **options, &optional_filter_block)
|
150
135
|
find(:link, locator, options, &optional_filter_block)
|
151
136
|
end
|
152
137
|
|
@@ -174,8 +159,7 @@ module Capybara
|
|
174
159
|
# @option options [String, Array<String>] class Match buttons that match the class(es) provided
|
175
160
|
# @return [Capybara::Node::Element] The found element
|
176
161
|
#
|
177
|
-
def find_button(locator=nil, options
|
178
|
-
locator, options = nil, locator if locator.is_a? Hash
|
162
|
+
def find_button(locator = nil, **options, &optional_filter_block)
|
179
163
|
find(:button, locator, options, &optional_filter_block)
|
180
164
|
end
|
181
165
|
|
@@ -189,7 +173,7 @@ module Capybara
|
|
189
173
|
#
|
190
174
|
# @return [Capybara::Node::Element] The found element
|
191
175
|
#
|
192
|
-
def find_by_id(id, options
|
176
|
+
def find_by_id(id, **options, &optional_filter_block)
|
193
177
|
find(:id, id, options, &optional_filter_block)
|
194
178
|
end
|
195
179
|
|
@@ -221,10 +205,11 @@ module Capybara
|
|
221
205
|
# page.all('a', text: 'Home')
|
222
206
|
# page.all('#menu li', visible: true)
|
223
207
|
#
|
224
|
-
# By default
|
225
|
-
#
|
226
|
-
#
|
227
|
-
#
|
208
|
+
# By default Capybara's waiting behavior will wait up to `Capybara.default_max_wait_time`
|
209
|
+
# seconds for matching elements to be available and then return an empty result if none
|
210
|
+
# are available. It is possible to set expectations on the number of results located and
|
211
|
+
# Capybara will raise an exception if the number of elements located don't satisfy the
|
212
|
+
# specified conditions. The expectations can be set using
|
228
213
|
#
|
229
214
|
# page.assert_selector('p#foo', count: 4)
|
230
215
|
# page.assert_selector('p#foo', maximum: 10)
|
@@ -235,9 +220,9 @@ module Capybara
|
|
235
220
|
# count matching.
|
236
221
|
#
|
237
222
|
# @param [Symbol] kind Optional selector type (:css, :xpath, :field, etc.) - Defaults to Capybara.default_selector
|
238
|
-
# @param [String] locator The selector
|
223
|
+
# @param [String] locator The locator for the specified selector
|
239
224
|
# @option options [String, Regexp] text Only find elements which contain this text or match this regexp
|
240
|
-
# @option options [String, Boolean] exact_text (Capybara.exact_text) When String the
|
225
|
+
# @option options [String, Boolean] exact_text (Capybara.exact_text) When String the elements contained text must match exactly, when Boolean controls whether the :text option must match exactly
|
241
226
|
# @option options [Boolean, Symbol] visible Only find elements with the specified visibility:
|
242
227
|
# * true - only finds visible elements.
|
243
228
|
# * false - finds invisible _and_ visible elements.
|
@@ -249,24 +234,28 @@ module Capybara
|
|
249
234
|
# @option options [Integer] minimum Minimum number of matches that are expected to be found
|
250
235
|
# @option options [Range] between Number of matches found must be within the given range
|
251
236
|
# @option options [Boolean] exact Control whether `is` expressions in the given XPath match exactly or partially
|
252
|
-
# @option options [Integer] wait (Capybara.default_max_wait_time) The time to wait for
|
237
|
+
# @option options [Integer, false] wait (Capybara.default_max_wait_time) The time to wait for matching elements to become available
|
253
238
|
# @overload all([kind = Capybara.default_selector], locator = nil, options = {})
|
254
239
|
# @overload all([kind = Capybara.default_selector], locator = nil, options = {}, &filter_block)
|
255
240
|
# @yieldparam element [Capybara::Node::Element] The element being considered for inclusion in the results
|
256
241
|
# @yieldreturn [Boolean] Should the element be considered in the results?
|
257
242
|
# @return [Capybara::Result] A collection of found elements
|
258
|
-
#
|
259
|
-
def all(*args, &optional_filter_block)
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
243
|
+
# @raise [Capybara::ExpectationNotMet] The number of elements found doesn't match the specified conditions
|
244
|
+
def all(*args, **options, &optional_filter_block)
|
245
|
+
minimum_specified = options_include_minimum?(options)
|
246
|
+
options = { minimum: 1 }.merge(options) unless minimum_specified
|
247
|
+
options[:session_options] = session_options
|
248
|
+
query = Capybara::Queries::SelectorQuery.new(*args.push(options), &optional_filter_block)
|
249
|
+
result = nil
|
250
|
+
begin
|
251
|
+
synchronize(query.wait) do
|
252
|
+
result = query.resolve_for(self)
|
253
|
+
raise Capybara::ExpectationNotMet, result.failure_message unless result.matches_count?
|
254
|
+
result
|
255
|
+
end
|
256
|
+
rescue Capybara::ExpectationNotMet
|
257
|
+
raise if minimum_specified || (result.compare_count == 1)
|
258
|
+
Result.new([], nil)
|
270
259
|
end
|
271
260
|
end
|
272
261
|
alias_method :find_all, :all
|
@@ -274,48 +263,51 @@ module Capybara
|
|
274
263
|
##
|
275
264
|
#
|
276
265
|
# Find the first element on the page matching the given selector
|
277
|
-
# and options
|
278
|
-
#
|
279
|
-
#
|
280
|
-
# return the first. Waiting behavior can also be triggered by passing in any of the count
|
281
|
-
# expectation options.
|
266
|
+
# and options. By default `first` will wait up to `Capybara.default_max_wait_time`
|
267
|
+
# seconds for matching elements to appear and then raise an error if no matching
|
268
|
+
# element is found, or `nil` if the provided count options allow for empty results.
|
282
269
|
#
|
283
270
|
# @overload first([kind], locator, options)
|
284
271
|
# @param [:css, :xpath] kind The type of selector
|
285
272
|
# @param [String] locator The selector
|
286
273
|
# @param [Hash] options Additional options; see {#all}
|
287
274
|
# @return [Capybara::Node::Element] The found element or nil
|
275
|
+
# @raise [Capybara::ElementNotFound] If element(s) matching the provided options can't be found before time expires
|
288
276
|
#
|
289
|
-
def first(*args, &optional_filter_block)
|
290
|
-
|
291
|
-
|
292
|
-
args.push({minimum: 1}.merge(options))
|
293
|
-
end
|
294
|
-
all(*args, &optional_filter_block).first
|
295
|
-
rescue Capybara::ExpectationNotMet
|
296
|
-
nil
|
277
|
+
def first(*args, **options, &optional_filter_block)
|
278
|
+
options = { minimum: 1 }.merge(options) unless options_include_minimum?(options)
|
279
|
+
all(*args, **options, &optional_filter_block).first
|
297
280
|
end
|
298
281
|
|
299
|
-
|
282
|
+
private
|
300
283
|
|
301
284
|
def synced_resolve(query)
|
302
285
|
synchronize(query.wait) do
|
303
|
-
if (query
|
286
|
+
if prefer_exact?(query)
|
304
287
|
result = query.resolve_for(self, true)
|
305
288
|
result = query.resolve_for(self, false) if result.empty? && query.supports_exact? && !query.exact?
|
306
289
|
else
|
307
290
|
result = query.resolve_for(self)
|
308
291
|
end
|
309
292
|
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
if result.empty?
|
314
|
-
raise Capybara::ElementNotFound.new("Unable to find #{query.description}")
|
315
|
-
end
|
293
|
+
raise Capybara::Ambiguous, "Ambiguous match, found #{result.size} elements matching #{query.description}" if ambiguous?(query, result)
|
294
|
+
raise Capybara::ElementNotFound, "Unable to find #{query.description}" if result.empty?
|
295
|
+
|
316
296
|
result.first
|
317
297
|
end.tap(&:allow_reload!)
|
318
298
|
end
|
299
|
+
|
300
|
+
def ambiguous?(query, result)
|
301
|
+
query.match == :one or query.match == :smart and result.size > 1
|
302
|
+
end
|
303
|
+
|
304
|
+
def prefer_exact?(query)
|
305
|
+
query.match == :smart or query.match == :prefer_exact
|
306
|
+
end
|
307
|
+
|
308
|
+
def options_include_minimum?(opts)
|
309
|
+
%i[count minimum between].any? { |k| opts.key?(k) }
|
310
|
+
end
|
319
311
|
end
|
320
312
|
end
|
321
313
|
end
|