capybara 2.18.0 → 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 (316) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +1 -1
  3. data/History.md +945 -12
  4. data/License.txt +1 -1
  5. data/README.md +264 -90
  6. data/lib/capybara/config.rb +29 -57
  7. data/lib/capybara/cucumber.rb +2 -3
  8. data/lib/capybara/driver/base.rb +35 -18
  9. data/lib/capybara/driver/node.rb +40 -10
  10. data/lib/capybara/dsl.rb +10 -7
  11. data/lib/capybara/helpers.rb +70 -31
  12. data/lib/capybara/minitest/spec.rb +185 -83
  13. data/lib/capybara/minitest.rb +232 -112
  14. data/lib/capybara/node/actions.rb +274 -171
  15. data/lib/capybara/node/base.rb +42 -34
  16. data/lib/capybara/node/document.rb +15 -3
  17. data/lib/capybara/node/document_matchers.rb +19 -21
  18. data/lib/capybara/node/element.rb +362 -135
  19. data/lib/capybara/node/finders.rb +151 -137
  20. data/lib/capybara/node/matchers.rb +394 -209
  21. data/lib/capybara/node/simple.rb +59 -26
  22. data/lib/capybara/node/whitespace_normalizer.rb +81 -0
  23. data/lib/capybara/queries/active_element_query.rb +18 -0
  24. data/lib/capybara/queries/ancestor_query.rb +12 -9
  25. data/lib/capybara/queries/base_query.rb +39 -28
  26. data/lib/capybara/queries/current_path_query.rb +21 -27
  27. data/lib/capybara/queries/match_query.rb +14 -7
  28. data/lib/capybara/queries/selector_query.rb +659 -149
  29. data/lib/capybara/queries/sibling_query.rb +11 -9
  30. data/lib/capybara/queries/style_query.rb +45 -0
  31. data/lib/capybara/queries/text_query.rb +56 -38
  32. data/lib/capybara/queries/title_query.rb +8 -11
  33. data/lib/capybara/rack_test/browser.rb +114 -42
  34. data/lib/capybara/rack_test/css_handlers.rb +6 -4
  35. data/lib/capybara/rack_test/driver.rb +22 -17
  36. data/lib/capybara/rack_test/errors.rb +6 -0
  37. data/lib/capybara/rack_test/form.rb +93 -58
  38. data/lib/capybara/rack_test/node.rb +184 -81
  39. data/lib/capybara/rails.rb +3 -7
  40. data/lib/capybara/registration_container.rb +41 -0
  41. data/lib/capybara/registrations/drivers.rb +42 -0
  42. data/lib/capybara/registrations/patches/puma_ssl.rb +29 -0
  43. data/lib/capybara/registrations/servers.rb +66 -0
  44. data/lib/capybara/result.rb +97 -63
  45. data/lib/capybara/rspec/features.rb +17 -50
  46. data/lib/capybara/rspec/matcher_proxies.rb +52 -15
  47. data/lib/capybara/rspec/matchers/base.rb +113 -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 +69 -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 +43 -0
  59. data/lib/capybara/rspec/matchers/spatial_sugar.rb +39 -0
  60. data/lib/capybara/rspec/matchers.rb +146 -310
  61. data/lib/capybara/rspec.rb +7 -11
  62. data/lib/capybara/selector/builders/css_builder.rb +84 -0
  63. data/lib/capybara/selector/builders/xpath_builder.rb +71 -0
  64. data/lib/capybara/selector/css.rb +85 -13
  65. data/lib/capybara/selector/definition/button.rb +68 -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 +28 -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 +55 -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/definition.rb +280 -0
  87. data/lib/capybara/selector/filter.rb +2 -17
  88. data/lib/capybara/selector/filter_set.rb +80 -33
  89. data/lib/capybara/selector/filters/base.rb +50 -6
  90. data/lib/capybara/selector/filters/expression_filter.rb +8 -26
  91. data/lib/capybara/selector/filters/locator_filter.rb +29 -0
  92. data/lib/capybara/selector/filters/node_filter.rb +16 -12
  93. data/lib/capybara/selector/regexp_disassembler.rb +211 -0
  94. data/lib/capybara/selector/selector.rb +93 -210
  95. data/lib/capybara/selector/xpath_extensions.rb +17 -0
  96. data/lib/capybara/selector.rb +475 -523
  97. data/lib/capybara/selenium/atoms/getAttribute.min.js +1 -0
  98. data/lib/capybara/selenium/atoms/isDisplayed.min.js +1 -0
  99. data/lib/capybara/selenium/atoms/src/getAttribute.js +161 -0
  100. data/lib/capybara/selenium/atoms/src/isDisplayed.js +454 -0
  101. data/lib/capybara/selenium/driver.rb +298 -267
  102. data/lib/capybara/selenium/driver_specializations/chrome_driver.rb +117 -0
  103. data/lib/capybara/selenium/driver_specializations/edge_driver.rb +128 -0
  104. data/lib/capybara/selenium/driver_specializations/firefox_driver.rb +84 -0
  105. data/lib/capybara/selenium/driver_specializations/internet_explorer_driver.rb +26 -0
  106. data/lib/capybara/selenium/driver_specializations/safari_driver.rb +24 -0
  107. data/lib/capybara/selenium/extensions/file_input_click_emulation.rb +34 -0
  108. data/lib/capybara/selenium/extensions/find.rb +110 -0
  109. data/lib/capybara/selenium/extensions/html5_drag.rb +229 -0
  110. data/lib/capybara/selenium/extensions/modifier_keys_stack.rb +28 -0
  111. data/lib/capybara/selenium/extensions/scroll.rb +76 -0
  112. data/lib/capybara/selenium/node.rb +517 -145
  113. data/lib/capybara/selenium/nodes/chrome_node.rb +125 -0
  114. data/lib/capybara/selenium/nodes/edge_node.rb +110 -0
  115. data/lib/capybara/selenium/nodes/firefox_node.rb +136 -0
  116. data/lib/capybara/selenium/nodes/ie_node.rb +22 -0
  117. data/lib/capybara/selenium/nodes/safari_node.rb +118 -0
  118. data/lib/capybara/selenium/patches/atoms.rb +18 -0
  119. data/lib/capybara/selenium/patches/is_displayed.rb +16 -0
  120. data/lib/capybara/selenium/patches/logs.rb +45 -0
  121. data/lib/capybara/selenium/patches/pause_duration_fix.rb +9 -0
  122. data/lib/capybara/selenium/patches/persistent_client.rb +20 -0
  123. data/lib/capybara/server/animation_disabler.rb +80 -0
  124. data/lib/capybara/server/checker.rb +44 -0
  125. data/lib/capybara/server/middleware.rb +71 -0
  126. data/lib/capybara/server.rb +59 -67
  127. data/lib/capybara/session/config.rb +81 -67
  128. data/lib/capybara/session/matchers.rb +28 -20
  129. data/lib/capybara/session.rb +337 -365
  130. data/lib/capybara/spec/public/jquery.js +5 -5
  131. data/lib/capybara/spec/public/offset.js +6 -0
  132. data/lib/capybara/spec/public/test.js +151 -12
  133. data/lib/capybara/spec/session/accept_alert_spec.rb +12 -11
  134. data/lib/capybara/spec/session/accept_confirm_spec.rb +6 -5
  135. data/lib/capybara/spec/session/accept_prompt_spec.rb +10 -10
  136. data/lib/capybara/spec/session/active_element_spec.rb +31 -0
  137. data/lib/capybara/spec/session/all_spec.rb +161 -57
  138. data/lib/capybara/spec/session/ancestor_spec.rb +27 -24
  139. data/lib/capybara/spec/session/assert_all_of_selectors_spec.rb +68 -38
  140. data/lib/capybara/spec/session/assert_current_path_spec.rb +75 -0
  141. data/lib/capybara/spec/session/assert_selector_spec.rb +143 -0
  142. data/lib/capybara/spec/session/assert_style_spec.rb +26 -0
  143. data/lib/capybara/spec/session/assert_text_spec.rb +258 -0
  144. data/lib/capybara/spec/session/{assert_title.rb → assert_title_spec.rb} +22 -12
  145. data/lib/capybara/spec/session/attach_file_spec.rb +144 -69
  146. data/lib/capybara/spec/session/body_spec.rb +12 -13
  147. data/lib/capybara/spec/session/check_spec.rb +117 -55
  148. data/lib/capybara/spec/session/choose_spec.rb +64 -31
  149. data/lib/capybara/spec/session/click_button_spec.rb +231 -173
  150. data/lib/capybara/spec/session/click_link_or_button_spec.rb +55 -35
  151. data/lib/capybara/spec/session/click_link_spec.rb +93 -58
  152. data/lib/capybara/spec/session/current_scope_spec.rb +12 -11
  153. data/lib/capybara/spec/session/current_url_spec.rb +57 -39
  154. data/lib/capybara/spec/session/dismiss_confirm_spec.rb +4 -4
  155. data/lib/capybara/spec/session/dismiss_prompt_spec.rb +3 -2
  156. data/lib/capybara/spec/session/element/{assert_match_selector.rb → assert_match_selector_spec.rb} +11 -9
  157. data/lib/capybara/spec/session/element/match_css_spec.rb +18 -10
  158. data/lib/capybara/spec/session/element/match_xpath_spec.rb +9 -7
  159. data/lib/capybara/spec/session/element/matches_selector_spec.rb +71 -57
  160. data/lib/capybara/spec/session/evaluate_async_script_spec.rb +8 -7
  161. data/lib/capybara/spec/session/evaluate_script_spec.rb +29 -8
  162. data/lib/capybara/spec/session/execute_script_spec.rb +10 -8
  163. data/lib/capybara/spec/session/fill_in_spec.rb +134 -43
  164. data/lib/capybara/spec/session/find_button_spec.rb +25 -24
  165. data/lib/capybara/spec/session/find_by_id_spec.rb +10 -9
  166. data/lib/capybara/spec/session/find_field_spec.rb +37 -41
  167. data/lib/capybara/spec/session/find_link_spec.rb +46 -17
  168. data/lib/capybara/spec/session/find_spec.rb +260 -145
  169. data/lib/capybara/spec/session/first_spec.rb +80 -52
  170. data/lib/capybara/spec/session/frame/frame_title_spec.rb +23 -0
  171. data/lib/capybara/spec/session/frame/frame_url_spec.rb +23 -0
  172. data/lib/capybara/spec/session/frame/switch_to_frame_spec.rb +33 -20
  173. data/lib/capybara/spec/session/frame/within_frame_spec.rb +52 -32
  174. data/lib/capybara/spec/session/go_back_spec.rb +2 -1
  175. data/lib/capybara/spec/session/go_forward_spec.rb +2 -1
  176. data/lib/capybara/spec/session/has_all_selectors_spec.rb +31 -31
  177. data/lib/capybara/spec/session/has_ancestor_spec.rb +46 -0
  178. data/lib/capybara/spec/session/has_any_selectors_spec.rb +29 -0
  179. data/lib/capybara/spec/session/has_button_spec.rb +100 -13
  180. data/lib/capybara/spec/session/has_css_spec.rb +272 -137
  181. data/lib/capybara/spec/session/has_current_path_spec.rb +60 -61
  182. data/lib/capybara/spec/session/has_element_spec.rb +47 -0
  183. data/lib/capybara/spec/session/has_field_spec.rb +139 -59
  184. data/lib/capybara/spec/session/has_link_spec.rb +47 -6
  185. data/lib/capybara/spec/session/has_none_selectors_spec.rb +42 -40
  186. data/lib/capybara/spec/session/has_select_spec.rb +107 -72
  187. data/lib/capybara/spec/session/has_selector_spec.rb +120 -71
  188. data/lib/capybara/spec/session/has_sibling_spec.rb +50 -0
  189. data/lib/capybara/spec/session/has_table_spec.rb +183 -5
  190. data/lib/capybara/spec/session/has_text_spec.rb +106 -62
  191. data/lib/capybara/spec/session/has_title_spec.rb +20 -14
  192. data/lib/capybara/spec/session/has_xpath_spec.rb +57 -38
  193. data/lib/capybara/spec/session/{headers.rb → headers_spec.rb} +3 -2
  194. data/lib/capybara/spec/session/html_spec.rb +14 -6
  195. data/lib/capybara/spec/session/matches_style_spec.rb +37 -0
  196. data/lib/capybara/spec/session/node_spec.rb +1024 -153
  197. data/lib/capybara/spec/session/node_wrapper_spec.rb +39 -0
  198. data/lib/capybara/spec/session/refresh_spec.rb +12 -6
  199. data/lib/capybara/spec/session/reset_session_spec.rb +82 -35
  200. data/lib/capybara/spec/session/{response_code.rb → response_code_spec.rb} +2 -1
  201. data/lib/capybara/spec/session/save_and_open_page_spec.rb +3 -2
  202. data/lib/capybara/spec/session/save_and_open_screenshot_spec.rb +8 -12
  203. data/lib/capybara/spec/session/save_page_spec.rb +42 -55
  204. data/lib/capybara/spec/session/save_screenshot_spec.rb +16 -14
  205. data/lib/capybara/spec/session/screenshot_spec.rb +2 -2
  206. data/lib/capybara/spec/session/scroll_spec.rb +119 -0
  207. data/lib/capybara/spec/session/select_spec.rb +107 -81
  208. data/lib/capybara/spec/session/selectors_spec.rb +52 -19
  209. data/lib/capybara/spec/session/sibling_spec.rb +10 -10
  210. data/lib/capybara/spec/session/text_spec.rb +37 -21
  211. data/lib/capybara/spec/session/title_spec.rb +17 -5
  212. data/lib/capybara/spec/session/uncheck_spec.rb +43 -23
  213. data/lib/capybara/spec/session/unselect_spec.rb +39 -38
  214. data/lib/capybara/spec/session/visit_spec.rb +85 -53
  215. data/lib/capybara/spec/session/window/become_closed_spec.rb +24 -20
  216. data/lib/capybara/spec/session/window/current_window_spec.rb +5 -3
  217. data/lib/capybara/spec/session/window/open_new_window_spec.rb +5 -3
  218. data/lib/capybara/spec/session/window/switch_to_window_spec.rb +27 -22
  219. data/lib/capybara/spec/session/window/window_opened_by_spec.rb +12 -6
  220. data/lib/capybara/spec/session/window/window_spec.rb +97 -63
  221. data/lib/capybara/spec/session/window/windows_spec.rb +12 -10
  222. data/lib/capybara/spec/session/window/within_window_spec.rb +31 -86
  223. data/lib/capybara/spec/session/within_spec.rb +83 -44
  224. data/lib/capybara/spec/spec_helper.rb +54 -44
  225. data/lib/capybara/spec/test_app.rb +158 -43
  226. data/lib/capybara/spec/views/animated.erb +49 -0
  227. data/lib/capybara/spec/views/form.erb +163 -42
  228. data/lib/capybara/spec/views/frame_child.erb +4 -3
  229. data/lib/capybara/spec/views/frame_one.erb +2 -1
  230. data/lib/capybara/spec/views/frame_parent.erb +1 -1
  231. data/lib/capybara/spec/views/frame_two.erb +1 -1
  232. data/lib/capybara/spec/views/initial_alert.erb +2 -1
  233. data/lib/capybara/spec/views/layout.erb +10 -0
  234. data/lib/capybara/spec/views/obscured.erb +47 -0
  235. data/lib/capybara/spec/views/offset.erb +33 -0
  236. data/lib/capybara/spec/views/path.erb +2 -2
  237. data/lib/capybara/spec/views/popup_one.erb +1 -1
  238. data/lib/capybara/spec/views/popup_two.erb +1 -1
  239. data/lib/capybara/spec/views/react.erb +45 -0
  240. data/lib/capybara/spec/views/scroll.erb +21 -0
  241. data/lib/capybara/spec/views/spatial.erb +31 -0
  242. data/lib/capybara/spec/views/tables.erb +68 -1
  243. data/lib/capybara/spec/views/with_animation.erb +81 -0
  244. data/lib/capybara/spec/views/with_base_tag.erb +2 -2
  245. data/lib/capybara/spec/views/with_dragula.erb +24 -0
  246. data/lib/capybara/spec/views/with_fixed_header_footer.erb +2 -1
  247. data/lib/capybara/spec/views/with_hover.erb +3 -2
  248. data/lib/capybara/spec/views/with_hover1.erb +10 -0
  249. data/lib/capybara/spec/views/with_html.erb +69 -12
  250. data/lib/capybara/spec/views/with_html5_svg.erb +20 -0
  251. data/lib/capybara/spec/views/with_jquery_animation.erb +24 -0
  252. data/lib/capybara/spec/views/with_js.erb +30 -5
  253. data/lib/capybara/spec/views/with_jstree.erb +26 -0
  254. data/lib/capybara/spec/views/with_namespace.erb +21 -0
  255. data/lib/capybara/spec/views/with_scope.erb +2 -2
  256. data/lib/capybara/spec/views/with_scope_other.erb +6 -0
  257. data/lib/capybara/spec/views/with_shadow.erb +31 -0
  258. data/lib/capybara/spec/views/with_slow_unload.erb +2 -1
  259. data/lib/capybara/spec/views/with_sortable_js.erb +21 -0
  260. data/lib/capybara/spec/views/with_unload_alert.erb +1 -0
  261. data/lib/capybara/spec/views/with_windows.erb +1 -1
  262. data/lib/capybara/spec/views/within_frames.erb +5 -2
  263. data/lib/capybara/version.rb +2 -1
  264. data/lib/capybara/window.rb +36 -34
  265. data/lib/capybara.rb +134 -107
  266. data/spec/basic_node_spec.rb +60 -34
  267. data/spec/capybara_spec.rb +63 -88
  268. data/spec/counter_spec.rb +35 -0
  269. data/spec/css_builder_spec.rb +101 -0
  270. data/spec/css_splitter_spec.rb +38 -0
  271. data/spec/dsl_spec.rb +85 -64
  272. data/spec/filter_set_spec.rb +27 -9
  273. data/spec/fixtures/certificate.pem +25 -0
  274. data/spec/fixtures/key.pem +27 -0
  275. data/spec/fixtures/selenium_driver_rspec_failure.rb +6 -5
  276. data/spec/fixtures/selenium_driver_rspec_success.rb +6 -5
  277. data/spec/minitest_spec.rb +52 -7
  278. data/spec/minitest_spec_spec.rb +94 -63
  279. data/spec/per_session_config_spec.rb +14 -13
  280. data/spec/rack_test_spec.rb +194 -125
  281. data/spec/regexp_dissassembler_spec.rb +250 -0
  282. data/spec/result_spec.rb +111 -50
  283. data/spec/rspec/features_spec.rb +37 -31
  284. data/spec/rspec/scenarios_spec.rb +10 -8
  285. data/spec/rspec/shared_spec_matchers.rb +473 -422
  286. data/spec/rspec/views_spec.rb +5 -3
  287. data/spec/rspec_matchers_spec.rb +52 -11
  288. data/spec/rspec_spec.rb +109 -89
  289. data/spec/sauce_spec_chrome.rb +43 -0
  290. data/spec/selector_spec.rb +397 -68
  291. data/spec/selenium_spec_chrome.rb +187 -40
  292. data/spec/selenium_spec_chrome_remote.rb +96 -0
  293. data/spec/selenium_spec_edge.rb +60 -0
  294. data/spec/selenium_spec_firefox.rb +201 -41
  295. data/spec/selenium_spec_firefox_remote.rb +94 -0
  296. data/spec/selenium_spec_ie.rb +149 -0
  297. data/spec/selenium_spec_safari.rb +162 -0
  298. data/spec/server_spec.rb +213 -102
  299. data/spec/session_spec.rb +53 -16
  300. data/spec/shared_selenium_node.rb +79 -0
  301. data/spec/shared_selenium_session.rb +473 -122
  302. data/spec/spec_helper.rb +126 -7
  303. data/spec/whitespace_normalizer_spec.rb +54 -0
  304. data/spec/xpath_builder_spec.rb +93 -0
  305. metadata +355 -73
  306. data/.yard/templates_custom/default/class/html/selectors.erb +0 -38
  307. data/.yard/templates_custom/default/class/html/setup.rb +0 -17
  308. data/.yard/yard_extensions.rb +0 -78
  309. data/lib/capybara/query.rb +0 -7
  310. data/lib/capybara/rspec/compound.rb +0 -95
  311. data/lib/capybara/spec/session/assert_current_path.rb +0 -72
  312. data/lib/capybara/spec/session/assert_selector.rb +0 -148
  313. data/lib/capybara/spec/session/assert_text.rb +0 -234
  314. data/lib/capybara/spec/session/source_spec.rb +0 -0
  315. data/lib/capybara/spec/views/with_title.erb +0 -5
  316. data/spec/selenium_spec_marionette.rb +0 -127
