capybara 2.7.0 → 3.35.3

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 (318) hide show
  1. checksums.yaml +5 -5
  2. data/.yardopts +1 -0
  3. data/History.md +1147 -11
  4. data/License.txt +1 -1
  5. data/README.md +252 -131
  6. data/lib/capybara/config.rb +92 -0
  7. data/lib/capybara/cucumber.rb +3 -3
  8. data/lib/capybara/driver/base.rb +52 -21
  9. data/lib/capybara/driver/node.rb +48 -14
  10. data/lib/capybara/dsl.rb +16 -9
  11. data/lib/capybara/helpers.rb +72 -81
  12. data/lib/capybara/minitest/spec.rb +267 -0
  13. data/lib/capybara/minitest.rb +385 -0
  14. data/lib/capybara/node/actions.rb +337 -89
  15. data/lib/capybara/node/base.rb +50 -32
  16. data/lib/capybara/node/document.rb +19 -3
  17. data/lib/capybara/node/document_matchers.rb +22 -24
  18. data/lib/capybara/node/element.rb +388 -125
  19. data/lib/capybara/node/finders.rb +231 -121
  20. data/lib/capybara/node/matchers.rb +503 -217
  21. data/lib/capybara/node/simple.rb +64 -27
  22. data/lib/capybara/queries/ancestor_query.rb +27 -0
  23. data/lib/capybara/queries/base_query.rb +87 -11
  24. data/lib/capybara/queries/current_path_query.rb +24 -24
  25. data/lib/capybara/queries/match_query.rb +15 -10
  26. data/lib/capybara/queries/selector_query.rb +675 -81
  27. data/lib/capybara/queries/sibling_query.rb +26 -0
  28. data/lib/capybara/queries/style_query.rb +45 -0
  29. data/lib/capybara/queries/text_query.rb +88 -20
  30. data/lib/capybara/queries/title_query.rb +9 -11
  31. data/lib/capybara/rack_test/browser.rb +63 -39
  32. data/lib/capybara/rack_test/css_handlers.rb +6 -4
  33. data/lib/capybara/rack_test/driver.rb +26 -16
  34. data/lib/capybara/rack_test/errors.rb +6 -0
  35. data/lib/capybara/rack_test/form.rb +73 -58
  36. data/lib/capybara/rack_test/node.rb +187 -67
  37. data/lib/capybara/rails.rb +4 -8
  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 +142 -14
  43. data/lib/capybara/rspec/features.rb +17 -42
  44. data/lib/capybara/rspec/matcher_proxies.rb +82 -0
  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 +143 -244
  59. data/lib/capybara/rspec.rb +10 -12
  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 +102 -0
  63. data/lib/capybara/selector/definition/button.rb +63 -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 +278 -0
  85. data/lib/capybara/selector/filter.rb +3 -46
  86. data/lib/capybara/selector/filter_set.rb +124 -0
  87. data/lib/capybara/selector/filters/base.rb +77 -0
  88. data/lib/capybara/selector/filters/expression_filter.rb +22 -0
  89. data/lib/capybara/selector/filters/locator_filter.rb +29 -0
  90. data/lib/capybara/selector/filters/node_filter.rb +31 -0
  91. data/lib/capybara/selector/regexp_disassembler.rb +214 -0
  92. data/lib/capybara/selector/selector.rb +155 -0
  93. data/lib/capybara/selector/xpath_extensions.rb +17 -0
  94. data/lib/capybara/selector.rb +232 -369
  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 +380 -142
  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 +528 -97
  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 +63 -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 +74 -71
  127. data/lib/capybara/session/config.rb +126 -0
  128. data/lib/capybara/session/matchers.rb +44 -27
  129. data/lib/capybara/session.rb +500 -297
  130. data/lib/capybara/spec/fixtures/no_extension +1 -0
  131. data/lib/capybara/spec/public/jquery.js +5 -5
  132. data/lib/capybara/spec/public/offset.js +6 -0
  133. data/lib/capybara/spec/public/test.js +168 -14
  134. data/lib/capybara/spec/session/accept_alert_spec.rb +37 -14
  135. data/lib/capybara/spec/session/accept_confirm_spec.rb +7 -6
  136. data/lib/capybara/spec/session/accept_prompt_spec.rb +38 -10
  137. data/lib/capybara/spec/session/all_spec.rb +179 -59
  138. data/lib/capybara/spec/session/ancestor_spec.rb +88 -0
  139. data/lib/capybara/spec/session/assert_all_of_selectors_spec.rb +140 -0
  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_spec.rb +93 -0
  145. data/lib/capybara/spec/session/attach_file_spec.rb +154 -48
  146. data/lib/capybara/spec/session/body_spec.rb +12 -13
  147. data/lib/capybara/spec/session/check_spec.rb +168 -41
  148. data/lib/capybara/spec/session/choose_spec.rb +75 -23
  149. data/lib/capybara/spec/session/click_button_spec.rb +243 -175
  150. data/lib/capybara/spec/session/click_link_or_button_spec.rb +57 -32
  151. data/lib/capybara/spec/session/click_link_spec.rb +100 -53
  152. data/lib/capybara/spec/session/current_scope_spec.rb +11 -10
  153. data/lib/capybara/spec/session/current_url_spec.rb +61 -35
  154. data/lib/capybara/spec/session/dismiss_confirm_spec.rb +7 -7
  155. data/lib/capybara/spec/session/dismiss_prompt_spec.rb +5 -4
  156. data/lib/capybara/spec/session/element/{assert_match_selector.rb → assert_match_selector_spec.rb} +13 -6
  157. data/lib/capybara/spec/session/element/match_css_spec.rb +21 -7
  158. data/lib/capybara/spec/session/element/match_xpath_spec.rb +9 -7
  159. data/lib/capybara/spec/session/element/matches_selector_spec.rb +91 -34
  160. data/lib/capybara/spec/session/evaluate_async_script_spec.rb +23 -0
  161. data/lib/capybara/spec/session/evaluate_script_spec.rb +45 -3
  162. data/lib/capybara/spec/session/execute_script_spec.rb +24 -4
  163. data/lib/capybara/spec/session/fill_in_spec.rb +166 -64
  164. data/lib/capybara/spec/session/find_button_spec.rb +37 -18
  165. data/lib/capybara/spec/session/find_by_id_spec.rb +10 -9
  166. data/lib/capybara/spec/session/find_field_spec.rb +57 -34
  167. data/lib/capybara/spec/session/find_link_spec.rb +47 -10
  168. data/lib/capybara/spec/session/find_spec.rb +290 -144
  169. data/lib/capybara/spec/session/first_spec.rb +91 -48
  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 +116 -0
  173. data/lib/capybara/spec/session/frame/within_frame_spec.rb +112 -0
  174. data/lib/capybara/spec/session/go_back_spec.rb +3 -2
  175. data/lib/capybara/spec/session/go_forward_spec.rb +3 -2
  176. data/lib/capybara/spec/session/has_all_selectors_spec.rb +69 -0
  177. data/lib/capybara/spec/session/has_ancestor_spec.rb +46 -0
  178. data/lib/capybara/spec/session/has_any_selectors_spec.rb +25 -0
  179. data/lib/capybara/spec/session/has_button_spec.rb +76 -19
  180. data/lib/capybara/spec/session/has_css_spec.rb +277 -131
  181. data/lib/capybara/spec/session/has_current_path_spec.rb +98 -26
  182. data/lib/capybara/spec/session/has_field_spec.rb +177 -107
  183. data/lib/capybara/spec/session/has_link_spec.rb +13 -12
  184. data/lib/capybara/spec/session/has_none_selectors_spec.rb +78 -0
  185. data/lib/capybara/spec/session/has_select_spec.rb +191 -95
  186. data/lib/capybara/spec/session/has_selector_spec.rb +128 -64
  187. data/lib/capybara/spec/session/has_sibling_spec.rb +50 -0
  188. data/lib/capybara/spec/session/has_table_spec.rb +172 -5
  189. data/lib/capybara/spec/session/has_text_spec.rb +126 -60
  190. data/lib/capybara/spec/session/has_title_spec.rb +35 -12
  191. data/lib/capybara/spec/session/has_xpath_spec.rb +74 -53
  192. data/lib/capybara/spec/session/{headers.rb → headers_spec.rb} +3 -2
  193. data/lib/capybara/spec/session/html_spec.rb +14 -6
  194. data/lib/capybara/spec/session/matches_style_spec.rb +35 -0
  195. data/lib/capybara/spec/session/node_spec.rb +1028 -131
  196. data/lib/capybara/spec/session/node_wrapper_spec.rb +39 -0
  197. data/lib/capybara/spec/session/refresh_spec.rb +34 -0
  198. data/lib/capybara/spec/session/reset_session_spec.rb +75 -34
  199. data/lib/capybara/spec/session/{response_code.rb → response_code_spec.rb} +2 -1
  200. data/lib/capybara/spec/session/save_and_open_page_spec.rb +3 -2
  201. data/lib/capybara/spec/session/save_and_open_screenshot_spec.rb +11 -15
  202. data/lib/capybara/spec/session/save_page_spec.rb +42 -55
  203. data/lib/capybara/spec/session/save_screenshot_spec.rb +16 -14
  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 +112 -85
  207. data/lib/capybara/spec/session/selectors_spec.rb +71 -8
  208. data/lib/capybara/spec/session/sibling_spec.rb +52 -0
  209. data/lib/capybara/spec/session/text_spec.rb +38 -23
  210. data/lib/capybara/spec/session/title_spec.rb +17 -5
  211. data/lib/capybara/spec/session/uncheck_spec.rb +71 -12
  212. data/lib/capybara/spec/session/unselect_spec.rb +44 -43
  213. data/lib/capybara/spec/session/visit_spec.rb +99 -32
  214. data/lib/capybara/spec/session/window/become_closed_spec.rb +33 -29
  215. data/lib/capybara/spec/session/window/current_window_spec.rb +5 -3
  216. data/lib/capybara/spec/session/window/open_new_window_spec.rb +5 -3
  217. data/lib/capybara/spec/session/window/switch_to_window_spec.rb +39 -30
  218. data/lib/capybara/spec/session/window/window_opened_by_spec.rb +17 -10
  219. data/lib/capybara/spec/session/window/window_spec.rb +121 -73
  220. data/lib/capybara/spec/session/window/windows_spec.rb +12 -10
  221. data/lib/capybara/spec/session/window/within_window_spec.rb +52 -82
  222. data/lib/capybara/spec/session/within_spec.rb +76 -43
  223. data/lib/capybara/spec/spec_helper.rb +67 -33
  224. data/lib/capybara/spec/test_app.rb +85 -36
  225. data/lib/capybara/spec/views/animated.erb +49 -0
  226. data/lib/capybara/spec/views/buttons.erb +1 -1
  227. data/lib/capybara/spec/views/fieldsets.erb +1 -1
  228. data/lib/capybara/spec/views/form.erb +227 -20
  229. data/lib/capybara/spec/views/frame_child.erb +10 -2
  230. data/lib/capybara/spec/views/frame_one.erb +2 -1
  231. data/lib/capybara/spec/views/frame_parent.erb +2 -2
  232. data/lib/capybara/spec/views/frame_two.erb +1 -1
  233. data/lib/capybara/spec/views/header_links.erb +1 -1
  234. data/lib/capybara/spec/views/host_links.erb +1 -1
  235. data/lib/capybara/spec/views/initial_alert.erb +10 -0
  236. data/lib/capybara/spec/views/obscured.erb +47 -0
  237. data/lib/capybara/spec/views/offset.erb +32 -0
  238. data/lib/capybara/spec/views/path.erb +1 -1
  239. data/lib/capybara/spec/views/popup_one.erb +1 -1
  240. data/lib/capybara/spec/views/popup_two.erb +1 -1
  241. data/lib/capybara/spec/views/postback.erb +1 -1
  242. data/lib/capybara/spec/views/react.erb +45 -0
  243. data/lib/capybara/spec/views/scroll.erb +20 -0
  244. data/lib/capybara/spec/views/spatial.erb +31 -0
  245. data/lib/capybara/spec/views/tables.erb +69 -2
  246. data/lib/capybara/spec/views/with_animation.erb +82 -0
  247. data/lib/capybara/spec/views/with_base_tag.erb +1 -1
  248. data/lib/capybara/spec/views/with_count.erb +1 -1
  249. data/lib/capybara/spec/views/with_dragula.erb +24 -0
  250. data/lib/capybara/spec/views/with_fixed_header_footer.erb +17 -0
  251. data/lib/capybara/spec/views/with_hover.erb +7 -1
  252. data/lib/capybara/spec/views/with_hover1.erb +10 -0
  253. data/lib/capybara/spec/views/with_html.erb +100 -10
  254. data/lib/capybara/spec/views/with_html5_svg.erb +20 -0
  255. data/lib/capybara/spec/views/with_html_entities.erb +1 -1
  256. data/lib/capybara/spec/views/with_jquery_animation.erb +24 -0
  257. data/lib/capybara/spec/views/with_js.erb +49 -3
  258. data/lib/capybara/spec/views/with_jstree.erb +26 -0
  259. data/lib/capybara/spec/views/with_namespace.erb +20 -0
  260. data/lib/capybara/spec/views/with_scope.erb +1 -1
  261. data/lib/capybara/spec/views/with_scope_other.erb +6 -0
  262. data/lib/capybara/spec/views/with_simple_html.erb +1 -1
  263. data/lib/capybara/spec/views/with_sortable_js.erb +21 -0
  264. data/lib/capybara/spec/views/with_title.erb +1 -1
  265. data/lib/capybara/spec/views/with_unload_alert.erb +3 -1
  266. data/lib/capybara/spec/views/with_windows.erb +7 -1
  267. data/lib/capybara/spec/views/within_frames.erb +6 -3
  268. data/lib/capybara/version.rb +2 -1
  269. data/lib/capybara/window.rb +39 -21
  270. data/lib/capybara.rb +208 -186
  271. data/spec/basic_node_spec.rb +52 -39
  272. data/spec/capybara_spec.rb +72 -50
  273. data/spec/css_builder_spec.rb +101 -0
  274. data/spec/css_splitter_spec.rb +38 -0
  275. data/spec/dsl_spec.rb +81 -61
  276. data/spec/filter_set_spec.rb +46 -0
  277. data/spec/fixtures/capybara.csv +1 -0
  278. data/spec/fixtures/certificate.pem +25 -0
  279. data/spec/fixtures/key.pem +27 -0
  280. data/spec/fixtures/selenium_driver_rspec_failure.rb +7 -3
  281. data/spec/fixtures/selenium_driver_rspec_success.rb +7 -3
  282. data/spec/minitest_spec.rb +164 -0
  283. data/spec/minitest_spec_spec.rb +162 -0
  284. data/spec/per_session_config_spec.rb +68 -0
  285. data/spec/rack_test_spec.rb +189 -96
  286. data/spec/regexp_dissassembler_spec.rb +250 -0
  287. data/spec/result_spec.rb +143 -13
  288. data/spec/rspec/features_spec.rb +38 -32
  289. data/spec/rspec/scenarios_spec.rb +9 -7
  290. data/spec/rspec/shared_spec_matchers.rb +959 -0
  291. data/spec/rspec/views_spec.rb +9 -3
  292. data/spec/rspec_matchers_spec.rb +62 -0
  293. data/spec/rspec_spec.rb +127 -30
  294. data/spec/sauce_spec_chrome.rb +43 -0
  295. data/spec/selector_spec.rb +458 -37
  296. data/spec/selenium_spec_chrome.rb +196 -9
  297. data/spec/selenium_spec_chrome_remote.rb +100 -0
  298. data/spec/selenium_spec_edge.rb +47 -0
  299. data/spec/selenium_spec_firefox.rb +210 -0
  300. data/spec/selenium_spec_firefox_remote.rb +80 -0
  301. data/spec/selenium_spec_ie.rb +150 -0
  302. data/spec/selenium_spec_safari.rb +148 -0
  303. data/spec/server_spec.rb +200 -101
  304. data/spec/session_spec.rb +91 -0
  305. data/spec/shared_selenium_node.rb +83 -0
  306. data/spec/shared_selenium_session.rb +558 -0
  307. data/spec/spec_helper.rb +94 -2
  308. data/spec/xpath_builder_spec.rb +93 -0
  309. metadata +420 -60
  310. data/lib/capybara/query.rb +0 -7
  311. data/lib/capybara/spec/session/assert_current_path.rb +0 -60
  312. data/lib/capybara/spec/session/assert_selector.rb +0 -148
  313. data/lib/capybara/spec/session/assert_text.rb +0 -196
  314. data/lib/capybara/spec/session/assert_title.rb +0 -70
  315. data/lib/capybara/spec/session/source_spec.rb +0 -0
  316. data/lib/capybara/spec/session/within_frame_spec.rb +0 -53
  317. data/spec/rspec/matchers_spec.rb +0 -827
  318. data/spec/selenium_spec.rb +0 -151
