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
data/spec/server_spec.rb CHANGED
@@ -3,216 +3,290 @@
3
3
  require 'spec_helper'
4
4
 
5
5
  RSpec.describe Capybara::Server do
6
- it "should spool up a rack server" do
7
- @app = proc { |_env| [200, {}, ["Hello Server!"]] }
8
- @server = Capybara::Server.new(@app).boot
6
+ it 'should spool up a rack server' do
7
+ app = proc { |_env| [200, {}, ['Hello Server!']] }
8
+ server = described_class.new(app).boot
9
9
 
10
- @res = Net::HTTP.start(@server.host, @server.port) { |http| http.get('/') }
10
+ res = Net::HTTP.start(server.host, server.port) { |http| http.get('/') }
11
11
 
12
- expect(@res.body).to include('Hello Server')
12
+ expect(res.body).to include('Hello Server')
13
13
  end
14
14
 
15
- it "should do nothing when no server given" do
15
+ it 'should do nothing when no server given' do
16
16
  expect do
17
- @server = Capybara::Server.new(nil).boot
17
+ described_class.new(nil).boot
18
18
  end.not_to raise_error
19
19
  end
20
20
 
21
- it "should bind to the specified host" do
21
+ it 'should bind to the specified host' do
22
22
  # TODO: travis with jruby in container mode has an issue with this test
23
+ skip 'This platform has an issue with this test' if (ENV.fetch('TRAVIS', nil) && (RUBY_ENGINE == 'jruby')) || Gem.win_platform?
24
+
23
25
  begin
24
26
  app = proc { |_env| [200, {}, ['Hello Server!']] }
25
27
 
26
28
  Capybara.server_host = '127.0.0.1'
27
- server = Capybara::Server.new(app).boot
29
+ server = described_class.new(app).boot
28
30
  res = Net::HTTP.get(URI("http://127.0.0.1:#{server.port}"))
29
31
  expect(res).to eq('Hello Server!')
30
32
 
31
33
  Capybara.server_host = '0.0.0.0'
32
- server = Capybara::Server.new(app).boot
34
+ server = described_class.new(app).boot
33
35
  res = Net::HTTP.get(URI("http://127.0.0.1:#{server.port}"))
34
36
  expect(res).to eq('Hello Server!')
35
37
  ensure
36
38
  Capybara.server_host = nil
37
39
  end
38
- end unless (ENV['TRAVIS'] && (RUBY_ENGINE == 'jruby')) || Gem.win_platform?
40
+ end
39
41
 
40
- it "should use specified port" do
42
+ it 'should use specified port' do
41
43
  Capybara.server_port = 22789
42
44
 
43
- @app = proc { |_env| [200, {}, ["Hello Server!"]] }
44
- @server = Capybara::Server.new(@app).boot
45
+ app = proc { |_env| [200, {}, ['Hello Server!']] }
46
+ server = described_class.new(app).boot
45
47
 
46
- @res = Net::HTTP.start(@server.host, 22789) { |http| http.get('/') }
47
- expect(@res.body).to include('Hello Server')
48
+ res = Net::HTTP.start(server.host, 22789) { |http| http.get('/') }
49
+ expect(res.body).to include('Hello Server')
48
50
 
49
51
  Capybara.server_port = nil
50
52
  end
51
53
 
52
- it "should use given port" do
53
- @app = proc { |_env| [200, {}, ["Hello Server!"]] }
54
- @server = Capybara::Server.new(@app, port: 22790).boot
54
+ it 'should use given port' do
55
+ app = proc { |_env| [200, {}, ['Hello Server!']] }
56
+ server = described_class.new(app, port: 22790).boot
55
57
 
56
- @res = Net::HTTP.start(@server.host, 22790) { |http| http.get('/') }
57
- expect(@res.body).to include('Hello Server')
58
+ res = Net::HTTP.start(server.host, 22790) { |http| http.get('/') }
59
+ expect(res.body).to include('Hello Server')
58
60
 
59
61
  Capybara.server_port = nil
60
62
  end
61
63
 
