capybara 3.23.0 → 3.35.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (183) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +264 -11
  3. data/README.md +10 -6
  4. data/lib/capybara.rb +20 -8
  5. data/lib/capybara/config.rb +10 -8
  6. data/lib/capybara/cucumber.rb +1 -1
  7. data/lib/capybara/driver/base.rb +4 -0
  8. data/lib/capybara/driver/node.rb +4 -0
  9. data/lib/capybara/dsl.rb +10 -2
  10. data/lib/capybara/helpers.rb +28 -2
  11. data/lib/capybara/minitest.rb +232 -144
  12. data/lib/capybara/minitest/spec.rb +156 -97
  13. data/lib/capybara/node/actions.rb +36 -36
  14. data/lib/capybara/node/base.rb +6 -6
  15. data/lib/capybara/node/document.rb +2 -2
  16. data/lib/capybara/node/document_matchers.rb +3 -3
  17. data/lib/capybara/node/element.rb +77 -33
  18. data/lib/capybara/node/finders.rb +24 -17
  19. data/lib/capybara/node/matchers.rb +79 -64
  20. data/lib/capybara/node/simple.rb +11 -4
  21. data/lib/capybara/queries/ancestor_query.rb +6 -10
  22. data/lib/capybara/queries/base_query.rb +2 -1
  23. data/lib/capybara/queries/current_path_query.rb +14 -4
  24. data/lib/capybara/queries/selector_query.rb +259 -23
  25. data/lib/capybara/queries/sibling_query.rb +5 -11
  26. data/lib/capybara/queries/style_query.rb +1 -1
  27. data/lib/capybara/queries/text_query.rb +13 -1
  28. data/lib/capybara/rack_test/browser.rb +13 -4
  29. data/lib/capybara/rack_test/driver.rb +2 -1
  30. data/lib/capybara/rack_test/form.rb +2 -2
  31. data/lib/capybara/rack_test/node.rb +42 -6
  32. data/lib/capybara/registration_container.rb +44 -0
  33. data/lib/capybara/registrations/drivers.rb +18 -12
  34. data/lib/capybara/registrations/patches/puma_ssl.rb +29 -0
  35. data/lib/capybara/registrations/servers.rb +9 -2
  36. data/lib/capybara/result.rb +39 -19
  37. data/lib/capybara/rspec.rb +2 -0
  38. data/lib/capybara/rspec/matcher_proxies.rb +5 -5
  39. data/lib/capybara/rspec/matchers.rb +97 -74
  40. data/lib/capybara/rspec/matchers/base.rb +19 -6
  41. data/lib/capybara/rspec/matchers/count_sugar.rb +2 -1
  42. data/lib/capybara/rspec/matchers/have_ancestor.rb +5 -7
  43. data/lib/capybara/rspec/matchers/have_current_path.rb +2 -2
  44. data/lib/capybara/rspec/matchers/have_selector.rb +15 -10
  45. data/lib/capybara/rspec/matchers/have_sibling.rb +4 -7
  46. data/lib/capybara/rspec/matchers/have_text.rb +4 -7
  47. data/lib/capybara/rspec/matchers/have_title.rb +2 -2
  48. data/lib/capybara/rspec/matchers/match_selector.rb +3 -3
  49. data/lib/capybara/rspec/matchers/match_style.rb +7 -2
  50. data/lib/capybara/rspec/matchers/spatial_sugar.rb +39 -0
  51. data/lib/capybara/selector.rb +46 -19
  52. data/lib/capybara/selector/builders/css_builder.rb +10 -6
  53. data/lib/capybara/selector/builders/xpath_builder.rb +4 -2
  54. data/lib/capybara/selector/css.rb +1 -1
  55. data/lib/capybara/selector/definition.rb +13 -11
  56. data/lib/capybara/selector/definition/button.rb +32 -15
  57. data/lib/capybara/selector/definition/checkbox.rb +2 -2
  58. data/lib/capybara/selector/definition/css.rb +3 -1
  59. data/lib/capybara/selector/definition/datalist_input.rb +2 -2
  60. data/lib/capybara/selector/definition/datalist_option.rb +1 -1
  61. data/lib/capybara/selector/definition/element.rb +3 -2
  62. data/lib/capybara/selector/definition/field.rb +1 -1
  63. data/lib/capybara/selector/definition/file_field.rb +1 -1
  64. data/lib/capybara/selector/definition/fillable_field.rb +2 -2
  65. data/lib/capybara/selector/definition/label.rb +5 -3
  66. data/lib/capybara/selector/definition/link.rb +8 -0
  67. data/lib/capybara/selector/definition/option.rb +1 -1
  68. data/lib/capybara/selector/definition/radio_button.rb +2 -2
  69. data/lib/capybara/selector/definition/select.rb +33 -14
  70. data/lib/capybara/selector/definition/table.rb +6 -3
  71. data/lib/capybara/selector/definition/table_row.rb +2 -2
  72. data/lib/capybara/selector/filter_set.rb +13 -11
  73. data/lib/capybara/selector/filters/base.rb +6 -1
  74. data/lib/capybara/selector/filters/locator_filter.rb +1 -1
  75. data/lib/capybara/selector/regexp_disassembler.rb +7 -0
  76. data/lib/capybara/selector/selector.rb +13 -3
  77. data/lib/capybara/selenium/atoms/getAttribute.min.js +1 -1
  78. data/lib/capybara/selenium/atoms/isDisplayed.min.js +1 -1
  79. data/lib/capybara/selenium/atoms/src/getAttribute.js +1 -1
  80. data/lib/capybara/selenium/atoms/src/isDisplayed.js +10 -10
  81. data/lib/capybara/selenium/driver.rb +86 -24
  82. data/lib/capybara/selenium/driver_specializations/chrome_driver.rb +24 -21
  83. data/lib/capybara/selenium/driver_specializations/edge_driver.rb +21 -19
  84. data/lib/capybara/selenium/driver_specializations/firefox_driver.rb +17 -1
  85. data/lib/capybara/selenium/driver_specializations/safari_driver.rb +0 -4
  86. data/lib/capybara/selenium/extensions/file_input_click_emulation.rb +34 -0
  87. data/lib/capybara/selenium/extensions/find.rb +37 -26
  88. data/lib/capybara/selenium/extensions/html5_drag.rb +55 -11
  89. data/lib/capybara/selenium/extensions/modifier_keys_stack.rb +28 -0
  90. data/lib/capybara/selenium/extensions/scroll.rb +8 -10
  91. data/lib/capybara/selenium/logger_suppressor.rb +8 -2
  92. data/lib/capybara/selenium/node.rb +160 -40
  93. data/lib/capybara/selenium/nodes/chrome_node.rb +72 -12
  94. data/lib/capybara/selenium/nodes/edge_node.rb +32 -14
  95. data/lib/capybara/selenium/nodes/firefox_node.rb +28 -32
  96. data/lib/capybara/selenium/nodes/safari_node.rb +5 -29
  97. data/lib/capybara/selenium/patches/action_pauser.rb +26 -0
  98. data/lib/capybara/selenium/patches/atoms.rb +4 -4
  99. data/lib/capybara/selenium/patches/is_displayed.rb +16 -0
  100. data/lib/capybara/selenium/patches/logs.rb +32 -7
  101. data/lib/capybara/server.rb +19 -3
  102. data/lib/capybara/server/animation_disabler.rb +8 -3
  103. data/lib/capybara/server/checker.rb +1 -1
  104. data/lib/capybara/server/middleware.rb +22 -10
  105. data/lib/capybara/session.rb +66 -40
  106. data/lib/capybara/session/config.rb +11 -3
  107. data/lib/capybara/session/matchers.rb +11 -11
  108. data/lib/capybara/spec/public/offset.js +6 -0
  109. data/lib/capybara/spec/public/test.js +75 -7
  110. data/lib/capybara/spec/session/accept_alert_spec.rb +1 -1
  111. data/lib/capybara/spec/session/all_spec.rb +60 -5
  112. data/lib/capybara/spec/session/ancestor_spec.rb +5 -0
  113. data/lib/capybara/spec/session/assert_text_spec.rb +9 -5
  114. data/lib/capybara/spec/session/check_spec.rb +6 -0
  115. data/lib/capybara/spec/session/click_button_spec.rb +16 -0
  116. data/lib/capybara/spec/session/click_link_or_button_spec.rb +9 -0
  117. data/lib/capybara/spec/session/current_url_spec.rb +11 -1
  118. data/lib/capybara/spec/session/fill_in_spec.rb +29 -0
  119. data/lib/capybara/spec/session/find_spec.rb +55 -0
  120. data/lib/capybara/spec/session/has_ancestor_spec.rb +2 -0
  121. data/lib/capybara/spec/session/has_button_spec.rb +51 -0
  122. data/lib/capybara/spec/session/has_css_spec.rb +26 -4
  123. data/lib/capybara/spec/session/has_current_path_spec.rb +15 -2
  124. data/lib/capybara/spec/session/has_field_spec.rb +34 -0
  125. data/lib/capybara/spec/session/has_select_spec.rb +32 -4
  126. data/lib/capybara/spec/session/has_selector_spec.rb +4 -4
  127. data/lib/capybara/spec/session/has_table_spec.rb +51 -5
  128. data/lib/capybara/spec/session/has_text_spec.rb +30 -0
  129. data/lib/capybara/spec/session/html_spec.rb +1 -1
  130. data/lib/capybara/spec/session/matches_style_spec.rb +2 -2
  131. data/lib/capybara/spec/session/node_spec.rb +394 -9
  132. data/lib/capybara/spec/session/refresh_spec.rb +2 -1
  133. data/lib/capybara/spec/session/save_and_open_screenshot_spec.rb +2 -2
  134. data/lib/capybara/spec/session/save_page_spec.rb +4 -4
  135. data/lib/capybara/spec/session/save_screenshot_spec.rb +4 -15
  136. data/lib/capybara/spec/session/selectors_spec.rb +16 -3
  137. data/lib/capybara/spec/session/window/switch_to_window_spec.rb +1 -1
  138. data/lib/capybara/spec/session/window/window_opened_by_spec.rb +1 -1
  139. data/lib/capybara/spec/session/window/window_spec.rb +8 -8
  140. data/lib/capybara/spec/session/window/windows_spec.rb +1 -1
  141. data/lib/capybara/spec/spec_helper.rb +14 -14
  142. data/lib/capybara/spec/test_app.rb +27 -21
  143. data/lib/capybara/spec/views/form.erb +47 -4
  144. data/lib/capybara/spec/views/offset.erb +32 -0
  145. data/lib/capybara/spec/views/spatial.erb +31 -0
  146. data/lib/capybara/spec/views/with_animation.erb +37 -1
  147. data/lib/capybara/spec/views/with_dragula.erb +24 -0
  148. data/lib/capybara/spec/views/with_html.erb +24 -2
  149. data/lib/capybara/spec/views/with_jquery_animation.erb +24 -0
  150. data/lib/capybara/spec/views/with_js.erb +4 -1
  151. data/lib/capybara/spec/views/with_jstree.erb +26 -0
  152. data/lib/capybara/spec/views/with_sortable_js.erb +1 -1
  153. data/lib/capybara/version.rb +1 -1
  154. data/lib/capybara/window.rb +3 -7
  155. data/spec/basic_node_spec.rb +15 -14
  156. data/spec/capybara_spec.rb +28 -28
  157. data/spec/dsl_spec.rb +16 -3
  158. data/spec/filter_set_spec.rb +5 -5
  159. data/spec/fixtures/selenium_driver_rspec_failure.rb +1 -1
  160. data/spec/fixtures/selenium_driver_rspec_success.rb +1 -1
  161. data/spec/minitest_spec.rb +3 -2
  162. data/spec/minitest_spec_spec.rb +46 -46
  163. data/spec/rack_test_spec.rb +38 -15
  164. data/spec/regexp_dissassembler_spec.rb +52 -38
  165. data/spec/result_spec.rb +43 -32
  166. data/spec/rspec/features_spec.rb +4 -1
  167. data/spec/rspec/scenarios_spec.rb +4 -0
  168. data/spec/rspec/shared_spec_matchers.rb +68 -56
  169. data/spec/rspec_spec.rb +9 -5
  170. data/spec/selector_spec.rb +32 -17
  171. data/spec/selenium_spec_chrome.rb +78 -11
  172. data/spec/selenium_spec_chrome_remote.rb +23 -6
  173. data/spec/selenium_spec_edge.rb +15 -12
  174. data/spec/selenium_spec_firefox.rb +24 -19
  175. data/spec/selenium_spec_firefox_remote.rb +0 -8
  176. data/spec/selenium_spec_ie.rb +1 -6
  177. data/spec/server_spec.rb +106 -44
  178. data/spec/session_spec.rb +5 -5
  179. data/spec/shared_selenium_node.rb +56 -2
  180. data/spec/shared_selenium_session.rb +122 -15
  181. data/spec/spec_helper.rb +2 -2
  182. metadata +63 -17
  183. data/lib/capybara/spec/session/source_spec.rb +0 -0
@@ -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) }
18
+ end
19
+
20
+ def positive?
21
+ @mutex.synchronize { @value.length.positive? }
16
22
  end
17
23
 
18
- def decrement
19
- @mutex.synchronize { @value -= 1 }
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,16 @@ module Capybara
43
53
  if env['PATH_INFO'] == '/__identify__'
44
54
  [200, {}, [@app.object_id.to_s]]
45
55
  else
46
- @counter.increment
56
+ request_uri = env['REQUEST_URI']
57
+ @counter.increment(request_uri)
58
+
47
59
  begin
48
60
  @extended_app.call(env)
49
61
  rescue *@server_errors => e
50
62
  @error ||= e
51
63
  raise e
52
64
  ensure
53
- @counter.decrement
65
+ @counter.decrement(request_uri)
54
66
  end
55
67
  end
56
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
@@ -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,15 +90,15 @@ 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
95
97
 
96
98
  def driver
97
99
  @driver ||= begin
98
- unless Capybara.drivers.key?(mode)
99
- other_drivers = Capybara.drivers.keys.map(&:inspect)
100
+ unless Capybara.drivers[mode]
101
+ other_drivers = Capybara.drivers.names.map(&:inspect)
100
102
  raise Capybara::DriverNotFoundError, "no driver called #{mode.inspect} was found, available drivers: #{other_drivers.join(', ')}"
101
103
  end
102
104
  driver = Capybara.drivers[mode].call(app)
@@ -190,7 +192,7 @@ module Capybara
190
192
  # @return [String] A snapshot of the DOM of the current document, as it looks right now (potentially modified by JavaScript).
191
193
  #
192
194
  def html
193
- driver.html
195
+ driver.html || ''
194
196
  end
195
197
  alias_method :body, :html
196
198
  alias_method :source, :html
@@ -301,6 +303,14 @@ module Capybara
301
303
  driver.go_forward
302
304
  end
303
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
+
304
314
  ##
305
315
  #
306
316
  # Executes the given block within the context of a node. {#within} takes the
@@ -336,8 +346,8 @@ module Capybara
336
346
  #
337
347
  # @raise [Capybara::ElementNotFound] If the scope can't be found before time expires
338
348
  #
339
- def within(*args)
340
- new_scope = args.first.respond_to?(:to_capybara_node) ? args.first.to_capybara_node : find(*args)
349
+ def within(*args, **kw_args)
350
+ new_scope = args.first.respond_to?(:to_capybara_node) ? args.first.to_capybara_node : find(*args, **kw_args)
341
351
  begin
342
352
  scopes.push(new_scope)
343
353
  yield if block_given?
@@ -353,8 +363,8 @@ module Capybara
353
363
  #
