capybara 3.3.0 → 3.40.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (308) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +1 -0
  3. data/History.md +803 -13
  4. data/License.txt +1 -1
  5. data/README.md +257 -84
  6. data/lib/capybara/config.rb +25 -9
  7. data/lib/capybara/cucumber.rb +1 -1
  8. data/lib/capybara/driver/base.rb +17 -3
  9. data/lib/capybara/driver/node.rb +31 -6
  10. data/lib/capybara/dsl.rb +9 -7
  11. data/lib/capybara/helpers.rb +31 -7
  12. data/lib/capybara/minitest/spec.rb +180 -88
  13. data/lib/capybara/minitest.rb +262 -149
  14. data/lib/capybara/node/actions.rb +202 -116
  15. data/lib/capybara/node/base.rb +34 -19
  16. data/lib/capybara/node/document.rb +14 -2
  17. data/lib/capybara/node/document_matchers.rb +10 -12
  18. data/lib/capybara/node/element.rb +269 -115
  19. data/lib/capybara/node/finders.rb +99 -77
  20. data/lib/capybara/node/matchers.rb +327 -151
  21. data/lib/capybara/node/simple.rb +48 -13
  22. data/lib/capybara/node/whitespace_normalizer.rb +81 -0
  23. data/lib/capybara/queries/active_element_query.rb +18 -0
  24. data/lib/capybara/queries/ancestor_query.rb +8 -9
  25. data/lib/capybara/queries/base_query.rb +23 -16
  26. data/lib/capybara/queries/current_path_query.rb +16 -6
  27. data/lib/capybara/queries/match_query.rb +1 -0
  28. data/lib/capybara/queries/selector_query.rb +587 -130
  29. data/lib/capybara/queries/sibling_query.rb +8 -6
  30. data/lib/capybara/queries/style_query.rb +6 -2
  31. data/lib/capybara/queries/text_query.rb +28 -14
  32. data/lib/capybara/queries/title_query.rb +2 -2
  33. data/lib/capybara/rack_test/browser.rb +92 -25
  34. data/lib/capybara/rack_test/driver.rb +16 -7
  35. data/lib/capybara/rack_test/errors.rb +6 -0
  36. data/lib/capybara/rack_test/form.rb +68 -41
  37. data/lib/capybara/rack_test/node.rb +106 -39
  38. data/lib/capybara/rails.rb +1 -1
  39. data/lib/capybara/registration_container.rb +41 -0
  40. data/lib/capybara/registrations/drivers.rb +42 -0
  41. data/lib/capybara/registrations/patches/puma_ssl.rb +29 -0
  42. data/lib/capybara/registrations/servers.rb +66 -0
  43. data/lib/capybara/result.rb +75 -52
  44. data/lib/capybara/rspec/features.rb +7 -7
  45. data/lib/capybara/rspec/matcher_proxies.rb +39 -18
  46. data/lib/capybara/rspec/matchers/base.rb +113 -0
  47. data/lib/capybara/rspec/matchers/become_closed.rb +33 -0
  48. data/lib/capybara/rspec/matchers/compound.rb +88 -0
  49. data/lib/capybara/rspec/matchers/count_sugar.rb +37 -0
  50. data/lib/capybara/rspec/matchers/have_ancestor.rb +28 -0
  51. data/lib/capybara/rspec/matchers/have_current_path.rb +29 -0
  52. data/lib/capybara/rspec/matchers/have_selector.rb +69 -0
  53. data/lib/capybara/rspec/matchers/have_sibling.rb +27 -0
  54. data/lib/capybara/rspec/matchers/have_text.rb +33 -0
  55. data/lib/capybara/rspec/matchers/have_title.rb +29 -0
  56. data/lib/capybara/rspec/matchers/match_selector.rb +27 -0
  57. data/lib/capybara/rspec/matchers/match_style.rb +43 -0
  58. data/lib/capybara/rspec/matchers/spatial_sugar.rb +39 -0
  59. data/lib/capybara/rspec/matchers.rb +141 -339
  60. data/lib/capybara/rspec.rb +2 -0
  61. data/lib/capybara/selector/builders/css_builder.rb +84 -0
  62. data/lib/capybara/selector/builders/xpath_builder.rb +71 -0
  63. data/lib/capybara/selector/css.rb +27 -25
  64. data/lib/capybara/selector/definition/button.rb +68 -0
  65. data/lib/capybara/selector/definition/checkbox.rb +26 -0
  66. data/lib/capybara/selector/definition/css.rb +10 -0
  67. data/lib/capybara/selector/definition/datalist_input.rb +35 -0
  68. data/lib/capybara/selector/definition/datalist_option.rb +25 -0
  69. data/lib/capybara/selector/definition/element.rb +28 -0
  70. data/lib/capybara/selector/definition/field.rb +40 -0
  71. data/lib/capybara/selector/definition/fieldset.rb +14 -0
  72. data/lib/capybara/selector/definition/file_field.rb +13 -0
  73. data/lib/capybara/selector/definition/fillable_field.rb +33 -0
  74. data/lib/capybara/selector/definition/frame.rb +17 -0
  75. data/lib/capybara/selector/definition/id.rb +6 -0
  76. data/lib/capybara/selector/definition/label.rb +62 -0
  77. data/lib/capybara/selector/definition/link.rb +55 -0
  78. data/lib/capybara/selector/definition/link_or_button.rb +16 -0
  79. data/lib/capybara/selector/definition/option.rb +27 -0
  80. data/lib/capybara/selector/definition/radio_button.rb +27 -0
  81. data/lib/capybara/selector/definition/select.rb +81 -0
  82. data/lib/capybara/selector/definition/table.rb +109 -0
  83. data/lib/capybara/selector/definition/table_row.rb +21 -0
  84. data/lib/capybara/selector/definition/xpath.rb +5 -0
  85. data/lib/capybara/selector/definition.rb +280 -0
  86. data/lib/capybara/selector/filter.rb +1 -0
  87. data/lib/capybara/selector/filter_set.rb +73 -25
  88. data/lib/capybara/selector/filters/base.rb +24 -5
  89. data/lib/capybara/selector/filters/expression_filter.rb +3 -3
  90. data/lib/capybara/selector/filters/locator_filter.rb +29 -0
  91. data/lib/capybara/selector/filters/node_filter.rb +16 -2
  92. data/lib/capybara/selector/regexp_disassembler.rb +211 -0
  93. data/lib/capybara/selector/selector.rb +85 -348
  94. data/lib/capybara/selector/xpath_extensions.rb +17 -0
  95. data/lib/capybara/selector.rb +474 -447
  96. data/lib/capybara/selenium/atoms/getAttribute.min.js +1 -0
  97. data/lib/capybara/selenium/atoms/isDisplayed.min.js +1 -0
  98. data/lib/capybara/selenium/atoms/src/getAttribute.js +161 -0
  99. data/lib/capybara/selenium/atoms/src/isDisplayed.js +454 -0
  100. data/lib/capybara/selenium/driver.rb +255 -143
  101. data/lib/capybara/selenium/driver_specializations/chrome_driver.rb +93 -11
  102. data/lib/capybara/selenium/driver_specializations/edge_driver.rb +128 -0
  103. data/lib/capybara/selenium/driver_specializations/firefox_driver.rb +84 -0
  104. data/lib/capybara/selenium/driver_specializations/internet_explorer_driver.rb +26 -0
  105. data/lib/capybara/selenium/driver_specializations/safari_driver.rb +24 -0
  106. data/lib/capybara/selenium/extensions/file_input_click_emulation.rb +34 -0
  107. data/lib/capybara/selenium/extensions/find.rb +110 -0
  108. data/lib/capybara/selenium/extensions/html5_drag.rb +229 -0
  109. data/lib/capybara/selenium/extensions/modifier_keys_stack.rb +28 -0
  110. data/lib/capybara/selenium/extensions/scroll.rb +76 -0
  111. data/lib/capybara/selenium/node.rb +436 -134
  112. data/lib/capybara/selenium/nodes/chrome_node.rb +125 -0
  113. data/lib/capybara/selenium/nodes/edge_node.rb +110 -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/atoms.rb +18 -0
  118. data/lib/capybara/selenium/patches/is_displayed.rb +16 -0
  119. data/lib/capybara/selenium/patches/logs.rb +45 -0
  120. data/lib/capybara/selenium/patches/pause_duration_fix.rb +9 -0
  121. data/lib/capybara/selenium/patches/persistent_client.rb +20 -0
  122. data/lib/capybara/server/animation_disabler.rb +56 -19
  123. data/lib/capybara/server/checker.rb +9 -3
  124. data/lib/capybara/server/middleware.rb +28 -12
  125. data/lib/capybara/server.rb +33 -10
  126. data/lib/capybara/session/config.rb +34 -10
  127. data/lib/capybara/session/matchers.rb +23 -16
  128. data/lib/capybara/session.rb +230 -170
  129. data/lib/capybara/spec/public/jquery.js +5 -5
  130. data/lib/capybara/spec/public/offset.js +6 -0
  131. data/lib/capybara/spec/public/test.js +121 -8
  132. data/lib/capybara/spec/session/accept_alert_spec.rb +11 -11
  133. data/lib/capybara/spec/session/accept_confirm_spec.rb +3 -3
  134. data/lib/capybara/spec/session/accept_prompt_spec.rb +9 -10
  135. data/lib/capybara/spec/session/active_element_spec.rb +31 -0
  136. data/lib/capybara/spec/session/all_spec.rb +127 -40
  137. data/lib/capybara/spec/session/ancestor_spec.rb +24 -19
  138. data/lib/capybara/spec/session/assert_all_of_selectors_spec.rb +67 -38
  139. data/lib/capybara/spec/session/assert_current_path_spec.rb +21 -18
  140. data/lib/capybara/spec/session/assert_selector_spec.rb +52 -58
  141. data/lib/capybara/spec/session/assert_style_spec.rb +7 -7
  142. data/lib/capybara/spec/session/assert_text_spec.rb +74 -50
  143. data/lib/capybara/spec/session/assert_title_spec.rb +12 -12
  144. data/lib/capybara/spec/session/attach_file_spec.rb +126 -72
  145. data/lib/capybara/spec/session/body_spec.rb +6 -6
  146. data/lib/capybara/spec/session/check_spec.rb +102 -47
  147. data/lib/capybara/spec/session/choose_spec.rb +58 -32
  148. data/lib/capybara/spec/session/click_button_spec.rb +219 -163
  149. data/lib/capybara/spec/session/click_link_or_button_spec.rb +49 -23
  150. data/lib/capybara/spec/session/click_link_spec.rb +77 -54
  151. data/lib/capybara/spec/session/current_scope_spec.rb +8 -8
  152. data/lib/capybara/spec/session/current_url_spec.rb +38 -29
  153. data/lib/capybara/spec/session/dismiss_confirm_spec.rb +3 -3
  154. data/lib/capybara/spec/session/dismiss_prompt_spec.rb +2 -2
  155. data/lib/capybara/spec/session/element/assert_match_selector_spec.rb +8 -8
  156. data/lib/capybara/spec/session/element/match_css_spec.rb +16 -10
  157. data/lib/capybara/spec/session/element/match_xpath_spec.rb +6 -6
  158. data/lib/capybara/spec/session/element/matches_selector_spec.rb +68 -56
  159. data/lib/capybara/spec/session/evaluate_async_script_spec.rb +7 -7
  160. data/lib/capybara/spec/session/evaluate_script_spec.rb +28 -8
  161. data/lib/capybara/spec/session/execute_script_spec.rb +8 -7
  162. data/lib/capybara/spec/session/fill_in_spec.rb +101 -46
  163. data/lib/capybara/spec/session/find_button_spec.rb +23 -23
  164. data/lib/capybara/spec/session/find_by_id_spec.rb +7 -7
  165. data/lib/capybara/spec/session/find_field_spec.rb +32 -30
  166. data/lib/capybara/spec/session/find_link_spec.rb +31 -21
  167. data/lib/capybara/spec/session/find_spec.rb +244 -141
  168. data/lib/capybara/spec/session/first_spec.rb +43 -43
  169. data/lib/capybara/spec/session/frame/frame_title_spec.rb +5 -5
  170. data/lib/capybara/spec/session/frame/frame_url_spec.rb +5 -5
  171. data/lib/capybara/spec/session/frame/switch_to_frame_spec.rb +30 -18
  172. data/lib/capybara/spec/session/frame/within_frame_spec.rb +45 -18
  173. data/lib/capybara/spec/session/go_back_spec.rb +1 -1
  174. data/lib/capybara/spec/session/go_forward_spec.rb +1 -1
  175. data/lib/capybara/spec/session/has_all_selectors_spec.rb +23 -23
  176. data/lib/capybara/spec/session/has_ancestor_spec.rb +46 -0
  177. data/lib/capybara/spec/session/has_any_selectors_spec.rb +29 -0
  178. data/lib/capybara/spec/session/has_button_spec.rb +94 -13
  179. data/lib/capybara/spec/session/has_css_spec.rb +272 -132
  180. data/lib/capybara/spec/session/has_current_path_spec.rb +50 -35
  181. data/lib/capybara/spec/session/has_element_spec.rb +47 -0
  182. data/lib/capybara/spec/session/has_field_spec.rb +137 -58
  183. data/lib/capybara/spec/session/has_link_spec.rb +44 -4
  184. data/lib/capybara/spec/session/has_none_selectors_spec.rb +31 -31
  185. data/lib/capybara/spec/session/has_select_spec.rb +84 -50
  186. data/lib/capybara/spec/session/has_selector_spec.rb +111 -71
  187. data/lib/capybara/spec/session/has_sibling_spec.rb +50 -0
  188. data/lib/capybara/spec/session/has_table_spec.rb +181 -4
  189. data/lib/capybara/spec/session/has_text_spec.rb +101 -53
  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_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 +37 -0
  195. data/lib/capybara/spec/session/node_spec.rb +894 -142
  196. data/lib/capybara/spec/session/node_wrapper_spec.rb +10 -7
  197. data/lib/capybara/spec/session/refresh_spec.rb +9 -7
  198. data/lib/capybara/spec/session/reset_session_spec.rb +63 -35
  199. data/lib/capybara/spec/session/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 +2 -2
  202. data/lib/capybara/spec/session/save_page_spec.rb +37 -37
  203. data/lib/capybara/spec/session/save_screenshot_spec.rb +10 -10
  204. data/lib/capybara/spec/session/screenshot_spec.rb +2 -2
  205. data/lib/capybara/spec/session/scroll_spec.rb +119 -0
  206. data/lib/capybara/spec/session/select_spec.rb +85 -85
  207. data/lib/capybara/spec/session/selectors_spec.rb +49 -18
  208. data/lib/capybara/spec/session/sibling_spec.rb +9 -9
  209. data/lib/capybara/spec/session/text_spec.rb +25 -24
  210. data/lib/capybara/spec/session/title_spec.rb +7 -6
  211. data/lib/capybara/spec/session/uncheck_spec.rb +33 -21
  212. data/lib/capybara/spec/session/unselect_spec.rb +37 -37
  213. data/lib/capybara/spec/session/visit_spec.rb +68 -49
  214. data/lib/capybara/spec/session/window/become_closed_spec.rb +20 -17
  215. data/lib/capybara/spec/session/window/current_window_spec.rb +1 -1
  216. data/lib/capybara/spec/session/window/switch_to_window_spec.rb +20 -16
  217. data/lib/capybara/spec/session/window/window_opened_by_spec.rb +6 -2
  218. data/lib/capybara/spec/session/window/window_spec.rb +62 -63
  219. data/lib/capybara/spec/session/window/windows_spec.rb +5 -1
  220. data/lib/capybara/spec/session/window/within_window_spec.rb +14 -14
  221. data/lib/capybara/spec/session/within_spec.rb +79 -42
  222. data/lib/capybara/spec/spec_helper.rb +41 -53
  223. data/lib/capybara/spec/test_app.rb +132 -43
  224. data/lib/capybara/spec/views/animated.erb +49 -0
  225. data/lib/capybara/spec/views/form.erb +139 -42
  226. data/lib/capybara/spec/views/frame_child.erb +4 -3
  227. data/lib/capybara/spec/views/frame_one.erb +2 -1
  228. data/lib/capybara/spec/views/frame_parent.erb +1 -1
  229. data/lib/capybara/spec/views/frame_two.erb +1 -1
  230. data/lib/capybara/spec/views/initial_alert.erb +2 -1
  231. data/lib/capybara/spec/views/layout.erb +10 -0
  232. data/lib/capybara/spec/views/obscured.erb +47 -0
  233. data/lib/capybara/spec/views/offset.erb +33 -0
  234. data/lib/capybara/spec/views/path.erb +2 -2
  235. data/lib/capybara/spec/views/popup_one.erb +1 -1
  236. data/lib/capybara/spec/views/popup_two.erb +1 -1
  237. data/lib/capybara/spec/views/react.erb +45 -0
  238. data/lib/capybara/spec/views/scroll.erb +21 -0
  239. data/lib/capybara/spec/views/spatial.erb +31 -0
  240. data/lib/capybara/spec/views/tables.erb +67 -0
  241. data/lib/capybara/spec/views/with_animation.erb +39 -4
  242. data/lib/capybara/spec/views/with_base_tag.erb +2 -2
  243. data/lib/capybara/spec/views/with_dragula.erb +24 -0
  244. data/lib/capybara/spec/views/with_fixed_header_footer.erb +2 -1
  245. data/lib/capybara/spec/views/with_hover.erb +3 -2
  246. data/lib/capybara/spec/views/with_hover1.erb +10 -0
  247. data/lib/capybara/spec/views/with_html.erb +37 -9
  248. data/lib/capybara/spec/views/with_html5_svg.erb +20 -0
  249. data/lib/capybara/spec/views/with_jquery_animation.erb +24 -0
  250. data/lib/capybara/spec/views/with_js.erb +26 -5
  251. data/lib/capybara/spec/views/with_jstree.erb +26 -0
  252. data/lib/capybara/spec/views/with_namespace.erb +1 -0
  253. data/lib/capybara/spec/views/with_scope.erb +2 -2
  254. data/lib/capybara/spec/views/with_scope_other.erb +6 -0
  255. data/lib/capybara/spec/views/with_shadow.erb +31 -0
  256. data/lib/capybara/spec/views/with_slow_unload.erb +2 -1
  257. data/lib/capybara/spec/views/with_sortable_js.erb +21 -0
  258. data/lib/capybara/spec/views/with_unload_alert.erb +1 -0
  259. data/lib/capybara/spec/views/with_windows.erb +1 -1
  260. data/lib/capybara/spec/views/within_frames.erb +1 -1
  261. data/lib/capybara/version.rb +1 -1
  262. data/lib/capybara/window.rb +19 -25
  263. data/lib/capybara.rb +126 -111
  264. data/spec/basic_node_spec.rb +59 -34
  265. data/spec/capybara_spec.rb +56 -44
  266. data/spec/counter_spec.rb +35 -0
  267. data/spec/css_builder_spec.rb +101 -0
  268. data/spec/css_splitter_spec.rb +8 -8
  269. data/spec/dsl_spec.rb +79 -52
  270. data/spec/filter_set_spec.rb +9 -9
  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 +45 -7
  274. data/spec/minitest_spec_spec.rb +87 -64
  275. data/spec/per_session_config_spec.rb +6 -6
  276. data/spec/rack_test_spec.rb +172 -116
  277. data/spec/regexp_dissassembler_spec.rb +250 -0
  278. data/spec/result_spec.rb +80 -72
  279. data/spec/rspec/features_spec.rb +21 -16
  280. data/spec/rspec/scenarios_spec.rb +10 -6
  281. data/spec/rspec/shared_spec_matchers.rb +407 -365
  282. data/spec/rspec/views_spec.rb +3 -3
  283. data/spec/rspec_matchers_spec.rb +35 -10
  284. data/spec/rspec_spec.rb +63 -41
  285. data/spec/sauce_spec_chrome.rb +43 -0
  286. data/spec/selector_spec.rb +334 -89
  287. data/spec/selenium_spec_chrome.rb +176 -62
  288. data/spec/selenium_spec_chrome_remote.rb +54 -14
  289. data/spec/selenium_spec_edge.rb +41 -8
  290. data/spec/selenium_spec_firefox.rb +228 -0
  291. data/spec/selenium_spec_firefox_remote.rb +94 -0
  292. data/spec/selenium_spec_ie.rb +129 -11
  293. data/spec/selenium_spec_safari.rb +162 -0
  294. data/spec/server_spec.rb +171 -97
  295. data/spec/session_spec.rb +34 -18
  296. data/spec/shared_selenium_node.rb +79 -0
  297. data/spec/shared_selenium_session.rb +344 -80
  298. data/spec/spec_helper.rb +124 -2
  299. data/spec/whitespace_normalizer_spec.rb +54 -0
  300. data/spec/xpath_builder_spec.rb +93 -0
  301. metadata +326 -28
  302. data/lib/capybara/rspec/compound.rb +0 -94
  303. data/lib/capybara/selenium/driver_specializations/marionette_driver.rb +0 -31
  304. data/lib/capybara/selenium/nodes/marionette_node.rb +0 -31
  305. data/lib/capybara/spec/session/has_style_spec.rb +0 -25
  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 -167
