capybara 3.35.0 → 3.40.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (184) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +168 -5
  3. data/README.md +199 -39
  4. data/lib/capybara/config.rb +16 -4
  5. data/lib/capybara/driver/base.rb +4 -0
  6. data/lib/capybara/driver/node.rb +5 -1
  7. data/lib/capybara/dsl.rb +4 -10
  8. data/lib/capybara/helpers.rb +9 -14
  9. data/lib/capybara/minitest/spec.rb +18 -6
  10. data/lib/capybara/minitest.rb +14 -1
  11. data/lib/capybara/node/actions.rb +14 -9
  12. data/lib/capybara/node/base.rb +2 -1
  13. data/lib/capybara/node/document.rb +2 -2
  14. data/lib/capybara/node/element.rb +13 -2
  15. data/lib/capybara/node/finders.rb +11 -2
  16. data/lib/capybara/node/matchers.rb +25 -0
  17. data/lib/capybara/node/simple.rb +5 -1
  18. data/lib/capybara/node/whitespace_normalizer.rb +81 -0
  19. data/lib/capybara/queries/active_element_query.rb +18 -0
  20. data/lib/capybara/queries/ancestor_query.rb +2 -1
  21. data/lib/capybara/queries/base_query.rb +2 -2
  22. data/lib/capybara/queries/current_path_query.rb +1 -1
  23. data/lib/capybara/queries/selector_query.rb +40 -11
  24. data/lib/capybara/queries/sibling_query.rb +2 -1
  25. data/lib/capybara/queries/text_query.rb +1 -1
  26. data/lib/capybara/rack_test/browser.rb +64 -8
  27. data/lib/capybara/rack_test/driver.rb +4 -4
  28. data/lib/capybara/rack_test/form.rb +29 -7
  29. data/lib/capybara/rack_test/node.rb +32 -33
  30. data/lib/capybara/registration_container.rb +2 -5
  31. data/lib/capybara/registrations/drivers.rb +7 -7
  32. data/lib/capybara/registrations/servers.rb +37 -16
  33. data/lib/capybara/result.rb +2 -2
  34. data/lib/capybara/rspec/matcher_proxies.rb +6 -6
  35. data/lib/capybara/rspec/matchers/base.rb +8 -6
  36. data/lib/capybara/rspec/matchers/compound.rb +1 -1
  37. data/lib/capybara/rspec/matchers/have_selector.rb +9 -17
  38. data/lib/capybara/rspec/matchers.rb +21 -16
  39. data/lib/capybara/selector/builders/css_builder.rb +1 -1
  40. data/lib/capybara/selector/builders/xpath_builder.rb +1 -1
  41. data/lib/capybara/selector/css.rb +6 -6
  42. data/lib/capybara/selector/definition/button.rb +10 -5
  43. data/lib/capybara/selector/definition/checkbox.rb +1 -1
  44. data/lib/capybara/selector/definition/file_field.rb +1 -1
  45. data/lib/capybara/selector/definition/fillable_field.rb +1 -1
  46. data/lib/capybara/selector/definition/link.rb +2 -1
  47. data/lib/capybara/selector/definition/radio_button.rb +1 -1
  48. data/lib/capybara/selector/definition/table.rb +1 -1
  49. data/lib/capybara/selector/definition/table_row.rb +2 -2
  50. data/lib/capybara/selector/definition.rb +4 -2
  51. data/lib/capybara/selector/filter_set.rb +4 -7
  52. data/lib/capybara/selector/regexp_disassembler.rb +2 -5
  53. data/lib/capybara/selector/selector.rb +5 -1
  54. data/lib/capybara/selector.rb +252 -0
  55. data/lib/capybara/selenium/driver.rb +31 -54
  56. data/lib/capybara/selenium/driver_specializations/chrome_driver.rb +1 -1
  57. data/lib/capybara/selenium/driver_specializations/edge_driver.rb +9 -5
  58. data/lib/capybara/selenium/driver_specializations/firefox_driver.rb +2 -7
  59. data/lib/capybara/selenium/extensions/html5_drag.rb +5 -4
  60. data/lib/capybara/selenium/node.rb +60 -38
  61. data/lib/capybara/selenium/nodes/chrome_node.rb +4 -16
  62. data/lib/capybara/selenium/nodes/edge_node.rb +19 -13
  63. data/lib/capybara/selenium/nodes/firefox_node.rb +3 -3
  64. data/lib/capybara/selenium/nodes/safari_node.rb +4 -4
  65. data/lib/capybara/selenium/patches/atoms.rb +1 -1
  66. data/lib/capybara/selenium/patches/pause_duration_fix.rb +1 -1
  67. data/lib/capybara/server/animation_disabler.rb +40 -23
  68. data/lib/capybara/server/middleware.rb +1 -1
  69. data/lib/capybara/server.rb +1 -1
  70. data/lib/capybara/session/config.rb +4 -2
  71. data/lib/capybara/session.rb +34 -34
  72. data/lib/capybara/spec/public/test.js +4 -0
  73. data/lib/capybara/spec/session/active_element_spec.rb +31 -0
  74. data/lib/capybara/spec/session/all_spec.rb +11 -15
  75. data/lib/capybara/spec/session/assert_text_spec.rb +17 -17
  76. data/lib/capybara/spec/session/attach_file_spec.rb +6 -0
  77. data/lib/capybara/spec/session/check_spec.rb +10 -0
  78. data/lib/capybara/spec/session/choose_spec.rb +6 -0
  79. data/lib/capybara/spec/session/click_link_or_button_spec.rb +9 -0
  80. data/lib/capybara/spec/session/click_link_spec.rb +12 -1
  81. data/lib/capybara/spec/session/current_scope_spec.rb +1 -1
  82. data/lib/capybara/spec/session/fill_in_spec.rb +6 -0
  83. data/lib/capybara/spec/session/find_link_spec.rb +10 -0
  84. data/lib/capybara/spec/session/find_spec.rb +15 -1
  85. data/lib/capybara/spec/session/first_spec.rb +1 -1
  86. data/lib/capybara/spec/session/frame/within_frame_spec.rb +2 -0
  87. data/lib/capybara/spec/session/has_all_selectors_spec.rb +5 -5
  88. data/lib/capybara/spec/session/has_ancestor_spec.rb +2 -2
  89. data/lib/capybara/spec/session/has_any_selectors_spec.rb +6 -2
  90. data/lib/capybara/spec/session/has_button_spec.rb +30 -0
  91. data/lib/capybara/spec/session/has_current_path_spec.rb +3 -3
  92. data/lib/capybara/spec/session/has_element_spec.rb +47 -0
  93. data/lib/capybara/spec/session/has_field_spec.rb +25 -1
  94. data/lib/capybara/spec/session/has_link_spec.rb +40 -0
  95. data/lib/capybara/spec/session/has_none_selectors_spec.rb +7 -7
  96. data/lib/capybara/spec/session/has_select_spec.rb +10 -4
  97. data/lib/capybara/spec/session/has_selector_spec.rb +15 -0
  98. data/lib/capybara/spec/session/has_table_spec.rb +13 -2
  99. data/lib/capybara/spec/session/has_text_spec.rb +6 -14
  100. data/lib/capybara/spec/session/matches_style_spec.rb +2 -0
  101. data/lib/capybara/spec/session/node_spec.rb +88 -1
  102. data/lib/capybara/spec/session/node_wrapper_spec.rb +1 -1
  103. data/lib/capybara/spec/session/reset_session_spec.rb +13 -0
  104. data/lib/capybara/spec/session/scroll_spec.rb +7 -5
  105. data/lib/capybara/spec/session/uncheck_spec.rb +1 -1
  106. data/lib/capybara/spec/session/visit_spec.rb +20 -0
  107. data/lib/capybara/spec/session/window/window_spec.rb +1 -1
  108. data/lib/capybara/spec/session/window/windows_spec.rb +1 -1
  109. data/lib/capybara/spec/session/within_spec.rb +13 -0
  110. data/lib/capybara/spec/spec_helper.rb +12 -5
  111. data/lib/capybara/spec/test_app.rb +91 -14
  112. data/lib/capybara/spec/views/animated.erb +1 -1
  113. data/lib/capybara/spec/views/form.erb +34 -4
  114. data/lib/capybara/spec/views/frame_child.erb +1 -1
  115. data/lib/capybara/spec/views/frame_one.erb +1 -1
  116. data/lib/capybara/spec/views/frame_parent.erb +1 -1
  117. data/lib/capybara/spec/views/frame_two.erb +1 -1
  118. data/lib/capybara/spec/views/initial_alert.erb +2 -1
  119. data/lib/capybara/spec/views/layout.erb +10 -0
  120. data/lib/capybara/spec/views/obscured.erb +1 -1
  121. data/lib/capybara/spec/views/offset.erb +2 -1
  122. data/lib/capybara/spec/views/path.erb +2 -2
  123. data/lib/capybara/spec/views/popup_one.erb +1 -1
  124. data/lib/capybara/spec/views/popup_two.erb +1 -1
  125. data/lib/capybara/spec/views/react.erb +2 -2
  126. data/lib/capybara/spec/views/scroll.erb +2 -1
  127. data/lib/capybara/spec/views/spatial.erb +1 -1
  128. data/lib/capybara/spec/views/with_animation.erb +2 -3
  129. data/lib/capybara/spec/views/with_base_tag.erb +2 -2
  130. data/lib/capybara/spec/views/with_dragula.erb +2 -2
  131. data/lib/capybara/spec/views/with_fixed_header_footer.erb +2 -1
  132. data/lib/capybara/spec/views/with_hover.erb +2 -2
  133. data/lib/capybara/spec/views/with_html.erb +5 -3
  134. data/lib/capybara/spec/views/with_jquery_animation.erb +1 -1
  135. data/lib/capybara/spec/views/with_js.erb +2 -3
  136. data/lib/capybara/spec/views/with_jstree.erb +1 -1
  137. data/lib/capybara/spec/views/with_namespace.erb +1 -0
  138. data/lib/capybara/spec/views/with_scope.erb +2 -2
  139. data/lib/capybara/spec/views/with_shadow.erb +31 -0
  140. data/lib/capybara/spec/views/with_slow_unload.erb +2 -1
  141. data/lib/capybara/spec/views/with_sortable_js.erb +2 -2
  142. data/lib/capybara/spec/views/with_unload_alert.erb +1 -0
  143. data/lib/capybara/spec/views/with_windows.erb +1 -1
  144. data/lib/capybara/spec/views/within_frames.erb +1 -1
  145. data/lib/capybara/version.rb +1 -1
  146. data/lib/capybara/window.rb +1 -1
  147. data/lib/capybara.rb +30 -30
  148. data/spec/basic_node_spec.rb +16 -3
  149. data/spec/capybara_spec.rb +12 -0
  150. data/spec/counter_spec.rb +35 -0
  151. data/spec/css_builder_spec.rb +1 -1
  152. data/spec/css_splitter_spec.rb +1 -1
  153. data/spec/dsl_spec.rb +5 -3
  154. data/spec/fixtures/selenium_driver_rspec_failure.rb +2 -2
  155. data/spec/fixtures/selenium_driver_rspec_success.rb +2 -2
  156. data/spec/minitest_spec.rb +12 -1
  157. data/spec/minitest_spec_spec.rb +4 -0
  158. data/spec/per_session_config_spec.rb +1 -1
  159. data/spec/rack_test_spec.rb +30 -12
  160. data/spec/result_spec.rb +41 -35
  161. data/spec/rspec/features_spec.rb +3 -3
  162. data/spec/rspec/scenarios_spec.rb +2 -2
  163. data/spec/rspec/shared_spec_matchers.rb +27 -3
  164. data/spec/rspec_matchers_spec.rb +25 -0
  165. data/spec/rspec_spec.rb +3 -3
  166. data/spec/sauce_spec_chrome.rb +5 -5
  167. data/spec/selector_spec.rb +4 -4
  168. data/spec/selenium_spec_chrome.rb +20 -18
  169. data/spec/selenium_spec_chrome_remote.rb +15 -19
  170. data/spec/selenium_spec_edge.rb +19 -6
  171. data/spec/selenium_spec_firefox.rb +26 -8
  172. data/spec/selenium_spec_firefox_remote.rb +18 -4
  173. data/spec/selenium_spec_ie.rb +7 -8
  174. data/spec/selenium_spec_safari.rb +34 -20
  175. data/spec/server_spec.rb +19 -7
  176. data/spec/shared_selenium_node.rb +0 -4
  177. data/spec/shared_selenium_session.rb +22 -14
  178. data/spec/spec_helper.rb +36 -3
  179. data/spec/whitespace_normalizer_spec.rb +54 -0
  180. data/spec/xpath_builder_spec.rb +1 -1
  181. metadata +49 -30
  182. data/lib/capybara/selenium/logger_suppressor.rb +0 -34
  183. data/lib/capybara/selenium/patches/action_pauser.rb +0 -26
  184. data/lib/capybara/spec/views/with_title.erb +0 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 00bf1cfd1e72093422fb61df1dae86d72948e8026d57fb00084d5bedceb0967e
