capybara 3.13.2 → 3.40.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 (260) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +1 -0
  3. data/History.md +587 -16
  4. data/README.md +240 -90
  5. data/lib/capybara/config.rb +24 -11
  6. data/lib/capybara/cucumber.rb +1 -1
  7. data/lib/capybara/driver/base.rb +8 -0
  8. data/lib/capybara/driver/node.rb +20 -4
  9. data/lib/capybara/dsl.rb +5 -3
  10. data/lib/capybara/helpers.rb +25 -4
  11. data/lib/capybara/minitest/spec.rb +174 -90
  12. data/lib/capybara/minitest.rb +256 -142
  13. data/lib/capybara/node/actions.rb +123 -77
  14. data/lib/capybara/node/base.rb +20 -12
  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 +223 -117
  18. data/lib/capybara/node/finders.rb +81 -71
  19. data/lib/capybara/node/matchers.rb +271 -134
  20. data/lib/capybara/node/simple.rb +18 -5
  21. data/lib/capybara/node/whitespace_normalizer.rb +81 -0
  22. data/lib/capybara/queries/active_element_query.rb +18 -0
  23. data/lib/capybara/queries/ancestor_query.rb +8 -9
  24. data/lib/capybara/queries/base_query.rb +3 -2
  25. data/lib/capybara/queries/current_path_query.rb +15 -5
  26. data/lib/capybara/queries/selector_query.rb +364 -54
  27. data/lib/capybara/queries/sibling_query.rb +8 -6
  28. data/lib/capybara/queries/style_query.rb +2 -2
  29. data/lib/capybara/queries/text_query.rb +13 -1
  30. data/lib/capybara/queries/title_query.rb +1 -1
  31. data/lib/capybara/rack_test/browser.rb +76 -11
  32. data/lib/capybara/rack_test/driver.rb +10 -5
  33. data/lib/capybara/rack_test/errors.rb +6 -0
  34. data/lib/capybara/rack_test/form.rb +31 -9
  35. data/lib/capybara/rack_test/node.rb +74 -23
  36. data/lib/capybara/registration_container.rb +41 -0
  37. data/lib/capybara/registrations/drivers.rb +42 -0
  38. data/lib/capybara/registrations/patches/puma_ssl.rb +29 -0
  39. data/lib/capybara/registrations/servers.rb +66 -0
  40. data/lib/capybara/result.rb +44 -20
  41. data/lib/capybara/rspec/matcher_proxies.rb +13 -11
  42. data/lib/capybara/rspec/matchers/base.rb +31 -16
  43. data/lib/capybara/rspec/matchers/compound.rb +1 -1
  44. data/lib/capybara/rspec/matchers/count_sugar.rb +37 -0
  45. data/lib/capybara/rspec/matchers/have_ancestor.rb +28 -0
  46. data/lib/capybara/rspec/matchers/have_current_path.rb +2 -2
  47. data/lib/capybara/rspec/matchers/have_selector.rb +21 -21
  48. data/lib/capybara/rspec/matchers/have_sibling.rb +27 -0
  49. data/lib/capybara/rspec/matchers/have_text.rb +4 -4
  50. data/lib/capybara/rspec/matchers/have_title.rb +2 -2
  51. data/lib/capybara/rspec/matchers/match_selector.rb +3 -3
  52. data/lib/capybara/rspec/matchers/match_style.rb +7 -2
  53. data/lib/capybara/rspec/matchers/spatial_sugar.rb +39 -0
  54. data/lib/capybara/rspec/matchers.rb +111 -68
  55. data/lib/capybara/rspec.rb +2 -0
  56. data/lib/capybara/selector/builders/css_builder.rb +11 -7
  57. data/lib/capybara/selector/builders/xpath_builder.rb +5 -3
  58. data/lib/capybara/selector/css.rb +11 -9
  59. data/lib/capybara/selector/definition/button.rb +68 -0
  60. data/lib/capybara/selector/definition/checkbox.rb +26 -0
  61. data/lib/capybara/selector/definition/css.rb +10 -0
  62. data/lib/capybara/selector/definition/datalist_input.rb +35 -0
  63. data/lib/capybara/selector/definition/datalist_option.rb +25 -0
  64. data/lib/capybara/selector/definition/element.rb +28 -0
  65. data/lib/capybara/selector/definition/field.rb +40 -0
  66. data/lib/capybara/selector/definition/fieldset.rb +14 -0
  67. data/lib/capybara/selector/definition/file_field.rb +13 -0
  68. data/lib/capybara/selector/definition/fillable_field.rb +33 -0
  69. data/lib/capybara/selector/definition/frame.rb +17 -0
  70. data/lib/capybara/selector/definition/id.rb +6 -0
  71. data/lib/capybara/selector/definition/label.rb +62 -0
  72. data/lib/capybara/selector/definition/link.rb +55 -0
  73. data/lib/capybara/selector/definition/link_or_button.rb +16 -0
  74. data/lib/capybara/selector/definition/option.rb +27 -0
  75. data/lib/capybara/selector/definition/radio_button.rb +27 -0
  76. data/lib/capybara/selector/definition/select.rb +81 -0
  77. data/lib/capybara/selector/definition/table.rb +109 -0
  78. data/lib/capybara/selector/definition/table_row.rb +21 -0
  79. data/lib/capybara/selector/definition/xpath.rb +5 -0
  80. data/lib/capybara/selector/definition.rb +280 -0
  81. data/lib/capybara/selector/filter_set.rb +19 -18
  82. data/lib/capybara/selector/filters/base.rb +11 -2
  83. data/lib/capybara/selector/filters/locator_filter.rb +13 -3
  84. data/lib/capybara/selector/regexp_disassembler.rb +11 -7
  85. data/lib/capybara/selector/selector.rb +50 -440
  86. data/lib/capybara/selector/xpath_extensions.rb +17 -0
  87. data/lib/capybara/selector.rb +473 -482
  88. data/lib/capybara/selenium/atoms/getAttribute.min.js +1 -0
  89. data/lib/capybara/selenium/atoms/isDisplayed.min.js +1 -0
  90. data/lib/capybara/selenium/atoms/src/getAttribute.js +161 -0
  91. data/lib/capybara/selenium/atoms/src/isDisplayed.js +454 -0
  92. data/lib/capybara/selenium/driver.rb +174 -62
  93. data/lib/capybara/selenium/driver_specializations/chrome_driver.rb +74 -18
  94. data/lib/capybara/selenium/driver_specializations/edge_driver.rb +128 -0
  95. data/lib/capybara/selenium/driver_specializations/firefox_driver.rb +37 -3
  96. data/lib/capybara/selenium/driver_specializations/internet_explorer_driver.rb +14 -1
  97. data/lib/capybara/selenium/driver_specializations/safari_driver.rb +24 -0
  98. data/lib/capybara/selenium/extensions/file_input_click_emulation.rb +34 -0
  99. data/lib/capybara/selenium/extensions/find.rb +68 -45
  100. data/lib/capybara/selenium/extensions/html5_drag.rb +192 -22
  101. data/lib/capybara/selenium/extensions/modifier_keys_stack.rb +28 -0
  102. data/lib/capybara/selenium/extensions/scroll.rb +8 -10
  103. data/lib/capybara/selenium/node.rb +268 -72
  104. data/lib/capybara/selenium/nodes/chrome_node.rb +105 -9
  105. data/lib/capybara/selenium/nodes/edge_node.rb +110 -0
  106. data/lib/capybara/selenium/nodes/firefox_node.rb +51 -61
  107. data/lib/capybara/selenium/nodes/ie_node.rb +22 -0
  108. data/lib/capybara/selenium/nodes/safari_node.rb +118 -0
  109. data/lib/capybara/selenium/patches/atoms.rb +18 -0
  110. data/lib/capybara/selenium/patches/is_displayed.rb +16 -0
  111. data/lib/capybara/selenium/patches/logs.rb +45 -0
  112. data/lib/capybara/selenium/patches/pause_duration_fix.rb +1 -1
  113. data/lib/capybara/selenium/patches/persistent_client.rb +20 -0
  114. data/lib/capybara/server/animation_disabler.rb +43 -21
  115. data/lib/capybara/server/checker.rb +6 -2
  116. data/lib/capybara/server/middleware.rb +25 -13
  117. data/lib/capybara/server.rb +20 -4
  118. data/lib/capybara/session/config.rb +15 -11
  119. data/lib/capybara/session/matchers.rb +11 -11
  120. data/lib/capybara/session.rb +162 -131
  121. data/lib/capybara/spec/public/offset.js +6 -0
  122. data/lib/capybara/spec/public/test.js +105 -6
  123. data/lib/capybara/spec/session/accept_alert_spec.rb +1 -1
  124. data/lib/capybara/spec/session/active_element_spec.rb +31 -0
  125. data/lib/capybara/spec/session/all_spec.rb +89 -15
  126. data/lib/capybara/spec/session/ancestor_spec.rb +5 -0
  127. data/lib/capybara/spec/session/assert_current_path_spec.rb +5 -2
  128. data/lib/capybara/spec/session/assert_text_spec.rb +26 -22
  129. data/lib/capybara/spec/session/attach_file_spec.rb +64 -31
  130. data/lib/capybara/spec/session/check_spec.rb +26 -4
  131. data/lib/capybara/spec/session/choose_spec.rb +14 -2
  132. data/lib/capybara/spec/session/click_button_spec.rb +109 -61
  133. data/lib/capybara/spec/session/click_link_or_button_spec.rb +9 -0
  134. data/lib/capybara/spec/session/click_link_spec.rb +23 -1
  135. data/lib/capybara/spec/session/current_scope_spec.rb +1 -1
  136. data/lib/capybara/spec/session/current_url_spec.rb +11 -1
  137. data/lib/capybara/spec/session/element/matches_selector_spec.rb +40 -39
  138. data/lib/capybara/spec/session/evaluate_script_spec.rb +12 -0
  139. data/lib/capybara/spec/session/fill_in_spec.rb +46 -5
  140. data/lib/capybara/spec/session/find_link_spec.rb +10 -0
  141. data/lib/capybara/spec/session/find_spec.rb +80 -7
  142. data/lib/capybara/spec/session/first_spec.rb +2 -2
  143. data/lib/capybara/spec/session/frame/switch_to_frame_spec.rb +14 -1
  144. data/lib/capybara/spec/session/frame/within_frame_spec.rb +14 -1
  145. data/lib/capybara/spec/session/has_all_selectors_spec.rb +5 -5
  146. data/lib/capybara/spec/session/has_ancestor_spec.rb +46 -0
  147. data/lib/capybara/spec/session/has_any_selectors_spec.rb +6 -2
  148. data/lib/capybara/spec/session/has_button_spec.rb +81 -0
  149. data/lib/capybara/spec/session/has_css_spec.rb +45 -8
  150. data/lib/capybara/spec/session/has_current_path_spec.rb +22 -7
  151. data/lib/capybara/spec/session/has_element_spec.rb +47 -0
  152. data/lib/capybara/spec/session/has_field_spec.rb +59 -1
  153. data/lib/capybara/spec/session/has_link_spec.rb +40 -0
  154. data/lib/capybara/spec/session/has_none_selectors_spec.rb +7 -7
  155. data/lib/capybara/spec/session/has_select_spec.rb +42 -8
  156. data/lib/capybara/spec/session/has_selector_spec.rb +19 -4
  157. data/lib/capybara/spec/session/has_sibling_spec.rb +50 -0
  158. data/lib/capybara/spec/session/has_table_spec.rb +177 -0
  159. data/lib/capybara/spec/session/has_text_spec.rb +31 -3
  160. data/lib/capybara/spec/session/html_spec.rb +1 -1
  161. data/lib/capybara/spec/session/matches_style_spec.rb +6 -4
  162. data/lib/capybara/spec/session/node_spec.rb +697 -23
  163. data/lib/capybara/spec/session/node_wrapper_spec.rb +1 -1
  164. data/lib/capybara/spec/session/refresh_spec.rb +2 -1
  165. data/lib/capybara/spec/session/reset_session_spec.rb +21 -7
  166. data/lib/capybara/spec/session/save_and_open_screenshot_spec.rb +2 -2
  167. data/lib/capybara/spec/session/save_page_spec.rb +4 -4
  168. data/lib/capybara/spec/session/save_screenshot_spec.rb +4 -4
  169. data/lib/capybara/spec/session/scroll_spec.rb +9 -7
  170. data/lib/capybara/spec/session/select_spec.rb +5 -10
  171. data/lib/capybara/spec/session/selectors_spec.rb +24 -3
  172. data/lib/capybara/spec/session/uncheck_spec.rb +3 -3
  173. data/lib/capybara/spec/session/unselect_spec.rb +1 -1
  174. data/lib/capybara/spec/session/visit_spec.rb +20 -0
  175. data/lib/capybara/spec/session/window/become_closed_spec.rb +20 -17
  176. data/lib/capybara/spec/session/window/switch_to_window_spec.rb +1 -1
  177. data/lib/capybara/spec/session/window/window_opened_by_spec.rb +1 -1
  178. data/lib/capybara/spec/session/window/window_spec.rb +54 -57
  179. data/lib/capybara/spec/session/window/windows_spec.rb +2 -2
  180. data/lib/capybara/spec/session/within_spec.rb +36 -0
  181. data/lib/capybara/spec/spec_helper.rb +30 -19
  182. data/lib/capybara/spec/test_app.rb +122 -34
  183. data/lib/capybara/spec/views/animated.erb +49 -0
  184. data/lib/capybara/spec/views/form.erb +86 -8
  185. data/lib/capybara/spec/views/frame_child.erb +3 -2
  186. data/lib/capybara/spec/views/frame_one.erb +2 -1
  187. data/lib/capybara/spec/views/frame_parent.erb +1 -1
  188. data/lib/capybara/spec/views/frame_two.erb +1 -1
  189. data/lib/capybara/spec/views/initial_alert.erb +2 -1
  190. data/lib/capybara/spec/views/layout.erb +10 -0
  191. data/lib/capybara/spec/views/obscured.erb +10 -10
  192. data/lib/capybara/spec/views/offset.erb +33 -0
  193. data/lib/capybara/spec/views/path.erb +2 -2
  194. data/lib/capybara/spec/views/popup_one.erb +1 -1
  195. data/lib/capybara/spec/views/popup_two.erb +1 -1
  196. data/lib/capybara/spec/views/react.erb +45 -0
  197. data/lib/capybara/spec/views/scroll.erb +2 -1
  198. data/lib/capybara/spec/views/spatial.erb +31 -0
  199. data/lib/capybara/spec/views/tables.erb +67 -0
  200. data/lib/capybara/spec/views/with_animation.erb +39 -4
  201. data/lib/capybara/spec/views/with_base_tag.erb +2 -2
  202. data/lib/capybara/spec/views/with_dragula.erb +24 -0
  203. data/lib/capybara/spec/views/with_fixed_header_footer.erb +2 -1
  204. data/lib/capybara/spec/views/with_hover.erb +3 -2
  205. data/lib/capybara/spec/views/with_hover1.erb +10 -0
  206. data/lib/capybara/spec/views/with_html.erb +34 -6
  207. data/lib/capybara/spec/views/with_jquery_animation.erb +24 -0
  208. data/lib/capybara/spec/views/with_js.erb +7 -4
  209. data/lib/capybara/spec/views/with_jstree.erb +26 -0
  210. data/lib/capybara/spec/views/with_namespace.erb +1 -0
  211. data/lib/capybara/spec/views/with_scope.erb +2 -2
  212. data/lib/capybara/spec/views/with_scope_other.erb +6 -0
  213. data/lib/capybara/spec/views/with_shadow.erb +31 -0
  214. data/lib/capybara/spec/views/with_slow_unload.erb +2 -1
  215. data/lib/capybara/spec/views/with_sortable_js.erb +21 -0
  216. data/lib/capybara/spec/views/with_unload_alert.erb +1 -0
  217. data/lib/capybara/spec/views/with_windows.erb +1 -1
  218. data/lib/capybara/spec/views/within_frames.erb +1 -1
  219. data/lib/capybara/version.rb +1 -1
  220. data/lib/capybara/window.rb +14 -18
  221. data/lib/capybara.rb +91 -126
  222. data/spec/basic_node_spec.rb +30 -16
  223. data/spec/capybara_spec.rb +40 -28
  224. data/spec/counter_spec.rb +35 -0
  225. data/spec/css_builder_spec.rb +3 -1
  226. data/spec/css_splitter_spec.rb +1 -1
  227. data/spec/dsl_spec.rb +33 -22
  228. data/spec/filter_set_spec.rb +5 -5
  229. data/spec/fixtures/selenium_driver_rspec_failure.rb +3 -3
  230. data/spec/fixtures/selenium_driver_rspec_success.rb +3 -3
  231. data/spec/minitest_spec.rb +24 -2
  232. data/spec/minitest_spec_spec.rb +60 -45
  233. data/spec/per_session_config_spec.rb +1 -1
  234. data/spec/rack_test_spec.rb +131 -98
  235. data/spec/regexp_dissassembler_spec.rb +53 -39
  236. data/spec/result_spec.rb +68 -66
  237. data/spec/rspec/features_spec.rb +9 -4
  238. data/spec/rspec/scenarios_spec.rb +6 -2
  239. data/spec/rspec/shared_spec_matchers.rb +137 -98
  240. data/spec/rspec_matchers_spec.rb +25 -0
  241. data/spec/rspec_spec.rb +23 -21
  242. data/spec/sauce_spec_chrome.rb +43 -0
  243. data/spec/selector_spec.rb +77 -21
  244. data/spec/selenium_spec_chrome.rb +141 -39
  245. data/spec/selenium_spec_chrome_remote.rb +32 -17
  246. data/spec/selenium_spec_edge.rb +36 -8
  247. data/spec/selenium_spec_firefox.rb +110 -68
  248. data/spec/selenium_spec_firefox_remote.rb +22 -15
  249. data/spec/selenium_spec_ie.rb +29 -22
  250. data/spec/selenium_spec_safari.rb +162 -0
  251. data/spec/server_spec.rb +153 -81
  252. data/spec/session_spec.rb +11 -4
  253. data/spec/shared_selenium_node.rb +79 -0
  254. data/spec/shared_selenium_session.rb +179 -74
  255. data/spec/spec_helper.rb +80 -5
  256. data/spec/whitespace_normalizer_spec.rb +54 -0
  257. data/spec/xpath_builder_spec.rb +3 -1
  258. metadata +218 -30
  259. data/lib/capybara/spec/session/source_spec.rb +0 -0
  260. data/lib/capybara/spec/views/with_title.erb +0 -5
