capybara 3.29.0 → 3.37.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (204) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +229 -15
  3. data/README.md +13 -4
  4. data/lib/capybara/config.rb +24 -10
  5. data/lib/capybara/cucumber.rb +1 -1
  6. data/lib/capybara/driver/base.rb +8 -0
  7. data/lib/capybara/driver/node.rb +5 -1
  8. data/lib/capybara/dsl.rb +5 -3
  9. data/lib/capybara/helpers.rb +19 -2
  10. data/lib/capybara/minitest/spec.rb +156 -97
  11. data/lib/capybara/minitest.rb +232 -144
  12. data/lib/capybara/node/actions.rb +41 -37
  13. data/lib/capybara/node/base.rb +6 -6
  14. data/lib/capybara/node/document.rb +2 -2
  15. data/lib/capybara/node/document_matchers.rb +3 -3
  16. data/lib/capybara/node/element.rb +35 -21
  17. data/lib/capybara/node/finders.rb +33 -19
  18. data/lib/capybara/node/matchers.rb +72 -57
  19. data/lib/capybara/node/simple.rb +13 -3
  20. data/lib/capybara/queries/active_element_query.rb +18 -0
  21. data/lib/capybara/queries/ancestor_query.rb +4 -3
  22. data/lib/capybara/queries/base_query.rb +2 -1
  23. data/lib/capybara/queries/current_path_query.rb +14 -4
  24. data/lib/capybara/queries/selector_query.rb +91 -30
  25. data/lib/capybara/queries/sibling_query.rb +4 -3
  26. data/lib/capybara/queries/style_query.rb +1 -1
  27. data/lib/capybara/queries/text_query.rb +7 -1
  28. data/lib/capybara/rack_test/browser.rb +68 -10
  29. data/lib/capybara/rack_test/driver.rb +6 -5
  30. data/lib/capybara/rack_test/form.rb +2 -2
  31. data/lib/capybara/rack_test/node.rb +44 -16
  32. data/lib/capybara/registration_container.rb +41 -0
  33. data/lib/capybara/registrations/drivers.rb +18 -12
  34. data/lib/capybara/registrations/patches/puma_ssl.rb +3 -1
  35. data/lib/capybara/registrations/servers.rb +3 -2
  36. data/lib/capybara/result.rb +35 -15
  37. data/lib/capybara/rspec/matcher_proxies.rb +8 -8
  38. data/lib/capybara/rspec/matchers/base.rb +12 -6
  39. data/lib/capybara/rspec/matchers/count_sugar.rb +2 -1
  40. data/lib/capybara/rspec/matchers/have_ancestor.rb +4 -3
  41. data/lib/capybara/rspec/matchers/have_current_path.rb +2 -2
  42. data/lib/capybara/rspec/matchers/have_selector.rb +16 -8
  43. data/lib/capybara/rspec/matchers/have_sibling.rb +3 -3
  44. data/lib/capybara/rspec/matchers/have_text.rb +3 -3
  45. data/lib/capybara/rspec/matchers/have_title.rb +2 -2
  46. data/lib/capybara/rspec/matchers/match_selector.rb +3 -3
  47. data/lib/capybara/rspec/matchers/match_style.rb +7 -2
  48. data/lib/capybara/rspec/matchers/spatial_sugar.rb +2 -1
  49. data/lib/capybara/rspec/matchers.rb +33 -32
  50. data/lib/capybara/rspec.rb +2 -0
  51. data/lib/capybara/selector/builders/css_builder.rb +2 -2
  52. data/lib/capybara/selector/builders/xpath_builder.rb +4 -2
  53. data/lib/capybara/selector/css.rb +2 -2
  54. data/lib/capybara/selector/definition/button.rb +35 -13
  55. data/lib/capybara/selector/definition/checkbox.rb +3 -3
  56. data/lib/capybara/selector/definition/css.rb +3 -1
  57. data/lib/capybara/selector/definition/datalist_input.rb +2 -2
  58. data/lib/capybara/selector/definition/datalist_option.rb +1 -1
  59. data/lib/capybara/selector/definition/element.rb +3 -2
  60. data/lib/capybara/selector/definition/field.rb +1 -1
  61. data/lib/capybara/selector/definition/file_field.rb +2 -2
  62. data/lib/capybara/selector/definition/fillable_field.rb +3 -3
  63. data/lib/capybara/selector/definition/label.rb +5 -3
  64. data/lib/capybara/selector/definition/link.rb +8 -0
  65. data/lib/capybara/selector/definition/radio_button.rb +3 -3
  66. data/lib/capybara/selector/definition/select.rb +33 -14
  67. data/lib/capybara/selector/definition/table.rb +6 -3
  68. data/lib/capybara/selector/definition/table_row.rb +2 -2
  69. data/lib/capybara/selector/definition.rb +15 -11
  70. data/lib/capybara/selector/filter_set.rb +17 -17
  71. data/lib/capybara/selector/filters/base.rb +6 -1
  72. data/lib/capybara/selector/filters/locator_filter.rb +1 -1
  73. data/lib/capybara/selector/selector.rb +17 -3
  74. data/lib/capybara/selector.rb +37 -19
  75. data/lib/capybara/selenium/atoms/getAttribute.min.js +1 -1
  76. data/lib/capybara/selenium/atoms/src/getAttribute.js +1 -1
  77. data/lib/capybara/selenium/atoms/src/isDisplayed.js +1 -1
  78. data/lib/capybara/selenium/driver.rb +84 -17
  79. data/lib/capybara/selenium/driver_specializations/chrome_driver.rb +11 -13
  80. data/lib/capybara/selenium/driver_specializations/edge_driver.rb +10 -12
  81. data/lib/capybara/selenium/driver_specializations/firefox_driver.rb +4 -4
  82. data/lib/capybara/selenium/extensions/find.rb +4 -4
  83. data/lib/capybara/selenium/extensions/html5_drag.rb +30 -13
  84. data/lib/capybara/selenium/extensions/scroll.rb +8 -10
  85. data/lib/capybara/selenium/logger_suppressor.rb +8 -2
  86. data/lib/capybara/selenium/node.rb +122 -26
  87. data/lib/capybara/selenium/nodes/chrome_node.rb +34 -19
  88. data/lib/capybara/selenium/nodes/edge_node.rb +5 -3
  89. data/lib/capybara/selenium/nodes/firefox_node.rb +11 -6
  90. data/lib/capybara/selenium/nodes/safari_node.rb +3 -3
  91. data/lib/capybara/selenium/patches/action_pauser.rb +26 -0
  92. data/lib/capybara/selenium/patches/atoms.rb +4 -4
  93. data/lib/capybara/selenium/patches/logs.rb +7 -9
  94. data/lib/capybara/server/animation_disabler.rb +38 -15
  95. data/lib/capybara/server/checker.rb +1 -1
  96. data/lib/capybara/server/middleware.rb +22 -10
  97. data/lib/capybara/server.rb +15 -3
  98. data/lib/capybara/session/config.rb +10 -4
  99. data/lib/capybara/session/matchers.rb +11 -11
  100. data/lib/capybara/session.rb +62 -39
  101. data/lib/capybara/spec/public/test.js +75 -7
  102. data/lib/capybara/spec/session/accept_alert_spec.rb +1 -1
  103. data/lib/capybara/spec/session/active_element_spec.rb +31 -0
  104. data/lib/capybara/spec/session/all_spec.rb +63 -12
  105. data/lib/capybara/spec/session/ancestor_spec.rb +5 -0
  106. data/lib/capybara/spec/session/assert_text_spec.rb +26 -22
  107. data/lib/capybara/spec/session/check_spec.rb +15 -0
  108. data/lib/capybara/spec/session/choose_spec.rb +6 -0
  109. data/lib/capybara/spec/session/click_button_spec.rb +16 -0
  110. data/lib/capybara/spec/session/click_link_or_button_spec.rb +9 -0
  111. data/lib/capybara/spec/session/current_url_spec.rb +11 -1
  112. data/lib/capybara/spec/session/fill_in_spec.rb +29 -0
  113. data/lib/capybara/spec/session/find_spec.rb +37 -8
  114. data/lib/capybara/spec/session/has_any_selectors_spec.rb +4 -0
  115. data/lib/capybara/spec/session/has_button_spec.rb +75 -0
  116. data/lib/capybara/spec/session/has_css_spec.rb +14 -10
  117. data/lib/capybara/spec/session/has_current_path_spec.rb +17 -4
  118. data/lib/capybara/spec/session/has_field_spec.rb +41 -1
  119. data/lib/capybara/spec/session/has_link_spec.rb +30 -0
  120. data/lib/capybara/spec/session/has_select_spec.rb +36 -8
  121. data/lib/capybara/spec/session/has_selector_spec.rb +19 -4
  122. data/lib/capybara/spec/session/has_table_spec.rb +51 -5
  123. data/lib/capybara/spec/session/has_text_spec.rb +21 -1
  124. data/lib/capybara/spec/session/html_spec.rb +1 -1
  125. data/lib/capybara/spec/session/matches_style_spec.rb +2 -2
  126. data/lib/capybara/spec/session/node_spec.rb +226 -33
  127. data/lib/capybara/spec/session/refresh_spec.rb +2 -1
  128. data/lib/capybara/spec/session/save_and_open_screenshot_spec.rb +2 -2
  129. data/lib/capybara/spec/session/save_page_spec.rb +4 -4
  130. data/lib/capybara/spec/session/save_screenshot_spec.rb +4 -4
  131. data/lib/capybara/spec/session/scroll_spec.rb +4 -4
  132. data/lib/capybara/spec/session/selectors_spec.rb +15 -2
  133. data/lib/capybara/spec/session/visit_spec.rb +20 -0
  134. data/lib/capybara/spec/session/window/switch_to_window_spec.rb +1 -1
  135. data/lib/capybara/spec/session/window/window_opened_by_spec.rb +1 -1
  136. data/lib/capybara/spec/session/window/window_spec.rb +9 -9
  137. data/lib/capybara/spec/session/window/windows_spec.rb +1 -1
  138. data/lib/capybara/spec/spec_helper.rb +17 -17
  139. data/lib/capybara/spec/test_app.rb +89 -29
  140. data/lib/capybara/spec/views/animated.erb +1 -1
  141. data/lib/capybara/spec/views/form.erb +52 -6
  142. data/lib/capybara/spec/views/frame_child.erb +1 -1
  143. data/lib/capybara/spec/views/frame_one.erb +1 -1
  144. data/lib/capybara/spec/views/frame_parent.erb +1 -1
  145. data/lib/capybara/spec/views/frame_two.erb +1 -1
  146. data/lib/capybara/spec/views/initial_alert.erb +2 -1
  147. data/lib/capybara/spec/views/layout.erb +10 -0
  148. data/lib/capybara/spec/views/obscured.erb +1 -1
  149. data/lib/capybara/spec/views/offset.erb +2 -1
  150. data/lib/capybara/spec/views/path.erb +2 -2
  151. data/lib/capybara/spec/views/popup_one.erb +1 -1
  152. data/lib/capybara/spec/views/popup_two.erb +1 -1
  153. data/lib/capybara/spec/views/react.erb +2 -2
  154. data/lib/capybara/spec/views/scroll.erb +2 -1
  155. data/lib/capybara/spec/views/spatial.erb +1 -1
  156. data/lib/capybara/spec/views/with_animation.erb +10 -3
  157. data/lib/capybara/spec/views/with_base_tag.erb +2 -2
  158. data/lib/capybara/spec/views/with_dragula.erb +5 -3
  159. data/lib/capybara/spec/views/with_fixed_header_footer.erb +2 -1
  160. data/lib/capybara/spec/views/with_hover.erb +2 -2
  161. data/lib/capybara/spec/views/with_html.erb +3 -3
  162. data/lib/capybara/spec/views/with_jquery_animation.erb +24 -0
  163. data/lib/capybara/spec/views/with_js.erb +5 -3
  164. data/lib/capybara/spec/views/with_jstree.erb +1 -1
  165. data/lib/capybara/spec/views/with_namespace.erb +1 -0
  166. data/lib/capybara/spec/views/with_shadow.erb +31 -0
  167. data/lib/capybara/spec/views/with_slow_unload.erb +2 -1
  168. data/lib/capybara/spec/views/with_sortable_js.erb +3 -3
  169. data/lib/capybara/spec/views/with_unload_alert.erb +1 -0
  170. data/lib/capybara/spec/views/with_windows.erb +1 -1
  171. data/lib/capybara/spec/views/within_frames.erb +1 -1
  172. data/lib/capybara/version.rb +1 -1
  173. data/lib/capybara/window.rb +4 -8
  174. data/lib/capybara.rb +36 -29
  175. data/spec/basic_node_spec.rb +25 -11
  176. data/spec/capybara_spec.rb +1 -1
  177. data/spec/dsl_spec.rb +18 -5
  178. data/spec/fixtures/selenium_driver_rspec_failure.rb +2 -2
  179. data/spec/fixtures/selenium_driver_rspec_success.rb +3 -3
  180. data/spec/minitest_spec.rb +3 -2
  181. data/spec/minitest_spec_spec.rb +46 -46
  182. data/spec/rack_test_spec.rb +43 -11
  183. data/spec/regexp_dissassembler_spec.rb +40 -36
  184. data/spec/result_spec.rb +53 -45
  185. data/spec/rspec/features_spec.rb +7 -4
  186. data/spec/rspec/scenarios_spec.rb +5 -1
  187. data/spec/rspec/shared_spec_matchers.rb +68 -56
  188. data/spec/rspec_spec.rb +8 -4
  189. data/spec/sauce_spec_chrome.rb +3 -3
  190. data/spec/selector_spec.rb +19 -4
  191. data/spec/selenium_spec_chrome.rb +49 -26
  192. data/spec/selenium_spec_chrome_remote.rb +13 -6
  193. data/spec/selenium_spec_firefox.rb +29 -17
  194. data/spec/selenium_spec_firefox_remote.rb +2 -2
  195. data/spec/selenium_spec_ie.rb +3 -6
  196. data/spec/selenium_spec_safari.rb +31 -19
  197. data/spec/server_spec.rb +88 -35
  198. data/spec/session_spec.rb +1 -1
  199. data/spec/shared_selenium_node.rb +21 -7
  200. data/spec/shared_selenium_session.rb +123 -21
  201. data/spec/spec_helper.rb +2 -2
  202. metadata +80 -21
  203. data/lib/capybara/spec/session/source_spec.rb +0 -0
  204. data/lib/capybara/spec/views/with_title.erb +0 -5
