capybara 3.32.2 → 3.35.2

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 (122) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +97 -15
  3. data/README.md +9 -4
  4. data/lib/capybara.rb +18 -8
  5. data/lib/capybara/config.rb +4 -6
  6. data/lib/capybara/cucumber.rb +1 -1
  7. data/lib/capybara/driver/base.rb +4 -0
  8. data/lib/capybara/helpers.rb +25 -1
  9. data/lib/capybara/minitest.rb +2 -3
  10. data/lib/capybara/minitest/spec.rb +14 -11
  11. data/lib/capybara/node/actions.rb +16 -21
  12. data/lib/capybara/node/base.rb +6 -6
  13. data/lib/capybara/node/element.rb +1 -5
  14. data/lib/capybara/node/finders.rb +7 -6
  15. data/lib/capybara/node/matchers.rb +12 -12
  16. data/lib/capybara/node/simple.rb +5 -1
  17. data/lib/capybara/queries/ancestor_query.rb +1 -1
  18. data/lib/capybara/queries/current_path_query.rb +14 -4
  19. data/lib/capybara/queries/selector_query.rb +40 -18
  20. data/lib/capybara/queries/sibling_query.rb +1 -1
  21. data/lib/capybara/queries/style_query.rb +1 -1
  22. data/lib/capybara/queries/text_query.rb +7 -1
  23. data/lib/capybara/rack_test/browser.rb +7 -3
  24. data/lib/capybara/rack_test/driver.rb +1 -0
  25. data/lib/capybara/rack_test/form.rb +1 -1
  26. data/lib/capybara/rack_test/node.rb +1 -1
  27. data/lib/capybara/registration_container.rb +44 -0
  28. data/lib/capybara/registrations/drivers.rb +18 -12
  29. data/lib/capybara/registrations/patches/puma_ssl.rb +3 -1
  30. data/lib/capybara/registrations/servers.rb +2 -1
  31. data/lib/capybara/result.rb +6 -10
  32. data/lib/capybara/rspec.rb +2 -0
  33. data/lib/capybara/rspec/matcher_proxies.rb +1 -1
  34. data/lib/capybara/rspec/matchers.rb +7 -6
  35. data/lib/capybara/rspec/matchers/have_current_path.rb +2 -2
  36. data/lib/capybara/rspec/matchers/match_style.rb +5 -0
  37. data/lib/capybara/selector.rb +12 -3
  38. data/lib/capybara/selector/builders/css_builder.rb +1 -1
  39. data/lib/capybara/selector/builders/xpath_builder.rb +3 -1
  40. data/lib/capybara/selector/definition.rb +11 -9
  41. data/lib/capybara/selector/definition/button.rb +26 -14
  42. data/lib/capybara/selector/definition/css.rb +1 -1
  43. data/lib/capybara/selector/definition/datalist_input.rb +1 -1
  44. data/lib/capybara/selector/definition/element.rb +2 -1
  45. data/lib/capybara/selector/definition/fillable_field.rb +1 -1
  46. data/lib/capybara/selector/definition/label.rb +1 -1
  47. data/lib/capybara/selector/definition/link.rb +8 -0
  48. data/lib/capybara/selector/definition/select.rb +1 -1
  49. data/lib/capybara/selector/definition/table.rb +1 -1
  50. data/lib/capybara/selector/definition/table_row.rb +2 -2
  51. data/lib/capybara/selector/filter_set.rb +2 -2
  52. data/lib/capybara/selector/selector.rb +9 -1
  53. data/lib/capybara/selenium/atoms/src/isDisplayed.js +1 -1
  54. data/lib/capybara/selenium/driver.rb +48 -4
  55. data/lib/capybara/selenium/driver_specializations/chrome_driver.rb +9 -11
  56. data/lib/capybara/selenium/driver_specializations/edge_driver.rb +9 -11
  57. data/lib/capybara/selenium/driver_specializations/firefox_driver.rb +1 -1
  58. data/lib/capybara/selenium/extensions/find.rb +4 -4
  59. data/lib/capybara/selenium/extensions/scroll.rb +8 -10
  60. data/lib/capybara/selenium/logger_suppressor.rb +8 -2
  61. data/lib/capybara/selenium/node.rb +9 -5
  62. data/lib/capybara/selenium/nodes/chrome_node.rb +23 -5
  63. data/lib/capybara/selenium/nodes/firefox_node.rb +7 -2
  64. data/lib/capybara/selenium/nodes/safari_node.rb +1 -1
  65. data/lib/capybara/selenium/patches/atoms.rb +4 -4
  66. data/lib/capybara/selenium/patches/logs.rb +7 -9
  67. data/lib/capybara/server/animation_disabler.rb +8 -3
  68. data/lib/capybara/server/middleware.rb +4 -2
  69. data/lib/capybara/session.rb +23 -14
  70. data/lib/capybara/session/config.rb +3 -1
  71. data/lib/capybara/session/matchers.rb +11 -11
  72. data/lib/capybara/spec/public/test.js +13 -1
  73. data/lib/capybara/spec/session/accept_alert_spec.rb +1 -1
  74. data/lib/capybara/spec/session/check_spec.rb +6 -0
  75. data/lib/capybara/spec/session/click_button_spec.rb +11 -0
  76. data/lib/capybara/spec/session/click_link_or_button_spec.rb +9 -0
  77. data/lib/capybara/spec/session/current_url_spec.rb +11 -1
  78. data/lib/capybara/spec/session/has_button_spec.rb +51 -0
  79. data/lib/capybara/spec/session/has_css_spec.rb +2 -1
  80. data/lib/capybara/spec/session/has_current_path_spec.rb +15 -2
  81. data/lib/capybara/spec/session/has_field_spec.rb +16 -0
  82. data/lib/capybara/spec/session/has_select_spec.rb +4 -4
  83. data/lib/capybara/spec/session/has_selector_spec.rb +4 -4
  84. data/lib/capybara/spec/session/has_text_spec.rb +0 -11
  85. data/lib/capybara/spec/session/html_spec.rb +1 -1
  86. data/lib/capybara/spec/session/matches_style_spec.rb +2 -2
  87. data/lib/capybara/spec/session/node_spec.rb +29 -9
  88. data/lib/capybara/spec/session/refresh_spec.rb +2 -1
  89. data/lib/capybara/spec/session/save_page_spec.rb +4 -4
  90. data/lib/capybara/spec/session/window/switch_to_window_spec.rb +1 -1
  91. data/lib/capybara/spec/session/window/window_opened_by_spec.rb +1 -1
  92. data/lib/capybara/spec/session/window/window_spec.rb +1 -1
  93. data/lib/capybara/spec/session/window/windows_spec.rb +1 -1
  94. data/lib/capybara/spec/spec_helper.rb +12 -12
  95. data/lib/capybara/spec/test_app.rb +23 -21
  96. data/lib/capybara/spec/views/form.erb +25 -2
  97. data/lib/capybara/spec/views/with_animation.erb +8 -0
  98. data/lib/capybara/spec/views/with_dragula.erb +3 -1
  99. data/lib/capybara/spec/views/with_jquery_animation.erb +24 -0
  100. data/lib/capybara/spec/views/with_js.erb +3 -0
  101. data/lib/capybara/spec/views/with_sortable_js.erb +1 -1
  102. data/lib/capybara/version.rb +1 -1
  103. data/lib/capybara/window.rb +3 -7
  104. data/spec/basic_node_spec.rb +9 -8
  105. data/spec/capybara_spec.rb +1 -1
  106. data/spec/dsl_spec.rb +14 -1
  107. data/spec/fixtures/selenium_driver_rspec_success.rb +1 -1
  108. data/spec/minitest_spec.rb +3 -2
  109. data/spec/rack_test_spec.rb +16 -5
  110. data/spec/rspec/features_spec.rb +3 -1
  111. data/spec/rspec/scenarios_spec.rb +4 -0
  112. data/spec/rspec/shared_spec_matchers.rb +61 -49
  113. data/spec/rspec_spec.rb +4 -0
  114. data/spec/selector_spec.rb +17 -2
  115. data/spec/selenium_spec_chrome.rb +39 -20
  116. data/spec/selenium_spec_chrome_remote.rb +5 -1
  117. data/spec/selenium_spec_firefox.rb +15 -13
  118. data/spec/server_spec.rb +60 -49
  119. data/spec/shared_selenium_session.rb +83 -1
  120. data/spec/spec_helper.rb +1 -1
  121. metadata +49 -14
  122. data/lib/capybara/spec/session/source_spec.rb +0 -0
