capybara 2.18.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 (316) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +1 -1
  3. data/History.md +945 -12
  4. data/License.txt +1 -1
  5. data/README.md +264 -90
  6. data/lib/capybara/config.rb +29 -57
  7. data/lib/capybara/cucumber.rb +2 -3
  8. data/lib/capybara/driver/base.rb +35 -18
  9. data/lib/capybara/driver/node.rb +40 -10
  10. data/lib/capybara/dsl.rb +10 -7
  11. data/lib/capybara/helpers.rb +70 -31
  12. data/lib/capybara/minitest/spec.rb +185 -83
  13. data/lib/capybara/minitest.rb +232 -112
  14. data/lib/capybara/node/actions.rb +274 -171
  15. data/lib/capybara/node/base.rb +42 -34
  16. data/lib/capybara/node/document.rb +15 -3
  17. data/lib/capybara/node/document_matchers.rb +19 -21
  18. data/lib/capybara/node/element.rb +362 -135
  19. data/lib/capybara/node/finders.rb +151 -137
  20. data/lib/capybara/node/matchers.rb +394 -209
  21. data/lib/capybara/node/simple.rb +59 -26
  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 +12 -9
  25. data/lib/capybara/queries/base_query.rb +39 -28
  26. data/lib/capybara/queries/current_path_query.rb +21 -27
  27. data/lib/capybara/queries/match_query.rb +14 -7
  28. data/lib/capybara/queries/selector_query.rb +659 -149
  29. data/lib/capybara/queries/sibling_query.rb +11 -9
  30. data/lib/capybara/queries/style_query.rb +45 -0
  31. data/lib/capybara/queries/text_query.rb +56 -38
  32. data/lib/capybara/queries/title_query.rb +8 -11
  33. data/lib/capybara/rack_test/browser.rb +114 -42
  34. data/lib/capybara/rack_test/css_handlers.rb +6 -4
  35. data/lib/capybara/rack_test/driver.rb +22 -17
  36. data/lib/capybara/rack_test/errors.rb +6 -0
  37. data/lib/capybara/rack_test/form.rb +93 -58
  38. data/lib/capybara/rack_test/node.rb +184 -81
  39. data/lib/capybara/rails.rb +3 -7
  40. data/lib/capybara/registration_container.rb +41 -0
  41. data/lib/capybara/registrations/drivers.rb +42 -0
  42. data/lib/capybara/registrations/patches/puma_ssl.rb +29 -0
  43. data/lib/capybara/registrations/servers.rb +66 -0
  44. data/lib/capybara/result.rb +97 -63
  45. data/lib/capybara/rspec/features.rb +17 -50
  46. data/lib/capybara/rspec/matcher_proxies.rb +52 -15
  47. data/lib/capybara/rspec/matchers/base.rb +113 -0
  48. data/lib/capybara/rspec/matchers/become_closed.rb +33 -0
  49. data/lib/capybara/rspec/matchers/compound.rb +88 -0
  50. data/lib/capybara/rspec/matchers/count_sugar.rb +37 -0
  51. data/lib/capybara/rspec/matchers/have_ancestor.rb +28 -0
  52. data/lib/capybara/rspec/matchers/have_current_path.rb +29 -0
  53. data/lib/capybara/rspec/matchers/have_selector.rb +69 -0
  54. data/lib/capybara/rspec/matchers/have_sibling.rb +27 -0
  55. data/lib/capybara/rspec/matchers/have_text.rb +33 -0
  56. data/lib/capybara/rspec/matchers/have_title.rb +29 -0
  57. data/lib/capybara/rspec/matchers/match_selector.rb +27 -0
  58. data/lib/capybara/rspec/matchers/match_style.rb +43 -0
  59. data/lib/capybara/rspec/matchers/spatial_sugar.rb +39 -0
  60. data/lib/capybara/rspec/matchers.rb +146 -310
  61. data/lib/capybara/rspec.rb +7 -11
  62. data/lib/capybara/selector/builders/css_builder.rb +84 -0
  63. data/lib/capybara/selector/builders/xpath_builder.rb +71 -0
  64. data/lib/capybara/selector/css.rb +85 -13
  65. data/lib/capybara/selector/definition/button.rb +68 -0
  66. data/lib/capybara/selector/definition/checkbox.rb +26 -0
  67. data/lib/capybara/selector/definition/css.rb +10 -0
  68. data/lib/capybara/selector/definition/datalist_input.rb +35 -0
  69. data/lib/capybara/selector/definition/datalist_option.rb +25 -0
  70. data/lib/capybara/selector/definition/element.rb +28 -0
  71. data/lib/capybara/selector/definition/field.rb +40 -0
  72. data/lib/capybara/selector/definition/fieldset.rb +14 -0
  73. data/lib/capybara/selector/definition/file_field.rb +13 -0
  74. data/lib/capybara/selector/definition/fillable_field.rb +33 -0
  75. data/lib/capybara/selector/definition/frame.rb +17 -0
  76. data/lib/capybara/selector/definition/id.rb +6 -0
  77. data/lib/capybara/selector/definition/label.rb +62 -0
  78. data/lib/capybara/selector/definition/link.rb +55 -0
  79. data/lib/capybara/selector/definition/link_or_button.rb +16 -0
  80. data/lib/capybara/selector/definition/option.rb +27 -0
  81. data/lib/capybara/selector/definition/radio_button.rb +27 -0
  82. data/lib/capybara/selector/definition/select.rb +81 -0
  83. data/lib/capybara/selector/definition/table.rb +109 -0
  84. data/lib/capybara/selector/definition/table_row.rb +21 -0
  85. data/lib/capybara/selector/definition/xpath.rb +5 -0
  86. data/lib/capybara/selector/definition.rb +280 -0
  87. data/lib/capybara/selector/filter.rb +2 -17
  88. data/lib/capybara/selector/filter_set.rb +80 -33
  89. data/lib/capybara/selector/filters/base.rb +50 -6
  90. data/lib/capybara/selector/filters/expression_filter.rb +8 -26
  91. data/lib/capybara/selector/filters/locator_filter.rb +29 -0
  92. data/lib/capybara/selector/filters/node_filter.rb +16 -12
  93. data/lib/capybara/selector/regexp_disassembler.rb +211 -0
  94. data/lib/capybara/selector/selector.rb +93 -210
  95. data/lib/capybara/selector/xpath_extensions.rb +17 -0
  96. data/lib/capybara/selector.rb +475 -523
  97. data/lib/capybara/selenium/atoms/getAttribute.min.js +1 -0
  98. data/lib/capybara/selenium/atoms/isDisplayed.min.js +1 -0
  99. data/lib/capybara/selenium/atoms/src/getAttribute.js +161 -0
  100. data/lib/capybara/selenium/atoms/src/isDisplayed.js +454 -0
  101. data/lib/capybara/selenium/driver.rb +298 -267
  102. data/lib/capybara/selenium/driver_specializations/chrome_driver.rb +117 -0
  103. data/lib/capybara/selenium/driver_specializations/edge_driver.rb +128 -0
  104. data/lib/capybara/selenium/driver_specializations/firefox_driver.rb +84 -0
  105. data/lib/capybara/selenium/driver_specializations/internet_explorer_driver.rb +26 -0
  106. data/lib/capybara/selenium/driver_specializations/safari_driver.rb +24 -0
  107. data/lib/capybara/selenium/extensions/file_input_click_emulation.rb +34 -0
  108. data/lib/capybara/selenium/extensions/find.rb +110 -0
  109. data/lib/capybara/selenium/extensions/html5_drag.rb +229 -0
  110. data/lib/capybara/selenium/extensions/modifier_keys_stack.rb +28 -0
  111. data/lib/capybara/selenium/extensions/scroll.rb +76 -0
  112. data/lib/capybara/selenium/node.rb +517 -145
  113. data/lib/capybara/selenium/nodes/chrome_node.rb +125 -0
  114. data/lib/capybara/selenium/nodes/edge_node.rb +110 -0
  115. data/lib/capybara/selenium/nodes/firefox_node.rb +136 -0
  116. data/lib/capybara/selenium/nodes/ie_node.rb +22 -0
  117. data/lib/capybara/selenium/nodes/safari_node.rb +118 -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 +80 -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 +59 -67
  127. data/lib/capybara/session/config.rb +81 -67
  128. data/lib/capybara/session/matchers.rb +28 -20
  129. data/lib/capybara/session.rb +337 -365
  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 +151 -12
  133. data/lib/capybara/spec/session/accept_alert_spec.rb +12 -11
  134. data/lib/capybara/spec/session/accept_confirm_spec.rb +6 -5
  135. data/lib/capybara/spec/session/accept_prompt_spec.rb +10 -10
  136. data/lib/capybara/spec/session/active_element_spec.rb +31 -0
  137. data/lib/capybara/spec/session/all_spec.rb +161 -57
  138. data/lib/capybara/spec/session/ancestor_spec.rb +27 -24
  139. data/lib/capybara/spec/session/assert_all_of_selectors_spec.rb +68 -38
  140. data/lib/capybara/spec/session/assert_current_path_spec.rb +75 -0
  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_spec.rb +258 -0
  144. data/lib/capybara/spec/session/{assert_title.rb → assert_title_spec.rb} +22 -12
  145. data/lib/capybara/spec/session/attach_file_spec.rb +144 -69
  146. data/lib/capybara/spec/session/body_spec.rb +12 -13
  147. data/lib/capybara/spec/session/check_spec.rb +117 -55
  148. data/lib/capybara/spec/session/choose_spec.rb +64 -31
  149. data/lib/capybara/spec/session/click_button_spec.rb +231 -173
  150. data/lib/capybara/spec/session/click_link_or_button_spec.rb +55 -35
  151. data/lib/capybara/spec/session/click_link_spec.rb +93 -58
  152. data/lib/capybara/spec/session/current_scope_spec.rb +12 -11
  153. data/lib/capybara/spec/session/current_url_spec.rb +57 -39
  154. data/lib/capybara/spec/session/dismiss_confirm_spec.rb +4 -4
  155. data/lib/capybara/spec/session/dismiss_prompt_spec.rb +3 -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 +9 -7
  159. data/lib/capybara/spec/session/element/matches_selector_spec.rb +71 -57
  160. data/lib/capybara/spec/session/evaluate_async_script_spec.rb +8 -7
  161. data/lib/capybara/spec/session/evaluate_script_spec.rb +29 -8
  162. data/lib/capybara/spec/session/execute_script_spec.rb +10 -8
  163. data/lib/capybara/spec/session/fill_in_spec.rb +134 -43
  164. data/lib/capybara/spec/session/find_button_spec.rb +25 -24
  165. data/lib/capybara/spec/session/find_by_id_spec.rb +10 -9
  166. data/lib/capybara/spec/session/find_field_spec.rb +37 -41
  167. data/lib/capybara/spec/session/find_link_spec.rb +46 -17
  168. data/lib/capybara/spec/session/find_spec.rb +260 -145
  169. data/lib/capybara/spec/session/first_spec.rb +80 -52
  170. data/lib/capybara/spec/session/frame/frame_title_spec.rb +23 -0
  171. data/lib/capybara/spec/session/frame/frame_url_spec.rb +23 -0
  172. data/lib/capybara/spec/session/frame/switch_to_frame_spec.rb +33 -20
  173. data/lib/capybara/spec/session/frame/within_frame_spec.rb +52 -32
  174. data/lib/capybara/spec/session/go_back_spec.rb +2 -1
  175. data/lib/capybara/spec/session/go_forward_spec.rb +2 -1
  176. data/lib/capybara/spec/session/has_all_selectors_spec.rb +31 -31
  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 +100 -13
  180. data/lib/capybara/spec/session/has_css_spec.rb +272 -137
  181. data/lib/capybara/spec/session/has_current_path_spec.rb +60 -61
  182. data/lib/capybara/spec/session/has_element_spec.rb +47 -0
  183. data/lib/capybara/spec/session/has_field_spec.rb +139 -59
  184. data/lib/capybara/spec/session/has_link_spec.rb +47 -6
  185. data/lib/capybara/spec/session/has_none_selectors_spec.rb +42 -40
  186. data/lib/capybara/spec/session/has_select_spec.rb +107 -72
  187. data/lib/capybara/spec/session/has_selector_spec.rb +120 -71
  188. data/lib/capybara/spec/session/has_sibling_spec.rb +50 -0
  189. data/lib/capybara/spec/session/has_table_spec.rb +183 -5
  190. data/lib/capybara/spec/session/has_text_spec.rb +106 -62
  191. data/lib/capybara/spec/session/has_title_spec.rb +20 -14
  192. data/lib/capybara/spec/session/has_xpath_spec.rb +57 -38
  193. data/lib/capybara/spec/session/{headers.rb → headers_spec.rb} +3 -2
  194. data/lib/capybara/spec/session/html_spec.rb +14 -6
  195. data/lib/capybara/spec/session/matches_style_spec.rb +37 -0
  196. data/lib/capybara/spec/session/node_spec.rb +1024 -153
  197. data/lib/capybara/spec/session/node_wrapper_spec.rb +39 -0
  198. data/lib/capybara/spec/session/refresh_spec.rb +12 -6
  199. data/lib/capybara/spec/session/reset_session_spec.rb +82 -35
  200. data/lib/capybara/spec/session/{response_code.rb → response_code_spec.rb} +2 -1
  201. data/lib/capybara/spec/session/save_and_open_page_spec.rb +3 -2
  202. data/lib/capybara/spec/session/save_and_open_screenshot_spec.rb +8 -12
  203. data/lib/capybara/spec/session/save_page_spec.rb +42 -55
  204. data/lib/capybara/spec/session/save_screenshot_spec.rb +16 -14
  205. data/lib/capybara/spec/session/screenshot_spec.rb +2 -2
  206. data/lib/capybara/spec/session/scroll_spec.rb +119 -0
  207. data/lib/capybara/spec/session/select_spec.rb +107 -81
  208. data/lib/capybara/spec/session/selectors_spec.rb +52 -19
  209. data/lib/capybara/spec/session/sibling_spec.rb +10 -10
  210. data/lib/capybara/spec/session/text_spec.rb +37 -21
  211. data/lib/capybara/spec/session/title_spec.rb +17 -5
  212. data/lib/capybara/spec/session/uncheck_spec.rb +43 -23
  213. data/lib/capybara/spec/session/unselect_spec.rb +39 -38
  214. data/lib/capybara/spec/session/visit_spec.rb +85 -53
  215. data/lib/capybara/spec/session/window/become_closed_spec.rb +24 -20
  216. data/lib/capybara/spec/session/window/current_window_spec.rb +5 -3
  217. data/lib/capybara/spec/session/window/open_new_window_spec.rb +5 -3
  218. data/lib/capybara/spec/session/window/switch_to_window_spec.rb +27 -22
  219. data/lib/capybara/spec/session/window/window_opened_by_spec.rb +12 -6
  220. data/lib/capybara/spec/session/window/window_spec.rb +97 -63
  221. data/lib/capybara/spec/session/window/windows_spec.rb +12 -10
  222. data/lib/capybara/spec/session/window/within_window_spec.rb +31 -86
  223. data/lib/capybara/spec/session/within_spec.rb +83 -44
  224. data/lib/capybara/spec/spec_helper.rb +54 -44
  225. data/lib/capybara/spec/test_app.rb +158 -43
  226. data/lib/capybara/spec/views/animated.erb +49 -0
  227. data/lib/capybara/spec/views/form.erb +163 -42
  228. data/lib/capybara/spec/views/frame_child.erb +4 -3
  229. data/lib/capybara/spec/views/frame_one.erb +2 -1
  230. data/lib/capybara/spec/views/frame_parent.erb +1 -1
  231. data/lib/capybara/spec/views/frame_two.erb +1 -1
  232. data/lib/capybara/spec/views/initial_alert.erb +2 -1
  233. data/lib/capybara/spec/views/layout.erb +10 -0
  234. data/lib/capybara/spec/views/obscured.erb +47 -0
  235. data/lib/capybara/spec/views/offset.erb +33 -0
  236. data/lib/capybara/spec/views/path.erb +2 -2
  237. data/lib/capybara/spec/views/popup_one.erb +1 -1
  238. data/lib/capybara/spec/views/popup_two.erb +1 -1
  239. data/lib/capybara/spec/views/react.erb +45 -0
  240. data/lib/capybara/spec/views/scroll.erb +21 -0
  241. data/lib/capybara/spec/views/spatial.erb +31 -0
  242. data/lib/capybara/spec/views/tables.erb +68 -1
  243. data/lib/capybara/spec/views/with_animation.erb +81 -0
  244. data/lib/capybara/spec/views/with_base_tag.erb +2 -2
  245. data/lib/capybara/spec/views/with_dragula.erb +24 -0
  246. data/lib/capybara/spec/views/with_fixed_header_footer.erb +2 -1
  247. data/lib/capybara/spec/views/with_hover.erb +3 -2
  248. data/lib/capybara/spec/views/with_hover1.erb +10 -0
  249. data/lib/capybara/spec/views/with_html.erb +69 -12
  250. data/lib/capybara/spec/views/with_html5_svg.erb +20 -0
  251. data/lib/capybara/spec/views/with_jquery_animation.erb +24 -0
  252. data/lib/capybara/spec/views/with_js.erb +30 -5
  253. data/lib/capybara/spec/views/with_jstree.erb +26 -0
  254. data/lib/capybara/spec/views/with_namespace.erb +21 -0
  255. data/lib/capybara/spec/views/with_scope.erb +2 -2
  256. data/lib/capybara/spec/views/with_scope_other.erb +6 -0
  257. data/lib/capybara/spec/views/with_shadow.erb +31 -0
  258. data/lib/capybara/spec/views/with_slow_unload.erb +2 -1
  259. data/lib/capybara/spec/views/with_sortable_js.erb +21 -0
  260. data/lib/capybara/spec/views/with_unload_alert.erb +1 -0
  261. data/lib/capybara/spec/views/with_windows.erb +1 -1
  262. data/lib/capybara/spec/views/within_frames.erb +5 -2
  263. data/lib/capybara/version.rb +2 -1
  264. data/lib/capybara/window.rb +36 -34
  265. data/lib/capybara.rb +134 -107
  266. data/spec/basic_node_spec.rb +60 -34
  267. data/spec/capybara_spec.rb +63 -88
  268. data/spec/counter_spec.rb +35 -0
  269. data/spec/css_builder_spec.rb +101 -0
  270. data/spec/css_splitter_spec.rb +38 -0
  271. data/spec/dsl_spec.rb +85 -64
  272. data/spec/filter_set_spec.rb +27 -9
  273. data/spec/fixtures/certificate.pem +25 -0
  274. data/spec/fixtures/key.pem +27 -0
  275. data/spec/fixtures/selenium_driver_rspec_failure.rb +6 -5
  276. data/spec/fixtures/selenium_driver_rspec_success.rb +6 -5
  277. data/spec/minitest_spec.rb +52 -7
  278. data/spec/minitest_spec_spec.rb +94 -63
  279. data/spec/per_session_config_spec.rb +14 -13
  280. data/spec/rack_test_spec.rb +194 -125
  281. data/spec/regexp_dissassembler_spec.rb +250 -0
  282. data/spec/result_spec.rb +111 -50
  283. data/spec/rspec/features_spec.rb +37 -31
  284. data/spec/rspec/scenarios_spec.rb +10 -8
  285. data/spec/rspec/shared_spec_matchers.rb +473 -422
  286. data/spec/rspec/views_spec.rb +5 -3
  287. data/spec/rspec_matchers_spec.rb +52 -11
  288. data/spec/rspec_spec.rb +109 -89
  289. data/spec/sauce_spec_chrome.rb +43 -0
  290. data/spec/selector_spec.rb +397 -68
  291. data/spec/selenium_spec_chrome.rb +187 -40
  292. data/spec/selenium_spec_chrome_remote.rb +96 -0
  293. data/spec/selenium_spec_edge.rb +60 -0
  294. data/spec/selenium_spec_firefox.rb +201 -41
  295. data/spec/selenium_spec_firefox_remote.rb +94 -0
  296. data/spec/selenium_spec_ie.rb +149 -0
  297. data/spec/selenium_spec_safari.rb +162 -0
  298. data/spec/server_spec.rb +213 -102
  299. data/spec/session_spec.rb +53 -16
  300. data/spec/shared_selenium_node.rb +79 -0
  301. data/spec/shared_selenium_session.rb +473 -122
  302. data/spec/spec_helper.rb +126 -7
  303. data/spec/whitespace_normalizer_spec.rb +54 -0
  304. data/spec/xpath_builder_spec.rb +93 -0
  305. metadata +355 -73
  306. data/.yard/templates_custom/default/class/html/selectors.erb +0 -38
  307. data/.yard/templates_custom/default/class/html/setup.rb +0 -17
  308. data/.yard/yard_extensions.rb +0 -78
  309. data/lib/capybara/query.rb +0 -7
  310. data/lib/capybara/rspec/compound.rb +0 -95
  311. data/lib/capybara/spec/session/assert_current_path.rb +0 -72
  312. data/lib/capybara/spec/session/assert_selector.rb +0 -148
  313. data/lib/capybara/spec/session/assert_text.rb +0 -234
  314. data/lib/capybara/spec/session/source_spec.rb +0 -0
  315. data/lib/capybara/spec/views/with_title.erb +0 -5
  316. data/spec/selenium_spec_marionette.rb +0 -127
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require 'forwardable'
3
4
  require 'capybara/session/config'
