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
@@ -1,16 +1,29 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  Capybara::SpecHelper.spec '#find_button' do
3
4
  before do
4
5
  @session.visit('/form')
5
6
  end
6
7
 
7
- it "should find any button" do
8
- expect(@session.find_button('med')[:id]).to eq("mediocre")
9
- expect(@session.find_button('crap321').value).to eq("crappy")
8
+ it 'should find any button' do
9
+ expect(@session.find_button('med')[:id]).to eq('mediocre')
10
+ expect(@session.find_button('crap321').value).to eq('crappy')
10
11
  end
11
12
 
12
- it "casts to string" do
13
- expect(@session.find_button(:'med')[:id]).to eq("mediocre")
13
+ context 'aria_label attribute with Capybara.enable_aria_label' do
14
+ it 'should find when true' do
15
+ Capybara.enable_aria_label = true
16
+ expect(@session.find_button('Mediocre Button')[:id]).to eq('mediocre')
17
+ end
18
+
19
+ it 'should not find when false' do
20
+ Capybara.enable_aria_label = false
21
+ expect { @session.find_button('Mediocre Button') }.to raise_error(Capybara::ElementNotFound)
22
+ end
23
+ end
24
+
25
+ it 'casts to string' do
26
+ expect(@session.find_button(:med)[:id]).to eq('mediocre')
14
27
  end
15
28
 
16
29
  it "should raise error if the button doesn't exist" do
@@ -19,37 +32,43 @@ Capybara::SpecHelper.spec '#find_button' do
19
32
  end.to raise_error(Capybara::ElementNotFound)
20
33
  end
21
34
 
22
- context "with :exact option" do
23
- it "should accept partial matches when false" do
24
- expect(@session.find_button('What an Awesome', :exact => false)[:value]).to eq("awesome")
35
+ context 'with :exact option' do
36
+ it 'should accept partial matches when false' do
37
+ expect(@session.find_button('What an Awesome', exact: false).value).to eq('awesome')
25
38
  end
26
39
 
27
- it "should not accept partial matches when true" do
40
+ it 'should not accept partial matches when true' do
28
41
  expect do
29
- @session.find_button('What an Awesome', :exact => true)
42
+ @session.find_button('What an Awesome', exact: true)
30
43
  end.to raise_error(Capybara::ElementNotFound)
31
44
  end
32
45
  end
33
46
 
34
- context "with :disabled option" do
35
- it "should find disabled buttons when true" do
36
- expect(@session.find_button('Disabled button', :disabled => true).value).to eq("Disabled button")
47
+ context 'with :disabled option' do
48
+ it 'should find disabled buttons when true' do
49
+ expect(@session.find_button('Disabled button', disabled: true).value).to eq('Disabled button')
37
50
  end
38
51
 
39
- it "should not find disabled buttons when false" do
52
+ it 'should not find disabled buttons when false' do
40
53
  expect do
41
- @session.find_button('Disabled button', :disabled => false)
54
+ @session.find_button('Disabled button', disabled: false)
42
55
  end.to raise_error(Capybara::ElementNotFound)
43
56
  end
44
57
 
45
- it "should default to not finding disabled buttons" do
58
+ it 'should default to not finding disabled buttons' do
46
59
  expect do
47
60
  @session.find_button('Disabled button')
48
61
  end.to raise_error(Capybara::ElementNotFound)
49
62
  end
50
63
 
51
- it "should find disabled buttons when :all" do
52
- expect(@session.find_button('Disabled button', :disabled => :all).value).to eq("Disabled button")
64
+ it 'should find disabled buttons when :all' do
65
+ expect(@session.find_button('Disabled button', disabled: :all).value).to eq('Disabled button')
66
+ end
67
+ end
68
+
69
+ context 'without locator' do
70
+ it 'should use options' do
71
+ expect(@session.find_button(disabled: true).value).to eq('Disabled button')
53
72
  end
54
73
  end
55
74
  end
@@ -1,31 +1,32 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  Capybara::SpecHelper.spec '#find_by_id' do
3
4
  before do
4
5
  @session.visit('/with_html')
5
6
  end
6
7
 
7
- it "should find any element by id" do
8
+ it 'should find any element by id' do
8
9
  expect(@session.find_by_id('red').tag_name).to eq('a')
9
10
  end
10
11
 
11
- it "casts to string" do
12
- expect(@session.find_by_id(:'red').tag_name).to eq('a')
12
+ it 'casts to string' do
13
+ expect(@session.find_by_id(:red).tag_name).to eq('a')
13
14
  end
14
15
 
15
- it "should raise error if no element with id is found" do
16
+ it 'should raise error if no element with id is found' do
16
17
  expect do
17
18
  @session.find_by_id('nothing_with_this_id')
18
19
  end.to raise_error(Capybara::ElementNotFound)
19
20
  end
20
21
 
21
- context "with :visible option" do
22
- it "finds invisible elements when `false`" do
23
- expect(@session.find_by_id("hidden_via_ancestor", :visible => false).text(:all)).to match(/with hidden ancestor/)
22
+ context 'with :visible option' do
23
+ it 'finds invisible elements when `false`' do
24
+ expect(@session.find_by_id('hidden_via_ancestor', visible: false).text(:all)).to match(/with hidden ancestor/)
24
25
  end
25
26
 
26
- it "finds invisible elements when `false`" do
27
+ it "doesn't find invisible elements when `true`" do
27
28
  expect do
28
- @session.find_by_id("hidden_via_ancestor", :visible => true)
29
+ @session.find_by_id('hidden_via_ancestor', visible: true)
29
30
  end.to raise_error(Capybara::ElementNotFound)
30
31
  end
31
32
  end
@@ -1,17 +1,35 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  Capybara::SpecHelper.spec '#find_field' do
3
4
  before do
4
5
  @session.visit('/form')
5
6
  end
6
7
 
7
- it "should find any field" do
8
+ it 'should find any field' do
9
+ Capybara.test_id = 'data-test-id'
8
10
  expect(@session.find_field('Dog').value).to eq('dog')
9
- expect(@session.find_field('form_description').text).to eq('Descriptive text goes here')
11
+ expect(@session.find_field('form_description').value).to eq('Descriptive text goes here')
10
12
  expect(@session.find_field('Region')[:name]).to eq('form[region]')
