test(fields): each test that uses jest-dom matchers declares the import itself (objectui#8722 round 2) - #9500
Conversation
…rt itself (objectui#8722) The fifteen test files in `packages/fields` that call `@testing-library/jest-dom` matchers carried no jest-dom import of their own. They type-checked only because some OTHER test file in the same program had a bare `import '@testing-library/jest-dom';`, which registers the matcher augmentation PROGRAM-WIDE rather than per file. The config was not the authority; whichever file happened to import won. Measured on this base with the compiler, not with a glob: ablating the bare import in all 104 carriers turns 92 files red with 723 TS2339 — and 15 of those 92 are files the ablation never touched. Those 15 are the leaning population, and the compiler's set is identical to the one the repo's own `census:tsconfig-test-parity` reports, with no drift in either direction. Each of the 15 now declares the import itself, on the line after its `@testing-library/react` import — the placement 103 of the 104 existing carriers already use. Re-running the identical ablation on the identical 104 files now leaves those 15 green, so no file's matcher types depend on another file's import. `packages/fields/tsconfig.test.json` is deliberately untouched and byte-identical. Naming `compilerOptions.types` switches off automatic `@types/*` inclusion, which would buy a leaning count of zero by recreating this card's own hazard on the `@types/*` axis. The `node` route for this program stays `none`, unchanged. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013VGeMu3p6qEFWR6K6GGLaW
✅ Console Performance Budget
The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it. 📦 Bundle Size Report
Size Limits
|
…am this PR leaves behind (objectui#8722)
The `types` paragraph justified leaving `compilerOptions.types` unset, and that
justification is correct and unchanged. Two claims inside it were not.
"the seven suites that use `@testing-library/jest-dom` matchers" was a count
taken once and never re-derived; the resolved program has 92 files that call
those matchers, out of 161 test files. And "its global augmentation reaches the
whole program through that import" described the mechanism the previous commit
exists to stop the program relying on — it would have told the next reader that
this package still leans on one file's import for another file's types.
Re-measured rather than re-worded:
- `global`: the grep that produced the original claim cannot tell code from
prose (six files here say the English word in a comment). The compiler can —
injecting `global.setTimeout` into a test file is TS2304 against an
unmutated exit 0, so no file uses the Node global and one could not slip in
unnoticed. That is the claim the paragraph actually rests on.
- jest-dom: 92 files call matchers and each now carries its own import; 119
carry the import in all, the extra 27 using no matcher themselves.
The new text also names the instrument that re-derives those counts
(`census:tsconfig-test-parity`, column `leaning`) and says in the file that they
are a reading rather than a live fact, per AGENTS.md commandment #9. It
deliberately does NOT claim any single import is load-bearing: the augmentation
is still program-scoped, and removing any proper subset leaves the program
green. What changed is that every matcher user is now also a supplier.
Comment text only. The parsed configuration is byte-identical — 223 canonical
bytes either side, same `compilerOptions` keys — and `types` is still absent
(`grep -cE '"types"'` reads 0, with `"noEmit"` and `"lib"` reading 1 in the same
command as firing controls). Naming `types` stays refused: it buys a leaning
count of zero by switching off automatic `@types/*` inclusion, which is this
card's own hazard on another axis.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013VGeMu3p6qEFWR6K6GGLaW
✅ Console Performance Budget
The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it. 📦 Bundle Size Report
Size Limits
|
CI green — and the landing probe, registered BEFORE the merge
⛔ Written here deliberately, because I failed to do it once today. PR objectui#9429 landed an hour ago with only a post-hoc probe — I had not registered one in its ACCEPT, and its readings are recorded as weaker for exactly that reason. The ACCEPT is the last moment a probe is still honest. This one is registered now. CI
⭐ Landing probe — P1–P4, fixed now⭐ Pre-validated, so it is not a probe that cannot fire. The population is the merge's own file list, ⛔ not a glob and ⛔ not one member generalised — "verify one member and you have verified one member" is this lane's own erratum and I am not repeating it.
⛔ P1's "15" is pinned, ⛔ but nothing else is. The count is a property of this diff and is already measured; the file names are not re-asserted here, because the merge cannot change them and listing them would add a second copy free to drift. ⛔ P4 is a red line: the parent is resolved from the actual merge afterwards. It has been another seat's PR eight times this shift, including both landings in the last hour. ⇒ flipping ready, re-reading Generated by Claude Code |
Part of #8722 — round 2, the
packages/fieldsresidue. Round 1 (#9480, merged360300fea3) landed the other three packages; this finishes the card's population but deliberately does not close it (see What is still open).What was wrong
Fifteen test files in
packages/fieldscall@testing-library/jest-dommatchers and carried no jest-dom import of their own. A bareimport '@testing-library/jest-dom';registers the matcher augmentation program-wide, so those fifteen type-checked only because some other test file in the same program happened to carry one. The config was not the authority; whichever file happened to import won.The runtime was never leaning —
vitest.setup.dom.tsxandvitest.setup.dom-light.tsxboth import jest-dom, so the matchers were always registered under vitest. Only the type program had no declared route. That is this card's class exactly: green under one tool, supplied by accident under the other.The partition, measured before editing
Enumerated from TypeScript's own resolved program file list (
tsc -p … --listFiles), not from globs — the card warns that globs read 0 for flat-layout packages.The compiler and the repo's own census agree exactly. Ablating all 104 carriers reddens 92 files with 723
TS2339; subtracting the files the ablation touched leaves 15, and that set is identical to the onecensus:tsconfig-test-parityreports in itsleaningcolumn — no false positive, no false negative, in either direction. So PM assumption A is confirmed: all fifteen really do use matchers, and the repair for each is an import, not nothing.d74e6b7c34. The carrier population did move, though — round 1 read 103, this base reads 104 — so the population is still accreting, just not on the leaning axis.The fix
Each of the fifteen now imports jest-dom itself, on the line after its
@testing-library/reactimport — the placement 103 of the 104 existing carriers already use. One line per file,+1/−0each.⛔ No shared importer was added. A single
setup-types.tswould turn 15 files leaning on accident into 15 files leaning on a new single point of failure — that is the defect this card describes, not its repair.⛔
packages/fields/tsconfig.test.jsonis byte-identical, proven by blob hash (383c6c6bf4…at base, atHEAD, and on disk), with a control in the same command showing a file that did move. NamingcompilerOptions.typeswould buy a leaning count of zero by switching off automatic@types/*inclusion — this card's own hazard, recreated on a different axis. The program'snoderoute staysnone, unchanged.Ablation, both directions — every zero carries a control
All legs: mutation proven to have reached disk (marker count = target and zero live imports remaining, else the reading is declared void), restore proven by blob-hash equality plus a clean
git status, held by anEXIT INT TERMtrap. Precondition recorded, not assumed:turbo run buildover the dependency closure first, 10/10, exit 0 — an unbuilt tree makes every program look broken identically.Leg A is the acceptance evidence: every red file is red because its own import was removed. No file is red because of someone else's.
plugin-detail— the program depends on the set — and that survives this change.Verification
tsc -p packages/fields/tsconfig.test.json— exit 0, 0 errors (baseline and after).vitest run packages/fields/— 161 files, 2785 tests, all passing, exit 0. Control: a named nonexistent path exits 1, and one edited file named directly runs 1 file / 5 tests.census:tsconfig-test-parity—packages/fieldsleaning 15 → 0; it was the only non-zero row, so the repo-wide total goes to 0. Control: the same filter applied to the before census prints the fields row.turbo run type-check --filter @object-ui/fields11/11 ·check-type-check-coverage43/43 test programs, 0 debt ·turbo run lint --filter @object-ui/fieldsexit 0 ·check-control-bytes7667 files ·check:phantom-deps,check:self-import,check:esm-specifiers,check:test-path-roots,check:vi-mock-*,check:new-line-citations,check:unreferenced-sources,check:published-tsconfig-exclude— all exit 0 ·check-governed-queue-guard --teston all 16 paths: NOT GOVERNED.@testing-library/jest-domis a root devDependency and no package declares it — including the 104 carriers already in this package. The new imports resolve exactly as the existing ones do.src/file as published source, so it fires here where round 1 owed nothing. Declared with empty frontmatter — the first-class "releases nothing" spelling — justified by measurement:filesshipsdistonly, and 0 artifacts derived from a.test.file reach it (controls: 80.d.tspresent;ImageLightboxfound in 2 dist files,ImageLightbox.testin 0).gates_weakened:NONE.What is still open — ⛔ this PR does not close #8722
packages/fields/tsconfig.test.jsoncarries a comment that is now more stale than before this change:There are 119 such suites, not seven, and the clause explaining that the augmentation arrives through that import is precisely the mechanism this PR stops relying on. Round 1 rewrote the equivalent comments in the other three configs; here the byte-identical fence forbids it, and I kept the fence rather than quietly taking the better-looking option. That comment is left for the maintainer or a follow-up dispatch — flagged, not fixed.
维护者速读(草稿)
改了什么 —
packages/fields里 15 个测试文件各加一行import '@testing-library/jest-dom';,一行一文件,没有别的改动。另加一个空 frontmatter 的 changeset(声明"不发版")。为什么改 — 这 15 个文件用了 jest-dom 的断言器,却没有自己导入它;它们能通过类型检查,纯粹因为同一个程序里别的文件恰好带了一行导入,而那行导入是程序级生效的。也就是说:配置不是权威,谁先导入谁说了算。运行时一直是好的(vitest setup 里有导入),坏的只有类型这一侧。
风险与代价(含回滚) — 风险很低:改动是 15 行纯增量,不触碰任何配置、任何生产代码、任何别的包;
dist里不含任何测试产物(已实测),所以发布面零变化。161 个测试文件 2785 条用例全绿。回滚就是 revert 这一个 commit,没有迁移、没有数据、没有顺序依赖。席位意见 — (留空,待定稿)
你要做的 — 两件事:① 确认
tsconfig.test.json里那句"seven suites"的过时注释怎么处理 —— 本轮禁令要求该文件字节不变,我没动它,但这句话现在比改之前更不准;② 确认本卡不随本 PR 关闭(只写Part of),因为注释残留还在。🤖 Generated with Claude Code
https://claude.ai/code/session_013VGeMu3p6qEFWR6K6GGLaW
Generated by Claude Code