Skip to main content

Ruby

Native adapter for Capybara and Selenium Ruby suites — no sidecar, no Chrome debug port, no wrapper around your test command. You run bundle exec rspec exactly as you do today.

New here? vs. rolling your own covers what this replaces in a hand-rolled screenshot setup.

Install

# Gemfile
gem "testivai", group: :test
bundle install

Capture

require "testivai"

RSpec.describe "Homepage", type: :feature do
it "looks right" do
visit "/"
Testivai.witness(page, "homepage")
end
end

Testivai.witness accepts a Capybara session (page), a Capybara driver, or a bare Selenium::WebDriver — it unwraps to the underlying browser itself.

Cucumber is the same call from a step definition:

Then("the page looks correct") do
Testivai.witness(page, "checkout")
end

Compare

bundle exec rspec     # your suite, unchanged — captures land in .testivai/temp/
npx testivai report # diff against baselines + write the HTML report

The first run creates baselines under .testivai/baselines/ — commit them. Later runs diff against them and write visual-report/index.html.

Why Node for the report?

Capture is native Ruby. The diff engine, tolerances, and HTML report are shared by every adapter and live in @testivai/witness — one comparison implementation rather than five subtly different ones. The Python and Java adapters split the same way. If a project has no Node, run npx --yes @testivai/witness report.

Options

Testivai.witness(page, "checkout",
ignore_selectors: [".live-chat", "#clock"], # hidden from pixels AND the DOM signal
stabilize: true, # freeze animations, hide caret, await web fonts
skip_dom: false, # the DOM snapshot powers the noise hint
skip_element_map: false,# the element map powers selector attribution
max_elements: 3000, # cap for very large pages
project_root: nil) # defaults to the nearest ancestor holding .testivai/

Anything omitted falls back to .testivai/config.json, the same file every other adapter reads.

What gets captured

FilePowers
screenshot.pngThe pixel diff and heatmap
dom.htmlNoise hint, text-change detection
elements.jsonRegion→selector attribution, shift detection, style checks

Full-page capture uses Chromium's CDP captureBeyondViewport when the driver exposes execute_cdp, Firefox's native full-page screenshot when available, and falls back to a viewport capture otherwise — documented, never silent.

The element-map collector is generated from a single TypeScript source shared by every TestivAI adapter, so a Ruby lane and a Python lane produce identical maps against the same baselines.

DOM and element-map capture are both best-effort: if a strict Content-Security-Policy blocks the injected script, the screenshot still lands and the report falls back to the layers it does have.

Driver notes

Works with any Capybara driver that exposes execute_scriptselenium (Chrome, Firefox, Safari), Cuprite, Apparition. Rack-test has no browser and cannot produce screenshots; use a real driver for visual specs:

RSpec.describe "Homepage", type: :feature, js: true do

Selenium · Python · Java