@@ -1,4 +1,4 @@
1
- <%# frozen_string_literal: true %>
1
+
2
2
  <h1>This page is used for testing various scopes</h1>
3
3
 
4
4
  <p id="for_foo">
@@ -0,0 +1,6 @@
1
+
2
+ <h1>This page is used for testing various scopes</h1>
3
+
4
+ <p id="for_foo">
5
+ Different text same wrapper id
6
+ </p>
@@ -1,2 +1,2 @@
1
- <%# frozen_string_literal: true %>
1
+
2
2
  Bar
@@ -0,0 +1,21 @@
1
+ <html xmlns="http://www.w3.org/1999/xhtml" lang="en">
2
+ <head>
3
+ <meta http-equiv="Content-type" content="text/html; charset=utf-8"/>
4
+ <title>with_sortable_js</title>
5
+ <script src="https://cdn.jsdelivr.net/npm/sortablejs@1.12.0/dist/sortable.umd.min.js" type="text/javascript"></script>
6
+ </head>
7
+
8
+ <body id="with_sortable_js">
9
+ <div id="sortable">
10
+ <div class="item1">Item 1</div>
11
+ <div class="item2">Item 2</div>
12
+ <div class="item3">Item 3</div>
13
+ <div class="item4">Item 4</div>
14
+ <div class="item5">Item 5</div>
15
+ </div>
16
+ <script>
17
+ new Sortable(document.getElementById("sortable"));
18
+ </script>
19
+ </body>
20
+ </html>
21
+
@@ -1,4 +1,4 @@
1
- <%# frozen_string_literal: true %>
1
+
2
2
  <title>Test Title</title>
