Class: Unmagic::Browser

Inherits:
Object
  • Object
show all
Defined in:
lib/unmagic/browser.rb,
lib/unmagic/browser.rb,
lib/unmagic/browser/error.rb,
lib/unmagic/browser/driver.rb,
lib/unmagic/browser/console.rb,
lib/unmagic/browser/element.rb,
lib/unmagic/browser/locator.rb,
lib/unmagic/browser/session.rb,
lib/unmagic/browser/version.rb,
lib/unmagic/browser/failures.rb,
lib/unmagic/browser/markdown.rb,
lib/unmagic/browser/emulation.rb,
lib/unmagic/browser/driver/base.rb,
lib/unmagic/browser/driver/local.rb,
lib/unmagic/browser/configuration.rb,
lib/unmagic/browser/driver/remote.rb,
lib/unmagic/browser/console/banner.rb,
lib/unmagic/browser/console/prompt.rb,
lib/unmagic/browser/console/values.rb,
lib/unmagic/browser/console/helpers.rb,
lib/unmagic/browser/console/graphics.rb,
lib/unmagic/browser/console/renderer.rb,
lib/unmagic/browser/console/terminal.rb,
lib/unmagic/browser/driver/cloudflare.rb,
lib/unmagic/browser/driver/connection.rb,
lib/unmagic/browser/driver/cloudflare/transport.rb

Overview

A real browser you can drive from Ruby — for one-off page grabs and multi-step automation.

The same API runs against local Chrome, any remote Puppeteer endpoint, and Cloudflare Browser Rendering. Which one is a construction-time decision; nothing else in your code changes.

There are two ways in. Call #markdown, #html, #screenshot or #pdf straight on the browser for "just get me this page", and each takes the cheapest path its driver offers. Call #open for anything with more than one step, and you get a Session — a live page with Capybara-flavoured verbs that auto-wait.

Examples:

One-off

Unmagic::Browser.new.markdown("https://example.com")

Multi-step

Unmagic::Browser.open("https://news.ycombinator.com/login") do |session|
  session.fill_in "acct", with: "pg"
  session.click_button "login"
  session.wait_for text: "logout"
end

Defined Under Namespace

Modules: Console, Driver, Failures, Markdown Classes: Configuration, Element, Emulation, Error, Locator, Session

Constant Summary collapse

DEVELOPMENT =

Environment names that mean "someone is sitting at this machine", where a local Chrome you can watch beats a remote one you can't.

["development", "dev", "test"].freeze
VERSION =

The gem's version.

"0.1.0"

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(driver: nil, timeout: nil, navigation_timeout: nil) ⇒ Browser

Returns a new instance of Browser.

Parameters:



115
116
117
118
119
# File 'lib/unmagic/browser.rb', line 115

def initialize(driver: nil, timeout: nil, navigation_timeout: nil)
  @driver = Driver.build(driver || default_driver)
  @timeout = timeout
  @navigation_timeout = navigation_timeout
end

Instance Attribute Details

#driverDriver::Base (readonly)

The driver doing the real work. The mirror of the driver: option: you pick one when you construct the browser, and this hands the instance back for anything the curated API doesn't wrap.

Returns:



107
108
109
# File 'lib/unmagic/browser.rb', line 107

def driver
  @driver
end

Class Method Details

.configurationConfiguration

Returns the current global defaults.

Returns:



69
70
71
# File 'lib/unmagic/browser.rb', line 69

def configuration
  @configuration ||= Configuration.new
end

.configure {|config| ... } ⇒ Configuration

Set the gem's global defaults.

Examples:

Unmagic::Browser.configure do |config|
  config.default_driver = :cloudflare
end

Yield Parameters:

Returns:



63
64
65
66
# File 'lib/unmagic/browser.rb', line 63

def configure
  yield(configuration) if block_given?
  configuration
end

.development?Boolean

Whether this process looks like somebody's machine rather than a server. Checked only when no driver was asked for.

Returns:

  • (Boolean)


94
95
96
97
98
99
# File 'lib/unmagic/browser.rb', line 94