62
- it "should find an available port" do
63
- @app1 = proc { |_env| [200, {}, ["Hello Server!"]] }
64
- @app2 = proc { |_env| [200, {}, ["Hello Second Server!"]] }
64
+ it 'should find an available port' do
65
+ responses = ['Hello Server!', 'Hello Second Server!']
66
+ apps = responses.map do |response|
67
+ proc { |_env| [200, {}, [response]] }
68
+ end
69
+ servers = apps.map { |app| described_class.new(app).boot }
65
70
 
66
- @server1 = Capybara::Server.new(@app1).boot
67
- @server2 = Capybara::Server.new(@app2).boot
71
+ servers.each_with_index do |server, idx|
72
+ result = Net::HTTP.start(server.host, server.port) { |http| http.get('/') }
73
+ expect(result.body).to include(responses[idx])
74
+ end
75
+ end
68
76
 
69
- @res1 = Net::HTTP.start(@server1.host, @server1.port) { |http| http.get('/') }
70
- expect(@res1.body).to include('Hello Server')
77
+ it 'should handle that getting available ports fails randomly' do
78
+ # Use a port to force a EADDRINUSE error to be generated
79
+ server = TCPServer.new('0.0.0.0', 0)
80
+ server_port = server.addr[1]
81
+ d_server = instance_double(TCPServer, addr: [nil, server_port, nil, nil], close: nil)
82
+ call_count = 0
83
+ allow(TCPServer).to receive(:new).and_wrap_original do |m, *args|
84
+ call_count.zero? ? d_server : m.call(*args)
85
+ ensure
86
+ call_count += 1
87
+ end
71
88
 
72
- @res2 = Net::HTTP.start(@server2.host, @server2.port) { |http| http.get('/') }
73
- expect(@res2.body).to include('Hello Second Server')
89
+ port = described_class.new(Object.new, host: '0.0.0.0').port
90
+ expect(port).not_to eq(server_port)
91
+ ensure
92
+ server&.close
74
93
  end
75
94
 
76
- it "should support SSL" do
77
- begin
78
- key = File.join(Dir.pwd, "spec", "fixtures", "key.pem")
79
- cert = File.join(Dir.pwd, "spec", "fixtures", "certificate.pem")
80
- Capybara.server = :puma, { Host: "ssl://#{Capybara.server_host}?key=#{key}&cert=#{cert}" }
81
- app = proc { |_env| [200, {}, ['Hello SSL Server!']] }
82
- server = Capybara::Server.new(app).boot
95
+ it 'should return its #base_url' do
96
+ app = proc { |_env| [200, {}, ['Hello Server!']] }
97
+ server = described_class.new(app).boot
98
+ uri = Addressable::URI.parse(server.base_url)
99
+ expect(uri.to_hash).to include(scheme: 'http', host: server.host, port: server.port)
100
+ end
83
101
 
84
- expect do
85
- Net::HTTP.start(server.host, server.port) { |http| http.get('/__idntify__') }
86
- end.to raise_error(EOFError)
102
+ it 'should call #clamp on the puma configuration to ensure that environment is a string' do
103
+ Capybara.server = :puma
104
+ app_proc = proc { |_env| [200, {}, ['Hello Puma!']] }
105
+ require 'puma'
106
+ allow(Puma::Server).to receive(:new).and_wrap_original do |method, app, events, options|
107
+ # If #clamp is not called on the puma config then this will be a Proc
108
+ expect(options.fetch(:environment)).to be_a(String)
109
+ method.call(app, events, options)
110
+ end
111
+ server = described_class.new(app_proc).boot
112
+ expect(Puma::Server).to have_received(:new).with(
113
+ anything,
114
+ anything,
115
+ satisfy { |opts| opts.final_options[:Port] == server.port }
116
+ )
117
+ ensure
118
+ Capybara.server = :default
119
+ end
87
120
 
88
- res = Net::HTTP.start(server.host, server.port, use_ssl: true, verify_mode: OpenSSL::SSL::VERIFY_NONE) do |https|
89
- https.get('/')
90
- end
121
+ it 'should not emit any warnings when booting puma' do
122
+ Capybara.server = :puma
123
+ app_proc = proc { |_env| [200, {}, ['Hello Puma!']] }
124
+ require 'puma'
91
125
 
