capybara 3.0.0 → 3.36.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (308) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +1 -1
  3. data/History.md +777 -10
  4. data/License.txt +1 -1
  5. data/README.md +75 -58
  6. data/lib/capybara/config.rb +29 -10
  7. data/lib/capybara/cucumber.rb +1 -1
  8. data/lib/capybara/driver/base.rb +22 -4
  9. data/lib/capybara/driver/node.rb +34 -9
  10. data/lib/capybara/dsl.rb +14 -6
  11. data/lib/capybara/helpers.rb +52 -7
  12. data/lib/capybara/minitest/spec.rb +173 -84
  13. data/lib/capybara/minitest.rb +250 -144
  14. data/lib/capybara/node/actions.rb +248 -124
  15. data/lib/capybara/node/base.rb +34 -20
  16. data/lib/capybara/node/document.rb +14 -2
  17. data/lib/capybara/node/document_matchers.rb +13 -15
  18. data/lib/capybara/node/element.rb +339 -113
  19. data/lib/capybara/node/finders.rb +95 -82
  20. data/lib/capybara/node/matchers.rb +338 -157
  21. data/lib/capybara/node/simple.rb +54 -15
  22. data/lib/capybara/queries/active_element_query.rb +18 -0
  23. data/lib/capybara/queries/ancestor_query.rb +9 -10
  24. data/lib/capybara/queries/base_query.rb +25 -18
  25. data/lib/capybara/queries/current_path_query.rb +16 -6
  26. data/lib/capybara/queries/match_query.rb +11 -0
  27. data/lib/capybara/queries/selector_query.rb +600 -103
  28. data/lib/capybara/queries/sibling_query.rb +9 -7
  29. data/lib/capybara/queries/style_query.rb +45 -0
  30. data/lib/capybara/queries/text_query.rb +40 -22
  31. data/lib/capybara/queries/title_query.rb +2 -2
  32. data/lib/capybara/rack_test/browser.rb +47 -28
  33. data/lib/capybara/rack_test/driver.rb +12 -3
  34. data/lib/capybara/rack_test/errors.rb +6 -0
  35. data/lib/capybara/rack_test/form.rb +53 -50
  36. data/lib/capybara/rack_test/node.rb +114 -37
  37. data/lib/capybara/rails.rb +1 -1
  38. data/lib/capybara/registration_container.rb +44 -0
  39. data/lib/capybara/registrations/drivers.rb +42 -0
  40. data/lib/capybara/registrations/patches/puma_ssl.rb +29 -0
  41. data/lib/capybara/registrations/servers.rb +45 -0
  42. data/lib/capybara/result.rb +86 -52
  43. data/lib/capybara/rspec/features.rb +8 -10
  44. data/lib/capybara/rspec/matcher_proxies.rb +39 -18
  45. data/lib/capybara/rspec/matchers/base.rb +111 -0
  46. data/lib/capybara/rspec/matchers/become_closed.rb +33 -0
  47. data/lib/capybara/rspec/matchers/compound.rb +88 -0
  48. data/lib/capybara/rspec/matchers/count_sugar.rb +37 -0
  49. data/lib/capybara/rspec/matchers/have_ancestor.rb +28 -0
  50. data/lib/capybara/rspec/matchers/have_current_path.rb +29 -0
  51. data/lib/capybara/rspec/matchers/have_selector.rb +77 -0
  52. data/lib/capybara/rspec/matchers/have_sibling.rb +27 -0
  53. data/lib/capybara/rspec/matchers/have_text.rb +33 -0
  54. data/lib/capybara/rspec/matchers/have_title.rb +29 -0
  55. data/lib/capybara/rspec/matchers/match_selector.rb +27 -0
  56. data/lib/capybara/rspec/matchers/match_style.rb +43 -0
  57. data/lib/capybara/rspec/matchers/spatial_sugar.rb +39 -0
  58. data/lib/capybara/rspec/matchers.rb +138 -316
  59. data/lib/capybara/rspec.rb +3 -2
  60. data/lib/capybara/selector/builders/css_builder.rb +84 -0
  61. data/lib/capybara/selector/builders/xpath_builder.rb +71 -0
  62. data/lib/capybara/selector/css.rb +89 -12
  63. data/lib/capybara/selector/definition/button.rb +68 -0
  64. data/lib/capybara/selector/definition/checkbox.rb +26 -0
  65. data/lib/capybara/selector/definition/css.rb +10 -0
  66. data/lib/capybara/selector/definition/datalist_input.rb +35 -0
  67. data/lib/capybara/selector/definition/datalist_option.rb +25 -0
  68. data/lib/capybara/selector/definition/element.rb +28 -0
  69. data/lib/capybara/selector/definition/field.rb +40 -0
  70. data/lib/capybara/selector/definition/fieldset.rb +14 -0
  71. data/lib/capybara/selector/definition/file_field.rb +13 -0
  72. data/lib/capybara/selector/definition/fillable_field.rb +33 -0
  73. data/lib/capybara/selector/definition/frame.rb +17 -0
  74. data/lib/capybara/selector/definition/id.rb +6 -0
  75. data/lib/capybara/selector/definition/label.rb +62 -0
  76. data/lib/capybara/selector/definition/link.rb +54 -0
  77. data/lib/capybara/selector/definition/link_or_button.rb +16 -0
  78. data/lib/capybara/selector/definition/option.rb +27 -0
  79. data/lib/capybara/selector/definition/radio_button.rb +27 -0
  80. data/lib/capybara/selector/definition/select.rb +81 -0
  81. data/lib/capybara/selector/definition/table.rb +109 -0
  82. data/lib/capybara/selector/definition/table_row.rb +21 -0
  83. data/lib/capybara/selector/definition/xpath.rb +5 -0
  84. data/lib/capybara/selector/definition.rb +279 -0
  85. data/lib/capybara/selector/filter.rb +1 -0
  86. data/lib/capybara/selector/filter_set.rb +72 -27
  87. data/lib/capybara/selector/filters/base.rb +45 -2
  88. data/lib/capybara/selector/filters/expression_filter.rb +5 -6
  89. data/lib/capybara/selector/filters/locator_filter.rb +29 -0
  90. data/lib/capybara/selector/filters/node_filter.rb +18 -4
  91. data/lib/capybara/selector/regexp_disassembler.rb +214 -0
  92. data/lib/capybara/selector/selector.rb +85 -200
  93. data/lib/capybara/selector/xpath_extensions.rb +17 -0
  94. data/lib/capybara/selector.rb +226 -537
  95. data/lib/capybara/selenium/atoms/getAttribute.min.js +1 -0
  96. data/lib/capybara/selenium/atoms/isDisplayed.min.js +1 -0
  97. data/lib/capybara/selenium/atoms/src/getAttribute.js +161 -0
  98. data/lib/capybara/selenium/atoms/src/isDisplayed.js +454 -0
  99. data/lib/capybara/selenium/driver.rb +296 -238
  100. data/lib/capybara/selenium/driver_specializations/chrome_driver.rb +117 -0
  101. data/lib/capybara/selenium/driver_specializations/edge_driver.rb +124 -0
  102. data/lib/capybara/selenium/driver_specializations/firefox_driver.rb +89 -0
  103. data/lib/capybara/selenium/driver_specializations/internet_explorer_driver.rb +26 -0
  104. data/lib/capybara/selenium/driver_specializations/safari_driver.rb +24 -0
  105. data/lib/capybara/selenium/extensions/file_input_click_emulation.rb +34 -0
  106. data/lib/capybara/selenium/extensions/find.rb +110 -0
  107. data/lib/capybara/selenium/extensions/html5_drag.rb +228 -0
  108. data/lib/capybara/selenium/extensions/modifier_keys_stack.rb +28 -0
  109. data/lib/capybara/selenium/extensions/scroll.rb +76 -0
  110. data/lib/capybara/selenium/logger_suppressor.rb +40 -0
  111. data/lib/capybara/selenium/node.rb +436 -166
  112. data/lib/capybara/selenium/nodes/chrome_node.rb +137 -0
  113. data/lib/capybara/selenium/nodes/edge_node.rb +104 -0
  114. data/lib/capybara/selenium/nodes/firefox_node.rb +136 -0
  115. data/lib/capybara/selenium/nodes/ie_node.rb +22 -0
  116. data/lib/capybara/selenium/nodes/safari_node.rb +118 -0
  117. data/lib/capybara/selenium/patches/action_pauser.rb +26 -0
  118. data/lib/capybara/selenium/patches/atoms.rb +18 -0
  119. data/lib/capybara/selenium/patches/is_displayed.rb +16 -0
  120. data/lib/capybara/selenium/patches/logs.rb +45 -0
  121. data/lib/capybara/selenium/patches/pause_duration_fix.rb +9 -0
  122. data/lib/capybara/selenium/patches/persistent_client.rb +20 -0
  123. data/lib/capybara/server/animation_disabler.rb +69 -0
  124. data/lib/capybara/server/checker.rb +44 -0
  125. data/lib/capybara/server/middleware.rb +71 -0
  126. data/lib/capybara/server.rb +58 -67
  127. data/lib/capybara/session/config.rb +38 -6
  128. data/lib/capybara/session/matchers.rb +26 -19
  129. data/lib/capybara/session.rb +258 -190
  130. data/lib/capybara/spec/public/jquery.js +5 -5
  131. data/lib/capybara/spec/public/offset.js +6 -0
  132. data/lib/capybara/spec/public/test.js +122 -8
  133. data/lib/capybara/spec/session/accept_alert_spec.rb +11 -11
  134. data/lib/capybara/spec/session/accept_confirm_spec.rb +3 -3
  135. data/lib/capybara/spec/session/accept_prompt_spec.rb +9 -10
  136. data/lib/capybara/spec/session/active_element_spec.rb +31 -0
  137. data/lib/capybara/spec/session/all_spec.rb +135 -42
  138. data/lib/capybara/spec/session/ancestor_spec.rb +24 -19
  139. data/lib/capybara/spec/session/assert_all_of_selectors_spec.rb +67 -38
  140. data/lib/capybara/spec/session/{assert_current_path.rb → assert_current_path_spec.rb} +20 -18
  141. data/lib/capybara/spec/session/assert_selector_spec.rb +143 -0
  142. data/lib/capybara/spec/session/assert_style_spec.rb +26 -0
  143. data/lib/capybara/spec/session/{assert_text.rb → assert_text_spec.rb} +62 -38
  144. data/lib/capybara/spec/session/{assert_title.rb → assert_title_spec.rb} +12 -12
  145. data/lib/capybara/spec/session/attach_file_spec.rb +120 -72
  146. data/lib/capybara/spec/session/body_spec.rb +11 -13
  147. data/lib/capybara/spec/session/check_spec.rb +111 -51
  148. data/lib/capybara/spec/session/choose_spec.rb +62 -30
  149. data/lib/capybara/spec/session/click_button_spec.rb +227 -161
  150. data/lib/capybara/spec/session/click_link_or_button_spec.rb +49 -30
  151. data/lib/capybara/spec/session/click_link_spec.rb +78 -55
  152. data/lib/capybara/spec/session/current_scope_spec.rb +7 -7
  153. data/lib/capybara/spec/session/current_url_spec.rb +44 -37
  154. data/lib/capybara/spec/session/dismiss_confirm_spec.rb +3 -3
  155. data/lib/capybara/spec/session/dismiss_prompt_spec.rb +2 -2
  156. data/lib/capybara/spec/session/element/{assert_match_selector.rb → assert_match_selector_spec.rb} +11 -9
  157. data/lib/capybara/spec/session/element/match_css_spec.rb +18 -10
  158. data/lib/capybara/spec/session/element/match_xpath_spec.rb +8 -6
  159. data/lib/capybara/spec/session/element/matches_selector_spec.rb +70 -56
  160. data/lib/capybara/spec/session/evaluate_async_script_spec.rb +7 -7
  161. data/lib/capybara/spec/session/evaluate_script_spec.rb +28 -8
  162. data/lib/capybara/spec/session/execute_script_spec.rb +8 -7
  163. data/lib/capybara/spec/session/fill_in_spec.rb +104 -44
  164. data/lib/capybara/spec/session/find_button_spec.rb +23 -23
  165. data/lib/capybara/spec/session/find_by_id_spec.rb +8 -8
  166. data/lib/capybara/spec/session/find_field_spec.rb +33 -31
  167. data/lib/capybara/spec/session/find_link_spec.rb +32 -14
  168. data/lib/capybara/spec/session/find_spec.rb +236 -141
  169. data/lib/capybara/spec/session/first_spec.rb +44 -43
  170. data/lib/capybara/spec/session/frame/frame_title_spec.rb +6 -6
  171. data/lib/capybara/spec/session/frame/frame_url_spec.rb +6 -6
  172. data/lib/capybara/spec/session/frame/switch_to_frame_spec.rb +32 -20
  173. data/lib/capybara/spec/session/frame/within_frame_spec.rb +44 -19
  174. data/lib/capybara/spec/session/go_back_spec.rb +1 -1
  175. data/lib/capybara/spec/session/go_forward_spec.rb +1 -1
  176. data/lib/capybara/spec/session/has_all_selectors_spec.rb +18 -18
  177. data/lib/capybara/spec/session/has_ancestor_spec.rb +46 -0
  178. data/lib/capybara/spec/session/has_any_selectors_spec.rb +29 -0
  179. data/lib/capybara/spec/session/has_button_spec.rb +92 -12
  180. data/lib/capybara/spec/session/has_css_spec.rb +271 -137
  181. data/lib/capybara/spec/session/has_current_path_spec.rb +48 -33
  182. data/lib/capybara/spec/session/has_field_spec.rb +137 -58
  183. data/lib/capybara/spec/session/has_link_spec.rb +30 -6
  184. data/lib/capybara/spec/session/has_none_selectors_spec.rb +26 -24
  185. data/lib/capybara/spec/session/has_select_spec.rb +75 -47
  186. data/lib/capybara/spec/session/has_selector_spec.rb +102 -69
  187. data/lib/capybara/spec/session/has_sibling_spec.rb +50 -0
  188. data/lib/capybara/spec/session/has_table_spec.rb +170 -4
  189. data/lib/capybara/spec/session/has_text_spec.rb +108 -52
  190. data/lib/capybara/spec/session/has_title_spec.rb +19 -14
  191. data/lib/capybara/spec/session/has_xpath_spec.rb +56 -38
  192. data/lib/capybara/spec/session/{headers.rb → headers_spec.rb} +1 -1
  193. data/lib/capybara/spec/session/html_spec.rb +13 -6
  194. data/lib/capybara/spec/session/matches_style_spec.rb +35 -0
  195. data/lib/capybara/spec/session/node_spec.rb +871 -122
  196. data/lib/capybara/spec/session/node_wrapper_spec.rb +15 -12
  197. data/lib/capybara/spec/session/refresh_spec.rb +9 -7
  198. data/lib/capybara/spec/session/reset_session_spec.rb +52 -37
  199. data/lib/capybara/spec/session/{response_code.rb → response_code_spec.rb} +1 -1
  200. data/lib/capybara/spec/session/save_and_open_page_spec.rb +2 -2
  201. data/lib/capybara/spec/session/save_and_open_screenshot_spec.rb +5 -4
  202. data/lib/capybara/spec/session/save_page_spec.rb +41 -38
  203. data/lib/capybara/spec/session/save_screenshot_spec.rb +13 -11
  204. data/lib/capybara/spec/session/screenshot_spec.rb +2 -2
  205. data/lib/capybara/spec/session/scroll_spec.rb +117 -0
  206. data/lib/capybara/spec/session/select_spec.rb +102 -76
  207. data/lib/capybara/spec/session/selectors_spec.rb +51 -18
  208. data/lib/capybara/spec/session/sibling_spec.rb +9 -9
  209. data/lib/capybara/spec/session/text_spec.rb +26 -24
  210. data/lib/capybara/spec/session/title_spec.rb +8 -6
  211. data/lib/capybara/spec/session/uncheck_spec.rb +40 -21
  212. data/lib/capybara/spec/session/unselect_spec.rb +37 -37
  213. data/lib/capybara/spec/session/visit_spec.rb +59 -53
  214. data/lib/capybara/spec/session/window/become_closed_spec.rb +22 -19
  215. data/lib/capybara/spec/session/window/current_window_spec.rb +4 -3
  216. data/lib/capybara/spec/session/window/open_new_window_spec.rb +4 -3
  217. data/lib/capybara/spec/session/window/switch_to_window_spec.rb +25 -21
  218. data/lib/capybara/spec/session/window/window_opened_by_spec.rb +10 -5
  219. data/lib/capybara/spec/session/window/window_spec.rb +88 -54
  220. data/lib/capybara/spec/session/window/windows_spec.rb +10 -7
  221. data/lib/capybara/spec/session/window/within_window_spec.rb +17 -16
  222. data/lib/capybara/spec/session/within_spec.rb +69 -44
  223. data/lib/capybara/spec/spec_helper.rb +41 -53
  224. data/lib/capybara/spec/test_app.rb +79 -40
  225. data/lib/capybara/spec/views/animated.erb +49 -0
  226. data/lib/capybara/spec/views/form.erb +134 -42
  227. data/lib/capybara/spec/views/frame_child.erb +4 -3
  228. data/lib/capybara/spec/views/frame_one.erb +2 -1
  229. data/lib/capybara/spec/views/frame_parent.erb +1 -1
  230. data/lib/capybara/spec/views/frame_two.erb +1 -1
  231. data/lib/capybara/spec/views/initial_alert.erb +2 -1
  232. data/lib/capybara/spec/views/layout.erb +10 -0
  233. data/lib/capybara/spec/views/obscured.erb +47 -0
  234. data/lib/capybara/spec/views/offset.erb +33 -0
  235. data/lib/capybara/spec/views/path.erb +2 -2
  236. data/lib/capybara/spec/views/popup_one.erb +1 -1
  237. data/lib/capybara/spec/views/popup_two.erb +1 -1
  238. data/lib/capybara/spec/views/react.erb +45 -0
  239. data/lib/capybara/spec/views/scroll.erb +21 -0
  240. data/lib/capybara/spec/views/spatial.erb +31 -0
  241. data/lib/capybara/spec/views/tables.erb +68 -1
  242. data/lib/capybara/spec/views/with_animation.erb +81 -0
  243. data/lib/capybara/spec/views/with_base_tag.erb +2 -2
  244. data/lib/capybara/spec/views/with_dragula.erb +24 -0
  245. data/lib/capybara/spec/views/with_fixed_header_footer.erb +2 -1
  246. data/lib/capybara/spec/views/with_hover.erb +3 -2
  247. data/lib/capybara/spec/views/with_hover1.erb +10 -0
  248. data/lib/capybara/spec/views/with_html.erb +43 -10
  249. data/lib/capybara/spec/views/with_html5_svg.erb +20 -0
  250. data/lib/capybara/spec/views/with_jquery_animation.erb +24 -0
  251. data/lib/capybara/spec/views/with_js.erb +30 -5
  252. data/lib/capybara/spec/views/with_jstree.erb +26 -0
  253. data/lib/capybara/spec/views/with_namespace.erb +21 -0
  254. data/lib/capybara/spec/views/with_scope_other.erb +6 -0
  255. data/lib/capybara/spec/views/with_slow_unload.erb +2 -1
  256. data/lib/capybara/spec/views/with_sortable_js.erb +21 -0
  257. data/lib/capybara/spec/views/with_unload_alert.erb +1 -0
  258. data/lib/capybara/spec/views/with_windows.erb +1 -1
  259. data/lib/capybara/spec/views/within_frames.erb +1 -1
  260. data/lib/capybara/version.rb +1 -1
  261. data/lib/capybara/window.rb +31 -25
  262. data/lib/capybara.rb +120 -100
  263. data/spec/basic_node_spec.rb +59 -34
  264. data/spec/capybara_spec.rb +54 -52
  265. data/spec/css_builder_spec.rb +101 -0
  266. data/spec/css_splitter_spec.rb +38 -0
  267. data/spec/dsl_spec.rb +80 -53
  268. data/spec/filter_set_spec.rb +24 -7
  269. data/spec/fixtures/certificate.pem +25 -0
  270. data/spec/fixtures/key.pem +27 -0
  271. data/spec/fixtures/selenium_driver_rspec_failure.rb +4 -4
  272. data/spec/fixtures/selenium_driver_rspec_success.rb +4 -4
  273. data/spec/minitest_spec.rb +38 -5
  274. data/spec/minitest_spec_spec.rb +88 -62
  275. data/spec/per_session_config_spec.rb +5 -5
  276. data/spec/rack_test_spec.rb +169 -115
  277. data/spec/regexp_dissassembler_spec.rb +250 -0
  278. data/spec/result_spec.rb +86 -33
  279. data/spec/rspec/features_spec.rb +26 -23
  280. data/spec/rspec/scenarios_spec.rb +8 -4
  281. data/spec/rspec/shared_spec_matchers.rb +393 -363
  282. data/spec/rspec/views_spec.rb +4 -3
  283. data/spec/rspec_matchers_spec.rb +10 -10
  284. data/spec/rspec_spec.rb +109 -85
  285. data/spec/sauce_spec_chrome.rb +43 -0
  286. data/spec/selector_spec.rb +391 -61
  287. data/spec/selenium_spec_chrome.rb +180 -41
  288. data/spec/selenium_spec_chrome_remote.rb +101 -0
  289. data/spec/selenium_spec_edge.rb +28 -8
  290. data/spec/selenium_spec_firefox.rb +211 -0
  291. data/spec/selenium_spec_firefox_remote.rb +80 -0
  292. data/spec/selenium_spec_ie.rb +127 -11
  293. data/spec/selenium_spec_safari.rb +156 -0
  294. data/spec/server_spec.rb +177 -78
  295. data/spec/session_spec.rb +52 -16
  296. data/spec/shared_selenium_node.rb +79 -0
  297. data/spec/shared_selenium_session.rb +455 -123
  298. data/spec/spec_helper.rb +91 -2
  299. data/spec/xpath_builder_spec.rb +93 -0
  300. metadata +343 -42
  301. data/.yard/templates_custom/default/class/html/selectors.erb +0 -38
  302. data/.yard/templates_custom/default/class/html/setup.rb +0 -17
  303. data/.yard/yard_extensions.rb +0 -78
  304. data/lib/capybara/rspec/compound.rb +0 -90
  305. data/lib/capybara/spec/session/assert_selector.rb +0 -149
  306. data/lib/capybara/spec/session/source_spec.rb +0 -0
  307. data/lib/capybara/spec/views/with_title.erb +0 -5
  308. data/spec/selenium_spec_marionette.rb +0 -143