4
- data.tar.gz: 65a8c6b66d1ef91586ca39f7eabcf800019f853e33e087d1bb65f02a85140c8b
3
+ metadata.gz: e0537a83e6809595a8e15b9c450f4f4b0976c5ebf1327cc0611ae20a05b3574b
4
+ data.tar.gz: c3035e7a05874cc93ab27c6aea26e529dea4c3b63bd5d3281deaaf34c45a91b0
5
5
  SHA512:
6
- metadata.gz: f961de052aa75cb3e3a941ea031d40d6d0f1fc2a9a80190c7dbe2f7d8e96b462fa71d4ed96d4dc45687e2baaf151579ca4508a2753a6e2073814857e2dee9bb4
7
- data.tar.gz: 4b02c84f7bd1d9da419e3f43848da87290ba303541df516e6217fd3fc2e4cf5263e212e9a4a5329c8505b2f6111c0ce6ea17537ea3099b04f12c9b662d364088
6
+ metadata.gz: 48c7bc5cbfc8e3324ea09d937a207299ad91ffc2e255dbbb7ed13265e4541c3672271ccb2f19b3902588d5c649cb6f561b7c483e7b815b824ccf37df8bbb5075
7
+ data.tar.gz: 5b3a9cc9a6ba6ed67a54ef381c00ed9cc94027d26bdfc98ba1c509a097c9dc123d39bd72a6a5728e5b5b4e503202e475889d22cf47c07ce88eb7afedf604ed83
data/History.md CHANGED
@@ -1,5 +1,169 @@
1
+ #Version 3.40.0
2
+ Release date: 2024-01-26
3
+
4
+ ### Changned
5
+
6
+ * Dropped support for Ruby 2.7, 3.0+ is now required
7
+ * Dropped support for Selenium < 4.8
8
+ * Use the new headless option on chromedriver with registered selenium driver [Neil Carvalho]
9
+
10
+ ### Added
11
+
12
+ * `Capybara::Result#to_ary` to support multiple assignment [Sean Doyle]
13
+ * `has_element?` and related matchers [Sean Doyle]
14
+ * Rack 3 support
15
+
16
+ ### Fixed
17
+
18
+ * Forward save_screenshot options to selenium - Issue 2738
19
+ * Rack test - don't auto submit forms with multiple inputs [Mitchell Henke]
20
+ * Table row selector matches cell values in order - Issue 2686 [Jeff Parr]
21
+ * Table row selector fixes for first column - Issue 2685 [Jeff Par]
22
+
23
+ # Version 3.39.2
24
+ Release date: 2023-06-10
25
+
26
+ ### Fixed
27
+
28
+ * Fix Selenium version comparison [aki77]
29
+
30
+ # Version 3.39.1
31
+ Release date: 2023-05-12
32
+
33
+ ### Fixed
34
+
35
+ * Fix usage of Selenium logger
36
+
37
+ # Version 3.39.0
38
+ Release date: 2023-04-02
39
+
40
+ ### Added
41
+
42
+ * Support `:target` filter option on `:link` selector [Yudai Takada]
43
+ * Experimental Rack 3 support
44
+ * Text normalization performance improvements [Brandon Weaver]
45
+
46
+ ### Fixed
47
+
48
+ * MS Edge button click [Brian J. Bayer]
49
+ * Options/Capabilities choosing based on Selenium versions
50
+ * Support for base versions [Matijs van Zuijlen]
51
+ * ExpectedError not defined in Selenium 4+
52
+ * Filter block forwarding to a number of matchers [Christophe Bliard]
53
+ ### Changed
54
+
55
+ * Dropped support for rack 1.x
56
+
57
+ # Version 3.38.0
58
+ Release date: 2022-11-03
59
+
60
+ ### Changed
61
+
62
+ * Capybara.w3c_click_offset now defaults to true. If you need click offsets to be from the elements top left corner set it to false in your config
63
+
64
+ ### Added
65
+
66
+ * Support Selenium 4.3 changes to click offset calculations
67
+ * `click`, `double_click`, `right_click` can now be called on the session to click the currently scoped element (or document)
68
+ * `Session#within` now passes the scoped element to the block
69
+ * Support rack-test 2+
70
+ * Retry interval is now configurable [Masahiro NOMOTO]
71
+ * Support Puma 6 - Issue #2590
72
+ * Selenium: DetachedShadowRootError is treated as an invalid element error [Perryn Fowler]
73
+ * Selenium: When inspected shadow roots will have a tag name of "ShadowRoot"
74
+ * `evaluate_async_script` added to Session::DSL_METHODS [Henry Blyth]
75
+
76
+ ### Fixed
77
+
78
+ * Use higher precision clock in Capybara::Helpers::Timer if available
79
+ * rack-test driver behavior with \r\n - Issue #2547 [Stefan Hoffmann]
80
+ * Updated for deprecation of positional parameters in Selenium::WebDriver::ActionBuilder#pause
81
+ * Explicitly set cause on server raised errors
82
+ * Options no longer duplicated in have_xxx invalid option error message [Yudai Takada]
83
+ * Animation disabler is now threadsafe [Daniel Sheppard]
84
+ * Server connection count tracking [Oleksandr K.]
85
+ * Ensure scopes are reset when session is [Henry Blyth]
86
+
87
+ # Version 3.37.1
88
+ Release date: 2022-05-09
89
+
90
+ ### Fixed
91
+
92
+ * Regression in rack-test visit - Issue #2548
93
+
94
+ # Version 3.37.0
95
+ Release date: 2022-05-07
96
+
97
+ ### Changed
98
+
99
+ * Ruby 2.7.0+ is now required
100
+
101
+ ### Added
102
+
103
+ * [Beta] CSP nonces inserted into animation disabler additions - Issue #2542
104
+ * Support `<base>` element in rack-test driver - ISsue #2544
105
+ * [Beta] `Element#shadow_root` support. Requires selenium-webdriver 4.1+. Only currently supported with Chrome when using the selenium driver. Note: only CSS can be used to find elements from the shadow root. Therefore you won't be able to use most Capybara helper methods (`fill_in`, `click_link`, `find_field`, etc) directly from the shadow root since those locators are built using XPath. If you first locate a descendant from the shadow root using CSS then you should be able to use all the Capybara methods from there.
106
+ * Regexp now supported for `exact_text` finder option
107
+
108
+ ### Fixed
109
+
110
+ * Fragments in referer headers in rack-test driver - Issue #2525
111
+ * Selenium v4.1 deprecation notice
112
+
113
+ # Version 3.36.0
114
+ Release date: 2021-10-24
115
+
116
+ ### Changed
117
+
118
+ * Ruby 2.6.0+ is now required
119
+ * Minimum selenium-webdriver supported is now 3.142.7
120
+
121
+ ### Added
122
+
123
+ * Support for selenium-webdriver 4.x
124
+ * `allow_label_click` accepts click options to be used when clicking an associated label
125
+ * Deprecated `allow_gumbo=` in favor of `use_html5_parsing=` to enable use of Nokogiri::HTML5 when available
126
+ * `Session#active_element` returns the element with focus - Not supported by the `RackTest` driver [Sean Doyle]
127
+ * Support `focused:` filter for finding interactive elements - Not supported by the `RackTest` driver [Sean Doyle]
128
+
129
+ ### Fixed
130
+
131
+ * Sibling and ancestor queries now work with Simple::Node - Issue #2452
132
+ * rack_test correctly ignores readonly attribute on specific input element types
133
+ * `Node#all_text` always returns a string - Issue #2477
134
+ * `have_any_of_selectors` negated match - Issue #2473
135
+ * `Document#scroll_to` fixed for standards behavior - pass quirks: true if you need the older behavior [Eric Anderson]
136
+ * Use capture on attach file event listener for better React compatibility [Jeff Way]
137
+ * Animation disabler produces valid HTML [Javi Martin]
138
+
139
+ ### Removed
140
+
141
+ * References to non-w3c mode in drivers/tests. Non-w3c mode is obsolete and no one should be using it anymore. Capybara hasn't been testing/supporting it in a while
142
+
143
+ # Version 3.35.3
144
+ Release date: 2021-01-29
145
+
146
+ ### Fixed
147
+
148
+ * Just a release to have the correct dates in the History.md in released gem
149
+
150
+ # Version 3.35.2
151
+ Release date: 2021-01-29
152
+
153
+ ### Fixed
154
+
155
+ * Selenium deprecation suppressor with Selenium 3.x
156
+
157
+ # Version 3.35.1
158
+ Release date: 2021-01-26
159
+
160
+ ### Fixed
161
+
162
+ * Default chrome driver registrations use chrome - Issue #2442 [Yuriy Alekseyev]
163
+ * 'Capybara.test_id' usage with the :button selector - Issue #2443
164
+
1
165
  # Version 3.35.0