13
+ expect(@session.find_field('With Asterisk*')).to be_truthy
14
+ expect(@session.find_field('my_test_id')).to be_truthy
15
+ end
16
+
17
+ context 'aria_label attribute with Capybara.enable_aria_label' do
18
+ it 'should find when true' do
19
+ Capybara.enable_aria_label = true
20
+ expect(@session.find_field('Unlabelled Input')[:name]).to eq('form[which_form]')
21
+ # expect(@session.find_field('Emergency Number')[:id]).to eq('html5_tel')
22
+ end
23
+
24
+ it 'should not find when false' do
25
+ Capybara.enable_aria_label = false
26
+ expect { @session.find_field('Unlabelled Input') }.to raise_error(Capybara::ElementNotFound)
27
+ # expect { @session.find_field('Emergency Number') }.to raise_error(Capybara::ElementNotFound)
28
+ end
11
29
  end
12
30
 
13
- it "casts to string" do
14
- expect(@session.find_field(:'Dog').value).to eq('dog')
31
+ it 'casts to string' do
32
+ expect(@session.find_field(:Dog).value).to eq('dog')
15
33
  end
16
34
 
17
35
  it "should raise error if the field doesn't exist" do
@@ -20,71 +38,76 @@ Capybara::SpecHelper.spec '#find_field' do
20
38
  end.to raise_error(Capybara::ElementNotFound)
21
39
  end
22
40
 
23
- it "should warn if filter option is invalid" do
24
- expect_any_instance_of(Kernel).to receive(:warn).
25
- with('Invalid value nil passed to filter disabled - defaulting to false')
26
- @session.find_field('Dog', disabled: nil)
27
- end
28
-
29
- it "should be aliased as 'field_labeled' for webrat compatibility" do
30
- expect(@session.field_labeled('Dog').value).to eq('dog')
41
+ it 'should raise error if filter option is invalid' do
31
42
  expect do
32
- @session.field_labeled('Does not exist')
33
- end.to raise_error(Capybara::ElementNotFound)
43
+ @session.find_field('Dog', disabled: nil)
44
+ end.to raise_error ArgumentError, 'Invalid value nil passed to NodeFilter disabled'
34
45
  end
35
46
 
36
- context "with :exact option" do
37
- it "should accept partial matches when false" do
38
- expect(@session.find_field("Explanation", :exact => false)[:name]).to eq("form[name_explanation]")
47
+ context 'with :exact option' do
48
+ it 'should accept partial matches when false' do
49
+ expect(@session.find_field('Explanation', exact: false)[:name]).to eq('form[name_explanation]')
39
50
  end
40
51
 
41
- it "should not accept partial matches when true" do
52
+ it 'should not accept partial matches when true' do
42
53
  expect do
43
- @session.find_field("Explanation", :exact => true)
54
+ @session.find_field('Explanation', exact: true)
44
55
  end.to raise_error(Capybara::ElementNotFound)
45
56
  end
46
57
  end
47
58
 
48
- context "with :disabled option" do
49
- it "should find disabled fields when true" do
50
- expect(@session.find_field("Disabled Checkbox", :disabled => true)[:name]).to eq("form[disabled_checkbox]")
59
+ context 'with :disabled option' do
60
+ it 'should find disabled fields when true' do
61
+ expect(@session.find_field('Disabled Checkbox', disabled: true)[:name]).to eq('form[disabled_checkbox]')
62
+ expect(@session.find_field('form_disabled_fieldset_child', disabled: true)[:name]).to eq('form[disabled_fieldset_child]')
63
+ expect(@session.find_field('form_disabled_fieldset_descendant', disabled: true)[:name]).to eq('form[disabled_fieldset_descendant]')
51
64
  end
52
65
 
53
- it "should not find disabled fields when false" do
66
+ it 'should not find disabled fields when false' do
54
67
  expect do
55
- @session.find_field("Disabled Checkbox", :disabled => false)
68
+ @session.find_field('Disabled Checkbox', disabled: false)
56
69
  end.to raise_error(Capybara::ElementNotFound)
57
70
  end
58
71
 
59
- it "should not find disabled fields by default" do
72
+ it 'should not find disabled fields by default' do
60
73
  expect do
61
- @session.find_field("Disabled Checkbox")
74
+ @session.find_field('Disabled Checkbox')
62
75
  end.to raise_error(Capybara::ElementNotFound)
63
76
  end
64
77
 
65
- it "should find disabled fields when :all" do
66
- expect(@session.find_field("Disabled Checkbox", :disabled => :all)[:name]).to eq("form[disabled_checkbox]")
78
+ it 'should find disabled fields when :all' do
79
+ expect(@session.find_field('Disabled Checkbox', disabled: :all)[:name]).to eq('form[disabled_checkbox]')
67
80
  end
68
81
 
69
- it "should find enabled fields when :all" do
70
- expect(@session.find_field('Dog', :disabled => :all).value).to eq('dog')
82
+ it 'should find enabled fields when :all' do
83
+ expect(@session.find_field('Dog', disabled: :all).value).to eq('dog')
71
84
  end
72
85
  end
73
86
 
74
-
75
87
  context 'with :readonly option' do
76
- it "should find readonly fields when true" do
88
+ it 'should find readonly fields when true' do
77
89
  expect(@session.find_field('form[readonly_test]', readonly: true)[:id]).to eq 'readonly'
78
90
  end
79
91
 
80
- it "should not find readonly fields when false" do
92
+ it 'should not find readonly fields when false' do
81
93
  expect(@session.find_field('form[readonly_test]', readonly: false)[:id]).to eq 'not_readonly'
82
94
  end
83
95
 
84
- it "should ignore readonly by default" do
96
+ it 'should ignore readonly by default' do
85
97
  expect do
86
98
  @session.find_field('form[readonly_test]')
87
99
  end.to raise_error(Capybara::Ambiguous, /found 2 elements/)
88
100
  end
89
101
  end
102
+
103
+ context 'with no locator' do
104
+ it 'should use options to find the field' do
105
+ expect(@session.find_field(type: 'checkbox', with: 'dog')['id']).to eq 'form_pets_dog'
106
+ end
107
+ end
108
+
109
+ it 'should accept an optional filter block' do
110
+ # this would be better done with the :with option but this is just a test
111
+ expect(@session.find_field('form[pets][]') { |node| node.value == 'dog' }[:id]).to eq 'form_pets_dog'
112
+ end
90
113
  end
