Fail the build and the tests on a silently broken design token #220
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "deps/nldd-guardrails"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Follow-up to #219. Independent of it: both branch off
main, and onlyCHANGELOG.mdconflicts between them (both add a bullet in the same spot), so whichever merges second keeps both lines.Why
Every risk found in the 0.8.77 upgrade passed typecheck, eslint, vitest, the build and the Playwright e2e suite while the app rendered in
Timesat 16px. Avar()pointing at a custom property nobody defines is invalid at computed-value time: the whole declaration is dropped, silently, with no warning anywhere in the toolchain. NLDD retires tokens inside 0.8.x patch releases, so the names we read move under us ---shadow-mdand--color-focushave already gone this way.Three checks
Each one is proven to fail on input that should fail it. A check whose reassuring answer is "nothing found" is worth nothing until you have seen it say something.
1.
frontend/src/styles/nlddTokens.test.ts- resolves everyvar(--...)insrc/**against the custom properties defined by the installed@nldd/design-systemplus our owntokens.css. Fails on a reference that has neither a definition nor a fallback.--color-danger,--font-weight-bold,--semantics-buttons-primary-tinted-background-color,--toast-duration) and all four carry a fallback, so they still render. They are untidy, not broken.tokens.csson 0.8.77 it names both offending lines. With a bogus reference added tobase.cssit reports--dit-token-bestaat-niet at src/styles/base.css:204.2.
frontend/tests/e2e/document-typography.spec.ts- asserts the rendered result rather than the cause:system-uiat 18px/27px, and no RijksSans in the computed stack or in any@font-face. The face list must still contain JetBrains Mono, so the negative assertion cannot pass on a page that loaded no stylesheets.3.
frontend/vite.config.ts-fontTuningPluginnow checks its own output instead of its removal counter.The comment already said "fail loudly rather than shipping the font because a rename broke a regex", but the code only called
this.warn. A reshaped@font-faceleaves the rule in the CSS whileremovedFacesreads zero, and the build would have shipped the licence-restricted font on a warning nobody reads in CI. Testing the stripped CSS for a surviving RijksSans face makes that an error.Self-tested by neutering
RIJKS_FACEso it matches nothing: the build fails witha RijksSans @font-face survived the strip in [assets/index-xEuRwH19.css]. Restored, it builds clean with only the two JetBrains Mono woff2 emitted.The counter check stays a warning on purpose: upstream may legitimately stop bundling RijksSans, and that should not break the build.
An earlier version of this also re-scanned the bundle for surviving RijksSans assets. That was a false positive - rolldown still enumerates entries the first pass deleted, so it failed a build that was in fact correct. Dropped, because every matching asset is deleted in the same pass and the check could never fire meaningfully.
What this does not cover
Honest scope: of the ten confirmed risks in the 0.8.77 analysis, this catches one. It happens to be the only breaking one.
The rest - the card shadow default going to
none, the corner radius going 0px to 10px, the divider colour shifting, the banner frame moving into the shadow DOM - are value and structure changes. The token name still exists; its meaning changed. No name check sees that. The only net that covers that class is Playwright screenshot baselines on a few surfaces, which costs baseline maintenance on every deliberate style change. Not proposed here.Verification
vue-tsctypecheck, eslint (0 errors), vitest 572 passed in 78 files (was 570/77),vite build, Playwright e2e 65 passed / 3 skipped (was 63),pre-commit run --all-files.01980f0e314a948c80af4a948c80af2a4fd4b326