capybara 3.0.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 (312) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +1 -1
  3. data/History.md +891 -12
  4. data/License.txt +1 -1
  5. data/README.md +257 -84
  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 +38 -9
  10. data/lib/capybara/dsl.rb +9 -7
  11. data/lib/capybara/helpers.rb +57 -8
  12. data/lib/capybara/minitest/spec.rb +185 -84
  13. data/lib/capybara/minitest.rb +264 -145
  14. data/lib/capybara/node/actions.rb +248 -124
  15. data/lib/capybara/node/base.rb +35 -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 +350 -113
  19. data/lib/capybara/node/finders.rb +104 -82
  20. data/lib/capybara/node/matchers.rb +363 -157
  21. data/lib/capybara/node/simple.rb +54 -15
  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 +9 -10
  25. data/lib/capybara/queries/base_query.rb +25 -18
  26. data/lib/capybara/queries/current_path_query.rb +16 -6
  27. data/lib/capybara/queries/match_query.rb +11 -0
  28. data/lib/capybara/queries/selector_query.rb +617 -104
  29. data/lib/capybara/queries/sibling_query.rb +9 -7
  30. data/lib/capybara/queries/style_query.rb +45 -0
  31. data/lib/capybara/queries/text_query.rb +40 -22
  32. data/lib/capybara/queries/title_query.rb +2 -2
  33. data/lib/capybara/rack_test/browser.rb +106 -31
  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 +74 -49
  37. data/lib/capybara/rack_test/node.rb +120 -47
  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 +87 -53
  44. data/lib/capybara/rspec/features.rb +8 -10
  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 +142 -315
  60. data/lib/capybara/rspec.rb +3 -2
  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 +85 -8
  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 +72 -28
  88. data/lib/capybara/selector/filters/base.rb +45 -2
  89. data/lib/capybara/selector/filters/expression_filter.rb +5 -6
  90. data/lib/capybara/selector/filters/locator_filter.rb +29 -0
  91. data/lib/capybara/selector/filters/node_filter.rb +18 -4
  92. data/lib/capybara/selector/regexp_disassembler.rb +211 -0
  93. data/lib/capybara/selector/selector.rb +89 -200
  94. data/lib/capybara/selector/xpath_extensions.rb +17 -0
  95. data/lib/capybara/selector.rb +474 -534
  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 +270 -245
  101. data/lib/capybara/selenium/driver_specializations/chrome_driver.rb +117 -0
  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 +460 -170
  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 +80 -0
  123. data/lib/capybara/server/checker.rb +44 -0
  124. data/lib/capybara/server/middleware.rb +71 -0
  125. data/lib/capybara/server.rb +58 -67
  126. data/lib/capybara/session/config.rb +40 -6
  127. data/lib/capybara/session/matchers.rb +26 -19
  128. data/lib/capybara/session.rb +252 -194
  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 +126 -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 +135 -44
  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.rb → assert_current_path_spec.rb} +20 -18
  140. data/lib/capybara/spec/session/assert_selector_spec.rb +143 -0
  141. data/lib/capybara/spec/session/assert_style_spec.rb +26 -0
  142. data/lib/capybara/spec/session/{assert_text.rb → assert_text_spec.rb} +76 -52
  143. data/lib/capybara/spec/session/{assert_title.rb → 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 +11 -13
  146. data/lib/capybara/spec/session/check_spec.rb +112 -51
  147. data/lib/capybara/spec/session/choose_spec.rb +62 -30
  148. data/lib/capybara/spec/session/click_button_spec.rb +227 -161
  149. data/lib/capybara/spec/session/click_link_or_button_spec.rb +49 -30
  150. data/lib/capybara/spec/session/click_link_spec.rb +89 -55
  151. data/lib/capybara/spec/session/current_scope_spec.rb +8 -8
  152. data/lib/capybara/spec/session/current_url_spec.rb +44 -37
  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.rb → assert_match_selector_spec.rb} +11 -9
  156. data/lib/capybara/spec/session/element/match_css_spec.rb +18 -10
  157. data/lib/capybara/spec/session/element/match_xpath_spec.rb +8 -6
  158. data/lib/capybara/spec/session/element/matches_selector_spec.rb +70 -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 +110 -44
  163. data/lib/capybara/spec/session/find_button_spec.rb +23 -23
  164. data/lib/capybara/spec/session/find_by_id_spec.rb +8 -8
  165. data/lib/capybara/spec/session/find_field_spec.rb +33 -31
  166. data/lib/capybara/spec/session/find_link_spec.rb +42 -14
  167. data/lib/capybara/spec/session/find_spec.rb +251 -142
  168. data/lib/capybara/spec/session/first_spec.rb +45 -44
  169. data/lib/capybara/spec/session/frame/frame_title_spec.rb +6 -6
  170. data/lib/capybara/spec/session/frame/frame_url_spec.rb +6 -6
  171. data/lib/capybara/spec/session/frame/switch_to_frame_spec.rb +32 -20
  172. data/lib/capybara/spec/session/frame/within_frame_spec.rb +46 -19
  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 +98 -12
  179. data/lib/capybara/spec/session/has_css_spec.rb +271 -137
  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 +46 -6
  184. data/lib/capybara/spec/session/has_none_selectors_spec.rb +33 -31
  185. data/lib/capybara/spec/session/has_select_spec.rb +84 -50
  186. data/lib/capybara/spec/session/has_selector_spec.rb +117 -69
  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.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 +37 -0
  195. data/lib/capybara/spec/session/node_spec.rb +958 -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 +65 -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 +119 -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 +41 -22
  212. data/lib/capybara/spec/session/unselect_spec.rb +37 -37
  213. data/lib/capybara/spec/session/visit_spec.rb +79 -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 +11 -8
  221. data/lib/capybara/spec/session/window/within_window_spec.rb +17 -16
  222. data/lib/capybara/spec/session/within_spec.rb +82 -44
  223. data/lib/capybara/spec/spec_helper.rb +46 -52
  224. data/lib/capybara/spec/test_app.rb +148 -41
  225. data/lib/capybara/spec/views/animated.erb +49 -0
  226. data/lib/capybara/spec/views/form.erb +156 -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 +46 -11
  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.erb +2 -2
  255. data/lib/capybara/spec/views/with_scope_other.erb +6 -0
  256. data/lib/capybara/spec/views/with_shadow.erb +31 -0
  257. data/lib/capybara/spec/views/with_slow_unload.erb +2 -1
  258. data/lib/capybara/spec/views/with_sortable_js.erb +21 -0
  259. data/lib/capybara/spec/views/with_unload_alert.erb +1 -0
  260. data/lib/capybara/spec/views/with_windows.erb +1 -1
  261. data/lib/capybara/spec/views/within_frames.erb +1 -1
  262. data/lib/capybara/version.rb +1 -1
  263. data/lib/capybara/window.rb +32 -26
  264. data/lib/capybara.rb +128 -104
  265. data/spec/basic_node_spec.rb +59 -34
  266. data/spec/capybara_spec.rb +65 -51
  267. data/spec/counter_spec.rb +35 -0
  268. data/spec/css_builder_spec.rb +101 -0
  269. data/spec/css_splitter_spec.rb +38 -0
  270. data/spec/dsl_spec.rb +84 -55
  271. data/spec/filter_set_spec.rb +24 -7
  272. data/spec/fixtures/certificate.pem +25 -0
  273. data/spec/fixtures/key.pem +27 -0
  274. data/spec/fixtures/selenium_driver_rspec_failure.rb +5 -5
  275. data/spec/fixtures/selenium_driver_rspec_success.rb +5 -5
  276. data/spec/minitest_spec.rb +49 -5
  277. data/spec/minitest_spec_spec.rb +92 -62
  278. data/spec/per_session_config_spec.rb +6 -6
  279. data/spec/rack_test_spec.rb +183 -115
  280. data/spec/regexp_dissassembler_spec.rb +250 -0
  281. data/spec/result_spec.rb +99 -39
  282. data/spec/rspec/features_spec.rb +28 -25
  283. data/spec/rspec/scenarios_spec.rb +10 -6
  284. data/spec/rspec/shared_spec_matchers.rb +418 -364
  285. data/spec/rspec/views_spec.rb +4 -3
  286. data/spec/rspec_matchers_spec.rb +35 -10
  287. data/spec/rspec_spec.rb +109 -85
  288. data/spec/sauce_spec_chrome.rb +43 -0
  289. data/spec/selector_spec.rb +392 -62
  290. data/spec/selenium_spec_chrome.rb +183 -41
  291. data/spec/selenium_spec_chrome_remote.rb +96 -0
  292. data/spec/selenium_spec_edge.rb +41 -8
  293. data/spec/selenium_spec_firefox.rb +228 -0
  294. data/spec/selenium_spec_firefox_remote.rb +94 -0
  295. data/spec/selenium_spec_ie.rb +129 -11
  296. data/spec/selenium_spec_safari.rb +162 -0
  297. data/spec/server_spec.rb +192 -81
  298. data/spec/session_spec.rb +52 -16
  299. data/spec/shared_selenium_node.rb +79 -0
  300. data/spec/shared_selenium_session.rb +460 -123
  301. data/spec/spec_helper.rb +124 -2
  302. data/spec/whitespace_normalizer_spec.rb +54 -0
  303. data/spec/xpath_builder_spec.rb +93 -0
  304. metadata +344 -45
  305. data/.yard/templates_custom/default/class/html/selectors.erb +0 -38
  306. data/.yard/templates_custom/default/class/html/setup.rb +0 -17
  307. data/.yard/yard_extensions.rb +0 -78
  308. data/lib/capybara/rspec/compound.rb +0 -90
  309. data/lib/capybara/spec/session/assert_selector.rb +0 -149
  310. data/lib/capybara/spec/session/source_spec.rb +0 -0
  311. data/lib/capybara/spec/views/with_title.erb +0 -5
  312. data/spec/selenium_spec_marionette.rb +0 -143