@@ -1,62 +1,209 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require 'spec_helper'
3
4
  require 'selenium-webdriver'
4
5
  require 'shared_selenium_session'
6
+ require 'shared_selenium_node'
7
+ require 'rspec/shared_spec_matchers'
8
+
9
+ CHROME_DRIVER = :selenium_chrome
10
+
11
+ Selenium::WebDriver::Chrome.path = '/usr/bin/google-chrome-beta' if ENV.fetch('CI', nil) && ENV.fetch('CHROME_BETA', nil)
12
+
13
+ Selenium::WebDriver.logger.ignore(:selenium_manager)
14
+
15
+ browser_options = if ENV['HEADLESS']
16
+ Selenium::WebDriver::Options.chrome(args: ['--headless=new'])
17
+ else
18
+ Selenium::WebDriver::Options.chrome
19
+ end
20
+
21
+ # Chromedriver 77 requires setting this for headless mode on linux
22
+ # Different versions of Chrome/selenium-webdriver require setting differently - jus set them all
23
+ browser_options.add_preference('download.default_directory', Capybara.save_path)
24
+ browser_options.add_preference(:download, default_directory: Capybara.save_path)
25
+
26
+ Capybara.register_driver :selenium_chrome do |app|
27
+ version = Capybara::Selenium::Driver.load_selenium
28
+ options_key = Capybara::Selenium::Driver::CAPS_VERSION.satisfied_by?(version) ? :capabilities : :options
29
+ driver_options = { browser: :chrome, timeout: 30 }.tap do |opts|
30
+ opts[options_key] = browser_options
31
+ end
32
+
33
+ Capybara::Selenium::Driver.new(app, **driver_options).tap do |driver|
34
+ # Set download dir for Chrome < 77
35
+ driver.browser.download_path = Capybara.save_path
36
+ end
37
+ end
38
+
39
+ Capybara.register_driver :selenium_chrome_not_clear_storage do |app|
40
+ version = Capybara::Selenium::Driver.load_selenium
41
+ options_key = Capybara::Selenium::Driver::CAPS_VERSION.satisfied_by?(version) ? :capabilities : :options
42
+ chrome_options = { browser: :chrome, clear_local_storage: false, clear_session_storage: false }.tap do |opts|
43
+ opts[options_key] = browser_options
44
+ end
5
45
 