@@ -19,21 +19,20 @@ module Capybara
19
19
  # This will check if the expression occurs exactly 4 times.
20
20
  #
21
21
  # It also accepts all options that {Capybara::Node::Finders#all} accepts,
22
- # such as :text and :visible.
22
+ # such as `:text` and `:visible`.
23
23
  #
24
24
  # page.has_selector?('li', text: 'Horse', visible: true)
25
25
  #
26
- # has_selector? can also accept XPath expressions generated by the
26
+ # {#has_selector?} can also accept XPath expressions generated by the
27
27
  # XPath gem:
28
28
  #
29
29
  # page.has_selector?(:xpath, XPath.descendant(:p))
30
30
  #
31
31
  # @param (see Capybara::Node::Finders#all)
32
- # @param args
33
- # @option args [Integer] :count (nil) Number of times the text should occur
34
- # @option args [Integer] :minimum (nil) Minimum number of times the text should occur
35
- # @option args [Integer] :maximum (nil) Maximum number of times the text should occur
36
- # @option args [Range] :between (nil) Range of times that should contain number of times text occurs
32
+ # @option options [Integer] :count (nil) Number of matching elements that should exist
33
+ # @option options [Integer] :minimum (nil) Minimum number of matching elements that should exist
34
+ # @option options [Integer] :maximum (nil) Maximum number of matching elements that should exist
35
+ # @option options [Range] :between (nil) Range of number of matching elements that should exist
37
36
  # @return [Boolean] If the expression exists