2
- Release date: 2020-01-25
166
+ Release date: 2021-01-25
3
167
 
4
168
  ### Added
5
169
 
@@ -732,7 +896,7 @@ Release date: 2018-03-23
732
896
 
733
897
  ### Changed
734
898
 
735
- * Visibile text whitespace is no longer fully normalized in favor of being more in line with the WebDriver spec for visible text
899
+ * Visible text whitespace is no longer fully normalized in favor of being more in line with the WebDriver spec for visible text
736
900
  * Drivers are expected to close extra windows when resetting the session
737
901
  * Selenium driver supports Date/Time when filling in date/time/datetime-local inputs
738
902
  * `current_url` returns the url for the top level browsing context
@@ -1138,7 +1302,7 @@ Release date: 2016-01-27
1138
1302
 
1139
1303
  # Version 2.6.0
1140
1304
 
1141
- Relase date: 2016-01-17
1305
+ Release date: 2016-01-17
1142
1306
 
1143
1307
  ### Fixed
1144
1308
 
@@ -1202,7 +1366,7 @@ Release date: 2014-10-13
1202
1366
 
1203
1367
  # Version 2.4.3
1204
1368
 
1205
- Relase date: 2014-09-21
1369
+ Release date: 2014-09-21
1206
1370
 
1207
1371
  ### Fixed
