capybara 3.29.0 → 3.31.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/History.md +40 -1
- data/README.md +1 -1
- data/lib/capybara/config.rb +7 -3
- data/lib/capybara/dsl.rb +10 -2
- data/lib/capybara/helpers.rb +3 -1
- data/lib/capybara/minitest.rb +18 -4
- data/lib/capybara/node/actions.rb +23 -19
- data/lib/capybara/node/document.rb +2 -2
- data/lib/capybara/node/document_matchers.rb +3 -3
- data/lib/capybara/node/element.rb +21 -16
- data/lib/capybara/node/finders.rb +17 -11
- data/lib/capybara/node/matchers.rb +60 -45
- data/lib/capybara/node/simple.rb +4 -2
- data/lib/capybara/queries/ancestor_query.rb +1 -1
- data/lib/capybara/queries/base_query.rb +2 -1
- data/lib/capybara/queries/selector_query.rb +17 -4
- data/lib/capybara/queries/sibling_query.rb +1 -1
- data/lib/capybara/rack_test/browser.rb +4 -1
- data/lib/capybara/rack_test/driver.rb +1 -1
- data/lib/capybara/rack_test/form.rb +1 -1
- data/lib/capybara/rack_test/node.rb +34 -9
- data/lib/capybara/result.rb +24 -4
- data/lib/capybara/rspec/matchers.rb +27 -27
- data/lib/capybara/rspec/matchers/base.rb +12 -6
- data/lib/capybara/rspec/matchers/count_sugar.rb +2 -1
- data/lib/capybara/rspec/matchers/have_ancestor.rb +4 -3
- data/lib/capybara/rspec/matchers/have_current_path.rb +2 -2
- data/lib/capybara/rspec/matchers/have_selector.rb +15 -7
- data/lib/capybara/rspec/matchers/have_sibling.rb +3 -3
- data/lib/capybara/rspec/matchers/have_text.rb +2 -2
- data/lib/capybara/rspec/matchers/have_title.rb +2 -2
- data/lib/capybara/rspec/matchers/match_selector.rb +3 -3
- data/lib/capybara/rspec/matchers/match_style.rb +2 -2
- data/lib/capybara/rspec/matchers/spatial_sugar.rb +2 -1
- data/lib/capybara/selector.rb +24 -16
- data/lib/capybara/selector/css.rb +1 -1
- data/lib/capybara/selector/definition.rb +2 -2
- data/lib/capybara/selector/definition/button.rb +7 -2
- data/lib/capybara/selector/definition/checkbox.rb +2 -2
- data/lib/capybara/selector/definition/css.rb +3 -1
- data/lib/capybara/selector/definition/datalist_input.rb +1 -1
- data/lib/capybara/selector/definition/datalist_option.rb +1 -1
- data/lib/capybara/selector/definition/element.rb +1 -1
- data/lib/capybara/selector/definition/field.rb +1 -1
- data/lib/capybara/selector/definition/file_field.rb +1 -1
- data/lib/capybara/selector/definition/fillable_field.rb +1 -1
- data/lib/capybara/selector/definition/label.rb +4 -2
- data/lib/capybara/selector/definition/radio_button.rb +2 -2
- data/lib/capybara/selector/definition/select.rb +32 -13
- data/lib/capybara/selector/definition/table.rb +5 -2
- data/lib/capybara/selector/filter_set.rb +11 -9
- data/lib/capybara/selector/filters/base.rb +6 -1
- data/lib/capybara/selector/filters/locator_filter.rb +1 -1
- data/lib/capybara/selector/selector.rb +4 -2
- data/lib/capybara/selenium/driver.rb +19 -11
- data/lib/capybara/selenium/driver_specializations/chrome_driver.rb +1 -1
- data/lib/capybara/selenium/driver_specializations/firefox_driver.rb +2 -2
- data/lib/capybara/selenium/extensions/html5_drag.rb +30 -13
- data/lib/capybara/selenium/node.rb +29 -10
- data/lib/capybara/selenium/nodes/chrome_node.rb +11 -5
- data/lib/capybara/selenium/nodes/edge_node.rb +4 -2
- data/lib/capybara/selenium/nodes/firefox_node.rb +2 -2
- data/lib/capybara/server.rb +15 -3
- data/lib/capybara/server/checker.rb +1 -1
- data/lib/capybara/server/middleware.rb +20 -10
- data/lib/capybara/session.rb +40 -23
- data/lib/capybara/session/config.rb +6 -2
- data/lib/capybara/session/matchers.rb +6 -6
- data/lib/capybara/spec/public/test.js +51 -6
- data/lib/capybara/spec/session/all_spec.rb +60 -5
- data/lib/capybara/spec/session/ancestor_spec.rb +5 -0
- data/lib/capybara/spec/session/assert_text_spec.rb +9 -5
- data/lib/capybara/spec/session/click_button_spec.rb +5 -0
- data/lib/capybara/spec/session/fill_in_spec.rb +20 -0
- data/lib/capybara/spec/session/find_spec.rb +20 -0
- data/lib/capybara/spec/session/has_css_spec.rb +3 -3
- data/lib/capybara/spec/session/has_select_spec.rb +28 -0
- data/lib/capybara/spec/session/has_table_spec.rb +51 -5
- data/lib/capybara/spec/session/has_text_spec.rb +35 -0
- data/lib/capybara/spec/session/node_spec.rb +106 -2
- data/lib/capybara/spec/session/save_and_open_screenshot_spec.rb +2 -2
- data/lib/capybara/spec/session/save_screenshot_spec.rb +4 -4
- data/lib/capybara/spec/session/selectors_spec.rb +15 -2
- data/lib/capybara/spec/views/form.erb +11 -1
- data/lib/capybara/version.rb +1 -1
- data/spec/dsl_spec.rb +2 -2
- data/spec/minitest_spec_spec.rb +46 -46
- data/spec/rack_test_spec.rb +0 -1
- data/spec/regexp_dissassembler_spec.rb +45 -37
- data/spec/result_spec.rb +7 -3
- data/spec/rspec/features_spec.rb +1 -0
- data/spec/rspec/shared_spec_matchers.rb +3 -3
- data/spec/rspec_spec.rb +4 -4
- data/spec/selenium_spec_chrome.rb +5 -4
- data/spec/selenium_spec_firefox.rb +7 -2
- data/spec/server_spec.rb +42 -0
- data/spec/session_spec.rb +1 -1
- data/spec/shared_selenium_node.rb +3 -3
- data/spec/shared_selenium_session.rb +8 -7
- metadata +3 -3
@@ -54,7 +54,9 @@ class Capybara::Selenium::Node < Capybara::Driver::Node
|
|
54
54
|
# :backspace => send backspace keystrokes to clear the field <br/>
|
55
55
|
# Array => an array of keys to send before the value being set, e.g. [[:command, 'a'], :backspace]
|
56
56
|
def set(value, **options)
|
57
|
-
|
57
|
+
if value.is_a?(Array) && !multiple?
|
58
|
+
raise ArgumentError, "Value cannot be an Array when 'multiple' attribute is not present. Not a #{value.class}"
|
59
|
+
end
|
58
60
|
|
59
61
|
tag_name, type = attrs(:tagName, :type).map { |val| val&.downcase }
|
60
62
|
@tag_name ||= tag_name
|
@@ -76,11 +78,13 @@ class Capybara::Selenium::Node < Capybara::Driver::Node
|
|
76
78
|
set_datetime_local(value)
|
77
79
|
when 'color'
|
78
80
|
set_color(value)
|
81
|
+
when 'range'
|
82
|
+
set_range(value)
|
79
83
|
else
|
80
|
-
set_text(value, options)
|
84
|
+
set_text(value, **options)
|
81
85
|
end
|
82
86
|
when 'textarea'
|
83
|
-
set_text(value, options)
|
87
|
+
set_text(value, **options)
|
84
88
|
else
|
85
89
|
set_content_editable(value)
|
86
90
|
end
|
@@ -132,11 +136,17 @@ class Capybara::Selenium::Node < Capybara::Driver::Node
|
|
132
136
|
scroll_if_needed { browser_action.move_to(native).perform }
|
133
137
|
end
|
134
138
|
|
135
|
-
def drag_to(element, **)
|
139
|
+
def drag_to(element, drop_modifiers: [], **)
|
140
|
+
drop_modifiers = Array(drop_modifiers)
|
136
141
|
# Due to W3C spec compliance - The Actions API no longer scrolls to elements when necessary
|
137
142
|
# which means Seleniums `drag_and_drop` is now broken - do it manually
|
138
143
|
scroll_if_needed { browser_action.click_and_hold(native).perform }
|
139
|
-
element.scroll_if_needed { browser_action.move_to(element.native).release.perform }
|
144
|
+
# element.scroll_if_needed { browser_action.move_to(element.native).release.perform }
|
145
|
+
element.scroll_if_needed do
|
146
|
+
keys_down = modifiers_down(browser_action, drop_modifiers)
|
147
|
+
keys_up = modifiers_up(keys_down.move_to(element.native).release, drop_modifiers)
|
148
|
+
keys_up.perform
|
149
|
+
end
|
140
150
|
end
|
141
151
|
|
142
152
|
def drop(*_)
|
@@ -202,7 +212,7 @@ protected
|
|
202
212
|
JS
|
203
213
|
begin
|
204
214
|
driver.execute_script(script, self)
|
205
|
-
rescue StandardError # rubocop:disable Lint/
|
215
|
+
rescue StandardError # rubocop:disable Lint/SuppressedException
|
206
216
|
# Swallow error if scrollIntoView with options isn't supported
|
207
217
|
end
|
208
218
|
end
|
@@ -288,6 +298,10 @@ private
|
|
288
298
|
update_value_js(value)
|
289
299
|
end
|
290
300
|
|
301
|
+
def set_range(value) # rubocop:disable Naming/AccessorMethodName
|
302
|
+
update_value_js(value)
|
303
|
+
end
|
304
|
+
|
291
305
|
def update_value_js(value)
|
292
306
|
driver.execute_script(<<-JS, self, value)
|
293
307
|
if (arguments[0].readOnly) { return };
|
@@ -373,10 +387,12 @@ private
|
|
373
387
|
|
374
388
|
def modifiers_down(actions, keys)
|
375
389
|
each_key(keys) { |key| actions.key_down(key) }
|
390
|
+
actions
|
376
391
|
end
|
377
392
|
|
378
393
|
def modifiers_up(actions, keys)
|
379
394
|
each_key(keys) { |key| actions.key_up(key) }
|
395
|
+
actions
|
380
396
|
end
|
381
397
|
|
382
398
|
def browser
|
@@ -391,18 +407,21 @@ private
|
|
391
407
|
browser.action
|
392
408
|
end
|
393
409
|
|
394
|
-
def
|
395
|
-
keys.
|
396
|
-
|
410
|
+
def normalize_keys(keys)
|
411
|
+
keys.map do |key|
|
412
|
+
case key
|
397
413
|
when :ctrl then :control
|
398
414
|
when :command, :cmd then :meta
|
399
415
|
else
|
400
416
|
key
|
401
417
|
end
|
402
|
-
yield key
|
403
418
|
end
|
404
419
|
end
|
405
420
|
|
421
|
+
def each_key(keys)
|
422
|
+
normalize_keys(keys).each { |key| yield(key) }
|
423
|
+
end
|
424
|
+
|
406
425
|
def find_context
|
407
426
|
native
|
408
427
|
end
|
@@ -18,14 +18,16 @@ class Capybara::Selenium::ChromeNode < Capybara::Selenium::Node
|
|
18
18
|
# In Chrome 75+ files are appended (due to WebDriver spec - why?) so we have to clear here if its multiple and already set
|
19
19
|
if browser_version >= 75.0
|
20
20
|
driver.execute_script(<<~JS, self)
|
21
|
-
if (arguments[0].multiple &&
|
21
|
+
if (arguments[0].multiple && arguments[0].files.length){
|
22
22
|
arguments[0].value = null;
|
23
23
|
}
|
24
24
|
JS
|
25
25
|
end
|
26
26
|
super
|
27
27
|
rescue *file_errors => e
|
28
|
-
|
28
|
+
if e.message.match?(/File not found : .+\n.+/m)
|
29
|
+
raise ArgumentError, "Selenium < 3.14 with remote Chrome doesn't support multiple file upload"
|
30
|
+
end
|
29
31
|
|
30
32
|
raise
|
31
33
|
end
|
@@ -34,13 +36,15 @@ class Capybara::Selenium::ChromeNode < Capybara::Selenium::Node
|
|
34
36
|
html5_drop(*args)
|
35
37
|
end
|
36
38
|
|
37
|
-
def click(
|
39
|
+
def click(*, **)
|
38
40
|
super
|
39
41
|
rescue ::Selenium::WebDriver::Error::ElementClickInterceptedError
|
40
42
|
raise
|
41
43
|
rescue ::Selenium::WebDriver::Error::WebDriverError => e
|
42
44
|
# chromedriver 74 (at least on mac) raises the wrong error for this
|
43
|
-
|
45
|
+
if e.message.match?(/element click intercepted/)
|
46
|
+
raise ::Selenium::WebDriver::Error::ElementClickInterceptedError, e.message
|
47
|
+
end
|
44
48
|
|
45
49
|
raise
|
46
50
|
end
|
@@ -71,9 +75,11 @@ class Capybara::Selenium::ChromeNode < Capybara::Selenium::Node
|
|
71
75
|
|
72
76
|
private
|
73
77
|
|
74
|
-
def perform_legacy_drag(element)
|
78
|
+
def perform_legacy_drag(element, drop_modifiers)
|
75
79
|
return super if chromedriver_fixed_actions_key_state? || !w3c? || element.obscured?
|
76
80
|
|
81
|
+
raise ArgumentError, 'Modifier keys are not supported while dragging in this version of Chrome.' unless drop_modifiers.empty?
|
82
|
+
|
77
83
|
# W3C Chrome/chromedriver < 77 doesn't maintain mouse button state across actions API performs
|
78
84
|
# https://bugs.chromium.org/p/chromedriver/issues/detail?id=2981
|
79
85
|
browser_action.release.perform
|
@@ -18,14 +18,16 @@ class Capybara::Selenium::EdgeNode < Capybara::Selenium::Node
|
|
18
18
|
# In Chrome 75+ files are appended (due to WebDriver spec - why?) so we have to clear here if its multiple and already set
|
19
19
|
if chrome_edge?
|
20
20
|
driver.execute_script(<<~JS, self)
|
21
|
-
if (arguments[0].multiple &&
|
21
|
+
if (arguments[0].multiple && arguments[0].files.length){
|
22
22
|
arguments[0].value = null;
|
23
23
|
}
|
24
24
|
JS
|
25
25
|
end
|
26
26
|
super
|
27
27
|
rescue *file_errors => e
|
28
|
-
|
28
|
+
if e.message.match?(/File not found : .+\n.+/m)
|
29
|
+
raise ArgumentError, "Selenium < 3.14 with remote Chrome doesn't support multiple file upload"
|
30
|
+
end
|
29
31
|
|
30
32
|
raise
|
31
33
|
end
|
@@ -14,7 +14,7 @@ class Capybara::Selenium::FirefoxNode < Capybara::Selenium::Node
|
|
14
14
|
warn 'You are attempting to click a table row which has issues in geckodriver/marionette - '\
|
15
15
|
'see https://github.com/mozilla/geckodriver/issues/1228. Your test should probably be '\
|
16
16
|
'clicking on a table cell like a user would. Clicking the first cell in the row instead.'
|
17
|
-
return find_css('th:first-child,td:first-child')[0].click(keys, options)
|
17
|
+
return find_css('th:first-child,td:first-child')[0].click(keys, **options)
|
18
18
|
end
|
19
19
|
raise
|
20
20
|
end
|
@@ -26,7 +26,7 @@ class Capybara::Selenium::FirefoxNode < Capybara::Selenium::Node
|
|
26
26
|
def set_file(value) # rubocop:disable Naming/AccessorMethodName
|
27
27
|
# By default files are appended so we have to clear here if its multiple and already set
|
28
28
|
driver.execute_script(<<~JS, self)
|
29
|
-
if (arguments[0].multiple &&
|
29
|
+
if (arguments[0].multiple && arguments[0].files.length){
|
30
30
|
arguments[0].value = null;
|
31
31
|
}
|
32
32
|
JS
|
data/lib/capybara/server.rb
CHANGED
@@ -24,7 +24,9 @@ module Capybara
|
|
24
24
|
host: Capybara.server_host,
|
25
25
|
reportable_errors: Capybara.server_errors,
|
26
26
|
extra_middleware: [])
|
27
|
-
|
27
|
+
unless deprecated_options.empty?
|
28
|
+
warn 'Positional arguments, other than the application, to Server#new are deprecated, please use keyword arguments'
|
29
|
+
end
|
28
30
|
@app = app
|
29
31
|
@extra_middleware = extra_middleware
|
30
32
|
@server_thread = nil # suppress warnings
|
@@ -61,7 +63,7 @@ module Capybara
|
|
61
63
|
def wait_for_pending_requests
|
62
64
|
timer = Capybara::Helpers.timer(expire_in: 60)
|
63
65
|
while pending_requests?
|
64
|
-
raise
|
66
|
+
raise "Requests did not finish in 60 seconds: #{middleware.pending_requests}" if timer.expired?
|
65
67
|
|
66
68
|
sleep 0.01
|
67
69
|
end
|
@@ -106,7 +108,17 @@ module Capybara
|
|
106
108
|
|
107
109
|
def find_available_port(host)
|
108
110
|
server = TCPServer.new(host, 0)
|
109
|
-
server.addr[1]
|
111
|
+
port = server.addr[1]
|
112
|
+
server.close
|
113
|
+
|
114
|
+
# Workaround issue where some platforms (mac, ???) when passed a host
|
115
|
+
# of '0.0.0.0' will return a port that is only available on one of the
|
116
|
+
# ip addresses that resolves to, but the next binding to that port requires
|
117
|
+
# that port to be available on all ips
|
118
|
+
server = TCPServer.new(host, port)
|
119
|
+
port
|
120
|
+
rescue Errno::EADDRINUSE
|
121
|
+
retry
|
110
122
|
ensure
|
111
123
|
server&.close
|
112
124
|
end
|
@@ -4,19 +4,25 @@ module Capybara
|
|
4
4
|
class Server
|
5
5
|
class Middleware
|
6
6
|
class Counter
|
7
|
-
attr_reader :value
|
8
|
-
|
9
7
|
def initialize
|
10
|
-
@value =
|
8
|
+
@value = []
|
11
9
|
@mutex = Mutex.new
|
12
10
|
end
|
13
11
|
|
14
|
-
def increment
|
15
|
-
@mutex.synchronize { @value
|
12
|
+
def increment(uri)
|
13
|
+
@mutex.synchronize { @value.push(uri) }
|
14
|
+
end
|
15
|
+
|
16
|
+
def decrement(uri)
|
17
|
+
@mutex.synchronize { @value.delete_at(@value.index(uri) || @value.length) }
|
16
18
|
end
|
17
19
|
|
18
|
-
def
|
19
|
-
@mutex.synchronize { @value
|
20
|
+
def positive?
|
21
|
+
@mutex.synchronize { @value.length.positive? }
|
22
|
+
end
|
23
|
+
|
24
|
+
def value
|
25
|
+
@mutex.synchronize { @value.dup }
|
20
26
|
end
|
21
27
|
end
|
22
28
|
|
@@ -31,8 +37,12 @@ module Capybara
|
|
31
37
|
@server_errors = server_errors
|
32
38
|
end
|
33
39
|
|
40
|
+
def pending_requests
|
41
|
+
@counter.value
|
42
|
+
end
|
43
|
+
|
34
44
|
def pending_requests?
|
35
|
-
@counter.
|
45
|
+
@counter.positive?
|
36
46
|
end
|
37
47
|
|
38
48
|
def clear_error
|
@@ -43,14 +53,14 @@ module Capybara
|
|
43
53
|
if env['PATH_INFO'] == '/__identify__'
|
44
54
|
[200, {}, [@app.object_id.to_s]]
|
45
55
|
else
|
46
|
-
@counter.increment
|
56
|
+
@counter.increment(env['REQUEST_URI'])
|
47
57
|
begin
|
48
58
|
@extended_app.call(env)
|
49
59
|
rescue *@server_errors => e
|
50
60
|
@error ||= e
|
51
61
|
raise e
|
52
62
|
ensure
|
53
|
-
@counter.decrement
|
63
|
+
@counter.decrement(env['REQUEST_URI'])
|
54
64
|
end
|
55
65
|
end
|
56
66
|
end
|
data/lib/capybara/session.rb
CHANGED
@@ -75,7 +75,9 @@ module Capybara
|
|
75
75
|
attr_accessor :synchronized
|
76
76
|
|
77
77
|
def initialize(mode, app = nil)
|
78
|
-
|
78
|
+
if app && !app.respond_to?(:call)
|
79
|
+
raise TypeError, 'The second parameter to Session::new should be a rack app if passed.'
|
80
|
+
end
|
79
81
|
|
80
82
|
@@instance_created = true # rubocop:disable Style/ClassVars
|
81
83
|
@mode = mode
|
@@ -88,7 +90,7 @@ module Capybara
|
|
88
90
|
@server = if config.run_server && @app && driver.needs_server?
|
89
91
|
server_options = { port: config.server_port, host: config.server_host, reportable_errors: config.server_errors }
|
90
92
|
server_options[:extra_middleware] = [Capybara::Server::AnimationDisabler] if config.disable_animation
|
91
|
-
Capybara::Server.new(@app, server_options).boot
|
93
|
+
Capybara::Server.new(@app, **server_options).boot
|
92
94
|
end
|
93
95
|
@touched = false
|
94
96
|
end
|
@@ -336,8 +338,8 @@ module Capybara
|
|
336
338
|
#
|
337
339
|
# @raise [Capybara::ElementNotFound] If the scope can't be found before time expires
|
338
340
|
#
|
339
|
-
def within(*args)
|
340
|
-
new_scope = args.first.respond_to?(:to_capybara_node) ? args.first.to_capybara_node : find(*args)
|
341
|
+
def within(*args, **kw_args)
|
342
|
+
new_scope = args.first.respond_to?(:to_capybara_node) ? args.first.to_capybara_node : find(*args, **kw_args)
|
341
343
|
begin
|
342
344
|
scopes.push(new_scope)
|
343
345
|
yield if block_given?
|
@@ -421,8 +423,8 @@ module Capybara
|
|
421
423
|
# @param [String] locator The locator for the given selector kind. For :frame this is the name/id of a frame/iframe element
|
422
424
|
# @overload within_frame(index)
|
423
425
|
# @param [Integer] index index of a frame (0 based)
|
424
|
-
def within_frame(*args)
|
425
|
-
switch_to_frame(_find_frame(*args))
|
426
|
+
def within_frame(*args, **kw_args)
|
427
|
+
switch_to_frame(_find_frame(*args, **kw_args))
|
426
428
|
begin
|
427
429
|
yield if block_given?
|
428
430
|
ensure
|
@@ -494,7 +496,7 @@ module Capybara
|
|
494
496
|
'`within` or `within_frame` blocks.'
|
495
497
|
end
|
496
498
|
|
497
|
-
_switch_to_window(window, options, &window_locator)
|
499
|
+
_switch_to_window(window, **options, &window_locator)
|
498
500
|
end
|
499
501
|
|
500
502
|
##
|
@@ -528,7 +530,7 @@ module Capybara
|
|
528
530
|
when Proc
|
529
531
|
_switch_to_window { window_or_proc.call }
|
530
532
|
else
|
531
|
-
raise ArgumentError
|
533
|
+
raise ArgumentError, '`#within_window` requires a `Capybara::Window` instance or a lambda'
|
532
534
|
end
|
533
535
|
|
534
536
|
begin
|
@@ -721,7 +723,7 @@ module Capybara
|
|
721
723
|
# @param [Hash] options a customizable set of options
|
722
724
|
# @return [String] the path to which the file was saved
|
723
725
|
def save_screenshot(path = nil, **options)
|
724
|
-
prepare_path(path, 'png').tap { |p_path| driver.save_screenshot(p_path, options) }
|
726
|
+
prepare_path(path, 'png').tap { |p_path| driver.save_screenshot(p_path, **options) }
|
725
727
|
end
|
726
728
|
|
727
729
|
##
|
@@ -736,7 +738,7 @@ module Capybara
|
|
736
738
|
# @param [Hash] options a customizable set of options
|
737
739
|
#
|
738
740
|
def save_and_open_screenshot(path = nil, **options)
|
739
|
-
save_screenshot(path, options).tap { |s_path| open_file(s_path) } # rubocop:disable Lint/Debugger
|
741
|
+
save_screenshot(path, **options).tap { |s_path| open_file(s_path) } # rubocop:disable Lint/Debugger
|
740
742
|
end
|
741
743
|
|
742
744
|
def document
|
@@ -744,15 +746,32 @@ module Capybara
|
|
744
746
|
end
|
745
747
|
|
746
748
|
NODE_METHODS.each do |method|
|
747
|
-
|
748
|
-
|
749
|
-
|
749
|
+
if RUBY_VERSION >= '2.7'
|
750
|
+
class_eval <<~METHOD, __FILE__, __LINE__ + 1
|
751
|
+
def #{method}(...)
|
752
|
+
@touched = true
|
753
|
+
current_scope.#{method}(...)
|
754
|
+
end
|
755
|
+
METHOD
|
756
|
+
else
|
757
|
+
define_method method do |*args, &block|
|
758
|
+
@touched = true
|
759
|
+
current_scope.send(method, *args, &block)
|
760
|
+
end
|
750
761
|
end
|
751
762
|
end
|
752
763
|
|
753
764
|
DOCUMENT_METHODS.each do |method|
|
754
|
-
|
755
|
-
|
765
|
+
if RUBY_VERSION >= '2.7'
|
766
|
+
class_eval <<~METHOD, __FILE__, __LINE__ + 1
|
767
|
+
def #{method}(...)
|
768
|
+
document.#{method}(...)
|
769
|
+
end
|
770
|
+
METHOD
|
771
|
+
else
|
772
|
+
define_method method do |*args, &block|
|
773
|
+
document.send(method, *args, &block)
|
774
|
+
end
|
756
775
|
end
|
757
776
|
end
|
758
777
|
|
@@ -819,11 +838,11 @@ module Capybara
|
|
819
838
|
end
|
820
839
|
|
821
840
|
def accept_modal(type, text_or_options, options, &blk)
|
822
|
-
driver.accept_modal(type, modal_options(text_or_options, options), &blk)
|
841
|
+
driver.accept_modal(type, **modal_options(text_or_options, **options), &blk)
|
823
842
|
end
|
824
843
|
|
825
844
|
def dismiss_modal(type, text_or_options, options, &blk)
|
826
|
-
driver.dismiss_modal(type, modal_options(text_or_options, options), &blk)
|
845
|
+
driver.dismiss_modal(type, **modal_options(text_or_options, **options), &blk)
|
827
846
|
end
|
828
847
|
|
829
848
|
def modal_options(text = nil, **options)
|
@@ -871,16 +890,14 @@ module Capybara
|
|
871
890
|
uri.port ||= @server.port if @server && config.always_include_port
|
872
891
|
end
|
873
892
|
|
874
|
-
def _find_frame(*args)
|
875
|
-
return find(:frame) if args.length.zero?
|
876
|
-
|
893
|
+
def _find_frame(*args, **kw_args)
|
877
894
|
case args[0]
|
878
895
|
when Capybara::Node::Element
|
879
896
|
args[0]
|
880
|
-
when String,
|
881
|
-
find(:frame, *args)
|
897
|
+
when String, nil
|
898
|
+
find(:frame, *args, **kw_args)
|
882
899
|
when Symbol
|
883
|
-
find(*args)
|
900
|
+
find(*args, **kw_args)
|
884
901
|
when Integer
|
885
902
|
idx = args[0]
|
886
903
|
all(:frame, minimum: idx + 1)[idx]
|
@@ -79,14 +79,18 @@ module Capybara
|
|
79
79
|
|
80
80
|
remove_method :app_host=
|
81
81
|
def app_host=(url)
|
82
|
-
|
82
|
+
unless url.nil? || url.match?(URI::DEFAULT_PARSER.make_regexp)
|
83
|
+
raise ArgumentError, "Capybara.app_host should be set to a url (http://www.example.com). Attempted to set #{url.inspect}."
|
84
|
+
end
|
83
85
|
|
84
86
|
@app_host = url
|
85
87
|
end
|
86
88
|
|
87
89
|
remove_method :default_host=
|
88
90
|
def default_host=(url)
|
89
|
-
|
91
|
+
unless url.nil? || url.match?(URI::DEFAULT_PARSER.make_regexp)
|
92
|
+
raise ArgumentError, "Capybara.default_host should be set to a url (http://www.example.com). Attempted to set #{url.inspect}."
|
93
|
+
end
|
90
94
|
|
91
95
|
@default_host = url
|
92
96
|
end
|