@@ -1,75 +1,78 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'spec_helper'
4
- require "selenium-webdriver"
4
+ require 'selenium-webdriver'
5
5
 
6
- RSpec.shared_examples "Capybara::Session" do |session, mode|
6
+ RSpec.shared_examples 'Capybara::Session' do |session, mode|
7
7
  let(:session) { session }
8
8
 
9
9
  context 'with selenium driver' do
10
10
  describe '#driver' do
11
- it "should be a selenium driver" do
11
+ it 'should be a selenium driver' do
12
12
  expect(session.driver).to be_an_instance_of(Capybara::Selenium::Driver)
13
13
  end
14
14
  end
15
15
 
16
16
  describe '#mode' do
17
- it "should remember the mode" do
17
+ it 'should remember the mode' do
18
18
  expect(session.mode).to eq(mode)
19
19
  end
20
20
  end
21
21
 
22
- describe "#reset!" do
23
- it "freshly reset session should not be touched" do
22
+ describe '#reset!' do
23
+ it 'freshly reset session should not be touched' do
24
24
  session.instance_variable_set(:@touched, true)
25
25
  session.reset!
26
- expect(session.instance_variable_get(:@touched)).to eq false
26
+ expect(session.instance_variable_get(:@touched)).to be false
27
27
  end
