capybara 3.32.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (313) hide show
  1. checksums.yaml +7 -0
  2. data/.yardopts +1 -0
  3. data/History.md +1813 -0
  4. data/License.txt +22 -0
  5. data/README.md +1099 -0
  6. data/lib/capybara.rb +511 -0
  7. data/lib/capybara/config.rb +94 -0
  8. data/lib/capybara/cucumber.rb +27 -0
  9. data/lib/capybara/driver/base.rb +170 -0
  10. data/lib/capybara/driver/node.rb +139 -0
  11. data/lib/capybara/dsl.rb +65 -0
  12. data/lib/capybara/helpers.rb +108 -0
  13. data/lib/capybara/minitest.rb +386 -0
  14. data/lib/capybara/minitest/spec.rb +264 -0
  15. data/lib/capybara/node/actions.rb +420 -0
  16. data/lib/capybara/node/base.rb +143 -0
  17. data/lib/capybara/node/document.rb +48 -0
  18. data/lib/capybara/node/document_matchers.rb +67 -0
  19. data/lib/capybara/node/element.rb +606 -0
  20. data/lib/capybara/node/finders.rb +325 -0
  21. data/lib/capybara/node/matchers.rb +883 -0
  22. data/lib/capybara/node/simple.rb +208 -0
  23. data/lib/capybara/queries/ancestor_query.rb +27 -0
  24. data/lib/capybara/queries/base_query.rb +106 -0
  25. data/lib/capybara/queries/current_path_query.rb +51 -0
  26. data/lib/capybara/queries/match_query.rb +26 -0
  27. data/lib/capybara/queries/selector_query.rb +710 -0
  28. data/lib/capybara/queries/sibling_query.rb +26 -0
  29. data/lib/capybara/queries/style_query.rb +45 -0
  30. data/lib/capybara/queries/text_query.rb +110 -0
  31. data/lib/capybara/queries/title_query.rb +39 -0
  32. data/lib/capybara/rack_test/browser.rb +140 -0
  33. data/lib/capybara/rack_test/css_handlers.rb +13 -0
  34. data/lib/capybara/rack_test/driver.rb +109 -0
  35. data/lib/capybara/rack_test/errors.rb +6 -0
  36. data/lib/capybara/rack_test/form.rb +127 -0
  37. data/lib/capybara/rack_test/node.rb +325 -0
  38. data/lib/capybara/rails.rb +16 -0
  39. data/lib/capybara/registrations/drivers.rb +36 -0
  40. data/lib/capybara/registrations/patches/puma_ssl.rb +27 -0
  41. data/lib/capybara/registrations/servers.rb +44 -0
  42. data/lib/capybara/result.rb +190 -0
  43. data/lib/capybara/rspec.rb +29 -0
  44. data/lib/capybara/rspec/features.rb +23 -0
  45. data/lib/capybara/rspec/matcher_proxies.rb +82 -0
  46. data/lib/capybara/rspec/matchers.rb +201 -0
  47. data/lib/capybara/rspec/matchers/base.rb +111 -0
  48. data/lib/capybara/rspec/matchers/become_closed.rb +33 -0
  49. data/lib/capybara/rspec/matchers/compound.rb +88 -0
  50. data/lib/capybara/rspec/matchers/count_sugar.rb +37 -0
  51. data/lib/capybara/rspec/matchers/have_ancestor.rb +28 -0
  52. data/lib/capybara/rspec/matchers/have_current_path.rb +29 -0
  53. data/lib/capybara/rspec/matchers/have_selector.rb +77 -0
  54. data/lib/capybara/rspec/matchers/have_sibling.rb +27 -0
  55. data/lib/capybara/rspec/matchers/have_text.rb +33 -0
  56. data/lib/capybara/rspec/matchers/have_title.rb +29 -0
  57. data/lib/capybara/rspec/matchers/match_selector.rb +27 -0
  58. data/lib/capybara/rspec/matchers/match_style.rb +38 -0
  59. data/lib/capybara/rspec/matchers/spatial_sugar.rb +39 -0
  60. data/lib/capybara/selector.rb +233 -0
  61. data/lib/capybara/selector/builders/css_builder.rb +84 -0
  62. data/lib/capybara/selector/builders/xpath_builder.rb +69 -0
  63. data/lib/capybara/selector/css.rb +102 -0
  64. data/lib/capybara/selector/definition.rb +276 -0
  65. data/lib/capybara/selector/definition/button.rb +51 -0
  66. data/lib/capybara/selector/definition/checkbox.rb +26 -0
  67. data/lib/capybara/selector/definition/css.rb +10 -0
  68. data/lib/capybara/selector/definition/datalist_input.rb +35 -0
  69. data/lib/capybara/selector/definition/datalist_option.rb +25 -0
  70. data/lib/capybara/selector/definition/element.rb +27 -0
  71. data/lib/capybara/selector/definition/field.rb +40 -0
  72. data/lib/capybara/selector/definition/fieldset.rb +14 -0
  73. data/lib/capybara/selector/definition/file_field.rb +13 -0
  74. data/lib/capybara/selector/definition/fillable_field.rb +33 -0
  75. data/lib/capybara/selector/definition/frame.rb +17 -0
  76. data/lib/capybara/selector/definition/id.rb +6 -0
  77. data/lib/capybara/selector/definition/label.rb +62 -0
  78. data/lib/capybara/selector/definition/link.rb +46 -0
  79. data/lib/capybara/selector/definition/link_or_button.rb +16 -0
  80. data/lib/capybara/selector/definition/option.rb +27 -0
  81. data/lib/capybara/selector/definition/radio_button.rb +27 -0
  82. data/lib/capybara/selector/definition/select.rb +81 -0
  83. data/lib/capybara/selector/definition/table.rb +109 -0
  84. data/lib/capybara/selector/definition/table_row.rb +21 -0
  85. data/lib/capybara/selector/definition/xpath.rb +5 -0
  86. data/lib/capybara/selector/filter.rb +5 -0
  87. data/lib/capybara/selector/filter_set.rb +124 -0
  88. data/lib/capybara/selector/filters/base.rb +77 -0
  89. data/lib/capybara/selector/filters/expression_filter.rb +22 -0
  90. data/lib/capybara/selector/filters/locator_filter.rb +29 -0
  91. data/lib/capybara/selector/filters/node_filter.rb +31 -0
  92. data/lib/capybara/selector/regexp_disassembler.rb +214 -0
  93. data/lib/capybara/selector/selector.rb +147 -0
  94. data/lib/capybara/selector/xpath_extensions.rb +17 -0
  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 +496 -0
  100. data/lib/capybara/selenium/driver_specializations/chrome_driver.rb +119 -0
  101. data/lib/capybara/selenium/driver_specializations/edge_driver.rb +126 -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 +78 -0
  110. data/lib/capybara/selenium/logger_suppressor.rb +34 -0
  111. data/lib/capybara/selenium/node.rb +610 -0
  112. data/lib/capybara/selenium/nodes/chrome_node.rb +119 -0
  113. data/lib/capybara/selenium/nodes/edge_node.rb +104 -0
  114. data/lib/capybara/selenium/nodes/firefox_node.rb +131 -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 +47 -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.rb +126 -0
  124. data/lib/capybara/server/animation_disabler.rb +58 -0
  125. data/lib/capybara/server/checker.rb +44 -0
  126. data/lib/capybara/server/middleware.rb +69 -0
  127. data/lib/capybara/session.rb +942 -0
  128. data/lib/capybara/session/config.rb +124 -0
  129. data/lib/capybara/session/matchers.rb +87 -0
  130. data/lib/capybara/spec/fixtures/another_test_file.txt +1 -0
  131. data/lib/capybara/spec/fixtures/capybara.jpg +3 -0
  132. data/lib/capybara/spec/fixtures/no_extension +1 -0
  133. data/lib/capybara/spec/fixtures/test_file.txt +1 -0
  134. data/lib/capybara/spec/public/jquery-ui.js +13 -0
  135. data/lib/capybara/spec/public/jquery.js +5 -0
  136. data/lib/capybara/spec/public/offset.js +6 -0
  137. data/lib/capybara/spec/public/test.js +268 -0
  138. data/lib/capybara/spec/session/accept_alert_spec.rb +81 -0
  139. data/lib/capybara/spec/session/accept_confirm_spec.rb +32 -0
  140. data/lib/capybara/spec/session/accept_prompt_spec.rb +78 -0
  141. data/lib/capybara/spec/session/all_spec.rb +278 -0
  142. data/lib/capybara/spec/session/ancestor_spec.rb +88 -0
  143. data/lib/capybara/spec/session/assert_all_of_selectors_spec.rb +140 -0
  144. data/lib/capybara/spec/session/assert_current_path_spec.rb +75 -0
  145. data/lib/capybara/spec/session/assert_selector_spec.rb +143 -0
  146. data/lib/capybara/spec/session/assert_style_spec.rb +26 -0
  147. data/lib/capybara/spec/session/assert_text_spec.rb +258 -0
  148. data/lib/capybara/spec/session/assert_title_spec.rb +93 -0
  149. data/lib/capybara/spec/session/attach_file_spec.rb +216 -0
  150. data/lib/capybara/spec/session/body_spec.rb +23 -0
  151. data/lib/capybara/spec/session/check_spec.rb +235 -0
  152. data/lib/capybara/spec/session/choose_spec.rb +121 -0
  153. data/lib/capybara/spec/session/click_button_spec.rb +506 -0
  154. data/lib/capybara/spec/session/click_link_or_button_spec.rb +129 -0
  155. data/lib/capybara/spec/session/click_link_spec.rb +229 -0
  156. data/lib/capybara/spec/session/current_scope_spec.rb +31 -0
  157. data/lib/capybara/spec/session/current_url_spec.rb +115 -0
  158. data/lib/capybara/spec/session/dismiss_confirm_spec.rb +36 -0
  159. data/lib/capybara/spec/session/dismiss_prompt_spec.rb +21 -0
  160. data/lib/capybara/spec/session/element/assert_match_selector_spec.rb +38 -0
  161. data/lib/capybara/spec/session/element/match_css_spec.rb +31 -0
  162. data/lib/capybara/spec/session/element/match_xpath_spec.rb +25 -0
  163. data/lib/capybara/spec/session/element/matches_selector_spec.rb +120 -0
  164. data/lib/capybara/spec/session/evaluate_async_script_spec.rb +23 -0
  165. data/lib/capybara/spec/session/evaluate_script_spec.rb +49 -0
  166. data/lib/capybara/spec/session/execute_script_spec.rb +28 -0
  167. data/lib/capybara/spec/session/fill_in_spec.rb +286 -0
  168. data/lib/capybara/spec/session/find_button_spec.rb +74 -0
  169. data/lib/capybara/spec/session/find_by_id_spec.rb +33 -0
  170. data/lib/capybara/spec/session/find_field_spec.rb +113 -0
  171. data/lib/capybara/spec/session/find_link_spec.rb +70 -0
  172. data/lib/capybara/spec/session/find_spec.rb +531 -0
  173. data/lib/capybara/spec/session/first_spec.rb +156 -0
  174. data/lib/capybara/spec/session/frame/frame_title_spec.rb +23 -0
  175. data/lib/capybara/spec/session/frame/frame_url_spec.rb +23 -0
  176. data/lib/capybara/spec/session/frame/switch_to_frame_spec.rb +116 -0
  177. data/lib/capybara/spec/session/frame/within_frame_spec.rb +112 -0
  178. data/lib/capybara/spec/session/go_back_spec.rb +12 -0
  179. data/lib/capybara/spec/session/go_forward_spec.rb +14 -0
  180. data/lib/capybara/spec/session/has_all_selectors_spec.rb +69 -0
  181. data/lib/capybara/spec/session/has_ancestor_spec.rb +46 -0
  182. data/lib/capybara/spec/session/has_any_selectors_spec.rb +25 -0
  183. data/lib/capybara/spec/session/has_button_spec.rb +69 -0
  184. data/lib/capybara/spec/session/has_css_spec.rb +374 -0
  185. data/lib/capybara/spec/session/has_current_path_spec.rb +138 -0
  186. data/lib/capybara/spec/session/has_field_spec.rb +349 -0
  187. data/lib/capybara/spec/session/has_link_spec.rb +39 -0
  188. data/lib/capybara/spec/session/has_none_selectors_spec.rb +78 -0
  189. data/lib/capybara/spec/session/has_select_spec.rb +310 -0
  190. data/lib/capybara/spec/session/has_selector_spec.rb +202 -0
  191. data/lib/capybara/spec/session/has_sibling_spec.rb +50 -0
  192. data/lib/capybara/spec/session/has_table_spec.rb +198 -0
  193. data/lib/capybara/spec/session/has_text_spec.rb +394 -0
  194. data/lib/capybara/spec/session/has_title_spec.rb +71 -0
  195. data/lib/capybara/spec/session/has_xpath_spec.rb +149 -0
  196. data/lib/capybara/spec/session/headers_spec.rb +8 -0
  197. data/lib/capybara/spec/session/html_spec.rb +47 -0
  198. data/lib/capybara/spec/session/matches_style_spec.rb +35 -0
  199. data/lib/capybara/spec/session/node_spec.rb +1292 -0
  200. data/lib/capybara/spec/session/node_wrapper_spec.rb +39 -0
  201. data/lib/capybara/spec/session/refresh_spec.rb +33 -0
  202. data/lib/capybara/spec/session/reset_session_spec.rb +148 -0
  203. data/lib/capybara/spec/session/response_code_spec.rb +8 -0
  204. data/lib/capybara/spec/session/save_and_open_page_spec.rb +21 -0
  205. data/lib/capybara/spec/session/save_and_open_screenshot_spec.rb +43 -0
  206. data/lib/capybara/spec/session/save_page_spec.rb +110 -0
  207. data/lib/capybara/spec/session/save_screenshot_spec.rb +55 -0
  208. data/lib/capybara/spec/session/screenshot_spec.rb +18 -0
  209. data/lib/capybara/spec/session/scroll_spec.rb +117 -0
  210. data/lib/capybara/spec/session/select_spec.rb +229 -0
  211. data/lib/capybara/spec/session/selectors_spec.rb +98 -0
  212. data/lib/capybara/spec/session/sibling_spec.rb +52 -0
  213. data/lib/capybara/spec/session/source_spec.rb +0 -0
  214. data/lib/capybara/spec/session/text_spec.rb +74 -0
  215. data/lib/capybara/spec/session/title_spec.rb +29 -0
  216. data/lib/capybara/spec/session/uncheck_spec.rb +100 -0
  217. data/lib/capybara/spec/session/unselect_spec.rb +116 -0
  218. data/lib/capybara/spec/session/visit_spec.rb +204 -0
  219. data/lib/capybara/spec/session/window/become_closed_spec.rb +89 -0
  220. data/lib/capybara/spec/session/window/current_window_spec.rb +28 -0
  221. data/lib/capybara/spec/session/window/open_new_window_spec.rb +31 -0
  222. data/lib/capybara/spec/session/window/switch_to_window_spec.rb +132 -0
  223. data/lib/capybara/spec/session/window/window_opened_by_spec.rb +99 -0
  224. data/lib/capybara/spec/session/window/window_spec.rb +203 -0
  225. data/lib/capybara/spec/session/window/windows_spec.rb +34 -0
  226. data/lib/capybara/spec/session/window/within_window_spec.rb +157 -0
  227. data/lib/capybara/spec/session/within_spec.rb +199 -0
  228. data/lib/capybara/spec/spec_helper.rb +134 -0
  229. data/lib/capybara/spec/test_app.rb +226 -0
  230. data/lib/capybara/spec/views/animated.erb +49 -0
  231. data/lib/capybara/spec/views/buttons.erb +5 -0
  232. data/lib/capybara/spec/views/fieldsets.erb +30 -0
  233. data/lib/capybara/spec/views/form.erb +685 -0
  234. data/lib/capybara/spec/views/frame_child.erb +18 -0
  235. data/lib/capybara/spec/views/frame_one.erb +10 -0
  236. data/lib/capybara/spec/views/frame_parent.erb +9 -0
  237. data/lib/capybara/spec/views/frame_two.erb +9 -0
  238. data/lib/capybara/spec/views/header_links.erb +8 -0
  239. data/lib/capybara/spec/views/host_links.erb +13 -0
  240. data/lib/capybara/spec/views/initial_alert.erb +10 -0
  241. data/lib/capybara/spec/views/obscured.erb +47 -0
  242. data/lib/capybara/spec/views/offset.erb +32 -0
  243. data/lib/capybara/spec/views/path.erb +13 -0
  244. data/lib/capybara/spec/views/popup_one.erb +9 -0
  245. data/lib/capybara/spec/views/popup_two.erb +9 -0
  246. data/lib/capybara/spec/views/postback.erb +14 -0
  247. data/lib/capybara/spec/views/react.erb +45 -0
  248. data/lib/capybara/spec/views/scroll.erb +20 -0
  249. data/lib/capybara/spec/views/spatial.erb +31 -0
  250. data/lib/capybara/spec/views/tables.erb +130 -0
  251. data/lib/capybara/spec/views/with_animation.erb +74 -0
  252. data/lib/capybara/spec/views/with_base_tag.erb +11 -0
  253. data/lib/capybara/spec/views/with_count.erb +8 -0
  254. data/lib/capybara/spec/views/with_dragula.erb +22 -0
  255. data/lib/capybara/spec/views/with_fixed_header_footer.erb +17 -0
  256. data/lib/capybara/spec/views/with_hover.erb +24 -0
  257. data/lib/capybara/spec/views/with_hover1.erb +10 -0
  258. data/lib/capybara/spec/views/with_html.erb +208 -0
  259. data/lib/capybara/spec/views/with_html5_svg.erb +20 -0
  260. data/lib/capybara/spec/views/with_html_entities.erb +2 -0
  261. data/lib/capybara/spec/views/with_js.erb +160 -0
  262. data/lib/capybara/spec/views/with_jstree.erb +26 -0
  263. data/lib/capybara/spec/views/with_namespace.erb +20 -0
  264. data/lib/capybara/spec/views/with_scope.erb +42 -0
  265. data/lib/capybara/spec/views/with_scope_other.erb +6 -0
  266. data/lib/capybara/spec/views/with_simple_html.erb +2 -0
  267. data/lib/capybara/spec/views/with_slow_unload.erb +17 -0
  268. data/lib/capybara/spec/views/with_sortable_js.erb +21 -0
  269. data/lib/capybara/spec/views/with_title.erb +5 -0
  270. data/lib/capybara/spec/views/with_unload_alert.erb +14 -0
  271. data/lib/capybara/spec/views/with_windows.erb +54 -0
  272. data/lib/capybara/spec/views/within_frames.erb +15 -0
  273. data/lib/capybara/version.rb +5 -0
  274. data/lib/capybara/window.rb +146 -0
  275. data/spec/basic_node_spec.rb +154 -0
  276. data/spec/capybara_spec.rb +112 -0
  277. data/spec/css_builder_spec.rb +101 -0
  278. data/spec/css_splitter_spec.rb +38 -0
  279. data/spec/dsl_spec.rb +276 -0
  280. data/spec/filter_set_spec.rb +46 -0
  281. data/spec/fixtures/capybara.csv +1 -0
  282. data/spec/fixtures/certificate.pem +25 -0
  283. data/spec/fixtures/key.pem +27 -0
  284. data/spec/fixtures/selenium_driver_rspec_failure.rb +13 -0
  285. data/spec/fixtures/selenium_driver_rspec_success.rb +13 -0
  286. data/spec/minitest_spec.rb +163 -0
  287. data/spec/minitest_spec_spec.rb +162 -0
  288. data/spec/per_session_config_spec.rb +68 -0
  289. data/spec/rack_test_spec.rb +268 -0
  290. data/spec/regexp_dissassembler_spec.rb +250 -0
  291. data/spec/result_spec.rb +196 -0
  292. data/spec/rspec/features_spec.rb +99 -0
  293. data/spec/rspec/scenarios_spec.rb +19 -0
  294. data/spec/rspec/shared_spec_matchers.rb +947 -0
  295. data/spec/rspec/views_spec.rb +14 -0
  296. data/spec/rspec_matchers_spec.rb +62 -0
  297. data/spec/rspec_spec.rb +145 -0
  298. data/spec/sauce_spec_chrome.rb +43 -0
  299. data/spec/selector_spec.rb +513 -0
  300. data/spec/selenium_spec_chrome.rb +188 -0
  301. data/spec/selenium_spec_chrome_remote.rb +96 -0
  302. data/spec/selenium_spec_edge.rb +47 -0
  303. data/spec/selenium_spec_firefox.rb +208 -0
  304. data/spec/selenium_spec_firefox_remote.rb +80 -0
  305. data/spec/selenium_spec_ie.rb +150 -0
  306. data/spec/selenium_spec_safari.rb +148 -0
  307. data/spec/server_spec.rb +292 -0
  308. data/spec/session_spec.rb +91 -0
  309. data/spec/shared_selenium_node.rb +83 -0
  310. data/spec/shared_selenium_session.rb +476 -0
  311. data/spec/spec_helper.rb +100 -0
  312. data/spec/xpath_builder_spec.rb +93 -0
  313. metadata +753 -0
