capybara 3.0.0 → 3.36.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 -1
  3. data/History.md +777 -10
  4. data/License.txt +1 -1
  5. data/README.md +75 -58
  6. data/lib/capybara/config.rb +29 -10
  7. data/lib/capybara/cucumber.rb +1 -1
  8. data/lib/capybara/driver/base.rb +22 -4
  9. data/lib/capybara/driver/node.rb +34 -9
  10. data/lib/capybara/dsl.rb +14 -6
  11. data/lib/capybara/helpers.rb +52 -7
  12. data/lib/capybara/minitest/spec.rb +173 -84
  13. data/lib/capybara/minitest.rb +250 -144
  14. data/lib/capybara/node/actions.rb +248 -124
  15. data/lib/capybara/node/base.rb +34 -20
  16. data/lib/capybara/node/document.rb +14 -2
  17. data/lib/capybara/node/document_matchers.rb +13 -15
  18. data/lib/capybara/node/element.rb +339 -113
  19. data/lib/capybara/node/finders.rb +95 -82
  20. data/lib/capybara/node/matchers.rb +338 -157
  21. data/lib/capybara/node/simple.rb +54 -15
  22. data/lib/capybara/queries/active_element_query.rb +18 -0
  23. data/lib/capybara/queries/ancestor_query.rb +9 -10
  24. data/lib/capybara/queries/base_query.rb +25 -18
  25. data/lib/capybara/queries/current_path_query.rb +16 -6
  26. data/lib/capybara/queries/match_query.rb +11 -0
  27. data/lib/capybara/queries/selector_query.rb +600 -103
  28. data/lib/capybara/queries/sibling_query.rb +9 -7
  29. data/lib/capybara/queries/style_query.rb +45 -0
  30. data/lib/capybara/queries/text_query.rb +40 -22
  31. data/lib/capybara/queries/title_query.rb +2 -2
  32. data/lib/capybara/rack_test/browser.rb +47 -28
  33. data/lib/capybara/rack_test/driver.rb +12 -3
  34. data/lib/capybara/rack_test/errors.rb +6 -0
  35. data/lib/capybara/rack_test/form.rb +53 -50
  36. data/lib/capybara/rack_test/node.rb +114 -37
  37. data/lib/capybara/rails.rb +1 -1
  38. data/lib/capybara/registration_container.rb +44 -0
  39. data/lib/capybara/registrations/drivers.rb +42 -0
  40. data/lib/capybara/registrations/patches/puma_ssl.rb +29 -0
  41. data/lib/capybara/registrations/servers.rb +45 -0
  42. data/lib/capybara/result.rb +86 -52
  43. data/lib/capybara/rspec/features.rb +8 -10
  44. data/lib/capybara/rspec/matcher_proxies.rb +39 -18
  45. data/lib/capybara/rspec/matchers/base.rb +111 -0
  46. data/lib/capybara/rspec/matchers/become_closed.rb +33 -0
  47. data/lib/capybara/rspec/matchers/compound.rb +88 -0
  48. data/lib/capybara/rspec/matchers/count_sugar.rb +37 -0
  49. data/lib/capybara/rspec/matchers/have_ancestor.rb +28 -0
  50. data/lib/capybara/rspec/matchers/have_current_path.rb +29 -0
  51. data/lib/capybara/rspec/matchers/have_selector.rb +77 -0
  52. data/lib/capybara/rspec/matchers/have_sibling.rb +27 -0
  53. data/lib/capybara/rspec/matchers/have_text.rb +33 -0
  54. data/lib/capybara/rspec/matchers/have_title.rb +29 -0
  55. data/lib/capybara/rspec/matchers/match_selector.rb +27 -0
  56. data/lib/capybara/rspec/matchers/match_style.rb +43 -0
  57. data/lib/capybara/rspec/matchers/spatial_sugar.rb +39 -0
  58. data/lib/capybara/rspec/matchers.rb +138 -316
  59. data/lib/capybara/rspec.rb +3 -2
  60. data/lib/capybara/selector/builders/css_builder.rb +84 -0
  61. data/lib/capybara/selector/builders/xpath_builder.rb +71 -0
  62. data/lib/capybara/selector/css.rb +89 -12
  63. data/lib/capybara/selector/definition/button.rb +68 -0
  64. data/lib/capybara/selector/definition/checkbox.rb +26 -0
  65. data/lib/capybara/selector/definition/css.rb +10 -0
  66. data/lib/capybara/selector/definition/datalist_input.rb +35 -0
  67. data/lib/capybara/selector/definition/datalist_option.rb +25 -0
  68. data/lib/capybara/selector/definition/element.rb +28 -0
  69. data/lib/capybara/selector/definition/field.rb +40 -0
  70. data/lib/capybara/selector/definition/fieldset.rb +14 -0
  71. data/lib/capybara/selector/definition/file_field.rb +13 -0
  72. data/lib/capybara/selector/definition/fillable_field.rb +33 -0
  73. data/lib/capybara/selector/definition/frame.rb +17 -0
  74. data/lib/capybara/selector/definition/id.rb +6 -0
  75. data/lib/capybara/selector/definition/label.rb +62 -0
  76. data/lib/capybara/selector/definition/link.rb +54 -0
  77. data/lib/capybara/selector/definition/link_or_button.rb +16 -0
  78. data/lib/capybara/selector/definition/option.rb +27 -0
  79. data/lib/capybara/selector/definition/radio_button.rb +27 -0
  80. data/lib/capybara/selector/definition/select.rb +81 -0
  81. data/lib/capybara/selector/definition/table.rb +109 -0
  82. data/lib/capybara/selector/definition/table_row.rb +21 -0
  83. data/lib/capybara/selector/definition/xpath.rb +5 -0
  84. data/lib/capybara/selector/definition.rb +279 -0
  85. data/lib/capybara/selector/filter.rb +1 -0
  86. data/lib/capybara/selector/filter_set.rb +72 -27
  87. data/lib/capybara/selector/filters/base.rb +45 -2
  88. data/lib/capybara/selector/filters/expression_filter.rb +5 -6
  89. data/lib/capybara/selector/filters/locator_filter.rb +29 -0
  90. data/lib/capybara/selector/filters/node_filter.rb +18 -4
  91. data/lib/capybara/selector/regexp_disassembler.rb +214 -0
  92. data/lib/capybara/selector/selector.rb +85 -200
  93. data/lib/capybara/selector/xpath_extensions.rb +17 -0
  94. data/lib/capybara/selector.rb +226 -537
  95. data/lib/capybara/selenium/atoms/getAttribute.min.js +1 -0
  96. data/lib/capybara/selenium/atoms/isDisplayed.min.js +1 -0
  97. data/lib/capybara/selenium/atoms/src/getAttribute.js +161 -0
  98. data/lib/capybara/selenium/atoms/src/isDisplayed.js +454 -0
  99. data/lib/capybara/selenium/driver.rb +296 -238
  100. data/lib/capybara/selenium/driver_specializations/chrome_driver.rb +117 -0
  101. data/lib/capybara/selenium/driver_specializations/edge_driver.rb +124 -0
  102. data/lib/capybara/selenium/driver_specializations/firefox_driver.rb +89 -0
  103. data/lib/capybara/selenium/driver_specializations/internet_explorer_driver.rb +26 -0
  104. data/lib/capybara/selenium/driver_specializations/safari_driver.rb +24 -0
  105. data/lib/capybara/selenium/extensions/file_input_click_emulation.rb +34 -0
  106. data/lib/capybara/selenium/extensions/find.rb +110 -0
  107. data/lib/capybara/selenium/extensions/html5_drag.rb +228 -0
  108. data/lib/capybara/selenium/extensions/modifier_keys_stack.rb +28 -0
  109. data/lib/capybara/selenium/extensions/scroll.rb +76 -0
  110. data/lib/capybara/selenium/logger_suppressor.rb +40 -0
  111. data/lib/capybara/selenium/node.rb +436 -166
  112. data/lib/capybara/selenium/nodes/chrome_node.rb +137 -0
  113. data/lib/capybara/selenium/nodes/edge_node.rb +104 -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/action_pauser.rb +26 -0
  118. data/lib/capybara/selenium/patches/atoms.rb +18 -0
  119. data/lib/capybara/selenium/patches/is_displayed.rb +16 -0
  120. data/lib/capybara/selenium/patches/logs.rb +45 -0
  121. data/lib/capybara/selenium/patches/pause_duration_fix.rb +9 -0
  122. data/lib/capybara/selenium/patches/persistent_client.rb +20 -0
  123. data/lib/capybara/server/animation_disabler.rb +69 -0
  124. data/lib/capybara/server/checker.rb +44 -0
  125. data/lib/capybara/server/middleware.rb +71 -0
  126. data/lib/capybara/server.rb +58 -67
  127. data/lib/capybara/session/config.rb +38 -6
  128. data/lib/capybara/session/matchers.rb +26 -19
  129. data/lib/capybara/session.rb +258 -190
  130. data/lib/capybara/spec/public/jquery.js +5 -5
  131. data/lib/capybara/spec/public/offset.js +6 -0
  132. data/lib/capybara/spec/public/test.js +122 -8
  133. data/lib/capybara/spec/session/accept_alert_spec.rb +11 -11
  134. data/lib/capybara/spec/session/accept_confirm_spec.rb +3 -3
  135. data/lib/capybara/spec/session/accept_prompt_spec.rb +9 -10
  136. data/lib/capybara/spec/session/active_element_spec.rb +31 -0
  137. data/lib/capybara/spec/session/all_spec.rb +135 -42
  138. data/lib/capybara/spec/session/ancestor_spec.rb +24 -19
  139. data/lib/capybara/spec/session/assert_all_of_selectors_spec.rb +67 -38
  140. data/lib/capybara/spec/session/{assert_current_path.rb → assert_current_path_spec.rb} +20 -18
  141. data/lib/capybara/spec/session/assert_selector_spec.rb +143 -0
  142. data/lib/capybara/spec/session/assert_style_spec.rb +26 -0
  143. data/lib/capybara/spec/session/{assert_text.rb → assert_text_spec.rb} +62 -38
  144. data/lib/capybara/spec/session/{assert_title.rb → assert_title_spec.rb} +12 -12
  145. data/lib/capybara/spec/session/attach_file_spec.rb +120 -72
  146. data/lib/capybara/spec/session/body_spec.rb +11 -13
  147. data/lib/capybara/spec/session/check_spec.rb +111 -51
  148. data/lib/capybara/spec/session/choose_spec.rb +62 -30
  149. data/lib/capybara/spec/session/click_button_spec.rb +227 -161
  150. data/lib/capybara/spec/session/click_link_or_button_spec.rb +49 -30
  151. data/lib/capybara/spec/session/click_link_spec.rb +78 -55
  152. data/lib/capybara/spec/session/current_scope_spec.rb +7 -7
  153. data/lib/capybara/spec/session/current_url_spec.rb +44 -37
  154. data/lib/capybara/spec/session/dismiss_confirm_spec.rb +3 -3
  155. data/lib/capybara/spec/session/dismiss_prompt_spec.rb +2 -2
  156. data/lib/capybara/spec/session/element/{assert_match_selector.rb → assert_match_selector_spec.rb} +11 -9
  157. data/lib/capybara/spec/session/element/match_css_spec.rb +18 -10
  158. data/lib/capybara/spec/session/element/match_xpath_spec.rb +8 -6
  159. data/lib/capybara/spec/session/element/matches_selector_spec.rb +70 -56
  160. data/lib/capybara/spec/session/evaluate_async_script_spec.rb +7 -7
  161. data/lib/capybara/spec/session/evaluate_script_spec.rb +28 -8
  162. data/lib/capybara/spec/session/execute_script_spec.rb +8 -7
  163. data/lib/capybara/spec/session/fill_in_spec.rb +104 -44
  164. data/lib/capybara/spec/session/find_button_spec.rb +23 -23
  165. data/lib/capybara/spec/session/find_by_id_spec.rb +8 -8
  166. data/lib/capybara/spec/session/find_field_spec.rb +33 -31
  167. data/lib/capybara/spec/session/find_link_spec.rb +32 -14
  168. data/lib/capybara/spec/session/find_spec.rb +236 -141
  169. data/lib/capybara/spec/session/first_spec.rb +44 -43
  170. data/lib/capybara/spec/session/frame/frame_title_spec.rb +6 -6
  171. data/lib/capybara/spec/session/frame/frame_url_spec.rb +6 -6
  172. data/lib/capybara/spec/session/frame/switch_to_frame_spec.rb +32 -20
  173. data/lib/capybara/spec/session/frame/within_frame_spec.rb +44 -19
  174. data/lib/capybara/spec/session/go_back_spec.rb +1 -1
  175. data/lib/capybara/spec/session/go_forward_spec.rb +1 -1
  176. data/lib/capybara/spec/session/has_all_selectors_spec.rb +18 -18
  177. data/lib/capybara/spec/session/has_ancestor_spec.rb +46 -0
  178. data/lib/capybara/spec/session/has_any_selectors_spec.rb +29 -0
  179. data/lib/capybara/spec/session/has_button_spec.rb +92 -12
  180. data/lib/capybara/spec/session/has_css_spec.rb +271 -137
  181. data/lib/capybara/spec/session/has_current_path_spec.rb +48 -33
  182. data/lib/capybara/spec/session/has_field_spec.rb +137 -58
  183. data/lib/capybara/spec/session/has_link_spec.rb +30 -6
  184. data/lib/capybara/spec/session/has_none_selectors_spec.rb +26 -24
  185. data/lib/capybara/spec/session/has_select_spec.rb +75 -47
  186. data/lib/capybara/spec/session/has_selector_spec.rb +102 -69
  187. data/lib/capybara/spec/session/has_sibling_spec.rb +50 -0
  188. data/lib/capybara/spec/session/has_table_spec.rb +170 -4
  189. data/lib/capybara/spec/session/has_text_spec.rb +108 -52
  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.rb → 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 +35 -0
  195. data/lib/capybara/spec/session/node_spec.rb +871 -122
  196. data/lib/capybara/spec/session/node_wrapper_spec.rb +15 -12
  197. data/lib/capybara/spec/session/refresh_spec.rb +9 -7
  198. data/lib/capybara/spec/session/reset_session_spec.rb +52 -37
  199. data/lib/capybara/spec/session/{response_code.rb → 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 +5 -4
  202. data/lib/capybara/spec/session/save_page_spec.rb +41 -38
  203. data/lib/capybara/spec/session/save_screenshot_spec.rb +13 -11
  204. data/lib/capybara/spec/session/screenshot_spec.rb +2 -2
  205. data/lib/capybara/spec/session/scroll_spec.rb +117 -0
  206. data/lib/capybara/spec/session/select_spec.rb +102 -76
  207. data/lib/capybara/spec/session/selectors_spec.rb +51 -18
  208. data/lib/capybara/spec/session/sibling_spec.rb +9 -9
  209. data/lib/capybara/spec/session/text_spec.rb +26 -24
  210. data/lib/capybara/spec/session/title_spec.rb +8 -6
  211. data/lib/capybara/spec/session/uncheck_spec.rb +40 -21
  212. data/lib/capybara/spec/session/unselect_spec.rb +37 -37
  213. data/lib/capybara/spec/session/visit_spec.rb +59 -53
  214. data/lib/capybara/spec/session/window/become_closed_spec.rb +22 -19
  215. data/lib/capybara/spec/session/window/current_window_spec.rb +4 -3
  216. data/lib/capybara/spec/session/window/open_new_window_spec.rb +4 -3
  217. data/lib/capybara/spec/session/window/switch_to_window_spec.rb +25 -21
  218. data/lib/capybara/spec/session/window/window_opened_by_spec.rb +10 -5
  219. data/lib/capybara/spec/session/window/window_spec.rb +88 -54
  220. data/lib/capybara/spec/session/window/windows_spec.rb +10 -7
  221. data/lib/capybara/spec/session/window/within_window_spec.rb +17 -16
  222. data/lib/capybara/spec/session/within_spec.rb +69 -44
  223. data/lib/capybara/spec/spec_helper.rb +41 -53
  224. data/lib/capybara/spec/test_app.rb +79 -40
  225. data/lib/capybara/spec/views/animated.erb +49 -0
  226. data/lib/capybara/spec/views/form.erb +134 -42
  227. data/lib/capybara/spec/views/frame_child.erb +4 -3
  228. data/lib/capybara/spec/views/frame_one.erb +2 -1
  229. data/lib/capybara/spec/views/frame_parent.erb +1 -1
  230. data/lib/capybara/spec/views/frame_two.erb +1 -1
  231. data/lib/capybara/spec/views/initial_alert.erb +2 -1
  232. data/lib/capybara/spec/views/layout.erb +10 -0
  233. data/lib/capybara/spec/views/obscured.erb +47 -0
  234. data/lib/capybara/spec/views/offset.erb +33 -0
  235. data/lib/capybara/spec/views/path.erb +2 -2
  236. data/lib/capybara/spec/views/popup_one.erb +1 -1
  237. data/lib/capybara/spec/views/popup_two.erb +1 -1
  238. data/lib/capybara/spec/views/react.erb +45 -0
  239. data/lib/capybara/spec/views/scroll.erb +21 -0
  240. data/lib/capybara/spec/views/spatial.erb +31 -0
  241. data/lib/capybara/spec/views/tables.erb +68 -1
  242. data/lib/capybara/spec/views/with_animation.erb +81 -0
  243. data/lib/capybara/spec/views/with_base_tag.erb +2 -2
  244. data/lib/capybara/spec/views/with_dragula.erb +24 -0
  245. data/lib/capybara/spec/views/with_fixed_header_footer.erb +2 -1
  246. data/lib/capybara/spec/views/with_hover.erb +3 -2
  247. data/lib/capybara/spec/views/with_hover1.erb +10 -0
  248. data/lib/capybara/spec/views/with_html.erb +43 -10
  249. data/lib/capybara/spec/views/with_html5_svg.erb +20 -0
  250. data/lib/capybara/spec/views/with_jquery_animation.erb +24 -0
  251. data/lib/capybara/spec/views/with_js.erb +30 -5
  252. data/lib/capybara/spec/views/with_jstree.erb +26 -0
  253. data/lib/capybara/spec/views/with_namespace.erb +21 -0
  254. data/lib/capybara/spec/views/with_scope_other.erb +6 -0
  255. data/lib/capybara/spec/views/with_slow_unload.erb +2 -1
  256. data/lib/capybara/spec/views/with_sortable_js.erb +21 -0
  257. data/lib/capybara/spec/views/with_unload_alert.erb +1 -0
  258. data/lib/capybara/spec/views/with_windows.erb +1 -1
  259. data/lib/capybara/spec/views/within_frames.erb +1 -1
  260. data/lib/capybara/version.rb +1 -1
  261. data/lib/capybara/window.rb +31 -25
  262. data/lib/capybara.rb +120 -100
  263. data/spec/basic_node_spec.rb +59 -34
  264. data/spec/capybara_spec.rb +54 -52
  265. data/spec/css_builder_spec.rb +101 -0
  266. data/spec/css_splitter_spec.rb +38 -0
  267. data/spec/dsl_spec.rb +80 -53
  268. data/spec/filter_set_spec.rb +24 -7
  269. data/spec/fixtures/certificate.pem +25 -0
  270. data/spec/fixtures/key.pem +27 -0
  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 +38 -5
  274. data/spec/minitest_spec_spec.rb +88 -62
  275. data/spec/per_session_config_spec.rb +5 -5
  276. data/spec/rack_test_spec.rb +169 -115
  277. data/spec/regexp_dissassembler_spec.rb +250 -0
  278. data/spec/result_spec.rb +86 -33
  279. data/spec/rspec/features_spec.rb +26 -23
  280. data/spec/rspec/scenarios_spec.rb +8 -4
  281. data/spec/rspec/shared_spec_matchers.rb +393 -363
  282. data/spec/rspec/views_spec.rb +4 -3
  283. data/spec/rspec_matchers_spec.rb +10 -10
  284. data/spec/rspec_spec.rb +109 -85
  285. data/spec/sauce_spec_chrome.rb +43 -0
  286. data/spec/selector_spec.rb +391 -61
  287. data/spec/selenium_spec_chrome.rb +180 -41
  288. data/spec/selenium_spec_chrome_remote.rb +101 -0
  289. data/spec/selenium_spec_edge.rb +28 -8
  290. data/spec/selenium_spec_firefox.rb +211 -0
  291. data/spec/selenium_spec_firefox_remote.rb +80 -0
  292. data/spec/selenium_spec_ie.rb +127 -11
  293. data/spec/selenium_spec_safari.rb +156 -0
  294. data/spec/server_spec.rb +177 -78
  295. data/spec/session_spec.rb +52 -16
  296. data/spec/shared_selenium_node.rb +79 -0
  297. data/spec/shared_selenium_session.rb +455 -123
  298. data/spec/spec_helper.rb +91 -2
  299. data/spec/xpath_builder_spec.rb +93 -0
  300. metadata +343 -42
  301. data/.yard/templates_custom/default/class/html/selectors.erb +0 -38
  302. data/.yard/templates_custom/default/class/html/setup.rb +0 -17
  303. data/.yard/yard_extensions.rb +0 -78
  304. data/lib/capybara/rspec/compound.rb +0 -90
  305. data/lib/capybara/spec/session/assert_selector.rb +0 -149
  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 -143
@@ -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
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Capybara
4
+ module RSpecMatchers
5
+ module SpatialSugar
6
+ def above(el)
7
+ options[:above] = el
8
+ self
9
+ end
10
+
11
+ def below(el)
12
+ options[:below] = el
13
+ self
14
+ end
15
+
16
+ def left_of(el)
17
+ options[:left_of] = el
18
+ self
19
+ end
20
+
21
+ def right_of(el)
22
+ options[:right_of] = el
23
+ self
24
+ end
25
+
26
+ def near(el)
27
+ options[:near] = el
28
+ self
29
+ end
30
+
31
+ private
32
+
33
+ def options
34
+ # (@args.last.is_a?(Hash) ? @args : @args.push({})).last
35
+ @kw_args
36
+ end
37
+ end
38
+ end
39
+ end
@@ -1,380 +1,202 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'capybara/rspec/matchers/have_selector'
4
+ require 'capybara/rspec/matchers/have_ancestor'
5
+ require 'capybara/rspec/matchers/have_sibling'
6
+ require 'capybara/rspec/matchers/match_selector'
7
+ require 'capybara/rspec/matchers/have_current_path'
8
+ require 'capybara/rspec/matchers/match_style'
9
+ require 'capybara/rspec/matchers/have_text'
10
+ require 'capybara/rspec/matchers/have_title'
11
+ require 'capybara/rspec/matchers/become_closed'
12
+
3
13
  module Capybara
4
14
  module RSpecMatchers
5
- class Matcher
6
- if defined?(::RSpec::Expectations::Version)
7
- require 'capybara/rspec/compound'
8
- include ::Capybara::RSpecMatchers::Compound
9
- end
10
-
11
- attr_reader :failure_message, :failure_message_when_negated
12
-
13
- def wrap(actual)
14
- actual = actual.to_capybara_node if actual.respond_to?(:to_capybara_node)
15
- @context_el = if actual.respond_to?(:has_selector?)
16
- actual
17
- else
18
- Capybara.string(actual.to_s)
19
- end
20
- end
21
-
22
- private
23
-
24
- def wrap_matches?(actual)
25
- yield(wrap(actual))
26
- rescue Capybara::ExpectationNotMet => e
27
- @failure_message = e.message
28
- return false
29
- end
30
-
31
- def wrap_does_not_match?(actual)
32
- yield(wrap(actual))
33
- rescue Capybara::ExpectationNotMet => e
34
- @failure_message_when_negated = e.message
35
- return false
36
- end
37
-
38
- def session_query_args
39
- if @args.last.is_a? Hash
40
- @args.last[:session_options] = session_options
41
- else
42
- @args.push(session_options: session_options)
43
- end
44
- @args
45
- end
46
-
47
- def session_options
48
- @context_el ||= nil
49
- if @context_el.respond_to? :session_options
50
- @context_el.session_options
51
- elsif @context_el.respond_to? :current_scope
52
- @context_el.current_scope.session_options
53
- else
54
- Capybara.session_options
55
- end
56
- end
15
+ # RSpec matcher for whether the element(s) matching a given selector exist.
16
+ #
17
+ # @see Capybara::Node::Matchers#assert_selector
18
+ def have_selector(*args, **kw_args, &optional_filter_block)
19
+ Matchers::HaveSelector.new(*args, **kw_args, &optional_filter_block)
57
20
  end
58
21
 
59
- class HaveSelector < Matcher
60
- def initialize(*args, &filter_block)
61
- @args = args
62
- @filter_block = filter_block
63
- end
64
-
65
- def matches?(actual)
66
- wrap_matches?(actual) { |el| el.assert_selector(*@args, &@filter_block) }
67
- end
68
-
69
- def does_not_match?(actual)
70
- wrap_does_not_match?(actual) { |el| el.assert_no_selector(*@args, &@filter_block) }
71
- end
72
-
73
- def description
74
- "have #{query.description}"
75
- end
76
-
77
- def query
78
- @query ||= Capybara::Queries::SelectorQuery.new(*session_query_args, &@filter_block)
79
- end
22
+ # RSpec matcher for whether the element(s) matching a group of selectors exist.
23
+ #
24
+ # @see Capybara::Node::Matchers#assert_all_of_selectors
25
+ def have_all_of_selectors(*args, **kw_args, &optional_filter_block)
26
+ Matchers::HaveAllSelectors.new(*args, **kw_args, &optional_filter_block)
80
27
  end
81
28
 
82
- class HaveAllSelectors < Matcher
83
- def initialize(*args, &filter_block)
84
- @args = args
85
- @filter_block = filter_block
86
- end
87
-
88
- def matches?(actual)
89
- wrap_matches?(actual) { |el| el.assert_all_of_selectors(*@args, &@filter_block) }
90
- end
91
-
92
- def does_not_match?(_actual)
93
- raise ArgumentError, "The have_all_selectors matcher does not support use with not_to/should_not"
94
- end
95
-
96
- def description
97
- "have all selectors"
98
- end
29
+ # RSpec matcher for whether no element(s) matching a group of selectors exist.
30
+ #
31
+ # @see Capybara::Node::Matchers#assert_none_of_selectors
32
+ def have_none_of_selectors(*args, **kw_args, &optional_filter_block)
33
+ Matchers::HaveNoSelectors.new(*args, **kw_args, &optional_filter_block)
99
34
  end
100
35
 
101
- class HaveNoSelectors < Matcher
102
- def initialize(*args, &filter_block)
103
- @args = args
104
- @filter_block = filter_block
105
- end
106
-
107
- def matches?(actual)
108
- wrap_matches?(actual) { |el| el.assert_none_of_selectors(*@args, &@filter_block) }
109
- end
110
-
111
- def does_not_match?(_actual)
112
- raise ArgumentError, "The have_none_of_selectors matcher does not support use with not_to/should_not"
113
- end
114
-
115
- def description
116
- "have no selectors"
117
- end
36
+ # RSpec matcher for whether the element(s) matching any of a group of selectors exist.
37
+ #
38
+ # @see Capybara::Node::Matchers#assert_any_of_selectors
39
+ def have_any_of_selectors(*args, **kw_args, &optional_filter_block)
40
+ Matchers::HaveAnySelectors.new(*args, **kw_args, &optional_filter_block)
118
41
  end
119
42
 
120
- class MatchSelector < HaveSelector
121
- def matches?(actual)
122
- wrap_matches?(actual) { |el| el.assert_matches_selector(*@args, &@filter_block) }
123
- end
124
-
125
- def does_not_match?(actual)
126
- wrap_does_not_match?(actual) { |el| el.assert_not_matches_selector(*@args, &@filter_block) }
127
- end
128
-
129
- def description
130
- "match #{query.description}"
131
- end
132
-
133
- def query
134
- @query ||= Capybara::Queries::MatchQuery.new(*session_query_args, &@filter_block)
135
- end
43
+ # RSpec matcher for whether the current element matches a given selector.
44
+ #
45
+ # @see Capybara::Node::Matchers#assert_matches_selector
46
+ def match_selector(*args, **kw_args, &optional_filter_block)
47
+ Matchers::MatchSelector.new(*args, **kw_args, &optional_filter_block)
136
48
  end
137
49
 
138
- class HaveText < Matcher
139
- def initialize(*args)
140
- @args = args.dup
141
- @content = args[0].is_a?(Symbol) ? args[1] : args[0]
50
+ %i[css xpath].each do |selector|
51
+ define_method "have_#{selector}" do |expr, **options, &optional_filter_block|
52
+ Matchers::HaveSelector.new(selector, expr, **options, &optional_filter_block)
142
53
  end
143
54
 
144
- def matches?(actual)
145
- wrap_matches?(actual) { |el| el.assert_text(*@args) }
146
- end
147
-
148
- def does_not_match?(actual)
149
- wrap_does_not_match?(actual) { |el| el.assert_no_text(*@args) }
150
- end
151
-
152
- def description
153
- "text #{format(@content)}"
154
- end
155
-
156
- def format(content)
157
- content.inspect
55
+ define_method "match_#{selector}" do |expr, **options, &optional_filter_block|
56
+ Matchers::MatchSelector.new(selector, expr, **options, &optional_filter_block)
158
57
  end
159
58
  end
160
59
 
161
- class HaveTitle < Matcher
162
- def initialize(*args)
163
- @args = args
60
+ # @!method have_xpath(xpath, **options, &optional_filter_block)
61
+ # RSpec matcher for whether elements(s) matching a given xpath selector exist.
62
+ #
63
+ # @see Capybara::Node::Matchers#has_xpath?
164
64
 
165
- # are set just for backwards compatability
166
- @title = args.first
167
- end
65
+ # @!method have_css(css, **options, &optional_filter_block)
66
+ # RSpec matcher for whether elements(s) matching a given css selector exist
67
+ #
68
+ # @see Capybara::Node::Matchers#has_css?
168
69
 
169
- def matches?(actual)
170
- wrap_matches?(actual) { |el| el.assert_title(*@args) }
171
- end
70
+ # @!method match_xpath(xpath, **options, &optional_filter_block)
71
+ # RSpec matcher for whether the current element matches a given xpath selector.
72
+ #
73
+ # @see Capybara::Node::Matchers#matches_xpath?
172
74
 
173
- def does_not_match?(actual)
174
- wrap_does_not_match?(actual) { |el| el.assert_no_title(*@args) }
175
- end
75
+ # @!method match_css(css, **options, &optional_filter_block)
76
+ # RSpec matcher for whether the current element matches a given css selector.
77
+ #
78
+ # @see Capybara::Node::Matchers#matches_css?
176
79
 
177
- def description
178
- "have title #{@title.inspect}"
80
+ %i[link button field select table].each do |selector|
81
+ define_method "have_#{selector}" do |locator = nil, **options, &optional_filter_block|
82
+ Matchers::HaveSelector.new(selector, locator, **options, &optional_filter_block)
179
83
  end
180
84
  end
181
85
 
182
- class HaveCurrentPath < Matcher
183
- def initialize(*args)
184
- @args = args
185
- @current_path = args.first
186
- end
187
-
188
- def matches?(actual)
189
- wrap_matches?(actual) { |el| el.assert_current_path(*@args) }
190
- end
191
-
192
- def does_not_match?(actual)
193
- wrap_does_not_match?(actual) { |el| el.assert_no_current_path(*@args) }
194
- end
195
-
196
- def description
197
- "have current path #{@current_path.inspect}"
198
- end
199
- end
200
-
201
- class NegatedMatcher
202
- def initialize(matcher)
203
- @matcher = matcher
204
- end
205
-
206
- def matches?(actual)
207
- @matcher.does_not_match?(actual)
208
- end
209
-
210
- def does_not_match?(actual)
211
- @matcher.matches?(actual)
212
- end
86
+ # @!method have_link(locator = nil, **options, &optional_filter_block)
87
+ # RSpec matcher for links.
88
+ #
89
+ # @see Capybara::Node::Matchers#has_link?
213
90
 
214
- def description
215
- "not #{@matcher.description}"
216
- end
91
+ # @!method have_button(locator = nil, **options, &optional_filter_block)
92
+ # RSpec matcher for buttons.
93
+ #
94
+ # @see Capybara::Node::Matchers#has_button?
217
95
 
218
- def failure_message
219
- @matcher.failure_message_when_negated
220
- end
96
+ # @!method have_field(locator = nil, **options, &optional_filter_block)
97
+ # RSpec matcher for form fields.
98
+ #
99
+ # @see Capybara::Node::Matchers#has_field?
221
100
 
222
- def failure_message_when_negated
223
- @matcher.failure_message
224
- end
225
- end
101
+ # @!method have_select(locator = nil, **options, &optional_filter_block)
102
+ # RSpec matcher for select elements.
103
+ #
104
+ # @see Capybara::Node::Matchers#has_select?
226
105
 
227
- class BecomeClosed
228
- def initialize(options)
229
- @options = options
230
- end
106
+ # @!method have_table(locator = nil, **options, &optional_filter_block)
107
+ # RSpec matcher for table elements.
108
+ #
109
+ # @see Capybara::Node::Matchers#has_table?
231
110
 
232
- def matches?(window)
233
- @window = window
234
- @wait_time = Capybara::Queries::BaseQuery.wait(@options, window.session.config.default_max_wait_time)
235
- start_time = Capybara::Helpers.monotonic_time
236
- while window.exists?
237
- return false if (Capybara::Helpers.monotonic_time - start_time) > @wait_time
238
- sleep 0.05
239
- end
240
- true
111
+ %i[checked unchecked].each do |state|
112
+ define_method "have_#{state}_field" do |locator = nil, **options, &optional_filter_block|
113
+ Matchers::HaveSelector.new(:field, locator, **options.merge(state => true), &optional_filter_block)
241
114
  end
242
-
243
- def failure_message
244
- "expected #{@window.inspect} to become closed after #{@wait_time} seconds"
245
- end
246
-
247
- def failure_message_when_negated
248
- "expected #{@window.inspect} not to become closed after #{@wait_time} seconds"
249
- end
250
- end
251
-
252
- # RSpec matcher for whether the element(s) matching a given selector exist
253
- # See {Capybara::Node::Matcher#assert_selector}
254
- def have_selector(*args, &optional_filter_block)
255
- HaveSelector.new(*args, &optional_filter_block)
256
- end
257
-
258
- # RSpec matcher for whether the element(s) matching a group of selectors exist
259
- # See {Capybara::Node::Matcher#assert_all_of_selectors}
260
- def have_all_of_selectors(*args, &optional_filter_block)
261
- HaveAllSelectors.new(*args, &optional_filter_block)
262
- end
263
-
264
- # RSpec matcher for whether no element(s) matching a group of selectors exist
265
- # See {Capybara::Node::Matcher#assert_none_of_selectors}
266
- def have_none_of_selectors(*args, &optional_filter_block)
267
- HaveNoSelectors.new(*args, &optional_filter_block)
268
115
  end
269
116
 
270
- # RSpec matcher for whether the current element matches a given selector
271
- # See {Capybara::Node::Matchers#assert_matches_selector}
272
- def match_selector(*args, &optional_filter_block)
273
- MatchSelector.new(*args, &optional_filter_block)
274
- end
117
+ # @!method have_checked_field(locator = nil, **options, &optional_filter_block)
118
+ # RSpec matcher for checked fields.
119
+ #
120
+ # @see Capybara::Node::Matchers#has_checked_field?
275
121
 
276
- # RSpec matcher for whether elements(s) matching a given xpath selector exist
277
- # See {Capybara::Node::Matchers#has_xpath?}
278
- def have_xpath(xpath, **options, &optional_filter_block)
279
- HaveSelector.new(:xpath, xpath, options, &optional_filter_block)
280
- end
281
-
282
- # RSpec matcher for whether the current element matches a given xpath selector
283
- def match_xpath(xpath, **options, &optional_filter_block)
284
- MatchSelector.new(:xpath, xpath, options, &optional_filter_block)
285
- end
122
+ # @!method have_unchecked_field(locator = nil, **options, &optional_filter_block)
123
+ # RSpec matcher for unchecked fields.
124
+ #
125
+ # @see Capybara::Node::Matchers#has_unchecked_field?
286
126
 
287
- # RSpec matcher for whether elements(s) matching a given css selector exist
288
- # See {Capybara::Node::Matchers#has_css?}
289
- def have_css(css, **options, &optional_filter_block)
290
- HaveSelector.new(:css, css, options, &optional_filter_block)
291
- end
292
-
293
- # RSpec matcher for whether the current element matches a given css selector
294
- def match_css(css, **options, &optional_filter_block)
295
- MatchSelector.new(:css, css, options, &optional_filter_block)
296
- end
297
-
298
- # RSpec matcher for text content
299
- # See {Capybara::SessionMatchers#assert_text}
300
- def have_text(*args)
301
- HaveText.new(*args)
127
+ # RSpec matcher for text content.
128
+ #
129
+ # @see Capybara::Node::Matchers#assert_text
130
+ def have_text(text_or_type, *args, **options)
131
+ Matchers::HaveText.new(text_or_type, *args, **options)
302
132
  end
303
133
  alias_method :have_content, :have_text
304
134
 
305
135
  def have_title(title, **options)
306
- HaveTitle.new(title, options)
307
- end
308
-
309
- # RSpec matcher for the current path
310
- # See {Capybara::SessionMatchers#assert_current_path}
311
- def have_current_path(path, **options)
312
- HaveCurrentPath.new(path, options)
136
+ Matchers::HaveTitle.new(title, **options)
313
137
  end
314
138
 
315
- # RSpec matcher for links
316
- # See {Capybara::Node::Matchers#has_link?}
317
- def have_link(locator = nil, **options, &optional_filter_block)
318
- HaveSelector.new(:link, locator, options, &optional_filter_block)
139
+ # RSpec matcher for the current path.
140
+ #
141
+ # @see Capybara::SessionMatchers#assert_current_path
142
+ def have_current_path(path, **options, &optional_filter_block)
143
+ Matchers::HaveCurrentPath.new(path, **options, &optional_filter_block)
319
144
  end
320
145
 
321
- # RSpec matcher for buttons
322
- # See {Capybara::Node::Matchers#has_button?}
323
- def have_button(locator = nil, **options, &optional_filter_block)
324
- HaveSelector.new(:button, locator, options, &optional_filter_block)
146
+ # RSpec matcher for element style.
147
+ #
148
+ # @see Capybara::Node::Matchers#matches_style?
149
+ def match_style(styles = nil, **options)
150
+ styles, options = options, {} if styles.nil?
151
+ Matchers::MatchStyle.new(styles, **options)
325
152
  end
326
153
 
327
- # RSpec matcher for links
328
- # See {Capybara::Node::Matchers#has_field?}
329
- def have_field(locator = nil, **options, &optional_filter_block)
330
- HaveSelector.new(:field, locator, options, &optional_filter_block)
331
- end
332
-
333
- # RSpec matcher for checked fields
334
- # See {Capybara::Node::Matchers#has_checked_field?}
335
- def have_checked_field(locator = nil, **options, &optional_filter_block)
336
- HaveSelector.new(:field, locator, options.merge(checked: true), &optional_filter_block)
337
- end
338
-
339
- # RSpec matcher for unchecked fields
340
- # See {Capybara::Node::Matchers#has_unchecked_field?}
341
- def have_unchecked_field(locator = nil, **options, &optional_filter_block)
342
- HaveSelector.new(:field, locator, options.merge(unchecked: true), &optional_filter_block)
343
- end
344
-
345
- # RSpec matcher for select elements
346
- # See {Capybara::Node::Matchers#has_select?}
347
- def have_select(locator = nil, **options, &optional_filter_block)
348
- HaveSelector.new(:select, locator, options, &optional_filter_block)
349
- end
350
-
351
- # RSpec matcher for table elements
352
- # See {Capybara::Node::Matchers#has_table?}
353
- def have_table(locator = nil, **options, &optional_filter_block)
354
- HaveSelector.new(:table, locator, options, &optional_filter_block)
154
+ ##
155
+ # @deprecated
156
+ #
157
+ def have_style(styles = nil, **options)
158
+ Capybara::Helpers.warn "DEPRECATED: have_style is deprecated, please use match_style : #{Capybara::Helpers.filter_backtrace(caller)}"
159
+ match_style(styles, **options)
355
160
  end
356
161
 
357
- %w[selector css xpath text title current_path link button field checked_field unchecked_field select table].each do |matcher_type|
358
- define_method "have_no_#{matcher_type}" do |*args, &optional_filter_block|
359
- NegatedMatcher.new(send("have_#{matcher_type}", *args, &optional_filter_block))
162
+ %w[selector css xpath text title current_path link button
163
+ field checked_field unchecked_field select table
164
+ sibling ancestor].each do |matcher_type|
165
+ define_method "have_no_#{matcher_type}" do |*args, **kw_args, &optional_filter_block|
166
+ Matchers::NegatedMatcher.new(send("have_#{matcher_type}", *args, **kw_args, &optional_filter_block))
360
167
  end
361
168
  end
362
169
  alias_method :have_no_content, :have_no_text
363
170
 
364
171
  %w[selector css xpath].each do |matcher_type|
365
- define_method "not_match_#{matcher_type}" do |*args, &optional_filter_block|
366
- NegatedMatcher.new(send("match_#{matcher_type}", *args, &optional_filter_block))
172
+ define_method "not_match_#{matcher_type}" do |*args, **kw_args, &optional_filter_block|
173
+ Matchers::NegatedMatcher.new(send("match_#{matcher_type}", *args, **kw_args, &optional_filter_block))
367
174
  end
368
175
  end
369
176
 
177
+ # RSpec matcher for whether sibling element(s) matching a given selector exist.
178
+ #
179
+ # @see Capybara::Node::Matchers#assert_sibling
180
+ def have_sibling(*args, **kw_args, &optional_filter_block)
181
+ Matchers::HaveSibling.new(*args, **kw_args, &optional_filter_block)
182
+ end
183
+
184
+ # RSpec matcher for whether ancestor element(s) matching a given selector exist.
185
+ #
186
+ # @see Capybara::Node::Matchers#assert_ancestor
187
+ def have_ancestor(*args, **kw_args, &optional_filter_block)
188
+ Matchers::HaveAncestor.new(*args, **kw_args, &optional_filter_block)
189
+ end
190
+
370
191
  ##
371
192
  # Wait for window to become closed.
193
+ #
372
194
  # @example
373
195
  # expect(window).to become_closed(wait: 0.8)
374
- # @param options [Hash] optional param
375
- # @option options [Numeric] :wait (Capybara.default_max_wait_time) Maximum wait time
196
+ #
197
+ # @option options [Numeric] :wait Maximum wait time. Defaults to {Capybara.configure default_max_wait_time}
376
198
  def become_closed(**options)
377
- BecomeClosed.new(options)
199
+ Matchers::BecomeClosed.new(options)
378
200
  end
379
201
  end
380
202
  end
@@ -9,6 +9,8 @@ require 'capybara/rspec/matcher_proxies'
9
9
  RSpec.configure do |config|
10
10
  config.include Capybara::DSL, type: :feature
11
11
  config.include Capybara::RSpecMatchers, type: :feature
12
+ config.include Capybara::DSL, type: :system
13
+ config.include Capybara::RSpecMatchers, type: :system
12
14
  config.include Capybara::RSpecMatchers, type: :view
13
15
 
14
16
  # The before and after blocks must run instantaneously, because Capybara
@@ -20,9 +22,8 @@ RSpec.configure do |config|
20
22
  end
21
23
  end
22
24
 
23
- config.before do
25
+ config.before do |example|
24
26
  if self.class.include?(Capybara::DSL)
25
- example = RSpec.current_example
26
27
  Capybara.current_driver = Capybara.javascript_driver if example.metadata[:js]
27
28
  Capybara.current_driver = example.metadata[:driver] if example.metadata[:driver]
28
29
  end