capybara 3.3.0 → 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 (308) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +1 -0
  3. data/History.md +803 -13
  4. data/License.txt +1 -1
  5. data/README.md +257 -84
  6. data/lib/capybara/config.rb +25 -9
  7. data/lib/capybara/cucumber.rb +1 -1
  8. data/lib/capybara/driver/base.rb +17 -3
  9. data/lib/capybara/driver/node.rb +31 -6
  10. data/lib/capybara/dsl.rb +9 -7
  11. data/lib/capybara/helpers.rb +31 -7
  12. data/lib/capybara/minitest/spec.rb +180 -88
  13. data/lib/capybara/minitest.rb +262 -149
  14. data/lib/capybara/node/actions.rb +202 -116
  15. data/lib/capybara/node/base.rb +34 -19
  16. data/lib/capybara/node/document.rb +14 -2
  17. data/lib/capybara/node/document_matchers.rb +10 -12
  18. data/lib/capybara/node/element.rb +269 -115
  19. data/lib/capybara/node/finders.rb +99 -77
  20. data/lib/capybara/node/matchers.rb +327 -151
  21. data/lib/capybara/node/simple.rb +48 -13
  22. data/lib/capybara/node/whitespace_normalizer.rb +81 -0
  23. data/lib/capybara/queries/active_element_query.rb +18 -0
  24. data/lib/capybara/queries/ancestor_query.rb +8 -9
  25. data/lib/capybara/queries/base_query.rb +23 -16
  26. data/lib/capybara/queries/current_path_query.rb +16 -6
  27. data/lib/capybara/queries/match_query.rb +1 -0
  28. data/lib/capybara/queries/selector_query.rb +587 -130
  29. data/lib/capybara/queries/sibling_query.rb +8 -6
  30. data/lib/capybara/queries/style_query.rb +6 -2
  31. data/lib/capybara/queries/text_query.rb +28 -14
  32. data/lib/capybara/queries/title_query.rb +2 -2
  33. data/lib/capybara/rack_test/browser.rb +92 -25
  34. data/lib/capybara/rack_test/driver.rb +16 -7
  35. data/lib/capybara/rack_test/errors.rb +6 -0
  36. data/lib/capybara/rack_test/form.rb +68 -41
  37. data/lib/capybara/rack_test/node.rb +106 -39
  38. data/lib/capybara/rails.rb +1 -1
  39. data/lib/capybara/registration_container.rb +41 -0
  40. data/lib/capybara/registrations/drivers.rb +42 -0
  41. data/lib/capybara/registrations/patches/puma_ssl.rb +29 -0
  42. data/lib/capybara/registrations/servers.rb +66 -0
  43. data/lib/capybara/result.rb +75 -52
  44. data/lib/capybara/rspec/features.rb +7 -7
  45. data/lib/capybara/rspec/matcher_proxies.rb +39 -18
  46. data/lib/capybara/rspec/matchers/base.rb +113 -0
  47. data/lib/capybara/rspec/matchers/become_closed.rb +33 -0
  48. data/lib/capybara/rspec/matchers/compound.rb +88 -0
  49. data/lib/capybara/rspec/matchers/count_sugar.rb +37 -0
  50. data/lib/capybara/rspec/matchers/have_ancestor.rb +28 -0
  51. data/lib/capybara/rspec/matchers/have_current_path.rb +29 -0
  52. data/lib/capybara/rspec/matchers/have_selector.rb +69 -0
  53. data/lib/capybara/rspec/matchers/have_sibling.rb +27 -0
  54. data/lib/capybara/rspec/matchers/have_text.rb +33 -0
  55. data/lib/capybara/rspec/matchers/have_title.rb +29 -0
  56. data/lib/capybara/rspec/matchers/match_selector.rb +27 -0
  57. data/lib/capybara/rspec/matchers/match_style.rb +43 -0
  58. data/lib/capybara/rspec/matchers/spatial_sugar.rb +39 -0
  59. data/lib/capybara/rspec/matchers.rb +141 -339
  60. data/lib/capybara/rspec.rb +2 -0
  61. data/lib/capybara/selector/builders/css_builder.rb +84 -0
  62. data/lib/capybara/selector/builders/xpath_builder.rb +71 -0
  63. data/lib/capybara/selector/css.rb +27 -25
  64. data/lib/capybara/selector/definition/button.rb +68 -0
  65. data/lib/capybara/selector/definition/checkbox.rb +26 -0
  66. data/lib/capybara/selector/definition/css.rb +10 -0
  67. data/lib/capybara/selector/definition/datalist_input.rb +35 -0
  68. data/lib/capybara/selector/definition/datalist_option.rb +25 -0
  69. data/lib/capybara/selector/definition/element.rb +28 -0
  70. data/lib/capybara/selector/definition/field.rb +40 -0
  71. data/lib/capybara/selector/definition/fieldset.rb +14 -0
  72. data/lib/capybara/selector/definition/file_field.rb +13 -0
  73. data/lib/capybara/selector/definition/fillable_field.rb +33 -0
  74. data/lib/capybara/selector/definition/frame.rb +17 -0
  75. data/lib/capybara/selector/definition/id.rb +6 -0
  76. data/lib/capybara/selector/definition/label.rb +62 -0
  77. data/lib/capybara/selector/definition/link.rb +55 -0
  78. data/lib/capybara/selector/definition/link_or_button.rb +16 -0
  79. data/lib/capybara/selector/definition/option.rb +27 -0
  80. data/lib/capybara/selector/definition/radio_button.rb +27 -0
  81. data/lib/capybara/selector/definition/select.rb +81 -0
  82. data/lib/capybara/selector/definition/table.rb +109 -0
  83. data/lib/capybara/selector/definition/table_row.rb +21 -0
  84. data/lib/capybara/selector/definition/xpath.rb +5 -0
  85. data/lib/capybara/selector/definition.rb +280 -0
  86. data/lib/capybara/selector/filter.rb +1 -0
  87. data/lib/capybara/selector/filter_set.rb +73 -25
  88. data/lib/capybara/selector/filters/base.rb +24 -5
  89. data/lib/capybara/selector/filters/expression_filter.rb +3 -3
  90. data/lib/capybara/selector/filters/locator_filter.rb +29 -0
  91. data/lib/capybara/selector/filters/node_filter.rb +16 -2
  92. data/lib/capybara/selector/regexp_disassembler.rb +211 -0
  93. data/lib/capybara/selector/selector.rb +85 -348
  94. data/lib/capybara/selector/xpath_extensions.rb +17 -0
  95. data/lib/capybara/selector.rb +474 -447
  96. data/lib/capybara/selenium/atoms/getAttribute.min.js +1 -0
  97. data/lib/capybara/selenium/atoms/isDisplayed.min.js +1 -0
  98. data/lib/capybara/selenium/atoms/src/getAttribute.js +161 -0
  99. data/lib/capybara/selenium/atoms/src/isDisplayed.js +454 -0
  100. data/lib/capybara/selenium/driver.rb +255 -143
  101. data/lib/capybara/selenium/driver_specializations/chrome_driver.rb +93 -11
  102. data/lib/capybara/selenium/driver_specializations/edge_driver.rb +128 -0
  103. data/lib/capybara/selenium/driver_specializations/firefox_driver.rb +84 -0
  104. data/lib/capybara/selenium/driver_specializations/internet_explorer_driver.rb +26 -0
  105. data/lib/capybara/selenium/driver_specializations/safari_driver.rb +24 -0
  106. data/lib/capybara/selenium/extensions/file_input_click_emulation.rb +34 -0
  107. data/lib/capybara/selenium/extensions/find.rb +110 -0
  108. data/lib/capybara/selenium/extensions/html5_drag.rb +229 -0
  109. data/lib/capybara/selenium/extensions/modifier_keys_stack.rb +28 -0
  110. data/lib/capybara/selenium/extensions/scroll.rb +76 -0
  111. data/lib/capybara/selenium/node.rb +436 -134
  112. data/lib/capybara/selenium/nodes/chrome_node.rb +125 -0
  113. data/lib/capybara/selenium/nodes/edge_node.rb +110 -0
  114. data/lib/capybara/selenium/nodes/firefox_node.rb +136 -0
  115. data/lib/capybara/selenium/nodes/ie_node.rb +22 -0
  116. data/lib/capybara/selenium/nodes/safari_node.rb +118 -0
  117. data/lib/capybara/selenium/patches/atoms.rb +18 -0
  118. data/lib/capybara/selenium/patches/is_displayed.rb +16 -0
  119. data/lib/capybara/selenium/patches/logs.rb +45 -0
  120. data/lib/capybara/selenium/patches/pause_duration_fix.rb +9 -0
  121. data/lib/capybara/selenium/patches/persistent_client.rb +20 -0
  122. data/lib/capybara/server/animation_disabler.rb +56 -19
  123. data/lib/capybara/server/checker.rb +9 -3
  124. data/lib/capybara/server/middleware.rb +28 -12
  125. data/lib/capybara/server.rb +33 -10
  126. data/lib/capybara/session/config.rb +34 -10
  127. data/lib/capybara/session/matchers.rb +23 -16
  128. data/lib/capybara/session.rb +230 -170
  129. data/lib/capybara/spec/public/jquery.js +5 -5
  130. data/lib/capybara/spec/public/offset.js +6 -0
  131. data/lib/capybara/spec/public/test.js +121 -8
  132. data/lib/capybara/spec/session/accept_alert_spec.rb +11 -11
  133. data/lib/capybara/spec/session/accept_confirm_spec.rb +3 -3
  134. data/lib/capybara/spec/session/accept_prompt_spec.rb +9 -10
  135. data/lib/capybara/spec/session/active_element_spec.rb +31 -0
  136. data/lib/capybara/spec/session/all_spec.rb +127 -40
  137. data/lib/capybara/spec/session/ancestor_spec.rb +24 -19
  138. data/lib/capybara/spec/session/assert_all_of_selectors_spec.rb +67 -38
  139. data/lib/capybara/spec/session/assert_current_path_spec.rb +21 -18
  140. data/lib/capybara/spec/session/assert_selector_spec.rb +52 -58
  141. data/lib/capybara/spec/session/assert_style_spec.rb +7 -7
  142. data/lib/capybara/spec/session/assert_text_spec.rb +74 -50
  143. data/lib/capybara/spec/session/assert_title_spec.rb +12 -12
  144. data/lib/capybara/spec/session/attach_file_spec.rb +126 -72
  145. data/lib/capybara/spec/session/body_spec.rb +6 -6
  146. data/lib/capybara/spec/session/check_spec.rb +102 -47
  147. data/lib/capybara/spec/session/choose_spec.rb +58 -32
  148. data/lib/capybara/spec/session/click_button_spec.rb +219 -163
  149. data/lib/capybara/spec/session/click_link_or_button_spec.rb +49 -23
  150. data/lib/capybara/spec/session/click_link_spec.rb +77 -54
  151. data/lib/capybara/spec/session/current_scope_spec.rb +8 -8
  152. data/lib/capybara/spec/session/current_url_spec.rb +38 -29
  153. data/lib/capybara/spec/session/dismiss_confirm_spec.rb +3 -3
  154. data/lib/capybara/spec/session/dismiss_prompt_spec.rb +2 -2
  155. data/lib/capybara/spec/session/element/assert_match_selector_spec.rb +8 -8
  156. data/lib/capybara/spec/session/element/match_css_spec.rb +16 -10
  157. data/lib/capybara/spec/session/element/match_xpath_spec.rb +6 -6
  158. data/lib/capybara/spec/session/element/matches_selector_spec.rb +68 -56
  159. data/lib/capybara/spec/session/evaluate_async_script_spec.rb +7 -7
  160. data/lib/capybara/spec/session/evaluate_script_spec.rb +28 -8
  161. data/lib/capybara/spec/session/execute_script_spec.rb +8 -7
  162. data/lib/capybara/spec/session/fill_in_spec.rb +101 -46
  163. data/lib/capybara/spec/session/find_button_spec.rb +23 -23
  164. data/lib/capybara/spec/session/find_by_id_spec.rb +7 -7
  165. data/lib/capybara/spec/session/find_field_spec.rb +32 -30
  166. data/lib/capybara/spec/session/find_link_spec.rb +31 -21
  167. data/lib/capybara/spec/session/find_spec.rb +244 -141
  168. data/lib/capybara/spec/session/first_spec.rb +43 -43
  169. data/lib/capybara/spec/session/frame/frame_title_spec.rb +5 -5
  170. data/lib/capybara/spec/session/frame/frame_url_spec.rb +5 -5
  171. data/lib/capybara/spec/session/frame/switch_to_frame_spec.rb +30 -18
  172. data/lib/capybara/spec/session/frame/within_frame_spec.rb +45 -18
  173. data/lib/capybara/spec/session/go_back_spec.rb +1 -1
  174. data/lib/capybara/spec/session/go_forward_spec.rb +1 -1
  175. data/lib/capybara/spec/session/has_all_selectors_spec.rb +23 -23
  176. data/lib/capybara/spec/session/has_ancestor_spec.rb +46 -0
  177. data/lib/capybara/spec/session/has_any_selectors_spec.rb +29 -0
  178. data/lib/capybara/spec/session/has_button_spec.rb +94 -13
  179. data/lib/capybara/spec/session/has_css_spec.rb +272 -132
  180. data/lib/capybara/spec/session/has_current_path_spec.rb +50 -35
  181. data/lib/capybara/spec/session/has_element_spec.rb +47 -0
  182. data/lib/capybara/spec/session/has_field_spec.rb +137 -58
  183. data/lib/capybara/spec/session/has_link_spec.rb +44 -4
  184. data/lib/capybara/spec/session/has_none_selectors_spec.rb +31 -31
  185. data/lib/capybara/spec/session/has_select_spec.rb +84 -50
  186. data/lib/capybara/spec/session/has_selector_spec.rb +111 -71
  187. data/lib/capybara/spec/session/has_sibling_spec.rb +50 -0
  188. data/lib/capybara/spec/session/has_table_spec.rb +181 -4
  189. data/lib/capybara/spec/session/has_text_spec.rb +101 -53
  190. data/lib/capybara/spec/session/has_title_spec.rb +19 -14
  191. data/lib/capybara/spec/session/has_xpath_spec.rb +56 -38
  192. data/lib/capybara/spec/session/headers_spec.rb +1 -1
  193. data/lib/capybara/spec/session/html_spec.rb +13 -6
  194. data/lib/capybara/spec/session/matches_style_spec.rb +37 -0
  195. data/lib/capybara/spec/session/node_spec.rb +894 -142
  196. data/lib/capybara/spec/session/node_wrapper_spec.rb +10 -7
  197. data/lib/capybara/spec/session/refresh_spec.rb +9 -7
  198. data/lib/capybara/spec/session/reset_session_spec.rb +63 -35
  199. data/lib/capybara/spec/session/response_code_spec.rb +1 -1
  200. data/lib/capybara/spec/session/save_and_open_page_spec.rb +2 -2
  201. data/lib/capybara/spec/session/save_and_open_screenshot_spec.rb +2 -2
  202. data/lib/capybara/spec/session/save_page_spec.rb +37 -37
  203. data/lib/capybara/spec/session/save_screenshot_spec.rb +10 -10
  204. data/lib/capybara/spec/session/screenshot_spec.rb +2 -2
  205. data/lib/capybara/spec/session/scroll_spec.rb +119 -0
  206. data/lib/capybara/spec/session/select_spec.rb +85 -85
  207. data/lib/capybara/spec/session/selectors_spec.rb +49 -18
  208. data/lib/capybara/spec/session/sibling_spec.rb +9 -9
  209. data/lib/capybara/spec/session/text_spec.rb +25 -24
  210. data/lib/capybara/spec/session/title_spec.rb +7 -6
  211. data/lib/capybara/spec/session/uncheck_spec.rb +33 -21
  212. data/lib/capybara/spec/session/unselect_spec.rb +37 -37
  213. data/lib/capybara/spec/session/visit_spec.rb +68 -49
  214. data/lib/capybara/spec/session/window/become_closed_spec.rb +20 -17
  215. data/lib/capybara/spec/session/window/current_window_spec.rb +1 -1
  216. data/lib/capybara/spec/session/window/switch_to_window_spec.rb +20 -16
  217. data/lib/capybara/spec/session/window/window_opened_by_spec.rb +6 -2
  218. data/lib/capybara/spec/session/window/window_spec.rb +62 -63
  219. data/lib/capybara/spec/session/window/windows_spec.rb +5 -1
  220. data/lib/capybara/spec/session/window/within_window_spec.rb +14 -14
  221. data/lib/capybara/spec/session/within_spec.rb +79 -42
  222. data/lib/capybara/spec/spec_helper.rb +41 -53
  223. data/lib/capybara/spec/test_app.rb +132 -43
  224. data/lib/capybara/spec/views/animated.erb +49 -0
  225. data/lib/capybara/spec/views/form.erb +139 -42
  226. data/lib/capybara/spec/views/frame_child.erb +4 -3
  227. data/lib/capybara/spec/views/frame_one.erb +2 -1
  228. data/lib/capybara/spec/views/frame_parent.erb +1 -1
  229. data/lib/capybara/spec/views/frame_two.erb +1 -1
  230. data/lib/capybara/spec/views/initial_alert.erb +2 -1
  231. data/lib/capybara/spec/views/layout.erb +10 -0
  232. data/lib/capybara/spec/views/obscured.erb +47 -0
  233. data/lib/capybara/spec/views/offset.erb +33 -0
  234. data/lib/capybara/spec/views/path.erb +2 -2
  235. data/lib/capybara/spec/views/popup_one.erb +1 -1
  236. data/lib/capybara/spec/views/popup_two.erb +1 -1
  237. data/lib/capybara/spec/views/react.erb +45 -0
  238. data/lib/capybara/spec/views/scroll.erb +21 -0
  239. data/lib/capybara/spec/views/spatial.erb +31 -0
  240. data/lib/capybara/spec/views/tables.erb +67 -0
  241. data/lib/capybara/spec/views/with_animation.erb +39 -4
  242. data/lib/capybara/spec/views/with_base_tag.erb +2 -2
  243. data/lib/capybara/spec/views/with_dragula.erb +24 -0
  244. data/lib/capybara/spec/views/with_fixed_header_footer.erb +2 -1
  245. data/lib/capybara/spec/views/with_hover.erb +3 -2
  246. data/lib/capybara/spec/views/with_hover1.erb +10 -0
  247. data/lib/capybara/spec/views/with_html.erb +37 -9
  248. data/lib/capybara/spec/views/with_html5_svg.erb +20 -0
  249. data/lib/capybara/spec/views/with_jquery_animation.erb +24 -0
  250. data/lib/capybara/spec/views/with_js.erb +26 -5
  251. data/lib/capybara/spec/views/with_jstree.erb +26 -0
  252. data/lib/capybara/spec/views/with_namespace.erb +1 -0
  253. data/lib/capybara/spec/views/with_scope.erb +2 -2
  254. data/lib/capybara/spec/views/with_scope_other.erb +6 -0
  255. data/lib/capybara/spec/views/with_shadow.erb +31 -0
  256. data/lib/capybara/spec/views/with_slow_unload.erb +2 -1
  257. data/lib/capybara/spec/views/with_sortable_js.erb +21 -0
  258. data/lib/capybara/spec/views/with_unload_alert.erb +1 -0
  259. data/lib/capybara/spec/views/with_windows.erb +1 -1
  260. data/lib/capybara/spec/views/within_frames.erb +1 -1
  261. data/lib/capybara/version.rb +1 -1
  262. data/lib/capybara/window.rb +19 -25
  263. data/lib/capybara.rb +126 -111
  264. data/spec/basic_node_spec.rb +59 -34
  265. data/spec/capybara_spec.rb +56 -44
  266. data/spec/counter_spec.rb +35 -0
  267. data/spec/css_builder_spec.rb +101 -0
  268. data/spec/css_splitter_spec.rb +8 -8
  269. data/spec/dsl_spec.rb +79 -52
  270. data/spec/filter_set_spec.rb +9 -9
  271. data/spec/fixtures/selenium_driver_rspec_failure.rb +4 -4
  272. data/spec/fixtures/selenium_driver_rspec_success.rb +4 -4
  273. data/spec/minitest_spec.rb +45 -7
  274. data/spec/minitest_spec_spec.rb +87 -64
  275. data/spec/per_session_config_spec.rb +6 -6
  276. data/spec/rack_test_spec.rb +172 -116
  277. data/spec/regexp_dissassembler_spec.rb +250 -0
  278. data/spec/result_spec.rb +80 -72
  279. data/spec/rspec/features_spec.rb +21 -16
  280. data/spec/rspec/scenarios_spec.rb +10 -6
  281. data/spec/rspec/shared_spec_matchers.rb +407 -365
  282. data/spec/rspec/views_spec.rb +3 -3
  283. data/spec/rspec_matchers_spec.rb +35 -10
  284. data/spec/rspec_spec.rb +63 -41
  285. data/spec/sauce_spec_chrome.rb +43 -0
  286. data/spec/selector_spec.rb +334 -89
  287. data/spec/selenium_spec_chrome.rb +176 -62
  288. data/spec/selenium_spec_chrome_remote.rb +54 -14
  289. data/spec/selenium_spec_edge.rb +41 -8
  290. data/spec/selenium_spec_firefox.rb +228 -0
  291. data/spec/selenium_spec_firefox_remote.rb +94 -0
  292. data/spec/selenium_spec_ie.rb +129 -11
  293. data/spec/selenium_spec_safari.rb +162 -0
  294. data/spec/server_spec.rb +171 -97
  295. data/spec/session_spec.rb +34 -18
  296. data/spec/shared_selenium_node.rb +79 -0
  297. data/spec/shared_selenium_session.rb +344 -80
  298. data/spec/spec_helper.rb +124 -2
  299. data/spec/whitespace_normalizer_spec.rb +54 -0
  300. data/spec/xpath_builder_spec.rb +93 -0
  301. metadata +326 -28
  302. data/lib/capybara/rspec/compound.rb +0 -94
  303. data/lib/capybara/selenium/driver_specializations/marionette_driver.rb +0 -31
  304. data/lib/capybara/selenium/nodes/marionette_node.rb +0 -31
  305. data/lib/capybara/spec/session/has_style_spec.rb +0 -25
  306. data/lib/capybara/spec/session/source_spec.rb +0 -0
  307. data/lib/capybara/spec/views/with_title.erb +0 -5
  308. data/spec/selenium_spec_marionette.rb +0 -167
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- RSpec.shared_context "Capybara Features", capybara_feature: true do
3
+ RSpec.shared_context 'Capybara Features', capybara_feature: true do
4
4
  instance_eval do
5
5
  alias background before
6
6
  alias given let
@@ -10,14 +10,14 @@ end
10
10
 
11
11
  # ensure shared_context is included if default shared_context_metadata_behavior is changed
12
12
  RSpec.configure do |config|
13
- config.include_context "Capybara Features", capybara_feature: true if config.respond_to?(:include_context)
13
+ config.include_context 'Capybara Features', capybara_feature: true if config.respond_to?(:include_context)
14
14
  end
15
15
 
16
16
  RSpec.configure do |config|
17
- config.alias_example_group_to :feature, capybara_feature: true, type: :feature
18
- config.alias_example_group_to :xfeature, capybara_feature: true, type: :feature, skip: "Temporarily disabled with xfeature"
19
- config.alias_example_group_to :ffeature, capybara_feature: true, type: :feature, focus: true
17
+ config.alias_example_group_to :feature, :capybara_feature, type: :feature
18
+ config.alias_example_group_to :xfeature, :capybara_feature, type: :feature, skip: 'Temporarily disabled with xfeature'
19
+ config.alias_example_group_to :ffeature, :capybara_feature, :focus, type: :feature
20
20
  config.alias_example_to :scenario
21
- config.alias_example_to :xscenario, skip: "Temporarily disabled with xscenario"
22
- config.alias_example_to :fscenario, focus: true
21
+ config.alias_example_to :xscenario, skip: 'Temporarily disabled with xscenario'
22
+ config.alias_example_to :fscenario, :focus
23
23
  end
@@ -2,41 +2,66 @@
2
2
 
3
3
  module Capybara
4
4
  module RSpecMatcherProxies
5
- def all(*args, &block)
5
+ def all(*args, **kwargs, &block)
6
6
  if defined?(::RSpec::Matchers::BuiltIn::All) && args.first.respond_to?(:matches?)
7
7
  ::RSpec::Matchers::BuiltIn::All.new(*args)
8
8
  else
9
- find_all(*args, &block)
9
+ find_all(*args, **kwargs, &block)
10
10
  end
11
11
  end
12
12
 
13
- def within(*args)
14
- if block_given?
15
- within_element(*args, &Proc.new)
13
+ def within(*args, **kwargs, &block)
14
+ if block
15
+ within_element(*args, **kwargs, &block)
16
16
  else
17
17
  be_within(*args)
18
18
  end
19
19
  end
20
20
  end
21
+ end
22
+
23
+ if RUBY_ENGINE == 'jruby'
24
+ # :nocov:
25
+ module Capybara::DSL
26
+ class << self
27
+ remove_method :included
21
28
 
22
- module DSLRSpecProxyInstaller
23
- module ClassMethods
24
29
  def included(base)
25
- if defined?(::RSpec::Matchers)
26
- base.include(::Capybara::RSpecMatcherProxies) if base.include?(::RSpec::Matchers)
30
+ warn 'including Capybara::DSL in the global scope is not recommended!' if base == Object
31
+ if defined?(::RSpec::Matchers) && base.include?(::RSpec::Matchers)
32
+ base.send(:include, ::Capybara::RSpecMatcherProxies)
27
33
  end
