capybara 2.18.0 → 3.40.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (316) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +1 -1
  3. data/History.md +945 -12
  4. data/License.txt +1 -1
  5. data/README.md +264 -90
  6. data/lib/capybara/config.rb +29 -57
  7. data/lib/capybara/cucumber.rb +2 -3
  8. data/lib/capybara/driver/base.rb +35 -18
  9. data/lib/capybara/driver/node.rb +40 -10
  10. data/lib/capybara/dsl.rb +10 -7
  11. data/lib/capybara/helpers.rb +70 -31
  12. data/lib/capybara/minitest/spec.rb +185 -83
  13. data/lib/capybara/minitest.rb +232 -112
  14. data/lib/capybara/node/actions.rb +274 -171
  15. data/lib/capybara/node/base.rb +42 -34
  16. data/lib/capybara/node/document.rb +15 -3
  17. data/lib/capybara/node/document_matchers.rb +19 -21
  18. data/lib/capybara/node/element.rb +362 -135
  19. data/lib/capybara/node/finders.rb +151 -137
  20. data/lib/capybara/node/matchers.rb +394 -209
  21. data/lib/capybara/node/simple.rb +59 -26
  22. data/lib/capybara/node/whitespace_normalizer.rb +81 -0
  23. data/lib/capybara/queries/active_element_query.rb +18 -0
  24. data/lib/capybara/queries/ancestor_query.rb +12 -9
  25. data/lib/capybara/queries/base_query.rb +39 -28
  26. data/lib/capybara/queries/current_path_query.rb +21 -27
  27. data/lib/capybara/queries/match_query.rb +14 -7
  28. data/lib/capybara/queries/selector_query.rb +659 -149
  29. data/lib/capybara/queries/sibling_query.rb +11 -9
  30. data/lib/capybara/queries/style_query.rb +45 -0
  31. data/lib/capybara/queries/text_query.rb +56 -38
  32. data/lib/capybara/queries/title_query.rb +8 -11
  33. data/lib/capybara/rack_test/browser.rb +114 -42
  34. data/lib/capybara/rack_test/css_handlers.rb +6 -4
  35. data/lib/capybara/rack_test/driver.rb +22 -17
  36. data/lib/capybara/rack_test/errors.rb +6 -0
  37. data/lib/capybara/rack_test/form.rb +93 -58
  38. data/lib/capybara/rack_test/node.rb +184 -81
  39. data/lib/capybara/rails.rb +3 -7
  40. data/lib/capybara/registration_container.rb +41 -0
  41. data/lib/capybara/registrations/drivers.rb +42 -0
  42. data/lib/capybara/registrations/patches/puma_ssl.rb +29 -0
  43. data/lib/capybara/registrations/servers.rb +66 -0
  44. data/lib/capybara/result.rb +97 -63
  45. data/lib/capybara/rspec/features.rb +17 -50
  46. data/lib/capybara/rspec/matcher_proxies.rb +52 -15
  47. data/lib/capybara/rspec/matchers/base.rb +113 -0
  48. data/lib/capybara/rspec/matchers/become_closed.rb +33 -0
  49. data/lib/capybara/rspec/matchers/compound.rb +88 -0
  50. data/lib/capybara/rspec/matchers/count_sugar.rb +37 -0
  51. data/lib/capybara/rspec/matchers/have_ancestor.rb +28 -0
  52. data/lib/capybara/rspec/matchers/have_current_path.rb +29 -0
  53. data/lib/capybara/rspec/matchers/have_selector.rb +69 -0
  54. data/lib/capybara/rspec/matchers/have_sibling.rb +27 -0
  55. data/lib/capybara/rspec/matchers/have_text.rb +33 -0
  56. data/lib/capybara/rspec/matchers/have_title.rb +29 -0
  57. data/lib/capybara/rspec/matchers/match_selector.rb +27 -0
  58. data/lib/capybara/rspec/matchers/match_style.rb +43 -0
  59. data/lib/capybara/rspec/matchers/spatial_sugar.rb +39 -0
  60. data/lib/capybara/rspec/matchers.rb +146 -310
  61. data/lib/capybara/rspec.rb +7 -11
  62. data/lib/capybara/selector/builders/css_builder.rb +84 -0
  63. data/lib/capybara/selector/builders/xpath_builder.rb +71 -0
  64. data/lib/capybara/selector/css.rb +85 -13
  65. data/lib/capybara/selector/definition/button.rb +68 -0
  66. data/lib/capybara/selector/definition/checkbox.rb +26 -0
  67. data/lib/capybara/selector/definition/css.rb +10 -0
  68. data/lib/capybara/selector/definition/datalist_input.rb +35 -0
  69. data/lib/capybara/selector/definition/datalist_option.rb +25 -0
  70. data/lib/capybara/selector/definition/element.rb +28 -0
  71. data/lib/capybara/selector/definition/field.rb +40 -0
  72. data/lib/capybara/selector/definition/fieldset.rb +14 -0
  73. data/lib/capybara/selector/definition/file_field.rb +13 -0
  74. data/lib/capybara/selector/definition/fillable_field.rb +33 -0
  75. data/lib/capybara/selector/definition/frame.rb +17 -0
  76. data/lib/capybara/selector/definition/id.rb +6 -0
  77. data/lib/capybara/selector/definition/label.rb +62 -0
  78. data/lib/capybara/selector/definition/link.rb +55 -0
  79. data/lib/capybara/selector/definition/link_or_button.rb +16 -0
  80. data/lib/capybara/selector/definition/option.rb +27 -0
  81. data/lib/capybara/selector/definition/radio_button.rb +27 -0
  82. data/lib/capybara/selector/definition/select.rb +81 -0
  83. data/lib/capybara/selector/definition/table.rb +109 -0
  84. data/lib/capybara/selector/definition/table_row.rb +21 -0
  85. data/lib/capybara/selector/definition/xpath.rb +5 -0
  86. data/lib/capybara/selector/definition.rb +280 -0
  87. data/lib/capybara/selector/filter.rb +2 -17
  88. data/lib/capybara/selector/filter_set.rb +80 -33
  89. data/lib/capybara/selector/filters/base.rb +50 -6
  90. data/lib/capybara/selector/filters/expression_filter.rb +8 -26
  91. data/lib/capybara/selector/filters/locator_filter.rb +29 -0
  92. data/lib/capybara/selector/filters/node_filter.rb +16 -12
  93. data/lib/capybara/selector/regexp_disassembler.rb +211 -0
  94. data/lib/capybara/selector/selector.rb +93 -210
  95. data/lib/capybara/selector/xpath_extensions.rb +17 -0
  96. data/lib/capybara/selector.rb +475 -523
  97. data/lib/capybara/selenium/atoms/getAttribute.min.js +1 -0
  98. data/lib/capybara/selenium/atoms/isDisplayed.min.js +1 -0
  99. data/lib/capybara/selenium/atoms/src/getAttribute.js +161 -0
  100. data/lib/capybara/selenium/atoms/src/isDisplayed.js +454 -0
  101. data/lib/capybara/selenium/driver.rb +298 -267
  102. data/lib/capybara/selenium/driver_specializations/chrome_driver.rb +117 -0
  103. data/lib/capybara/selenium/driver_specializations/edge_driver.rb +128 -0
  104. data/lib/capybara/selenium/driver_specializations/firefox_driver.rb +84 -0
  105. data/lib/capybara/selenium/driver_specializations/internet_explorer_driver.rb +26 -0
  106. data/lib/capybara/selenium/driver_specializations/safari_driver.rb +24 -0
  107. data/lib/capybara/selenium/extensions/file_input_click_emulation.rb +34 -0
  108. data/lib/capybara/selenium/extensions/find.rb +110 -0
  109. data/lib/capybara/selenium/extensions/html5_drag.rb +229 -0
  110. data/lib/capybara/selenium/extensions/modifier_keys_stack.rb +28 -0
  111. data/lib/capybara/selenium/extensions/scroll.rb +76 -0
  112. data/lib/capybara/selenium/node.rb +517 -145
  113. data/lib/capybara/selenium/nodes/chrome_node.rb +125 -0
  114. data/lib/capybara/selenium/nodes/edge_node.rb +110 -0
  115. data/lib/capybara/selenium/nodes/firefox_node.rb +136 -0
  116. data/lib/capybara/selenium/nodes/ie_node.rb +22 -0
  117. data/lib/capybara/selenium/nodes/safari_node.rb +118 -0
  118. data/lib/capybara/selenium/patches/atoms.rb +18 -0
  119. data/lib/capybara/selenium/patches/is_displayed.rb +16 -0
  120. data/lib/capybara/selenium/patches/logs.rb +45 -0
  121. data/lib/capybara/selenium/patches/pause_duration_fix.rb +9 -0
  122. data/lib/capybara/selenium/patches/persistent_client.rb +20 -0
  123. data/lib/capybara/server/animation_disabler.rb +80 -0
  124. data/lib/capybara/server/checker.rb +44 -0
  125. data/lib/capybara/server/middleware.rb +71 -0
  126. data/lib/capybara/server.rb +59 -67
  127. data/lib/capybara/session/config.rb +81 -67
  128. data/lib/capybara/session/matchers.rb +28 -20
  129. data/lib/capybara/session.rb +337 -365
  130. data/lib/capybara/spec/public/jquery.js +5 -5
  131. data/lib/capybara/spec/public/offset.js +6 -0
  132. data/lib/capybara/spec/public/test.js +151 -12
  133. data/lib/capybara/spec/session/accept_alert_spec.rb +12 -11
  134. data/lib/capybara/spec/session/accept_confirm_spec.rb +6 -5
  135. data/lib/capybara/spec/session/accept_prompt_spec.rb +10 -10
  136. data/lib/capybara/spec/session/active_element_spec.rb +31 -0
  137. data/lib/capybara/spec/session/all_spec.rb +161 -57
  138. data/lib/capybara/spec/session/ancestor_spec.rb +27 -24
  139. data/lib/capybara/spec/session/assert_all_of_selectors_spec.rb +68 -38
  140. data/lib/capybara/spec/session/assert_current_path_spec.rb +75 -0
  141. data/lib/capybara/spec/session/assert_selector_spec.rb +143 -0
  142. data/lib/capybara/spec/session/assert_style_spec.rb +26 -0
  143. data/lib/capybara/spec/session/assert_text_spec.rb +258 -0
  144. data/lib/capybara/spec/session/{assert_title.rb → assert_title_spec.rb} +22 -12
  145. data/lib/capybara/spec/session/attach_file_spec.rb +144 -69
  146. data/lib/capybara/spec/session/body_spec.rb +12 -13
  147. data/lib/capybara/spec/session/check_spec.rb +117 -55
  148. data/lib/capybara/spec/session/choose_spec.rb +64 -31
  149. data/lib/capybara/spec/session/click_button_spec.rb +231 -173
  150. data/lib/capybara/spec/session/click_link_or_button_spec.rb +55 -35
  151. data/lib/capybara/spec/session/click_link_spec.rb +93 -58
  152. data/lib/capybara/spec/session/current_scope_spec.rb +12 -11
  153. data/lib/capybara/spec/session/current_url_spec.rb +57 -39
  154. data/lib/capybara/spec/session/dismiss_confirm_spec.rb +4 -4
  155. data/lib/capybara/spec/session/dismiss_prompt_spec.rb +3 -2
  156. data/lib/capybara/spec/session/element/{assert_match_selector.rb → assert_match_selector_spec.rb} +11 -9
  157. data/lib/capybara/spec/session/element/match_css_spec.rb +18 -10
  158. data/lib/capybara/spec/session/element/match_xpath_spec.rb +9 -7
  159. data/lib/capybara/spec/session/element/matches_selector_spec.rb +71 -57
  160. data/lib/capybara/spec/session/evaluate_async_script_spec.rb +8 -7
  161. data/lib/capybara/spec/session/evaluate_script_spec.rb +29 -8
  162. data/lib/capybara/spec/session/execute_script_spec.rb +10 -8
  163. data/lib/capybara/spec/session/fill_in_spec.rb +134 -43
  164. data/lib/capybara/spec/session/find_button_spec.rb +25 -24
  165. data/lib/capybara/spec/session/find_by_id_spec.rb +10 -9
  166. data/lib/capybara/spec/session/find_field_spec.rb +37 -41
  167. data/lib/capybara/spec/session/find_link_spec.rb +46 -17
  168. data/lib/capybara/spec/session/find_spec.rb +260 -145
  169. data/lib/capybara/spec/session/first_spec.rb +80 -52
  170. data/lib/capybara/spec/session/frame/frame_title_spec.rb +23 -0
  171. data/lib/capybara/spec/session/frame/frame_url_spec.rb +23 -0
  172. data/lib/capybara/spec/session/frame/switch_to_frame_spec.rb +33 -20
  173. data/lib/capybara/spec/session/frame/within_frame_spec.rb +52 -32
  174. data/lib/capybara/spec/session/go_back_spec.rb +2 -1
  175. data/lib/capybara/spec/session/go_forward_spec.rb +2 -1
  176. data/lib/capybara/spec/session/has_all_selectors_spec.rb +31 -31
  177. data/lib/capybara/spec/session/has_ancestor_spec.rb +46 -0
  178. data/lib/capybara/spec/session/has_any_selectors_spec.rb +29 -0
  179. data/lib/capybara/spec/session/has_button_spec.rb +100 -13
  180. data/lib/capybara/spec/session/has_css_spec.rb +272 -137
  181. data/lib/capybara/spec/session/has_current_path_spec.rb +60 -61
  182. data/lib/capybara/spec/session/has_element_spec.rb +47 -0
  183. data/lib/capybara/spec/session/has_field_spec.rb +139 -59
  184. data/lib/capybara/spec/session/has_link_spec.rb +47 -6
  185. data/lib/capybara/spec/session/has_none_selectors_spec.rb +42 -40
  186. data/lib/capybara/spec/session/has_select_spec.rb +107 -72
  187. data/lib/capybara/spec/session/has_selector_spec.rb +120 -71
  188. data/lib/capybara/spec/session/has_sibling_spec.rb +50 -0
  189. data/lib/capybara/spec/session/has_table_spec.rb +183 -5
  190. data/lib/capybara/spec/session/has_text_spec.rb +106 -62
  191. data/lib/capybara/spec/session/has_title_spec.rb +20 -14
  192. data/lib/capybara/spec/session/has_xpath_spec.rb +57 -38
  193. data/lib/capybara/spec/session/{headers.rb → headers_spec.rb} +3 -2
  194. data/lib/capybara/spec/session/html_spec.rb +14 -6
  195. data/lib/capybara/spec/session/matches_style_spec.rb +37 -0
  196. data/lib/capybara/spec/session/node_spec.rb +1024 -153
  197. data/lib/capybara/spec/session/node_wrapper_spec.rb +39 -0
  198. data/lib/capybara/spec/session/refresh_spec.rb +12 -6
  199. data/lib/capybara/spec/session/reset_session_spec.rb +82 -35
  200. data/lib/capybara/spec/session/{response_code.rb → response_code_spec.rb} +2 -1
  201. data/lib/capybara/spec/session/save_and_open_page_spec.rb +3 -2
  202. data/lib/capybara/spec/session/save_and_open_screenshot_spec.rb +8 -12
  203. data/lib/capybara/spec/session/save_page_spec.rb +42 -55
  204. data/lib/capybara/spec/session/save_screenshot_spec.rb +16 -14
  205. data/lib/capybara/spec/session/screenshot_spec.rb +2 -2
  206. data/lib/capybara/spec/session/scroll_spec.rb +119 -0
  207. data/lib/capybara/spec/session/select_spec.rb +107 -81
  208. data/lib/capybara/spec/session/selectors_spec.rb +52 -19
  209. data/lib/capybara/spec/session/sibling_spec.rb +10 -10
  210. data/lib/capybara/spec/session/text_spec.rb +37 -21
  211. data/lib/capybara/spec/session/title_spec.rb +17 -5
  212. data/lib/capybara/spec/session/uncheck_spec.rb +43 -23
  213. data/lib/capybara/spec/session/unselect_spec.rb +39 -38
  214. data/lib/capybara/spec/session/visit_spec.rb +85 -53
  215. data/lib/capybara/spec/session/window/become_closed_spec.rb +24 -20
  216. data/lib/capybara/spec/session/window/current_window_spec.rb +5 -3
  217. data/lib/capybara/spec/session/window/open_new_window_spec.rb +5 -3
  218. data/lib/capybara/spec/session/window/switch_to_window_spec.rb +27 -22
  219. data/lib/capybara/spec/session/window/window_opened_by_spec.rb +12 -6
  220. data/lib/capybara/spec/session/window/window_spec.rb +97 -63
  221. data/lib/capybara/spec/session/window/windows_spec.rb +12 -10
  222. data/lib/capybara/spec/session/window/within_window_spec.rb +31 -86
  223. data/lib/capybara/spec/session/within_spec.rb +83 -44
  224. data/lib/capybara/spec/spec_helper.rb +54 -44
  225. data/lib/capybara/spec/test_app.rb +158 -43
  226. data/lib/capybara/spec/views/animated.erb +49 -0
  227. data/lib/capybara/spec/views/form.erb +163 -42
  228. data/lib/capybara/spec/views/frame_child.erb +4 -3
  229. data/lib/capybara/spec/views/frame_one.erb +2 -1
  230. data/lib/capybara/spec/views/frame_parent.erb +1 -1
  231. data/lib/capybara/spec/views/frame_two.erb +1 -1
  232. data/lib/capybara/spec/views/initial_alert.erb +2 -1
  233. data/lib/capybara/spec/views/layout.erb +10 -0
  234. data/lib/capybara/spec/views/obscured.erb +47 -0
  235. data/lib/capybara/spec/views/offset.erb +33 -0
  236. data/lib/capybara/spec/views/path.erb +2 -2
  237. data/lib/capybara/spec/views/popup_one.erb +1 -1
  238. data/lib/capybara/spec/views/popup_two.erb +1 -1
  239. data/lib/capybara/spec/views/react.erb +45 -0
  240. data/lib/capybara/spec/views/scroll.erb +21 -0
  241. data/lib/capybara/spec/views/spatial.erb +31 -0
  242. data/lib/capybara/spec/views/tables.erb +68 -1
  243. data/lib/capybara/spec/views/with_animation.erb +81 -0
  244. data/lib/capybara/spec/views/with_base_tag.erb +2 -2
  245. data/lib/capybara/spec/views/with_dragula.erb +24 -0
  246. data/lib/capybara/spec/views/with_fixed_header_footer.erb +2 -1
  247. data/lib/capybara/spec/views/with_hover.erb +3 -2
  248. data/lib/capybara/spec/views/with_hover1.erb +10 -0
  249. data/lib/capybara/spec/views/with_html.erb +69 -12
  250. data/lib/capybara/spec/views/with_html5_svg.erb +20 -0
  251. data/lib/capybara/spec/views/with_jquery_animation.erb +24 -0
  252. data/lib/capybara/spec/views/with_js.erb +30 -5
  253. data/lib/capybara/spec/views/with_jstree.erb +26 -0
  254. data/lib/capybara/spec/views/with_namespace.erb +21 -0
  255. data/lib/capybara/spec/views/with_scope.erb +2 -2
  256. data/lib/capybara/spec/views/with_scope_other.erb +6 -0
  257. data/lib/capybara/spec/views/with_shadow.erb +31 -0
  258. data/lib/capybara/spec/views/with_slow_unload.erb +2 -1
  259. data/lib/capybara/spec/views/with_sortable_js.erb +21 -0
  260. data/lib/capybara/spec/views/with_unload_alert.erb +1 -0
  261. data/lib/capybara/spec/views/with_windows.erb +1 -1
  262. data/lib/capybara/spec/views/within_frames.erb +5 -2
  263. data/lib/capybara/version.rb +2 -1
  264. data/lib/capybara/window.rb +36 -34
  265. data/lib/capybara.rb +134 -107
  266. data/spec/basic_node_spec.rb +60 -34
  267. data/spec/capybara_spec.rb +63 -88
  268. data/spec/counter_spec.rb +35 -0
  269. data/spec/css_builder_spec.rb +101 -0
  270. data/spec/css_splitter_spec.rb +38 -0
  271. data/spec/dsl_spec.rb +85 -64
  272. data/spec/filter_set_spec.rb +27 -9
  273. data/spec/fixtures/certificate.pem +25 -0
  274. data/spec/fixtures/key.pem +27 -0
  275. data/spec/fixtures/selenium_driver_rspec_failure.rb +6 -5
  276. data/spec/fixtures/selenium_driver_rspec_success.rb +6 -5
  277. data/spec/minitest_spec.rb +52 -7
  278. data/spec/minitest_spec_spec.rb +94 -63
  279. data/spec/per_session_config_spec.rb +14 -13
  280. data/spec/rack_test_spec.rb +194 -125
  281. data/spec/regexp_dissassembler_spec.rb +250 -0
  282. data/spec/result_spec.rb +111 -50
  283. data/spec/rspec/features_spec.rb +37 -31
  284. data/spec/rspec/scenarios_spec.rb +10 -8
  285. data/spec/rspec/shared_spec_matchers.rb +473 -422
  286. data/spec/rspec/views_spec.rb +5 -3
  287. data/spec/rspec_matchers_spec.rb +52 -11
  288. data/spec/rspec_spec.rb +109 -89
  289. data/spec/sauce_spec_chrome.rb +43 -0
  290. data/spec/selector_spec.rb +397 -68
  291. data/spec/selenium_spec_chrome.rb +187 -40
  292. data/spec/selenium_spec_chrome_remote.rb +96 -0
  293. data/spec/selenium_spec_edge.rb +60 -0
  294. data/spec/selenium_spec_firefox.rb +201 -41
  295. data/spec/selenium_spec_firefox_remote.rb +94 -0
  296. data/spec/selenium_spec_ie.rb +149 -0
  297. data/spec/selenium_spec_safari.rb +162 -0
  298. data/spec/server_spec.rb +213 -102
  299. data/spec/session_spec.rb +53 -16
  300. data/spec/shared_selenium_node.rb +79 -0
  301. data/spec/shared_selenium_session.rb +473 -122
  302. data/spec/spec_helper.rb +126 -7
  303. data/spec/whitespace_normalizer_spec.rb +54 -0
  304. data/spec/xpath_builder_spec.rb +93 -0
  305. metadata +355 -73
  306. data/.yard/templates_custom/default/class/html/selectors.erb +0 -38
  307. data/.yard/templates_custom/default/class/html/setup.rb +0 -17
  308. data/.yard/yard_extensions.rb +0 -78
  309. data/lib/capybara/query.rb +0 -7
  310. data/lib/capybara/rspec/compound.rb +0 -95
  311. data/lib/capybara/spec/session/assert_current_path.rb +0 -72
  312. data/lib/capybara/spec/session/assert_selector.rb +0 -148
  313. data/lib/capybara/spec/session/assert_text.rb +0 -234
  314. data/lib/capybara/spec/session/source_spec.rb +0 -0
  315. data/lib/capybara/spec/views/with_title.erb +0 -5
  316. data/spec/selenium_spec_marionette.rb +0 -127
