Skip to content

Add a repeatable headless visual check for the running app #512

Description

@richardthe3rd

Summary

There is no repeatable way to boot the real app and look at it. scripts/check-page.mjs screenshots a static page load; it cannot drive the UI, so nothing verifies that a screen renders correctly with live data.

This gap has cost something concrete: the centre-aligned category headers shipped in #506 passed 1313 tests and were caught only by an ad-hoc browser session. That session was rebuilt from scratch each time and then discarded.

Why not just goldens

Goldens are the right fix for layout regressions and are tracked separately. They cannot tell you the app boots, that the real feed parses, or that CanvasKit and fonts load — all of which are exactly what a browser check covers. The two are complementary.

What to add

A scripts/visual-check.mjs alongside the existing check-page.mjs / screenshot-batch.mjs, taking a URL and a screenshot prefix, that boots the app, waits for first render, and drives a scripted sequence with a screenshot per step.

Environment notes worth recording with it, all discovered the hard way:

  • Chromium path is /opt/pw-browsers/chromium-1194/chrome-linux/chrome. Playwright's default chromium/chrome-linux/chrome does not exist in the managed image and fails with "executable doesn't exist".
  • Flutter web builds no DOM semantics tree until accessibility is enabled. Clicking flt-semantics-placeholder programmatically turns it on. Even then it exposed only the nav bar in practice, so coordinate-driven clicks were the workable approach — worth stating so the next attempt doesn't sink time into the semantics route.
  • Egress-blocked hosts. In the sandbox, www.gstatic.com and fonts.gstatic.com were refused, which breaks three things at once: CanvasKit (blank page), Firebase (firebasejs module import), and every webfont including Flutter's Roboto fallback — so no glyphs render at all and the UI looks empty. Workarounds if still blocked: set "useLocalCanvasKit":true in build/web/flutter_bootstrap.js to use the bundled copy, stub **/firebasejs/**, and serve a TTF from the Flutter SDK for **fonts.gstatic.com**.
  • The font substitution invalidates any typography judgement — every Google font collapses to one face, so typeface questions cannot be answered from these screenshots.
  • Preview *.pages.dev URLs were blocked; serving build/web on localhost worked.

The allow-list has since been widened, so the first step should be to try it clean and treat the stubs above as fallbacks.

Where it belongs

Script in scripts/, notes in the diagnostics-and-tooling skill, which already owns headless page checks and ships helper scripts.

Impact

Low, but it is the only route to answering "does this actually render on a real device" for an agent, and today that answer is re-derived from zero every time.

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions