Cuprite Documentation

repository·main·Indexed 23 days ago

https://github.com/rubycdp/cuprite

A pure Ruby headless Chrome driver for Capybara that uses the Chrome DevTools Protocol (CDP) via the Ferrum library, eliminating the need for Selenium or ChromeDriver. It provides advanced capabilities for network traffic inspection, cookie management, HTTP header manipulation, and low-level browser interactions such as coordinate-based clicking, scrolling, and drag-and-drop operations.

Tokens
5.1K
Snippets
12
Records
42
Agent score
79%

What's inside Cuprite

  1. Install Cuprite for Capybara

    main

    Add cuprite to your Gemfile within the :test group and run bundle install. To use it with Capybara, require capybara/cuprite, set the javascript_driver to :cuprite, and register the driver. If running in a Docker environment, you must pass the no-sandbox option via browser_options.

    # Gemfile
    group :test do
      gem "cuprite"
    end

    Test Setup

    require "capybara/cuprite" Capybara.javascript_driver = :cuprite Capybara.register_driver(:cuprite) do |app| Capybara::Cuprite::Driver.new(app, window_size: [1200, 800]) end

    Docker Setup

    Capybara::Cuprite::Driver.new(app, browser_options: { 'no-sandbox': nil })

  2. Debug tests with page.driver.debug

    main

    To pause test execution and inspect the browser state, use page.driver.debug. You can pass a binding to open an irb or pry console in your terminal while the browser remains open in a new tab. This allows you to interact with the page and experiment with the test state live.

    it "does something useful" do
      visit root_path
    
      fill_in "field", with: "value"
      page.driver.debug(binding)
    
      expect(page).to have_content("value")
    end
  3. Configure Cuprite driver options

    main

    You can customize the driver by passing an options hash to Capybara::Cuprite::Driver.new.

    Cuprite-specific options include:

    • :url_blacklist (Array): An array of regexes to match against requested URLs to prevent them from loading.
    • :url_whitelist (Array): An array of regexes to match against requested URLs to allow only these to load.

    Note: For direct browser access, you can also use page.driver.browser.url_blocklist= and page.driver.browser.url_allowlist= with regexes.

  4. Inspect network traffic and wait for idle

    main

    Cuprite allows you to inspect network exchanges and manage synchronization with network activity:

    • page.driver.network_traffic: Returns an array of Ferrum::Network::Exchange objects representing requests and responses.
    • page.driver.wait_for_network_idle: Waits until there are no active network connections. Raises TimeoutError if it fails. Accepts options compatible with Ferrum's wait_for_idle.
    • page.driver.wait_for_reload: Waits specifically for a full page reload.
    • page.driver.clear_network_traffic: Manually clears the recorded traffic.
    • page.driver.reset: Resets the driver state.
  5. Perform low-level clicking and scrolling

    main

    Cuprite provides direct methods for precise interaction beyond standard Capybara selectors:

    • page.driver.click(x, y): Click a specific coordinate on the screen.
    • page.driver.scroll_to(left, top): Scroll to a specific position.
    • element.send_keys(*keys): Send keys to a specific node.
  6. Configure Authorization and Proxy

    main

    Cuprite provides methods for handling authentication and proxy settings:

    • page.driver.basic_authorize(user, password): Sets up Basic Authentication.
    • page.driver.set_proxy(ip, port, user, password): Configures a proxy server.
  7. Manage cookies

    main

    Use the following methods to interact with browser cookies:

    • page.driver.cookies: Returns a hash where keys are cookie names and values are Cookie objects (providing methods like .name, .value, .domain, .path, .secure?, .httponly?, .session?, .expires).
    • page.driver.set_cookie(name, value, options = {}): Sets a cookie. Options include :domain, :path, :secure, :httponly, and :expires (must be a Time object).
    • page.driver.remove_cookie(name): Removes a specific cookie.
    • page.driver.clear_cookies: Removes all cookies.
  8. Manipulate HTTP request headers

    main

    You can manage HTTP headers for all subsequent requests (including assets and AJAX) using the following methods:

    • page.driver.headers: Returns the current headers hash.
    • page.driver.headers = { "Key" => "Value" }: Overwrites all existing headers.
    • page.driver.add_headers("Key" => "Value"): Adds new headers without overwriting existing ones.

    Headers are automatically cleared at the end of the test.

    page.driver.headers = { "User-Agent" => "Cuprite" }
    page.driver.add_headers("Referer" => "https://example.com")
    # Result: { "User-Agent" => "Cuprite", "Referer" => "https://example.com" }
  9. Handle MouseEventFailed errors

    main

    A MouseEventFailed error occurs when Cuprite attempts to fire a mouse event (like a click) at a specific coordinate, but detects that another element with a different CSS selector is overlapping that position.

    To resolve this, you can either:

    1. Ensure the target element is not being obscured by another element.
    2. If overlapping elements are acceptable for your test, use node.trigger("event_name") instead of a standard click to bypass the overlap check.
  10. Handle ObsoleteNode errors

    main

    An ObsoleteNode error is raised when you attempt to interact with an element that is no longer part of the DOM or is currently invisible (e.g., display: none is set). This often happens when a page update or a JavaScript framework replaces an element with a new one.

    To fix this, perform a new find operation to obtain a fresh reference to the element currently in the DOM.

  11. Execute JavaScript in Cuprite

    main

    Use these methods to interact with the page via JavaScript:

    • evaluate_script(script, *args): Executes a script and returns the result. Arguments are automatically unwrapped from Cuprite nodes to native types.
    • evaluate_async_script(script, *args): Executes an asynchronous script, respecting the session's wait time.
    • execute_script(script, *args): Executes a script but returns nil (useful for side effects).