@@ -15,11 +15,11 @@ class Capybara::Driver::Base
15
15
  raise NotImplementedError
16
16
  end
17
17
 
18
- def find_xpath(query)
18
+ def find_xpath(query, **options)
19
19
  raise NotImplementedError
20
20
  end
21
21
 
22
- def find_css(query)
22
+ def find_css(query, **options)
23
23
  raise NotImplementedError
24
24
  end
25
25
 
@@ -59,6 +59,14 @@ class Capybara::Driver::Base
59
59
  raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#status_code'
60
60
  end
61
61
 
62
+ def send_keys(*)
63
+ raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#send_keys'
64
+ end
65
+
66
+ def active_element
67
+ raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#active_element'
68
+ end
69
+
62
70
  ##
63
71
  #
64
72
  # @param frame [Capybara::Node::Element, :parent, :top] The iframe element to switch to
@@ -90,7 +98,11 @@ class Capybara::Driver::Base
90
98
  end
91
99
 
92
100
  def maximize_window(handle)
93
- raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#maximize_current_window'
101
+ raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#maximize_window'
102
+ end
103
+
104
+ def fullscreen_window(handle)
105
+ raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#fullscreen_window'
94
106
  end
95
107
 
96
108
  def close_window(handle)
@@ -155,6 +167,12 @@ class Capybara::Driver::Base
155
167
  end
