capybara 2.7.0 → 3.35.3

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 (318) hide show
  1. checksums.yaml +5 -5
  2. data/.yardopts +1 -0
  3. data/History.md +1147 -11
  4. data/License.txt +1 -1
  5. data/README.md +252 -131
  6. data/lib/capybara/config.rb +92 -0
  7. data/lib/capybara/cucumber.rb +3 -3
  8. data/lib/capybara/driver/base.rb +52 -21
  9. data/lib/capybara/driver/node.rb +48 -14
  10. data/lib/capybara/dsl.rb +16 -9
  11. data/lib/capybara/helpers.rb +72 -81
  12. data/lib/capybara/minitest/spec.rb +267 -0
  13. data/lib/capybara/minitest.rb +385 -0
  14. data/lib/capybara/node/actions.rb +337 -89
  15. data/lib/capybara/node/base.rb +50 -32
  16. data/lib/capybara/node/document.rb +19 -3
  17. data/lib/capybara/node/document_matchers.rb +22 -24
  18. data/lib/capybara/node/element.rb +388 -125
  19. data/lib/capybara/node/finders.rb +231 -121
  20. data/lib/capybara/node/matchers.rb +503 -217
  21. data/lib/capybara/node/simple.rb +64 -27
  22. data/lib/capybara/queries/ancestor_query.rb +27 -0
  23. data/lib/capybara/queries/base_query.rb +87 -11
  24. data/lib/capybara/queries/current_path_query.rb +24 -24
  25. data/lib/capybara/queries/match_query.rb +15 -10
  26. data/lib/capybara/queries/selector_query.rb +675 -81
  27. data/lib/capybara/queries/sibling_query.rb +26 -0
  28. data/lib/capybara/queries/style_query.rb +45 -0
  29. data/lib/capybara/queries/text_query.rb +88 -20
  30. data/lib/capybara/queries/title_query.rb +9 -11
  31. data/lib/capybara/rack_test/browser.rb +63 -39
  32. data/lib/capybara/rack_test/css_handlers.rb +6 -4
  33. data/lib/capybara/rack_test/driver.rb +26 -16
  34. data/lib/capybara/rack_test/errors.rb +6 -0
  35. data/lib/capybara/rack_test/form.rb +73 -58
  36. data/lib/capybara/rack_test/node.rb +187 -67
  37. data/lib/capybara/rails.rb +4 -8
  38. data/lib/capybara/registration_container.rb +44 -0
  39. data/lib/capybara/registrations/drivers.rb +42 -0
  40. data/lib/capybara/registrations/patches/puma_ssl.rb +29 -0
  41. data/lib/capybara/registrations/servers.rb +45 -0
  42. data/lib/capybara/result.rb +142 -14
  43. data/lib/capybara/rspec/features.rb +17 -42
  44. data/lib/capybara/rspec/matcher_proxies.rb +82 -0
  45. data/lib/capybara/rspec/matchers/base.rb +111 -0
  46. data/lib/capybara/rspec/matchers/become_closed.rb +33 -0
  47. data/lib/capybara/rspec/matchers/compound.rb +88 -0
  48. data/lib/capybara/rspec/matchers/count_sugar.rb +37 -0
  49. data/lib/capybara/rspec/matchers/have_ancestor.rb +28 -0
  50. data/lib/capybara/rspec/matchers/have_current_path.rb +29 -0
  51. data/lib/capybara/rspec/matchers/have_selector.rb +77 -0
  52. data/lib/capybara/rspec/matchers/have_sibling.rb +27 -0
  53. data/lib/capybara/rspec/matchers/have_text.rb +33 -0
  54. data/lib/capybara/rspec/matchers/have_title.rb +29 -0
  55. data/lib/capybara/rspec/matchers/match_selector.rb +27 -0
  56. data/lib/capybara/rspec/matchers/match_style.rb +43 -0
  57. data/lib/capybara/rspec/matchers/spatial_sugar.rb +39 -0
  58. data/lib/capybara/rspec/matchers.rb +143 -244
  59. data/lib/capybara/rspec.rb +10 -12
  60. data/lib/capybara/selector/builders/css_builder.rb +84 -0
  61. data/lib/capybara/selector/builders/xpath_builder.rb +71 -0
  62. data/lib/capybara/selector/css.rb +102 -0
  63. data/lib/capybara/selector/definition/button.rb +63 -0
  64. data/lib/capybara/selector/definition/checkbox.rb +26 -0
  65. data/lib/capybara/selector/definition/css.rb +10 -0
  66. data/lib/capybara/selector/definition/datalist_input.rb +35 -0
  67. data/lib/capybara/selector/definition/datalist_option.rb +25 -0
  68. data/lib/capybara/selector/definition/element.rb +28 -0
  69. data/lib/capybara/selector/definition/field.rb +40 -0
  70. data/lib/capybara/selector/definition/fieldset.rb +14 -0
  71. data/lib/capybara/selector/definition/file_field.rb +13 -0
  72. data/lib/capybara/selector/definition/fillable_field.rb +33 -0
  73. data/lib/capybara/selector/definition/frame.rb +17 -0
  74. data/lib/capybara/selector/definition/id.rb +6 -0
  75. data/lib/capybara/selector/definition/label.rb +62 -0
  76. data/lib/capybara/selector/definition/link.rb +54 -0
  77. data/lib/capybara/selector/definition/link_or_button.rb +16 -0
  78. data/lib/capybara/selector/definition/option.rb +27 -0
  79. data/lib/capybara/selector/definition/radio_button.rb +27 -0
  80. data/lib/capybara/selector/definition/select.rb +81 -0
  81. data/lib/capybara/selector/definition/table.rb +109 -0
  82. data/lib/capybara/selector/definition/table_row.rb +21 -0
  83. data/lib/capybara/selector/definition/xpath.rb +5 -0
  84. data/lib/capybara/selector/definition.rb +278 -0
  85. data/lib/capybara/selector/filter.rb +3 -46
  86. data/lib/capybara/selector/filter_set.rb +124 -0
  87. data/lib/capybara/selector/filters/base.rb +77 -0
  88. data/lib/capybara/selector/filters/expression_filter.rb +22 -0
  89. data/lib/capybara/selector/filters/locator_filter.rb +29 -0
  90. data/lib/capybara/selector/filters/node_filter.rb +31 -0
  91. data/lib/capybara/selector/regexp_disassembler.rb +214 -0
  92. data/lib/capybara/selector/selector.rb +155 -0
  93. data/lib/capybara/selector/xpath_extensions.rb +17 -0
  94. data/lib/capybara/selector.rb +232 -369
  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 +380 -142
  100. data/lib/capybara/selenium/driver_specializations/chrome_driver.rb +117 -0
  101. data/lib/capybara/selenium/driver_specializations/edge_driver.rb +124 -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 +76 -0
  110. data/lib/capybara/selenium/logger_suppressor.rb +40 -0
  111. data/lib/capybara/selenium/node.rb +528 -97
  112. data/lib/capybara/selenium/nodes/chrome_node.rb +137 -0
  113. data/lib/capybara/selenium/nodes/edge_node.rb +104 -0
  114. data/lib/capybara/selenium/nodes/firefox_node.rb +136 -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 +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 +63 -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 +74 -71
  127. data/lib/capybara/session/config.rb +126 -0
  128. data/lib/capybara/session/matchers.rb +44 -27
  129. data/lib/capybara/session.rb +500 -297
  130. data/lib/capybara/spec/fixtures/no_extension +1 -0
  131. data/lib/capybara/spec/public/jquery.js +5 -5
  132. data/lib/capybara/spec/public/offset.js +6 -0
  133. data/lib/capybara/spec/public/test.js +168 -14
  134. data/lib/capybara/spec/session/accept_alert_spec.rb +37 -14
  135. data/lib/capybara/spec/session/accept_confirm_spec.rb +7 -6
  136. data/lib/capybara/spec/session/accept_prompt_spec.rb +38 -10
  137. data/lib/capybara/spec/session/all_spec.rb +179 -59
  138. data/lib/capybara/spec/session/ancestor_spec.rb +88 -0
  139. data/lib/capybara/spec/session/assert_all_of_selectors_spec.rb +140 -0
  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_spec.rb +93 -0
  145. data/lib/capybara/spec/session/attach_file_spec.rb +154 -48
  146. data/lib/capybara/spec/session/body_spec.rb +12 -13
  147. data/lib/capybara/spec/session/check_spec.rb +168 -41
  148. data/lib/capybara/spec/session/choose_spec.rb +75 -23
  149. data/lib/capybara/spec/session/click_button_spec.rb +243 -175
  150. data/lib/capybara/spec/session/click_link_or_button_spec.rb +57 -32
  151. data/lib/capybara/spec/session/click_link_spec.rb +100 -53
  152. data/lib/capybara/spec/session/current_scope_spec.rb +11 -10
  153. data/lib/capybara/spec/session/current_url_spec.rb +61 -35
  154. data/lib/capybara/spec/session/dismiss_confirm_spec.rb +7 -7
  155. data/lib/capybara/spec/session/dismiss_prompt_spec.rb +5 -4
  156. data/lib/capybara/spec/session/element/{assert_match_selector.rb → assert_match_selector_spec.rb} +13 -6
  157. data/lib/capybara/spec/session/element/match_css_spec.rb +21 -7
  158. data/lib/capybara/spec/session/element/match_xpath_spec.rb +9 -7
  159. data/lib/capybara/spec/session/element/matches_selector_spec.rb +91 -34
  160. data/lib/capybara/spec/session/evaluate_async_script_spec.rb +23 -0
  161. data/lib/capybara/spec/session/evaluate_script_spec.rb +45 -3
  162. data/lib/capybara/spec/session/execute_script_spec.rb +24 -4
  163. data/lib/capybara/spec/session/fill_in_spec.rb +166 -64
  164. data/lib/capybara/spec/session/find_button_spec.rb +37 -18
  165. data/lib/capybara/spec/session/find_by_id_spec.rb +10 -9
  166. data/lib/capybara/spec/session/find_field_spec.rb +57 -34
  167. data/lib/capybara/spec/session/find_link_spec.rb +47 -10
  168. data/lib/capybara/spec/session/find_spec.rb +290 -144
  169. data/lib/capybara/spec/session/first_spec.rb +91 -48
  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 +116 -0
  173. data/lib/capybara/spec/session/frame/within_frame_spec.rb +112 -0
  174. data/lib/capybara/spec/session/go_back_spec.rb +3 -2
  175. data/lib/capybara/spec/session/go_forward_spec.rb +3 -2
  176. data/lib/capybara/spec/session/has_all_selectors_spec.rb +69 -0
  177. data/lib/capybara/spec/session/has_ancestor_spec.rb +46 -0
  178. data/lib/capybara/spec/session/has_any_selectors_spec.rb +25 -0
  179. data/lib/capybara/spec/session/has_button_spec.rb +76 -19
  180. data/lib/capybara/spec/session/has_css_spec.rb +277 -131
  181. data/lib/capybara/spec/session/has_current_path_spec.rb +98 -26
  182. data/lib/capybara/spec/session/has_field_spec.rb +177 -107
  183. data/lib/capybara/spec/session/has_link_spec.rb +13 -12
  184. data/lib/capybara/spec/session/has_none_selectors_spec.rb +78 -0
  185. data/lib/capybara/spec/session/has_select_spec.rb +191 -95
  186. data/lib/capybara/spec/session/has_selector_spec.rb +128 -64
  187. data/lib/capybara/spec/session/has_sibling_spec.rb +50 -0
  188. data/lib/capybara/spec/session/has_table_spec.rb +172 -5
  189. data/lib/capybara/spec/session/has_text_spec.rb +126 -60
  190. data/lib/capybara/spec/session/has_title_spec.rb +35 -12
  191. data/lib/capybara/spec/session/has_xpath_spec.rb +74 -53
  192. data/lib/capybara/spec/session/{headers.rb → headers_spec.rb} +3 -2
  193. data/lib/capybara/spec/session/html_spec.rb +14 -6
  194. data/lib/capybara/spec/session/matches_style_spec.rb +35 -0
  195. data/lib/capybara/spec/session/node_spec.rb +1028 -131
  196. data/lib/capybara/spec/session/node_wrapper_spec.rb +39 -0
  197. data/lib/capybara/spec/session/refresh_spec.rb +34 -0
  198. data/lib/capybara/spec/session/reset_session_spec.rb +75 -34
  199. data/lib/capybara/spec/session/{response_code.rb → response_code_spec.rb} +2 -1
  200. data/lib/capybara/spec/session/save_and_open_page_spec.rb +3 -2
  201. data/lib/capybara/spec/session/save_and_open_screenshot_spec.rb +11 -15
  202. data/lib/capybara/spec/session/save_page_spec.rb +42 -55
  203. data/lib/capybara/spec/session/save_screenshot_spec.rb +16 -14
  204. data/lib/capybara/spec/session/screenshot_spec.rb +2 -2
  205. data/lib/capybara/spec/session/scroll_spec.rb +117 -0
  206. data/lib/capybara/spec/session/select_spec.rb +112 -85
  207. data/lib/capybara/spec/session/selectors_spec.rb +71 -8
  208. data/lib/capybara/spec/session/sibling_spec.rb +52 -0
  209. data/lib/capybara/spec/session/text_spec.rb +38 -23
  210. data/lib/capybara/spec/session/title_spec.rb +17 -5
  211. data/lib/capybara/spec/session/uncheck_spec.rb +71 -12
  212. data/lib/capybara/spec/session/unselect_spec.rb +44 -43
  213. data/lib/capybara/spec/session/visit_spec.rb +99 -32
  214. data/lib/capybara/spec/session/window/become_closed_spec.rb +33 -29
  215. data/lib/capybara/spec/session/window/current_window_spec.rb +5 -3
  216. data/lib/capybara/spec/session/window/open_new_window_spec.rb +5 -3
  217. data/lib/capybara/spec/session/window/switch_to_window_spec.rb +39 -30
  218. data/lib/capybara/spec/session/window/window_opened_by_spec.rb +17 -10
  219. data/lib/capybara/spec/session/window/window_spec.rb +121 -73
  220. data/lib/capybara/spec/session/window/windows_spec.rb +12 -10
  221. data/lib/capybara/spec/session/window/within_window_spec.rb +52 -82
  222. data/lib/capybara/spec/session/within_spec.rb +76 -43
  223. data/lib/capybara/spec/spec_helper.rb +67 -33
  224. data/lib/capybara/spec/test_app.rb +85 -36
  225. data/lib/capybara/spec/views/animated.erb +49 -0
  226. data/lib/capybara/spec/views/buttons.erb +1 -1
  227. data/lib/capybara/spec/views/fieldsets.erb +1 -1
  228. data/lib/capybara/spec/views/form.erb +227 -20
  229. data/lib/capybara/spec/views/frame_child.erb +10 -2
  230. data/lib/capybara/spec/views/frame_one.erb +2 -1
  231. data/lib/capybara/spec/views/frame_parent.erb +2 -2
  232. data/lib/capybara/spec/views/frame_two.erb +1 -1
  233. data/lib/capybara/spec/views/header_links.erb +1 -1
  234. data/lib/capybara/spec/views/host_links.erb +1 -1
  235. data/lib/capybara/spec/views/initial_alert.erb +10 -0
  236. data/lib/capybara/spec/views/obscured.erb +47 -0
  237. data/lib/capybara/spec/views/offset.erb +32 -0
  238. data/lib/capybara/spec/views/path.erb +1 -1
  239. data/lib/capybara/spec/views/popup_one.erb +1 -1
  240. data/lib/capybara/spec/views/popup_two.erb +1 -1
  241. data/lib/capybara/spec/views/postback.erb +1 -1
  242. data/lib/capybara/spec/views/react.erb +45 -0
  243. data/lib/capybara/spec/views/scroll.erb +20 -0
  244. data/lib/capybara/spec/views/spatial.erb +31 -0
  245. data/lib/capybara/spec/views/tables.erb +69 -2
  246. data/lib/capybara/spec/views/with_animation.erb +82 -0
  247. data/lib/capybara/spec/views/with_base_tag.erb +1 -1
  248. data/lib/capybara/spec/views/with_count.erb +1 -1
  249. data/lib/capybara/spec/views/with_dragula.erb +24 -0
  250. data/lib/capybara/spec/views/with_fixed_header_footer.erb +17 -0
  251. data/lib/capybara/spec/views/with_hover.erb +7 -1
  252. data/lib/capybara/spec/views/with_hover1.erb +10 -0
  253. data/lib/capybara/spec/views/with_html.erb +100 -10
  254. data/lib/capybara/spec/views/with_html5_svg.erb +20 -0
  255. data/lib/capybara/spec/views/with_html_entities.erb +1 -1
  256. data/lib/capybara/spec/views/with_jquery_animation.erb +24 -0
  257. data/lib/capybara/spec/views/with_js.erb +49 -3
  258. data/lib/capybara/spec/views/with_jstree.erb +26 -0
  259. data/lib/capybara/spec/views/with_namespace.erb +20 -0
  260. data/lib/capybara/spec/views/with_scope.erb +1 -1
  261. data/lib/capybara/spec/views/with_scope_other.erb +6 -0
  262. data/lib/capybara/spec/views/with_simple_html.erb +1 -1
  263. data/lib/capybara/spec/views/with_sortable_js.erb +21 -0
  264. data/lib/capybara/spec/views/with_title.erb +1 -1
  265. data/lib/capybara/spec/views/with_unload_alert.erb +3 -1
  266. data/lib/capybara/spec/views/with_windows.erb +7 -1
  267. data/lib/capybara/spec/views/within_frames.erb +6 -3
  268. data/lib/capybara/version.rb +2 -1
  269. data/lib/capybara/window.rb +39 -21
  270. data/lib/capybara.rb +208 -186
  271. data/spec/basic_node_spec.rb +52 -39
  272. data/spec/capybara_spec.rb +72 -50
  273. data/spec/css_builder_spec.rb +101 -0
  274. data/spec/css_splitter_spec.rb +38 -0
  275. data/spec/dsl_spec.rb +81 -61
  276. data/spec/filter_set_spec.rb +46 -0
  277. data/spec/fixtures/capybara.csv +1 -0
  278. data/spec/fixtures/certificate.pem +25 -0
  279. data/spec/fixtures/key.pem +27 -0
  280. data/spec/fixtures/selenium_driver_rspec_failure.rb +7 -3
  281. data/spec/fixtures/selenium_driver_rspec_success.rb +7 -3
  282. data/spec/minitest_spec.rb +164 -0
  283. data/spec/minitest_spec_spec.rb +162 -0
  284. data/spec/per_session_config_spec.rb +68 -0
  285. data/spec/rack_test_spec.rb +189 -96
  286. data/spec/regexp_dissassembler_spec.rb +250 -0
  287. data/spec/result_spec.rb +143 -13
  288. data/spec/rspec/features_spec.rb +38 -32
  289. data/spec/rspec/scenarios_spec.rb +9 -7
  290. data/spec/rspec/shared_spec_matchers.rb +959 -0
  291. data/spec/rspec/views_spec.rb +9 -3
  292. data/spec/rspec_matchers_spec.rb +62 -0
  293. data/spec/rspec_spec.rb +127 -30
  294. data/spec/sauce_spec_chrome.rb +43 -0
  295. data/spec/selector_spec.rb +458 -37
  296. data/spec/selenium_spec_chrome.rb +196 -9
  297. data/spec/selenium_spec_chrome_remote.rb +100 -0
  298. data/spec/selenium_spec_edge.rb +47 -0
  299. data/spec/selenium_spec_firefox.rb +210 -0
  300. data/spec/selenium_spec_firefox_remote.rb +80 -0
  301. data/spec/selenium_spec_ie.rb +150 -0
  302. data/spec/selenium_spec_safari.rb +148 -0
  303. data/spec/server_spec.rb +200 -101
  304. data/spec/session_spec.rb +91 -0
  305. data/spec/shared_selenium_node.rb +83 -0
  306. data/spec/shared_selenium_session.rb +558 -0
  307. data/spec/spec_helper.rb +94 -2
  308. data/spec/xpath_builder_spec.rb +93 -0
  309. metadata +420 -60
  310. data/lib/capybara/query.rb +0 -7
  311. data/lib/capybara/spec/session/assert_current_path.rb +0 -60
  312. data/lib/capybara/spec/session/assert_selector.rb +0 -148
  313. data/lib/capybara/spec/session/assert_text.rb +0 -196
  314. data/lib/capybara/spec/session/assert_title.rb +0 -70
  315. data/lib/capybara/spec/session/source_spec.rb +0 -0
  316. data/lib/capybara/spec/session/within_frame_spec.rb +0 -53
  317. data/spec/rspec/matchers_spec.rb +0 -827
  318. data/spec/selenium_spec.rb +0 -151