@@ -1,16 +1,29 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  Capybara::SpecHelper.spec '#find_link' do
3
4
  before do
4
5
  @session.visit('/with_html')
5
6
  end
6
7
 
7
- it "should find any field" do
8
- expect(@session.find_link('foo').text).to eq("ullamco")
9
- expect(@session.find_link('labore')[:href]).to match %r(/with_simple_html$)
8
+ it 'should find any link' do
9
+ expect(@session.find_link('foo').text).to eq('ullamco')
10
+ expect(@session.find_link('labore')[:href]).to match %r{/with_simple_html$}
10
11
  end
11
12
 
12
- it "casts to string" do
13
- expect(@session.find_link(:'foo').text).to eq("ullamco")
13
+ context 'aria_label attribute with Capybara.enable_aria_label' do
14
+ it 'should find when true' do
15
+ Capybara.enable_aria_label = true
16
+ expect(@session.find_link('Go to simple')[:href]).to match %r{/with_simple_html$}
17
+ end
18
+
19
+ it 'should not find when false' do
20
+ Capybara.enable_aria_label = false
21
+ expect { @session.find_link('Go to simple') }.to raise_error(Capybara::ElementNotFound)
22
+ end
23
+ end
24
+
25
+ it 'casts to string' do
26
+ expect(@session.find_link(:foo).text).to eq('ullamco')
14
27
  end
15
28
 
16
29
  it "should raise error if the field doesn't exist" do
@@ -19,15 +32,39 @@ Capybara::SpecHelper.spec '#find_link' do
19
32
  end.to raise_error(Capybara::ElementNotFound)
20
33
  end
21
34
 
22
- context "with :exact option" do
23
- it "should accept partial matches when false" do
24
- expect(@session.find_link('abo', :exact => false).text).to eq("labore")
35
+ context 'with :exact option' do
36
+ it 'should accept partial matches when false' do
37
+ expect(@session.find_link('abo', exact: false).text).to eq('labore')
25
38
  end
26
39
 
27
- it "should not accept partial matches when true" do
40
+ it 'should not accept partial matches when true' do
28
41
  expect do
29
- @session.find_link('abo', :exact => true)
42
+ @session.find_link('abo', exact: true)
30
43
  end.to raise_error(Capybara::ElementNotFound)
31
44
  end
32
45
  end
46
+
47
+ context 'without locator' do
48
+ it 'should use options' do
49
+ expect(@session.find_link(href: '#anchor').text).to eq 'Normal Anchor'
50
+ end
51
+ end
52
+
53
+ context 'download filter' do
54
+ it 'finds a download link' do
55
+ expect(@session.find_link('Download Me', download: true).text).to eq 'Download Me'
56
+ end
57
+
58
+ it "doesn't find a download link if download is false" do
59
+ expect { @session.find_link('Download Me', download: false) }.to raise_error Capybara::ElementNotFound
60
+ end
61
+
62
+ it 'finds a renaming download link' do
63
+ expect(@session.find_link(download: 'other.csv').text).to eq 'Download Other'
64
+ end
65
+
66
+ it 'raises if passed an invalid value' do
67
+ expect { @session.find_link(download: 37) }.to raise_error ArgumentError
68
+ end
69
+ end
33
70
  end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  Capybara::SpecHelper.spec '#find' do
3
4
  before do
4
5
  @session.visit('/with_html')
@@ -8,66 +9,67 @@ Capybara::SpecHelper.spec '#find' do
8
9
  Capybara::Selector.remove(:monkey)
9
10
  end
10
11
 
11
- it "should find the first element using the given locator" do
12
+ it 'should find the first element using the given locator' do
12
13
  expect(@session.find('//h1').text).to eq('This is a test')
13
- expect(@session.find("//input[@id='test_field']")[:value]).to eq('monkey')
14
+ expect(@session.find("//input[@id='test_field']").value).to eq('monkey')
14
15
  end
15
16
 
16
- it "should find the first element using the given locator and options" do
17
- expect(@session.find('//a', :text => 'Redirect')[:id]).to eq('red')
18
- expect(@session.find(:css, 'a', :text => 'A link came first')[:title]).to eq('twas a fine link')
17
+ it 'should find the first element using the given locator and options' do
18
+ expect(@session.find('//a', text: 'Redirect')[:id]).to eq('red')
19
+ expect(@session.find(:css, 'a', text: 'A link came first')[:title]).to eq('twas a fine link')
19
20
  end
20
21
 
21
- it "should raise an error if there are multiple matches" do
22
+ it 'should raise an error if there are multiple matches' do
22
23
  expect { @session.find('//a') }.to raise_error(Capybara::Ambiguous)
23
24
  end
24
25
 
25
- it "should wait for asynchronous load", :requires => [:js] do
26
+ it 'should wait for asynchronous load', requires: [:js] do
27
+ Capybara.default_max_wait_time = 2
26
28
  @session.visit('/with_js')
27
29
  @session.click_link('Click me')
28
- expect(@session.find(:css, "a#has-been-clicked").text).to include('Has been clicked')
30
+ expect(@session.find(:css, 'a#has-been-clicked').text).to include('Has been clicked')
29
31
  end
30
32
 
31
- context "with :text option" do
33
+ context 'with :text option' do
32
34
  it "casts text's argument to string" do
33
- expect(@session.find(:css, '.number', text: 42)).to have_content("42")
35
+ expect(@session.find(:css, '.number', text: 42)).to have_content('42')
34
36
  end
35
37
  end
36
38
 
37
- context "with :wait option", :requires => [:js] do
38
- it "should not wait for asynchronous load when `false` given" do
39
+ context 'with :wait option', requires: [:js] do
40
+ it 'should not wait for asynchronous load when `false` given' do
39
41
  @session.visit('/with_js')
40
42
  @session.click_link('Click me')
41
43
  expect do
42
- @session.find(:css, "a#has-been-clicked", :wait => false)
44
+ @session.find(:css, 'a#has-been-clicked', wait: false)
43
45
  end.to raise_error(Capybara::ElementNotFound)
44
46
  end
45
47
 
46
- it "should not find element if it appears after given wait duration" do
48
+ it 'should not find element if it appears after given wait duration' do
47
49
  @session.visit('/with_js')
48
50
  @session.click_link('Slowly')