6
- CHROME_DRIVER = if ENV['HEADLESS'] then :selenium_chrome_headless else :selenium_chrome end
46
+ Capybara::Selenium::Driver.new(app, **chrome_options)
47
+ end
48
+
49
+ Capybara.register_driver :selenium_chrome_not_clear_session_storage do |app|
50
+ version = Capybara::Selenium::Driver.load_selenium
51
+ options_key = Capybara::Selenium::Driver::CAPS_VERSION.satisfied_by?(version) ? :capabilities : :options
52
+ chrome_options = { browser: :chrome, clear_session_storage: false }.tap do |opts|
53
+ opts[options_key] = browser_options
54
+ end
55
+
56
+ Capybara::Selenium::Driver.new(app, **chrome_options)
57
+ end
58
+
59
+ Capybara.register_driver :selenium_chrome_not_clear_local_storage do |app|
60
+ version = Capybara::Selenium::Driver.load_selenium
61
+ options_key = Capybara::Selenium::Driver::CAPS_VERSION.satisfied_by?(version) ? :capabilities : :options
62
+ chrome_options = { browser: :chrome, clear_local_storage: false }.tap do |opts|
63
+ opts[options_key] = browser_options
64
+ end
65
+ Capybara::Selenium::Driver.new(app, **chrome_options)
66
+ end
7
67
 
