Class: Flunky::Drivers::FerrumDriver

Inherits:
Base
  • Object
show all
Defined in:
lib/flunky/drivers/ferrum_driver.rb

Overview

Default backend. Ferrum drives Chrome over the DevTools Protocol with no Selenium server in the loop, which keeps setup to “have Chrome installed”.

Constant Summary collapse

KEY_MAP =

Named keys Ferrum expects as symbols; anything else is typed literally.

{
  "Enter" => :Enter,
  "Tab" => :Tab,
  "Escape" => :Escape,
  "Backspace" => :Backspace,
  "Delete" => :Delete,
  "ArrowUp" => :Up,
  "ArrowDown" => :Down,
  "ArrowLeft" => :Left,
  "ArrowRight" => :Right
}.freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(headless: true, window_size: [1280, 800], default_timeout: 10, user_agent: nil, browser_options: {}, process_timeout: nil) ⇒ FerrumDriver

browser_options passes raw Chrome flags through to Ferrum (for example { “no-sandbox” => nil } when running as root in CI). process_timeout is how long to wait for Chrome to come up; it is separate from the per command timeout.



29
30
31
32
33
34
35
36
37
38
39
# File 'lib/flunky/drivers/ferrum_driver.rb', line 29

def initialize(headless: true, window_size: [1280, 800], default_timeout: 10,
               user_agent: nil, browser_options: {}, process_timeout: nil)
  super()
  @headless = headless
  @window_size = window_size
  @default_timeout = default_timeout
  @user_agent = user_agent
  @browser_options = browser_options || {}
  @process_timeout = process_timeout
  @browser = nil
end

Instance Attribute Details

#browserObject (readonly)

Returns the value of attribute browser.



23
24
25
# File 'lib/flunky/drivers/ferrum_driver.rb', line 23

def browser
  @browser
end

Instance Method Details

#click(ref) ⇒ Object



90
91
92
93
# File 'lib/flunky/drivers/ferrum_driver.rb', line 90

def click(ref)
  resolve(ref).click
  true
end

#current_urlObject



65
66
67
# File 'lib/flunky/drivers/ferrum_driver.rb', line 65

def current_url
  page.current_url
end

#evaluate(js) ⇒ Object



77
78
79
# File 'lib/flunky/drivers/ferrum_driver.rb', line 77

def evaluate(js)
  page.evaluate(js)
end

#execute(js) ⇒ Object

Side-effecting JS where we do not care about the return value.



82
83
84
# File 'lib/flunky/drivers/ferrum_driver.rb', line 82

def execute(js)
  page.execute(js)
end

#go_to(url) ⇒ Object



61
62
63
# File 'lib/flunky/drivers/ferrum_driver.rb', line 61

def go_to(url)
  page.go_to(url)
end

#htmlObject



73
74
75
# File 'lib/flunky/drivers/ferrum_driver.rb', line 73

def html
  page.body
end

#press_key(key) ⇒ Object



116
117
118
119
# File 'lib/flunky/drivers/ferrum_driver.rb', line 116

def press_key(key)
  page.keyboard.type(KEY_MAP.fetch(key, key))
  true
end

#quitObject



56
57
58
59
# File 'lib/flunky/drivers/ferrum_driver.rb', line 56

def quit
  @browser&.quit
  @browser = nil
end

#screenshot_base64Object



86
87
88
# File 'lib/flunky/drivers/ferrum_driver.rb', line 86

def screenshot_base64
  page.screenshot(encoding: :base64)
end

#scroll_by(dx, dy) ⇒ Object



121
122
123
124
# File 'lib/flunky/drivers/ferrum_driver.rb', line 121

def scroll_by(dx, dy)
  page.execute("window.scrollBy(#{Integer(dx)}, #{Integer(dy)})")
  true
end

#select_option(ref, value) ⇒ Object



105
106
107
108
109
110
111
112
113
114
# File 'lib/flunky/drivers/ferrum_driver.rb', line 105

def select_option(ref, value)
  node = resolve(ref)
  if tag_name(node) == "select"
    node.select(value)
  else
    # Custom (non-native) selects are just clickable elements.
    node.click
  end
  true
end

#startObject



41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/flunky/drivers/ferrum_driver.rb', line 41

def start
  return @browser if @browser

  options = {
    headless: @headless,
    window_size: @window_size,
    timeout: @default_timeout,
    browser_options: @browser_options
  }
  options[:process_timeout] = @process_timeout if @process_timeout
  @browser = Ferrum::Browser.new(**options)
  @browser.headers.set("User-Agent" => @user_agent) if @user_agent
  @browser
end

#titleObject



69
70
71
# File 'lib/flunky/drivers/ferrum_driver.rb', line 69

def title
  page.title
end

#type_text(ref, text, clear: false) ⇒ Object



95
96
97
98
99
100
101
102
103
# File 'lib/flunky/drivers/ferrum_driver.rb', line 95

def type_text(ref, text, clear: false)
  node = resolve(ref)
  node.focus
  # Clear by emptying the field's value rather than sending backspaces,
  # which is both faster and robust to long existing contents.
  node.evaluate("this.value = ''") if clear
  node.type(text)
  true
end