From 12efbac95ad41806ac274c03d00dc75bff23af29 Mon Sep 17 00:00:00 2001 From: "gandalf-the-greybeard[bot]" Date: Mon, 9 Mar 2026 21:14:53 +0000 Subject: [PATCH] fix: improve E2E auth resilience and diagnostics MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Wait for Authentik popup to fully load (domcontentloaded + networkidle) before interacting with form elements - Add explicit waitFor on username/password fields with 15s timeout - Enable screenshot capture on test failure for better diagnostics - Increase auth setup timeout to 60s to accommodate slow IdP responses The auth setup was failing because the popup form elements weren't ready when Playwright tried to fill them — this adds proper load state waits between each interaction step. --- e2e/auth.setup.ts | 17 +++++++++++++---- playwright.config.ts | 3 ++- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/e2e/auth.setup.ts b/e2e/auth.setup.ts index bbf0054..817f003 100644 --- a/e2e/auth.setup.ts +++ b/e2e/auth.setup.ts @@ -12,12 +12,21 @@ async function authenticateWithOIDC(page: Page, username: string, password: stri await page.getByRole('button', { name: /sign in/i }).click(); const popup = await popupPromise; - // Authentik step 1: fill username - await popup.getByRole('textbox', { name: /email or username/i }).fill(username); + // Wait for the Authentik popup to fully load before interacting + await popup.waitForLoadState('domcontentloaded'); + await popup.waitForLoadState('networkidle'); + + // Authentik step 1: fill username — wait for the form to render + const usernameField = popup.getByRole('textbox', { name: /email or username/i }); + await usernameField.waitFor({ state: 'visible', timeout: 15_000 }); + await usernameField.fill(username); await popup.getByRole('button', { name: /log in/i }).click(); - // Authentik step 2: fill password - await popup.getByRole('textbox', { name: /password/i }).fill(password); + // Authentik step 2: fill password — wait for the next step to load + await popup.waitForLoadState('networkidle'); + const passwordField = popup.getByRole('textbox', { name: /password/i }); + await passwordField.waitFor({ state: 'visible', timeout: 15_000 }); + await passwordField.fill(password); await popup.getByRole('button', { name: /continue|log in/i }).click(); // Wait for the popup to close (Authentik redirects back, Headlamp processes callback) diff --git a/playwright.config.ts b/playwright.config.ts index 1043870..16808ba 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -11,9 +11,10 @@ export default defineConfig({ use: { baseURL: process.env.HEADLAMP_URL || 'https://headlamp.animaniacs.farh.net', trace: 'on-first-retry', + screenshot: 'only-on-failure', }, projects: [ - { name: 'setup', testMatch: /auth\.setup\.ts/ }, + { name: 'setup', testMatch: /auth\.setup\.ts/, timeout: 60_000 }, { name: 'chromium', use: { -- 2.52.0