38
37
  #
39
38
  def has_selector?(*args, **options, &optional_filter_block)
@@ -43,9 +42,9 @@ module Capybara
43
42
  ##
44
43
  #
45
44
  # Checks if a given selector is not on the page or a descendant of the current node.
46
- # Usage is identical to Capybara::Node::Matchers#has_selector?
45
+ # Usage is identical to {#has_selector?}.
47
46
  #
48
- # @param (see Capybara::Node::Finders#has_selector?)
47
+ # @param (see #has_selector?)
49
48
  # @return [Boolean]
50
49
  #
51
50
  def has_no_selector?(*args, **options, &optional_filter_block)
@@ -54,22 +53,23 @@ module Capybara
54
53
 
55
54
  ##
56
55
  #
57
- # Checks if a an element has the specified CSS styles
56
+ # Checks if a an element has the specified CSS styles.
58
57
  #
59
58
  # element.matches_style?( 'color' => 'rgb(0,0,255)', 'font-size' => /px/ )
60
59
  #
61
60
  # @param styles [Hash]
62
61
  # @return [Boolean] If the styles match
63
62
  #
64
- def matches_style?(styles, **options)
65
- make_predicate(options) { assert_matches_style(styles, options) }
63
+ def matches_style?(styles = nil, **options)
64
+ styles, options = options, {} if styles.nil?
65
+ make_predicate(options) { assert_matches_style(styles, **options) }
66
66
  end
67
67
 
68
68
  ##
69
- # @deprecated
69
+ # @deprecated Use {#matches_style?} instead.
70
70
  #
71
- def has_style?(styles, **options)
72
- warn 'DEPRECATED: has_style? is deprecated, please use matches_style?'
71
+ def has_style?(styles = nil, **options)
72
+ Capybara::Helpers.warn "DEPRECATED: has_style? is deprecated, please use matches_style? : #{Capybara::Helpers.filter_backtrace(caller)}"
73
73
  matches_style?(styles, **options)
74
74
  end
75
75
 
@@ -89,15 +89,15 @@ module Capybara
89
89
  # This will check if the expression occurs exactly 4 times. See
90
90
  # {Capybara::Node::Finders#all} for other available result size options.
91
91
  #
92
- # If a :count of 0 is specified, it will behave like {#assert_no_selector};
92
+ # If a `:count` of 0 is specified, it will behave like {#assert_no_selector};
93
93
  # however, use of that method is preferred over this one.
94
94
  #
95
95
  # It also accepts all options that {Capybara::Node::Finders#all} accepts,
96
- # such as :text and :visible.
96
+ # such as `:text` and `:visible`.
97
97
  #
98
98
  # page.assert_selector('li', text: 'Horse', visible: true)
99
99
  #
100
- # `assert_selector` can also accept XPath expressions generated by the
100
+ # {#assert_selector} can also accept XPath expressions generated by the
101
101
  # XPath gem:
102
102
  #
103
103
  # page.assert_selector(:xpath, XPath.descendant(:p))
@@ -108,22 +108,25 @@ module Capybara
108
108
  #
109
109
  def assert_selector(*args, &optional_filter_block)
110
110
  _verify_selector_result(args, optional_filter_block) do |result, query|
