capybara 2.18.0 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (172) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +55 -1
  3. data/README.md +18 -17
  4. data/lib/capybara/config.rb +11 -58
  5. data/lib/capybara/cucumber.rb +2 -3
  6. data/lib/capybara/driver/base.rb +15 -16
  7. data/lib/capybara/driver/node.rb +5 -4
  8. data/lib/capybara/dsl.rb +1 -0
  9. data/lib/capybara/helpers.rb +19 -29
  10. data/lib/capybara/minitest/spec.rb +15 -14
  11. data/lib/capybara/minitest.rb +139 -138
  12. data/lib/capybara/node/actions.rb +60 -81
  13. data/lib/capybara/node/base.rb +11 -18
  14. data/lib/capybara/node/document.rb +2 -2
  15. data/lib/capybara/node/document_matchers.rb +8 -8
  16. data/lib/capybara/node/element.rb +30 -40
  17. data/lib/capybara/node/finders.rb +62 -70
  18. data/lib/capybara/node/matchers.rb +50 -71
  19. data/lib/capybara/node/simple.rb +11 -17
  20. data/lib/capybara/queries/ancestor_query.rb +11 -7
  21. data/lib/capybara/queries/base_query.rb +22 -18
  22. data/lib/capybara/queries/current_path_query.rb +8 -24
  23. data/lib/capybara/queries/match_query.rb +3 -7
  24. data/lib/capybara/queries/selector_query.rb +92 -95
  25. data/lib/capybara/queries/sibling_query.rb +4 -4
  26. data/lib/capybara/queries/text_query.rb +35 -35
  27. data/lib/capybara/queries/title_query.rb +8 -11
  28. data/lib/capybara/rack_test/browser.rb +15 -18
  29. data/lib/capybara/rack_test/css_handlers.rb +6 -4
  30. data/lib/capybara/rack_test/driver.rb +6 -10
  31. data/lib/capybara/rack_test/form.rb +50 -40
  32. data/lib/capybara/rack_test/node.rb +93 -63
  33. data/lib/capybara/rails.rb +2 -6
  34. data/lib/capybara/result.rb +22 -22
  35. data/lib/capybara/rspec/compound.rb +5 -10
  36. data/lib/capybara/rspec/features.rb +17 -48
  37. data/lib/capybara/rspec/matcher_proxies.rb +31 -15
  38. data/lib/capybara/rspec/matchers.rb +70 -61
  39. data/lib/capybara/rspec.rb +5 -10
  40. data/lib/capybara/selector/css.rb +6 -11
  41. data/lib/capybara/selector/filter.rb +1 -17
  42. data/lib/capybara/selector/filter_set.rb +18 -15
  43. data/lib/capybara/selector/filters/base.rb +7 -6
  44. data/lib/capybara/selector/filters/expression_filter.rb +6 -23
  45. data/lib/capybara/selector/filters/node_filter.rb +2 -12
  46. data/lib/capybara/selector/selector.rb +28 -34
  47. data/lib/capybara/selector.rb +129 -117
  48. data/lib/capybara/selenium/driver.rb +131 -125
  49. data/lib/capybara/selenium/node.rb +197 -115
  50. data/lib/capybara/server.rb +3 -2
  51. data/lib/capybara/session/config.rb +47 -67
  52. data/lib/capybara/session/matchers.rb +8 -7
  53. data/lib/capybara/session.rb +138 -224
  54. data/lib/capybara/spec/public/test.js +25 -4
  55. data/lib/capybara/spec/session/accept_alert_spec.rb +1 -0
  56. data/lib/capybara/spec/session/accept_confirm_spec.rb +3 -2
  57. data/lib/capybara/spec/session/accept_prompt_spec.rb +1 -0
  58. data/lib/capybara/spec/session/all_spec.rb +31 -18
  59. data/lib/capybara/spec/session/ancestor_spec.rb +6 -8
  60. data/lib/capybara/spec/session/assert_all_of_selectors_spec.rb +6 -5
  61. data/lib/capybara/spec/session/assert_current_path.rb +12 -11
  62. data/lib/capybara/spec/session/assert_selector.rb +1 -0
  63. data/lib/capybara/spec/session/assert_text.rb +23 -23
  64. data/lib/capybara/spec/session/assert_title.rb +13 -3
  65. data/lib/capybara/spec/session/attach_file_spec.rb +51 -30
  66. data/lib/capybara/spec/session/body_spec.rb +1 -0
  67. data/lib/capybara/spec/session/check_spec.rb +7 -6
  68. data/lib/capybara/spec/session/choose_spec.rb +5 -4
  69. data/lib/capybara/spec/session/click_button_spec.rb +24 -32
  70. data/lib/capybara/spec/session/click_link_or_button_spec.rb +8 -7
  71. data/lib/capybara/spec/session/click_link_spec.rb +8 -7
  72. data/lib/capybara/spec/session/current_scope_spec.rb +4 -3
  73. data/lib/capybara/spec/session/current_url_spec.rb +17 -6
  74. data/lib/capybara/spec/session/dismiss_confirm_spec.rb +1 -1
  75. data/lib/capybara/spec/session/dismiss_prompt_spec.rb +1 -0
  76. data/lib/capybara/spec/session/element/assert_match_selector.rb +1 -1
  77. data/lib/capybara/spec/session/element/match_xpath_spec.rb +1 -1
  78. data/lib/capybara/spec/session/element/matches_selector_spec.rb +5 -5
  79. data/lib/capybara/spec/session/evaluate_async_script_spec.rb +3 -2
  80. data/lib/capybara/spec/session/evaluate_script_spec.rb +4 -3
  81. data/lib/capybara/spec/session/execute_script_spec.rb +4 -3
  82. data/lib/capybara/spec/session/fill_in_spec.rb +30 -5
  83. data/lib/capybara/spec/session/find_button_spec.rb +4 -3
  84. data/lib/capybara/spec/session/find_by_id_spec.rb +2 -1
  85. data/lib/capybara/spec/session/find_field_spec.rb +9 -15
  86. data/lib/capybara/spec/session/find_link_spec.rb +6 -5
  87. data/lib/capybara/spec/session/find_spec.rb +37 -31
  88. data/lib/capybara/spec/session/first_spec.rb +60 -33
  89. data/lib/capybara/spec/session/frame/frame_title_spec.rb +23 -0
  90. data/lib/capybara/spec/session/frame/frame_url_spec.rb +23 -0
  91. data/lib/capybara/spec/session/frame/switch_to_frame_spec.rb +2 -1
  92. data/lib/capybara/spec/session/frame/within_frame_spec.rb +9 -16
  93. data/lib/capybara/spec/session/go_back_spec.rb +1 -0
  94. data/lib/capybara/spec/session/go_forward_spec.rb +1 -0
  95. data/lib/capybara/spec/session/has_all_selectors_spec.rb +15 -15
  96. data/lib/capybara/spec/session/has_button_spec.rb +2 -1
  97. data/lib/capybara/spec/session/has_css_spec.rb +3 -2
  98. data/lib/capybara/spec/session/has_current_path_spec.rb +12 -28
  99. data/lib/capybara/spec/session/has_field_spec.rb +4 -3
  100. data/lib/capybara/spec/session/has_link_spec.rb +1 -0
  101. data/lib/capybara/spec/session/has_none_selectors_spec.rb +17 -17
  102. data/lib/capybara/spec/session/has_select_spec.rb +30 -29
  103. data/lib/capybara/spec/session/has_selector_spec.rb +5 -4
  104. data/lib/capybara/spec/session/has_table_spec.rb +2 -1
  105. data/lib/capybara/spec/session/has_text_spec.rb +9 -13
  106. data/lib/capybara/spec/session/has_title_spec.rb +1 -0
  107. data/lib/capybara/spec/session/has_xpath_spec.rb +1 -0
  108. data/lib/capybara/spec/session/headers.rb +2 -1
  109. data/lib/capybara/spec/session/html_spec.rb +1 -0
  110. data/lib/capybara/spec/session/node_spec.rb +91 -56
  111. data/lib/capybara/spec/session/node_wrapper_spec.rb +36 -0
  112. data/lib/capybara/spec/session/refresh_spec.rb +6 -2
  113. data/lib/capybara/spec/session/reset_session_spec.rb +19 -0
  114. data/lib/capybara/spec/session/response_code.rb +1 -0
  115. data/lib/capybara/spec/session/save_and_open_page_spec.rb +1 -0
  116. data/lib/capybara/spec/session/save_and_open_screenshot_spec.rb +6 -11
  117. data/lib/capybara/spec/session/save_page_spec.rb +1 -17
  118. data/lib/capybara/spec/session/save_screenshot_spec.rb +3 -3
  119. data/lib/capybara/spec/session/select_spec.rb +20 -20
  120. data/lib/capybara/spec/session/selectors_spec.rb +2 -2
  121. data/lib/capybara/spec/session/sibling_spec.rb +1 -1
  122. data/lib/capybara/spec/session/text_spec.rb +17 -3
  123. data/lib/capybara/spec/session/title_spec.rb +11 -1
  124. data/lib/capybara/spec/session/uncheck_spec.rb +4 -3
  125. data/lib/capybara/spec/session/unselect_spec.rb +6 -5
  126. data/lib/capybara/spec/session/visit_spec.rb +9 -3
  127. data/lib/capybara/spec/session/window/become_closed_spec.rb +2 -1
  128. data/lib/capybara/spec/session/window/current_window_spec.rb +1 -0
  129. data/lib/capybara/spec/session/window/open_new_window_spec.rb +1 -0
  130. data/lib/capybara/spec/session/window/switch_to_window_spec.rb +2 -1
  131. data/lib/capybara/spec/session/window/window_opened_by_spec.rb +2 -1
  132. data/lib/capybara/spec/session/window/window_spec.rb +12 -12
  133. data/lib/capybara/spec/session/window/windows_spec.rb +2 -3
  134. data/lib/capybara/spec/session/window/within_window_spec.rb +15 -71
  135. data/lib/capybara/spec/session/within_spec.rb +1 -0
  136. data/lib/capybara/spec/spec_helper.rb +34 -18
  137. data/lib/capybara/spec/test_app.rb +17 -9
  138. data/lib/capybara/spec/views/form.erb +7 -0
  139. data/lib/capybara/spec/views/with_html.erb +23 -1
  140. data/lib/capybara/spec/views/within_frames.erb +4 -1
  141. data/lib/capybara/version.rb +2 -1
  142. data/lib/capybara/window.rb +6 -10
  143. data/lib/capybara.rb +28 -25
  144. data/spec/basic_node_spec.rb +1 -0
  145. data/spec/capybara_spec.rb +11 -50
  146. data/spec/dsl_spec.rb +5 -13
  147. data/spec/filter_set_spec.rb +5 -4
  148. data/spec/fixtures/selenium_driver_rspec_failure.rb +2 -1
  149. data/spec/fixtures/selenium_driver_rspec_success.rb +3 -2
  150. data/spec/minitest_spec.rb +4 -3
  151. data/spec/minitest_spec_spec.rb +3 -2
  152. data/spec/per_session_config_spec.rb +9 -8
  153. data/spec/rack_test_spec.rb +21 -20
  154. data/spec/result_spec.rb +17 -16
  155. data/spec/rspec/features_spec.rb +17 -14
  156. data/spec/rspec/scenarios_spec.rb +5 -7
  157. data/spec/rspec/shared_spec_matchers.rb +96 -99
  158. data/spec/rspec/views_spec.rb +2 -1
  159. data/spec/rspec_matchers_spec.rb +18 -2
  160. data/spec/rspec_spec.rb +11 -15
  161. data/spec/selector_spec.rb +5 -6
  162. data/spec/selenium_spec_chrome.rb +9 -4
  163. data/spec/selenium_spec_edge.rb +27 -0
  164. data/spec/selenium_spec_ie.rb +31 -0
  165. data/spec/selenium_spec_marionette.rb +28 -12
  166. data/spec/server_spec.rb +33 -33
  167. data/spec/session_spec.rb +2 -1
  168. data/spec/shared_selenium_session.rb +36 -22
  169. data/spec/spec_helper.rb +3 -6
  170. metadata +68 -85
  171. data/lib/capybara/query.rb +0 -7
  172. data/spec/selenium_spec_firefox.rb +0 -68
@@ -1,14 +1,15 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require "uri"
4
+ require "English"
3
5
 
4
6
  class Capybara::Selenium::Driver < Capybara::Driver::Base
5
-
6
7
  DEFAULT_OPTIONS = {
7
- :browser => :firefox,
8
+ browser: :firefox,
8
9
  clear_local_storage: false,
9
10
  clear_session_storage: false
10
- }
11
- SPECIAL_OPTIONS = [:browser, :clear_local_storage, :clear_session_storage]
11
+ }.freeze
12
+ SPECIAL_OPTIONS = %i[browser clear_local_storage clear_session_storage].freeze
12
13
 
13
14
  attr_reader :app, :options
14
15
 
@@ -16,18 +17,19 @@ class Capybara::Selenium::Driver < Capybara::Driver::Base
16
17
  unless @browser
17
18
  if firefox?
18
19
  options[:desired_capabilities] ||= {}
19
- options[:desired_capabilities].merge!({ unexpectedAlertBehaviour: "ignore" })
20
+ options[:desired_capabilities][:unexpectedAlertBehaviour] = "ignore"
20
21
  end
21
22
 
22
- @processed_options = options.reject { |key,_val| SPECIAL_OPTIONS.include?(key) }
23
+ @processed_options = options.reject { |key, _val| SPECIAL_OPTIONS.include?(key) }
23
24
  @browser = Selenium::WebDriver.for(options[:browser], @processed_options)
