capybara 3.13.2 → 3.40.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (260) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +1 -0
  3. data/History.md +587 -16
  4. data/README.md +240 -90
  5. data/lib/capybara/config.rb +24 -11
  6. data/lib/capybara/cucumber.rb +1 -1
  7. data/lib/capybara/driver/base.rb +8 -0
  8. data/lib/capybara/driver/node.rb +20 -4
  9. data/lib/capybara/dsl.rb +5 -3
  10. data/lib/capybara/helpers.rb +25 -4
  11. data/lib/capybara/minitest/spec.rb +174 -90
  12. data/lib/capybara/minitest.rb +256 -142
  13. data/lib/capybara/node/actions.rb +123 -77
  14. data/lib/capybara/node/base.rb +20 -12
  15. data/lib/capybara/node/document.rb +2 -2
  16. data/lib/capybara/node/document_matchers.rb +3 -3
  17. data/lib/capybara/node/element.rb +223 -117
  18. data/lib/capybara/node/finders.rb +81 -71
  19. data/lib/capybara/node/matchers.rb +271 -134
  20. data/lib/capybara/node/simple.rb +18 -5
  21. data/lib/capybara/node/whitespace_normalizer.rb +81 -0
  22. data/lib/capybara/queries/active_element_query.rb +18 -0
  23. data/lib/capybara/queries/ancestor_query.rb +8 -9
  24. data/lib/capybara/queries/base_query.rb +3 -2
  25. data/lib/capybara/queries/current_path_query.rb +15 -5
  26. data/lib/capybara/queries/selector_query.rb +364 -54
  27. data/lib/capybara/queries/sibling_query.rb +8 -6
  28. data/lib/capybara/queries/style_query.rb +2 -2
  29. data/lib/capybara/queries/text_query.rb +13 -1
  30. data/lib/capybara/queries/title_query.rb +1 -1
  31. data/lib/capybara/rack_test/browser.rb +76 -11
  32. data/lib/capybara/rack_test/driver.rb +10 -5
  33. data/lib/capybara/rack_test/errors.rb +6 -0
  34. data/lib/capybara/rack_test/form.rb +31 -9
  35. data/lib/capybara/rack_test/node.rb +74 -23
  36. data/lib/capybara/registration_container.rb +41 -0
  37. data/lib/capybara/registrations/drivers.rb +42 -0
  38. data/lib/capybara/registrations/patches/puma_ssl.rb +29 -0
  39. data/lib/capybara/registrations/servers.rb +66 -0
  40. data/lib/capybara/result.rb +44 -20
  41. data/lib/capybara/rspec/matcher_proxies.rb +13 -11
  42. data/lib/capybara/rspec/matchers/base.rb +31 -16
  43. data/lib/capybara/rspec/matchers/compound.rb +1 -1
  44. data/lib/capybara/rspec/matchers/count_sugar.rb +37 -0
  45. data/lib/capybara/rspec/matchers/have_ancestor.rb +28 -0
  46. data/lib/capybara/rspec/matchers/have_current_path.rb +2 -2
  47. data/lib/capybara/rspec/matchers/have_selector.rb +21 -21
  48. data/lib/capybara/rspec/matchers/have_sibling.rb +27 -0
  49. data/lib/capybara/rspec/matchers/have_text.rb +4 -4
  50. data/lib/capybara/rspec/matchers/have_title.rb +2 -2
  51. data/lib/capybara/rspec/matchers/match_selector.rb +3 -3
  52. data/lib/capybara/rspec/matchers/match_style.rb +7 -2
  53. data/lib/capybara/rspec/matchers/spatial_sugar.rb +39 -0
  54. data/lib/capybara/rspec/matchers.rb +111 -68
  55. data/lib/capybara/rspec.rb +2 -0
  56. data/lib/capybara/selector/builders/css_builder.rb +11 -7
  57. data/lib/capybara/selector/builders/xpath_builder.rb +5 -3
  58. data/lib/capybara/selector/css.rb +11 -9
  59. data/lib/capybara/selector/definition/button.rb +68 -0
  60. data/lib/capybara/selector/definition/checkbox.rb +26 -0
  61. data/lib/capybara/selector/definition/css.rb +10 -0
  62. data/lib/capybara/selector/definition/datalist_input.rb +35 -0
  63. data/lib/capybara/selector/definition/datalist_option.rb +25 -0
  64. data/lib/capybara/selector/definition/element.rb +28 -0
  65. data/lib/capybara/selector/definition/field.rb +40 -0
  66. data/lib/capybara/selector/definition/fieldset.rb +14 -0
  67. data/lib/capybara/selector/definition/file_field.rb +13 -0
  68. data/lib/capybara/selector/definition/fillable_field.rb +33 -0
  69. data/lib/capybara/selector/definition/frame.rb +17 -0
  70. data/lib/capybara/selector/definition/id.rb +6 -0
  71. data/lib/capybara/selector/definition/label.rb +62 -0
  72. data/lib/capybara/selector/definition/link.rb +55 -0
  73. data/lib/capybara/selector/definition/link_or_button.rb +16 -0
  74. data/lib/capybara/selector/definition/option.rb +27 -0
  75. data/lib/capybara/selector/definition/radio_button.rb +27 -0
  76. data/lib/capybara/selector/definition/select.rb +81 -0
  77. data/lib/capybara/selector/definition/table.rb +109 -0
  78. data/lib/capybara/selector/definition/table_row.rb +21 -0
  79. data/lib/capybara/selector/definition/xpath.rb +5 -0
  80. data/lib/capybara/selector/definition.rb +280 -0
  81. data/lib/capybara/selector/filter_set.rb +19 -18
  82. data/lib/capybara/selector/filters/base.rb +11 -2
  83. data/lib/capybara/selector/filters/locator_filter.rb +13 -3
  84. data/lib/capybara/selector/regexp_disassembler.rb +11 -7
  85. data/lib/capybara/selector/selector.rb +50 -440
  86. data/lib/capybara/selector/xpath_extensions.rb +17 -0
  87. data/lib/capybara/selector.rb +473 -482
  88. data/lib/capybara/selenium/atoms/getAttribute.min.js +1 -0
  89. data/lib/capybara/selenium/atoms/isDisplayed.min.js +1 -0
  90. data/lib/capybara/selenium/atoms/src/getAttribute.js +161 -0
  91. data/lib/capybara/selenium/atoms/src/isDisplayed.js +454 -0
  92. data/lib/capybara/selenium/driver.rb +174 -62
  93. data/lib/capybara/selenium/driver_specializations/chrome_driver.rb +74 -18
  94. data/lib/capybara/selenium/driver_specializations/edge_driver.rb +128 -0
  95. data/lib/capybara/selenium/driver_specializations/firefox_driver.rb +37 -3
  96. data/lib/capybara/selenium/driver_specializations/internet_explorer_driver.rb +14 -1
  97. data/lib/capybara/selenium/driver_specializations/safari_driver.rb +24 -0
  98. data/lib/capybara/selenium/extensions/file_input_click_emulation.rb +34 -0
  99. data/lib/capybara/selenium/extensions/find.rb +68 -45
  100. data/lib/capybara/selenium/extensions/html5_drag.rb +192 -22
  101. data/lib/capybara/selenium/extensions/modifier_keys_stack.rb +28 -0
  102. data/lib/capybara/selenium/extensions/scroll.rb +8 -10
  103. data/lib/capybara/selenium/node.rb +268 -72
  104. data/lib/capybara/selenium/nodes/chrome_node.rb +105 -9
  105. data/lib/capybara/selenium/nodes/edge_node.rb +110 -0
  106. data/lib/capybara/selenium/nodes/firefox_node.rb +51 -61
  107. data/lib/capybara/selenium/nodes/ie_node.rb +22 -0
  108. data/lib/capybara/selenium/nodes/safari_node.rb +118 -0
  109. data/lib/capybara/selenium/patches/atoms.rb +18 -0
  110. data/lib/capybara/selenium/patches/is_displayed.rb +16 -0
  111. data/lib/capybara/selenium/patches/logs.rb +45 -0
  112. data/lib/capybara/selenium/patches/pause_duration_fix.rb +1 -1
  113. data/lib/capybara/selenium/patches/persistent_client.rb +20 -0
  114. data/lib/capybara/server/animation_disabler.rb +43 -21
  115. data/lib/capybara/server/checker.rb +6 -2
  116. data/lib/capybara/server/middleware.rb +25 -13
  117. data/lib/capybara/server.rb +20 -4
  118. data/lib/capybara/session/config.rb +15 -11
  119. data/lib/capybara/session/matchers.rb +11 -11
  120. data/lib/capybara/session.rb +162 -131
  121. data/lib/capybara/spec/public/offset.js +6 -0
  122. data/lib/capybara/spec/public/test.js +105 -6
  123. data/lib/capybara/spec/session/accept_alert_spec.rb +1 -1
  124. data/lib/capybara/spec/session/active_element_spec.rb +31 -0
  125. data/lib/capybara/spec/session/all_spec.rb +89 -15
  126. data/lib/capybara/spec/session/ancestor_spec.rb +5 -0
  127. data/lib/capybara/spec/session/assert_current_path_spec.rb +5 -2
  128. data/lib/capybara/spec/session/assert_text_spec.rb +26 -22
  129. data/lib/capybara/spec/session/attach_file_spec.rb +64 -31
  130. data/lib/capybara/spec/session/check_spec.rb +26 -4
  131. data/lib/capybara/spec/session/choose_spec.rb +14 -2
  132. data/lib/capybara/spec/session/click_button_spec.rb +109 -61
  133. data/lib/capybara/spec/session/click_link_or_button_spec.rb +9 -0
  134. data/lib/capybara/spec/session/click_link_spec.rb +23 -1
  135. data/lib/capybara/spec/session/current_scope_spec.rb +1 -1
  136. data/lib/capybara/spec/session/current_url_spec.rb +11 -1
  137. data/lib/capybara/spec/session/element/matches_selector_spec.rb +40 -39
  138. data/lib/capybara/spec/session/evaluate_script_spec.rb +12 -0
  139. data/lib/capybara/spec/session/fill_in_spec.rb +46 -5
  140. data/lib/capybara/spec/session/find_link_spec.rb +10 -0
  141. data/lib/capybara/spec/session/find_spec.rb +80 -7
  142. data/lib/capybara/spec/session/first_spec.rb +2 -2
  143. data/lib/capybara/spec/session/frame/switch_to_frame_spec.rb +14 -1
  144. data/lib/capybara/spec/session/frame/within_frame_spec.rb +14 -1
  145. data/lib/capybara/spec/session/has_all_selectors_spec.rb +5 -5
  146. data/lib/capybara/spec/session/has_ancestor_spec.rb +46 -0
  147. data/lib/capybara/spec/session/has_any_selectors_spec.rb +6 -2
  148. data/lib/capybara/spec/session/has_button_spec.rb +81 -0
  149. data/lib/capybara/spec/session/has_css_spec.rb +45 -8
  150. data/lib/capybara/spec/session/has_current_path_spec.rb +22 -7
  151. data/lib/capybara/spec/session/has_element_spec.rb +47 -0
  152. data/lib/capybara/spec/session/has_field_spec.rb +59 -1
  153. data/lib/capybara/spec/session/has_link_spec.rb +40 -0
  154. data/lib/capybara/spec/session/has_none_selectors_spec.rb +7 -7
  155. data/lib/capybara/spec/session/has_select_spec.rb +42 -8
  156. data/lib/capybara/spec/session/has_selector_spec.rb +19 -4
  157. data/lib/capybara/spec/session/has_sibling_spec.rb +50 -0
  158. data/lib/capybara/spec/session/has_table_spec.rb +177 -0
  159. data/lib/capybara/spec/session/has_text_spec.rb +31 -3
  160. data/lib/capybara/spec/session/html_spec.rb +1 -1
  161. data/lib/capybara/spec/session/matches_style_spec.rb +6 -4
  162. data/lib/capybara/spec/session/node_spec.rb +697 -23
  163. data/lib/capybara/spec/session/node_wrapper_spec.rb +1 -1
  164. data/lib/capybara/spec/session/refresh_spec.rb +2 -1
  165. data/lib/capybara/spec/session/reset_session_spec.rb +21 -7
  166. data/lib/capybara/spec/session/save_and_open_screenshot_spec.rb +2 -2
  167. data/lib/capybara/spec/session/save_page_spec.rb +4 -4
  168. data/lib/capybara/spec/session/save_screenshot_spec.rb +4 -4
  169. data/lib/capybara/spec/session/scroll_spec.rb +9 -7
  170. data/lib/capybara/spec/session/select_spec.rb +5 -10
  171. data/lib/capybara/spec/session/selectors_spec.rb +24 -3
  172. data/lib/capybara/spec/session/uncheck_spec.rb +3 -3
  173. data/lib/capybara/spec/session/unselect_spec.rb +1 -1
  174. data/lib/capybara/spec/session/visit_spec.rb +20 -0
  175. data/lib/capybara/spec/session/window/become_closed_spec.rb +20 -17
  176. data/lib/capybara/spec/session/window/switch_to_window_spec.rb +1 -1
  177. data/lib/capybara/spec/session/window/window_opened_by_spec.rb +1 -1
  178. data/lib/capybara/spec/session/window/window_spec.rb +54 -57
  179. data/lib/capybara/spec/session/window/windows_spec.rb +2 -2
  180. data/lib/capybara/spec/session/within_spec.rb +36 -0
  181. data/lib/capybara/spec/spec_helper.rb +30 -19
  182. data/lib/capybara/spec/test_app.rb +122 -34
  183. data/lib/capybara/spec/views/animated.erb +49 -0
  184. data/lib/capybara/spec/views/form.erb +86 -8
  185. data/lib/capybara/spec/views/frame_child.erb +3 -2
  186. data/lib/capybara/spec/views/frame_one.erb +2 -1
  187. data/lib/capybara/spec/views/frame_parent.erb +1 -1
  188. data/lib/capybara/spec/views/frame_two.erb +1 -1
  189. data/lib/capybara/spec/views/initial_alert.erb +2 -1
  190. data/lib/capybara/spec/views/layout.erb +10 -0
  191. data/lib/capybara/spec/views/obscured.erb +10 -10
  192. data/lib/capybara/spec/views/offset.erb +33 -0
  193. data/lib/capybara/spec/views/path.erb +2 -2
  194. data/lib/capybara/spec/views/popup_one.erb +1 -1
  195. data/lib/capybara/spec/views/popup_two.erb +1 -1
  196. data/lib/capybara/spec/views/react.erb +45 -0
  197. data/lib/capybara/spec/views/scroll.erb +2 -1
  198. data/lib/capybara/spec/views/spatial.erb +31 -0
  199. data/lib/capybara/spec/views/tables.erb +67 -0
  200. data/lib/capybara/spec/views/with_animation.erb +39 -4
  201. data/lib/capybara/spec/views/with_base_tag.erb +2 -2
  202. data/lib/capybara/spec/views/with_dragula.erb +24 -0
  203. data/lib/capybara/spec/views/with_fixed_header_footer.erb +2 -1
  204. data/lib/capybara/spec/views/with_hover.erb +3 -2
  205. data/lib/capybara/spec/views/with_hover1.erb +10 -0
  206. data/lib/capybara/spec/views/with_html.erb +34 -6
  207. data/lib/capybara/spec/views/with_jquery_animation.erb +24 -0
  208. data/lib/capybara/spec/views/with_js.erb +7 -4
  209. data/lib/capybara/spec/views/with_jstree.erb +26 -0
  210. data/lib/capybara/spec/views/with_namespace.erb +1 -0
  211. data/lib/capybara/spec/views/with_scope.erb +2 -2
  212. data/lib/capybara/spec/views/with_scope_other.erb +6 -0
  213. data/lib/capybara/spec/views/with_shadow.erb +31 -0
  214. data/lib/capybara/spec/views/with_slow_unload.erb +2 -1
  215. data/lib/capybara/spec/views/with_sortable_js.erb +21 -0
  216. data/lib/capybara/spec/views/with_unload_alert.erb +1 -0
  217. data/lib/capybara/spec/views/with_windows.erb +1 -1
  218. data/lib/capybara/spec/views/within_frames.erb +1 -1
  219. data/lib/capybara/version.rb +1 -1
  220. data/lib/capybara/window.rb +14 -18
  221. data/lib/capybara.rb +91 -126
  222. data/spec/basic_node_spec.rb +30 -16
  223. data/spec/capybara_spec.rb +40 -28
  224. data/spec/counter_spec.rb +35 -0
  225. data/spec/css_builder_spec.rb +3 -1
  226. data/spec/css_splitter_spec.rb +1 -1
  227. data/spec/dsl_spec.rb +33 -22
  228. data/spec/filter_set_spec.rb +5 -5
  229. data/spec/fixtures/selenium_driver_rspec_failure.rb +3 -3
  230. data/spec/fixtures/selenium_driver_rspec_success.rb +3 -3
  231. data/spec/minitest_spec.rb +24 -2
  232. data/spec/minitest_spec_spec.rb +60 -45
  233. data/spec/per_session_config_spec.rb +1 -1
  234. data/spec/rack_test_spec.rb +131 -98
  235. data/spec/regexp_dissassembler_spec.rb +53 -39
  236. data/spec/result_spec.rb +68 -66
  237. data/spec/rspec/features_spec.rb +9 -4
  238. data/spec/rspec/scenarios_spec.rb +6 -2
  239. data/spec/rspec/shared_spec_matchers.rb +137 -98
  240. data/spec/rspec_matchers_spec.rb +25 -0
  241. data/spec/rspec_spec.rb +23 -21
  242. data/spec/sauce_spec_chrome.rb +43 -0
  243. data/spec/selector_spec.rb +77 -21
  244. data/spec/selenium_spec_chrome.rb +141 -39
  245. data/spec/selenium_spec_chrome_remote.rb +32 -17
  246. data/spec/selenium_spec_edge.rb +36 -8
  247. data/spec/selenium_spec_firefox.rb +110 -68
  248. data/spec/selenium_spec_firefox_remote.rb +22 -15
  249. data/spec/selenium_spec_ie.rb +29 -22
  250. data/spec/selenium_spec_safari.rb +162 -0
  251. data/spec/server_spec.rb +153 -81
  252. data/spec/session_spec.rb +11 -4
  253. data/spec/shared_selenium_node.rb +79 -0
  254. data/spec/shared_selenium_session.rb +179 -74
  255. data/spec/spec_helper.rb +80 -5
  256. data/spec/whitespace_normalizer_spec.rb +54 -0
  257. data/spec/xpath_builder_spec.rb +3 -1
  258. metadata +218 -30
  259. data/lib/capybara/spec/session/source_spec.rb +0 -0
  260. data/lib/capybara/spec/views/with_title.erb +0 -5