49
51
  expect do
50
- @session.find(:css, "a#slow-clicked", :wait => 0.2)
52
+ @session.find(:css, 'a#slow-clicked', wait: 0.2)
51
53
  end.to raise_error(Capybara::ElementNotFound)
52
54
  end
53
55
 
54
- it "should find element if it appears before given wait duration" do
56
+ it 'should find element if it appears before given wait duration' do
55
57
  @session.visit('/with_js')
56
58
  @session.click_link('Click me')
57
- expect(@session.find(:css, "a#has-been-clicked", :wait => 0.9).text).to include('Has been clicked')
59
+ expect(@session.find(:css, 'a#has-been-clicked', wait: 3.0).text).to include('Has been clicked')
58
60
  end
59
61
  end
60
62
 
61
- context "with frozen time", :requires => [:js] do
63
+ context 'with frozen time', requires: [:js] do
62
64
  if defined?(Process::CLOCK_MONOTONIC)
63
- it "will time out even if time is frozen" do
65
+ it 'will time out even if time is frozen' do
64
66
  @session.visit('/with_js')
65
67
  now = Time.now
66
68
  allow(Time).to receive(:now).and_return(now)
67
69
  expect { @session.find('//isnotthere') }.to raise_error(Capybara::ElementNotFound)
68
70
  end
69
71
  else
70
- it "raises an error suggesting that Capybara is stuck in time" do
72
+ it 'raises an error suggesting that Capybara is stuck in time' do
71
73
  @session.visit('/with_js')
72
74
  now = Time.now
73
75
  allow(Time).to receive(:now).and_return(now)
@@ -76,26 +78,42 @@ Capybara::SpecHelper.spec '#find' do
76
78
  end
77
79
  end
78
80
 
79
- context "with css selectors" do
80
- it "should find the first element using the given locator" do
81
+ context 'with css selectors' do
82
+ it 'should find the first element using the given locator' do
81
83
  expect(@session.find(:css, 'h1').text).to eq('This is a test')
82
- expect(@session.find(:css, "input[id='test_field']")[:value]).to eq('monkey')
84
+ expect(@session.find(:css, "input[id='test_field']").value).to eq('monkey')
83
85
  end
84
86
 
85
- it "should support pseudo selectors" do
87
+ it 'should support pseudo selectors' do
86
88
  expect(@session.find(:css, 'input:disabled').value).to eq('This is disabled')
87
89
  end
90
+
91
+ it 'should support escaping characters' do
92
+ expect(@session.find(:css, '#\31 escape\.me').text).to eq('needs escaping')
93
+ expect(@session.find(:css, '.\32 escape').text).to eq('needs escaping')
94
+ end
95
+
96
+ it 'should not warn about locator' do
97
+ expect { @session.find(:css, '#not_on_page') }.to raise_error Capybara::ElementNotFound do |e|
98
+ expect(e.message).not_to match(/you may be passing a CSS selector or XPath expression/)
99
+ end
100
+ end
88
101
  end
89
102
 
90
- context "with xpath selectors" do
91
- it "should find the first element using the given locator" do
103
+ context 'with xpath selectors' do
104
+ it 'should find the first element using the given locator' do
92
105
  expect(@session.find(:xpath, '//h1').text).to eq('This is a test')
93
- expect(@session.find(:xpath, "//input[@id='test_field']")[:value]).to eq('monkey')
106
+ expect(@session.find(:xpath, "//input[@id='test_field']").value).to eq('monkey')
107
+ end
108
+
109
+ it 'should warn if passed a non-valid locator type' do
110
+ expect { @session.find(:xpath, 123) }.to raise_error(Exception) # The exact error is not yet well defined
111
+ .and output(/must respond to to_xpath or be an instance of String/).to_stderr
94
112
  end
95
113
  end
96
114
 
97
- context "with custom selector" do
98
- it "should use the custom selector" do
115
+ context 'with custom selector' do
116
+ it 'should use the custom selector' do
99
117
  Capybara.add_selector(:beatle) do
100
118
  xpath { |name| ".//*[@id='#{name}']" }
101
119
  end
@@ -104,11 +122,11 @@ Capybara::SpecHelper.spec '#find' do
104
122
  end
105
123
  end
106
124
 
107
- context "with custom selector with :for option" do
108
- it "should use the selector when it matches the :for option" do
125
+ context 'with custom selector with custom `match` block' do
126
+ it 'should use the custom selector when locator matches the block' do
109
127
  Capybara.add_selector(:beatle) do
110
128
  xpath { |num| ".//*[contains(@class, 'beatle')][#{num}]" }
111
- match { |value| value.is_a?(Fixnum) }
129
+ match { |value| value.is_a?(Integer) }
112
130
  end
113
131
  expect(@session.find(:beatle, '2').text).to eq('Paul')
114
132
  expect(@session.find(1).text).to eq('John')
@@ -117,269 +135,397 @@ Capybara::SpecHelper.spec '#find' do
117
135
  end
118
136
  end
119
137
 
120
- context "with custom selector with custom filter" do
138
+ context 'with custom selector with custom filter' do
121
139
  before do
122
140
  Capybara.add_selector(:beatle) do
123
141
  xpath { |name| ".//li[contains(@class, 'beatle')][contains(text(), '#{name}')]" }
124
- filter(:type) { |node, type| node[:class].split(/\s+/).include?(type) }
142
+ node_filter(:type) { |node, type| node[:class].split(/\s+/).include?(type) }
143
+ node_filter(:fail) { |_node, _val| raise Capybara::ElementNotFound, 'fail' }
125
144
  end
126
145
  end
127
146
 
128
- it "should find elements that match the filter" do
129
- expect(@session.find(:beatle, 'Paul', :type => 'drummer').text).to eq('Paul')
130
- expect(@session.find(:beatle, 'Ringo', :type => 'drummer').text).to eq('Ringo')
147
+ it 'should find elements that match the filter' do
148
+ expect(@session.find(:beatle, 'Paul', type: 'drummer').text).to eq('Paul')
149
+ expect(@session.find(:beatle, 'Ringo', type: 'drummer').text).to eq('Ringo')
131
150
  end
132
151
 
133
- it "ignores filter when it is not given" do
152
+ it 'ignores filter when it is not given' do
134
153
  expect(@session.find(:beatle, 'Paul').text).to eq('Paul')