@@ -0,0 +1,93 @@
1
+ # frozen_string_literal: true
2
+
3
+ Capybara::SpecHelper.spec '#assert_title' do
4
+ before do
5
+ @session.visit('/with_js')
6
+ end
7
+
8
+ it "should not raise if the page's title contains the given string" do
9
+ expect do
10
+ @session.assert_title('js')
11
+ end.not_to raise_error
12
+ end
13
+
14
+ it 'should not raise when given an empty string' do
15
+ expect do
16
+ @session.assert_title('')
17
+ end.not_to raise_error
18
+ end
19
+
20
+ it 'should allow regexp matches' do
21
+ expect do
22
+ @session.assert_title(/w[a-z]{3}_js/)
23
+ end.not_to raise_error
24
+
25
+ expect do
26
+ @session.assert_title(/w[a-z]{10}_js/)
27
+ end.to raise_error(Capybara::ExpectationNotMet, 'expected "with_js" to match /w[a-z]{10}_js/')
28
+ end
29
+
30
+ it 'should wait for title', requires: [:js] do
31
+ @session.click_link('Change title')
32
+ expect do
33
+ @session.assert_title('changed title', wait: 3)
34
+ end.not_to raise_error
35
+ end
36
+
37
+ it "should raise error if the title doesn't contain the given string" do
38
+ expect do
39
+ @session.assert_title('monkey')
40
+ end.to raise_error(Capybara::ExpectationNotMet, 'expected "with_js" to include "monkey"')
41
+ end
42
+
43
+ it 'should not normalize given title' do
44
+ @session.visit('/with_js')
45
+ expect { @session.assert_title(' with_js ') }.to raise_error(Capybara::ExpectationNotMet)
46
+ end
47
+
48
+ it 'should match correctly normalized title' do
49
+ uri = Addressable::URI.parse('/with_title')
50
+ uri.query_values = { title: '   with space  title ' }
51
+ @session.visit(uri.to_s)
52
+ @session.assert_title(' with space title')
53
+ expect { @session.assert_title('with space title') }.to raise_error(Capybara::ExpectationNotMet)
54
+ end
55
+
56
+ it 'should not normalize given title in error message' do
57
+ expect do
58
+ @session.assert_title(2)
59
+ end.to raise_error(Capybara::ExpectationNotMet, 'expected "with_js" to include "2"')
60
+ end
61
+ end
62
+
63
+ Capybara::SpecHelper.spec '#assert_no_title' do
64
+ before do
65
+ @session.visit('/with_js')
66
+ end
67
+
68
+ it 'should raise error if the title contains the given string' do
69
+ expect do
70
+ @session.assert_no_title('with_j')
71
+ end.to raise_error(Capybara::ExpectationNotMet, 'expected "with_js" not to include "with_j"')
72
+ end
73
+
74
+ it 'should allow regexp matches' do
75
+ expect do
76
+ @session.assert_no_title(/w[a-z]{3}_js/)
77
+ end.to raise_error(Capybara::ExpectationNotMet, 'expected "with_js" not to match /w[a-z]{3}_js/')
78
+ @session.assert_no_title(/monkey/)
79
+ end
80
+
81
+ it 'should wait for title to disappear', requires: [:js] do
82
+ @session.click_link('Change title')
83
+ expect do
84
+ @session.assert_no_title('with_js', wait: 3)
85
+ end.not_to raise_error
86
+ end
87
+
88
+ it "should not raise if the title doesn't contain the given string" do
89
+ expect do
90
+ @session.assert_no_title('monkey')
91
+ end.not_to raise_error
92
+ end
93
+ end
@@ -1,110 +1,216 @@
1
1
  # frozen_string_literal: true
