test(stringified-props): scan the corpus once, outside the timed test - #561
Merged
Conversation
The guard added with #545 read all 218 snapshot files inside its `it()`, so 28 MB of I/O sat under vitest's 5s per-test default. Measured: ~0.5s in plain node, 1.9s in the `nuxt` project on its own — 38% of the budget with no contention — and past 5s under a full run sharing forks with 346 other files. It timed out that way twice. The first time was reported as an unexplained single failure that three clean re-runs could not reproduce and I would not call flaky without a name; this is the name. The scan now happens in the describe body, which is how the collision guard beside it has always done the same read. Describe-body work is not subject to the per-test timeout, so the assertions are free and the corpus is read once instead of once per assertion. No behaviour change to what the guard catches: verified by appending an `[object Object]` attribute to a snapshot, which reds it in both projects and names the file and the attribute. Worth recording that the first attempt at that mutation stayed green and the guard was briefly suspect — `printf` had escaped the quotes, so the injected text did not match a pattern that was working correctly. A mutation that fails to go red is a claim about the mutation before it is a claim about the test. Full suite green on two consecutive runs. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012MsMuj8Fic9tjWVjyEyrxc
IgorShevchik
pushed a commit
that referenced
this pull request
Sep 10, 2026
…eading them Every assertion this repository makes about theme classes is a string assertion: `test/utils/*.spec.ts` reads the theme sources, the component snapshots record the rendered `class` attribute, and nothing compiles CSS. An arbitrary value was therefore only ever proved to be written. `theme-css-compiles.spec.ts` runs the token entry through the installed `tailwindcss` engine with the candidate classes read out of `src/theme/*.ts`, and asserts a `max-height` declaration is emitted for each and that the `--max-height-popup-*` tokens they reference reach the compiled output. The incident behind it is #430, which moved the popup caps from literals into tokens: the mechanism had to be checked by hand during that review, by exactly this compile. It confirmed the caps worked, and nothing kept them working. Candidates are extracted rather than restated, so a class that is edited stays covered and one that is deleted trips the floor assertion instead of thinning the list in silence. The compile happens once at module scope, not inside an `it()` — the shape that flaked in #561. What the guard cannot catch is recorded in the file, measured against the engine rather than assumed: Tailwind v4 does not validate the meaning of an arbitrary value. It emits a rule for `max-h-[not a length]` and for an unbalanced `max-h-[min(var(--x)]`; it refuses an empty value or an unknown utility. So the first failure mode is caught only in its total form, while the second — the token dropping out of `:root` — is caught exactly, verified by deleting `--max-height-popup-list` from `sizes.css`. A `the guard itself` block pins that `ruleFor` reports absence as well as presence, so a matcher that always found something could not pass the file vacuously. Closes #457 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012MsMuj8Fic9tjWVjyEyrxc
9 tasks
IgorShevchik
added a commit
that referenced
this pull request
Sep 10, 2026
…eading them (#564) Every assertion this repository makes about theme classes is a string assertion: `test/utils/*.spec.ts` reads the theme sources, the component snapshots record the rendered `class` attribute, and nothing compiles CSS. An arbitrary value was therefore only ever proved to be written. `theme-css-compiles.spec.ts` runs the token entry through the installed `tailwindcss` engine with the candidate classes read out of `src/theme/*.ts`, and asserts a `max-height` declaration is emitted for each and that the `--max-height-popup-*` tokens they reference reach the compiled output. The incident behind it is #430, which moved the popup caps from literals into tokens: the mechanism had to be checked by hand during that review, by exactly this compile. It confirmed the caps worked, and nothing kept them working. Candidates are extracted rather than restated, so a class that is edited stays covered and one that is deleted trips the floor assertion instead of thinning the list in silence. The compile happens once at module scope, not inside an `it()` — the shape that flaked in #561. What the guard cannot catch is recorded in the file, measured against the engine rather than assumed: Tailwind v4 does not validate the meaning of an arbitrary value. It emits a rule for `max-h-[not a length]` and for an unbalanced `max-h-[min(var(--x)]`; it refuses an empty value or an unknown utility. So the first failure mode is caught only in its total form, while the second — the token dropping out of `:root` — is caught exactly, verified by deleting `--max-height-popup-list` from `sizes.css`. A `the guard itself` block pins that `ruleFor` reports absence as well as presence, so a matcher that always found something could not pass the file vacuously. Closes #457 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012MsMuj8Fic9tjWVjyEyrxc
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.
Linked issue
None — this fixes a defect introduced by #545, found by it going red on an unrelated branch.
Type of change
revert(Scope): ...)Description
The guard added with #545 read all 218 snapshot files inside its
it(), so 28 MB of I/O sat under vitest's 5-second per-test default.nuxtproject, file run aloneNot a leak — a direct
grepover the corpus returns zero[object Object]either side of this change.The fix is the pattern already next door
indistinguishable-snapshots.spec.tsdoes the same 28 MB read and does not flake, because it does it in the describe body:This file now does the same. The corpus is read once instead of once per assertion, and the assertions are free.
It timed out twice; the first time went unnamed
The first occurrence was reported as an unexplained single failure during #549 — one test, one project, and three clean re-runs afterwards. The log had been captured as a tail so the test's identity was lost, and I said at the time I would not call it flaky without a name. This is the name, and the shape matches: one test, one project, intermittent, load-dependent.
Verifying the guard still bites
Appended an
[object Object]attribute toBadge.spec.ts.snap; it reds in both projects and names the file and the attribute:Worth recording that the first attempt at that mutation stayed green and the guard was briefly under suspicion. The cause was
printfescaping the quotes, so the injected text never matched a pattern that was working correctly. A mutation that fails to go red is a claim about the mutation before it is a claim about the test — the mirror of the lesson from #529, where a mutation went red for the wrong reason.Checks
pnpm lintgreengit checkout --Checklist
🤖 Generated with Claude Code
https://claude.ai/code/session_012MsMuj8Fic9tjWVjyEyrxc
Generated by Claude Code