capybara 3.3.0 → 3.40.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (308) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +1 -0
  3. data/History.md +803 -13
  4. data/License.txt +1 -1
  5. data/README.md +257 -84
  6. data/lib/capybara/config.rb +25 -9
  7. data/lib/capybara/cucumber.rb +1 -1
  8. data/lib/capybara/driver/base.rb +17 -3
  9. data/lib/capybara/driver/node.rb +31 -6
  10. data/lib/capybara/dsl.rb +9 -7
  11. data/lib/capybara/helpers.rb +31 -7
  12. data/lib/capybara/minitest/spec.rb +180 -88
  13. data/lib/capybara/minitest.rb +262 -149
  14. data/lib/capybara/node/actions.rb +202 -116
  15. data/lib/capybara/node/base.rb +34 -19
  16. data/lib/capybara/node/document.rb +14 -2
  17. data/lib/capybara/node/document_matchers.rb +10 -12
  18. data/lib/capybara/node/element.rb +269 -115
  19. data/lib/capybara/node/finders.rb +99 -77
  20. data/lib/capybara/node/matchers.rb +327 -151
  21. data/lib/capybara/node/simple.rb +48 -13
  22. data/lib/capybara/node/whitespace_normalizer.rb +81 -0
  23. data/lib/capybara/queries/active_element_query.rb +18 -0
  24. data/lib/capybara/queries/ancestor_query.rb +8 -9
  25. data/lib/capybara/queries/base_query.rb +23 -16
  26. data/lib/capybara/queries/current_path_query.rb +16 -6
  27. data/lib/capybara/queries/match_query.rb +1 -0
  28. data/lib/capybara/queries/selector_query.rb +587 -130
  29. data/lib/capybara/queries/sibling_query.rb +8 -6
  30. data/lib/capybara/queries/style_query.rb +6 -2
  31. data/lib/capybara/queries/text_query.rb +28 -14
  32. data/lib/capybara/queries/title_query.rb +2 -2
  33. data/lib/capybara/rack_test/browser.rb +92 -25
  34. data/lib/capybara/rack_test/driver.rb +16 -7
  35. data/lib/capybara/rack_test/errors.rb +6 -0
  36. data/lib/capybara/rack_test/form.rb +68 -41
  37. data/lib/capybara/rack_test/node.rb +106 -39
  38. data/lib/capybara/rails.rb +1 -1
  39. data/lib/capybara/registration_container.rb +41 -0
  40. data/lib/capybara/registrations/drivers.rb +42 -0
  41. data/lib/capybara/registrations/patches/puma_ssl.rb +29 -0
  42. data/lib/capybara/registrations/servers.rb +66 -0
  43. data/lib/capybara/result.rb +75 -52
  44. data/lib/capybara/rspec/features.rb +7 -7
  45. data/lib/capybara/rspec/matcher_proxies.rb +39 -18
  46. data/lib/capybara/rspec/matchers/base.rb +113 -0
  47. data/lib/capybara/rspec/matchers/become_closed.rb +33 -0
  48. data/lib/capybara/rspec/matchers/compound.rb +88 -0
  49. data/lib/capybara/rspec/matchers/count_sugar.rb +37 -0
  50. data/lib/capybara/rspec/matchers/have_ancestor.rb +28 -0
  51. data/lib/capybara/rspec/matchers/have_current_path.rb +29 -0
  52. data/lib/capybara/rspec/matchers/have_selector.rb +69 -0
  53. data/lib/capybara/rspec/matchers/have_sibling.rb +27 -0
  54. data/lib/capybara/rspec/matchers/have_text.rb +33 -0
  55. data/lib/capybara/rspec/matchers/have_title.rb +29 -0
  56. data/lib/capybara/rspec/matchers/match_selector.rb +27 -0
  57. data/lib/capybara/rspec/matchers/match_style.rb +43 -0
  58. data/lib/capybara/rspec/matchers/spatial_sugar.rb +39 -0
  59. data/lib/capybara/rspec/matchers.rb +141 -339
  60. data/lib/capybara/rspec.rb +2 -0
  61. data/lib/capybara/selector/builders/css_builder.rb +84 -0
  62. data/lib/capybara/selector/builders/xpath_builder.rb +71 -0
  63. data/lib/capybara/selector/css.rb +27 -25
  64. data/lib/capybara/selector/definition/button.rb +68 -0
  65. data/lib/capybara/selector/definition/checkbox.rb +26 -0
  66. data/lib/capybara/selector/definition/css.rb +10 -0
  67. data/lib/capybara/selector/definition/datalist_input.rb +35 -0
  68. data/lib/capybara/selector/definition/datalist_option.rb +25 -0
  69. data/lib/capybara/selector/definition/element.rb +28 -0
  70. data/lib/capybara/selector/definition/field.rb +40 -0
  71. data/lib/capybara/selector/definition/fieldset.rb +14 -0
  72. data/lib/capybara/selector/definition/file_field.rb +13 -0
  73. data/lib/capybara/selector/definition/fillable_field.rb +33 -0
  74. data/lib/capybara/selector/definition/frame.rb +17 -0
  75. data/lib/capybara/selector/definition/id.rb +6 -0
  76. data/lib/capybara/selector/definition/label.rb +62 -0
  77. data/lib/capybara/selector/definition/link.rb +55 -0
  78. data/lib/capybara/selector/definition/link_or_button.rb +16 -0
  79. data/lib/capybara/selector/definition/option.rb +27 -0
  80. data/lib/capybara/selector/definition/radio_button.rb +27 -0
  81. data/lib/capybara/selector/definition/select.rb +81 -0
  82. data/lib/capybara/selector/definition/table.rb +109 -0
  83. data/lib/capybara/selector/definition/table_row.rb +21 -0
  84. data/lib/capybara/selector/definition/xpath.rb +5 -0
  85. data/lib/capybara/selector/definition.rb +280 -0
  86. data/lib/capybara/selector/filter.rb +1 -0
  87. data/lib/capybara/selector/filter_set.rb +73 -25
  88. data/lib/capybara/selector/filters/base.rb +24 -5
  89. data/lib/capybara/selector/filters/expression_filter.rb +3 -3
  90. data/lib/capybara/selector/filters/locator_filter.rb +29 -0
  91. data/lib/capybara/selector/filters/node_filter.rb +16 -2
  92. data/lib/capybara/selector/regexp_disassembler.rb +211 -0
  93. data/lib/capybara/selector/selector.rb +85 -348
  94. data/lib/capybara/selector/xpath_extensions.rb +17 -0
  95. data/lib/capybara/selector.rb +474 -447
  96. data/lib/capybara/selenium/atoms/getAttribute.min.js +1 -0
  97. data/lib/capybara/selenium/atoms/isDisplayed.min.js +1 -0
  98. data/lib/capybara/selenium/atoms/src/getAttribute.js +161 -0
  99. data/lib/capybara/selenium/atoms/src/isDisplayed.js +454 -0
  100. data/lib/capybara/selenium/driver.rb +255 -143
  101. data/lib/capybara/selenium/driver_specializations/chrome_driver.rb +93 -11
  102. data/lib/capybara/selenium/driver_specializations/edge_driver.rb +128 -0
  103. data/lib/capybara/selenium/driver_specializations/firefox_driver.rb +84 -0
  104. data/lib/capybara/selenium/driver_specializations/internet_explorer_driver.rb +26 -0
  105. data/lib/capybara/selenium/driver_specializations/safari_driver.rb +24 -0
  106. data/lib/capybara/selenium/extensions/file_input_click_emulation.rb +34 -0
  107. data/lib/capybara/selenium/extensions/find.rb +110 -0
  108. data/lib/capybara/selenium/extensions/html5_drag.rb +229 -0
  109. data/lib/capybara/selenium/extensions/modifier_keys_stack.rb +28 -0
  110. data/lib/capybara/selenium/extensions/scroll.rb +76 -0
  111. data/lib/capybara/selenium/node.rb +436 -134
  112. data/lib/capybara/selenium/nodes/chrome_node.rb +125 -0
  113. data/lib/capybara/selenium/nodes/edge_node.rb +110 -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/atoms.rb +18 -0
  118. data/lib/capybara/selenium/patches/is_displayed.rb +16 -0
  119. data/lib/capybara/selenium/patches/logs.rb +45 -0
  120. data/lib/capybara/selenium/patches/pause_duration_fix.rb +9 -0
  121. data/lib/capybara/selenium/patches/persistent_client.rb +20 -0
  122. data/lib/capybara/server/animation_disabler.rb +56 -19
  123. data/lib/capybara/server/checker.rb +9 -3
  124. data/lib/capybara/server/middleware.rb +28 -12
  125. data/lib/capybara/server.rb +33 -10
  126. data/lib/capybara/session/config.rb +34 -10
  127. data/lib/capybara/session/matchers.rb +23 -16
  128. data/lib/capybara/session.rb +230 -170
  129. data/lib/capybara/spec/public/jquery.js +5 -5
  130. data/lib/capybara/spec/public/offset.js +6 -0
  131. data/lib/capybara/spec/public/test.js +121 -8
  132. data/lib/capybara/spec/session/accept_alert_spec.rb +11 -11
  133. data/lib/capybara/spec/session/accept_confirm_spec.rb +3 -3
  134. data/lib/capybara/spec/session/accept_prompt_spec.rb +9 -10
  135. data/lib/capybara/spec/session/active_element_spec.rb +31 -0
  136. data/lib/capybara/spec/session/all_spec.rb +127 -40
  137. data/lib/capybara/spec/session/ancestor_spec.rb +24 -19
  138. data/lib/capybara/spec/session/assert_all_of_selectors_spec.rb +67 -38
  139. data/lib/capybara/spec/session/assert_current_path_spec.rb +21 -18
  140. data/lib/capybara/spec/session/assert_selector_spec.rb +52 -58
  141. data/lib/capybara/spec/session/assert_style_spec.rb +7 -7
  142. data/lib/capybara/spec/session/assert_text_spec.rb +74 -50
  143. data/lib/capybara/spec/session/assert_title_spec.rb +12 -12
  144. data/lib/capybara/spec/session/attach_file_spec.rb +126 -72
  145. data/lib/capybara/spec/session/body_spec.rb +6 -6
  146. data/lib/capybara/spec/session/check_spec.rb +102 -47
  147. data/lib/capybara/spec/session/choose_spec.rb +58 -32
  148. data/lib/capybara/spec/session/click_button_spec.rb +219 -163
  149. data/lib/capybara/spec/session/click_link_or_button_spec.rb +49 -23
  150. data/lib/capybara/spec/session/click_link_spec.rb +77 -54
  151. data/lib/capybara/spec/session/current_scope_spec.rb +8 -8
  152. data/lib/capybara/spec/session/current_url_spec.rb +38 -29
  153. data/lib/capybara/spec/session/dismiss_confirm_spec.rb +3 -3
  154. data/lib/capybara/spec/session/dismiss_prompt_spec.rb +2 -2
  155. data/lib/capybara/spec/session/element/assert_match_selector_spec.rb +8 -8
  156. data/lib/capybara/spec/session/element/match_css_spec.rb +16 -10
  157. data/lib/capybara/spec/session/element/match_xpath_spec.rb +6 -6
  158. data/lib/capybara/spec/session/element/matches_selector_spec.rb +68 -56
  159. data/lib/capybara/spec/session/evaluate_async_script_spec.rb +7 -7
  160. data/lib/capybara/spec/session/evaluate_script_spec.rb +28 -8
  161. data/lib/capybara/spec/session/execute_script_spec.rb +8 -7
  162. data/lib/capybara/spec/session/fill_in_spec.rb +101 -46
  163. data/lib/capybara/spec/session/find_button_spec.rb +23 -23
  164. data/lib/capybara/spec/session/find_by_id_spec.rb +7 -7
  165. data/lib/capybara/spec/session/find_field_spec.rb +32 -30
  166. data/lib/capybara/spec/session/find_link_spec.rb +31 -21
  167. data/lib/capybara/spec/session/find_spec.rb +244 -141
  168. data/lib/capybara/spec/session/first_spec.rb +43 -43
  169. data/lib/capybara/spec/session/frame/frame_title_spec.rb +5 -5
  170. data/lib/capybara/spec/session/frame/frame_url_spec.rb +5 -5
  171. data/lib/capybara/spec/session/frame/switch_to_frame_spec.rb +30 -18
  172. data/lib/capybara/spec/session/frame/within_frame_spec.rb +45 -18
  173. data/lib/capybara/spec/session/go_back_spec.rb +1 -1
  174. data/lib/capybara/spec/session/go_forward_spec.rb +1 -1
  175. data/lib/capybara/spec/session/has_all_selectors_spec.rb +23 -23
  176. data/lib/capybara/spec/session/has_ancestor_spec.rb +46 -0
  177. data/lib/capybara/spec/session/has_any_selectors_spec.rb +29 -0
  178. data/lib/capybara/spec/session/has_button_spec.rb +94 -13
  179. data/lib/capybara/spec/session/has_css_spec.rb +272 -132
  180. data/lib/capybara/spec/session/has_current_path_spec.rb +50 -35
  181. data/lib/capybara/spec/session/has_element_spec.rb +47 -0
  182. data/lib/capybara/spec/session/has_field_spec.rb +137 -58
  183. data/lib/capybara/spec/session/has_link_spec.rb +44 -4
  184. data/lib/capybara/spec/session/has_none_selectors_spec.rb +31 -31
  185. data/lib/capybara/spec/session/has_select_spec.rb +84 -50
  186. data/lib/capybara/spec/session/has_selector_spec.rb +111 -71
  187. data/lib/capybara/spec/session/has_sibling_spec.rb +50 -0
  188. data/lib/capybara/spec/session/has_table_spec.rb +181 -4
  189. data/lib/capybara/spec/session/has_text_spec.rb +101 -53
  190. data/lib/capybara/spec/session/has_title_spec.rb +19 -14
  191. data/lib/capybara/spec/session/has_xpath_spec.rb +56 -38
  192. data/lib/capybara/spec/session/headers_spec.rb +1 -1
  193. data/lib/capybara/spec/session/html_spec.rb +13 -6
  194. data/lib/capybara/spec/session/matches_style_spec.rb +37 -0
  195. data/lib/capybara/spec/session/node_spec.rb +894 -142
  196. data/lib/capybara/spec/session/node_wrapper_spec.rb +10 -7
  197. data/lib/capybara/spec/session/refresh_spec.rb +9 -7
  198. data/lib/capybara/spec/session/reset_session_spec.rb +63 -35
  199. data/lib/capybara/spec/session/response_code_spec.rb +1 -1
  200. data/lib/capybara/spec/session/save_and_open_page_spec.rb +2 -2
  201. data/lib/capybara/spec/session/save_and_open_screenshot_spec.rb +2 -2
  202. data/lib/capybara/spec/session/save_page_spec.rb +37 -37
  203. data/lib/capybara/spec/session/save_screenshot_spec.rb +10 -10
  204. data/lib/capybara/spec/session/screenshot_spec.rb +2 -2
  205. data/lib/capybara/spec/session/scroll_spec.rb +119 -0
  206. data/lib/capybara/spec/session/select_spec.rb +85 -85
  207. data/lib/capybara/spec/session/selectors_spec.rb +49 -18
  208. data/lib/capybara/spec/session/sibling_spec.rb +9 -9
  209. data/lib/capybara/spec/session/text_spec.rb +25 -24
  210. data/lib/capybara/spec/session/title_spec.rb +7 -6
  211. data/lib/capybara/spec/session/uncheck_spec.rb +33 -21
  212. data/lib/capybara/spec/session/unselect_spec.rb +37 -37
  213. data/lib/capybara/spec/session/visit_spec.rb +68 -49
  214. data/lib/capybara/spec/session/window/become_closed_spec.rb +20 -17
  215. data/lib/capybara/spec/session/window/current_window_spec.rb +1 -1
  216. data/lib/capybara/spec/session/window/switch_to_window_spec.rb +20 -16
  217. data/lib/capybara/spec/session/window/window_opened_by_spec.rb +6 -2
  218. data/lib/capybara/spec/session/window/window_spec.rb +62 -63
  219. data/lib/capybara/spec/session/window/windows_spec.rb +5 -1
  220. data/lib/capybara/spec/session/window/within_window_spec.rb +14 -14
  221. data/lib/capybara/spec/session/within_spec.rb +79 -42
  222. data/lib/capybara/spec/spec_helper.rb +41 -53
  223. data/lib/capybara/spec/test_app.rb +132 -43
  224. data/lib/capybara/spec/views/animated.erb +49 -0
  225. data/lib/capybara/spec/views/form.erb +139 -42
  226. data/lib/capybara/spec/views/frame_child.erb +4 -3
  227. data/lib/capybara/spec/views/frame_one.erb +2 -1
  228. data/lib/capybara/spec/views/frame_parent.erb +1 -1
  229. data/lib/capybara/spec/views/frame_two.erb +1 -1
  230. data/lib/capybara/spec/views/initial_alert.erb +2 -1
  231. data/lib/capybara/spec/views/layout.erb +10 -0
  232. data/lib/capybara/spec/views/obscured.erb +47 -0
  233. data/lib/capybara/spec/views/offset.erb +33 -0
  234. data/lib/capybara/spec/views/path.erb +2 -2
  235. data/lib/capybara/spec/views/popup_one.erb +1 -1
  236. data/lib/capybara/spec/views/popup_two.erb +1 -1
  237. data/lib/capybara/spec/views/react.erb +45 -0
  238. data/lib/capybara/spec/views/scroll.erb +21 -0
  239. data/lib/capybara/spec/views/spatial.erb +31 -0
  240. data/lib/capybara/spec/views/tables.erb +67 -0
  241. data/lib/capybara/spec/views/with_animation.erb +39 -4
  242. data/lib/capybara/spec/views/with_base_tag.erb +2 -2
  243. data/lib/capybara/spec/views/with_dragula.erb +24 -0
  244. data/lib/capybara/spec/views/with_fixed_header_footer.erb +2 -1
  245. data/lib/capybara/spec/views/with_hover.erb +3 -2
  246. data/lib/capybara/spec/views/with_hover1.erb +10 -0
  247. data/lib/capybara/spec/views/with_html.erb +37 -9
  248. data/lib/capybara/spec/views/with_html5_svg.erb +20 -0
  249. data/lib/capybara/spec/views/with_jquery_animation.erb +24 -0
  250. data/lib/capybara/spec/views/with_js.erb +26 -5
  251. data/lib/capybara/spec/views/with_jstree.erb +26 -0
  252. data/lib/capybara/spec/views/with_namespace.erb +1 -0
  253. data/lib/capybara/spec/views/with_scope.erb +2 -2
  254. data/lib/capybara/spec/views/with_scope_other.erb +6 -0
  255. data/lib/capybara/spec/views/with_shadow.erb +31 -0
  256. data/lib/capybara/spec/views/with_slow_unload.erb +2 -1
  257. data/lib/capybara/spec/views/with_sortable_js.erb +21 -0
  258. data/lib/capybara/spec/views/with_unload_alert.erb +1 -0
  259. data/lib/capybara/spec/views/with_windows.erb +1 -1
  260. data/lib/capybara/spec/views/within_frames.erb +1 -1
  261. data/lib/capybara/version.rb +1 -1
  262. data/lib/capybara/window.rb +19 -25
  263. data/lib/capybara.rb +126 -111
  264. data/spec/basic_node_spec.rb +59 -34
  265. data/spec/capybara_spec.rb +56 -44
  266. data/spec/counter_spec.rb +35 -0
  267. data/spec/css_builder_spec.rb +101 -0
  268. data/spec/css_splitter_spec.rb +8 -8
  269. data/spec/dsl_spec.rb +79 -52
  270. data/spec/filter_set_spec.rb +9 -9
  271. data/spec/fixtures/selenium_driver_rspec_failure.rb +4 -4
  272. data/spec/fixtures/selenium_driver_rspec_success.rb +4 -4
  273. data/spec/minitest_spec.rb +45 -7
  274. data/spec/minitest_spec_spec.rb +87 -64
  275. data/spec/per_session_config_spec.rb +6 -6
  276. data/spec/rack_test_spec.rb +172 -116
  277. data/spec/regexp_dissassembler_spec.rb +250 -0
  278. data/spec/result_spec.rb +80 -72
  279. data/spec/rspec/features_spec.rb +21 -16
  280. data/spec/rspec/scenarios_spec.rb +10 -6
  281. data/spec/rspec/shared_spec_matchers.rb +407 -365
  282. data/spec/rspec/views_spec.rb +3 -3
  283. data/spec/rspec_matchers_spec.rb +35 -10
  284. data/spec/rspec_spec.rb +63 -41
  285. data/spec/sauce_spec_chrome.rb +43 -0
  286. data/spec/selector_spec.rb +334 -89
  287. data/spec/selenium_spec_chrome.rb +176 -62
  288. data/spec/selenium_spec_chrome_remote.rb +54 -14
  289. data/spec/selenium_spec_edge.rb +41 -8
  290. data/spec/selenium_spec_firefox.rb +228 -0
  291. data/spec/selenium_spec_firefox_remote.rb +94 -0
  292. data/spec/selenium_spec_ie.rb +129 -11
  293. data/spec/selenium_spec_safari.rb +162 -0
  294. data/spec/server_spec.rb +171 -97
  295. data/spec/session_spec.rb +34 -18
  296. data/spec/shared_selenium_node.rb +79 -0
  297. data/spec/shared_selenium_session.rb +344 -80
  298. data/spec/spec_helper.rb +124 -2
  299. data/spec/whitespace_normalizer_spec.rb +54 -0
  300. data/spec/xpath_builder_spec.rb +93 -0
  301. metadata +326 -28
  302. data/lib/capybara/rspec/compound.rb +0 -94
  303. data/lib/capybara/selenium/driver_specializations/marionette_driver.rb +0 -31
  304. data/lib/capybara/selenium/nodes/marionette_node.rb +0 -31
  305. data/lib/capybara/spec/session/has_style_spec.rb +0 -25
  306. data/lib/capybara/spec/session/source_spec.rb +0 -0
  307. data/lib/capybara/spec/views/with_title.erb +0 -5
  308. data/spec/selenium_spec_marionette.rb +0 -167