354
364
  # @param [String] locator Id or legend of the fieldset
355
365
  #
356
- def within_fieldset(locator)
357
- within(:fieldset, locator) { yield }
366
+ def within_fieldset(locator, &block)
367
+ within(:fieldset, locator, &block)
358
368
  end
359
369
 
360
370
  ##
@@ -363,8 +373,8 @@ module Capybara
363
373
  #
364
374
  # @param [String] locator Id or caption of the table
365
375
  #
366
- def within_table(locator)
367
- within(:table, locator) { yield }
376
+ def within_table(locator, &block)
377
+ within(:table, locator, &block)
368
378
  end
369
379
 
370
380
  ##
@@ -396,8 +406,9 @@ module Capybara
396
406
  driver.switch_to_frame(:parent)
397
407
  when :top
398
408
  idx = scopes.index(:frame)
409
+ top_level_scopes = [:frame, nil]
399
410
  if idx
400
- if scopes.slice(idx..-1).any? { |scope| ![:frame, nil].include?(scope) }
411
+ if scopes.slice(idx..-1).any? { |scope| !top_level_scopes.include?(scope) }
401
412
  raise Capybara::ScopeError, "`switch_to_frame(:top)` cannot be called from inside a descendant frame's "\
402
413
  '`within` block.'
403
414
  end
