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,34 +1,71 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  Capybara::SpecHelper.spec '#within' do
3
4
  before do
4
5
  @session.visit('/with_scope')
5
6
  end
6
7
 
7
- context "with CSS selector" do
8
- it "should click links in the given scope" do
9
- @session.within(:css, "#for_bar li", text: 'With Simple HTML') do
8
+ context 'with CSS selector' do
9
+ it 'should click links in the given scope' do
10
+ @session.within(:css, '#for_bar li:first-child') do
10
11
  @session.click_link('Go')
11
12
  end
12
13
  expect(@session).to have_content('Bar')
13
14
  end
14
15
 
15
- it "should assert content in the given scope" do
16
- @session.within(:css, "#for_foo") do
16
+ it 'should assert content in the given scope' do
17
+ @session.within(:css, '#for_foo') do
17
18
  expect(@session).not_to have_content('First Name')
18
19
  end
19
20
  expect(@session).to have_content('First Name')
20
21
  end
21
22
 
22
- it "should accept additional options" do
23
- @session.within(:css, "#for_bar li", text: 'With Simple HTML') do
23
+ it 'should accept additional options' do
24
+ @session.within(:css, '#for_bar li', text: 'With Simple HTML') do
24
25
  @session.click_link('Go')
25
26
  end
26
27
  expect(@session).to have_content('Bar')
27
28
  end
29
+
30
+ it 'should reload the node if the page is changed' do
31
+ @session.within(:css, '#for_foo') do
32
+ @session.visit('/with_scope_other')
33
+ expect(@session).to have_content('Different text')
34
+ end
35
+ end
36
+
37
+ it 'should reload multiple nodes if the page is changed' do
38
+ @session.within(:css, '#for_bar') do
39
+ @session.within(:css, 'form[action="/redirect"]') do
40
+ @session.refresh
41
+ expect(@session).to have_content('First Name')
42
+ end
43
+ end
44
+ end
45
+
46
+ it 'should error if the page is changed and a matching node no longer exists' do
47
+ @session.within(:css, '#for_foo') do
48
+ @session.visit('/')
49
+ expect { @session.text }.to raise_error(StandardError)
50
+ end
51
+ end
52
+
53
+ it 'should pass scope element to the block' do
54
+ @session.within(:css, '#another_foo') do |scope|
55
+ expect(scope).to match_css('#another_foo')
56
+ end
57
+ end
58
+
59
+ it 'should scope click', requires: [:js] do
60
+ @session.within(:css, '#another_foo') do |scope|
61
+ @session.click
62
+ expect(scope).to have_text('I was clicked')
63
+ end
64
+ end
28
65
  end
29
66
 
30
- context "with XPath selector" do
31
- it "should click links in the given scope" do
67
+ context 'with XPath selector' do
68
+ it 'should click links in the given scope' do
32
69
  @session.within(:xpath, "//div[@id='for_bar']//li[contains(.,'With Simple HTML')]") do
33
70
  @session.click_link('Go')
34
71
  end
@@ -36,8 +73,8 @@ Capybara::SpecHelper.spec '#within' do
36
73
  end
37
74
  end
38
75
 
39
- context "with the default selector" do
40
- it "should use XPath" do
76
+ context 'with the default selector' do
77
+ it 'should use XPath' do
41
78
  @session.within("//div[@id='for_bar']//li[contains(.,'With Simple HTML')]") do
42
79
  @session.click_link('Go')
43
80
  end
@@ -45,9 +82,9 @@ Capybara::SpecHelper.spec '#within' do
45
82
  end
46
83
  end
47
84
 
48
- context "with Node rather than selector" do
49
- it "should click links in the given scope" do
50
- node_of_interest = @session.find(:css, "#for_bar li", text: 'With Simple HTML')
85
+ context 'with Node rather than selector' do
86
+ it 'should click links in the given scope' do
87
+ node_of_interest = @session.find(:css, '#for_bar li', text: 'With Simple HTML')
51
88
 
52
89
  @session.within(node_of_interest) do
53
90
  @session.click_link('Go')
@@ -56,19 +93,21 @@ Capybara::SpecHelper.spec '#within' do
56
93
  end
57
94
  end
58
95
 
59
- context "with the default selector set to CSS" do
96
+ context 'with the default selector set to CSS' do
60
97
  before { Capybara.default_selector = :css }
61
- it "should use CSS" do
62
- @session.within("#for_bar li", text: 'With Simple HTML') do
98
+
99
+ after { Capybara.default_selector = :xpath }
100
+
101
+ it 'should use CSS' do
102
+ @session.within('#for_bar li', text: 'With Simple HTML') do
63
103
  @session.click_link('Go')