4
5
 
@@ -6,11 +7,12 @@ module Capybara
6
7
  class Config
7
8
  extend Forwardable
8
9
 
9
- OPTIONS = [:app, :reuse_server, :threadsafe, :default_wait_time, :server, :default_driver, :javascript_driver]
10
+ OPTIONS = %i[
11
+ app reuse_server threadsafe server default_driver javascript_driver use_html5_parsing allow_gumbo
12
+ ].freeze
10
13
 
11
- attr_accessor :app
12
- attr_reader :reuse_server, :threadsafe
13
- attr_reader :session_options
14
+ attr_accessor :app, :use_html5_parsing
15
+ attr_reader :reuse_server, :threadsafe, :session_options # rubocop:disable Style/BisectedAttrAccessor
14
16
  attr_writer :default_driver, :javascript_driver
15
17
 
16
18
  SessionConfig::OPTIONS.each do |method|
@@ -19,15 +21,16 @@ module Capybara
19
21
 
20
22
  def initialize
21
23
  @session_options = Capybara::SessionConfig.new
24
+ @javascript_driver = nil
22
25
  end
23
26
 
24
- def reuse_server=(bool)
25
- @reuse_server = bool
26
- end
27
+ attr_writer :reuse_server # rubocop:disable Style/BisectedAttrAccessor
27
28
 
28
29
  def threadsafe=(bool)
29
- warn "Capybara.threadsafe == true is a BETA feature and may change in future minor versions" if bool
30
- raise "Threadsafe setting cannot be changed once a session is created" if (bool != threadsafe) && Session.instance_created?
30
+ if (bool != threadsafe) && Session.instance_created?
31
+ raise 'Threadsafe setting cannot be changed once a session is created'
32
+ end
33
+
31
34
  @threadsafe = bool
32
35
  end
33
36
 
@@ -35,16 +38,9 @@ module Capybara
35
38
  #
36
39
  # Return the proc that Capybara will call to run the Rack application.
37
40
  # The block returned receives a rack app, port, and host/ip and should run a Rack handler
38
- # By default, Capybara will try to run webrick.
41
+ # By default, Capybara will try to use puma.
39
42
  #
40
- def server(&block)
41
- if block_given?
42
- warn "DEPRECATED: Passing a block to Capybara::server is deprecated, please use Capybara::register_server instead"
43
- @server = block
44
- else
45
- @server
46
- end
47
- end
43
+ attr_reader :server
48
44
 
49
45
  ##
50
46
  #
@@ -64,12 +60,10 @@ module Capybara
64
60
  name, options = *name if name.is_a? Array
65
61
  @server = if name.respond_to? :call