111
- raise Capybara::ExpectationNotMet, result.failure_message unless result.matches_count? && (result.any? || query.expects_none?)
111
+ unless result.matches_count? && (result.any? || query.expects_none?)
112
+ raise Capybara::ExpectationNotMet, result.failure_message
113
+ end
112
114
  end
113
115
  end
114
116
 
115
117
  ##
116
118
  #
117
- # Asserts that an element has the specified CSS styles
119
+ # Asserts that an element has the specified CSS styles.
118
120
  #
119
121
  # element.assert_matches_style( 'color' => 'rgb(0,0,255)', 'font-size' => /px/ )
120
122
  #
121
123
  # @param styles [Hash]
122
124
  # @raise [Capybara::ExpectationNotMet] If the element doesn't have the specified styles
123
125
  #
124
- def assert_matches_style(styles, **options)
125
- query_args = _set_query_session_options(styles, options)
126
- query = Capybara::Queries::StyleQuery.new(*query_args)
126
+ def assert_matches_style(styles = nil, **options)
127
+ styles, options = options, {} if styles.nil?
128
+ query_args, query_opts = _set_query_session_options(styles, options)
129
+ query = Capybara::Queries::StyleQuery.new(*query_args, **query_opts)
127
130
  synchronize(query.wait) do
128
131
  raise Capybara::ExpectationNotMet, query.failure_message unless query.resolves_for?(self)
129
132
  end
@@ -131,66 +134,67 @@ module Capybara
131
134
  end
132
135
 
133
136
  ##
134
- # @deprecated
135
- def assert_style(styles, **options)
137
+ # @deprecated Use {#assert_matches_style} instead.
138
+ #
139
+ def assert_style(styles = nil, **options)
136
140
  warn 'assert_style is deprecated, please use assert_matches_style instead'
137
141
  assert_matches_style(styles, **options)
138
142
  end
139
143
 
140
144
  # Asserts that all of the provided selectors are present on the given page
141
145
  # or descendants of the current node. If options are provided, the assertion
142
- # will check that each locator is present with those options as well (other than :wait).
146
+ # will check that each locator is present with those options as well (other than `:wait`).
143
147
  #
144
- # page.assert_all_of_selectors(:custom, 'Tom', 'Joe', visible: all)
145
- # page.assert_all_of_selectors(:css, '#my_div', 'a.not_clicked')
148
+ # page.assert_all_of_selectors(:custom, 'Tom', 'Joe', visible: all)
149
+ # page.assert_all_of_selectors(:css, '#my_div', 'a.not_clicked')
146
150
  #
147
151
  # It accepts all options that {Capybara::Node::Finders#all} accepts,
148
- # such as :text and :visible.
152
+ # such as `:text` and `:visible`.
149
153
  #
150
- # The :wait option applies to all of the selectors as a group, so all of the locators must be present
151
- # within :wait (Defaults to Capybara.default_max_wait_time) seconds.
154
+ # The `:wait` option applies to all of the selectors as a group, so all of the locators must be present
155
+ # within `:wait` (defaults to {Capybara.configure default_max_wait_time}) seconds.
152
156
  #
153
157
  # @overload assert_all_of_selectors([kind = Capybara.default_selector], *locators, **options)
154
158
  #
155
159
  def assert_all_of_selectors(*args, **options, &optional_filter_block)
156
- _verify_multiple(*args, options) do |selector, locator, opts|
160
+ _verify_multiple(*args, **options) do |selector, locator, opts|
157
161
  assert_selector(selector, locator, opts, &optional_filter_block)
158
162
  end
159
163
  end
160
164
 
161
165
  # Asserts that none of the provided selectors are present on the given page
162
166
  # or descendants of the current node. If options are provided, the assertion
163
- # will check that each locator is present with those options as well (other than :wait).
167
+ # will check that each locator is not present with those options as well (other than `:wait`).
164
168
  #
165
- # page.assert_none_of_selectors(:custom, 'Tom', 'Joe', visible: all)
166
- # page.assert_none_of_selectors(:css, '#my_div', 'a.not_clicked')
169
+ # page.assert_none_of_selectors(:custom, 'Tom', 'Joe', visible: all)
170
+ # page.assert_none_of_selectors(:css, '#my_div', 'a.not_clicked')
167
171
  #
168
172
  # It accepts all options that {Capybara::Node::Finders#all} accepts,
169
- # such as :text and :visible.
173
+ # such as `:text` and `:visible`.
170
174
  #
171
- # The :wait option applies to all of the selectors as a group, so none of the locators must be present
172
- # within :wait (Defaults to Capybara.default_max_wait_time) seconds.
175
+ # The `:wait` option applies to all of the selectors as a group, so none of the locators must be present
176
+ # within `:wait` (defaults to {Capybara.configure default_max_wait_time}) seconds.
173
177
  #
174
178
  # @overload assert_none_of_selectors([kind = Capybara.default_selector], *locators, **options)
175
179
  #
176
180
  def assert_none_of_selectors(*args, **options, &optional_filter_block)
177
- _verify_multiple(*args, options) do |selector, locator, opts|
181
+ _verify_multiple(*args, **options) do |selector, locator, opts|
178
182
  assert_no_selector(selector, locator, opts, &optional_filter_block)
179
183
  end
180
184
  end
181
185
 
182
186
  # Asserts that any of the provided selectors are present on the given page
183
- # or descendants of the current node. If options are provided, the assertion
184
- # will check that each locator is present with those options as well (other than :wait).
187
+ # or descendants of the current node. If options are provided, the assertion
188
+ # will check that each locator is present with those options as well (other than `:wait`).
185
189
  #
186
- # page.assert_any_of_selectors(:custom, 'Tom', 'Joe', visible: all)
187
- # page.assert_any_of_selectors(:css, '#my_div', 'a.not_clicked')
190
+ # page.assert_any_of_selectors(:custom, 'Tom', 'Joe', visible: all)
191
+ # page.assert_any_of_selectors(:css, '#my_div', 'a.not_clicked')
188
192
  #
189
193
  # It accepts all options that {Capybara::Node::Finders#all} accepts,
190
- # such as :text and :visible.
194
+ # such as `:text` and `:visible`.
191
195
  #
192
- # The :wait option applies to all of the selectors as a group, so any of the locators must be present
193
- # within :wait (Defaults to Capybara.default_max_wait_time) seconds.
196
+ # The `:wait` option applies to all of the selectors as a group, so any of the locators must be present
197
+ # within `:wait` (defaults to {Capybara.configure default_max_wait_time}) seconds.
194
198
  #
195
199
  # @overload assert_any_of_selectors([kind = Capybara.default_selector], *locators, **options)
196
200
  #
@@ -199,12 +203,10 @@ module Capybara
199
203
  selector = extract_selector(args)
200
204
  synchronize(wait) do
201
205
  res = args.map do |locator|
202
- begin
203
- assert_selector(selector, locator, options, &optional_filter_block)
204
- break nil
205
- rescue Capybara::ExpectationNotMet => e
206
- e.message
207
- end
206
+ assert_selector(selector, locator, options, &optional_filter_block)
207
+ break nil
208
+ rescue Capybara::ExpectationNotMet => e
209
+ e.message
208
210
  end
209
211
  raise Capybara::ExpectationNotMet, res.join(' or ') if res
210
212
 
@@ -215,17 +217,17 @@ module Capybara
215
217
  ##
216
218
  #
217
219
  # Asserts that a given selector is not on the page or a descendant of the current node.
218
- # Usage is identical to Capybara::Node::Matchers#assert_selector
220
+ # Usage is identical to {#assert_selector}.
219
221
  #
220
- # Query options such as :count, :minimum, :maximum, and :between are
222
+ # Query options such as `:count`, `:minimum`, `:maximum`, and `:between` are
221
223
  # considered to be an integral part of the selector. This will return