64
104
  end
65
105
  expect(@session).to have_content('Bar')
66
106
  end
67
- after { Capybara.default_selector = :xpath }
68
107
  end
69
108
 
70
- context "with nested scopes" do
71
- it "should respect the inner scope" do
109
+ context 'with nested scopes' do
110
+ it 'should respect the inner scope' do
72
111
  @session.within("//div[@id='for_bar']") do
73
112
  @session.within(".//li[contains(.,'Bar')]") do
74
113
  @session.click_link('Go')
@@ -77,7 +116,7 @@ Capybara::SpecHelper.spec '#within' do
77
116
  expect(@session).to have_content('Another World')
78
117
  end
79
118
 
80
- it "should respect the outer scope" do
119
+ it 'should respect the outer scope' do
81
120
  @session.within("//div[@id='another_foo']") do
82
121
  @session.within(".//li[contains(.,'With Simple HTML')]") do
83
122
  @session.click_link('Go')
@@ -87,14 +126,14 @@ Capybara::SpecHelper.spec '#within' do
87
126
  end
88
127
  end
89
128
 
90
- it "should raise an error if the scope is not found on the page" do
129
+ it 'should raise an error if the scope is not found on the page' do
91
130
  expect do
92
131
  @session.within("//div[@id='doesnotexist']") do
93
132
  end
94
133
  end.to raise_error(Capybara::ElementNotFound)
95
134
  end
96
135
 
97
- it "should restore the scope when an error is raised" do
136
+ it 'should restore the scope when an error is raised' do
98
137
  expect do
99
138
  @session.within("//div[@id='for_bar']") do
100
139
  expect do
@@ -102,12 +141,12 @@ Capybara::SpecHelper.spec '#within' do
102
141
  @session.within(".//div[@id='doesnotexist']") do
103
142
  end
104
143
  end.to raise_error(Capybara::ElementNotFound)
105
- end.to_not change { @session.has_xpath?(".//div[@id='another_foo']") }.from(false)
144
+ end.not_to change { @session.has_xpath?(".//div[@id='another_foo']") }.from(false)
106
145
  end
107
- end.to_not change { @session.has_xpath?(".//div[@id='another_foo']") }.from(true)
146
+ end.not_to change { @session.has_xpath?(".//div[@id='another_foo']") }.from(true)
108
147
  end
109
148
 
110
- it "should fill in a field and click a button" do
149
+ it 'should fill in a field and click a button' do
111
150
  @session.within("//li[contains(.,'Bar')]") do
112
151
  @session.click_button('Go')
113
152
  end
@@ -120,9 +159,9 @@ Capybara::SpecHelper.spec '#within' do
120
159
  expect(extract_results(@session)['first_name']).to eq('Dagobert')
121
160
  end
122
161
 
123
- it "should have #within_element as an alias" do
162
+ it 'should have #within_element as an alias' do
124
163
  expect(Capybara::Session.instance_method(:within)).to eq Capybara::Session.instance_method(:within_element)
125
- @session.within_element(:css, "#for_foo") do
164
+ @session.within_element(:css, '#for_foo') do
126
165
  expect(@session).not_to have_content('First Name')
127
166
  end
128
167
  end
@@ -133,18 +172,18 @@ Capybara::SpecHelper.spec '#within_fieldset' do
133
172
  @session.visit('/fieldsets')
134
173
  end
135
174
 
136
- it "should restrict scope to a fieldset given by id" do
137
- @session.within_fieldset("villain_fieldset") do
138
- @session.fill_in("Name", with: 'Goldfinger')
139
- @session.click_button("Create")
175
+ it 'should restrict scope to a fieldset given by id' do
176
+ @session.within_fieldset('villain_fieldset') do
177
+ @session.fill_in('Name', with: 'Goldfinger')
178
+ @session.click_button('Create')
140
179
  end
141
180
  expect(extract_results(@session)['villain_name']).to eq('Goldfinger')
142
181
  end
143
182
 
144
- it "should restrict scope to a fieldset given by legend" do
145
- @session.within_fieldset("Villain") do
146
- @session.fill_in("Name", with: 'Goldfinger')
147
- @session.click_button("Create")
183
+ it 'should restrict scope to a fieldset given by legend' do
184
+ @session.within_fieldset('Villain') do
185
+ @session.fill_in('Name', with: 'Goldfinger')
186
+ @session.click_button('Create')
148
187
  end
149
188
  expect(extract_results(@session)['villain_name']).to eq('Goldfinger')
150
189
  end