@@ -45,20 +45,18 @@ module Capybara
45
45
  JS
46
46
  end
47
47
 
48
+ SCROLL_POSITIONS = {
49
+ top: '0',
50
+ bottom: 'arguments[0].scrollHeight',
51
+ center: '(arguments[0].scrollHeight - arguments[0].clientHeight)/2'
52
+ }.freeze
53
+
48
54
  def scroll_to_location(location)
49
- scroll_y = case location
50
- when :top
51
- '0'
52
- when :bottom
53
- 'arguments[0].scrollHeight'
54
- when :center
55
- '(arguments[0].scrollHeight - arguments[0].clientHeight)/2'
56
- end
57
55
  driver.execute_script <<~JS, self
58
56
  if (arguments[0].scrollTo){
59
- arguments[0].scrollTo(0, #{scroll_y});
57
+ arguments[0].scrollTo(0, #{SCROLL_POSITIONS[location]});
60
58
  } else {
61
- arguments[0].scrollTop = #{scroll_y};
59
+ arguments[0].scrollTop = #{SCROLL_POSITIONS[location]};
62
60
  }
63
61
  JS
64
62
  end
@@ -8,8 +8,14 @@ module Capybara
8
8
  super
9
9
  end
10
10
 
11
- def deprecate(*)
12
- super unless @suppress_for_capybara
11
+ def deprecate(*args, **opts, &block)
12
+ return if @suppress_for_capybara
13
+
14
+ if opts.empty?
15
+ super(*args, &block) # support Selenium 3
16
+ else
17
+ super
18
+ end
13
19
  end
14
20
 
15
21
  def suppress_deprecations
@@ -120,7 +120,7 @@ class Capybara::Selenium::Node < Capybara::Driver::Node
120
120
  end
121
121
  rescue StandardError => e
122
122
  if e.is_a?(::Selenium::WebDriver::Error::ElementClickInterceptedError) ||
123
- e.message.match?(/Other element would receive the click/)
123
+ e.message.include?('Other element would receive the click')
124
124
  scroll_to_center
125
125
  end
126
126
 
@@ -281,7 +281,7 @@ private
281
281
  driver.execute_script 'arguments[0].select()', self unless clear == :none
282
282
  if rapid == true || ((value.length > auto_rapid_set_length) && rapid != false)
283
283
  send_keys(value[0..3])
284
- driver.execute_script RAPID_SET_TEXT, self, value[0...-3]
284
+ driver.execute_script RAPID_APPEND_TEXT, self, value[4...-3]
285
285
  send_keys(value[-3..-1])
286
286
  else
287
287
  send_keys(value)
@@ -464,8 +464,8 @@ private
464
464
  end
465
465
  end
466
466
 
467
- def each_key(keys)
468
- normalize_keys(keys).each { |key| yield(key) }
467
+ def each_key(keys, &block)
468
+ normalize_keys(keys).each(&block)
469
469
  end
470
470
 
471
471
  def find_context
@@ -493,6 +493,9 @@ private
493
493
  var xpath = '';
494
494
  var pos, tempitem2;
495
495
 
496
+ if (el.getRootNode && el.getRootNode() instanceof ShadowRoot) {
497
+ return "(: Shadow DOM element - no XPath :)";
498
+ };
496
499
  while(el !== xml.documentElement) {
497
500
  pos = 0;
498
501
  tempitem2 = el;
@@ -534,8 +537,9 @@ private
534
537
  })(arguments[0], arguments[1], arguments[2])
535
538
  JS
536
539
 
537
- RAPID_SET_TEXT = <<~'JS'
540
+ RAPID_APPEND_TEXT = <<~'JS'
538
541
  (function(el, value) {
542
+ value = el.value + value;
539
543
  if (el.maxLength && el.maxLength != -1){
540
544
  value = value.slice(0, el.maxLength);
541
545
  }
@@ -42,7 +42,7 @@ class Capybara::Selenium::ChromeNode < Capybara::Selenium::Node
42
42
  raise
43
43
  rescue ::Selenium::WebDriver::Error::WebDriverError => e
44
44
  # chromedriver 74 (at least on mac) raises the wrong error for this
45
- if e.message.match?(/element click intercepted/)
45
+ if e.message.include?('element click intercepted')
46
46
  raise ::Selenium::WebDriver::Error::ElementClickInterceptedError, e.message
47
47
  end
48
48
 
@@ -73,6 +73,24 @@ class Capybara::Selenium::ChromeNode < Capybara::Selenium::Node
73
73
  end
74
74
  end
75
75
 
76
+ def send_keys(*args)
77
+ args.chunk { |inp| inp.is_a?(String) && inp.match?(/\p{Emoji Presentation}/) }
78
+ .each do |contains_emoji, inputs|
79
+ if contains_emoji
80
+ inputs.join.grapheme_clusters.chunk { |gc| gc.match?(/\p{Emoji Presentation}/) }
81
+ .each do |emoji, clusters|
82
+ if emoji
83
+ driver.send(:execute_cdp, 'Input.insertText', text: clusters.join)
84
+ else
85
+ super(clusters.join)
86
+ end
87
+ end
88
+ else
89
+ super(*inputs)
90
+ end
91
+ end
92
+ end
93
+
76
94
  private
77
95
 
78
96
  def perform_legacy_drag(element, drop_modifiers)
@@ -92,7 +110,7 @@ private
92
110
  end
93
111
  end
94
112
 
95
- def browser_version(to_float = true)
113
+ def browser_version(to_float: true)
96
114
  caps = capabilities
97
115
  ver = (caps[:browser_version] || caps[:version])
98
116
  ver = ver.to_f if to_float
@@ -100,15 +118,15 @@ private
100
118
  end
101
119
 
102
120
  def chromedriver_fixed_actions_key_state?
103
- Gem::Version.new(chromedriver_version) >= Gem::Version.new('76.0.3809.68')
121
+ Gem::Requirement.new('>= 76.0.3809.68').satisfied_by?(chromedriver_version)
104
122
  end
105
123
 
106
124
  def chromedriver_supports_displayed_endpoint?
107
- Gem::Version.new(chromedriver_version) >= Gem::Version.new('76.0.3809.25')
125
+ Gem::Requirement.new('>= 76.0.3809.25').satisfied_by?(chromedriver_version)
108
126
  end
109
127
 
110
128
  def chromedriver_version
111
- capabilities['chrome']['chromedriverVersion'].split(' ')[0]
129
+ Gem::Version.new(capabilities['chrome']['chromedriverVersion'].split(' ')[0]) # rubocop:disable Style/RedundantArgument
112
130
  end
113
131
 
114
132
  def native_displayed?
@@ -40,11 +40,16 @@ class Capybara::Selenium::FirefoxNode < Capybara::Selenium::Node
40
40
  path_names.each { |path| native.send_keys(path) }
41
41
  end
42
42
 
43
+ def focused?
44
+ driver.evaluate_script('arguments[0] == document.activeElement', self)
45
+ end
46
+
43
47
  def send_keys(*args)
44
48
  # https://github.com/mozilla/geckodriver/issues/846
45
- return super(*args.map { |arg| arg == :space ? ' ' : arg }) if args.none? { |arg| arg.is_a? Array }
49
+ return super(*args.map { |arg| arg == :space ? ' ' : arg }) if args.none?(Array)
50
+
51
+ native.click unless focused?
46
52
 
47
- native.click
48
53
  _send_keys(args).perform
49
54
  end
50
55
 
@@ -43,7 +43,7 @@ class Capybara::Selenium::SafariNode < Capybara::Selenium::Node
43
43
  return '' unless visible?
44
44
 
45
45
  vis_text = driver.execute_script('return arguments[0].innerText', self)
46
- vis_text.gsub(/\ +/, ' ')
46
+ vis_text.squeeze(' ')
47
47
  .gsub(/[\ \n]*\n[\ \n]*/, "\n")
48
48
  .gsub(/\A[[:space:]&&[^\u00a0]]+/, '')
49
49
  .gsub(/[[:space:]&&[^\u00a0]]+\z/, '')
@@ -6,10 +6,10 @@ private
6
6
  def read_atom(function)
7
7
  @atoms ||= Hash.new do |hash, key|
8
8
  hash[key] = begin
9
- File.read(File.expand_path("../../atoms/#{key}.min.js", __FILE__))
10
- rescue Errno::ENOENT
11
- super
12
- end
9
+ File.read(File.expand_path("../../atoms/#{key}.min.js", __FILE__))
10
+ rescue Errno::ENOENT
11
+ super
12
+ end
13
13
  end
14
14
  @atoms[function]
15
15
  end
@@ -27,17 +27,15 @@ module Capybara
27
27
 
28
28
  def log(type)
29
29
  data = begin
30
- execute :get_log, {}, type: type.to_s
31
- rescue ::Selenium::WebDriver::Error::UnknownCommandError
32
- execute :get_log_legacy, {}, type: type.to_s
33
- end
30
+ execute :get_log, {}, type: type.to_s
31
+ rescue ::Selenium::WebDriver::Error::UnknownCommandError
32
+ execute :get_log_legacy, {}, type: type.to_s
33
+ end
34
34
 
35
35
  Array(data).map do |l|
36
- begin
37
- ::Selenium::WebDriver::LogEntry.new l.fetch('level', 'UNKNOWN'), l.fetch('timestamp'), l.fetch('message')
38
- rescue KeyError
39
- next
40
- end
36
+ ::Selenium::WebDriver::LogEntry.new l.fetch('level', 'UNKNOWN'), l.fetch('timestamp'), l.fetch('message')
37
+ rescue KeyError
38
+ next
41
39
  end
42
40
  rescue ::Selenium::WebDriver::Error::UnknownCommandError
43
41
  raise NotImplementedError, LOG_MSG
@@ -40,16 +40,21 @@ module Capybara
40
40
  end
41
41
 
42
42
  def insert_disable(html)
43
- html.sub(%r{(</head>)}, disable_markup + '\\1')
43
+ html.sub(%r{(</body>)}, "#{disable_markup}\\1")
44
44
  end
45
45
 
46
46
  DISABLE_MARKUP_TEMPLATE = <<~HTML
47
- <script defer>(typeof jQuery !== 'undefined') && (jQuery.fx.off = true);</script>
47
+ <script>
48
+ //<![CDATA[
49
+ (typeof jQuery !== 'undefined') && (jQuery.fx.off = true);
50
+ //]]>
51
+ </script>
48
52
  <style>
49
- %<selector>s, %<selector>s::before, %<selector>s::after {
53
+ %<selector>s, %<selector>s::before, %<selector>s::after {
50
54
  transition: none !important;
51
55
  animation-duration: 0s !important;
52
56
  animation-delay: 0s !important;
57
+ scroll-behavior: auto !important;
53
58
  }
54
59
  </style>
55
60
  HTML
@@ -53,14 +53,16 @@ module Capybara
53
53
  if env['PATH_INFO'] == '/__identify__'
54
54
  [200, {}, [@app.object_id.to_s]]
55
55
  else
56
- @counter.increment(env['REQUEST_URI'])
56
+ request_uri = env['REQUEST_URI']
57
+ @counter.increment(request_uri)
58
+
57
59
  begin
58
60
  @extended_app.call(env)
59
61
  rescue *@server_errors => e
60
62
  @error ||= e
61
63
  raise e
62
64
  ensure
63
- @counter.decrement(env['REQUEST_URI'])
65
+ @counter.decrement(request_uri)
64
66
  end
65
67
  end
66
68
  end
@@ -58,7 +58,7 @@ module Capybara
58
58
  ].freeze
59
59
  SESSION_METHODS = %i[
60
60
  body html source current_url current_host current_path
61
- execute_script evaluate_script visit refresh go_back go_forward
61
+ execute_script evaluate_script visit refresh go_back go_forward send_keys
62
62
  within within_element within_fieldset within_table within_frame switch_to_frame
63
63
  current_window windows open_new_window switch_to_window within_window window_opened_by
64
64
  save_page save_and_open_page save_screenshot
@@ -97,8 +97,8 @@ module Capybara
97
97
 
98
98
  def driver
99
99
  @driver ||= begin
100
- unless Capybara.drivers.key?(mode)
101
- other_drivers = Capybara.drivers.keys.map(&:inspect)
100
+ unless Capybara.drivers[mode]
101
+ other_drivers = Capybara.drivers.names.map(&:inspect)
102
102
  raise Capybara::DriverNotFoundError, "no driver called #{mode.inspect} was found, available drivers: #{other_drivers.join(', ')}"
103
103
  end
104
104
  driver = Capybara.drivers[mode].call(app)
@@ -192,7 +192,7 @@ module Capybara
192
192
  # @return [String] A snapshot of the DOM of the current document, as it looks right now (potentially modified by JavaScript).
193
193
  #
194
194
  def html
195
- driver.html
195
+ driver.html || ''
196
196
  end
197
197
  alias_method :body, :html
198
198
  alias_method :source, :html
@@ -303,6 +303,14 @@ module Capybara
303
303
  driver.go_forward
304
304
  end
305
305
 
306
+ ##
307
+ # @!method send_keys
308
+ # @see Capybara::Node::Element#send_keys
309
+ #
310
+ def send_keys(*args, **kw_args)
311
+ driver.send_keys(*args, **kw_args)
312
+ end
313
+
306
314
  ##
307
315
  #
308
316
  # Executes the given block within the context of a node. {#within} takes the
@@ -355,8 +363,8 @@ module Capybara
355
363
  #
356
364
  # @param [String] locator Id or legend of the fieldset
357
365
  #
358
- def within_fieldset(locator)
359
- within(:fieldset, locator) { yield }
366
+ def within_fieldset(locator, &block)
367
+ within(:fieldset, locator, &block)
360
368
  end
361
369
 
362
370
  ##
@@ -365,8 +373,8 @@ module Capybara
365
373
  #
366
374
  # @param [String] locator Id or caption of the table
367
375
  #
368
- def within_table(locator)
369
- within(:table, locator) { yield }
376
+ def within_table(locator, &block)
377
+ within(:table, locator, &block)
370
378
  end
371
379
 
372
380
  ##
@@ -398,8 +406,9 @@ module Capybara
398
406
  driver.switch_to_frame(:parent)
399
407
  when :top
400
408
  idx = scopes.index(:frame)
409
+ top_level_scopes = [:frame, nil]
401
410
  if idx
402
- if scopes.slice(idx..-1).any? { |scope| ![:frame, nil].include?(scope) }
411
+ if scopes.slice(idx..-1).any? { |scope| !top_level_scopes.include?(scope) }
403
412
  raise Capybara::ScopeError, "`switch_to_frame(:top)` cannot be called from inside a descendant frame's "\
404
413
  '`within` block.'
405
414
  end
@@ -488,8 +497,8 @@ module Capybara
488
497
  # @raise [ArgumentError] if both or neither arguments were provided
489
498
  #
490
499
  def switch_to_window(window = nil, **options, &window_locator)
491
- raise ArgumentError, '`switch_to_window` can take either a block or a window, not both' if window && block_given?
492
- raise ArgumentError, '`switch_to_window`: either window or block should be provided' if !window && !block_given?
500
+ raise ArgumentError, '`switch_to_window` can take either a block or a window, not both' if window && window_locator
501
+ raise ArgumentError, '`switch_to_window`: either window or block should be provided' if !window && !window_locator
493
502
 
494
503
  unless scopes.last.nil?
495
504
  raise Capybara::ScopeError, '`switch_to_window` is not supposed to be invoked from '\
@@ -738,7 +747,7 @@ module Capybara
738
747
  # @param [Hash] options a customizable set of options
739
748
  #
740
749
  def save_and_open_screenshot(path = nil, **options)
741
- save_screenshot(path, **options).tap { |s_path| open_file(s_path) } # rubocop:disable Lint/Debugger
750
+ save_screenshot(path, **options).tap { |s_path| open_file(s_path) }
742
751
  end
743
752
 
744
753
  def document
@@ -788,7 +797,7 @@ module Capybara
788
797
  #
789
798
  # Yield a block using a specific maximum wait time.
790
799
  #
791
- def using_wait_time(seconds)
800
+ def using_wait_time(seconds, &block)
792
801
  if Capybara.threadsafe
793
802
  begin
794
803
  previous_wait_time = config.default_max_wait_time
@@ -798,7 +807,7 @@ module Capybara
798
807
  config.default_max_wait_time = previous_wait_time
799
808
  end
800
809
  else
801
- Capybara.using_wait_time(seconds) { yield }
810
+ Capybara.using_wait_time(seconds, &block)
802
811
  end
803
812
  end
804
813
 
@@ -8,7 +8,7 @@ module Capybara
8
8
  automatic_reload match exact exact_text raise_server_errors visible_text_only
9
9
  automatic_label_click enable_aria_label save_path asset_host default_host app_host
10
10
  server_host server_port server_errors default_set_options disable_animation test_id
11
- predicates_wait default_normalize_ws w3c_click_offset].freeze
11
+ predicates_wait default_normalize_ws w3c_click_offset enable_aria_role].freeze
12
12
 
13
13
  attr_accessor(*OPTIONS)
14
14
 
@@ -37,6 +37,8 @@ module Capybara
37
37
  # See {Capybara.configure}
38
38
  # @!method enable_aria_label
39
39
  # See {Capybara.configure}
40
+ # @!method enable_aria_role
41
+ # See {Capybara.configure}
40
42
  # @!method save_path
41
43
  # See {Capybara.configure}
42
44
  # @!method asset_host
@@ -13,14 +13,14 @@ module Capybara
13
13
  # @param string [String] The string that the current 'path' should equal
14
14
  # @overload $0(regexp, **options)
15
15
  # @param regexp [Regexp] The regexp that the current 'path' should match to
16
- # @option options [Boolean] :url (true if `string` ia a full url, otherwise false) Whether the compare should be done against the full current url or just the path
16
+ # @option options [Boolean] :url (true if `string` is a full url, otherwise false) Whether the comparison should be done against the full current url or just the path
17
17
  # @option options [Boolean] :ignore_query (false) Whether the query portion of the current url/path should be ignored
18
18
  # @option options [Numeric] :wait (Capybara.default_max_wait_time) Maximum time that Capybara will wait for the current url/path to eq/match given string/regexp argument
19
19
  # @raise [Capybara::ExpectationNotMet] if the assertion hasn't succeeded during wait time
20
20
  # @return [true]
21
21
  #
22
- def assert_current_path(path, **options)
23
- _verify_current_path(path, **options) do |query|
22
+ def assert_current_path(path, **options, &optional_filter_block)
23
+ _verify_current_path(path, optional_filter_block, **options) do |query|
24
24
  raise Capybara::ExpectationNotMet, query.failure_message unless query.resolves_for?(self)
25
25
  end
26
26
  end
@@ -35,8 +35,8 @@ module Capybara
35
35
  # @raise [Capybara::ExpectationNotMet] if the assertion hasn't succeeded during wait time
36
36
  # @return [true]
37
37
  #
38
- def assert_no_current_path(path, **options)
39
- _verify_current_path(path, **options) do |query|
38
+ def assert_no_current_path(path, **options, &optional_filter_block)
39
+ _verify_current_path(path, optional_filter_block, **options) do |query|
40
40
  raise Capybara::ExpectationNotMet, query.negative_failure_message if query.resolves_for?(self)
41
41
  end
42
42
  end
@@ -50,8 +50,8 @@ module Capybara
50
50
  # @macro current_path_query_params
51
51
  # @return [Boolean]
52
52
  #
53
- def has_current_path?(path, **options)
54
- make_predicate(options) { assert_current_path(path, **options) }
53
+ def has_current_path?(path, **options, &optional_filter_block)
54
+ make_predicate(options) { assert_current_path(path, **options, &optional_filter_block) }
55
55
  end
56
56
 
57
57
  ##
@@ -63,14 +63,14 @@ module Capybara
63
63
  # @macro current_path_query_params
64
64
  # @return [Boolean]
65
65
  #
66
- def has_no_current_path?(path, **options)
67
- make_predicate(options) { assert_no_current_path(path, **options) }
66
+ def has_no_current_path?(path, **options, &optional_filter_block)
67
+ make_predicate(options) { assert_no_current_path(path, **options, &optional_filter_block) }
68
68
  end
69
69
 
70
70
  private
71
71
 
72
- def _verify_current_path(path, **options)
73
- query = Capybara::Queries::CurrentPathQuery.new(path, **options)
72
+ def _verify_current_path(path, filter_block, **options)
73
+ query = Capybara::Queries::CurrentPathQuery.new(path, **options, &filter_block)
74
74
  document.synchronize(query.wait) do
75
75
  yield(query)
76
76
  end