Class: Capybara::Apparition::Driver

Inherits:
Driver::Base
  • Object
show all
Extended by:
Forwardable
Defined in:
lib/capybara/apparition/driver.rb

Constant Summary collapse

DEFAULT_TIMEOUT =
30

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(app, options = {}) ⇒ Driver

Returns a new instance of Driver.



29
30
31
32
33
34
35
36
37
38
# File 'lib/capybara/apparition/driver.rb', line 29

def initialize(app, options = {})
  @app       = app
  @options   = options
  generate_browser_options
  @browser   = nil
  @inspector = nil
  @client    = nil
  @launcher  = nil
  @started   = false
end

Instance Attribute Details

#appObject (readonly)

Returns the value of attribute app.



15
16
17
# File 'lib/capybara/apparition/driver.rb', line 15

def app
  @app
end

#optionsObject (readonly)

Returns the value of attribute options.



15
16
17
# File 'lib/capybara/apparition/driver.rb', line 15

def options
  @options
end

Instance Method Details

#accept_modal(type, options = {}) ⇒ Object



310
311
312
313
314
315
316
317
318
319
320
321
322
323
# File 'lib/capybara/apparition/driver.rb', line 310

def accept_modal(type, options = {})
  case type
  when :alert
    browser.accept_alert
  when :confirm
    browser.accept_confirm
  when :prompt
    browser.accept_prompt options[:with]
  end

  yield if block_given?

  find_modal(options)
end

#add_header(name, value, options = {}) ⇒ Object Also known as: header



215
216
217
# File 'lib/capybara/apparition/driver.rb', line 215

def add_header(name, value, options = {})
  browser.add_header({ name => value }, **{ permanent: true }.merge(options))
end

#basic_authorize(user = nil, password = nil) ⇒ Object Also known as: authenticate



244
245
246
# File 'lib/capybara/apparition/driver.rb', line 244

def basic_authorize(user = nil, password = nil)
  browser.set_http_auth(user, password)
end

#browserObject

def chrome_url

'ws://localhost:9223'

end



48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/capybara/apparition/driver.rb', line 48

def browser
  @browser ||= begin
    Browser.new(client, browser_logger) do |browser|
      browser.js_errors = options.fetch(:js_errors, true)
      browser.ignore_https_errors = options.fetch(:ignore_https_errors, false)
      browser.extensions = options.fetch(:extensions, [])
      browser.debug      = options.fetch(:debug, false)
      browser.url_blacklist = options[:url_blacklist] || []
      browser.url_whitelist = options[:url_whitelist] || []
    end
  end
end

#browser_loggerObject

logger should be an object that behaves like IO or nil



84
85
86
# File 'lib/capybara/apparition/driver.rb', line 84

def browser_logger
  options.fetch(:browser_logger, $stdout)
end

#click(x, y) ⇒ Object



113
114
115
# File 'lib/capybara/apparition/driver.rb', line 113

def click(x, y)
  browser.click_coordinates(x, y)
end

#clientObject



65
66
67
68
69
70
71
# File 'lib/capybara/apparition/driver.rb', line 65

def client
  @client ||= begin
    @launcher ||= Browser::Launcher.start(options)
    ws_url = @launcher.ws_url
    ::Capybara::Apparition::ChromeClient.client(ws_url.to_s)
  end
end

#current_window_handleObject



136
137
138
# File 'lib/capybara/apparition/driver.rb', line 136

def current_window_handle
  browser.current_window_handle
end

#debugObject



249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
# File 'lib/capybara/apparition/driver.rb', line 249

def debug
  if @options[:inspector]
    # Fall back to default scheme
    scheme = begin
               URI.parse(browser.current_url).scheme
             rescue StandardError
               nil
             end
    scheme = 'http' if scheme != 'https'
    inspector.open(scheme)
    pause
  else
    raise Error, 'To use the remote debugging, you have to launch the driver ' \
                 'with `:inspector => true` configuration option'
  end
end

#dismiss_modal(type, options = {}) ⇒ Object



325
326
327
328
329
330
331
332
333
334
335
# File 'lib/capybara/apparition/driver.rb', line 325

def dismiss_modal(type, options = {})
  case type
  when :confirm
    browser.dismiss_confirm
  when :prompt
    browser.dismiss_prompt
  end

  yield if block_given?
  find_modal(options)
end

#error_messagesObject



345
346
347
# File 'lib/capybara/apparition/driver.rb', line 345

def error_messages
  console_messages('error')
end

#evaluate_async_script(script, *args) ⇒ Object



123
124
125
126
127
# File 'lib/capybara/apparition/driver.rb', line 123

def evaluate_async_script(script, *args)
  retry_if_wrong_world do
    unwrap_script_result(browser.evaluate_async(script, session_wait_time, *native_args(args)))
  end
end

#evaluate_script(script, *args) ⇒ Object



