capybara 2.5.0 → 2.18.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 +5 -5
- data/.yard/templates_custom/default/class/html/selectors.erb +38 -0
- data/.yard/templates_custom/default/class/html/setup.rb +17 -0
- data/.yard/yard_extensions.rb +78 -0
- data/.yardopts +1 -0
- data/History.md +413 -10
- data/License.txt +1 -1
- data/README.md +237 -130
- data/lib/capybara/config.rb +132 -0
- data/lib/capybara/cucumber.rb +3 -1
- data/lib/capybara/driver/base.rb +27 -6
- data/lib/capybara/driver/node.rb +14 -5
- data/lib/capybara/dsl.rb +2 -3
- data/lib/capybara/helpers.rb +13 -65
- data/lib/capybara/minitest/spec.rb +177 -0
- data/lib/capybara/minitest.rb +278 -0
- data/lib/capybara/node/actions.rb +180 -24
- data/lib/capybara/node/base.rb +17 -5
- data/lib/capybara/node/document.rb +5 -0
- data/lib/capybara/node/document_matchers.rb +15 -14
- data/lib/capybara/node/element.rb +55 -7
- data/lib/capybara/node/finders.rb +179 -67
- data/lib/capybara/node/matchers.rb +301 -105
- data/lib/capybara/node/simple.rb +15 -4
- data/lib/capybara/queries/ancestor_query.rb +25 -0
- data/lib/capybara/queries/base_query.rb +69 -3
- data/lib/capybara/queries/current_path_query.rb +17 -8
- data/lib/capybara/queries/match_query.rb +19 -0
- data/lib/capybara/queries/selector_query.rb +251 -0
- data/lib/capybara/queries/sibling_query.rb +25 -0
- data/lib/capybara/queries/text_query.rb +67 -16
- data/lib/capybara/queries/title_query.rb +4 -2
- data/lib/capybara/query.rb +3 -131
- data/lib/capybara/rack_test/browser.rb +14 -5
- data/lib/capybara/rack_test/css_handlers.rb +1 -0
- data/lib/capybara/rack_test/driver.rb +15 -8
- data/lib/capybara/rack_test/form.rb +34 -12
- data/lib/capybara/rack_test/node.rb +29 -12
- data/lib/capybara/rails.rb +3 -3
- data/lib/capybara/result.rb +104 -9
- data/lib/capybara/rspec/compound.rb +95 -0
- data/lib/capybara/rspec/features.rb +17 -6
- data/lib/capybara/rspec/matcher_proxies.rb +45 -0
- data/lib/capybara/rspec/matchers.rb +199 -80
- data/lib/capybara/rspec.rb +4 -2
- data/lib/capybara/selector/css.rb +30 -0
- data/lib/capybara/selector/filter.rb +20 -0
- data/lib/capybara/selector/filter_set.rb +74 -0
- data/lib/capybara/selector/filters/base.rb +33 -0
- data/lib/capybara/selector/filters/expression_filter.rb +40 -0
- data/lib/capybara/selector/filters/node_filter.rb +27 -0
- data/lib/capybara/selector/selector.rb +276 -0
- data/lib/capybara/selector.rb +452 -157
- data/lib/capybara/selenium/driver.rb +282 -81
- data/lib/capybara/selenium/node.rb +144 -46
- data/lib/capybara/server.rb +59 -16
- data/lib/capybara/session/config.rb +114 -0
- data/lib/capybara/session/matchers.rb +29 -19
- data/lib/capybara/session.rb +378 -143
- data/lib/capybara/spec/fixtures/no_extension +1 -0
- data/lib/capybara/spec/public/jquery-ui.js +13 -791
- data/lib/capybara/spec/public/jquery.js +4 -9045
- data/lib/capybara/spec/public/test.js +45 -11
- data/lib/capybara/spec/session/accept_alert_spec.rb +30 -7
- data/lib/capybara/spec/session/accept_confirm_spec.rb +14 -2
- data/lib/capybara/spec/session/accept_prompt_spec.rb +35 -6
- data/lib/capybara/spec/session/all_spec.rb +45 -32
- data/lib/capybara/spec/session/ancestor_spec.rb +85 -0
- data/lib/capybara/spec/session/assert_all_of_selectors_spec.rb +110 -0
- data/lib/capybara/spec/session/assert_current_path.rb +15 -2
- data/lib/capybara/spec/session/assert_selector.rb +29 -28
- data/lib/capybara/spec/session/assert_text.rb +59 -20
- data/lib/capybara/spec/session/assert_title.rb +25 -11
- data/lib/capybara/spec/session/attach_file_spec.rb +42 -4
- data/lib/capybara/spec/session/body_spec.rb +1 -0
- data/lib/capybara/spec/session/check_spec.rb +90 -14
- data/lib/capybara/spec/session/choose_spec.rb +31 -5
- data/lib/capybara/spec/session/click_button_spec.rb +20 -9
- data/lib/capybara/spec/session/click_link_or_button_spec.rb +15 -9
- data/lib/capybara/spec/session/click_link_spec.rb +39 -15
- data/lib/capybara/spec/session/current_scope_spec.rb +2 -1
- data/lib/capybara/spec/session/current_url_spec.rb +12 -3
- data/lib/capybara/spec/session/dismiss_confirm_spec.rb +6 -5
- data/lib/capybara/spec/session/dismiss_prompt_spec.rb +4 -3
- data/lib/capybara/spec/session/element/assert_match_selector.rb +36 -0
- data/lib/capybara/spec/session/element/match_css_spec.rb +23 -0
- data/lib/capybara/spec/session/element/match_xpath_spec.rb +23 -0
- data/lib/capybara/spec/session/element/matches_selector_spec.rb +106 -0
- data/lib/capybara/spec/session/evaluate_async_script_spec.rb +22 -0
- data/lib/capybara/spec/session/evaluate_script_spec.rb +23 -1
- data/lib/capybara/spec/session/execute_script_spec.rb +22 -3
- data/lib/capybara/spec/session/fill_in_spec.rb +50 -32
- data/lib/capybara/spec/session/find_button_spec.rb +43 -2
- data/lib/capybara/spec/session/find_by_id_spec.rb +3 -2
- data/lib/capybara/spec/session/find_field_spec.rb +42 -6
- data/lib/capybara/spec/session/find_link_spec.rb +22 -3
- data/lib/capybara/spec/session/find_spec.rb +103 -57
- data/lib/capybara/spec/session/first_spec.rb +34 -18
- 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} +44 -2
- data/lib/capybara/spec/session/go_back_spec.rb +2 -1
- data/lib/capybara/spec/session/go_forward_spec.rb +2 -1
- data/lib/capybara/spec/session/has_all_selectors_spec.rb +69 -0
- data/lib/capybara/spec/session/has_button_spec.rb +17 -8
- data/lib/capybara/spec/session/has_css_spec.rb +85 -73
- data/lib/capybara/spec/session/has_current_path_spec.rb +91 -7
- data/lib/capybara/spec/session/has_field_spec.rb +93 -58
- data/lib/capybara/spec/session/has_link_spec.rb +9 -8
- data/lib/capybara/spec/session/has_none_selectors_spec.rb +76 -0
- data/lib/capybara/spec/session/has_select_spec.rb +159 -59
- data/lib/capybara/spec/session/has_selector_spec.rb +64 -28
- data/lib/capybara/spec/session/has_table_spec.rb +1 -0
- data/lib/capybara/spec/session/has_text_spec.rb +27 -12
- data/lib/capybara/spec/session/has_title_spec.rb +22 -4
- data/lib/capybara/spec/session/has_xpath_spec.rb +32 -29
- data/lib/capybara/spec/session/headers.rb +2 -1
- data/lib/capybara/spec/session/html_spec.rb +4 -3
- data/lib/capybara/spec/session/node_spec.rb +198 -38
- data/lib/capybara/spec/session/refresh_spec.rb +28 -0
- data/lib/capybara/spec/session/reset_session_spec.rb +46 -5
- data/lib/capybara/spec/session/response_code.rb +2 -1
- 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 -5
- data/lib/capybara/spec/session/save_page_spec.rb +34 -2
- data/lib/capybara/spec/session/save_screenshot_spec.rb +31 -1
- data/lib/capybara/spec/session/screenshot_spec.rb +4 -2
- data/lib/capybara/spec/session/select_spec.rb +34 -32
- data/lib/capybara/spec/session/selectors_spec.rb +65 -0
- data/lib/capybara/spec/session/sibling_spec.rb +52 -0
- data/lib/capybara/spec/session/text_spec.rb +4 -4
- data/lib/capybara/spec/session/title_spec.rb +2 -1
- data/lib/capybara/spec/session/uncheck_spec.rb +42 -2
- data/lib/capybara/spec/session/unselect_spec.rb +17 -16
- data/lib/capybara/spec/session/visit_spec.rb +77 -2
- data/lib/capybara/spec/session/window/become_closed_spec.rb +12 -11
- 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 +16 -11
- data/lib/capybara/spec/session/window/window_opened_by_spec.rb +7 -4
- data/lib/capybara/spec/session/window/window_spec.rb +36 -29
- data/lib/capybara/spec/session/window/windows_spec.rb +1 -0
- data/lib/capybara/spec/session/window/within_window_spec.rb +31 -7
- data/lib/capybara/spec/session/within_spec.rb +14 -6
- data/lib/capybara/spec/spec_helper.rb +37 -4
- data/lib/capybara/spec/test_app.rb +15 -3
- data/lib/capybara/spec/views/buttons.erb +1 -0
- data/lib/capybara/spec/views/fieldsets.erb +2 -1
- data/lib/capybara/spec/views/form.erb +169 -9
- data/lib/capybara/spec/views/frame_child.erb +10 -2
- data/lib/capybara/spec/views/frame_one.erb +2 -1
- data/lib/capybara/spec/views/frame_parent.erb +3 -2
- data/lib/capybara/spec/views/frame_two.erb +2 -1
- data/lib/capybara/spec/views/header_links.erb +1 -0
- data/lib/capybara/spec/views/host_links.erb +1 -0
- data/lib/capybara/spec/views/initial_alert.erb +10 -0
- data/lib/capybara/spec/views/path.erb +1 -0
- data/lib/capybara/spec/views/popup_one.erb +1 -0
- data/lib/capybara/spec/views/popup_two.erb +1 -0
- data/lib/capybara/spec/views/postback.erb +2 -1
- data/lib/capybara/spec/views/tables.erb +1 -0
- data/lib/capybara/spec/views/with_base_tag.erb +1 -0
- data/lib/capybara/spec/views/with_count.erb +2 -1
- data/lib/capybara/spec/views/with_fixed_header_footer.erb +17 -0
- data/lib/capybara/spec/views/with_hover.erb +7 -1
- data/lib/capybara/spec/views/with_html.erb +40 -2
- data/lib/capybara/spec/views/with_html_entities.erb +1 -0
- data/lib/capybara/spec/views/with_js.erb +32 -1
- data/lib/capybara/spec/views/with_scope.erb +1 -0
- data/lib/capybara/spec/views/with_simple_html.erb +2 -1
- data/lib/capybara/spec/views/with_slow_unload.erb +17 -0
- data/lib/capybara/spec/views/with_title.erb +2 -1
- data/lib/capybara/spec/views/with_unload_alert.erb +14 -0
- data/lib/capybara/spec/views/with_windows.erb +7 -0
- data/lib/capybara/spec/views/within_frames.erb +3 -2
- data/lib/capybara/version.rb +2 -1
- data/lib/capybara/window.rb +20 -3
- data/lib/capybara.rb +189 -93
- data/spec/basic_node_spec.rb +7 -6
- data/spec/capybara_spec.rb +90 -4
- data/spec/dsl_spec.rb +3 -1
- data/spec/filter_set_spec.rb +28 -0
- data/spec/fixtures/capybara.csv +1 -0
- data/spec/fixtures/selenium_driver_rspec_failure.rb +5 -1
- data/spec/fixtures/selenium_driver_rspec_success.rb +5 -1
- data/spec/minitest_spec.rb +130 -0
- data/spec/minitest_spec_spec.rb +135 -0
- data/spec/per_session_config_spec.rb +67 -0
- data/spec/rack_test_spec.rb +50 -7
- data/spec/result_spec.rb +76 -0
- data/spec/rspec/features_spec.rb +21 -8
- data/spec/rspec/scenarios_spec.rb +21 -0
- data/spec/rspec/{matchers_spec.rb → shared_spec_matchers.rb} +160 -54
- data/spec/rspec/views_spec.rb +5 -0
- data/spec/rspec_matchers_spec.rb +46 -0
- data/spec/rspec_spec.rb +79 -1
- data/spec/selector_spec.rb +199 -0
- data/spec/selenium_spec_chrome.rb +54 -9
- data/spec/selenium_spec_firefox.rb +68 -0
- data/spec/selenium_spec_marionette.rb +127 -0
- data/spec/server_spec.rb +102 -14
- data/spec/session_spec.rb +54 -0
- data/spec/shared_selenium_session.rb +215 -0
- data/spec/spec_helper.rb +7 -0
- metadata +140 -15
- data/spec/selenium_spec.rb +0 -128
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
module Capybara
|
|
2
3
|
module Node
|
|
3
4
|
module DocumentMatchers
|
|
@@ -10,17 +11,12 @@ module Capybara
|
|
|
10
11
|
# @overload $0(regexp, options = {})
|
|
11
12
|
# @param regexp [Regexp] The regexp that title should match to
|
|
12
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
|
|
13
15
|
# @raise [Capybara::ExpectationNotMet] if the assertion hasn't succeeded during wait time
|
|
14
16
|
# @return [true]
|
|
15
17
|
#
|
|
16
18
|
def assert_title(title, options = {})
|
|
17
|
-
query
|
|
18
|
-
synchronize(query.wait) do
|
|
19
|
-
unless query.resolves_for?(self)
|
|
20
|
-
raise Capybara::ExpectationNotMet, query.failure_message
|
|
21
|
-
end
|
|
22
|
-
end
|
|
23
|
-
return true
|
|
19
|
+
_verify_title(title,options) { |query| raise Capybara::ExpectationNotMet, query.failure_message unless query.resolves_for?(self) }
|
|
24
20
|
end
|
|
25
21
|
|
|
26
22
|
##
|
|
@@ -31,13 +27,7 @@ module Capybara
|
|
|
31
27
|
# @return [true]
|
|
32
28
|
#
|
|
33
29
|
def assert_no_title(title, options = {})
|
|
34
|
-
query
|
|
35
|
-
synchronize(query.wait) do
|
|
36
|
-
if query.resolves_for?(self)
|
|
37
|
-
raise Capybara::ExpectationNotMet, query.negative_failure_message
|
|
38
|
-
end
|
|
39
|
-
end
|
|
40
|
-
return true
|
|
30
|
+
_verify_title(title,options) { |query| raise Capybara::ExpectationNotMet, query.negative_failure_message if query.resolves_for?(self) }
|
|
41
31
|
end
|
|
42
32
|
|
|
43
33
|
##
|
|
@@ -63,6 +53,17 @@ module Capybara
|
|
|
63
53
|
rescue Capybara::ExpectationNotMet
|
|
64
54
|
return false
|
|
65
55
|
end
|
|
56
|
+
|
|
57
|
+
private
|
|
58
|
+
|
|
59
|
+
def _verify_title(title, options)
|
|
60
|
+
query = Capybara::Queries::TitleQuery.new(title, options)
|
|
61
|
+
synchronize(query.wait) do
|
|
62
|
+
yield(query)
|
|
63
|
+
end
|
|
64
|
+
return true
|
|
65
|
+
end
|
|
66
|
+
|
|
66
67
|
end
|
|
67
68
|
end
|
|
68
69
|
end
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
module Capybara
|
|
2
3
|
module Node
|
|
3
4
|
|
|
@@ -9,7 +10,7 @@ module Capybara
|
|
|
9
10
|
# session = Capybara::Session.new(:rack_test, my_app)
|
|
10
11
|
#
|
|
11
12
|
# bar = session.find('#bar') # from Capybara::Node::Finders
|
|
12
|
-
# bar.select('Baz', :
|
|
13
|
+
# bar.select('Baz', from: 'Quox') # from Capybara::Node::Actions
|
|
13
14
|
#
|
|
14
15
|
# {Capybara::Node::Element} also has access to HTML attributes and other properties of the
|
|
15
16
|
# element:
|
|
@@ -22,10 +23,11 @@ module Capybara
|
|
|
22
23
|
#
|
|
23
24
|
class Element < Base
|
|
24
25
|
|
|
25
|
-
def initialize(session, base,
|
|
26
|
+
def initialize(session, base, query_scope, query)
|
|
26
27
|
super(session, base)
|
|
27
|
-
@
|
|
28
|
+
@query_scope = query_scope
|
|
28
29
|
@query = query
|
|
30
|
+
@allow_reload = false
|
|
29
31
|
end
|
|
30
32
|
|
|
31
33
|
def allow_reload!
|
|
@@ -53,7 +55,7 @@ module Capybara
|
|
|
53
55
|
# @return [String] The text of the element
|
|
54
56
|
#
|
|
55
57
|
def text(type=nil)
|
|
56
|
-
type ||= :all unless
|
|
58
|
+
type ||= :all unless session_options.ignore_hidden_elements or session_options.visible_text_only
|
|
57
59
|
synchronize do
|
|
58
60
|
if type == :all
|
|
59
61
|
base.all_text
|
|
@@ -91,6 +93,7 @@ module Capybara
|
|
|
91
93
|
# @param [String] value The new value
|
|
92
94
|
# @param [Hash{}] options Driver specific options for how to set the value
|
|
93
95
|
#
|
|
96
|
+
# @return [Capybara::Node::Element] The element
|
|
94
97
|
def set(value, options={})
|
|
95
98
|
options ||= {}
|
|
96
99
|
|
|
@@ -107,47 +110,58 @@ module Capybara
|
|
|
107
110
|
base.set(value)
|
|
108
111
|
end
|
|
109
112
|
end
|
|
113
|
+
return self
|
|
110
114
|
end
|
|
111
115
|
|
|
112
116
|
##
|
|
113
117
|
#
|
|
114
118
|
# Select this node if is an option element inside a select tag
|
|
115
119
|
#
|
|
120
|
+
# @return [Capybara::Node::Element] The element
|
|
116
121
|
def select_option
|
|
117
122
|
warn "Attempt to select disabled option: #{value || text}" if disabled?
|
|
118
123
|
synchronize { base.select_option }
|
|
124
|
+
return self
|
|
119
125
|
end
|
|
120
126
|
|
|
121
127
|
##
|
|
122
128
|
#
|
|
123
129
|
# Unselect this node if is an option element inside a multiple select tag
|
|
124
130
|
#
|
|
131
|
+
# @return [Capybara::Node::Element] The element
|
|
125
132
|
def unselect_option
|
|
126
133
|
synchronize { base.unselect_option }
|
|
134
|
+
return self
|
|
127
135
|
end
|
|
128
136
|
|
|
129
137
|
##
|
|
130
138
|
#
|
|
131
139
|
# Click the Element
|
|
132
140
|
#
|
|
141
|
+
# @return [Capybara::Node::Element] The element
|
|
133
142
|
def click
|
|
134
143
|
synchronize { base.click }
|
|
144
|
+
return self
|
|
135
145
|
end
|
|
136
146
|
|
|
137
147
|
##
|
|
138
148
|
#
|
|
139
149
|
# Right Click the Element
|
|
140
150
|
#
|
|
151
|
+
# @return [Capybara::Node::Element] The element
|
|
141
152
|
def right_click
|
|
142
153
|
synchronize { base.right_click }
|
|
154
|
+
return self
|
|
143
155
|
end
|
|
144
156
|
|
|
145
157
|
##
|
|
146
158
|
#
|
|
147
159
|
# Double Click the Element
|
|
148
160
|
#
|
|
161
|
+
# @return [Capybara::Node::Element] The element
|
|
149
162
|
def double_click
|
|
150
163
|
synchronize { base.double_click }
|
|
164
|
+
return self
|
|
151
165
|
end
|
|
152
166
|
|
|
153
167
|
##
|
|
@@ -220,16 +234,20 @@ module Capybara
|
|
|
220
234
|
# :meta
|
|
221
235
|
# :command - alias of :meta
|
|
222
236
|
#
|
|
237
|
+
# @return [Capybara::Node::Element] The element
|
|
223
238
|
def send_keys(*args)
|
|
224
239
|
synchronize { base.send_keys(*args) }
|
|
240
|
+
return self
|
|
225
241
|
end
|
|
226
242
|
|
|
227
243
|
##
|
|
228
244
|
#
|
|
229
245
|
# Hover on the Element
|
|
230
246
|
#
|
|
247
|
+
# @return [Capybara::Node::Element] The element
|
|
231
248
|
def hover
|
|
232
249
|
synchronize { base.hover }
|
|
250
|
+
return self
|
|
233
251
|
end
|
|
234
252
|
|
|
235
253
|
##
|
|
@@ -281,6 +299,26 @@ module Capybara
|
|
|
281
299
|
synchronize { base.disabled? }
|
|
282
300
|
end
|
|
283
301
|
|
|
302
|
+
##
|
|
303
|
+
#
|
|
304
|
+
# Whether or not the element is readonly.
|
|
305
|
+
#
|
|
306
|
+
# @return [Boolean] Whether the element is readonly
|
|
307
|
+
#
|
|
308
|
+
def readonly?
|
|
309
|
+
synchronize { base.readonly? }
|
|
310
|
+
end
|
|
311
|
+
|
|
312
|
+
##
|
|
313
|
+
#
|
|
314
|
+
# Whether or not the element supports multiple results.
|
|
315
|
+
#
|
|
316
|
+
# @return [Boolean] Whether the element supports multiple results.
|
|
317
|
+
#
|
|
318
|
+
def multiple?
|
|
319
|
+
synchronize { base.multiple? }
|
|
320
|
+
end
|
|
321
|
+
|
|
284
322
|
##
|
|
285
323
|
#
|
|
286
324
|
# An XPath expression describing where on the page the element can be found
|
|
@@ -298,8 +336,10 @@ module Capybara
|
|
|
298
336
|
#
|
|
299
337
|
# @param [String] event The name of the event to trigger
|
|
300
338
|
#
|
|
339
|
+
# @return [Capybara::Node::Element] The element
|
|
301
340
|
def trigger(event)
|
|
302
341
|
synchronize { base.trigger(event) }
|
|
342
|
+
return self
|
|
303
343
|
end
|
|
304
344
|
|
|
305
345
|
##
|
|
@@ -312,14 +352,16 @@ module Capybara
|
|
|
312
352
|
#
|
|
313
353
|
# @param [Capybara::Node::Element] node The element to drag to
|
|
314
354
|
#
|
|
355
|
+
# @return [Capybara::Node::Element] The element
|
|
315
356
|
def drag_to(node)
|
|
316
357
|
synchronize { base.drag_to(node.base) }
|
|
358
|
+
return self
|
|
317
359
|
end
|
|
318
360
|
|
|
319
361
|
def reload
|
|
320
362
|
if @allow_reload
|
|
321
363
|
begin
|
|
322
|
-
reloaded =
|
|
364
|
+
reloaded = query_scope.reload.first(@query.name, @query.locator, @query.options)
|
|
323
365
|
@base = reloaded.base if reloaded
|
|
324
366
|
rescue => e
|
|
325
367
|
raise e unless catch_error?(e)
|
|
@@ -329,9 +371,15 @@ module Capybara
|
|
|
329
371
|
end
|
|
330
372
|
|
|
331
373
|
def inspect
|
|
332
|
-
%(#<Capybara::Node::Element tag="#{tag_name}" path="#{path}">)
|
|
374
|
+
%(#<Capybara::Node::Element tag="#{base.tag_name}" path="#{base.path}">)
|
|
333
375
|
rescue NotSupportedByDriverError
|
|
334
|
-
%(#<Capybara::Node::Element tag="#{tag_name}">)
|
|
376
|
+
%(#<Capybara::Node::Element tag="#{base.tag_name}">)
|
|
377
|
+
rescue => e
|
|
378
|
+
if session.driver.invalid_element_errors.any? { |et| e.is_a?(et)}
|
|
379
|
+
%(Obsolete #<Capybara::Node::Element>)
|
|
380
|
+
else
|
|
381
|
+
raise
|
|
382
|
+
end
|
|
335
383
|
end
|
|
336
384
|
end
|
|
337
385
|
end
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
module Capybara
|
|
2
3
|
module Node
|
|
3
4
|
module Finders
|
|
@@ -17,8 +18,8 @@ module Capybara
|
|
|
17
18
|
# +find+ takes the same options as +all+.
|
|
18
19
|
#
|
|
19
20
|
# page.find('#foo').find('.bar')
|
|
20
|
-
# page.find(:xpath, '
|
|
21
|
-
# page.find('li', :
|
|
21
|
+
# page.find(:xpath, './/div[contains(., "bar")]')
|
|
22
|
+
# page.find('li', text: 'Quox').click_link('Delete')
|
|
22
23
|
#
|
|
23
24
|
# @param (see Capybara::Node::Finders#all)
|
|
24
25
|
#
|
|
@@ -27,43 +28,104 @@ module Capybara
|
|
|
27
28
|
# @return [Capybara::Node::Element] The found element
|
|
28
29
|
# @raise [Capybara::ElementNotFound] If the element can't be found before time expires
|
|
29
30
|
#
|
|
30
|
-
def find(*args)
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
result = query.resolve_for(self)
|
|
38
|
-
end
|
|
39
|
-
if query.match == :one or query.match == :smart and result.size > 1
|
|
40
|
-
raise Capybara::Ambiguous.new("Ambiguous match, found #{result.size} elements matching #{query.description}")
|
|
41
|
-
end
|
|
42
|
-
if result.size == 0
|
|
43
|
-
raise Capybara::ElementNotFound.new("Unable to find #{query.description}")
|
|
44
|
-
end
|
|
45
|
-
result.first
|
|
46
|
-
end.tap(&:allow_reload!)
|
|
31
|
+
def find(*args, &optional_filter_block)
|
|
32
|
+
if args.last.is_a? Hash
|
|
33
|
+
args.last[:session_options] = session_options
|
|
34
|
+
else
|
|
35
|
+
args.push(session_options: session_options)
|
|
36
|
+
end
|
|
37
|
+
synced_resolve Capybara::Queries::SelectorQuery.new(*args, &optional_filter_block)
|
|
47
38
|
end
|
|
48
39
|
|
|
49
40
|
##
|
|
50
41
|
#
|
|
51
|
-
# Find
|
|
42
|
+
# Find an {Capybara::Node::Element} based on the given arguments that is also an ancestor of the element called on. +ancestor+ will raise an error if the element
|
|
43
|
+
# is not found.
|
|
44
|
+
#
|
|
45
|
+
# +ancestor+ takes the same options as +find+.
|
|
46
|
+
#
|
|
47
|
+
# element.ancestor('#foo').find('.bar')
|
|
48
|
+
# element.ancestor(:xpath, './/div[contains(., "bar")]')
|
|
49
|
+
# element.ancestor('ul', text: 'Quox').click_link('Delete')
|
|
50
|
+
#
|
|
51
|
+
# @param (see Capybara::Node::Finders#find)
|
|
52
|
+
#
|
|
53
|
+
# @!macro waiting_behavior
|
|
54
|
+
#
|
|
55
|
+
# @option options [Boolean] match The matching strategy to use.
|
|
56
|
+
#
|
|
57
|
+
# @return [Capybara::Node::Element] The found element
|
|
58
|
+
# @raise [Capybara::ElementNotFound] If the element can't be found before time expires
|
|
59
|
+
#
|
|
60
|
+
def ancestor(*args, &optional_filter_block)
|
|
61
|
+
if args.last.is_a? Hash
|
|
62
|
+
args.last[:session_options] = session_options
|
|
63
|
+
else
|
|
64
|
+
args.push(session_options: session_options)
|
|
65
|
+
end
|
|
66
|
+
synced_resolve Capybara::Queries::AncestorQuery.new(*args, &optional_filter_block)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
##
|
|
70
|
+
#
|
|
71
|
+
# Find an {Capybara::Node::Element} based on the given arguments that is also a sibling of the element called on. +sibling+ will raise an error if the element
|
|
72
|
+
# is not found.
|
|
73
|
+
#
|
|
74
|
+
#
|
|
75
|
+
# +sibling+ takes the same options as +find+.
|
|
76
|
+
#
|
|
77
|
+
# element.sibling('#foo').find('.bar')
|
|
78
|
+
# element.sibling(:xpath, './/div[contains(., "bar")]')
|
|
79
|
+
# element.sibling('ul', text: 'Quox').click_link('Delete')
|
|
80
|
+
#
|
|
81
|
+
# @param (see Capybara::Node::Finders#find)
|
|
52
82
|
#
|
|
53
83
|
# @macro waiting_behavior
|
|
54
84
|
#
|
|
55
|
-
# @
|
|
85
|
+
# @option options [Boolean] match The matching strategy to use.
|
|
86
|
+
#
|
|
87
|
+
# @return [Capybara::Node::Element] The found element
|
|
88
|
+
# @raise [Capybara::ElementNotFound] If the element can't be found before time expires
|
|
89
|
+
#
|
|
90
|
+
def sibling(*args, &optional_filter_block)
|
|
91
|
+
if args.last.is_a? Hash
|
|
92
|
+
args.last[:session_options] = session_options
|
|
93
|
+
else
|
|
94
|
+
args.push(session_options: session_options)
|
|
95
|
+
end
|
|
96
|
+
synced_resolve Capybara::Queries::SiblingQuery.new(*args, &optional_filter_block)
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
##
|
|
100
|
+
#
|
|
101
|
+
# Find a form field on the page. The field can be found by its name, id or label text.
|
|
56
102
|
#
|
|
57
|
-
# @
|
|
58
|
-
#
|
|
59
|
-
#
|
|
60
|
-
#
|
|
61
|
-
#
|
|
62
|
-
#
|
|
103
|
+
# @overload find_field([locator], options={})
|
|
104
|
+
# @param [String] locator name, id, placeholder or text of associated label element
|
|
105
|
+
#
|
|
106
|
+
# @macro waiting_behavior
|
|
107
|
+
#
|
|
108
|
+
#
|
|
109
|
+
# @option options [Boolean] checked Match checked field?
|
|
110
|
+
# @option options [Boolean] unchecked Match unchecked field?
|
|
111
|
+
# @option options [Boolean, Symbol] disabled (false) Match disabled field?
|
|
112
|
+
# * true - only finds a disabled field
|
|
113
|
+
# * false - only finds an enabled field
|
|
114
|
+
# * :all - finds either an enabled or disabled field
|
|
115
|
+
# @option options [Boolean] readonly Match readonly field?
|
|
116
|
+
# @option options [String, Regexp] with Value of field to match on
|
|
117
|
+
# @option options [String] type Type of field to match on
|
|
118
|
+
# @option options [Boolean] multiple Match fields that can have multiple values?
|
|
119
|
+
# @option options [String] id Match fields that match the id attribute
|
|
120
|
+
# @option options [String] name Match fields that match the name attribute
|
|
121
|
+
# @option options [String] placeholder Match fields that match the placeholder attribute
|
|
122
|
+
# @option options [String, Array<String>] Match fields that match the class(es) passed
|
|
63
123
|
# @return [Capybara::Node::Element] The found element
|
|
64
124
|
#
|
|
65
|
-
|
|
66
|
-
|
|
125
|
+
|
|
126
|
+
def find_field(locator=nil, options={}, &optional_filter_block)
|
|
127
|
+
locator, options = nil, locator if locator.is_a? Hash
|
|
128
|
+
find(:field, locator, options, &optional_filter_block)
|
|
67
129
|
end
|
|
68
130
|
alias_method :field_labeled, :find_field
|
|
69
131
|
|
|
@@ -71,14 +133,21 @@ module Capybara
|
|
|
71
133
|
#
|
|
72
134
|
# Find a link on the page. The link can be found by its id or text.
|
|
73
135
|
#
|
|
74
|
-
# @
|
|
136
|
+
# @overload find_link([locator], options={})
|
|
137
|
+
# @param [String] locator id, title, text, or alt of enclosed img element
|
|
138
|
+
#
|
|
139
|
+
# @macro waiting_behavior
|
|
75
140
|
#
|
|
76
|
-
#
|
|
77
|
-
#
|
|
141
|
+
# @option options [String,Regexp,nil] href Value to match against the links href, if nil finds link placeholders (<a> elements with no href attribute)
|
|
142
|
+
# @option options [String] id Match links with the id provided
|
|
143
|
+
# @option options [String] title Match links with the title provided
|
|
144
|
+
# @option options [String] alt Match links with a contained img element whose alt matches
|
|
145
|
+
# @option options [String, Array<String>] class Match links that match the class(es) provided
|
|
78
146
|
# @return [Capybara::Node::Element] The found element
|
|
79
147
|
#
|
|
80
|
-
def find_link(locator, options={})
|
|
81
|
-
|
|
148
|
+
def find_link(locator=nil, options={}, &optional_filter_block)
|
|
149
|
+
locator, options = nil, locator if locator.is_a? Hash
|
|
150
|
+
find(:link, locator, options, &optional_filter_block)
|
|
82
151
|
end
|
|
83
152
|
|
|
84
153
|
##
|
|
@@ -87,15 +156,27 @@ module Capybara
|
|
|
87
156
|
# This can be any \<input> element of type submit, reset, image, button or it can be a
|
|
88
157
|
# \<button> element. All buttons can be found by their id, value, or title. \<button> elements can also be found
|
|
89
158
|
# by their text content, and image \<input> elements by their alt attribute
|
|
90
|
-
|
|
91
|
-
# @macro waiting_behavior
|
|
92
159
|
#
|
|
93
|
-
# @
|
|
94
|
-
#
|
|
160
|
+
# @overload find_button([locator], options={})
|
|
161
|
+
# @param [String] locator id, value, title, text content, alt of image
|
|
162
|
+
#
|
|
163
|
+
# @overload find_button(options={})
|
|
164
|
+
#
|
|
165
|
+
# @macro waiting_behavior
|
|
166
|
+
#
|
|
167
|
+
# @option options [Boolean, Symbol] disabled (false) Match disabled button?
|
|
168
|
+
# * true - only finds a disabled button
|
|
169
|
+
# * false - only finds an enabled button
|
|
170
|
+
# * :all - finds either an enabled or disabled button
|
|
171
|
+
# @option options [String] id Match buttons with the id provided
|
|
172
|
+
# @option options [String] title Match buttons with the title provided
|
|
173
|
+
# @option options [String] value Match buttons with the value provided
|
|
174
|
+
# @option options [String, Array<String>] class Match buttons that match the class(es) provided
|
|
95
175
|
# @return [Capybara::Node::Element] The found element
|
|
96
176
|
#
|
|
97
|
-
def find_button(locator, options={})
|
|
98
|
-
|
|
177
|
+
def find_button(locator=nil, options={}, &optional_filter_block)
|
|
178
|
+
locator, options = nil, locator if locator.is_a? Hash
|
|
179
|
+
find(:button, locator, options, &optional_filter_block)
|
|
99
180
|
end
|
|
100
181
|
|
|
101
182
|
##
|
|
@@ -104,15 +185,16 @@ module Capybara
|
|
|
104
185
|
#
|
|
105
186
|
# @macro waiting_behavior
|
|
106
187
|
#
|
|
107
|
-
# @param [String] id
|
|
188
|
+
# @param [String] id id of element
|
|
108
189
|
#
|
|
109
190
|
# @return [Capybara::Node::Element] The found element
|
|
110
191
|
#
|
|
111
|
-
def find_by_id(id, options={})
|
|
112
|
-
find(:id, id, options)
|
|
192
|
+
def find_by_id(id, options={}, &optional_filter_block)
|
|
193
|
+
find(:id, id, options, &optional_filter_block)
|
|
113
194
|
end
|
|
114
195
|
|
|
115
196
|
##
|
|
197
|
+
# @!method all([kind = Capybara.default_selector], locator = nil, options = {})
|
|
116
198
|
#
|
|
117
199
|
# Find all elements on the page matching the given selector
|
|
118
200
|
# and options.
|
|
@@ -122,7 +204,7 @@ module Capybara
|
|
|
122
204
|
# following statements are equivalent:
|
|
123
205
|
#
|
|
124
206
|
# page.all(:css, 'a#person_123')
|
|
125
|
-
# page.all(:xpath, '
|
|
207
|
+
# page.all(:xpath, './/a[@id="person_123"]')
|
|
126
208
|
#
|
|
127
209
|
#
|
|
128
210
|
# If the type of selector is left out, Capybara uses
|
|
@@ -131,47 +213,56 @@ module Capybara
|
|
|
131
213
|
# page.all("a#person_123")
|
|
132
214
|
#
|
|
133
215
|
# Capybara.default_selector = :xpath
|
|
134
|
-
# page.all('
|
|
216
|
+
# page.all('.//a[@id="person_123"]')
|
|
135
217
|
#
|
|
136
218
|
# The set of found elements can further be restricted by specifying
|
|
137
219
|
# options. It's possible to select elements by their text or visibility:
|
|
138
220
|
#
|
|
139
|
-
# page.all('a', :
|
|
140
|
-
# page.all('#menu li', :
|
|
221
|
+
# page.all('a', text: 'Home')
|
|
222
|
+
# page.all('#menu li', visible: true)
|
|
141
223
|
#
|
|
142
224
|
# By default if no elements are found, an empty array is returned;
|
|
143
225
|
# however, expectations can be set on the number of elements to be found which
|
|
144
226
|
# will trigger Capybara's waiting behavior for the expectations to match.The
|
|
145
227
|
# expectations can be set using
|
|
146
228
|
#
|
|
147
|
-
# page.assert_selector('p#foo', :
|
|
148
|
-
# page.assert_selector('p#foo', :
|
|
149
|
-
# page.assert_selector('p#foo', :
|
|
150
|
-
# page.assert_selector('p#foo', :
|
|
229
|
+
# page.assert_selector('p#foo', count: 4)
|
|
230
|
+
# page.assert_selector('p#foo', maximum: 10)
|
|
231
|
+
# page.assert_selector('p#foo', minimum: 1)
|
|
232
|
+
# page.assert_selector('p#foo', between: 1..10)
|
|
151
233
|
#
|
|
152
234
|
# See {Capybara::Helpers#matches_count?} for additional information about
|
|
153
235
|
# count matching.
|
|
154
236
|
#
|
|
155
|
-
# @
|
|
156
|
-
#
|
|
157
|
-
#
|
|
158
|
-
#
|
|
159
|
-
#
|
|
237
|
+
# @param [Symbol] kind Optional selector type (:css, :xpath, :field, etc.) - Defaults to Capybara.default_selector
|
|
238
|
+
# @param [String] locator The selector
|
|
239
|
+
# @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 string the elements contained text must match exactly, when Boolean controls whether the :text option must match exactly
|
|
241
|
+
# @option options [Boolean, Symbol] visible Only find elements with the specified visibility:
|
|
160
242
|
# * true - only finds visible elements.
|
|
161
243
|
# * false - finds invisible _and_ visible elements.
|
|
162
244
|
# * :all - same as false; finds visible and invisible elements.
|
|
163
245
|
# * :hidden - only finds invisible elements.
|
|
164
246
|
# * :visible - same as true; only finds visible elements.
|
|
165
|
-
#
|
|
166
|
-
#
|
|
167
|
-
#
|
|
168
|
-
#
|
|
169
|
-
#
|
|
170
|
-
#
|
|
247
|
+
# @option options [Integer] count Exact number of matches that are expected to be found
|
|
248
|
+
# @option options [Integer] maximum Maximum number of matches that are expected to be found
|
|
249
|
+
# @option options [Integer] minimum Minimum number of matches that are expected to be found
|
|
250
|
+
# @option options [Range] between Number of matches found must be within the given range
|
|
251
|
+
# @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 element count expectations to become true
|
|
253
|
+
# @overload all([kind = Capybara.default_selector], locator = nil, options = {})
|
|
254
|
+
# @overload all([kind = Capybara.default_selector], locator = nil, options = {}, &filter_block)
|
|
255
|
+
# @yieldparam element [Capybara::Node::Element] The element being considered for inclusion in the results
|
|
256
|
+
# @yieldreturn [Boolean] Should the element be considered in the results?
|
|
171
257
|
# @return [Capybara::Result] A collection of found elements
|
|
172
258
|
#
|
|
173
|
-
def all(*args)
|
|
174
|
-
|
|
259
|
+
def all(*args, &optional_filter_block)
|
|
260
|
+
if args.last.is_a? Hash
|
|
261
|
+
args.last[:session_options] = session_options
|
|
262
|
+
else
|
|
263
|
+
args.push(session_options: session_options)
|
|
264
|
+
end
|
|
265
|
+
query = Capybara::Queries::SelectorQuery.new(*args, &optional_filter_block)
|
|
175
266
|
synchronize(query.wait) do
|
|
176
267
|
result = query.resolve_for(self)
|
|
177
268
|
raise Capybara::ExpectationNotMet, result.failure_message unless result.matches_count?
|
|
@@ -195,15 +286,36 @@ module Capybara
|
|
|
195
286
|
# @param [Hash] options Additional options; see {#all}
|
|
196
287
|
# @return [Capybara::Node::Element] The found element or nil
|
|
197
288
|
#
|
|
198
|
-
def first(*args)
|
|
199
|
-
if
|
|
289
|
+
def first(*args, &optional_filter_block)
|
|
290
|
+
if session_options.wait_on_first_by_default
|
|
200
291
|
options = if args.last.is_a?(Hash) then args.pop.dup else {} end
|
|
201
292
|
args.push({minimum: 1}.merge(options))
|
|
202
293
|
end
|
|
203
|
-
all(*args).first
|
|
294
|
+
all(*args, &optional_filter_block).first
|
|
204
295
|
rescue Capybara::ExpectationNotMet
|
|
205
296
|
nil
|
|
206
297
|
end
|
|
298
|
+
|
|
299
|
+
private
|
|
300
|
+
|
|
301
|
+
def synced_resolve(query)
|
|
302
|
+
synchronize(query.wait) do
|
|
303
|
+
if (query.match == :smart or query.match == :prefer_exact)
|
|
304
|
+
result = query.resolve_for(self, true)
|
|
305
|
+
result = query.resolve_for(self, false) if result.empty? && query.supports_exact? && !query.exact?
|
|
306
|
+
else
|
|
307
|
+
result = query.resolve_for(self)
|
|
308
|
+
end
|
|
309
|
+
|
|
310
|
+
if query.match == :one or query.match == :smart and result.size > 1
|
|
311
|
+
raise Capybara::Ambiguous.new("Ambiguous match, found #{result.size} elements matching #{query.description}")
|
|
312
|
+
end
|
|
313
|
+
if result.empty?
|
|
314
|
+
raise Capybara::ElementNotFound.new("Unable to find #{query.description}")
|
|
315
|
+
end
|
|
316
|
+
result.first
|
|
317
|
+
end.tap(&:allow_reload!)
|
|
318
|
+
end
|
|
207
319
|
end
|
|
208
320
|
end
|
|
209
321
|
end
|