@@ -1,125 +1,259 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  Capybara::SpecHelper.spec '#has_css?' do
3
4
  before do
4
5
  @session.visit('/with_html')
5
6
  end
6
7
 
7
- it "should be true if the given selector is on the page" do
8
- expect(@session).to have_css("p")
9
- expect(@session).to have_css("p a#foo")
8
+ it 'should be true if the given selector is on the page' do
9
+ expect(@session).to have_css('p')
10
+ expect(@session).to have_css('p a#foo')
10
11
  end
11
12
 
12
- it "should be false if the given selector is not on the page" do
13
- expect(@session).not_to have_css("abbr")
14
- expect(@session).not_to have_css("p a#doesnotexist")
15
- expect(@session).not_to have_css("p.nosuchclass")
13
+ it 'should warn when passed a symbol' do
14
+ # This was never a specifically accepted format but it has worked for a
15
+ # lot of versions.
16
+ # TODO: Remove in 4.0
17
+ allow(Capybara::Helpers).to receive(:warn).and_return(nil)
18
+ expect(@session).to have_css(:p)
19
+ expect(Capybara::Helpers).to have_received(:warn)
16
20
  end
17
21
 
18
- it "should respect scopes" do
19
- @session.within "//p[@id='first']" do
20
- expect(@session).to have_css("a#foo")
21
- expect(@session).not_to have_css("a#red")
22
+ it 'should be false if the given selector is not on the page' do
23
+ expect(@session).not_to have_css('abbr')
24
+ expect(@session).not_to have_css('p a#doesnotexist')
25
+ expect(@session).not_to have_css('p.nosuchclass')
26
+ end
27
+
28
+ it 'should support :id option' do
29
+ expect(@session).to have_css('h2', id: 'h2one')
30
+ expect(@session).to have_css('h2')
31
+ expect(@session).to have_css('h2', id: /h2o/)
32
+ expect(@session).to have_css('li', id: /john|paul/)
33
+ end
34
+
35
+ it 'should support :class option' do
36
+ expect(@session).to have_css('li', class: 'guitarist')
37
+ expect(@session).to have_css('li', class: /guitar/)
38
+ expect(@session).to have_css('li', class: /guitar|drummer/)
39
+ expect(@session).to have_css('li', class: %w[beatle guitarist])
40
+ expect(@session).to have_css('li', class: /.*/)
41
+ end
42
+
43
+ context ':style option' do
44
+ it 'should support String' do
45
+ expect(@session).to have_css('p', style: 'line-height: 25px;')
46
+
47
+ expect do
48
+ expect(@session).to have_css('p', style: 'display: not_valid')
49
+ end.to raise_error(RSpec::Expectations::ExpectationNotMetError, /style attribute "display: not_valid"/)
50
+ end
51
+
52
+ it 'should support Regexp' do
53
+ expect(@session).to have_css('p', style: /-height: 2/)
54
+
55
+ expect do
56
+ expect(@session).to have_css('p', style: /not_valid/)
57
+ end.to raise_error(RSpec::Expectations::ExpectationNotMetError, %r{style attribute matching /not_valid/})
58
+ end
59
+
60
+ it 'should support Hash', requires: [:css] do
61
+ expect(@session).to have_css('p', style: { 'line-height': '25px' })
62
+
63
+ expect do
64
+ expect(@session).to have_css('p', style: { 'line-height': '30px' })
65
+ end.to raise_error(RSpec::Expectations::ExpectationNotMetError, /with styles \{:"line-height"=>"30px"\}/)
66
+ end
67
+ end
68
+
69
+ it 'should support case insensitive :class and :id options' do
70
+ expect(@session).to have_css('li', class: /UiTaRI/i)
71
+ expect(@session).to have_css('h2', id: /2ON/i)
72
+ end
73
+
74
+ context 'when scoped' do
75
+ it 'should look in the scope' do
76
+ @session.within "//p[@id='first']" do
77
+ expect(@session).to have_css('a#foo')
78
+ expect(@session).not_to have_css('a#red')
79
+ end
80
+ end
81
+
82
+ it 'should be able to generate an error message if the scope is a sibling' do
83
+ el = @session.find(:css, '#first')
84
+ @session.within el.sibling(:css, '#second') do
85
+ expect do
86
+ expect(@session).to have_css('a#not_on_page')
87
+ end.to raise_error(/there were no matches/)
88
+ end
89
+ end
90
+
91
+ it 'should be able to generate an error message if the scope is a sibling from XPath' do
92
+ el = @session.find(:css, '#first').find(:xpath, './following-sibling::*[1]') do
93
+ expect do
94
+ expect(el).to have_css('a#not_on_page')
95
+ end.to raise_error(/there were no matches/)
96
+ end
22
97
  end
