# 0022b — E2E Tests: Auth fixtures y helpers de interaccion > Parte de [0022 — Tests E2E con Playwright](0022-e2e-tests-playwright.md) > Depende de: [0022a — Infraestructura base](0022a-e2e-infra.md) ## Objetivo Implementar los fixtures de Playwright para autenticacion en Element Web (login + cross-signing E2EE) y los helpers de interaccion con rooms Matrix (enviar mensajes, esperar respuestas de bots). ## Contexto - Element Web requiere login + verificacion de dispositivo con recovery key para desencriptar mensajes E2EE - El flujo de login es lento (~10s) — se cachea con `storageState` de Playwright para reutilizar entre tests - Los helpers de room abstraen la interaccion con la UI de Element para que los tests sean legibles - Depende de 0022a: el proyecto Node.js y Element Web local ya deben estar configurados ## Arquitectura ``` e2e/ ├── global-setup.ts NEW — ejecuta login una vez, guarda storageState ├── fixtures/ │ ├── element-auth.ts NEW — flujo de login + cross-signing │ └── matrix-room.ts NEW — goToRoom, sendMessage, waitForBotReply, getLastMessage └── .auth/ └── state.json NEW (generado) — sesion autenticada cacheada ``` ### Patron pure core / impure shell 100% infra de testing, sin cambios al codigo Go. ## Tareas ### Fase 1: Fixture de autenticacion - [ ] **1.1** Crear `e2e/fixtures/element-auth.ts` con el flujo completo: 1. Navegar a Element Web 2. Click "Sign in" 3. Configurar homeserver URL si no esta preset 4. Ingresar usuario y contraseña 5. Manejar prompt de verificacion de dispositivo 6. Ingresar recovery key para cross-signing 7. Verificar login exitoso (lista de rooms visible) - [ ] **1.2** Crear `e2e/global-setup.ts`: - Lanzar browser - Ejecutar flujo de login de `element-auth.ts` - Guardar sesion con `page.context().storageState({ path: 'e2e/.auth/state.json' })` - Cerrar browser - [ ] **1.3** Actualizar `playwright.config.ts` para usar `globalSetup` y `storageState` ### Fase 2: Helpers de interaccion - [ ] **2.1** Crear `e2e/fixtures/matrix-room.ts` con helpers: - `goToRoom(page, roomName)` — buscar y navegar a un room por nombre - `sendMessage(page, text)` — escribir mensaje en el composer y enviar - `waitForBotReply(page, options?)` — esperar respuesta de un bot con timeout configurable, filtrar por sender si se especifica - `getLastMessage(page)` — obtener texto del ultimo mensaje del timeline - [ ] **2.2** Implementar deteccion de "Unable to decrypt" — si aparece, el test debe fallar con mensaje claro indicando problema de E2EE ### Fase 3: Tests de validacion - [ ] **3.1** Crear `e2e/tests/login.spec.ts` — smoke test: - Login funciona (usa storageState cacheado) - Se ven rooms en el sidebar - No aparece "Unable to decrypt" en mensajes recientes - [ ] **3.2** Verificar que el segundo run reutiliza la sesion cacheada (no repite login) - [ ] **3.3** Verificar que los helpers navegan correctamente a rooms de los bots --- ## Ejemplo de uso ```typescript // global-setup.ts import { chromium } from '@playwright/test'; import { loginToElement } from './fixtures/element-auth'; async function globalSetup() { const browser = await chromium.launch(); const page = await browser.newPage(); await loginToElement(page, { url: process.env.ELEMENT_URL!, user: process.env.MATRIX_USER!, password: process.env.MATRIX_PASSWORD!, recoveryKey: process.env.MATRIX_RECOVERY_KEY!, }); await page.context().storageState({ path: 'e2e/.auth/state.json' }); await browser.close(); } export default globalSetup; ``` ```typescript // Uso de helpers en un test (preview de 0022c) import { goToRoom, sendMessage, waitForBotReply } from '../fixtures/matrix-room'; test('bot responde', async ({ page }) => { await goToRoom(page, 'Assistant Bot'); await sendMessage(page, 'Hola'); const reply = await waitForBotReply(page, { timeout: 30_000 }); expect(reply).toBeTruthy(); }); ``` ## Decisiones de diseno - **storageState global**: el login + cross-signing se hace una sola vez en `globalSetup`. Todos los tests arrancan ya autenticados. - **Helpers como funciones puras de page**: reciben `page` como argumento en vez de extender fixtures de Playwright, para simplicidad y reusabilidad. - **Deteccion explicita de E2EE fallido**: en vez de timeouts silenciosos, detectar "Unable to decrypt" y fallar con mensaje descriptivo. ## Prerequisitos - 0022a completado (proyecto Node.js, Element Web local funcionando) - Usuario de test con cross-signing configurado en el homeserver - `.env` con credenciales validas ## Riesgos - **UI de cross-signing cambia entre versiones de Element**: mitigacion con version fijada en 0022a y screenshots on failure. - **Recovery key formato inconsistente**: las palabras pueden tener espacios. Asegurarse de que el input acepta el formato tal cual esta en `.env`. - **Sesion expirada**: si el token caduca entre runs, `globalSetup` debe re-autenticar. Implementar deteccion de sesion invalida.