3
3
  <body>
4
4
  <svg><title>abcdefg</title></svg>
@@ -8,5 +8,7 @@
8
8
  </head>
9
9
  <body>
10
10
  <div>This triggers an alert on unload</div>
11
+
12
+ <a href="/">Go away</a>
11
13
  </body>
12
- </html>
14
+ </html>
@@ -1,4 +1,4 @@
1
- <%# frozen_string_literal: true %>
1
+
2
2
  <html>
3
3
  <head>
4
4
  <title>With Windows</title>
@@ -29,6 +29,8 @@
29
29
  window.open('/popup_two', 'secondPopup');
30
30
  return false;
31
31
  });
32
+
33
+ $('body').addClass('loaded');
32
34
  });
33
35
  </script>
34
36
  </head>
@@ -44,5 +46,9 @@
44
46
  <button id="doesNotOpenWindows">Does not open windows</button>
45
47
 
46
48
  <iframe src="/frame_one" id="frameOne"></iframe>
49
+
50
+ <div id="scope">
51
+ <span>My scoped content</span>
52
+ </div>
47
53
  </body>
48
54
  </html>
@@ -1,11 +1,14 @@
1
- <%# frozen_string_literal: true %>
1
+
2
2
  <html>
3
3
  <head>
4
4
  <title>With Frames</title>
