Three of the six Vitest projects ran on Vitest's own testTimeout: 5000 and five on its hookTimeout/teardownTimeout: 10000, and all 788 Testing Library waits in the web unit project ran on asyncUtilTimeout: 1000. None of those numbers was chosen here, and all of them were sized for an idle machine rather than for three or four concurrent worktree sessions each running a full local:gate on eight cores. #2292, #2278, #2250, #1942 and #1742 were each that class, diagnosed one site at a time. This is the complement of #1596, not a retreat from it: every fix that issue produced stands, and no race is hidden here. What changes is that a correct, deterministic test is no longer cut off by a budget nobody picked. - vitest.shared.mts exports frozen TIMEOUTS / INTEGRATION_TIMEOUTS; all six projects spread one of them, clients/launcher importing the shared module for the first time to do so. - Both web projects configure Testing Library's asyncUtilTimeout. The storybook one needs its own setup file, deliberately outside .storybook/ and free of setProjectAnnotations so the automatic preview-annotation provisioning (#1898) is untouched. - 28 per-suite restatements of the integration project's own budget are gone, so raising the shared value now moves every site under it. The handful that genuinely differ — cross-process lock contention, a full OAuth round trip — keep their budget as a named constant that says why. - AppRenderer's waitFor no longer asks for exactly its enclosing budget, which it could never win (#2292's shape); cli's e2e child timer drops below the project budget so the bound carrying the diagnostic is the one that fires. - The transition auto-settle's slack term is named RAF_SLACK_MS and raised; the term derived from HEADER_ANIM_MS is untouched. The two answer to different things and must not be scaled as one number. - The 19 Playwright budgets scattered across three web smokes become four named constants in scripts/lib/browser-timeouts.mjs. scripts/verify-test-timeouts.mjs resolves each project through Vitest itself and asserts the budgets, the asyncUtilTimeout sites, and that retry stays unset. It was observed red against the pre-change config: unit/tui/launcher at testTimeout 5000, five projects at hookTimeout 10000, both asyncUtilTimeout sites unmet. Closes #2323 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PsmUAZ6aLUAFqenjJKSSRp Signed-off-by: cliffhall <cliff@futurescale.com>
49 lines
2.2 KiB
JavaScript
49 lines
2.2 KiB
JavaScript
/**
|
|
* Playwright wall-clock budgets for the web smokes (#2323).
|
|
*
|
|
* Before this, `smoke-web-tabs.mjs`, `smoke-web-elicitation.mjs` and
|
|
* `smoke-web-browser.mjs` carried 15 locator budgets between them across three
|
|
* independently-chosen scales, with no config anywhere to raise. They are the
|
|
* same three or four decisions repeated, so they are named once here and the
|
|
* scripts import them — the same shape `render-smoke.mjs`'s `DEFAULTS` already
|
|
* has, and for the same reason: a budget nobody can find is a budget nobody
|
|
* revisits.
|
|
*
|
|
* These are generous on purpose and cost a passing run nothing. Playwright
|
|
* budgets are ceilings on a poll, not sleeps: every one of them returns the
|
|
* instant its locator condition holds. What they have to absorb is a smoke
|
|
* running against a cold `dist/` build on a machine already carrying three
|
|
* other agent sessions' gates.
|
|
*
|
|
* ⚠️ Raising one of these does NOT make a smoke wait longer for a server that
|
|
* is never coming: the launcher-death race in `smoke-web-browser.mjs` and the
|
|
* `waitForStage` diagnostics in the other two are what report that, and they
|
|
* report it with a cause rather than a timeout.
|
|
*/
|
|
|
|
export const BROWSER_TIMEOUTS = Object.freeze({
|
|
/**
|
|
* Load the page, or act on a control the app is already showing — a click on
|
|
* a rendered tab or list row, a wait for the first meaningful frame. What it
|
|
* absorbs is the browser's own scheduling under load, not a server.
|
|
*/
|
|
ui: 30_000,
|
|
/**
|
|
* Wait for something that only appears after a round trip to an MCP server:
|
|
* an elicitation modal, a tool result panel. Longer than `ui` because a test
|
|
* server has to boot, negotiate and answer before the DOM can change.
|
|
*/
|
|
roundTrip: 45_000,
|
|
/**
|
|
* Wait on a sub-element of something already on screen — a row inside a
|
|
* populated panel, a section of an open accordion. The enclosing wait has
|
|
* already paid for the round trip, so this only covers the render.
|
|
*/
|
|
nested: 15_000,
|
|
/**
|
|
* A wait whose expiry is caught and ignored, so it must stay short: it is
|
|
* pure added latency on every passing run. `networkidle` is the only one —
|
|
* the Google Fonts request may never idle on a restricted network.
|
|
*/
|
|
bestEffort: 5_000,
|
|
});
|