@@ -9,66 +9,67 @@ Capybara::SpecHelper.spec '#find' do
9
9
  Capybara::Selector.remove(:monkey)
10
10
  end
11
11
 
12
- it "should find the first element using the given locator" do
12
+ it 'should find the first element using the given locator' do
13
13
  expect(@session.find('//h1').text).to eq('This is a test')
14
14
  expect(@session.find("//input[@id='test_field']").value).to eq('monkey')
15
15
  end
16
16
 
17
- it "should find the first element using the given locator and options" do
17
+ it 'should find the first element using the given locator and options' do
18
18
  expect(@session.find('//a', text: 'Redirect')[:id]).to eq('red')
19
19
  expect(@session.find(:css, 'a', text: 'A link came first')[:title]).to eq('twas a fine link')
20
20
  end
21
21
 
22
- it "should raise an error if there are multiple matches" do
22
+ it 'should raise an error if there are multiple matches' do
23
23
  expect { @session.find('//a') }.to raise_error(Capybara::Ambiguous)
24
24
  end
25
25
 
26
- 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
27
28
  @session.visit('/with_js')
28
29
  @session.click_link('Click me')
29
- 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')
30
31
  end
31
32
 
32
- context "with :text option" do
33
+ context 'with :text option' do
33
34
  it "casts text's argument to string" do