5
5
  </head>
6
6
  <body>
7
- <div id="divInMainWindow">This is the text for divInMainWindow</div>
8
- <iframe src="/frame_one" id="frameOne"></iframe>
7
+ <div id="divInMainWindow">
8
+ This is the text for divInMainWindow
9
+ <iframe src="/frame_parent" id="innerParentFrame"></iframe>
10
+ </div>
11
+ <iframe src="/frame_one" id="frameOne" name="my frame one"></iframe>
9
12
  <iframe src="/frame_two" id="frameTwo"></iframe>
10
13
  <iframe src="/frame_parent" id="parentFrame"></iframe>
11
14
  </body>
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Capybara
3
- VERSION = '2.7.0'
4
+ VERSION = '3.35.3'
4
5
  end
@@ -1,9 +1,10 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Capybara
3
4
  ##
4
- # The Window class represents a browser window.
5
+ # The {Window} class represents a browser window.
5
6
  #
6
- # You can get an instance of the class by calling either of:
7
+ # You can get an instance of the class by calling any of:
7
8
  #
8
9
  # * {Capybara::Session#windows}
9
10
  # * {Capybara::Session#current_window}
@@ -11,12 +12,12 @@ module Capybara
11
12
  # * {Capybara::Session#switch_to_window}
12
13
  #
13
14
  # Note that some drivers (e.g. Selenium) support getting size of/resizing/closing only
14
- # current window. So if you invoke such method for:
15
+ # current window. So if you invoke such method for:
15
16
  #
16
- # * window that is current, Capybara will make 2 Selenium method invocations
17
- # (get handle of current window + get size/resize/close).
18
- # * window that is not current, Capybara will make 4 Selenium method invocations
19
- # (get handle of current window + switch to given handle + get size/resize/close + switch to original handle)
17
+ # * window that is current, Capybara will make 2 Selenium method invocations
18
+ # (get handle of current window + get size/resize/close).
19
+ # * window that is not current, Capybara will make 4 Selenium method invocations
20
+ # (get handle of current window + switch to given handle + get size/resize/close + switch to original handle)
20
21
  #
21
22
  class Window
22
23
  # @return [String] a string that uniquely identifies window within session
@@ -56,12 +57,12 @@ module Capybara
56
57
  # Close window.
57
58
  #
58
59
  # If this method was called for window that is current, then after calling this method
59
- # future invocations of other Capybara methods should raise
60
- # `session.driver.no_such_window_error` until another window will be switched to.
60
+ # future invocations of other Capybara methods should raise
61
+ # {Capybara::Driver::Base#no_such_window_error session.driver.no_such_window_error} until another window will be switched to.
61
62
  #
62
63
  # @!macro about_current
63
64
  # If this method was called for window that is not current, then after calling this method
64
- # current window shouldn remain the same as it was before calling this method.
65
+ # current window should remain the same as it was before calling this method.
65
66
  #
66
67
  def close
67
68
  @driver.close_window(handle)
@@ -71,7 +72,7 @@ module Capybara
71
72
  # Get window size.
72
73
  #
73
74
  # @macro about_current
74
- # @return [Array<(Fixnum, Fixnum)>] an array with width and height
75
+ # @return [Array<(Integer, Integer)>] an array with width and height
75
76
  #
76
77
  def size
77
78
  @driver.window_size(handle)
@@ -81,27 +82,38 @@ module Capybara
81
82
  # Resize window.
82
83
  #
83
84
  # @macro about_current
84
- # @param width [String] the new window width in pixels
85
- # @param height [String] the new window height in pixels
85
+ # @param width [Integer] the new window width in pixels
86
+ # @param height [Integer] the new window height in pixels
86
87
  #
87
88
  def resize_to(width, height)
88
- @driver.resize_window_to(handle, width, height)
89
+ wait_for_stable_size { @driver.resize_window_to(handle, width, height) }
89
90
  end
90
91
 
91
92
  ##
92
93
  # Maximize window.
93
94
  #
94
95
  # If a particular driver (e.g. headless driver) doesn't have concept of maximizing it
95
- # may not support this method.
96
+ # may not support this method.
96
97
  #
97
98
  # @macro about_current
98
99
  #
99
100
  def maximize
100
- @driver.maximize_window(handle)
101
+ wait_for_stable_size { @driver.maximize_window(handle) }
102
+ end
103
+
104
+ ##
105
+ # Fullscreen window.
106
+ #
107
+ # If a particular driver doesn't have concept of fullscreen it may not support this method.
108
+ #
109
+ # @macro about_current
110
+ #
111
+ def fullscreen
112
+ @driver.fullscreen_window(handle)
101
113
  end
102
114
 
103
115
  def eql?(other)
104
- other.kind_of?(self.class) && @session == other.session && @handle == other.handle
116
+ other.is_a?(self.class) && @session == other.session && @handle == other.handle
105
117
  end
106
118
  alias_method :==, :eql?
107
119
 
@@ -113,12 +125,18 @@ module Capybara
113
125
  "#<Window @handle=#{@handle.inspect}>"
114
126
  end
115
127
 
116
- private
128
+ private
117
129
 
118
- def raise_unless_current(what)
119
- unless current?
120
- raise Capybara::WindowError, "#{what} not current window is not possible."
130
+ def wait_for_stable_size(seconds = session.config.default_max_wait_time)
131
+ res = yield if block_given?
132
+ timer = Capybara::Helpers.timer(expire_in: seconds)
133
+ loop do
134
+ prev_size = size
135
+ sleep 0.025
136
+ return res if prev_size == size
137
+ break if timer.expired?
121
138
  end
139
+ raise Capybara::WindowError, "Window size not stable within #{seconds} seconds."
122
140
  end