66
62
  name
63
+ elsif options
64
+ proc { |app, port, host| Capybara.servers[name.to_sym].call(app, port, host, **options) }
67
65
  else
68
- if options
69
- Proc.new { |app, port, host| Capybara.servers[name.to_sym].call(app,port,host,options) }
70
- else
71
- Capybara.servers[name.to_sym]
72
- end
66
+ Capybara.servers[name.to_sym]
73
67
  end
74
68
  end
75
69
 
@@ -89,44 +83,22 @@ module Capybara
89
83
  @javascript_driver || :selenium
90
84
  end
91
85
 
92
- # @deprecated Use default_max_wait_time instead
93
- def default_wait_time
94
- deprecate('default_wait_time', 'default_max_wait_time', true)
95
- default_max_wait_time
96
- end
97
-
98
- # @deprecated Use default_max_wait_time= instead
99
- def default_wait_time=(t)
100
- deprecate('default_wait_time=', 'default_max_wait_time=')
101
- self.default_max_wait_time = t
102
- end
103
-
104
- def deprecate(method, alternate_method, once=false)
86
+ def deprecate(method, alternate_method, once: false)
105
87
  @deprecation_notified ||= {}
106
- warn "DEPRECATED: ##{method} is deprecated, please use ##{alternate_method} instead" unless once and @deprecation_notified[method]
107
- @deprecation_notified[method]=true
108
- end
109
- end
110
-
111
- # @api private
112
- class ConfigureDeprecator
113
- def initialize(config)
114
- @config = config
88
+ unless once && @deprecation_notified[method]
89
+ Capybara::Helpers.warn "DEPRECATED: ##{method} is deprecated, please use ##{alternate_method} instead: #{Capybara::Helpers.filter_backtrace(caller)}"
90
+ end
91
+ @deprecation_notified[method] = true
115
92
  end
