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
@@ -6,7 +6,7 @@ module TestSessions
6
6
  RackTest = Capybara::Session.new(:rack_test, TestApp)
7
7
  end
8
8
 
9
- Capybara::SpecHelper.run_specs TestSessions::RackTest, "RackTest", capybara_skip: %i[
9
+ skipped_tests = %i[
10
10
  js
11
11
  modals
12
12
  screenshot
@@ -16,214 +16,268 @@ Capybara::SpecHelper.run_specs TestSessions::RackTest, "RackTest", capybara_skip
16
16
  server
17
17
  hover
18
18
  about_scheme
19
+ download
20
+ css
21
+ scroll
22
+ spatial
23
+ html_validation
24
+ shadow_dom
25
+ active_element
19
26
  ]
27
+ Capybara::SpecHelper.run_specs TestSessions::RackTest, 'RackTest', capybara_skip: skipped_tests do |example|
28
+ case example.metadata[:full_description]
29
+ when /has_css\? should support case insensitive :class and :id options/
30
+ skip "Nokogiri doesn't support case insensitive CSS attribute matchers"
31
+ when /#click_button should follow permanent redirects that maintain method/
32
+ skip "Rack < 2 doesn't support 308" if Gem.loaded_specs['rack'].version < Gem::Version.new('2.0.0')
33
+ end
34
+ end
20
35
 
21
- RSpec.describe Capybara::Session do
36
+ RSpec.describe Capybara::Session do # rubocop:disable RSpec/MultipleDescribes
37
+ include Capybara::RSpecMatchers
22
38
  context 'with rack test driver' do
23
- before do
24
- @session = TestSessions::RackTest
25
- end
39
+ let(:session) { TestSessions::RackTest }
26
40
 
27
41
  describe '#driver' do
28
- it "should be a rack test driver" do
29
- expect(@session.driver).to be_an_instance_of(Capybara::RackTest::Driver)
42
+ it 'should be a rack test driver' do
43
+ expect(session.driver).to be_an_instance_of(Capybara::RackTest::Driver)
30
44
  end
31
45
  end
32
46
 
33
47
  describe '#mode' do
34
- it "should remember the mode" do
35
- expect(@session.mode).to eq(:rack_test)
48
+ it 'should remember the mode' do
49
+ expect(session.mode).to eq(:rack_test)
36
50
  end
37
51
  end
38
52
 
39
53
  describe '#click_link' do
40
- it "should use data-method if option is true" do
41
- @session.driver.options[:respect_data_method] = true
42
- @session.visit "/with_html"
43
- @session.click_link "A link with data-method"
44
- expect(@session.html).to include('The requested object was deleted')
54
+ after do
55
+ session.driver.options[:respect_data_method] = false
45
56
  end
46
57
 
47
- it "should not use data-method if option is false" do
48
- @session.driver.options[:respect_data_method] = false
49
- @session.visit "/with_html"
50
- @session.click_link "A link with data-method"
51
- expect(@session.html).to include('Not deleted')
58
+ it 'should use data-method if option is true' do
59
+ session.driver.options[:respect_data_method] = true
60
+ session.visit '/with_html'
61
+ session.click_link 'A link with data-method'
62
+ expect(session.html).to include('The requested object was deleted')
52
63
  end
53
64
 
54
- it "should use data-method if available even if it's capitalized" do
55
- @session.driver.options[:respect_data_method] = true
56
- @session.visit "/with_html"
57
- @session.click_link "A link with capitalized data-method"
58
- expect(@session.html).to include('The requested object was deleted')
65
+ it 'should not use data-method if option is false' do
66
+ session.driver.options[:respect_data_method] = false
67
+ session.visit '/with_html'
68
+ session.click_link 'A link with data-method'
69
+ expect(session.html).to include('Not deleted')
59
70
  end
60
71
 
61
- after do
62
- @session.driver.options[:respect_data_method] = false
72
+ it "should use data-method if available even if it's capitalized" do
73
+ session.driver.options[:respect_data_method] = true
74
+ session.visit '/with_html'
75
+ session.click_link 'A link with capitalized data-method'
76
+ expect(session.html).to include('The requested object was deleted')
63
77
  end
64
78
  end
65
79
 
66
- describe "#fill_in" do
67
- it "should warn that :fill_options are not supported" do
68
- expect_any_instance_of(Capybara::RackTest::Node).to receive(:warn)
69
- .with("Options passed to Node#set but the RackTest driver doesn't support any - ignoring")
70
- @session.visit "/with_html"
71
- @session.fill_in 'test_field', with: 'not_monkey', fill_options: { random: true }
72
- expect(@session).to have_field('test_field', with: 'not_monkey')
80
+ describe '#fill_in' do
81
+ it 'should warn that :fill_options are not supported' do
82
+ session.visit '/with_html'
83
+ expect { session.fill_in 'test_field', with: 'not_monkey', fill_options: { random: true } }.to \
84
+ output(/^Options passed to Node#set but the RackTest driver doesn't support any - ignoring/).to_stderr
85
+ expect(session).to have_field('test_field', with: 'not_monkey')
73
86
  end
74
87
  end
75
88
 
76
- describe "#attach_file" do
77
- context "with multipart form" do
78
- it "should submit an empty form-data section if no file is submitted" do
79
- @session.visit("/form")
80
- @session.click_button("Upload Empty")
81
- expect(@session.html).to include('Successfully ignored empty file field.')
89
+ describe '#attach_file' do
90
+ context 'with multipart form' do
91
+ it 'should submit an empty form-data section if no file is submitted' do
92
+ session.visit('/form')
93
+ session.click_button('Upload Empty')
94
+ expect(session.html).to include('Successfully ignored empty file field.')
82
95
  end
83
96
  end
84
97
 
85
- it "should not submit an obsolete mime type" do
86
- @test_jpg_file_path = File.expand_path('fixtures/capybara.csv', File.dirname(__FILE__))
87
- @session.visit("/form")
88
- @session.attach_file "form_document", @test_jpg_file_path
89
- @session.click_button('Upload Single')
90
- expect(@session).to have_content("Content-type: text/csv")
98
+ it 'should not submit an obsolete mime type' do
99
+ test_jpg_file_path = File.expand_path('fixtures/capybara.csv', File.dirname(__FILE__))
100
+ session.visit('/form')
101
+ session.attach_file 'form_document', test_jpg_file_path
102
+ session.click_button('Upload Single')
103
+ expect(session).to have_content('Content-type: text/csv')
91
104
  end
92
105
  end
93
106
 
94
- describe "#click" do
95
- context "on a label" do
96
- it "should toggle the associated checkbox" do
97
- @session.visit("/form")
98
- expect(@session).to have_unchecked_field('form_pets_cat')
99
- @session.find(:label, 'Cat').click
100
- expect(@session).to have_checked_field('form_pets_cat')
101
- @session.find(:label, 'Cat').click
102
- expect(@session).to have_unchecked_field('form_pets_cat')
103
- @session.find(:label, 'McLaren').click
104
- expect(@session).to have_checked_field('form_cars_mclaren', visible: :hidden)
107
+ describe '#click' do
108
+ context 'on a label' do
109
+ it 'should toggle the associated checkbox' do
110
+ session.visit('/form')
111
+ expect(session).to have_unchecked_field('form_pets_cat')
112
+ session.find(:label, 'Cat').click
113
+ expect(session).to have_checked_field('form_pets_cat')
114
+ session.find(:label, 'Cat').click
115
+ expect(session).to have_unchecked_field('form_pets_cat')
116
+ session.find(:label, 'McLaren').click
117
+ expect(session).to have_checked_field('form_cars_mclaren', visible: :hidden)
105
118
  end
106
119
 
107
- it "should toggle the associated radio" do
108
- @session.visit("/form")
109
- expect(@session).to have_unchecked_field('gender_male')
110
- @session.find(:label, 'Male').click
111
- expect(@session).to have_checked_field('gender_male')
112
- @session.find(:label, 'Female').click
113
- expect(@session).to have_unchecked_field('gender_male')
120
+ it 'should toggle the associated radio' do
121
+ session.visit('/form')
122
+ expect(session).to have_unchecked_field('gender_male')
123
+ session.find(:label, 'Male').click
124
+ expect(session).to have_checked_field('gender_male')
125
+ session.find(:label, 'Female').click
126
+ expect(session).to have_unchecked_field('gender_male')
114
127
  end
128
+
129
+ it 'should rewrite the forms action query for get submission' do
130
+ session.visit('/form')
131
+ session.click_button('mediocre')
132
+ expect(session).not_to have_current_path(/foo|bar/)
133
+ end
134
+
135
+ it 'should rewrite the submit buttons formaction query for get submission' do
136
+ session.visit('/form')
137
+ session.click_button('mediocre2')
138
+ expect(session).not_to have_current_path(/foo|bar/)
139
+ end
140
+ end
141
+ end
142
+
143
+ describe '#send_keys' do
144
+ it 'raises an UnsupportedMethodError' do
145
+ session.visit('/form')
146
+
147
+ expect { session.send_keys(:tab) }.to raise_error(Capybara::NotSupportedByDriverError)
148
+ end
149
+ end
150
+
151
+ describe '#active_element' do
152
+ it 'raises an UnsupportedMethodError' do
153
+ session.visit('/form')
154
+
155
+ expect { session.active_element }.to raise_error(Capybara::NotSupportedByDriverError)
115
156
  end
116
157
  end
117
158
 
118
159
  describe '#text' do
119
- it "should return original text content for textareas" do
120
- @session.visit('/with_html')
121
- @session.find_field('normal', type: 'textarea', with: 'banana').set('hello')
122
- normal = @session.find(:css, '#normal')
160
+ it 'should return original text content for textareas' do
161
+ session.visit('/with_html')
162
+ session.find_field('normal', type: 'textarea', with: 'banana').set('hello')
163
+ normal = session.find(:css, '#normal')
123
164
  expect(normal.value).to eq 'hello'
124
165
  expect(normal.text).to eq 'banana'
125
166
  end
126
167
  end
168
+
169
+ describe '#style' do
170
+ it 'should raise an error' do
171
+ session.visit('/with_html')
172
+ el = session.find(:css, '#first')
173
+ expect { el.style('display') }.to raise_error NotImplementedError, /not process CSS/
174
+ end
175
+ end
127
176
  end
128
177
  end
129
178
 
130
179
  RSpec.describe Capybara::RackTest::Driver do
131
- before do
132
- @driver = TestSessions::RackTest.driver
133
- end
180
+ let(:driver) { TestSessions::RackTest.driver }
134
181
 
135
182
  describe ':headers option' do
136
183
  it 'should always set headers' do
137
- @driver = Capybara::RackTest::Driver.new(TestApp, headers: { 'HTTP_FOO' => 'foobar' })
138
- @driver.visit('/get_header')
139
- expect(@driver.html).to include('foobar')
184
+ driver = described_class.new(TestApp, headers: { 'HTTP_FOO' => 'foobar' })
185
+ driver.visit('/get_header')
186
+ expect(driver.html).to include('foobar')
140
187
  end
141
188
 
142
189
  it 'should keep headers on link clicks' do
143
- @driver = Capybara::RackTest::Driver.new(TestApp, headers: { 'HTTP_FOO' => 'foobar' })
144
- @driver.visit('/header_links')
145
- @driver.find_xpath('.//a').first.click
146
- expect(@driver.html).to include('foobar')
190
+ driver = described_class.new(TestApp, headers: { 'HTTP_FOO' => 'foobar' })
191
+ driver.visit('/header_links')
192
+ driver.find_xpath('.//a').first.click
193
+ expect(driver.html).to include('foobar')
147
194
  end
148
195
 
149
196
  it 'should keep headers on form submit' do
150
- @driver = Capybara::RackTest::Driver.new(TestApp, headers: { 'HTTP_FOO' => 'foobar' })
151
- @driver.visit('/header_links')
152
- @driver.find_xpath('.//input').first.click
153
- expect(@driver.html).to include('foobar')
197
+ driver = described_class.new(TestApp, headers: { 'HTTP_FOO' => 'foobar' })
198
+ driver.visit('/header_links')
199
+ driver.find_xpath('.//input').first.click
200
+ expect(driver.html).to include('foobar')
154
201
  end
155
202
 
156
203
  it 'should keep headers on redirects' do
157
- @driver = Capybara::RackTest::Driver.new(TestApp, headers: { 'HTTP_FOO' => 'foobar' })
158
- @driver.visit('/get_header_via_redirect')
159
- expect(@driver.html).to include('foobar')
204
+ driver = described_class.new(TestApp, headers: { 'HTTP_FOO' => 'foobar' })
205
+ driver.visit('/get_header_via_redirect')
206
+ expect(driver.html).to include('foobar')
160
207
  end
161
208
  end
162
209
 
163
210
  describe ':follow_redirects option' do
164
- it "defaults to following redirects" do
165
- @driver = Capybara::RackTest::Driver.new(TestApp)
211
+ it 'defaults to following redirects' do
212
+ driver = described_class.new(TestApp)
166
213
 
167
- @driver.visit('/redirect')
168
- expect(@driver.response.header['Location']).to be_nil
169
- expect(@driver.current_url).to match %r{/landed$}
214
+ driver.visit('/redirect')
215
+ expect(driver.response.header['Location']).to be_nil
216
+ expect(driver.current_url).to match %r{/landed$}
170
217
  end
171
218
 
172
- it "is possible to not follow redirects" do
173
- @driver = Capybara::RackTest::Driver.new(TestApp, follow_redirects: false)
219
+ it 'is possible to not follow redirects' do
220
+ driver = described_class.new(TestApp, follow_redirects: false)
174
221
 
175
- @driver.visit('/redirect')
176
- expect(@driver.response.header['Location']).to match %r{/redirect_again$}
177
- expect(@driver.current_url).to match %r{/redirect$}
222
+ driver.visit('/redirect')
223
+ expect(driver.response.header['Location']).to match %r{/redirect_again$}
224
+ expect(driver.current_url).to match %r{/redirect$}
178
225
  end
179
226
  end
180
227
 
181
228
  describe ':redirect_limit option' do
182
- context "with default redirect limit" do
183
- before do
184
- @driver = Capybara::RackTest::Driver.new(TestApp)
185
- end
229
+ context 'with default redirect limit' do
230
+ let(:driver) { described_class.new(TestApp) }
186
231
 
187
- it "should follow 5 redirects" do
188
- @driver.visit("/redirect/5/times")
189
- expect(@driver.html).to include('redirection complete')
232
+ it 'should follow 5 redirects' do
233
+ driver.visit('/redirect/5/times')
234
+ expect(driver.html).to include('redirection complete')
190
235
  end
191
236
 
192
- it "should not follow more than 6 redirects" do
237
+ it 'should not follow more than 6 redirects' do
193
238
  expect do
194
- @driver.visit("/redirect/6/times")
239
+ driver.visit('/redirect/6/times')
195
240
  end.to raise_error(Capybara::InfiniteRedirectError)
196
241
  end
197
242
  end
198
243
 
199
- context "with 21 redirect limit" do
200
- before do
201
- @driver = Capybara::RackTest::Driver.new(TestApp, redirect_limit: 21)
202
- end
244
+ context 'with 21 redirect limit' do
245
+ let(:driver) { described_class.new(TestApp, redirect_limit: 21) }
203
246
 
204
- it "should follow 21 redirects" do
205
- @driver.visit("/redirect/21/times")
206
- expect(@driver.html).to include('redirection complete')
247
+ it 'should follow 21 redirects' do
248
+ driver.visit('/redirect/21/times')
249
+ expect(driver.html).to include('redirection complete')
207
250
  end
208
251
 
209
- it "should not follow more than 21 redirects" do
252
+ it 'should not follow more than 21 redirects' do
210
253
  expect do
211
- @driver.visit("/redirect/22/times")
254
+ driver.visit('/redirect/22/times')
212
255
  end.to raise_error(Capybara::InfiniteRedirectError)
213
256
  end
214
257
  end
215
258
  end
216
259
  end
217
260
 
261
+ RSpec.describe 'Capybara::String' do
262
+ it 'should use HTML5 parsing' do
263
+ skip 'Only valid if Nokogiri >= 1.12.0 or gumbo is included' unless defined? Nokogiri::HTML5
264
+ Capybara.use_html5_parsing = true
265
+ allow(Nokogiri::HTML5).to receive(:parse).and_call_original
266
+ Capybara.string('<div id=test_div></div>')
267
+ expect(Nokogiri::HTML5).to have_received(:parse)
268
+ end
269
+ end
270
+
218
271
  module CSSHandlerIncludeTester
219
272
  def dont_extend_css_handler
220
273
  raise 'should never be called'
221
274
  end
222
275
  end
223
- include CSSHandlerIncludeTester # rubocop:disable Style/MixinUsage
224
276
 
225
277
  RSpec.describe Capybara::RackTest::CSSHandlers do
226
- it "should not be extended by global includes" do
227
- expect(Capybara::RackTest::CSSHandlers.new).not_to respond_to(:dont_extend_css_handler)
278
+ include CSSHandlerIncludeTester
279
+
280
+ it 'should not be extended by global includes' do
281
+ expect(described_class.new).not_to respond_to(:dont_extend_css_handler)
228
282
  end
229
283
  end
@@ -0,0 +1,250 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe Capybara::Selector::RegexpDisassembler, :aggregate_failures do
6
+ it 'handles strings' do
7
+ verify_strings(
8
+ /abcdef/ => %w[abcdef],
9
+ /abc def/ => ['abc def']
10
+ )
11
+ end
12
+
13
+ it 'handles escaped characters' do
14
+ verify_strings(
15
+ /abc\\def/ => %w[abc\def],
16
+ /abc\.def/ => %w[abc.def],
17
+ /\nabc/ => ["\nabc"],
18
+ %r{abc/} => %w[abc/],
19
+ /ab\++cd/ => %w[ab+ cd]
20
+ )
21
+ end
22
+
23
+ it 'handles wildcards' do
24
+ verify_strings(
25
+ /abc.*def/ => %w[abc def],
26
+ /.*def/ => %w[def],
27
+ /abc./ => %w[abc],
28
+ /abc.*/ => %w[abc],
29
+ /abc.def/ => %w[abc def],
30
+ /abc.def.ghi/ => %w[abc def ghi],
31
+ /abc.abcd.abcde/ => %w[abcde],
32
+ /.*/ => []
33
+ )
34
+ end
35
+
36
+ it 'ignores optional characters for substrings' do
37
+ {
38
+ /abc*def/ => %w[ab def],
39
+ /abc*/ => %w[ab],
40
+ /c*/ => [],
41
+ /abc?def/ => %w[ab def],
42
+ /abc?/ => %w[ab],
43
+ /abc?def?/ => %w[ab de],
44
+ /abc?def?g/ => %w[ab de g],
45
+ /d?/ => []
46
+ }.each do |regexp, expected|
47
+ expect(described_class.new(regexp).substrings).to eq expected
48
+ end
49
+ end
50
+
51
+ it 'handles optional characters for #alternated_substrings' do
52
+ verify_alternated_strings(
53
+ {
54
+ /abc*def/ => [%w[ab def]],
55
+ /abc*/ => [%w[ab]],
56
+ /c*/ => [],
57
+ /abc?def/ => [%w[abdef], %w[abcdef]],
58
+ /abc?/ => [%w[ab]],
59
+ /abc?def?/ => [%w[abde], %w[abcde]],
60
+ /abc?def?g/ => [%w[abdeg], %w[abdefg], %w[abcdeg], %w[abcdefg]],
61
+ /d?/ => []
62
+ }
63
+ )
64
+ end
65
+
66
+ it 'handles character classes' do
67
+ verify_strings(
68
+ /abc[a-z]/ => %w[abc],
69
+ /abc[a-z]def[0-9]g/ => %w[abc def g],
70
+ /[0-9]abc/ => %w[abc],
71
+ /[0-9]+/ => [],
72
+ /abc[0-9&&[^7]]/ => %w[abc]
73
+ )
74
+ end
75
+
76
+ it 'handles posix bracket expressions' do
77
+ verify_strings(
78
+ /abc[[:alpha:]]/ => %w[abc],
79
+ /[[:digit:]]abc/ => %w[abc],
80
+ /abc[[:print:]]def/ => %w[abc def]
81
+ )
82
+ end
83
+
84
+ it 'handles repitition' do
85
+ verify_strings(
86
+ /abc{3}/ => %w[abccc],
87
+ /abc{3}d/ => %w[abcccd],
88
+ /abc{0}/ => %w[ab],
89
+ /abc{,2}/ => %w[ab],
90
+ /abc{2,}/ => %w[abcc],
91
+ /def{1,5}/ => %w[def],
92
+ /abc+def/ => %w[abc def],
93
+ /ab(cde){,4}/ => %w[ab],
94
+ /(ab){,2}cd/ => %w[cd],
95
+ /(abc){2,3}/ => %w[abcabc],
96
+ /(abc){3}/ => %w[abcabcabc],
97
+ /ab{2,3}cd/ => %w[abb cd],
98
+ /(ab){2,3}cd/ => %w[abab cd]
99
+ )
100
+ end
101
+
102
+ it 'handles non-greedy repetition' do
103
+ verify_strings(
104
+ /abc.*?/ => %w[abc],
105
+ /abc+?/ => %w[abc],
106
+ /abc*?cde/ => %w[ab cde],
107
+ /(abc)+?def/ => %w[abc def],
108
+ /ab(cde)*?fg/ => %w[ab fg]
109
+ )
110
+ end
111
+
112
+ it 'ignores alternation for #substrings' do
113
+ {
114
+ /abc|def/ => [],
115
+ /ab(?:c|d)/ => %w[ab],
116
+ /ab(c|d|e)fg/ => %w[ab fg],
117
+ /ab?(c|d)fg/ => %w[a fg],
118
+ /ab(c|d)ef/ => %w[ab ef],
119
+ /ab(cd?|ef)g/ => %w[ab g],
120
+ /ab(cd|ef*)g/ => %w[ab g],
121
+ /ab|cd*/ => [],
122
+ /cd(?:ef|gh)|xyz/ => [],
123
+ /(cd(?:ef|gh)|xyz)/ => [],
124
+ /cd(ef|gh)+/ => %w[cd],
125
+ /cd(ef|gh)?/ => %w[cd],
126
+ /cd(ef|gh)?ij/ => %w[cd ij],
127
+ /cd(ef|gh)+ij/ => %w[cd ij],
128
+ /cd(ef|gh){2}ij/ => %w[cd ij],
129
+ /(cd(ef|g*))/ => %w[cd],
130
+ /ab(cd){0,2}ef/ => %w[ab ef],
131
+ /ab(cd){0,1}ef/ => %w[ab ef],
132
+ /ab(cd|cd)ef/ => %w[ab ef],
133
+ /ab(cd|cd)?ef/ => %w[ab ef],
134
+ /ab\\?cd/ => %w[ab cd]
135
+ }.each do |regexp, expected|
136
+ expect(described_class.new(regexp).substrings).to eq expected
137
+ end
138
+ end
139
+
140
+ it 'handles alternation for #alternated_substrings' do
141
+ verify_alternated_strings(
142
+ {
143
+ /abc|def/ => [%w[abc], %w[def]],
144
+ /ab(?:c|d)/ => [%w[abc], %w[abd]],
145
+ /ab(c|d|e)fg/ => [%w[abcfg], %w[abdfg], %w[abefg]],
146
+ /ab?(c|d)fg/ => [%w[acfg], %w[adfg], %w[abcfg], %w[abdfg]],
147
+ /ab(c|d)ef/ => [%w[abcef], %w[abdef]],
148
+ /ab(cd?|ef)g/ => [%w[abcg], %w[abcdg], %w[abefg]],
149
+ /ab(cd|ef*)g/ => [%w[abcdg], %w[abe g]],
150
+ /ab|cd*/ => [%w[ab], %w[c]],
151
+ /cd(?:ef|gh)|xyz/ => [%w[cdef], %w[cdgh], %w[xyz]],
152
+ /(cd(?:ef|gh)|xyz)/ => [%w[cdef], %w[cdgh], %w[xyz]],
153
+ /cd(ef|gh)+/ => [%w[cdef], %w[cdgh]],
154
+ /cd(ef|gh)?/ => [%w[cd]],
155
+ /cd(ef|gh)?ij/ => [%w[cdij], %w[cdefij], %w[cdghij]],
156
+ /cd(ef|gh)+ij/ => [%w[cdef ij], %w[cdgh ij]],
157
+ /cd(ef|gh){2}ij/ => [%w[cdefefij], %w[cdefghij], %w[cdghefij], %w[cdghghij]],
158
+ /(cd(ef|g*))/ => [%w[cd]],
159
+ /a|b*/ => [],
160
+ /ab(?:c|d?)/ => [%w[ab]],
161
+ /ab(c|d)|a*/ => [],
162
+ /(abc)?(d|e)/ => [%w[d], %w[e]],
163
+ /(abc*de)?(d|e)/ => [%w[d], %w[e]],
164
+ /(abc*de)?(d|e?)/ => [],
165
+ /(abc)?(d|e?)/ => [],
166
+ /ab(cd){0,2}ef/ => [%w[ab ef]],
167
+ /ab(cd){0,1}ef/ => [%w[abef], %w[abcdef]],
168
+ /ab(cd|cd)ef/ => [%w[abcdef]],
169
+ /ab(cd|cd)?ef/ => [%w[abef], %w[abcdef]],
170
+ /ab\\?cd/ => [%w[abcd], %w[ab\cd]]
171
+ }
172
+ )
173
+ end
174
+
175
+ it 'handles grouping' do
176
+ verify_strings(
177
+ /(abc)/ => %w[abc],
178
+ /(abc)?/ => [],
179
+ /ab(cde)/ => %w[abcde],
180
+ /(abc)de/ => %w[abcde],
181
+ /ab(cde)fg/ => %w[abcdefg],
182
+ /ab(?<name>cd)ef/ => %w[abcdef],
183
+ /gh(?>ij)kl/ => %w[ghijkl],
184
+ /m(n.*p)q/ => %w[mn pq],
185
+ /(?:ab(cd)*){2,3}/ => %w[ab],
186
+ /(ab(cd){3})?/ => [],
187
+ /(ab(cd)+){2}/ => %w[abcd]
188
+ )
189
+ end
190
+
191
+ it 'handles meta characters' do
192
+ verify_strings(
193
+ /abc\d/ => %w[abc],
194
+ /abc\wdef/ => %w[abc def],
195
+ /\habc/ => %w[abc]
196
+ )
197
+ end
198
+
199
+ it 'handles character properties' do
200
+ verify_strings(
201
+ /ab\p{Alpha}cd/ => %w[ab cd],
202
+ /ab\p{Blank}/ => %w[ab],
203
+ /\p{Digit}cd/ => %w[cd]
204
+ )
205
+ end
206
+
207
+ it 'handles backreferences' do
208
+ verify_strings(
209
+ /a(?<group>abc).\k<group>.+/ => %w[aabc]
210
+ )
211
+ end
212
+
213
+ it 'handles subexpressions' do
214
+ verify_strings(
215
+ /\A(?<paren>a\g<paren>*b)+\z/ => %w[a b]
216
+ )
217
+ end
218
+
219
+ it 'ignores negative lookaheads' do
220
+ verify_strings(
221
+ /^(?!.*\bContributing Editor\b).*$/ => %w[],
222
+ /abc(?!.*def).*/ => %w[abc],
223
+ /(?!.*def)abc/ => %w[abc],
224
+ /abc(?!.*def.*).*ghi/ => %w[abc ghi],
225
+ /abc(?!.*bcd)def/ => %w[abcdef]
226
+ )
227
+ end
228
+
229
+ it 'handles anchors' do
230
+ verify_strings(
231
+ /^abc/ => %w[abc],
232
+ /def$/ => %w[def],
233
+ /^abc$/ => %w[abc]
234
+ )
235
+ end
236
+
237
+ def verify_strings(hsh)
238
+ hsh.each do |regexp, expected|
239
+ expect(Capybara::Selector::RegexpDisassembler.new(regexp).substrings).to eq expected
240
+ end
241
+ verify_alternated_strings(hsh, wrap: true)
242
+ end
243
+
244
+ def verify_alternated_strings(hsh, wrap: false)
245
+ hsh.each do |regexp, expected|
246
+ expected = [expected] if wrap && (expected != [])
247
+ expect(Capybara::Selector::RegexpDisassembler.new(regexp).alternated_substrings).to eq expected
248
+ end
249
+ end
250
+ end