123
141
  end
124
142
  end
data/lib/capybara.rb CHANGED
@@ -1,7 +1,11 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require 'timeout'
3
4
  require 'nokogiri'
4
5
  require 'xpath'
6
+ require 'forwardable'
7
+ require 'capybara/config'
8
+ require 'capybara/registration_container'
5
9
 
6
10
  module Capybara
7
11
  class CapybaraError < StandardError; end
@@ -20,14 +24,39 @@ module Capybara
20
24
  class ReadOnlyElementError < CapybaraError; end
21
25
 
22
26
  class << self
23
- attr_accessor :asset_host, :app_host, :run_server, :default_host, :always_include_port
24
- attr_accessor :server_port, :exact, :match, :exact_options, :visible_text_only
25
- attr_accessor :default_selector, :default_max_wait_time, :ignore_hidden_elements
26
- attr_accessor :save_path, :wait_on_first_by_default, :automatic_reload
27
- attr_accessor :reuse_server, :raise_server_errors, :server_errors
28
- attr_writer :default_driver, :current_driver, :javascript_driver, :session_name, :server_host
29
- attr_reader :save_and_open_page_path
30
- attr_accessor :app
27
+ extend Forwardable
28
+
29
+ # DelegateCapybara global configurations
30
+ # @!method app
31
+ # See {Capybara.configure}
32
+ # @!method reuse_server
33
+ # See {Capybara.configure}
34
+ # @!method threadsafe
35
+ # See {Capybara.configure}
36
+ # @!method server
37
+ # See {Capybara.configure}
38
+ # @!method default_driver
39
+ # See {Capybara.configure}
40
+ # @!method javascript_driver
41
+ # See {Capybara.configure}
42
+ # @!method allow_gumbo
43
+ # See {Capybara.configure}
44
+ Config::OPTIONS.each do |method|
45
+ def_delegators :config, method, "#{method}="
46
+ end
47
+
48
+ # Delegate Capybara global configurations
49
+ # @!method default_selector
50
+ # See {Capybara.configure}
51
+ # @!method default_max_wait_time
52
+ # See {Capybara.configure}
53
+ # @!method app_host
54
+ # See {Capybara.configure}
55
+ # @!method always_include_port
56
+ # See {Capybara.configure}
57
+ SessionConfig::OPTIONS.each do |method|
58
+ def_delegators :config, method, "#{method}="
59
+ end
31
60
 
32
61
  ##
33
62
  #
@@ -38,30 +67,50 @@ module Capybara
38
67
  # config.app_host = 'http://www.google.com'
39
68
  # end
40
69
  #
41
- # === Configurable options
42
- #
43
- # [app_host = String] The default host to use when giving a relative URL to visit
44
- # [always_include_port = Boolean] Whether the Rack server's port should automatically be inserted into every visited URL (Default: false)
45
- # [asset_host = String] Where dynamic assets are hosted - will be prepended to relative asset locations if present (Default: nil)
46
- # [run_server = Boolean] Whether to start a Rack server for the given Rack app (Default: true)
47
- # [raise_server_errors = Boolean] Should errors raised in the server be raised in the tests? (Default: true)
48
- # [server_errors = Array\<Class\>] Error classes that should be raised in the tests if they are raised in the server and Capybara.raise_server_errors is true (Default: [StandardError])
49
- # [default_selector = :css/:xpath] Methods which take a selector use the given type by default (Default: :css)
50
- # [default_max_wait_time = Numeric] The maximum number of seconds to wait for asynchronous processes to finish (Default: 2)
51
- # [ignore_hidden_elements = Boolean] Whether to ignore hidden elements on the page (Default: true)
52
- # [automatic_reload = Boolean] Whether to automatically reload elements as Capybara is waiting (Default: true)
53
- # [save_path = String] Where to put pages saved through save_(page|screenshot), save_and_open_(page|screenshot) (Default: Dir.pwd)
54
- # [wait_on_first_by_default = Boolean] Whether Node#first defaults to Capybara waiting behavior for at least 1 element to match (Default: false)
55
- # [reuse_server = Boolean] Reuse the server thread between multiple sessions using the same app object (Default: true)
56
- # === DSL Options
57
- #
58
- # when using capybara/dsl, the following options are also available:
59
- #
60
- # [default_driver = Symbol] The name of the driver to use by default. (Default: :rack_test)
61
- # [javascript_driver = Symbol] The name of a driver to use for JavaScript enabled tests. (Default: :selenium)
70
+ # #### Configurable options
71
+ #
72
+ # - **allow_gumbo** (Boolean = `false`) - When `nokogumbo` is available, whether it will be used to parse HTML strings.
73
+ # - **always_include_port** (Boolean = `false`) - Whether the Rack server's port should automatically be inserted into every visited URL
74
+ # unless another port is explicitly specified.
75
+ # - **app_host** (String, `nil`) - The default host to use when giving a relative URL to visit, must be a valid URL e.g. `http://www.example.com`.
76
+ # - **asset_host** (String = `nil`) - Where dynamic assets are hosted - will be prepended to relative asset locations if present.
77
+ # - **automatic_label_click** (Boolean = `false`) - Whether {Capybara::Node::Element#choose Element#choose}, {Capybara::Node::Element#check Element#check},
78
+ # {Capybara::Node::Element#uncheck Element#uncheck} will attempt to click the associated `<label>` element if the checkbox/radio button are non-visible.
79
+ # - **automatic_reload** (Boolean = `true`) - Whether to automatically reload elements as Capybara is waiting.
80
+ # - **default_max_wait_time** (Numeric = `2`) - The maximum number of seconds to wait for asynchronous processes to finish.
81
+ # - **default_normalize_ws** (Boolean = `false`) - Whether text predicates and matchers use normalize whitespace behavior.
82
+ # - **default_selector** (`:css`, `:xpath` = `:css`) - Methods which take a selector use the given type by default. See also {Capybara::Selector}.
83
+ # - **default_set_options** (Hash = `{}`) - The default options passed to {Capybara::Node::Element#set Element#set}.
84
+ # - **enable_aria_label** (Boolean = `false`) - Whether fields, links, and buttons will match against `aria-label` attribute.
85
+ # - **enable_aria_role** (Boolean = `false`) - Selectors will check for relevant aria role (currently only `button`).
86
+ # - **exact** (Boolean = `false`) - Whether locators are matched exactly or with substrings. Only affects selector conditions
87
+ # written using the `XPath#is` method.
88
+ # - **exact_text** (Boolean = `false`) - Whether the text matchers and `:text` filter match exactly or on substrings.
89
+ # - **ignore_hidden_elements** (Boolean = `true`) - Whether to ignore hidden elements on the page.
90
+ # - **match** (`:one`, `:first`, `:prefer_exact`, `:smart` = `:smart`) - The matching strategy to find nodes.
91
+ # - **predicates_wait** (Boolean = `true`) - Whether Capybara's predicate matchers use waiting behavior by default.
92
+ # - **raise_server_errors** (Boolean = `true`) - Should errors raised in the server be raised in the tests?
93
+ # - **reuse_server** (Boolean = `true`) - Whether to reuse the server thread between multiple sessions using the same app object.
94
+ # - **run_server** (Boolean = `true`) - Whether to start a Rack server for the given Rack app.
95
+ # - **save_path** (String = `Dir.pwd`) - Where to put pages saved through {Capybara::Session#save_page save_page}, {Capybara::Session#save_screenshot save_screenshot},
96
+ # {Capybara::Session#save_and_open_page save_and_open_page}, or {Capybara::Session#save_and_open_screenshot save_and_open_screenshot}.
97
+ # - **server** (Symbol = `:default` (which uses puma)) - The name of the registered server to use when running the app under test.
98
+ # - **server_port** (Integer) - The port Capybara will run the application server on, if not specified a random port will be used.
99
+ # - **server_errors** (Array\<Class> = `[Exception]`) - Error classes that should be raised in the tests if they are raised in the server
100
+ # and {configure raise_server_errors} is `true`.
101
+ # - **test_id** (Symbol, String, `nil` = `nil`) - Optional attribute to match locator against with built-in selectors along with id.
102
+ # - **threadsafe** (Boolean = `false`) - Whether sessions can be configured individually.
103
+ # - **w3c_click_offset** (Boolean = 'false') - Whether click offsets should be from element center (true) or top left (false)
104
+ #
105
+ # #### DSL Options
106
+ #
107
+ # When using `capybara/dsl`, the following options are also available:
108
+ #
109
+ # - **default_driver** (Symbol = `:rack_test`) - The name of the driver to use by default.
110
+ # - **javascript_driver** (Symbol = `:selenium`) - The name of a driver to use for JavaScript enabled tests.
62
111
  #