@@ -421,8 +432,8 @@ module Capybara
421
432
  # @param [String] locator The locator for the given selector kind. For :frame this is the name/id of a frame/iframe element
422
433
  # @overload within_frame(index)
423
434
  # @param [Integer] index index of a frame (0 based)
424
- def within_frame(*args)
425
- switch_to_frame(_find_frame(*args))
435
+ def within_frame(*args, **kw_args)
436
+ switch_to_frame(_find_frame(*args, **kw_args))
426
437
  begin
427
438
  yield if block_given?
428
439
  ensure
@@ -486,15 +497,15 @@ module Capybara
486
497
  # @raise [ArgumentError] if both or neither arguments were provided
487
498
  #
488
499
  def switch_to_window(window = nil, **options, &window_locator)
489
- raise ArgumentError, '`switch_to_window` can take either a block or a window, not both' if window && block_given?
490
- 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
491
502
 
492
503
  unless scopes.last.nil?
493
504
  raise Capybara::ScopeError, '`switch_to_window` is not supposed to be invoked from '\
494
505
  '`within` or `within_frame` blocks.'
495
506
  end
496
507
 
497
- _switch_to_window(window, options, &window_locator)
508
+ _switch_to_window(window, **options, &window_locator)
498
509
  end
499
510
 
500
511
  ##
@@ -528,7 +539,7 @@ module Capybara
528
539
  when Proc
529
540
  _switch_to_window { window_or_proc.call }
530
541
  else
531
- raise ArgumentError('`#within_window` requires a `Capybara::Window` instance or a lambda')
542
+ raise ArgumentError, '`#within_window` requires a `Capybara::Window` instance or a lambda'
532
543
  end
533
544
 
534
545
  begin
@@ -721,7 +732,7 @@ module Capybara
721
732
  # @param [Hash] options a customizable set of options
722
733
  # @return [String] the path to which the file was saved
723
734
  def save_screenshot(path = nil, **options)
724
- prepare_path(path, 'png').tap { |p_path| driver.save_screenshot(p_path, options) }
735
+ prepare_path(path, 'png').tap { |p_path| driver.save_screenshot(p_path, **options) }
725
736
  end
726
737
 
727
738
  ##
@@ -736,7 +747,7 @@ module Capybara
736
747
  # @param [Hash] options a customizable set of options
737
748
  #
738
749
  def save_and_open_screenshot(path = nil, **options)
739
- 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) }
740
751
  end
741
752
 
742
753
  def document
@@ -744,15 +755,32 @@ module Capybara
744
755
  end
745
756
 
746
757
  NODE_METHODS.each do |method|
747
- define_method method do |*args, &block|
748
- @touched = true
749
- current_scope.send(method, *args, &block)
758
+ if RUBY_VERSION >= '2.7'
759
+ class_eval <<~METHOD, __FILE__, __LINE__ + 1
760
+ def #{method}(...)
761
+ @touched = true
762
+ current_scope.#{method}(...)
763
+ end
764
+ METHOD
765
+ else
766
+ define_method method do |*args, &block|
767
+ @touched = true
768
+ current_scope.send(method, *args, &block)
769
+ end
750
770
  end
751
771
  end
752
772
 
753
773
  DOCUMENT_METHODS.each do |method|
754
- define_method method do |*args, &block|
755
- document.send(method, *args, &block)
774
+ if RUBY_VERSION >= '2.7'
775
+ class_eval <<~METHOD, __FILE__, __LINE__ + 1
776
+ def #{method}(...)
777
+ document.#{method}(...)
778
+ end
779
+ METHOD
780
+ else
781
+ define_method method do |*args, &block|
782
+ document.send(method, *args, &block)
783
+ end
756
784
  end
757
785
  end
758
786
 
@@ -769,7 +797,7 @@ module Capybara
769
797
  #
770
798
  # Yield a block using a specific maximum wait time.
771
799
  #
772
- def using_wait_time(seconds)
800
+ def using_wait_time(seconds, &block)
773
801
  if Capybara.threadsafe
774
802
  begin
775
803
  previous_wait_time = config.default_max_wait_time
