capybara 2.7.0 → 3.35.3

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 (318) hide show
  1. checksums.yaml +5 -5
  2. data/.yardopts +1 -0
  3. data/History.md +1147 -11
  4. data/License.txt +1 -1
  5. data/README.md +252 -131
  6. data/lib/capybara/config.rb +92 -0
  7. data/lib/capybara/cucumber.rb +3 -3
  8. data/lib/capybara/driver/base.rb +52 -21
  9. data/lib/capybara/driver/node.rb +48 -14
  10. data/lib/capybara/dsl.rb +16 -9
  11. data/lib/capybara/helpers.rb +72 -81
  12. data/lib/capybara/minitest/spec.rb +267 -0
  13. data/lib/capybara/minitest.rb +385 -0
  14. data/lib/capybara/node/actions.rb +337 -89
  15. data/lib/capybara/node/base.rb +50 -32
  16. data/lib/capybara/node/document.rb +19 -3
  17. data/lib/capybara/node/document_matchers.rb +22 -24
  18. data/lib/capybara/node/element.rb +388 -125
  19. data/lib/capybara/node/finders.rb +231 -121
  20. data/lib/capybara/node/matchers.rb +503 -217
  21. data/lib/capybara/node/simple.rb +64 -27
  22. data/lib/capybara/queries/ancestor_query.rb +27 -0
  23. data/lib/capybara/queries/base_query.rb +87 -11
  24. data/lib/capybara/queries/current_path_query.rb +24 -24
  25. data/lib/capybara/queries/match_query.rb +15 -10
  26. data/lib/capybara/queries/selector_query.rb +675 -81
  27. data/lib/capybara/queries/sibling_query.rb +26 -0
  28. data/lib/capybara/queries/style_query.rb +45 -0
  29. data/lib/capybara/queries/text_query.rb +88 -20
  30. data/lib/capybara/queries/title_query.rb +9 -11
  31. data/lib/capybara/rack_test/browser.rb +63 -39
  32. data/lib/capybara/rack_test/css_handlers.rb +6 -4
  33. data/lib/capybara/rack_test/driver.rb +26 -16
  34. data/lib/capybara/rack_test/errors.rb +6 -0
  35. data/lib/capybara/rack_test/form.rb +73 -58
  36. data/lib/capybara/rack_test/node.rb +187 -67
  37. data/lib/capybara/rails.rb +4 -8
  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 +142 -14
  43. data/lib/capybara/rspec/features.rb +17 -42
  44. data/lib/capybara/rspec/matcher_proxies.rb +82 -0
  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 +143 -244
  59. data/lib/capybara/rspec.rb +10 -12
  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 +102 -0
  63. data/lib/capybara/selector/definition/button.rb +63 -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 +278 -0
  85. data/lib/capybara/selector/filter.rb +3 -46
  86. data/lib/capybara/selector/filter_set.rb +124 -0
  87. data/lib/capybara/selector/filters/base.rb +77 -0
  88. data/lib/capybara/selector/filters/expression_filter.rb +22 -0
  89. data/lib/capybara/selector/filters/locator_filter.rb +29 -0
  90. data/lib/capybara/selector/filters/node_filter.rb +31 -0
  91. data/lib/capybara/selector/regexp_disassembler.rb +214 -0
  92. data/lib/capybara/selector/selector.rb +155 -0
  93. data/lib/capybara/selector/xpath_extensions.rb +17 -0
  94. data/lib/capybara/selector.rb +232 -369
  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 +380 -142
  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 +528 -97
  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 +63 -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 +74 -71
  127. data/lib/capybara/session/config.rb +126 -0
  128. data/lib/capybara/session/matchers.rb +44 -27
  129. data/lib/capybara/session.rb +500 -297
  130. data/lib/capybara/spec/fixtures/no_extension +1 -0
  131. data/lib/capybara/spec/public/jquery.js +5 -5
  132. data/lib/capybara/spec/public/offset.js +6 -0
  133. data/lib/capybara/spec/public/test.js +168 -14
  134. data/lib/capybara/spec/session/accept_alert_spec.rb +37 -14
  135. data/lib/capybara/spec/session/accept_confirm_spec.rb +7 -6
  136. data/lib/capybara/spec/session/accept_prompt_spec.rb +38 -10
  137. data/lib/capybara/spec/session/all_spec.rb +179 -59
  138. data/lib/capybara/spec/session/ancestor_spec.rb +88 -0
  139. data/lib/capybara/spec/session/assert_all_of_selectors_spec.rb +140 -0
  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_spec.rb +93 -0
  145. data/lib/capybara/spec/session/attach_file_spec.rb +154 -48
  146. data/lib/capybara/spec/session/body_spec.rb +12 -13
  147. data/lib/capybara/spec/session/check_spec.rb +168 -41
  148. data/lib/capybara/spec/session/choose_spec.rb +75 -23
  149. data/lib/capybara/spec/session/click_button_spec.rb +243 -175
  150. data/lib/capybara/spec/session/click_link_or_button_spec.rb +57 -32
  151. data/lib/capybara/spec/session/click_link_spec.rb +100 -53
  152. data/lib/capybara/spec/session/current_scope_spec.rb +11 -10
  153. data/lib/capybara/spec/session/current_url_spec.rb +61 -35
  154. data/lib/capybara/spec/session/dismiss_confirm_spec.rb +7 -7
  155. data/lib/capybara/spec/session/dismiss_prompt_spec.rb +5 -4
  156. data/lib/capybara/spec/session/element/{assert_match_selector.rb → assert_match_selector_spec.rb} +13 -6
  157. data/lib/capybara/spec/session/element/match_css_spec.rb +21 -7
  158. data/lib/capybara/spec/session/element/match_xpath_spec.rb +9 -7
  159. data/lib/capybara/spec/session/element/matches_selector_spec.rb +91 -34
  160. data/lib/capybara/spec/session/evaluate_async_script_spec.rb +23 -0
  161. data/lib/capybara/spec/session/evaluate_script_spec.rb +45 -3
  162. data/lib/capybara/spec/session/execute_script_spec.rb +24 -4
  163. data/lib/capybara/spec/session/fill_in_spec.rb +166 -64
  164. data/lib/capybara/spec/session/find_button_spec.rb +37 -18
  165. data/lib/capybara/spec/session/find_by_id_spec.rb +10 -9
  166. data/lib/capybara/spec/session/find_field_spec.rb +57 -34
  167. data/lib/capybara/spec/session/find_link_spec.rb +47 -10
  168. data/lib/capybara/spec/session/find_spec.rb +290 -144
  169. data/lib/capybara/spec/session/first_spec.rb +91 -48
  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 +116 -0
  173. data/lib/capybara/spec/session/frame/within_frame_spec.rb +112 -0
  174. data/lib/capybara/spec/session/go_back_spec.rb +3 -2
  175. data/lib/capybara/spec/session/go_forward_spec.rb +3 -2
  176. data/lib/capybara/spec/session/has_all_selectors_spec.rb +69 -0
  177. data/lib/capybara/spec/session/has_ancestor_spec.rb +46 -0
  178. data/lib/capybara/spec/session/has_any_selectors_spec.rb +25 -0
  179. data/lib/capybara/spec/session/has_button_spec.rb +76 -19
  180. data/lib/capybara/spec/session/has_css_spec.rb +277 -131
  181. data/lib/capybara/spec/session/has_current_path_spec.rb +98 -26
  182. data/lib/capybara/spec/session/has_field_spec.rb +177 -107
  183. data/lib/capybara/spec/session/has_link_spec.rb +13 -12
  184. data/lib/capybara/spec/session/has_none_selectors_spec.rb +78 -0
  185. data/lib/capybara/spec/session/has_select_spec.rb +191 -95
  186. data/lib/capybara/spec/session/has_selector_spec.rb +128 -64
  187. data/lib/capybara/spec/session/has_sibling_spec.rb +50 -0
  188. data/lib/capybara/spec/session/has_table_spec.rb +172 -5
  189. data/lib/capybara/spec/session/has_text_spec.rb +126 -60
  190. data/lib/capybara/spec/session/has_title_spec.rb +35 -12
  191. data/lib/capybara/spec/session/has_xpath_spec.rb +74 -53
  192. data/lib/capybara/spec/session/{headers.rb → headers_spec.rb} +3 -2
  193. data/lib/capybara/spec/session/html_spec.rb +14 -6
  194. data/lib/capybara/spec/session/matches_style_spec.rb +35 -0
  195. data/lib/capybara/spec/session/node_spec.rb +1028 -131
  196. data/lib/capybara/spec/session/node_wrapper_spec.rb +39 -0
  197. data/lib/capybara/spec/session/refresh_spec.rb +34 -0
  198. data/lib/capybara/spec/session/reset_session_spec.rb +75 -34
  199. data/lib/capybara/spec/session/{response_code.rb → response_code_spec.rb} +2 -1
  200. data/lib/capybara/spec/session/save_and_open_page_spec.rb +3 -2
  201. data/lib/capybara/spec/session/save_and_open_screenshot_spec.rb +11 -15
  202. data/lib/capybara/spec/session/save_page_spec.rb +42 -55
  203. data/lib/capybara/spec/session/save_screenshot_spec.rb +16 -14
  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 +112 -85
  207. data/lib/capybara/spec/session/selectors_spec.rb +71 -8
  208. data/lib/capybara/spec/session/sibling_spec.rb +52 -0
  209. data/lib/capybara/spec/session/text_spec.rb +38 -23
  210. data/lib/capybara/spec/session/title_spec.rb +17 -5
  211. data/lib/capybara/spec/session/uncheck_spec.rb +71 -12
  212. data/lib/capybara/spec/session/unselect_spec.rb +44 -43
  213. data/lib/capybara/spec/session/visit_spec.rb +99 -32
  214. data/lib/capybara/spec/session/window/become_closed_spec.rb +33 -29
  215. data/lib/capybara/spec/session/window/current_window_spec.rb +5 -3
  216. data/lib/capybara/spec/session/window/open_new_window_spec.rb +5 -3
  217. data/lib/capybara/spec/session/window/switch_to_window_spec.rb +39 -30
  218. data/lib/capybara/spec/session/window/window_opened_by_spec.rb +17 -10
  219. data/lib/capybara/spec/session/window/window_spec.rb +121 -73
  220. data/lib/capybara/spec/session/window/windows_spec.rb +12 -10
  221. data/lib/capybara/spec/session/window/within_window_spec.rb +52 -82
  222. data/lib/capybara/spec/session/within_spec.rb +76 -43
  223. data/lib/capybara/spec/spec_helper.rb +67 -33
  224. data/lib/capybara/spec/test_app.rb +85 -36
  225. data/lib/capybara/spec/views/animated.erb +49 -0
  226. data/lib/capybara/spec/views/buttons.erb +1 -1
  227. data/lib/capybara/spec/views/fieldsets.erb +1 -1
  228. data/lib/capybara/spec/views/form.erb +227 -20
  229. data/lib/capybara/spec/views/frame_child.erb +10 -2
  230. data/lib/capybara/spec/views/frame_one.erb +2 -1
  231. data/lib/capybara/spec/views/frame_parent.erb +2 -2
  232. data/lib/capybara/spec/views/frame_two.erb +1 -1
  233. data/lib/capybara/spec/views/header_links.erb +1 -1
  234. data/lib/capybara/spec/views/host_links.erb +1 -1
  235. data/lib/capybara/spec/views/initial_alert.erb +10 -0
  236. data/lib/capybara/spec/views/obscured.erb +47 -0
  237. data/lib/capybara/spec/views/offset.erb +32 -0
  238. data/lib/capybara/spec/views/path.erb +1 -1
  239. data/lib/capybara/spec/views/popup_one.erb +1 -1
  240. data/lib/capybara/spec/views/popup_two.erb +1 -1
  241. data/lib/capybara/spec/views/postback.erb +1 -1
  242. data/lib/capybara/spec/views/react.erb +45 -0
  243. data/lib/capybara/spec/views/scroll.erb +20 -0
  244. data/lib/capybara/spec/views/spatial.erb +31 -0
  245. data/lib/capybara/spec/views/tables.erb +69 -2
  246. data/lib/capybara/spec/views/with_animation.erb +82 -0
  247. data/lib/capybara/spec/views/with_base_tag.erb +1 -1
  248. data/lib/capybara/spec/views/with_count.erb +1 -1
  249. data/lib/capybara/spec/views/with_dragula.erb +24 -0
  250. data/lib/capybara/spec/views/with_fixed_header_footer.erb +17 -0
  251. data/lib/capybara/spec/views/with_hover.erb +7 -1
  252. data/lib/capybara/spec/views/with_hover1.erb +10 -0
  253. data/lib/capybara/spec/views/with_html.erb +100 -10
  254. data/lib/capybara/spec/views/with_html5_svg.erb +20 -0
  255. data/lib/capybara/spec/views/with_html_entities.erb +1 -1
  256. data/lib/capybara/spec/views/with_jquery_animation.erb +24 -0
  257. data/lib/capybara/spec/views/with_js.erb +49 -3
  258. data/lib/capybara/spec/views/with_jstree.erb +26 -0
  259. data/lib/capybara/spec/views/with_namespace.erb +20 -0
  260. data/lib/capybara/spec/views/with_scope.erb +1 -1
  261. data/lib/capybara/spec/views/with_scope_other.erb +6 -0
  262. data/lib/capybara/spec/views/with_simple_html.erb +1 -1
  263. data/lib/capybara/spec/views/with_sortable_js.erb +21 -0
  264. data/lib/capybara/spec/views/with_title.erb +1 -1
  265. data/lib/capybara/spec/views/with_unload_alert.erb +3 -1
  266. data/lib/capybara/spec/views/with_windows.erb +7 -1
  267. data/lib/capybara/spec/views/within_frames.erb +6 -3
  268. data/lib/capybara/version.rb +2 -1
  269. data/lib/capybara/window.rb +39 -21
  270. data/lib/capybara.rb +208 -186
  271. data/spec/basic_node_spec.rb +52 -39
  272. data/spec/capybara_spec.rb +72 -50
  273. data/spec/css_builder_spec.rb +101 -0
  274. data/spec/css_splitter_spec.rb +38 -0
  275. data/spec/dsl_spec.rb +81 -61
  276. data/spec/filter_set_spec.rb +46 -0
  277. data/spec/fixtures/capybara.csv +1 -0
  278. data/spec/fixtures/certificate.pem +25 -0
  279. data/spec/fixtures/key.pem +27 -0
  280. data/spec/fixtures/selenium_driver_rspec_failure.rb +7 -3
  281. data/spec/fixtures/selenium_driver_rspec_success.rb +7 -3
  282. data/spec/minitest_spec.rb +164 -0
  283. data/spec/minitest_spec_spec.rb +162 -0
  284. data/spec/per_session_config_spec.rb +68 -0
  285. data/spec/rack_test_spec.rb +189 -96
  286. data/spec/regexp_dissassembler_spec.rb +250 -0
  287. data/spec/result_spec.rb +143 -13
  288. data/spec/rspec/features_spec.rb +38 -32
  289. data/spec/rspec/scenarios_spec.rb +9 -7
  290. data/spec/rspec/shared_spec_matchers.rb +959 -0
  291. data/spec/rspec/views_spec.rb +9 -3
  292. data/spec/rspec_matchers_spec.rb +62 -0
  293. data/spec/rspec_spec.rb +127 -30
  294. data/spec/sauce_spec_chrome.rb +43 -0
  295. data/spec/selector_spec.rb +458 -37
  296. data/spec/selenium_spec_chrome.rb +196 -9
  297. data/spec/selenium_spec_chrome_remote.rb +100 -0
  298. data/spec/selenium_spec_edge.rb +47 -0
  299. data/spec/selenium_spec_firefox.rb +210 -0
  300. data/spec/selenium_spec_firefox_remote.rb +80 -0
  301. data/spec/selenium_spec_ie.rb +150 -0
  302. data/spec/selenium_spec_safari.rb +148 -0
  303. data/spec/server_spec.rb +200 -101
  304. data/spec/session_spec.rb +91 -0
  305. data/spec/shared_selenium_node.rb +83 -0
  306. data/spec/shared_selenium_session.rb +558 -0
  307. data/spec/spec_helper.rb +94 -2
  308. data/spec/xpath_builder_spec.rb +93 -0
  309. metadata +420 -60
  310. data/lib/capybara/query.rb +0 -7
  311. data/lib/capybara/spec/session/assert_current_path.rb +0 -60
  312. data/lib/capybara/spec/session/assert_selector.rb +0 -148
  313. data/lib/capybara/spec/session/assert_text.rb +0 -196
  314. data/lib/capybara/spec/session/assert_title.rb +0 -70
  315. data/lib/capybara/spec/session/source_spec.rb +0 -0
  316. data/lib/capybara/spec/session/within_frame_spec.rb +0 -53
  317. data/spec/rspec/matchers_spec.rb +0 -827
  318. data/spec/selenium_spec.rb +0 -151
@@ -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
data/spec/result_spec.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require 'spec_helper'
3
4
 
4
5
  RSpec.describe Capybara::Result do
@@ -14,43 +15,43 @@ RSpec.describe Capybara::Result do
14
15
  end
15
16
 
16
17
  let :result do
17
- string.all '//li'
18
+ string.all '//li', minimum: 0 # pass minimum: 0 so lazy evaluation doesn't get triggered yet
18
19
  end
19
20
 
20
- it "has a length" do
21
+ it 'has a length' do
21
22
  expect(result.length).to eq(4)
22
23
  end
23
24
 
24
- it "has a first element" do
25
+ it 'has a first element' do
25
26
  result.first.text == 'Alpha'
26
27
  end
27
28
 
28
- it "has a last element" do
29
+ it 'has a last element' do
29
30
  result.last.text == 'Delta'
30
31
  end
31
32
 
32
33
  it 'can supports values_at method' do
33
- expect(result.values_at(0, 2).map(&:text)).to eq(%w(Alpha Gamma))
34
+ expect(result.values_at(0, 2).map(&:text)).to eq(%w[Alpha Gamma])
34
35
  end
35
36
 
36
- it "can return an element by its index" do
37
+ it 'can return an element by its index' do
37
38
  expect(result.at(1).text).to eq('Beta')
38
39
  expect(result[2].text).to eq('Gamma')
39
40
  end
40
41
 
41
- it "can be mapped" do
42
- expect(result.map(&:text)).to eq(%w(Alpha Beta Gamma Delta))
42
+ it 'can be mapped' do
43
+ expect(result.map(&:text)).to eq(%w[Alpha Beta Gamma Delta])
43
44
  end
44
45
 
45
- it "can be selected" do
46
- expect(result.select do |element|
46
+ it 'can be selected' do
47
+ expect(result.count do |element|
47
48
  element.text.include? 't'
48
- end.length).to eq(2)
49
+ end).to eq(2)
49
50
  end
50
51
 
51
- it "can be reduced" do
52
+ it 'can be reduced' do
52
53
  expect(result.reduce('') do |memo, element|
53
- memo += element.text[0]
54
+ memo + element.text[0]
54
55
  end).to eq('ABGD')
55
56
  end
56
57
 
@@ -63,4 +64,133 @@ RSpec.describe Capybara::Result do
63
64
  el.text == 'Gamma'
64
65
  end).to eq(2)
65
66
  end
67
+
68
+ def recalc_result
69
+ string.all '//li', minimum: 0 # pass minimum: 0 so lazy evaluation doesn't get triggered yet
70
+ end
71
+
72
+ it 'supports all modes of []' do
73
+ expect(recalc_result[1].text).to eq 'Beta'
74
+ expect(recalc_result[0, 2].map(&:text)).to eq %w[Alpha Beta]
75
+ expect(recalc_result[1..3].map(&:text)).to eq %w[Beta Gamma Delta]
76
+ expect(recalc_result[-1].text).to eq 'Delta'
77
+ expect(recalc_result[-2, 3].map(&:text)).to eq %w[Gamma Delta]
78
+ expect(recalc_result[1...3].map(&:text)).to eq %w[Beta Gamma]
79
+ expect(recalc_result[1..7].map(&:text)).to eq %w[Beta Gamma Delta]
80
+ expect(recalc_result[2...-1].map(&:text)).to eq %w[Gamma]
81
+ expect(recalc_result[2..-1].map(&:text)).to eq %w[Gamma Delta]
82
+ end
83
+
84
+ eval <<~TEST, binding, __FILE__, __LINE__ + 1 if RUBY_VERSION.to_f > 2.5
85
+ it 'supports endless ranges' do
86
+ expect(result[2..].map(&:text)).to eq %w[Gamma Delta]
87
+ end
88
+ TEST
89
+
90
+ eval <<~TEST, binding, __FILE__, __LINE__ + 1 if RUBY_VERSION.to_f > 2.6
91
+ it 'supports inclusive positive beginless ranges' do
92
+ expect(result[..2].map(&:text)).to eq %w[Alpha Beta Gamma]
93
+ end
94
+
95
+ it 'supports inclusive negative beginless ranges' do
96
+ expect(result[..-2].map(&:text)).to eq %w[Alpha Beta Gamma]
97
+ expect(result[..-1].map(&:text)).to eq %w[Alpha Beta Gamma Delta]
98
+ end
99
+
100
+ it 'supports exclusive positive beginless ranges' do
101
+ expect(result[...2].map(&:text)).to eq %w[Alpha Beta]
102
+ end
103
+
104
+ it 'supports exclusive negative beginless ranges' do
105
+ expect(result[...-2].map(&:text)).to eq %w[Alpha Beta]
106
+ expect(result[...-1].map(&:text)).to eq %w[Alpha Beta Gamma]
107
+ end
108
+ TEST
109
+
110
+ it 'works with filter blocks' do
111
+ result = string.all('//li') { |node| node.text == 'Alpha' }
112
+ expect(result.size).to eq 1
113
+ end
114
+
115
+ # Not a great test but it indirectly tests what is needed
116
+ it 'should evaluate filters lazily for idx' do
117
+ skip 'JRuby has an issue with lazy enumerator evaluation' if jruby_lazy_enumerator_workaround?
118
+ # Not processed until accessed
119
+ expect(result.instance_variable_get('@result_cache').size).to be 0
120
+
121
+ # Only one retrieved when needed
122
+ result.first
123
+ expect(result.instance_variable_get('@result_cache').size).to be 1
124
+
125
+ # works for indexed access
126
+ result[0]
127
+ expect(result.instance_variable_get('@result_cache').size).to be 1
128
+
129
+ result[2]
130
+ expect(result.instance_variable_get('@result_cache').size).to be 3
131
+
132
+ # All cached when converted to array
133
+ result.to_a
134
+ expect(result.instance_variable_get('@result_cache').size).to eq 4
135
+ end
136
+
137
+ it 'should evaluate filters lazily for range' do
138
+ skip 'JRuby has an issue with lazy enumerator evaluation' if jruby_lazy_enumerator_workaround?
139
+ result[0..1]
140
+ expect(result.instance_variable_get('@result_cache').size).to be 2
141
+
142
+ expect(result[0..7].size).to eq 4
143
+ expect(result.instance_variable_get('@result_cache').size).to be 4
144
+ end
145
+
146
+ it 'should evaluate filters lazily for idx and length' do
147
+ skip 'JRuby has an issue with lazy enumerator evaluation' if jruby_lazy_enumerator_workaround?
148
+ result[1, 2]
149
+ expect(result.instance_variable_get('@result_cache').size).to be 3
150
+
151
+ expect(result[2, 5].size).to eq 2
152
+ expect(result.instance_variable_get('@result_cache').size).to be 4
153
+ end
154
+
155
+ it 'should only need to evaluate one result for any?' do
156
+ skip 'JRuby has an issue with lazy enumerator evaluation' if jruby_lazy_enumerator_workaround?
157
+ result.any?
158
+ expect(result.instance_variable_get('@result_cache').size).to be 1
159
+ end
160
+
161
+ it 'should evaluate all elements when #to_a called' do
162
+ # All cached when converted to array
163
+ result.to_a
164
+ expect(result.instance_variable_get('@result_cache').size).to eq 4
165
+ end
166
+
167
+ describe '#each' do
168
+ it 'lazily evaluates' do
169
+ skip 'JRuby has an issue with lazy enumerator evaluation' if jruby_lazy_enumerator_workaround?
170
+ results = []
171
+ result.each do |el|
172
+ results << el
173
+ expect(result.instance_variable_get('@result_cache').size).to eq results.size
174
+ end
175
+
176
+ expect(results.size).to eq 4
177
+ end
178
+
179
+ context 'without a block' do
180
+ it 'returns an iterator' do
181
+ expect(result.each).to be_a(Enumerator)
182
+ end
183
+
184
+ it 'lazily evaluates' do
185
+ skip 'JRuby has an issue with lazy enumerator evaluation' if jruby_lazy_enumerator_workaround?
186
+ result.each.with_index do |_el, idx|
187
+ expect(result.instance_variable_get('@result_cache').size).to eq(idx + 1) # 0 indexing
188
+ end
189
+ end
190
+ end
191
+ end
192
+
193
+ def jruby_lazy_enumerator_workaround?
194
+ RUBY_PLATFORM == 'java'
195
+ end
66
196
  end
@@ -1,44 +1,44 @@
1
1
  # frozen_string_literal: true
2
+
3
+ # rubocop:disable RSpec/MultipleDescribes
4
+
2
5
  require 'spec_helper'
3
6
  require 'capybara/rspec'
4
7
 
5
- RSpec.configuration.before(:each, { file_path: "./spec/rspec/features_spec.rb" } ) do
8
+ # rubocop:disable RSpec/InstanceVariable
9
+ RSpec.configuration.before(:each, file_path: './spec/rspec/features_spec.rb') do
6
10
  @in_filtered_hook = true
7
11
  end
8
12
 
9
- feature "Capybara's feature DSL" do
13
+ feature "Capybara's feature DSL" do
10
14
  background do
11
15
  @in_background = true
12
16
  end
13
-
14
- def current_example(context)
15
- RSpec.respond_to?(:current_example) ? RSpec.current_example : context.example
16
- end
17
17
 
18
- scenario "includes Capybara" do
18
+ scenario 'includes Capybara' do
19
19
  visit('/')
20
20
  expect(page).to have_content('Hello world!')
21
21
  end
22
22
 
23
- scenario "preserves description" do
24
- expect(current_example(self).metadata[:full_description])
23
+ scenario 'preserves description' do |ex|
24
+ expect(ex.metadata[:full_description])
25
25
  .to eq("Capybara's feature DSL preserves description")
26
26
  end
27
27
 
28
- scenario "allows driver switching", :driver => :selenium do
28
+ scenario 'allows driver switching', driver: :selenium do
29
29
  expect(Capybara.current_driver).to eq(:selenium)
30
30
  end
31
31
 
32
- scenario "runs background" do
32
+ scenario 'runs background' do
33
33
  expect(@in_background).to be_truthy
34
34
  end
35
35
 
36
- scenario "runs hooks filtered by file path" do
36
+ scenario 'runs hooks filtered by file path' do
37
37
  expect(@in_filtered_hook).to be_truthy
38
38
  end
39
39
 
40
40
  scenario "doesn't pollute the Object namespace" do
41
- expect(Object.new.respond_to?(:feature, true)).to be_falsey
41
+ expect(Object.new).not_to respond_to(:feature)
42
42
  end
43
43
 
44
44
  feature 'nested features' do
@@ -47,17 +47,18 @@ feature "Capybara's feature DSL" do
47
47
  expect(page).to have_content 'Hello world!'
48
48
  end
49
49
 
50
- scenario 'are marked in the metadata as capybara_feature' do
51
- expect(current_example(self).metadata[:capybara_feature]).to be_truthy
50
+ scenario 'are marked in the metadata as capybara_feature' do |ex|
51
+ expect(ex.metadata[:capybara_feature]).to be_truthy
52
52
  end
53
53
 
54
- scenario 'have a type of :feature' do
55
- expect(current_example(self).metadata[:type]).to eq :feature
54
+ scenario 'have a type of :feature' do |ex|
55
+ expect(ex.metadata[:type]).to eq :feature
56
56
  end
57
57
  end
58
58
  end
59
+ # rubocop:enable RSpec/InstanceVariable
59
60
 
60
- feature "given and given! aliases to let and let!" do
61
+ feature 'given and given! aliases to let and let!' do
61
62
  given(:value) { :available }
62
63
  given!(:value_in_background) { :available }
63
64
 
@@ -65,31 +66,36 @@ feature "given and given! aliases to let and let!" do
65
66
  expect(value_in_background).to be(:available)
66
67
  end
67
68
 
68
- scenario "given and given! work as intended" do
69
+ scenario 'given and given! work as intended' do
69
70
  expect(value).to be(:available)
70
71
  expect(value_in_background).to be(:available)
71
72
  end
72
73
  end
73
74
 
74
- feature "Capybara's feature DSL with driver", :driver => :culerity do
75
- scenario "switches driver" do
75
+ feature "Capybara's feature DSL with driver", driver: :culerity do
76
+ scenario 'switches driver' do
76
77
  expect(Capybara.current_driver).to eq(:culerity)
