capybara 3.29.0 → 3.30.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.
Files changed (79) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +19 -1
  3. data/README.md +1 -1
  4. data/lib/capybara/config.rb +7 -3
  5. data/lib/capybara/helpers.rb +3 -1
  6. data/lib/capybara/node/actions.rb +23 -19
  7. data/lib/capybara/node/document.rb +2 -2
  8. data/lib/capybara/node/document_matchers.rb +3 -3
  9. data/lib/capybara/node/element.rb +10 -8
  10. data/lib/capybara/node/finders.rb +12 -10
  11. data/lib/capybara/node/matchers.rb +39 -33
  12. data/lib/capybara/node/simple.rb +3 -1
  13. data/lib/capybara/queries/ancestor_query.rb +1 -1
  14. data/lib/capybara/queries/selector_query.rb +17 -4
  15. data/lib/capybara/queries/sibling_query.rb +1 -1
  16. data/lib/capybara/rack_test/browser.rb +4 -1
  17. data/lib/capybara/rack_test/driver.rb +1 -1
  18. data/lib/capybara/rack_test/form.rb +1 -1
  19. data/lib/capybara/selector.rb +22 -16
  20. data/lib/capybara/selector/css.rb +1 -1
  21. data/lib/capybara/selector/definition.rb +2 -2
  22. data/lib/capybara/selector/definition/button.rb +7 -2
  23. data/lib/capybara/selector/definition/checkbox.rb +2 -2
  24. data/lib/capybara/selector/definition/css.rb +3 -1
  25. data/lib/capybara/selector/definition/datalist_input.rb +1 -1
  26. data/lib/capybara/selector/definition/datalist_option.rb +1 -1
  27. data/lib/capybara/selector/definition/element.rb +1 -1
  28. data/lib/capybara/selector/definition/field.rb +1 -1
  29. data/lib/capybara/selector/definition/file_field.rb +1 -1
  30. data/lib/capybara/selector/definition/fillable_field.rb +1 -1
  31. data/lib/capybara/selector/definition/label.rb +3 -1
  32. data/lib/capybara/selector/definition/radio_button.rb +2 -2
  33. data/lib/capybara/selector/definition/select.rb +1 -1
  34. data/lib/capybara/selector/definition/table.rb +5 -2
  35. data/lib/capybara/selector/filter_set.rb +11 -9
  36. data/lib/capybara/selector/filters/base.rb +6 -1
  37. data/lib/capybara/selector/filters/locator_filter.rb +1 -1
  38. data/lib/capybara/selector/selector.rb +4 -2
  39. data/lib/capybara/selenium/driver.rb +19 -11
  40. data/lib/capybara/selenium/driver_specializations/firefox_driver.rb +2 -2
  41. data/lib/capybara/selenium/extensions/html5_drag.rb +6 -5
  42. data/lib/capybara/selenium/node.rb +6 -4
  43. data/lib/capybara/selenium/nodes/chrome_node.rb +7 -3
  44. data/lib/capybara/selenium/nodes/edge_node.rb +3 -1
  45. data/lib/capybara/selenium/nodes/firefox_node.rb +1 -1
  46. data/lib/capybara/server.rb +15 -3
  47. data/lib/capybara/server/checker.rb +1 -1
  48. data/lib/capybara/server/middleware.rb +20 -10
  49. data/lib/capybara/session.rb +10 -8
  50. data/lib/capybara/session/config.rb +6 -2
  51. data/lib/capybara/session/matchers.rb +6 -6
  52. data/lib/capybara/spec/public/test.js +11 -0
  53. data/lib/capybara/spec/session/all_spec.rb +15 -0
  54. data/lib/capybara/spec/session/ancestor_spec.rb +5 -0
  55. data/lib/capybara/spec/session/assert_text_spec.rb +4 -0
  56. data/lib/capybara/spec/session/click_button_spec.rb +5 -0
  57. data/lib/capybara/spec/session/find_spec.rb +20 -0
  58. data/lib/capybara/spec/session/has_table_spec.rb +51 -5
  59. data/lib/capybara/spec/session/has_text_spec.rb +31 -0
  60. data/lib/capybara/spec/session/node_spec.rb +15 -0
  61. data/lib/capybara/spec/session/save_and_open_screenshot_spec.rb +2 -2
  62. data/lib/capybara/spec/session/save_screenshot_spec.rb +4 -4
  63. data/lib/capybara/spec/session/selectors_spec.rb +15 -2
  64. data/lib/capybara/spec/views/form.erb +5 -0
  65. data/lib/capybara/version.rb +1 -1
  66. data/spec/dsl_spec.rb +2 -2
  67. data/spec/minitest_spec_spec.rb +46 -46
  68. data/spec/regexp_dissassembler_spec.rb +45 -37
  69. data/spec/result_spec.rb +3 -3
  70. data/spec/rspec/features_spec.rb +1 -0
  71. data/spec/rspec/shared_spec_matchers.rb +3 -3
  72. data/spec/rspec_spec.rb +4 -4
  73. data/spec/selenium_spec_chrome.rb +3 -3
  74. data/spec/selenium_spec_firefox.rb +7 -2
  75. data/spec/server_spec.rb +42 -0
  76. data/spec/session_spec.rb +1 -1
  77. data/spec/shared_selenium_node.rb +3 -3
  78. data/spec/shared_selenium_session.rb +8 -7
  79. metadata +3 -3
@@ -48,7 +48,12 @@ module Capybara
48
48
 
49
49
  def apply(subject, name, value, skip_value, ctx)
50
50
  return skip_value if skip?(value)
51
- raise ArgumentError, "Invalid value #{value.inspect} passed to #{self.class.name.split('::').last} #{name}#{" : #{@name}" if @name.is_a?(Regexp)}" unless valid_value?(value)
51
+
52
+ unless valid_value?(value)
53
+ raise ArgumentError,
54
+ "Invalid value #{value.inspect} passed to #{self.class.name.split('::').last} #{name}" \
55
+ "#{" : #{name}" if @name.is_a?(Regexp)}"
56
+ end
52
57
 
53
58
  if @block.arity == 2
54
59
  filter_context(ctx).instance_exec(subject, value, &@block)
@@ -7,7 +7,7 @@ module Capybara
7
7
  module Filters
8
8
  class LocatorFilter < NodeFilter
9
9
  def initialize(block, **options)
10
- super(nil, nil, block, options)
10
+ super(nil, nil, block, **options)
11
11
  end
12
12
 
13
13
  def matches?(node, value, context = nil, exact:)
@@ -56,12 +56,14 @@ module Capybara
56
56
  if format
57
57
  raise ArgumentError, "Selector #{@name} does not support #{format}" unless expressions.key?(format)
58
58
 
59
- instance_exec(locator, options, &expressions[format])
59
+ instance_exec(locator, **options, &expressions[format])
60
60
  else
61
61
  warn 'Selector has no format'
62
62
  end
63
63
  ensure
64
- warn "Locator #{locator.class}:#{locator.inspect} for selector #{name.inspect} must #{locator_description}. This will raise an error in a future version of Capybara." unless locator_valid?(locator)
64
+ unless locator_valid?(locator)
65
+ warn "Locator #{locator.class}:#{locator.inspect} for selector #{name.inspect} must #{locator_description}. This will raise an error in a future version of Capybara."
66
+ end
65
67
  end
66
68
 
67
69
  def add_error(error_msg)
@@ -20,7 +20,9 @@ class Capybara::Selenium::Driver < Capybara::Driver::Base
20
20
  require 'capybara/selenium/logger_suppressor'
21
21
  require 'capybara/selenium/patches/atoms'
22
22
  require 'capybara/selenium/patches/is_displayed'