116
93
 
117
- def method_missing(m, *args, &block)
118
- if @config.respond_to?(m)
119
- @config.public_send(m, *args, &block)
120
- elsif Capybara.respond_to?(m)
121
- warn "Calling #{m} from Capybara.configure is deprecated - please call it on Capybara directly ( Capybara.#{m}(...) )"
122
- Capybara.public_send(m, *args, &block)
123
- else
124
- super
125
- end
94
+ def allow_gumbo=(val)
95
+ deprecate('allow_gumbo=', 'use_html5_parsing=')
96
+ self.use_html5_parsing = val
126
97
  end
127
98
 
128
- def respond_to_missing?(m, include_private = false)
129
- @config.respond_to?(m) || Capybara.respond_to?(m) || super
99
+ def allow_gumbo
100
+ deprecate('allow_gumbo', 'use_html5_parsing')
101
+ use_html5_parsing
130
102
  end
131
103
  end
132
- end
104
+ end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require 'capybara/dsl'
3
4
  require 'capybara/rspec/matchers'
4
5
  require 'capybara/rspec/matcher_proxies'
@@ -21,8 +22,6 @@ end
21
22
  Before do |scenario|
22
23
  scenario.source_tag_names.each do |tag|
23
24
  driver_name = tag.sub(/^@/, '').to_sym
