Skip to main content
Verification is the half of the workflow agents historically reinvented per session with hand-written Playwright. eu-studio packages it as one-call gates. Never hand-write browser scripts for these. Requirements: Playwright (npm i playwright, or set EXJSX_IT_PLAYWRIGHT to an existing install’s entry file).

check: the entire gate in one call

Running verify and clicktest separately costs three browser launches and two model round-trips in the tail of every build; check shares a single Chromium session. Real output against a production build:
After a fix that touches one page, re-check only it (eu-studio check --pages /pricing/); do not re-run the full matrix for a single-page change.

The structural matrix

Every page at every width (default 1200,1920,390), scroll-settled and with animations finished. Per combination it asserts:
  • scrollWidth equals the viewport width, with overflow offenders named by selector when it does not,
  • exactly one h1,
  • zero console page errors,
  • and it reports body height.
Two forensic probes fail the gate. Both were added after a ten-site audit where every defective site passed the basic checks:
  • empty-flex-slot: a space-between/around/evenly row balancing against an invisible child (the zero-width burger-wrapper signature). The geometry is legal, but the page looks broken to a human. Intentional spacers (flex-grow > 0) and aria-hidden separators with real width are exempt.
  • css-coverage: every c-* class the DOM uses must be defined by some served rule. A page can serve 200 with N stylesheets while its own post CSS or carrier went stale; this probe catches the “748px z-stack while the gate reports green” incident class. Runs once per page (width-independent).
Two probes warn without failing (some designs run legitimately narrow or rotated):
  • min-content-collapse: a squeezed column rendering one word per line never overflows; the layout gave way instead of the content.
  • text-escapes-rotated-card: text bleeding out of a transformed card never trips scrollWidth; measured via text ink rectangles.

Interaction tests

The --nav matcher accepts either the link’s visible text or its href pathname, so --nav /=about passes whether the link says “About us” or points at /about/. All four can be passed to check directly.

verify: anchor deltas against a design

For pixel-faithful rebuilds with a reference design, verify measures where your sections actually land:
  • selector is a CSS selector or text=<exact starting text>; y targets are design-absolute px, pass/fail at --tolerance (default 2px).
  • bands assert that a horizontal strip actually paints ink: DOM probes cannot see paint, so black-ink assets on black sections pass every geometric check while rendering invisible.
  • Mobile: asserts scrollWidth == 390 and names the overflowing elements.

doctor: health checks plus self-heal

Checks, in order: site (frontend answers 200), auth (app-password REST auth works), seam (companion plugin capabilities endpoint), store (every global class a page references exists in the class store), css (every stylesheet the page enqueues actually serves as CSS; a followed 200 that comes back text/html is a redirected miss, not a healthy sheet). Real output:
On a css failure, doctor heals: cache regen plus prime-css with retries, then a re-check. On a store failure it can only detect, not invent: classes a page references are gone from the store, and the fix is redeploying the bundle (exjsx deploy), which doctor tells you. When styles look broken, run doctor instead of hand-grepping page HTML; it names the failing stylesheets.

carry-css: independence from a flaky file store

A playground-specific last resort: if the WASM file store keeps flaking after doctor heals, run carry-css once at the end of a build.

Which tool when