@@ -14,28 +14,31 @@ browser_options.profile = Selenium::WebDriver::Firefox::Profile.new.tap do |prof
14
14
  profile['browser.download.dir'] = Capybara.save_path
15
15
  profile['browser.download.folderList'] = 2
16
16
  profile['browser.helperApps.neverAsk.saveToDisk'] = 'text/csv'
17
+ profile['browser.startup.homepage'] = 'about:blank' # workaround bug in Selenium 4 alpha4-7
18
+ profile['accessibility.tabfocus'] = 7 # make tab move over links too
17
19
  end
18
20
 
19
21
  Capybara.register_driver :selenium_firefox do |app|
20
22
  # ::Selenium::WebDriver.logger.level = "debug"
21
- Capybara::Selenium::Driver.new(
22
- app,
23
- browser: :firefox,
24
- options: browser_options,
25
- timeout: 31
23
+ version = Capybara::Selenium::Driver.load_selenium
24
+ options_key = Capybara::Selenium::Driver::CAPS_VERSION.satisfied_by?(version) ? :capabilities : :options
25
+ driver_options = { browser: :firefox, timeout: 31 }.tap do |opts|
26
+ opts[options_key] = browser_options
26
27
  # Get a trace level log from geckodriver
27
28
  # :driver_opts => { args: ['-vv'] }
28
- )
29
+ end
30
+
31
+ Capybara::Selenium::Driver.new(app, **driver_options)
29
32
  end