23
98
  end
24
99
 
25
- it "should wait for content to appear", requires: [:js] do
100
+ it 'should wait for content to appear', requires: [:js] do
101
+ Capybara.default_max_wait_time = 2
26
102
  @session.visit('/with_js')
27
103
  @session.click_link('Click me')
28
104
  expect(@session).to have_css("input[type='submit'][value='New Here']")
29
105
  end
30
106
 
31
- context "with between" do
32
- it "should be true if the content occurs within the range given" do
33
- expect(@session).to have_css("p", between: 1..4)
34
- expect(@session).to have_css("p a#foo", between: 1..3)
35
- expect(@session).to have_css("p a.doesnotexist", between: 0..8)
107
+ context 'with predicates_wait == true' do
108
+ it 'should wait for content to appear', requires: [:js] do
109
+ Capybara.predicates_wait = true
110
+ Capybara.default_max_wait_time = 2
111
+ @session.visit('/with_js')
112
+ @session.click_link('Click me')
113
+ expect(@session.has_css?("input[type='submit'][value='New Here']")).to be true
114
+ end
115
+ end
116
+
117
+ context 'with predicates_wait == false' do
118
+ before do
119
+ Capybara.predicates_wait = false
120
+ Capybara.default_max_wait_time = 5
121
+ @session.visit('/with_js')
122
+ @session.click_link('Click me')
123
+ end
124
+
125
+ it 'should not wait for content to appear', requires: [:js] do
126
+ expect(@session.has_css?("input[type='submit'][value='New Here']")).to be false
127
+ end
128
+
129
+ it 'should should the default wait time if true is passed for :wait', requires: [:js] do
130
+ expect(@session.has_css?("input[type='submit'][value='New Here']", wait: true)).to be true
131
+ end
132
+ end
133
+
134
+ context 'with between' do
135
+ it 'should be true if the content occurs within the range given' do
136
+ expect(@session).to have_css('p', between: 1..4)
137
+ expect(@session).to have_css('p a#foo', between: 1..3)
138
+ expect(@session).to have_css('p a.doesnotexist', between: 0..8)
36
139
  end