8
- # if ENV['HEADLESS'] && ENV['TRAVIS']
9
- # Selenium::WebDriver::Chrome.path='/usr/bin/google-chrome-beta'
10
- # end
68
+ Capybara.register_driver :selenium_driver_subclass_with_chrome do |app|
69
+ version = Capybara::Selenium::Driver.load_selenium
70
+ options_key = Capybara::Selenium::Driver::CAPS_VERSION.satisfied_by?(version) ? :capabilities : :options
71
+ subclass = Class.new(Capybara::Selenium::Driver)
72
+ chrome_options = { browser: :chrome, timeout: 30 }.tap do |opts|
73
+ opts[options_key] = browser_options
74
+ end
11
75
 
12
- Capybara.register_driver :selenium_chrome_clear_storage do |app|
13
- chrome_options = {
14
- browser: :chrome,
15
- options: ::Selenium::WebDriver::Chrome::Options.new()
16
- }
17
- chrome_options[:options].args << 'headless' if ENV['HEADLESS']
18
- Capybara::Selenium::Driver.new(app, chrome_options.merge(clear_local_storage: true, clear_session_storage: true))
76
+ subclass.new(app, **chrome_options)
19
77
  end
20
78
 
21
79
  module TestSessions
22
80
  Chrome = Capybara::Session.new(CHROME_DRIVER, TestApp)