30
33
 
31
34
  Capybara.register_driver :selenium_firefox_not_clear_storage do |app|
32
- Capybara::Selenium::Driver.new(
33
- app,
34
- browser: :firefox,
35
- clear_local_storage: false,
36
- clear_session_storage: false,
37
- options: browser_options
38
- )
35
+ version = Capybara::Selenium::Driver.load_selenium
36
+ options_key = Capybara::Selenium::Driver::CAPS_VERSION.satisfied_by?(version) ? :capabilities : :options
37
+ driver_options = { browser: :firefox, clear_local_storage: false, clear_session_storage: false }.tap do |opts|
38
+ opts[options_key] = browser_options
39
+ end
40
+
41
+ Capybara::Selenium::Driver.new(app, **driver_options)
39
42
  end
40
43
 
41
44
  module TestSessions
@@ -49,7 +52,7 @@ Capybara::SpecHelper.log_selenium_driver_version(Selenium::WebDriver::Firefox) i
49
52
  Capybara::SpecHelper.run_specs TestSessions::SeleniumFirefox, 'selenium', capybara_skip: skipped_tests do |example|
50
53
  case example.metadata[:full_description]
51
54
  when 'Capybara::Session selenium node #click should allow multiple modifiers'
52
- pending "Firefox doesn't generate an event for shift+control+click" if firefox_gte?(62, @session) && !Gem.win_platform?
55
+ pending "Firefox on OSX doesn't generate an event for shift+control+click" if firefox_gte?(62, @session) && Selenium::WebDriver::Platform.mac?
53
56
  when /^Capybara::Session selenium node #double_click/
54
57
  pending "selenium-webdriver/geckodriver doesn't generate double click event" if firefox_lt?(59, @session)
55
58
  when 'Capybara::Session selenium #accept_prompt should accept the prompt with a blank response when there is a default'
@@ -57,13 +60,22 @@ Capybara::SpecHelper.run_specs TestSessions::SeleniumFirefox, 'selenium', capyba
57
60
  when 'Capybara::Session selenium #attach_file with multipart form should fire change once when uploading multiple files from empty'
58
61
  pending "FF < 62 doesn't support setting all files at once" if firefox_lt?(62, @session)
59
62
  when 'Capybara::Session selenium #accept_confirm should work with nested modals'
60
- skip 'Broken in 63 <= FF < 69 - https://bugzilla.mozilla.org/show_bug.cgi?id=1487358' if firefox_gte?(63, @session) && firefox_lt?(69, @session)
63
+ skip 'Broken in 63 <= FF < 69 - https://bugzilla.mozilla.org/show_bug.cgi?id=1487358' if firefox_gte?(63, @session) && firefox_lt?(69, @session)
64
+ skip 'Hangs in 69 <= FF < 71 - Dont know what issue for this - previous issue was closed as fixed but it is not' if firefox_gte?(69, @session) && firefox_lt?(71, @session)
65
+ skip 'Broken again intermittently in FF 71 - jus skip it'
61
66
  when 'Capybara::Session selenium #click_link can download a file'
62
67
  skip 'Need to figure out testing of file downloading on windows platform' if Gem.win_platform?
63
68
  when 'Capybara::Session selenium #reset_session! removes ALL cookies'
64
69
  pending "Geckodriver doesn't provide a way to remove cookies outside the current domain"
65
70
  when /drag_to.*HTML5/
66
71
  pending "Firefox < 62 doesn't support a DataTransfer constuctor" if firefox_lt?(62.0, @session)
72
+ when 'Capybara::Session selenium #accept_alert should handle the alert if the page changes',
73
+ 'Capybara::Session selenium #accept_alert with an asynchronous alert should accept the alert'
74
+ skip 'No clue what Firefox is doing here - works fine on MacOS locally'
75
+ when 'Capybara::Session selenium node #shadow_root should get the shadow root',
76
+ 'Capybara::Session selenium node #shadow_root should find elements inside the shadow dom using CSS',
77
+ 'Capybara::Session selenium node #shadow_root should find nested shadow roots'
78
+ pending "Firefox doesn't yet have W3C shadow root support"
67
79
  end
68
80
  end
69
81
 
@@ -95,7 +107,7 @@ RSpec.describe 'Capybara::Session with firefox' do # rubocop:disable RSpec/Multi
95
107
  end
96
108
 
97
109
  it 'should fill in a datetime input with a String' do
98
- # FF doesn't currently support datetime-local so this is really just a text input
110
+ pending 'Need to figure out what string format this will actually accept'
99
111
  session.fill_in('form_datetime', with: datetime.iso8601)
100
112
  session.click_button('awesome')
101
113
  expect(Time.parse(extract_results(session)['datetime'])).to eq datetime
@@ -181,7 +193,7 @@ RSpec.describe Capybara::Selenium::Driver do
181
193
  end
182
194
 
183
195
  RSpec.describe Capybara::Selenium::Node do
184
- context '#click' do
196
+ describe '#click' do
185
197
  it 'warns when attempting on a table row' do
186
198
  session = TestSessions::SeleniumFirefox
187
199
  session.visit('/tables')
@@ -21,8 +21,8 @@ def ensure_selenium_running!
21
21
  rescue StandardError
22
22
  if timer.expired?
23
23
  raise 'Selenium is not running. ' \
24
- "You can run a selenium server easily with: \n" \
25
- ' $ docker-compose up -d selenium_firefox'
24
+ "You can run a selenium server easily with: \n" \
25
+ ' $ docker-compose up -d selenium_firefox'
26
26
  else
27
27
  puts 'Waiting for Selenium docker instance...'
28
28
  sleep 1
@@ -71,13 +71,10 @@ Capybara::SpecHelper.run_specs TestSessions::SeleniumIE, 'selenium', capybara_sk
71
71
  pending "IE 11 doesn't support date input types"
72
72
  when /#click_link_or_button with :disabled option happily clicks on links which incorrectly have the disabled attribute$/
73
73
  skip 'IE 11 obeys non-standard disabled attribute on anchor tag'
74
- when /#right_click should allow modifiers$/
75
- skip "Windows can't :meta click because :meta triggers start menu"
76
- when /#click should allow modifiers$/
74
+ when /#click should allow modifiers$/, /#double_click should allow modifiers$/
77
75
  pending "Doesn't work with IE for some unknown reason$"
78
- when /#double_click should allow modifiers$/
79
76
  pending "Doesn't work with IE for some unknown reason$"
80
- when /#click should allow multiple modifiers$/
77
+ when /#click should allow multiple modifiers$/, /#right_click should allow modifiers$/
81
78
  skip "Windows can't :meta click because :meta triggers start menu"
82
79
  when /#double_click should allow multiple modifiers$/
83
80
  skip "Windows can't :alt double click due to being properties shortcut"
@@ -91,7 +88,7 @@ Capybara::SpecHelper.run_specs TestSessions::SeleniumIE, 'selenium', capybara_sk
91
88
  pending "Window 7 and 8.1 don't support 308 http status code"
92
89
  when /#scroll_to can scroll an element to the center of the viewport$/,
93
90
  /#scroll_to can scroll an element to the center of the scrolling element$/
94
- pending " IE doesn't support ScrollToOptions"
91
+ pending "IE doesn't support ScrollToOptions"
95
92
  when /#attach_file with multipart form should fire change once for each set of files uploaded$/,
96
93
  /#attach_file with multipart form should fire change once when uploading multiple files from empty$/,
97
94
  /#attach_file with multipart form should not break when using HTML5 multiple file input uploading multiple files$/
@@ -8,28 +8,40 @@ require 'rspec/shared_spec_matchers'
8
8
 
9
9
  SAFARI_DRIVER = :selenium_safari
10
10
 
11
- if ::Selenium::WebDriver::Service.respond_to? :driver_path=
12
- ::Selenium::WebDriver::Safari::Service
13
- else
14
- ::Selenium::WebDriver::Safari
15
- end.driver_path = '/Applications/Safari Technology Preview.app/Contents/MacOS/safaridriver'
11
+ # if ::Selenium::WebDriver::Service.respond_to? :driver_path=
12
+ # ::Selenium::WebDriver::Safari::Service
13
+ # else
14
+ # ::Selenium::WebDriver::Safari
15
+ # end.driver_path = '/Applications/Safari Technology Preview.app/Contents/MacOS/safaridriver'
16
16
 
17
17
  browser_options = ::Selenium::WebDriver::Safari::Options.new
18
18
  # browser_options.headless! if ENV['HEADLESS']
19
- # browser_options.add_option(:w3c, !!ENV['W3C'])
20
19
 
21
20
  Capybara.register_driver :selenium_safari do |app|
22
- Capybara::Selenium::Driver.new(app, browser: :safari, options: browser_options, timeout: 30).tap do |driver|
21
+ version = Capybara::Selenium::Driver.load_selenium
22
+ options_key = Capybara::Selenium::Driver::CAPS_VERSION.satisfied_by?(version) ? :capabilities : :options
23
+ driver_options = { browser: :safari, timeout: 30 }.tap do |opts|
24
+ opts[options_key] = browser_options
25
+ end
26
+
27
+ Capybara::Selenium::Driver.new(app, **driver_options).tap do |driver|
23
28
  # driver.browser.download_path = Capybara.save_path
24
29
  end
25
30
  end
26
31
 
27
32
  Capybara.register_driver :selenium_safari_not_clear_storage do |app|
28
- safari_options = {
33
+ version = Capybara::Selenium::Driver.load_selenium
34
+ options_key = Capybara::Selenium::Driver::CAPS_VERSION.satisfied_by?(version) ? :capabilities : :options
35
+ driver_options = {
29
36
  browser: :safari,
30
- options: browser_options
31
- }
32
- Capybara::Selenium::Driver.new(app, safari_options.merge(clear_local_storage: false, clear_session_storage: false))
37
+ clear_local_storage: false,
38
+ clear_session_storage: false,
39
+ timeout: 30
40
+ }.tap do |opts|
41
+ opts[options_key] = browser_options
42
+ end
43
+
44
+ Capybara::Selenium::Driver.new(app, **driver_options)
33
45
  end
34
46
 
35
47
  module TestSessions
@@ -65,16 +77,17 @@ Capybara::SpecHelper.run_specs TestSessions::Safari, SAFARI_DRIVER.to_s, capybar
65
77
  when 'Capybara::Session selenium_safari node #double_click should allow to adjust the offset',
66
78
  'Capybara::Session selenium_safari node #double_click should double click an element'
67
79
  pending "safardriver doesn't generate a double click event"
68
- when 'Capybara::Session selenium_safari node #click should allow multiple modifiers',
69
- /Capybara::Session selenium_safari node #(click|right_click|double_click) should allow modifiers/
70
- pending "safaridriver doesn't take key state into account when clicking"
71
- when 'Capybara::Session selenium_safari #fill_in on a pre-populated textfield with a reformatting onchange should trigger change when clearing field'
72
- pending "safardriver clear doesn't generate change event"
80
+ when 'Capybara::Session selenium_safari node #double_click should allow modifiers'
81
+ pending "safaridriver doesn't generate double click with key modifiers"
82
+ when /when w3c_click_offset is true should offset/
83
+ pending 'w3c_click_offset is not currently supported with safaridriver'
73
84
  when 'Capybara::Session selenium_safari #go_back should fetch a response from the driver from the previous page',
74
85
  'Capybara::Session selenium_safari #go_forward should fetch a response from the driver from the previous page'
75
86
  skip 'safaridriver loses the ability to find elements in the document after `go_back`'
76
- when /drag_to.*HTML5/
77
- pending "Safari doesn't support"
87
+ when 'Capybara::Session selenium node #shadow_root should get the shadow root',
88
+ 'Capybara::Session selenium node #shadow_root should find elements inside the shadow dom using CSS',
89
+ 'Capybara::Session selenium node #shadow_root should find nested shadow roots'
90
+ pending "Safari doesn't yet have W3C shadow root support"
78
91
  end
79
92
  end
80
93
 
@@ -124,7 +137,6 @@ RSpec.describe 'Capybara::Session with safari' do
124
137
  end
125
138
 
126
139
  it 'should fill in a date input with a String' do
127
- pending "Safari doesn't support date inputs"
128
140
  session.fill_in('form_date', with: '06/19/1983')
129
141
  session.click_button('awesome')
130
142
  expect(Date.parse(extract_results(session)['date'])).to eq datetime.to_date
data/spec/server_spec.rb CHANGED
@@ -20,7 +20,7 @@ RSpec.describe Capybara::Server do
20
20
 
21
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?
23
+ skip 'This platform has an issue with this test' if (ENV.fetch('TRAVIS', nil) && (RUBY_ENGINE == 'jruby')) || Gem.win_platform?
24
24
 
25
25
  begin
26
26
  app = proc { |_env| [200, {}, ['Hello Server!']] }
@@ -74,6 +74,24 @@ RSpec.describe Capybara::Server do
74
74
  end
75
75
  end
76
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
88
+
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
94
+
77
95
  it 'should return its #base_url' do
78
96
  app = proc { |_env| [200, {}, ['Hello Server!']] }
79
97
  server = described_class.new(app).boot
@@ -81,30 +99,47 @@ RSpec.describe Capybara::Server do
81
99
  expect(uri.to_hash).to include(scheme: 'http', host: server.host, port: server.port)
82
100
  end
83
101
 
84
- it 'should support SSL' do
85
- begin
86
- key = File.join(Dir.pwd, 'spec', 'fixtures', 'key.pem')
87
- cert = File.join(Dir.pwd, 'spec', 'fixtures', 'certificate.pem')
88
- Capybara.server = :puma, { Host: "ssl://#{Capybara.server_host}?key=#{key}&cert=#{cert}" }
89
- app = proc { |_env| [200, {}, ['Hello SSL Server!']] }
90
- server = described_class.new(app).boot
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
91
120
 
92
- expect do
93
- Net::HTTP.start(server.host, server.port, max_retries: 0) { |http| http.get('/__identify__') }
94
- end.to(raise_error do |e|
95
- expect(e.is_a?(EOFError) || e.is_a?(Net::ReadTimeout)).to be true
96
- end)
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
97
127
 
98
- res = Net::HTTP.start(server.host, server.port, use_ssl: true, verify_mode: OpenSSL::SSL::VERIFY_NONE) do |https|
99
- https.get('/')
100
- end
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)
101
133
 
102
- expect(res.body).to include('Hello SSL Server!')
103
- uri = ::Addressable::URI.parse(server.base_url)
104
- expect(uri.to_hash).to include(scheme: 'https', host: server.host, port: server.port)
105
- ensure
106
- Capybara.server = :default
134
+ res = Net::HTTP.start(server.host, server.port, use_ssl: true, verify_mode: OpenSSL::SSL::VERIFY_NONE) do |https|
135
+ https.get('/')
107
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
108
143
  end
109
144
 
110
145
  context 'When Capybara.reuse_server is true' do
@@ -149,7 +184,7 @@ RSpec.describe Capybara::Server do
149
184
  start_request(server2, 3.0)
150
185
  server1.wait_for_pending_requests