156
168
 
157
169
  def session_options
158
- (@session && @session.config) || Capybara.session_options
170
+ session&.config || Capybara.session_options
171
+ end
172
+
173
+ private
174
+
175
+ def session
176
+ @session ||= nil
159
177
  end
160
178
  end
@@ -3,11 +3,12 @@
3
3
  module Capybara
4
4
  module Driver
5
5
  class Node
6
- attr_reader :driver, :native
6
+ attr_reader :driver, :native, :initial_cache
7
7
 
8
- def initialize(driver, native)
8
+ def initialize(driver, native, initial_cache = {})
9
9
  @driver = driver
10
10
  @native = native
11
+ @initial_cache = initial_cache
11
12
  end
12
13
 
13
14
  def all_text
@@ -26,8 +27,12 @@ module Capybara
26
27
  raise NotImplementedError
27
28
  end
28
29
 
29
- # @param value String or Array. Array is only allowed if node has 'multiple' attribute
30
- # @param options [Hash{}] Driver specific options for how to set a value on a node
30
+ def style(styles)
31
+ raise NotImplementedError
32
+ end
33
+
34
+ # @param value [String, Array] Array is only allowed if node has 'multiple' attribute
35
+ # @param options [Hash] Driver specific options for how to set a value on a node
31
36
  def set(value, **options)
32
37
  raise NotImplementedError
33
38
  end
@@ -40,15 +45,15 @@ module Capybara
40
45
  raise NotImplementedError
41
46
  end
42
47
 
43
- def click(keys = [], options = {})
48
+ def click(keys = [], **options)
44
49
  raise NotImplementedError
45
50
  end
46
51
 
47
- def right_click(keys = [], options = {})
52
+ def right_click(keys = [], **options)
48
53
  raise NotImplementedError
49
54
  end
50
55
 
51
- def double_click(keys = [], options = {})
56
+ def double_click(keys = [], **options)
52
57
  raise NotImplementedError
53
58
  end
54
59
 
@@ -60,7 +65,19 @@ module Capybara
60
65
  raise NotImplementedError
61
66
  end
62
67
 
