* Capture full content for tall visual elements beyond viewport (#271)
Element-level screenshots of components taller than the 800px viewport
(e.g. the token board with 128 leaves, which is ~7k px) only painted
the first viewport's worth of content. The PNG was sized to the full
document height but rows below the fold were blank because Playwright
omits content outside the viewport by default.
Add captureBeyondViewport: true to the visual project's toMatchScreenshot
config so Playwright renders the full element regardless of viewport
bounds. This applies to all 126+ existing captures; only the handful
that are taller than 800px change in practice.
Add a post-capture check that warns when scrollHeight exceeds the
viewport but no child element actually reaches below it — a sanity
check that catches scrollHeight inflation without false positives.
The visual regression comparison pipeline in scripts/visual-regression
will flag any capture with dimension mismatch as 'changed', so if
captureBeyondViewport is ever removed the regression is caught at the
image-comparison level.
Closes #271.
* Fix lint and type errors in visual capture config
- Type the resolveScreenshotPath callback params explicitly so the as any
cast on toMatchScreenshot doesn't lose type safety for known properties
- Suppress the no-console lint warning on the post-capture warn call
* Use CDP viewport resize instead of captureBeyondViewport config
captureBeyondViewport: true in the vitest toMatchScreenshot config
caused ALL visual captures to time out in CI (Matcher did not succeed
in time). The Playwright internal handler only sets captureBeyondViewport
when !fitsViewport, but forcing it globally adds overhead even for
elements that fit within the viewport.
Instead, resize the viewport to the element's full height via CDP in
captureVisual only when the element extends beyond the 800px viewport.
This ensures Playwright renders the full content without affecting
the majority of captures that fit within the viewport.
The viewport metadata embedded in the filename is captured before
resizing (so it always shows the configured 1024x800 viewport). The
viewport is restored to its original size after capture.
* Configure vitest API write and Vite FS allow for visual captures in worktree
Two guards in @vitest/browser 4.1.x block screenshot writes
when vitest runs in a git worktree:
- assertBrowserApiWrite requires api.allowWrite and
browser.api.allowWrite to be truthy
- assertBrowserFileAccess requires the capture path to be
within Vite's server.fs.allow scope (fails when
VISUAL_CAPTURE_DIR points outside the worktree root)
Add api.allowWrite at project level, browser.api.allowWrite
in the visual project, and server.fs.allow pointing at
.artifacts (found by searching up from the config dir) so
captures written to the cache directory pass the Vite FS
check.