222
- # true, for example, if a page contains 4 anchors but the query expects 5:
224
+ # `true`, for example, if a page contains 4 anchors but the query expects 5:
223
225
  #
224
226
  # page.assert_no_selector('a', minimum: 1) # Found, raises Capybara::ExpectationNotMet
225
227
  # page.assert_no_selector('a', count: 4) # Found, raises Capybara::ExpectationNotMet
226
228
  # page.assert_no_selector('a', count: 5) # Not Found, returns true
227
229
  #
228
- # @param (see Capybara::Node::Finders#assert_selector)
230
+ # @param (see #assert_selector)
229
231
  # @raise [Capybara::ExpectationNotMet] If the selector exists
230
232
  #
231
233
  def assert_no_selector(*args, &optional_filter_block)
@@ -250,11 +252,11 @@ module Capybara
250
252
  # This will check if the expression occurs exactly 4 times.
251
253
  #
252
254
  # It also accepts all options that {Capybara::Node::Finders#all} accepts,
253
- # such as :text and :visible.
255
+ # such as `:text` and `:visible`.
254
256
  #
255
257
  # page.has_xpath?('.//li', text: 'Horse', visible: true)
256
258
  #
257
- # has_xpath? can also accept XPath expressions generate by the
259
+ # {#has_xpath?} can also accept XPath expressions generated by the
258
260
  # XPath gem:
259
261
  #
260
262
  # xpath = XPath.generate { |x| x.descendant(:p) }
@@ -266,19 +268,19 @@ module Capybara
266
268
  # @return [Boolean] If the expression exists
267
269
  #
268
270
  def has_xpath?(path, **options, &optional_filter_block)
269
- has_selector?(:xpath, path, options, &optional_filter_block)
271
+ has_selector?(:xpath, path, **options, &optional_filter_block)
270
272
  end
271
273
 
272
274
  ##
273
275
  #
274
276
  # Checks if a given XPath expression is not on the page or a descendant of the current node.
275
- # Usage is identical to Capybara::Node::Matchers#has_xpath?
277
+ # Usage is identical to {#has_xpath?}.
276
278
  #
277
- # @param (see Capybara::Node::Finders#has_xpath?)
279
+ # @param (see #has_xpath?)
278
280
  # @return [Boolean]
279
281
  #
280
282
  def has_no_xpath?(path, **options, &optional_filter_block)
281
- has_no_selector?(:xpath, path, options, &optional_filter_block)
283
+ has_no_selector?(:xpath, path, **options, &optional_filter_block)
282
284
  end
283
285
 
284
286
  ##
@@ -295,7 +297,7 @@ module Capybara
295
297
  # This will check if the selector occurs exactly 4 times.
296
298
  #
297
299
  # It also accepts all options that {Capybara::Node::Finders#all} accepts,
298
- # such as :text and :visible.
300
+ # such as `:text` and `:visible`.
299
301
  #
300
302
  # page.has_css?('li', text: 'Horse', visible: true)
301
303
  #
@@ -305,19 +307,44 @@ module Capybara
305
307
  # @return [Boolean] If the selector exists
306
308
  #
307
309
  def has_css?(path, **options, &optional_filter_block)
308
- has_selector?(:css, path, options, &optional_filter_block)
310
+ has_selector?(:css, path, **options, &optional_filter_block)
309
311
  end
310
312
 
311
313
  ##
312
314
  #
313
315
  # Checks if a given CSS selector is not on the page or a descendant of the current node.
314
- # Usage is identical to Capybara::Node::Matchers#has_css?
316
+ # Usage is identical to {#has_css?}.
315
317
  #
316
- # @param (see Capybara::Node::Finders#has_css?)
318
+ # @param (see #has_css?)
317
319
  # @return [Boolean]
318
320
  #
319
321
  def has_no_css?(path, **options, &optional_filter_block)
320
- has_no_selector?(:css, path, options, &optional_filter_block)
322
+ has_no_selector?(:css, path, **options, &optional_filter_block)
323
+ end
324
+
325
+ ##
326
+ #
327
+ # Checks if the page or current node has a element with the given
328
+ # local name.
329
+ #
330
+ # @param [String] locator The local name of a element to check for
331
+ # @option options [String, Regexp] The attributes values of matching elements
332
+ # @return [Boolean] Whether it exists
333
+ #
334
+ def has_element?(locator = nil, **options, &optional_filter_block)
335
+ has_selector?(:element, locator, **options, &optional_filter_block)
336
+ end
337
+
338
+ ##
339
+ #
340
+ # Checks if the page or current node has no element with the given
341
+ # local name.
342
+ #
343
+ # @param (see #has_element?)
344
+ # @return [Boolean] Whether it doesn't exist
345
+ #
346
+ def has_no_element?(locator = nil, **options, &optional_filter_block)
347
+ has_no_selector?(:element, locator, **options, &optional_filter_block)
321
348
  end
322
349
 
323
350
  ##
@@ -326,12 +353,11 @@ module Capybara
326
353
  # text or id.
327
354
  #
328
355
  # @param [String] locator The text or id of a link to check for
329
- # @param options
330
356
  # @option options [String, Regexp] :href The value the href attribute must be
331
357
  # @return [Boolean] Whether it exists
332
358
  #
333
359
  def has_link?(locator = nil, **options, &optional_filter_block)
334
- has_selector?(:link, locator, options, &optional_filter_block)
360
+ has_selector?(:link, locator, **options, &optional_filter_block)
335
361
  end
336
362
 
337
363
  ##
@@ -339,11 +365,11 @@ module Capybara
339
365
  # Checks if the page or current node has no link with the given
340
366
  # text or id.
341
367
  #
342
- # @param (see Capybara::Node::Finders#has_link?)
368
+ # @param (see #has_link?)
343
369
  # @return [Boolean] Whether it doesn't exist
344
370
  #
345
371
  def has_no_link?(locator = nil, **options, &optional_filter_block)
346
- has_no_selector?(:link, locator, options, &optional_filter_block)
372
+ has_no_selector?(:link, locator, **options, &optional_filter_block)
347
373
  end
348
374
 
349
375
  ##
@@ -355,7 +381,7 @@ module Capybara
355
381
  # @return [Boolean] Whether it exists
356
382
  #
357
383
  def has_button?(locator = nil, **options, &optional_filter_block)
358
- has_selector?(:button, locator, options, &optional_filter_block)
384
+ has_selector?(:button, locator, **options, &optional_filter_block)
359
385
  end
360
386
 
361
387
  ##
@@ -367,7 +393,7 @@ module Capybara
367
393
  # @return [Boolean] Whether it doesn't exist
368
394
  #
369
395
  def has_no_button?(locator = nil, **options, &optional_filter_block)
370
- has_no_selector?(:button, locator, options, &optional_filter_block)
396
+ has_no_selector?(:button, locator, **options, &optional_filter_block)
371
397
  end
372
398
 
373
399
  ##
@@ -376,7 +402,7 @@ module Capybara
376
402
  # label, name or id.
377
403
  #
378
404
  # For text fields and other textual fields, such as textareas and
379
- # HTML5 email/url/etc. fields, it's possible to specify a :with
405
+ # HTML5 email/url/etc. fields, it's possible to specify a `:with`
380
406
  # option to specify the text the field should contain:
381
407
  #
382
408
  # page.has_field?('Name', with: 'Jonas')
@@ -385,7 +411,7 @@ module Capybara
385
411
  #
386
412
  # page.has_field?('Email', type: 'email')
387
413
  #
388
- # Note: 'textarea' and 'select' are valid type values, matching the associated tag names.
414
+ # NOTE: 'textarea' and 'select' are valid type values, matching the associated tag names.
389
415
  #
390
416
  # @param [String] locator The label, name or id of a field to check for
391
417
  # @option options [String, Regexp] :with The text content of the field or a Regexp to match
@@ -393,13 +419,13 @@ module Capybara
393
419
  # @return [Boolean] Whether it exists
