Class: Rubium::Browser

Inherits:
Object
  • Object
show all
Defined in:
lib/rubium/browser.rb

Defined Under Namespace

Classes: ConfigurationError

Constant Summary collapse

MAX_CONNECT_WAIT_TIME =
6
MAX_DEFAULT_TIMEOUT =
60

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ Browser



33
34
35
36
37
38
39
40
41
42
# File 'lib/rubium/browser.rb', line 33

def initialize(options = {})
  @options = options

  if @options[:enable_logger]
    @logger = Logger.new(STDOUT)
    @logger.progname = self.class.to_s
  end

  create_browser
end

Instance Attribute Details

#clientObject (readonly)

Returns the value of attribute client.



31
32
33
# File 'lib/rubium/browser.rb', line 31

def client
  @client
end

#devtools_urlObject (readonly)

Returns the value of attribute devtools_url.



31
32
33
# File 'lib/rubium/browser.rb', line 31

def devtools_url
  @devtools_url
end

#loggerObject (readonly)

Returns the value of attribute logger.



31
32
33
# File 'lib/rubium/browser.rb', line 31

def logger
  @logger
end

#optionsObject (readonly)

Returns the value of attribute options.



31
32
33
# File 'lib/rubium/browser.rb', line 31

def options
  @options
end

#pidObject (readonly)

Returns the value of attribute pid.



31
32
33
# File 'lib/rubium/browser.rb', line 31

def pid
  @pid
end

#portObject (readonly)

Returns the value of attribute port.



31
32
33
# File 'lib/rubium/browser.rb', line 31

def port
  @port
end

#processed_requests_countObject (readonly)

Returns the value of attribute processed_requests_count.



31
32
33
# File 'lib/rubium/browser.rb', line 31

def processed_requests_count
  @processed_requests_count
end

Class Method Details

.ports_poolObject



22
23
24
# File 'lib/rubium/browser.rb', line 22

def ports_pool
  @pool ||= RandomPort::Pool.new
end

.running_pidsObject



26
27
28
# File 'lib/rubium/browser.rb', line 26

def running_pids
  @running_pids ||= []
end

Instance Method Details

#bodyObject



101
102
103
104
# File 'lib/rubium/browser.rb', line 101

def body
  response = @client.send_cmd "Runtime.evaluate", expression: 'document.documentElement.outerHTML'
  response.dig("result", "value")
end

#click(selector) ⇒ Object



140
141
142
143
144
# File 'lib/rubium/browser.rb', line 140

def click(selector)
  @client.send_cmd "Runtime.evaluate", expression: "    document.querySelector(`\#{selector}`).click();\n  js\nend\n"

#closeObject Also known as: destroy_driver!



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/rubium/browser.rb', line 51

def close
  if closed?
    logger.info "Browser already has been closed" if options[:enable_logger]
  else
    Process.kill("HUP", @pid)
    self.class.running_pids.delete(@pid)
    self.class.ports_pool.release(@port)

    # Delete temp profile directory, if there is no custom one
    unless options[:data_dir]
      FileUtils.rm_rf(@data_dir) if Dir.exist?(@data_dir)
    end

    logger.info "Closed browser" if options[:enable_logger]
    @closed = true
  end
end

#closed?Boolean



71
72
73
# File 'lib/rubium/browser.rb', line 71

def closed?
  @closed
end

#cookiesObject



167
168
169
170
# File 'lib/rubium/browser.rb', line 167

def cookies
  response = @client.send_cmd "Network.getCookies"
  response["cookies"]
end

#current_responseObject



106
107
108
# File 'lib/rubium/browser.rb', line 106

def current_response
  Nokogiri::HTML(body)
end

#evaluate_on_new_document(script) ⇒ Object



161
162
163
# File 'lib/rubium/browser.rb', line 161

def evaluate_on_new_document(script)
  @client.send_cmd "Page.addScriptToEvaluateOnNewDocument", source: script
end

#execute_script(script) ⇒ Object



185
186
187
# File 'lib/rubium/browser.rb', line 185

def execute_script(script)
  @client.send_cmd "Runtime.evaluate", expression: script
end

#fill_in(selector, text) ⇒ Object



179
180
181
182
183
# File 'lib/rubium/browser.rb', line 179

def fill_in(selector, text)
  execute_script "    document.querySelector(`\#{selector}`).value = \"\#{text}\"\n  js\nend\n"

#goto(url, wait: options[:max_timeout] || MAX_DEFAULT_TIMEOUT) ⇒ Object Also known as: visit



75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/rubium/browser.rb', line 75

def goto(url, wait: options[:max_timeout] || MAX_DEFAULT_TIMEOUT)
  logger.info "Started request: #{url}" if options[:enable_logger]
  if options[:restart_after] && processed_requests_count >= options[:restart_after]
    restart!
  end

  response = @client.send_cmd "Page.navigate", url: url

  # By default, after Page.navigate we should wait till page will load completely
  # using Page.loadEventFired. But on some websites with Ajax navigation, Page.loadEventFired
  # will stuck forever. In this case you can provide `wait: false` option to skip waiting.
  if wait != false
    # https://chromedevtools.github.io/devtools-protocol/tot/Page#event-frameStoppedLoading
    Timeout.timeout(wait) do
      @client.wait_for do |event_name, event_params|
        event_name == "Page.frameStoppedLoading" && event_params["frameId"] == response["frameId"]
      end
    end
  end

  @processed_requests_count += 1
  logger.info "Finished request: #{url}" if options[:enable_logger]
end

#has_css?(selector, wait: 0) ⇒ Boolean



120
121
122
123
124
125
126
127
128
# File 'lib/rubium/browser.rb', line 120

def has_css?(selector, wait: 0)
  timer = 0
  until current_response.at_css(selector)
    return false if timer >= wait
    timer += 0.2 and sleep 0.2
  end

  true
end

#has_text?(text, wait: 0) ⇒ Boolean



130
131
132
133
134
135
136
137
138
# File 'lib/rubium/browser.rb', line 130

def has_text?(text, wait: 0)
  timer = 0
  until body&.include?(text)
    return false if timer >= wait
    timer += 0.2 and sleep 0.2
  end

  true
end

#has_xpath?(path, wait: 0) ⇒ Boolean



110
111
112
113
114
115
116
117
118
# File 'lib/rubium/browser.rb', line 110

def has_xpath?(path, wait: 0)
  timer = 0
  until current_response.at_xpath(path)
    return false if timer >= wait
    timer += 0.2 and sleep 0.2
  end

  true
end

#restart!Object



44
45
46
47
48
49
# File 'lib/rubium/browser.rb', line 44

def restart!
  logger.info "Restarting..." if options[:enable_logger]

  close
  create_browser
end

#send_key_on(selector, key) ⇒ Object



148
149
150
151
152
153
154
155
156
# File 'lib/rubium/browser.rb', line 148

def send_key_on(selector, key)
  @client.send_cmd "Runtime.evaluate", expression: "    document.querySelector(`\#{selector}`).dispatchEvent(\n      new KeyboardEvent(\"keydown\", {\n        bubbles: true, cancelable: true, keyCode: \#{key}\n      })\n    );\n  js\nend\n"

#set_cookies(cookies) ⇒ Object



173
174
175
# File 'lib/rubium/browser.rb', line 173

def set_cookies(cookies)
  @client.send_cmd "Network.setCookies", cookies: cookies
end