34
- expect(@session.find(:css, '.number', text: 42)).to have_content("42")
35
+ expect(@session.find(:css, '.number', text: 42)).to have_content('42')
35
36
  end
36
37
  end
37
38
 
38
- context "with :wait option", requires: [:js] do
39
- 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
40
41
  @session.visit('/with_js')
41
42
  @session.click_link('Click me')
42
43
  expect do
43
- @session.find(:css, "a#has-been-clicked", wait: false)
44
+ @session.find(:css, 'a#has-been-clicked', wait: false)
44
45
  end.to raise_error(Capybara::ElementNotFound)
45
46
  end
46
47
 
47
- 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
48
49
  @session.visit('/with_js')
49
50
  @session.click_link('Slowly')
50
51
  expect do
51
- @session.find(:css, "a#slow-clicked", wait: 0.2)
52
+ @session.find(:css, 'a#slow-clicked', wait: 0.2)
52
53
  end.to raise_error(Capybara::ElementNotFound)
53
54
  end
54
55
 
55
- 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
56
57
  @session.visit('/with_js')
57
58
  @session.click_link('Click me')
58
- expect(@session.find(:css, "a#has-been-clicked", wait: 2.0).text).to include('Has been clicked')
59
+ expect(@session.find(:css, 'a#has-been-clicked', wait: 3.0).text).to include('Has been clicked')
59
60
  end
