Repository navigation
Conversation
Dependency upgrades like MUI 9 pass tsc and vitest without anything checking the rendered pages. `npm run visual-diff` renders every route in src/App.tsx on the current branch and on its merge base with origin/main, then lists the pages whose screenshots changed, the pages that are new, and the console, network, and render errors only the branch has. It exits 1 only on new errors, since a screenshot diff may be intended. It is a local tool, not a CI check. Both sides render on the developer's machine in one run, so no baseline images are stored and OS font differences don't matter. The base is checked out into a temporary worktree (installed with --ignore-scripts so husky leaves the shared core.hooksPath alone), and its install and build are cached by commit. Each side gets its own SQLite database, backend, and static server on free ports, seeded identically from fixed ids and timestamps with the browser clock frozen to match, so nothing touches Okta or a running dev server. The current branch's Playwright spec renders both sides, so a route the branch adds reports as new instead of failing. Ctrl-C stops every child and removes the worktree. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The MUI 9 upgrade (#706) renamed handlers and dropped default props on components above an existing button-in-button warning on the home page, so the warning's component stack differed between the two sides and the visual diff reported it as new. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
3 tasks done
barborico
commented
Nov 5, 2026
…rrent The tool's details now live in scripts/visual-diff/README.md, with a short lead-in in the testing guide saying when to reach for it. The README adds what to update when a route, a seeded model column, or a loading indicator changes, and the frontend guide and CLAUDE.md's common mistakes point new routes at the spec's page table, so the table and the seed don't drift from the app between dependency upgrades. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
barborico
marked this pull request as ready for review
November 5, 2026 02:54
Jeff-Rowell
previously approved these changes
Nov 5, 2026
Jeff-Rowell
left a comment
Contributor
There was a problem hiding this comment.
This is great! IMO I'd drop the "side by side" screen shot viewer or make the side by side images larger. I found I just toggled between "Actual" and "Expected" or used the slider more.
The frontend steering doc now lists the same dependencies as the tool's README and the testing doc, so all three agree on when to run it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
barborico
enabled auto-merge (squash)
November 5, 2026 18:06
barborico
disabled auto-merge
November 5, 2026 18:06
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds
npm run visual-diff, a local command that renders every route insrc/App.tsxon the current branch and on its merge base withorigin/main. It then lists the pages whose screenshots changed, the pages that are new, and console, network, or render errors that only the branch has. It exits non-zero only on new errors, and it adds no CI workflow and stores no baseline images.Urgency: low - one week
Expected review effort: <15 min, assuming focus on the tool's shape and documentation rather than reading the script logic itself (IMO not worth scrutiny)
Motivation
Frontend dependency PRs such as the MUI 9 / MUI X 9 upgrade (#706) pass tsc and vitest, but nothing checks the rendered pages, and clicking through about 25 pages by hand on every upgrade isn't practical. Rendering both sides on the same machine in one run avoids stored baselines and the font differences between operating systems that make checked-in screenshots brittle.
Validation
Confidence: medium
Run on macOS (Node 22, Playwright 1.64 with Chromium):
mt: 4→mt: 6on the mainContainerflagged every page with a readable 16px-shift diff, and the run exited 0./aboutroute was reported as a new page, and a temporaryconsole.errorinHomewas reported as a branch-only error with exit code 1.git status, the checkout'sbuild/, and.claude/.api-portwere unchanged afterwards.--base HEAD~3(whose merge base has a differentuv.lock) built its own virtualenv and worked.fontSize="small"intosx={{fontSize: 'small'}}),EmptyListEntry's "None" turning from grey to black, nav chevrons moving to the drawer edge, and Chip labels shifting by about 1px. Its one false "new error" (a pre-existing warning whose React component stack changed) led to the second commit, which compares warnings without their stacks.Risks
None for the app itself: the change adds a dev-only tool and the
@playwright/testdevDependency. The tool's main limitation is that the seed data and the spec's route table need a case added whenever a page is added. A spec test fails the run whensrc/App.tsxhas an uncovered<Route>.Guidance for Reviewers
Design choices worth a look:
uv.lockwithout dev dependencies. Neither the checkout's.envnor plugins installed in its.venvcan leak in. The first attempt failed exactly this way: an example plugin installed in.venvrequired Google credentials.Detailed Description of Changes
scripts/visual-diff/run.jsis the orchestrator. It computes the merge base, adds a temporarygit worktree, runsnpm ci --ignore-scriptsand builds the base on a cache miss (cache key is the commit), builds the branch from the working tree into a temp directory, seeds and starts both backends, serves each build with a small static server that proxies/api, runs Playwright twice, and prints the summary. Cache lives under${XDG_CACHE_HOME:-~/.cache}/access-visual-diff.scripts/visual-diff/seed.pyandfixtures.jsonhold the fixed data set. Timestamps are offsets from midnight UTC of the run, and the browser clock is frozen relative to the same point, so relative dates match.scripts/visual-diff/pages.spec.tsvisits each route, records errors, waits for spinners and skeletons to clear, grows the viewport to<main>'s scroll height (the app scrolls inside<main>, sofullPagealone stops at one screenful), and takes the screenshot. A route that renders the not-found page on the base writes no expectation, so it reports as new.scripts/visual-diff/README.md, including what to update as pages and models change. The testing guide and the top-level README each have a short pointer to it. The frontend guide and CLAUDE.md's common mistakes tell authors to add a page case and seed data with every new route.main: request detail pages fire/api/audit/...with empty ids (404s), and several list pages nest<a>/<td>/<button>invalidly. These appear on both sides, so they aren't reported as new.🤖 Generated with Claude Code