diff --git a/.changeset/default-timeout-margin-repair.md b/.changeset/default-timeout-margin-repair.md new file mode 100644 index 0000000000..ad760a2952 --- /dev/null +++ b/.changeset/default-timeout-margin-repair.md @@ -0,0 +1,40 @@ +--- +"@objectstack/types": patch +"@objectstack/dogfood": patch +--- + +fix(tests): give two default-vitest-timeout cases real margin instead of a bare default (#9311) + +Two cases only passed `pnpm test` when they were not competing for CPU — the +same defect class as the already-closed precedents #3662, #4186, #4485, +#5421, #6329: a test running under vitest's **default** `testTimeout` / +`hookTimeout` with no margin for anything heavier than an idle box. + +**`packages/types/src/node.test.ts`** — `"falls back to the importing +package's own resolution when the host does not declare"` is the only case +in the file that performs a real dynamic `import()` of `@objectstack/spec` (a +multi-megabyte package); every sibling in the same `describe` block resolves +a small on-disk fixture or fails fast, all under 10ms. Measured on this box: +~0.9-1.1s unloaded, already observed failing at 5061ms against the 5000ms +default under nothing heavier than `turbo run test --concurrency=2` (#9311's +own isolation runs). Gave that one case an explicit 30s `testTimeout` — the +same order of magnitude the repo already uses for subprocess/real-load cases +(`#3662` precedent) — and left every sub-10ms sibling alone. + +**`packages/qa/dogfood/test/semantic-roles.dogfood.test.ts`** — its +`beforeAll` boots the full showcase stack (ObjectQL + ~45 plugins) through +`@objectstack/verify`'s `bootStack`, which does not fit vitest's 10s +`hookTimeout` default with any margin at all: observed failing at 10027ms +against the 10000ms budget, and this file's own isolated run measured 18.3s +(vitest `Duration`) / 19.5s wall clock for the whole file even with the box +otherwise idle. Gave the hook an explicit 180s timeout, matching this +package's own existing house pattern for the identical +`bootStack(showcaseStack, …)` call +(`admin-identity-audit-trail.dogfood.test.ts`'s `beforeAll(…, 180_000)`) +rather than inventing a new number for the same operation. + +**No behaviour change** — both suites already pass; this only gives the two +timeout-sensitive cases room to finish on a loaded box. The repo's full test +suite is confirmed green at low concurrency (#9311), so this is margin +repair, not a product fix. `turbo.json`'s default concurrency is out of scope +for this change (a maintainer-level default, per #9311's own filing). diff --git a/packages/qa/dogfood/test/semantic-roles.dogfood.test.ts b/packages/qa/dogfood/test/semantic-roles.dogfood.test.ts index a9d7701cba..5f75e77541 100644 --- a/packages/qa/dogfood/test/semantic-roles.dogfood.test.ts +++ b/packages/qa/dogfood/test/semantic-roles.dogfood.test.ts @@ -49,10 +49,20 @@ async function servedObject(name: string): Promise> { return envelope.item as Record; } +// Explicit hookTimeout (#9311): booting the full showcase stack (ObjectQL + +// ~45 plugins) through `@objectstack/verify`'s `bootStack` does not fit +// vitest's 10_000ms `hookTimeout` default with any real margin — observed +// failing at 10027ms against the 10000ms budget, and this file's own isolated +// run measured 18.3s (vitest-reported `Duration`) / 19.5s wall clock for the +// whole file even on an otherwise-idle box (boot dominates; the 5 tests +// themselves run in ~3.5s). 180_000ms follows this package's existing house +// pattern for the identical `bootStack(showcaseStack, …)` call — see +// `admin-identity-audit-trail.dogfood.test.ts`'s `beforeAll(…, 180_000)` — +// rather than inventing a new number for the same operation. beforeAll(async () => { stack = await bootStack(showcaseStack); token = await stack.signIn(); -}); +}, 180_000); afterAll(async () => { await stack?.stop(); diff --git a/packages/types/src/node.test.ts b/packages/types/src/node.test.ts index b1be2435ed..0f10c4c803 100644 --- a/packages/types/src/node.test.ts +++ b/packages/types/src/node.test.ts @@ -175,14 +175,27 @@ describe('host-app package resolution (cloud#1013, #4700)', () => { expect(new mod.OrganizationsPlugin().name).toBe('com.objectstack.organizations'); }); - it("falls back to the importing package's own resolution when the host does not declare", async () => { - // Whatever the host app does not declare must still load from the framework - // package's own dependencies — that fallback is what keeps every - // framework-owned load in `serve` (plugin-auth, plugin-security, - // service-i18n, …) and in `bootStack` working exactly as before. - const mod = await createHostImporter(undeclaringRoot)('@objectstack/spec'); - expect(mod).toBeTypeOf('object'); - }); + it( + "falls back to the importing package's own resolution when the host does not declare", + async () => { + // Whatever the host app does not declare must still load from the framework + // package's own dependencies — that fallback is what keeps every + // framework-owned load in `serve` (plugin-auth, plugin-security, + // service-i18n, …) and in `bootStack` working exactly as before. + const mod = await createHostImporter(undeclaringRoot)('@objectstack/spec'); + expect(mod).toBeTypeOf('object'); + }, + // Explicit testTimeout (#9311): this is the ONE case in this file that + // actually loads `@objectstack/spec` — a real dynamic `import()` of a + // multi-megabyte package, not the small on-disk fixtures its siblings use + // (all <10ms). Measured unloaded on a 4-CPU box: ~0.9-1.1s. Under nothing + // heavier than `turbo run test --concurrency=2` it was already observed at + // 5061ms against the 5000ms default — margin, not correctness, is the + // defect (#9311). 30s matches the #3662 precedent for subprocess/real-load + // cases elsewhere in the repo (~30x the unloaded cost, ~6x the already- + // observed loaded failure point) rather than a bare guess. + 30_000, + ); it('reports a package that neither can resolve as module-not-found', async () => { const importFromHost = createHostImporter(hostRoot);