capybara 2.18.0 → 3.0.0.rc1
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 +26 -1
- data/README.md +12 -12
- data/lib/capybara.rb +13 -25
- data/lib/capybara/config.rb +11 -57
- data/lib/capybara/cucumber.rb +2 -3
- data/lib/capybara/driver/base.rb +5 -16
- data/lib/capybara/driver/node.rb +5 -4
- data/lib/capybara/dsl.rb +1 -0
- data/lib/capybara/helpers.rb +16 -28
- data/lib/capybara/minitest.rb +139 -138
- data/lib/capybara/minitest/spec.rb +15 -14
- data/lib/capybara/node/actions.rb +59 -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 +48 -71
- data/lib/capybara/node/simple.rb +11 -17
- data/lib/capybara/queries/ancestor_query.rb +4 -6
- data/lib/capybara/queries/base_query.rb +18 -17
- 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 +37 -34
- 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 +70 -56
- data/lib/capybara/rails.rb +2 -6
- data/lib/capybara/result.rb +22 -22
- data/lib/capybara/rspec.rb +5 -10
- 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 -60
- data/lib/capybara/selector.rb +129 -117
- data/lib/capybara/selector/css.rb +6 -11
- data/lib/capybara/selector/filter.rb +1 -17
- data/lib/capybara/selector/filter_set.rb +17 -14
- 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 +27 -33
- data/lib/capybara/selenium/driver.rb +113 -127
- data/lib/capybara/selenium/node.rb +148 -113
- data/lib/capybara/server.rb +3 -2
- data/lib/capybara/session.rb +137 -223
- data/lib/capybara/session/config.rb +47 -67
- data/lib/capybara/session/matchers.rb +8 -7
- data/lib/capybara/spec/public/test.js +26 -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 +2 -4
- 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 +18 -17
- data/lib/capybara/spec/session/assert_title.rb +1 -0
- data/lib/capybara/spec/session/attach_file_spec.rb +14 -13
- 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 +20 -28
- 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 +7 -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 +6 -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 +8 -14
- 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/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 +6 -5
- 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 +4 -2
- data/lib/capybara/spec/session/reset_session_spec.rb +1 -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 +1 -1
- 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 +1 -0
- data/lib/capybara/spec/session/title_spec.rb +1 -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 +13 -68
- data/lib/capybara/spec/session/within_spec.rb +1 -0
- data/lib/capybara/spec/spec_helper.rb +26 -18
- data/lib/capybara/spec/test_app.rb +8 -9
- data/lib/capybara/spec/views/form.erb +1 -0
- data/lib/capybara/spec/views/with_html.erb +3 -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/spec/basic_node_spec.rb +1 -0
- data/spec/capybara_spec.rb +9 -32
- 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 +19 -2
- data/spec/rspec_spec.rb +11 -15
- data/spec/selector_spec.rb +5 -6
- data/spec/selenium_spec_chrome.rb +7 -4
- data/spec/selenium_spec_marionette.rb +26 -12
- data/spec/server_spec.rb +33 -33
- data/spec/session_spec.rb +2 -1
- data/spec/shared_selenium_session.rb +27 -21
- data/spec/spec_helper.rb +2 -5
- metadata +66 -87
- data/lib/capybara/query.rb +0 -7
- data/spec/selenium_spec_firefox.rb +0 -68
@@ -3,32 +3,34 @@ require 'minitest/spec'
|
|
3
3
|
module Capybara
|
4
4
|
module Minitest
|
5
5
|
module Expectations
|
6
|
-
%w
|
6
|
+
%w[text content title current_path].each do |assertion|
|
7
7
|
infect_an_assertion "assert_#{assertion}", "must_have_#{assertion}", :reverse
|
8
8
|
infect_an_assertion "refute_#{assertion}", "wont_have_#{assertion}", :reverse
|
9
9
|
end
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
11
|
+
# rubocop:disable Style/MultilineBlockChain
|
12
|
+
(%w[selector xpath css link button field select table checked_field unchecked_field].flat_map do |assertion|
|
13
|
+
[%W[assert_#{assertion} must_have_#{assertion}],
|
14
|
+
%W[refute_#{assertion} wont_have_#{assertion}]]
|
15
|
+
end + [%w[assert_all_of_selectors must_have_all_of_selectors],
|
16
|
+
%w[assert_none_of_selectors must_have_none_of_selectors]] +
|
17
|
+
%w[selector xpath css].flat_map do |assertion|
|
18
|
+
[%W[assert_matches_#{assertion} must_match_#{assertion}],
|
19
|
+
%W[refute_matches_#{assertion} wont_match_#{assertion}]]
|
19
20
|
end).each do |(meth, new_name)|
|
20
|
-
|
21
|
+
class_eval <<-ASSERTION, __FILE__, __LINE__ + 1
|
21
22
|
def #{new_name} *args, &block
|
22
23
|
::Minitest::Expectation.new(self, ::Minitest::Spec.current).#{new_name}(*args, &block)
|
23
24
|
end
|
24
|
-
|
25
|
+
ASSERTION
|
25
26
|
|
26
|
-
::Minitest::Expectation.class_eval <<-
|
27
|
+
::Minitest::Expectation.class_eval <<-ASSERTION, __FILE__, __LINE__ + 1
|
27
28
|
def #{new_name} *args, &block
|
28
29
|
ctx.#{meth}(target, *args, &block)
|
29
30
|
end
|
30
|
-
|
31
|
+
ASSERTION
|
31
32
|
end
|
33
|
+
# rubocop:enable Style/MultilineBlockChain
|
32
34
|
|
33
35
|
##
|
34
36
|
# Expectation that there is xpath
|
@@ -159,7 +161,6 @@ module Capybara
|
|
159
161
|
#
|
160
162
|
# @!method wont_have_current_path
|
161
163
|
# see {Capybara::SessionMatchers#assert_no_current_path}
|
162
|
-
|
163
164
|
end
|
164
165
|
end
|
165
166
|
end
|
@@ -1,8 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module Capybara
|
3
4
|
module Node
|
4
5
|
module Actions
|
5
|
-
|
6
6
|
##
|
7
7
|
#
|
8
8
|
# Finds a button or link and clicks it. See {Capybara::Node::Actions#click_button} and
|
@@ -20,8 +20,7 @@ module Capybara
|
|
20
20
|
#
|
21
21
|
# @return [Capybara::Node::Element] The element clicked
|
22
22
|
#
|
23
|
-
def click_link_or_button(locator=nil, options
|
24
|
-
locator, options = nil, locator if locator.is_a? Hash
|
23
|
+
def click_link_or_button(locator = nil, **options)
|
25
24
|
find(:link_or_button, locator, options).click
|
26
25
|
end
|
27
26
|
alias_method :click_on, :click_link_or_button
|
@@ -38,8 +37,7 @@ module Capybara
|
|
38
37
|
# @param options See {Capybara::Node::Finders#find_link}
|
39
38
|
#
|
40
39
|
# @return [Capybara::Node::Element] The element clicked
|
41
|
-
def click_link(locator=nil, options
|
42
|
-
locator, options = nil, locator if locator.is_a? Hash
|
40
|
+
def click_link(locator = nil, **options)
|
43
41
|
find(:link, locator, options).click
|
44
42
|
end
|
45
43
|
|
@@ -56,8 +54,7 @@ module Capybara
|
|
56
54
|
# @param [String] locator Which button to find
|
57
55
|
# @param options See {Capybara::Node::Finders#find_button}
|
58
56
|
# @return [Capybara::Node::Element] The element clicked
|
59
|
-
def click_button(locator=nil, options
|
60
|
-
locator, options = nil, locator if locator.is_a? Hash
|
57
|
+
def click_button(locator = nil, **options)
|
61
58
|
find(:button, locator, options).click
|
62
59
|
end
|
63
60
|
|
@@ -83,12 +80,8 @@ module Capybara
|
|
83
80
|
# @option options [String, Array<String>] :class Match fields that match the class(es) provided
|
84
81
|
#
|
85
82
|
# @return [Capybara::Node::Element] The element filled_in
|
86
|
-
def fill_in(locator,
|
87
|
-
|
88
|
-
raise "Must pass a hash containing 'with'" if not options.is_a?(Hash) or not options.has_key?(:with)
|
89
|
-
with = options.delete(:with)
|
90
|
-
fill_options = options.delete(:fill_options)
|
91
|
-
options[:with] = options.delete(:currently_with) if options.has_key?(:currently_with)
|
83
|
+
def fill_in(locator = nil, with:, fill_options: {}, **options)
|
84
|
+
options[:with] = options.delete(:currently_with) if options.key?(:currently_with)
|
92
85
|
find(:fillable_field, locator, options).set(with, fill_options)
|
93
86
|
end
|
94
87
|
|
@@ -113,8 +106,8 @@ module Capybara
|
|
113
106
|
# @macro label_click
|
114
107
|
#
|
115
108
|
# @return [Capybara::Node::Element] The element chosen or the label clicked
|
116
|
-
def choose(locator, options
|
117
|
-
_check_with_label(:radio_button, true, locator, options)
|
109
|
+
def choose(locator = nil, **options)
|
110
|
+
_check_with_label(:radio_button, true, locator, **options)
|
118
111
|
end
|
119
112
|
|
120
113
|
##
|
@@ -136,8 +129,8 @@ module Capybara
|
|
136
129
|
# @macro waiting_behavior
|
137
130
|
#
|
138
131
|
# @return [Capybara::Node::Element] The element checked or the label clicked
|
139
|
-
def check(locator, options
|
140
|
-
_check_with_label(:checkbox, true, locator, options)
|
132
|
+
def check(locator, **options)
|
133
|
+
_check_with_label(:checkbox, true, locator, **options)
|
141
134
|
end
|
142
135
|
|
143
136
|
##
|
@@ -159,8 +152,8 @@ module Capybara
|
|
159
152
|
# @macro waiting_behavior
|
160
153
|
#
|
161
154
|
# @return [Capybara::Node::Element] The element unchecked or the label clicked
|
162
|
-
def uncheck(locator, options
|
163
|
-
_check_with_label(:checkbox, false, locator, options)
|
155
|
+
def uncheck(locator = nil, **options)
|
156
|
+
_check_with_label(:checkbox, false, locator, **options)
|
164
157
|
end
|
165
158
|
|
166
159
|
##
|
@@ -180,13 +173,9 @@ module Capybara
|
|
180
173
|
# @option options [String] :from The id, name or label of the select box
|
181
174
|
#
|
182
175
|
# @return [Capybara::Node::Element] The option element selected
|
183
|
-
def select(value, options
|
184
|
-
|
185
|
-
|
186
|
-
find(:select, from, options).find(:option, value, options).select_option
|
187
|
-
else
|
188
|
-
find(:option, value, options).select_option
|
189
|
-
end
|
176
|
+
def select(value = nil, from: nil, **options)
|
177
|
+
scope = from ? find(:select, from, options) : self
|
178
|
+
scope.find(:option, value, options).select_option
|
190
179
|
end
|
191
180
|
|
192
181
|
##
|
@@ -203,13 +192,9 @@ module Capybara
|
|
203
192
|
# @param [Hash{:from => String}] options The id, name or label of the select box
|
204
193
|
#
|
205
194
|
# @return [Capybara::Node::Element] The option element unselected
|
206
|
-
def unselect(value, options
|
207
|
-
|
208
|
-
|
209
|
-
find(:select, from, options).find(:option, value, options).unselect_option
|
210
|
-
else
|
211
|
-
find(:option, value, options).unselect_option
|
212
|
-
end
|
195
|
+
def unselect(value = nil, from: nil, **options)
|
196
|
+
scope = from ? find(:select, from, options) : self
|
197
|
+
scope.find(:option, value, options).unselect_option
|
213
198
|
end
|
214
199
|
|
215
200
|
##
|
@@ -233,68 +218,44 @@ module Capybara
|
|
233
218
|
# @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)
|
234
219
|
#
|
235
220
|
# @return [Capybara::Node::Element] The file field element
|
236
|
-
def attach_file(locator, path, options
|
237
|
-
locator, path, options = nil, locator, path if path.is_a? Hash
|
221
|
+
def attach_file(locator = nil, path, make_visible: nil, **options) # rubocop:disable Style/OptionalArguments
|
238
222
|
Array(path).each do |p|
|
239
223
|
raise Capybara::FileNotFound, "cannot attach file, #{p} does not exist" unless File.exist?(p.to_s)
|
240
224
|
end
|
241
225
|
# Allow user to update the CSS style of the file input since they are so often hidden on a page
|
242
|
-
if
|
243
|
-
|
244
|
-
ff
|
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
|
226
|
+
if make_visible
|
227
|
+
ff = find(:file_field, locator, options.merge(visible: :all))
|
228
|
+
while_visible(ff, make_visible) { |el| el.set(path) }
|
255
229
|
else
|
256
230
|
find(:file_field, locator, options).set(path)
|
257
231
|
end
|
258
232
|
end
|
259
233
|
|
260
234
|
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
235
|
|
279
|
-
def
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
el.style.cssText = el.capybara_style_cache;
|
284
|
-
delete el.capybara_style_cache;
|
285
|
-
}
|
286
|
-
JS
|
236
|
+
def while_visible(element, visible_css)
|
237
|
+
visible_css = { opacity: 1, display: 'block', visibility: 'visible' } if visible_css == true
|
238
|
+
_update_style(element, visible_css)
|
239
|
+
raise ExpectationNotMet, "The style changes in :make_visible did not make the file input visible" unless element.visible?
|
287
240
|
begin
|
288
|
-
|
289
|
-
|
241
|
+
yield element
|
242
|
+
ensure
|
243
|
+
_reset_style(element)
|
290
244
|
end
|
291
245
|
end
|
292
246
|
|
247
|
+
def _update_style(element, style)
|
248
|
+
session.execute_script(UPDATE_STYLE_SCRIPT, element, style)
|
249
|
+
rescue Capybara::NotSupportedByDriverError
|
250
|
+
warn "The :make_visible option is not supported by the current driver - ignoring"
|
251
|
+
end
|
293
252
|
|
294
|
-
def
|
295
|
-
|
296
|
-
|
253
|
+
def _reset_style(element)
|
254
|
+
session.execute_script(RESET_STYLE_SCRIPT, element)
|
255
|
+
rescue # swallow extra errors
|
256
|
+
end
|
297
257
|
|
258
|
+
def _check_with_label(selector, checked, locator, allow_label_click: session_options.automatic_label_click, **options)
|
298
259
|
synchronize(Capybara::Queries::BaseQuery.wait(options, session_options.default_max_wait_time)) do
|
299
260
|
begin
|
300
261
|
el = find(selector, locator, options)
|
@@ -303,15 +264,32 @@ module Capybara
|
|
303
264
|
raise unless allow_label_click && catch_error?(e)
|
304
265
|
begin
|
305
266
|
el ||= find(selector, locator, options.merge(visible: :all))
|
306
|
-
|
307
|
-
|
308
|
-
rescue
|
267
|
+
find(:label, for: el, visible: true).click unless el.checked? == checked
|
268
|
+
rescue # swallow extra errors - raise original
|
309
269
|
raise e
|
310
270
|
end
|
311
271
|
end
|
312
272
|
end
|
313
273
|
end
|
314
274
|
|
275
|
+
UPDATE_STYLE_SCRIPT = <<-'JS'.freeze
|
276
|
+
var el = arguments[0];
|
277
|
+
el.capybara_style_cache = el.style.cssText;
|
278
|
+
var css = arguments[1];
|
279
|
+
for (var prop in css){
|
280
|
+
if (css.hasOwnProperty(prop)) {
|
281
|
+
el.style[prop] = css[prop]
|
282
|
+
}
|
283
|
+
}
|
284
|
+
JS
|
285
|
+
|
286
|
+
RESET_STYLE_SCRIPT = <<-'JS'.freeze
|
287
|
+
var el = arguments[0];
|
288
|
+
if (el.hasOwnProperty('capybara_style_cache')) {
|
289
|
+
el.style.cssText = el.capybara_style_cache;
|
290
|
+
delete el.capybara_style_cache;
|
291
|
+
}
|
292
|
+
JS
|
315
293
|
end
|
316
294
|
end
|
317
295
|
end
|
data/lib/capybara/node/base.rb
CHANGED
@@ -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::Base} represents either an element on a page through the subclass
|
@@ -67,26 +67,23 @@ module Capybara
|
|
67
67
|
# time has passed. On rubies/platforms which don't support access to a monotonic process clock
|
68
68
|
# if the return value of `Time.now` is stubbed out, Capybara will raise `Capybara::FrozenInTime`.
|
69
69
|
#
|
70
|
-
# @param [Integer] seconds
|
71
|
-
# @param
|
72
|
-
# @option options [Array<Exception>] :errors (driver.invalid_element_errors +
|
70
|
+
# @param [Integer] seconds (current sessions default_max_wait_time) Maximum number of seconds to retry this block
|
71
|
+
# @param [Array<Exception>] errors (driver.invalid_element_errors +
|
73
72
|
# [Capybara::ElementNotFound]) exception types that cause the block to be rerun
|
74
73
|
# @return [Object] The result of the given block
|
75
74
|
# @raise [Capybara::FrozenInTime] If the return value of `Time.now` appears stuck
|
76
75
|
#
|
77
|
-
def synchronize(seconds=session_options.default_max_wait_time,
|
78
|
-
start_time = Capybara::Helpers.monotonic_time
|
79
|
-
|
76
|
+
def synchronize(seconds = session_options.default_max_wait_time, errors: nil)
|
80
77
|
if session.synchronized
|
81
78
|
yield
|
82
79
|
else
|
83
80
|
session.synchronized = true
|
81
|
+
start_time = Capybara::Helpers.monotonic_time
|
84
82
|
begin
|
85
83
|
yield
|
86
84
|
rescue => e
|
87
85
|
session.raise_server_error!
|
88
|
-
raise e unless driver.wait?
|
89
|
-
raise e unless catch_error?(e, options[:errors])
|
86
|
+
raise e unless driver.wait? && catch_error?(e, errors)
|
90
87
|
raise e if (Capybara::Helpers.monotonic_time - start_time) >= seconds
|
91
88
|
sleep(0.05)
|
92
89
|
raise Capybara::FrozenInTime, "time appears to be frozen, Capybara does not work with libraries which freeze time, consider using time travelling instead" if Capybara::Helpers.monotonic_time == start_time
|
@@ -108,24 +105,20 @@ module Capybara
|
|
108
105
|
base.find_xpath(xpath)
|
109
106
|
end
|
110
107
|
|
111
|
-
# @deprecated Use query_scope instead
|
112
|
-
def parent
|
113
|
-
warn "DEPRECATED: #parent is deprecated in favor of #query_scope - Note: #parent was not the elements parent in the document so it's most likely not what you wanted anyway"
|
114
|
-
query_scope
|
115
|
-
end
|
116
|
-
|
117
108
|
# @api private
|
118
109
|
def session_options
|
119
110
|
session.config
|
120
111
|
end
|
121
112
|
|
113
|
+
def to_capybara_node
|
114
|
+
self
|
115
|
+
end
|
116
|
+
|
122
117
|
protected
|
123
118
|
|
124
119
|
def catch_error?(error, errors = nil)
|
125
120
|
errors ||= (driver.invalid_element_errors + [Capybara::ElementNotFound])
|
126
|
-
errors.any?
|
127
|
-
error.is_a?(type)
|
128
|
-
end
|
121
|
+
errors.any? { |type| error.is_a?(type) }
|
129
122
|
end
|
130
123
|
|
131
124
|
def driver
|
@@ -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
|