60
61
  end
61
62
 
62
- context "with frozen time", requires: [:js] do
63
+ context 'with frozen time', requires: [:js] do
63
64
  if defined?(Process::CLOCK_MONOTONIC)
64
- it "will time out even if time is frozen" do
65
+ it 'will time out even if time is frozen' do
65
66
  @session.visit('/with_js')
66
67
  now = Time.now
67
68
  allow(Time).to receive(:now).and_return(now)
68
69
  expect { @session.find('//isnotthere') }.to raise_error(Capybara::ElementNotFound)
69
70
  end
70
71
  else
71
- 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
72
73
  @session.visit('/with_js')
73
74
  now = Time.now
74
75
  allow(Time).to receive(:now).and_return(now)
@@ -77,31 +78,42 @@ Capybara::SpecHelper.spec '#find' do
77
78
  end
78
79
  end
79
80
 
80
- context "with css selectors" do
81
- 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
82
83
  expect(@session.find(:css, 'h1').text).to eq('This is a test')
83
84
  expect(@session.find(:css, "input[id='test_field']").value).to eq('monkey')
84
85
  end
85
86
 
86
- it "should support pseudo selectors" do
87
+ it 'should support pseudo selectors' do
87
88
  expect(@session.find(:css, 'input:disabled').value).to eq('This is disabled')
88
89
  end
89
90
 
90
- it "should support escaping characters" do
91
+ it 'should support escaping characters' do
91
92
  expect(@session.find(:css, '#\31 escape\.me').text).to eq('needs escaping')
92
93
  expect(@session.find(:css, '.\32 escape').text).to eq('needs escaping')