2
- Capybara::SpecHelper.spec "#attach_file" do
2
+
3
+ Capybara::SpecHelper.spec '#attach_file' do
4
+ let(:test_file_path) { File.expand_path('../fixtures/test_file.txt', File.dirname(__FILE__)) }
5
+ let(:another_test_file_path) { File.expand_path('../fixtures/another_test_file.txt', File.dirname(__FILE__)) }
6
+ let(:test_jpg_file_path) { File.expand_path('../fixtures/capybara.jpg', File.dirname(__FILE__)) }
7
+ let(:no_extension_file_path) { File.expand_path('../fixtures/no_extension', File.dirname(__FILE__)) }
8
+
3
9
  before do
4
- @test_file_path = File.expand_path('../fixtures/test_file.txt', File.dirname(__FILE__))
5
- @another_test_file_path = File.expand_path('../fixtures/another_test_file.txt', File.dirname(__FILE__))
6
- @test_jpg_file_path = File.expand_path('../fixtures/capybara.jpg', File.dirname(__FILE__))
7
10
  @session.visit('/form')
8
11
  end
9
12
 
10
- context "with normal form" do
11
- it "should set a file path by id" do
12
- @session.attach_file "form_image", __FILE__
13
+ context 'with normal form' do
14
+ it 'should set a file path by id' do
15
+ @session.attach_file 'form_image', with_os_path_separators(__FILE__)
16
+ @session.click_button('awesome')
17
+ expect(extract_results(@session)['image']).to end_with(File.basename(__FILE__))
18
+ end
19
+
20
+ it 'should set a file path by label' do
21
+ @session.attach_file 'Image', with_os_path_separators(__FILE__)
13
22
  @session.click_button('awesome')