135
154
  expect(@session.find(:beatle, 'John').text).to eq('John')
136
155
  end
137
156
 
138
157
  it "should not find elements that don't match the filter" do
139
- expect { @session.find(:beatle, 'John', :type => 'drummer') }.to raise_error(Capybara::ElementNotFound)
140
- expect { @session.find(:beatle, 'George', :type => 'drummer') }.to raise_error(Capybara::ElementNotFound)
158
+ expect { @session.find(:beatle, 'John', type: 'drummer') }.to raise_error(Capybara::ElementNotFound)
159
+ expect { @session.find(:beatle, 'George', type: 'drummer') }.to raise_error(Capybara::ElementNotFound)
160
+ end
161
+
162
+ it 'should not raise an ElementNotFound error from in a filter' do
163
+ expect { @session.find(:beatle, 'John', fail: 'something') }.to raise_error(Capybara::ElementNotFound, /beatle "John"/)
141
164
  end
142
165
  end
143
166
 
144
- context "with custom selector with custom filter and default" do
167
+ context 'with custom selector with custom filter and default' do
145
168
  before do
146
169
  Capybara.add_selector(:beatle) do
147
170
  xpath { |name| ".//li[contains(@class, 'beatle')][contains(text(), '#{name}')]" }
148
- filter(:type, :default => "drummer") { |node, type| node[:class].split(/\s+/).include?(type) }
171
+ node_filter(:type, default: 'drummer') { |node, type| node[:class].split(/\s+/).include?(type) }
149
172
  end
150
173
  end
151
174
 
152
- it "should find elements that match the filter" do
153
- expect(@session.find(:beatle, 'Paul', :type => 'drummer').text).to eq('Paul')
154
- expect(@session.find(:beatle, 'Ringo', :type => 'drummer').text).to eq('Ringo')
175
+ it 'should find elements that match the filter' do
176
+ expect(@session.find(:beatle, 'Paul', type: 'drummer').text).to eq('Paul')
177
+ expect(@session.find(:beatle, 'Ringo', type: 'drummer').text).to eq('Ringo')
155
178
  end
156
179
 
157
- it "should use default value when filter is not given" do
180
+ it 'should use default value when filter is not given' do
158
181
  expect(@session.find(:beatle, 'Paul').text).to eq('Paul')
159
182
  expect { @session.find(:beatle, 'John') }.to raise_error(Capybara::ElementNotFound)
160
183
  end
161
184
 
162
185
  it "should not find elements that don't match the filter" do
163
- expect { @session.find(:beatle, 'John', :type => 'drummer') }.to raise_error(Capybara::ElementNotFound)
164
- expect { @session.find(:beatle, 'George', :type => 'drummer') }.to raise_error(Capybara::ElementNotFound)
186
+ expect { @session.find(:beatle, 'John', type: 'drummer') }.to raise_error(Capybara::ElementNotFound)
187
+ expect { @session.find(:beatle, 'George', type: 'drummer') }.to raise_error(Capybara::ElementNotFound)
165
188
  end
166
189
  end
167
190
 
168
- context "with css as default selector" do
191
+ context 'with alternate filter set' do
192
+ before do
193
+ Capybara::Selector::FilterSet.add(:value) do
194
+ node_filter(:with) { |node, with| node.value == with.to_s }
195
+ end
196
+
197
+ Capybara.add_selector(:id_with_field_filters) do
198
+ xpath { |id| XPath.descendant[XPath.attr(:id) == id.to_s] }
199
+ filter_set(:field)
200
+ end
201
+ end
202
+
203
+ it 'should allow use of filters from custom filter set' do
204
+ expect(@session.find(:id, 'test_field', filter_set: :value, with: 'monkey').value).to eq('monkey')
205
+ expect { @session.find(:id, 'test_field', filter_set: :value, with: 'not_monkey') }.to raise_error(Capybara::ElementNotFound)
206
+ end
207
+
208
+ it 'should allow use of filter set from a different selector' do
209
+ expect(@session.find(:id, 'test_field', filter_set: :field, with: 'monkey').value).to eq('monkey')
210
+ expect { @session.find(:id, 'test_field', filter_set: :field, with: 'not_monkey') }.to raise_error(Capybara::ElementNotFound)
211
+ end
212
+
213
+ it 'should allow importing of filter set into selector' do
214
+ expect(@session.find(:id_with_field_filters, 'test_field', with: 'monkey').value).to eq('monkey')
215
+ expect { @session.find(:id_with_field_filters, 'test_field', with: 'not_monkey') }.to raise_error(Capybara::ElementNotFound)
216
+ end
217
+ end
218
+
219
+ context 'with css as default selector' do
169
220
  before { Capybara.default_selector = :css }
170
- it "should find the first element using the given locator" do
221
+
222
+ after { Capybara.default_selector = :xpath }
223
+
224
+ it 'should find the first element using the given locator' do
171
225
  expect(@session.find('h1').text).to eq('This is a test')
172
- expect(@session.find("input[id='test_field']")[:value]).to eq('monkey')
226
+ expect(@session.find("input[id='test_field']").value).to eq('monkey')
173
227
  end
174
- after { Capybara.default_selector = :xpath }
175
228
  end
176
229
 
177
- it "should raise ElementNotFound with a useful default message if nothing was found" do
230
+ it 'should raise ElementNotFound with a useful default message if nothing was found' do
178
231
  expect do
179
232
  @session.find(:xpath, '//div[@id="nosuchthing"]').to be_nil
180
- end.to raise_error(Capybara::ElementNotFound, "Unable to find xpath \"//div[@id=\\\"nosuchthing\\\"]\"")
233
+ end.to raise_error(Capybara::ElementNotFound, 'Unable to find xpath "//div[@id=\\"nosuchthing\\"]"')
181
234
  end
182
235
 
183
- it "should accept an XPath instance" do
236
+ it 'should accept an XPath instance' do
184
237
  @session.visit('/form')
185
- @xpath = XPath::HTML.fillable_field('First Name')
238
+ @xpath = Capybara::Selector.new(:fillable_field, config: {}, format: :xpath).call('First Name')
239
+ expect(@xpath).to be_a(::XPath::Union)
186
240
  expect(@session.find(@xpath).value).to eq('John')
187
241
  end
188
242
 