28
34
  super
29
35
  end
30
36
  end
37
+ end
38
+
39
+ if defined?(RSpec::Matchers)
40
+ module ::RSpec::Matchers
41
+ def self.included(base)
42
+ base.send(:include, ::Capybara::RSpecMatcherProxies) if base.include?(::Capybara::DSL)
43
+ super
44
+ end
45
+ end
46
+ end
47
+ # :nocov:
48
+ else
49
+ module Capybara::DSLRSpecProxyInstaller
50
+ module ClassMethods
51
+ def included(base)
52
+ base.include(::Capybara::RSpecMatcherProxies) if defined?(::RSpec::Matchers) && base.include?(::RSpec::Matchers)
53
+ super
54
+ end
55
+ end
31
56
 
32
57
  def self.prepended(base)
33
- class <<base
58
+ class << base
34
59
  prepend ClassMethods
35
60
  end
36
61
  end
37
62
  end
38
63
 
39
- module RSpecMatcherProxyInstaller
64
+ module Capybara::RSpecMatcherProxyInstaller
40
65
  module ClassMethods
41
66
  def included(base)
42
67
  base.include(::Capybara::RSpecMatcherProxies) if base.include?(::Capybara::DSL)
@@ -45,17 +70,13 @@ module Capybara
45
70
  end
