chore(types): plugin-dashboard's tests compile — the #4040 program closes at 40/40 - #4530
Merged
Merged
Conversation
…oses at 40/40 `@object-ui/plugin-dashboard` was the last TEST_DEBT entry. Its 47 test files are now read by a `tsconfig.test.json` chained off `type-check`, and the registry's table is empty. Remeasured, not inherited: the ledger declared 6 errors and `tsc -p` reported 14 — wrong in the same direction the whole table was wrong in (i18n 13 -> 103, react 27 -> 43). Twelve were fixed as type errors in the tests; two were a packaging gap, filed as #4529. What the type errors actually were, in both directions: - 6x TS2493/TS2352 — `queryDataset` and `find` mocks declared with NO parameters, so `mock.calls` typed as empty tuples and every `calls[0][1]` the drill and broadcast assertions are built on read out of bounds. Cast, so invisible at runtime too. The mocks now declare the call shape `DatasetWidget` really uses. - 3x TS2322 — two fixtures spelling `options: ['EMEA']`, a UI-side shorthand `GlobalFilterSchema` does not declare. Re-spelled to the pair form; the shorthand's own pin lives in core's `dashboard-filters.test.ts`, so no coverage moved. - 2x TS7006 — `onWidgetClick={(id) => …}` inferring `any`, because `DashboardRendererProps`' index signature collapses every declared prop through `PropsWithoutRef`. Annotated here; the underlying hole is #4528. - 1x TS2571 — `vi.importActual('react')` answering `unknown`, so the `.createContext` read was unchecked. No source file was touched. The gate's TEST_DEBT row is deleted in the same PR, per the ratchet, and its self-test gains a block stating the terminal condition and what an empty table does: it does NOT close the population (a declared entry still suppresses 5c — this gate is declared/reasoned/shrink-only, not "forbidden"), it makes a SILENT gap impossible, and section 6 still evicts a row whose package graduated. Red-first: - gate pre-fix reported the debt row (39/40, 1 declared debt); post-fix 41/41, 0 declared debt. - planting a type error in a dashboard test left `tsc --noEmit` green and turned the chained project red naming the exact line — the new project is the only thing that reads these files. - restoring the deleted row turns both the gate (section 6) and the new self-test case red. Must-not-change, green both sides: 47 files / 388 tests pass, the gate's other entries are unmoved, and the self-test suite is green (37 cases).
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
Contributor
✅ Console Performance Budget
📦 Bundle Size Report
Size Limits
|
Collaborator
Author
|
PM step-7 复核 — ACCEPT (session_017Qqyix2QcnpUC9XeYVDzx3)
Program note: the gate now prints 41/41 (its own number, used here in preference to the card's 40/40 shorthand) with 0 declared debt. #4040 stays open until this PR lands; the PM will close it with the program summary and evaluate closing objectstack#4118 (the row-tag source issue) at the same time. Auto-merge armed (squash). Generated by Claude Code Generated by Claude Code |
yinlianghui
marked this pull request as ready for review
August 13, 2026 05:11
This was referenced Aug 13, 2026
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.
Part of #4040 — the program card stays open for the PM to close with a summary.
@object-ui/plugin-dashboardwas the lastTEST_DEBTentry. Its 47 test files are now compiled by atsconfig.test.jsonchained offtype-check, and the registry table is empty.The measured debt: 14, not 6
The ledger row said 6. Remeasured against
origin/main@932cbcd6bwith the sibling-convention project,tsc -p tsconfig.test.jsonreported 14 — the same direction the whole table was wrong in (i18n declared 13 / measured 103; react 27 / 43). Verbatim:(The
Record< string, string >spacings above are the GitHub sanitizer workaround; the compiler printed them closed up.)What the 14 were — no source file touched
6x TS2493 / TS2352 — mocks that could not be read.
queryDatasetandfindwere declaredvi.fn(async () => …), with no parameters, whileDatasetWidgetcalls them asqueryDataset(dataset, selection)/find(object, params).mock.callstherefore typed as an array of EMPTY tuples, so everycalls[0][1]the drill and dashboard-broadcast assertions are built on read out of bounds — and because each read is cast, it was invisible at runtime too. The mocks now declare the call shape (DatasetCapableSourcein../DatasetWidget). Assertion strength unchanged; what changed is that the reads are now checked.3x TS2322 — two fixtures spelling
options: ['EMEA', 'APAC']. That bare-string form is a UI-side authoring shorthandnormalizeFilterOptionslifts;GlobalFilterSchemadeclares only the{ value, label }pair form. Re-spelled to the pair form. No coverage moved: the shorthand's own pin ispackages/core/src/utils/__tests__/dashboard-filters.test.ts:46, in a package that already type-checks its tests, and neither dashboard case reads the option list — both broadcasts come fromdefaultValue.2x TS7006 —
onWidgetClick={(id) => …}inferringany. Annotated(id: string | null), which restates whatDashboardRendererPropsitself declares. The reason inference failed is a real defect and is not fixed here:DashboardRendererPropscarries[key: string]: any, which putsstringinto itskeyof, so React'sPropsWithoutRefalways takes theOmitbranch, andOmitover an index-signature type keeps only the index signature. Measured with a throwaway probe compiled by the new project:So the interface is right and no JSX call site is held to it. Filed as #4528 — with
packages/plugin-list/src/ListView.tsx, the other survivor of the sweep #4422 explicitly left owed, and the note that #4438's guard test is scoped topackages/components/srcand structurally cannot see either.1x TS2571 —
vi.importActual('react')answeringunknown. The.createContextread was unchecked; it now names the module's type.2 that are NOT test defects — the packaging gap, filed as #4529. Two suites import
@object-ui/plugin-chartssubpaths that the package does not publish (itsexportsmap declares"."alone, and neither name is on the barrel); they resolve only through the repo vitest alias. This is #4325's shape one package over, and #4325's own answer — drop the import — does not transfer:normalizeChartSchemais a value the assertions run the emitted schema through, so removing it would not relocate the guarantee, it would replace the test with a restatement of the thing under test. Rather than rewrite test semantics to satisfytsc(the #4471 discipline) or change another package's public surface from a test-surface card, this PR restates the vitest alias as one narrow, commentedpathsentry in the new test project, pointingtscat the very files vitest loads. The comment says to delete it once #4529 is ruled either way, and the PM may prefer to re-scope: #4325's precedent went to "drop the subpath".Wiring
packages/plugin-dashboard/tsconfig.test.json, mirroring the recently wired siblings (core/app-shell/plugin-list), chained as"type-check": "tsc --noEmit && tsc -p tsconfig.test.json". Notsconfig.typetests.json— that population is closed by #4291.Two config choices are measured rather than copied:
types: ["node"]— load-bearing: droppingnodeturns five suites red withTS2304: Cannot find name 'global'(they install aglobal.fetchdouble).@testing-library/jest-domis deliberately absent even though 18 suites use its matchers — measured too: removing it changes nothing, because the files that use them import it explicitly and a global augmentation reached by an import applies to the whole program.libstays at the root's ES2020, unlike plugin-list / plugin-grid / app-shell which needed ES2022 forArray.prototype.at. Nothing here does, so the tests are held to the same lib the shipped source targets.includenamessrc/**/*.d.tsas well:--listFilesconfirms all 47 test files plussrc/global.d.tsare in the program (of 1818 files).The gate consequence, and what an empty table actually does
TEST_DEBTis now{}. I read the gate's code rather than assuming, because "empty" reads like "closed", and it is not:TEST_DEBTentry as an alternative to a test project, so a package that stops reading its tests can still declare the gap. The gate's design is declared / reasoned / shrink-only, not forbidden.That reasoning is written into the table's comment and pinned by a new self-test block, which asserts the table is empty and that no package with tests is uncovered (the first alone would be satisfied by deleting a row without paying it), plus three fixture cases for the three behaviours above.
Red-first
Gate, pre-fix (at
932cbcd6b):Gate, post-fix:
The wiring is load-bearing — a planted type error in
computeMetricDelta.test.ts, run through the package's own script exactly as CI does:Note which half spoke: the build
tsc --noEmitpassed silently — that is the pre-#4040 state — and only the chained project caught it. Removed immediately after; the file is byte-identical toorigin/main.The ratchet fires — restoring the deleted row while the package is covered:
and the new self-test case goes red with it:
Restored from a sha256-verified copy (
c1d1cea2…, matched after restore).Green / must-not-change
pnpm run type-check(plugin-dashboard, both passes)npx vitest run packages/plugin-dashboard/npx vitest run scripts/__tests__/check-type-check-coverage.test.tsnode scripts/check-type-check-coverage.mjsnode scripts/check-control-bytes.mjsnpx eslinton all changed filescheck-changeset-presence/-no-major/-fixedChangeset:
.changeset/plugin-dashboard-test-typecheck.mdwith empty frontmatter — the gate demanded a file (5 files under a released package'ssrc/), and this releases nothing.Findings filed, both unassigned: #4528 (forwardRef prop erasure, plugin-dashboard + plugin-list), #4529 (plugin-charts unpublished subpaths).
Generated by Claude Code