394
420
  #
395
421
  def has_field?(locator = nil, **options, &optional_filter_block)
396
- has_selector?(:field, locator, options, &optional_filter_block)
422
+ has_selector?(:field, locator, **options, &optional_filter_block)
397
423
  end
398
424
 
399
425
  ##
400
426
  #
401
427
  # Checks if the page or current node has no form field with the given
402
- # label, name or id. See {Capybara::Node::Matchers#has_field?}.
428
+ # label, name or id. See {#has_field?}.
403
429
  #
404
430
  # @param [String] locator The label, name or id of a field to check for
405
431
  # @option options [String, Regexp] :with The text content of the field or a Regexp to match
@@ -407,59 +433,59 @@ module Capybara
407
433
  # @return [Boolean] Whether it doesn't exist
408
434
  #
409
435
  def has_no_field?(locator = nil, **options, &optional_filter_block)
410
- has_no_selector?(:field, locator, options, &optional_filter_block)
436
+ has_no_selector?(:field, locator, **options, &optional_filter_block)
411
437
  end
412
438
 
413
439
  ##
414
440
  #
415
441
  # Checks if the page or current node has a radio button or
416
- # checkbox with the given label, value, id, or Capybara.test_id attribute that is currently
442
+ # checkbox with the given label, value, id, or {Capybara.configure test_id} attribute that is currently
417
443
  # checked.
418
444
  #
419
445
  # @param [String] locator The label, name or id of a checked field
420
446
  # @return [Boolean] Whether it exists
421
447
  #
422
448
  def has_checked_field?(locator = nil, **options, &optional_filter_block)
423
- has_selector?(:field, locator, options.merge(checked: true), &optional_filter_block)
449
+ has_selector?(:field, locator, **options.merge(checked: true), &optional_filter_block)
424
450
  end
425
451
 
426
452
  ##
427
453
  #
428
454
  # Checks if the page or current node has no radio button or
429
- # checkbox with the given label, value or id, or Capybara.test_id attribute that is currently
455
+ # checkbox with the given label, value or id, or {Capybara.configure test_id} attribute that is currently
430
456
  # checked.
431
457
  #
432
458
  # @param [String] locator The label, name or id of a checked field
433
459
  # @return [Boolean] Whether it doesn't exist
434
460
  #
435
461
  def has_no_checked_field?(locator = nil, **options, &optional_filter_block)
436
- has_no_selector?(:field, locator, options.merge(checked: true), &optional_filter_block)
462
+ has_no_selector?(:field, locator, **options.merge(checked: true), &optional_filter_block)
437
463
  end
438
464
 
439
465
  ##
440
466
  #
441
467
  # Checks if the page or current node has a radio button or
442
- # checkbox with the given label, value or id, or Capybara.test_id attribute that is currently
468
+ # checkbox with the given label, value or id, or {Capybara.configure test_id} attribute that is currently
443
469
  # unchecked.
444
470
  #
445
471
  # @param [String] locator The label, name or id of an unchecked field
446
472
  # @return [Boolean] Whether it exists
447
473
  #
448
474
  def has_unchecked_field?(locator = nil, **options, &optional_filter_block)
449
- has_selector?(:field, locator, options.merge(unchecked: true), &optional_filter_block)
475
+ has_selector?(:field, locator, **options.merge(unchecked: true), &optional_filter_block)
450
476
  end
451
477
 
452
478
  ##
453
479
  #
454
480
  # Checks if the page or current node has no radio button or
455
- # checkbox with the given label, value or id, or Capybara.test_id attribute that is currently
481
+ # checkbox with the given label, value or id, or {Capybara.configure test_id} attribute that is currently
456
482
  # unchecked.
457
483
  #
458
484
  # @param [String] locator The label, name or id of an unchecked field
459
485
  # @return [Boolean] Whether it doesn't exist
460
486
  #
461
487
  def has_no_unchecked_field?(locator = nil, **options, &optional_filter_block)
462
- has_no_selector?(:field, locator, options.merge(unchecked: true), &optional_filter_block)
488
+ has_no_selector?(:field, locator, **options.merge(unchecked: true), &optional_filter_block)
463
489
  end
464
490
 
465
491
  ##
@@ -492,19 +518,19 @@ module Capybara
492
518
  # @return [Boolean] Whether it exists
493
519
  #
494
520
  def has_select?(locator = nil, **options, &optional_filter_block)
495
- has_selector?(:select, locator, options, &optional_filter_block)
521
+ has_selector?(:select, locator, **options, &optional_filter_block)
496
522
  end
497
523
 
498
524
  ##
499
525
  #
500
526
  # Checks if the page or current node has no select field with the
501
- # given label, name or id. See {Capybara::Node::Matchers#has_select?}.
527
+ # given label, name or id. See {#has_select?}.
502
528
  #
503
- # @param (see Capybara::Node::Matchers#has_select?)
529
+ # @param (see #has_select?)
504
530
  # @return [Boolean] Whether it doesn't exist
505
531
  #
506
532
  def has_no_select?(locator = nil, **options, &optional_filter_block)
507
- has_no_selector?(:select, locator, options, &optional_filter_block)
533
+ has_no_selector?(:select, locator, **options, &optional_filter_block)
508
534
  end
509
535
 
510
536
  ##
@@ -514,35 +540,43 @@ module Capybara
514
540
  #
515
541
  # page.has_table?('People')
516
542
  #
517
- # @param [String] locator The id or caption of a table
518
- # @return [Boolean] Whether it exist
543
+ # @param [String] locator The id or caption of a table
544
+ # @option options [Array<Array<String>>] :rows
545
+ # Text which should be contained in the tables `<td>` elements organized by row (`<td>` visibility is not considered)
546
+ # @option options [Array<Array<String>>, Array<Hash<String,String>>] :with_rows
547
+ # Partial set of text which should be contained in the tables `<td>` elements organized by row (`<td>` visibility is not considered)
548
+ # @option options [Array<Array<String>>] :cols
549
+ # Text which should be contained in the tables `<td>` elements organized by column (`<td>` visibility is not considered)
550
+ # @option options [Array<Array<String>>, Array<Hash<String,String>>] :with_cols
551
+ # Partial set of text which should be contained in the tables `<td>` elements organized by column (`<td>` visibility is not considered)
552
+ # @return [Boolean] Whether it exists
519
553
  #
520
554
  def has_table?(locator = nil, **options, &optional_filter_block)
521
- has_selector?(:table, locator, options, &optional_filter_block)
555
+ has_selector?(:table, locator, **options, &optional_filter_block)
522
556
  end
523
557
 
524
558
  ##
525
559
  #
526
560
  # Checks if the page or current node has no table with the given id
527
- # or caption. See {Capybara::Node::Matchers#has_table?}.
561
+ # or caption. See {#has_table?}.
528
562
  #
529
- # @param (see Capybara::Node::Matchers#has_table?)
563
+ # @param (see #has_table?)
530
564
  # @return [Boolean] Whether it doesn't exist
531
565
  #
532
566
  def has_no_table?(locator = nil, **options, &optional_filter_block)
533
- has_no_selector?(:table, locator, options, &optional_filter_block)
567
+ has_no_selector?(:table, locator, **options, &optional_filter_block)
534
568
  end
535
569
 
536
570
  ##
537
571
  #
538
- # Asserts that the current_node matches a given selector
572
+ # Asserts that the current node matches a given selector.
539
573
  #
540
574
  # node.assert_matches_selector('p#foo')
541
575
  # node.assert_matches_selector(:xpath, '//p[@id="foo"]')
542
576
  # node.assert_matches_selector(:foo)
543
577
  #
544
578
  # It also accepts all options that {Capybara::Node::Finders#all} accepts,
545
- # such as :text and :visible.
579
+ # such as `:text` and `:visible`.
546
580
  #
547
581
  # node.assert_matches_selector('li', text: 'Horse', visible: true)
