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:
{ "kind": "web", "name": "home", "url": "http://localhost:3000" }Or snapshot a static HTML fixture:
{ "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 tolifecycle.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:
{
"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:
A system browser channel:
json{ "browser": { "channel": "chrome" } }An explicit executable path:
json{ "browser": { "executablePath": "/path/to/chromium" } }An environment variable:
shexport 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 globalcomparison.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.
{
"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:
{
"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
- The runnable example at
examples/p1/playwright. - Configuration and the configuration reference.