It is Ruby clean and high-level API to Chrome. Runs headless by default, but you can configure it to run in a headful mode. All you need is Ruby and Chrome or Chromium. Ferrum connects to the browser by CDP protocol and there's no Selenium/WebDriver/ChromeDriver dependency. The emphasis was made on a raw CDP protocol because Chrome allows you to do so many things that are barely supported by WebDriver because it should have consistent design with other browsers.
Cuprite is a pure Ruby driver for Capybara based on Ferrum. If you are going to crawl sites you better use Ferrum or Vessel because you crawl, not test.
Vessel high-level web crawling framework based on Ferrum and Mechanize.
There's no official Chrome or Chromium package for Linux don't install it this
way because it's either outdated or unofficial, both are bad. Download it from
official source for Chrome or
Chromium.
Chrome binary should be in the PATH or BROWSER_PATH and you can pass it as an
option to browser instance see :browser_path in
Customization.
Add this to your Gemfile and run bundle install.
gem "ferrum"Navigate to a website and save a screenshot:
browser = Ferrum::Browser.new
browser.go_to("https://google.com")
browser.screenshot(path: "google.png")
browser.quitWhen you work with browser instance Ferrum creates and maintains a default page for you, in fact all the methods above
are sent to the page instance that is created in the default_context of the browser instance. You can interact
with a page created manually and this is preferred:
browser = Ferrum::Browser.new
page = browser.create_page
page.go_to("https://google.com")
input = page.at_xpath("//input[@name='q']")
input.focus.type("Ruby headless driver for Chrome", :Enter)
page.at_css("a > h3").text # => "rubycdp/ferrum: Ruby Chrome/Chromium driver - GitHub"
browser.quitEvaluate some JavaScript and get full width/height:
browser = Ferrum::Browser.new
page = browser.create_page
page.go_to("https://www.google.com/search?q=Ruby+headless+driver+for+Capybara")
width, height = page.evaluate <<~JS
[document.documentElement.offsetWidth,
document.documentElement.offsetHeight]
JS
# => [1024, 1931]
browser.quitDo any mouse movements you like:
# Trace a 100x100 square
browser = Ferrum::Browser.new
page = browser.create_page
page.go_to("https://google.com")
page.mouse
.move(x: 0, y: 0)
.down
.move(x: 0, y: 100)
.move(x: 100, y: 100)
.move(x: 100, y: 0)
.move(x: 0, y: 0)
.up
browser.quitIn docker as root you must pass the no-sandbox browser option:
Ferrum::Browser.new(browser_options: { 'no-sandbox': nil })It has also been reported that the Chrome process repeatedly crashes when running inside a Docker container on an M1 Mac preventing Ferrum from working. Ferrum should work as expected when deployed to a Docker container on a non-M1 Mac.
You can customize options with the following code in your test setup:
Ferrum::Browser.new(options)Hash
:headless (String | Boolean) - Set browser as headless or not, true by default. You can set "new" to support
new headless mode.:xvfb (Boolean) - Run browser in a virtual framebuffer, false by default.:flatten (Boolean) - Use one websocket connection to the browser and all the pages in flatten mode.:window_size (Array) - The dimensions of the browser window in which to
test, expressed as a 2-element array, e.g. [1024, 768]. Default: [1024, 768]:extensions (Array[String | Hash]) - An array of paths to files or JS
source code to be preloaded into the browser e.g.:
["/path/to/script.js", { source: "window.secret = 'top'" }]:logger (Object responding to puts) - When present, debug output is
written to this object.:slowmo (Integer | Float) - Set a delay in seconds to wait before sending command.
Useful companion of headless option, so that you have time to see changes.:timeout (Numeric) - The number of seconds we'll wait for a response when
communicating with browser. Default is 5.:js_errors (Boolean) - When true, JavaScript errors get re-raised in Ruby.:pending_connection_errors (Boolean) - When main frame is still waiting for slow responses while timeout is
reached PendingConnectionsError is raised. It's better to figure out why you have slow responses and fix or
block them rather than turn this setting off. Default is true.:browser_name (Symbol) - :chrome by default, only experimental support
for :firefox for now.:browser_path (String) - Path to Chrome binary, you can also set ENV
variable as BROWSER_PATH=some/path/chrome bundle exec rspec.:browser_options (Hash) - Additional command line options,
see them all
e.g. { "ignore-certificate-errors" => nil }:ignore_default_browser_options (Boolean) - Ferrum has a number of default
options it passes to the browser, if you set this to true then only
options you put in :browser_options will be passed to the browser,
except required ones of course.:port (Integer) - Remote debugging port for headless Chrome.:host (String) - Remote debugging address for headless Chrome.:url (String) - URL for a running instance of Chrome. If this is set, a
browser process will not be spawned.:ws_url (String) - Websocket url for a running instance of Chrome. If this is set, a
browser process will not be spawned. It's higher priority than :url, setting both doesn't make sense.:process_timeout (Integer) - How long to wait for the Chrome process to
respond on startup.:ws_max_receive_size (Integer) - How big messages to accept from Chrome
over the web socket, in bytes. Defaults to 64MB. Incoming messages larger
than this will cause a Ferrum::DeadBrowserError.:proxy (Hash) - Specify proxy settings, read more:save_path (String) - Path to save attachments with Content-Disposition header.:env (Hash) - Environment variables you'd like to pass through to the processStringNavigate page to.
String The url should include scheme unless you set base_url when
configuring driver.page.go_to("https://github.com/")Navigate to the previous page in history.
page.go_to("https://github.com/")
page.at_xpath("//a").click
page.backNavigate to the next page in history.
page.go_to("https://github.com/")
page.at_xpath("//a").click
page.back
page.forwardReload current page.
page.go_to("https://github.com/")
page.refreshStop all navigations and loading pending resources on the page
page.go_to("https://github.com/")
page.stopSet the position for the browser window
Hash
IntegerIntegerbrowser.position = { left: 10, top: 20 }Array<Integer>Get the position for the browser window
browser.position # => [10, 20]Set window bounds
Hash
IntegerIntegerIntegerIntegerStringbrowser.window_bounds = { left: 10, top: 20, width: 1024, height: 768, window_state: "normal" }Hash<String, Integer | String>Get window bounds
browser.window_bounds # => { "left": 0, "top": 1286, "width": 10, "height": 10, "windowState": "normal" }IntegerCurrent window id
browser.window_id # => 1Node | nilFind node by selector. Runs document.querySelector within the document or
provided node.
StringHash
Node | nilpage.go_to("https://github.com/")
page.at_css("a[aria-label='Issues you created']") # => NodeArray<Node> | []Find nodes by selector. The method runs document.querySelectorAll within the
document or provided node.
StringHash
Node | nilpage.go_to("https://github.com/")
page.css("a[aria-label='Issues you created']") # => [Node]Node | nilFind node by xpath.
StringHash
Node | nilpage.go_to("https://github.com/")
page.at_xpath("//a[@aria-label='Issues you created']") # => NodeArray<Node> | []Find nodes by xpath.
StringHash
Node | nilpage.go_to("https://github.com/")
page.xpath("//a[@aria-label='Issues you created']") # => [Node]StringReturns current top window location href.
page.go_to("https://google.com/")
page.current_url # => "https://www.google.com/"StringReturns current top window title
page.go_to("https://google.com/")
page.current_title # => "Google"StringReturns current page's html.
page.go_to("https://google.com/")
page.body # => '<html itemscope="" itemtype="http://schema.org/WebPage" lang="ru"><head>...String | IntegerSaves screenshot on a disk or returns it as base64.
Hash
String to save a screenshot on the disk. :encoding will be set to
:binary automaticallySymbol :base64 | :binary you can set it to return image as
Base64String "jpeg" ("jpg") | "png" | "webp"Integer 0-100 works for jpeg onlyBoolean whether you need full page screenshot or a viewportString css selector for given element, optionalHash area for screenshot, optional
IntegerIntegerIntegerIntegerFloat zoom in/outFerrum::RGBA.new(0, 0, 0, 0.0) to have specific background colorpage.go_to("https://google.com/")
# Save on the disk in PNG
page.screenshot(path: "google.png") # => 134660
# Save on the disk in JPG
page.screenshot(path: "google.jpg") # => 30902
# Save to Base64 the whole page not only viewport and reduce quality
page.screenshot(full: true, quality: 60, encoding: :base64) # "iVBORw0KGgoAAAANSUhEUgAABAAAAAMACAYAAAC6uhUNAAAAAXNSR0IArs4c6Q...
# Save on the disk with the selected element in PNG
page.screenshot(path: "google.png", selector: 'textarea') # => 11340
# Save to Base64 with an area of the page in PNG
page.screenshot(path: "google.png", area: { x: 0, y: 0, width: 400, height: 300 }) # => 54239
# Save with specific background color
page.screenshot(background_color: Ferrum::RGBA.new(0, 0, 0, 0.0))String | BooleanSaves PDF on a disk or returns it as base64.
Hash
:path String to save a pdf on the disk. :encoding will be set to
:binary automatically
:encoding Symbol :base64 | :binary you can set it to return pdf as
Base64
:landscape Boolean paper orientation. Defaults to false.
:scale Float zoom in/out
:format symbol standard paper sizes :letter, :legal, :tabloid, :ledger, :A0, :A1, :A2, :A3, :A4, :A5, :A6
:paper_width Float set paper width
:paper_height Float set paper height
See other native options you can pass
page.go_to("https://google.com/")
# Save to disk as a PDF
page.pdf(path: "google.pdf", paper_width: 1.0, paper_height: 1.0) # => trueString | IntegerSaves MHTML on a disk or returns it as a string.
Hash
String to save a file on the disk.page.go_to("https://google.com/")
page.mhtml(path: "google.mhtml") # => 87742page.network
Array<Network::Exchange>Returns all information about network traffic as Network::Exchange instance
which in general is a wrapper around request, response and error.
page.go_to("https://github.com/")
page.network.traffic # => [#<Ferrum::Network::Exchange, ...]Network::RequestPage request of the main frame.
page.go_to("https://github.com/")
page.network.request # => #<Ferrum::Network::Request...Network::ResponsePage response of the main frame.
page.go_to("https://github.com/")
page.network.response # => #<Ferrum::Network::Response...IntegerContains the status code of the main page response (e.g., 200 for a
success). This is just a shortcut for response.status.
page.go_to("https://github.com/")
page.network.status # => 200BooleanWaits for network idle, returns true in case of success and false if there are still connections.
Hash
Integer how many connections are allowed for network to be
idling, 0 by defaultFloat sleep for given amount of time and check again, 0.05 by
defaultFloat during what time we try to check idle, browser.timeout
by defaultpage.go_to("https://example.com/")
page.at_xpath("//a[text() = 'No UI changes button']").click
page.network.wait_for_idle # => trueWaits for network idle or raises Ferrum::TimeoutError error. Accepts same arguments as wait_for_idle.
page.go_to("https://example.com/")
page.at_xpath("//a[text() = 'No UI changes button']").click
page.network.wait_for_idle! # might raise an errorClear page's cache or collected traffic.
Symbol it is either :traffic or :cachetraffic = page.network.traffic # => []
page.go_to("https://github.com/")
traffic.size # => 51
page.network.clear(:traffic)
traffic.size # => 0Set request interception for given options. This method is only sets request
interception, you should use on callback to catch requests and abort or
continue them.
Hash
String * by defaultSymbol one of the resource typesbrowser = Ferrum::Browser.new
page = browser.create_page
page.network.intercept
page.on(:request) do |request|
if request.match?(/bla-bla/)
request.abort
elsif request.match?(/lorem/)
request.respond(body: "Lorem ipsum")
else
request.continue
end
end
page.go_to("https://google.com")If site or proxy uses authorization you can provide credentials using this method.
Hash
Symbol :server | :proxy site or proxy authorizationStringStringrequest.continue.page.network.authorize(user: "login", password: "pass") { |req| req.continue }
page.go_to("http://example.com/authenticated")
puts page.network.status # => 200
puts page.body # => Welcome, authenticated clientSince Chrome implements authorize using request interception you must continue or abort authorized requests. If you
already have code that uses interception you can use authorize without block, but if not you are obliged to pass
block, so this is version doesn't pass block and can work just fine:
browser = Ferrum::Browser.new
page = browser.create_page
page.network.intercept
page.on(:request) do |request|
if request.resource_type == "Image"
request.abort
else
request.continue
end
end
page.network.authorize(user: "login", password: "pass", type: :proxy)
page.go_to("https://google.com")You used to call authorize method without block, but since it's implemented using request interception there could be
a collision with another part of your code that also uses request interception, so that authorize allows the request
while your code denies but it's too late. The block is mandatory now.
Activates emulation of network conditions.
Hash
Boolean emulate internet disconnection, false by defaultInteger minimum latency from request sent to response headers received (ms), 0 by
defaultInteger maximal aggregated download throughput (bytes/sec), -1
by default, disables download throttlingInteger maximal aggregated upload throughput (bytes/sec), -1
by default, disables download throttlingString connection type if known, one of: none, cellular2g, cellular3g, cellular4g,
bluetooth, ethernet, wifi, wimax, other. nil by defaultpage.network.emulate_network_conditions(connection_type: "cellular2g")
page.go_to("https://github.com/")Activates offline mode for a page.
page.network.offline_mode
page.go_to("https://github.com/") # => Ferrum::StatusError (Request to https://github.com/ failed(net::ERR_INTERNET_DISCONNECTED))Boolean)Toggles ignoring cache for each request. If true, cache will not be used.
page.network.cache(disable: true)page.downloads
Array<Hash>Returns all information about downloaded files as a Hash.
page.go_to("http://localhost/attachment.pdf")
page.downloads.files # => [{"frameId"=>"E3316DF1B5383D38F8ADF7485005FDE3", "guid"=>"11a68745-98ac-4d54-9b57-9f9016c268b3", "url"=>"http://localhost/attachment.pdf", "suggestedFilename"=>"attachment.pdf", "totalBytes"=>4911, "receivedBytes"=>4911, "state"=>"completed"}]Waits until the download is finished.
page.go_to("http://localhost/attachment.pdf")
page.downloads.waitor
page.go_to("http://localhost/page")
page.downloads.wait { page.at_css("#download").click }Sets behavior in case of file to be downloaded.
Hash
String absolute path of where to store the fileSymbol deny | allow | allowAndName | default, allow by defaultpage.go_to("https://example.com/")
page.downloads.set_behavior(save_path: "/tmp", behavior: :allow)You can set a proxy with a :proxy option:
Ferrum::Browser.new(proxy: { host: "x.x.x.x", port: "8800", user: "user", password: "pa$$" }):bypass can specify semi-colon-separated list of hosts for which proxy shouldn't be used:
Ferrum::Browser.new(proxy: { host: "x.x.x.x", port: "8800", bypass: "*.google.com;*foo.com" })In general passing a proxy option when instantiating a browser results in a browser running with proxy command line flags, so that it affects all pages and contexts. You can create a page in a new context which can use its own proxy settings:
browser = Ferrum::Browser.new
browser.create_page(proxy: { host: "x.x.x.x", port: 31337, user: "user", password: "password" }) do |page|
page.go_to("https://api.ipify.org?format=json")
page.body # => "x.x.x.x"
end
browser.create_page(proxy: { host: "y.y.y.y", port: 31337, user: "user", password: "password" }) do |page|
page.go_to("https://api.ipify.org?format=json")
page.body # => "y.y.y.y"
endpage.mouse
Scroll page to a given x, y
Integer the pixel along the horizontal axis of the document that you
want displayed in the upper leftInteger the pixel along the vertical axis of the document that you want
displayed in the upper leftpage.go_to("https://www.google.com/search?q=Ruby+headless+driver+for+Capybara")
page.mouse.scroll_to(0, 400)MouseClick given coordinates, fires mouse move, down and up events.
Hash
IntegerIntegerFloat defaults to 0. Delay between mouse down and mouse up eventsSymbol :left | :right, defaults to :leftInteger defaults to 1Integer bitfield for key modifiers. Seekeyboard.modifiersMouseMouse down for given coordinates.
Hash
Symbol :left | :right, defaults to :leftInteger defaults to 1Integer bitfield for key modifiers. Seekeyboard.modifiersMouseMouse up for given coordinates.
Hash
Symbol :left | :right, defaults to :leftInteger defaults to 1Integer bitfield for key modifiers. Seekeyboard.modifiersMouseMouse move to given x and y.
Hash
IntegerIntegerInteger defaults to 1. Sends intermediate mousemove events.page.keyboard
KeyboardDispatches a keydown event.
String | Symbol Name of key such as "a", :enter, :backspaceKeyboardDispatches a keyup event.
String | Symbol Name of key such as "b", :enter, :backspaceKeyboardSends a keydown, keypress/input, and keyup event for each character in the text.
String | Array<String> | Array<Symbol> A text to type into a focused
element, [:Shift, "s"], "tring"IntegerReturns bitfield for a given keys
Array<Symbol> :alt | :ctrl | :command | :shiftpage.cookies
Hash<String, Cookie>Returns cookies hash
page.cookies.all # => {"NID"=>#<Ferrum::Cookies::Cookie:0x0000558624b37a40 @attributes={"name"=>"NID", "value"=>"...", "domain"=>".google.com", "path"=>"/", "expires"=>1583211046.575681, "size"=>178, "httpOnly"=>true, "secure"=>false, "session"=>false}>}CookieReturns cookie
Stringpage.cookies["NID"] # => <Ferrum::Cookies::Cookie:0x0000558624b67a88 @attributes={"name"=>"NID", "value"=>"...", "domain"=>".google.com", "path"=>"/", "expires"=>1583211046.575681, "size"=>178, "httpOnly"=>true, "secure"=>false, "session"=>false}>BooleanSets a cookie
Hash
StringStringStringIntegerStringBooleanpage.cookies.set(name: "stealth", value: "omg", domain: "google.com") # => trueCookienid_cookie = page.cookies["NID"] # => <Ferrum::Cookies::Cookie:0x0000558624b67a88>
page.cookies.set(nid_cookie) # => trueBooleanRemoves given cookie
Hash
StringStringStringpage.cookies.remove(name: "stealth", domain: "google.com") # => trueBooleanRemoves all cookies for current page
page.cookies.clear # => trueBooleanStores all cookies of current page in a file.
# Cookies are saved into cookies.yml
page.cookies.store # => 15657BooleanLoads all cookies from the file and sets them for current page.
# Cookies are loaded from cookies.yml
page.cookies.load # => truepage.headers
HashGet all headers
BooleanSet given headers. Eventually clear all headers and set given ones.
Hash key-value pairs for example "User-Agent" => "Browser"BooleanAdds given headers to already set ones.
Hash key-value pairs for example "Referer" => "http://example.com"BooleanClear all headers.
Evaluate and return result for given JS expression
String should be valid JavaScriptObject you can pass arguments, though it should be a valid Node or a
simple value.page.evaluate("[window.scrollX, window.scrollY]")Evaluate asynchronous expression and return result
String should be valid JavaScriptObject you can pass arguments, though it should be a valid Node or a
simple value.page.evaluate_async(%(arguments[0]({foo: "bar"})), 5) # => { "foo" => "bar" }Execute expression. Doesn't return the result
String should be valid JavaScriptObject you can pass arguments, though it should be a valid Node or a
simple value.page.execute(%(1 + 1)) # => trueEvaluate JavaScript to modify things before a page load
String should be valid JavaScriptbrowser.evaluate_on_new_document <<~JS
Object.defineProperty(navigator, "languages", {
get: function() { return ["tlh"]; }
});
JSBooleanHash
StringStringStringString - text/javascript by defaultpage.add_script_tag(url: "http://example.com/stylesheet.css") # => trueBooleanHash
StringStringStringpage.add_style_tag(content: "h1 { font-size: 40px; }") # => trueBooleanHash
Boolean, true by defaultpage.bypass_csp # => true
page.go_to("https://github.com/ruby-concurrency/concurrent-ruby/blob/master/docs-source/promises.in.md")
page.refresh
page.add_script_tag(content: "window.__injected = 42")
page.evaluate("window.__injected") # => 42Disables Javascripts from the loaded HTML source.
You can still evaluate JavaScript with evaluate or execute.
Returns nothing.
page.disable_javascriptOverrides device screen dimensions and emulates viewport.
Hash
Integer, viewport width. 0 by defaultInteger, viewport height. 0 by defaultFloat, device scale factor. 0 by defaultBoolean, whether to emulate mobile device. false by defaultpage.set_viewport(width: 1000, height: 600, scale_factor: 3)Array[Frame] | []Returns all the frames current page have.
page.go_to("https://www.w3schools.com/tags/tag_frame.asp")
page.frames # =>
# [
# #<Ferrum::Frame @id="C6D104CE454A025FBCF22B98DE612B12" @parent_id=nil @name=nil @state=:stopped_loading @execution_id=1>,
# #<Ferrum::Frame @id="C09C4E4404314AAEAE85928EAC109A93" @parent_id="C6D104CE454A025FBCF22B98DE612B12" @state=:stopped_loading @execution_id=2>,
# #<Ferrum::Frame @id="2E9C7F476ED09D87A42F2FEE3C6FBC3C" @parent_id="C6D104CE454A025FBCF22B98DE612B12" @state=:stopped_loading @execution_id=3>,
# ...
# ]FrameReturns page's main frame, the top of the tree and the parent of all frames.
Frame | nilFind frame by given options.
Hash
String - Unique frame's id that browser providesString - Frame's name if there's onepage.frame_by(id: "C6D104CE454A025FBCF22B98DE612B12")StringFrame's unique id.
String | nilParent frame id if this one is nested in another one.
IntegerExecution context id which is used by JS, each frame has it's own context in which JS evaluates.
String | nilIf frame was given a name it should be here.
Symbol | nilOne of the states frame's in:
:started_loading:navigated:stopped_loadingStringReturns current frame's location href.
page.go_to("https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe")
frame = page.frames[1]
frame.url # => https://interactive-examples.mdn.mozilla.net/pages/tabbed/iframe.htmlReturns current frame's title.
page.go_to("https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe")
frame = page.frames[1]
frame.title # => HTML Demo: <iframe>BooleanIf current frame is the main frame of the page (top of the tree).
page.go_to("https://www.w3schools.com/tags/tag_frame.asp")
frame = page.frame_by(id: "C09C4E4404314AAEAE85928EAC109A93")
frame.main? # => falseStringReturns current frame's top window location href.
page.go_to("https://www.w3schools.com/tags/tag_frame.asp")
frame = page.frame_by(id: "C09C4E4404314AAEAE85928EAC109A93")
frame.current_url # => "https://www.w3schools.com/tags/tag_frame.asp"StringReturns current frame's top window title.
page.go_to("https://www.w3schools.com/tags/tag_frame.asp")
frame = page.frame_by(id: "C09C4E4404314AAEAE85928EAC109A93")
frame.current_title # => "HTML frame tag"StringReturns current frame's html.
page.go_to("https://www.w3schools.com/tags/tag_frame.asp")
frame = page.frame_by(id: "C09C4E4404314AAEAE85928EAC109A93")
frame.body # => "<html><head></head><body></body></html>"Returns current frame's doctype.
page.go_to("https://www.w3schools.com/tags/tag_frame.asp")
page.main_frame.doctype # => "<!DOCTYPE html>"Sets a content of a given frame.
Stringpage.go_to("https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe")
frame = page.frames[1]
frame.body # <html lang="en"><head><style>body {transition: opacity ease-in 0.2s; }...
frame.content = "<html><head></head><body><p>lol</p></body></html>"
frame.body # => <html><head></head><body><p>lol</p></body></html>Accept dialog with given text or default prompt if applicable
StringDismiss dialog
page.on(:dialog) do |dialog|
if dialog.match?(/bla-bla/)
dialog.accept
else
dialog.dismiss
end
end
page.go_to("https://google.com")You can slow down or speed up CSS animations.
IntegerReturns playback rate for CSS animations, defaults to 1.
Sets playback rate of CSS animations
Integerpage.playback_rate = 2000
page.go_to("https://google.com")
page.playback_rate # => 2000BooleanFrameReturns Frame object for current node, you can keep using Finders for that object:
frame = page.at_xpath("//iframe").frame # => Frame
frame.at_css("//a[text() = 'Log in']") # => NodeBooleanArray<Node>Node | nil) : Boolean(chainable) Selects options by passed attribute.
page.at_xpath("//*[select]").select(["1"]) # => Node (select)
page.at_xpath("//*[select]").select(["text"], by: :text) # => Node (select)Accept string, array or strings:
page.at_xpath("//*[select]").select("1")
page.at_xpath("//*[select]").select("1", "2")
page.at_xpath("//*[select]").select(["1", "2"])You can use tracing.record to create a trace file which can be opened in Chrome DevTools or
timeline viewer.
page.tracing.record(path: "trace.json") do
page.go_to("https://www.google.com")
endStringAccepts block, records trace and by default returns trace data from Tracing.tracingComplete event as output. When
path is specified returns true and stores trace data into file.
Hash
String save data on the disk, nil by defaultSymbol :base64 | :binary encode output as Base64 or plain text. :binary by defaultFloat wait until file streaming finishes in the specified time or raise error, defaults to nilBoolean capture screenshots in the trace, false by defaultHash<String, Object> config for
trace, for categories
see getCategories,
only one trace config can be active at a time per browser.Closes browser tabs opened by the Browser instance.
# connect to a long-running Chrome process
browser = Ferrum::Browser.new(url: 'http://localhost:9222')
browser.go_to("https://github.com/")
# clean up, lest the tab stays there hanging forever
browser.reset
browser.quitFerrum is fully thread-safe. You can create one browser or a few as you wish and start playing around using threads. Example below shows how to create a few pages which share the same context. Context is similar to an incognito profile but you can have more than one, think of it like it's independent browser session:
browser = Ferrum::Browser.new
context = browser.contexts.create
t1 = Thread.new(context) do |c|
page = c.create_page
page.go_to("https://www.google.com/search?q=Ruby+headless+driver+for+Capybara")
page.screenshot(path: "t1.png")
end
t2 = Thread.new(context) do |c|
page = c.create_page
page.go_to("https://www.google.com/search?q=Ruby+static+typing")
page.screenshot(path: "t2.png")
end
t1.join
t2.join
context.dispose
browser.quitor you can create two independent contexts:
browser = Ferrum::Browser.new
t1 = Thread.new(browser) do |b|
context = b.contexts.create
page = context.create_page
page.go_to("https://www.google.com/search?q=Ruby+headless+driver+for+Capybara")
page.screenshot(path: "t1.png")
context.dispose
end
t2 = Thread.new(browser) do |b|
context = b.contexts.create
page = context.create_page
page.go_to("https://www.google.com/search?q=Ruby+static+typing")
page.screenshot(path: "t2.png")
context.dispose
end
t1.join
t2.join
browser.quitAfter checking out the repo, run bundle install to install dependencies.
Then, run bundle exec rake test to run the tests. You can also run bin/console for an interactive prompt that will
allow you to experiment.
To install this gem onto your local machine, run bundle exec rake install. To release a new version, update the
version number in version.rb, and then run bundle exec rake release, which will create a git tag for the version,
push git commits and the created tag, and push the .gem file to rubygems.org.
Bug reports and pull requests are welcome on GitHub.
The gem is available as open source under the terms of the MIT License.