capybara 3.32.2

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 (313) hide show
  1. checksums.yaml +7 -0
  2. data/.yardopts +1 -0
  3. data/History.md +1813 -0
  4. data/License.txt +22 -0
  5. data/README.md +1099 -0
  6. data/lib/capybara.rb +511 -0
  7. data/lib/capybara/config.rb +94 -0
  8. data/lib/capybara/cucumber.rb +27 -0
  9. data/lib/capybara/driver/base.rb +170 -0
  10. data/lib/capybara/driver/node.rb +139 -0
  11. data/lib/capybara/dsl.rb +65 -0
  12. data/lib/capybara/helpers.rb +108 -0
  13. data/lib/capybara/minitest.rb +386 -0
  14. data/lib/capybara/minitest/spec.rb +264 -0
  15. data/lib/capybara/node/actions.rb +420 -0
  16. data/lib/capybara/node/base.rb +143 -0
  17. data/lib/capybara/node/document.rb +48 -0
  18. data/lib/capybara/node/document_matchers.rb +67 -0
  19. data/lib/capybara/node/element.rb +606 -0
  20. data/lib/capybara/node/finders.rb +325 -0
  21. data/lib/capybara/node/matchers.rb +883 -0
  22. data/lib/capybara/node/simple.rb +208 -0
  23. data/lib/capybara/queries/ancestor_query.rb +27 -0
  24. data/lib/capybara/queries/base_query.rb +106 -0
  25. data/lib/capybara/queries/current_path_query.rb +51 -0
  26. data/lib/capybara/queries/match_query.rb +26 -0
  27. data/lib/capybara/queries/selector_query.rb +710 -0
  28. data/lib/capybara/queries/sibling_query.rb +26 -0
  29. data/lib/capybara/queries/style_query.rb +45 -0
  30. data/lib/capybara/queries/text_query.rb +110 -0
  31. data/lib/capybara/queries/title_query.rb +39 -0
  32. data/lib/capybara/rack_test/browser.rb +140 -0
  33. data/lib/capybara/rack_test/css_handlers.rb +13 -0
  34. data/lib/capybara/rack_test/driver.rb +109 -0
  35. data/lib/capybara/rack_test/errors.rb +6 -0
  36. data/lib/capybara/rack_test/form.rb +127 -0
  37. data/lib/capybara/rack_test/node.rb +325 -0
  38. data/lib/capybara/rails.rb +16 -0
  39. data/lib/capybara/registrations/drivers.rb +36 -0
  40. data/lib/capybara/registrations/patches/puma_ssl.rb +27 -0
  41. data/lib/capybara/registrations/servers.rb +44 -0
  42. data/lib/capybara/result.rb +190 -0
  43. data/lib/capybara/rspec.rb +29 -0
  44. data/lib/capybara/rspec/features.rb +23 -0
  45. data/lib/capybara/rspec/matcher_proxies.rb +82 -0
  46. data/lib/capybara/rspec/matchers.rb +201 -0
  47. data/lib/capybara/rspec/matchers/base.rb +111 -0
  48. data/lib/capybara/rspec/matchers/become_closed.rb +33 -0
  49. data/lib/capybara/rspec/matchers/compound.rb +88 -0
  50. data/lib/capybara/rspec/matchers/count_sugar.rb +37 -0
  51. data/lib/capybara/rspec/matchers/have_ancestor.rb +28 -0
  52. data/lib/capybara/rspec/matchers/have_current_path.rb +29 -0
  53. data/lib/capybara/rspec/matchers/have_selector.rb +77 -0
  54. data/lib/capybara/rspec/matchers/have_sibling.rb +27 -0
  55. data/lib/capybara/rspec/matchers/have_text.rb +33 -0
  56. data/lib/capybara/rspec/matchers/have_title.rb +29 -0
  57. data/lib/capybara/rspec/matchers/match_selector.rb +27 -0
  58. data/lib/capybara/rspec/matchers/match_style.rb +38 -0
  59. data/lib/capybara/rspec/matchers/spatial_sugar.rb +39 -0
  60. data/lib/capybara/selector.rb +233 -0
  61. data/lib/capybara/selector/builders/css_builder.rb +84 -0
  62. data/lib/capybara/selector/builders/xpath_builder.rb +69 -0
  63. data/lib/capybara/selector/css.rb +102 -0
  64. data/lib/capybara/selector/definition.rb +276 -0
  65. data/lib/capybara/selector/definition/button.rb +51 -0
  66. data/lib/capybara/selector/definition/checkbox.rb +26 -0
  67. data/lib/capybara/selector/definition/css.rb +10 -0
  68. data/lib/capybara/selector/definition/datalist_input.rb +35 -0
  69. data/lib/capybara/selector/definition/datalist_option.rb +25 -0
  70. data/lib/capybara/selector/definition/element.rb +27 -0
  71. data/lib/capybara/selector/definition/field.rb +40 -0
  72. data/lib/capybara/selector/definition/fieldset.rb +14 -0
  73. data/lib/capybara/selector/definition/file_field.rb +13 -0
  74. data/lib/capybara/selector/definition/fillable_field.rb +33 -0
  75. data/lib/capybara/selector/definition/frame.rb +17 -0
  76. data/lib/capybara/selector/definition/id.rb +6 -0
  77. data/lib/capybara/selector/definition/label.rb +62 -0
  78. data/lib/capybara/selector/definition/link.rb +46 -0
  79. data/lib/capybara/selector/definition/link_or_button.rb +16 -0
  80. data/lib/capybara/selector/definition/option.rb +27 -0
  81. data/lib/capybara/selector/definition/radio_button.rb +27 -0
  82. data/lib/capybara/selector/definition/select.rb +81 -0
  83. data/lib/capybara/selector/definition/table.rb +109 -0
  84. data/lib/capybara/selector/definition/table_row.rb +21 -0
  85. data/lib/capybara/selector/definition/xpath.rb +5 -0
  86. data/lib/capybara/selector/filter.rb +5 -0
  87. data/lib/capybara/selector/filter_set.rb +124 -0
  88. data/lib/capybara/selector/filters/base.rb +77 -0
  89. data/lib/capybara/selector/filters/expression_filter.rb +22 -0
  90. data/lib/capybara/selector/filters/locator_filter.rb +29 -0
  91. data/lib/capybara/selector/filters/node_filter.rb +31 -0
  92. data/lib/capybara/selector/regexp_disassembler.rb +214 -0
  93. data/lib/capybara/selector/selector.rb +147 -0
  94. data/lib/capybara/selector/xpath_extensions.rb +17 -0
  95. data/lib/capybara/selenium/atoms/getAttribute.min.js +1 -0
  96. data/lib/capybara/selenium/atoms/isDisplayed.min.js +1 -0
  97. data/lib/capybara/selenium/atoms/src/getAttribute.js +161 -0
  98. data/lib/capybara/selenium/atoms/src/isDisplayed.js +454 -0
  99. data/lib/capybara/selenium/driver.rb +496 -0
  100. data/lib/capybara/selenium/driver_specializations/chrome_driver.rb +119 -0
  101. data/lib/capybara/selenium/driver_specializations/edge_driver.rb +126 -0
  102. data/lib/capybara/selenium/driver_specializations/firefox_driver.rb +89 -0
  103. data/lib/capybara/selenium/driver_specializations/internet_explorer_driver.rb +26 -0
  104. data/lib/capybara/selenium/driver_specializations/safari_driver.rb +24 -0
  105. data/lib/capybara/selenium/extensions/file_input_click_emulation.rb +34 -0
  106. data/lib/capybara/selenium/extensions/find.rb +110 -0
  107. data/lib/capybara/selenium/extensions/html5_drag.rb +228 -0
  108. data/lib/capybara/selenium/extensions/modifier_keys_stack.rb +28 -0
  109. data/lib/capybara/selenium/extensions/scroll.rb +78 -0
  110. data/lib/capybara/selenium/logger_suppressor.rb +34 -0
  111. data/lib/capybara/selenium/node.rb +610 -0
  112. data/lib/capybara/selenium/nodes/chrome_node.rb +119 -0
  113. data/lib/capybara/selenium/nodes/edge_node.rb +104 -0
  114. data/lib/capybara/selenium/nodes/firefox_node.rb +131 -0
  115. data/lib/capybara/selenium/nodes/ie_node.rb +22 -0
  116. data/lib/capybara/selenium/nodes/safari_node.rb +118 -0
  117. data/lib/capybara/selenium/patches/action_pauser.rb +26 -0
  118. data/lib/capybara/selenium/patches/atoms.rb +18 -0
  119. data/lib/capybara/selenium/patches/is_displayed.rb +16 -0
  120. data/lib/capybara/selenium/patches/logs.rb +47 -0
  121. data/lib/capybara/selenium/patches/pause_duration_fix.rb +9 -0
  122. data/lib/capybara/selenium/patches/persistent_client.rb +20 -0
  123. data/lib/capybara/server.rb +126 -0
  124. data/lib/capybara/server/animation_disabler.rb +58 -0
  125. data/lib/capybara/server/checker.rb +44 -0
  126. data/lib/capybara/server/middleware.rb +69 -0
  127. data/lib/capybara/session.rb +942 -0
  128. data/lib/capybara/session/config.rb +124 -0
  129. data/lib/capybara/session/matchers.rb +87 -0
  130. data/lib/capybara/spec/fixtures/another_test_file.txt +1 -0
  131. data/lib/capybara/spec/fixtures/capybara.jpg +3 -0
  132. data/lib/capybara/spec/fixtures/no_extension +1 -0
  133. data/lib/capybara/spec/fixtures/test_file.txt +1 -0
  134. data/lib/capybara/spec/public/jquery-ui.js +13 -0
  135. data/lib/capybara/spec/public/jquery.js +5 -0
  136. data/lib/capybara/spec/public/offset.js +6 -0
  137. data/lib/capybara/spec/public/test.js +268 -0
  138. data/lib/capybara/spec/session/accept_alert_spec.rb +81 -0
  139. data/lib/capybara/spec/session/accept_confirm_spec.rb +32 -0
  140. data/lib/capybara/spec/session/accept_prompt_spec.rb +78 -0
  141. data/lib/capybara/spec/session/all_spec.rb +278 -0
  142. data/lib/capybara/spec/session/ancestor_spec.rb +88 -0
  143. data/lib/capybara/spec/session/assert_all_of_selectors_spec.rb +140 -0
  144. data/lib/capybara/spec/session/assert_current_path_spec.rb +75 -0
  145. data/lib/capybara/spec/session/assert_selector_spec.rb +143 -0
  146. data/lib/capybara/spec/session/assert_style_spec.rb +26 -0
  147. data/lib/capybara/spec/session/assert_text_spec.rb +258 -0
  148. data/lib/capybara/spec/session/assert_title_spec.rb +93 -0
  149. data/lib/capybara/spec/session/attach_file_spec.rb +216 -0
  150. data/lib/capybara/spec/session/body_spec.rb +23 -0
  151. data/lib/capybara/spec/session/check_spec.rb +235 -0
  152. data/lib/capybara/spec/session/choose_spec.rb +121 -0
  153. data/lib/capybara/spec/session/click_button_spec.rb +506 -0
  154. data/lib/capybara/spec/session/click_link_or_button_spec.rb +129 -0
  155. data/lib/capybara/spec/session/click_link_spec.rb +229 -0
  156. data/lib/capybara/spec/session/current_scope_spec.rb +31 -0
  157. data/lib/capybara/spec/session/current_url_spec.rb +115 -0
  158. data/lib/capybara/spec/session/dismiss_confirm_spec.rb +36 -0
  159. data/lib/capybara/spec/session/dismiss_prompt_spec.rb +21 -0
  160. data/lib/capybara/spec/session/element/assert_match_selector_spec.rb +38 -0
  161. data/lib/capybara/spec/session/element/match_css_spec.rb +31 -0
  162. data/lib/capybara/spec/session/element/match_xpath_spec.rb +25 -0
  163. data/lib/capybara/spec/session/element/matches_selector_spec.rb +120 -0
  164. data/lib/capybara/spec/session/evaluate_async_script_spec.rb +23 -0
  165. data/lib/capybara/spec/session/evaluate_script_spec.rb +49 -0
  166. data/lib/capybara/spec/session/execute_script_spec.rb +28 -0
  167. data/lib/capybara/spec/session/fill_in_spec.rb +286 -0
  168. data/lib/capybara/spec/session/find_button_spec.rb +74 -0
  169. data/lib/capybara/spec/session/find_by_id_spec.rb +33 -0
  170. data/lib/capybara/spec/session/find_field_spec.rb +113 -0
  171. data/lib/capybara/spec/session/find_link_spec.rb +70 -0
  172. data/lib/capybara/spec/session/find_spec.rb +531 -0
  173. data/lib/capybara/spec/session/first_spec.rb +156 -0
  174. data/lib/capybara/spec/session/frame/frame_title_spec.rb +23 -0
  175. data/lib/capybara/spec/session/frame/frame_url_spec.rb +23 -0
  176. data/lib/capybara/spec/session/frame/switch_to_frame_spec.rb +116 -0
  177. data/lib/capybara/spec/session/frame/within_frame_spec.rb +112 -0
  178. data/lib/capybara/spec/session/go_back_spec.rb +12 -0
  179. data/lib/capybara/spec/session/go_forward_spec.rb +14 -0
  180. data/lib/capybara/spec/session/has_all_selectors_spec.rb +69 -0
  181. data/lib/capybara/spec/session/has_ancestor_spec.rb +46 -0
  182. data/lib/capybara/spec/session/has_any_selectors_spec.rb +25 -0
  183. data/lib/capybara/spec/session/has_button_spec.rb +69 -0
  184. data/lib/capybara/spec/session/has_css_spec.rb +374 -0
  185. data/lib/capybara/spec/session/has_current_path_spec.rb +138 -0
  186. data/lib/capybara/spec/session/has_field_spec.rb +349 -0
  187. data/lib/capybara/spec/session/has_link_spec.rb +39 -0
  188. data/lib/capybara/spec/session/has_none_selectors_spec.rb +78 -0
  189. data/lib/capybara/spec/session/has_select_spec.rb +310 -0
  190. data/lib/capybara/spec/session/has_selector_spec.rb +202 -0
  191. data/lib/capybara/spec/session/has_sibling_spec.rb +50 -0
  192. data/lib/capybara/spec/session/has_table_spec.rb +198 -0
  193. data/lib/capybara/spec/session/has_text_spec.rb +394 -0
  194. data/lib/capybara/spec/session/has_title_spec.rb +71 -0
  195. data/lib/capybara/spec/session/has_xpath_spec.rb +149 -0
  196. data/lib/capybara/spec/session/headers_spec.rb +8 -0
  197. data/lib/capybara/spec/session/html_spec.rb +47 -0
  198. data/lib/capybara/spec/session/matches_style_spec.rb +35 -0
  199. data/lib/capybara/spec/session/node_spec.rb +1292 -0
  200. data/lib/capybara/spec/session/node_wrapper_spec.rb +39 -0
  201. data/lib/capybara/spec/session/refresh_spec.rb +33 -0
  202. data/lib/capybara/spec/session/reset_session_spec.rb +148 -0
  203. data/lib/capybara/spec/session/response_code_spec.rb +8 -0
  204. data/lib/capybara/spec/session/save_and_open_page_spec.rb +21 -0
  205. data/lib/capybara/spec/session/save_and_open_screenshot_spec.rb +43 -0
  206. data/lib/capybara/spec/session/save_page_spec.rb +110 -0
  207. data/lib/capybara/spec/session/save_screenshot_spec.rb +55 -0
  208. data/lib/capybara/spec/session/screenshot_spec.rb +18 -0
  209. data/lib/capybara/spec/session/scroll_spec.rb +117 -0
  210. data/lib/capybara/spec/session/select_spec.rb +229 -0
  211. data/lib/capybara/spec/session/selectors_spec.rb +98 -0
  212. data/lib/capybara/spec/session/sibling_spec.rb +52 -0
  213. data/lib/capybara/spec/session/source_spec.rb +0 -0
  214. data/lib/capybara/spec/session/text_spec.rb +74 -0
  215. data/lib/capybara/spec/session/title_spec.rb +29 -0
  216. data/lib/capybara/spec/session/uncheck_spec.rb +100 -0
  217. data/lib/capybara/spec/session/unselect_spec.rb +116 -0
  218. data/lib/capybara/spec/session/visit_spec.rb +204 -0
  219. data/lib/capybara/spec/session/window/become_closed_spec.rb +89 -0
  220. data/lib/capybara/spec/session/window/current_window_spec.rb +28 -0
  221. data/lib/capybara/spec/session/window/open_new_window_spec.rb +31 -0
  222. data/lib/capybara/spec/session/window/switch_to_window_spec.rb +132 -0
  223. data/lib/capybara/spec/session/window/window_opened_by_spec.rb +99 -0
  224. data/lib/capybara/spec/session/window/window_spec.rb +203 -0
  225. data/lib/capybara/spec/session/window/windows_spec.rb +34 -0
  226. data/lib/capybara/spec/session/window/within_window_spec.rb +157 -0
  227. data/lib/capybara/spec/session/within_spec.rb +199 -0
  228. data/lib/capybara/spec/spec_helper.rb +134 -0
  229. data/lib/capybara/spec/test_app.rb +226 -0
  230. data/lib/capybara/spec/views/animated.erb +49 -0
  231. data/lib/capybara/spec/views/buttons.erb +5 -0
  232. data/lib/capybara/spec/views/fieldsets.erb +30 -0
  233. data/lib/capybara/spec/views/form.erb +685 -0
  234. data/lib/capybara/spec/views/frame_child.erb +18 -0
  235. data/lib/capybara/spec/views/frame_one.erb +10 -0
  236. data/lib/capybara/spec/views/frame_parent.erb +9 -0
  237. data/lib/capybara/spec/views/frame_two.erb +9 -0
  238. data/lib/capybara/spec/views/header_links.erb +8 -0
  239. data/lib/capybara/spec/views/host_links.erb +13 -0
  240. data/lib/capybara/spec/views/initial_alert.erb +10 -0
  241. data/lib/capybara/spec/views/obscured.erb +47 -0
  242. data/lib/capybara/spec/views/offset.erb +32 -0
  243. data/lib/capybara/spec/views/path.erb +13 -0
  244. data/lib/capybara/spec/views/popup_one.erb +9 -0
  245. data/lib/capybara/spec/views/popup_two.erb +9 -0
  246. data/lib/capybara/spec/views/postback.erb +14 -0
  247. data/lib/capybara/spec/views/react.erb +45 -0
  248. data/lib/capybara/spec/views/scroll.erb +20 -0
  249. data/lib/capybara/spec/views/spatial.erb +31 -0
  250. data/lib/capybara/spec/views/tables.erb +130 -0
  251. data/lib/capybara/spec/views/with_animation.erb +74 -0
  252. data/lib/capybara/spec/views/with_base_tag.erb +11 -0
  253. data/lib/capybara/spec/views/with_count.erb +8 -0
  254. data/lib/capybara/spec/views/with_dragula.erb +22 -0
  255. data/lib/capybara/spec/views/with_fixed_header_footer.erb +17 -0
  256. data/lib/capybara/spec/views/with_hover.erb +24 -0
  257. data/lib/capybara/spec/views/with_hover1.erb +10 -0
  258. data/lib/capybara/spec/views/with_html.erb +208 -0
  259. data/lib/capybara/spec/views/with_html5_svg.erb +20 -0
  260. data/lib/capybara/spec/views/with_html_entities.erb +2 -0
  261. data/lib/capybara/spec/views/with_js.erb +160 -0
  262. data/lib/capybara/spec/views/with_jstree.erb +26 -0
  263. data/lib/capybara/spec/views/with_namespace.erb +20 -0
  264. data/lib/capybara/spec/views/with_scope.erb +42 -0
  265. data/lib/capybara/spec/views/with_scope_other.erb +6 -0
  266. data/lib/capybara/spec/views/with_simple_html.erb +2 -0
  267. data/lib/capybara/spec/views/with_slow_unload.erb +17 -0
  268. data/lib/capybara/spec/views/with_sortable_js.erb +21 -0
  269. data/lib/capybara/spec/views/with_title.erb +5 -0
  270. data/lib/capybara/spec/views/with_unload_alert.erb +14 -0
  271. data/lib/capybara/spec/views/with_windows.erb +54 -0
  272. data/lib/capybara/spec/views/within_frames.erb +15 -0
  273. data/lib/capybara/version.rb +5 -0
  274. data/lib/capybara/window.rb +146 -0
  275. data/spec/basic_node_spec.rb +154 -0
  276. data/spec/capybara_spec.rb +112 -0
  277. data/spec/css_builder_spec.rb +101 -0
  278. data/spec/css_splitter_spec.rb +38 -0
  279. data/spec/dsl_spec.rb +276 -0
  280. data/spec/filter_set_spec.rb +46 -0
  281. data/spec/fixtures/capybara.csv +1 -0
  282. data/spec/fixtures/certificate.pem +25 -0
  283. data/spec/fixtures/key.pem +27 -0
  284. data/spec/fixtures/selenium_driver_rspec_failure.rb +13 -0
  285. data/spec/fixtures/selenium_driver_rspec_success.rb +13 -0
  286. data/spec/minitest_spec.rb +163 -0
  287. data/spec/minitest_spec_spec.rb +162 -0
  288. data/spec/per_session_config_spec.rb +68 -0
  289. data/spec/rack_test_spec.rb +268 -0
  290. data/spec/regexp_dissassembler_spec.rb +250 -0
  291. data/spec/result_spec.rb +196 -0
  292. data/spec/rspec/features_spec.rb +99 -0
  293. data/spec/rspec/scenarios_spec.rb +19 -0
  294. data/spec/rspec/shared_spec_matchers.rb +947 -0
  295. data/spec/rspec/views_spec.rb +14 -0
  296. data/spec/rspec_matchers_spec.rb +62 -0
  297. data/spec/rspec_spec.rb +145 -0
  298. data/spec/sauce_spec_chrome.rb +43 -0
  299. data/spec/selector_spec.rb +513 -0
  300. data/spec/selenium_spec_chrome.rb +188 -0
  301. data/spec/selenium_spec_chrome_remote.rb +96 -0
  302. data/spec/selenium_spec_edge.rb +47 -0
  303. data/spec/selenium_spec_firefox.rb +208 -0
  304. data/spec/selenium_spec_firefox_remote.rb +80 -0
  305. data/spec/selenium_spec_ie.rb +150 -0
  306. data/spec/selenium_spec_safari.rb +148 -0
  307. data/spec/server_spec.rb +292 -0
  308. data/spec/session_spec.rb +91 -0
  309. data/spec/shared_selenium_node.rb +83 -0
  310. data/spec/shared_selenium_session.rb +476 -0
  311. data/spec/spec_helper.rb +100 -0
  312. data/spec/xpath_builder_spec.rb +93 -0
  313. metadata +753 -0