24
- if Capybara.drivers.has_key?(driver_name)
25
- Capybara.current_driver = driver_name
26
- end
25
+ Capybara.current_driver = driver_name if Capybara.drivers[driver_name]
27
26
  end
28
27
  end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  class Capybara::Driver::Base
3
4
  attr_writer :session
4
5
 
@@ -14,11 +15,11 @@ class Capybara::Driver::Base
14
15
  raise NotImplementedError
15
16
  end
16
17
 
17
- def find_xpath(query)
18
+ def find_xpath(query, **options)
18
19
  raise NotImplementedError
19
20
  end
20
21
 
21
- def find_css(query)
22
+ def find_css(query, **options)
22
23
  raise NotImplementedError
23
24
  end
24
25
 
@@ -46,7 +47,7 @@ class Capybara::Driver::Base
46
47
  raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#evaluate_script_asnyc'
47
48
  end
48
49
 
49
- def save_screenshot(path, options={})
50
+ def save_screenshot(path, **options)
50
51
  raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#save_screenshot'
51
52
  end
52
53
 
@@ -58,6 +59,14 @@ class Capybara::Driver::Base
58
59
  raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#status_code'
59
60
  end
60
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
+
61
70
  ##
62
71
  #
63
72
  # @param frame [Capybara::Node::Element, :parent, :top] The iframe element to switch to
@@ -66,6 +75,16 @@ class Capybara::Driver::Base
66
75
  raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#switch_to_frame'
67
76
  end
68
77
 
78
+ def frame_title
79
+ find_xpath('/html/head/title').map(&:all_text).first.to_s
80
+ end
81
+
82
+ def frame_url
83
+ evaluate_script('document.location.href')
84
+ rescue Capybara::NotSupportedByDriverError
85
+ raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#frame_title'
86
+ end
87
+
69
88
  def current_window_handle
70
89
  raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#current_window_handle'
71
90
  end
@@ -79,7 +98,11 @@ class Capybara::Driver::Base
79
98
  end
80
99
 
81
100
  def maximize_window(handle)
82
- 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'
83
106
  end
84
107
 
85
108
  def close_window(handle)