24
25
 
25
26
  @w3c = ((defined?(Selenium::WebDriver::Remote::W3CCapabilities) && @browser.capabilities.is_a?(Selenium::WebDriver::Remote::W3CCapabilities)) ||
26
27
  (defined?(Selenium::WebDriver::Remote::W3C::Capabilities) && @browser.capabilities.is_a?(Selenium::WebDriver::Remote::W3C::Capabilities)))
27
28
  main = Process.pid
29
+
28
30
  at_exit do
29
31
  # Store the exit status of the test run since it goes away after calling the at_exit proc...
30
- @exit_status = $!.status if $!.is_a?(SystemExit)
32
+ @exit_status = $ERROR_INFO.status if $ERROR_INFO.is_a?(SystemExit)
31
33
  quit if Process.pid == main
32
34
  exit @exit_status if @exit_status # Force exit with stored status
33
35
  end
@@ -35,7 +37,7 @@ class Capybara::Selenium::Driver < Capybara::Driver::Base
35
37
  @browser
36
38
  end
37
39
 
38
- def initialize(app, options={})
40
+ def initialize(app, **options)
39
41
  load_selenium
40
42
  @session = nil
41
43
  @app = app
@@ -50,10 +52,7 @@ class Capybara::Selenium::Driver < Capybara::Driver::Base
50
52
  end