92
- expect(res.body).to include('Hello SSL Server!')
93
- ensure
94
- Capybara.server = :default
126
+ expect do
127
+ described_class.new(app_proc).boot
128
+ end.not_to output.to_stderr
129
+ ensure
130
+ Capybara.server = :default
131
+ end
132
+
133
+ it 'should support SSL' do
134
+ key = File.join(Dir.pwd, 'spec', 'fixtures', 'key.pem')
135
+ cert = File.join(Dir.pwd, 'spec', 'fixtures', 'certificate.pem')
136
+ Capybara.server = :puma, { Host: "ssl://#{Capybara.server_host}?key=#{key}&cert=#{cert}" }
137
+ app = proc { |_env| [200, {}, ['Hello SSL Server!']] }
138
+ server = described_class.new(app).boot
139
+
140
+ expect do
141
+ Net::HTTP.start(server.host, server.port, max_retries: 0) { |http| http.get('/__identify__') }
142
+ end.to(raise_error do |e|
143
+ expect(e.is_a?(EOFError) || e.is_a?(Net::ReadTimeout)).to be true
144
+ end)
145
+
146
+ res = Net::HTTP.start(server.host, server.port, use_ssl: true, verify_mode: OpenSSL::SSL::VERIFY_NONE) do |https|
147
+ https.get('/')
95
148
  end
149
+
150
+ expect(res.body).to include('Hello SSL Server!')
151
+ uri = Addressable::URI.parse(server.base_url)
152
+ expect(uri.to_hash).to include(scheme: 'https', host: server.host, port: server.port)
153
+ ensure
154
+ Capybara.server = :default
96
155
  end
97
156
 
98
- context "When Capybara.reuse_server is true" do
157
+ context 'When Capybara.reuse_server is true' do
158
+ let!(:old_reuse_server) { Capybara.reuse_server }
159
+
99
160
  before do
100
- @old_reuse_server = Capybara.reuse_server
101
161
  Capybara.reuse_server = true
102
162
  end
103
163
 
104
164
  after do
105
- Capybara.reuse_server = @old_reuse_server
165
+ Capybara.reuse_server = old_reuse_server
106
166
  end
107
167
 
108
- it "should use the existing server if it already running" do
109
- @app = proc { |_env| [200, {}, ["Hello Server!"]] }
110
-
111
- @server1 = Capybara::Server.new(@app).boot
112
- @server2 = Capybara::Server.new(@app).boot
168
+ it 'should use the existing server if it already running' do
169
+ app = proc { |_env| [200, {}, ['Hello Server!']] }
113
170
 
114
- res = Net::HTTP.start(@server1.host, @server1.port) { |http| http.get('/') }
115
- expect(res.body).to include('Hello Server')
171
+ servers = Array.new(2) { described_class.new(app).boot }
116
172
 
117
- res = Net::HTTP.start(@server2.host, @server2.port) { |http| http.get('/') }
118
- expect(res.body).to include('Hello Server')
173
+ servers.each do |server|
174
+ res = Net::HTTP.start(server.host, server.port) { |http| http.get('/') }
175
+ expect(res.body).to include('Hello Server')
176
+ end
119
177
 
120
- expect(@server1.port).to eq(@server2.port)
178
+ expect(servers[0].port).to eq(servers[1].port)
121
179
  end
122
180
 
123
- it "detects and waits for all reused server sessions pending requests" do
181
+ it 'detects and waits for all reused server sessions pending requests' do
124
182
  done = 0
125
183
 
126
184
  app = proc do |env|
127
185
  request = Rack::Request.new(env)
128
186
  sleep request.params['wait_time'].to_f
129
187
  done += 1
130
- [200, {}, ["Hello Server!"]]
188
+ [200, {}, ['Hello Server!']]
131
189
  end
132
190
 
133
- server1 = Capybara::Server.new(app).boot
134
- server2 = Capybara::Server.new(app).boot
191
+ server1 = described_class.new(app).boot
192
+ server2 = described_class.new(app).boot
135
193
 
136
194
  expect do
137
195
  start_request(server1, 1.0)
138
196
  start_request(server2, 3.0)
139
197
  server1.wait_for_pending_requests
140
198
  end.to change { done }.from(0).to(2)
141
- expect(server2.send(:pending_requests?)).to eq(false)
199
+ expect(server2.send(:pending_requests?)).to be(false)
142
200
  end