93
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
94
101
  end
95
102
 
96
- context "with xpath selectors" do
97
- 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
98
105
  expect(@session.find(:xpath, '//h1').text).to eq('This is a test')
99
106
  expect(@session.find(:xpath, "//input[@id='test_field']").value).to eq('monkey')
100
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
112
+ end
101
113
  end
102
114
 
103
- context "with custom selector" do
104
- it "should use the custom selector" do
115
+ context 'with custom selector' do
116
+ it 'should use the custom selector' do
105
117
  Capybara.add_selector(:beatle) do
106
118
  xpath { |name| ".//*[@id='#{name}']" }
107
119
  end
@@ -110,8 +122,8 @@ Capybara::SpecHelper.spec '#find' do
110
122
  end
111
123
  end
112
124
 
113
- context "with custom selector with custom `match` block" do
114
- it "should use the custom selector when locator matches the block" do
125
+ context 'with custom selector with custom `match` block' do
126
+ it 'should use the custom selector when locator matches the block' do
115
127
  Capybara.add_selector(:beatle) do
116
128
  xpath { |num| ".//*[contains(@class, 'beatle')][#{num}]" }
117
129
  match { |value| value.is_a?(Integer) }
@@ -123,7 +135,7 @@ Capybara::SpecHelper.spec '#find' do
123
135
  end
124
136
  end
125
137
 
126
- context "with custom selector with custom filter" do
138
+ context 'with custom selector with custom filter' do
127
139
  before do
128
140
  Capybara.add_selector(:beatle) do
129
141
  xpath { |name| ".//li[contains(@class, 'beatle')][contains(text(), '#{name}')]" }
@@ -132,12 +144,12 @@ Capybara::SpecHelper.spec '#find' do
132
144
  end
133
145
  end
134
146
 
135
- it "should find elements that match the filter" do
147
+ it 'should find elements that match the filter' do
136
148
  expect(@session.find(:beatle, 'Paul', type: 'drummer').text).to eq('Paul')
137
149
  expect(@session.find(:beatle, 'Ringo', type: 'drummer').text).to eq('Ringo')
138
150
  end
139
151
 
140
- it "ignores filter when it is not given" do
152
+ it 'ignores filter when it is not given' do
141
153
  expect(@session.find(:beatle, 'Paul').text).to eq('Paul')
142
154
  expect(@session.find(:beatle, 'John').text).to eq('John')
143
155
  end
@@ -147,25 +159,25 @@ Capybara::SpecHelper.spec '#find' do
147
159
  expect { @session.find(:beatle, 'George', type: 'drummer') }.to raise_error(Capybara::ElementNotFound)
148
160
  end
149
161
 
150
- it "should not raise an ElementNotFound error from in a filter" do
162
+ it 'should not raise an ElementNotFound error from in a filter' do
151
163
  expect { @session.find(:beatle, 'John', fail: 'something') }.to raise_error(Capybara::ElementNotFound, /beatle "John"/)
152
164
  end
153
165
  end
154
166
 
155
- context "with custom selector with custom filter and default" do
167
+ context 'with custom selector with custom filter and default' do
156
168
  before do
157
169
  Capybara.add_selector(:beatle) do
158
170
  xpath { |name| ".//li[contains(@class, 'beatle')][contains(text(), '#{name}')]" }
159
- node_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) }
160
172
  end
161
173
  end
162
174
 
163
- it "should find elements that match the filter" do
175
+ it 'should find elements that match the filter' do
164
176
  expect(@session.find(:beatle, 'Paul', type: 'drummer').text).to eq('Paul')
165
177
  expect(@session.find(:beatle, 'Ringo', type: 'drummer').text).to eq('Ringo')
166
178
  end
167
179
 
168
- it "should use default value when filter is not given" do
180
+ it 'should use default value when filter is not given' do
169
181
  expect(@session.find(:beatle, 'Paul').text).to eq('Paul')
170
182
  expect { @session.find(:beatle, 'John') }.to raise_error(Capybara::ElementNotFound)
171
183
  end
@@ -176,7 +188,7 @@ Capybara::SpecHelper.spec '#find' do
176
188
  end
177
189
  end
178
190
 
179
- context "with alternate filter set" do
191
+ context 'with alternate filter set' do
180
192
  before do
181
193
  Capybara::Selector::FilterSet.add(:value) do
182
194
  node_filter(:with) { |node, with| node.value == with.to_s }
@@ -188,255 +200,346 @@ Capybara::SpecHelper.spec '#find' do
188
200
  end
189
201
  end
190
202
 
191
- it "should allow use of filters from custom filter set" do
203
+ it 'should allow use of filters from custom filter set' do
192
204
  expect(@session.find(:id, 'test_field', filter_set: :value, with: 'monkey').value).to eq('monkey')
193
205
  expect { @session.find(:id, 'test_field', filter_set: :value, with: 'not_monkey') }.to raise_error(Capybara::ElementNotFound)
194
206
  end
195
207
 
196
- it "should allow use of filter set from a different selector" do
208
+ it 'should allow use of filter set from a different selector' do
197
209
  expect(@session.find(:id, 'test_field', filter_set: :field, with: 'monkey').value).to eq('monkey')
198
210
  expect { @session.find(:id, 'test_field', filter_set: :field, with: 'not_monkey') }.to raise_error(Capybara::ElementNotFound)
199
211
  end
200
212
 
201
- it "should allow importing of filter set into selector" do
213
+ it 'should allow importing of filter set into selector' do
202
214
  expect(@session.find(:id_with_field_filters, 'test_field', with: 'monkey').value).to eq('monkey')
203
215
  expect { @session.find(:id_with_field_filters, 'test_field', with: 'not_monkey') }.to raise_error(Capybara::ElementNotFound)
204
216
  end
205
217
  end
206
218
 
207
- context "with css as default selector" do
219
+ context 'with css as default selector' do
208
220
  before { Capybara.default_selector = :css }
209
221
 
210
- it "should find the first element using the given locator" do
222
+ after { Capybara.default_selector = :xpath }
223
+
224
+ it 'should find the first element using the given locator' do
211
225
  expect(@session.find('h1').text).to eq('This is a test')
212
226
  expect(@session.find("input[id='test_field']").value).to eq('monkey')
213
227
  end
214
- after { Capybara.default_selector = :xpath }
215
228
  end
216
229
 
217
- 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
218
231
  expect do
219
232
  @session.find(:xpath, '//div[@id="nosuchthing"]').to be_nil
220
- end.to raise_error(Capybara::ElementNotFound, "Unable to find visible xpath \"//div[@id=\\\"nosuchthing\\\"]\"")
233
+ end.to raise_error(Capybara::ElementNotFound, 'Unable to find xpath "//div[@id=\\"nosuchthing\\"]"')
221
234
  end