63
- def drag_to(element)
68
+ def drag_to(element, **options)
69
+ raise NotImplementedError
70
+ end
71
+
72
+ def drop(*args)
73
+ raise NotImplementedError
74
+ end
75
+
76
+ def scroll_by(x, y)
77
+ raise NotImplementedError
78
+ end
79
+
80
+ def scroll_to(element, alignment, position = nil)
64
81
  raise NotImplementedError
65
82
  end
66
83
 
@@ -72,6 +89,10 @@ module Capybara
72
89
  raise NotImplementedError
73
90
  end
74
91
 
92
+ def obscured?
93
+ raise NotImplementedError
94
+ end
95
+
75
96
  def checked?
76
97
  raise NotImplementedError
77
98
  end
@@ -92,6 +113,10 @@ module Capybara
92
113
  !!self[:multiple]
93
114
  end
94
115
 
116
+ def rect
117
+ raise NotSupportedByDriverError, 'Capybara::Driver::Node#rect'
118
+ end
119
+
95
120
  def path
96
121
  raise NotSupportedByDriverError, 'Capybara::Driver::Node#path'
97
122
  end
@@ -100,6 +125,10 @@ module Capybara
100
125
  raise NotSupportedByDriverError, 'Capybara::Driver::Node#trigger'
101
126
  end
102
127
 
128
+ def shadow_root
129
+ raise NotSupportedByDriverError, 'Capybara::Driver::Node#shadow_root'
130
+ end
131
+
103
132
  def inspect