@@ -155,18 +194,18 @@ Capybara::SpecHelper.spec '#within_table' do
155
194
  @session.visit('/tables')
156
195
  end
157
196
 
158
- it "should restrict scope to a fieldset given by id" do
159
- @session.within_table("girl_table") do
160
- @session.fill_in("Name", with: 'Christmas')
161
- @session.click_button("Create")
197
+ it 'should restrict scope to a fieldset given by id' do
198
+ @session.within_table('girl_table') do
199
+ @session.fill_in('Name', with: 'Christmas')
200
+ @session.click_button('Create')
162
201
  end
163
202
  expect(extract_results(@session)['girl_name']).to eq('Christmas')
164
203
  end
165
204
 
166
- it "should restrict scope to a fieldset given by legend" do
167
- @session.within_table("Villain") do
168
- @session.fill_in("Name", with: 'Quantum')
169
- @session.click_button("Create")
205
+ it 'should restrict scope to a fieldset given by legend' do
206
+ @session.within_table('Villain') do
207
+ @session.fill_in('Name', with: 'Quantum')
208
+ @session.click_button('Create')
170
209
  end
171
210
  expect(extract_results(@session)['villain_name']).to eq('Quantum')
172
211
  end
@@ -1,19 +1,13 @@
1
1
  # frozen_string_literal: true
2
- require "rspec"
3
- require "rspec/expectations"
4
- require "capybara"
5
- require "capybara/rspec" # Required here instead of in rspec_spec to avoid RSpec deprecation warning
6
- require "capybara/spec/test_app"
7
- require "nokogiri"
8
-
9
- # Alias be_truthy/be_falsey if not already defined to be able to use in RSpec 2 and 3
10
- unless RSpec::Matchers.method_defined?(:be_truthy)
11
- RSpec::Matchers.module_eval do
12
- alias be_truthy be_true
13
- alias be_falsey be_false
14
- alias be_falsy be_false
15
- end
16
- end
2
+
3
+ require 'rspec'
4
+ require 'rspec/expectations'
5
+ require 'capybara'
6
+ require 'capybara/rspec' # Required here instead of in rspec_spec to avoid RSpec deprecation warning
7
+ require 'capybara/spec/test_app'
8
+ require 'nokogiri'
9
+
10
+ Capybara.save_path = File.join(Dir.pwd, 'save_path_tmp')
17
11
 
18
12
  module Capybara
19
13
  module SpecHelper
@@ -22,8 +16,7 @@ module Capybara
22
16
  config.filter_run_excluding requires: method(:filter).to_proc
23
17
  config.before { Capybara::SpecHelper.reset! }
24
18
  config.after { Capybara::SpecHelper.reset! }
25
- # Test in 3.5+ where metadata doesn't autotrigger shared context inclusion - will be only behavior in RSpec 4
26
- config.shared_context_metadata_behavior = :apply_to_host_groups if RSpec::Core::Version::STRING.to_f >= 3.5
19
+ config.shared_context_metadata_behavior = :apply_to_host_groups
27
20
  end
28
21
 
29
22
  def reset!
@@ -31,21 +24,26 @@ module Capybara
31
24
  Capybara.app_host = nil
32
25
  Capybara.default_selector = :xpath
33
26
  Capybara.default_max_wait_time = 1
27
+ Capybara.default_retry_interval = 0.01
34
28
  Capybara.ignore_hidden_elements = true
35
29
  Capybara.exact = false
36
- # `exact_options` is deprecated - set instancce var directly so we
37
- # don't generate message every reset
38
- Capybara.send(:config).session_options.instance_variable_set('@exact_options', false)
39
30
  Capybara.raise_server_errors = true
40
31
  Capybara.visible_text_only = false
41
32
  Capybara.match = :smart
42
- Capybara.wait_on_first_by_default = false
43
33
  Capybara.enable_aria_label = false
34
+ Capybara.enable_aria_role = false
35
+ Capybara.default_set_options = {}
36
+ Capybara.disable_animation = false
37
+ Capybara.test_id = nil
38
+ Capybara.predicates_wait = true
39
+ Capybara.default_normalize_ws = false
40
+ Capybara.use_html5_parsing = !ENV['HTML5_PARSING'].nil?
41
+ Capybara.w3c_click_offset = true
44
42
  reset_threadsafe
45
43
  end
46
44
 
47
45
  def filter(requires, metadata)
48
- if requires and metadata[:capybara_skip]
46
+ if requires && metadata[:capybara_skip]
49
47
  requires.any? do |require|
50
48
  metadata[:capybara_skip].include?(require)
51
49
  end