548
582
  #
@@ -555,6 +589,14 @@ module Capybara
555
589
  end
556
590
  end
557
591
 
592
+ ##
593
+ #
594
+ # Asserts that the current node does not match a given selector.
595
+ # Usage is identical to {#assert_matches_selector}.
596
+ #
597
+ # @param (see #assert_matches_selector)
598
+ # @raise [Capybara::ExpectationNotMet] If the selector matches
599
+ #
558
600
  def assert_not_matches_selector(*args, &optional_filter_block)
559
601
  _verify_match_result(args, optional_filter_block) do |result|
560
602
  raise Capybara::ExpectationNotMet, 'Item matched the provided selector' if result.include? self
@@ -563,9 +605,9 @@ module Capybara
563
605
 
564
606
  ##
565
607
  #
566
- # Checks if the current node matches given selector
608
+ # Checks if the current node matches given selector.
567
609
  #
568
- # @param (see Capybara::Node::Finders#has_selector?)
610
+ # @param (see #has_selector?)
569
611
  # @return [Boolean]
570
612
  #
571
613
  def matches_selector?(*args, **options, &optional_filter_block)
@@ -574,32 +616,32 @@ module Capybara
574
616
 
575
617
  ##
576
618
  #
577
- # Checks if the current node matches given XPath expression
619
+ # Checks if the current node matches given XPath expression.
578
620
  #
579
621
  # @param [String, XPath::Expression] xpath The XPath expression to match against the current code
580
622
  # @return [Boolean]
581
623
  #
582
624
  def matches_xpath?(xpath, **options, &optional_filter_block)
583
- matches_selector?(:xpath, xpath, options, &optional_filter_block)
625
+ matches_selector?(:xpath, xpath, **options, &optional_filter_block)
584
626
  end
585
627
 
586
628
  ##
587
629
  #
588
- # Checks if the current node matches given CSS selector
630
+ # Checks if the current node matches given CSS selector.
589
631
  #
590
632
  # @param [String] css The CSS selector to match against the current code
591
633
  # @return [Boolean]
592
634
  #
593
635
  def matches_css?(css, **options, &optional_filter_block)
594
- matches_selector?(:css, css, options, &optional_filter_block)
636
+ matches_selector?(:css, css, **options, &optional_filter_block)
595
637
  end
596
638
 
597
639
  ##
598
640
  #
599
- # Checks if the current node does not match given selector
600
- # Usage is identical to Capybara::Node::Matchers#has_selector?
641
+ # Checks if the current node does not match given selector.
642
+ # Usage is identical to {#has_selector?}.
601
643
  #
602
- # @param (see Capybara::Node::Finders#has_selector?)
644
+ # @param (see #has_selector?)
603
645
  # @return [Boolean]
604
646
  #
605
647
  def not_matches_selector?(*args, **options, &optional_filter_block)
@@ -608,24 +650,24 @@ module Capybara
608
650
 
609
651
  ##
610
652
  #
611
- # Checks if the current node does not match given XPath expression
653
+ # Checks if the current node does not match given XPath expression.
612
654
  #
613
655
  # @param [String, XPath::Expression] xpath The XPath expression to match against the current code
614
656
  # @return [Boolean]
615
657
  #
616
658
  def not_matches_xpath?(xpath, **options, &optional_filter_block)
617
- not_matches_selector?(:xpath, xpath, options, &optional_filter_block)
659
+ not_matches_selector?(:xpath, xpath, **options, &optional_filter_block)
618
660
  end
619
661
 
620
662
  ##
621
663
  #
622
- # Checks if the current node does not match given CSS selector
664
+ # Checks if the current node does not match given CSS selector.
623
665
  #
624
666
  # @param [String] css The CSS selector to match against the current code
625
667
  # @return [Boolean]
626
668
  #
627
669
  def not_matches_css?(css, **options, &optional_filter_block)
628
- not_matches_selector?(:css, css, options, &optional_filter_block)
670
+ not_matches_selector?(:css, css, **options, &optional_filter_block)
629
671
  end
630
672
 
631
673
  ##
@@ -634,29 +676,29 @@ module Capybara
634
676
  #
635
677
  # @!macro text_query_params
636
678
  # @overload $0(type, text, **options)
637
- # @param [:all, :visible] type Whether to check for only visible or all text. If this parameter is missing or nil then we use the value of `Capybara.ignore_hidden_elements`, which defaults to `true`, corresponding to `:visible`.
679
+ # @param [:all, :visible] type Whether to check for only visible or all text. If this parameter is missing or nil then we use the value of {Capybara.configure ignore_hidden_elements}, which defaults to `true`, corresponding to `:visible`.
638
680
  # @param [String, Regexp] text The string/regexp to check for. If it's a string, text is expected to include it. If it's a regexp, text is expected to match it.
639
681
  # @option options [Integer] :count (nil) Number of times the text is expected to occur
640
682
  # @option options [Integer] :minimum (nil) Minimum number of times the text is expected to occur
641
683
  # @option options [Integer] :maximum (nil) Maximum number of times the text is expected to occur
642
684
  # @option options [Range] :between (nil) Range of times that is expected to contain number of times text occurs
643
- # @option options [Numeric] :wait (Capybara.default_max_wait_time) Maximum time that Capybara will wait for text to eq/match given string/regexp argument
644
- # @option options [Boolean] :exact (Capybara.exact_text) Whether text must be an exact match or just substring
645
- # @option options [Boolean] :normalize_ws (false) When true replace all whitespace with standard spaces and collapse consecutive whitespace to a single space
685
+ # @option options [Numeric] :wait Maximum time that Capybara will wait for text to eq/match given string/regexp argument. Defaults to {Capybara.configure default_max_wait_time}.
686
+ # @option options [Boolean] :exact Whether text must be an exact match or just substring. Defaults to {Capybara.configure exact_text}.
687
+ # @option options [Boolean] :normalize_ws (false) When `true` replace all whitespace with standard spaces and collapse consecutive whitespace to a single space
646
688
  # @overload $0(text, **options)
647
689
  # @param [String, Regexp] text The string/regexp to check for. If it's a string, text is expected to include it. If it's a regexp, text is expected to match it.
648
690
  # @option options [Integer] :count (nil) Number of times the text is expected to occur
649
691
  # @option options [Integer] :minimum (nil) Minimum number of times the text is expected to occur
650
692
  # @option options [Integer] :maximum (nil) Maximum number of times the text is expected to occur
651
693
  # @option options [Range] :between (nil) Range of times that is expected to contain number of times text occurs
652
- # @option options [Numeric] :wait (Capybara.default_max_wait_time) Maximum time that Capybara will wait for text to eq/match given string/regexp argument
653
- # @option options [Boolean] :exact (Capybara.exact_text) Whether text must be an exact match or just substring
654
- # @option options [Boolean] :normalize_ws (false) When true replace all whitespace with standard spaces and collapse consecutive whitespace to a single space
694
+ # @option options [Numeric] :wait Maximum time that Capybara will wait for text to eq/match given string/regexp argument. Defaults to {Capybara.configure default_max_wait_time}.
695
+ # @option options [Boolean] :exact Whether text must be an exact match or just substring. Defaults to {Capybara.configure exact_text}.
696
+ # @option options [Boolean] :normalize_ws (false) When `true` replace all whitespace with standard spaces and collapse consecutive whitespace to a single space
655
697
  # @raise [Capybara::ExpectationNotMet] if the assertion hasn't succeeded during wait time
656
698
  # @return [true]
657
699
  #
658
- def assert_text(*args)
659
- _verify_text(args) do |count, query|
700
+ def assert_text(type_or_text, *args, **opts)
701
+ _verify_text(type_or_text, *args, **opts) do |count, query|
660
702
  unless query.matches_count?(count) && (count.positive? || query.expects_none?)
661
703
  raise Capybara::ExpectationNotMet, query.failure_message