14
- expect(extract_results(@session)['image']).to eq(File.basename(__FILE__))
23
+ expect(extract_results(@session)['image']).to end_with(File.basename(__FILE__))
15
24
  end
16
25
 
17
- it "should set a file path by label" do
18
- @session.attach_file "Image", __FILE__
26
+ it 'should be able to set on element if no locator passed' do
27
+ ff = @session.find(:file_field, 'Image')
28
+ ff.attach_file(with_os_path_separators(__FILE__))
19
29
  @session.click_button('awesome')
20
- expect(extract_results(@session)['image']).to eq(File.basename(__FILE__))
30
+ expect(extract_results(@session)['image']).to end_with(File.basename(__FILE__))
21
31
  end
22
32
 
23
- it "casts to string" do
24
- @session.attach_file :"form_image", __FILE__
33
+ it 'casts to string' do
34
+ @session.attach_file :form_image, with_os_path_separators(__FILE__)
25
35
  @session.click_button('awesome')
26
- expect(extract_results(@session)['image']).to eq(File.basename(__FILE__))
36
+ expect(extract_results(@session)['image']).to end_with(File.basename(__FILE__))
27
37
  end
28
38
  end
29
39
 
30
- context "with multipart form" do
31
- it "should set a file path by id" do
32
- @session.attach_file "form_document", @test_file_path
40
+ context 'with multipart form' do
41
+ it 'should set a file path by id' do
42
+ @session.attach_file 'form_document', with_os_path_separators(test_file_path)
33
43
  @session.click_button('Upload Single')