37
140
 
38
- it "should be false if the content occurs more or fewer times than range" do
39
- expect(@session).not_to have_css("p", between: 6..11 )
40
- expect(@session).not_to have_css("p a#foo", between: 4..7)
41
- expect(@session).not_to have_css("p a.doesnotexist", between: 3..8)
141
+ it 'should be false if the content occurs more or fewer times than range' do
142
+ expect(@session).not_to have_css('p', between: 6..11)
143
+ expect(@session).not_to have_css('p a#foo', between: 4..7)
144
+ expect(@session).not_to have_css('p a.doesnotexist', between: 3..8)
42
145
  end
43
146
  end
44
147
 
45
- context "with count" do
46
- it "should be true if the content occurs the given number of times" do
47
- expect(@session).to have_css("p", count: 3)
48
- expect(@session).to have_css("p a#foo", count: 1)
49
- expect(@session).to have_css("p a.doesnotexist", count: 0)
148
+ context 'with count' do
149
+ it 'should be true if the content occurs the given number of times' do
150
+ expect(@session).to have_css('p', count: 3)
151
+ expect(@session).to have_css('p').exactly(3).times
152
+ expect(@session).to have_css('p a#foo', count: 1)
153
+ expect(@session).to have_css('p a#foo').once
154
+ expect(@session).to have_css('p a.doesnotexist', count: 0)
155
+ expect(@session).to have_css('li', class: /guitar|drummer/, count: 4)
156
+ expect(@session).to have_css('li', id: /john|paul/, class: /guitar|drummer/, count: 2)
157
+ expect(@session).to have_css('li', class: %w[beatle guitarist], count: 2)
158
+ expect(@session).to have_css('p', style: 'line-height: 25px;', count: 1)
159
+ expect(@session).to have_css('p', style: /-height: 2/, count: 1)
160
+ end
161
+
162
+ it 'should be true if the content occurs the given number of times in CSS processing drivers', requires: [:css] do
163
+ expect(@session).to have_css('p', style: { 'line-height': '25px' }, count: 1)
50
164
  end