51
53
 
52
54
  def refresh
53
- accept_modal(nil, wait: 0.1) do
54
- browser.navigate.refresh
55
- end
56
- rescue Capybara::ModalNotFound
55
+ browser.navigate.refresh
57
56
  end
58
57
 
59
58
  def go_back
@@ -88,7 +87,7 @@ class Capybara::Selenium::Driver < Capybara::Driver::Base
88
87
  def needs_server?; true; end
89
88
 
90
89
  def execute_script(script, *args)
91
- browser.execute_script(script, *args.map { |arg| arg.is_a?(Capybara::Selenium::Node) ? arg.native : arg} )
90
+ browser.execute_script(script, *args.map { |arg| arg.is_a?(Capybara::Selenium::Node) ? arg.native : arg })
92
91
  end
93
92
 
94
93
  def evaluate_script(script, *args)
@@ -98,66 +97,69 @@ class Capybara::Selenium::Driver < Capybara::Driver::Base
98
97
 
99
98
  def evaluate_async_script(script, *args)
100
99
  browser.manage.timeouts.script_timeout = Capybara.default_max_wait_time
101
- result = browser.execute_async_script(script, *args.map { |arg| arg.is_a?(Capybara::Selenium::Node) ? arg.native : arg} )
100
+ result = browser.execute_async_script(script, *args.map { |arg| arg.is_a?(Capybara::Selenium::Node) ? arg.native : arg })
102
101
  unwrap_script_result(result)