23
81
  end
24
82
 
25
- skipped_tests = [:response_headers, :status_code, :trigger]
26
- # skip window tests when headless for now - closing a window not supported by chromedriver/chrome
27
- skipped_tests << :windows if ENV['TRAVIS'] && (ENV['SKIP_WINDOW'] || ENV['HEADLESS'])
83
+ skipped_tests = %i[response_headers status_code trigger]
28
84
 
29
- Capybara::SpecHelper.run_specs TestSessions::Chrome, CHROME_DRIVER.to_s, capybara_skip: skipped_tests
85
+ Capybara::SpecHelper.log_selenium_driver_version(Selenium::WebDriver::Chrome) if ENV['CI']
30
86
 
31
- RSpec.describe "Capybara::Session with chrome" do
87
+ Capybara::SpecHelper.run_specs TestSessions::Chrome, CHROME_DRIVER.to_s, capybara_skip: skipped_tests do |example|
88
+ case example.metadata[:full_description]
89
+ when /#click_link can download a file$/
90
+ skip 'Need to figure out testing of file downloading on windows platform' if Gem.win_platform?
91
+ when /Capybara::Session selenium_chrome node #shadow_root should get visible text/
92
+ pending "Selenium doesn't currently support getting visible text for shadow root elements"
93
+ when /Capybara::Session selenium_chrome node #shadow_root/
94
+ skip 'Not supported with this chromedriver version' if chromedriver_lt?('96.0', @session)
95
+ end
96
+ end
97
+
98
+ RSpec.describe 'Capybara::Session with chrome' do
32
99
  include Capybara::SpecHelper