34
- expect(@session).to have_content(File.read(@test_file_path))
44
+ expect(@session).to have_content(File.read(test_file_path))
35
45
  end
36
46
 
37
- it "should set a file path by label" do
38
- @session.attach_file "Single Document", @test_file_path
47
+ it 'should set a file path by label' do
48
+ @session.attach_file 'Single Document', with_os_path_separators(test_file_path)
39
49
  @session.click_button('Upload Single')
40
- expect(@session).to have_content(File.read(@test_file_path))
50
+ expect(@session).to have_content(File.read(test_file_path))
41
51
  end
42
52
 
43
- it "should not break if no file is submitted" do
53
+ it 'should not break if no file is submitted' do
44
54
  @session.click_button('Upload Single')
45
55
  expect(@session).to have_content('No file uploaded')
46
56
  end
47
57
 
48
- it "should send content type text/plain when uploading a text file" do
49
- @session.attach_file "Single Document", @test_file_path
58
+ it 'should send content type text/plain when uploading a text file' do
59
+ @session.attach_file 'Single Document', with_os_path_separators(test_file_path)
50
60
  @session.click_button 'Upload Single'
51
61
  expect(@session).to have_content('text/plain')
52
62
  end
53
63
 
54
- it "should send content type image/jpeg when uploading an image" do
55
- @session.attach_file "Single Document", @test_jpg_file_path
64
+ it 'should send content type image/jpeg when uploading an image' do
65
+ @session.attach_file 'Single Document', with_os_path_separators(test_jpg_file_path)
56
66
  @session.click_button 'Upload Single'
57
67
  expect(@session).to have_content('image/jpeg')
58
68
  end
59
69
 
60
- it "should not break when using HTML5 multiple file input" do
61
- @session.attach_file "Multiple Documents", @test_file_path
70
+ it 'should not break when uploading a file without extension' do
71
+ @session.attach_file 'Single Document', with_os_path_separators(no_extension_file_path)
72
+ @session.click_button 'Upload Single'
73
+ expect(@session).to have_content(File.read(no_extension_file_path))
74
+ end
75
+
76
+ it 'should not break when using HTML5 multiple file input' do
77
+ @session.attach_file 'Multiple Documents', with_os_path_separators(test_file_path)
62
78
  @session.click_button('Upload Multiple')
63
- expect(@session).to have_content(File.read(@test_file_path))
64
- expect(@session.body).to include("1 | ")#number of files
79
+ expect(@session).to have_content(File.read(test_file_path))
80
+ expect(@session.body).to include('1 | ') # number of files
65
81
  end
66
82
 
67
- it "should not break when using HTML5 multiple file input uploading multiple files" do
68
- pending "Selenium is buggy on this, see http://code.google.com/p/selenium/issues/detail?id=2239" if @session.respond_to?(:mode) && @session.mode.to_s =~ /^selenium/
69
- @session.attach_file "Multiple Documents", [@test_file_path, @another_test_file_path]
83
+ it 'should not break when using HTML5 multiple file input uploading multiple files' do
84
+ @session.attach_file('Multiple Documents',
85
+ [test_file_path, another_test_file_path].map { |f| with_os_path_separators(f) })
70
86
  @session.click_button('Upload Multiple')
71
- expect(@session.body).to include("2 | ")#number of files
72
- expect(@session.body).to include(File.read(@test_file_path))
73
- expect(@session.body).to include(File.read(@another_test_file_path))
87
+ expect(@session).to have_content('2 | ') # number of files
88
+ expect(@session.body).to include(File.read(test_file_path))
89
+ expect(@session.body).to include(File.read(another_test_file_path))
74
90
  end
75
91
 
76
- it "should not send anything when attaching no files to a multiple upload field" do
92
+ it 'should not send anything when attaching no files to a multiple upload field' do
77
93
  @session.click_button('Upload Empty Multiple')
78
- expect(@session).to have_content("Successfully ignored empty file field")
94
+ expect(@session).to have_content('Successfully ignored empty file field')
95
+ end
96
+
97
+ it 'should not append files to already attached' do
98
+ @session.attach_file 'Multiple Documents', with_os_path_separators(test_file_path)
99
+ @session.attach_file 'Multiple Documents', with_os_path_separators(another_test_file_path)
100
+ @session.click_button('Upload Multiple')
101
+ expect(@session).to have_content('1 | ') # number of files
102
+ expect(@session.body).to include(File.read(another_test_file_path))
103
+ expect(@session.body).not_to include(File.read(test_file_path))
104
+ end
105
+
106
+ it 'should fire change once when uploading multiple files from empty', requires: [:js] do
107
+ @session.visit('with_js')
108
+ @session.attach_file('multiple-file',
109
+ [test_file_path, another_test_file_path].map { |f| with_os_path_separators(f) })
110
+ expect(@session).to have_css('.file_change', count: 1)
111
+ end
112
+
113
+ it 'should fire change once for each set of files uploaded', requires: [:js] do
114
+ @session.visit('with_js')
115
+ @session.attach_file('multiple-file', [test_jpg_file_path].map { |f| with_os_path_separators(f) })
116
+ @session.attach_file('multiple-file',
117
+ [test_file_path, another_test_file_path].map { |f| with_os_path_separators(f) })
118
+ expect(@session).to have_css('.file_change', count: 2)
79
119
  end
