Class: Capybara::Selenium::Driver
Constant Summary
collapse
- DEFAULT_OPTIONS =
{
browser: :firefox,
clear_local_storage: false,
clear_session_storage: false
}.freeze
- SPECIAL_OPTIONS =
%i[browser clear_local_storage clear_session_storage].freeze
Instance Attribute Summary collapse
Attributes inherited from Driver::Base
#session
Class Method Summary
collapse
Instance Method Summary
collapse
#frame_title, #frame_url, #response_headers, #session_options, #status_code
Constructor Details
#initialize(app, **options) ⇒ Driver
Returns a new instance of Driver.
54
55
56
57
58
59
60
61
62
|
# File 'lib/capybara/selenium/driver.rb', line 54
def initialize(app, **options)
self.class.load_selenium
@session = nil
@app = app
@browser = nil
@exit_status = nil
@frame_handles = {}
@options = DEFAULT_OPTIONS.merge(options)
end
|
Instance Attribute Details
#app ⇒ Object
Returns the value of attribute app.
14
15
16
|
# File 'lib/capybara/selenium/driver.rb', line 14
def app
@app
end
|
#options ⇒ Object
Returns the value of attribute options.
14
15
16
|
# File 'lib/capybara/selenium/driver.rb', line 14
def options
@options
end
|
Class Method Details
.load_selenium ⇒ Object
16
17
18
19
20
21
22
23
24
25
26
27
28
|
# File 'lib/capybara/selenium/driver.rb', line 16
def self.load_selenium
require 'selenium-webdriver'
unless defined?(::Selenium::WebDriver::Error::ElementNotInteractableError)
::Selenium::WebDriver::Error.const_set('ElementNotInteractableError', Class.new(::Selenium::WebDriver::Error::WebDriverError))
end
unless defined?(::Selenium::WebDriver::Error::ElementClickInterceptedError)
::Selenium::WebDriver::Error.const_set('ElementClickInterceptedError', Class.new(::Selenium::WebDriver::Error::WebDriverError))
end
rescue LoadError => e
raise e if e.message !~ /selenium-webdriver/
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."
end
|
Instance Method Details
#accept_modal(_type, **options) ⇒ Object
250
251
252
253
254
255
256
257
258
259
|
# File 'lib/capybara/selenium/driver.rb', line 250
def accept_modal(_type, **options)
yield if block_given?
modal = find_modal(options)
modal.send_keys options[:with] if options[:with]
message = modal.text
modal.accept
message
end
|
#browser ⇒ Object
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
|
# File 'lib/capybara/selenium/driver.rb', line 30
def browser
unless @browser
@processed_options = options.reject { |key, _val| SPECIAL_OPTIONS.include?(key) }
@browser = Selenium::WebDriver.for(options[:browser], @processed_options)
@w3c = ((defined?(Selenium::WebDriver::Remote::W3CCapabilities) && @browser.capabilities.is_a?(Selenium::WebDriver::Remote::W3CCapabilities)) ||
(defined?(Selenium::WebDriver::Remote::W3C::Capabilities) && @browser.capabilities.is_a?(Selenium::WebDriver::Remote::W3C::Capabilities)))
main = Process.pid
at_exit do
@exit_status = $ERROR_INFO.status if $ERROR_INFO.is_a?(SystemExit)
quit if Process.pid == main
exit @exit_status if @exit_status end
end
@browser
end
|
#browser_name ⇒ Object
This method is part of a private API.
You should avoid using this method if possible, as it may be removed or be changed in the future.
328
329
330
|
# File 'lib/capybara/selenium/driver.rb', line 328
def browser_name
browser.browser
end
|
#chrome? ⇒ Boolean
This method is part of a private API.
You should avoid using this method if possible, as it may be removed or be changed in the future.
313
314
315
|
# File 'lib/capybara/selenium/driver.rb', line 313
def chrome?
browser_name == :chrome
end
|
#close_window(handle) ⇒ Object
231
232
233
234
235
236
|
# File 'lib/capybara/selenium/driver.rb', line 231
def close_window(handle)
raise ArgumentError, "Not allowed to close the primary window" if handle == window_handles.first
within_given_window(handle) do
browser.close
end
end
|
#current_url ⇒ Object
88
89
90
|
# File 'lib/capybara/selenium/driver.rb', line 88
def current_url
browser.current_url
end
|
#current_window_handle ⇒ Object
202
203
204
|
# File 'lib/capybara/selenium/driver.rb', line 202
def current_window_handle
browser.window_handle
end
|
#dismiss_modal(_type, **options) ⇒ Object
261
262
263
264
265
266
267
|
# File 'lib/capybara/selenium/driver.rb', line 261
def dismiss_modal(_type, **options)
yield if block_given?
modal = find_modal(options)
message = modal.text
modal.dismiss
message
end
|
#edge? ⇒ Boolean
This method is part of a private API.
You should avoid using this method if possible, as it may be removed or be changed in the future.
318
319
320
|
# File 'lib/capybara/selenium/driver.rb', line 318
def edge?
browser_name == :edge
end
|
#evaluate_async_script(script, *args) ⇒ Object
112
113
114
115
116
|
# File 'lib/capybara/selenium/driver.rb', line 112
def evaluate_async_script(script, *args)
browser.manage.timeouts.script_timeout = Capybara.default_max_wait_time
result = browser.execute_async_script(script, *native_args(args))
unwrap_script_result(result)
end
|
#evaluate_script(script, *args) ⇒ Object
107
108
109
110
|
# File 'lib/capybara/selenium/driver.rb', line 107
def evaluate_script(script, *args)
result = execute_script("return #{script}", *args)
unwrap_script_result(result)
end
|
#execute_script(script, *args) ⇒ Object
103
104
105
|
# File 'lib/capybara/selenium/driver.rb', line 103
def execute_script(script, *args)
browser.execute_script(script, *native_args(args))
end
|
#find_css(selector) ⇒ Object
96
97
98
|
# File 'lib/capybara/selenium/driver.rb', line 96
def find_css(selector)
browser.find_elements(:css, selector).map { |node| Capybara::Selenium::Node.new(self, node) }
end
|
#find_xpath(selector) ⇒ Object
92
93
94
|
# File 'lib/capybara/selenium/driver.rb', line 92
def find_xpath(selector)
browser.find_elements(:xpath, selector).map { |node| Capybara::Selenium::Node.new(self, node) }
end
|
#firefox? ⇒ Boolean
This method is part of a private API.
You should avoid using this method if possible, as it may be removed or be changed in the future.
308
309
310
|
# File 'lib/capybara/selenium/driver.rb', line 308
def firefox?
browser_name == :firefox
end
|
#go_back ⇒ Object
72
73
74
|
# File 'lib/capybara/selenium/driver.rb', line 72
def go_back
browser.navigate.back
end
|
#go_forward ⇒ Object
76
77
78
|
# File 'lib/capybara/selenium/driver.rb', line 76
def go_forward
browser.navigate.forward
end
|
#html ⇒ Object
80
81
82
|
# File 'lib/capybara/selenium/driver.rb', line 80
def html
browser.page_source
end
|
#ie? ⇒ Boolean
This method is part of a private API.
You should avoid using this method if possible, as it may be removed or be changed in the future.
323
324
325
|
# File 'lib/capybara/selenium/driver.rb', line 323
def ie?
browser_name == :ie
end
|
#invalid_element_errors ⇒ Object
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
|
# File 'lib/capybara/selenium/driver.rb', line 282
def invalid_element_errors
[
::Selenium::WebDriver::Error::StaleElementReferenceError,
::Selenium::WebDriver::Error::UnhandledError,
::Selenium::WebDriver::Error::ElementNotVisibleError,
::Selenium::WebDriver::Error::InvalidSelectorError, ::Selenium::WebDriver::Error::ElementNotInteractableError,
::Selenium::WebDriver::Error::ElementClickInterceptedError,
::Selenium::WebDriver::Error::InvalidElementStateError,
::Selenium::WebDriver::Error::ElementNotSelectableError,
::Selenium::WebDriver::Error::ElementNotSelectableError,
::Selenium::WebDriver::Error::NoSuchElementError, ::Selenium::WebDriver::Error::InvalidArgumentError ]
end
|
#marionette? ⇒ Boolean
This method is part of a private API.
You should avoid using this method if possible, as it may be removed or be changed in the future.
303
304
305
|
# File 'lib/capybara/selenium/driver.rb', line 303
def marionette?
firefox? && browser && @w3c
end
|
#maximize_window(handle) ⇒ Object
224
225
226
227
228
229
|
# File 'lib/capybara/selenium/driver.rb', line 224
def maximize_window(handle)
within_given_window(handle) do
browser.manage.window.maximize
end
sleep 0.1 end
|
#needs_server? ⇒ Boolean
101
|
# File 'lib/capybara/selenium/driver.rb', line 101
def needs_server?; true; end
|
#no_such_window_error ⇒ Object
298
299
300
|
# File 'lib/capybara/selenium/driver.rb', line 298
def no_such_window_error
Selenium::WebDriver::Error::NoSuchWindowError
end
|
#open_new_window ⇒ Object
242
243
244
|
# File 'lib/capybara/selenium/driver.rb', line 242
def open_new_window
browser.execute_script('window.open();')
end
|
#quit ⇒ Object
269
270
271
272
273
274
275
276
277
278
279
280
|
# File 'lib/capybara/selenium/driver.rb', line 269
def quit
@browser&.quit
rescue Selenium::WebDriver::Error::SessionNotCreatedError, Errno::ECONNREFUSED rescue Selenium::WebDriver::Error::UnknownError => e
unless silenced_unknown_error_message?(e.message) warn "Ignoring Selenium UnknownError during driver quit: #{e.message}"
end
ensure
@browser = nil
end
|
#refresh ⇒ Object
68
69
70
|
# File 'lib/capybara/selenium/driver.rb', line 68
def refresh
browser.navigate.refresh
end
|
#reset! ⇒ Object
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
|
# File 'lib/capybara/selenium/driver.rb', line 122
def reset!
return unless @browser
if firefox? || chrome?
switch_to_window(window_handles.first)
window_handles.slice(1..-1).each { |win| close_window(win) }
end
navigated = false
start_time = Capybara::Helpers.monotonic_time
begin
unless navigated
begin
@browser.manage.delete_all_cookies
clear_storage
rescue Selenium::WebDriver::Error::UnhandledError end
@browser.navigate.to("about:blank")
end
navigated = true
until find_xpath("/html/body/*").empty?
raise Capybara::ExpectationNotMet, 'Timed out waiting for Selenium session reset' if (Capybara::Helpers.monotonic_time - start_time) >= 10
sleep 0.05
end
rescue Selenium::WebDriver::Error::UnhandledAlertError, Selenium::WebDriver::Error::UnexpectedAlertOpenError
begin
@browser.switch_to.alert.accept
sleep 0.25 rescue modal_error
if current_url != "about:blank"
begin
@browser.navigate.to("about:blank")
sleep 0.1 @browser.switch_to.alert.accept
rescue modal_error end
end
end
retry
end
end
|
#resize_window_to(handle, width, height) ⇒ Object
213
214
215
216
217
218
219
220
221
222
|
# File 'lib/capybara/selenium/driver.rb', line 213
def resize_window_to(handle, width, height)
within_given_window(handle) do
if marionette? && (window_size(handle) == [width, height])
{}
else
browser.manage.window.resize_to(width, height)
end
end
end
|
#save_screenshot(path, **_options) ⇒ Object
118
119
120
|
# File 'lib/capybara/selenium/driver.rb', line 118
def save_screenshot(path, **_options)
browser.save_screenshot(path)
end
|
#switch_to_frame(frame) ⇒ Object
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
|
# File 'lib/capybara/selenium/driver.rb', line 184
def switch_to_frame(frame)
case frame
when :top
@frame_handles[browser.window_handle] = []
browser.switch_to.default_content
when :parent
@frame_handles[browser.window_handle].pop
browser.switch_to.default_content
@frame_handles[browser.window_handle].each { |fh| browser.switch_to.frame(fh) }
else
@frame_handles[browser.window_handle] ||= []
@frame_handles[browser.window_handle] << frame.native
browser.switch_to.frame(frame.native)
end
end
|
#switch_to_window(handle) ⇒ Object
246
247
248
|
# File 'lib/capybara/selenium/driver.rb', line 246
def switch_to_window(handle)
browser.switch_to.window handle
end
|
#title ⇒ Object
84
85
86
|
# File 'lib/capybara/selenium/driver.rb', line 84
def title
browser.title
end
|
#visit(path) ⇒ Object
64
65
66
|
# File 'lib/capybara/selenium/driver.rb', line 64
def visit(path)
browser.navigate.to(path)
end
|
#wait? ⇒ Boolean
100
|
# File 'lib/capybara/selenium/driver.rb', line 100
def wait?; true; end
|
#window_handles ⇒ Object
238
239
240
|
# File 'lib/capybara/selenium/driver.rb', line 238
def window_handles
browser.window_handles
end
|
#window_size(handle) ⇒ Object
206
207
208
209
210
211
|
# File 'lib/capybara/selenium/driver.rb', line 206
def window_size(handle)
within_given_window(handle) do
size = browser.manage.window.size
[size.width, size.height]
end
end
|