143
201
  end
144
202
 
145
- context "When Capybara.reuse_server is false" do
203
+ context 'When Capybara.reuse_server is false' do
146
204
  before do
147
205
  @old_reuse_server = Capybara.reuse_server
148
206
  Capybara.reuse_server = false
149
207
  end
150
208
 
151
209
  after do
152
- Capybara.reuse_server = @old_reuse_server
210
+ Capybara.reuse_server = @old_reuse_server # rubocop:disable RSpec/InstanceVariable
153
211
  end
154
212
 
155
- it "should not reuse an already running server" do
156
- @app = proc { |_env| [200, {}, ["Hello Server!"]] }
157
-
158
- @server1 = Capybara::Server.new(@app).boot
159
- @server2 = Capybara::Server.new(@app).boot
213
+ it 'should not reuse an already running server' do
214
+ app = proc { |_env| [200, {}, ['Hello Server!']] }
160
215
 
161
- res = Net::HTTP.start(@server1.host, @server1.port) { |http| http.get('/') }
162
- expect(res.body).to include('Hello Server')
216
+ servers = Array.new(2) { described_class.new(app).boot }
163
217
 
164
- res = Net::HTTP.start(@server2.host, @server2.port) { |http| http.get('/') }
165
- expect(res.body).to include('Hello Server')
218
+ servers.each do |server|
219
+ res = Net::HTTP.start(server.host, server.port) { |http| http.get('/') }
220
+ expect(res.body).to include('Hello Server')
221
+ end
166
222
 
167
- expect(@server1.port).not_to eq(@server2.port)
223
+ expect(servers[0].port).not_to eq(servers[1].port)
168
224
  end
169
225
 
170
- it "detects and waits for only one sessions pending requests" do
226
+ it 'detects and waits for only one sessions pending requests' do
171
227
  done = 0
172
228
 
173
229
  app = proc do |env|
174
230
  request = Rack::Request.new(env)
175
231
  sleep request.params['wait_time'].to_f
176
232
  done += 1
177
- [200, {}, ["Hello Server!"]]
233
+ [200, {}, ['Hello Server!']]
178
234
  end
179
235
 
180
- server1 = Capybara::Server.new(app).boot
181
- server2 = Capybara::Server.new(app).boot
236
+ server1 = described_class.new(app).boot
237
+ server2 = described_class.new(app).boot
182
238
 
183
239
  expect do
184
240
  start_request(server1, 1.0)
185
241
  start_request(server2, 3.0)
186
242
  server1.wait_for_pending_requests
187
243
  end.to change { done }.from(0).to(1)
188
- expect(server2.send(:pending_requests?)).to eq(true)
244
+ expect(server2.send(:pending_requests?)).to be(true)
189
245
  expect do
190
246
  server2.wait_for_pending_requests
191
247
  end.to change { done }.from(1).to(2)
192
248
  end
193
249
  end
194
250
 
195
- it "should raise server errors when the server errors before the timeout" do
196
- begin
197
- Capybara.register_server :kaboom do
198
- sleep 0.1
199
- raise 'kaboom'
200
- end
201
- Capybara.server = :kaboom
251
+ it 'should raise server errors when the server errors before the timeout' do
252
+ Capybara.register_server :kaboom do
253
+ sleep 0.1
254
+ raise 'kaboom'
255
+ end
256
+ Capybara.server = :kaboom
202
257
 
203
- expect do
204
- Capybara::Server.new(proc { |e| }).boot
205
- end.to raise_error(RuntimeError, 'kaboom')
206
- ensure
207
- Capybara.server = :default
258
+ expect do
259
+ described_class.new(proc { |e| }).boot
260
+ end.to raise_error(RuntimeError, 'kaboom')
261
+ ensure
262
+ Capybara.server = :default
263
+ end
264
+
265
+ it 'should raise an error when there are pending requests' do
266
+ app = proc do |env|
267
+ request = Rack::Request.new(env)
268
+ sleep request.params['wait_time'].to_f
269
+ [200, {}, ['Hello Server!']]
208
270
  end
271
+
272
+ server = described_class.new(app).boot
273
+
274
+ expect do
275
+ start_request(server, 59.0)
276
+ server.wait_for_pending_requests
277
+ end.not_to raise_error
278
+
279
+ expect do
280
+ start_request(server, 61.0)
281
+ server.wait_for_pending_requests
282
+ end.to raise_error('Requests did not finish in 60 seconds: ["/?wait_time=61.0"]')
209
283
  end
210
284
 
211
- it "is not #responsive? when Net::HTTP raises a SystemCallError" do
285
+ it 'is not #responsive? when Net::HTTP raises a SystemCallError' do
212
286
  app = -> { [200, {}, ['Hello, world']] }
213
- server = Capybara::Server.new(app)
287
+ server = described_class.new(app)
214
288
  allow(Net::HTTP).to receive(:start).and_raise(SystemCallError.allocate)
215
- expect(server.responsive?).to eq false
289
+ expect(server.responsive?).to be false
216
290
  end
217
291
 
218
292
  [EOFError, Net::ReadTimeout].each do |err|
@@ -225,7 +299,7 @@ RSpec.describe Capybara::Server do
225
299
  response = Net::HTTPSuccess.allocate
226
300
  allow(response).to receive(:body).and_return app.object_id.to_s
227
301
  allow(Net::HTTP).to receive(:start).with(anything, anything, hash_including(use_ssl: true)).and_return(response).once
228
- Capybara::Server.new(app).boot
302
+ described_class.new(app).boot
229
303
  expect(Net::HTTP).to have_received(:start).exactly(3).times
230
304
  end
231
305
  end
data/spec/session_spec.rb CHANGED
@@ -3,28 +3,28 @@
3
3
  require 'spec_helper'
4
4
 
5
5
  RSpec.describe Capybara::Session do
6
- context "#new" do
7
- it "should raise an error if passed non-existent driver" do
6
+ describe '#new' do
7
+ it 'should raise an error if passed non-existent driver' do
8
8
  expect do
9
- Capybara::Session.new(:quox, TestApp).driver
9
+ described_class.new(:quox, TestApp).driver
10
10
  end.to raise_error(Capybara::DriverNotFoundError)
11
11
  end
12
12
 
13
- it "verifies a passed app is a rack app" do
13
+ it 'verifies a passed app is a rack app' do
14
14
  expect do
15
- Capybara::Session.new(:unknown, random: "hash")
16
- end.to raise_error TypeError, "The second parameter to Session::new should be a rack app if passed."
15
+ described_class.new(:unknown, random: 'hash')
16
+ end.to raise_error TypeError, 'The second parameter to Session::new should be a rack app if passed.'
17
17
  end
18
18
  end
19
19
 
20
- context "current_driver" do
20
+ context 'current_driver' do
21
21
  around do |example|
22
22
  orig_driver = Capybara.current_driver
23
23
  example.run
24
24
  Capybara.current_driver = orig_driver
25
25
  end
26
26
 
27
- it "is global when threadsafe false" do
27
+ it 'is global when threadsafe false' do
28
28
  Capybara.threadsafe = false
29
29
  Capybara.current_driver = :selenium
30
30
  thread = Thread.new do
@@ -34,7 +34,7 @@ RSpec.describe Capybara::Session do
34
34
  expect(Capybara.current_driver).to eq :random
35
35
  end
36
36
 
37
- it "is thread specific threadsafe true" do
37
+ it 'is thread specific threadsafe true' do
38
38
  Capybara.threadsafe = true
39
39
  Capybara.current_driver = :selenium
40
40
  thread = Thread.new do
@@ -45,31 +45,47 @@ RSpec.describe Capybara::Session do
45
45
  end
46
46
  end
47
47
 
48
- context "session_name" do
48
+ context 'session_name' do
49
49
  around do |example|
50
50
  orig_name = Capybara.session_name
51
51
  example.run
52
52
  Capybara.session_name = orig_name
53
53
  end
54
54
 
55
- it "is global when threadsafe false" do
55
+ it 'is global when threadsafe false' do
56
56
  Capybara.threadsafe = false
57
- Capybara.session_name = "sess1"
57
+ Capybara.session_name = 'sess1'
58
58
  thread = Thread.new do
59
- Capybara.session_name = "sess2"
59
+ Capybara.session_name = 'sess2'
60
60
  end
61
61
  thread.join
62
- expect(Capybara.session_name).to eq "sess2"
62
+ expect(Capybara.session_name).to eq 'sess2'
63
63
  end
64
64
 
65
- it "is thread specific when threadsafe true" do
65
+ it 'is thread specific when threadsafe true' do
66
66
  Capybara.threadsafe = true
67
- Capybara.session_name = "sess1"
67
+ Capybara.session_name = 'sess1'
68
68
  thread = Thread.new do
69
- Capybara.session_name = "sess2"
69
+ Capybara.session_name = 'sess2'
70
70
  end
71
71
  thread.join
72
- expect(Capybara.session_name).to eq "sess1"
72
+ expect(Capybara.session_name).to eq 'sess1'
73
+ end
74
+ end
75
+
76
+ context 'quit' do
77
+ it 'will reset the driver' do
78
+ session = described_class.new(:rack_test, TestApp)
79
+ driver = session.driver
80
+ session.quit
81
+ expect(session.driver).not_to eql driver
82
+ end
83
+
84
+ it 'resets the document' do
85
+ session = described_class.new(:rack_test, TestApp)
86
+ document = session.document
87
+ session.quit
88
+ expect(session.document.base).not_to eql document.base
73
89
  end
74
90
  end
75
91
  end
@@ -0,0 +1,79 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+ require 'selenium-webdriver'
5
+
6
+ RSpec.shared_examples 'Capybara::Node' do |session, _mode|
7
+ let(:session) { session }
8
+
9
+ describe '#content_editable?' do
10
+ it 'returns true when the element is content editable' do
11
+ session.visit('/with_js')
12
+ expect(session.find(:css, '#existing_content_editable').base.content_editable?).to be true
13
+ expect(session.find(:css, '#existing_content_editable_child').base.content_editable?).to be true
14
+ end
15
+
16
+ it 'returns false when the element is not content editable' do
17
+ session.visit('/with_js')
18
+ expect(session.find(:css, '#drag').base.content_editable?).to be false
19
+ end
20
+ end
21
+
22
+ describe '#send_keys' do
23
+ it 'should process space' do
24
+ session.visit('/form')
25
+ session.find(:css, '#address1_city').send_keys('ocean', [:shift, :space, 'side'])
26
+ expect(session.find(:css, '#address1_city').value).to eq 'ocean SIDE'
27
+ end
28
+ end
29
+
30
+ describe '#[]' do
31
+ it 'should work for spellcheck' do
32
+ session.visit('/with_html')
33
+ expect(session.find('//input[@spellcheck="TRUE"]')[:spellcheck]).to eq('true')
34
+ expect(session.find('//input[@spellcheck="FALSE"]')[:spellcheck]).to eq('false')
35
+ end
36
+ end
37
+
38
+ describe '#set' do
39
+ it 'respects maxlength when using rapid set' do
40
+ session.visit('/form')
41
+ inp = session.find(:css, '#long_length')
42
+ value = (0...50).map { |i| ((i % 26) + 65).chr }.join
43
+ inp.set(value, rapid: true)
44
+ expect(inp.value).to eq value[0...35]
45
+ end
46
+ end
47
+
48
+ describe '#visible?' do
49
+ let(:bridge) do
50
+ session.driver.browser.send(:bridge)
51
+ end
52
+
53
+ around do |example|
54
+ native_displayed = session.driver.options[:native_displayed]
55
+ example.run
56
+ session.driver.options[:native_displayed] = native_displayed
57
+ end
58
+
59
+ before do
60
+ allow(bridge).to receive(:execute_atom).and_call_original
61
+ end
62
+
63
+ it 'will use native displayed if told to' do
64
+ session.driver.options[:native_displayed] = true
65
+ session.visit('/form')
66
+ session.find(:css, '#address1_city', visible: true)
67
+
68
+ expect(bridge).not_to have_received(:execute_atom)
69
+ end
70
+
71
+ it "won't use native displayed if told not to" do
72
+ session.driver.options[:native_displayed] = false
73
+ session.visit('/form')
74
+ session.find(:css, '#address1_city', visible: true)
75
+
76
+ expect(bridge).to have_received(:execute_atom).with(:isDisplayed, any_args)
77
+ end
78
+ end
79
+ end