33
- include_examples "Capybara::Session", TestSessions::Chrome, CHROME_DRIVER
34
-
35
- context "storage" do
36
- describe "#reset!" do
37
- it "does not clear either storage by default" do
38
- @session = TestSessions::Chrome
39
- @session.visit('/with_js')
40
- @session.find(:css, '#set-storage').click
41
- @session.reset!
42
- @session.visit('/with_js')
43
- # expect(@session.driver.browser.local_storage.keys).not_to be_empty
44
- # expect(@session.driver.browser.session_storage.keys).not_to be_empty
45
- expect(@session.evaluate_script('Object.keys(localStorage)')).not_to be_empty
46
- expect(@session.evaluate_script('Object.keys(sessionStorage)')).not_to be_empty
100
+ ['Capybara::Session', 'Capybara::Node', Capybara::RSpecMatchers].each do |examples|
101
+ include_examples examples, TestSessions::Chrome, CHROME_DRIVER
102
+ end
103
+
104
+ context 'storage' do
105
+ describe '#reset!' do
106
+ it 'clears storage by default' do
107
+ session = TestSessions::Chrome
108
+ session.visit('/with_js')
109
+ session.find(:css, '#set-storage').click
110
+ session.reset!
111
+ session.visit('/with_js')
112
+ expect(session.evaluate_script('Object.keys(localStorage)')).to be_empty
113
+ expect(session.evaluate_script('Object.keys(sessionStorage)')).to be_empty
47
114
  end
48
115
 
49
- it "clears storage when set" do
50
- @session = Capybara::Session.new(:selenium_chrome_clear_storage, TestApp)
51
- @session.visit('/with_js')
52
- @session.find(:css, '#set-storage').click
53
- @session.reset!
54
- @session.visit('/with_js')
55
- # expect(@session.driver.browser.local_storage.keys).to be_empty
56
- # expect(@session.driver.browser.session_storage.keys).to be_empty
57
- expect(@session.evaluate_script('Object.keys(localStorage)')).to be_empty
58
- expect(@session.evaluate_script('Object.keys(sessionStorage)')).to be_empty
116
+ it 'does not clear storage when false' do
117
+ session = Capybara::Session.new(:selenium_chrome_not_clear_storage, TestApp)
118
+ session.visit('/with_js')
119
+ session.find(:css, '#set-storage').click
120
+ session.reset!
121
+ session.visit('/with_js')
122
+ expect(session.evaluate_script('Object.keys(localStorage)')).not_to be_empty
123
+ expect(session.evaluate_script('Object.keys(sessionStorage)')).not_to be_empty
59
124
  end