46
71
 
47
72
  def self.prepended(base)
48
- class <<base
73
+ class << base
49
74
  prepend ClassMethods
50
75
  end
51
76
  end
52
77
  end
53
78
 
54
- DSL.prepend ::Capybara::DSLRSpecProxyInstaller
55
- end
79
+ Capybara::DSL.prepend Capybara::DSLRSpecProxyInstaller
56
80
 
57
- if defined?(::RSpec::Matchers)
58
- module ::RSpec::Matchers
59
- prepend ::Capybara::RSpecMatcherProxyInstaller
60
- end
81
+ RSpec::Matchers.prepend Capybara::RSpecMatcherProxyInstaller if defined?(RSpec::Matchers)
61
82
  end
@@ -0,0 +1,113 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'capybara/rspec/matchers/compound'
4
+ require 'capybara/rspec/matchers/count_sugar'
5
+ require 'capybara/rspec/matchers/spatial_sugar'
6
+
7
+ module Capybara
8
+ module RSpecMatchers
9
+ module Matchers
10
+ class Base
11
+ include ::Capybara::RSpecMatchers::Matchers::Compound if defined?(::Capybara::RSpecMatchers::Matchers::Compound)
12
+
13
+ attr_reader :failure_message, :failure_message_when_negated
14
+
15
+ def initialize(*args, **kw_args, &filter_block)
16
+ @args = args.dup
17
+ @kw_args = kw_args || {}
18
+ @filter_block = filter_block
19
+ end
20
+
21
+ private
22
+
23
+ def session_query_args
24
+ # if @args.last.is_a? Hash
25
+ # @args.last[:session_options] = session_options
26
+ # else
27
+ # @args.push(session_options: session_options)
28
+ # end
29
+ @args
30
+ end
31
+
32
+ def session_query_options
33
+ @kw_args[:session_options] = session_options
34
+ @kw_args
35
+ end
36
+
37
+ def session_options
38
+ @context_el ||= nil
39
+ if @context_el.respond_to? :session_options
40
+ @context_el.session_options
41
+ elsif @context_el.respond_to? :current_scope
42
+ @context_el.current_scope.session_options
43
+ else
44
+ Capybara.session_options
45
+ end
46
+ end
47
+ end
48
+
49
+ class WrappedElementMatcher < Base
50
+ def matches?(actual, &filter_block)
51
+ @filter_block ||= filter_block
52
+ element_matches?(wrap(actual))
53
+ rescue Capybara::ExpectationNotMet => e
54
+ @failure_message = e.message
55
+ false
56
+ end
57
+
58
+ def does_not_match?(actual, &filter_block)
59
+ @filter_block ||= filter_block
60
+ element_does_not_match?(wrap(actual))
61
+ rescue Capybara::ExpectationNotMet => e
62
+ @failure_message_when_negated = e.message
63
+ false
64
+ end
65
+
66
+ private
67
+
68
+ def wrap(actual)
69
+ actual = actual.to_capybara_node if actual.respond_to?(:to_capybara_node)
70
+ @context_el = if actual.respond_to?(:has_selector?)
71
+ actual
72
+ else
73
+ Capybara.string(actual.to_s)
74
+ end
75
+ end
76
+ end
77
+
78
+ class CountableWrappedElementMatcher < WrappedElementMatcher
79
+ include ::Capybara::RSpecMatchers::CountSugar
80
+ include ::Capybara::RSpecMatchers::SpatialSugar
81
+ end
82
+
83
+ class NegatedMatcher
84
+ include ::Capybara::RSpecMatchers::Matchers::Compound if defined?(::Capybara::RSpecMatchers::Matchers::Compound)
85
+
86
+ def initialize(matcher)
87
+ super()
88
+ @matcher = matcher
89
+ end
90
+
91
+ def matches?(actual, &filter_block)
92
+ @matcher.does_not_match?(actual, &filter_block)
93
+ end
94
+
95
+ def does_not_match?(actual, &filter_block)
96
+ @matcher.matches?(actual, &filter_block)
97
+ end
98
+
99
+ def description
100
+ "not #{@matcher.description}"
101
+ end
102
+
103
+ def failure_message
104
+ @matcher.failure_message_when_negated
105
+ end
106
+
107
+ def failure_message_when_negated
108
+ @matcher.failure_message
109
+ end
110
+ end
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Capybara
4
+ module RSpecMatchers
5
+ module Matchers
6
+ class BecomeClosed
7
+ def initialize(options)
8
+ @options = options
9
+ end
10
+
11
+ def matches?(window)
12
+ @window = window
13
+ @wait_time = Capybara::Queries::BaseQuery.wait(@options, window.session.config.default_max_wait_time)
14
+ timer = Capybara::Helpers.timer(expire_in: @wait_time)
15
+ while window.exists?
16
+ return false if timer.expired?
17
+
18
+ sleep 0.01
19
+ end
20
+ true
21
+ end
22
+
23
+ def failure_message
24
+ "expected #{@window.inspect} to become closed after #{@wait_time} seconds"
25
+ end
26
+
27
+ def failure_message_when_negated
28
+ "expected #{@window.inspect} not to become closed after #{@wait_time} seconds"
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,88 @@
1
+ # frozen_string_literal: true
2
+
3
+ if defined?(RSpec::Expectations::Version)
4
+ module Capybara
5
+ module RSpecMatchers
6
+ module Matchers
7
+ module Compound
8
+ include ::RSpec::Matchers::Composable
9
+
10
+ def and(matcher)
11
+ And.new(self, matcher)
12
+ end
13
+
14
+ def and_then(matcher)
15
+ ::RSpec::Matchers::BuiltIn::Compound::And.new(self, matcher)
16
+ end
17
+
18
+ def or(matcher)
19
+ Or.new(self, matcher)
20
+ end
21
+
22
+ class CapybaraEvaluator
23
+ def initialize(actual)
24
+ @actual = actual
25
+ @match_results = Hash.new { |hsh, matcher| hsh[matcher] = matcher.matches?(@actual) }
26
+ end
27
+
28
+ def matcher_matches?(matcher)
29
+ @match_results[matcher]
30
+ end
31
+
32
+ def reset
33
+ @match_results.clear
34
+ end
35
+ end
36
+
37
+ # @api private
38
+ module Synchronizer
39
+ def match(_expected, actual)
40
+ @evaluator = CapybaraEvaluator.new(actual)
41
+ syncer = sync_element(actual)
42
+ begin
43
+ syncer.synchronize do
44
+ @evaluator.reset
45
+ raise ::Capybara::ElementNotFound unless synchronized_match?
46
+
47
+ true
48
+ end
49
+ rescue StandardError
50
+ false
51
+ end
52
+ end
53
+
54
+ def sync_element(el)
55
+ if el.respond_to? :synchronize
56
+ el
57
+ elsif el.respond_to? :current_scope
58
+ el.current_scope
59
+ else
60
+ Capybara.string(el)
61
+ end
62
+ end
63
+ end
64
+
65
+ class And < ::RSpec::Matchers::BuiltIn::Compound::And
66
+ include Synchronizer
67
+
68
+ private
69
+
70
+ def synchronized_match?
71
+ [matcher_1_matches?, matcher_2_matches?].all?
72
+ end
73
+ end
74
+
75
+ class Or < ::RSpec::Matchers::BuiltIn::Compound::Or
76
+ include Synchronizer
77
+
78
+ private
79
+
80
+ def synchronized_match?
81
+ [matcher_1_matches?, matcher_2_matches?].any?
82
+ end
83
+ end
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Capybara
4
+ module RSpecMatchers
5
+ module CountSugar
6
+ def once; exactly(1); end
7
+ def twice; exactly(2); end
8
+ def thrice; exactly(3); end
9
+
10
+ def exactly(number)
11
+ options[:count] = number
12
+ self
13
+ end
14
+
15
+ def at_most(number)
16
+ options[:maximum] = number
17
+ self
18
+ end
19
+
20
+ def at_least(number)
21
+ options[:minimum] = number
22
+ self
23
+ end
24
+
25
+ def times
26
+ self
27
+ end
28
+
29
+ private
30
+
31
+ def options
32
+ # (@args.last.is_a?(Hash) ? @args : @args.push({})).last
33
+ @kw_args
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'capybara/rspec/matchers/base'
4
+
5
+ module Capybara
6
+ module RSpecMatchers
7
+ module Matchers
8
+ class HaveAncestor < CountableWrappedElementMatcher
9
+ def element_matches?(el)
10
+ el.assert_ancestor(*@args, **session_query_options, &@filter_block)
11
+ end
12
+
13
+ def element_does_not_match?(el)
14
+ el.assert_no_ancestor(*@args, **session_query_options, &@filter_block)
15
+ end
16
+
17
+ def description
18
+ "have ancestor #{query.description}"
19
+ end
20
+
21
+ def query
22
+ # @query ||= Capybara::Queries::AncestorQuery.new(*session_query_args, &@filter_block)
23
+ @query ||= Capybara::Queries::AncestorQuery.new(*session_query_args, **session_query_options, &@filter_block)
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'capybara/rspec/matchers/base'
4
+
5
+ module Capybara
6
+ module RSpecMatchers
7
+ module Matchers
8
+ class HaveCurrentPath < WrappedElementMatcher
9
+ def element_matches?(el)
10
+ el.assert_current_path(current_path, **@kw_args, &@filter_block)
11
+ end
12
+
13
+ def element_does_not_match?(el)
14
+ el.assert_no_current_path(current_path, **@kw_args, &@filter_block)
15
+ end
16
+
17
+ def description
18
+ "have current path #{current_path.inspect}"
19
+ end
20
+
21
+ private
22
+
23
+ def current_path
24
+ @args.first
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'capybara/rspec/matchers/base'
4
+
5
+ module Capybara
6
+ module RSpecMatchers
7
+ module Matchers
8
+ class HaveSelector < CountableWrappedElementMatcher
9
+ def initialize(*args, **kw_args, &filter_block)
10
+ super
11
+ return unless (@args.size < 2) && @kw_args.keys.any?(String)
12
+
13
+ @args.push(@kw_args)
14
+ @kw_args = {}
15
+ end
16
+
17
+ def element_matches?(el)
18
+ el.assert_selector(*@args, **session_query_options, &@filter_block)
19
+ end
20
+
21
+ def element_does_not_match?(el)
22
+ el.assert_no_selector(*@args, **session_query_options, &@filter_block)
23
+ end
24
+
25
+ def description = "have #{query.description}"
26
+
27
+ def query
28
+ @query ||= Capybara::Queries::SelectorQuery.new(*session_query_args, **session_query_options, &@filter_block)
29
+ end
30
+ end
31
+
32
+ class HaveAllSelectors < WrappedElementMatcher
33
+ def element_matches?(el)
34
+ el.assert_all_of_selectors(*@args, **session_query_options, &@filter_block)
35
+ end
36
+
37
+ def does_not_match?(_actual)
38
+ raise ArgumentError, 'The have_all_selectors matcher does not support use with not_to/should_not'
39
+ end
40
+
41
+ def description = 'have all selectors'
42
+ end
43
+
44
+ class HaveNoSelectors < WrappedElementMatcher
45
+ def element_matches?(el)
46
+ el.assert_none_of_selectors(*@args, **session_query_options, &@filter_block)
47
+ end
48
+
49
+ def does_not_match?(_actual)
50
+ raise ArgumentError, 'The have_none_of_selectors matcher does not support use with not_to/should_not'
51
+ end
52
+
53
+ def description = 'have no selectors'
54
+ end
55
+
56
+ class HaveAnySelectors < WrappedElementMatcher
57
+ def element_matches?(el)
58
+ el.assert_any_of_selectors(*@args, **session_query_options, &@filter_block)
59
+ end
60
+
61
+ def does_not_match?(el)
62
+ el.assert_none_of_selectors(*@args, **session_query_options, &@filter_block)
63
+ end
64
+
65
+ def description = 'have any selectors'
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'capybara/rspec/matchers/base'
4
+
5
+ module Capybara
6
+ module RSpecMatchers
7
+ module Matchers
8
+ class HaveSibling < CountableWrappedElementMatcher
9
+ def element_matches?(el)
10
+ el.assert_sibling(*@args, **session_query_options, &@filter_block)
11
+ end
12
+
13
+ def element_does_not_match?(el)
14
+ el.assert_no_sibling(*@args, **session_query_options, &@filter_block)
15
+ end
16
+
17
+ def description
18
+ "have sibling #{query.description}"
19
+ end
20
+
21
+ def query
22
+ @query ||= Capybara::Queries::SiblingQuery.new(*session_query_args, **session_query_options, &@filter_block)
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'capybara/rspec/matchers/base'
4
+
5
+ module Capybara
6
+ module RSpecMatchers
7
+ module Matchers
8
+ class HaveText < CountableWrappedElementMatcher
9
+ def element_matches?(el)
10
+ el.assert_text(*@args, **@kw_args)
11
+ end
12
+
13
+ def element_does_not_match?(el)
14
+ el.assert_no_text(*@args, **@kw_args)
15
+ end
16
+
17
+ def description
18
+ "have text #{format(text)}"
19
+ end
20
+
21
+ def format(content)
22
+ content.inspect
23
+ end
24
+
25
+ private
26
+
27
+ def text
28
+ @args[0].is_a?(Symbol) ? @args[1] : @args[0]
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'capybara/rspec/matchers/base'
4
+
5
+ module Capybara
6
+ module RSpecMatchers
7
+ module Matchers
8
+ class HaveTitle < WrappedElementMatcher
9
+ def element_matches?(el)
10
+ el.assert_title(*@args, **@kw_args)
11
+ end
12
+
13
+ def element_does_not_match?(el)
14
+ el.assert_no_title(*@args, **@kw_args)
15
+ end
16
+
17
+ def description
18
+ "have title #{title.inspect}"
19
+ end
20
+
21
+ private
22
+
23
+ def title
24
+ @args.first
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'capybara/rspec/matchers/have_selector'
4
+
5
+ module Capybara
6
+ module RSpecMatchers
7
+ module Matchers
8
+ class MatchSelector < HaveSelector
9
+ def element_matches?(el)
10
+ el.assert_matches_selector(*@args, **session_query_options, &@filter_block)
11
+ end
12
+
13
+ def element_does_not_match?(el)
14
+ el.assert_not_matches_selector(*@args, **session_query_options, &@filter_block)
15
+ end
16
+
17
+ def description
18
+ "match #{query.description}"
19
+ end
20
+
21
+ def query
22
+ @query ||= Capybara::Queries::MatchQuery.new(*session_query_args, **session_query_options, &@filter_block)
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'capybara/rspec/matchers/base'
4
+
5
+ module Capybara
6
+ module RSpecMatchers
7
+ module Matchers
8
+ class MatchStyle < WrappedElementMatcher
9
+ def initialize(styles = nil, **kw_args, &filter_block)
10
+ styles, kw_args = kw_args, {} if styles.nil?
11
+ super(styles, **kw_args, &filter_block)
12
+ end
13
+
14
+ def element_matches?(el)
15
+ el.assert_matches_style(*@args, **@kw_args)
16
+ end
17
+
18
+ def does_not_match?(_actual)
19
+ raise ArgumentError, 'The match_style matcher does not support use with not_to/should_not'
20
+ end
21
+
22
+ def description
23
+ 'match style'
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+
30
+ module Capybara
31
+ module RSpecMatchers
32
+ module Matchers
33
+ ##
34
+ # @deprecated
35
+ class HaveStyle < MatchStyle
36
+ def initialize(*args, **kw_args, &filter_block)
37
+ warn 'HaveStyle matcher is deprecated, please use the MatchStyle matcher instead'
38
+ super
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end