test(plugin-list): type-check its tests and clear its TEST_DEBT entry (#4040) - #4338
Merged
Conversation
…#4040) Wires `tsconfig.test.json` into the package's `type-check` script and fixes the 9 code-tier errors that surfaced (registry declared 6). A further 14 were config-tier — all one missing built-in, `Array.prototype.at` — closed by raising the test project's `lib` to ES2022, not the package's. Four of the nine are one phenomenon: `ListViewSchema` is the CANONICAL surface and `ListView` reads only that (it calls `normalizeListViewSchema` first), so fixtures authoring the LEGACY spellings the fold exists to accept — `aria.label`, `sharing: { enabled, visibility }`, and the ObjectQL FilterNode form of `filter` — were pre-fold input sitting in a post-fold type. Re-spelling them canonically would delete the only coverage that the fold still runs; widening the schema would re-fork the vocabulary #2890 unified. They are cast through a named `authored()` helper instead, and the missing input type is filed as #4337. The rest: a permissions fixture whose object grants were spelled in two keys `ObjectPermissionConfig` never declared, in two places — one of which carried a comment crediting the inert block with driving a gate it does not reach; a gantt fixture missing the spec-required `titleField`; and `emitFor`'s untyped `Record<string, unknown>` parameter, which was hiding a call that supplies no `operator` at all. Refs #4040
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
Contributor
✅ Console Performance Budget
📦 Bundle Size Report
Size Limits
|
yinlianghui
marked this pull request as ready for review
August 11, 2026 17:19
github-merge-queue
Bot
removed this pull request from the merge queue due to a conflict with the base branch
Aug 11, 2026
…il removal landed in #4326, plugin-list removal is this PR's)
Contributor
✅ Console Performance Budget
📦 Bundle Size Report
Size Limits
|
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 — one package per PR, per the standing objectstack#4118 ruling.
@object-ui/plugin-listnow type-checks its 31 test files; itsTEST_DEBTentry is gone.Measured, not trusted
The registry declared 6. The package has 23 raw errors, splitting 14 config-tier / 9 code-tier — so 9 real, 1.5x the declared count. The 14 are a single missing built-in:
Array.prototype.at, used to read the last emitted call. The compiler named the remedy itself ("Try changing the 'lib' compiler option to 'es2022' or later"), so the test project takeslib: ES2022— nottsconfig.json, which keeps compiling the shipped source against its ES2020 baseline. That split is the whole reason the config-tier/code-tier distinction exists; measuring at the root'slibwould have reported this package as 2.5x worse than it is.Four of the nine are one phenomenon
ListView.tsx:581isnormalizeListViewSchema(propSchema)before anything else, soListViewonly ever reads the canonical vocabulary — andListViewSchematypes exactly that. Fixtures that author the legacy spellings the fold exists to accept were therefore pre-fold input sitting in a post-fold type:ListView.test.tsx:561aria: { label }aria: { ariaLabel }ListView.test.tsx:579sharing: { enabled, visibility }sharing: { type }emptyStateFilteredCopyx2filter: [['status','not_in',[…]]]ViewFilterRule[]All three compiler verdicts are correct and none of the fixtures is wrong. The two tempting fixes are both worse than a cast, which is why they are named in the code:
ListViewSchemare-forks the vocabulary Migrate the remaining ListView legacy vocabulary to spec-canonical keys, and audit ObjectView/DetailView (#2231 phases 4–5) #2890 unified, and puts legacy keys back on the surface every consumer reads.So they go through a named
authored()helper whose comment carries the reasoning. The missing input type is filed as #4337 —normalizeListViewSchemais< T >(schema: T): T, so the legacy vocabulary it accepts is documented in prose and declared nowhere. That finding also records the sharperfiltercase: per the normalizer's own contract note, objectui'sfiltercarries an ObjectQL FilterNode array in production while being typed asViewFilterRule[]— a real divergence, not a test artefact.The other five
ListView.permissions.test.tsx, two fixtures — object grants spelledobjectPermissions: { read: true, … }beside aroleNameecho of the map key. Neither key exists onObjectPermissionConfig['roles'][string]; both were inert. Rewritten to theactionschannelevaluatePermissionactually reads. No assertion moves: the field gate runs throughcheckField, which readsfieldPermissionsdirectly. The second fixture is the more interesting one — it already carried the correctactionslist, under a comment crediting the inertobjectPermissionsblock with driving "the field-level gate". That gate ischeckField, it readsfieldPermissions, and that fixture declares none, so the block decided nothing there at all. TheRoleDefinitionfixture gainslabel+permissions: []per the convention fix(permissions): type-check its tests (#4040 tranche 1) #4287 set (dormancy filed asRoleDefinition.permissionsis required and read by nothing — every consumer uses onlyname/inherits#4288).ListView.test.tsx:1813— gantt fixture missing the spec-requiredtitleField. Supplied rather than cast: the case is about the spec config winning over the legacyoptionsblock, so it ought to be a spec-valid config.UserFilters.tabPresetOperators.test.tsx—emitFor(rule: Record< string, unknown >). Typing it properly immediately surfaced a second error the bag had been hiding: one call supplies nooperatorat all. That call is deliberate (it pins that the deletedcase undefined: return '='branch has not come back), so the parameter makesoperatoroptional and the single cast moves to the boundary where the off-spec rule is injected, with the reason next to it.Discrimination proof
A — the config actually runs. objectui#3009's third failure mode. A provably-false line in a file only the new project reads; the first two compilers pass it, the third reports it:
B — the legacy fixtures are real coverage of the fold, not decoration. This is the claim the whole
authored()decision rests on, so it is measured rather than asserted. Change only the LEGACY value (visibility: 'team'to'private') and the folded output moves:The legacy key is read, folded, and drives the assertion — so re-spelling the fixture canonically would have removed the only thing testing it. The same probe on the
ariacase: deleting the block fails withUnable to find an accessible element with the role "region" and name "Contacts List", and the canonicalariaLabelspelling passes — both spellings work, which is exactly what the fold promises and what this fixture is here to keep true.Verification
Merged
origin/main(clean — no registry conflict; #4324/#4331/#4327 landed while this was in flight), rebuilt the dependency closure because@object-ui/corechanged in that merge, and re-ran both type-check and the suite afterwards.Changeset: empty frontmatter — tests and build config only, no package source changed, so nothing is released.
Generated by Claude Code