222
235
 
223
- it "should accept an XPath instance" do
236
+ context 'without locator' do
237
+ it 'should not output `nil` in the ElementNotFound message if nothing was found' do
238
+ expect do
239
+ @session.find(:label, text: 'no such thing').to be_nil
240
+ end.to raise_error(Capybara::ElementNotFound, 'Unable to find label')
241
+ end
242
+ end
243
+
244
+ it 'should accept an XPath instance' do
224
245
  @session.visit('/form')
225
- @xpath = Capybara::Selector.all[:fillable_field].call('First Name')
226
- expect(@xpath).to be_a(::XPath::Union)
246
+ @xpath = Capybara::Selector.new(:fillable_field, config: {}, format: :xpath).call('First Name')
247
+ expect(@xpath).to be_a(XPath::Union)
227
248
  expect(@session.find(@xpath).value).to eq('John')
228
249
  end
229
250
 
230
- context "with :exact option" do
231
- it "matches exactly when true" do
232
- expect(@session.find(:xpath, XPath.descendant(:input)[XPath.attr(:id).is("test_field")], exact: true).value).to eq("monkey")
251
+ context 'with :exact option' do
252
+ it 'matches exactly when true' do
253
+ expect(@session.find(:xpath, XPath.descendant(:input)[XPath.attr(:id).is('test_field')], exact: true).value).to eq('monkey')
233
254
  expect do
234
- @session.find(:xpath, XPath.descendant(:input)[XPath.attr(:id).is("est_fiel")], exact: true)
255
+ @session.find(:xpath, XPath.descendant(:input)[XPath.attr(:id).is('est_fiel')], exact: true)
235
256
  end.to raise_error(Capybara::ElementNotFound)
236
257
  end
237
258
 
238
- it "matches loosely when false" do
239
- expect(@session.find(:xpath, XPath.descendant(:input)[XPath.attr(:id).is("test_field")], exact: false).value).to eq("monkey")
240
- expect(@session.find(:xpath, XPath.descendant(:input)[XPath.attr(:id).is("est_fiel")], exact: false).value).to eq("monkey")
259
+ it 'matches loosely when false' do
260
+ expect(@session.find(:xpath, XPath.descendant(:input)[XPath.attr(:id).is('test_field')], exact: false).value).to eq('monkey')
261
+ expect(@session.find(:xpath, XPath.descendant(:input)[XPath.attr(:id).is('est_fiel')], exact: false).value).to eq('monkey')
241
262
  end
242
263
 
243
- it "defaults to `Capybara.exact`" do
264
+ it 'defaults to `Capybara.exact`' do
244
265
  Capybara.exact = true
245
266
  expect do
246
- @session.find(:xpath, XPath.descendant(:input)[XPath.attr(:id).is("est_fiel")])
267
+ @session.find(:xpath, XPath.descendant(:input)[XPath.attr(:id).is('est_fiel')])
247
268
  end.to raise_error(Capybara::ElementNotFound)
248
269
  Capybara.exact = false
249
- @session.find(:xpath, XPath.descendant(:input)[XPath.attr(:id).is("est_fiel")])
270
+ @session.find(:xpath, XPath.descendant(:input)[XPath.attr(:id).is('est_fiel')])
250
271
  end
251
272
 
252
- it "warns when the option has no effect" do
253
- expect_any_instance_of(Kernel).to receive(:warn)
254
- .with('The :exact option only has an effect on queries using the XPath#is method. Using it with the query "#test_field" has no effect.')
255
- @session.find(:css, '#test_field', exact: true)
273
+ it 'warns when the option has no effect' do
274
+ expect { @session.find(:css, '#test_field', exact: true) }.to \
275
+ 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
256
276
  end
257
277
  end
258
278
 
259
- context "with :match option" do
260
- context "when set to `one`" do
261
- it "raises an error when multiple matches exist" do
279
+ context 'with :match option' do
280
+ context 'when set to `one`' do
281
+ it 'raises an error when multiple matches exist' do
262
282
  expect do
263
- @session.find(:css, ".multiple", match: :one)
283
+ @session.find(:css, '.multiple', match: :one)
264
284
  end.to raise_error(Capybara::Ambiguous)
265
285
  end
266
- it "raises an error even if there the match is exact and the others are inexact" do
286
+
287
+ it 'raises an error even if there the match is exact and the others are inexact' do
267
288
  expect do
268
- @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("almost_singular")], exact: false, match: :one)
289
+ @session.find(:xpath, XPath.descendant[XPath.attr(:class).is('almost_singular')], exact: false, match: :one)
269
290
  end.to raise_error(Capybara::Ambiguous)
270
291
  end
271
- it "returns the element if there is only one" do
272
- expect(@session.find(:css, ".singular", match: :one).text).to eq("singular")
292
+
293
+ it 'returns the element if there is only one' do
294
+ expect(@session.find(:css, '.singular', match: :one).text).to eq('singular')
273
295
  end
274
- it "raises an error if there is no match" do
296
+
297
+ it 'raises an error if there is no match' do
275
298
  expect do
276
- @session.find(:css, ".does-not-exist", match: :one)
299
+ @session.find(:css, '.does-not-exist', match: :one)
277
300
  end.to raise_error(Capybara::ElementNotFound)
278
301
  end
279
302
  end
280
303
 
281
- context "when set to `first`" do
282
- it "returns the first matched element" do
283
- expect(@session.find(:css, ".multiple", match: :first).text).to eq("multiple one")
304
+ context 'when set to `first`' do
305
+ it 'returns the first matched element' do
306
+ expect(@session.find(:css, '.multiple', match: :first).text).to eq('multiple one')
284
307
  end
285
- it "raises an error if there is no match" do
308
+
309
+ it 'raises an error if there is no match' do
286
310
  expect do
287
- @session.find(:css, ".does-not-exist", match: :first)
311
+ @session.find(:css, '.does-not-exist', match: :first)
288
312
  end.to raise_error(Capybara::ElementNotFound)
289
313
  end
290
314
  end
291
315
 
292
- context "when set to `smart`" do
293
- context "and `exact` set to `false`" do
294
- it "raises an error when there are multiple exact matches" do
316
+ context 'when set to `smart`' do
317
+ context 'and `exact` set to `false`' do
318
+ it 'raises an error when there are multiple exact matches' do
295
319
  expect do
296
- @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("multiple")], match: :smart, exact: false)
320
+ @session.find(:xpath, XPath.descendant[XPath.attr(:class).is('multiple')], match: :smart, exact: false)
297
321
  end.to raise_error(Capybara::Ambiguous)
298
322
  end