662
704
  end
@@ -671,8 +713,8 @@ module Capybara
671
713
  # @raise [Capybara::ExpectationNotMet] if the assertion hasn't succeeded during wait time
672
714
  # @return [true]
673
715
  #
674
- def assert_no_text(*args)
675
- _verify_text(args) do |count, query|
716
+ def assert_no_text(type_or_text, *args, **opts)
717
+ _verify_text(type_or_text, *args, **opts) do |count, query|
676
718
  if query.matches_count?(count) && (count.positive? || query.expects_none?)
677
719
  raise Capybara::ExpectationNotMet, query.negative_failure_message
678
720
  end
@@ -694,7 +736,7 @@ module Capybara
694
736
  # @return [Boolean] Whether it exists
695
737
  #
696
738
  def has_text?(*args, **options)
697
- make_predicate(options) { assert_text(*args, options) }
739
+ make_predicate(options) { assert_text(*args, **options) }
698
740
  end
699
741
  alias_method :has_content?, :has_text?
700
742
 
@@ -706,10 +748,96 @@ module Capybara
706
748
  # @return [Boolean] Whether it doesn't exist
707
749
  #
708
750
  def has_no_text?(*args, **options)
709
- make_predicate(options) { assert_no_text(*args, options) }
751
+ make_predicate(options) { assert_no_text(*args, **options) }
710
752
  end
711
753
  alias_method :has_no_content?, :has_no_text?
712
754
 
755
+ ##
756
+ #
757
+ # Asserts that a given selector matches an ancestor of the current node.
758
+ #
759
+ # element.assert_ancestor('p#foo')
760
+ #
761
+ # Accepts the same options as {#assert_selector}
762
+ #
763
+ # @param (see Capybara::Node::Finders#find)
764
+ # @raise [Capybara::ExpectationNotMet] If the selector does not exist
765
+ #
766
+ def assert_ancestor(*args, &optional_filter_block)
767
+ _verify_selector_result(args, optional_filter_block, Capybara::Queries::AncestorQuery) do |result, query|
768
+ unless result.matches_count? && (result.any? || query.expects_none?)
769
+ raise Capybara::ExpectationNotMet, result.failure_message
770
+ end
771
+ end
772
+ end
773
+
774
+ def assert_no_ancestor(*args, &optional_filter_block)
775
+ _verify_selector_result(args, optional_filter_block, Capybara::Queries::AncestorQuery) do |result, query|
776
+ if result.matches_count? && (!result.empty? || query.expects_none?)
777
+ raise Capybara::ExpectationNotMet, result.negative_failure_message
778
+ end
779
+ end
780
+ end
781
+
782
+ ##
783
+ #
784
+ # Predicate version of {#assert_ancestor}
785
+ #
786
+ def has_ancestor?(*args, **options, &optional_filter_block)
787
+ make_predicate(options) { assert_ancestor(*args, options, &optional_filter_block) }
788
+ end
789
+
790
+ ##
791
+ #
792
+ # Predicate version of {#assert_no_ancestor}
793
+ #
794
+ def has_no_ancestor?(*args, **options, &optional_filter_block)
795
+ make_predicate(options) { assert_no_ancestor(*args, options, &optional_filter_block) }
796
+ end
797
+
798
+ ##
799
+ #
800
+ # Asserts that a given selector matches a sibling of the current node.
801
+ #
802
+ # element.assert_sibling('p#foo')
803
+ #
804
+ # Accepts the same options as {#assert_selector}
805
+ #
806
+ # @param (see Capybara::Node::Finders#find)
807
+ # @raise [Capybara::ExpectationNotMet] If the selector does not exist
808
+ #
809
+ def assert_sibling(*args, &optional_filter_block)
810
+ _verify_selector_result(args, optional_filter_block, Capybara::Queries::SiblingQuery) do |result, query|
811
+ unless result.matches_count? && (result.any? || query.expects_none?)
812
+ raise Capybara::ExpectationNotMet, result.failure_message
813
+ end
814
+ end
815
+ end
816
+
817
+ def assert_no_sibling(*args, &optional_filter_block)
818
+ _verify_selector_result(args, optional_filter_block, Capybara::Queries::SiblingQuery) do |result, query|
819
+ if result.matches_count? && (!result.empty? || query.expects_none?)
820
+ raise Capybara::ExpectationNotMet, result.negative_failure_message
821
+ end
822
+ end
823
+ end
824
+
825
+ ##
826
+ #
827
+ # Predicate version of {#assert_sibling}
828
+ #
829
+ def has_sibling?(*args, **options, &optional_filter_block)
830
+ make_predicate(options) { assert_sibling(*args, options, &optional_filter_block) }
831
+ end
832
+
833
+ ##
834
+ #
835
+ # Predicate version of {#assert_no_sibling}
836
+ #
837
+ def has_no_sibling?(*args, **options, &optional_filter_block)
838
+ make_predicate(options) { assert_no_sibling(*args, options, &optional_filter_block) }
839
+ end
840
+
713
841
  def ==(other)
714
842
  eql?(other) || (other.respond_to?(:base) && base == other.base)
715
843
  end
@@ -728,9 +856,15 @@ module Capybara
728
856
  end
729
857
  end
730
858
 
731
- def _verify_selector_result(query_args, optional_filter_block)
732
- query_args = _set_query_session_options(*query_args)
733
- query = Capybara::Queries::SelectorQuery.new(*query_args, &optional_filter_block)
859
+ def _verify_selector_result(query_args, optional_filter_block, query_type = Capybara::Queries::SelectorQuery)
860
+ # query_args, query_opts = if query_args[0].is_a? Symbol
861
+ # a,o = _set_query_session_options(*query_args.slice(2..))
862
+ # [query_args.slice(0..1).concat(a), o]
863
+ # else
864
+ # _set_query_session_options(*query_args)
865
+ # end
866
+ query_args, query_opts = _set_query_session_options(*query_args)
867
+ query = query_type.new(*query_args, **query_opts, &optional_filter_block)
734
868
  synchronize(query.wait) do
735
869
  yield query.resolve_for(self), query
736
870
  end
@@ -738,26 +872,29 @@ module Capybara
738
872
  end
739
873
 
740
874
  def _verify_match_result(query_args, optional_filter_block)
741
- query_args = _set_query_session_options(*query_args)
742
- query = Capybara::Queries::MatchQuery.new(*query_args, &optional_filter_block)
875
+ query_args, query_opts = _set_query_session_options(*query_args)
876
+ query = Capybara::Queries::MatchQuery.new(*query_args, **query_opts, &optional_filter_block)
743
877
  synchronize(query.wait) do
744
878
  yield query.resolve_for(parent || session&.document || query_scope)
745
879
  end
746
880
  true
747
881
  end
748
882
 
749
- def _verify_text(query_args)
750
- query_args = _set_query_session_options(*query_args)
751
- query = Capybara::Queries::TextQuery.new(*query_args)
883
+ def _verify_text(type = nil, expected_text, **query_options) # rubocop:disable Style/OptionalArguments
884
+ query_options[:session_options] = session_options
885
+ query = Capybara::Queries::TextQuery.new(type, expected_text, **query_options)
752
886
  synchronize(query.wait) do
753
887
  yield query.resolve_for(self), query
754
888
  end
755
889
  true
756
890
  end
757
891
 
758
- def _set_query_session_options(*query_args, **query_options)
892
+ def _set_query_session_options(*query_args)
893
+ query_args, query_options = query_args.dup, {}
894
+ # query_options = query_args.pop if query_options.empty? && query_args.last.is_a?(Hash)
895
+ query_options = query_args.pop if query_args.last.is_a?(Hash)
759
896
  query_options[:session_options] = session_options
760
- query_args.push(query_options)
897
+ [query_args, query_options]
761
898
  end
762
899
 
763
900
  def make_predicate(options)