189
- context "with :exact option" do
190
- it "matches exactly when true" do
191
- expect(@session.find(:xpath, XPath.descendant(:input)[XPath.attr(:id).is("test_field")], :exact => true).value).to eq("monkey")
243
+ context 'with :exact option' do
244
+ it 'matches exactly when true' do
245
+ expect(@session.find(:xpath, XPath.descendant(:input)[XPath.attr(:id).is('test_field')], exact: true).value).to eq('monkey')
192
246
  expect do
193
- @session.find(:xpath, XPath.descendant(:input)[XPath.attr(:id).is("est_fiel")], :exact => true)
247
+ @session.find(:xpath, XPath.descendant(:input)[XPath.attr(:id).is('est_fiel')], exact: true)
194
248
  end.to raise_error(Capybara::ElementNotFound)
195
249
  end
196
250
 
197
- it "matches loosely when false" do
198
- expect(@session.find(:xpath, XPath.descendant(:input)[XPath.attr(:id).is("test_field")], :exact => false).value).to eq("monkey")
199
- expect(@session.find(:xpath, XPath.descendant(:input)[XPath.attr(:id).is("est_fiel")], :exact => false).value).to eq("monkey")
251
+ it 'matches loosely when false' do
252
+ expect(@session.find(:xpath, XPath.descendant(:input)[XPath.attr(:id).is('test_field')], exact: false).value).to eq('monkey')
253
+ expect(@session.find(:xpath, XPath.descendant(:input)[XPath.attr(:id).is('est_fiel')], exact: false).value).to eq('monkey')
200
254
  end
201
255
 
202
- it "defaults to `Capybara.exact`" do
256
+ it 'defaults to `Capybara.exact`' do
203
257
  Capybara.exact = true
204
258
  expect do
205
- @session.find(:xpath, XPath.descendant(:input)[XPath.attr(:id).is("est_fiel")])
259
+ @session.find(:xpath, XPath.descendant(:input)[XPath.attr(:id).is('est_fiel')])
206
260
  end.to raise_error(Capybara::ElementNotFound)
207
261
  Capybara.exact = false
208
- @session.find(:xpath, XPath.descendant(:input)[XPath.attr(:id).is("est_fiel")])
262
+ @session.find(:xpath, XPath.descendant(:input)[XPath.attr(:id).is('est_fiel')])
263
+ end
264
+
265
+ it 'warns when the option has no effect' do
266
+ expect { @session.find(:css, '#test_field', exact: true) }.to \
267
+ output(/^The :exact option only has an effect on queries using the XPath#is method. Using it with the query "#test_field" has no effect/).to_stderr
209
268
  end
210
269
  end
211
270
 
212
- context "with :match option" do
213
- context "when set to `one`" do
214
- it "raises an error when multiple matches exist" do
271
+ context 'with :match option' do
272
+ context 'when set to `one`' do
273
+ it 'raises an error when multiple matches exist' do
215
274
  expect do
216
- @session.find(:css, ".multiple", :match => :one)
275
+ @session.find(:css, '.multiple', match: :one)
217
276
  end.to raise_error(Capybara::Ambiguous)
218
277
  end
219
- it "raises an error even if there the match is exact and the others are inexact" do
278
+
279
+ it 'raises an error even if there the match is exact and the others are inexact' do
220
280
  expect do
221
- @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("almost_singular")], :exact => false, :match => :one)
281
+ @session.find(:xpath, XPath.descendant[XPath.attr(:class).is('almost_singular')], exact: false, match: :one)
222
282
  end.to raise_error(Capybara::Ambiguous)
223
283
  end
224
- it "returns the element if there is only one" do
225
- expect(@session.find(:css, ".singular", :match => :one).text).to eq("singular")
284
+
285
+ it 'returns the element if there is only one' do
286
+ expect(@session.find(:css, '.singular', match: :one).text).to eq('singular')
226
287
  end
227
- it "raises an error if there is no match" do
288
+
289
+ it 'raises an error if there is no match' do
228
290
  expect do
229
- @session.find(:css, ".does-not-exist", :match => :one)
291
+ @session.find(:css, '.does-not-exist', match: :one)
230
292
  end.to raise_error(Capybara::ElementNotFound)
231
293
  end
232
294
  end
233
295
 
234
- context "when set to `first`" do
235
- it "returns the first matched element" do
236
- expect(@session.find(:css, ".multiple", :match => :first).text).to eq("multiple one")
296
+ context 'when set to `first`' do
297
+ it 'returns the first matched element' do
298
+ expect(@session.find(:css, '.multiple', match: :first).text).to eq('multiple one')
237
299
  end
238
- it "raises an error if there is no match" do
300
+
301
+ it 'raises an error if there is no match' do
239
302
  expect do
240
- @session.find(:css, ".does-not-exist", :match => :first)
303
+ @session.find(:css, '.does-not-exist', match: :first)
241
304
  end.to raise_error(Capybara::ElementNotFound)
242
305
  end
243
306
  end
244
307
 
245
- context "when set to `smart`" do
246
- context "and `exact` set to `false`" do
247
- it "raises an error when there are multiple exact matches" do
308
+ context 'when set to `smart`' do
309
+ context 'and `exact` set to `false`' do
310
+ it 'raises an error when there are multiple exact matches' do
248
311
  expect do
249
- @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("multiple")], :match => :smart, :exact => false)
312
+ @session.find(:xpath, XPath.descendant[XPath.attr(:class).is('multiple')], match: :smart, exact: false)
250
313
  end.to raise_error(Capybara::Ambiguous)
251
314
  end
252
- it "finds a single exact match when there also are inexact matches" do
253
- result = @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("almost_singular")], :match => :smart, :exact => false)
254
- expect(result.text).to eq("almost singular")
315
+
316
+ it 'finds a single exact match when there also are inexact matches' do
317
+ result = @session.find(:xpath, XPath.descendant[XPath.attr(:class).is('almost_singular')], match: :smart, exact: false)
318
+ expect(result.text).to eq('almost singular')
255
319
  end
256
- it "raises an error when there are multiple inexact matches" do
320
+
321
+ it 'raises an error when there are multiple inexact matches' do
257
322
  expect do
258
- @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("almost_singul")], :match => :smart, :exact => false)
323
+ @session.find(:xpath, XPath.descendant[XPath.attr(:class).is('almost_singul')], match: :smart, exact: false)
259
324
  end.to raise_error(Capybara::Ambiguous)