125
+
126
+ it 'can not clear session storage' do
127
+ session = Capybara::Session.new(:selenium_chrome_not_clear_session_storage, TestApp)
128
+ session.visit('/with_js')
129
+ session.find(:css, '#set-storage').click
130
+ session.reset!
131
+ session.visit('/with_js')
132
+ expect(session.evaluate_script('Object.keys(localStorage)')).to be_empty
133
+ expect(session.evaluate_script('Object.keys(sessionStorage)')).not_to be_empty
134
+ end
135
+
136
+ it 'can not clear local storage' do
137
+ session = Capybara::Session.new(:selenium_chrome_not_clear_local_storage, TestApp)
138
+ session.visit('/with_js')
139
+ session.find(:css, '#set-storage').click
140
+ session.reset!
141
+ session.visit('/with_js')
142
+ expect(session.evaluate_script('Object.keys(localStorage)')).not_to be_empty
143
+ expect(session.evaluate_script('Object.keys(sessionStorage)')).to be_empty
144
+ end
145
+ end
146
+ end
147
+
148
+ context 'timeout' do
149
+ it 'sets the http client read timeout' do
150
+ expect(TestSessions::Chrome.driver.browser.send(:bridge).http.read_timeout).to eq 30
151
+ end
152
+ end
153
+
154
+ describe 'filling in Chrome-specific date and time fields with keystrokes' do
155
+ let(:datetime) { Time.new(1983, 6, 19, 6, 30) }
156
+ let(:session) { TestSessions::Chrome }
157
+
158
+ before do
159
+ session.visit('/form')
160
+ end
161
+
162
+ it 'should fill in a date input with a String' do
163
+ session.fill_in('form_date', with: '06/19/1983')
164
+ session.click_button('awesome')
165
+ expect(Date.parse(extract_results(session)['date'])).to eq datetime.to_date
166
+ end
167
+
168
+ it 'should fill in a time input with a String' do
169
+ session.fill_in('form_time', with: '06:30A')
170
+ session.click_button('awesome')
171
+ results = extract_results(session)['time']
172
+ expect(Time.parse(results).strftime('%r')).to eq datetime.strftime('%r')
173
+ end
174
+
175
+ it 'should fill in a datetime input with a String' do
176
+ session.fill_in('form_datetime', with: "06/19/1983\t06:30A")
177
+ session.click_button('awesome')
178
+ expect(Time.parse(extract_results(session)['datetime'])).to eq datetime
179
+ end
180
+ end
181
+
182
+ describe 'using subclass of selenium driver' do
183
+ it 'works' do
184
+ session = Capybara::Session.new(:selenium_driver_subclass_with_chrome, TestApp)
185
+ session.visit('/form')
186
+ expect(session).to have_current_path('/form')
187
+ end
188
+ end
189
+
190
+ describe 'log access' do
191
+ let(:logs) do
192
+ session.driver.browser.then do |chrome_driver|
193
+ chrome_driver.respond_to?(:logs) ? chrome_driver : chrome_driver.manage
194
+ end.logs
195
+ end
196
+
197
+ it 'does not error getting log types' do
198
+ expect do
199
+ logs.available_types
200
+ end.not_to raise_error
201
+ end
202
+
203
+ it 'does not error when getting logs' do
204
+ expect do
205
+ logs.get(:browser)
206
+ end.not_to raise_error
60
207
  end
61
208
  end
62
209
  end