def development?
  return Rails.env.development? || Rails.env.test? if defined?(Rails) && Rails.respond_to?(:env) && Rails.env

  environment = ENV["RAILS_ENV"] || ENV["RACK_ENV"] || ENV["APP_ENV"]
  environment.nil? || DEVELOPMENT.include?(environment)
end

.open(url, **options) {|session| ... } ⇒ Session, Object

Shorthand for Unmagic::Browser.new.open(url).

Parameters:

  • url (String)

    the page to open

  • options (Hash)

    see #open

Yield Parameters:

Returns:

  • (Session, Object)

    the session, or the block's value



86
87
88
# File 'lib/unmagic/browser.rb', line 86

def open(url, **options, &block)
  new.open(url, **options, &block)
end

.reset!void

This method returns an undefined value.

Throw the configuration away. Mostly for tests.



76
77
78
# File 'lib/unmagic/browser.rb', line 76

def reset!
  @configuration = Configuration.new
end

Instance Method Details

#closevoid

This method returns an undefined value.

Release the shared browser one-off grabs run on. Sessions are unaffected — each holds its own.



182
183
184
# File 'lib/unmagic/browser.rb', line 182

def close
  @driver.close
end

#html(url) ⇒ String

Returns the page's HTML, after JavaScript has run.

Parameters:

  • url (String)

    the page to render

Returns:

  • (String)

    the page's HTML, after JavaScript has run



129
130
131
# File 'lib/unmagic/browser.rb', line 129

def html(url)
  @driver.html(url)
end

#inspectString

Returns the browser and the driver behind it.

Returns:

  • (String)

    the browser and the driver behind it



187
188
189
# File 'lib/unmagic/browser.rb', line 187

def inspect
  "#<#{self.class.name} driver=#{@driver.name}>"
end

#markdown(url) ⇒ String

Returns the page as Markdown.

Parameters:

  • url (String)

    the page to render

Returns:

  • (String)

    the page as Markdown



123
124
125
# File 'lib/unmagic/browser.rb', line 123

def markdown(url)
  @driver.markdown(url)
end

#open(url = nil, emulate: nil, timeout: nil, navigation_timeout: nil) {|session| ... } ⇒ Session, Object

Open a page you can drive step by step.

Works like File.open: with a block you get a session already on that page, cleaned up when the block ends. Without one, the session is yours to keep — and yours to Unmagic::Browser::Session#close, because it holds a real browser (and on Cloudflare, one of a limited number of concurrent slots) until you do.

Parameters:

  • url (String, nil) (defaults to: nil)

    the page to start on, or nil for a blank one

  • emulate (Emulation, Hash, nil) (defaults to: nil)

    how the page should render

  • timeout (Numeric, nil) (defaults to: nil)

    seconds a locator waits in this session

  • navigation_timeout (Numeric, nil) (defaults to: nil)

    seconds a navigation is given in this session

Yield Parameters:

Returns:

  • (Session, Object)

    the session, or the block's value



160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
# File 'lib/unmagic/browser.rb', line 160

def open(url = nil, emulate: nil, timeout: nil, navigation_timeout: nil)
  session = start_session(emulate: emulate, timeout: timeout, navigation_timeout: navigation_timeout)
  begin
    session.visit(url) if url
  rescue StandardError
    session.close
    raise
  end

  return session unless block_given?

  begin
    yield(session)
  ensure
    session.close
  end
end

#pdf(url) ⇒ String

Returns PDF bytes.

Parameters:

  • url (String)

    the page to render

Returns:

  • (String)

    PDF bytes



143
144
145
# File 'lib/unmagic/browser.rb', line 143

def pdf(url)
  @driver.pdf(url)
end

#screenshot(url, full_page: false, selector: nil) ⇒ String

Returns PNG bytes.

Parameters:

  • url (String)

    the page to render

  • full_page (Boolean) (defaults to: false)

    capture the whole scrollable page

  • selector (String, nil) (defaults to: nil)

    capture just the first element matching this CSS

Returns:

  • (String)

    PNG bytes



137
138
139
# File 'lib/unmagic/browser.rb', line 137

def screenshot(url, full_page: false, selector: nil)
  @driver.screenshot(url, full_page: full_page, selector: selector)
end