28
28
  end
29
29
 
30
- describe "exit codes" do
30
+ describe 'exit codes' do
31
+ let(:env) { { 'SELENIUM_BROWSER' => session.driver.options[:browser].to_s } }
32
+ let!(:orig_dir) { Dir.getwd }
33
+
31
34
  before do
32
- @current_dir = Dir.getwd
33
35
  Dir.chdir(File.join(File.dirname(__FILE__), '..'))
34
- @env = { 'SELENIUM_BROWSER' => session.driver.options[:browser].to_s }
35
36
  end
36
37
 
37
38
  after do
38
- Dir.chdir(@current_dir)
39
+ Dir.chdir(orig_dir)
39
40
  end
40
41
 
41
- it "should have return code 1 when running selenium_driver_rspec_failure.rb" do
42
- skip if headless_or_remote?
42
+ it 'should have return code 1 when running selenium_driver_rspec_failure.rb' do
43
+ skip 'only setup for local non-headless' if headless_or_remote?
44
+ skip 'Not setup for edge' if edge?(session)
43
45
 
44
- system(@env, 'rspec spec/fixtures/selenium_driver_rspec_failure.rb', out: File::NULL, err: File::NULL)
46
+ system(env, 'rspec spec/fixtures/selenium_driver_rspec_failure.rb', out: File::NULL, err: File::NULL)
45
47
  expect($CHILD_STATUS.exitstatus).to eq(1)