23
- warn "Warning: You're using an unsupported version of selenium-webdriver, please upgrade." if Gem.loaded_specs['selenium-webdriver'].version < Gem::Version.new('3.5.0')
23
+ if Gem.loaded_specs['selenium-webdriver'].version < Gem::Version.new('3.5.0')
24
+ warn "Warning: You're using an unsupported version of selenium-webdriver, please upgrade."
25
+ end
24
26
  rescue LoadError => e
25
27
  raise e unless e.message.match?(/selenium-webdriver/)
26
28
 
@@ -143,7 +145,7 @@ class Capybara::Selenium::Driver < Capybara::Driver::Base
143
145
 
144
146
  switch_to_frame(:parent)
145
147
  begin
146
- return frame.base.obscured?(x: x, y: y)
148
+ frame.base.obscured?(x: x, y: y)
147
149
  ensure
148
150
  switch_to_frame(frame)
149
151
  end
@@ -219,7 +221,7 @@ class Capybara::Selenium::Driver < Capybara::Driver::Base
219
221
 
220
222
  def accept_modal(_type, **options)
221
223
  yield if block_given?
222
- modal = find_modal(options)
224
+ modal = find_modal(**options)
223
225
 
224
226
  modal.send_keys options[:with] if options[:with]
225
227
 
@@ -230,7 +232,7 @@ class Capybara::Selenium::Driver < Capybara::Driver::Base
230
232
 
231
233
  def dismiss_modal(_type, **options)
232
234
  yield if block_given?
233
- modal = find_modal(options)
235
+ modal = find_modal(**options)
234
236
  message = modal.text
235
237
  modal.dismiss
236
238
  message
@@ -238,7 +240,7 @@ class Capybara::Selenium::Driver < Capybara::Driver::Base
238
240
 
239
241
  def quit
240
242
  @browser&.quit
241
- rescue Selenium::WebDriver::Error::SessionNotCreatedError, Errno::ECONNREFUSED # rubocop:disable Lint/HandleExceptions
243
+ rescue Selenium::WebDriver::Error::SessionNotCreatedError, Errno::ECONNREFUSED # rubocop:disable Lint/SuppressedException
242
244
  # Browser must have already gone
243
245
  rescue Selenium::WebDriver::Error::UnknownError => e
244
246
  unless silenced_unknown_error_message?(e.message) # Most likely already gone
@@ -290,7 +292,7 @@ private
290
292
  def clear_browser_state
291
293
  delete_all_cookies
292
294
  clear_storage
293
- rescue *clear_browser_state_errors # rubocop:disable Lint/HandleExceptions
295
+ rescue *clear_browser_state_errors # rubocop:disable Lint/SuppressedException
294
296
  # delete_all_cookies fails when we've previously gone
295
297
  # to about:blank, so we rescue this error and do nothing
296
298
  # instead.
@@ -314,7 +316,7 @@ private
314
316
  def clear_storage
315
317
  clear_session_storage unless options[:clear_session_storage] == false
316
318
  clear_local_storage unless options[:clear_local_storage] == false
317
- rescue Selenium::WebDriver::Error::JavascriptError # rubocop:disable Lint/HandleExceptions
319
+ rescue Selenium::WebDriver::Error::JavascriptError # rubocop:disable Lint/SuppressedException
318
320
  # session/local storage may not be available if on non-http pages (e.g. about:blank)
319
321
  end
320
322
 
@@ -325,7 +327,9 @@ private
325
327
  begin
326
328
  @browser&.execute_script('window.sessionStorage.clear()')
327
329
  rescue # rubocop:disable Style/RescueStandardError
328
- warn 'sessionStorage clear requested but is not supported by this driver' unless options[:clear_session_storage].nil?
330
+ unless options[:clear_session_storage].nil?
331
+ warn 'sessionStorage clear requested but is not supported by this driver'
332
+ end
329
333
  end
330
334
  end
331
335
  end
@@ -337,7 +341,9 @@ private
337
341
  begin
338
342
  @browser&.execute_script('window.localStorage.clear()')