299
- it "finds a single exact match when there also are inexact matches" do
300
- result = @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("almost_singular")], match: :smart, exact: false)
301
- expect(result.text).to eq("almost singular")
323
+
324
+ it 'finds a single exact match when there also are inexact matches' do
325
+ result = @session.find(:xpath, XPath.descendant[XPath.attr(:class).is('almost_singular')], match: :smart, exact: false)
326
+ expect(result.text).to eq('almost singular')
302
327
  end
303
- it "raises an error when there are multiple inexact matches" do
328
+
329
+ it 'raises an error when there are multiple inexact matches' do
304
330
  expect do
305
- @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("almost_singul")], match: :smart, exact: false)
331
+ @session.find(:xpath, XPath.descendant[XPath.attr(:class).is('almost_singul')], match: :smart, exact: false)
306
332
  end.to raise_error(Capybara::Ambiguous)
307
333
  end
308
- it "finds a single inexact match" do
309
- result = @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("almost_singular but")], match: :smart, exact: false)
310
- expect(result.text).to eq("almost singular but not quite")
334
+
335
+ it 'finds a single inexact match' do
336
+ result = @session.find(:xpath, XPath.descendant[XPath.attr(:class).is('almost_singular but')], match: :smart, exact: false)
337
+ expect(result.text).to eq('almost singular but not quite')
311
338
  end
312
- it "raises an error if there is no match" do
339
+
340
+ it 'raises an error if there is no match' do
313
341
  expect do
314
- @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("does-not-exist")], match: :smart, exact: false)
342
+ @session.find(:xpath, XPath.descendant[XPath.attr(:class).is('does-not-exist')], match: :smart, exact: false)
315
343
  end.to raise_error(Capybara::ElementNotFound)
316
344
  end
317
345
  end
318
346
 
319
- context "with `exact` set to `true`" do
320
- it "raises an error when there are multiple exact matches" do
347
+ context 'with `exact` set to `true`' do
348
+ it 'raises an error when there are multiple exact matches' do
321
349
  expect do
322
- @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("multiple")], match: :smart, exact: true)
350
+ @session.find(:xpath, XPath.descendant[XPath.attr(:class).is('multiple')], match: :smart, exact: true)
323
351
  end.to raise_error(Capybara::Ambiguous)
324
352
  end
325
- it "finds a single exact match when there also are inexact matches" do
326
- result = @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("almost_singular")], match: :smart, exact: true)
327
- expect(result.text).to eq("almost singular")
353
+
354
+ it 'finds a single exact match when there also are inexact matches' do
355
+ result = @session.find(:xpath, XPath.descendant[XPath.attr(:class).is('almost_singular')], match: :smart, exact: true)
356
+ expect(result.text).to eq('almost singular')
328
357
  end
329
- it "raises an error when there are multiple inexact matches" do
358
+
359
+ it 'raises an error when there are multiple inexact matches' do
330
360
  expect do
331
- @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("almost_singul")], match: :smart, exact: true)
361
+ @session.find(:xpath, XPath.descendant[XPath.attr(:class).is('almost_singul')], match: :smart, exact: true)
332
362
  end.to raise_error(Capybara::ElementNotFound)
333
363
  end
334
- it "raises an error when there is a single inexact matches" do
364
+
365
+ it 'raises an error when there is a single inexact matches' do
335
366
  expect do
336
- @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("almost_singular but")], match: :smart, exact: true)
367
+ @session.find(:xpath, XPath.descendant[XPath.attr(:class).is('almost_singular but')], match: :smart, exact: true)
337
368
  end.to raise_error(Capybara::ElementNotFound)
338
369
  end
339
- it "raises an error if there is no match" do
370
+
371
+ it 'raises an error if there is no match' do
340
372
  expect do
341
- @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("does-not-exist")], match: :smart, exact: true)
373
+ @session.find(:xpath, XPath.descendant[XPath.attr(:class).is('does-not-exist')], match: :smart, exact: true)
342
374
  end.to raise_error(Capybara::ElementNotFound)
343
375
  end
344
376
  end
345
377
  end
346
378
 
347
- context "when set to `prefer_exact`" do
348
- context "and `exact` set to `false`" do
349
- it "picks the first one when there are multiple exact matches" do
350
- result = @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("multiple")], match: :prefer_exact, exact: false)
351
- expect(result.text).to eq("multiple one")
379
+ context 'when set to `prefer_exact`' do
380
+ context 'and `exact` set to `false`' do
381
+ it 'picks the first one when there are multiple exact matches' do
382
+ result = @session.find(:xpath, XPath.descendant[XPath.attr(:class).is('multiple')], match: :prefer_exact, exact: false)
383
+ expect(result.text).to eq('multiple one')
352
384
  end
353
- it "finds a single exact match when there also are inexact matches" do
354
- result = @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("almost_singular")], match: :prefer_exact, exact: false)
355
- expect(result.text).to eq("almost singular")
385
+
386
+ it 'finds a single exact match when there also are inexact matches' do
387
+ result = @session.find(:xpath, XPath.descendant[XPath.attr(:class).is('almost_singular')], match: :prefer_exact, exact: false)
388
+ expect(result.text).to eq('almost singular')
356
389
  end
357
- it "picks the first one when there are multiple inexact matches" do
358
- result = @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("almost_singul")], match: :prefer_exact, exact: false)
359
- expect(result.text).to eq("almost singular but not quite")
390
+
391
+ it 'picks the first one when there are multiple inexact matches' do
392
+ result = @session.find(:xpath, XPath.descendant[XPath.attr(:class).is('almost_singul')], match: :prefer_exact, exact: false)
393
+ expect(result.text).to eq('almost singular but not quite')
360
394
  end
361
- it "finds a single inexact match" do
362
- result = @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("almost_singular but")], match: :prefer_exact, exact: false)
363
- expect(result.text).to eq("almost singular but not quite")
395
+
396
+ it 'finds a single inexact match' do
397
+ result = @session.find(:xpath, XPath.descendant[XPath.attr(:class).is('almost_singular but')], match: :prefer_exact, exact: false)
398
+ expect(result.text).to eq('almost singular but not quite')
364
399
  end
365
- it "raises an error if there is no match" do
400
+
401
+ it 'raises an error if there is no match' do
366
402
  expect do
367
- @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("does-not-exist")], match: :prefer_exact, exact: false)
403
+ @session.find(:xpath, XPath.descendant[XPath.attr(:class).is('does-not-exist')], match: :prefer_exact, exact: false)
368
404
  end.to raise_error(Capybara::ElementNotFound)
369
405
  end
370
406
  end
371
407
 
372
- context "with `exact` set to `true`" 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: true)
375
- expect(result.text).to eq("multiple one")
408
+ context 'with `exact` set to `true`' do
409
+ it 'picks the first one when there are multiple exact matches' do
410
+ result = @session.find(:xpath, XPath.descendant[XPath.attr(:class).is('multiple')], match: :prefer_exact, exact: true)
411
+ expect(result.text).to eq('multiple one')
376
412
  end
