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,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ Capybara::SpecHelper.spec '#evaluate_async_script', requires: [:js] do
4
+ it 'should evaluate the given script and return whatever it produces' do
5
+ @session.visit('/with_js')
6
+ expect(@session.evaluate_async_script('arguments[0](4)')).to eq(4)
7
+ end
8
+
9
+ it 'should support passing elements as arguments to the script', requires: %i[js es_args] do
10
+ @session.visit('/with_js')
11
+ el = @session.find(:css, '#drag p')
12
+ result = @session.evaluate_async_script('arguments[2]([arguments[0].innerText, arguments[1]])', el, 'Doodle Funk')
13
+ expect(result).to eq ['This is a draggable element.', 'Doodle Funk']
14
+ end
15
+
16
+ it 'should support returning elements after asynchronous operation', requires: %i[js es_args] do
17
+ @session.visit('/with_js')
18
+ @session.find(:css, '#change') # ensure page has loaded and element is available
19
+ el = @session.evaluate_async_script("var cb = arguments[0]; setTimeout(function(){ cb(document.getElementById('change')) }, 100)")
20
+ expect(el).to be_instance_of(Capybara::Node::Element)
21
+ expect(el).to eq(@session.find(:css, '#change'))
22
+ end
23
+ end
@@ -1,7 +1,49 @@
1
1
  # frozen_string_literal: true
2
- Capybara::SpecHelper.spec "#evaluate_script", :requires => [:js] do
3
- it "should evaluate the given script and return whatever it produces" do
2
+
3
+ Capybara::SpecHelper.spec '#evaluate_script', requires: [:js] do
4
+ it 'should evaluate the given script and return whatever it produces' do
4
5
  @session.visit('/with_js')