51
165
 
52
- it "should be false if the content occurs a different number of times than the given" do
53
- expect(@session).not_to have_css("p", count: 6)
54
- expect(@session).not_to have_css("p a#foo", count: 2)
55
- expect(@session).not_to have_css("p a.doesnotexist", count: 1)
166
+ it 'should be false if the content occurs a different number of times than the given' do
167
+ expect(@session).not_to have_css('p', count: 6)
168
+ expect(@session).not_to have_css('p').exactly(5).times
169
+ expect(@session).not_to have_css('p a#foo', count: 2)
170
+ expect(@session).not_to have_css('p a.doesnotexist', count: 1)
56
171
  end
57
172
 
58
- it "should coerce count to an integer" do
59
- expect(@session).to have_css("p", count: "3")
60
- expect(@session).to have_css("p a#foo", count: "1")
173
+ it 'should coerce count to an integer' do
174
+ expect(@session).to have_css('p', count: '3')
175
+ expect(@session).to have_css('p a#foo', count: '1')
61
176
  end
62
177
  end
63
178
 
64
- context "with maximum" do
65
- it "should be true when content occurs same or fewer times than given" do
66
- expect(@session).to have_css("h2.head", maximum: 5) # edge case
67
- expect(@session).to have_css("h2", maximum: 10)
68
- expect(@session).to have_css("p a.doesnotexist", maximum: 1)
69
- expect(@session).to have_css("p a.doesnotexist", maximum: 0)
179
+ context 'with maximum' do
180
+ it 'should be true when content occurs same or fewer times than given' do
181
+ expect(@session).to have_css('h2.head', maximum: 5) # edge case
182
+ expect(@session).to have_css('h2', maximum: 10)
183
+ expect(@session).to have_css('h2').at_most(10).times
184
+ expect(@session).to have_css('p a.doesnotexist', maximum: 1)
185
+ expect(@session).to have_css('p a.doesnotexist', maximum: 0)
70
186
  end