103
102
  end
104
103
 
105
- def save_screenshot(path, _options={})
104
+ def save_screenshot(path, **_options)
106
105
  browser.save_screenshot(path)
107
106
  end
108
107
 
109
108
  def reset!
110
109
  # Use instance variable directly so we avoid starting the browser just to reset the session
111
- if @browser
112
- navigated = false
113
- start_time = Capybara::Helpers.monotonic_time
110
+ return unless @browser
111
+
112
+ if firefox? || chrome?
113
+ switch_to_window(window_handles.first)
114
+ window_handles.slice(1..-1).each { |win| close_window(win) }
115
+ end
116
+
117
+ navigated = false
118
+ start_time = Capybara::Helpers.monotonic_time
119
+ begin
120
+ unless navigated
121
+ # Only trigger a navigation if we haven't done it already, otherwise it
122
+ # can trigger an endless series of unload modals
123
+ begin
124
+ @browser.manage.delete_all_cookies
125
+ clear_storage
126
+ rescue Selenium::WebDriver::Error::UnhandledError
127
+ # delete_all_cookies fails when we've previously gone
128
+ # to about:blank, so we rescue this error and do nothing
129
+ # instead.
130
+ end
131
+ @browser.navigate.to("about:blank")
132
+ end
133
+ navigated = true
134
+
135
+ # Ensure the page is empty and trigger an UnhandledAlertError for any modals that appear during unload
136
+ until find_xpath("/html/body/*").empty?
137
+ raise Capybara::ExpectationNotMet, 'Timed out waiting for Selenium session reset' if (Capybara::Helpers.monotonic_time - start_time) >= 10
138
+ sleep 0.05
139
+ end
140
+ rescue Selenium::WebDriver::Error::UnhandledAlertError, Selenium::WebDriver::Error::UnexpectedAlertOpenError
141
+ # This error is thrown if an unhandled alert is on the page
142
+ # Firefox appears to automatically dismiss this alert, chrome does not
143
+ # We'll try to accept it
114
144
  begin
115
- if !navigated
116
- # Only trigger a navigation if we haven't done it already, otherwise it
117
- # can trigger an endless series of unload modals
145
+ @browser.switch_to.alert.accept
146
+ sleep 0.25 # allow time for the modal to be handled
147
+ rescue modal_error
148
+ # The alert is now gone
149
+ if current_url != "about:blank"
118
150
  begin
119
- @browser.manage.delete_all_cookies
120
- if options[:clear_session_storage]
121
- if @browser.respond_to? :session_storage
122
- @browser.session_storage.clear
123
- else
124
- warn "sessionStorage clear requested but is not available for this driver"
125
- end
126
- end
127
- if options[:clear_local_storage]
128
- if @browser.respond_to? :local_storage
129
- @browser.local_storage.clear
130
- else
131
- warn "localStorage clear requested but is not available for this driver"
132
- end
133
- end
134
- rescue Selenium::WebDriver::Error::UnhandledError
135
- # delete_all_cookies fails when we've previously gone
136
- # to about:blank, so we rescue this error and do nothing
137
- # instead.
151
+ # If navigation has not occurred attempt again and accept alert
152
+ # since FF may have dismissed the alert at first attempt
153
+ @browser.navigate.to("about:blank")
154
+ sleep 0.1 # slight wait for alert
155
+ @browser.switch_to.alert.accept
156
+ rescue modal_error # rubocop:disable Metrics/BlockNesting
157
+ # alert now gone, should mean navigation happened
138
158
  end
139
- @browser.navigate.to("about:blank")
140
- end
141
- navigated = true
142
-
143
- #Ensure the page is empty and trigger an UnhandledAlertError for any modals that appear during unload
144
- until find_xpath("/html/body/*").empty? do
145
- raise Capybara::ExpectationNotMet.new('Timed out waiting for Selenium session reset') if (Capybara::Helpers.monotonic_time - start_time) >= 10
146
- sleep 0.05
147
159
  end
148
- rescue Selenium::WebDriver::Error::UnhandledAlertError, Selenium::WebDriver::Error::UnexpectedAlertOpenError
149
- # This error is thrown if an unhandled alert is on the page
150
- # Firefox appears to automatically dismiss this alert, chrome does not
151
- # We'll try to accept it
152
- begin
153
- @browser.switch_to.alert.accept
154
- sleep 0.25 # allow time for the modal to be handled
155
- rescue modal_error
156
- # The alert is now gone - nothing to do
157
- end
158
- # try cleaning up the browser again
159
- retry
160
160
  end
161
+ # try cleaning up the browser again
162
+ retry
161
163
  end
162
164
  end
163
165
 
@@ -209,6 +211,7 @@ class Capybara::Selenium::Driver < Capybara::Driver::Base
209
211
  end
210
212
 
211
213
  def close_window(handle)
214
+ raise ArgumentError, "Not allowed to close the primary window" if handle == window_handles.first
212
215
  within_given_window(handle) do
213
216
  browser.close
214
217
  end
@@ -226,12 +229,7 @@ class Capybara::Selenium::Driver < Capybara::Driver::Base
226
229
  browser.switch_to.window handle
227
230
  end
228
231
 
229
- def within_window(locator)
230
- handle = find_window(locator)
231
- browser.switch_to.window(handle) { yield }
232
- end
233
-
234
- def accept_modal(_type, options={})
232
+ def accept_modal(_type, **options)
235
233
  yield if block_given?
236
234
  modal = find_modal(options)
237
235
 
@@ -242,7 +240,7 @@ class Capybara::Selenium::Driver < Capybara::Driver::Base
242
240
  message
243
241
  end
244
242
 
245
- def dismiss_modal(_type, options={})
243
+ def dismiss_modal(_type, **options)
246
244
  yield if block_given?
247
245
  modal = find_modal(options)
248
246
  message = modal.text
@@ -264,14 +262,18 @@ class Capybara::Selenium::Driver < Capybara::Driver::Base
264
262
  end
265
263
 
266
264
  def invalid_element_errors
267
- [::Selenium::WebDriver::Error::StaleElementReferenceError,
268
- ::Selenium::WebDriver::Error::UnhandledError,
269
- ::Selenium::WebDriver::Error::ElementNotVisibleError,
270
- ::Selenium::WebDriver::Error::InvalidSelectorError, # Work around a race condition that can occur with chromedriver and #go_back/#go_forward
271
- ::Selenium::WebDriver::Error::ElementNotInteractableError,
272
- ::Selenium::WebDriver::Error::ElementClickInterceptedError,
273
- ::Selenium::WebDriver::Error::InvalidElementStateError,
274
- ::Selenium::WebDriver::Error::ElementNotSelectableError,
265
+ [
266
+ ::Selenium::WebDriver::Error::StaleElementReferenceError,
267
+ ::Selenium::WebDriver::Error::UnhandledError,
268
+ ::Selenium::WebDriver::Error::ElementNotVisibleError,
269
+ ::Selenium::WebDriver::Error::InvalidSelectorError, # Work around a race condition that can occur with chromedriver and #go_back/#go_forward
270
+ ::Selenium::WebDriver::Error::ElementNotInteractableError,
271
+ ::Selenium::WebDriver::Error::ElementClickInterceptedError,
272
+ ::Selenium::WebDriver::Error::InvalidElementStateError,
273
+ ::Selenium::WebDriver::Error::ElementNotSelectableError,
274
+ ::Selenium::WebDriver::Error::ElementNotSelectableError,
275
+ ::Selenium::WebDriver::Error::NoSuchElementError, # IE
276
+ ::Selenium::WebDriver::Error::InvalidArgumentError # IE
275
277
  ]
276
278
  end
277
279
 
@@ -294,18 +296,39 @@ class Capybara::Selenium::Driver < Capybara::Driver::Base
294
296
  browser_name == "chrome"
295
297
  end
296
298
 
297
- # @deprecated This method is being removed
298
- def browser_initialized?
299
- super && !@browser.nil?
299
+ # @api private
300
+ def edge?
301
+ browser_name == "edge"
300
302
  end
301
303
 
302
- private
303
-
304
304
  # @api private
305
+ def ie?
306
+ browser_name == "ie"
307
+ end
308
+
309
+ private
310
+
305
311
  def browser_name
306
312
  options[:browser].to_s
307
313
  end
308
314
 
315
+ def clear_storage
316
+ if options[:clear_session_storage]
317
+ if @browser.respond_to? :session_storage
318
+ @browser.session_storage.clear
319
+ else
320
+ warn "sessionStorage clear requested but is not available for this driver"
321
+ end
322
+ end
323
+ if options[:clear_local_storage]
324
+ if @browser.respond_to? :local_storage
325
+ @browser.local_storage.clear
326
+ else
327
+ warn "localStorage clear requested but is not available for this driver"
328
+ end
329
+ end
330
+ end
331
+
309
332
  def modal_error
310
333
  if defined?(Selenium::WebDriver::Error::NoSuchAlertError)
311
334
  Selenium::WebDriver::Error::NoSuchAlertError
@@ -314,23 +337,6 @@ class Capybara::Selenium::Driver < Capybara::Driver::Base
314
337
  end
315
338
  end
316
339
 
317
- def find_window(locator)
318
- handles = browser.window_handles
319
- return locator if handles.include? locator
320
-
321
- original_handle = browser.window_handle
322
- handles.each do |handle|
323
- switch_to_window(handle)
324
- if (locator == browser.execute_script("return window.name") ||
325
- browser.title.include?(locator) ||
326
- browser.current_url.include?(locator))
327
- switch_to_window(original_handle)
328
- return handle
329
- end
330
- end
331
- raise Capybara::ElementNotFound, "Could not find a window identified by #{locator}"
332
- end
333
-
334
340
  def insert_modal_handlers(accept, response_text)
335
341
  prompt_response = if accept
336
342
  if response_text.nil?
@@ -386,7 +392,7 @@ class Capybara::Selenium::Driver < Capybara::Driver::Base
386
392
  end
387
393
 
388
394
  def within_given_window(handle)
389
- original_handle = self.current_window_handle
395
+ original_handle = current_window_handle
390
396
  if handle == original_handle
391
397
  yield
392
398
  else
@@ -397,39 +403,41 @@ class Capybara::Selenium::Driver < Capybara::Driver::Base
397
403
  end
398
404
  end
399
405
 
400
- def find_modal(options={})
406
+ def find_modal(text: nil, **options)
401
407
  # Selenium has its own built in wait (2 seconds)for a modal to show up, so this wait is really the minimum time
402
408
  # Actual wait time may be longer than specified
403
409
  wait = Selenium::WebDriver::Wait.new(
404
- timeout: options.fetch(:wait, session_options.default_max_wait_time) || 0 ,
405
- ignore: modal_error)
410
+ timeout: options.fetch(:wait, session_options.default_max_wait_time) || 0,
411
+ ignore: modal_error
412
+ )
406
413
  begin
407
414
  wait.until do
408
415
  alert = @browser.switch_to.alert
409
- regexp = options[:text].is_a?(Regexp) ? options[:text] : Regexp.escape(options[:text].to_s)
416
+ regexp = text.is_a?(Regexp) ? text : Regexp.escape(text.to_s)
410
417
  alert.text.match(regexp) ? alert : nil
411
418
  end
412
419
  rescue Selenium::WebDriver::Error::TimeOutError
413
- raise Capybara::ModalNotFound.new("Unable to find modal dialog#{" with #{options[:text]}" if options[:text]}")
420
+ raise Capybara::ModalNotFound, "Unable to find modal dialog#{" with #{text}" if text}"
414
421
  end
415
422
  end
416
423
 
417
- def find_headless_modal(options={})
424
+ def find_headless_modal(text: nil, **options)
418
425
  # Selenium has its own built in wait (2 seconds)for a modal to show up, so this wait is really the minimum time
419
426
  # Actual wait time may be longer than specified
420
427
  wait = Selenium::WebDriver::Wait.new(
421
- timeout: options.fetch(:wait, session_options.default_max_wait_time) || 0 ,
422
- ignore: modal_error)
428
+ timeout: options.fetch(:wait, session_options.default_max_wait_time) || 0,
429
+ ignore: modal_error
430
+ )
423
431
  begin
