capybara 3.0.0 → 3.36.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 -1
  3. data/History.md +777 -10
  4. data/License.txt +1 -1
  5. data/README.md +75 -58
  6. data/lib/capybara/config.rb +29 -10
  7. data/lib/capybara/cucumber.rb +1 -1
  8. data/lib/capybara/driver/base.rb +22 -4
  9. data/lib/capybara/driver/node.rb +34 -9
  10. data/lib/capybara/dsl.rb +14 -6
  11. data/lib/capybara/helpers.rb +52 -7
  12. data/lib/capybara/minitest/spec.rb +173 -84
  13. data/lib/capybara/minitest.rb +250 -144
  14. data/lib/capybara/node/actions.rb +248 -124
  15. data/lib/capybara/node/base.rb +34 -20
  16. data/lib/capybara/node/document.rb +14 -2
  17. data/lib/capybara/node/document_matchers.rb +13 -15
  18. data/lib/capybara/node/element.rb +339 -113
  19. data/lib/capybara/node/finders.rb +95 -82
  20. data/lib/capybara/node/matchers.rb +338 -157
  21. data/lib/capybara/node/simple.rb +54 -15
  22. data/lib/capybara/queries/active_element_query.rb +18 -0
  23. data/lib/capybara/queries/ancestor_query.rb +9 -10
  24. data/lib/capybara/queries/base_query.rb +25 -18
  25. data/lib/capybara/queries/current_path_query.rb +16 -6
  26. data/lib/capybara/queries/match_query.rb +11 -0
  27. data/lib/capybara/queries/selector_query.rb +600 -103
  28. data/lib/capybara/queries/sibling_query.rb +9 -7
  29. data/lib/capybara/queries/style_query.rb +45 -0
  30. data/lib/capybara/queries/text_query.rb +40 -22
  31. data/lib/capybara/queries/title_query.rb +2 -2
  32. data/lib/capybara/rack_test/browser.rb +47 -28
  33. data/lib/capybara/rack_test/driver.rb +12 -3
  34. data/lib/capybara/rack_test/errors.rb +6 -0
  35. data/lib/capybara/rack_test/form.rb +53 -50
  36. data/lib/capybara/rack_test/node.rb +114 -37
  37. data/lib/capybara/rails.rb +1 -1
  38. data/lib/capybara/registration_container.rb +44 -0
  39. data/lib/capybara/registrations/drivers.rb +42 -0
  40. data/lib/capybara/registrations/patches/puma_ssl.rb +29 -0
  41. data/lib/capybara/registrations/servers.rb +45 -0
  42. data/lib/capybara/result.rb +86 -52
  43. data/lib/capybara/rspec/features.rb +8 -10
  44. data/lib/capybara/rspec/matcher_proxies.rb +39 -18
  45. data/lib/capybara/rspec/matchers/base.rb +111 -0
  46. data/lib/capybara/rspec/matchers/become_closed.rb +33 -0
  47. data/lib/capybara/rspec/matchers/compound.rb +88 -0
  48. data/lib/capybara/rspec/matchers/count_sugar.rb +37 -0
  49. data/lib/capybara/rspec/matchers/have_ancestor.rb +28 -0
  50. data/lib/capybara/rspec/matchers/have_current_path.rb +29 -0
  51. data/lib/capybara/rspec/matchers/have_selector.rb +77 -0
  52. data/lib/capybara/rspec/matchers/have_sibling.rb +27 -0
  53. data/lib/capybara/rspec/matchers/have_text.rb +33 -0
  54. data/lib/capybara/rspec/matchers/have_title.rb +29 -0
  55. data/lib/capybara/rspec/matchers/match_selector.rb +27 -0
  56. data/lib/capybara/rspec/matchers/match_style.rb +43 -0
  57. data/lib/capybara/rspec/matchers/spatial_sugar.rb +39 -0
  58. data/lib/capybara/rspec/matchers.rb +138 -316
  59. data/lib/capybara/rspec.rb +3 -2
  60. data/lib/capybara/selector/builders/css_builder.rb +84 -0
  61. data/lib/capybara/selector/builders/xpath_builder.rb +71 -0
  62. data/lib/capybara/selector/css.rb +89 -12
  63. data/lib/capybara/selector/definition/button.rb +68 -0
  64. data/lib/capybara/selector/definition/checkbox.rb +26 -0
  65. data/lib/capybara/selector/definition/css.rb +10 -0
  66. data/lib/capybara/selector/definition/datalist_input.rb +35 -0
  67. data/lib/capybara/selector/definition/datalist_option.rb +25 -0
  68. data/lib/capybara/selector/definition/element.rb +28 -0
  69. data/lib/capybara/selector/definition/field.rb +40 -0
  70. data/lib/capybara/selector/definition/fieldset.rb +14 -0
  71. data/lib/capybara/selector/definition/file_field.rb +13 -0
  72. data/lib/capybara/selector/definition/fillable_field.rb +33 -0
  73. data/lib/capybara/selector/definition/frame.rb +17 -0
  74. data/lib/capybara/selector/definition/id.rb +6 -0
  75. data/lib/capybara/selector/definition/label.rb +62 -0
  76. data/lib/capybara/selector/definition/link.rb +54 -0
  77. data/lib/capybara/selector/definition/link_or_button.rb +16 -0
  78. data/lib/capybara/selector/definition/option.rb +27 -0
  79. data/lib/capybara/selector/definition/radio_button.rb +27 -0
  80. data/lib/capybara/selector/definition/select.rb +81 -0
  81. data/lib/capybara/selector/definition/table.rb +109 -0
  82. data/lib/capybara/selector/definition/table_row.rb +21 -0
  83. data/lib/capybara/selector/definition/xpath.rb +5 -0
  84. data/lib/capybara/selector/definition.rb +279 -0
  85. data/lib/capybara/selector/filter.rb +1 -0
  86. data/lib/capybara/selector/filter_set.rb +72 -27
  87. data/lib/capybara/selector/filters/base.rb +45 -2
  88. data/lib/capybara/selector/filters/expression_filter.rb +5 -6
  89. data/lib/capybara/selector/filters/locator_filter.rb +29 -0
  90. data/lib/capybara/selector/filters/node_filter.rb +18 -4
  91. data/lib/capybara/selector/regexp_disassembler.rb +214 -0
  92. data/lib/capybara/selector/selector.rb +85 -200
  93. data/lib/capybara/selector/xpath_extensions.rb +17 -0
  94. data/lib/capybara/selector.rb +226 -537
  95. data/lib/capybara/selenium/atoms/getAttribute.min.js +1 -0
  96. data/lib/capybara/selenium/atoms/isDisplayed.min.js +1 -0
  97. data/lib/capybara/selenium/atoms/src/getAttribute.js +161 -0
  98. data/lib/capybara/selenium/atoms/src/isDisplayed.js +454 -0
  99. data/lib/capybara/selenium/driver.rb +296 -238
  100. data/lib/capybara/selenium/driver_specializations/chrome_driver.rb +117 -0
  101. data/lib/capybara/selenium/driver_specializations/edge_driver.rb +124 -0
  102. data/lib/capybara/selenium/driver_specializations/firefox_driver.rb +89 -0
  103. data/lib/capybara/selenium/driver_specializations/internet_explorer_driver.rb +26 -0
  104. data/lib/capybara/selenium/driver_specializations/safari_driver.rb +24 -0
  105. data/lib/capybara/selenium/extensions/file_input_click_emulation.rb +34 -0
  106. data/lib/capybara/selenium/extensions/find.rb +110 -0
  107. data/lib/capybara/selenium/extensions/html5_drag.rb +228 -0
  108. data/lib/capybara/selenium/extensions/modifier_keys_stack.rb +28 -0
  109. data/lib/capybara/selenium/extensions/scroll.rb +76 -0
  110. data/lib/capybara/selenium/logger_suppressor.rb +40 -0
  111. data/lib/capybara/selenium/node.rb +436 -166
  112. data/lib/capybara/selenium/nodes/chrome_node.rb +137 -0
  113. data/lib/capybara/selenium/nodes/edge_node.rb +104 -0
  114. data/lib/capybara/selenium/nodes/firefox_node.rb +136 -0
  115. data/lib/capybara/selenium/nodes/ie_node.rb +22 -0
  116. data/lib/capybara/selenium/nodes/safari_node.rb +118 -0
  117. data/lib/capybara/selenium/patches/action_pauser.rb +26 -0
  118. data/lib/capybara/selenium/patches/atoms.rb +18 -0
  119. data/lib/capybara/selenium/patches/is_displayed.rb +16 -0
  120. data/lib/capybara/selenium/patches/logs.rb +45 -0
  121. data/lib/capybara/selenium/patches/pause_duration_fix.rb +9 -0
  122. data/lib/capybara/selenium/patches/persistent_client.rb +20 -0
  123. data/lib/capybara/server/animation_disabler.rb +69 -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 +58 -67
  127. data/lib/capybara/session/config.rb +38 -6
  128. data/lib/capybara/session/matchers.rb +26 -19
  129. data/lib/capybara/session.rb +258 -190
  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 +122 -8
  133. data/lib/capybara/spec/session/accept_alert_spec.rb +11 -11
  134. data/lib/capybara/spec/session/accept_confirm_spec.rb +3 -3
  135. data/lib/capybara/spec/session/accept_prompt_spec.rb +9 -10
  136. data/lib/capybara/spec/session/active_element_spec.rb +31 -0
  137. data/lib/capybara/spec/session/all_spec.rb +135 -42
  138. data/lib/capybara/spec/session/ancestor_spec.rb +24 -19
  139. data/lib/capybara/spec/session/assert_all_of_selectors_spec.rb +67 -38
  140. data/lib/capybara/spec/session/{assert_current_path.rb → assert_current_path_spec.rb} +20 -18
  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.rb → assert_text_spec.rb} +62 -38
  144. data/lib/capybara/spec/session/{assert_title.rb → assert_title_spec.rb} +12 -12
  145. data/lib/capybara/spec/session/attach_file_spec.rb +120 -72
  146. data/lib/capybara/spec/session/body_spec.rb +11 -13
  147. data/lib/capybara/spec/session/check_spec.rb +111 -51
  148. data/lib/capybara/spec/session/choose_spec.rb +62 -30
  149. data/lib/capybara/spec/session/click_button_spec.rb +227 -161
  150. data/lib/capybara/spec/session/click_link_or_button_spec.rb +49 -30
  151. data/lib/capybara/spec/session/click_link_spec.rb +78 -55
  152. data/lib/capybara/spec/session/current_scope_spec.rb +7 -7
  153. data/lib/capybara/spec/session/current_url_spec.rb +44 -37
  154. data/lib/capybara/spec/session/dismiss_confirm_spec.rb +3 -3
  155. data/lib/capybara/spec/session/dismiss_prompt_spec.rb +2 -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 +8 -6
  159. data/lib/capybara/spec/session/element/matches_selector_spec.rb +70 -56
  160. data/lib/capybara/spec/session/evaluate_async_script_spec.rb +7 -7
  161. data/lib/capybara/spec/session/evaluate_script_spec.rb +28 -8
  162. data/lib/capybara/spec/session/execute_script_spec.rb +8 -7
  163. data/lib/capybara/spec/session/fill_in_spec.rb +104 -44
  164. data/lib/capybara/spec/session/find_button_spec.rb +23 -23
  165. data/lib/capybara/spec/session/find_by_id_spec.rb +8 -8
  166. data/lib/capybara/spec/session/find_field_spec.rb +33 -31
  167. data/lib/capybara/spec/session/find_link_spec.rb +32 -14
  168. data/lib/capybara/spec/session/find_spec.rb +236 -141
  169. data/lib/capybara/spec/session/first_spec.rb +44 -43
  170. data/lib/capybara/spec/session/frame/frame_title_spec.rb +6 -6
  171. data/lib/capybara/spec/session/frame/frame_url_spec.rb +6 -6
  172. data/lib/capybara/spec/session/frame/switch_to_frame_spec.rb +32 -20
  173. data/lib/capybara/spec/session/frame/within_frame_spec.rb +44 -19
  174. data/lib/capybara/spec/session/go_back_spec.rb +1 -1
  175. data/lib/capybara/spec/session/go_forward_spec.rb +1 -1
  176. data/lib/capybara/spec/session/has_all_selectors_spec.rb +18 -18
  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 +92 -12
  180. data/lib/capybara/spec/session/has_css_spec.rb +271 -137
  181. data/lib/capybara/spec/session/has_current_path_spec.rb +48 -33
  182. data/lib/capybara/spec/session/has_field_spec.rb +137 -58
  183. data/lib/capybara/spec/session/has_link_spec.rb +30 -6
  184. data/lib/capybara/spec/session/has_none_selectors_spec.rb +26 -24
  185. data/lib/capybara/spec/session/has_select_spec.rb +75 -47
  186. data/lib/capybara/spec/session/has_selector_spec.rb +102 -69
  187. data/lib/capybara/spec/session/has_sibling_spec.rb +50 -0
  188. data/lib/capybara/spec/session/has_table_spec.rb +170 -4
  189. data/lib/capybara/spec/session/has_text_spec.rb +108 -52
  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.rb → 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 +35 -0
  195. data/lib/capybara/spec/session/node_spec.rb +871 -122
  196. data/lib/capybara/spec/session/node_wrapper_spec.rb +15 -12
  197. data/lib/capybara/spec/session/refresh_spec.rb +9 -7
  198. data/lib/capybara/spec/session/reset_session_spec.rb +52 -37
  199. data/lib/capybara/spec/session/{response_code.rb → 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 +5 -4
  202. data/lib/capybara/spec/session/save_page_spec.rb +41 -38
  203. data/lib/capybara/spec/session/save_screenshot_spec.rb +13 -11
  204. data/lib/capybara/spec/session/screenshot_spec.rb +2 -2
  205. data/lib/capybara/spec/session/scroll_spec.rb +117 -0
  206. data/lib/capybara/spec/session/select_spec.rb +102 -76
  207. data/lib/capybara/spec/session/selectors_spec.rb +51 -18
  208. data/lib/capybara/spec/session/sibling_spec.rb +9 -9
  209. data/lib/capybara/spec/session/text_spec.rb +26 -24
  210. data/lib/capybara/spec/session/title_spec.rb +8 -6
  211. data/lib/capybara/spec/session/uncheck_spec.rb +40 -21
  212. data/lib/capybara/spec/session/unselect_spec.rb +37 -37
  213. data/lib/capybara/spec/session/visit_spec.rb +59 -53
  214. data/lib/capybara/spec/session/window/become_closed_spec.rb +22 -19
  215. data/lib/capybara/spec/session/window/current_window_spec.rb +4 -3
  216. data/lib/capybara/spec/session/window/open_new_window_spec.rb +4 -3
  217. data/lib/capybara/spec/session/window/switch_to_window_spec.rb +25 -21
  218. data/lib/capybara/spec/session/window/window_opened_by_spec.rb +10 -5
  219. data/lib/capybara/spec/session/window/window_spec.rb +88 -54
  220. data/lib/capybara/spec/session/window/windows_spec.rb +10 -7
  221. data/lib/capybara/spec/session/window/within_window_spec.rb +17 -16
  222. data/lib/capybara/spec/session/within_spec.rb +69 -44
  223. data/lib/capybara/spec/spec_helper.rb +41 -53
  224. data/lib/capybara/spec/test_app.rb +79 -40
  225. data/lib/capybara/spec/views/animated.erb +49 -0
  226. data/lib/capybara/spec/views/form.erb +134 -42
  227. data/lib/capybara/spec/views/frame_child.erb +4 -3
  228. data/lib/capybara/spec/views/frame_one.erb +2 -1
  229. data/lib/capybara/spec/views/frame_parent.erb +1 -1
  230. data/lib/capybara/spec/views/frame_two.erb +1 -1
  231. data/lib/capybara/spec/views/initial_alert.erb +2 -1
  232. data/lib/capybara/spec/views/layout.erb +10 -0
  233. data/lib/capybara/spec/views/obscured.erb +47 -0
  234. data/lib/capybara/spec/views/offset.erb +33 -0
  235. data/lib/capybara/spec/views/path.erb +2 -2
  236. data/lib/capybara/spec/views/popup_one.erb +1 -1
  237. data/lib/capybara/spec/views/popup_two.erb +1 -1
  238. data/lib/capybara/spec/views/react.erb +45 -0
  239. data/lib/capybara/spec/views/scroll.erb +21 -0
  240. data/lib/capybara/spec/views/spatial.erb +31 -0
  241. data/lib/capybara/spec/views/tables.erb +68 -1
  242. data/lib/capybara/spec/views/with_animation.erb +81 -0
  243. data/lib/capybara/spec/views/with_base_tag.erb +2 -2
  244. data/lib/capybara/spec/views/with_dragula.erb +24 -0
  245. data/lib/capybara/spec/views/with_fixed_header_footer.erb +2 -1
  246. data/lib/capybara/spec/views/with_hover.erb +3 -2
  247. data/lib/capybara/spec/views/with_hover1.erb +10 -0
  248. data/lib/capybara/spec/views/with_html.erb +43 -10
  249. data/lib/capybara/spec/views/with_html5_svg.erb +20 -0
  250. data/lib/capybara/spec/views/with_jquery_animation.erb +24 -0
  251. data/lib/capybara/spec/views/with_js.erb +30 -5
  252. data/lib/capybara/spec/views/with_jstree.erb +26 -0
  253. data/lib/capybara/spec/views/with_namespace.erb +21 -0
  254. data/lib/capybara/spec/views/with_scope_other.erb +6 -0
  255. data/lib/capybara/spec/views/with_slow_unload.erb +2 -1
  256. data/lib/capybara/spec/views/with_sortable_js.erb +21 -0
  257. data/lib/capybara/spec/views/with_unload_alert.erb +1 -0
  258. data/lib/capybara/spec/views/with_windows.erb +1 -1
  259. data/lib/capybara/spec/views/within_frames.erb +1 -1
  260. data/lib/capybara/version.rb +1 -1
  261. data/lib/capybara/window.rb +31 -25
  262. data/lib/capybara.rb +120 -100
  263. data/spec/basic_node_spec.rb +59 -34
  264. data/spec/capybara_spec.rb +54 -52
  265. data/spec/css_builder_spec.rb +101 -0
  266. data/spec/css_splitter_spec.rb +38 -0
  267. data/spec/dsl_spec.rb +80 -53
  268. data/spec/filter_set_spec.rb +24 -7
  269. data/spec/fixtures/certificate.pem +25 -0
  270. data/spec/fixtures/key.pem +27 -0
  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 +38 -5
  274. data/spec/minitest_spec_spec.rb +88 -62
  275. data/spec/per_session_config_spec.rb +5 -5
  276. data/spec/rack_test_spec.rb +169 -115
  277. data/spec/regexp_dissassembler_spec.rb +250 -0
  278. data/spec/result_spec.rb +86 -33
  279. data/spec/rspec/features_spec.rb +26 -23
  280. data/spec/rspec/scenarios_spec.rb +8 -4
  281. data/spec/rspec/shared_spec_matchers.rb +393 -363
  282. data/spec/rspec/views_spec.rb +4 -3
  283. data/spec/rspec_matchers_spec.rb +10 -10
  284. data/spec/rspec_spec.rb +109 -85
  285. data/spec/sauce_spec_chrome.rb +43 -0
  286. data/spec/selector_spec.rb +391 -61
  287. data/spec/selenium_spec_chrome.rb +180 -41
  288. data/spec/selenium_spec_chrome_remote.rb +101 -0
  289. data/spec/selenium_spec_edge.rb +28 -8
  290. data/spec/selenium_spec_firefox.rb +211 -0
  291. data/spec/selenium_spec_firefox_remote.rb +80 -0
  292. data/spec/selenium_spec_ie.rb +127 -11
  293. data/spec/selenium_spec_safari.rb +156 -0
  294. data/spec/server_spec.rb +177 -78
  295. data/spec/session_spec.rb +52 -16
  296. data/spec/shared_selenium_node.rb +79 -0
  297. data/spec/shared_selenium_session.rb +455 -123
  298. data/spec/spec_helper.rb +91 -2
  299. data/spec/xpath_builder_spec.rb +93 -0
  300. metadata +343 -42
  301. data/.yard/templates_custom/default/class/html/selectors.erb +0 -38
  302. data/.yard/templates_custom/default/class/html/setup.rb +0 -17
  303. data/.yard/yard_extensions.rb +0 -78
  304. data/lib/capybara/rspec/compound.rb +0 -90
  305. data/lib/capybara/spec/session/assert_selector.rb +0 -149
  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 -143
@@ -5,101 +5,128 @@ Capybara::SpecHelper.spec '#has_selector?' do
5
5
  @session.visit('/with_html')
6
6
  end
7
7
 
8
- it "should be true if the given selector is on the page" do
9
- expect(@session).to have_selector(:xpath, "//p")
10
- expect(@session).to have_selector(:css, "p a#foo")
8
+ it 'should be true if the given selector is on the page' do
9
+ expect(@session).to have_selector(:xpath, '//p')
10
+ expect(@session).to have_selector(:css, 'p a#foo')
11
11
  expect(@session).to have_selector("//p[contains(.,'est')]")
12
12
  end
13
13
 
14
- it "should be false if the given selector is not on the page" do
15
- expect(@session).not_to have_selector(:xpath, "//abbr")
16
- expect(@session).not_to have_selector(:css, "p a#doesnotexist")
14
+ it 'should be false if the given selector is not on the page' do
15
+ expect(@session).not_to have_selector(:xpath, '//abbr')
16
+ expect(@session).not_to have_selector(:css, 'p a#doesnotexist')
17
17
  expect(@session).not_to have_selector("//p[contains(.,'thisstringisnotonpage')]")
18
18
  end
19
19
 
20
- it "should use default selector" do
20
+ it 'should use default selector' do
21
21
  Capybara.default_selector = :css
22
- expect(@session).not_to have_selector("p a#doesnotexist")
23
- expect(@session).to have_selector("p a#foo")
22
+ expect(@session).not_to have_selector('p a#doesnotexist')
23
+ expect(@session).to have_selector('p a#foo')
24
24
  end
25
25
 
26
- it "should respect scopes" do
26
+ it 'should respect scopes' do
27
27
  @session.within "//p[@id='first']" do
28
28
  expect(@session).to have_selector(".//a[@id='foo']")
29
29
  expect(@session).not_to have_selector(".//a[@id='red']")
30
30
  end
31
31
  end
32
32
 
33
- it "should accept a filter block" do
34
- expect(@session).to have_selector(:css, "a", count: 1) { |el| el[:id] == "foo" }
33
+ it 'should accept a filter block' do
34
+ expect(@session).to have_selector(:css, 'a', count: 1) { |el| el[:id] == 'foo' }
35
35
  end
36
36
 
37
- context "with count" do
38
- it "should be true if the content is on the page the given number of times" do
39
- expect(@session).to have_selector("//p", count: 3)
37
+ context 'with count' do
38
+ it 'should be true if the content is on the page the given number of times' do
39
+ expect(@session).to have_selector('//p', count: 3)
40
40
  expect(@session).to have_selector("//p//a[@id='foo']", count: 1)
41
41
  expect(@session).to have_selector("//p[contains(.,'est')]", count: 1)
42
42
  end
43
43
 
44
- it "should be false if the content is on the page the given number of times" do
45
- expect(@session).not_to have_selector("//p", count: 6)
44
+ it 'should be false if the content is on the page the given number of times' do
45
+ expect(@session).not_to have_selector('//p', count: 6)
46
46
  expect(@session).not_to have_selector("//p//a[@id='foo']", count: 2)
47
47
  expect(@session).not_to have_selector("//p[contains(.,'est')]", count: 5)
48
48
  end
49
49
 
50
50
  it "should be false if the content isn't on the page at all" do
51
- expect(@session).not_to have_selector("//abbr", count: 2)
51
+ expect(@session).not_to have_selector('//abbr', count: 2)
52
52
  expect(@session).not_to have_selector("//p//a[@id='doesnotexist']", count: 1)
53
53
  end
54
54
  end
55
55
 
56
- context "with text" do
57
- it "should discard all matches where the given string is not contained" do
58
- expect(@session).to have_selector("//p//a", text: "Redirect", count: 1)
59
- expect(@session).not_to have_selector("//p", text: "Doesnotexist")
56
+ context 'with text' do
57
+ it 'should discard all matches where the given string is not contained' do
58
+ expect(@session).to have_selector('//p//a', text: 'Redirect', count: 1)
59
+ expect(@session).to have_selector(:css, 'p a', text: 'Redirect', count: 1)
60
+ expect(@session).not_to have_selector('//p', text: 'Doesnotexist')
60
61
  end
61
62
 
62
- it "should respect visibility setting" do
63
- expect(@session).to have_selector(:id, "hidden-text", text: "Some of this text is hidden!", visible: false)
64
- expect(@session).not_to have_selector(:id, "hidden-text", text: "Some of this text is hidden!", visible: true)
63
+ it 'should respect visibility setting' do
64
+ expect(@session).to have_selector(:id, 'hidden-text', text: 'Some of this text is hidden!', visible: :all)
65
+ expect(@session).not_to have_selector(:id, 'hidden-text', text: 'Some of this text is hidden!', visible: :visible)
65
66
  Capybara.ignore_hidden_elements = false
66
- expect(@session).to have_selector(:id, "hidden-text", text: "Some of this text is hidden!", visible: false)
67
+ expect(@session).to have_selector(:id, 'hidden-text', text: 'Some of this text is hidden!', visible: :all)
67
68
  Capybara.visible_text_only = true
68
- expect(@session).not_to have_selector(:id, "hidden-text", text: "Some of this text is hidden!", visible: true)
69
+ expect(@session).not_to have_selector(:id, 'hidden-text', text: 'Some of this text is hidden!', visible: :visible)
69
70
  end
70
71
 
71
- it "should discard all matches where the given regexp is not matched" do
72
- expect(@session).to have_selector("//p//a", text: /re[dab]i/i, count: 1)
73
- expect(@session).not_to have_selector("//p//a", text: /Red$/)
72
+ it 'should discard all matches where the given regexp is not matched' do
73
+ expect(@session).to have_selector('//p//a', text: /re[dab]i/i, count: 1)
74
+ expect(@session).not_to have_selector('//p//a', text: /Red$/)
74
75
  end
75
76
 
76
- it "should raise when extra parameters passed" do
77
+ it 'should raise when extra parameters passed' do
77
78
  expect do
78
- expect(@session).to have_selector(:css, "p a#foo", 'extra')
79
+ expect(@session).to have_selector(:css, 'p a#foo', 'extra')
79
80
  end.to raise_error ArgumentError, /extra/
80
81
  end
82
+
83
+ context 'with whitespace normalization' do
84
+ context 'Capybara.default_normalize_ws = false' do
85
+ it 'should support normalize_ws option' do
86
+ Capybara.default_normalize_ws = false
87
+ expect(@session).not_to have_selector(:id, 'second', text: 'text with whitespace')
88
+ expect(@session).to have_selector(:id, 'second', text: 'text with whitespace', normalize_ws: true)
89
+ end
90
+ end
91
+
92
+ context 'Capybara.default_normalize_ws = true' do
93
+ it 'should support normalize_ws option' do
94
+ Capybara.default_normalize_ws = true
95
+ expect(@session).to have_selector(:id, 'second', text: 'text with whitespace')
96
+ expect(@session).not_to have_selector(:id, 'second', text: 'text with whitespace', normalize_ws: false)
97
+ end
98
+ end
99
+ end
81
100
  end
82
101
 
83
- context "with exact_text" do
84
- context "string" do
85
- it "should only match elements that match exactly" do
86
- expect(@session).to have_selector(:id, "h2one", exact_text: "Header Class Test One")
87
- expect(@session).to have_no_selector(:id, "h2one", exact_text: "Header Class Test")
102
+ context 'with exact_text' do
103
+ context 'string' do
104
+ it 'should only match elements that match exactly' do
105
+ expect(@session).to have_selector(:id, 'h2one', exact_text: 'Header Class Test One')
106
+ expect(@session).to have_no_selector(:id, 'h2one', exact_text: 'Header Class Test')
88
107
  end
89
108
  end
90
109
 
91
- context "boolean" do
92
- it "should only match elements that match exactly when true" do
93
- expect(@session).to have_selector(:id, "h2one", text: "Header Class Test One", exact_text: true)
94
- expect(@session).to have_no_selector(:id, "h2one", text: "Header Class Test", exact_text: true)
110
+ context 'boolean' do
111
+ it 'should only match elements that match exactly when true' do
112
+ expect(@session).to have_selector(:id, 'h2one', text: 'Header Class Test One', exact_text: true)
113
+ expect(@session).to have_no_selector(:id, 'h2one', text: 'Header Class Test', exact_text: true)
95
114
  end
96
115
 
97
- it "should match substrings when false" do
98
- expect(@session).to have_selector(:id, "h2one", text: "Header Class Test One", exact_text: false)
99
- expect(@session).to have_selector(:id, "h2one", text: "Header Class Test", exact_text: false)
116
+ it 'should match substrings when false' do
117
+ expect(@session).to have_selector(:id, 'h2one', text: 'Header Class Test One', exact_text: false)
118
+ expect(@session).to have_selector(:id, 'h2one', text: 'Header Class Test', exact_text: false)
100
119
  end
101
120
  end
102
121
  end
122
+
123
+ context 'datalist' do
124
+ it 'should match options' do
125
+ @session.visit('/form')
126
+ expect(@session).to have_selector(:datalist_input, with_options: %w[Jaguar Audi Mercedes])
127
+ expect(@session).not_to have_selector(:datalist_input, with_options: %w[Ford Chevy])
128
+ end
129
+ end
103
130
  end
104
131
 
105
132
  Capybara::SpecHelper.spec '#has_no_selector?' do
@@ -107,63 +134,69 @@ Capybara::SpecHelper.spec '#has_no_selector?' do
107
134
  @session.visit('/with_html')
108
135
  end
109
136
 
110
- it "should be false if the given selector is on the page" do
111
- expect(@session).not_to have_no_selector(:xpath, "//p")
112
- expect(@session).not_to have_no_selector(:css, "p a#foo")
137
+ it 'should be false if the given selector is on the page' do
138
+ expect(@session).not_to have_no_selector(:xpath, '//p')
139
+ expect(@session).not_to have_no_selector(:css, 'p a#foo')
113
140
  expect(@session).not_to have_no_selector("//p[contains(.,'est')]")
114
141
  end
115
142
 
116
- it "should be true if the given selector is not on the page" do
117
- expect(@session).to have_no_selector(:xpath, "//abbr")
118
- expect(@session).to have_no_selector(:css, "p a#doesnotexist")
143
+ it 'should be true if the given selector is not on the page' do
144
+ expect(@session).to have_no_selector(:xpath, '//abbr')
145
+ expect(@session).to have_no_selector(:css, 'p a#doesnotexist')
119
146
  expect(@session).to have_no_selector("//p[contains(.,'thisstringisnotonpage')]")
120
147
  end
121
148
 
122
- it "should use default selector" do
149
+ it 'should use default selector' do
123
150
  Capybara.default_selector = :css
124
- expect(@session).to have_no_selector("p a#doesnotexist")
125
- expect(@session).not_to have_no_selector("p a#foo")
151
+ expect(@session).to have_no_selector('p a#doesnotexist')
152
+ expect(@session).not_to have_no_selector('p a#foo')
126
153
  end
127
154
 
128
- it "should respect scopes" do
155
+ it 'should respect scopes' do
129
156
  @session.within "//p[@id='first']" do
130
157
  expect(@session).not_to have_no_selector(".//a[@id='foo']")
131
158
  expect(@session).to have_no_selector(".//a[@id='red']")
132
159
  end
133
160
  end
134
161
 
135
- it "should accept a filter block" do
136
- expect(@session).to have_no_selector(:css, "a#foo") { |el| el[:id] != "foo" }
162
+ it 'should accept a filter block' do
163
+ expect(@session).to have_no_selector(:css, 'a#foo') { |el| el[:id] != 'foo' }
137
164
  end
138
165
 
139
- context "with count" do
140
- it "should be false if the content is on the page the given number of times" do
141
- expect(@session).not_to have_no_selector("//p", count: 3)
166
+ context 'with count' do
167
+ it 'should be false if the content is on the page the given number of times' do
168
+ expect(@session).not_to have_no_selector('//p', count: 3)
142
169
  expect(@session).not_to have_no_selector("//p//a[@id='foo']", count: 1)
143
170
  expect(@session).not_to have_no_selector("//p[contains(.,'est')]", count: 1)
144
171
  end
145
172
 
146
- it "should be true if the content is on the page the wrong number of times" do
147
- expect(@session).to have_no_selector("//p", count: 6)
173
+ it 'should be true if the content is on the page the wrong number of times' do
174
+ expect(@session).to have_no_selector('//p', count: 6)
148
175
  expect(@session).to have_no_selector("//p//a[@id='foo']", count: 2)
149
176
  expect(@session).to have_no_selector("//p[contains(.,'est')]", count: 5)
150
177
  end
151
178
 
152
179
  it "should be true if the content isn't on the page at all" do
153
- expect(@session).to have_no_selector("//abbr", count: 2)
180
+ expect(@session).to have_no_selector('//abbr', count: 2)
154
181
  expect(@session).to have_no_selector("//p//a[@id='doesnotexist']", count: 1)
155
182
  end
156
183
  end
157
184
 
158
- context "with text" do
159
- it "should discard all matches where the given string is contained" do
160
- expect(@session).not_to have_no_selector("//p//a", text: "Redirect", count: 1)
161
- expect(@session).to have_no_selector("//p", text: "Doesnotexist")
185
+ context 'with text' do
186
+ it 'should discard all matches where the given string is contained' do
187
+ expect(@session).not_to have_no_selector('//p//a', text: 'Redirect', count: 1)
188
+ expect(@session).to have_no_selector('//p', text: 'Doesnotexist')
162
189
  end
163
190
 
164
- it "should discard all matches where the given regexp is matched" do
165
- expect(@session).not_to have_no_selector("//p//a", text: /re[dab]i/i, count: 1)
166
- expect(@session).to have_no_selector("//p//a", text: /Red$/)
191
+ it 'should discard all matches where the given regexp is matched' do
192
+ expect(@session).not_to have_no_selector('//p//a', text: /re[dab]i/i, count: 1)
193
+ expect(@session).to have_no_selector('//p//a', text: /Red$/)
194
+ end
195
+
196
+ it 'should error when matching element exists' do
197
+ expect do
198
+ expect(@session).to have_no_selector('//h2', text: 'Header Class Test Five')
199
+ end.to raise_error RSpec::Expectations::ExpectationNotMetError
167
200
  end
168
201
  end
169
202
  end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ Capybara::SpecHelper.spec '#have_sibling' do
4
+ before do
5
+ @session.visit('/with_html')
6
+ end
7
+
8
+ it 'should assert a prior sibling element using the given locator' do
9
+ el = @session.find(:css, '#mid_sibling')
10
+ expect(el).to have_sibling(:css, '#pre_sibling')
11
+ end
12
+
13
+ it 'should assert a following sibling element using the given locator' do
14
+ el = @session.find(:css, '#mid_sibling')
15
+ expect(el).to have_sibling(:css, '#post_sibling')
16
+ end
17
+
18
+ it 'should not raise an error if there are multiple matches' do
19
+ el = @session.find(:css, '#mid_sibling')
20
+ expect(el).to have_sibling(:css, 'div')
21
+ end
22
+
23
+ it 'should allow counts to be specified' do
24
+ el = @session.find(:css, '#mid_sibling')
25
+
26
+ expect(el).to have_sibling(:css, 'div').exactly(2).times
27
+ expect do
28
+ expect(el).to have_sibling(:css, 'div').once
29
+ end.to raise_error(RSpec::Expectations::ExpectationNotMetError)
30
+ end
31
+ end
32
+
33
+ Capybara::SpecHelper.spec '#have_no_sibling' do
34
+ before do
35
+ @session.visit('/with_html')
36
+ end
37
+
38
+ it 'should assert no matching sibling' do
39
+ el = @session.find(:css, '#mid_sibling')
40
+ expect(el).to have_no_sibling(:css, '#not_a_sibling')
41
+ expect(el).not_to have_sibling(:css, '#not_a_sibling')
42
+ end
43
+
44
+ it 'should raise if there are matching siblings' do
45
+ el = @session.find(:css, '#mid_sibling')
46
+ expect do
47
+ expect(el).to have_no_sibling(:css, '#pre_sibling')
48
+ end.to raise_error(RSpec::Expectations::ExpectationNotMetError)
49
+ end
50
+ end
@@ -5,15 +5,121 @@ Capybara::SpecHelper.spec '#has_table?' do
5
5
  @session.visit('/tables')
6
6
  end
7
7
 
8
- it "should be true if the table is on the page" do
8
+ it 'should be true if the table is on the page' do
9
9
  expect(@session).to have_table('Villain')
10
10
  expect(@session).to have_table('villain_table')
11
11
  expect(@session).to have_table(:villain_table)
12
12
  end
13
13
 
14
- it "should be false if the table is not on the page" do
14
+ it 'should accept rows with column header hashes' do
15
+ expect(@session).to have_table('Horizontal Headers', with_rows:
16
+ [
17
+ { 'First Name' => 'Vern', 'Last Name' => 'Konopelski', 'City' => 'Everette' },
18
+ { 'First Name' => 'Palmer', 'Last Name' => 'Sawayn', 'City' => 'West Trinidad' }
19
+ ])
20
+ end
21
+
22
+ it 'should accept rows with partial column header hashses' do
23
+ expect(@session).to have_table('Horizontal Headers', with_rows:
24
+ [
25
+ { 'First Name' => 'Thomas' },
26
+ { 'Last Name' => 'Sawayn', 'City' => 'West Trinidad' }
27
+ ])
28
+ end
29
+
30
+ it 'should accept rows with array of cell values' do
31
+ expect(@session).to have_table('Horizontal Headers', with_rows:
32
+ [
33
+ %w[Thomas Walpole Oceanside],
34
+ ['Ratke', 'Lawrence', 'East Sorayashire']
35
+ ])
36
+ end
37
+
38
+ it 'should consider order of cells in each row' do
39
+ expect(@session).not_to have_table('Horizontal Headers', with_rows:
40
+ [
41
+ %w[Thomas Walpole Oceanside],
42
+ ['Lawrence', 'Ratke', 'East Sorayashire']
43
+ ])
44
+ end
45
+
46
+ it 'should accept all rows with array of cell values' do
47
+ expect(@session).to have_table('Horizontal Headers', rows:
48
+ [
49
+ %w[Thomas Walpole Oceanside],
50
+ %w[Danilo Wilkinson Johnsonville],
51
+ %w[Vern Konopelski Everette],
52
+ ['Ratke', 'Lawrence', 'East Sorayashire'],
53
+ ['Palmer', 'Sawayn', 'West Trinidad']
54
+ ])
55
+ end
56
+
57
+ it 'should match with vertical headers' do
58
+ expect(@session).to have_table('Vertical Headers', with_cols:
59
+ [
60
+ { 'First Name' => 'Thomas' },
61
+ { 'First Name' => 'Danilo', 'Last Name' => 'Wilkinson', 'City' => 'Johnsonville' },
62
+ { 'Last Name' => 'Sawayn', 'City' => 'West Trinidad' }
63
+ ])
64
+ end
65
+
66
+ it 'should match col with array of cell values' do
67
+ expect(@session).to have_table('Vertical Headers', with_cols:
68
+ [
69
+ %w[Vern Konopelski Everette]
70
+ ])
71
+ end
72
+
73
+ it 'should match cols with array of cell values' do
74
+ expect(@session).to have_table('Vertical Headers', with_cols:
75
+ [
76
+ %w[Danilo Wilkinson Johnsonville],
77
+ %w[Vern Konopelski Everette]
78
+ ])
79
+ end
80
+
81
+ it 'should match all cols with array of cell values' do
82
+ expect(@session).to have_table('Vertical Headers', cols:
83
+ [
84
+ %w[Thomas Walpole Oceanside],
85
+ %w[Danilo Wilkinson Johnsonville],
86
+ %w[Vern Konopelski Everette],
87
+ ['Ratke', 'Lawrence', 'East Sorayashire'],
88
+ ['Palmer', 'Sawayn', 'West Trinidad']
89
+ ])
90
+ end
91
+
92
+ it "should not match if the order of cell values doesn't match" do
93
+ expect(@session).not_to have_table('Vertical Headers', with_cols:
94
+ [
95
+ %w[Vern Everette Konopelski]
96
+ ])
97
+ end
98
+
99
+ it "should not match with vertical headers if the columns don't match" do
100
+ expect(@session).not_to have_table('Vertical Headers', with_cols:
101
+ [
102
+ { 'First Name' => 'Thomas' },
103
+ { 'First Name' => 'Danilo', 'Last Name' => 'Walpole', 'City' => 'Johnsonville' },
104
+ { 'Last Name' => 'Sawayn', 'City' => 'West Trinidad' }
105
+ ])
106
+ end
107
+
108
+ it 'should be false if the table is not on the page' do
15
109
  expect(@session).not_to have_table('Monkey')
16
110
  end
111
+
112
+ it 'should find row by header and cell values' do
113
+ expect(@session.find(:table, 'Horizontal Headers')).to have_selector(:table_row, 'First Name' => 'Thomas', 'Last Name' => 'Walpole')
114
+ expect(@session.find(:table, 'Horizontal Headers')).to have_selector(:table_row, 'Last Name' => 'Walpole')
115
+ expect(@session.find(:table, 'Horizontal Headers')).not_to have_selector(:table_row, 'First Name' => 'Walpole')
116
+ end
117
+
118
+ it 'should find row by cell values' do
119
+ expect(@session.find(:table, 'Horizontal Headers')).to have_selector(:table_row, %w[Thomas Walpole])
120
+ expect(@session.find(:table, 'Horizontal Headers')).not_to have_selector(:table_row, %w[Walpole Thomas])
121
+ expect(@session.find(:table, 'Horizontal Headers')).not_to have_selector(:table_row, %w[Other])
122
+ end
17
123
  end
18
124
 
19
125
  Capybara::SpecHelper.spec '#has_no_table?' do
@@ -21,12 +127,72 @@ Capybara::SpecHelper.spec '#has_no_table?' do
21
127
  @session.visit('/tables')
22
128
  end
23
129
 
24
- it "should be false if the table is on the page" do
130
+ it 'should be false if the table is on the page' do
25
131
  expect(@session).not_to have_no_table('Villain')
26
132
  expect(@session).not_to have_no_table('villain_table')
27
133
  end
28
134
 
29
- it "should be true if the table is not on the page" do
135
+ it 'should be true if the table is not on the page' do
30
136
  expect(@session).to have_no_table('Monkey')
31
137
  end
138
+
139
+ it 'should consider rows' do
140
+ expect(@session).to have_no_table('Horizontal Headers', with_rows:
141
+ [
142
+ { 'First Name' => 'Thomas', 'City' => 'Los Angeles' }
143
+ ])
144
+ end
145
+
146
+ context 'using :with_cols' do
147
+ it 'should consider a single column' do
148
+ expect(@session).to have_no_table('Vertical Headers', with_cols:
149
+ [
150
+ { 'First Name' => 'Joe' }
151
+ ])
152
+ end
153
+
154
+ it 'should be true even if the last column does exist' do
155
+ expect(@session).to have_no_table('Vertical Headers', with_cols:
156
+ [
157
+ {
158
+ 'First Name' => 'What?',
159
+ 'What?' => 'Walpole',
160
+ 'City' => 'Oceanside' # This line makes the example fail
161
+ }
162
+ ])
163
+ end
164
+
165
+ it 'should be true if none of the columns exist' do
166
+ expect(@session).to have_no_table('Vertical Headers', with_cols:
167
+ [
168
+ {
169
+ 'First Name' => 'What?',
170
+ 'What?' => 'Walpole',
171
+ 'City' => 'What?'
172
+ }
173
+ ])
174
+ end
175
+
176
+ it 'should be true if the first column does match' do
177
+ expect(@session).to have_no_table('Vertical Headers', with_cols:
178
+ [
179
+ {
180
+ 'First Name' => 'Thomas',
181
+ 'Last Name' => 'What',
182
+ 'City' => 'What'
183
+ }
184
+ ])
185
+ end
186
+
187
+ it 'should be true if none of the columns match' do
188
+ expect(@session).to have_no_table('Vertical Headers', with_cols:
189
+ [
190
+ {
191
+ 'First Name' => 'What',
192
+ 'Last Name' => 'What',
193
+ 'City' => 'What'
194
+ }
195
+ ])
196
+ end
197
+ end
32
198
  end