63
112
  def configure
64
- yield self
113
+ yield config
65
114
  end
66
115
 
67
116
  ##
@@ -78,7 +127,7 @@ module Capybara
78
127
  # @yieldreturn [Capybara::Driver::Base] A Capybara driver instance
79
128
  #
80
129
  def register_driver(name, &block)
81
- drivers[name] = block
130
+ drivers.send(:register, name, block)
82
131
  end
83
132
 
84
133
  ##
@@ -95,10 +144,9 @@ module Capybara
95
144
  # @yieldparam [<Rack>] app The rack application that this server will contain.
96
145
  # @yieldparam port The port number the server should listen on
97
146
  # @yieldparam host The host/ip to bind to
98
- # @yieldreturn [Capybara::Driver::Base] A Capybara driver instance
99
147
  #
100
148
  def register_server(name, &block)
101
- servers[name.to_sym] = block
149
+ servers.send(:register, name.to_sym, block)
102
150
  end
103
151
 
104
152
  ##
@@ -129,20 +177,21 @@ module Capybara
129
177
  # @param [Symbol] name The name of the selector to add
130
178
  # @yield A block executed in the context of the new {Capybara::Selector}
131
179
  #
132
- def add_selector(name, &block)
133
- Capybara::Selector.add(name, &block)
180
+ def add_selector(name, **options, &block)
181
+ Capybara::Selector.add(name, **options, &block)
134
182
  end
135
183
 
136
184
  ##
137
185
  #
138
186
  # Modify a selector previously created by {Capybara.add_selector}.
139
- # For example modifying the :button selector to also find divs styled
140
- # to look like buttons might look like this
187
+ # For example, adding a new filter to the :button selector to filter based on
188
+ # button style (a class) might look like this
141
189
  #
142
190
  # Capybara.modify_selector(:button) do
143
- # xpath { |locator| XPath::HTML.button(locator).or(XPath::css('div.btn')[XPath::string.n.is(locator)]) }
191
+ # filter (:btn_style, valid_values: [:primary, :secondary]) { |node, style| node[:class].split.include? "btn-#{style}" }
144
192
  # end
145
193
  #
194
+ #
146
195
  # @param [Symbol] name The name of the selector to modify
147
196
  # @yield A block executed in the context of the existing {Capybara::Selector}
148
197
  #
@@ -151,69 +200,26 @@ module Capybara
151
200
  end
152
201
 
153
202
  def drivers
154
- @drivers ||= {}
203
+ @drivers ||= RegistrationContainer.new
155
204
  end
156
205
 
157
206
  def servers
158
- @servers ||= {}
159
- end
160
-
161
- ##
162
- #
163
- # Register a proc that Capybara will call to run the Rack application.
164
- #
165
- # Capybara.server do |app, port, host|
166
- # require 'rack/handler/mongrel'
167
- # Rack::Handler::Mongrel.run(app, :Port => port)
168
- # end
169
- #
170
- # By default, Capybara will try to run webrick.
171
- #
172
- # @yield [app, port, host] This block receives a rack app, port, and host/ip and should run a Rack handler
173
- #
174
- def server(&block)
175
- if block_given?
176
- warn "DEPRECATED: Passing a block to Capybara::server is deprecated, please use Capybara::register_server instead"
177
- @server = block
178
- else
179
- @server
180
- end
181
- end
182
-
183
- ##
184
- #
185
- # Set the server to use.
186
- #
187
- # Capybara.server = :webrick
188
- #
189
- # @param [Symbol] name Name of the server type to use
190
- # @see register_server
191
- #
192
- def server=(name)
193
- @server = if name.respond_to? :call
194
- name
195
- else
196
- servers[name.to_sym]
197
- end
207
+ @servers ||= RegistrationContainer.new
198
208
  end
199
209
 
200
- ##
201
- #
202
210
  # Wraps the given string, which should contain an HTML document or fragment
203
211
  # in a {Capybara::Node::Simple} which exposes all {Capybara::Node::Matchers},
204
212
  # {Capybara::Node::Finders} and {Capybara::Node::DocumentMatchers}. This allows you to query
205
213
  # any string containing HTML in the exact same way you would query the current document in a Capybara
