diff --git a/.changeset/vi-mock-inherit-slice9-plugin-detail.md b/.changeset/vi-mock-inherit-slice9-plugin-detail.md new file mode 100644 index 0000000000..b5f8f8856d --- /dev/null +++ b/.changeset/vi-mock-inherit-slice9-plugin-detail.md @@ -0,0 +1,4 @@ +--- +--- + +Test-only change: the 13 `vi.mock('@object-ui/plugin-detail', ...)` factories that hand-listed the barrel's exports now inherit the real module and override after it, and `@object-ui/plugin-detail` joins the `check-vi-mock-inherit` gate's covered set. No published behaviour changes. diff --git a/packages/plugin-calendar/src/ObjectCalendar.colorFieldLadder-7243.test.tsx b/packages/plugin-calendar/src/ObjectCalendar.colorFieldLadder-7243.test.tsx index 9cce4d7c8b..ffd8e2d847 100644 --- a/packages/plugin-calendar/src/ObjectCalendar.colorFieldLadder-7243.test.tsx +++ b/packages/plugin-calendar/src/ObjectCalendar.colorFieldLadder-7243.test.tsx @@ -92,7 +92,8 @@ import { describe, it, expect, vi } from 'vitest'; import { ObjectCalendar } from './ObjectCalendar'; import { __resolveEventColorForTest as resolveEventColor } from './CalendarView'; -vi.mock('@object-ui/plugin-detail', () => ({ +vi.mock('@object-ui/plugin-detail', async (importOriginal) => ({ + ...(await importOriginal()), RecordDetailDrawer: () => null, deriveRecordPageHref: () => null, })); diff --git a/packages/plugin-calendar/src/ObjectCalendar.externalDataCeiling-7507.test.tsx b/packages/plugin-calendar/src/ObjectCalendar.externalDataCeiling-7507.test.tsx index 988663e55c..54cd8c1278 100644 --- a/packages/plugin-calendar/src/ObjectCalendar.externalDataCeiling-7507.test.tsx +++ b/packages/plugin-calendar/src/ObjectCalendar.externalDataCeiling-7507.test.tsx @@ -40,7 +40,8 @@ import { describe, it, expect, vi } from 'vitest'; import { NON_GRID_ROW_CEILING } from '@object-ui/react'; import { ObjectCalendar } from './ObjectCalendar'; -vi.mock('@object-ui/plugin-detail', () => ({ +vi.mock('@object-ui/plugin-detail', async (importOriginal) => ({ + ...(await importOriginal()), RecordDetailDrawer: () => null, deriveRecordPageHref: () => null, })); diff --git a/packages/plugin-calendar/src/ObjectCalendar.rowCeiling-7210.test.tsx b/packages/plugin-calendar/src/ObjectCalendar.rowCeiling-7210.test.tsx index bc195b81da..9b563fce2c 100644 --- a/packages/plugin-calendar/src/ObjectCalendar.rowCeiling-7210.test.tsx +++ b/packages/plugin-calendar/src/ObjectCalendar.rowCeiling-7210.test.tsx @@ -49,7 +49,8 @@ import { describe, it, expect, vi } from 'vitest'; import { NON_GRID_ROW_CEILING, NON_GRID_ROW_CEILING_TOP } from '@object-ui/react'; import { ObjectCalendar } from './ObjectCalendar'; -vi.mock('@object-ui/plugin-detail', () => ({ +vi.mock('@object-ui/plugin-detail', async (importOriginal) => ({ + ...(await importOriginal()), RecordDetailDrawer: () => null, deriveRecordPageHref: () => null, })); diff --git a/packages/plugin-calendar/src/ObjectCalendar.unscheduled-7071.test.tsx b/packages/plugin-calendar/src/ObjectCalendar.unscheduled-7071.test.tsx index 91da72f22f..ac18c89d07 100644 --- a/packages/plugin-calendar/src/ObjectCalendar.unscheduled-7071.test.tsx +++ b/packages/plugin-calendar/src/ObjectCalendar.unscheduled-7071.test.tsx @@ -53,7 +53,8 @@ afterEach(cleanup); // The overlay drawer is irrelevant here and drags in a per-record permission // probe that would leave the process for real (see the propsContract suite's // own note on that probe). Stub it out. -vi.mock('@object-ui/plugin-detail', () => ({ +vi.mock('@object-ui/plugin-detail', async (importOriginal) => ({ + ...(await importOriginal()), RecordDetailDrawer: () => null, deriveRecordPageHref: () => null, })); diff --git a/packages/plugin-gantt/src/ObjectGantt.apifetch.test.tsx b/packages/plugin-gantt/src/ObjectGantt.apifetch.test.tsx index f214891e1b..37b1ceca4a 100644 --- a/packages/plugin-gantt/src/ObjectGantt.apifetch.test.tsx +++ b/packages/plugin-gantt/src/ObjectGantt.apifetch.test.tsx @@ -26,7 +26,8 @@ vi.mock('./GanttView', () => ({ ), })); -vi.mock('@object-ui/plugin-detail', () => ({ +vi.mock('@object-ui/plugin-detail', async (importOriginal) => ({ + ...(await importOriginal()), RecordDetailDrawer: () => null, deriveRecordPageHref: () => null, })); diff --git a/packages/plugin-gantt/src/ObjectGantt.colorFieldLadder-7243.test.tsx b/packages/plugin-gantt/src/ObjectGantt.colorFieldLadder-7243.test.tsx index 70c0acade7..20044248e6 100644 --- a/packages/plugin-gantt/src/ObjectGantt.colorFieldLadder-7243.test.tsx +++ b/packages/plugin-gantt/src/ObjectGantt.colorFieldLadder-7243.test.tsx @@ -104,7 +104,8 @@ import { ObjectGantt } from './ObjectGantt'; vi.mock('sonner', () => ({ toast: { error: vi.fn() } })); -vi.mock('@object-ui/plugin-detail', () => ({ +vi.mock('@object-ui/plugin-detail', async (importOriginal) => ({ + ...(await importOriginal()), RecordDetailDrawer: () => null, deriveRecordPageHref: () => null, })); diff --git a/packages/plugin-gantt/src/ObjectGantt.drawerfetch.test.tsx b/packages/plugin-gantt/src/ObjectGantt.drawerfetch.test.tsx index 634e47265e..536afb544c 100644 --- a/packages/plugin-gantt/src/ObjectGantt.drawerfetch.test.tsx +++ b/packages/plugin-gantt/src/ObjectGantt.drawerfetch.test.tsx @@ -31,7 +31,8 @@ vi.mock('./GanttView', () => ({ })); let drawerProps: any = null; -vi.mock('@object-ui/plugin-detail', () => ({ +vi.mock('@object-ui/plugin-detail', async (importOriginal) => ({ + ...(await importOriginal()), RecordDetailDrawer: (props: any) => { drawerProps = props; return ( diff --git a/packages/plugin-gantt/src/ObjectGantt.drawerlock.test.tsx b/packages/plugin-gantt/src/ObjectGantt.drawerlock.test.tsx index 39bcd136a6..8ed9ccbe39 100644 --- a/packages/plugin-gantt/src/ObjectGantt.drawerlock.test.tsx +++ b/packages/plugin-gantt/src/ObjectGantt.drawerlock.test.tsx @@ -29,7 +29,8 @@ vi.mock('./GanttView', () => ({ ), })); -vi.mock('@object-ui/plugin-detail', () => ({ +vi.mock('@object-ui/plugin-detail', async (importOriginal) => ({ + ...(await importOriginal()), RecordDetailDrawer: (props: any) => (
({ GanttView: ({ tasks }: any) =>
{tasks.length}
, })); -vi.mock('@object-ui/plugin-detail', () => ({ +vi.mock('@object-ui/plugin-detail', async (importOriginal) => ({ + ...(await importOriginal()), RecordDetailDrawer: () => null, deriveRecordPageHref: () => null, })); diff --git a/packages/plugin-gantt/src/ObjectGantt.fetchGate-7225.test.tsx b/packages/plugin-gantt/src/ObjectGantt.fetchGate-7225.test.tsx index 16729a0c40..c30c226508 100644 --- a/packages/plugin-gantt/src/ObjectGantt.fetchGate-7225.test.tsx +++ b/packages/plugin-gantt/src/ObjectGantt.fetchGate-7225.test.tsx @@ -70,7 +70,8 @@ vi.mock('./GanttView', () => ({ ), })); -vi.mock('@object-ui/plugin-detail', () => ({ +vi.mock('@object-ui/plugin-detail', async (importOriginal) => ({ + ...(await importOriginal()), RecordDetailDrawer: () => null, deriveRecordPageHref: () => null, })); diff --git a/packages/plugin-gantt/src/ObjectGantt.hostDataProp-7210.test.tsx b/packages/plugin-gantt/src/ObjectGantt.hostDataProp-7210.test.tsx index 86e76a4df7..d80dc9255a 100644 --- a/packages/plugin-gantt/src/ObjectGantt.hostDataProp-7210.test.tsx +++ b/packages/plugin-gantt/src/ObjectGantt.hostDataProp-7210.test.tsx @@ -67,7 +67,8 @@ vi.mock('./GanttView', () => ({ ), })); -vi.mock('@object-ui/plugin-detail', () => ({ +vi.mock('@object-ui/plugin-detail', async (importOriginal) => ({ + ...(await importOriginal()), RecordDetailDrawer: () => null, deriveRecordPageHref: () => null, })); diff --git a/packages/plugin-gantt/src/ObjectGantt.rowCeiling-7210.test.tsx b/packages/plugin-gantt/src/ObjectGantt.rowCeiling-7210.test.tsx index 566c981a8a..080e6cf569 100644 --- a/packages/plugin-gantt/src/ObjectGantt.rowCeiling-7210.test.tsx +++ b/packages/plugin-gantt/src/ObjectGantt.rowCeiling-7210.test.tsx @@ -61,7 +61,8 @@ vi.mock('./GanttView', () => ({ ), })); -vi.mock('@object-ui/plugin-detail', () => ({ +vi.mock('@object-ui/plugin-detail', async (importOriginal) => ({ + ...(await importOriginal()), RecordDetailDrawer: () => null, deriveRecordPageHref: () => null, })); diff --git a/packages/plugin-tree/src/ObjectTree.rowCeiling-7210.test.tsx b/packages/plugin-tree/src/ObjectTree.rowCeiling-7210.test.tsx index 1495e1c42d..9c768873b0 100644 --- a/packages/plugin-tree/src/ObjectTree.rowCeiling-7210.test.tsx +++ b/packages/plugin-tree/src/ObjectTree.rowCeiling-7210.test.tsx @@ -44,7 +44,18 @@ import { describe, it, expect, vi } from 'vitest'; import { NON_GRID_ROW_CEILING, NON_GRID_ROW_CEILING_TOP } from '@object-ui/react'; import { ObjectTree } from './ObjectTree'; -vi.mock('@object-ui/plugin-detail', () => ({ +// objectui#6892 slice 9 — inherit the real surface, but through `` rather +// than the `typeof import('@object-ui/plugin-detail')` its twelve siblings use. +// ⚠️ Not a style drift, and ⛔ do not "fix" it to match them: `plugin-tree` does +// NOT declare `@object-ui/plugin-detail`, and it has no reason to — measured, +// `ObjectTree`'s module graph reaches ZERO plugin-detail modules, where +// `ObjectGantt`'s and `ObjectCalendar`'s each reach 50. So this factory mocks a +// module nothing under test ever loads. A type-position `import()` of it is a +// real specifier to `check-phantom-dependencies`, which then (correctly) demands +// the package declare a dependency its runtime does not have. `` inherits +// the surface without asserting an edge that isn't there. +vi.mock('@object-ui/plugin-detail', async (importOriginal) => ({ + ...((await importOriginal()) as Record), RecordDetailDrawer: () => null, deriveRecordPageHref: () => null, })); diff --git a/scripts/check-vi-mock-inherit.mjs b/scripts/check-vi-mock-inherit.mjs index 6829fbaff0..849f7714e8 100644 --- a/scripts/check-vi-mock-inherit.mjs +++ b/scripts/check-vi-mock-inherit.mjs @@ -82,7 +82,7 @@ * - **Workspace specifiers not in `COVERED_SPECIFIERS`.** See below. * * `COVERED_SPECIFIERS` holds the workspace packages whose frozen sites have - * actually been SWEPT to zero. Today that is thirteen, and each joined by sweep + * actually been SWEPT to zero. Today that is fourteen, and each joined by sweep * rather than by judgement. Running this file's classifier over all 1,499 * `vi.mock` call sites in the tree at `9ce20233f`: * @@ -460,12 +460,60 @@ * module's graph reaches it; walk the graph, then read the neighbours against * it. * - * The remaining 74 stay on objectui#6892: `@object-ui/app-shell` (23, ALL - * frozen, still only after objectui#6580 -- which is now CLOSED, so that - * reading is a git-history read rather than an open card), - * `@object-ui/plugin-detail` (13), `@object-ui/plugin-chatbot` (11), - * `@object-ui/plugin-designer` (10), `@object-ui/plugin-list` (9) and - * `@object-ui/fields` (8). + * `@object-ui/plugin-detail` joined as objectui#6892's NINTH slice, re-derived + * on `310c0ab19` by the same `scan()` method, the constant below again never + * widened-and-reverted: + * + * @object-ui/plugin-detail 17 judged, 4 inheriting, 13 frozen -> 0 + * + * with the population moving 74 -> 61 frozen over 659 judged and no site moving + * the other way. The 13 frozen sites sit in three owning packages (8 under + * `packages/plugin-gantt`, 4 under `packages/plugin-calendar`, 1 under + * `packages/plugin-tree`) and in ONE syntactic shape -- all 13 are + * zero-parameter object-literal arrows, the most uniform surface this worklist + * has swept. + * + * ⭐ The import-cost reading this slice owed, and why an isolated probe would + * have answered it WRONG. Both `vitest.config.mts` and `apps/console`'s config + * alias this specifier to `packages/plugin-detail/src`, so `importOriginal` + * transforms the barrel's graph on demand -- and that graph is the LARGEST this + * worklist has walked: 564 modules and 6,181 module-scope statements, carrying + * 127 `ComponentRegistry.register` calls and 99 bare side-effect imports, the + * latter almost entirely the `@object-ui/components` renderer cascade. Timed + * COLD in an otherwise-empty test file, `importOriginal` of this barrel costs a + * median of 8.8s (8815ms / 8646ms / 8827ms) -- squarely in objectui#6580's + * ~10s `@object-ui/app-shell` range, which the dispatch defined as a STOP. + * + * ⛔ That number is an ARTEFACT of the empty file, and acting on it would have + * stopped a free conversion. Measured on the REAL files instead -- the only + * measurement that decides anything -- the marginal cost is roughly zero: + * gantt 9.81s frozen -> 9.73s inheriting, tree 9.65s -> 9.84s, calendar 9.32s + * -> 10.32s, i.e. -0.1s to +1.0s per file, the `@object-ui/plugin-grid` range + * and not objectui#6580's. The mechanism is a SUBSET relation, and it is + * measured rather than argued: every one of these 13 files already imports + * `@object-ui/react` and its own view component (`./ObjectGantt` and friends) + * at module scope, and those two together reach 572 modules -- a strict + * SUPERSET of the barrel's 564, with `comm -23` reporting exactly ZERO modules + * that inheriting adds. `importOriginal` here resolves an already-resident + * graph; it loads nothing new. + * + * ⇒ CARRY-FORWARD, and it generalises past this specifier: a barrel's import + * cost is NOT a property of the barrel. Measure it in the files that will pay + * it, against what they already load, and never from a probe that imports the + * barrel alone -- the probe answers "what does this graph cost from cold", + * which is the wrong question whenever the consuming file already holds it. + * + * The neighbours in these 13 files are 7 frozen `sonner` factories plus 12 + * local whole-module replacements (`./GanttView` 8, `./CalendarView` 4), all + * out of scope by construction, and slice 6's collection-death class again did + * not fire: this barrel's graph reaches neither `sonner` nor those local + * modules. ZERO neighbouring repairs. + * + * The remaining 61 stay on objectui#6892: `@object-ui/app-shell` (23, ALL + * frozen, PARKED under objectui#8173 -- objectui#6892 and the closed + * objectui#6580 point opposite ways on that one specifier and a seat does not + * decide it), `@object-ui/plugin-chatbot` (11), `@object-ui/plugin-designer` + * (10), `@object-ui/plugin-list` (9) and `@object-ui/fields` (8). * * **The precondition for widening is a sweep, not a judgement.** Convert a * specifier's frozen factories to the inheriting form, confirm this gate reads @@ -563,6 +611,7 @@ export const COVERED_SPECIFIERS = Object.freeze([ '@object-ui/components', '@object-ui/plugin-grid', '@object-ui/permissions', + '@object-ui/plugin-detail', ]); /** Files the walk reads at all. */