151
186
  end.to change { done }.from(0).to(2)
152
- expect(server2.send(:pending_requests?)).to eq(false)
187
+ expect(server2.send(:pending_requests?)).to be(false)
153
188
  end
154
189
  end
155
190
 
@@ -194,7 +229,7 @@ RSpec.describe Capybara::Server do
194
229
  start_request(server2, 3.0)
195
230
  server1.wait_for_pending_requests
196
231
  end.to change { done }.from(0).to(1)
197
- expect(server2.send(:pending_requests?)).to eq(true)
232
+ expect(server2.send(:pending_requests?)).to be(true)
198
233
  expect do
199
234
  server2.wait_for_pending_requests
200
235
  end.to change { done }.from(1).to(2)
@@ -202,26 +237,44 @@ RSpec.describe Capybara::Server do
202
237
  end
203
238
 
204
239
  it 'should raise server errors when the server errors before the timeout' do
205
- begin
206
- Capybara.register_server :kaboom do
207
- sleep 0.1
208
- raise 'kaboom'
209
- end
210
- Capybara.server = :kaboom
240
+ Capybara.register_server :kaboom do
241
+ sleep 0.1
242
+ raise 'kaboom'
243
+ end
244
+ Capybara.server = :kaboom
211
245
 
212
- expect do
213
- described_class.new(proc { |e| }).boot
214
- end.to raise_error(RuntimeError, 'kaboom')
215
- ensure
216
- 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!']]
217
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"]')
218
271
  end
219
272
 
220
273
  it 'is not #responsive? when Net::HTTP raises a SystemCallError' do
221
274
  app = -> { [200, {}, ['Hello, world']] }
222
275
  server = described_class.new(app)
223
276
  allow(Net::HTTP).to receive(:start).and_raise(SystemCallError.allocate)
224
- expect(server.responsive?).to eq false
277
+ expect(server.responsive?).to be false
225
278
  end
226
279
 
227
280
  [EOFError, Net::ReadTimeout].each do |err|
data/spec/session_spec.rb CHANGED
@@ -3,7 +3,7 @@
3
3
  require 'spec_helper'
4
4
 
5
5
  RSpec.describe Capybara::Session do
6
- context '#new' do
6
+ describe '#new' do
7
7
  it 'should raise an error if passed non-existent driver' do
8
8
  expect do
9
9
  described_class.new(:quox, TestApp).driver
@@ -6,7 +6,7 @@ require 'selenium-webdriver'
6
6
  RSpec.shared_examples 'Capybara::Node' do |session, _mode|
7
7
  let(:session) { session }
8
8
 
9
- context '#content_editable?' do
9
+ describe '#content_editable?' do
10
10
  it 'returns true when the element is content editable' do
11
11
  session.visit('/with_js')
12
12
  expect(session.find(:css, '#existing_content_editable').base.content_editable?).to be true
@@ -19,7 +19,7 @@ RSpec.shared_examples 'Capybara::Node' do |session, _mode|
19
19
  end
20
20
  end
21
21
 
22
- context '#send_keys' do
22
+ describe '#send_keys' do
23
23
  it 'should process space' do
24
24
  session.visit('/form')
25
25
  session.find(:css, '#address1_city').send_keys('ocean', [:shift, :space, 'side'])
@@ -27,7 +27,25 @@ RSpec.shared_examples 'Capybara::Node' do |session, _mode|
27
27
  end
28
28
  end
29
29
 
30
- context '#visible?' do
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
31
49
  let(:bridge) do
32
50
  session.driver.browser.send(:bridge)
33
51
  end
@@ -43,8 +61,6 @@ RSpec.shared_examples 'Capybara::Node' do |session, _mode|
43
61
  end
44
62
 
45
63
  it 'will use native displayed if told to' do
46
- pending "Chromedriver < 76.0.3809.25 doesn't support native displayed in W3C mode" if chrome_lt?(76, session) && (ENV['W3C'] != 'false')
47
-
48
64
  session.driver.options[:native_displayed] = true
49
65
  session.visit('/form')
50
66
  session.find(:css, '#address1_city', visible: true)
@@ -53,8 +69,6 @@ RSpec.shared_examples 'Capybara::Node' do |session, _mode|
53
69
  end
54
70
 
55
71
  it "won't use native displayed if told not to" do
56
- skip 'Non-W3C uses native' if chrome?(session) && (ENV['W3C'] == 'false')
57
-
58
72
  session.driver.options[:native_displayed] = false
59
73
  session.visit('/form')
60
74
  session.find(:css, '#address1_city', visible: true)