import type { Page } from "playwright"; /** Options for authenticating a Playwright Page against the kanban backend. */ export interface PwLoginOptions { username: string; password: string; /** Base URL of the kanban server. Defaults to the origin of page.url(). */ baseUrl?: string; } /** * pw_kanban_login — authenticates a Playwright Page against the kanban backend. * * Posts credentials to POST /api/auth/login. The request fixture shares storageState * with the page context, so the Set-Cookie: kanban_session cookie auto-propagates. * After successful login, navigates to root and verifies the login page is gone. * * Throws if the login response returns HTTP >= 400 or if the login page remains * visible after navigation. */ export async function pw_kanban_login(page: Page, opts: PwLoginOptions): Promise { const { username, password } = opts; // Resolve baseUrl from opts or from current page origin const baseUrl = opts.baseUrl ?? new URL(page.url()).origin; // POST credentials — page.request shares cookies/storageState with the page context const response = await page.request.post(`${baseUrl}/api/auth/login`, { data: { username, password }, }); if (response.status() >= 400) { throw new Error(`kanban login failed: ${response.status()}`); } // Navigate to root; cookie is already propagated via shared context await page.goto(`${baseUrl}/`); await page.waitForLoadState("networkidle"); await page.waitForSelector("body", { state: "attached" }); // Sanity check: ensure we are no longer on the login page const loginTextVisible = (await page.locator("text=Login").isVisible()) || (await page.locator("text=Iniciar sesión").isVisible()); if (loginTextVisible) { throw new Error("kanban login failed: login page still visible after authentication"); } }