1208
1372
 
@@ -1877,4 +2041,3 @@ too many users, please read the release notes carefully!
1877
2041
  * clicking links where the image's alt attribute contains the text is now possible
1878
2042
  * within_fieldset and within_table work when the default selector is CSS
1879
2043
  * boolean attributes work the same across drivers (return true/false)
1880
-
data/README.md CHANGED
@@ -1,11 +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
5
  [![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
6
 
10
7
  Capybara helps you test web applications by simulating how a real user would
11
8
  interact with your app. It is agnostic about the driver running your tests and
@@ -18,8 +15,7 @@ If you and/or your company find value in Capybara and would like to contribute f
18
15
  <a href="https://www.patreon.com/capybara">Patreon</a>
19
16
 
20
17
 
21
- **Need help?** Ask on the mailing list (please do not open an issue on
22
- 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
23
19
 
24
20
  ## Table of contents
25
21
 
@@ -34,7 +30,6 @@ GitHub): http://groups.google.com/group/ruby-capybara
34
30
  - [Selecting the Driver](#selecting-the-driver)
35
31
  - [RackTest](#racktest)
36
32
  - [Selenium](#selenium)
37
- - [Apparition](#apparition)
38
33
  - [The DSL](#the-dsl)
39
34
  - [Navigating](#navigating)
40
35
  - [Clicking links and buttons](#clicking-links-and-buttons)
@@ -46,6 +41,10 @@ GitHub): http://groups.google.com/group/ruby-capybara
46
41
  - [Scripting](#scripting)
47
42
  - [Modals](#modals)
48
43
  - [Debugging](#debugging)
44
+ - [Selectors](#selectors)
45
+ - [Name](#selectors-name)
46
+ - [Locator](#selectors-locator)
47
+ - [Filters](#selectors-filters)
49
48
  - [Matching](#matching)
50
49
  - [Exactness](#exactness)
51
50
  - [Strategy](#strategy)
@@ -74,7 +73,7 @@ GitHub): http://groups.google.com/group/ruby-capybara
74
73
 
75
74
  ## <a name="setup"></a>Setup
76
75
 
77
- Capybara requires Ruby 2.5.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
78
77
  `Gemfile` and run `bundle install`:
79
78
 
80
79
  ```ruby
@@ -145,11 +144,13 @@ Load RSpec 3.5+ support by adding the following line (typically to your
145
144
  require 'capybara/rspec'
146
145
  ```
147
146
 
148
- If you are using Rails, put your Capybara specs in `spec/features` or `spec/system` (only works
149
- if [you have it configured in
150
- RSpec](https://relishapp.com/rspec/rspec-rails/v/4-0/docs/directory-structure))
151
- and if you have your Capybara specs in a different directory, then tag the
152
- 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.
153
154
 
154
155
  If you are not using Rails, tag all the example groups in which you want to use
155
156
  Capybara with `type: :feature`.
@@ -159,7 +160,7 @@ You can now write your specs like so:
159
160
  ```ruby
160
161
  describe "the signin process", type: :feature do
161
162
  before :each do
162
- User.make(email: 'user@example.com', password: 'password')
163
+ User.create(email: 'user@example.com', password: 'password')
163
164
  end
164
165
 
165
166
  it "signs me in" do
@@ -181,7 +182,7 @@ to one specific driver. For example:
181
182
  ```ruby
182
183
  describe 'some stuff which requires js', js: true do
183
184
  it 'will use the default js driver'
184
- it 'will switch to one specific driver', driver: :apparition
185
+ it 'will switch to one specific driver', driver: :selenium
185
186
  end
186
187
  ```
187
188
 
@@ -190,7 +191,7 @@ Capybara also comes with a built in DSL for creating descriptive acceptance test
190
191
  ```ruby
191
192
  feature "Signing in" do
192
193
  background do
193
- User.make(email: 'user@example.com', password: 'caplin')
194
+ User.create(email: 'user@example.com', password: 'caplin')
194
195
  end
195
196
 
196
197
  scenario "Signing in with correct credentials" do
@@ -203,7 +204,7 @@ feature "Signing in" do
203
204
  expect(page).to have_content 'Success'
204
205
  end
205
206
 
206
- given(:other_user) { User.make(email: 'other@example.com', password: 'rous') }
207
+ given(:other_user) { User.create(email: 'other@example.com', password: 'rous') }
207
208
 
208
209
  scenario "Signing in as another user" do
209
210
  visit '/sessions/new'
@@ -258,6 +259,8 @@ end
258
259
 
259
260
  ## <a name="using-capybara-with-minitest"></a>Using Capybara with Minitest
260
261
 
262
+ * If you are using Rails system tests please see their documentation for information on selecting the driver you wish to use.
263
+
261
264
  * If you are using Rails, but not using Rails system tests, add the following code in your `test_helper.rb`
262
265
  file to make Capybara available in all test cases deriving from
263
266
  `ActionDispatch::IntegrationTest`:
@@ -332,7 +335,7 @@ By default, Capybara uses the `:rack_test` driver, which is fast but limited: it
332
335
  does not support JavaScript, nor is it able to access HTTP resources outside of
333
336
  your Rack application, such as remote APIs and OAuth services. To get around
334
337
  these limitations, you can set up a different default driver for your features.
335
- 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:
336
339
 
337
340
  ```ruby
338
341
  Capybara.default_driver = :selenium # :selenium_chrome and :selenium_chrome_headless are also registered
@@ -349,7 +352,7 @@ You can also change the driver temporarily (typically in the Before/setup and
349
352
  After/teardown blocks):
350
353
 
351
354
  ```ruby
352
- Capybara.current_driver = :apparition # temporarily select different driver
355
+ Capybara.current_driver = :selenium # temporarily select different driver
353
356
  # tests here
354
357
  Capybara.use_default_driver # switch back to default driver
355
358
  ```
@@ -405,15 +408,6 @@ to the browsers. See the section on adding and configuring drivers.
405
408
  same transaction as your tests, causing data not to be shared between your test
406
409
  and test server, see [Transactions and database setup](#transactions-and-database-setup) below.
407
410
 
408
- ### <a name="apparition"></a>Apparition
409
-
410
- The [apparition driver](https://github.com/twalpole/apparition) is a new driver that allows you to run tests using Chrome in a headless
411
- or headed configuration. It attempts to provide backwards compatibility with the [Poltergeist driver API](https://github.com/teampoltergeist/poltergeist)
412
- and [capybara-webkit API](https://github.com/thoughtbot/capybara-webkit) while allowing for the use of modern JS/CSS. It
413
- uses CDP to communicate with Chrome, thereby obviating the need for chromedriver. This driver is being developed by the
414
- current developer of Capybara and will attempt to keep up to date with new Capybara releases. It will probably be moved into the
415
- teamcapybara repo once it reaches v1.0.
416
-
417
411
  ## <a name="the-dsl"></a>The DSL
418
412
 
419
413
  *A complete reference is available at
@@ -626,12 +620,12 @@ JS
626
620
 
627
621
  ### <a name="modals"></a>Modals
628
622
 
629
- 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.
630
624
 
631
- 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:
632
626
 
633
627
  ```ruby
634
- accept_alert do
628
+ accept_alert 'optional text or regex' do
635
629
  click_link('Show Alert')
636
630
  end
637
631
  ```
@@ -639,7 +633,13 @@ end
639
633
  You can accept or dismiss a confirmation by wrapping it in a block, as well:
640
634
 
641
635
  ```ruby
642
- 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
643
643
  click_link('Show Confirm')
644
644
  end
645
645
  ```
@@ -647,7 +647,13 @@ end
647
647
  You can accept or dismiss prompts as well, and also provide text to fill in for the response:
648
648
 
649
649
  ```ruby
650
- 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
651
657
  click_link('Show Prompt About Linux')
652
658
  end
653
659
  ```
@@ -697,6 +703,148 @@ Screenshots are saved to `Capybara.save_path`, relative to the app directory.
697
703
  If you have required `capybara/rails`, `Capybara.save_path` will default to
698
704
  `tmp/capybara`.
699
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
+
700
848
  ## <a name="matching"></a>Matching
701
849
 
702
850
  It is possible to customize how Capybara finds elements. At your disposal
@@ -777,7 +925,7 @@ expect(page).to have_content('baz')
777
925
  If clicking on the *foo* link triggers an asynchronous process, such as
778
926
  an Ajax request, which, when complete will add the *bar* link to the page,
779
927
  clicking on the *bar* link would be expected to fail, since that link doesn't
780
- 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
781
929
  brief period of time before giving up and throwing an error. The same is true of
782
930
  the next line, which looks for the content *baz* on the page; it will retry
783
931
  looking for that content for a brief time. You can adjust how long this period
@@ -791,13 +939,25 @@ Be aware that because of this behaviour, the following two statements are **not*
791
939
  equivalent, and you should **always** use the latter!
792
940
 
793
941
  ```ruby
794
- !page.has_xpath?('a')
795
- 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
796
948
  ```
797
949
 
798
- The former would immediately fail because the content has not yet been removed.
799
- Only the latter would wait for the asynchronous process to remove the content
800
- 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`
801
961
 
802
962
  Capybara's RSpec matchers, however, are smart enough to handle either form.
803
963
  The two following statements are functionally equivalent:
@@ -7,10 +7,12 @@ module Capybara
7
7
  class Config
8
8
  extend Forwardable
9
9
 
10
- OPTIONS = %i[app reuse_server threadsafe server 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
11
13
 
12
- attr_accessor :app, :allow_gumbo
13
- attr_reader :reuse_server, :threadsafe, :session_options
14
+ attr_accessor :app, :use_html5_parsing
15
+ attr_reader :reuse_server, :threadsafe, :session_options # rubocop:disable Style/BisectedAttrAccessor
14
16
  attr_writer :default_driver, :javascript_driver
15
17
 
16
18
  SessionConfig::OPTIONS.each do |method|
@@ -22,7 +24,7 @@ module Capybara
22
24
  @javascript_driver = nil
23
25
  end
24
26
 
25
- attr_writer :reuse_server
27
+ attr_writer :reuse_server # rubocop:disable Style/BisectedAttrAccessor
26
28
 
27
29
  def threadsafe=(bool)
28
30
  if (bool != threadsafe) && Session.instance_created?
@@ -88,5 +90,15 @@ module Capybara
88
90
  end
89
91
  @deprecation_notified[method] = true
90
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
91
103
  end
92
104
  end
@@ -63,6 +63,10 @@ class Capybara::Driver::Base
63
63
  raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#send_keys'
64
64
  end
65
65
 
66
+ def active_element
67
+ raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#active_element'
68
+ end
69
+
66
70
  ##
67
71
  #
68
72
  # @param frame [Capybara::Node::Element, :parent, :top] The iframe element to switch to
@@ -125,6 +125,10 @@ module Capybara
125
125
  raise NotSupportedByDriverError, 'Capybara::Driver::Node#trigger'
126
126
  end
127
127
 
128
+ def shadow_root
129
+ raise NotSupportedByDriverError, 'Capybara::Driver::Node#shadow_root'
130
+ end
131
+
128
132
  def inspect
129
133
  %(#<#{self.class} tag="#{tag_name}" path="#{path}">)
130
134
  rescue NotSupportedByDriverError
@@ -132,7 +136,7 @@ module Capybara
132
136
  end
133
137
 
134
138
  def ==(other)
135
- raise NotSupportedByDriverError, 'Capybara::Driver::Node#=='
139
+ eql?(other) || (other.respond_to?(:native) && native == other.native)
136
140
  end
137
141
  end
138
142
  end