206
214
  # session.
207
215
  #
208
- # Example: A single element
209
- #
216
+ # @example A single element
210
217
  # node = Capybara.string('<a href="foo">bar</a>')
211
218
  # anchor = node.first('a')
212
219
  # anchor[:href] #=> 'foo'
213
220
  # anchor.text #=> 'bar'
214
221
  #
215
- # Example: Multiple elements
216
- #
222
+ # @example Multiple elements
217
223
  # node = Capybara.string <<-HTML
218
224
  # <ul>
219
225
  # <li id="home">Home</li>
@@ -222,7 +228,7 @@ module Capybara
222
228
  # HTML
223
229
  #
224
230
  # node.find('#projects').text # => 'Projects'
225
- # node.has_selector?('li#home', :text => 'Home')
231
+ # node.has_selector?('li#home', text: 'Home')
226
232
  # node.has_selector?('#projects')
227
233
  # node.find('ul').find('li:first-child').text # => 'Home'
228
234
  #
@@ -240,18 +246,10 @@ module Capybara
240
246
  # manually.
241
247
  #
242
248
  # @param [Rack Application] app The rack application to run
243
- # @param [Fixnum] port The port to run the application on
249
+ # @param [Integer] port The port to run the application on
244
250
  #
245
251
  def run_default_server(app, port)
246
- servers[:webrick].call(app, port, server_host)
247
- end
248
-
249
- ##
250
- #
251
- # @return [Symbol] The name of the driver to use by default
252
- #
253
- def default_driver
254
- @default_driver || :rack_test
252
+ servers[:puma].call(app, port, server_host)
255
253
  end
256
254
 
257
255
  ##
@@ -259,16 +257,20 @@ module Capybara
259
257
  # @return [Symbol] The name of the driver currently in use
260
258
  #
261
259
  def current_driver
262
- @current_driver || default_driver
260
+ if threadsafe
261
+ Thread.current['capybara_current_driver']
262
+ else
263
+ @current_driver
264
+ end || default_driver
263
265
  end
264
266
  alias_method :mode, :current_driver
265
267
 
266
- ##
267
- #
268
- # @return [Symbol] The name of the driver used when JavaScript is needed
269
- #
270
- def javascript_driver
271
- @javascript_driver || :selenium
268
+ def current_driver=(name)
269
+ if threadsafe
270
+ Thread.current['capybara_current_driver'] = name
271
+ else
272
+ @current_driver = name
273
+ end
272
274
  end
273
275
 
274
276
  ##
@@ -276,7 +278,7 @@ module Capybara
276
278
  # Use the default driver as the current driver
277
279
  #
278
280
  def use_default_driver
279
- @current_driver = nil
281
+ self.current_driver = nil
280
282
  end
281
283
 
282
284
  ##
@@ -288,15 +290,7 @@ module Capybara
288
290
  Capybara.current_driver = driver
289
291
  yield
290
292
  ensure
291
- @current_driver = previous_driver
292
- end
293
-
294
- ##
295
- #
296
- # @return [String] The IP address bound by default server
297
- #
298
- def server_host
299
- @server_host || '127.0.0.1'
293
+ self.current_driver = previous_driver
300
294
  end
301
295
 
302
296
  ##
@@ -313,12 +307,12 @@ module Capybara
313
307
 
314
308
  ##
315
309
  #
316
- # The current Capybara::Session based on what is set as Capybara.app and Capybara.current_driver
310
+ # The current {Capybara::Session} based on what is set as {app} and {current_driver}.
317
311
  #
318
312
  # @return [Capybara::Session] The currently used session
319
313
  #
320
314
  def current_session
321
- session_pool["#{current_driver}:#{session_name}:#{app.object_id}"] ||= Capybara::Session.new(current_driver, app)
315
+ specified_session || session_pool["#{current_driver}:#{session_name}:#{app.object_id}"]
322
316
  end
323
317
 
324
318
  ##
@@ -327,7 +321,8 @@ module Capybara
327
321
  # as cookies.
328
322
  #
329
323
  def reset_sessions!
330
- session_pool.each { |mode, session| session.reset! }
324
+ # reset in reverse so sessions that started servers are reset last
325
+ session_pool.reverse_each { |_mode, session| session.reset! }
331
326
  end
332
327
  alias_method :reset!, :reset_sessions!
333
328
 
@@ -338,19 +333,48 @@ module Capybara
338
333
  # @return [Symbol] The name of the currently used session.
339
334
  #
340
335
  def session_name
341
- @session_name ||= :default
336
+ if threadsafe
337
+ Thread.current['capybara_session_name'] ||= :default
338
+ else
339
+ @session_name ||= :default
340
+ end
341
+ end
342
+
343
+ def session_name=(name)
344
+ if threadsafe
345
+ Thread.current['capybara_session_name'] = name
346
+ else
347
+ @session_name = name
348
+ end
342
349
  end
343
350
 
344
351
  ##
345
352
  #
346
- # Yield a block using a specific session name.
347
- #
348
- def using_session(name)
349
- previous_session_name = self.session_name
350
- self.session_name = name
351
- yield
353
+ # Yield a block using a specific session name or {Capybara::Session} instance.
354
+ #
355
+ def using_session(name_or_session, &block)
356
+ previous_session = current_session
357
+ previous_session_info = {
358
+ specified_session: specified_session,
359
+ session_name: session_name,
360
+ current_driver: current_driver,
361
+ app: app
362
+ }
363
+ self.specified_session = self.session_name = nil
364
+ if name_or_session.is_a? Capybara::Session
365
+ self.specified_session = name_or_session
366
+ else
367
+ self.session_name = name_or_session
368
+ end
369
+
370
+ if block.arity.zero?
371
+ yield
372
+ else
373
+ yield current_session, previous_session
374
+ end
352
375
  ensure
353
- self.session_name = previous_session_name
376
+ self.session_name, self.specified_session = previous_session_info.values_at(:session_name, :specified_session)
377
+ self.current_driver, self.app = previous_session_info.values_at(:current_driver, :app) if threadsafe
354
378
  end
355
379
 
356
380
  ##
@@ -360,52 +384,61 @@ module Capybara
360
384
  # @param [String] html The raw html
361
385
  # @return [Nokogiri::HTML::Document] HTML document
362
386
  #