@@ -59,25 +57,31 @@ module Capybara
59
57
  @specs << [name, options, block]
60
58
  end
61
59
 
62
- def run_specs(session, name, options={})
60
+ def run_specs(session, name, **options, &filter_block)
63
61
  specs = @specs
64
62
  RSpec.describe Capybara::Session, name, options do
65
63
  include Capybara::SpecHelper
66
64
  include Capybara::RSpecMatchers
67
- before do
65
+
66
+ before do |example|
68
67
  @session = session
68
+ instance_exec(example, &filter_block) if filter_block
69
69
  end
70
70
 
71
71
  after do
72
- @session.reset_session!
72
+ session.reset_session!
73
73
  end
74
74
 
75
- before :each, psc: true do
76
- SpecHelper.reset_threadsafe(true, @session)
75
+ before :each, :psc do
76
+ SpecHelper.reset_threadsafe(bool: true, session: session)
77
77
  end
78
78
 
79
79
  after psc: true do
80
- SpecHelper.reset_threadsafe(false, @session)
80
+ SpecHelper.reset_threadsafe(session: session)
81
+ end
82
+
83
+ before :each, :exact_false do
84
+ Capybara.exact = false
81
85
  end
82
86
 
83
87
  specs.each do |spec_name, spec_options, block|
@@ -88,44 +92,50 @@ module Capybara
88
92
  end
89
93
  end
90
94
 
91
- def reset_threadsafe(bool = false, session = nil)
92
- Capybara::Session.class_variable_set(:@@instance_created, false) # Work around limit on when threadsafe can be changed
95
+ def reset_threadsafe(bool: false, session: nil)
96
+ # Work around limit on when threadsafe can be changed
97
+ Capybara::Session.class_variable_set(:@@instance_created, false) # rubocop:disable Style/ClassVars
93
98
  Capybara.threadsafe = bool
94
99
  session = session.current_session if session.respond_to?(:current_session)
95
- session.instance_variable_set(:@config, nil) if session
100
+ session&.instance_variable_set(:@config, nil)
96
101
  end
97
- end # class << self
102
+ end
98
103
 
99
104
  def silence_stream(stream)
100
105
  old_stream = stream.dup
101
- stream.reopen(RbConfig::CONFIG['host_os'] =~ /rmswin|mingw/ ? 'NUL:' : '/dev/null')
106
+ stream.reopen(RbConfig::CONFIG['host_os'].match?(/rmswin|mingw/) ? 'NUL:' : '/dev/null')
102
107
  stream.sync = true
103
108
  yield
104
109
  ensure
105
110
  stream.reopen(old_stream)
106
111
  end
107
112
 
108
- def quietly
109
- silence_stream(STDOUT) do
110
- silence_stream(STDERR) do
111
- yield
112
- end
113
+ def quietly(&block)
114
+ silence_stream($stdout) do
115
+ silence_stream($stderr, &block)
113
116
  end
114
117
  end
115
118
 
116
119
  def extract_results(session)
117
120
  expect(session).to have_xpath("//pre[@id='results']")
118
- YAML.load Nokogiri::HTML(session.body).xpath("//pre[@id='results']").first.inner_html.lstrip
121
+ perms = [(::Sinatra::IndifferentHash if defined? ::Sinatra::IndifferentHash)].compact
122
+ results = Capybara::HTML(session.body).xpath("//pre[@id='results']").first.inner_html.lstrip
123
+ YAML.safe_load results, permitted_classes: perms
124
+ end
125
+
126
+ def extract_content_type(session)
127
+ expect(session).to have_xpath("//pre[@id='content_type']")
128
+ Capybara::HTML(session.body).xpath("//pre[@id='content_type']").first.text
119
129
  end
120
130
 
121
- def marionette?(session)
122
- session.driver.respond_to?(:marionette?, true) && session.driver.send(:marionette?)
131
+ def be_an_invalid_element_error(session)
132
+ satisfy { |error| session.driver.invalid_element_errors.any? { |e| error.is_a? e } }
123
133
  end
124
134
 
125
- def rspec2?
126
- !defined?(::RSpec::Expectations::Version) || (Gem::Version.new(RSpec::Expectations::Version::STRING) < Gem::Version.new('3.0'))
135
+ def with_os_path_separators(path)
136
+ Gem.win_platform? ? path.to_s.tr('/', '\\') : path.to_s
127
137
  end
128
138
  end
129
139
  end
130
140
 
131
- Dir[File.dirname(__FILE__) + "/session/**/*.rb"].each { |file| require_relative file }
141
+ Dir["#{File.dirname(__FILE__)}/session/**/*.rb"].each { |file| require_relative file }