capybara 3.0.0 → 3.36.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (308) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +1 -1
  3. data/History.md +777 -10
  4. data/License.txt +1 -1
  5. data/README.md +75 -58
  6. data/lib/capybara/config.rb +29 -10
  7. data/lib/capybara/cucumber.rb +1 -1
  8. data/lib/capybara/driver/base.rb +22 -4
  9. data/lib/capybara/driver/node.rb +34 -9
  10. data/lib/capybara/dsl.rb +14 -6
  11. data/lib/capybara/helpers.rb +52 -7
  12. data/lib/capybara/minitest/spec.rb +173 -84
  13. data/lib/capybara/minitest.rb +250 -144
  14. data/lib/capybara/node/actions.rb +248 -124
  15. data/lib/capybara/node/base.rb +34 -20
  16. data/lib/capybara/node/document.rb +14 -2
  17. data/lib/capybara/node/document_matchers.rb +13 -15
  18. data/lib/capybara/node/element.rb +339 -113
  19. data/lib/capybara/node/finders.rb +95 -82
  20. data/lib/capybara/node/matchers.rb +338 -157
  21. data/lib/capybara/node/simple.rb +54 -15
  22. data/lib/capybara/queries/active_element_query.rb +18 -0
  23. data/lib/capybara/queries/ancestor_query.rb +9 -10
  24. data/lib/capybara/queries/base_query.rb +25 -18
  25. data/lib/capybara/queries/current_path_query.rb +16 -6
  26. data/lib/capybara/queries/match_query.rb +11 -0
  27. data/lib/capybara/queries/selector_query.rb +600 -103
  28. data/lib/capybara/queries/sibling_query.rb +9 -7
  29. data/lib/capybara/queries/style_query.rb +45 -0
  30. data/lib/capybara/queries/text_query.rb +40 -22
  31. data/lib/capybara/queries/title_query.rb +2 -2
  32. data/lib/capybara/rack_test/browser.rb +47 -28
  33. data/lib/capybara/rack_test/driver.rb +12 -3
  34. data/lib/capybara/rack_test/errors.rb +6 -0
  35. data/lib/capybara/rack_test/form.rb +53 -50
  36. data/lib/capybara/rack_test/node.rb +114 -37
  37. data/lib/capybara/rails.rb +1 -1
  38. data/lib/capybara/registration_container.rb +44 -0
  39. data/lib/capybara/registrations/drivers.rb +42 -0
  40. data/lib/capybara/registrations/patches/puma_ssl.rb +29 -0
  41. data/lib/capybara/registrations/servers.rb +45 -0
  42. data/lib/capybara/result.rb +86 -52
  43. data/lib/capybara/rspec/features.rb +8 -10
  44. data/lib/capybara/rspec/matcher_proxies.rb +39 -18
  45. data/lib/capybara/rspec/matchers/base.rb +111 -0
  46. data/lib/capybara/rspec/matchers/become_closed.rb +33 -0
  47. data/lib/capybara/rspec/matchers/compound.rb +88 -0
  48. data/lib/capybara/rspec/matchers/count_sugar.rb +37 -0
  49. data/lib/capybara/rspec/matchers/have_ancestor.rb +28 -0
  50. data/lib/capybara/rspec/matchers/have_current_path.rb +29 -0
  51. data/lib/capybara/rspec/matchers/have_selector.rb +77 -0
  52. data/lib/capybara/rspec/matchers/have_sibling.rb +27 -0
  53. data/lib/capybara/rspec/matchers/have_text.rb +33 -0
  54. data/lib/capybara/rspec/matchers/have_title.rb +29 -0
  55. data/lib/capybara/rspec/matchers/match_selector.rb +27 -0
  56. data/lib/capybara/rspec/matchers/match_style.rb +43 -0
  57. data/lib/capybara/rspec/matchers/spatial_sugar.rb +39 -0
  58. data/lib/capybara/rspec/matchers.rb +138 -316
  59. data/lib/capybara/rspec.rb +3 -2
  60. data/lib/capybara/selector/builders/css_builder.rb +84 -0
  61. data/lib/capybara/selector/builders/xpath_builder.rb +71 -0
  62. data/lib/capybara/selector/css.rb +89 -12
  63. data/lib/capybara/selector/definition/button.rb +68 -0
  64. data/lib/capybara/selector/definition/checkbox.rb +26 -0
  65. data/lib/capybara/selector/definition/css.rb +10 -0
  66. data/lib/capybara/selector/definition/datalist_input.rb +35 -0
  67. data/lib/capybara/selector/definition/datalist_option.rb +25 -0
  68. data/lib/capybara/selector/definition/element.rb +28 -0
  69. data/lib/capybara/selector/definition/field.rb +40 -0
  70. data/lib/capybara/selector/definition/fieldset.rb +14 -0
  71. data/lib/capybara/selector/definition/file_field.rb +13 -0
  72. data/lib/capybara/selector/definition/fillable_field.rb +33 -0
  73. data/lib/capybara/selector/definition/frame.rb +17 -0
  74. data/lib/capybara/selector/definition/id.rb +6 -0
  75. data/lib/capybara/selector/definition/label.rb +62 -0
  76. data/lib/capybara/selector/definition/link.rb +54 -0
  77. data/lib/capybara/selector/definition/link_or_button.rb +16 -0
  78. data/lib/capybara/selector/definition/option.rb +27 -0
  79. data/lib/capybara/selector/definition/radio_button.rb +27 -0
  80. data/lib/capybara/selector/definition/select.rb +81 -0
  81. data/lib/capybara/selector/definition/table.rb +109 -0
  82. data/lib/capybara/selector/definition/table_row.rb +21 -0
  83. data/lib/capybara/selector/definition/xpath.rb +5 -0
  84. data/lib/capybara/selector/definition.rb +279 -0
  85. data/lib/capybara/selector/filter.rb +1 -0
  86. data/lib/capybara/selector/filter_set.rb +72 -27
  87. data/lib/capybara/selector/filters/base.rb +45 -2
  88. data/lib/capybara/selector/filters/expression_filter.rb +5 -6
  89. data/lib/capybara/selector/filters/locator_filter.rb +29 -0
  90. data/lib/capybara/selector/filters/node_filter.rb +18 -4
  91. data/lib/capybara/selector/regexp_disassembler.rb +214 -0
  92. data/lib/capybara/selector/selector.rb +85 -200
  93. data/lib/capybara/selector/xpath_extensions.rb +17 -0
  94. data/lib/capybara/selector.rb +226 -537
  95. data/lib/capybara/selenium/atoms/getAttribute.min.js +1 -0
  96. data/lib/capybara/selenium/atoms/isDisplayed.min.js +1 -0
  97. data/lib/capybara/selenium/atoms/src/getAttribute.js +161 -0
  98. data/lib/capybara/selenium/atoms/src/isDisplayed.js +454 -0
  99. data/lib/capybara/selenium/driver.rb +296 -238
  100. data/lib/capybara/selenium/driver_specializations/chrome_driver.rb +117 -0
  101. data/lib/capybara/selenium/driver_specializations/edge_driver.rb +124 -0
  102. data/lib/capybara/selenium/driver_specializations/firefox_driver.rb +89 -0
  103. data/lib/capybara/selenium/driver_specializations/internet_explorer_driver.rb +26 -0
  104. data/lib/capybara/selenium/driver_specializations/safari_driver.rb +24 -0
  105. data/lib/capybara/selenium/extensions/file_input_click_emulation.rb +34 -0
  106. data/lib/capybara/selenium/extensions/find.rb +110 -0
  107. data/lib/capybara/selenium/extensions/html5_drag.rb +228 -0
  108. data/lib/capybara/selenium/extensions/modifier_keys_stack.rb +28 -0
  109. data/lib/capybara/selenium/extensions/scroll.rb +76 -0
  110. data/lib/capybara/selenium/logger_suppressor.rb +40 -0
  111. data/lib/capybara/selenium/node.rb +436 -166
  112. data/lib/capybara/selenium/nodes/chrome_node.rb +137 -0
  113. data/lib/capybara/selenium/nodes/edge_node.rb +104 -0
  114. data/lib/capybara/selenium/nodes/firefox_node.rb +136 -0
  115. data/lib/capybara/selenium/nodes/ie_node.rb +22 -0
  116. data/lib/capybara/selenium/nodes/safari_node.rb +118 -0
  117. data/lib/capybara/selenium/patches/action_pauser.rb +26 -0
  118. data/lib/capybara/selenium/patches/atoms.rb +18 -0
  119. data/lib/capybara/selenium/patches/is_displayed.rb +16 -0
  120. data/lib/capybara/selenium/patches/logs.rb +45 -0
  121. data/lib/capybara/selenium/patches/pause_duration_fix.rb +9 -0
  122. data/lib/capybara/selenium/patches/persistent_client.rb +20 -0
  123. data/lib/capybara/server/animation_disabler.rb +69 -0
  124. data/lib/capybara/server/checker.rb +44 -0
  125. data/lib/capybara/server/middleware.rb +71 -0
  126. data/lib/capybara/server.rb +58 -67
  127. data/lib/capybara/session/config.rb +38 -6
  128. data/lib/capybara/session/matchers.rb +26 -19
  129. data/lib/capybara/session.rb +258 -190
  130. data/lib/capybara/spec/public/jquery.js +5 -5
  131. data/lib/capybara/spec/public/offset.js +6 -0
  132. data/lib/capybara/spec/public/test.js +122 -8
  133. data/lib/capybara/spec/session/accept_alert_spec.rb +11 -11
  134. data/lib/capybara/spec/session/accept_confirm_spec.rb +3 -3
  135. data/lib/capybara/spec/session/accept_prompt_spec.rb +9 -10
  136. data/lib/capybara/spec/session/active_element_spec.rb +31 -0
  137. data/lib/capybara/spec/session/all_spec.rb +135 -42
  138. data/lib/capybara/spec/session/ancestor_spec.rb +24 -19
  139. data/lib/capybara/spec/session/assert_all_of_selectors_spec.rb +67 -38
  140. data/lib/capybara/spec/session/{assert_current_path.rb → assert_current_path_spec.rb} +20 -18
  141. data/lib/capybara/spec/session/assert_selector_spec.rb +143 -0
  142. data/lib/capybara/spec/session/assert_style_spec.rb +26 -0
  143. data/lib/capybara/spec/session/{assert_text.rb → assert_text_spec.rb} +62 -38
  144. data/lib/capybara/spec/session/{assert_title.rb → assert_title_spec.rb} +12 -12
  145. data/lib/capybara/spec/session/attach_file_spec.rb +120 -72
  146. data/lib/capybara/spec/session/body_spec.rb +11 -13
  147. data/lib/capybara/spec/session/check_spec.rb +111 -51
  148. data/lib/capybara/spec/session/choose_spec.rb +62 -30
  149. data/lib/capybara/spec/session/click_button_spec.rb +227 -161
  150. data/lib/capybara/spec/session/click_link_or_button_spec.rb +49 -30
  151. data/lib/capybara/spec/session/click_link_spec.rb +78 -55
  152. data/lib/capybara/spec/session/current_scope_spec.rb +7 -7
  153. data/lib/capybara/spec/session/current_url_spec.rb +44 -37
  154. data/lib/capybara/spec/session/dismiss_confirm_spec.rb +3 -3
  155. data/lib/capybara/spec/session/dismiss_prompt_spec.rb +2 -2
  156. data/lib/capybara/spec/session/element/{assert_match_selector.rb → assert_match_selector_spec.rb} +11 -9
  157. data/lib/capybara/spec/session/element/match_css_spec.rb +18 -10
  158. data/lib/capybara/spec/session/element/match_xpath_spec.rb +8 -6
  159. data/lib/capybara/spec/session/element/matches_selector_spec.rb +70 -56
  160. data/lib/capybara/spec/session/evaluate_async_script_spec.rb +7 -7
  161. data/lib/capybara/spec/session/evaluate_script_spec.rb +28 -8
  162. data/lib/capybara/spec/session/execute_script_spec.rb +8 -7
  163. data/lib/capybara/spec/session/fill_in_spec.rb +104 -44
  164. data/lib/capybara/spec/session/find_button_spec.rb +23 -23
  165. data/lib/capybara/spec/session/find_by_id_spec.rb +8 -8
  166. data/lib/capybara/spec/session/find_field_spec.rb +33 -31
  167. data/lib/capybara/spec/session/find_link_spec.rb +32 -14
  168. data/lib/capybara/spec/session/find_spec.rb +236 -141
  169. data/lib/capybara/spec/session/first_spec.rb +44 -43
  170. data/lib/capybara/spec/session/frame/frame_title_spec.rb +6 -6
  171. data/lib/capybara/spec/session/frame/frame_url_spec.rb +6 -6
  172. data/lib/capybara/spec/session/frame/switch_to_frame_spec.rb +32 -20
  173. data/lib/capybara/spec/session/frame/within_frame_spec.rb +44 -19
  174. data/lib/capybara/spec/session/go_back_spec.rb +1 -1
  175. data/lib/capybara/spec/session/go_forward_spec.rb +1 -1
  176. data/lib/capybara/spec/session/has_all_selectors_spec.rb +18 -18
  177. data/lib/capybara/spec/session/has_ancestor_spec.rb +46 -0
  178. data/lib/capybara/spec/session/has_any_selectors_spec.rb +29 -0
  179. data/lib/capybara/spec/session/has_button_spec.rb +92 -12
  180. data/lib/capybara/spec/session/has_css_spec.rb +271 -137
  181. data/lib/capybara/spec/session/has_current_path_spec.rb +48 -33
  182. data/lib/capybara/spec/session/has_field_spec.rb +137 -58
  183. data/lib/capybara/spec/session/has_link_spec.rb +30 -6
  184. data/lib/capybara/spec/session/has_none_selectors_spec.rb +26 -24
  185. data/lib/capybara/spec/session/has_select_spec.rb +75 -47
  186. data/lib/capybara/spec/session/has_selector_spec.rb +102 -69
  187. data/lib/capybara/spec/session/has_sibling_spec.rb +50 -0
  188. data/lib/capybara/spec/session/has_table_spec.rb +170 -4
  189. data/lib/capybara/spec/session/has_text_spec.rb +108 -52
  190. data/lib/capybara/spec/session/has_title_spec.rb +19 -14
  191. data/lib/capybara/spec/session/has_xpath_spec.rb +56 -38
  192. data/lib/capybara/spec/session/{headers.rb → headers_spec.rb} +1 -1
  193. data/lib/capybara/spec/session/html_spec.rb +13 -6
  194. data/lib/capybara/spec/session/matches_style_spec.rb +35 -0
  195. data/lib/capybara/spec/session/node_spec.rb +871 -122
  196. data/lib/capybara/spec/session/node_wrapper_spec.rb +15 -12
  197. data/lib/capybara/spec/session/refresh_spec.rb +9 -7
  198. data/lib/capybara/spec/session/reset_session_spec.rb +52 -37
  199. data/lib/capybara/spec/session/{response_code.rb → response_code_spec.rb} +1 -1
  200. data/lib/capybara/spec/session/save_and_open_page_spec.rb +2 -2
  201. data/lib/capybara/spec/session/save_and_open_screenshot_spec.rb +5 -4
  202. data/lib/capybara/spec/session/save_page_spec.rb +41 -38
  203. data/lib/capybara/spec/session/save_screenshot_spec.rb +13 -11
  204. data/lib/capybara/spec/session/screenshot_spec.rb +2 -2
  205. data/lib/capybara/spec/session/scroll_spec.rb +117 -0
  206. data/lib/capybara/spec/session/select_spec.rb +102 -76
  207. data/lib/capybara/spec/session/selectors_spec.rb +51 -18
  208. data/lib/capybara/spec/session/sibling_spec.rb +9 -9
  209. data/lib/capybara/spec/session/text_spec.rb +26 -24
  210. data/lib/capybara/spec/session/title_spec.rb +8 -6
  211. data/lib/capybara/spec/session/uncheck_spec.rb +40 -21
  212. data/lib/capybara/spec/session/unselect_spec.rb +37 -37
  213. data/lib/capybara/spec/session/visit_spec.rb +59 -53
  214. data/lib/capybara/spec/session/window/become_closed_spec.rb +22 -19
  215. data/lib/capybara/spec/session/window/current_window_spec.rb +4 -3
  216. data/lib/capybara/spec/session/window/open_new_window_spec.rb +4 -3
  217. data/lib/capybara/spec/session/window/switch_to_window_spec.rb +25 -21
  218. data/lib/capybara/spec/session/window/window_opened_by_spec.rb +10 -5
  219. data/lib/capybara/spec/session/window/window_spec.rb +88 -54
  220. data/lib/capybara/spec/session/window/windows_spec.rb +10 -7
  221. data/lib/capybara/spec/session/window/within_window_spec.rb +17 -16
  222. data/lib/capybara/spec/session/within_spec.rb +69 -44
  223. data/lib/capybara/spec/spec_helper.rb +41 -53
  224. data/lib/capybara/spec/test_app.rb +79 -40
  225. data/lib/capybara/spec/views/animated.erb +49 -0
  226. data/lib/capybara/spec/views/form.erb +134 -42
  227. data/lib/capybara/spec/views/frame_child.erb +4 -3
  228. data/lib/capybara/spec/views/frame_one.erb +2 -1
  229. data/lib/capybara/spec/views/frame_parent.erb +1 -1
  230. data/lib/capybara/spec/views/frame_two.erb +1 -1
  231. data/lib/capybara/spec/views/initial_alert.erb +2 -1
  232. data/lib/capybara/spec/views/layout.erb +10 -0
  233. data/lib/capybara/spec/views/obscured.erb +47 -0
  234. data/lib/capybara/spec/views/offset.erb +33 -0
  235. data/lib/capybara/spec/views/path.erb +2 -2
  236. data/lib/capybara/spec/views/popup_one.erb +1 -1
  237. data/lib/capybara/spec/views/popup_two.erb +1 -1
  238. data/lib/capybara/spec/views/react.erb +45 -0
  239. data/lib/capybara/spec/views/scroll.erb +21 -0
  240. data/lib/capybara/spec/views/spatial.erb +31 -0
  241. data/lib/capybara/spec/views/tables.erb +68 -1
  242. data/lib/capybara/spec/views/with_animation.erb +81 -0
  243. data/lib/capybara/spec/views/with_base_tag.erb +2 -2
  244. data/lib/capybara/spec/views/with_dragula.erb +24 -0
  245. data/lib/capybara/spec/views/with_fixed_header_footer.erb +2 -1
  246. data/lib/capybara/spec/views/with_hover.erb +3 -2
  247. data/lib/capybara/spec/views/with_hover1.erb +10 -0
  248. data/lib/capybara/spec/views/with_html.erb +43 -10
  249. data/lib/capybara/spec/views/with_html5_svg.erb +20 -0
  250. data/lib/capybara/spec/views/with_jquery_animation.erb +24 -0
  251. data/lib/capybara/spec/views/with_js.erb +30 -5
  252. data/lib/capybara/spec/views/with_jstree.erb +26 -0
  253. data/lib/capybara/spec/views/with_namespace.erb +21 -0
  254. data/lib/capybara/spec/views/with_scope_other.erb +6 -0
  255. data/lib/capybara/spec/views/with_slow_unload.erb +2 -1
  256. data/lib/capybara/spec/views/with_sortable_js.erb +21 -0
  257. data/lib/capybara/spec/views/with_unload_alert.erb +1 -0
  258. data/lib/capybara/spec/views/with_windows.erb +1 -1
  259. data/lib/capybara/spec/views/within_frames.erb +1 -1
  260. data/lib/capybara/version.rb +1 -1
  261. data/lib/capybara/window.rb +31 -25
  262. data/lib/capybara.rb +120 -100
  263. data/spec/basic_node_spec.rb +59 -34
  264. data/spec/capybara_spec.rb +54 -52
  265. data/spec/css_builder_spec.rb +101 -0
  266. data/spec/css_splitter_spec.rb +38 -0
  267. data/spec/dsl_spec.rb +80 -53
  268. data/spec/filter_set_spec.rb +24 -7
  269. data/spec/fixtures/certificate.pem +25 -0
  270. data/spec/fixtures/key.pem +27 -0
  271. data/spec/fixtures/selenium_driver_rspec_failure.rb +4 -4
  272. data/spec/fixtures/selenium_driver_rspec_success.rb +4 -4
  273. data/spec/minitest_spec.rb +38 -5
  274. data/spec/minitest_spec_spec.rb +88 -62
  275. data/spec/per_session_config_spec.rb +5 -5
  276. data/spec/rack_test_spec.rb +169 -115
  277. data/spec/regexp_dissassembler_spec.rb +250 -0
  278. data/spec/result_spec.rb +86 -33
  279. data/spec/rspec/features_spec.rb +26 -23
  280. data/spec/rspec/scenarios_spec.rb +8 -4
  281. data/spec/rspec/shared_spec_matchers.rb +393 -363
  282. data/spec/rspec/views_spec.rb +4 -3
  283. data/spec/rspec_matchers_spec.rb +10 -10
  284. data/spec/rspec_spec.rb +109 -85
  285. data/spec/sauce_spec_chrome.rb +43 -0
  286. data/spec/selector_spec.rb +391 -61
  287. data/spec/selenium_spec_chrome.rb +180 -41
  288. data/spec/selenium_spec_chrome_remote.rb +101 -0
  289. data/spec/selenium_spec_edge.rb +28 -8
  290. data/spec/selenium_spec_firefox.rb +211 -0
  291. data/spec/selenium_spec_firefox_remote.rb +80 -0
  292. data/spec/selenium_spec_ie.rb +127 -11
  293. data/spec/selenium_spec_safari.rb +156 -0
  294. data/spec/server_spec.rb +177 -78
  295. data/spec/session_spec.rb +52 -16
  296. data/spec/shared_selenium_node.rb +79 -0
  297. data/spec/shared_selenium_session.rb +455 -123
  298. data/spec/spec_helper.rb +91 -2
  299. data/spec/xpath_builder_spec.rb +93 -0
  300. metadata +343 -42
  301. data/.yard/templates_custom/default/class/html/selectors.erb +0 -38
  302. data/.yard/templates_custom/default/class/html/setup.rb +0 -17
  303. data/.yard/yard_extensions.rb +0 -78
  304. data/lib/capybara/rspec/compound.rb +0 -90
  305. data/lib/capybara/spec/session/assert_selector.rb +0 -149
  306. data/lib/capybara/spec/session/source_spec.rb +0 -0
  307. data/lib/capybara/spec/views/with_title.erb +0 -5
  308. data/spec/selenium_spec_marionette.rb +0 -143
data/spec/server_spec.rb CHANGED
@@ -3,113 +3,181 @@
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['TRAVIS'] && (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') or 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, 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 }
70
+
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
76
+
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
65
88
 
66
- @server1 = Capybara::Server.new(@app1).boot
67
- @server2 = Capybara::Server.new(@app2).boot
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
93
+ end
68
94
 
69
- @res1 = Net::HTTP.start(@server1.host, @server1.port) { |http| http.get('/') }
70
- expect(@res1.body).to include('Hello Server')
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
71
101
 
72
- @res2 = Net::HTTP.start(@server2.host, @server2.port) { |http| http.get('/') }
73
- expect(@res2.body).to include('Hello Second Server')
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
74
119
  end
75
120
 
76
- context "When Capybara.reuse_server is true" do
121
+ it 'should support SSL' do
122
+ key = File.join(Dir.pwd, 'spec', 'fixtures', 'key.pem')
123
+ cert = File.join(Dir.pwd, 'spec', 'fixtures', 'certificate.pem')
124
+ Capybara.server = :puma, { Host: "ssl://#{Capybara.server_host}?key=#{key}&cert=#{cert}" }
125
+ app = proc { |_env| [200, {}, ['Hello SSL Server!']] }
126
+ server = described_class.new(app).boot
127
+
128
+ expect do
129
+ Net::HTTP.start(server.host, server.port, max_retries: 0) { |http| http.get('/__identify__') }
130
+ end.to(raise_error do |e|
131
+ expect(e.is_a?(EOFError) || e.is_a?(Net::ReadTimeout)).to be true
132
+ end)
133
+
134
+ res = Net::HTTP.start(server.host, server.port, use_ssl: true, verify_mode: OpenSSL::SSL::VERIFY_NONE) do |https|
135
+ https.get('/')
136
+ end
137
+
138
+ expect(res.body).to include('Hello SSL Server!')
139
+ uri = ::Addressable::URI.parse(server.base_url)
140
+ expect(uri.to_hash).to include(scheme: 'https', host: server.host, port: server.port)
141
+ ensure
142
+ Capybara.server = :default
143
+ end
144
+
145
+ context 'When Capybara.reuse_server is true' do
146
+ let!(:old_reuse_server) { Capybara.reuse_server }
147
+
77
148
  before do
78
- @old_reuse_server = Capybara.reuse_server
79
149
  Capybara.reuse_server = true
80
150
  end
81
151
 
82
152
  after do
83
- Capybara.reuse_server = @old_reuse_server
153
+ Capybara.reuse_server = old_reuse_server
84
154
  end
85
155
 
86
- it "should use the existing server if it already running" do
87
- @app = proc { |_env| [200, {}, ["Hello Server!"]] }
88
-
89
- @server1 = Capybara::Server.new(@app).boot
90
- @server2 = Capybara::Server.new(@app).boot
156
+ it 'should use the existing server if it already running' do
157
+ app = proc { |_env| [200, {}, ['Hello Server!']] }
91
158
 
92
- res = Net::HTTP.start(@server1.host, @server1.port) { |http| http.get('/') }
93
- expect(res.body).to include('Hello Server')
159
+ servers = Array.new(2) { described_class.new(app).boot }
94
160
 
95
- res = Net::HTTP.start(@server2.host, @server2.port) { |http| http.get('/') }
96
- expect(res.body).to include('Hello Server')
161
+ servers.each do |server|
162
+ res = Net::HTTP.start(server.host, server.port) { |http| http.get('/') }
163
+ expect(res.body).to include('Hello Server')
164
+ end
97
165
 
98
- expect(@server1.port).to eq(@server2.port)
166
+ expect(servers[0].port).to eq(servers[1].port)
99
167
  end
100
168
 
101
- it "detects and waits for all reused server sessions pending requests" do
169
+ it 'detects and waits for all reused server sessions pending requests' do
102
170
  done = 0
103
171
 
104
172
  app = proc do |env|
105
173
  request = Rack::Request.new(env)
106
174
  sleep request.params['wait_time'].to_f
107
175
  done += 1
108
- [200, {}, ["Hello Server!"]]
176
+ [200, {}, ['Hello Server!']]
109
177
  end
110
178
 
111
- server1 = Capybara::Server.new(app).boot
112
- server2 = Capybara::Server.new(app).boot
179
+ server1 = described_class.new(app).boot
180
+ server2 = described_class.new(app).boot
113
181
 
114
182
  expect do
115
183
  start_request(server1, 1.0)
@@ -120,43 +188,41 @@ RSpec.describe Capybara::Server do
120
188
  end
121
189
  end
122
190
 
123
- context "When Capybara.reuse_server is false" do
191
+ context 'When Capybara.reuse_server is false' do
124
192
  before do
125
193
  @old_reuse_server = Capybara.reuse_server
126
194
  Capybara.reuse_server = false
127
195
  end
128
196
 
129
197
  after do
130
- Capybara.reuse_server = @old_reuse_server
198
+ Capybara.reuse_server = @old_reuse_server # rubocop:disable RSpec/InstanceVariable
131
199
  end
132
200
 
133
- it "should not reuse an already running server" do
134
- @app = proc { |_env| [200, {}, ["Hello Server!"]] }
135
-
136
- @server1 = Capybara::Server.new(@app).boot
137
- @server2 = Capybara::Server.new(@app).boot
201
+ it 'should not reuse an already running server' do
202
+ app = proc { |_env| [200, {}, ['Hello Server!']] }
138
203
 
139
- res = Net::HTTP.start(@server1.host, @server1.port) { |http| http.get('/') }
140
- expect(res.body).to include('Hello Server')
204
+ servers = Array.new(2) { described_class.new(app).boot }
141
205
 
142
- res = Net::HTTP.start(@server2.host, @server2.port) { |http| http.get('/') }
143
- expect(res.body).to include('Hello Server')
206
+ servers.each do |server|
207
+ res = Net::HTTP.start(server.host, server.port) { |http| http.get('/') }
208
+ expect(res.body).to include('Hello Server')
209
+ end
144
210
 
145
- expect(@server1.port).not_to eq(@server2.port)
211
+ expect(servers[0].port).not_to eq(servers[1].port)
146
212
  end
147
213
 
148
- it "detects and waits for only one sessions pending requests" do
214
+ it 'detects and waits for only one sessions pending requests' do
149
215
  done = 0
150
216
 
151
217
  app = proc do |env|
152
218
  request = Rack::Request.new(env)
153
219
  sleep request.params['wait_time'].to_f
154
220
  done += 1
155
- [200, {}, ["Hello Server!"]]
221
+ [200, {}, ['Hello Server!']]
156
222
  end
157
223
 
158
- server1 = Capybara::Server.new(app).boot
159
- server2 = Capybara::Server.new(app).boot
224
+ server1 = described_class.new(app).boot
225
+ server2 = described_class.new(app).boot
160
226
 
161
227
  expect do
162
228
  start_request(server1, 1.0)
@@ -170,29 +236,62 @@ RSpec.describe Capybara::Server do
170
236
  end
171
237
  end
172
238
 
173
- it "should raise server errors when the server errors before the timeout" do
174
- begin
175
- Capybara.register_server :kaboom do
176
- sleep 0.1
177
- raise 'kaboom'
178
- end
179
- Capybara.server = :kaboom
239
+ it 'should raise server errors when the server errors before the timeout' do
240
+ Capybara.register_server :kaboom do
241
+ sleep 0.1
242
+ raise 'kaboom'
243
+ end
244
+ Capybara.server = :kaboom
180
245
 
181
- expect do
182
- Capybara::Server.new(proc { |e| }).boot
183
- end.to raise_error(RuntimeError, 'kaboom')
184
- ensure
185
- Capybara.server = :default
246
+ expect do
247
+ described_class.new(proc { |e| }).boot
248
+ end.to raise_error(RuntimeError, 'kaboom')
249
+ ensure
250
+ Capybara.server = :default
251
+ end
252
+
253
+ it 'should raise an error when there are pending requests' do
254
+ app = proc do |env|
255
+ request = Rack::Request.new(env)
256
+ sleep request.params['wait_time'].to_f
257
+ [200, {}, ['Hello Server!']]
186
258
  end
259
+
260
+ server = described_class.new(app).boot
261
+
262
+ expect do
263
+ start_request(server, 59.0)
264
+ server.wait_for_pending_requests
265
+ end.not_to raise_error
266
+
267
+ expect do
268
+ start_request(server, 61.0)
269
+ server.wait_for_pending_requests
270
+ end.to raise_error('Requests did not finish in 60 seconds: ["/?wait_time=61.0"]')
187
271
  end
188
272
 
189
- it "is not #responsive? when Net::HTTP raises a SystemCallError" do
273
+ it 'is not #responsive? when Net::HTTP raises a SystemCallError' do
190
274
  app = -> { [200, {}, ['Hello, world']] }
191
- server = Capybara::Server.new(app)
192
- expect(Net::HTTP).to receive(:start).and_raise(SystemCallError.allocate)
275
+ server = described_class.new(app)
276
+ allow(Net::HTTP).to receive(:start).and_raise(SystemCallError.allocate)
193
277
  expect(server.responsive?).to eq false
194
278
  end
195
279
 
280
+ [EOFError, Net::ReadTimeout].each do |err|
281
+ it "should attempt an HTTPS connection if HTTP connection returns #{err}" do
282
+ app = -> { [200, {}, ['Hello, world']] }
283
+ ordered_errors = [Errno::ECONNREFUSED, err]
284
+ allow(Net::HTTP).to receive(:start).with(anything, anything, hash_excluding(:use_ssl)) do
285
+ raise ordered_errors.shift
286
+ end
287
+ response = Net::HTTPSuccess.allocate
288
+ allow(response).to receive(:body).and_return app.object_id.to_s
289
+ allow(Net::HTTP).to receive(:start).with(anything, anything, hash_including(use_ssl: true)).and_return(response).once
290
+ described_class.new(app).boot
291
+ expect(Net::HTTP).to have_received(:start).exactly(3).times
292
+ end
293
+ end
294
+
196
295
  def start_request(server, wait_time)
197
296
  # Start request, but don't wait for it to finish
198
297
  socket = TCPSocket.new(server.host, server.port)
data/spec/session_spec.rb CHANGED
@@ -3,14 +3,28 @@
3
3
  require 'spec_helper'
4
4
 
5
5
  RSpec.describe Capybara::Session do
6
- it "verifies a passed app is a rack app" do
7
- expect do
8
- Capybara::Session.new(:unknown, random: "hash")
9
- end.to raise_error TypeError, "The second parameter to Session::new should be a rack app if passed."
6
+ describe '#new' do
7
+ it 'should raise an error if passed non-existent driver' do
8
+ expect do
9
+ described_class.new(:quox, TestApp).driver
10
+ end.to raise_error(Capybara::DriverNotFoundError)
11
+ end
12
+
13
+ it 'verifies a passed app is a rack app' do
14
+ expect do
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
+ end
10
18
  end
11
19
 
12
- context "current_driver" do
13
- it "is global when threadsafe false" do
20
+ context 'current_driver' do
21
+ around do |example|
22
+ orig_driver = Capybara.current_driver
23
+ example.run
24
+ Capybara.current_driver = orig_driver
25
+ end
26
+
27
+ it 'is global when threadsafe false' do
14
28
  Capybara.threadsafe = false
15
29
  Capybara.current_driver = :selenium
16
30
  thread = Thread.new do
@@ -20,7 +34,7 @@ RSpec.describe Capybara::Session do
20
34
  expect(Capybara.current_driver).to eq :random
21
35
  end
22
36
 
23
- it "is thread specific threadsafe true" do
37
+ it 'is thread specific threadsafe true' do
24
38
  Capybara.threadsafe = true
25
39
  Capybara.current_driver = :selenium
26
40
  thread = Thread.new do
@@ -31,25 +45,47 @@ RSpec.describe Capybara::Session do
31
45
  end
32
46
  end
33
47
 
34
- context "session_name" do
35
- it "is global when threadsafe false" do
48
+ context 'session_name' do
49
+ around do |example|
50
+ orig_name = Capybara.session_name
51
+ example.run
52
+ Capybara.session_name = orig_name
53
+ end
54
+
55
+ it 'is global when threadsafe false' do
36
56
  Capybara.threadsafe = false
37
- Capybara.session_name = "sess1"
57
+ Capybara.session_name = 'sess1'
38
58
  thread = Thread.new do
39
- Capybara.session_name = "sess2"
59
+ Capybara.session_name = 'sess2'
40
60
  end
41
61
  thread.join
42
- expect(Capybara.session_name).to eq "sess2"
62
+ expect(Capybara.session_name).to eq 'sess2'
43
63
  end
44
64
 
45
- it "is thread specific when threadsafe true" do
65
+ it 'is thread specific when threadsafe true' do
46
66
  Capybara.threadsafe = true
47
- Capybara.session_name = "sess1"
67
+ Capybara.session_name = 'sess1'
48
68
  thread = Thread.new do
49
- Capybara.session_name = "sess2"
69
+ Capybara.session_name = 'sess2'
50
70
  end
51
71
  thread.join
52
- 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
53
89
  end
54
90
  end
55
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