test(preview): raise heavy-SSR/whatIf timeouts so slow windows flake not fail (#2480)

On a contended preview node the single-replica pod gets CPU-throttled and the
heaviest flows intermittently crossed their timeout ceilings and HARD-failed
(both attempts), instead of flaking-and-recovering on retry:
 - /user/membership, /models SSR goto: observed ~66s, just past the 60s test +
   nav timeout.
 - generation whatIf waitForResponse: pushed past 25s (page+hydrate+form+resource
   +orchestrator chain) under load.

Raise per-test + navigationTimeout 60s -> 90s, and the whatIf waitForResponse
25s -> 45s. These are margins for slow windows, not masks for real breaks: the
orchestrator is ~57ms and /generate SSR ~0.4s when healthy, so a healthy run
never approaches these. Removes the hard-fail mode that made the report-only
smoke comment show  on clean PRs — a prerequisite for ever flipping smoke to
gating.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Zachary Lowden
2026-06-11 15:14:11 -05:00
committed by GitHub
parent 803c9f1c71
commit c659ff0fd0
2 changed files with 14 additions and 5 deletions
+8 -4
View File
@@ -37,16 +37,20 @@ export default defineConfig({
// and opens DB pools. The default 30s per-test timeout is too tight for that cold
// first hit, so raise both the per-test and navigation timeouts. The setup project
// also fires a warm-up request before the suite (preview-auth.setup.ts).
timeout: 60_000,
// 90s (was 60s): on a contended preview node the single-replica pod gets CPU-
// throttled and the heaviest SSR pages (/user/membership, /models) intermittently
// crossed the 60s ceiling (observed ~66s) — a slow window should flake-and-recover
// on retry, not hard-fail. 90s gives comfortable margin without masking a real hang.
timeout: 90_000,
reporter: [['list'], ['html', { open: 'never', outputFolder: 'playwright-report' }]],
use: {
baseURL: PREVIEW_URL,
trace: 'on-first-retry',
screenshot: 'only-on-failure',
// Align with the per-test timeout: a cold heavy-page (/models) goto can need
// most of the budget, and a 45s nav cap would fail it even though the test has
// 60s. The setup project also pre-warms /models + /images authenticated.
navigationTimeout: 60_000,
// most of the budget, and a tighter nav cap would fail it even though the test
// has 90s. The setup project also pre-warms /models + /images authenticated.
navigationTimeout: 90_000,
},
projects: [
{ name: 'preview-setup', testMatch: /(^|\/)preview-auth\.setup\.ts$/ },
+6 -1
View File
@@ -46,9 +46,14 @@ test.describe('generation cost quote (gold)', () => {
// 1. Primary, network-based: whatIf fires on /generate load and quotes a cost.
test('whatIfFromGraph fires on /generate and returns a numeric cost', async ({ page }) => {
// Arm the response listener BEFORE navigating so an on-load fire isn't missed.
// 45s (was 25s): whatIf is the heaviest client-side flow — page load + hydrate +
// form init + resource resolve + orchestrator round-trip must all complete before
// it fires. On a CPU-throttled preview pod a slow window pushed this past 25s and
// it hard-failed (both attempts). 45s lets a slow window flake-and-recover; the
// orchestrator itself is fast (~57ms), so this never approaches 45s when healthy.
const whatIfResponse = page.waitForResponse(
(r) => r.url().includes(WHATIF_URL) && r.status() === 200,
{ timeout: 25_000 }
{ timeout: 45_000 }
);
const resp = await page.goto('/generate', { waitUntil: 'domcontentloaded' });