Skip to content

Web snapshots

A web target captures a structured DOM snapshot. By default it uses a zero-dependency fetch (no browser required); an optional Playwright driver adds browser-rendered DOM, accessibility snapshots, and screenshots.

Configure a target

Fetch a live URL:

json
{ "kind": "web", "name": "home", "url": "http://localhost:3000" }

Or snapshot a static HTML fixture:

json
{ "kind": "web", "name": "home", "html": "fixtures/home.html" }

Options:

  • url — fetch and snapshot a live page (default driver, no browser needed).
  • html — path to a local HTML fixture to snapshot instead of fetching.
  • driver — set to "playwright" for browser-backed capture (below).
  • timeoutMs — per-target timeout; falls back to lifecycle.wait.timeoutMs.

The default fetch driver does not require a browser install.

How it's compared

DOM uses a structural tree diff that aligns nodes by tag/id and reports node-level changes — added, removed, moved, tag-changed, text-changed, and per-attribute changes — without cascading on a single insertion. A semantic text change reads as "Stable" → "Changed" rather than a line diff.

Playwright driver

Use Playwright mode when you need browser-rendered DOM, accessibility snapshots, or screenshot fallback data:

json
{
  "kind": "web",
  "name": "browser-home",
  "driver": "playwright",
  "url": "http://127.0.0.1:4173",
  "accessibility": true,
  "screenshot": true,
  "browser": { "channel": "chrome" },
  "viewport": { "width": 1280, "height": 720 }
}

The resulting baseline stores the structured DOM; when enabled, accessibility and screenshot fallback data are included in the captured snapshot artifact.

Browser setup

Dungbeetle depends on playwright-core, so it does not download browsers during install. Provide a Chromium browser in one of three ways:

  1. A system browser channel:

    json
    { "browser": { "channel": "chrome" } }
  2. An explicit executable path:

    json
    { "browser": { "executablePath": "/path/to/chromium" } }
  3. An environment variable:

    sh
    export DUNGBEETLE_CHROMIUM_EXECUTABLE_PATH=/path/to/chromium

Run dungbeetle doctor before updating baselines. If it reports a warning for browser.channel, make sure that channel is installed on the machine running Dungbeetle. If it reports a missing executable, correct the path or remove it and use a supported channel instead.

Screenshots

Screenshots are stored as a content digest in the baseline (with the PNG written alongside) and compared with a tolerant pixel diff when the digests differ. Tune comparison.pixelTolerance — see Comparison tolerances. A failing web test embeds before/after screenshots in the HTML report.

Visual comparison

Two per-target knobs control how screenshot changes are judged:

  • pixelTolerance — this target's own tolerance ({ "maxChangedRatio": …, "perChannelThreshold": … }), overriding the global comparison.pixelTolerance. Useful when one page is noisier than the rest.
  • screenshotMode"strict" (default): a pixel diff beyond tolerance fails the run like any other change. "advisory": the DOM is the gate — screenshot changes are reported in the diff but don't fail.
json
{
  "kind": "web",
  "name": "home",
  "driver": "playwright",
  "url": "http://127.0.0.1:8000",
  "screenshot": true,
  "pixelTolerance": { "maxChangedRatio": 0.01 },
  "screenshotMode": "strict"
}

Ingest existing screenshots (Dusk, browser tests)

A web target can also snapshot a PNG your browser tests already produce — no page capture, the image is the whole snapshot. Laravel Dusk writes screenshots to tests/Browser/screenshots/; baseline them directly:

json
{
  "kind": "web",
  "name": "dusk-dashboard",
  "screenshotFile": "tests/Browser/screenshots/dashboard.png",
  "pixelTolerance": { "maxChangedRatio": 0.005 }
}

Run your Dusk suite first, then dungbeetle test — a visual regression fails with a pixel summary (~ screenshot: 312/16384 pixels changed (1.90%)) and the before/after pair lands in the HTML report and the cloud review UI. doctor warns (rather than fails) when the screenshot file hasn't been produced yet.

See also

Source-available: CLI under FSL-1.1-ALv2, cloud server under BUSL-1.1. See Licensing.