data/README.md CHANGED
@@ -1,12 +1,8 @@
1
1
  # Capybara
2
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)
3
+ [![Build Status](https://github.com/teamcapybara/capybara/actions/workflows/build.yml/badge.svg)](https://github.com/teamcapybara/capybara/actions/workflows/build.yml)
5
4
  [![Code Climate](https://codeclimate.com/github/teamcapybara/capybara.svg)](https://codeclimate.com/github/teamcapybara/capybara)
6
- [![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)
7
- [![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)
8
-
9
- **Note** You are viewing the README for the version 3.13.x of Capybara.
5
+ [![Coverage Status](https://coveralls.io/repos/github/teamcapybara/capybara/badge.svg?branch=master)](https://coveralls.io/github/teamcapybara/capybara?branch=master)
10
6
 
11
7
  Capybara helps you test web applications by simulating how a real user would
12
8
  interact with your app. It is agnostic about the driver running your tests and
@@ -19,8 +15,7 @@ If you and/or your company find value in Capybara and would like to contribute f
19
15
  <a href="https://www.patreon.com/capybara">Patreon</a>
20
16
 
21
17
 
22
- **Need help?** Ask on the mailing list (please do not open an issue on
23
- GitHub): http://groups.google.com/group/ruby-capybara
18
+ **Need help?** Ask on the discussions (please do not open an issue): https://github.com/orgs/teamcapybara/discussions/categories/q-a
24
19
 
25
20
  ## Table of contents
26
21
 
@@ -35,9 +30,6 @@ GitHub): http://groups.google.com/group/ruby-capybara
35
30
  - [Selecting the Driver](#selecting-the-driver)
36
31
  - [RackTest](#racktest)
37
32
  - [Selenium](#selenium)
38
- - [Apparition](#apparition)
39
- - [Capybara-webkit](#capybara-webkit)
40
- - [Poltergeist](#poltergeist)
41
33
  - [The DSL](#the-dsl)
42
34
  - [Navigating](#navigating)
43
35
  - [Clicking links and buttons](#clicking-links-and-buttons)
@@ -49,6 +41,10 @@ GitHub): http://groups.google.com/group/ruby-capybara
49
41
  - [Scripting](#scripting)
50
42
  - [Modals](#modals)
51
43
  - [Debugging](#debugging)
44
+ - [Selectors](#selectors)
45
+ - [Name](#selectors-name)
46
+ - [Locator](#selectors-locator)
47
+ - [Filters](#selectors-filters)
52
48
  - [Matching](#matching)
53
49
  - [Exactness](#exactness)
54
50
  - [Strategy](#strategy)
@@ -57,11 +53,13 @@ GitHub): http://groups.google.com/group/ruby-capybara
57
53
  - [Using the DSL elsewhere](#using-the-dsl-elsewhere)
58
54
  - [Calling remote servers](#calling-remote-servers)
59
55
  - [Using sessions](#using-sessions)
56
+ - [Named sessions](#named-sessions)
57
+ - [Using sessions manually](#using-sessions-manually)
60
58
  - [XPath, CSS and selectors](#xpath-css-and-selectors)
61
59
  - [Beware the XPath // trap](#beware-the-xpath--trap)
62
60
  - [Configuring and adding drivers](#configuring-and-adding-drivers)
63
61
  - [Gotchas:](#gotchas)
64
- - ["Threadsafe" mode](#threadsafe)
62
+ - ["Threadsafe" mode](#threadsafe-mode)
65
63
  - [Development](#development)
66
64
 
67
65
  ## <a name="key-benefits"></a>Key benefits
@@ -75,7 +73,7 @@ GitHub): http://groups.google.com/group/ruby-capybara
75
73
 
76
74
  ## <a name="setup"></a>Setup
77
75
 
78
- Capybara requires Ruby 2.3.0 or later. To install, add this line to your
76
+ Capybara requires Ruby 3.0.0 or later. To install, add this line to your
79
77
  `Gemfile` and run `bundle install`:
80
78
 
81
79
  ```ruby
@@ -146,11 +144,13 @@ Load RSpec 3.5+ support by adding the following line (typically to your
146
144
  require 'capybara/rspec'
147
145
  ```
148
146
 
149
- If you are using Rails, put your Capybara specs in `spec/features` or `spec/system` (only works
150
- if [you have it configured in
151
- RSpec](https://www.relishapp.com/rspec/rspec-rails/docs/upgrade#file-type-inference-disabled))
152
- and if you have your Capybara specs in a different directory, then tag the
153
- example groups with `type: :feature` or `type: :system` depending on which type of test you're writing.
147
+ If you are using Rails, put your Capybara specs in `spec/features` or `spec/system` (only works if
148
+ [you have it configured in RSpec](https://rspec.info/features/6-0/rspec-rails/directory-structure/))
149
+ and if you have your Capybara specs in a different directory, then tag the example groups with
150
+ `type: :feature` or `type: :system` depending on which type of test you're writing.
151
+
152
+ If you are using Rails system specs please see [their documentation](https://rspec.info/features/6-0/rspec-rails/system-specs/system-specs)
153
+ for selecting the driver you wish to use.
154
154
 
155
155
  If you are not using Rails, tag all the example groups in which you want to use
156
156
  Capybara with `type: :feature`.
@@ -160,7 +160,7 @@ You can now write your specs like so:
160
160
  ```ruby
161
161
  describe "the signin process", type: :feature do
162
162
  before :each do
163
- User.make(email: 'user@example.com', password: 'password')
163
+ User.create(email: 'user@example.com', password: 'password')
164
164
  end
165
165
 
166
166
  it "signs me in" do
@@ -182,7 +182,7 @@ to one specific driver. For example:
182
182
  ```ruby
183
183
  describe 'some stuff which requires js', js: true do
184
184
  it 'will use the default js driver'
185
- it 'will switch to one specific driver', driver: :webkit
185
+ it 'will switch to one specific driver', driver: :selenium
186
186
  end
187
187
  ```
188
188
 
@@ -191,7 +191,7 @@ Capybara also comes with a built in DSL for creating descriptive acceptance test
191
191
  ```ruby
192
192
  feature "Signing in" do
193
193
  background do
194
- User.make(email: 'user@example.com', password: 'caplin')
194
+ User.create(email: 'user@example.com', password: 'caplin')
195
195
  end
196
196
 
197
197
  scenario "Signing in with correct credentials" do
@@ -204,7 +204,7 @@ feature "Signing in" do
204
204
  expect(page).to have_content 'Success'
205
205
  end
206
206
 
207
- given(:other_user) { User.make(email: 'other@example.com', password: 'rous') }
207
+ given(:other_user) { User.create(email: 'other@example.com', password: 'rous') }
208
208
 
209
209
  scenario "Signing in as another user" do
210
210
  visit '/sessions/new'
@@ -259,7 +259,9 @@ end
259
259
 
260
260
  ## <a name="using-capybara-with-minitest"></a>Using Capybara with Minitest
261
261
 
262
- * If you are using Rails, add the following code in your `test_helper.rb`
262
+ * If you are using Rails system tests please see their documentation for information on selecting the driver you wish to use.
263
+
264
+ * If you are using Rails, but not using Rails system tests, add the following code in your `test_helper.rb`
263
265
  file to make Capybara available in all test cases deriving from
264
266
  `ActionDispatch::IntegrationTest`:
265
267
 
@@ -274,8 +276,7 @@ end
274
276
  include Capybara::Minitest::Assertions
275
277
 
276
278
  # Reset sessions and driver between tests
277
- # Use super wherever this method is redefined in your individual test classes
278
- def teardown
279
+ teardown do
279
280
  Capybara.reset_sessions!
280
281
  Capybara.use_default_driver
281
282
  end
@@ -334,15 +335,15 @@ By default, Capybara uses the `:rack_test` driver, which is fast but limited: it
334
335
  does not support JavaScript, nor is it able to access HTTP resources outside of
335
336
  your Rack application, such as remote APIs and OAuth services. To get around
336
337
  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
+ For example, if you'd prefer to run everything in Selenium, you could do:
338
339
 
339
340
  ```ruby
340
341
  Capybara.default_driver = :selenium # :selenium_chrome and :selenium_chrome_headless are also registered
341
342
  ```
342
343
 
343
- However, if you are using RSpec or Cucumber, you may instead want to consider
344
- leaving the faster `:rack_test` as the __default_driver__, and marking only those
345
- tests that require a JavaScript-capable driver using `js: true` or
344
+ However, if you are using RSpec or Cucumber (and your app runs correctly without JS),
345
+ you may instead want to consider leaving the faster `:rack_test` as the __default_driver__, and
346
+ marking only those tests that require a JavaScript-capable driver using `js: true` or
346
347
  `@javascript`, respectively. By default, JavaScript tests are run using the
347
348
  `:selenium` driver. You can change this by setting
348
349
  `Capybara.javascript_driver`.
@@ -351,7 +352,7 @@ You can also change the driver temporarily (typically in the Before/setup and
351
352
  After/teardown blocks):
352
353
 
353
354
  ```ruby
354
- Capybara.current_driver = :webkit # temporarily select different driver
355
+ Capybara.current_driver = :selenium # temporarily select different driver
355
356
  # tests here
356
357
  Capybara.use_default_driver # switch back to default driver
357
358
  ```
@@ -391,7 +392,7 @@ Capybara supports [Selenium 3.5+
391
392
  In order to use Selenium, you'll need to install the `selenium-webdriver` gem,
392
393
  and add it to your Gemfile if you're using bundler.
393
394
 
394
- Capybara pre-registers a number of named drives that use Selenium - they are:
395
+ Capybara pre-registers a number of named drivers that use Selenium - they are:
395
396
 
396
397
  * :selenium => Selenium driving Firefox
397
398
  * :selenium_headless => Selenium driving Firefox in a headless configuration
@@ -407,45 +408,6 @@ to the browsers. See the section on adding and configuring drivers.
407
408
  same transaction as your tests, causing data not to be shared between your test
408
409
  and test server, see [Transactions and database setup](#transactions-and-database-setup) below.
409
410
 
410
- ### <a name="apparition"></a>Apparition
411
-
412
- The [apparition driver](https://github.com/twalpole/apparition) in a new driver thatallows 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
- while allowing for the use of modern JS/CSS. It uses CDP to communicate with Chrome, thereby obviating the need for chromedriver.
415
- A compatibility layer for capybara-webkit is planned, although has not yet been started. This driver is being developed by the
416
- maintainer 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 completely stable.
418
-
419
- ### <a name="capybara-webkit"></a>Capybara-webkit
420
-
421
- Note: `capybara-webkit` depends on QtWebkit which went EOL quite some time ago. There has been an attempt to revive the project but `capybara-webkit` is not yet (AFAIK) compatible with the revived version of QtWebKit (could be a good OSS project for someone) and as such is still limited to an old version of QtWebKit. This means its support for modern JS and CSS is severely limited.
422
-
423
- The [capybara-webkit driver](https://github.com/thoughtbot/capybara-webkit) is for true headless
424
- testing. It uses QtWebKit to start a rendering engine process. It can execute JavaScript as well.
425
- It is significantly faster than drivers like Selenium since it does not load an entire browser.
426
-
427
- You can install it with:
428
-
429
- ```bash
430
- gem install capybara-webkit
431
- ```
432
-
433
- And you can use it by:
434
-
435
- ```ruby
436
- Capybara.javascript_driver = :webkit
437
- ```
438
-
439
- ### <a name="poltergeist"></a>Poltergeist
440
-
441
- Note: `poltergeist` depends on PhantomJS for which active development ended quite some time ago (2.1.1). As such it is roughly equivalent to a 6-7 year old version of Safari, meaning lack of support for modern JS and CSS. If any effort to update PhantomJS succeeds in the future this situation could change.
442
-
443
- [Poltergeist](https://github.com/teampoltergeist/poltergeist) is another
444
- headless driver which integrates Capybara with
445
- [PhantomJS](http://phantomjs.org/). It is truly headless, so doesn't
446
- require Xvfb to run on your CI server. It will also detect and report
447
- any Javascript errors that happen within the page.
448
-
449
411
  ## <a name="the-dsl"></a>The DSL
450
412
 
451
413
  *A complete reference is available at
@@ -639,21 +601,31 @@ In drivers which support it, you can easily execute JavaScript:
639
601
  page.execute_script("$('body').empty()")
640
602
  ```
641
603
 
642
- For simple expressions, you can return the result of the script. Note
643
- that this may break with more complicated expressions:
604
+ For simple expressions, you can return the result of the script.
644
605
 
645
606
  ```ruby
646
607
  result = page.evaluate_script('4 + 4');
647
608
  ```
648
609
 
610
+ For more complicated scripts you'll need to write them as one expression.
611
+
612
+ ```ruby
613
+ result = page.evaluate_script(<<~JS, 3, element)
614
+ (function(n, el){
615
+ var val = parseInt(el.value, 10);
616
+ return n+val;
617
+ })(arguments[0], arguments[1])
618
+ JS
619
+ ```
620
+
649
621
  ### <a name="modals"></a>Modals
650
622
 
651
- In drivers which support it, you can accept, dismiss and respond to alerts, confirms and prompts.
623
+ In drivers which support it, you can accept, dismiss and respond to alerts, confirms, and prompts.
652
624
 
653
- You can accept or dismiss alert messages by wrapping the code that produces an alert in a block:
625
+ You can accept alert messages by wrapping the code that produces an alert in a block:
654
626
 
655
627
  ```ruby
656
- accept_alert do
628
+ accept_alert 'optional text or regex' do
657
629
  click_link('Show Alert')
658
630
  end
659
631
  ```
@@ -661,7 +633,13 @@ end
661
633
  You can accept or dismiss a confirmation by wrapping it in a block, as well:
662
634
 
663
635
  ```ruby
664
- dismiss_confirm do
636
+ accept_confirm 'optional text' do
637
+ click_link('Show Confirm')
638
+ end
639
+ ```
640
+
641
+ ```ruby
642
+ dismiss_confirm 'optional text' do
665
643
  click_link('Show Confirm')
666
644
  end
667
645
  ```
@@ -669,7 +647,13 @@ end
669
647
  You can accept or dismiss prompts as well, and also provide text to fill in for the response:
670
648
 
671
649
  ```ruby
672
- accept_prompt(with: 'Linus Torvalds') do
650
+ accept_prompt('optional text', with: 'Linus Torvalds') do
651
+ click_link('Show Prompt About Linux')
652
+ end
653
+ ```
654
+
655
+ ```ruby
656
+ dismiss_prompt('optional text') do
673
657
  click_link('Show Prompt About Linux')
674
658
  end
675
659
  ```
@@ -719,6 +703,148 @@ Screenshots are saved to `Capybara.save_path`, relative to the app directory.
719
703
  If you have required `capybara/rails`, `Capybara.save_path` will default to
720
704
  `tmp/capybara`.
721
705
 
706
+ ## <a name="selectors"></a>Selectors
707
+
708
+ Helpers and matchers that accept Selectors share a common method signature that
709
+ includes:
710
+
711
+ 1. a positional Name argument
712
+ 2. a positional Locator argument
713
+ 3. keyword Filter arguments
714
+ 4. a predicate Filter block argument
715
+
716
+ These arguments are usually optional in one way or another.
717
+
718
+ ### <a name="selectors-name"></a>Name
719
+
720
+ The name argument determines the Selector to use. The argument is optional when
721
+ a helper explicitly conveys the selector name (for example, [`find_field`][]
722
+ uses `:field`, [`find_link`][] uses `:link`, etc):
723
+
724
+ ```ruby
725
+ page.html # => '<a href="/">Home</a>'
726
+
727
+ page.find(:link) == page.find_link
728
+
729
+ page.html # => '<input>'
730
+
731
+ page.find(:field) == page.find_field
732
+ ```
733
+
734
+ ### <a name="selectors-locator"></a>Locator
735
+
736
+ The locator argument usually represents information that can most meaningfully
737
+ distinguish an element that matches the selector from an element that does not:
738
+
739
+ ```ruby
740
+ page.html # => '<div id="greeting">Hello world</div>'
741
+
742
+ page.find(:css, 'div').text # => 'Hello world'
743
+ page.find(:xpath, './/div').text # => 'Hello world'
744
+ ```
745
+
746
+ General purpose finder methods like [`find`][] and [`all`][] can accept the
747
+ locator as their first positional argument when the method can infer the default
748
+ value from the [`Capybara.default_selector`][] configuration:
749
+
750
+ ```ruby
751
+ page.html # => '<div id="greeting">Hello world</div>'
752
+
753
+ Capybara.default_selector = :css
754
+
755
+ page.find('div').text # => 'Hello world'
756
+
757
+ Capybara.default_selector = :xpath
758
+
759
+ page.find('.//div').text # => 'Hello world'
760
+ ```
761
+
762
+ The locator argument's semantics are context-specific, and depend on the
763
+ selector. The types of arguments are varied. Some selectors support `String` or
764
+ `Regexp` arguments, while others like `:table_row` support `Array<String>` and
765
+ `Hash<String, String>`:
766
+
767
+ ```ruby
768
+ page.html # => '<label for="greeting">Greeting</label>
769
+ <input id="greeting" name="content">'
770
+
771
+ # find by the <input> element's [id] attribute
772
+ page.find(:id, 'greeting') == page.find_by_id('greeting') # => true
773
+
774
+ # find by the <input> element's [id] attribute
775
+ page.find(:field, 'greeting') == page.find_field('greeting') # => true
776
+
777
+ # find by the <input> element's [name] attribute
778
+ page.find(:field, 'content') == page.find_field('content') # => true
779
+
780
+ # find by the <label> element's text
781
+ page.find(:field, 'Greeting') == page.find_field('Greeting') # => true
782
+
783
+ page.html # => '<table>
784
+ <tr>
785
+ <th>A</th>
786
+ <th>B</th>
787
+ </tr>
788
+ <tr>
789
+ <td>1</td>
790
+ <td>2</td>
791
+ </tr>
792
+ </table>'
793
+
794
+ # find by <td> content
795
+ page.find(:table_row, ['1', '2']) == page.find(:css, 'tr:last-of-type') # => true
796
+
797
+ # find by <th> content paired with corresponding <td> content
798
+ page.find(:table_row, 'A' => '1') == page.find(:table_row, 'B' => '2') # => true
799
+ ```
800
+
801
+ ### <a name="selectors-filters"></a> Filters
802
+
803
+ All filters are optional. The supported set of keys is a mixture of both global
804
+ and context-specific filters.The supported types of values depend on the
805
+ context:
806
+
807
+ ```ruby
808
+ page.html # => '<a href="/">Home</a>'
809
+
810
+ # find by the [href] attribute
811
+ page.find_link(href: '/') == page.find_link(text: 'Home') # => true
812
+
813
+ page.html # => '<div id="element" data-attribute="value">Content</div>'
814
+
815
+ # find by the [id] attribute
816
+ page.find(id: 'element') == page.find(text: 'Content') # => true
817
+
818
+ # find by the [data-attribute] attribute
819
+ page.find(:element, 'data-attribute': /value/) == page.find(text: 'Content') # => true
820
+
821
+ page.html # => '<input type="checkbox">'
822
+
823
+ # find by the absence of the [checked] attribute
824
+ page.find_field(checked: false) == page.find_field(unchecked: true) # => true
825
+ ```
826
+
827
+ The predicate block is always optional. When there are results for a selector
828
+ query, the block is called with each item in the result set. When the block
829
+ evaluates to true, the item is included from the result set. Otherwise, the item
830
+ is excluded:
831
+
832
+ ```ruby
833
+ page.html # => '<input role="switch" type="checkbox" checked>'
834
+
835
+ switch = page.find_field { |input| input["role"] == "switch" }
836
+ field = page.find_field(checked: true)
837
+
838
+ switch == field # => true
839
+ ```
840
+
841
+ [`find`]: https://rubydoc.info/github/teamcapybara/capybara/master/Capybara/Node/Finders:find
842
+ [`all`]: https://rubydoc.info/github/teamcapybara/capybara/master/Capybara/Node/Finders:all
843
+ [`Capybara.default_selector`]: https://rubydoc.info/github/teamcapybara/capybara/master/Capybara%2Econfigure
844
+ [`find_by_id`]: https://rubydoc.info/github/teamcapybara/capybara/master/Capybara/Node/Finders:find_by_id
845
+ [`find_field`]: https://rubydoc.info/github/teamcapybara/capybara/master/Capybara/Node/Finders:find_field
846
+ [`find_link`]: https://rubydoc.info/github/teamcapybara/capybara/master/Capybara/Node/Finders:find_link
847
+
722
848
  ## <a name="matching"></a>Matching
723
849
 
724
850
  It is possible to customize how Capybara finds elements. At your disposal
@@ -799,7 +925,7 @@ expect(page).to have_content('baz')
799
925
  If clicking on the *foo* link triggers an asynchronous process, such as
800
926
  an Ajax request, which, when complete will add the *bar* link to the page,
801
927
  clicking on the *bar* link would be expected to fail, since that link doesn't
802
- exist yet. However Capybara is smart enough to retry finding the link for a
928
+ exist yet. However, Capybara is smart enough to retry finding the link for a
803
929
  brief period of time before giving up and throwing an error. The same is true of
804
930
  the next line, which looks for the content *baz* on the page; it will retry
805
931
  looking for that content for a brief time. You can adjust how long this period
@@ -813,13 +939,25 @@ Be aware that because of this behaviour, the following two statements are **not*
813
939
  equivalent, and you should **always** use the latter!
814
940
 
815
941
  ```ruby
816
- !page.has_xpath?('a')
817
- page.has_no_xpath?('a')
942
+ # Given use of a driver where the page is loaded when visit returns
943
+ # and that Capybara.predicates_wait is `true`
944
+ # consider a page where the `a` tag is removed through AJAX after 1s
945
+ visit(some_path)
946
+ !page.has_xpath?('a') # is false
947
+ page.has_no_xpath?('a') # is true
818
948
  ```
819
949
 
820
- The former would immediately fail because the content has not yet been removed.
821
- Only the latter would wait for the asynchronous process to remove the content
822
- from the page.
950
+ First expression:
951
+ - `has_xpath?('a')` is called right after `visit` returns. It is `true` because the link has not yet been removed
952
+ - Capybara does not wait upon successful predicates/assertions, therefore **has_xpath? returns `true` immediately**
953
+ - The expression returns `false` (because it is negated with the leading `!`)
954
+
955
+ Second expression:
956
+ - `has_no_xpath?('a')` is called right after `visit` returns. It is `false` because the link has not yet been removed.
957
+ - Capybara waits upon failed predicates/assertions, therefore **has_no_xpath? does not return `false` immediately**
958
+ - Capybara will periodically re-check the predicate/assertion up to the `default_max_wait_time` defined
959
+ - after 1s, the predicate becomes `true` (because the link has been removed)
960
+ - The expression returns `true`
823
961
 
824
962
  Capybara's RSpec matchers, however, are smart enough to handle either form.
825
963
  The two following statements are functionally equivalent:
@@ -954,12 +1092,17 @@ Capybara.default_selector = :xpath
954
1092
  find('.//ul/li').text
955
1093
  ```
956
1094
 
957
- Capybara allows you to add custom selectors, which can be very useful if you
958
- find yourself using the same kinds of selectors very often:
1095
+ Capybara provides a number of other built-in selector types. The full list, along
1096
+ with applicable filters, can be seen at [built-in selectors](https://www.rubydoc.info/github/teamcapybara/capybara/Capybara/Selector)
1097
+
1098
+ Capybara also allows you to add custom selectors, which can be very useful if you
1099
+ find yourself using the same kinds of selectors very often. The examples below are very
1100
+ simple, and there are many available features not demonstrated. For more in-depth examples
1101
+ please see Capybaras built-in selector definitions.
959
1102
 
960
1103
  ```ruby
961
- Capybara.add_selector(:id) do
962
- xpath { |id| XPath.descendant[XPath.attr(:id) == id.to_s] }
1104
+ Capybara.add_selector(:my_attribute) do
1105
+ xpath { |id| XPath.descendant[XPath.attr(:my_attribute) == id.to_s] }
963
1106
  end
964
1107
 
965
1108
  Capybara.add_selector(:row) do
@@ -976,9 +1119,9 @@ an XPath expression generated through the XPath gem. You can now use these
976
1119
  selectors like this:
977
1120
 
978
1121
  ```ruby
979
- find(:id, 'post_123')
980
- find(:row, 3)
981
- find(:flash_type, :notice)
1122
+ find(:my_attribute, 'post_123') # find element with matching attribute
1123
+ find(:row, 3) # find 3rd row in table body
1124
+ find(:flash_type, :notice) # find element with id of 'flash' and class of 'notice'
982
1125
  ```
983
1126
 
984
1127
  ## <a name="beware-the-xpath--trap"></a>Beware the XPath // trap
@@ -1070,6 +1213,13 @@ additional info about how the underlying driver can be configured.
1070
1213
  are testing for specific server errors and using multiple sessions make sure to test for the
1071
1214
  errors using the initial session (usually :default)
1072
1215
 
1216
+ * If WebMock is enabled, you may encounter a "Too many open files"
1217
+ error. A simple `page.find` call may cause thousands of HTTP requests
1218
+ until the timeout occurs. By default, WebMock will cause each of these
1219
+ requests to spawn a new connection. To work around this problem, you
1220
+ may need to [enable WebMock's `net_http_connect_on_start: true`
1221
+ parameter](https://github.com/bblimke/webmock/blob/master/README.md#connecting-on-nethttpstart).
1222
+
1073
1223
  ## <a name="threadsafe"></a>"Threadsafe" mode
1074
1224
 
1075
1225
  In normal mode most of Capybara's configuration options are global settings which can cause issues
@@ -7,14 +7,13 @@ module Capybara
7
7
  class Config
8
8
  extend Forwardable
9
9
 
10
- OPTIONS = %i[app reuse_server threadsafe default_wait_time server
11
- default_driver javascript_driver allow_gumbo].freeze
10
+ OPTIONS = %i[
11
+ app reuse_server threadsafe server default_driver javascript_driver use_html5_parsing allow_gumbo
12
+ ].freeze
12
13
 
13
- attr_accessor :app
14
- attr_reader :reuse_server, :threadsafe
15
- attr_reader :session_options
14
+ attr_accessor :app, :use_html5_parsing
15
+ attr_reader :reuse_server, :threadsafe, :session_options # rubocop:disable Style/BisectedAttrAccessor
16
16
  attr_writer :default_driver, :javascript_driver
17
- attr_accessor :allow_gumbo
18
17
 
19
18
  SessionConfig::OPTIONS.each do |method|
20
19
  def_delegators :session_options, method, "#{method}="
@@ -25,10 +24,12 @@ module Capybara
25
24
  @javascript_driver = nil
26
25
  end
27
26
 
28
- attr_writer :reuse_server
27
+ attr_writer :reuse_server # rubocop:disable Style/BisectedAttrAccessor
29
28
 
30
29
  def threadsafe=(bool)
31
- 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
32
33
 
33
34
  @threadsafe = bool
34
35
  end
@@ -60,7 +61,7 @@ module Capybara
60
61
  @server = if name.respond_to? :call
61
62
  name
62
63
  elsif options
63
- proc { |app, port, host| Capybara.servers[name.to_sym].call(app, port, host, options) }
64
+ proc { |app, port, host| Capybara.servers[name.to_sym].call(app, port, host, **options) }
64
65
  else
65
66
  Capybara.servers[name.to_sym]
66
67
  end
@@ -82,10 +83,22 @@ module Capybara
82
83
  @javascript_driver || :selenium
83
84
  end
84
85
 
85
- def deprecate(method, alternate_method, once = false)
86
+ def deprecate(method, alternate_method, once: false)
86
87
  @deprecation_notified ||= {}
87
- warn "DEPRECATED: ##{method} is deprecated, please use ##{alternate_method} instead" unless once && @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
88
91
  @deprecation_notified[method] = true
89
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
90
103
  end
91
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
@@ -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