@@ -0,0 +1,18 @@
1
+ # coding: US-ASCII
2
+ # frozen_string_literal: true
3
+
4
+ Capybara::SpecHelper.spec '#save_screenshot' do
5
+ let(:image_path) { File.join(Dir.tmpdir, 'capybara-screenshot.png') }
6
+
7
+ before do
8
+ @session.visit '/'
9
+ end
10
+
11
+ it 'should generate PNG file', requires: [:screenshot] do
12
+ path = @session.save_screenshot image_path
13
+
14
+ magic = File.read(image_path, 4)
15
+ expect(magic).to eq "\x89PNG"
16
+ expect(path).to eq image_path
17
+ end
18
+ end
@@ -0,0 +1,117 @@
1
+ # frozen_string_literal: true
2
+
3
+ Capybara::SpecHelper.spec '#scroll_to', requires: [:scroll] do
4
+ before do
5
+ @session.visit('/scroll')
6
+ end
7
+
8
+ it 'can scroll an element to the top of the viewport' do
9
+ el = @session.find(:css, '#scroll')
10
+ @session.scroll_to(el, align: :top)
11
+ expect(el.evaluate_script('this.getBoundingClientRect().top')).to be_within(1).of(0)
12
+ end
13
+
14
+ it 'can scroll an element to the bottom of the viewport' do
15
+ el = @session.find(:css, '#scroll')
16
+ @session.scroll_to(el, align: :bottom)
17
+ el_bottom = el.evaluate_script('this.getBoundingClientRect().bottom')
18
+ viewport_bottom = el.evaluate_script('document.body.clientHeight')
19
+ expect(el_bottom).to be_within(1).of(viewport_bottom)
20
+ end
21
+
22
+ it 'can scroll an element to the center of the viewport' do
23
+ el = @session.find(:css, '#scroll')
24
+ @session.scroll_to(el, align: :center)
25
+ el_center = el.evaluate_script('(function(rect){return (rect.top + rect.bottom)/2})(this.getBoundingClientRect())')
26
+ viewport_bottom = el.evaluate_script('document.body.clientHeight')
27
+ expect(el_center).to be_within(2).of(viewport_bottom / 2)
28
+ end
29
+
30
+ it 'can scroll the window to the vertical top' do
31
+ @session.scroll_to :bottom
32
+ @session.scroll_to :top
33
+ expect(@session.evaluate_script('[window.scrollX || window.pageXOffset, window.scrollY || window.pageYOffset]')).to eq [0, 0]
34
+ end
35
+
36
+ it 'can scroll the window to the vertical bottom' do
37
+ @session.scroll_to :bottom
38
+ max_scroll = @session.evaluate_script('document.body.scrollHeight - document.body.clientHeight')
39
+ expect(@session.evaluate_script('[window.scrollX || window.pageXOffset, window.scrollY || window.pageYOffset]')).to eq [0, max_scroll]
40
+ end
41
+
42
+ it 'can scroll the window to the vertical center' do
43
+ @session.scroll_to :center
44
+ max_scroll = @session.evaluate_script('document.documentElement.scrollHeight - document.body.clientHeight')
45
+ expect(@session.evaluate_script('[window.scrollX || window.pageXOffset, window.scrollY || window.pageYOffset]')).to eq [0, max_scroll / 2]
46
+ end
47
+
48
+ it 'can scroll the window to specific location' do
49
+ @session.scroll_to 100, 100
50
+ expect(@session.evaluate_script('[window.scrollX || window.pageXOffset, window.scrollY || window.pageYOffset]')).to eq [100, 100]
51
+ end
52
+
53
+ it 'can scroll an element to the top of the scrolling element' do
54
+ scrolling_element = @session.find(:css, '#scrollable')
55
+ el = scrolling_element.find(:css, '#inner')
56
+ scrolling_element.scroll_to(el, align: :top)
57
+ scrolling_element_top = scrolling_element.evaluate_script('this.getBoundingClientRect().top')
58
+ expect(el.evaluate_script('this.getBoundingClientRect().top')).to be_within(3).of(scrolling_element_top)
59
+ end
60
+
61
+ it 'can scroll an element to the bottom of the scrolling element' do
62
+ scrolling_element = @session.find(:css, '#scrollable')
63
+ el = scrolling_element.find(:css, '#inner')
64
+ scrolling_element.scroll_to(el, align: :bottom)
65
+ el_bottom = el.evaluate_script('this.getBoundingClientRect().bottom')
66
+ scroller_bottom = scrolling_element.evaluate_script('this.getBoundingClientRect().top + this.clientHeight')
67
+ expect(el_bottom).to be_within(1).of(scroller_bottom)
68
+ end
69
+
70
+ it 'can scroll an element to the center of the scrolling element' do
71
+ scrolling_element = @session.find(:css, '#scrollable')
72
+ el = scrolling_element.find(:css, '#inner')
73
+ scrolling_element.scroll_to(el, align: :center)
74
+ el_center = el.evaluate_script('(function(rect){return (rect.top + rect.bottom)/2})(this.getBoundingClientRect())')
75
+ scrollable_center = scrolling_element.evaluate_script('(this.clientHeight / 2) + this.getBoundingClientRect().top')
76
+ expect(el_center).to be_within(1).of(scrollable_center)
77
+ end
78
+
79
+ it 'can scroll the scrolling element to the top' do
80
+ scrolling_element = @session.find(:css, '#scrollable')
81
+ scrolling_element.scroll_to :bottom
82
+ scrolling_element.scroll_to :top
83
+ expect(scrolling_element.evaluate_script('[this.scrollLeft, this.scrollTop]')).to eq [0, 0]
84
+ end
85
+
86
+ it 'can scroll the scrolling element to the bottom' do
87
+ scrolling_element = @session.find(:css, '#scrollable')
88
+ scrolling_element.scroll_to :bottom
89
+ max_scroll = scrolling_element.evaluate_script('this.scrollHeight - this.clientHeight')
90
+ expect(scrolling_element.evaluate_script('[this.scrollLeft, this.scrollTop]')).to eq [0, max_scroll]
91
+ end
92
+
93
+ it 'can scroll the scrolling element to the vertical center' do
94
+ scrolling_element = @session.find(:css, '#scrollable')
95
+ scrolling_element.scroll_to :center
96
+ max_scroll = scrolling_element.evaluate_script('this.scrollHeight - this.clientHeight')
97
+ expect(scrolling_element.evaluate_script('[this.scrollLeft, this.scrollTop]')).to eq [0, max_scroll / 2]
98
+ end
99
+
100
+ it 'can scroll the scrolling element to specific location' do
101
+ scrolling_element = @session.find(:css, '#scrollable')
102
+ scrolling_element.scroll_to 100, 100
103
+ expect(scrolling_element.evaluate_script('[this.scrollLeft, this.scrollTop]')).to eq [100, 100]
104
+ end
105
+
106
+ it 'can scroll the window by a specific amount' do
107
+ @session.scroll_to(:current, offset: [50, 75])
108
+ expect(@session.evaluate_script('[window.scrollX || window.pageXOffset, window.scrollY || window.pageYOffset]')).to eq [50, 75]
109
+ end
110
+
111
+ it 'can scroll the scroll the scrolling element by a specific amount' do
112
+ scrolling_element = @session.find(:css, '#scrollable')
113
+ scrolling_element.scroll_to 100, 100
114
+ scrolling_element.scroll_to(:current, offset: [-50, 50])
115
+ expect(scrolling_element.evaluate_script('[this.scrollLeft, this.scrollTop]')).to eq [50, 150]
116
+ end
117
+ end
@@ -0,0 +1,229 @@
1
+ # frozen_string_literal: true
2
+
3
+ Capybara::SpecHelper.spec '#select' do
4
+ before do
5
+ @session.visit('/form')
6
+ end
7
+
8
+ it 'should return value of the first option' do
9
+ expect(@session.find_field('Title').value).to eq('Mrs')
10
+ end
11
+
12
+ it 'should return value of the selected option' do
13
+ @session.select('Miss', from: 'Title')
14
+ expect(@session.find_field('Title').value).to eq('Miss')
15
+ end
16
+
17
+ it 'should allow selecting exact options where there are inexact matches', :exact_false do
18
+ @session.select('Mr', from: 'Title')
19
+ expect(@session.find_field('Title').value).to eq('Mr')
20
+ end
21
+
22
+ it 'should allow selecting options where they are the only inexact match', :exact_false do
23
+ @session.select('Mis', from: 'Title')
24
+ expect(@session.find_field('Title').value).to eq('Miss')
25
+ end
26
+
27
+ it 'should not allow selecting options where they are the only inexact match if `exact: true` is specified' do
28
+ sel = @session.find(:select, 'Title')
29
+ expect do
30
+ sel.select('Mis', exact: true)
31
+ end.to raise_error(Capybara::ElementNotFound)
32
+ end
33
+
34
+ it 'should not allow selecting an option if the match is ambiguous', :exact_false do
35
+ expect do
36
+ @session.select('M', from: 'Title')
37
+ end.to raise_error(Capybara::Ambiguous)
38
+ end
39
+
40
+ it 'should return the value attribute rather than content if present' do
41
+ expect(@session.find_field('Locale').value).to eq('en')
42
+ end
43
+
44
+ it 'should select an option from a select box by id' do
45
+ @session.select('Finnish', from: 'form_locale')
46
+ @session.click_button('awesome')
47
+ expect(extract_results(@session)['locale']).to eq('fi')
48
+ end
49
+
50
+ it 'should select an option from a select box by label' do
51
+ @session.select('Finnish', from: 'Locale')
52
+ @session.click_button('awesome')
53
+ expect(extract_results(@session)['locale']).to eq('fi')
54
+ end
55
+
56
+ it 'should select an option without giving a select box' do
57
+ @session.select('Swedish')
58
+ @session.click_button('awesome')
59
+ expect(extract_results(@session)['locale']).to eq('sv')
60
+ end
61
+
62
+ it 'should escape quotes' do
63
+ @session.select("John's made-up language", from: 'Locale')
64
+ @session.click_button('awesome')
65
+ expect(extract_results(@session)['locale']).to eq('jo')
66
+ end
67
+
68
+ it 'should obey from' do
69
+ @session.select('Miss', from: 'Other title')
70
+ @session.click_button('awesome')
71
+ results = extract_results(@session)
72
+ expect(results['other_title']).to eq('Miss')
73
+ expect(results['title']).not_to eq('Miss')
74
+ end
75
+
76
+ it 'show match labels with preceding or trailing whitespace' do
77
+ @session.select('Lojban', from: 'Locale')
78
+ @session.click_button('awesome')
79
+ expect(extract_results(@session)['locale']).to eq('jbo')
80
+ end
81
+
82
+ it 'casts to string' do
83
+ @session.select(:Miss, from: :Title)
84
+ expect(@session.find_field('Title').value).to eq('Miss')
85
+ end
86
+
87
+ context 'input with datalist' do
88
+ it 'should select an option' do
89
+ @session.select('Audi', from: 'manufacturer')
90
+ @session.click_button('awesome')
91
+ expect(extract_results(@session)['manufacturer']).to eq('Audi')
92
+ end
93
+
94
+ it 'should not find an input without a datalist' do
95
+ expect do
96
+ @session.select('Thomas', from: 'form_first_name')
97
+ end.to raise_error(/Unable to find input box with datalist completion "form_first_name"/)
98
+ end
99
+
100
+ it "should not select an option that doesn't exist" do
101
+ expect do
102
+ @session.select('Tata', from: 'manufacturer')
103
+ end.to raise_error(/Unable to find datalist option "Tata"/)
104
+ end
105
+
106
+ it 'should not select a disabled option' do
107
+ expect do
108
+ @session.select('Mercedes', from: 'manufacturer')
109
+ end.to raise_error(/Unable to find datalist option "Mercedes"/)
110
+ end
111
+ end
112
+
113
+ context "with a locator that doesn't exist" do
114
+ it 'should raise an error' do
115
+ msg = /Unable to find select box "does not exist"/
116
+ expect do
117
+ @session.select('foo', from: 'does not exist')
118
+ end.to raise_error(Capybara::ElementNotFound, msg)
119
+ end
120
+ end
121
+
122
+ context "with an option that doesn't exist" do
123
+ it 'should raise an error' do
124
+ msg = /^Unable to find option "Does not Exist" within/
125
+ expect do
126
+ @session.select('Does not Exist', from: 'form_locale')
127
+ end.to raise_error(Capybara::ElementNotFound, msg)
128
+ end
129
+ end
130
+
131
+ context 'on a disabled select' do
132
+ it 'should raise an error' do
133
+ expect do
134
+ @session.select('Should not see me', from: 'Disabled Select')
135
+ end.to raise_error(Capybara::ElementNotFound)
136
+ end
137
+ end
138
+
139
+ context 'on a disabled option' do
140
+ it 'should not select' do
141
+ @session.select('Other', from: 'form_title')
142
+ expect(@session.find_field('form_title').value).not_to eq 'Other'
143
+ end
144
+ end
145
+
146
+ context 'with multiple select' do
147
+ it 'should return an empty value' do
148
+ expect(@session.find_field('Languages').value).to eq([])
149
+ end
150
+
151
+ it 'should return value of the selected options' do
152
+ @session.select('Ruby', from: 'Languages')
153
+ @session.select('Javascript', from: 'Languages')
154
+ expect(@session.find_field('Languages').value).to include('Ruby', 'Javascript')
155
+ end
156
+
157
+ it 'should select one option' do
158
+ @session.select('Ruby', from: 'Languages')
159
+ @session.click_button('awesome')
160
+ expect(extract_results(@session)['languages']).to eq(['Ruby'])
161
+ end
162
+
163
+ it 'should select multiple options' do
164
+ @session.select('Ruby', from: 'Languages')
165
+ @session.select('Javascript', from: 'Languages')
166
+ @session.click_button('awesome')
167
+ expect(extract_results(@session)['languages']).to include('Ruby', 'Javascript')
168
+ end
169
+
170
+ it 'should remain selected if already selected' do
171
+ @session.select('Ruby', from: 'Languages')
172
+ @session.select('Javascript', from: 'Languages')
173
+ @session.select('Ruby', from: 'Languages')
174
+ @session.click_button('awesome')
175
+ expect(extract_results(@session)['languages']).to include('Ruby', 'Javascript')
176
+ end
177
+
178
+ it 'should return value attribute rather than content if present' do
179
+ expect(@session.find_field('Underwear').value).to include('thermal')
180
+ end
181
+ end
182
+
183
+ context 'with :exact option' do
184
+ context 'when `false`' do
185
+ it 'can match select box approximately' do
186
+ @session.select('Finnish', from: 'Loc', exact: false)
187
+ @session.click_button('awesome')
188
+ expect(extract_results(@session)['locale']).to eq('fi')
189
+ end
190
+
191
+ it 'can match option approximately' do
192
+ @session.select('Fin', from: 'Locale', exact: false)
193
+ @session.click_button('awesome')
194
+ expect(extract_results(@session)['locale']).to eq('fi')
195
+ end
196
+
197
+ it 'can match option approximately when :from not given' do
198
+ @session.select('made-up language', exact: false)
199
+ @session.click_button('awesome')
200
+ expect(extract_results(@session)['locale']).to eq('jo')
201
+ end
202
+ end
203
+
204
+ context 'when `true`' do
205
+ it 'can match select box approximately' do
206
+ expect do
207
+ @session.select('Finnish', from: 'Loc', exact: true)
208
+ end.to raise_error(Capybara::ElementNotFound)
209
+ end
210
+
211
+ it 'can match option approximately' do
212
+ expect do
213
+ @session.select('Fin', from: 'Locale', exact: true)
214
+ end.to raise_error(Capybara::ElementNotFound)
215
+ end
216
+
217
+ it 'can match option approximately when :from not given' do
218
+ expect do
219
+ @session.select('made-up language', exact: true)
220
+ end.to raise_error(Capybara::ElementNotFound)
221
+ end
222
+ end
223
+ end
224
+
225
+ it 'should error when not passed a locator for :from option' do
226
+ select = @session.find(:select, 'Title')
227
+ expect { @session.select('Mr', from: select) }.to raise_error(ArgumentError, /does not take an element/)
228
+ end
229
+ end
@@ -0,0 +1,98 @@
1
+ # frozen_string_literal: true
2
+
3
+ Capybara::SpecHelper.spec Capybara::Selector do
4
+ before do
5
+ @session.visit('/form')
6
+ end
7
+
8
+ describe ':label selector' do
9
+ it 'finds a label by text' do
10
+ expect(@session.find(:label, 'Customer Name').text).to eq 'Customer Name'
11
+ end
12
+
13
+ it 'finds a label by for attribute string' do
14
+ expect(@session.find(:label, for: 'form_other_title')['for']).to eq 'form_other_title'
15
+ end
16
+
17
+ it 'finds a label for for attribute regex' do
18
+ expect(@session.find(:label, for: /_other_title/)['for']).to eq 'form_other_title'
19
+ end
20
+
21
+ it 'finds a label from nested input using :for filter with id string' do
22
+ expect(@session.find(:label, for: 'nested_label').text).to eq 'Nested Label'
23
+ end
24
+
25
+ it 'finds a label from nested input using :for filter with id regexp' do
26
+ expect(@session.find(:label, for: /nested_lab/).text).to eq 'Nested Label'
27
+ end
28
+
29
+ it 'finds a label from nested input using :for filter with element' do
30
+ input = @session.find(:id, 'nested_label')
31
+ expect(@session.find(:label, for: input).text).to eq 'Nested Label'
32
+ end
33
+
34
+ it 'finds a label from nested input using :for filter with element when no id on label' do
35
+ input = @session.find(:css, '#wrapper_label').find(:css, 'input')
36
+ expect(@session.find(:label, for: input).text).to eq 'Wrapper Label'
37
+ end
38
+
39
+ it 'finds the label for an non-nested element when using :for filter' do
40
+ select = @session.find(:id, 'form_other_title')
41
+ expect(@session.find(:label, for: select)['for']).to eq 'form_other_title'
42
+ end
43
+
44
+ context 'with exact option' do
45
+ it 'matches substrings' do
46
+ expect(@session.find(:label, 'Customer Na', exact: false).text).to eq 'Customer Name'
47
+ end
48
+
49
+ it "doesn't match substrings" do
50
+ expect { @session.find(:label, 'Customer Na', exact: true) }.to raise_error(Capybara::ElementNotFound)
51
+ end
52
+ end
53
+ end
54
+
55
+ describe 'field selectors' do
56
+ context 'with :id option' do
57
+ it 'can find specifically by id' do
58
+ expect(@session.find(:field, id: 'customer_email').value).to eq 'ben@ben.com'
59
+ end
60
+
61
+ it 'can find by regex' do
62
+ expect(@session.find(:field, id: /ustomer.emai/).value).to eq 'ben@ben.com'
63
+ end
64
+
65
+ it 'can find by case-insensitive id' do
66
+ expect(@session.find(:field, id: /StOmer.emAI/i).value).to eq 'ben@ben.com'
67
+ end
68
+ end
69
+
70
+ it 'can find specifically by name string' do
71
+ expect(@session.find(:field, name: 'form[other_title]')['id']).to eq 'form_other_title'
72
+ end
73
+
74
+ it 'can find specifically by name regex' do
75
+ expect(@session.find(:field, name: /form\[other_.*\]/)['id']).to eq 'form_other_title'
76
+ end
77
+
78
+ it 'can find specifically by placeholder string' do
79
+ expect(@session.find(:field, placeholder: 'FirstName')['id']).to eq 'form_first_name'
80
+ end
81
+
82
+ it 'can find specifically by placeholder regex' do
83
+ expect(@session.find(:field, placeholder: /FirstN.*/)['id']).to eq 'form_first_name'
84
+ end
85
+
86
+ it 'can find by type' do
87
+ expect(@session.find(:field, 'Confusion', type: 'checkbox')['id']).to eq 'confusion_checkbox'
88
+ expect(@session.find(:field, 'Confusion', type: 'text')['id']).to eq 'confusion_text'
89
+ expect(@session.find(:field, 'Confusion', type: 'textarea')['id']).to eq 'confusion_textarea'
90
+ end
91
+
92
+ it 'can find by class' do
93
+ expect(@session.find(:field, class: 'confusion-checkbox')['id']).to eq 'confusion_checkbox'
94
+ expect(@session).to have_selector(:field, class: 'confusion', count: 3)
95
+ expect(@session.find(:field, class: %w[confusion confusion-textarea])['id']).to eq 'confusion_textarea'
96
+ end
97
+ end
98
+ end