@@ -779,7 +807,7 @@ module Capybara
779
807
  config.default_max_wait_time = previous_wait_time
780
808
  end
781
809
  else
782
- Capybara.using_wait_time(seconds) { yield }
810
+ Capybara.using_wait_time(seconds, &block)
783
811
  end
784
812
  end
785
813
 
@@ -806,6 +834,10 @@ module Capybara
806
834
  end
807
835
  end
808
836
 
837
+ def server_url
838
+ @server&.base_url
839
+ end
840
+
809
841
  private
810
842
 
811
843
  @@instance_created = false # rubocop:disable Style/ClassVars
@@ -815,11 +847,11 @@ module Capybara
815
847
  end
816
848
 
817
849
  def accept_modal(type, text_or_options, options, &blk)
818
- driver.accept_modal(type, modal_options(text_or_options, options), &blk)
850
+ driver.accept_modal(type, **modal_options(text_or_options, **options), &blk)
819
851
  end
820
852
 
821
853
  def dismiss_modal(type, text_or_options, options, &blk)
822
- driver.dismiss_modal(type, modal_options(text_or_options, options), &blk)
854
+ driver.dismiss_modal(type, **modal_options(text_or_options, **options), &blk)
823
855
  end
824
856
 
825
857
  def modal_options(text = nil, **options)
@@ -863,24 +895,18 @@ module Capybara
863
895
  end
864
896
  end
865
897
 
866
- def server_url
867
- "http#{'s' if @server.using_ssl?}://#{@server.host}:#{@server.port}" if @server
868
- end
869
-
870
898
  def adjust_server_port(uri)
871
899
  uri.port ||= @server.port if @server && config.always_include_port
872
900
  end
873
901
 
874
- def _find_frame(*args)
875
- return find(:frame) if args.length.zero?
876
-
902
+ def _find_frame(*args, **kw_args)
877
903
  case args[0]
878
904
  when Capybara::Node::Element
879
905
  args[0]
880
- when String, Hash
881
- find(:frame, *args)
906
+ when String, nil
907
+ find(:frame, *args, **kw_args)
882
908
  when Symbol
883
- find(*args)
909
+ find(*args, **kw_args)
884
910
  when Integer
885
911
  idx = args[0]
886
912
  all(:frame, minimum: idx + 1)[idx]
@@ -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].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
@@ -59,6 +61,8 @@ module Capybara
59
61
  # See {Capybara.configure}
60
62
  # @!method default_normalize_ws
61
63
  # See {Capybara.configure}
64
+ # @!method w3c_click_offset
65
+ # See {Capybara.configure}
62
66
 
63
67
  remove_method :server_host
64
68
 
@@ -77,14 +81,18 @@ module Capybara
77
81
 
78
82
  remove_method :app_host=
79
83
  def app_host=(url)
80
- raise ArgumentError, "Capybara.app_host should be set to a url (http://www.example.com). Attempted to set #{url.inspect}." unless url.nil? || url.match?(URI::DEFAULT_PARSER.make_regexp)
84
+ unless url.nil? || url.match?(URI::DEFAULT_PARSER.make_regexp)
85
+ raise ArgumentError, "Capybara.app_host should be set to a url (http://www.example.com). Attempted to set #{url.inspect}."
86
+ end
81
87
 
82
88
  @app_host = url
83
89
  end
84
90
 
85
91
  remove_method :default_host=
86
92
  def default_host=(url)
87
- raise ArgumentError, "Capybara.default_host should be set to a url (http://www.example.com). Attempted to set #{url.inspect}." unless url.nil? || url.match?(URI::DEFAULT_PARSER.make_regexp)
93
+ unless url.nil? || url.match?(URI::DEFAULT_PARSER.make_regexp)
94
+ raise ArgumentError, "Capybara.default_host should be set to a url (http://www.example.com). Attempted to set #{url.inspect}."
95
+ end
88
96
 
89
97
  @default_host = url
90
98
  end
@@ -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
@@ -0,0 +1,6 @@
1
+ $(function() {
2
+ $(document).on('click dblclick contextmenu', function(e){
3
+ e.preventDefault();
4
+ $(document.body).append('<div id="has-been-clicked">Has been clicked at ' + e.clientX + ',' + e.clientY + '</div>');
5
+ })
6
+ })