80
120
  end
81
121
 
82
122
  context "with a locator that doesn't exist" do
83
- it "should raise an error" do
84
- msg = "Unable to find file field \"does not exist\""
123
+ it 'should raise an error' do
124
+ msg = /Unable to find file field "does not exist"/
85
125
  expect do
86
- @session.attach_file('does not exist', @test_file_path)
126
+ @session.attach_file('does not exist', with_os_path_separators(test_file_path))
87
127
  end.to raise_error(Capybara::ElementNotFound, msg)
88
128
  end
89
129
  end
90
130
 
91
131
  context "with a path that doesn't exist" do
92
- it "should raise an error" do
132
+ it 'should raise an error' do
93
133
  expect { @session.attach_file('Image', '/no_such_file.png') }.to raise_error(Capybara::FileNotFound)
94
134
  end
95
135
  end
96
136
 
97
- context "with :exact option" do
98
- it "should set a file path by partial label when false" do
99
- @session.attach_file "Imag", __FILE__, :exact => false
137
+ context 'with :exact option' do
138
+ it 'should set a file path by partial label when false' do
139
+ @session.attach_file 'Imag', with_os_path_separators(__FILE__), exact: false
100
140
  @session.click_button('awesome')
101
- expect(extract_results(@session)['image']).to eq(File.basename(__FILE__))
141
+ expect(extract_results(@session)['image']).to end_with(File.basename(__FILE__))
102
142
  end
103
143
 
104
- it "not allow partial matches when true" do
144
+ it 'should not allow partial matches when true' do
105
145
  expect do
106
- @session.attach_file "Imag", __FILE__, :exact => true
146
+ @session.attach_file 'Imag', with_os_path_separators(__FILE__), exact: true
107
147
  end.to raise_error(Capybara::ElementNotFound)
108
148
  end
109
149
  end
150
+
151
+ context 'with :make_visible option', requires: %i[js es_args] do
152
+ it 'applies a default style change when true' do
153
+ @session.visit('/with_js')
154
+ expect do
155
+ @session.attach_file('hidden_file', with_os_path_separators(__FILE__))
156
+ end.to raise_error Capybara::ElementNotFound
157
+ expect do
158
+ @session.attach_file('hidden_file', with_os_path_separators(__FILE__), make_visible: true)
159
+ end.not_to raise_error
160
+ end
161
+
162
+ it 'accepts a hash of styles to be applied' do
163
+ @session.visit('/with_js')
164
+ expect do
165
+ @session.attach_file('hidden_file',
166
+ with_os_path_separators(__FILE__),
167
+ make_visible: { opacity: 1, display: 'block' })
168
+ end.not_to raise_error
169
+ end
170
+
171
+ it 'raises an error when the file input is not made visible' do
172
+ @session.visit('/with_js')
173
+ expect do
174
+ @session.attach_file('hidden_file', with_os_path_separators(__FILE__), make_visible: { color: 'red' })
175
+ end.to raise_error(Capybara::ExpectationNotMet)
176
+ end
177
+
178
+ it 'resets the style when done' do
179
+ @session.visit('/with_js')
180
+ @session.attach_file('hidden_file', with_os_path_separators(__FILE__), make_visible: true)
181
+ expect(@session.evaluate_script('arguments[0].style.display', @session.find(:css, '#hidden_file', visible: :all))).to eq 'none'
182
+ end
183
+
184
+ it 'should fire change' do
185
+ @session.visit('/with_js')
186
+ @session.attach_file('hidden_file', with_os_path_separators(__FILE__), make_visible: true)
187
+ expect(@session).to have_css('.file_change')
188
+ end
189
+ end
190
+
191
+ context 'with a block', requires: %i[js] do
192
+ it 'can upload by clicking the file input' do
193
+ @session.attach_file(with_os_path_separators(__FILE__)) do
194
+ @session.find(:file_field, 'form[image]').click
195
+ end
196
+ @session.click_button('awesome')
197
+ expect(extract_results(@session)['image']).to end_with(File.basename(__FILE__))
198
+ end
199
+
200
+ it 'can upload by clicking the label' do
201
+ @session.attach_file(with_os_path_separators(__FILE__)) do
202
+ @session.find(:label, 'Hidden Image').click
203
+ end
204
+ @session.click_button('awesome')
205
+ expect(extract_results(@session)['hidden_image']).to end_with(File.basename(__FILE__))
206
+ end
207
+
208
+ it 'should fire change' do
209
+ @session.visit('/with_js')
210
+ @session.attach_file(with_os_path_separators(__FILE__)) do
211
+ @session.find(:label, 'Label for hidden file input').click
212
+ end
213
+ expect(@session).to have_css('.file_change')
214
+ end
215
+ end
110
216
  end
@@ -1,24 +1,23 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  Capybara::SpecHelper.spec '#body' do
3
- it "should return the unmodified page body" do
4
+ it 'should return the unmodified page body' do
4
5
  @session.visit('/')
5
6
  expect(@session).to have_content('Hello world!') # wait for content to appear if visit is async
6
7
  expect(@session.body).to include('Hello world!')
7
8
  end
8
9
 
9
- if "".respond_to?(:encoding)
10
- context "encoding of response between ascii and utf8" do
11
- it "should be valid with html entities" do
12
- @session.visit('/with_html_entities')
13
- expect(@session).to have_content('Encoding') # wait for content to appear if visit is async
14
- expect { @session.body.encode!("UTF-8") }.not_to raise_error
15
- end
10
+ context 'encoding of response between ascii and utf8' do
11
+ it 'should be valid with html entities' do
12
+ @session.visit('/with_html_entities')
13
+ expect(@session).to have_content('Encoding') # wait for content to appear if visit is async
14
+ expect { @session.body.encode!('UTF-8') }.not_to raise_error
15
+ end
16
16
 
17
- it "should be valid without html entities" do
18
- @session.visit('/with_html')
19
- expect(@session).to have_content('This is a test') # wait for content to appear if visit is async
20
- expect { @session.body.encode!("UTF-8") }.not_to raise_error
21
- end
17
+ it 'should be valid without html entities' do
18
+ @session.visit('/with_html')
19
+ expect(@session).to have_content('This is a test') # wait for content to appear if visit is async
20
+ expect { @session.body.encode!('UTF-8') }.not_to raise_error
22
21
  end
23
22
  end
24
23
  end
@@ -1,114 +1,241 @@
1
1
  # frozen_string_literal: true
2
- Capybara::SpecHelper.spec "#check" do
2
+
3
+ Capybara::SpecHelper.spec '#check' do
3
4
  before do
4
5
  @session.visit('/form')
5
6
  end
6
7
 
