fix: state every test-gate timeout instead of inheriting a library default
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>
This commit is contained in:
parent
336e045210
commit
58e53d5a92
1 changed files with 1276 additions and 394 deletions
|
|
@ -57,6 +57,7 @@ import { setTimeout as delay } from "node:timers/promises";
|
|||
import { join, resolve } from "node:path";
|
||||
import { startProdWebServer } from "./lib/prod-web-server.mjs";
|
||||
import { stopChild } from "./lib/child-cleanup.mjs";
|
||||
import { BROWSER_TIMEOUTS } from "./lib/browser-timeouts.mjs";
|
||||
import {
|
||||
attachPageDiagnostics,
|
||||
loadBrowser,
|
||||
|
|
@ -203,13 +204,16 @@ async function runTool(page) {
|
|||
// The main-view tabs are a Mantine SegmentedControl: a visually-hidden radio
|
||||
// plus a sibling <label for>. The label is the clickable element — there is
|
||||
// no role="tab" here, and the radio itself has no hit box.
|
||||
await page.locator('label[for$="-Tools"]').first().click({ timeout: 30_000 });
|
||||
await page
|
||||
.locator('label[for$="-Tools"]')
|
||||
.first()
|
||||
.click({ timeout: BROWSER_TIMEOUTS.ui });
|
||||
await page
|
||||
.getByRole("button", { name: TOOL, exact: true })
|
||||
.click({ timeout: 30_000 });
|
||||
.click({ timeout: BROWSER_TIMEOUTS.ui });
|
||||
await page
|
||||
.getByRole("button", { name: /execute tool/i })
|
||||
.click({ timeout: 30_000 });
|
||||
.click({ timeout: BROWSER_TIMEOUTS.ui });
|
||||
}
|
||||
|
||||
try {
|
||||
|
|
@ -244,7 +248,10 @@ try {
|
|||
'[data-testid="app-elicitation"][data-app-elicitation-status="ready"]',
|
||||
);
|
||||
try {
|
||||
await modal.waitFor({ state: "attached", timeout: 45_000 });
|
||||
await modal.waitFor({
|
||||
state: "attached",
|
||||
timeout: BROWSER_TIMEOUTS.roundTrip,
|
||||
});
|
||||
} catch {
|
||||
const any = page.locator('[data-testid="app-elicitation"]');
|
||||
const last = (await any.count())
|
||||
|
|
@ -261,14 +268,16 @@ try {
|
|||
const app = page
|
||||
.frameLocator('[data-testid="app-elicitation"] iframe')
|
||||
.frameLocator("iframe");
|
||||
await app.locator('[data-testid="choose-a"]').click({ timeout: 30_000 });
|
||||
await app
|
||||
.locator('[data-testid="choose-a"]')
|
||||
.click({ timeout: BROWSER_TIMEOUTS.ui });
|
||||
|
||||
// The tool echoes the ElicitResult it received, so the result pane proves
|
||||
// the app's standard result reached the SERVER — not merely the host.
|
||||
await page
|
||||
.getByText(/"action":"accept".*"choice":"option-a"/)
|
||||
.first()
|
||||
.waitFor({ state: "attached", timeout: 45_000 });
|
||||
.waitFor({ state: "attached", timeout: BROWSER_TIMEOUTS.roundTrip });
|
||||
await shot(page, "app-elicitation-result");
|
||||
|
||||
// ── 2. Not negotiated: the same tool falls back to the native form ─────
|
||||
|
|
@ -279,11 +288,14 @@ try {
|
|||
const nativeDialog = page.getByRole("dialog", {
|
||||
name: /elicitation request/i,
|
||||
});
|
||||
await nativeDialog.waitFor({ state: "visible", timeout: 45_000 });
|
||||
await nativeDialog.waitFor({
|
||||
state: "visible",
|
||||
timeout: BROWSER_TIMEOUTS.roundTrip,
|
||||
});
|
||||
await nativeDialog
|
||||
.getByText("Choose option A or B.")
|
||||
.first()
|
||||
.waitFor({ state: "visible", timeout: 15_000 });
|
||||
.waitFor({ state: "visible", timeout: BROWSER_TIMEOUTS.nested });
|
||||
// The modal fades in; a screenshot taken on the first visible frame catches
|
||||
// a transparent overlay. Nothing is asserted on this delay.
|
||||
await delay(600);
|
||||
|
|
|
|||
Loading…
Reference in a new issue