From 5925d09e8b047ffd44769f8c677c7aea4b9f41d4 Mon Sep 17 00:00:00 2001 From: Steve Cliff Date: Fri, 8 May 2026 22:00:24 +0100 Subject: [PATCH] e2e: wait for repo_status=ready and bump test timeout Two issues uncovered by the page-snapshot dump after the agent state-dir fix: * The host page server-renders `Run backup now` as disabled while repo_status != ready, and the page has no live-refresh on that field. The test was navigating right after status flipped to 'online' but before auto-init had completed (~3s later), so the rendered HTML still showed init_running and the click was a no-op. Wait for repo_status === 'ready' before navigating. * playwright.config.ts pinned the per-test timeout at 60s, but the test itself uses 60s + 120s of internal waits. Bump to 240s so the test fails on real regressions instead of timing out on its own internal budget. Renamed the test description away from "under a minute" since it overpromises against the new timeout. The performance SLO belongs in a separate test if we want to assert it. --- e2e/playwright/playwright.config.ts | 6 +++++- e2e/playwright/tests/lib/server.ts | 1 + e2e/playwright/tests/smoke.spec.ts | 23 +++++++++++++++-------- 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/e2e/playwright/playwright.config.ts b/e2e/playwright/playwright.config.ts index d6dbc0d..5fb2c70 100644 --- a/e2e/playwright/playwright.config.ts +++ b/e2e/playwright/playwright.config.ts @@ -10,7 +10,11 @@ const baseURL = process.env.RM_BASE_URL ?? 'http://127.0.0.1:8080'; export default defineConfig({ testDir: './tests', - timeout: 60_000, + // 4 minutes — the smoke test waits for: enrolment + bootstrap + // (~5s), auto-init landing (~10s), backup completion (~120s + // budget). 60s is far too tight in CI; 4m gives headroom even + // on a contended runner without masking real regressions. + timeout: 240_000, expect: { timeout: 10_000 }, fullyParallel: false, retries: process.env.CI ? 1 : 0, diff --git a/e2e/playwright/tests/lib/server.ts b/e2e/playwright/tests/lib/server.ts index 397a908..80bd499 100644 --- a/e2e/playwright/tests/lib/server.ts +++ b/e2e/playwright/tests/lib/server.ts @@ -10,6 +10,7 @@ export interface HostJSON { id: string; name: string; status: string; + repo_status?: string; last_backup_status?: string; } diff --git a/e2e/playwright/tests/smoke.spec.ts b/e2e/playwright/tests/smoke.spec.ts index 0dbd307..f67a806 100644 --- a/e2e/playwright/tests/smoke.spec.ts +++ b/e2e/playwright/tests/smoke.spec.ts @@ -18,7 +18,7 @@ import { } from './lib/server'; test.describe('smoke: enrol-via-announce → backup', () => { - test('happy path completes in under a minute', async ({ page, request }) => { + test('happy path: enrol → accept → backup → succeeded', async ({ page, request }) => { const { username, password } = await bootstrapAdmin(request); await loginViaUI(page, username, password); @@ -38,16 +38,23 @@ test.describe('smoke: enrol-via-announce → backup', () => { password: 'e2e-repo-password', }); - // Wait for the host to come online + auto-init to land. - const onlineHost = await waitForHostStatus( + // Wait for the host to come online AND for auto-init to + // finish. Coming online happens as soon as the agent's + // bearer-authed WS attaches (~1s after accept); repo_status + // flips to 'ready' once the auto-init job completes (a + // couple of seconds later). Loading the host page before + // that leaves the Run-backup button disabled because the + // server-rendered HTML reflects the still-in-progress init, + // and the page has no live-refresh on that field. + const readyHost = await waitForHostStatus( request, cookie, - (h) => h.status === 'online', - 60_000, + (h) => h.status === 'online' && h.repo_status === 'ready', + 90_000, ); - expect(onlineHost.id).toBeTruthy(); + expect(readyHost.id).toBeTruthy(); // Trigger a backup via the UI form-post (HX-Redirect to /jobs/{id}). - await page.goto(`${baseURL}/hosts/${onlineHost.id}`); + await page.goto(`${baseURL}/hosts/${readyHost.id}`); await Promise.all([ page.waitForURL(/\/jobs\//), page.locator('form[action$="/run-backup"] button[type="submit"]').first().click(), @@ -60,7 +67,7 @@ test.describe('smoke: enrol-via-announce → backup', () => { // surfaces. const finishedHost = await waitForHostStatus( request, cookie, - (h) => h.id === onlineHost.id && h.last_backup_status === 'succeeded', + (h) => h.id === readyHost.id && h.last_backup_status === 'succeeded', 120_000, ); expect(finishedHost.last_backup_status).toBe('succeeded');