@@ -98,15 +121,10 @@ class Capybara::Driver::Base
98
121
  raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#switch_to_window'
99
122
  end
100
123
 
101
- def within_window(locator)
102
- raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#within_window'
103
- end
104
-
105
124
  def no_such_window_error
106
125
  raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#no_such_window_error'
107
126
  end
108
127
 
109
-
110
128
  ##
111
129
  #
112
130
  # Execute the block, and then accept the modal opened.
@@ -117,7 +135,7 @@ class Capybara::Driver::Base
117
135
  # @return [String] the message shown in the modal
118
136
  # @raise [Capybara::ModalNotFound] if modal dialog hasn't been found
119
137
  #
120
- def accept_modal(type, options={}, &blk)
138
+ def accept_modal(type, **options, &blk)
121
139
  raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#accept_modal'
122
140
  end
123
141
 
@@ -130,7 +148,7 @@ class Capybara::Driver::Base
130
148
  # @return [String] the message shown in the modal
131
149
  # @raise [Capybara::ModalNotFound] if modal dialog hasn't been found
132
150
  #
133
- def dismiss_modal(type, options={}, &blk)
151
+ def dismiss_modal(type, **options, &blk)
134
152
  raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#dismiss_modal'
135
153
  end
136
154
 
@@ -142,20 +160,19 @@ class Capybara::Driver::Base
142
160
  false
143
161
  end
144
162
 
145
- def reset!
146
- end
163
+ def reset!; end
147
164
 
148
165
  def needs_server?
149
166
  false
150
167
  end
151
168
 
152
169
  def session_options
153
- (@session && @session.config) || Capybara.session_options
170
+ session&.config || Capybara.session_options
154
171
  end
155
172
 
156
- # @deprecated This method is being removed
157
- def browser_initialized?
158
- warn "DEPRECATED: #browser_initialized? is deprecated and will be removed in the next version of Capybara"
159
- true
173
+ private
174
+
175
+ def session
176
+ @session ||= nil
160
177
  end
161
178
  end
@@ -1,12 +1,14 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Capybara
3
4
  module Driver
4
5
  class Node
5
- attr_reader :driver, :native
6
+ attr_reader :driver, :native, :initial_cache
6
7
 
7
- def initialize(driver, native)
8
+ def initialize(driver, native, initial_cache = {})
8
9
  @driver = driver
9
10
  @native = native
11
+ @initial_cache = initial_cache
10
12
  end
11
13
 
12
14
  def all_text
@@ -25,9 +27,13 @@ module Capybara
25
27
  raise NotImplementedError
26
28
  end
27
29
 
28
- # @param value String or Array. Array is only allowed if node has 'multiple' attribute
29
- # @param options [Hash{}] Driver specific options for how to set a value on a node
30
- def set(value, options={})
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
36
+ def set(value, **options)
31
37
  raise NotImplementedError
32
38
  end
33
39
 
@@ -39,15 +45,15 @@ module Capybara
39
45
  raise NotImplementedError
40
46
  end
41
47
 
42
- def click
48
+ def click(keys = [], **options)
43
49
  raise NotImplementedError
44
50
  end
45
51
 
46
- def right_click
52
+ def right_click(keys = [], **options)
47
53
  raise NotImplementedError
48
54
  end
49
55
 
50
- def double_click
56
+ def double_click(keys = [], **options)
51
57
  raise NotImplementedError
52
58
  end
53
59
 
@@ -59,7 +65,19 @@ module Capybara
59
65
  raise NotImplementedError
60
66
  end
61
67
 
62
- 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)
63
81
  raise NotImplementedError
64
82
  end
65
83
 
@@ -71,6 +89,10 @@ module Capybara
71
89
  raise NotImplementedError
72
90
  end
73
91
 
92
+ def obscured?
93
+ raise NotImplementedError
94
+ end
95
+
74
96
  def checked?
75
97
  raise NotImplementedError
76
98
  end
@@ -91,6 +113,10 @@ module Capybara
91
113
  !!self[:multiple]
92
114
  end
93
115
 
116
+ def rect
117
+ raise NotSupportedByDriverError, 'Capybara::Driver::Node#rect'
118
+ end
119
+
94
120
  def path
95
121
  raise NotSupportedByDriverError, 'Capybara::Driver::Node#path'
96
122
  end
@@ -99,6 +125,10 @@ module Capybara
99
125
  raise NotSupportedByDriverError, 'Capybara::Driver::Node#trigger'
100
126
  end
101
127
 
128
+ def shadow_root
129
+ raise NotSupportedByDriverError, 'Capybara::Driver::Node#shadow_root'
130
+ end
131
+
102
132
  def inspect