data/License.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  (The MIT License)
2
2
 
3
- Copyright (c) 2009-2016 Jonas Nicklas
3
+ Copyright (c) 2009-2018 Thomas Walpole, Jonas Nicklas
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining
6
6
  a copy of this software and associated documentation files (the
data/README.md CHANGED
@@ -2,13 +2,10 @@
2
2
 
3
3
  [![Build Status](https://secure.travis-ci.org/teamcapybara/capybara.svg)](https://travis-ci.org/teamcapybara/capybara)
4
4
  [![Build Status](https://ci.appveyor.com/api/projects/status/github/teamcapybara/capybara?svg=true)](https://ci.appveyor.com/api/projects/github/teamcapybara/capybara)
5
- [![Dependency Status](https://gemnasium.com/teamcapybara/capybara.svg)](https://gemnasium.com/teamcapybara/capybara)
6
5
  [![Code Climate](https://codeclimate.com/github/teamcapybara/capybara.svg)](https://codeclimate.com/github/teamcapybara/capybara)
6
+ [![Coverage Status](https://coveralls.io/repos/github/teamcapybara/capybara/badge.svg?branch=master)](https://coveralls.io/github/teamcapybara/capybara?branch=master)
7
7
  [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/jnicklas/capybara?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
8
-
9
- **Note** You are viewing the README for the development version of Capybara. If you are using the current release version
10
- you can find the README at https://github.com/teamcapybara/capybara/blob/3.0_stable/README.md
11
-
8
+ [![SemVer](https://api.dependabot.com/badges/compatibility_score?dependency-name=capybara&package-manager=bundler&version-scheme=semver)](https://dependabot.com/compatibility-score.html?dependency-name=capybara&package-manager=bundler&version-scheme=semver)
12
9
 
13
10
  Capybara helps you test web applications by simulating how a real user would
14
11
  interact with your app. It is agnostic about the driver running your tests and
@@ -37,8 +34,7 @@ GitHub): http://groups.google.com/group/ruby-capybara
37
34
  - [Selecting the Driver](#selecting-the-driver)
38
35
  - [RackTest](#racktest)
39
36
  - [Selenium](#selenium)
40
- - [Capybara-webkit](#capybara-webkit)
41
- - [Poltergeist](#poltergeist)
37
+ - [Apparition](#apparition)
42
38
  - [The DSL](#the-dsl)
43
39
  - [Navigating](#navigating)
44
40
  - [Clicking links and buttons](#clicking-links-and-buttons)
@@ -58,11 +54,13 @@ GitHub): http://groups.google.com/group/ruby-capybara
58
54
  - [Using the DSL elsewhere](#using-the-dsl-elsewhere)
59
55
  - [Calling remote servers](#calling-remote-servers)
60
56
  - [Using sessions](#using-sessions)
57
+ - [Named sessions](#named-sessions)
58
+ - [Using sessions manually](#using-sessions-manually)
61
59
  - [XPath, CSS and selectors](#xpath-css-and-selectors)
62
60
  - [Beware the XPath // trap](#beware-the-xpath--trap)
63
61
  - [Configuring and adding drivers](#configuring-and-adding-drivers)
64
62
  - [Gotchas:](#gotchas)
65
- - ["Threadsafe" mode](#threadsafe)
63
+ - ["Threadsafe" mode](#threadsafe-mode)
66
64
  - [Development](#development)
67
65
 
68
66
  ## <a name="key-benefits"></a>Key benefits
@@ -76,7 +74,7 @@ GitHub): http://groups.google.com/group/ruby-capybara
76
74
 
77
75
  ## <a name="setup"></a>Setup
78
76
 
79
- Capybara requires Ruby 2.2.2 or later. To install, add this line to your
77
+ Capybara requires Ruby 2.6.0 or later. To install, add this line to your
80
78
  `Gemfile` and run `bundle install`:
81
79
 
82
80
  ```ruby
@@ -140,7 +138,7 @@ There are also explicit tags for each registered driver set up for you (`@seleni
140
138
 
141
139
  ## <a name="using-capybara-with-rspec"></a>Using Capybara with RSpec
142
140
 
143
- Load RSpec 3.x support by adding the following line (typically to your
141
+ Load RSpec 3.5+ support by adding the following line (typically to your
144
142
  `spec_helper.rb` file):
145
143
 
146
144
  ```ruby
@@ -149,10 +147,12 @@ require 'capybara/rspec'
149
147
 
150
148
  If you are using Rails, put your Capybara specs in `spec/features` or `spec/system` (only works
151
149
  if [you have it configured in
152
- RSpec](https://www.relishapp.com/rspec/rspec-rails/docs/upgrade#file-type-inference-disabled))
150
+ RSpec](https://relishapp.com/rspec/rspec-rails/v/4-0/docs/directory-structure))
153
151
  and if you have your Capybara specs in a different directory, then tag the
154
152
  example groups with `type: :feature` or `type: :system` depending on which type of test you're writing.
155
153
 
154
+ If you are using Rails system specs please see [their documentation](https://relishapp.com/rspec/rspec-rails/docs/system-specs/system-spec#system-specs-driven-by-selenium-chrome-headless) for selecting the driver you wish to use.
155
+
156
156
  If you are not using Rails, tag all the example groups in which you want to use
157
157
  Capybara with `type: :feature`.
158
158
 
@@ -183,7 +183,7 @@ to one specific driver. For example:
183
183
  ```ruby
184
184
  describe 'some stuff which requires js', js: true do
185
185
  it 'will use the default js driver'
186
- it 'will switch to one specific driver', driver: :webkit
186
+ it 'will switch to one specific driver', driver: :apparition
187
187
  end
188
188
  ```
189
189
 
@@ -219,7 +219,7 @@ feature "Signing in" do
219
219
  end
220
220
  ```
221
221
 
222
- `feature` is in fact just an alias for `describe ..., type:> :feature`,
222
+ `feature` is in fact just an alias for `describe ..., type: :feature`,
223
223
  `background` is an alias for `before`, `scenario` for `it`, and
224
224
  `given`/`given!` aliases for `let`/`let!`, respectively.
225
225
 
@@ -260,7 +260,9 @@ end
260
260
 
261
261
  ## <a name="using-capybara-with-minitest"></a>Using Capybara with Minitest
262
262
 
263
- * If you are using Rails, add the following code in your `test_helper.rb`
263
+ * If you are using Rails system tests please see their documentation for information on selecting the driver you wish to use.
264
+
265
+ * If you are using Rails, but not using Rails system tests, add the following code in your `test_helper.rb`
264
266
  file to make Capybara available in all test cases deriving from
265
267
  `ActionDispatch::IntegrationTest`:
266
268
 
@@ -275,8 +277,7 @@ end
275
277
  include Capybara::Minitest::Assertions
276
278
 
277
279
  # Reset sessions and driver between tests
278
- # Use super wherever this method is redefined in your individual test classes
279
- def teardown
280
+ teardown do
280
281
  Capybara.reset_sessions!
281
282
  Capybara.use_default_driver
282
283
  end
@@ -341,9 +342,9 @@ For example if you'd prefer to run everything in Selenium, you could do:
341
342
  Capybara.default_driver = :selenium # :selenium_chrome and :selenium_chrome_headless are also registered
342
343
  ```
343
344
 
344
- However, if you are using RSpec or Cucumber, you may instead want to consider
345
- leaving the faster `:rack_test` as the __default_driver__, and marking only those
346
- tests that require a JavaScript-capable driver using `js: true` or
345
+ However, if you are using RSpec or Cucumber (and your app runs correctly without JS),
346
+ you may instead want to consider leaving the faster `:rack_test` as the __default_driver__, and
347
+ marking only those tests that require a JavaScript-capable driver using `js: true` or
347
348
  `@javascript`, respectively. By default, JavaScript tests are run using the
348
349
  `:selenium` driver. You can change this by setting
349
350
  `Capybara.javascript_driver`.
@@ -352,7 +353,7 @@ You can also change the driver temporarily (typically in the Before/setup and
352
353
  After/teardown blocks):
353
354
 
354
355
  ```ruby
355
- Capybara.current_driver = :webkit # temporarily select different driver
356
+ Capybara.current_driver = :apparition # temporarily select different driver
356
357
  # tests here
357
358
  Capybara.use_default_driver # switch back to default driver
358
359
  ```
@@ -387,42 +388,35 @@ See the section on adding and configuring drivers.
387
388
 
388
389
  ### <a name="selenium"></a>Selenium
389
390
 
390
- At the moment, Capybara supports [Selenium 2.0+
391
- (Webdriver)](http://seleniumhq.org/docs/01_introducing_selenium.html#selenium-2-aka-selenium-webdriver),
392
- *not* Selenium RC. In order to use Selenium, you'll need to install the
393
- `selenium-webdriver` gem, and add it to your Gemfile if you're using bundler.
394
- Provided Firefox is installed, everything is set up for you, and you should be
395
- able to start using Selenium right away.
391
+ Capybara supports [Selenium 3.5+
392
+ (Webdriver)](https://www.seleniumhq.org/projects/webdriver/).
393
+ In order to use Selenium, you'll need to install the `selenium-webdriver` gem,
394
+ and add it to your Gemfile if you're using bundler.
396
395
 
397
- **Note**: drivers which run the server in a different thread may not share the
398
- same transaction as your tests, causing data not to be shared between your test
399
- and test server, see "Transactions and database setup" below.
400
-
401
- ### <a name="capybara-webkit"></a>Capybara-webkit
402
-
403
- The [capybara-webkit driver](https://github.com/thoughtbot/capybara-webkit) is for true headless
404
- testing. It uses QtWebKit to start a rendering engine process. It can execute JavaScript as well.
405
- It is significantly faster than drivers like Selenium since it does not load an entire browser.
396
+ Capybara pre-registers a number of named drivers that use Selenium - they are:
406
397
 
407
- You can install it with:
398
+ * :selenium => Selenium driving Firefox
399
+ * :selenium_headless => Selenium driving Firefox in a headless configuration
400
+ * :selenium_chrome => Selenium driving Chrome
401
+ * :selenium_chrome_headless => Selenium driving Chrome in a headless configuration
408
402
 
409
- ```bash
410
- gem install capybara-webkit
411
- ```
403
+ These should work (with relevant software installation) in a local desktop configuration but you may
404
+ need to customize them if using in a CI environment where additional options may need to be passed
405
+ to the browsers. See the section on adding and configuring drivers.
412
406
 
413
- And you can use it by:
414
407
 
415
- ```ruby
416
- Capybara.javascript_driver = :webkit
417
- ```
408
+ **Note**: drivers which run the server in a different thread may not share the
409
+ same transaction as your tests, causing data not to be shared between your test
410
+ and test server, see [Transactions and database setup](#transactions-and-database-setup) below.
418
411
 
419
- ### <a name="poltergeist"></a>Poltergeist
412
+ ### <a name="apparition"></a>Apparition
420
413
 
421
- [Poltergeist](https://github.com/teampoltergeist/poltergeist) is another
422
- headless driver which integrates Capybara with
423
- [PhantomJS](http://phantomjs.org/). It is truly headless, so doesn't
424
- require Xvfb to run on your CI server. It will also detect and report
425
- any Javascript errors that happen within the page.
414
+ The [apparition driver](https://github.com/twalpole/apparition) is a new driver that allows you to run tests using Chrome in a headless
415
+ or headed configuration. It attempts to provide backwards compatibility with the [Poltergeist driver API](https://github.com/teampoltergeist/poltergeist)
416
+ and [capybara-webkit API](https://github.com/thoughtbot/capybara-webkit) while allowing for the use of modern JS/CSS. It
417
+ uses CDP to communicate with Chrome, thereby obviating the need for chromedriver. This driver is being developed by the
418
+ current developer of Capybara and will attempt to keep up to date with new Capybara releases. It will probably be moved into the
419
+ teamcapybara repo once it reaches v1.0.
426
420
 
427
421
  ## <a name="the-dsl"></a>The DSL
428
422
 
@@ -617,13 +611,23 @@ In drivers which support it, you can easily execute JavaScript:
617
611
  page.execute_script("$('body').empty()")
618
612
  ```
619
613
 
620
- For simple expressions, you can return the result of the script. Note
621
- that this may break with more complicated expressions:
614
+ For simple expressions, you can return the result of the script.
622
615
 
623
616
  ```ruby
624
617
  result = page.evaluate_script('4 + 4');
625
618
  ```
626
619
 
620
+ For more complicated scripts you'll need to write them as one expression.
621
+
622
+ ```ruby
623
+ result = page.evaluate_script(<<~JS, 3, element)
624
+ (function(n, el){
625
+ var val = parseInt(el.value, 10);
626
+ return n+val;
627
+ })(arguments[0], arguments[1])
628
+ JS
629
+ ```
630
+
627
631
  ### <a name="modals"></a>Modals
628
632
 
629
633
  In drivers which support it, you can accept, dismiss and respond to alerts, confirms and prompts.
@@ -932,12 +936,17 @@ Capybara.default_selector = :xpath
932
936
  find('.//ul/li').text
933
937
  ```
934
938
 
935
- Capybara allows you to add custom selectors, which can be very useful if you
936
- find yourself using the same kinds of selectors very often:
939
+ Capybara provides a number of other built-in selector types. The full list, along
940
+ with applicable filters, can be seen at [built-in selectors](https://www.rubydoc.info/github/teamcapybara/capybara/Capybara/Selector)
941
+
942
+ Capybara also allows you to add custom selectors, which can be very useful if you
943
+ find yourself using the same kinds of selectors very often. The examples below are very
944
+ simple, and there are many available features not demonstrated. For more in-depth examples
945
+ please see Capybaras built-in selector definitions.
937
946
 
938
947
  ```ruby
939
- Capybara.add_selector(:id) do
940
- xpath { |id| XPath.descendant[XPath.attr(:id) == id.to_s] }
948
+ Capybara.add_selector(:my_attribute) do
949
+ xpath { |id| XPath.descendant[XPath.attr(:my_attribute) == id.to_s] }
941
950
  end
942
951
 
943
952
  Capybara.add_selector(:row) do
@@ -954,9 +963,9 @@ an XPath expression generated through the XPath gem. You can now use these
954
963
  selectors like this:
955
964
 
956
965
  ```ruby
957
- find(:id, 'post_123')
958
- find(:row, 3)
959
- find(:flash_type, :notice)
966
+ find(:my_attribute, 'post_123') # find element with matching attribute
967
+ find(:row, 3) # find 3rd row in table body
968
+ find(:flash_type, :notice) # find element with id of 'flash' and class of 'notice'
960
969
  ```
961
970
 
962
971
  ## <a name="beware-the-xpath--trap"></a>Beware the XPath // trap
@@ -1002,6 +1011,7 @@ end
1002
1011
  However, it's also possible to give this configuration a different name.
1003
1012
 
1004
1013
  ```ruby
1014
+ # Note: Capybara registers this by default
1005
1015
  Capybara.register_driver :selenium_chrome do |app|
1006
1016
  Capybara::Selenium::Driver.new(app, :browser => :chrome)
1007
1017
  end
@@ -1047,6 +1057,13 @@ additional info about how the underlying driver can be configured.
1047
1057
  are testing for specific server errors and using multiple sessions make sure to test for the
1048
1058
  errors using the initial session (usually :default)
1049
1059
 
1060
+ * If WebMock is enabled, you may encounter a "Too many open files"
1061
+ error. A simple `page.find` call may cause thousands of HTTP requests
1062
+ until the timeout occurs. By default, WebMock will cause each of these
1063
+ requests to spawn a new connection. To work around this problem, you
1064
+ may need to [enable WebMock's `net_http_connect_on_start: true`
1065
+ parameter](https://github.com/bblimke/webmock/blob/master/README.md#connecting-on-nethttpstart).
1066
+
1050
1067
  ## <a name="threadsafe"></a>"Threadsafe" mode
1051
1068
 
1052
1069
  In normal mode most of Capybara's configuration options are global settings which can cause issues
@@ -7,11 +7,12 @@ module Capybara
7
7
  class Config
8
8
  extend Forwardable
9
9
 
10
- OPTIONS = %i[app reuse_server threadsafe default_wait_time server default_driver javascript_driver].freeze
10
+ OPTIONS = %i[
11
+ app reuse_server threadsafe server default_driver javascript_driver use_html5_parsing allow_gumbo
12
+ ].freeze
11
13
 
12
- attr_accessor :app
13
- attr_reader :reuse_server, :threadsafe
14
- attr_reader :session_options
14
+ attr_accessor :app, :use_html5_parsing
15
+ attr_reader :reuse_server, :threadsafe, :session_options # rubocop:disable Style/BisectedAttrAccessor
15
16
  attr_writer :default_driver, :javascript_driver
16
17
 
17
18
  SessionConfig::OPTIONS.each do |method|
@@ -20,12 +21,16 @@ module Capybara
20
21
 
21
22
  def initialize
22
23
  @session_options = Capybara::SessionConfig.new
24
+ @javascript_driver = nil
23
25
  end
24
26
 
25
- attr_writer :reuse_server
27
+ attr_writer :reuse_server # rubocop:disable Style/BisectedAttrAccessor
26
28
 
27
29
  def threadsafe=(bool)
28
- 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
+
29
34
  @threadsafe = bool
30
35
  end
31
36
 
@@ -53,8 +58,10 @@ module Capybara
53
58
  #
54
59
  def server=(name)
55
60
  name, options = *name if name.is_a? Array
56
- @server = if options
57
- proc { |app, port, host| Capybara.servers[name.to_sym].call(app, port, host, options) }
61
+ @server = if name.respond_to? :call
62
+ name
63
+ elsif options
64
+ proc { |app, port, host| Capybara.servers[name.to_sym].call(app, port, host, **options) }
58
65
  else
59
66
  Capybara.servers[name.to_sym]
60
67
  end
@@ -76,10 +83,22 @@ module Capybara
76
83
  @javascript_driver || :selenium
77
84
  end
78
85
 
79
- def deprecate(method, alternate_method, once = false)
86
+ def deprecate(method, alternate_method, once: false)
80
87
  @deprecation_notified ||= {}
81
- warn "DEPRECATED: ##{method} is deprecated, please use ##{alternate_method} instead" unless once and @deprecation_notified[method]
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
82
91
  @deprecation_notified[method] = true
83
92
  end
93
+
94
+ def allow_gumbo=(val)
95
+ deprecate('allow_gumbo=', 'use_html5_parsing=')
96
+ self.use_html5_parsing = val
97
+ end
98
+
99
+ def allow_gumbo
100
+ deprecate('allow_gumbo', 'use_html5_parsing')
101
+ use_html5_parsing
102
+ end
84
103
  end
85
104
  end
@@ -22,6 +22,6 @@ end
22
22
  Before do |scenario|
23
23
  scenario.source_tag_names.each do |tag|
24
24
  driver_name = tag.sub(/^@/, '').to_sym
25
- Capybara.current_driver = driver_name if Capybara.drivers.key?(driver_name)
25
+ Capybara.current_driver = driver_name if Capybara.drivers[driver_name]
26
26
  end
27
27
  end
@@ -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
@@ -107,7 +132,7 @@ module Capybara
107
132
  end
108
133
 
109
134
  def ==(other)
110
- raise NotSupportedByDriverError, 'Capybara::Driver::Node#=='
135
+ eql?(other) || (other.respond_to?(:native) && native == other.native)
111
136
  end
112
137
  end
113
138
  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,8 +47,16 @@ 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
50
+ if RUBY_VERSION >= '2.7'
51
+ class_eval <<~METHOD, __FILE__, __LINE__ + 1
52
+ def #{method}(...)
53
+ page.method("#{method}").call(...)
54
+ end
55
+ METHOD
56
+ else
57
+ define_method method do |*args, &block|
58
+ page.send method, *args, &block
59
+ end
52
60
  end
53
61
  end
54
62
  end
@@ -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,54 @@ module Capybara
69
70
  count == 1 ? singular : plural
70
71
  end
71
72
 
73
+ def filter_backtrace(trace)
74
+ return 'No backtrace' unless trace
75
+
76
+ filter = %r{lib/capybara/|lib/rspec/|lib/minitest/}
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
+
72
88
  if defined?(Process::CLOCK_MONOTONIC)
73
89
  def monotonic_time; Process.clock_gettime Process::CLOCK_MONOTONIC; end
74
90
  else
75
91
  def monotonic_time; Time.now.to_f; end
76
92
  end
93
+
94
+ def timer(expire_in:)
95
+ Timer.new(expire_in)
96
+ end
97
+
98
+ class Timer
99
+ def initialize(expire_in)
100
+ @start = current
101
+ @expire_in = expire_in
102
+ end
103
+
104
+ def expired?
105
+ if stalled?
106
+ raise Capybara::FrozenInTime, 'Time appears to be frozen. Capybara does not work with libraries which freeze time, consider using time travelling instead'
107
+ end
108
+
109
+ current - @start >= @expire_in
110
+ end
111
+
112
+ def stalled?
113
+ @start == current
114
+ end
115
+
116
+ private
117
+
118
+ def current
119
+ Capybara::Helpers.monotonic_time
120
+ end
121
+ end
77
122
  end
78
123
  end