What 29,000 tests look like in a UI kit
"Tested" is the cheapest word on a component library's landing page. Here is what it means for Styloviz, in the numbers from the 1.0.1 release gate, and three things that gate caught in its last week.
- Engineering
- Quality
"Tested" is the cheapest word on a component library's landing page. Here is what it means for Styloviz, with the numbers from the release gate that shipped 1.0.1 on 7 October 2026, and three things that gate caught in the last week.
The numbers
| What | Count | Where it comes from |
|---|---|---|
| Unit and component tests | 29,176 | The last full instrumented run (scripts/coverage.baseline.json) |
| Spec files | 1,253 | Every *.spec.ts in the libraries and the app |
| Line coverage | 99.15% | Same run; branches 94.9% |
| Browser end-to-end tests | 158, across 25 files | Playwright, run per browser project, with axe on every page they visit |
| Static gates | 64 check:* scripts | 58 of them chained into npm run verify on every build |
| Angular versions proven | 21 and 22 | Every package installed, type-checked and linked against both before each release |
The full gate takes a little over four hours on one laptop. A release does not go out until all of it is green.
Why so many
Styloviz ships 169 components. A component is not one behaviour; it is every state it can be in, multiplied by keyboard, screen reader, dark mode, right-to-left text and the data arriving late, empty or wrong. Most of the tests are of the boring kind: a button with [loading] set is not clickable, a select announces its options, a table keeps its scroll position when a row is added.
The count is not the point. What matters is whether a test would fail if the thing it describes broke. Coverage tells you a line ran; it does not tell you anyone checked what it did. So every new behaviour gets a test that is first run against the code without the fix, and has to fail there.
What the gate caught this week
A real bug, in a test that kept failing for the wrong reason
The drawer has an unsaved-changes guard: dismiss a drawer with edits in it and it asks first, with focus on "Keep editing". The release gate failed a test of exactly that, once, under load. Re-running would have passed. Reading it instead showed the drawer moves focus into itself 60 milliseconds after opening, and when the prompt appeared inside that window, the late focus moved back to the close button. A user pressing Enter would have closed the drawer and lost their edits. The fix is three lines; the test that proves it waits past the 60 ms window and fails without them. It shipped in 1.0.1.
Three tests that were wrong, not the code
A tree with 1,500 rows took 1 to 6 seconds to render in a test on an idle machine and up to 98 seconds while the coverage run shared the laptop, against a 30-second limit. A product-tour test gave a missing target 150 ms and asserted the tour was still waiting; on a busy machine, setting the test up took longer than that. And the shared until() helper declared that a 20 ms debounce "never arrived" after two seconds of wall-clock time, in a test that took 16.5 seconds because the worker had been starved. Each was fixed at the cause: a budget sized for the claim, a wait that outlasts setup, and a helper that only gives up once the event loop has actually had its turns.
A gap in a promise
Writing the security page meant checking that npm attaches build provenance to the free packages, as the release workflow's comments said. It does not, for packages published from a private repository. The page now says what is true, and the free packages now publish from their public repository, so provenance arrives with the next release.
The gates nobody sees
Tests check behaviour. The static gates check the things a test would not think to ask:
- check:contrast measures every text and background pair against WCAG AA, in light and dark mode.
- check:ssr-safety fails any component that touches window or document where server rendering would crash.
- check:collection-keyboard proves every list, grid and tree has exactly one tab stop and arrow-key movement, at 1,500 rows.
- check:date-math runs the date arithmetic specs in five time zones, including Lord Howe Island's half-hour daylight saving.
- check:marketing fails the build when a number on the website, in the docs or in an article like this one stops matching the kit.
That last one exists because a website still quoting last quarter's component count is a small lie, and small lies are the ones nobody fixes.
Read the tests yourself
The free packages' source and their specs are public. Pick a component you would use, open its *.spec.ts, and see whether the tests describe what you would have checked.
- github.com/styloviz/styloviz The free packages, their specs and the CI that runs them on every push. 92 free components, MIT.