117
118
119
120
121
# File 'lib/capybara/apparition/driver.rb', line 117

def evaluate_script(script, *args)
  retry_if_wrong_world do
    unwrap_script_result(browser.evaluate(script, *native_args(args)))
  end
end

#execute_script(script, *args) ⇒ Object



129
130
131
132
133
134
# File 'lib/capybara/apparition/driver.rb', line 129

def execute_script(script, *args)
  retry_if_wrong_world do
    browser.execute(script, *native_args(args))
  end
  nil
end

#find(method, selector) ⇒ Object



99
100
101
102
103
# File 'lib/capybara/apparition/driver.rb', line 99

def find(method, selector)
  browser.find(method, selector).map do |page_id, id, attrs|
    Capybara::Apparition::Node.new(self, page_id, id, attrs)
  end
end

#find_css(selector) ⇒ Object



109
110
111
# File 'lib/capybara/apparition/driver.rb', line 109

def find_css(selector)
  find :css, selector.to_s
end

#find_xpath(selector) ⇒ Object



105
106
107
# File 'lib/capybara/apparition/driver.rb', line 105

def find_xpath(selector)
  find :xpath, selector.to_s
end

#fullscreen_window(handle) ⇒ Object



187
188
189
190
191
# File 'lib/capybara/apparition/driver.rb', line 187

def fullscreen_window(handle)
  _within_window(handle) do
    browser.fullscreen
  end
end

#inspectorObject



61
62
63
# File 'lib/capybara/apparition/driver.rb', line 61

def inspector
  @inspector ||= options[:inspector] && Inspector.new(options[:inspector])
end

#invalid_element_errorsObject



306
307
308
# File 'lib/capybara/apparition/driver.rb', line 306

def invalid_element_errors
  [Capybara::Apparition::ObsoleteNode, Capybara::Apparition::MouseEventFailed, Capybara::Apparition::WrongWorld]
end

#loggerObject

logger should be an object that responds to puts, or nil



79
80
81
# File 'lib/capybara/apparition/driver.rb', line 79

def logger
  options[:logger] || (options[:debug] && STDERR)
end

#maximize_window(handle) ⇒ Object



181
182
183
184
185
# File 'lib/capybara/apparition/driver.rb', line 181

def maximize_window(handle)
  _within_window(handle) do
    browser.maximize
  end
end

#needs_server?Boolean

Returns:

  • (Boolean)


40
41
42
# File 'lib/capybara/apparition/driver.rb', line 40

def needs_server?
  true
end

#no_such_window_errorObject



140
141
142
# File 'lib/capybara/apparition/driver.rb', line 140

def no_such_window_error
  NoSuchWindowError
end

#open_new_windowObject



369
370
371
372
# File 'lib/capybara/apparition/driver.rb', line 369

def open_new_window
  # needed because Capybara does arity detection on this method
  browser.open_new_window
end

#pauseObject



266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
# File 'lib/capybara/apparition/driver.rb', line 266

def pause
  # STDIN is not necessarily connected to a keyboard. It might even be closed.
  # So we need a method other than keypress to continue.

  # In jRuby - STDIN returns immediately from select
  # see https://github.com/jruby/jruby/issues/1783
  # TODO: This limitation is no longer true can we simplify?
  read, write = IO.pipe
  Thread.new do
    IO.copy_stream(STDIN, write)
    write.close
  end

  STDERR.puts "Apparition execution paused. Press enter (or run 'kill -CONT #{Process.pid}') to continue." # rubocop:disable Style/StderrPuts

  signal = false
  old_trap = trap('SIGCONT') do
    signal = true
    STDERR.puts "\nSignal SIGCONT received" # rubocop:disable Style/StderrPuts
  end
  # wait for data on STDIN or signal SIGCONT received
  keyboard = IO.select([read], nil, nil, 1) until keyboard || signal

  unless signal
    begin
      input = read.read_nonblock(80) # clear out the read buffer
      puts unless input&.end_with?("\n")
    rescue EOFError, IO::WaitReadable
      # Ignore problems reading from STDIN.
    end
  end
ensure
  trap('SIGCONT', old_trap) # Restore the previous signal handler, if there was one.
  STDERR.puts 'Continuing' # rubocop:disable Style/StderrPuts
end

#proxy_authorize(user = nil, password = nil) ⇒ Object



240
241
242
# File 'lib/capybara/apparition/driver.rb', line 240

def proxy_authorize(user = nil, password = nil)
  browser.set_proxy_auth(user, password)
end

#quitObject



73
74
75
76
# File 'lib/capybara/apparition/driver.rb', line 73

def quit
  @client&.stop
  @launcher&.stop
end

#render_base64(format = :png, options = {}) ⇒ Object



161
162
163
# File 'lib/capybara/apparition/driver.rb', line 161

def render_base64(format = :png, options = {})
  browser.render_base64(options.merge(format: format))
end

#reset!Object



144
145
146
147
148
149
150
151
152
153
154
# File 'lib/capybara/apparition/driver.rb', line 144

def reset!
  begin
    browser.reset
  rescue TimeoutError
    puts 'Reset timed out - retrying'
    browser.reset
  end
  browser.url_blacklist = options[:url_blacklist] || []
  browser.url_whitelist = options[:url_whitelist] || []
  @started = false
end

#resize(width, height) ⇒ Object



165
166
167
# File 'lib/capybara/apparition/driver.rb', line 165

def resize(width, height)
  browser.resize(width, height, screen: options[:screen_size])
end

#resize_window(width, height) ⇒ Object



169
170
171
172
173
# File 'lib/capybara/apparition/driver.rb', line 169

def resize_window(width, height)
  warn '[DEPRECATION] Capybara::Apparition::Driver#resize_window ' \
    'is deprecated. Please use Capybara::Window#resize_to instead.'
  resize(width, height)
end

#resize_window_to(handle, width, height) ⇒ Object



175
176
177
178
179
# File 'lib/capybara/apparition/driver.rb', line 175

def resize_window_to(handle, width, height)
  _within_window(handle) do
    resize(width, height)
  end
end

#response_headersObject



220
221
222
# File 'lib/capybara/apparition/driver.rb', line 220

def response_headers
  browser.response_headers.transform_keys { |key| key.split('-').map(&:capitalize).join('-') }
end

#save_screenshot(path, options = {}) ⇒ Object Also known as: render



156
157
158
# File 'lib/capybara/apparition/driver.rb', line 156

def save_screenshot(path, options = {})
  browser.render(path, options)
end


224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
# File 'lib/capybara/apparition/driver.rb', line 224

def set_cookie(name, value = nil, options = {})
  name, value, options = parse_raw_cookie(name) if value.nil?

  options[:name]  ||= name
  options[:value] ||= value
  options[:domain] ||= begin
    if @started
      URI.parse(browser.current_url).host
    else
      URI.parse(default_cookie_host).host || '127.0.0.1'
    end
  end

  browser.set_cookie(options)
end

#set_proxy(host, port, type = nil, user_ = nil, password_ = nil, user: nil, password: nil, bypass: []) ⇒ Object



199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
# File 'lib/capybara/apparition/driver.rb', line 199

def set_proxy(host, port, type = nil, user_ = nil, password_ = nil, user: nil, password: nil, bypass: [])
  if user_ || password_
    warn '#set_proxy: Passing `user` and `password` as positional arguments is deprecated. ' \
         'Please pass as keyword arguments.'
    user ||= user_
    password ||= password_
  end

  # TODO: Look at implementing via the CDP Fetch domain when available
  @options[:browser_options] ||= {}
  @options[:browser_options]['proxy-server'] = "#{type + '=' if type}#{host}:#{port}"
  bypass = Array(bypass).join(';')
  @options[:browser_options]['proxy-bypass-list'] = bypass unless bypass.empty?
  browser.set_proxy_auth(user, password) if user || password
end

#sourceObject



95
96
97
# File 'lib/capybara/apparition/driver.rb', line 95

def source
  browser.source.to_s
end

#timeoutObject



337
338
339
# File 'lib/capybara/apparition/driver.rb', line 337

def timeout
  client.timeout
end

#timeout=(sec) ⇒ Object



341
342
343
# File 'lib/capybara/apparition/driver.rb', line 341

def timeout=(sec)
  client.timeout = sec
end

#versionObject



361
362
363
364
365
366
367
# File 'lib/capybara/apparition/driver.rb', line 361

def version
  chrome_version = browser.command('Browser.getVersion')
  format(VERSION_STRING,
         capybara: Capybara::VERSION,
         apparition: Capybara::Apparition::VERSION,
         chrome: chrome_version['product'])
end

#visit(url) ⇒ Object



88
89
90
91
# File 'lib/capybara/apparition/driver.rb', line 88

def visit(url)
  @started = true
  browser.visit(url)
end

#wait?Boolean

Returns:

  • (Boolean)


302
303
304
# File 'lib/capybara/apparition/driver.rb', line 302

def wait?
  true
end

#window_size(handle) ⇒ Object



193
194
195
196
197
# File 'lib/capybara/apparition/driver.rb', line 193

def window_size(handle)
  _within_window(handle) do
    evaluate_script('[window.innerWidth, window.innerHeight]')
  end
end

#within_window(selector, &block) ⇒ Object



349
350
351
352
353
354
355
356
357
358
359
# File 'lib/capybara/apparition/driver.rb', line 349

def within_window(selector, &block)
  warn 'Driver#within_window is deprecated, please switch to using Session#within_window instead.'
  _within_window(selector, &block)
  orig_window = current_window_handle
  switch_to_window(selector)
  begin
    yield
  ensure
    switch_to_window(orig_window)
  end
end