7
8
  describe "'checked' attribute" do
8
- it "should be true if checked" do
9
- @session.check("Terms of Use")
9
+ it 'should be true if checked' do
10
+ @session.check('Terms of Use')
10
11
  expect(@session.find(:xpath, "//input[@id='form_terms_of_use']")['checked']).to be_truthy
11
12
  end
12
13
 
13
- it "should be false if unchecked" do
14
+ it 'should be false if unchecked' do
14
15
  expect(@session.find(:xpath, "//input[@id='form_terms_of_use']")['checked']).to be_falsey
15
16
  end
16
17
  end
17
18
 
18
- it "should trigger associated events", :requires => [:js] do
19
+ it 'should trigger associated events', requires: [:js] do
19
20
  @session.visit('/with_js')
20
21
  @session.check('checkbox_with_event')
21
- expect(@session).to have_css('#checkbox_event_triggered');
22
+ expect(@session).to have_css('#checkbox_event_triggered')
22
23
  end
23
24
 
24
- describe "checking" do
25
- it "should not change an already checked checkbox" do
26
- expect(@session.find(:xpath, "//input[@id='form_pets_dog']")['checked']).to be_truthy
25
+ describe 'checking' do
26
+ it 'should not change an already checked checkbox' do
27
+ expect(@session.find(:xpath, "//input[@id='form_pets_dog']")).to be_checked
27
28
  @session.check('form_pets_dog')
28
- expect(@session.find(:xpath, "//input[@id='form_pets_dog']")['checked']).to be_truthy
29
+ expect(@session.find(:xpath, "//input[@id='form_pets_dog']")).to be_checked
29
30
  end
30
31
 
31
- it "should check an unchecked checkbox" do
32
- expect(@session.find(:xpath, "//input[@id='form_pets_cat']")['checked']).to be_falsey
32
+ it 'should check an unchecked checkbox' do
33
+ expect(@session.find(:xpath, "//input[@id='form_pets_cat']")).not_to be_checked
33
34
  @session.check('form_pets_cat')
34
- expect(@session.find(:xpath, "//input[@id='form_pets_cat']")['checked']).to be_truthy
35
+ expect(@session.find(:xpath, "//input[@id='form_pets_cat']")).to be_checked
35
36
  end
36
37
  end
37
38
 
38
- describe "unchecking" do
39
- it "should not change an already unchecked checkbox" do
40
- expect(@session.find(:xpath, "//input[@id='form_pets_cat']")['checked']).to be_falsey
39
+ describe 'unchecking' do
40
+ it 'should not change an already unchecked checkbox' do
41
+ expect(@session.find(:xpath, "//input[@id='form_pets_cat']")).not_to be_checked
41
42
  @session.uncheck('form_pets_cat')
42
- expect(@session.find(:xpath, "//input[@id='form_pets_cat']")['checked']).to be_falsey
43
+ expect(@session.find(:xpath, "//input[@id='form_pets_cat']")).not_to be_checked
43
44
  end
44
45
 
45
- it "should uncheck a checked checkbox" do
46
- expect(@session.find(:xpath, "//input[@id='form_pets_dog']")['checked']).to be_truthy
46
+ it 'should uncheck a checked checkbox' do
47
+ expect(@session.find(:xpath, "//input[@id='form_pets_dog']")).to be_checked
47
48
  @session.uncheck('form_pets_dog')
48
- expect(@session.find(:xpath, "//input[@id='form_pets_dog']")['checked']).to be_falsey
49
+ expect(@session.find(:xpath, "//input[@id='form_pets_dog']")).not_to be_checked
49
50
  end
50
51
  end
51
52
 
52
- it "should check a checkbox by id" do
53
- @session.check("form_pets_cat")
53
+ it 'should check a checkbox by id' do
54
+ @session.check('form_pets_cat')
55
+ @session.click_button('awesome')
56
+ expect(extract_results(@session)['pets']).to include('dog', 'cat', 'hamster')
57
+ end
58
+
59
+ it 'should check a checkbox by label' do
60
+ @session.check('Cat')
54
61
  @session.click_button('awesome')
55
62
  expect(extract_results(@session)['pets']).to include('dog', 'cat', 'hamster')
56
63
  end
57
64
 
58
- it "should check a checkbox by label" do
59
- @session.check("Cat")
65
+ it 'should work without a locator string' do
66
+ @session.check(id: 'form_pets_cat')
60
67
  @session.click_button('awesome')
61
68
  expect(extract_results(@session)['pets']).to include('dog', 'cat', 'hamster')
62
69
  end
63
70
 
64
- it "casts to string" do
65
- @session.check(:"form_pets_cat")
71
+ it 'should be able to check itself if no locator specified' do
72
+ cb = @session.find(:id, 'form_pets_cat')
73
+ cb.check
74
+ @session.click_button('awesome')
75
+ expect(extract_results(@session)['pets']).to include('dog', 'cat', 'hamster')
76
+ end
77
+
78
+ it 'casts to string' do
79
+ @session.check(:form_pets_cat)
66
80
  @session.click_button('awesome')
67
81
  expect(extract_results(@session)['pets']).to include('dog', 'cat', 'hamster')
68
82
  end
69
83
 
70
84
  context "with a locator that doesn't exist" do
71
- it "should raise an error" do
72
- msg = "Unable to find checkbox \"does not exist\""
85
+ it 'should raise an error' do
86
+ msg = /Unable to find checkbox "does not exist"/
73
87
  expect do
74
88
  @session.check('does not exist')
75
89
  end.to raise_error(Capybara::ElementNotFound, msg)
76
90
  end
77
91
  end
78
92
 
79
- context "with a disabled checkbox" do
80
- it "should raise an error" do
93
+ context 'with a disabled checkbox' do
94
+ it 'should raise an error' do
95
+ msg = 'Unable to find visible checkbox "Disabled Checkbox" that is not disabled'
81
96
  expect do
82
97
  @session.check('Disabled Checkbox')
83
- end.to raise_error(Capybara::ElementNotFound)
98
+ end.to raise_error(Capybara::ElementNotFound, msg)
84
99
  end
85
100
  end
86
101
 
87
- context "with :exact option" do
88
- it "should accept partial matches when false" do
89
- @session.check('Ham', :exact => false)
102
+ context 'with :exact option' do
103
+ it 'should accept partial matches when false' do
104
+ @session.check('Ham', exact: false)
90
105
  @session.click_button('awesome')
91
106
  expect(extract_results(@session)['pets']).to include('hamster')
92
107
  end
93
108
 
94
- it "should not accept partial matches when true" do
109
+ it 'should not accept partial matches when true' do
95
110
  expect do
