Capybara Cheatsheet

by Giang, last updated 18 Sep 2020


Different way to write predicates:

expect(page).to have_selector 'selector' # prefered method
page.should have_selector 'selector'
page.has_selector? 'selector'
page.assert_selector 'selector', count: 3
find('selector').text.should == 'something'

List of predicates

# User has_*? and has_no_*? if you use page.has_*?(selector) syntax
have_selector      | have_no_selector
have_css           | have_no_css
has_xpath          | has_no_xpath?
has_link?          | has_no_link?
has_button?        | has_no_button?
has_field?         | has_no_field?
has_checked_field? | has_unchecked_field?
has_table?         | has_no_table?
has_select?        | has_no_select?

Note: Avoid using should_not have_* or expect(page).not_to have_* in RSpec because they don't wait for timeout in from the driver.

Mouse emulator

Move mouse around. This seems only work with driver using CDP protocol such as cuprite

browser = page.driver.browser
browser.mouse.move(x: 123, y: 456).down.up

Click/Scroll, y) Click a very specific area of the screen.
page.driver.scroll_to(left, top) Scroll to a given position.
element.send_keys(*keys) Send keys to a given node.

Register a driver

The example below uses cuprite driver.

Capybara.register_driver(:cuprite) do |app|
    window_size: [1200, 800],
    browser_options: { "no-sandbox" => nil },
    # Increase Chrome startup wait time (required for stable CI builds)
    process_timeout: 10,
    # Enable debugging capabilities
    inspector: true,
    # Allow running Chrome in a headful mode by setting HEADLESS env
    # var to a falsey value
    headless: ENV.fetch('HEADLESS', 'true') == 'true'

# Configure Capybara to use :cuprite driver by default
Capybara.default_driver = Capybara.javascript_driver = :cuprite

URL whitelist and blacklist

Blacklist/Whitelist config tell Capybara to ignore unneccesary resources, reduce loading time for the site and thus improve testing speed as well as avoid timeout errors.

config.before :each, :js do
  page.driver.browser.url_blacklist = [
  ].flat_map { |domain| [ "http://#{domain}", "https://#{domain}" ] }
page.driver.browser.url_whitelist = ['']

Override Capybase screenshot_and_save_page

This snippet does 2 things:

  • Delete the HTML file and only keep the screenshot.
  • Rename the screenshot if filename argument is present.
module ScreenshotHelper

  # override Capybara#screenshot_and_save_page
  def screenshot_and_save_page(filename = nil)
    # {:html => saver.html_path, :image => saver.screenshot_path}
    result = super()


    if filename
      folder_path, _, _ = result[:image].rpartition('/')
      new_file = folder_path + '/' + filename + '.png'
      File.rename(result[:image], new_file)