@@ -0,0 +1,22 @@
1
+ (The MIT License)
2
+
3
+ Copyright (c) 2009-2018 Thomas Walpole, Jonas Nicklas
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ 'Software'), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,1099 @@
1
+ # Capybara
2
+
3
+ [![Build Status](https://secure.travis-ci.org/teamcapybara/capybara.svg)](https://travis-ci.org/teamcapybara/capybara)
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
+ [![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
+ [![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
+ [![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)
9
+
10
+ **Note** You are viewing the README for the 3.32.x version of Capybara.
11
+
12
+ Capybara helps you test web applications by simulating how a real user would
13
+ interact with your app. It is agnostic about the driver running your tests and
14
+ comes with Rack::Test and Selenium support built in. WebKit is supported
15
+ through an external gem.
16
+
17
+ ## Support Capybara
18
+
19
+ If you and/or your company find value in Capybara and would like to contribute financially to its ongoing maintenance and development, please visit
20
+ <a href="https://www.patreon.com/capybara">Patreon</a>
21
+
22
+
23
+ **Need help?** Ask on the mailing list (please do not open an issue on
24
+ GitHub): http://groups.google.com/group/ruby-capybara
25
+
26
+ ## Table of contents
27
+
28
+ - [Key benefits](#key-benefits)
29
+ - [Setup](#setup)
30
+ - [Using Capybara with Cucumber](#using-capybara-with-cucumber)
31
+ - [Using Capybara with RSpec](#using-capybara-with-rspec)
32
+ - [Using Capybara with Test::Unit](#using-capybara-with-testunit)
33
+ - [Using Capybara with Minitest](#using-capybara-with-minitest)
34
+ - [Using Capybara with Minitest::Spec](#using-capybara-with-minitestspec)
35
+ - [Drivers](#drivers)
36
+ - [Selecting the Driver](#selecting-the-driver)
37
+ - [RackTest](#racktest)
38
+ - [Selenium](#selenium)
39
+ - [Apparition](#apparition)
40
+ - [The DSL](#the-dsl)
41
+ - [Navigating](#navigating)
42
+ - [Clicking links and buttons](#clicking-links-and-buttons)
43
+ - [Interacting with forms](#interacting-with-forms)
44
+ - [Querying](#querying)
45
+ - [Finding](#finding)
46
+ - [Scoping](#scoping)
47
+ - [Working with windows](#working-with-windows)
48
+ - [Scripting](#scripting)
49
+ - [Modals](#modals)
50
+ - [Debugging](#debugging)
51
+ - [Matching](#matching)
52
+ - [Exactness](#exactness)
53
+ - [Strategy](#strategy)
54
+ - [Transactions and database setup](#transactions-and-database-setup)
55
+ - [Asynchronous JavaScript (Ajax and friends)](#asynchronous-javascript-ajax-and-friends)
56
+ - [Using the DSL elsewhere](#using-the-dsl-elsewhere)
57
+ - [Calling remote servers](#calling-remote-servers)
58
+ - [Using sessions](#using-sessions)
59
+ - [Named sessions](#named-sessions)
60
+ - [Using sessions manually](#using-sessions-manually)
61
+ - [XPath, CSS and selectors](#xpath-css-and-selectors)
62
+ - [Beware the XPath // trap](#beware-the-xpath--trap)
63
+ - [Configuring and adding drivers](#configuring-and-adding-drivers)
64
+ - [Gotchas:](#gotchas)
65
+ - ["Threadsafe" mode](#threadsafe-mode)
66
+ - [Development](#development)
67
+
68
+ ## <a name="key-benefits"></a>Key benefits
69
+
70
+ - **No setup** necessary for Rails and Rack application. Works out of the box.
71
+ - **Intuitive API** which mimics the language an actual user would use.
72
+ - **Switch the backend** your tests run against from fast headless mode
73
+ to an actual browser with no changes to your tests.
74
+ - **Powerful synchronization** features mean you never have to manually wait
75
+ for asynchronous processes to complete.
76
+
77
+ ## <a name="setup"></a>Setup
78
+
79
+ Capybara requires Ruby 2.4.0 or later. To install, add this line to your
80
+ `Gemfile` and run `bundle install`:
81
+
82
+ ```ruby
83
+ gem 'capybara'
84
+ ```
85
+
86
+ If the application that you are testing is a Rails app, add this line to your test helper file:
87
+
88
+ ```ruby
89
+ require 'capybara/rails'
90
+ ```
91
+
92
+ If the application that you are testing is a Rack app, but not Rails, set Capybara.app to your Rack app:
93
+
94
+ ```ruby
95
+ Capybara.app = MyRackApp
96
+ ```
97
+
98
+ If you need to test JavaScript, or if your app interacts with (or is located at)
99
+ a remote URL, you'll need to [use a different driver](#drivers). If using Rails 5.0+, but not using the Rails system tests from 5.1, you'll probably also
100
+ want to swap the "server" used to launch your app to Puma in order to match Rails defaults.
101
+
102
+ ```ruby
103
+ Capybara.server = :puma # Until your setup is working
104
+ Capybara.server = :puma, { Silent: true } # To clean up your test output
105
+ ```
106
+
107
+ ## <a name="using-capybara-with-cucumber"></a>Using Capybara with Cucumber
108
+
109
+ The `cucumber-rails` gem comes with Capybara support built-in. If you
110
+ are not using Rails, manually load the `capybara/cucumber` module:
111
+
112
+ ```ruby
113
+ require 'capybara/cucumber'
114
+ Capybara.app = MyRackApp
115
+ ```
116
+
117
+ You can use the Capybara DSL in your steps, like so:
118
+
119
+ ```ruby
120
+ When /I sign in/ do
121
+ within("#session") do
122
+ fill_in 'Email', with: 'user@example.com'
123
+ fill_in 'Password', with: 'password'
124
+ end
125
+ click_button 'Sign in'
126
+ end
127
+ ```
128
+
129
+ You can switch to the `Capybara.javascript_driver` (`:selenium`
130
+ by default) by tagging scenarios (or features) with `@javascript`:
131
+
132
+ ```ruby
133
+ @javascript
134
+ Scenario: do something Ajaxy
135
+ When I click the Ajax link
136
+ ...
137
+ ```
138
+
139
+ There are also explicit tags for each registered driver set up for you (`@selenium`, `@rack_test`, etc).
140
+
141
+ ## <a name="using-capybara-with-rspec"></a>Using Capybara with RSpec
142
+
143
+ Load RSpec 3.5+ support by adding the following line (typically to your
144
+ `spec_helper.rb` file):
145
+
146
+ ```ruby
147
+ require 'capybara/rspec'
148
+ ```
149
+
150
+ If you are using Rails, put your Capybara specs in `spec/features` or `spec/system` (only works
151
+ if [you have it configured in
152
+ RSpec](https://www.relishapp.com/rspec/rspec-rails/docs/upgrade#file-type-inference-disabled))
153
+ and if you have your Capybara specs in a different directory, then tag the
154
+ example groups with `type: :feature` or `type: :system` depending on which type of test you're writing.
155
+
156
+ If you are not using Rails, tag all the example groups in which you want to use
157
+ Capybara with `type: :feature`.
158
+
159
+ You can now write your specs like so:
160
+
161
+ ```ruby
162
+ describe "the signin process", type: :feature do
163
+ before :each do
164
+ User.make(email: 'user@example.com', password: 'password')
165
+ end
166
+
167
+ it "signs me in" do
168
+ visit '/sessions/new'
169
+ within("#session") do
170
+ fill_in 'Email', with: 'user@example.com'
171
+ fill_in 'Password', with: 'password'
172
+ end
173
+ click_button 'Sign in'
174
+ expect(page).to have_content 'Success'
175
+ end
176
+ end
177
+ ```
178
+
179
+ Use `js: true` to switch to the `Capybara.javascript_driver`
180
+ (`:selenium` by default), or provide a `:driver` option to switch
181
+ to one specific driver. For example:
182
+
183
+ ```ruby
184
+ describe 'some stuff which requires js', js: true do
185
+ it 'will use the default js driver'
186
+ it 'will switch to one specific driver', driver: :apparition
187
+ end
188
+ ```
189
+
190
+ Capybara also comes with a built in DSL for creating descriptive acceptance tests:
191
+
192
+ ```ruby
193
+ feature "Signing in" do
194
+ background do
195
+ User.make(email: 'user@example.com', password: 'caplin')
196
+ end
197
+
198
+ scenario "Signing in with correct credentials" do
199
+ visit '/sessions/new'
200
+ within("#session") do
201
+ fill_in 'Email', with: 'user@example.com'
202
+ fill_in 'Password', with: 'caplin'
203
+ end
204
+ click_button 'Sign in'
205
+ expect(page).to have_content 'Success'
206
+ end
207
+
208
+ given(:other_user) { User.make(email: 'other@example.com', password: 'rous') }
209
+
210
+ scenario "Signing in as another user" do
211
+ visit '/sessions/new'
212
+ within("#session") do
213
+ fill_in 'Email', with: other_user.email
214
+ fill_in 'Password', with: other_user.password
215
+ end
216
+ click_button 'Sign in'
217
+ expect(page).to have_content 'Invalid email or password'
218
+ end
219
+ end
220
+ ```
221
+
222
+ `feature` is in fact just an alias for `describe ..., type: :feature`,
223
+ `background` is an alias for `before`, `scenario` for `it`, and
224
+ `given`/`given!` aliases for `let`/`let!`, respectively.
225
+
226
+ Finally, Capybara matchers are also supported in view specs:
227
+
228
+ ```ruby
229
+ RSpec.describe "todos/show.html.erb", type: :view do
230
+ it "displays the todo title" do
231
+ assign :todo, Todo.new(title: "Buy milk")
232
+
233
+ render
234
+
235
+ expect(rendered).to have_css("header h1", text: "Buy milk")
236
+ end
237
+ end
238
+ ```
239
+
240
+ **Note: When you require 'capybara/rspec' proxy methods are installed to work around name collisions between Capybara::DSL methods
241
+ `all`/`within` and the identically named built-in RSpec matchers. If you opt not to require 'capybara/rspec' you can install the proxy methods by requiring 'capybara/rspec/matcher_proxies' after requiring RSpec and 'capybara/dsl'**
242
+
243
+ ## <a name="using-capybara-with-testunit"></a>Using Capybara with Test::Unit
244
+
245
+ * If you are using `Test::Unit`, define a base class for your Capybara tests
246
+ like so:
247
+
248
+ ```ruby
249
+ require 'capybara/dsl'
250
+
251
+ class CapybaraTestCase < Test::Unit::TestCase
252
+ include Capybara::DSL
253
+
254
+ def teardown
255
+ Capybara.reset_sessions!
256
+ Capybara.use_default_driver
257
+ end
258
+ end
259
+ ```
260
+
261
+ ## <a name="using-capybara-with-minitest"></a>Using Capybara with Minitest
262
+
263
+ * If you are using Rails, but not using Rails system tests, add the following code in your `test_helper.rb`
264
+ file to make Capybara available in all test cases deriving from
265
+ `ActionDispatch::IntegrationTest`:
266
+
267
+ ```ruby
268
+ require 'capybara/rails'
269
+ require 'capybara/minitest'
270
+
271
+ class ActionDispatch::IntegrationTest
272
+ # Make the Capybara DSL available in all integration tests
273
+ include Capybara::DSL
274
+ # Make `assert_*` methods behave like Minitest assertions
275
+ include Capybara::Minitest::Assertions
276
+
277
+ # Reset sessions and driver between tests
278
+ teardown do
279
+ Capybara.reset_sessions!
280
+ Capybara.use_default_driver
281
+ end
282
+ end
283
+ ```
284
+
285
+ * If you are not using Rails, define a base class for your Capybara tests like
286
+ so:
287
+
288
+ ```ruby
289
+ require 'capybara/minitest'
290
+
291
+ class CapybaraTestCase < Minitest::Test
292
+ include Capybara::DSL
293
+ include Capybara::Minitest::Assertions
294
+
295
+ def teardown
296
+ Capybara.reset_sessions!
297
+ Capybara.use_default_driver
298
+ end
299
+ end
300
+ ```
301
+
302
+ Remember to call `super` in any subclasses that override
303
+ `teardown`.
304
+
305
+ To switch the driver, set `Capybara.current_driver`. For instance,
306
+
307
+ ```ruby
308
+ class BlogTest < ActionDispatch::IntegrationTest
309
+ setup do
310
+ Capybara.current_driver = Capybara.javascript_driver # :selenium by default
311
+ end
312
+
313
+ test 'shows blog posts' do
314
+ # ... this test is run with Selenium ...
315
+ end
316
+ end
317
+ ```
318
+
319
+ ## <a name="using-capybara-with-minitestspec"></a>Using Capybara with Minitest::Spec
320
+
321
+ Follow the above instructions for Minitest and additionally require capybara/minitest/spec
322
+
323
+ ```ruby
324
+ page.must_have_content('Important!')
325
+ ```
326
+
327
+ ## <a name="drivers"></a>Drivers
328
+
329
+ Capybara uses the same DSL to drive a variety of browser and headless drivers.
330
+
331
+ ### <a name="selecting-the-driver"></a>Selecting the Driver
332
+
333
+ By default, Capybara uses the `:rack_test` driver, which is fast but limited: it
334
+ does not support JavaScript, nor is it able to access HTTP resources outside of
335
+ your Rack application, such as remote APIs and OAuth services. To get around
336
+ these limitations, you can set up a different default driver for your features.
337
+ For example if you'd prefer to run everything in Selenium, you could do:
338
+
339
+ ```ruby
340
+ Capybara.default_driver = :selenium # :selenium_chrome and :selenium_chrome_headless are also registered
341
+ ```
342
+
343
+ However, if you are using RSpec or Cucumber (and your app runs correctly without JS),
344
+ you may instead want to consider leaving the faster `:rack_test` as the __default_driver__, and
345
+ marking only those tests that require a JavaScript-capable driver using `js: true` or
346
+ `@javascript`, respectively. By default, JavaScript tests are run using the
347
+ `:selenium` driver. You can change this by setting
348
+ `Capybara.javascript_driver`.
349
+
350
+ You can also change the driver temporarily (typically in the Before/setup and
351
+ After/teardown blocks):
352
+
353
+ ```ruby
354
+ Capybara.current_driver = :apparition # temporarily select different driver
355
+ # tests here
356
+ Capybara.use_default_driver # switch back to default driver
357
+ ```
358
+
359
+ **Note**: switching the driver creates a new session, so you may not be able to
360
+ switch in the middle of a test.
361
+
362
+ ### <a name="racktest"></a>RackTest
363
+
364
+ RackTest is Capybara's default driver. It is written in pure Ruby and does not
365
+ have any support for executing JavaScript. Since the RackTest driver interacts
366
+ directly with Rack interfaces, it does not require a server to be started.
367
+ However, this means that if your application is not a Rack application (Rails,
368
+ Sinatra and most other Ruby frameworks are Rack applications) then you cannot
369
+ use this driver. Furthermore, you cannot use the RackTest driver to test a
370
+ remote application, or to access remote URLs (e.g., redirects to external
371
+ sites, external APIs, or OAuth services) that your application might interact
372
+ with.
373
+
374
+ [capybara-mechanize](https://github.com/jeroenvandijk/capybara-mechanize)
375
+ provides a similar driver that can access remote servers.
376
+
377
+ RackTest can be configured with a set of headers like this:
378
+
379
+ ```ruby
380
+ Capybara.register_driver :rack_test do |app|
381
+ Capybara::RackTest::Driver.new(app, headers: { 'HTTP_USER_AGENT' => 'Capybara' })
382
+ end
383
+ ```
384
+
385
+ See the section on adding and configuring drivers.
386
+
387
+ ### <a name="selenium"></a>Selenium
388
+
389
+ Capybara supports [Selenium 3.5+
390
+ (Webdriver)](https://www.seleniumhq.org/projects/webdriver/).
391
+ In order to use Selenium, you'll need to install the `selenium-webdriver` gem,
392
+ and add it to your Gemfile if you're using bundler.
393
+
394
+ Capybara pre-registers a number of named drivers that use Selenium - they are:
395
+
396
+ * :selenium => Selenium driving Firefox
397
+ * :selenium_headless => Selenium driving Firefox in a headless configuration
398
+ * :selenium_chrome => Selenium driving Chrome
399
+ * :selenium_chrome_headless => Selenium driving Chrome in a headless configuration
400
+
401
+ These should work (with relevant software installation) in a local desktop configuration but you may
402
+ need to customize them if using in a CI environment where additional options may need to be passed
403
+ to the browsers. See the section on adding and configuring drivers.
404
+
405
+
406
+ **Note**: drivers which run the server in a different thread may not share the
407
+ same transaction as your tests, causing data not to be shared between your test
408
+ and test server, see [Transactions and database setup](#transactions-and-database-setup) below.
409
+
410
+ ### <a name="apparition"></a>Apparition
411
+
412
+ The [apparition driver](https://github.com/twalpole/apparition) is a new driver that allows you to run tests using Chrome in a headless
413
+ or headed configuration. It attempts to provide backwards compatibility with the [Poltergeist driver API](https://github.com/teampoltergeist/poltergeist)
414
+ and [capybara-webkit API](https://github.com/thoughtbot/capybara-webkit) while allowing for the use of modern JS/CSS. It
415
+ uses CDP to communicate with Chrome, thereby obviating the need for chromedriver. This driver is being developed by the
416
+ current developer of Capybara and will attempt to keep up to date with new Capybara releases. It will probably be moved into the
417
+ teamcapybara repo once it reaches v1.0.
418
+
419
+ ## <a name="the-dsl"></a>The DSL
420
+
421
+ *A complete reference is available at
422
+ [rubydoc.info](http://rubydoc.info/github/teamcapybara/capybara/master)*.
423
+
424
+ **Note: By default Capybara will only locate visible elements. This is because
425
+ a real user would not be able to interact with non-visible elements.**
426
+
427
+ **Note**: All searches in Capybara are *case sensitive*. This is because
428
+ Capybara heavily uses XPath, which doesn't support case insensitivity.
429
+
430
+ ### <a name="navigating"></a>Navigating
431
+
432
+ You can use the
433
+ <tt>[visit](http://rubydoc.info/github/teamcapybara/capybara/master/Capybara/Session#visit-instance_method)</tt>
434
+ method to navigate to other pages:
435
+
436
+ ```ruby
437
+ visit('/projects')
438
+ visit(post_comments_path(post))
439
+ ```
440
+
441
+ The visit method only takes a single parameter, the request method is **always**
442
+ GET.
443
+
444
+ You can get the [current path](http://rubydoc.info/github/teamcapybara/capybara/master/Capybara/Session#current_path-instance_method)
445
+ of the browsing session, and test it using the [`have_current_path`](http://www.rubydoc.info/github/teamcapybara/capybara/master/Capybara/RSpecMatchers#have_current_path-instance_method) matcher:
446
+
447
+ ```ruby
448
+ expect(page).to have_current_path(post_comments_path(post))
449
+ ```
450
+
451
+ **Note**: You can also assert the current path by testing the value of
452
+ `current_path` directly. However, using the `have_current_path` matcher is
453
+ safer since it uses Capybara's [waiting behaviour](#asynchronous-javascript-ajax-and-friends)
454
+ to ensure that preceding actions (such as a `click_link`) have completed.
455
+
456
+ ### <a name="clicking-links-and-buttons"></a>Clicking links and buttons
457
+
458
+ *Full reference: [Capybara::Node::Actions](http://rubydoc.info/github/teamcapybara/capybara/master/Capybara/Node/Actions)*
459
+
460
+ You can interact with the webapp by following links and buttons. Capybara
461
+ automatically follows any redirects, and submits forms associated with buttons.
462
+
463
+ ```ruby
464
+ click_link('id-of-link')
465
+ click_link('Link Text')
466
+ click_button('Save')
467
+ click_on('Link Text') # clicks on either links or buttons
468
+ click_on('Button Value')
469
+ ```
470
+
471
+ ### <a name="interacting-with-forms"></a>Interacting with forms
472
+
473
+ *Full reference: [Capybara::Node::Actions](http://rubydoc.info/github/teamcapybara/capybara/master/Capybara/Node/Actions)*
474
+
475
+ There are a number of tools for interacting with form elements:
476
+
477
+ ```ruby
478
+ fill_in('First Name', with: 'John')
479
+ fill_in('Password', with: 'Seekrit')
480
+ fill_in('Description', with: 'Really Long Text...')
481
+ choose('A Radio Button')
482
+ check('A Checkbox')
483
+ uncheck('A Checkbox')
484
+ attach_file('Image', '/path/to/image.jpg')
485
+ select('Option', from: 'Select Box')
486
+ ```
487
+
488
+ ### <a name="querying"></a>Querying
489
+
490
+ *Full reference: [Capybara::Node::Matchers](http://rubydoc.info/github/teamcapybara/capybara/master/Capybara/Node/Matchers)*
491
+
492
+ Capybara has a rich set of options for querying the page for the existence of
493
+ certain elements, and working with and manipulating those elements.
494
+
495
+ ```ruby
496
+ page.has_selector?('table tr')
497
+ page.has_selector?(:xpath, './/table/tr')
498
+
499
+ page.has_xpath?('.//table/tr')
500
+ page.has_css?('table tr.foo')
501
+ page.has_content?('foo')
502
+ ```
503
+
504
+ **Note:** The negative forms like `has_no_selector?` are different from `not
505
+ has_selector?`. Read the section on asynchronous JavaScript for an explanation.
506
+
507
+ You can use these with RSpec's magic matchers:
508
+
509
+ ```ruby
510
+ expect(page).to have_selector('table tr')
511
+ expect(page).to have_selector(:xpath, './/table/tr')
512
+
513
+ expect(page).to have_xpath('.//table/tr')
514
+ expect(page).to have_css('table tr.foo')
515
+ expect(page).to have_content('foo')
516
+ ```
517
+
518
+ ### <a name="finding"></a>Finding
519
+
520
+ _Full reference: [Capybara::Node::Finders](http://rubydoc.info/github/teamcapybara/capybara/master/Capybara/Node/Finders)_
521
+
522
+ You can also find specific elements, in order to manipulate them:
523
+
524
+ ```ruby
525
+ find_field('First Name').value
526
+ find_field(id: 'my_field').value
527
+ find_link('Hello', :visible => :all).visible?
528
+ find_link(class: ['some_class', 'some_other_class'], :visible => :all).visible?
529
+
530
+ find_button('Send').click
531
+ find_button(value: '1234').click
532
+
533
+ find(:xpath, ".//table/tr").click
534
+ find("#overlay").find("h1").click
535
+ all('a').each { |a| a[:href] }
536
+ ```
537
+
538
+ If you need to find elements by additional attributes/properties you can also pass a filter block, which will be checked inside the normal waiting behavior.
539
+ If you find yourself needing to use this a lot you may be better off adding a [custom selector](http://www.rubydoc.info/github/teamcapybara/capybara/Capybara#add_selector-class_method) or [adding a filter to an existing selector](http://www.rubydoc.info/github/teamcapybara/capybara/Capybara#modify_selector-class_method).
540
+
541
+ ```ruby
542
+ find_field('First Name'){ |el| el['data-xyz'] == '123' }
543
+ find("#img_loading"){ |img| img['complete'] == true }
544
+ ```
545
+
546
+ **Note**: `find` will wait for an element to appear on the page, as explained in the
547
+ Ajax section. If the element does not appear it will raise an error.
548
+
549
+ These elements all have all the Capybara DSL methods available, so you can restrict them
550
+ to specific parts of the page:
551
+
552
+ ```ruby
553
+ find('#navigation').click_link('Home')
554
+ expect(find('#navigation')).to have_button('Sign out')
555
+ ```
556
+
557
+ ### <a name="scoping"></a>Scoping
558
+
559
+ Capybara makes it possible to restrict certain actions, such as interacting with
560
+ forms or clicking links and buttons, to within a specific area of the page. For
561
+ this purpose you can use the generic
562
+ <tt>[within](http://rubydoc.info/github/teamcapybara/capybara/master/Capybara/Session#within-instance_method)</tt>
563
+ method. Optionally you can specify which kind of selector to use.
564
+
565
+ ```ruby
566
+ within("li#employee") do
567
+ fill_in 'Name', with: 'Jimmy'
568
+ end
569
+
570
+ within(:xpath, ".//li[@id='employee']") do
571
+ fill_in 'Name', with: 'Jimmy'
572
+ end
573
+ ```
574
+
575
+ There are special methods for restricting the scope to a specific fieldset,
576
+ identified by either an id or the text of the fieldset's legend tag, and to a
577
+ specific table, identified by either id or text of the table's caption tag.
578
+
579
+ ```ruby
580
+ within_fieldset('Employee') do
581
+ fill_in 'Name', with: 'Jimmy'
582
+ end
583
+
584
+ within_table('Employee') do
585
+ fill_in 'Name', with: 'Jimmy'
586
+ end
587
+ ```
588
+
589
+ ### <a name="working-with-windows"></a>Working with windows
590
+
591
+ Capybara provides some methods to ease finding and switching windows:
592
+
593
+ ```ruby
594
+ facebook_window = window_opened_by do
595
+ click_button 'Like'
596
+ end
597
+ within_window facebook_window do
598
+ find('#login_email').set('a@example.com')
599
+ find('#login_password').set('qwerty')
600
+ click_button 'Submit'
601
+ end
602
+ ```
603
+
604
+ ### <a name="scripting"></a>Scripting
605
+
606
+ In drivers which support it, you can easily execute JavaScript:
607
+
608
+ ```ruby
609
+ page.execute_script("$('body').empty()")
610
+ ```
611
+
612
+ For simple expressions, you can return the result of the script.
613
+
614
+ ```ruby
615
+ result = page.evaluate_script('4 + 4');
616
+ ```
617
+
618
+ For more complicated scripts you'll need to write them as one expression.
619
+
620
+ ```ruby
621
+ result = page.evaluate_script(<<~JS, 3, element)
622
+ (function(n, el){
623
+ var val = parseInt(el.value, 10);
624
+ return n+val;
625
+ })(arguments[0], arguments[1])
626
+ JS
627
+ ```
628
+
629
+ ### <a name="modals"></a>Modals
630
+
631
+ In drivers which support it, you can accept, dismiss and respond to alerts, confirms and prompts.
632
+
633
+ You can accept or dismiss alert messages by wrapping the code that produces an alert in a block:
634
+
635
+ ```ruby
636
+ accept_alert do
637
+ click_link('Show Alert')
638
+ end
639
+ ```
640
+
641
+ You can accept or dismiss a confirmation by wrapping it in a block, as well:
642
+
643
+ ```ruby
644
+ dismiss_confirm do
645
+ click_link('Show Confirm')
646
+ end
647
+ ```
648
+
649
+ You can accept or dismiss prompts as well, and also provide text to fill in for the response:
650
+
651
+ ```ruby
652
+ accept_prompt(with: 'Linus Torvalds') do
653
+ click_link('Show Prompt About Linux')
654
+ end
655
+ ```
656
+
657
+ All modal methods return the message that was presented. So, you can access the prompt message
658
+ by assigning the return to a variable:
659
+
660
+ ```ruby
661
+ message = accept_prompt(with: 'Linus Torvalds') do
662
+ click_link('Show Prompt About Linux')
663
+ end
664
+ expect(message).to eq('Who is the chief architect of Linux?')
665
+ ```
666
+
667
+ ### <a name="debugging"></a>Debugging
668
+
669
+ It can be useful to take a snapshot of the page as it currently is and take a
670
+ look at it:
671
+
672
+ ```ruby
673
+ save_and_open_page
674
+ ```
675
+
676
+ You can also retrieve the current state of the DOM as a string using
677
+ <tt>[page.html](http://rubydoc.info/github/teamcapybara/capybara/master/Capybara/Session#html-instance_method)</tt>.
678
+
679
+ ```ruby
680
+ print page.html
681
+ ```
682
+
683
+ This is mostly useful for debugging. You should avoid testing against the
684
+ contents of `page.html` and use the more expressive finder methods instead.
685
+
686
+ Finally, in drivers that support it, you can save a screenshot:
687
+
688
+ ```ruby
689
+ page.save_screenshot('screenshot.png')
690
+ ```
691
+
692
+ Or have it save and automatically open:
693
+
694
+ ```ruby
695
+ save_and_open_screenshot
696
+ ```
697
+
698
+ Screenshots are saved to `Capybara.save_path`, relative to the app directory.
699
+ If you have required `capybara/rails`, `Capybara.save_path` will default to
700
+ `tmp/capybara`.
701
+
702
+ ## <a name="matching"></a>Matching
703
+
704
+ It is possible to customize how Capybara finds elements. At your disposal
705
+ are two options, `Capybara.exact` and `Capybara.match`.
706
+
707
+ ### <a name="exactness"></a>Exactness
708
+
709
+ `Capybara.exact` and the `exact` option work together with the `is` expression
710
+ inside the XPath gem. When `exact` is true, all `is` expressions match exactly,
711
+ when it is false, they allow substring matches. Many of the selectors built into
712
+ Capybara use the `is` expression. This way you can specify whether you want to
713
+ allow substring matches or not. `Capybara.exact` is false by default.
714
+
715
+ For example:
716
+
717
+ ```ruby
718
+ click_link("Password") # also matches "Password confirmation"
719
+ Capybara.exact = true
720
+ click_link("Password") # does not match "Password confirmation"
721
+ click_link("Password", exact: false) # can be overridden
722
+ ```
723
+
724
+ ### <a name="strategy"></a>Strategy
725
+
726
+ Using `Capybara.match` and the equivalent `match` option, you can control how
727
+ Capybara behaves when multiple elements all match a query. There are currently
728
+ four different strategies built into Capybara:
729
+
730
+ 1. **first:** Just picks the first element that matches.
731
+ 2. **one:** Raises an error if more than one element matches.
732
+ 3. **smart:** If `exact` is `true`, raises an error if more than one element
733
+ matches, just like `one`. If `exact` is `false`, it will first try to find
734
+ an exact match. An error is raised if more than one element is found. If no
735
+ element is found, a new search is performed which allows partial matches. If
736
+ that search returns multiple matches, an error is raised.
737
+ 4. **prefer_exact:** If multiple matches are found, some of which are exact,
738
+ and some of which are not, then the first exactly matching element is
739
+ returned.
740
+
741
+ The default for `Capybara.match` is `:smart`. To emulate the behaviour in
742
+ Capybara 2.0.x, set `Capybara.match` to `:one`. To emulate the behaviour in
743
+ Capybara 1.x, set `Capybara.match` to `:prefer_exact`.
744
+
745
+ ## <a name="transactions-and-database-setup"></a>Transactions and database setup
746
+
747
+ **Note:** Rails 5.1+ "safely" shares the database connection between the app and test threads. Therefore,
748
+ if using Rails 5.1+ you SHOULD be able to ignore this section.
749
+
750
+ Some Capybara drivers need to run against an actual HTTP server. Capybara takes
751
+ care of this and starts one for you in the same process as your test, but on
752
+ another thread. Selenium is one of those drivers, whereas RackTest is not.
753
+
754
+ If you are using a SQL database, it is common to run every test in a
755
+ transaction, which is rolled back at the end of the test, rspec-rails does this
756
+ by default out of the box for example. Since transactions are usually not
757
+ shared across threads, this will cause data you have put into the database in
758
+ your test code to be invisible to Capybara.
759
+
760
+ Cucumber handles this by using truncation instead of transactions, i.e. they
761
+ empty out the entire database after each test. You can get the same behaviour
762
+ by using a gem such as [database_cleaner](https://github.com/DatabaseCleaner/database_cleaner).
763
+
764
+ ## <a name="asynchronous-javascript-ajax-and-friends"></a>Asynchronous JavaScript (Ajax and friends)
765
+
766
+ When working with asynchronous JavaScript, you might come across situations
767
+ where you are attempting to interact with an element which is not yet present
768
+ on the page. Capybara automatically deals with this by waiting for elements
769
+ to appear on the page.
770
+
771
+ When issuing instructions to the DSL such as:
772
+
773
+ ```ruby
774
+ click_link('foo')
775
+ click_link('bar')
776
+ expect(page).to have_content('baz')
777
+ ```
778
+
779
+ If clicking on the *foo* link triggers an asynchronous process, such as
780
+ an Ajax request, which, when complete will add the *bar* link to the page,
781
+ clicking on the *bar* link would be expected to fail, since that link doesn't
782
+ exist yet. However Capybara is smart enough to retry finding the link for a
783
+ brief period of time before giving up and throwing an error. The same is true of
784
+ the next line, which looks for the content *baz* on the page; it will retry
785
+ looking for that content for a brief time. You can adjust how long this period
786
+ is (the default is 2 seconds):
787
+
788
+ ```ruby
789
+ Capybara.default_max_wait_time = 5
790
+ ```
791
+
792
+ Be aware that because of this behaviour, the following two statements are **not**
793
+ equivalent, and you should **always** use the latter!
794
+
795
+ ```ruby
796
+ !page.has_xpath?('a')
797
+ page.has_no_xpath?('a')
798
+ ```
799
+
800
+ The former would immediately fail because the content has not yet been removed.
801
+ Only the latter would wait for the asynchronous process to remove the content
802
+ from the page.
803
+
804
+ Capybara's RSpec matchers, however, are smart enough to handle either form.
805
+ The two following statements are functionally equivalent:
806
+
807
+ ```ruby
808
+ expect(page).not_to have_xpath('a')
809
+ expect(page).to have_no_xpath('a')
810
+ ```
811
+
812
+ Capybara's waiting behaviour is quite advanced, and can deal with situations
813
+ such as the following line of code:
814
+
815
+ ```ruby
816
+ expect(find('#sidebar').find('h1')).to have_content('Something')
817
+ ```
818
+
819
+ Even if JavaScript causes `#sidebar` to disappear off the page, Capybara
820
+ will automatically reload it and any elements it contains. So if an AJAX
821
+ request causes the contents of `#sidebar` to change, which would update
822
+ the text of the `h1` to "Something", and this happened, this test would
823
+ pass. If you do not want this behaviour, you can set
824
+ `Capybara.automatic_reload` to `false`.
825
+
826
+ ## <a name="using-the-dsl-elsewhere"></a>Using the DSL elsewhere
827
+
828
+ You can mix the DSL into any context by including <tt>Capybara::DSL</tt>:
829
+
830
+
831
+ ```ruby
832
+ require 'capybara/dsl'
833
+
834
+ Capybara.default_driver = :webkit
835
+
836
+ module MyModule
837
+ include Capybara::DSL
838
+
839
+ def login!
840
+ within(:xpath, ".//form[@id='session']") do
841
+ fill_in 'Email', with: 'user@example.com'
842
+ fill_in 'Password', with: 'password'
843
+ end
844
+ click_button 'Sign in'
845
+ end
846
+ end
847
+ ```
848
+
849
+ This enables its use in unsupported testing frameworks, and for general-purpose scripting.
850
+
851
+ ## <a name="calling-remote-servers"></a>Calling remote servers
852
+
853
+ Normally Capybara expects to be testing an in-process Rack application, but you
854
+ can also use it to talk to a web server running anywhere on the internet, by
855
+ setting app_host:
856
+
857
+ ```ruby
858
+ Capybara.current_driver = :selenium
859
+ Capybara.app_host = 'http://www.google.com'
860
+ ...
861
+ visit('/')
862
+ ```
863
+
864
+ **Note**: the default driver (`:rack_test`) does not support running
865
+ against a remote server. With drivers that support it, you can also visit any
866
+ URL directly:
867
+
868
+ ```ruby
869
+ visit('http://www.google.com')
870
+ ```
871
+
872
+ By default Capybara will try to boot a rack application automatically. You
873
+ might want to switch off Capybara's rack server if you are running against a
874
+ remote application:
875
+
876
+ ```ruby
877
+ Capybara.run_server = false
878
+ ```
879
+
880
+ ## <a name="using-sessions"></a>Using sessions
881
+
882
+ Capybara manages named sessions (:default if not specified) allowing multiple sessions using the same driver and test app instance to be interacted with.
883
+ A new session will be created using the current driver if a session with the given name using the current driver and test app instance is not found.
884
+
885
+ ### Named sessions
886
+ To perform operations in a different session and then revert to the previous session
887
+
888
+ ```ruby
889
+ Capybara.using_session("Bob's session") do
890
+ #do something in Bob's browser session
891
+ end
892
+ #reverts to previous session
893
+ ```
894
+
895
+ To permanently switch the current session to a different session
896
+
897
+ ```ruby
898
+ Capybara.session_name = "some other session"
899
+ ```
900
+
901
+ ### <a name="using-sessions-manually"></a>Using sessions manually
902
+
903
+ For ultimate control, you can instantiate and use a
904
+ [Session](http://rubydoc.info/github/teamcapybara/capybara/master/Capybara/Session)
905
+ manually.
906
+
907
+ ```ruby
908
+ require 'capybara'
909
+
910
+ session = Capybara::Session.new(:webkit, my_rack_app)
911
+ session.within("form#session") do
912
+ session.fill_in 'Email', with: 'user@example.com'
913
+ session.fill_in 'Password', with: 'password'
914
+ end
915
+ session.click_button 'Sign in'
916
+ ```
917
+
918
+ ## <a name="xpath-css-and-selectors"></a>XPath, CSS and selectors
919
+
920
+ Capybara does not try to guess what kind of selector you are going to give it,
921
+ and will always use CSS by default. If you want to use XPath, you'll need to
922
+ do:
923
+
924
+ ```ruby
925
+ within(:xpath, './/ul/li') { ... }
926
+ find(:xpath, './/ul/li').text
927
+ find(:xpath, './/li[contains(.//a[@href = "#"]/text(), "foo")]').value
928
+ ```
929
+
930
+ Alternatively you can set the default selector to XPath:
931
+
932
+ ```ruby
933
+ Capybara.default_selector = :xpath
934
+ find('.//ul/li').text
935
+ ```
936
+
937
+ Capybara provides a number of other built-in selector types. The full list, along
938
+ with applicable filters, can be seen at [built-in selectors](https://www.rubydoc.info/github/teamcapybara/capybara/Capybara/Selector)
939
+
940
+ Capybara also allows you to add custom selectors, which can be very useful if you
941
+ find yourself using the same kinds of selectors very often. The examples below are very
942
+ simple, and there are many available features not demonstrated. For more in-depth examples
943
+ please see Capybaras built-in selector definitions.
944
+
945
+ ```ruby
946
+ Capybara.add_selector(:my_attribute) do
947
+ xpath { |id| XPath.descendant[XPath.attr(:my_attribute) == id.to_s] }
948
+ end
949
+
950
+ Capybara.add_selector(:row) do
951
+ xpath { |num| ".//tbody/tr[#{num}]" }
952
+ end
953
+
954
+ Capybara.add_selector(:flash_type) do
955
+ css { |type| "#flash.#{type}" }
956
+ end
957
+ ```
958
+
959
+ The block given to xpath must always return an XPath expression as a String, or
960
+ an XPath expression generated through the XPath gem. You can now use these
961
+ selectors like this:
962
+
963
+ ```ruby
964
+ find(:my_attribute, 'post_123') # find element with matching attribute
965
+ find(:row, 3) # find 3rd row in table body
966
+ find(:flash_type, :notice) # find element with id of 'flash' and class of 'notice'
967
+ ```
968
+
969
+ ## <a name="beware-the-xpath--trap"></a>Beware the XPath // trap
970
+
971
+ In XPath the expression // means something very specific, and it might not be what
972
+ you think. Contrary to common belief, // means "anywhere in the document" not "anywhere
973
+ in the current context". As an example:
974
+
975
+ ```ruby
976
+ page.find(:xpath, '//body').all(:xpath, '//script')
977
+ ```
978
+
979
+ You might expect this to find all script tags in the body, but actually, it finds all
980
+ script tags in the entire document, not only those in the body! What you're looking
981
+ for is the .// expression which means "any descendant of the current node":
982
+
983
+ ```ruby
984
+ page.find(:xpath, '//body').all(:xpath, './/script')
985
+ ```
986
+ The same thing goes for within:
987
+
988
+ ```ruby
989
+ within(:xpath, '//body') do
990
+ page.find(:xpath, './/script')
991
+ within(:xpath, './/table/tbody') do
992
+ ...
993
+ end
994
+ end
995
+ ```
996
+
997
+ ## <a name="configuring-and-adding-drivers"></a>Configuring and adding drivers
998
+
999
+ Capybara makes it convenient to switch between different drivers. It also exposes
1000
+ an API to tweak those drivers with whatever settings you want, or to add your own
1001
+ drivers. This is how to override the selenium driver configuration to use chrome:
1002
+
1003
+ ```ruby
1004
+ Capybara.register_driver :selenium do |app|
1005
+ Capybara::Selenium::Driver.new(app, :browser => :chrome)
1006
+ end
1007
+ ```
1008
+
1009
+ However, it's also possible to give this configuration a different name.
1010
+
1011
+ ```ruby
1012
+ # Note: Capybara registers this by default
1013
+ Capybara.register_driver :selenium_chrome do |app|
1014
+ Capybara::Selenium::Driver.new(app, :browser => :chrome)
1015
+ end
1016
+ ```
1017
+
1018
+ Then tests can switch between using different browsers effortlessly:
1019
+ ```ruby
1020
+ Capybara.current_driver = :selenium_chrome
1021
+ ```
1022
+
1023
+ Whatever is returned from the block should conform to the API described by
1024
+ Capybara::Driver::Base, it does not however have to inherit from this class.
1025
+ Gems can use this API to add their own drivers to Capybara.
1026
+
1027
+ The [Selenium wiki](https://github.com/SeleniumHQ/selenium/wiki/Ruby-Bindings) has
1028
+ additional info about how the underlying driver can be configured.
1029
+
1030
+ ## <a name="gotchas"></a>Gotchas:
1031
+
1032
+ * Access to session and request is not possible from the test, Access to
1033
+ response is limited. Some drivers allow access to response headers and HTTP
1034
+ status code, but this kind of functionality is not provided by some drivers,
1035
+ such as Selenium.
1036
+
1037
+ * Access to Rails specific stuff (such as `controller`) is unavailable,
1038
+ since we're not using Rails' integration testing.
1039
+
1040
+ * Freezing time: It's common practice to mock out the Time so that features
1041
+ that depend on the current Date work as expected. This can be problematic on
1042
+ ruby/platform combinations that don't support access to a monotonic process clock,
1043
+ since Capybara's Ajax timing uses the system time, resulting in Capybara
1044
+ never timing out and just hanging when a failure occurs. It's still possible to
1045
+ use gems which allow you to travel in time, rather than freeze time.
1046
+ One such gem is [Timecop](https://github.com/travisjeffery/timecop).
1047
+
1048
+ * When using Rack::Test, beware if attempting to visit absolute URLs. For
1049
+ example, a session might not be shared between visits to `posts_path`
1050
+ and `posts_url`. If testing an absolute URL in an Action Mailer email,
1051
+ set `default_url_options` to match the Rails default of
1052
+ `www.example.com`.
1053
+
1054
+ * Server errors will only be raised in the session that initiates the server thread. If you
1055
+ are testing for specific server errors and using multiple sessions make sure to test for the
1056
+ errors using the initial session (usually :default)
1057
+
1058
+ ## <a name="threadsafe"></a>"Threadsafe" mode
1059
+
1060
+ In normal mode most of Capybara's configuration options are global settings which can cause issues
1061
+ if using multiple sessions and wanting to change a setting for only one of the sessions. To provide
1062
+ support for this type of usage Capybara now provides a "threadsafe" mode which can be enabled by setting
1063
+
1064
+ ```ruby
1065
+ Capybara.threadsafe = true
1066
+ ```
1067
+
1068
+ This setting can only be changed before any sessions have been created. In "threadsafe" mode the following
1069
+ behaviors of Capybara change
1070
+
1071
+ * Most options can now be set on a session. These can either be set at session creation time or after, and
1072
+ default to the global options at the time of session creation. Options which are NOT session specific are
1073
+ `app`, `reuse_server`, `default_driver`, `javascript_driver`, and (obviously) `threadsafe`. Any drivers and servers
1074
+ registered through `register_driver` and `register_server` are also global.
1075
+
1076
+ ```ruby
1077
+ my_session = Capybara::Session.new(:driver, some_app) do |config|
1078
+ config.automatic_label_click = true # only set for my_session
1079
+ end
1080
+ my_session.config.default_max_wait_time = 10 # only set for my_session
1081
+ Capybara.default_max_wait_time = 2 # will not change the default_max_wait in my_session
1082
+ ```
1083
+
1084
+ * `current_driver` and `session_name` are thread specific. This means that `using_session` and
1085
+ `using_driver` also only affect the current thread.
1086
+
1087
+ ## <a name="development"></a>Development
1088
+
1089
+ To set up a development environment, simply do:
1090
+
1091
+ ```bash
1092
+ bundle install
1093
+ bundle exec rake # run the test suite with Firefox - requires `geckodriver` to be installed
1094
+ bundle exec rake spec_chrome # run the test suite with Chrome - require `chromedriver` to be installed
1095
+ ```
1096
+
1097
+ See
1098
+ [CONTRIBUTING.md](https://github.com/teamcapybara/capybara/blob/master/CONTRIBUTING.md)
1099
+ for how to send issues and pull requests.