339
343
  rescue # rubocop:disable Style/RescueStandardError
340
- warn 'localStorage clear requested but is not supported by this driver' unless options[:clear_local_storage].nil?
344
+ unless options[:clear_local_storage].nil?
345
+ warn 'localStorage clear requested but is not supported by this driver'
346
+ end
341
347
  end
342
348
  end
343
349
  end
@@ -346,7 +352,7 @@ private
346
352
  @browser.navigate.to(url)
347
353
  sleep 0.1 # slight wait for alert
348
354
  @browser.switch_to.alert.accept
349
- rescue modal_error # rubocop:disable Lint/HandleExceptions
355
+ rescue modal_error # rubocop:disable Lint/SuppressedException
350
356
  # alert now gone, should mean navigation happened
351
357
  end
352
358
 
@@ -378,7 +384,9 @@ private
378
384
  alert = @browser.switch_to.alert
379
385
  regexp = text.is_a?(Regexp) ? text : Regexp.new(Regexp.escape(text.to_s))
380
386
  matched = alert.text.match?(regexp)
381
- raise Capybara::ModalNotFound, "Unable to find modal dialog with #{text} - found '#{alert.text}' instead." unless matched
387
+ unless matched
388
+ raise Capybara::ModalNotFound, "Unable to find modal dialog with #{text} - found '#{alert.text}' instead."
389
+ end
382
390
 
383
391
  alert
384
392
  end
@@ -46,7 +46,7 @@ module Capybara::Selenium::Driver::W3CFirefoxDriver
46
46
  begin
47
47
  # Firefox 68 hangs if we try to switch windows while a modal is visible
48
48
  browser.switch_to.alert&.dismiss
49
- rescue Selenium::WebDriver::Error::NoSuchAlertError # rubocop:disable Lint/HandleExceptions
49
+ rescue Selenium::WebDriver::Error::NoSuchAlertError # rubocop:disable Lint/SuppressedException
50
50
  # Swallow
51
51
  end
52
52
  end
@@ -61,7 +61,7 @@ module Capybara::Selenium::Driver::W3CFirefoxDriver
61
61
  accept_modal :confirm, wait: 0.1 do
62
62
  super
63
63
  end
64
- rescue Capybara::ModalNotFound # rubocop:disable Lint/HandleExceptions
64
+ rescue Capybara::ModalNotFound # rubocop:disable Lint/SuppressedException
65
65
  # No modal was opened - page has refreshed - ignore
66
66
  end
67
67
 
@@ -166,17 +166,18 @@ class Capybara::Selenium::Node
166
166
  var dragOverOpts = Object.assign({clientX: targetCenter.x, clientY: targetCenter.y}, opts);
167
167
  var dragOverEvent = new DragEvent('dragover', dragOverOpts);
168
168
  target.dispatchEvent(dragOverEvent);
169
- window.setTimeout(dragLeave, step_delay, dragOverEvent.defaultPrevented);
169
+ window.setTimeout(dragLeave, step_delay, dragOverEvent.defaultPrevented, dragOverOpts);
170
170
  }
171
171
 