104
133
  %(#<#{self.class} tag="#{tag_name}" path="#{path}">)
105
134
  rescue NotSupportedByDriverError
@@ -107,7 +136,7 @@ module Capybara
107
136
  end
108
137
 
109
138
  def ==(other)
110
- raise NotSupportedByDriverError, 'Capybara::Driver::Node#=='
139
+ eql?(other) || (other.respond_to?(:native) && native == other.native)
111
140
  end
112
141
  end
113
142
  end
data/lib/capybara/dsl.rb CHANGED
@@ -5,12 +5,12 @@ require 'capybara'
5
5
  module Capybara
6
6
  module DSL
7
7
  def self.included(base)
8
- warn "including Capybara::DSL in the global scope is not recommended!" if base == Object
8
+ warn 'including Capybara::DSL in the global scope is not recommended!' if base == Object
9
9
  super
10
10
  end
11
11
 
12
12
  def self.extended(base)
13
- warn "extending the main object with Capybara::DSL is not recommended!" if base == TOPLEVEL_BINDING.eval("self")
13
+ warn 'extending the main object with Capybara::DSL is not recommended!' if base == TOPLEVEL_BINDING.eval('self')
14
14
  super
15
15
  end
16
16
 
@@ -18,8 +18,8 @@ module Capybara
18
18
  #
19
19
  # Shortcut to working in a different session.
20
20
  #
21
- def using_session(name, &block)
22
- Capybara.using_session(name, &block)
21
+ def using_session(name_or_session, &block)
22
+ Capybara.using_session(name_or_session, &block)
23
23
  end
24
24
 
25
25
  # Shortcut to using a different wait time.
@@ -47,9 +47,11 @@ module Capybara
47
47
  end
48
48
 
49
49
  Session::DSL_METHODS.each do |method|
50
- define_method method do |*args, &block|
51
- page.send method, *args, &block
52
- end
50
+ class_eval <<~METHOD, __FILE__, __LINE__ + 1
51
+ def #{method}(...)
52
+ page.method("#{method}").call(...)
53
+ end
54
+ METHOD
53
55
  end
54
56
  end
55
57
 
@@ -3,7 +3,7 @@
3
3
  module Capybara
4
4
  # @api private
5
5
  module Helpers
6
- extend self
6
+ module_function
7
7
 
8
8
  ##
9
9
  # @deprecated
@@ -15,7 +15,7 @@ module Capybara
15
15
  # @return [String] Normalized text
16
16
  #
17
17
  def normalize_whitespace(text)
18
- warn "DEPRECATED: Capybara::Helpers::normalize_whitespace is deprecated, please update your driver"
18
+ Capybara::Helpers.warn 'DEPRECATED: Capybara::Helpers::normalize_whitespace is deprecated, please update your driver'
19
19
  text.to_s.gsub(/[[:space:]]+/, ' ').strip
20
20
  end
21
21
 
@@ -33,7 +33,7 @@ module Capybara
33
33
  return text if text.is_a?(Regexp)
34
34
 
35
35
  escaped = Regexp.escape(text)
36
- escaped = escaped.gsub("\\ ", "[[:blank:]]") if all_whitespace
36
+ escaped = escaped.gsub('\\ ', '[[:blank:]]') if all_whitespace
37
37
  escaped = "\\A#{escaped}\\z" if exact
38
38
  Regexp.new(escaped, options)
39
39
  end
@@ -41,16 +41,17 @@ module Capybara
41
41
  ##
42
42
  #
43
43
  # Injects a `<base>` tag into the given HTML code, pointing to
44
- # `Capybara.asset_host`.
44
+ # {Capybara.configure asset_host}.
45
45
  #
46
46
  # @param [String] html HTML code to inject into
47
47
  # @param [URL] host (Capybara.asset_host) The host from which assets should be loaded
48
48
  # @return [String] The modified HTML code
49
49
  #
50
50
  def inject_asset_host(html, host: Capybara.asset_host)
51
- if host && Nokogiri::HTML(html).css("base").empty?
52
- match = html.match(/<head[^<]*?>/)
53
- return html.clone.insert match.end(0), "<base href='#{host}' />" if match
51
+ if host && Nokogiri::HTML(html).css('base').empty?
52
+ html.match(/<head[^<]*?>/) do |m|
53
+ return html.clone.insert m.end(0), "<base href='#{host}' />"
54
+ end
54
55
  end
55
56
  html
56
57
  end
@@ -69,10 +70,58 @@ module Capybara
69
70
  count == 1 ? singular : plural
70
71
  end
71
72
 
72
- if defined?(Process::CLOCK_MONOTONIC)
73
+ def filter_backtrace(trace)
74
+ return 'No backtrace' unless trace
75
+
76
+ filter = %r{lib/capybara/|lib/rspec/|lib/minitest/|delegate.rb}
77
+ new_trace = trace.take_while { |line| line !~ filter }
78
+ new_trace = trace.grep_v(filter) if new_trace.empty?
79
+ new_trace = trace.dup if new_trace.empty?
80
+
81
+ new_trace.first.split(':in ', 2).first
82
+ end
83
+
84
+ def warn(message, uplevel: 1)
85
+ Kernel.warn(message, uplevel: uplevel)
86
+ end
87
+
88
+ if defined?(Process::CLOCK_MONOTONIC_RAW)
89
+ def monotonic_time; Process.clock_gettime Process::CLOCK_MONOTONIC_RAW; end
90
+ elsif defined?(Process::CLOCK_MONOTONIC_PRECISE)
91
+ def monotonic_time; Process.clock_gettime Process::CLOCK_MONOTONIC_PRECISE; end
92
+ elsif defined?(Process::CLOCK_MONOTONIC)
73
93
  def monotonic_time; Process.clock_gettime Process::CLOCK_MONOTONIC; end
74
94
  else
75
95
  def monotonic_time; Time.now.to_f; end
76
96
  end
97
+
98
+ def timer(expire_in:)
99
+ Timer.new(expire_in)
100
+ end
101
+
102
+ class Timer
103
+ def initialize(expire_in)
104
+ @start = current
105
+ @expire_in = expire_in
106
+ end
107
+
108
+ def expired?
109
+ if stalled?
110
+ raise Capybara::FrozenInTime, 'Time appears to be frozen. Capybara does not work with libraries which freeze time, consider using time travelling instead'
111
+ end
112
+
113
+ current - @start >= @expire_in
114
+ end
115
+
116
+ def stalled?
117
+ @start == current
118
+ end
119
+
120
+ private
121
+
122
+ def current
123
+ Capybara::Helpers.monotonic_time
124
+ end
125
+ end
77
126
  end
78
127
  end
@@ -1,178 +1,279 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'minitest/spec'
2
4
 
3
5
  module Capybara
4
6
  module Minitest
5
7
  module Expectations
6
- %w[text content title current_path].each do |assertion|
7
- infect_an_assertion "assert_#{assertion}", "must_have_#{assertion}", :reverse
8
- infect_an_assertion "refute_#{assertion}", "wont_have_#{assertion}", :reverse
9
- end
8
+ ##
9
+ # Expectation that there is an ancestor
10
+ #
11
+ # @!method must_have_ancestor
12
+ # See {Capybara::Node::Matchers#has_ancestor?}
10
13
 
11
- # rubocop:disable Style/MultilineBlockChain
12
- (%w[selector xpath css link button field select table checked_field unchecked_field].flat_map do |assertion|
13
- [%W[assert_#{assertion} must_have_#{assertion}],
14
- %W[refute_#{assertion} wont_have_#{assertion}]]
15
- end + [%w[assert_all_of_selectors must_have_all_of_selectors],
16
- %w[assert_none_of_selectors must_have_none_of_selectors]] +
17
- %w[selector xpath css].flat_map do |assertion|
18
- [%W[assert_matches_#{assertion} must_match_#{assertion}],
19
- %W[refute_matches_#{assertion} wont_match_#{assertion}]]
20
- end).each do |(meth, new_name)|
21
- class_eval <<-ASSERTION, __FILE__, __LINE__ + 1
22
- def #{new_name} *args, &block
23
- ::Minitest::Expectation.new(self, ::Minitest::Spec.current).#{new_name}(*args, &block)
24
- end
25
- ASSERTION
14
+ ##
15
+ # Expectation that there is button
16
+ #
17
+ # @!method must_have_button
18
+ # See {Capybara::Node::Matchers#has_button?}
26
19
 
27
- ::Minitest::Expectation.class_eval <<-ASSERTION, __FILE__, __LINE__ + 1
28
- def #{new_name} *args, &block
29
- ctx.#{meth}(target, *args, &block)
30
- end
31
- ASSERTION
32
- end
33
- # rubocop:enable Style/MultilineBlockChain
20
+ ##
21
+ # Expectation that there is no button
22
+ #
23
+ # @!method wont_have_button
24
+ # See {Capybara::Node::Matchers#has_no_button?}
34
25
 
35
26
  ##
36
- # Expectation that there is xpath
27
+ # Expectation that there is checked_field
37
28
  #
38
- # @!method must_have_xpath
39
- # see Capybara::Node::Matchers#has_xpath?
29
+ # @!method must_have_checked_field
30
+ # See {Capybara::Node::Matchers#has_checked_field?}
40
31
 
41
32
  ##
42
- # Expectation that there is no xpath
33
+ # Expectation that there is no checked_field
43
34
  #
44
- # @!method wont_have_xpath
45
- # see Capybara::Node::Matchers#has_no_xpath?
35
+ # @!method wont_have_checked_field
36
+ # See {Capybara::Node::Matchers#has_no_checked_field?}
46
37
 
47
38
  ##
48
- # Expectation that there is css
39
+ # Expectation that there is unchecked_field
49
40
  #
50
- # @!method must_have_css
51
- # see Capybara::Node::Matchers#has_css?
41
+ # @!method must_have_unchecked_field
42
+ # See {Capybara::Node::Matchers#has_unchecked_field?}
52
43
 
53
44
  ##
54
- # Expectation that there is no css
45
+ # Expectation that there is no unchecked_field
55
46
  #
56
- # @!method wont_have_css
57
- # see Capybara::Node::Matchers#has_no_css?
47
+ # @!method wont_have_unchecked_field
48
+ # See {Capybara::Node::Matchers#has_no_unchecked_field?}
58
49
 
59
50
  ##
60
- # Expectation that there is link
51
+ # Expectation that page content does match
61
52
  #
62
- # @!method must_have_link
63
- # see {Capybara::Node::Matchers#has_link?}
53
+ # @!method must_have_content
54
+ # See {Capybara::Node::Matchers#has_content?}
64
55
 
65
56
  ##
66
- # Expectation that there is no link
57
+ # Expectation that page content does not match
67
58
  #
68
- # @!method wont_have_link
69
- # see {Capybara::Node::Matchers#has_no_link?}
59
+ # @!method wont_have_content
60
+ # See {Capybara::Node::Matchers#has_no_content?}
70
61
 
71
62
  ##
72
- # Expectation that there is button
63
+ # Expectation that there is css
73
64
  #
74
- # @!method must_have_button
75
- # see {Capybara::Node::Matchers#has_button?}
65
+ # @!method must_have_css
66
+ # See {Capybara::Node::Matchers#has_css?}
76
67
 
77
68
  ##
78
- # Expectation that there is no button
69
+ # Expectation that there is no css
79
70
  #
80
- # @!method wont_have_button
81
- # see {Capybara::Node::Matchers#has_no_button?}
71
+ # @!method wont_have_css
72
+ # See {Capybara::Node::Matchers#has_no_css?}
73
+
74
+ ##
75
+ # Expectation that current path matches
76
+ #
77
+ # @!method must_have_current_path
78
+ # See {Capybara::SessionMatchers#has_current_path?}
79
+
80
+ ##
81
+ # Expectation that current page does not match
82
+ #
83
+ # @!method wont_have_current_path
84
+ # See {Capybara::SessionMatchers#has_no_current_path?}
82
85
 
83
86
  ##
84
87
  # Expectation that there is field
85
88
  #
86
89
  # @!method must_have_field
87
- # see {Capybara::Node::Matchers#has_field?}
90
+ # See {Capybara::Node::Matchers#has_field?}
88
91
 
89
92
  ##
90
93
  # Expectation that there is no field
91
94
  #
92
95
  # @!method wont_have_field
93
- # see {Capybara::Node::Matchers#has_no_field?}
96
+ # See {Capybara::Node::Matchers#has_no_field?}
94
97
 
95
98
  ##
96
- # Expectation that there is checked_field
99
+ # Expectation that there is element
97
100
  #
98
- # @!method must_have_checked_field
99
- # see {Capybara::Node::Matchers#has_checked_field?}
101
+ # @!method must_have_element
102
+ # See {Capybara::Node::Matchers#has_element?}
100
103
 
101
104
  ##
102
- # Expectation that there is no checked_field
105
+ # Expectation that there is no element
103
106
  #
104
- # @!method wont_have_chceked_field
107
+ # @!method wont_have_element
108
+ # See {Capybara::Node::Matchers#has_no_element?}
105
109
 
106
110
  ##
107
- # Expectation that there is unchecked_field
111
+ # Expectation that there is link
108
112
  #
109
- # @!method must_have_unchecked_field
110
- # see {Capybara::Node::Matchers#has_unchecked_field?}
113
+ # @!method must_have_link
114
+ # See {Capybara::Node::Matchers#has_link?}
111
115
 
112
116
  ##
113
- # Expectation that there is no unchecked_field
117
+ # Expectation that there is no link
114
118
  #
115
- # @!method wont_have_unchceked_field
119
+ # @!method wont_have_link
120
+ # See {Capybara::Node::Matchers#has_no_link?}
121
+
122
+ ##
123
+ # Expectation that page text does match
124
+ #
125
+ # @!method must_have_text
126
+ # See {Capybara::Node::Matchers#has_text?}
127
+
128
+ ##
129
+ # Expectation that page text does not match
130
+ #
131
+ # @!method wont_have_text
132
+ # See {Capybara::Node::Matchers#has_no_text?}
133
+
134
+ ##
135
+ # Expectation that page title does match
136
+ #
137
+ # @!method must_have_title
138
+ # See {Capybara::Node::DocumentMatchers#has_title?}
139
+
140
+ ##
141
+ # Expectation that page title does not match
142
+ #
143
+ # @!method wont_have_title
144
+ # See {Capybara::Node::DocumentMatchers#has_no_title?}
116
145
 
117
146
  ##
118
147
  # Expectation that there is select
119
148
  #
120
149
  # @!method must_have_select
121
- # see {Capybara::Node::Matchers#has_select?}
150
+ # See {Capybara::Node::Matchers#has_select?}
122
151
 
123
152
  ##
124
153
  # Expectation that there is no select
125
154
  #
126
155
  # @!method wont_have_select
127
- # see {Capybara::Node::Matchers#has_no_select?}
156
+ # See {Capybara::Node::Matchers#has_no_select?}
157
+
158
+ ##
159
+ # Expectation that there is a selector
160
+ #
161
+ # @!method must_have_selector
162
+ # See {Capybara::Node::Matchers#has_selector?}
163
+
164
+ ##
165
+ # Expectation that there is no selector
166
+ #
167
+ # @!method wont_have_selector
168
+ # See {Capybara::Node::Matchers#has_no_selector?}
169
+
170
+ ##
171
+ # Expectation that all of the provided selectors are present
172
+ #
173
+ # @!method must_have_all_of_selectors
174
+ # See {Capybara::Node::Matchers#assert_all_of_selectors}
175
+
176
+ ##
177
+ # Expectation that none of the provided selectors are present
178
+ #
179
+ # @!method must_have_none_of_selectors
180
+ # See {Capybara::Node::Matchers#assert_none_of_selectors}
181
+
182
+ ##
183
+ # Expectation that any of the provided selectors are present
184
+ #
185
+ # @!method must_have_any_of_selectors
186
+ # See {Capybara::Node::Matchers#assert_any_of_selectors}
187
+
188
+ ##
189
+ # Expectation that there is a sibling
190
+ #
191
+ # @!method must_have_sibling
192
+ # See {Capybara::Node::Matchers#has_sibling?}
193
+
194
+ ##
195
+ # Expectation that element has style
196
+ #
197
+ # @!method must_match_style
198
+ # See {Capybara::Node::Matchers#matches_style?}
128
199
 
129
200
  ##
130
201
  # Expectation that there is table
131
202
  #
132
203
  # @!method must_have_table
133
- # see {Capybara::Node::Matchers#has_table?}
204
+ # See {Capybara::Node::Matchers#has_table?}
134
205
 
135
206
  ##
136
207
  # Expectation that there is no table
137
208
  #
138
209
  # @!method wont_have_table
139
- # see {Capybara::Node::Matchers#has_no_table?}
210
+ # See {Capybara::Node::Matchers#has_no_table?}
140
211
 
141
212
  ##
142
- # Expectation that page title does match
213
+ # Expectation that there is xpath
143
214
  #
144
- # @!method must_have_title
145
- # see {Capybara::Node::DocumentMatchers#assert_title}
215
+ # @!method must_have_xpath
216
+ # See {Capybara::Node::Matchers#has_xpath?}
146
217
 
147
218
  ##
148
- # Expectation that page title does not match
219
+ # Expectation that there is no xpath
149
220
  #
150
- # @!method wont_have_title
151
- # see {Capybara::Node::DocumentMatchers#assert_no_title}
221
+ # @!method wont_have_xpath
222
+ # See {Capybara::Node::Matchers#has_no_xpath?}
152
223
 
153
- ##
154
- # Expectation that current path matches
155
- #
156
- # @!method must_have_current_path
157
- # see {Capybara::SessionMatchers#assert_current_path}
224
+ # This currently doesn't work for Ruby 2.8 due to Minitest not forwarding keyword args separately
225
+ # %w[text content title current_path].each do |assertion|
226
+ # infect_an_assertion "assert_#{assertion}", "must_have_#{assertion}", :reverse
227
+ # infect_an_assertion "refute_#{assertion}", "wont_have_#{assertion}", :reverse
228
+ # end
229
+
230
+ # rubocop:disable Style/MultilineBlockChain
231
+ (%w[text content title current_path
232
+ selector xpath css link button field select table checked_field unchecked_field
233
+ ancestor sibling].flat_map do |assertion|
234
+ [%W[assert_#{assertion} must_have_#{assertion}],
235
+ %W[refute_#{assertion} wont_have_#{assertion}]]
236
+ end + [%w[assert_all_of_selectors must_have_all_of_selectors],
237
+ %w[assert_none_of_selectors must_have_none_of_selectors],
238
+ %w[assert_any_of_selectors must_have_any_of_selectors],
239
+ %w[assert_matches_style must_match_style]] +
240
+ %w[selector xpath css].flat_map do |assertion|
241
+ [%W[assert_matches_#{assertion} must_match_#{assertion}],
242
+ %W[refute_matches_#{assertion} wont_match_#{assertion}]]
243
+ end).each do |(meth, new_name)|
244
+ class_eval <<-ASSERTION, __FILE__, __LINE__ + 1
245
+ def #{new_name}(...)
246
+ ::Minitest::Expectation.new(self, ::Minitest::Spec.current).#{new_name}(...)
247
+ end
248
+ ASSERTION
249
+
250
+ ::Minitest::Expectation.class_eval <<-ASSERTION, __FILE__, __LINE__ + 1
251
+ def #{new_name}(...)
252
+ raise "Calling ##{new_name} outside of test." unless ctx
253
+ ctx.#{meth}(target, ...)
254
+ end
255
+ ASSERTION
256
+ end
257
+ # rubocop:enable Style/MultilineBlockChain
158
258
 
159
259
  ##
160
- # Expectation that current page does not match
161
- #
162
- # @!method wont_have_current_path
163
- # see {Capybara::SessionMatchers#assert_no_current_path}
260
+ # @deprecated
261
+ def must_have_style(...)
262
+ warn 'must_have_style is deprecated, please use must_match_style'
263
+ must_match_style(...)
264
+ end
164
265
  end
165
266
  end
166
267
  end
167
268
 
168
269
  class Capybara::Session
169
- include Capybara::Minitest::Expectations unless ENV["MT_NO_EXPECTATIONS"]
270
+ include Capybara::Minitest::Expectations unless ENV['MT_NO_EXPECTATIONS']
170
271
  end
171
272
 
172
273
  class Capybara::Node::Base
173
- include Capybara::Minitest::Expectations unless ENV["MT_NO_EXPECTATIONS"]
274
+ include Capybara::Minitest::Expectations unless ENV['MT_NO_EXPECTATIONS']
174
275
  end
175
276
 
176
277
  class Capybara::Node::Simple
177
- include Capybara::Minitest::Expectations unless ENV["MT_NO_EXPECTATIONS"]
278
+ include Capybara::Minitest::Expectations unless ENV['MT_NO_EXPECTATIONS']
178
279
  end