377
- it "finds a single exact match when there also are inexact matches" do
378
- result = @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("almost_singular")], match: :prefer_exact, exact: true)
379
- expect(result.text).to eq("almost singular")
413
+
414
+ it 'finds a single exact match when there also are inexact matches' do
415
+ result = @session.find(:xpath, XPath.descendant[XPath.attr(:class).is('almost_singular')], match: :prefer_exact, exact: true)
416
+ expect(result.text).to eq('almost singular')
380
417
  end
381
- it "raises an error if there are multiple inexact matches" do
418
+
419
+ it 'raises an error if there are multiple inexact matches' do
382
420
  expect do
383
- @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("almost_singul")], match: :prefer_exact, exact: true)
421
+ @session.find(:xpath, XPath.descendant[XPath.attr(:class).is('almost_singul')], match: :prefer_exact, exact: true)
384
422
  end.to raise_error(Capybara::ElementNotFound)
385
423
  end
386
- it "raises an error if there is a single inexact match" do
424
+
425
+ it 'raises an error if there is a single inexact match' do
387
426
  expect do
388
- @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("almost_singular but")], match: :prefer_exact, exact: true)
427
+ @session.find(:xpath, XPath.descendant[XPath.attr(:class).is('almost_singular but')], match: :prefer_exact, exact: true)
389
428
  end.to raise_error(Capybara::ElementNotFound)
390
429
  end
391
- it "raises an error if there is no match" do
430
+
431
+ it 'raises an error if there is no match' do
392
432
  expect do
393
- @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("does-not-exist")], match: :prefer_exact, exact: true)
433
+ @session.find(:xpath, XPath.descendant[XPath.attr(:class).is('does-not-exist')], match: :prefer_exact, exact: true)
394
434
  end.to raise_error(Capybara::ElementNotFound)
395
435
  end
396
436
  end
397
437
  end
398
438
 
399
- it "defaults to `Capybara.match`" do
439
+ it 'defaults to `Capybara.match`' do
400
440
  Capybara.match = :one
401
441
  expect do
402
- @session.find(:css, ".multiple")
442
+ @session.find(:css, '.multiple')
403
443
  end.to raise_error(Capybara::Ambiguous)
404
444
  Capybara.match = :first
405
- expect(@session.find(:css, ".multiple").text).to eq("multiple one")
445
+ expect(@session.find(:css, '.multiple').text).to eq('multiple one')
406
446
  end
407
447
 
408
- it "raises an error when unknown option given" do
448
+ it 'raises an error when unknown option given' do
409
449
  expect do
410
- @session.find(:css, ".singular", match: :schmoo)
450
+ @session.find(:css, '.singular', match: :schmoo)
411
451
  end.to raise_error(ArgumentError)
412
452
  end
413
453
  end
414
454
 
415
- it "supports a custom filter block" do
455
+ it 'supports a custom filter block' do
416
456
  expect(@session.find(:css, 'input', &:disabled?)[:name]).to eq('disabled_text')
417
457
  end
418
458
 
419
- context "within a scope" do
459
+ context 'with spatial filters', requires: [:spatial] do
460
+ before do
461
+ @session.visit('/spatial')
462
+ end
463
+
464
+ let :center do
465
+ @session.find(:css, 'div.center')
466
+ end
467
+
468
+ it 'should find an element above another element' do
469
+ expect(@session.find(:css, 'div:not(.corner)', above: center).text).to eq('2')
470
+ end
471
+
472
+ it 'should find an element below another element' do
473
+ expect(@session.find(:css, 'div:not(.corner):not(.footer)', below: center).text).to eq('8')
474
+ end
475
+
476
+ it 'should find an element left of another element' do
477
+ expect(@session.find(:css, 'div:not(.corner)', left_of: center).text).to eq('4')
478
+ end
479
+
480
+ it 'should find an element right of another element' do
481
+ expect(@session.find(:css, 'div:not(.corner)', right_of: center).text).to eq('6')
482
+ end
483
+
484
+ it 'should combine spatial filters' do
485
+ expect(@session.find(:css, 'div', left_of: center, above: center).text).to eq('1')
486
+ expect(@session.find(:css, 'div', right_of: center, below: center).text).to eq('9')
487
+ end
488
+
489
+ it 'should find an element "near" another element' do
490
+ expect(@session.find(:css, 'div.distance', near: center).text).to eq('2')
491
+ end
492
+ end
493
+
494
+ context 'within a scope' do
420
495
  before do
421
496
  @session.visit('/with_scope')
422
497
  end
423
498
 
424
- it "should find the an element using the given locator" do
499
+ it 'should find the an element using the given locator' do
425
500
  @session.within(:xpath, "//div[@id='for_bar']") do
426
501
  expect(@session.find('.//li[1]').text).to match(/With Simple HTML/)
427
502
  end
428
503
  end
429
504
 
430
- it "should support pseudo selectors" do
505
+ it 'should support pseudo selectors' do
431
506
  @session.within(:xpath, "//div[@id='for_bar']") do
432
507
  expect(@session.find(:css, 'input:disabled').value).to eq('James')
433
508
  end
434
509
  end
435
510
  end
436
511
 
437
- it "should raise if selector type is unknown" do
512
+ it 'should raise if selector type is unknown' do
438
513
  expect do
439
514
  @session.find(:unknown, '//h1')
440
515
  end.to raise_error(ArgumentError)
441
516
  end
517
+
518
+ context 'with Capybara.test_id' do
519
+ it 'should not match on it when nil' do
520
+ Capybara.test_id = nil
521
+ expect(@session).not_to have_field('test_id')
522
+ end
523
+
524
+ it 'should work with the attribute set to `data-test-id` attribute' do
525
+ Capybara.test_id = 'data-test-id'
526
+ expect(@session.find(:field, 'test_id')[:id]).to eq 'test_field'
527
+ end
528
+
529
+ it 'should use a different attribute if set' do
530
+ Capybara.test_id = 'data-other-test-id'
531
+ expect(@session.find(:field, 'test_id')[:id]).to eq 'normal'
532
+ end
533
+
534
+ it 'should find a link with the test_id' do
535
+ Capybara.test_id = 'data-test-id'
536
+ expect(@session.find(:link, 'test-foo')[:id]).to eq 'foo'
537
+ end
538
+ end
539
+
540
+ it 'should warn if passed count options' do
541
+ allow(Capybara::Helpers).to receive(:warn)
542
+ @session.find('//h1', count: 44)
543
+ expect(Capybara::Helpers).to have_received(:warn).with(/'find' does not support count options/)
544
+ end
442
545
  end