172
- function dragLeave(drop) {
173
- var dragLeaveEvent = new DragEvent('dragleave', opts);
172
+ function dragLeave(drop, dragOverOpts) {
173
+ var dragLeaveOptions = Object.assign({}, opts, dragOverOpts);
174
+ var dragLeaveEvent = new DragEvent('dragleave', dragLeaveOptions);
174
175
  target.dispatchEvent(dragLeaveEvent);
175
176
  if (drop) {
176
- var dropEvent = new DragEvent('drop', opts);
177
+ var dropEvent = new DragEvent('drop', dragLeaveOptions);
177
178
  target.dispatchEvent(dropEvent);
178
179
  }
179
- var dragEndEvent = new DragEvent('dragend', opts);
180
+ var dragEndEvent = new DragEvent('dragend', dragLeaveOptions);
180
181
  source.dispatchEvent(dragEndEvent);
181
182
  callback.call(true);
182
183
  }
@@ -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
- raise ArgumentError, "Value cannot be an Array when 'multiple' attribute is not present. Not a #{value.class}" if value.is_a?(Array) && !multiple?
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
@@ -77,10 +79,10 @@ class Capybara::Selenium::Node < Capybara::Driver::Node
77
79
  when 'color'
78
80
  set_color(value)
79
81
  else
80
- set_text(value, options)
82
+ set_text(value, **options)
81
83
  end
82
84
  when 'textarea'
83
- set_text(value, options)
85
+ set_text(value, **options)
84
86
  else
85
87
  set_content_editable(value)
86
88
  end
@@ -202,7 +204,7 @@ protected
202
204
  JS
203
205
  begin
204
206
  driver.execute_script(script, self)
205
- rescue StandardError # rubocop:disable Lint/HandleExceptions
207
+ rescue StandardError # rubocop:disable Lint/SuppressedException
206
208
  # Swallow error if scrollIntoView with options isn't supported
207
209
  end
208
210
  end
@@ -25,7 +25,9 @@ class Capybara::Selenium::ChromeNode < Capybara::Selenium::Node
25
25
  end
26
26
  super
27
27
  rescue *file_errors => e
28
- raise ArgumentError, "Selenium < 3.14 with remote Chrome doesn't support multiple file upload" if e.message.match?(/File not found : .+\n.+/m)
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
- raise ::Selenium::WebDriver::Error::ElementClickInterceptedError, e.message if e.message.match?(/element click intercepted/)
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
@@ -25,7 +25,9 @@ class Capybara::Selenium::EdgeNode < Capybara::Selenium::Node
25
25
  end
26
26
  super
27
27
  rescue *file_errors => e
28
- raise ArgumentError, "Selenium < 3.14 with remote Chrome doesn't support multiple file upload" if e.message.match?(/File not found : .+\n.+/m)
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
@@ -24,7 +24,9 @@ module Capybara
24
24
  host: Capybara.server_host,
25
25
  reportable_errors: Capybara.server_errors,
26
26
  extra_middleware: [])
27
- warn 'Positional arguments, other than the application, to Server#new are deprecated, please use keyword arguments' unless deprecated_options.empty?
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 'Requests did not finish in 60 seconds' if timer.expired?
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
@@ -29,7 +29,7 @@ module Capybara
29
29
  end
30
30
 
31
31
  def https_request(&block)
32
- make_request(ssl_options, &block)
32
+ make_request(**ssl_options, &block)
33
33
  end
34
34
 
35
35
  def make_request(**options, &block)
@@ -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 = 0
8
+ @value = []
11
9
  @mutex = Mutex.new
12
10
  end
13
11
 
14
- def increment
15
- @mutex.synchronize { @value += 1 }
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 decrement
19
- @mutex.synchronize { @value -= 1 }
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.value.positive?
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
@@ -75,7 +75,9 @@ module Capybara
75
75
  attr_accessor :synchronized
76
76
 
77
77
  def initialize(mode, app = nil)
78
- raise TypeError, 'The second parameter to Session::new should be a rack app if passed.' if app && !app.respond_to?(:call)
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
@@ -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('`#within_window` requires a `Capybara::Window` instance or a lambda')
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
@@ -819,11 +821,11 @@ module Capybara
819
821
  end
820
822
 
821
823
  def accept_modal(type, text_or_options, options, &blk)
822
- driver.accept_modal(type, modal_options(text_or_options, options), &blk)
824
+ driver.accept_modal(type, **modal_options(text_or_options, **options), &blk)
823
825
  end
824
826
 
825
827
  def dismiss_modal(type, text_or_options, options, &blk)
826
- driver.dismiss_modal(type, modal_options(text_or_options, options), &blk)
828
+ driver.dismiss_modal(type, **modal_options(text_or_options, **options), &blk)
827
829
  end
828
830
 
829
831
  def modal_options(text = nil, **options)