46
48
  end
47
49
 
48
- it "should have return code 0 when running selenium_driver_rspec_success.rb" do
49
- skip if headless_or_remote?
50
+ it 'should have return code 0 when running selenium_driver_rspec_success.rb' do
51
+ skip 'only setup for local non-headless' if headless_or_remote?
52
+ skip 'Not setup for edge' if edge?(session)
50
53
 
51
- system(@env, 'rspec spec/fixtures/selenium_driver_rspec_success.rb', out: File::NULL, err: File::NULL)
54
+ system(env, 'rspec spec/fixtures/selenium_driver_rspec_success.rb', out: File::NULL, err: File::NULL)
52
55
  expect($CHILD_STATUS.exitstatus).to eq(0)
53
56
  end
54
57
  end
55
58
 
56
- describe "#accept_alert", requires: [:modals] do
57
- it "supports a blockless mode" do
59
+ describe '#accept_alert', requires: [:modals] do
60
+ it 'supports a blockless mode' do
58
61
  session.visit('/with_js')
59
62
  session.click_link('Open alert')
60
63
  session.accept_alert
61
64
  expect { session.driver.browser.switch_to.alert }.to raise_error(session.driver.send(:modal_error))
62
65
  end
63
66
 
64
- it "can be called before visiting" do
65
- session.accept_alert "Initial alert" do
67
+ it 'can be called before visiting' do
68
+ session.accept_alert 'Initial alert' do
66
69
  session.visit('/initial_alert')
67
70
  end
68
71
  expect(session).to have_text('Initial alert page')
69
72
  end
70
73
  end
71
74
 
72
- context '#fill_in_with empty string and no options' do
75
+ describe '#fill_in_with empty string and no options' do
73
76
  it 'should trigger change when clearing a field' do
74
77
  session.visit('/with_js')
75
78
  session.fill_in('with_change_event', with: '')
