Skip to content

test: snapshot corpus is 26.4 MB — measured, not worth shrinking; staying with upstream's approach #87

Description

@IgorShevchik

Closed as not planned. The silent: true half was done (#506, #512, #516). Shrinking the corpus was measured and is not worth what it costs — figures below, so returning to it is cheap.


Background

Surfaced during the June 2026 multi-angle project audit (QA review). Thematically adjacent to #63/#74.

Problem as filed

test/components/__snapshots__ = 23 MB across 198 files (+ 376 KB / 4 in content/). Top offenders: Calendar.spec.ts.snap at 1.9 MB ×2, DropdownMenu 836 KB ×2, CommandPalette ~800 KB ×2.

No human reviews a 60 KB-per-case diff, so snapshot churn is rubber-stamped — which defeats the purpose of snapshot review, especially on upstream-sync PRs where the snapshot diff is the primary review signal (#75).

Compounding it: vitest.config.ts set silent: true, which suppressed Vue warnings and console errors during render, so a component that rendered something while logging errors still produced a green snapshot.


Done: the silent: true half

#506 added test/utils/console-gate.ts, which fails any test that writes to console.warn or console.error while rendering. #507 and #508 corrected what it found. #512 and #516 then removed the causes of the noise rather than exempting them, by mounting into the document and unmounting after each test:

register entries tests logging messages
before #512 38 62 623
after #512 37 56 366
after #516 25 44 569

Between them those two changes surfaced four real defects that a detached, never-unmounted harness had been hiding: Modal and Slideover silently dropping the actions slot, Countdown keeping a requestAnimationFrame handle in a ref, the vue project's singleton router losing its navigation between cases, and the console gate itself being registered so that it stopped watching before teardown ran.

#514, which proposed re-shaping the register into per-file budgets, is closed as not planned for the same reason as this issue.

Not done, and not planned: the size

Where it stands

Measured with git ls-tree -r --long (content bytes). Attaching did not meaningfully change it: 26.35 MB before #512, 26.38 MB after.

size entries average entry
whole corpus 26.4 MB / 212 files 4,359 6.2 KB
Calendar ×2 2,539 KB each 44 57.7 KB
DropdownMenu ×2 817 / 816 KB 32 25.5 KB
CommandPalette ×2 784 / 782 KB 42 18.7 KB
InputMenu ×2 707 / 705 KB 57 12.4 KB
Table ×2 681 / 680 KB 36 18.9 KB

That is 38% of the tracked tree (70 MB excluding node_modules and .git).

Upstream has the same corpus, and lives with it

Fetched from nuxt/ui@v4 and measured the same way:

file nuxt/ui b24ui avg class attribute
Calendar.spec.ts.snap 1,666 KB (32.7 KB/entry) 2,539 KB (57.7 KB/entry) 214 → 431 chars
DropdownMenu.spec.ts.snap 348 KB (14.5 KB/entry) 817 KB (25.5 KB/entry) 115 → 243 chars
CommandPalette.spec.ts.snap 531 KB (12.6 KB/entry) 784 KB (18.7 KB/entry) 101 → 163 chars

There is no upstream technique being missed — this is a property of snapshot testing a Tailwind component library. Our entries run about 1.8× larger for a measurable and deliberate reason: the Bitrix24 design tokens live inside Tailwind arbitrary values (text-(--ui-color-accent-main-primary), text-(length:--ui-font-size-md)/(--ui-font-line-height-md)) where upstream uses short semantic utilities. That is the point of the fork.

What was evaluated, and why it was rejected

Hoisting repeated class strings into a per-entry legend. 63% of the corpus is class= attributes, and 34% (8.78 MB) is the same string repeated within one entry. A prototype cut the corpus 32% (26.4 → 17.7 MB) and Calendar's average entry from 57.7 KB to 18.8 KB, with no loss of coverage.

Rejected because it does not solve the problem this issue names. On the scenario that matters — an upstream sync flips one utility sitting on 47 elements of one entry:

diff lines bytes to read
as-is 94 29,155
hoisted 98 13,765

Half the bytes, the same number of places to look. The elements share a utility, not a whole class string, so each distinct string is its own legend line. It buys weight, not reviewability, at the cost of snapshots no longer being literal HTML.

(Recorded in case anyone builds something similar: legend tokens must be named by content hash, not sequentially. With sequential numbering, inserting one element renumbered the legend and turned a 3-line diff into a 227-line one.)

Snapshotting only the variant-bearing subtree. The only evaluated option that does cut diff lines. Rejected on cost: per-case judgement across the six largest components about what each case may stop asserting, a deliberate reduction in coverage, and snapshots that diverge further from upstream's exactly where we compare against them on sync PRs.

Decision

Stay with upstream's shape and live with the corpus. Neither fix pays for itself: one gives weight without reviewability, the other gives reviewability by giving up coverage and by diverging from the repository we sync against.

No CI size budget either — a soft warning over a corpus that is knowingly and permanently over budget is noise, and the exception list would be most of the largest files.

The trigger to reopen would be the corpus growing materially beyond 26 MB, or a sync PR where an unreviewed snapshot diff actually lets a regression through.

Original Fix section, for the record

Priority: P3.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions