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



315
316
317
318
319
320
321
322
323
324
325
326
327
328
# File 'lib/capybara/apparition/driver.rb', line 315

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



218
219
220
# File 'lib/capybara/apparition/driver.rb', line 218

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



249
250
251
# File 'lib/capybara/apparition/driver.rb', line 249

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



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

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

#click(x, y) ⇒ Object



116
117
118
# File 'lib/capybara/apparition/driver.rb', line 116

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

#clientObject



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

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

#current_window_handleObject



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

def current_window_handle
  browser.current_window_handle
end

#debugObject



254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
# File 'lib/capybara/apparition/driver.rb', line 254

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



330
331
332
333
334
335
336
337
338
339
340
# File 'lib/capybara/apparition/driver.rb', line 330

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



350
351
352
# File 'lib/capybara/apparition/driver.rb', line 350

def error_messages
  console_messages('error')
end

#evaluate_async_script(script, *args) ⇒ Object



126
127
128
129
130
# File 'lib/capybara/apparition/driver.rb', line 126

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



120
121
122
123
124
# File 'lib/capybara/apparition/driver.rb', line 120

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



132
133
134
135
136
137
# File 'lib/capybara/apparition/driver.rb', line 132

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

#find(method, selector) ⇒ Object



102
103
104
105
106
# File 'lib/capybara/apparition/driver.rb', line 102

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



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

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

#find_xpath(selector) ⇒ Object



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

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

#fullscreen_window(handle) ⇒ Object



190
191
192
193
194
# File 'lib/capybara/apparition/driver.rb', line 190

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



311
312
313
# File 'lib/capybara/apparition/driver.rb', line 311

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



82
83
84
# File 'lib/capybara/apparition/driver.rb', line 82

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

#maximize_window(handle) ⇒ Object



184
185
186
187
188
# File 'lib/capybara/apparition/driver.rb', line 184

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



143
144
145
# File 'lib/capybara/apparition/driver.rb', line 143

def no_such_window_error
  NoSuchWindowError
end

#open_new_windowObject



374
375
376
377
# File 'lib/capybara/apparition/driver.rb', line 374

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

#pauseObject



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
301
302
303
304
305
# File 'lib/capybara/apparition/driver.rb', line 271

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 # rubocop:disable Lint/HandleExceptions
      # 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



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

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

#quitObject



76
77
78
79
# File 'lib/capybara/apparition/driver.rb', line 76

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

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



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

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

#reset!Object



147
148
149
150
151
152
153
154
155
156
157
# File 'lib/capybara/apparition/driver.rb', line 147

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



168
169
170
# File 'lib/capybara/apparition/driver.rb', line 168

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

#resize_window(width, height) ⇒ Object



172
173
174
175
176
# File 'lib/capybara/apparition/driver.rb', line 172

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



178
179
180
181
182
# File 'lib/capybara/apparition/driver.rb', line 178

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

#response_headersObject



223
224
225
226
227
# File 'lib/capybara/apparition/driver.rb', line 223

def response_headers
  browser.response_headers.each_with_object({}) do |(key, value), hsh|
    hsh[key.split('-').map(&:capitalize).join('-')] = value
  end
end

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



159
160
161
# File 'lib/capybara/apparition/driver.rb', line 159

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


229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
# File 'lib/capybara/apparition/driver.rb', line 229

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



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

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



98
99
100
# File 'lib/capybara/apparition/driver.rb', line 98

def source
  browser.source.to_s
end

#timeoutObject



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

def timeout
  client.timeout
end

#timeout=(sec) ⇒ Object



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

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

#versionObject



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

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



91
92
93
94
# File 'lib/capybara/apparition/driver.rb', line 91

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

#wait?Boolean

Returns:

  • (Boolean)


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

def wait?
  true
end

#window_size(handle) ⇒ Object



196
197
198
199
200
# File 'lib/capybara/apparition/driver.rb', line 196

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

#within_window(selector, &block) ⇒ Object



354
355
356
357
358
359
360
361
362
363
364
# File 'lib/capybara/apparition/driver.rb', line 354

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