Conversation
Fixture tolerances have been maintained by nudging a number upward whenever a browser update made a fixture fail. That calibrates from the one value in the failure report, which is a guess at the margin rather than a measurement of it, and it leaves the suite loose everywhere while still failing somewhere. `npm run measure-tolerances` measures instead. Every fixture is forced to `tolerance: 0` so it reports its real pixel delta, in four environments: the host's Chrome and Firefox, plus Linux Chrome and Firefox in a container built to match the CI image. Tolerances are then derived: - delta 0 in every environment -> 0 - otherwise -> max(1.5 * linux, 1.05 * host) Linux gets a real margin because CI is the gate; the host gets enough to keep local runs green without sizing every tolerance for a platform that renders text 3-4x further from the reference. The container runs linux/amd64 under emulation deliberately: Chrome is not published for linux/arm64, and native arm64 rendering differs (point/starShadow measures 1474px there against 1476px in CI). It was validated against three pixel counts from a real CI run, all reproduced exactly. Runs that end early are rejected rather than measured, since partial data would silently yield tolerances that are too tight. The fixtures it rewrites are restored afterwards, and it refuses to start if test/fixtures is dirty. Verified end to end: run against master's fixtures it reproduces all 226 values from the recalibration in chartjs#992 exactly. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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.
Follow-up to #992, which recalibrated every fixture tolerance from measurement. This adds the tool that produced those numbers, so the next browser update does not start the guessing cycle over.
The problem
Fixture tolerances have been maintained reactively: a browser update shifts rendering, a fixture fails, and its tolerance gets nudged above the one number in the failure report. That number is the delta in the environment that happened to fail — it says nothing about the margin needed, so the new value is a guess. Repeat a few times and the suite is loose everywhere and still failing somewhere.
Usage
Requires Docker. Refuses to start if
test/fixturesis dirty, since it rewrites the fixtures and restores them withgit checkoutafterwards.Method
Every fixture is forced to
tolerance: 0, which makes each one report its real pixel delta rather than just passing or failing. That runs in four environments: the host's Chrome and Firefox, and Linux Chrome and Firefox in a container matching the CI image.0max(1.5 × linux, 1.05 × host)Linux gets a real margin because CI is what gates the build. The host gets only enough to keep local runs green — macOS renders text 3-4x further from the reference than Linux does, and sizing every tolerance for it is what made them loose.
Validation
Run against master's fixtures, the tool reproduces all 226 values from #992 exactly, including the total allowed-pixel budget (247,975 → 159,947).
The container itself was validated against three pixel counts observed in a real CI run:
point/crossShadowpoint/starShadowdoughnutLabel/contentMultilineNotes for review
The container runs
linux/amd64under emulation even on Apple Silicon. That is deliberate and documented: Chrome is not published forlinux/arm64, and native arm64 rendering genuinely differs —point/starShadowmeasures 1474px there against 1476px in CI, andline/labelShadowColorsdiffers by 74%. Faster, but not CI-faithful.Incomplete runs are rejected rather than measured. A browser that disconnects partway still yields deltas for the specs it reached, and deriving tolerances from those would silently produce values that are too tight — the same class of failure as a green check that never measured anything.
Emulated Chrome needs
--shm-size=2g(without it it hangs rather than running slowly), raised karma timeouts, and--no-sandbox. The flag was confirmed not to affect rendering rather than assumed:contentMultilinestill measures the same 919px with it.🤖 Generated with Claude Code