71
187
 
72
- it "should be false when content occurs more times than given" do
73
- expect(@session).not_to have_css("h2.head", maximum: 4) # edge case
74
- expect(@session).not_to have_css("h2", maximum: 3)
75
- expect(@session).not_to have_css("p", maximum: 1)
188
+ it 'should be false when content occurs more times than given' do
189
+ # expect(@session).not_to have_css('h2.head', maximum: 4) # edge case
190
+ # expect(@session).not_to have_css('h2', maximum: 3)
191
+ expect(@session).not_to have_css('h2').at_most(3).times
192
+ # expect(@session).not_to have_css('p', maximum: 1)
76
193
  end
77
194
 
78
- it "should coerce maximum to an integer" do
79
- expect(@session).to have_css("h2.head", maximum: "5") # edge case
80
- expect(@session).to have_css("h2", maximum: "10")
195
+ it 'should coerce maximum to an integer' do
196
+ expect(@session).to have_css('h2.head', maximum: '5') # edge case
197
+ expect(@session).to have_css('h2', maximum: '10')
81
198
  end
82
199
  end
83
200
 
84
- context "with minimum" do
85
- it "should be true when content occurs same or more times than given" do
86
- expect(@session).to have_css("h2.head", minimum: 5) # edge case
87
- expect(@session).to have_css("h2", minimum: 3)
88
- expect(@session).to have_css("p a.doesnotexist", minimum: 0)
201
+ context 'with minimum' do
202
+ it 'should be true when content occurs same or more times than given' do
203
+ expect(@session).to have_css('h2.head', minimum: 5) # edge case
204
+ expect(@session).to have_css('h2', minimum: 3)
205
+ expect(@session).to have_css('h2').at_least(2).times
206
+ expect(@session).to have_css('p a.doesnotexist', minimum: 0)
89
207
  end
90
208
 
91
- it "should be false when content occurs fewer times than given" do
92
- expect(@session).not_to have_css("h2.head", minimum: 6) # edge case
93
- expect(@session).not_to have_css("h2", minimum: 8)
94
- expect(@session).not_to have_css("p", minimum: 10)
95
- expect(@session).not_to have_css("p a.doesnotexist", minimum: 1)
209
+ it 'should be false when content occurs fewer times than given' do
210
+ expect(@session).not_to have_css('h2.head', minimum: 6) # edge case
211
+ expect(@session).not_to have_css('h2', minimum: 8)
212
+ expect(@session).not_to have_css('h2').at_least(8).times
213
+ expect(@session).not_to have_css('p', minimum: 10)
214
+ expect(@session).not_to have_css('p a.doesnotexist', minimum: 1)
96
215
  end
97
216
 
98
- it "should coerce minimum to an integer" do
99
- expect(@session).to have_css("h2.head", minimum: "5") # edge case
100
- expect(@session).to have_css("h2", minimum: "3")
217
+ it 'should coerce minimum to an integer' do
218
+ expect(@session).to have_css('h2.head', minimum: '5') # edge case
219
+ expect(@session).to have_css('h2', minimum: '3')
101
220
  end
102
221
  end
103
222
 
104
- context "with text" do
105
- it "should discard all matches where the given string is not contained" do
106
- expect(@session).to have_css("p a", text: "Redirect", count: 1)
107
- expect(@session).not_to have_css("p a", text: "Doesnotexist")
223
+ context 'with text' do
224
+ it 'should discard all matches where the given string is not contained' do
225
+ expect(@session).to have_css('p a', text: 'Redirect', count: 1)
226
+ expect(@session).not_to have_css('p a', text: 'Doesnotexist')
108
227
  end
109
228
 
110
- it "should discard all matches where the given regexp is not matched" do
111
- expect(@session).to have_css("p a", text: /re[dab]i/i, count: 1)
112
- expect(@session).not_to have_css("p a", text: /Red$/)
229
+ it 'should discard all matches where the given regexp is not matched' do
230
+ expect(@session).to have_css('p a', text: /re[dab]i/i, count: 1)
231
+ expect(@session).not_to have_css('p a', text: /Red$/)
113
232
  end
114
233
  end
115
234
 
116
- it "should allow escapes in the CSS selector" do
117
- if (defined?(TestClass) && @session.is_a?(TestClass)) || @session.driver.is_a?(Capybara::RackTest::Driver)
118
- # Nokogiri doesn't unescape CSS selectors when converting from CSS to XPath
119
- # See: https://github.com/teamcapybara/capybara/issues/1866
120
- # Also: https://github.com/sparklemotion/nokogiri/pull/1646
121
- pending "Current Nokogiri doesn't handle escapes in CSS attribute selectors correctly"
235
+ context 'with spatial requirements', requires: [:spatial] do
236
+ before do
237
+ @session.visit('/spatial')
122
238
  end
239
+
240
+ let :center do
241
+ @session.find(:css, '.center')
242
+ end
243
+
244
+ it 'accepts spatial options' do
245
+ expect(@session).to have_css('div', above: center).thrice
246
+ expect(@session).to have_css('div', above: center, right_of: center).once
247
+ end
248
+
249
+ it 'supports spatial sugar' do
250
+ expect(@session).to have_css('div').left_of(center).thrice
251
+ expect(@session).to have_css('div').below(center).right_of(center).once
252
+ expect(@session).to have_css('div').near(center).exactly(8).times
253
+ end
254
+ end
255
+
256
+ it 'should allow escapes in the CSS selector' do
123
257
  expect(@session).to have_css('p[data-random="abc\\\\def"]')
124
258
  expect(@session).to have_css("p[data-random='#{Capybara::Selector::CSS.escape('abc\def')}']")
125
259
  end
@@ -130,111 +264,112 @@ Capybara::SpecHelper.spec '#has_no_css?' do
130
264
  @session.visit('/with_html')
131
265
  end
132
266
 
133
- it "should be false if the given selector is on the page" do
134
- expect(@session).not_to have_no_css("p")
135
- expect(@session).not_to have_no_css("p a#foo")
267
+ it 'should be false if the given selector is on the page' do
268
+ expect(@session).not_to have_no_css('p')
269
+ expect(@session).not_to have_no_css('p a#foo')
136
270
  end
137
271
 
138
- it "should be true if the given selector is not on the page" do
139
- expect(@session).to have_no_css("abbr")
140
- expect(@session).to have_no_css("p a#doesnotexist")
141
- expect(@session).to have_no_css("p.nosuchclass")
272
+ it 'should be true if the given selector is not on the page' do
273
+ expect(@session).to have_no_css('abbr')
274
+ expect(@session).to have_no_css('p a#doesnotexist')
275
+ expect(@session).to have_no_css('p.nosuchclass')
142
276
  end
143
277
 
144
- it "should respect scopes" do
278
+ it 'should respect scopes' do
145
279
  @session.within "//p[@id='first']" do
146
- expect(@session).not_to have_no_css("a#foo")
147
- expect(@session).to have_no_css("a#red")
280
+ expect(@session).not_to have_no_css('a#foo')
281
+ expect(@session).to have_no_css('a#red')
148
282
  end
149
283
  end
150
284
 
151
- it "should wait for content to disappear", requires: [:js] do
285
+ it 'should wait for content to disappear', requires: [:js] do
286
+ Capybara.default_max_wait_time = 2
152
287
  @session.visit('/with_js')
153
288
  @session.click_link('Click me')
154
- expect(@session).to have_no_css("p#change")
289
+ expect(@session).to have_no_css('p#change')
155
290
  end
156
291
 
157
- context "with between" do
158
- it "should be false if the content occurs within the range given" do
159
- expect(@session).not_to have_no_css("p", between: 1..4)
160
- expect(@session).not_to have_no_css("p a#foo", between: 1..3)
161
- expect(@session).not_to have_no_css("p a.doesnotexist", between: 0..2)
292
+ context 'with between' do
293
+ it 'should be false if the content occurs within the range given' do
294
+ expect(@session).not_to have_no_css('p', between: 1..4)
295
+ expect(@session).not_to have_no_css('p a#foo', between: 1..3)
296
+ expect(@session).not_to have_no_css('p a.doesnotexist', between: 0..2)
162
297
  end
163
298
 
164
- it "should be true if the content occurs more or fewer times than range" do
165
- expect(@session).to have_no_css("p", between: 6..11 )
166
- expect(@session).to have_no_css("p a#foo", between: 4..7)
167
- expect(@session).to have_no_css("p a.doesnotexist", between: 3..8)
299
+ it 'should be true if the content occurs more or fewer times than range' do
300
+ expect(@session).to have_no_css('p', between: 6..11)
301
+ expect(@session).to have_no_css('p a#foo', between: 4..7)
302
+ expect(@session).to have_no_css('p a.doesnotexist', between: 3..8)
168
303
  end
169
304
  end
170
305
 