424
432
  wait.until do
425
433
  called, alert_text = evaluate_script('window.capybara && window.capybara.current_modal_status()')
426
434
  if called
427
435
  execute_script('window.capybara && window.capybara.modal_handlers.shift()')
428
- regexp = options[:text].is_a?(Regexp) ? options[:text] : Regexp.escape(options[:text].to_s)
436
+ regexp = text.is_a?(Regexp) ? text : Regexp.escape(text.to_s)
429
437
  if alert_text.match(regexp)
430
438
  alert_text
431
439
  else
432
- raise Capybara::ModalNotFound.new("Unable to find modal dialog#{" with #{options[:text]}" if options[:text]}")
440
+ raise Capybara::ModalNotFound, "Unable to find modal dialog#{" with #{text}" if text}"
433
441
  end
434
442
  elsif called.nil?
435
443
  # page changed so modal_handler data has gone away
@@ -440,7 +448,7 @@ class Capybara::Selenium::Driver < Capybara::Driver::Base
440
448
  end
441
449
  end
442
450
  rescue Selenium::WebDriver::Error::TimeOutError
443
- raise Capybara::ModalNotFound.new("Unable to find modal dialog#{" with #{options[:text]}" if options[:text]}")
451
+ raise Capybara::ModalNotFound, "Unable to find modal dialog#{" with #{options[:text]}" if options[:text]}"
444
452
  end
445
453
  end
446
454
 
@@ -449,7 +457,7 @@ class Capybara::Selenium::Driver < Capybara::Driver::Base
449
457
  end
450
458
 
451
459
  def silenced_unknown_error_messages
452
- [ /Error communicating with the remote browser/ ]
460
+ [/Error communicating with the remote browser/]
453
461
  end
454
462
 
455
463
  def unwrap_script_result(arg)
@@ -466,21 +474,19 @@ class Capybara::Selenium::Driver < Capybara::Driver::Base
466
474
  end
467
475
 
468
476
  def load_selenium
469
- begin
470
- require 'selenium-webdriver'
471
- # Fix for selenium-webdriver 3.4.0 which misnamed these
472
- if !defined?(::Selenium::WebDriver::Error::ElementNotInteractableError)
473
- ::Selenium::WebDriver::Error.const_set('ElementNotInteractableError', Class.new(::Selenium::WebDriver::Error::WebDriverError))
474
- end
475
- if !defined?(::Selenium::WebDriver::Error::ElementClickInterceptedError)
476
- ::Selenium::WebDriver::Error.const_set('ElementClickInterceptedError', Class.new(::Selenium::WebDriver::Error::WebDriverError))
477
- end
478
- rescue LoadError => e
479
- if e.message =~ /selenium-webdriver/
480
- raise LoadError, "Capybara's selenium driver is unable to load `selenium-webdriver`, please install the gem and add `gem 'selenium-webdriver'` to your Gemfile if you are using bundler."
481
- else
482
- raise e
483
- end
477
+ require 'selenium-webdriver'
478
+ # Fix for selenium-webdriver 3.4.0 which misnamed these
479
+ unless defined?(::Selenium::WebDriver::Error::ElementNotInteractableError)
480
+ ::Selenium::WebDriver::Error.const_set('ElementNotInteractableError', Class.new(::Selenium::WebDriver::Error::WebDriverError))
481
+ end
482
+ unless defined?(::Selenium::WebDriver::Error::ElementClickInterceptedError)
483
+ ::Selenium::WebDriver::Error.const_set('ElementClickInterceptedError', Class.new(::Selenium::WebDriver::Error::WebDriverError))
484
+ end
485
+ rescue LoadError => e
486
+ if e.message =~ /selenium-webdriver/
487
+ raise LoadError, "Capybara's selenium driver is unable to load `selenium-webdriver`, please install the gem and add `gem 'selenium-webdriver'` to your Gemfile if you are using bundler."
488
+ else
489
+ raise e
484
490
  end
485
491
  end
486
492
  end