77
78
  end
78
79
  end
79
80
 
80
- if RSpec::Core::Version::STRING.to_f >= 3.0
81
- xfeature "if xfeature aliases to pending then" do
82
- scenario "this should be 'temporarily disabled with xfeature'" do; end
83
- scenario "this also should be 'temporarily disabled with xfeature'" do; end
81
+ # rubocop:disable RSpec/RepeatedExample
82
+ xfeature 'if xfeature aliases to pending then' do
83
+ scenario "this should be 'temporarily disabled with xfeature'" do
84
+ # dummy
84
85
  end
85
86
 
86
- ffeature "if ffeature aliases focused tag then" do
87
- scenario "scenario inside this feature has metatag focus tag" do |example|
88
- expect(example.metadata[:focus]).to eq true
89
- end
87
+ scenario "this also should be 'temporarily disabled with xfeature'" do
88
+ # dummy
89
+ end
90
+ end
90
91
 
91
- scenario "other scenarios also has metatag focus tag " do |example|
92
- expect(example.metadata[:focus]).to eq true
93
- end
92
+ ffeature 'if ffeature aliases focused tag then' do # rubocop:disable RSpec/Focus
93
+ scenario 'scenario inside this feature has metatag focus tag' do |example|
94
+ expect(example.metadata[:focus]).to eq true
95
+ end
96
+
97
+ scenario 'other scenarios also has metatag focus tag ' do |example|
98
+ expect(example.metadata[:focus]).to eq true
94
99
  end
95
100
  end
101
+ # rubocop:enable RSpec/RepeatedExample, RSpec/MultipleDescribes