From 8e8b3bb6ccfb90f0041321c05b7a11beb050e6ff Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 2 Oct 2026 21:35:08 +0000 Subject: [PATCH] test: load package barrels at module top so the collect phase pays for them Five test cases loaded a package barrel with a dynamic import inside the case, which charges the whole index graph's load to vitest's per-case 5000ms budget; one of them was measured timing out on a loaded box. Each barrel is now loaded at module top, as the core precedent service-resolution-discriminator.contract.test.ts already does, so the load is charged to the collect phase and the cases assert behaviour only. - objectql system-write-organization: static namespace import of the barrel. - core security/platform-admin: static namespace import of the security entry. - lint validate-predicate-path-refs: static namespace import of the barrel. - plugin-sharing translations/serving-seam: the committed barrel is a static import; the moved-source barrel is evaluated at module top (resetModules, doMock, import, doUnmock), which replaces the per-case beforeEach. - lint lazy-deps keeps its in-case import (the load is its subject), now with a one-line note saying so. No timeout, retry, skip, config or source change. Claude-Session: https://claude.ai/code/session_01DDZNkDVwPQnevTFcYE47H3 Co-authored-by: Claude --- .../core/src/security/platform-admin.test.ts | 15 +++++++- packages/lint/src/lazy-deps.test.ts | 1 + .../src/validate-predicate-path-refs.test.ts | 14 ++++++- .../src/system-write-organization.test.ts | 15 +++++++- .../src/translations/serving-seam.test.ts | 38 ++++++++++++------- 5 files changed, 64 insertions(+), 19 deletions(-) diff --git a/packages/core/src/security/platform-admin.test.ts b/packages/core/src/security/platform-admin.test.ts index 707034e2d41..5942b7294ab 100644 --- a/packages/core/src/security/platform-admin.test.ts +++ b/packages/core/src/security/platform-admin.test.ts @@ -23,6 +23,17 @@ import { setPlatformAdminConfigSink, type PlatformAdminConfigSink, } from './platform-admin.js'; +// The security entry is loaded HERE, at module top, and not by a dynamic import +// inside the case that probes it below. That import loads the entry's whole +// re-export graph (signatures, sandbox, permission enforcement), and inside a +// case the load is charged to vitest's per-case budget (5000ms by default), so +// the pin's verdict would turn on how loaded the machine is. At module top the +// same load is charged to the COLLECT phase, where no per-case budget applies. +// The case loses nothing: it asserts export presence and absence only, and the +// entry only re-exports, so loading it earlier observes no env this file's +// hooks set or clear. Same reasoning as the core precedent +// `packages/core/src/service-resolution-discriminator.contract.test.ts`. +import * as securityEntry from './index.js'; const ENV = 'OS_PLATFORM_OWNER_EMAIL'; @@ -275,8 +286,8 @@ describe('[#11663 L5] the legacy-grant deprecation pointer is retired', () => { expect('resolvePlatformAdminEmails' in mod).toBe(true); }); - it("⛔ nor by `@objectstack/core`'s security entry — the published surface lost them", async () => { - const entry: Record = await import('./index.js'); + it("⛔ nor by `@objectstack/core`'s security entry — the published surface lost them", () => { + const entry: Record = securityEntry; expect('reportLegacyPlatformAdminGrant' in entry).toBe(false); expect('resetLegacyPlatformAdminGrantReport' in entry).toBe(false); // Positive control on the same entry: its sibling config exports are still diff --git a/packages/lint/src/lazy-deps.test.ts b/packages/lint/src/lazy-deps.test.ts index 6f16b9cac05..fb1dec22892 100644 --- a/packages/lint/src/lazy-deps.test.ts +++ b/packages/lint/src/lazy-deps.test.ts @@ -180,6 +180,7 @@ describe('lazy dependency loading (kernel boot-path contract)', () => { it('loads each dep lazily in-process and the gates still work', async () => { const req = createRequire(import.meta.url); + // Kept in-case on purpose: loading the barrel IS this case's subject, budgeted by COLD_LOAD_TIMEOUT_MS. const { validateReactPages, validateReactPageProps, diff --git a/packages/lint/src/validate-predicate-path-refs.test.ts b/packages/lint/src/validate-predicate-path-refs.test.ts index 4f29fb15112..6fdf7489d8b 100644 --- a/packages/lint/src/validate-predicate-path-refs.test.ts +++ b/packages/lint/src/validate-predicate-path-refs.test.ts @@ -26,6 +26,17 @@ import { PREDICATE_RHS_PATH_SHAPED, } from './validate-predicate-path-refs.js'; import { AUTHORING_RULES } from './authoring-rules.js'; +// The published barrel is loaded HERE, at module top, and not by a dynamic +// import inside the case that reads the id off it. That import loads the whole +// `@objectstack/lint` index graph, and inside a case the load is charged to +// vitest's per-case budget (5000ms by default), so the case's verdict would +// turn on how loaded the machine is. At module top the same load is charged to +// the COLLECT phase, where no per-case budget applies. The case loses nothing: +// it asserts an id's value and identity only. `lazy-deps.test.ts` is the one +// file here that keeps its barrel load inside a case, because that load is its +// subject. Same reasoning as the core precedent +// `packages/core/src/service-resolution-discriminator.contract.test.ts`. +import * as barrel from './index.js'; // ── A miniature target schema, so the traversal is pinned against a shape the // test fully controls rather than against whatever `FieldSchema` happens to @@ -372,8 +383,7 @@ describe('validatePredicatePathRefs — path-shaped right-hand side (#7659)', () expect(rhs('data.name == $b')).toEqual([]); }); - it('emits the id the published barrel exports', async () => { - const barrel = await import('./index.js'); + it('emits the id the published barrel exports', () => { expect(barrel.PREDICATE_RHS_PATH_SHAPED).toBe('predicate-rhs-path-shaped'); expect(rhs('data.name == data.type')[0].rule).toBe(barrel.PREDICATE_RHS_PATH_SHAPED); }); diff --git a/packages/objectql/src/system-write-organization.test.ts b/packages/objectql/src/system-write-organization.test.ts index 1679cb84eb2..f5d00312a92 100644 --- a/packages/objectql/src/system-write-organization.test.ts +++ b/packages/objectql/src/system-write-organization.test.ts @@ -44,6 +44,17 @@ import { SystemWriteOrganizationRequiredError, SYSTEM_WRITE_ORGANIZATION_REQUIRED_CODE, } from './tenancy/system-write-organization.js'; +// The package barrel is loaded HERE, at module top, and not by a dynamic import +// inside the barrel case at the foot of this file. That import loads the whole +// `@objectstack/objectql` index graph, and inside a case the load is charged to +// vitest's per-case budget (5000ms by default): the case was measured timing +// out on a loaded box while its assertions held, so its verdict was a function +// of the machine rather than of the code. At module top the same load is +// charged to the COLLECT phase, where no per-case budget applies. The case +// loses nothing: it asserts symbol identity only, and the barrel itself only +// re-exports. Same reasoning, and the same shape, as the core precedent +// `packages/core/src/service-resolution-discriminator.contract.test.ts`. +import * as barrel from './index.js'; const ORG_ID = 'org_msokm9oaz0cal87q'; const SECOND_ORG_ID = 'org_second'; @@ -499,11 +510,11 @@ describe('#14936 the published recognizer for the org-less system-write refusal' expect(pinned).toBe(SYSTEM_WRITE_ORGANIZATION_REQUIRED_CODE); }); - it('publishes both names from the package BARREL, not only from the module', async () => { + it('publishes both names from the package BARREL, not only from the module', () => { // The card's landing surface is "the module plus that package's index.ts // export" - a consumer reaches these by bare specifier, so an export that // exists only on the deep module is not the affordance that was asked for. - const barrel = await import('./index.js'); + // `barrel` is the module-top import (see the imports for why it is there). expect(barrel.SYSTEM_WRITE_ORGANIZATION_REQUIRED_CODE).toBe(SYSTEM_WRITE_ORGANIZATION_REQUIRED_CODE); expect(barrel.isSystemWriteOrganizationRequiredError).toBe(isSystemWriteOrganizationRequiredError); }); diff --git a/packages/plugins/plugin-sharing/src/translations/serving-seam.test.ts b/packages/plugins/plugin-sharing/src/translations/serving-seam.test.ts index 71220809dcf..9d8e14d9fe2 100644 --- a/packages/plugins/plugin-sharing/src/translations/serving-seam.test.ts +++ b/packages/plugins/plugin-sharing/src/translations/serving-seam.test.ts @@ -35,11 +35,20 @@ // the seam is wired. The source has to be MOVED for the two to differ, which is // what the mock below does. -import { describe, it, expect, vi, beforeEach } from 'vitest'; +import { describe, it, expect, vi } from 'vitest'; import { withSourceFallback, findStaleFills } from '@objectstack/platform-objects/apps'; import { enObjects } from './en.objects.generated.js'; import { esESObjects } from './es-ES.objects.generated.js'; import { esESGeneratedSourceHashes } from './es-ES.source-hashes.generated.js'; +// The barrel as committed, loaded HERE, at module top. Both of this file's +// barrel loads happen at module top and neither inside a case: a fresh load of +// the barrel and its bundles inside a case is charged to vitest's per-case +// budget (5000ms by default), so the verdict would turn on how loaded the +// machine is, while at module top the same load is charged to the COLLECT +// phase, where no per-case budget applies. The second load, against a moved +// source, is below `revisedSource`. Same reasoning as the core precedent +// `packages/core/src/service-resolution-discriminator.contract.test.ts`. +import { SharingTranslations } from './index.js'; /** The leaf the gap was measured on: recorded in es-ES only. */ const PATH = ['objects', 'sys_share_link', 'fields', 'token', 'label'] as const; @@ -64,12 +73,18 @@ function revisedObjects() { /** The same thing as a `TranslationData` — what the barrel passes as `source`. */ const revisedSource = () => ({ objects: revisedObjects() }); -describe('SharingTranslations — the provenance companion is read at serving time', () => { - beforeEach(() => { - vi.resetModules(); - vi.doUnmock('./en.objects.generated.js'); - }); +// The SAME barrel, evaluated a second time with the source string behind the +// recorded leaf revised. This setup has to run before the load it shapes, which +// is why it sits here at module top rather than in a hook: `resetModules` drops +// the copy the static import above cached, so the import below evaluates the +// barrel afresh against the mock, and `doUnmock` takes the mock straight back +// out, so the static bindings and every case see the committed bundles. +vi.resetModules(); +vi.doMock('./en.objects.generated.js', () => ({ enObjects: revisedObjects() })); +const { SharingTranslations: servedAfterSourceMoved } = await import('./index.js'); +vi.doUnmock('./en.objects.generated.js'); +describe('SharingTranslations — the provenance companion is read at serving time', () => { it('the leaf under test is recorded in es-ES and is a byte copy of the current source', () => { const path = PATH.join('.'); expect(esESGeneratedSourceHashes[path]).toBeTypeOf('string'); @@ -81,14 +96,12 @@ describe('SharingTranslations — the provenance companion is read at serving ti expect(stale.map((s) => s.path)).toEqual([PATH.join('.')]); }); - it('SERVES the current source when the source moves under the recorded leaf', async () => { - vi.doMock('./en.objects.generated.js', () => ({ enObjects: revisedObjects() })); - const { SharingTranslations } = await import('./index.js'); - expect(read(SharingTranslations['es-ES'])).toBe(REVISED); + it('SERVES the current source when the source moves under the recorded leaf', () => { + expect(read(servedAfterSourceMoved['es-ES'])).toBe(REVISED); // The locales with no record for this path are legacy-trusted and untouched — // recovery is per-locale, which is the half of ruling #8765 Option B that a // blanket "fall back to source" would have destroyed. - expect(read(SharingTranslations['zh-CN'])).toBe('令牌'); + expect(read(servedAfterSourceMoved['zh-CN'])).toBe('令牌'); }); it('NEGATIVE CONTROL: the same bundle with no companion serves the superseded draft', () => { @@ -96,8 +109,7 @@ describe('SharingTranslations — the provenance companion is read at serving ti expect(read(unserved)).toBe('Token'); }); - it('substitutes nothing while the source has not moved', async () => { - const { SharingTranslations } = await import('./index.js'); + it('substitutes nothing while the source has not moved', () => { expect(read(SharingTranslations['es-ES'])).toBe(read({ objects: enObjects })); }); });