96
- @session.check('Ham', :exact => true)
111
+ @session.check('Ham', exact: true)
97
112
  end.to raise_error(Capybara::ElementNotFound)
98
113
  end
99
114
  end
100
115
 
101
- context "with `option` option" do
102
- it "can check boxes by their value" do
103
- @session.check('form[pets][]', :option => "cat")
116
+ context 'with `option` option' do
117
+ it 'can check boxes by their value' do
118
+ @session.check('form[pets][]', option: 'cat')
119
+ @session.click_button('awesome')
120
+ expect(extract_results(@session)['pets']).to include('cat')
121
+ end
122
+
123
+ it 'should alias `with`' do
124
+ @session.check('form[pets][]', with: 'cat')
104
125
  @session.click_button('awesome')
105
126
  expect(extract_results(@session)['pets']).to include('cat')
106
127
  end
107
128
 
108
- it "should raise an error if option not found" do
129
+ it 'should raise an error if option not found' do
109
130
  expect do
110
- @session.check('form[pets][]', :option => "elephant")
131
+ @session.check('form[pets][]', option: 'elephant')
111
132
  end.to raise_error(Capybara::ElementNotFound)
112
133
  end
113
134
  end
135
+
136
+ context 'when checkbox hidden' do
137
+ context 'with Capybara.automatic_label_click == true' do
138
+ around do |spec|
139
+ old_click_label, Capybara.automatic_label_click = Capybara.automatic_label_click, true
140
+ spec.run
141
+ Capybara.automatic_label_click = old_click_label
142
+ end
143
+
144
+ it 'should check via clicking the label with :for attribute if possible' do
145
+ expect(@session.find(:checkbox, 'form_cars_tesla', unchecked: true, visible: :hidden)).to be_truthy
146
+ @session.check('form_cars_tesla')
147
+ @session.click_button('awesome')
148
+ expect(extract_results(@session)['cars']).to include('tesla')
149
+ end
150
+
151
+ it 'should check via clicking the wrapping label if possible' do
152
+ expect(@session.find(:checkbox, 'form_cars_mclaren', unchecked: true, visible: :hidden)).to be_truthy
153
+ @session.check('form_cars_mclaren')
154
+ @session.click_button('awesome')
155
+ expect(extract_results(@session)['cars']).to include('mclaren')
156
+ end
157
+
158
+ it 'should check via clicking the label with :for attribute if locator nil' do
159
+ cb = @session.find(:checkbox, 'form_cars_tesla', unchecked: true, visible: :hidden)
160
+ cb.check
161
+ @session.click_button('awesome')
162
+ expect(extract_results(@session)['cars']).to include('tesla')
163
+ end
164
+
165
+ it 'should check self via clicking the wrapping label if locator nil' do
166
+ cb = @session.find(:checkbox, 'form_cars_mclaren', unchecked: true, visible: :hidden)
167
+ cb.check
168
+ @session.click_button('awesome')
169
+ expect(extract_results(@session)['cars']).to include('mclaren')
170
+ end
171
+
172
+ it 'should not click the label if unneeded' do
173
+ expect(@session.find(:checkbox, 'form_cars_jaguar', checked: true, visible: :hidden)).to be_truthy
174
+ @session.check('form_cars_jaguar')
175
+ @session.click_button('awesome')
176
+ expect(extract_results(@session)['cars']).to include('jaguar')
177
+ end
178
+
179
+ it 'should raise original error when no label available' do
180
+ expect { @session.check('form_cars_ariel') }.to raise_error(Capybara::ElementNotFound, /Unable to find visible checkbox "form_cars_ariel"/)
181
+ end
182
+
183
+ it 'should raise error if not allowed to click label' do
184
+ expect { @session.check('form_cars_mclaren', allow_label_click: false) }.to raise_error(Capybara::ElementNotFound, /Unable to find visible checkbox "form_cars_mclaren"/)
185
+ end
186
+ end
187
+
188
+ context 'with Capybara.automatic_label_click == false' do
189
+ around do |spec|
190
+ old_label_click, Capybara.automatic_label_click = Capybara.automatic_label_click, false
191
+ spec.run
192
+ Capybara.automatic_label_click = old_label_click
193
+ end
194
+
195
+ it 'should raise error if checkbox not visible' do
196
+ expect { @session.check('form_cars_mclaren') }.to raise_error(Capybara::ElementNotFound, /Unable to find visible checkbox "form_cars_mclaren"/)
197
+ end
198
+
199
+ it 'should include node filter in error if verified' do
200
+ expect { @session.check('form_cars_maserati') }.to raise_error(Capybara::ElementNotFound, 'Unable to find visible checkbox "form_cars_maserati" that is not disabled')
201
+ end
202
+
203
+ context 'with allow_label_click == true' do
204
+ it 'should check via the label if input is hidden' do
205
+ expect(@session.find(:checkbox, 'form_cars_tesla', unchecked: true, visible: :hidden)).to be_truthy
206
+ @session.check('form_cars_tesla', allow_label_click: true)
207
+ @session.click_button('awesome')
208
+ expect(extract_results(@session)['cars']).to include('tesla')
209
+ end
210
+
211
+ it 'should not wait the full time if label can be clicked' do
212
+ expect(@session.find(:checkbox, 'form_cars_tesla', unchecked: true, visible: :hidden)).to be_truthy
213
+ start_time = Time.now
214
+ @session.check('form_cars_tesla', allow_label_click: true, wait: 10)
215
+ end_time = Time.now
216
+ expect(end_time - start_time).to be < 10
217
+ end
218
+
219
+ it 'should check via the label if input is moved off the left edge of the page' do
220
+ expect(@session.find(:checkbox, 'form_cars_pagani', unchecked: true, visible: :all)).to be_truthy
221
+ @session.check('form_cars_pagani', allow_label_click: true)
222
+ @session.click_button('awesome')
223
+ expect(extract_results(@session)['cars']).to include('pagani')
224
+ end
225
+
226
+ it 'should check via the label if input is visible but blocked by another element' do
227
+ expect(@session.find(:checkbox, 'form_cars_bugatti', unchecked: true, visible: :all)).to be_truthy
228
+ @session.check('form_cars_bugatti', allow_label_click: true)
229
+ @session.click_button('awesome')
230
+ expect(extract_results(@session)['cars']).to include('bugatti')
231
+ end
232
+
233
+ it 'should check via label if multiple labels' do
234
+ expect(@session).to have_field('multi_label_checkbox', checked: false, visible: :hidden)
235
+ @session.check('Label to click', allow_label_click: true)
236
+ expect(@session).to have_field('multi_label_checkbox', checked: true, visible: :hidden)
237
+ end
238
+ end
239
+ end
240
+ end
114
241
  end