@@ -79,7 +82,12 @@ RSpec.shared_examples "Capybara::Session" do |session, mode|
79
82
  end
80
83
  end
81
84
 
82
- context "#fill_in with { :clear => :backspace } fill_option", requires: [:js] do
85
+ describe '#fill_in with { :clear => :backspace } fill_option', requires: [:js] do
86
+ before do
87
+ # Firefox has an issue with change events if the main window doesn't think it's focused
88
+ session.execute_script('window.focus()')
89
+ end
90
+
83
91
  it 'should fill in a field, replacing an existing value' do
84
92
  session.visit('/form')
85
93
  session.fill_in('form_first_name',
@@ -88,6 +96,19 @@ RSpec.shared_examples "Capybara::Session" do |session, mode|
88
96
  expect(session.find(:fillable_field, 'form_first_name').value).to eq('Harry')
89
97
  end
90
98
 
99
+ it 'should fill in a field, replacing an existing value, even with caret position' do
100
+ session.visit('/form')
101
+ session.find(:css, '#form_first_name').execute_script <<-JS
102
+ this.focus();
103
+ this.setSelectionRange(0, 0);
104
+ JS
105
+
106
+ session.fill_in('form_first_name',
107
+ with: 'Harry',
108
+ fill_options: { clear: :backspace })
109
+ expect(session.find(:fillable_field, 'form_first_name').value).to eq('Harry')
110
+ end
111
+
91
112
  it 'should fill in if the option is set via global option' do
92
113
  Capybara.default_set_options = { clear: :backspace }
93
114
  session.visit('/form')
@@ -97,12 +118,13 @@ RSpec.shared_examples "Capybara::Session" do |session, mode|
97
118
 
98
119
  it 'should only trigger onchange once' do
99
120
  session.visit('/with_js')
121
+ sleep 2 if safari?(session) # Safari needs a delay (to load event handlers maybe ???)
100
122
  session.fill_in('with_change_event',
101
123
  with: 'some value',
102
124
  fill_options: { clear: :backspace })
103
125
  # click outside the field to trigger the change event
104
- session.find(:css, 'body').click
105
- expect(session.find(:css, '.change_event_triggered', match: :one)).to have_text 'some value'
126
+ session.find(:css, '#with_focus_event').click
127
+ expect(session.find(:css, '.change_event_triggered', match: :one, wait: 5)).to have_text 'some value'
106
128
  end
107
129
 
108
130
  it 'should trigger change when clearing field' do
@@ -111,8 +133,8 @@ RSpec.shared_examples "Capybara::Session" do |session, mode|
111
133
  with: '',
112
134
  fill_options: { clear: :backspace })
113
135
  # click outside the field to trigger the change event
114
- session.find(:css, 'body').click
115
- expect(session).to have_selector(:css, '.change_event_triggered', match: :one)
136
+ session.find(:css, '#with_focus_event').click
137
+ expect(session).to have_selector(:css, '.change_event_triggered', match: :one, wait: 5)
116
138
  end
117
139
 
118
140
  it 'should trigger input event field_value.length times' do
@@ -121,41 +143,56 @@ RSpec.shared_examples "Capybara::Session" do |session, mode|
121
143
  with: '',
122
144
  fill_options: { clear: :backspace })
123
145
  # click outside the field to trigger the change event
124
- session.find(:css, 'body').click
146
+ # session.find(:css, 'body').click
147
+ session.find(:css, 'h1', text: 'FooBar').click
125
148
  expect(session).to have_xpath('//p[@class="input_event_triggered"]', count: 13)
126
149
  end
127
150
  end
128
151
 
129
- context "#fill_in with { clear: :none } fill_options" do
152
+ describe '#fill_in with { clear: :none } fill_options' do
130
153
  it 'should append to content in a field' do
154
+ pending 'Safari overwrites by default - need to figure out a workaround' if safari?(session)
155
+
131
156
  session.visit('/form')
132
157
  session.fill_in('form_first_name',
133
158
  with: 'Harry',
134
159
  fill_options: { clear: :none })
135
160
  expect(session.find(:fillable_field, 'form_first_name').value).to eq('JohnHarry')
136
161
  end
162
+
163
+ it 'works with rapid fill' do
164
+ pending 'Safari overwrites by default - need to figure out a workaround' if safari?(session)
165
+
166
+ long_string = (0...60).map { |i| ((i % 26) + 65).chr }.join
167
+ session.visit('/form')
168
+ session.fill_in('form_first_name', with: long_string, fill_options: { clear: :none })
169
+ expect(session.find(:fillable_field, 'form_first_name').value).to eq("John#{long_string}")
170
+ end
137
171
  end
138
172
 
139
- context '#fill_in with Date' do
173
+ describe '#fill_in with Date' do
140
174
  before do
141
175
  session.visit('/form')
142
- session.execute_script <<-JS
176
+ session.find(:css, '#form_date').execute_script <<-JS
143
177
  window.capybara_formDateFiredEvents = [];
178
+ var fd = this;
144
179
  ['focus', 'input', 'change'].forEach(function(eventType) {
145
- document.getElementById('form_date')
146
- .addEventListener(eventType, function() { window.capybara_formDateFiredEvents.push(eventType); });
180
+ fd.addEventListener(eventType, function() { window.capybara_formDateFiredEvents.push(eventType); });
147
181
  });
148
182
  JS
149
183
  # work around weird FF issue where it would create an extra focus issue in some cases
150
- session.find(:css, 'body').click
184
+ session.find(:css, 'h1', text: 'Form').click
185
+ # session.find(:css, 'body').click
151
186
  end
152
187
 
153
- it "should generate standard events on changing value" do
188
+ it 'should generate standard events on changing value' do
189
+ pending "IE 11 doesn't support date input type" if ie?(session)
154
190
  session.fill_in('form_date', with: Date.today)
155
191
  expect(session.evaluate_script('window.capybara_formDateFiredEvents')).to eq %w[focus input change]
156
192
  end
157
193
 
158
- it "should not generate input and change events if the value is not changed" do
194
+ it 'should not generate input and change events if the value is not changed' do
195
+ pending "IE 11 doesn't support date input type" if ie?(session)
159
196
  session.fill_in('form_date', with: Date.today)
160
197
  session.fill_in('form_date', with: Date.today)
161
198
  # Chrome adds an extra focus for some reason - ok for now
@@ -163,9 +200,8 @@ RSpec.shared_examples "Capybara::Session" do |session, mode|
163
200
  end
164
201
  end
165
202
 
166
- context "#fill_in with { clear: Array } fill_options" do
203
+ describe '#fill_in with { clear: Array } fill_options' do
167
204
  it 'should pass the array through to the element' do
168
- pending "selenium-webdriver/geckodriver doesn't support complex sets of characters" if marionette?(session)
169
205
  # this is mainly for use with [[:control, 'a'], :backspace] - however since that is platform dependant I'm testing with something less useful
170
206
  session.visit('/form')
171
207
  session.fill_in('form_first_name',
@@ -175,53 +211,90 @@ RSpec.shared_examples "Capybara::Session" do |session, mode|
175
211
  end
176
212
  end
177
213
 
178
- describe "#path" do
179
- it "returns xpath" do
214
+ describe '#fill_in with Emoji' do
215
+ it 'sends emojis' do
216
+ session.visit('/form')
217
+ session.fill_in('form_first_name', with: 'a😀cd😴 🛌🏽🇵🇹 e🤾🏽‍♀️f')
218
+ expect(session.find(:fillable_field, 'form_first_name').value).to eq('a😀cd😴 🛌🏽🇵🇹 e🤾🏽‍♀️f')
219
+ end
220
+ end
221
+
222
+ describe '#send_keys' do
223
+ it 'defaults to sending keys to the active_element' do
224
+ session.visit('/form')
225
+
226
+ expect(session.active_element).to match_selector(:css, 'body')
227
+
228
+ session.send_keys(:tab)
229
+
230
+ expect(session.active_element).to match_selector(:css, '[tabindex="1"]')
231
+ end
232
+ end
233
+
234
+ describe '#path' do
235
+ it 'returns xpath' do
180
236
  # this is here because it is testing for an XPath that is specific to the algorithm used in the selenium driver
181
237
  session.visit('/path')
182
238
  element = session.find(:link, 'Second Link')
183
- expect(element.path).to eq('/HTML/BODY/DIV[2]/A[1]')
239
+ expect(element.path).to eq('/HTML/BODY[1]/DIV[2]/A[1]')
240
+ end
241
+
242
+ it 'handles namespaces in xhtml' do
243
+ pending "IE 11 doesn't handle all XPath querys (namespace-uri, etc)" if ie?(session)
244
+ session.visit '/with_namespace'
245
+ rect = session.find(:css, 'div svg rect:first-of-type')
246
+ expect(rect.path).to eq("/HTML/BODY[1]/DIV[1]/*[local-name()='svg' and namespace-uri()='http://www.w3.org/2000/svg'][1]/*[local-name()='rect' and namespace-uri()='http://www.w3.org/2000/svg'][1]")
247
+ expect(session.find(:xpath, rect.path)).to eq rect
184
248
  end
185
249
 
186
- it "handles namespaces" do
187
- session.visit "/with_namespace"
188
- rect = session.find(:css, "div svg rect")
189
- expect(rect.path).to eq("/HTML/BODY/DIV/./*[((local-name(.) = 'svg') and (namespace-uri(.) = 'http://www.w3.org/2000/svg'))]/./*[((local-name(.) = 'rect') and (namespace-uri(.) = 'http://www.w3.org/2000/svg'))][1]")
250
+ it 'handles default namespaces in html5' do
251
+ pending "IE 11 doesn't handle all XPath querys (namespace-uri, etc)" if ie?(session)
252
+ session.visit '/with_html5_svg'
253
+ rect = session.find(:css, 'div svg rect:first-of-type')
254
+ expect(rect.path).to eq("/HTML/BODY[1]/DIV[1]/*[local-name()='svg' and namespace-uri()='http://www.w3.org/2000/svg'][1]/*[local-name()='rect' and namespace-uri()='http://www.w3.org/2000/svg'][1]")
190
255
  expect(session.find(:xpath, rect.path)).to eq rect
191
256
  end
192
257
 
193
- it "handles case sensitive element names" do
194
- session.visit "/with_namespace"
195
- els = session.all(:css, "div *", visible: :all)
258
+ it 'handles case sensitive element names' do
259
+ pending "IE 11 doesn't handle all XPath querys (namespace-uri, etc)" if ie?(session)
260
+ session.visit '/with_namespace'
261
+ els = session.all(:css, 'div *', visible: :all)
196
262
  expect { els.map(&:path) }.not_to raise_error
197
- lg = session.find(:css, "div linearGradient", visible: :all)
263
+ lg = session.find(:css, 'div linearGradient', visible: :all)
198
264
  expect(session.find(:xpath, lg.path, visible: :all)).to eq lg
199
265
  end
200
266
  end
201
267
 
202
- describe "all with disappearing elements" do
203
- it "ignores stale elements in results" do
268
+ describe 'all with disappearing elements' do
269
+ it 'ignores stale elements in results' do
204
270
  session.visit('/path')
205
271
  elements = session.all(:link) { |_node| raise Selenium::WebDriver::Error::StaleElementReferenceError }
206
272
  expect(elements.size).to eq 0
207
273
  end
208
274
  end
209
275
 
210
- describe "#evaluate_script" do
211
- it "can return an element" do
276
+ describe '#evaluate_script' do
277
+ it 'can return an element' do
212
278
  session.visit('/form')
213
279
  element = session.evaluate_script("document.getElementById('form_title')")
214
280
  expect(element).to eq session.find(:id, 'form_title')
215
281
  end
216
282
 
217
- it "can return arrays of nested elements" do
283
+ it 'returns a shadow root' do
284
+ session.visit('/with_shadow')
285
+ shadow = session.find(:css, '#shadow_host')
286
+ element = session.evaluate_script('arguments[0].shadowRoot', shadow)
287
+ expect(element).to be_instance_of(Capybara::Node::Element)
288
+ end
289
+
290
+ it 'can return arrays of nested elements' do
218
291
  session.visit('/form')
219
292
  elements = session.evaluate_script('document.querySelectorAll("#form_city option")')
220
293
  expect(elements).to all(be_instance_of Capybara::Node::Element)
221
294
  expect(elements).to eq session.find(:css, '#form_city').all(:css, 'option').to_a
222
295
  end
223
296
 
224
- it "can return hashes with elements" do
297
+ it 'can return hashes with elements' do
225
298
  session.visit('/form')
226
299
  result = session.evaluate_script("{ a: document.getElementById('form_title'), b: {c: document.querySelectorAll('#form_city option')}}")
227
300
  expect(result).to eq(
@@ -232,39 +305,66 @@ RSpec.shared_examples "Capybara::Session" do |session, mode|
232
305
  )
233
306
  end
234
307
 
235
- describe "#evaluate_async_script" do
236
- it "will timeout if the script takes too long" do
308
+ describe '#evaluate_async_script' do
309
+ it 'will timeout if the script takes too long' do
310
+ skip 'safaridriver returns the wrong error type' if safari?(session)
237
311
  session.visit('/with_js')
238
312
  expect do
239
313
  session.using_wait_time(1) do
240
- session.evaluate_async_script("var cb = arguments[0]; setTimeout(function(){ cb(null) }, 3000)")
314
+ session.evaluate_async_script('var cb = arguments[0]; setTimeout(function(){ cb(null) }, 3000)')
241
315
  end
242
316
  end.to raise_error Selenium::WebDriver::Error::ScriptTimeoutError
243
317
  end
244
318
  end
245
319
  end
246
320
 
247
- describe "Element#inspect" do
248
- it "outputs obsolete elements" do
321
+ describe 'Element#inspect' do
322
+ it 'outputs obsolete elements' do
249
323
  session.visit('/form')
250
324
  el = session.find(:button, 'Click me!').click
251
325
  expect(session).to have_no_button('Click me!')
252
326
  allow(el).to receive(:synchronize)
253
- expect(el.inspect).to eq "Obsolete #<Capybara::Node::Element>"
327
+ expect(el.inspect).to eq 'Obsolete #<Capybara::Node::Element>'
254
328
  expect(el).not_to have_received(:synchronize)
255
329
  end
256
330
  end
257
331
 
258
- describe "Element#click" do
259
- it "should handle fixed headers/footers" do
332
+ describe 'Element#click' do
333
+ it 'should handle fixed headers/footers' do
260
334
  session.visit('/with_fixed_header_footer')
261
- # session.click_link('Go to root')
262
- session.find(:link, 'Go to root').click
335
+ session.using_wait_time(2) do
336
+ session.find(:link, 'Go to root').click
337
+ end
263
338
  expect(session).to have_current_path('/')
264
339
  end
265
340
  end
266
341
 
267
- context "Windows" do
342
+ describe 'Capybara#Node#attach_file' do
343
+ it 'can attach a directory' do
344
+ pending "Geckodriver doesn't support uploading a directory" if firefox?(session)
345
+ pending "Selenium remote doesn't support transferring a directory" if remote?(session)
346
+ pending "Headless Chrome doesn't support directory upload - https://bugs.chromium.org/p/chromedriver/issues/detail?id=2521&q=directory%20upload&colspec=ID%20Status%20Pri%20Owner%20Summary" if chrome?(session) && chrome_lt?(110, session) && ENV.fetch('HEADLESS', nil)
347
+ pending "IE doesn't support uploading a directory" if ie?(session)
348
+ pending 'Chrome/chromedriver 73 breaks this' if chrome?(session) && chrome_gte?(73, session) && chrome_lt?(75, session)
349
+
350
+ session.visit('/form')
351
+ test_file_dir = File.expand_path('./fixtures', File.dirname(__FILE__))
352
+ session.attach_file('Directory Upload', test_file_dir)
353
+ session.click_button('Upload Multiple')
354
+ expect(session).to have_text('5 | ') # number of files
355
+ end
356
+
357
+ it 'can attach a relative file' do
358
+ pending 'Geckdoriver on windows requires alternate file separator which path expansion replaces' if Gem.win_platform? && firefox?(session)
359
+
360
+ session.visit('/form')
361
+ session.attach_file('Single Document', 'spec/fixtures/capybara.csv')
362
+ session.click_button('Upload Single')
363
+ expect(session).to have_text('Content-type: text/csv')
364
+ end
365
+ end
366
+
367
+ context 'Windows' do
268
368
  it "can't close the primary window" do
269
369
  expect do
270
370
  session.current_window.close
@@ -272,26 +372,190 @@ RSpec.shared_examples "Capybara::Session" do |session, mode|
272
372
  end
273
373
  end
274
374
 
275
- context "AnimationDisabler" do
276
- before(:context) do # rubocop:disable RSpec/BeforeAfterAll
277
- Capybara.disable_animation = true
278
- @animation_session = Capybara::Session.new(session.mode, TestApp.new)
375
+ # rubocop:disable RSpec/InstanceVariable
376
+ describe 'Capybara#disable_animation' do
377
+ context 'when set to `true`' do
378
+ before(:context) do # rubocop:disable RSpec/BeforeAfterAll
379
+ skip "Safari doesn't support multiple sessions" if safari?(session)
380
+ # NOTE: Although Capybara.SpecHelper.reset! sets Capybara.disable_animation to false,
381
+ # it doesn't affect any of these tests because the settings are applied per-session
382
+ Capybara.disable_animation = true
383
+ @animation_session = Capybara::Session.new(session.mode, TestApp.new)
384
+ end
385
+
386
+ it 'should add CSS to the <head> element' do
387
+ @animation_session.visit('with_animation')
388
+
389
+ expect(@animation_session).to have_selector(:css, 'head > style', text: 'transition: none', visible: :hidden)
390
+ end
391
+
392
+ it 'should disable CSS transitions' do
393
+ @animation_session.visit('with_animation')
394
+ @animation_session.click_link('transition me away')
395
+ expect(@animation_session).to have_no_link('transition me away', wait: 0.5)
396
+ end
397
+
398
+ it 'should disable CSS animations (set to 0s)' do
399
+ @animation_session.visit('with_animation')
400
+ sleep 1
401
+ @animation_session.click_link('animate me away')
402
+ expect(@animation_session).to have_no_link('animate me away', wait: 0.5)
403
+ end
404
+
405
+ it 'should disable CSS animations on pseudo elements (set to 0s)' do
406
+ @animation_session.visit('with_animation')
407
+ sleep 1
408
+ @animation_session.find_link('animate me away').right_click
409
+ expect(@animation_session).to have_content('Animation Ended', wait: 0.1)
410
+ end
411
+
412
+ it 'should scroll the page instantly', requires: [:js] do
413
+ @animation_session.visit('with_animation')
414
+ scroll_y = @animation_session.evaluate_script(<<~JS)
415
+ (function(){
416
+ window.scrollTo(0,500);
417
+ return window.scrollY;
418
+ })()
419
+ JS
420
+ expect(scroll_y).to eq 500
421
+ end
422
+
423
+ it 'should scroll the page instantly without jquery animation', requires: [:js] do
424
+ @animation_session.visit('with_jquery_animation')
425
+ @animation_session.click_link('scroll top 500')
426
+ scroll_y = @animation_session.evaluate_script('window.scrollY')
427
+ expect(scroll_y).to eq 500
428
+ end
279
429
  end
280
430
 
281
- after(:context) do # rubocop:disable RSpec/BeforeAfterAll
282
- Capybara.disable_animation = false
431
+ context 'when set to `false`' do
432
+ before(:context) do # rubocop:disable RSpec/BeforeAfterAll
433
+ skip "Safari doesn't support multiple sessions" if safari?(session)
434
+ # NOTE: Although Capybara.SpecHelper.reset! sets Capybara.disable_animation to false,
435
+ # it doesn't affect any of these tests because the settings are applied per-session
436
+ Capybara.disable_animation = false
437
+ @animation_session = Capybara::Session.new(session.mode, TestApp.new)
438
+ end
439
+
440
+ it 'should scroll the page with a smooth animation', requires: [:js] do
441
+ @animation_session.visit('with_animation')
442
+ scroll_y = @animation_session.evaluate_script(<<~JS)
443
+ (function(){
444
+ window.scrollTo(0,500);
445
+ return window.scrollY;
446
+ })()
447
+ JS
448
+ # measured over 0.5 seconds: 0, 75, 282, 478, 500
449
+ expect(scroll_y).to be < 500
450
+ end
451
+
452
+ it 'should scroll the page with jquery animation', requires: [:js] do
453
+ @animation_session.visit('with_jquery_animation')
454
+ @animation_session.click_link('scroll top 500')
455
+ scroll_y = @animation_session.evaluate_script('window.scrollY')
456
+ expect(scroll_y).to be < 500
457
+ end
283
458
  end
284
459
 
285
- it "should disable CSS transitions" do
286
- @animation_session.visit('with_animation')
287
- @animation_session.click_link('transition me away')
288
- expect(@animation_session).to have_no_link('transition me away', wait: 0.5)
460
+ context 'if we pass in css that matches elements' do
461
+ before(:context) do # rubocop:disable RSpec/BeforeAfterAll
462
+ skip "safaridriver doesn't support multiple sessions" if safari?(session)
463
+ # NOTE: Although Capybara.SpecHelper.reset! sets Capybara.disable_animation to false,
464
+ # it doesn't affect any of these tests because the settings are applied per-session
465
+ Capybara.disable_animation = '#with_animation a'
466
+ @animation_session_with_matching_css = Capybara::Session.new(session.mode, TestApp.new)
467
+ end
468
+
469
+ it 'should disable CSS transitions' do
470
+ @animation_session_with_matching_css.visit('with_animation')
471
+ sleep 1
472
+ @animation_session_with_matching_css.click_link('transition me away')
473
+ expect(@animation_session_with_matching_css).to have_no_link('transition me away', wait: 0.5)
474
+ end
475
+
476
+ it 'should disable CSS animations' do
477
+ @animation_session_with_matching_css.visit('with_animation')
478
+ sleep 1
479
+ @animation_session_with_matching_css.click_link('animate me away')
480
+ expect(@animation_session_with_matching_css).to have_no_link('animate me away', wait: 0.5)
481
+ end
482
+ end
483
+
484
+ context 'if we pass in css that does not match elements' do
485
+ before(:context) do # rubocop:disable RSpec/BeforeAfterAll
486
+ skip "Safari doesn't support multiple sessions" if safari?(session)
487
+ # NOTE: Although Capybara.SpecHelper.reset! sets Capybara.disable_animation to false,
488
+ # it doesn't affect any of these tests because the settings are applied per-session
489
+ Capybara.disable_animation = '.this-class-matches-nothing'
490
+ @animation_session_without_matching_css = Capybara::Session.new(session.mode, TestApp.new)
491
+ end
492
+
493
+ it 'should not disable CSS transitions' do
494
+ @animation_session_without_matching_css.visit('with_animation')
495
+ sleep 1
496
+ @animation_session_without_matching_css.click_link('transition me away')
497
+ sleep 0.5 # Wait long enough for click to have been processed
498
+ expect(@animation_session_without_matching_css).to have_link('transition me away', wait: false)
499
+ expect(@animation_session_without_matching_css).to have_no_link('transition me away', wait: 5)
500
+ end
501
+
502
+ it 'should not disable CSS animations' do
503
+ @animation_session_without_matching_css.visit('with_animation')
504
+ sleep 1
505
+ @animation_session_without_matching_css.click_link('animate me away')
506
+ sleep 0.5 # Wait long enough for click to have been processed
507
+ expect(@animation_session_without_matching_css).to have_link('animate me away', wait: false)
508
+ expect(@animation_session_without_matching_css).to have_no_link('animate me away', wait: 5)
509
+ end
510
+ end
511
+ end
512
+ # rubocop:enable RSpec/InstanceVariable
513
+
514
+ describe ':element selector' do
515
+ it 'can find html5 svg elements' do
516
+ session.visit('with_html5_svg')
517
+ expect(session).to have_selector(:element, :svg)
518
+ expect(session).to have_selector(:element, :rect, visible: :visible)
519
+ expect(session).to have_selector(:element, :circle)
520
+ expect(session).to have_selector(:element, :linearGradient, visible: :all)
289
521
  end
290
522
 
291
- it "should disable CSS animations" do
292
- @animation_session.visit('with_animation')
293
- @animation_session.click_link('animate me away')
294
- expect(@animation_session).to have_no_link('animate me away', wait: 0.5)
523
+ it 'can query attributes with strange characters' do
524
+ session.visit('/form')
525
+ expect(session).to have_selector(:element, '{custom}': true)
526
+ expect(session).to have_selector(:element, '{custom}': 'abcdef')
527
+ end
528
+ end
529
+
530
+ describe 'with react' do
531
+ context 'controlled components' do
532
+ it 'can set and clear a text field' do
533
+ skip "This test doesn't support older browsers" if ie?(session)
534
+
535
+ session.visit 'react'
536
+
537
+ session.fill_in('Name:', with: 'abc')
538
+ session.accept_prompt 'A name was submitted: abc' do
539
+ session.click_button('Submit')
540
+ end
541
+
542
+ session.fill_in('Name:', with: '')
543
+ session.accept_prompt(/A name was submitted: $/) do
544
+ session.click_button('Submit')
545
+ end
546
+ end
547
+
548
+ it 'works with rapid fill' do
549
+ skip "This test doesn't support older browsers" if ie?(session)
550
+
551
+ session.visit 'react'
552
+ long_string = (0...60).map { |i| ((i % 26) + 65).chr }.join
553
+
554
+ session.fill_in('Name:', with: long_string)
555
+ session.accept_prompt "A name was submitted: #{long_string}" do
556
+ session.click_button('Submit')
557
+ end
558
+ end
295
559
  end
296
560
  end
297
561
  end