171
- context "with count" do
172
- it "should be false if the content is on the page the given number of times" do
173
- expect(@session).not_to have_no_css("p", count: 3)
174
- expect(@session).not_to have_no_css("p a#foo", count: 1)
175
- expect(@session).not_to have_no_css("p a.doesnotexist", count: 0)
306
+ context 'with count' do
307
+ it 'should be false if the content is on the page the given number of times' do
308
+ expect(@session).not_to have_no_css('p', count: 3)
309
+ expect(@session).not_to have_no_css('p a#foo', count: 1)
310
+ expect(@session).not_to have_no_css('p a.doesnotexist', count: 0)
176
311
  end
177
312
 
178
- it "should be true if the content is on the page the given number of times" do
179
- expect(@session).to have_no_css("p", count: 6)
180
- expect(@session).to have_no_css("p a#foo", count: 2)
181
- expect(@session).to have_no_css("p a.doesnotexist", count: 1)
313
+ it 'should be true if the content is on the page the given number of times' do
314
+ expect(@session).to have_no_css('p', count: 6)
315
+ expect(@session).to have_no_css('p a#foo', count: 2)
316
+ expect(@session).to have_no_css('p a.doesnotexist', count: 1)
182
317
  end
183
318
 
184
- it "should coerce count to an integer" do
185
- expect(@session).not_to have_no_css("p", count: "3")
186
- expect(@session).not_to have_no_css("p a#foo", count: "1")
319
+ it 'should coerce count to an integer' do
320
+ expect(@session).not_to have_no_css('p', count: '3')
321
+ expect(@session).not_to have_no_css('p a#foo', count: '1')
187
322
  end
188
323
  end
189
324
 
190
- context "with maximum" do
191
- it "should be false when content occurs same or fewer times than given" do
192
- expect(@session).not_to have_no_css("h2.head", maximum: 5) # edge case
193
- expect(@session).not_to have_no_css("h2", maximum: 10)
194
- expect(@session).not_to have_no_css("p a.doesnotexist", maximum: 0)
325
+ context 'with maximum' do
326
+ it 'should be false when content occurs same or fewer times than given' do
327
+ expect(@session).not_to have_no_css('h2.head', maximum: 5) # edge case
328
+ expect(@session).not_to have_no_css('h2', maximum: 10)
329
+ expect(@session).not_to have_no_css('p a.doesnotexist', maximum: 0)
195
330
  end
196
331
 
197
- it "should be true when content occurs more times than given" do
198
- expect(@session).to have_no_css("h2.head", maximum: 4) # edge case
199
- expect(@session).to have_no_css("h2", maximum: 3)
200
- expect(@session).to have_no_css("p", maximum: 1)
332
+ it 'should be true when content occurs more times than given' do
333
+ expect(@session).to have_no_css('h2.head', maximum: 4) # edge case
334
+ expect(@session).to have_no_css('h2', maximum: 3)
335
+ expect(@session).to have_no_css('p', maximum: 1)
201
336
  end
202
337
 
203
- it "should coerce maximum to an integer" do
204
- expect(@session).not_to have_no_css("h2.head", maximum: "5") # edge case
205
- expect(@session).not_to have_no_css("h2", maximum: "10")
338
+ it 'should coerce maximum to an integer' do
339
+ expect(@session).not_to have_no_css('h2.head', maximum: '5') # edge case
340
+ expect(@session).not_to have_no_css('h2', maximum: '10')
206
341
  end
207
342
  end
208
343
 
209
- context "with minimum" do
210
- it "should be false when content occurs same or more times than given" do
211
- expect(@session).not_to have_no_css("h2.head", minimum: 5) # edge case
212
- expect(@session).not_to have_no_css("h2", minimum: 3)
213
- expect(@session).not_to have_no_css("p a.doesnotexist", minimum: 0)
344
+ context 'with minimum' do
345
+ it 'should be false when content occurs same or more times than given' do
346
+ expect(@session).not_to have_no_css('h2.head', minimum: 5) # edge case
347
+ expect(@session).not_to have_no_css('h2', minimum: 3)
348
+ expect(@session).not_to have_no_css('p a.doesnotexist', minimum: 0)
214
349
  end
215
350
 
216
- it "should be true when content occurs fewer times than given" do
217
- expect(@session).to have_no_css("h2.head", minimum: 6) # edge case
218
- expect(@session).to have_no_css("h2", minimum: 8)
219
- expect(@session).to have_no_css("p", minimum: 15)
220
- expect(@session).to have_no_css("p a.doesnotexist", minimum: 1)
351
+ it 'should be true when content occurs fewer times than given' do
352
+ expect(@session).to have_no_css('h2.head', minimum: 6) # edge case
353
+ expect(@session).to have_no_css('h2', minimum: 8)
354
+ expect(@session).to have_no_css('p', minimum: 15)
355
+ expect(@session).to have_no_css('p a.doesnotexist', minimum: 1)
221
356
  end
222
357
 
223
- it "should coerce minimum to an integer" do
224
- expect(@session).not_to have_no_css("h2.head", minimum: "4") # edge case
225
- expect(@session).not_to have_no_css("h2", minimum: "3")
358
+ it 'should coerce minimum to an integer' do
359
+ expect(@session).not_to have_no_css('h2.head', minimum: '4') # edge case
360
+ expect(@session).not_to have_no_css('h2', minimum: '3')
226
361
  end
227
362
  end
228
363
 
229
- context "with text" do
230
- it "should discard all matches where the given string is not contained" do
231
- expect(@session).not_to have_no_css("p a", text: "Redirect", count: 1)
232
- expect(@session).to have_no_css("p a", text: "Doesnotexist")
364
+ context 'with text' do
365
+ it 'should discard all matches where the given string is not contained' do
366
+ expect(@session).not_to have_no_css('p a', text: 'Redirect', count: 1)
367
+ expect(@session).to have_no_css('p a', text: 'Doesnotexist')
233
368
  end
234
369
 
235
- it "should discard all matches where the given regexp is not matched" do
236
- expect(@session).not_to have_no_css("p a", text: /re[dab]i/i, count: 1)
237
- expect(@session).to have_no_css("p a", text: /Red$/)
370
+ it 'should discard all matches where the given regexp is not matched' do
371
+ expect(@session).not_to have_no_css('p a', text: /re[dab]i/i, count: 1)
372
+ expect(@session).to have_no_css('p a', text: /Red$/)
238
373
  end
239
374
  end
240
375
  end