5
- expect(@session.evaluate_script("1+3")).to eq(4)
6
+ expect(@session.evaluate_script('1+3')).to eq(4)
7
+ end
8
+
9
+ it 'should ignore leading whitespace' do
10
+ @session.visit('/with_js')
11
+ expect(@session.evaluate_script('
12
+ 1 + 3
13
+ ')).to eq(4)
14
+ end
15
+
16
+ it 'should pass arguments to the script', requires: %i[js es_args] do
17
+ @session.visit('/with_js')
18
+ expect(@session).to have_css('#change')
19
+ @session.evaluate_script("document.getElementById('change').textContent = arguments[0]", 'Doodle Funk')
20
+ expect(@session).to have_css('#change', text: 'Doodle Funk')
21
+ end
22
+
23
+ it 'should support passing elements as arguments to the script', requires: %i[js es_args] do
24
+ @session.visit('/with_js')
25
+ el = @session.find(:css, '#change')
26
+ @session.evaluate_script('arguments[0].textContent = arguments[1]', el, 'Doodle Funk')
27
+ expect(@session).to have_css('#change', text: 'Doodle Funk')
28
+ end
29
+
30
+ it 'should support returning elements', requires: %i[js es_args] do
31
+ @session.visit('/with_js')
32
+ @session.find(:css, '#change') # ensure page has loaded and element is available
33
+ el = @session.evaluate_script("document.getElementById('change')")
34
+ expect(el).to be_instance_of(Capybara::Node::Element)
35
+ expect(el).to eq(@session.find(:css, '#change'))
36
+ end
37
+
38
+ it 'should support multi statement via IIFE' do
39
+ @session.visit('/with_js')
40
+ @session.find(:css, '#change')
41
+ el = @session.evaluate_script(<<~JS)
42
+ (function(){
43
+ var el = document.getElementById('change');
44
+ return el;
45
+ })()
46
+ JS
47
+ expect(el).to eq(@session.find(:css, '#change'))
6
48
  end
7
49
  end
@@ -1,8 +1,28 @@
1
1
  # frozen_string_literal: true
2
- Capybara::SpecHelper.spec "#execute_script", :requires => [:js] do
3
- it "should execute the given script and return nothing" do
2
+
3
+ Capybara::SpecHelper.spec '#execute_script', requires: [:js] do
4
+ it 'should execute the given script and return nothing' do
4
5
  @session.visit('/with_js')
5
- expect(@session.execute_script("$('#change').text('Funky Doodle')")).to be_nil
6
- expect(@session).to have_css('#change', :text => 'Funky Doodle')
6
+ expect(@session.execute_script("document.getElementById('change').textContent = 'Funky Doodle'")).to be_nil
7
+ expect(@session).to have_css('#change', text: 'Funky Doodle')
8
+ end
9
+
10
+ it 'should be able to call functions defined in the page' do
11
+ @session.visit('/with_js')
12
+ expect { @session.execute_script("$('#change').text('Funky Doodle')") }.not_to raise_error
13
+ end
14
+
15
+ it 'should pass arguments to the script', requires: %i[js es_args] do
16
+ @session.visit('/with_js')
17
+ expect(@session).to have_css('#change')
18
+ @session.execute_script("document.getElementById('change').textContent = arguments[0]", 'Doodle Funk')
19
+ expect(@session).to have_css('#change', text: 'Doodle Funk')
20
+ end
21
+
22
+ it 'should support passing elements as arguments to the script', requires: %i[js es_args] do
23
+ @session.visit('/with_js')
24
+ el = @session.find(:css, '#change')
25
+ @session.execute_script('arguments[1].textContent = arguments[0]', 'Doodle Funk', el)
26
+ expect(@session).to have_css('#change', text: 'Doodle Funk')
7
27
  end
8
28
  end
@@ -1,184 +1,286 @@
1
1
  # frozen_string_literal: true
2
- Capybara::SpecHelper.spec "#fill_in" do
2
+
3
+ Capybara::SpecHelper.spec '#fill_in' do
3
4
  before do
4
5
  @session.visit('/form')
5
6
  end
6
7
 
7
- it "should fill in a text field by id" do
8
- @session.fill_in('form_first_name', :with => 'Harry')
8
+ it 'should fill in a text field by id' do
9
+ @session.fill_in('form_first_name', with: 'Harry')
9
10
  @session.click_button('awesome')
10
11
  expect(extract_results(@session)['first_name']).to eq('Harry')
11
12
  end
12
13
 
13
- it "should fill in a text field by name" do
14
- @session.fill_in('form[last_name]', :with => 'Green')
14
+ it 'should fill in a text field by name' do
15
+ @session.fill_in('form[last_name]', with: 'Green')
15
16
  @session.click_button('awesome')
16
17
  expect(extract_results(@session)['last_name']).to eq('Green')
17
18
  end
18
19
 
19
- it "should fill in a text field by label without for" do
20
- @session.fill_in('First Name', :with => 'Harry')
20
+ it 'should fill in a text field by label without for' do
21
+ @session.fill_in('First Name', with: 'Harry')
21
22
  @session.click_button('awesome')
22
23
  expect(extract_results(@session)['first_name']).to eq('Harry')
23
24
  end
24
25
 
25
- it "should fill in a url field by label without for" do
26
- @session.fill_in('Html5 Url', :with => 'http://www.avenueq.com')
26
+ it 'should fill in a url field by label without for' do
27
+ @session.fill_in('Html5 Url', with: 'http://www.avenueq.com')
27
28
  @session.click_button('html5_submit')
28
29
  expect(extract_results(@session)['html5_url']).to eq('http://www.avenueq.com')
29
30
  end
30
31
 
31
- it "should fill in a textarea by id" do
32
- @session.fill_in('form_description', :with => 'Texty text')
32
+ it 'should fill in a textarea by id' do
33
+ @session.fill_in('form_description', with: 'Texty text')
33
34
  @session.click_button('awesome')
34
35
  expect(extract_results(@session)['description']).to eq('Texty text')
35
36
  end
36
37
 
37
- it "should fill in a textarea by label" do
38
- @session.fill_in('Description', :with => 'Texty text')
38
+ it 'should fill in a textarea by label' do
39
+ @session.fill_in('Description', with: 'Texty text')
39
40
  @session.click_button('awesome')
40
41
  expect(extract_results(@session)['description']).to eq('Texty text')
41
42
  end
42
43
 
43
- it "should fill in a textarea by name" do
44
- @session.fill_in('form[description]', :with => 'Texty text')
44
+ it 'should fill in a textarea by name' do
45
+ @session.fill_in('form[description]', with: 'Texty text')
45
46
  @session.click_button('awesome')
46
47
  expect(extract_results(@session)['description']).to eq('Texty text')
47
48
  end
48
49
 
49
- it "should fill in a password field by id" do
50
- @session.fill_in('form_password', :with => 'supasikrit')
50
+ it 'should fill in a textarea in a reasonable time by default' do
51
+ textarea = @session.find(:fillable_field, 'form[description]')
52
+ value = 'a' * 4000
53
+ start = Time.now
54
+ textarea.fill_in(with: value)
55
+ expect(Time.now.to_f).to be_within(0.25).of start.to_f
56
+ expect(textarea.value).to eq value
57
+ end
58
+
59
+ it 'should fill in a password field by id' do
60
+ @session.fill_in('form_password', with: 'supasikrit')
51
61
  @session.click_button('awesome')
52
62
  expect(extract_results(@session)['password']).to eq('supasikrit')
53
63
  end
54
64
 
55
- it "should handle HTML in a textarea" do
56
- @session.fill_in('form_description', :with => 'is <strong>very</strong> secret!')
65
+ context 'Date/Time' do
66
+ it 'should fill in a date input' do
67
+ date = Date.today
68
+ @session.fill_in('form_date', with: date)
69
+ @session.click_button('awesome')
70
+ expect(Date.parse(extract_results(@session)['date'])).to eq date
71
+ end
72
+
73
+ it 'should fill in a time input' do
74
+ time = Time.new(2018, 3, 9, 15, 26)
75
+ @session.fill_in('form_time', with: time)
76
+ @session.click_button('awesome')
77
+ results = extract_results(@session)['time']
78
+ expect(Time.parse(results).strftime('%r')).to eq time.strftime('%r')
79
+ end
80
+
81
+ it 'should fill in a datetime input' do
82
+ dt = Time.new(2018, 3, 13, 9, 53)
83
+ @session.fill_in('form_datetime', with: dt)
84
+ @session.click_button('awesome')
85
+ expect(Time.parse(extract_results(@session)['datetime'])).to eq dt
86
+ end
87
+ end
88
+
89
+ it 'should handle HTML in a textarea' do
90
+ @session.fill_in('form_description', with: 'is <strong>very</strong> secret!')
57
91
  @session.click_button('awesome')
58
92
  expect(extract_results(@session)['description']).to eq('is <strong>very</strong> secret!')
59
93
  end
60
94
 
61
- it "should handle newlines in a textarea" do
62
- @session.fill_in('form_description', :with => "\nSome text\n")
95
+ it 'should handle newlines in a textarea' do
96
+ @session.fill_in('form_description', with: "\nSome text\n")
63
97
  @session.click_button('awesome')
64
98
  expect(extract_results(@session)['description']).to eq("\r\nSome text\r\n")
65
99
  end
66
100
 
67
- it "should fill in a field with a custom type" do
68
- @session.fill_in('Schmooo', :with => 'Schmooo is the game')
101
+ it 'should fill in a color field' do
102
+ @session.fill_in('Html5 Color', with: '#112233')
103
+ @session.click_button('html5_submit')
104
+ expect(extract_results(@session)['html5_color']).to eq('#112233')
105
+ end
106
+
107
+ describe 'with input[type="range"]' do
108
+ it 'should set the range slider correctly' do
109
+ @session.fill_in('form_age', with: 51)
110
+ @session.click_button('awesome')
111
+ expect(extract_results(@session)['age'].to_f).to eq 51
112
+ end
113
+
114
+ it 'should set the range slider to valid values' do
115
+ @session.fill_in('form_age', with: '37.6')
116
+ @session.click_button('awesome')
117
+ expect(extract_results(@session)['age'].to_f).to eq 37.5
118
+ end
119
+
120
+ it 'should respect the range slider limits' do
121
+ @session.fill_in('form_age', with: '3')
122
+ @session.click_button('awesome')
123
+ expect(extract_results(@session)['age'].to_f).to eq 13
124
+ end
125
+ end
126
+
127
+ it 'should fill in a field with a custom type' do
128
+ @session.fill_in('Schmooo', with: 'Schmooo is the game')
69
129
  @session.click_button('awesome')
70
130
  expect(extract_results(@session)['schmooo']).to eq('Schmooo is the game')
71
131
  end
72
132
 
73
- it "should fill in a field without a type" do
74
- @session.fill_in('Phone', :with => '+1 555 7022')
133
+ it 'should fill in a field without a type' do
134
+ @session.fill_in('Phone', with: '+1 555 7022')
75
135
  @session.click_button('awesome')
76
136
  expect(extract_results(@session)['phone']).to eq('+1 555 7022')
77
137
  end
78
138
 
79
- it "should fill in a text field respecting its maxlength attribute" do
80
- @session.fill_in('Zipcode', :with => '52071350')
139
+ it 'should fill in a text field respecting its maxlength attribute' do
140
+ @session.fill_in('Zipcode', with: '52071350')
81
141
  @session.click_button('awesome')
82
142
  expect(extract_results(@session)['zipcode']).to eq('52071')
83
143
  end
84
144
 
85
- it "should fill in a password field by name" do
86
- @session.fill_in('form[password]', :with => 'supasikrit')
145
+ it 'should fill in a password field by name' do
146
+ @session.fill_in('form[password]', with: 'supasikrit')
87
147
  @session.click_button('awesome')
88
148
  expect(extract_results(@session)['password']).to eq('supasikrit')
89
149
  end
90
150
 
91
- it "should fill in a password field by label" do
92
- @session.fill_in('Password', :with => 'supasikrit')
151
+ it 'should fill in a password field by label' do
152
+ @session.fill_in('Password', with: 'supasikrit')
93
153
  @session.click_button('awesome')
94
154
  expect(extract_results(@session)['password']).to eq('supasikrit')
95
155
  end
96
156
 
97
- it "should fill in a password field by name" do
98
- @session.fill_in('form[password]', :with => 'supasikrit')
157
+ it 'should fill in a password field by name' do
158
+ @session.fill_in('form[password]', with: 'supasikrit')
159
+ @session.click_button('awesome')
160
+ expect(extract_results(@session)['password']).to eq('supasikrit')
161
+ end
162
+
163
+ it 'should fill in a field based on current value' do
164
+ @session.fill_in(id: /form.*name/, currently_with: 'John', with: 'Thomas')
165
+ @session.click_button('awesome')
166
+ expect(extract_results(@session)['first_name']).to eq('Thomas')
167
+ end
168
+
169
+ it 'should fill in a field based on type' do
170
+ @session.fill_in(type: 'schmooo', with: 'Schmooo for all')
171
+ @session.click_button('awesome')
172
+ expect(extract_results(@session)['schmooo']).to eq('Schmooo for all')
173
+ end
174
+
175
+ it 'should be able to fill in element called on when no locator passed' do
176
+ field = @session.find(:fillable_field, 'form[password]')
177
+ field.fill_in(with: 'supasikrit')
99
178
  @session.click_button('awesome')
100
179
  expect(extract_results(@session)['password']).to eq('supasikrit')
101
180
  end
102
181
 
103
182
  it "should throw an exception if a hash containing 'with' is not provided" do
104
- expect {@session.fill_in 'Name', 'ignu'}.to raise_error(RuntimeError, /with/)
183
+ expect { @session.fill_in 'Name' }.to raise_error(ArgumentError, /with/)
105
184
  end
106
185
 
107
- it "should wait for asynchronous load", :requires => [:js] do
186
+ it 'should wait for asynchronous load', requires: [:js] do
187
+ Capybara.default_max_wait_time = 2
108
188
  @session.visit('/with_js')
109
189
  @session.click_link('Click me')
110
- @session.fill_in('new_field', :with => 'Testing...')
190
+ @session.fill_in('new_field', with: 'Testing...')
111
191
  end
112
192
 
113
- it "casts to string" do
114
- @session.fill_in(:'form_first_name', :with => :'Harry')
193
+ it 'casts to string' do
194
+ @session.fill_in(:form_first_name, with: :Harry)
115
195
  @session.click_button('awesome')
116
196
  expect(extract_results(@session)['first_name']).to eq('Harry')
117
197
  end
118
198
 
119
- it "casts to string if field has maxlength" do
120
- @session.fill_in(:'form_zipcode', :with => 1234567)
199
+ it 'casts to string if field has maxlength' do
200
+ @session.fill_in(:form_zipcode, with: 1234567)
121
201
  @session.click_button('awesome')
122
202
  expect(extract_results(@session)['zipcode']).to eq('12345')
123
203
  end
124
204
 
125
- context 'on a pre-populated textfield with a reformatting onchange', :requires => [:js] do
205
+ it 'fills in a field if default_set_options is nil' do
206
+ Capybara.default_set_options = nil
207
+ @session.fill_in(:form_first_name, with: 'Thomas')
208
+ @session.click_button('awesome')
209
+ expect(extract_results(@session)['first_name']).to eq('Thomas')
210
+ end
211
+
212
+ context 'on a pre-populated textfield with a reformatting onchange', requires: [:js] do
126
213
  it 'should only trigger onchange once' do
127
214
  @session.visit('/with_js')
128
- @session.fill_in('with_change_event', :with => 'some value')
215
+ # Click somewhere on the page to ensure focus is acquired. Without this FF won't generate change events for some reason???
216
+ @session.find(:css, 'h1', text: 'FooBar').click
217
+ @session.fill_in('with_change_event', with: 'some value')
129
218
  # click outside the field to trigger the change event
130
- @session.find(:css, 'body').click
131
- expect(@session.find(:css, '.change_event_triggered', :match => :one)).to have_text 'some value'
219
+ @session.find(:css, 'h1', text: 'FooBar').click
220
+ expect(@session.find(:css, '.change_event_triggered', match: :one)).to have_text 'some value'
132
221
  end
133
222
 
134
223
  it 'should trigger change when clearing field' do
135
224
  @session.visit('/with_js')
136
- @session.fill_in('with_change_event', :with => '')
225
+ @session.fill_in('with_change_event', with: '')
137
226
  # click outside the field to trigger the change event
138
- @session.find(:css, 'body').click
139
- expect(@session).to have_selector(:css, '.change_event_triggered', :match => :one)
227
+ @session.find(:css, 'h1', text: 'FooBar').click
228
+ expect(@session).to have_selector(:css, '.change_event_triggered', match: :one)
140
229
  end
141
230
  end
142
231
 
143
- context "with ignore_hidden_fields" do
232
+ context 'with ignore_hidden_fields' do
144
233
  before { Capybara.ignore_hidden_elements = true }
234
+
145
235
  after { Capybara.ignore_hidden_elements = false }
146
- it "should not find a hidden field" do
147
- msg = "Unable to find field \"Super Secret\""
236
+
237
+ it 'should not find a hidden field' do
238
+ msg = /Unable to find visible field "Super Secret"/
148
239
  expect do
149
- @session.fill_in('Super Secret', :with => '777')
240
+ @session.fill_in('Super Secret', with: '777')
150
241
  end.to raise_error(Capybara::ElementNotFound, msg)
151
242
  end
152
243
  end
153
244
 
154
245
  context "with a locator that doesn't exist" do
155
- it "should raise an error" do
156
- msg = "Unable to find field \"does not exist\""
246
+ it 'should raise an error' do
247
+ msg = /Unable to find field "does not exist"/
157
248
  expect do
158
- @session.fill_in('does not exist', :with => 'Blah blah')
249
+ @session.fill_in('does not exist', with: 'Blah blah')
159
250
  end.to raise_error(Capybara::ElementNotFound, msg)
160
251
  end
161
252
  end
162
253
 
163
- context "on a disabled field" do
164
- it "should raise an error" do
254
+ context 'on a disabled field' do
255
+ it 'should raise an error' do
165
256
  expect do
166
- @session.fill_in('Disabled Text Field', :with => 'Blah blah')
257
+ @session.fill_in('Disabled Text Field', with: 'Blah blah')
167
258
  end.to raise_error(Capybara::ElementNotFound)
168
259
  end
169
260
  end
170
261
 
171
- context "with :exact option" do
172
- it "should accept partial matches when false" do
173
- @session.fill_in("Explanation", :with => "Dude", :exact => false)
174
- @session.click_button("awesome")
175
- expect(extract_results(@session)["name_explanation"]).to eq("Dude")
262
+ context 'with :exact option' do
263
+ it 'should accept partial matches when false' do
264
+ @session.fill_in('Explanation', with: 'Dude', exact: false)
265
+ @session.click_button('awesome')
266
+ expect(extract_results(@session)['name_explanation']).to eq('Dude')
176
267
  end
177
268
 
178
- it "should not accept partial matches when true" do
269
+ it 'should not accept partial matches when true' do
179
270
  expect do
180
- @session.fill_in("Explanation", :with => "Dude", :exact => true)
271
+ @session.fill_in('Explanation', with: 'Dude', exact: true)
181
272
  end.to raise_error(Capybara::ElementNotFound)
182
273
  end
183
274
  end
275
+
276
+ it 'should return the element filled in' do
277
+ el = @session.find(:fillable_field, 'form_first_name')
278
+ expect(@session.fill_in('form_first_name', with: 'Harry')).to eq el
279
+ end
280
+
281
+ it 'should warn if passed what looks like a CSS id selector' do
282
+ expect do
283
+ @session.fill_in('#form_first_name', with: 'Harry')
284
+ end.to raise_error(/you may be passing a CSS selector or XPath expression rather than a locator/)
285
+ end
184
286
  end