103
133
  %(#<#{self.class} tag="#{tag_name}" path="#{path}">)
104
134
  rescue NotSupportedByDriverError
@@ -106,7 +136,7 @@ module Capybara
106
136
  end
107
137
 
108
138
  def ==(other)
109
- raise NotSupportedByDriverError, 'Capybara::Driver::Node#=='
139
+ eql?(other) || (other.respond_to?(:native) && native == other.native)
110
140
  end
111
141
  end
112
142
  end
data/lib/capybara/dsl.rb CHANGED
@@ -1,15 +1,16 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require 'capybara'
3
4
 
4
5
  module Capybara
5
6
  module DSL
6
7
  def self.included(base)
7
- 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
8
9
  super
9
10
  end
10
11
 
11
12
  def self.extended(base)
12
- 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')
13
14
  super
14
15
  end
15
16
 
@@ -17,8 +18,8 @@ module Capybara
17
18
  #
18
19
  # Shortcut to working in a different session.
19
20
  #
20
- def using_session(name, &block)
21
- Capybara.using_session(name, &block)
21
+ def using_session(name_or_session, &block)
22
+ Capybara.using_session(name_or_session, &block)
22
23
  end
23
24
 
24
25
  # Shortcut to using a different wait time.
@@ -46,9 +47,11 @@ module Capybara
46
47
  end
47
48
 
48
49
  Session::DSL_METHODS.each do |method|
49
- define_method method do |*args, &block|
50
- page.send method, *args, &block
51
- end
50
+ class_eval <<~METHOD, __FILE__, __LINE__ + 1
51
+ def #{method}(...)
52
+ page.method("#{method}").call(...)
53
+ end
54
+ METHOD
52
55
  end
53
56
  end
54
57
 
@@ -1,14 +1,12 @@
1
- # encoding: UTF-8
2
1
  # frozen_string_literal: true
3
2
 
4
3
  module Capybara
5
-
6
4
  # @api private
7
5
  module Helpers
8
- extend self
6
+ module_function
9
7
 
10
8
  ##
11
- #
9
+ # @deprecated
12
10
  # Normalizes whitespace space by stripping leading and trailing
13
11
  # whitespace and replacing sequences of whitespace characters
14
12
  # with a single space.
@@ -17,6 +15,7 @@ module Capybara
17
15
  # @return [String] Normalized text
18
16
  #
19
17
  def normalize_whitespace(text)
18
+ Capybara::Helpers.warn 'DEPRECATED: Capybara::Helpers::normalize_whitespace is deprecated, please update your driver'
20
19
  text.to_s.gsub(/[[:space:]]+/, ' ').strip
21
20
  end
22
21
 
@@ -26,34 +25,34 @@ module Capybara
26
25
  # if text is not a regexp
27
26
  #
28
27
  # @param [String] text Text to escape
29
- # @return [String] Escaped text
28
+ # @param [Boolean] exact (false) Whether or not this should be an exact text match
29
+ # @param [Fixnum, Boolean, nil] options Options passed to Regexp.new when creating the Regexp
30
+ # @return [Regexp] Regexp to match the passed in text and options
30
31
  #
31
- def to_regexp(text, regexp_options=nil, exact=false)
32
- if text.is_a?(Regexp)
33
- text
34
- else
35
- escaped = Regexp.escape(normalize_whitespace(text))
36
- escaped = "\\A#{escaped}\\z" if exact
37
- Regexp.new(escaped, regexp_options)
38
- end
32
+ def to_regexp(text, exact: false, all_whitespace: false, options: nil)
33
+ return text if text.is_a?(Regexp)
34
+
35
+ escaped = Regexp.escape(text)
36
+ escaped = escaped.gsub('\\ ', '[[:blank:]]') if all_whitespace
37
+ escaped = "\\A#{escaped}\\z" if exact
38
+ Regexp.new(escaped, options)
39
39
  end
40
40
 
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
+ # @param [URL] host (Capybara.asset_host) The host from which assets should be loaded
47
48
  # @return [String] The modified HTML code
48
49
  #
49
- def inject_asset_host(html, asset_host = Capybara.asset_host)
50
- if asset_host && Nokogiri::HTML(html).css("base").empty?
51
- match = html.match(/<head[^<]*?>/)
52
- if match
53
- return html.clone.insert match.end(0), "<base href='#{asset_host}' />"
50
+ def inject_asset_host(html, host: Capybara.asset_host)
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
54
  end
55
55
  end
56
-
57
56
  html
58
57
  end
59
58
 
@@ -68,20 +67,60 @@ module Capybara
68
67
  # @param [Integer] count The number of items
69
68
  #
70
69
  def declension(singular, plural, count)
71
- if count == 1
72
- singular
73
- else
74
- plural
75
- end
70
+ count == 1 ? singular : plural
76
71
  end
77
72
 
78
- if defined?(Process::CLOCK_MONOTONIC)
79
- def monotonic_time
80
- Process.clock_gettime Process::CLOCK_MONOTONIC
81
- end
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)
93
+ def monotonic_time; Process.clock_gettime Process::CLOCK_MONOTONIC; end
82
94
  else
83
- def monotonic_time
84
- Time.now.to_f
95
+ def monotonic_time; Time.now.to_f; end
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
85
124
  end
86
125
  end
87
126
  end