---
name: pw_kanban_login
kind: function
lang: ts
domain: browser
version: "1.0.0"
purity: impure
signature: "async (page: Page, opts: PwLoginOptions) => Promise<void>"
description: "Authenticates a Playwright Page against the kanban backend via POST /api/login. Sets session cookie and navigates to root. Throws on failure or if login page remains visible."
tags: [playwright, e2e, browser, kanban]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: "error_go_core"
imports: []
params:
  - name: page
    desc: "Playwright Page (typically from pw_launch_browser). The page context shares storageState with page.request, so the Set-Cookie response propagates automatically."
  - name: opts
    desc: "{username, password, baseUrl?}. baseUrl defaults to the origin derived from page.url() — so the page must already be navigated to the target host before calling this function."
output: "void; throws on failed login (HTTP >= 400) or if login page selectors remain visible after navigation. After resolve, page is on root (baseUrl + '/') and the kanban_session cookie is active."
tested: true
tests:
  - "happy path"
  - "rejects 401"
  - "rejects when login page still visible"
test_file_path: "frontend/functions/browser/pw_kanban_login.test.ts"
file_path: "frontend/functions/browser/pw_kanban_login.ts"
---

## Ejemplo

```typescript
import { pw_launch_browser } from "@fn_library/../browser/pw_launch_browser";
import { pw_kanban_login } from "@fn_library/../browser/pw_kanban_login";

const { page, close } = await pw_launch_browser({ baseUrl: "http://localhost:5180" });
await pw_kanban_login(page, { username: "egutierrez", password: "..." });
// page is now on http://localhost:5180/ with kanban_session cookie active
await close();
```

## Cuando usarla

Usala al inicio de cualquier test Playwright o script e2e contra el kanban. Despues de esta llamada el `page` esta autenticado y puede acceder a rutas protegidas sin redireccion al login.

## Gotchas

- `page.url()` debe devolver una URL valida con origin antes de llamar a esta funcion si no se pasa `baseUrl`. Si la pagina no ha navegado todavia (`about:blank`), pasar `baseUrl` explicitamente.
- La funcion asume que `page.request` comparte el contexto de cookies con `page` (comportamiento por defecto de Playwright). Si usas un `APIRequestContext` separado, la cookie no se propagara automaticamente.
- La comprobacion post-login busca texto literal "Login" o "Iniciar sesion". Si el backend usa otro texto en el boton, la comprobacion pasara aunque la autenticacion haya fallado silenciosamente — en ese caso ampliar los selectores de sanidad.
- Espera `networkidle` tras `goto`: si la app lanza requests continuos (polling, WebSocket upgrade), `networkidle` puede tardar o no resolverse. Considerar `page.waitForURL` como alternativa en esos casos.