260
325
  end
261
- it "finds a single inexact match" do
262
- result = @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("almost_singular but")], :match => :smart, :exact => false)
263
- expect(result.text).to eq("almost singular but not quite")
326
+
327
+ it 'finds a single inexact match' do
328
+ result = @session.find(:xpath, XPath.descendant[XPath.attr(:class).is('almost_singular but')], match: :smart, exact: false)
329
+ expect(result.text).to eq('almost singular but not quite')
264
330
  end
265
- it "raises an error if there is no match" do
331
+
332
+ it 'raises an error if there is no match' do
266
333
  expect do
267
- @session.find(:css, ".does-not-exist", :match => :smart, :exact => false)
334
+ @session.find(:xpath, XPath.descendant[XPath.attr(:class).is('does-not-exist')], match: :smart, exact: false)
268
335
  end.to raise_error(Capybara::ElementNotFound)
269
336
  end
270
337
  end
271
338
 
272
- context "with `exact` set to `true`" do
273
- it "raises an error when there are multiple exact matches" do
339
+ context 'with `exact` set to `true`' do
340
+ it 'raises an error when there are multiple exact matches' do
274
341
  expect do
275
- @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("multiple")], :match => :smart, :exact => true)
342
+ @session.find(:xpath, XPath.descendant[XPath.attr(:class).is('multiple')], match: :smart, exact: true)
276
343
  end.to raise_error(Capybara::Ambiguous)
277
344
  end
278
- it "finds a single exact match when there also are inexact matches" do
279
- result = @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("almost_singular")], :match => :smart, :exact => true)
280
- expect(result.text).to eq("almost singular")
345
+
346
+ it 'finds a single exact match when there also are inexact matches' do
347
+ result = @session.find(:xpath, XPath.descendant[XPath.attr(:class).is('almost_singular')], match: :smart, exact: true)
348
+ expect(result.text).to eq('almost singular')
281
349
  end
282
- it "raises an error when there are multiple inexact matches" do
350
+
351
+ it 'raises an error when there are multiple inexact matches' do
283
352
  expect do
284
- @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("almost_singul")], :match => :smart, :exact => true)
353
+ @session.find(:xpath, XPath.descendant[XPath.attr(:class).is('almost_singul')], match: :smart, exact: true)
285
354
  end.to raise_error(Capybara::ElementNotFound)
286
355
  end
287
- it "raises an error when there is a single inexact matches" do
356
+
357
+ it 'raises an error when there is a single inexact matches' do
288
358
  expect do
289
- result = @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("almost_singular but")], :match => :smart, :exact => true)
359
+ @session.find(:xpath, XPath.descendant[XPath.attr(:class).is('almost_singular but')], match: :smart, exact: true)
290
360
  end.to raise_error(Capybara::ElementNotFound)
291
361
  end
292
- it "raises an error if there is no match" do
362
+
363
+ it 'raises an error if there is no match' do
293
364
  expect do
294
- @session.find(:css, ".does-not-exist", :match => :smart, :exact => true)
365
+ @session.find(:xpath, XPath.descendant[XPath.attr(:class).is('does-not-exist')], match: :smart, exact: true)
295
366
  end.to raise_error(Capybara::ElementNotFound)
296
367
  end
297
368
  end
298
369
  end
299
370
 
300
- context "when set to `prefer_exact`" do
301
- context "and `exact` set to `false`" do
302
- it "picks the first one when there are multiple exact matches" do
303
- result = @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("multiple")], :match => :prefer_exact, :exact => false)
304
- expect(result.text).to eq("multiple one")
371
+ context 'when set to `prefer_exact`' do
372
+ context 'and `exact` set to `false`' do
373
+ it 'picks the first one when there are multiple exact matches' do
374
+ result = @session.find(:xpath, XPath.descendant[XPath.attr(:class).is('multiple')], match: :prefer_exact, exact: false)
375
+ expect(result.text).to eq('multiple one')
305
376
  end
306
- it "finds a single exact match when there also are inexact matches" do
307
- result = @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("almost_singular")], :match => :prefer_exact, :exact => false)
308
- expect(result.text).to eq("almost singular")
377
+
378
+ it 'finds a single exact match when there also are inexact matches' do
379
+ result = @session.find(:xpath, XPath.descendant[XPath.attr(:class).is('almost_singular')], match: :prefer_exact, exact: false)
380
+ expect(result.text).to eq('almost singular')
309
381
  end
310
- it "picks the first one when there are multiple inexact matches" do
311
- result = @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("almost_singul")], :match => :prefer_exact, :exact => false)
312
- expect(result.text).to eq("almost singular but not quite")
382
+
383
+ it 'picks the first one when there are multiple inexact matches' do
384
+ result = @session.find(:xpath, XPath.descendant[XPath.attr(:class).is('almost_singul')], match: :prefer_exact, exact: false)
385
+ expect(result.text).to eq('almost singular but not quite')
313
386
  end
314
- it "finds a single inexact match" do
315
- result = @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("almost_singular but")], :match => :prefer_exact, :exact => false)
316
- expect(result.text).to eq("almost singular but not quite")
387
+
388
+ it 'finds a single inexact match' do
389
+ result = @session.find(:xpath, XPath.descendant[XPath.attr(:class).is('almost_singular but')], match: :prefer_exact, exact: false)
390
+ expect(result.text).to eq('almost singular but not quite')
317
391
  end
318
- it "raises an error if there is no match" do
392
+
393
+ it 'raises an error if there is no match' do
319
394
  expect do
320
- @session.find(:css, ".does-not-exist", :match => :prefer_exact, :exact => false)
395
+ @session.find(:xpath, XPath.descendant[XPath.attr(:class).is('does-not-exist')], match: :prefer_exact, exact: false)
321
396
  end.to raise_error(Capybara::ElementNotFound)
322
397
  end
323
398
  end
324
399
 
325
- context "with `exact` set to `true`" do
326
- it "picks the first one when there are multiple exact matches" do
327
- result = @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("multiple")], :match => :prefer_exact, :exact => true)
328
- expect(result.text).to eq("multiple one")
400
+ context 'with `exact` set to `true`' do
401
+ it 'picks the first one when there are multiple exact matches' do
402
+ result = @session.find(:xpath, XPath.descendant[XPath.attr(:class).is('multiple')], match: :prefer_exact, exact: true)
403
+ expect(result.text).to eq('multiple one')
329
404
  end