@@ -0,0 +1,96 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+ require 'selenium-webdriver'
5
+ require 'shared_selenium_session'
6
+ require 'shared_selenium_node'
7
+ require 'rspec/shared_spec_matchers'
8
+
9
+ def selenium_host
10
+ ENV.fetch('SELENIUM_HOST', '0.0.0.0')
11
+ end
12
+
13
+ def selenium_port
14
+ ENV.fetch('SELENIUM_PORT', 4444)
15
+ end
16
+
17
+ def ensure_selenium_running!
18
+ timer = Capybara::Helpers.timer(expire_in: 20)
19
+ begin
20
+ TCPSocket.open(selenium_host, selenium_port)
21
+ rescue StandardError
22
+ if timer.expired?
23
+ raise 'Selenium is not running. ' \
24
+ "You can run a selenium server easily with: \n " \
25
+ '$ docker-compose up -d selenium_chrome'
26
+ else
27
+ puts 'Waiting for Selenium docker instance...'
28
+ sleep 1
29
+ retry
30
+ end
31
+ end
32
+ end
33
+
34
+ def selenium_gte?(version)
35
+ defined?(Selenium::WebDriver::VERSION) && (Gem::Version.new(Selenium::WebDriver::VERSION) >= Gem::Version.new(version))
36
+ end
37
+
38
+ Capybara.register_driver :selenium_chrome_remote do |app|
39
+ ensure_selenium_running!
40
+
41
+ url = "http://#{selenium_host}:#{selenium_port}/wd/hub"
42
+ browser_options = Selenium::WebDriver::Chrome::Options.new
43
+
44
+ Capybara::Selenium::Driver.new app,
45
+ browser: :remote,
46
+ options: browser_options,
47
+ url: url
48
+ end
49
+
50
+ CHROME_REMOTE_DRIVER = :selenium_chrome_remote
51
+
52
+ module TestSessions
53
+ Chrome = Capybara::Session.new(CHROME_REMOTE_DRIVER, TestApp)
54
+ end
55
+
56
+ skipped_tests = %i[response_headers status_code trigger download]
57
+
58
+ Capybara::SpecHelper.run_specs TestSessions::Chrome, CHROME_REMOTE_DRIVER.to_s, capybara_skip: skipped_tests do |example|
59
+ case example.metadata[:full_description]
60
+ when /Capybara::Session selenium_chrome_remote node #shadow_root should get visible text/
61
+ pending "Selenium doesn't currently support getting visible text for shadow root elements"
62
+ when /Capybara::Session selenium_chrome_remote node #shadow_root/
63
+ skip 'Not supported with this chromedriver version' if chromedriver_lt?('96.0', @session)
64
+ end
65
+ end
66
+
67
+ RSpec.describe 'Capybara::Session with remote Chrome' do
68
+ include Capybara::SpecHelper
69
+ ['Capybara::Session', 'Capybara::Node', Capybara::RSpecMatchers].each do |examples|
70
+ include_examples examples, TestSessions::Chrome, CHROME_REMOTE_DRIVER
71
+ end
72
+
73
+ it 'is considered to be chrome' do
74
+ expect(session.driver.browser.browser).to eq :chrome
75
+ end
76
+
77
+ describe 'log access' do
78
+ let(:logs) do
79
+ session.driver.browser.then do |chrome_driver|
80
+ chrome_driver.respond_to?(:logs) ? chrome_driver : chrome_driver.manage
81
+ end.logs
82
+ end
83
+
84
+ it 'does not error when getting log types' do
85
+ expect do
86
+ logs.available_types
87
+ end.not_to raise_error
88
+ end
89
+
90
+ it 'does not error when getting logs' do
91
+ expect do
92
+ logs.get(:browser)
93
+ end.not_to raise_error
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+ require 'selenium-webdriver'
5
+ require 'shared_selenium_session'
6
+ require 'shared_selenium_node'
7
+ require 'rspec/shared_spec_matchers'
8
+
9
+ # unless ENV['CI']
10
+ # Selenium::WebDriver::Edge::Service.driver_path = '/usr/local/bin/msedgedriver'
11
+ # end
12
+
13
+ Selenium::WebDriver.logger.ignore(:selenium_manager)
14
+
15
+ if Selenium::WebDriver::Platform.mac?
16
+ Selenium::WebDriver::Edge.path = '/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge'
17
+ end
18
+
19
+ Capybara.register_driver :selenium_edge do |app|
20
+ # ::Selenium::WebDriver.logger.level = "debug"
21
+ # If we don't create an options object the path set above won't be used
22
+
23
+ # browser_options = Selenium::WebDriver::Edge::Options.new
24
+ # browser_options.add_argument('--headless') if ENV['HEADLESS']
25
+
26
+ browser_options = if ENV['HEADLESS']
27
+ Selenium::WebDriver::Options.edge(args: ['--headless=new'])
28
+ else
29
+ Selenium::WebDriver::Options.edge
30
+ end
31
+
32
+ Capybara::Selenium::Driver.new(app, browser: :edge, options: browser_options).tap do |driver|
33
+ driver.browser
34
+ driver.download_path = Capybara.save_path
35
+ end
36
+ end
37
+
38
+ module TestSessions
39
+ SeleniumEdge = Capybara::Session.new(:selenium_edge, TestApp)
40
+ end
41
+
42
+ skipped_tests = %i[response_headers status_code trigger]
43
+
44
+ Capybara::SpecHelper.log_selenium_driver_version(Selenium::WebDriver::Edge) if ENV['CI']
45
+
46
+ Capybara::SpecHelper.run_specs TestSessions::SeleniumEdge, 'selenium', capybara_skip: skipped_tests do |example|
47
+ case example.metadata[:full_description]
48
+ when 'Capybara::Session selenium #attach_file with a block can upload by clicking the file input'
49
+ pending "Edge doesn't allow clicking on file inputs"
50
+ when /Capybara::Session selenium node #shadow_root should get visible text/
51
+ pending "Selenium doesn't currently support getting visible text for shadow root elements"
52
+ end
53
+ end
54
+
55
+ RSpec.describe 'Capybara::Session with Edge', capybara_skip: skipped_tests do
56
+ include Capybara::SpecHelper
57
+ ['Capybara::Session', 'Capybara::Node', Capybara::RSpecMatchers].each do |examples|
58
+ include_examples examples, TestSessions::SeleniumEdge, :selenium_edge
59
+ end
60
+ end