363
- def HTML(html)
364
- Nokogiri::HTML(html).tap do |document|
365
- document.xpath('//textarea').each do |textarea|
366
- textarea.content=textarea.content.sub(/\A\n/,'')
387
+ def HTML(html) # rubocop:disable Naming/MethodName
388
+ if Nokogiri.respond_to?(:HTML5) && Capybara.allow_gumbo # Nokogumbo installed and allowed for use
389
+ Nokogiri::HTML5(html).tap do |document|
390
+ document.xpath('//template').each do |template|
391
+ # template elements content is not part of the document
392
+ template.inner_html = ''
393
+ end
394
+ document.xpath('//textarea').each do |textarea|
395
+ # The Nokogumbo HTML5 parser already returns spec compliant contents
396
+ textarea['_capybara_raw_value'] = textarea.content
397
+ end
398
+ end
399
+ else
400
+ Nokogiri::HTML(html).tap do |document|
401
+ document.xpath('//template').each do |template|
402
+ # template elements content is not part of the document
403
+ template.inner_html = ''
404
+ end
405
+ document.xpath('//textarea').each do |textarea|
406
+ textarea['_capybara_raw_value'] = textarea.content.delete_prefix("\n")
407
+ end
367
408
  end
368
409
  end
369
410
  end
370
411
 
371
- # @deprecated Use default_max_wait_time instead
372
- def default_wait_time
373
- deprecate('default_wait_time', 'default_max_wait_time', true)
374
- default_max_wait_time
375
- end
376
-
377
- # @deprecated Use default_max_wait_time= instead
378
- def default_wait_time=(t)
379
- deprecate('default_wait_time=', 'default_max_wait_time=')
380
- self.default_max_wait_time = t
412
+ def session_options
413
+ config.session_options
381
414
  end
382
415
 
383
- def save_and_open_page_path=(path)
384
- warn "DEPRECATED: #save_and_open_page_path is deprecated, please use #save_path instead. \n"\
385
- "Note: Behavior is slightly different with relative paths - see documentation" unless path.nil?
386
- @save_and_open_page_path = path
387
- end
416
+ private
388
417
 
389
- def included(base)
390
- base.send(:include, Capybara::DSL)
391
- warn "`include Capybara` is deprecated. Please use `include Capybara::DSL` instead."
418
+ def config
419
+ @config ||= Capybara::Config.new
392
420
  end
393
421
 
394
- def reuse_server=(bool)
395
- warn "Capybara.reuse_server == false is a BETA feature and may change in a future version" unless bool
396
- @reuse_server = bool
422
+ def session_pool
423
+ @session_pool ||= Hash.new do |hash, name|
424
+ hash[name] = Capybara::Session.new(current_driver, app)
425
+ end
397
426
  end
398
427
 
399
- def deprecate(method, alternate_method, once=false)
400
- @deprecation_notified ||= {}
401
- warn "DEPRECATED: ##{method} is deprecated, please use ##{alternate_method} instead" unless once and @deprecation_notified[method]
402
- @deprecation_notified[method]=true
428
+ def specified_session
429
+ if threadsafe
430
+ Thread.current['capybara_specified_session']
431
+ else
432
+ @specified_session ||= nil
433
+ end
403
434
  end
404
435
 
405
- private
406
-
407
- def session_pool
408
- @session_pool ||= {}
436
+ def specified_session=(session)
437
+ if threadsafe
438
+ Thread.current['capybara_specified_session'] = session
439
+ else
440
+ @specified_session = session
441
+ end
409
442
  end
410
443
  end
411
444
 
@@ -431,7 +464,9 @@ module Capybara
431
464
  require 'capybara/queries/title_query'
432
465
  require 'capybara/queries/current_path_query'
433
466
  require 'capybara/queries/match_query'
434
- require 'capybara/query'
467
+ require 'capybara/queries/ancestor_query'
468
+ require 'capybara/queries/sibling_query'
469
+ require 'capybara/queries/style_query'
435
470
 
436
471
  require 'capybara/node/finders'
437
472
  require 'capybara/node/matchers'
@@ -449,27 +484,14 @@ module Capybara
449
484
  require 'capybara/rack_test/node'
450
485
  require 'capybara/rack_test/form'
451
486
  require 'capybara/rack_test/browser'
452
- require 'capybara/rack_test/css_handlers.rb'
487
+ require 'capybara/rack_test/css_handlers'
453
488
 
454
489
  require 'capybara/selenium/node'
455
490
  require 'capybara/selenium/driver'
456
491
  end
457
492
 
458
- Capybara.register_server :default do |app, port, host|
459
- Capybara.run_default_server(app, port)
460
- end
461
-
462
- Capybara.register_server :webrick do |app, port, host|
463
- require 'rack/handler/webrick'
464
- Rack::Handler::WEBrick.run(app, :Host => host, :Port => port, :AccessLog => [], :Logger => WEBrick::Log::new(nil, 0))
465
- end
466
-
467
- Capybara.register_server :puma do |app, port, host|
468
- require 'puma'
469
- Puma::Server.new(app).tap do |s|
470
- s.add_tcp_listener host, port
471
- end.run.join
472
- end
493
+ require 'capybara/registrations/servers'
494
+ require 'capybara/registrations/drivers'
473
495
 
474
496
  Capybara.configure do |config|
475
497
  config.always_include_port = false
@@ -478,22 +500,22 @@ Capybara.configure do |config|
478
500
  config.default_selector = :css
479
501
  config.default_max_wait_time = 2
480
502
  config.ignore_hidden_elements = true
481
- config.default_host = "http://www.example.com"
503
+ config.default_host = 'http://www.example.com'
482
504
  config.automatic_reload = true
483
505
  config.match = :smart
484
506
  config.exact = false
507
+ config.exact_text = false
485
508
  config.raise_server_errors = true
486
- config.server_errors = [StandardError]
509
+ config.server_errors = [Exception]
487
510
  config.visible_text_only = false
488
- config.wait_on_first_by_default = false
511
+ config.automatic_label_click = false
512
+ config.enable_aria_label = false
513
+ config.enable_aria_role = false
489
514
  config.reuse_server = true
515
+ config.default_set_options = {}
516
+ config.test_id = nil
517
+ config.predicates_wait = true
518
+ config.default_normalize_ws = false
519
+ config.allow_gumbo = false
520
+ config.w3c_click_offset = false
490
521
  end
491
-
492
- Capybara.register_driver :rack_test do |app|
493
- Capybara::RackTest::Driver.new(app)
494
- end
495
-
496
- Capybara.register_driver :selenium do |app|
497
- Capybara::Selenium::Driver.new(app)
498
- end
499
-