330
- it "finds a single exact match when there also are inexact matches" do
331
- result = @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("almost_singular")], :match => :prefer_exact, :exact => true)
332
- expect(result.text).to eq("almost singular")
405
+
406
+ it 'finds a single exact match when there also are inexact matches' do
407
+ result = @session.find(:xpath, XPath.descendant[XPath.attr(:class).is('almost_singular')], match: :prefer_exact, exact: true)
408
+ expect(result.text).to eq('almost singular')
333
409
  end
334
- it "raises an error if there are multiple inexact matches" do
410
+
411
+ it 'raises an error if there are multiple inexact matches' do
335
412
  expect do
336
- @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("almost_singul")], :match => :prefer_exact, :exact => true)
413
+ @session.find(:xpath, XPath.descendant[XPath.attr(:class).is('almost_singul')], match: :prefer_exact, exact: true)
337
414
  end.to raise_error(Capybara::ElementNotFound)
338
415
  end
339
- it "raises an error if there is a single inexact match" do
416
+
417
+ it 'raises an error if there is a single inexact match' do
340
418
  expect do
341
- @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("almost_singular but")], :match => :prefer_exact, :exact => true)
419
+ @session.find(:xpath, XPath.descendant[XPath.attr(:class).is('almost_singular but')], match: :prefer_exact, exact: true)
342
420
  end.to raise_error(Capybara::ElementNotFound)
343
421
  end
344
- it "raises an error if there is no match" do
422
+
423
+ it 'raises an error if there is no match' do
345
424
  expect do
346
- @session.find(:css, ".does-not-exist", :match => :prefer_exact, :exact => true)
425
+ @session.find(:xpath, XPath.descendant[XPath.attr(:class).is('does-not-exist')], match: :prefer_exact, exact: true)
347
426
  end.to raise_error(Capybara::ElementNotFound)
348
427
  end
349
428
  end
350
429
  end
351
430
 
352
- it "defaults to `Capybara.match`" do
431
+ it 'defaults to `Capybara.match`' do
353
432
  Capybara.match = :one
354
433
  expect do
355
- @session.find(:css, ".multiple")
434
+ @session.find(:css, '.multiple')
356
435
  end.to raise_error(Capybara::Ambiguous)
357
436
  Capybara.match = :first
358
- expect(@session.find(:css, ".multiple").text).to eq("multiple one")
437
+ expect(@session.find(:css, '.multiple').text).to eq('multiple one')
359
438
  end
360
439
 
361
- it "raises an error when unknown option given" do
440
+ it 'raises an error when unknown option given' do
362
441
  expect do
363
- @session.find(:css, ".singular", :match => :schmoo)
442
+ @session.find(:css, '.singular', match: :schmoo)
364
443
  end.to raise_error(ArgumentError)
365
444
  end
366
445
  end
367
446
 
368
- context "within a scope" do
447
+ it 'supports a custom filter block' do
448
+ expect(@session.find(:css, 'input', &:disabled?)[:name]).to eq('disabled_text')
449
+ end
450
+
451
+ context 'with spatial filters', requires: [:spatial] do
452
+ before do
453
+ @session.visit('/spatial')
454
+ end
455
+
456
+ let :center do
457
+ @session.find(:css, 'div.center')
458
+ end
459
+
460
+ it 'should find an element above another element' do
461
+ expect(@session.find(:css, 'div:not(.corner)', above: center).text).to eq('2')
462
+ end
463
+
464
+ it 'should find an element below another element' do
465
+ expect(@session.find(:css, 'div:not(.corner):not(.footer)', below: center).text).to eq('8')
466
+ end
467
+
468
+ it 'should find an element left of another element' do
469
+ expect(@session.find(:css, 'div:not(.corner)', left_of: center).text).to eq('4')
470
+ end
471
+
472
+ it 'should find an element right of another element' do
473
+ expect(@session.find(:css, 'div:not(.corner)', right_of: center).text).to eq('6')
474
+ end
475
+
476
+ it 'should combine spatial filters' do
477
+ expect(@session.find(:css, 'div', left_of: center, above: center).text).to eq('1')
478
+ expect(@session.find(:css, 'div', right_of: center, below: center).text).to eq('9')
479
+ end
480
+
481
+ it 'should find an element "near" another element' do
482
+ expect(@session.find(:css, 'div.distance', near: center).text).to eq('2')
483
+ end
484
+ end
485
+
486
+ context 'within a scope' do
369
487
  before do
370
488
  @session.visit('/with_scope')
371
489
  end
372
490
 
373
- it "should find the an element using the given locator" do
491
+ it 'should find the an element using the given locator' do
374
492
  @session.within(:xpath, "//div[@id='for_bar']") do
375
493
  expect(@session.find('.//li[1]').text).to match(/With Simple HTML/)
376
494
  end
377
495
  end
378
496
 
379
- it "should support pseudo selectors" do
497
+ it 'should support pseudo selectors' do
380
498
  @session.within(:xpath, "//div[@id='for_bar']") do
381
499
  expect(@session.find(:css, 'input:disabled').value).to eq('James')
382
500
  end
383
501
  end
384
502
  end
503
+
504
+ it 'should raise if selector type is unknown' do
505
+ expect do
506
+ @session.find(:unknown, '//h1')
507
+ end.to raise_error(ArgumentError)
508
+ end
509
+
510
+ context 'with Capybara.test_id' do
511
+ it 'should not match on it when nil' do
512
+ Capybara.test_id = nil
513
+ expect(@session).not_to have_field('test_id')
514
+ end
515
+
516
+ it 'should work with the attribute set to `data-test-id` attribute' do
517
+ Capybara.test_id = 'data-test-id'
518
+ expect(@session.find(:field, 'test_id')[:id]).to eq 'test_field'
519
+ end
520
+
521
+ it 'should use a different attribute if set' do
522
+ Capybara.test_id = 'data-other-test-id'
523
+ expect(@session.find(:field, 'test_id')[:id]).to eq 'normal'
524
+ end
525
+
526
+ it 'should find a link with the test_id' do
527
+ Capybara.test_id = 'data-test-id'
528
+ expect(@session.find(:link, 'test-foo')[:id]).to eq 'foo'
529
+ end
530
+ end
385
531
  end