feat: auth fixtures y helpers de interaccion E2E
Implementa el issue 0022b — fixtures de Playwright para autenticacion en Element Web y helpers de interaccion con rooms. - element-auth.ts: flujo completo de login + cross-signing con recovery key, preparado para cachear sesion via storageState - global-setup.ts: ejecuta login una vez antes de todos los tests, reutiliza sesion cacheada si tiene menos de 12 horas - matrix-room.ts: helpers goToRoom, sendMessage, waitForBotReply, getLastMessage, assertNoDecryptionErrors (detecta "Unable to decrypt") - login.spec.ts: 3 smoke tests validando sesion, E2EE y navegacion - playwright.config.ts: configurado storageState para inyectar sesion Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
import { chromium } from "@playwright/test";
|
||||
import * as path from "path";
|
||||
import * as fs from "fs";
|
||||
import * as dotenv from "dotenv";
|
||||
import { loginToElement } from "./fixtures/element-auth";
|
||||
|
||||
dotenv.config({ path: path.resolve(__dirname, ".env") });
|
||||
|
||||
const AUTH_DIR = path.resolve(__dirname, ".auth");
|
||||
const STATE_PATH = path.join(AUTH_DIR, "state.json");
|
||||
|
||||
/**
|
||||
* Global setup: ejecuta login una vez y guarda storageState
|
||||
* para reutilizar en todos los tests sin repetir el login.
|
||||
*
|
||||
* Si state.json ya existe y no esta expirado, lo reutiliza.
|
||||
*/
|
||||
async function globalSetup() {
|
||||
const elementURL = process.env.ELEMENT_URL || "http://localhost:8080";
|
||||
const user = process.env.MATRIX_USER;
|
||||
const password = process.env.MATRIX_PASSWORD;
|
||||
const recoveryKey = process.env.MATRIX_RECOVERY_KEY;
|
||||
|
||||
if (!user || !password || !recoveryKey) {
|
||||
throw new Error(
|
||||
"Faltan variables de entorno: MATRIX_USER, MATRIX_PASSWORD, MATRIX_RECOVERY_KEY"
|
||||
);
|
||||
}
|
||||
|
||||
// Reutilizar sesion cacheada si existe y tiene menos de 12 horas
|
||||
if (isStateFresh(STATE_PATH, 12 * 60 * 60 * 1000)) {
|
||||
console.log("[global-setup] Reutilizando sesion cacheada");
|
||||
return;
|
||||
}
|
||||
|
||||
console.log("[global-setup] Ejecutando login en Element Web...");
|
||||
|
||||
// Asegurar que el directorio .auth existe
|
||||
fs.mkdirSync(AUTH_DIR, { recursive: true });
|
||||
|
||||
const browser = await chromium.launch();
|
||||
const context = await browser.newContext();
|
||||
const page = await context.newPage();
|
||||
|
||||
try {
|
||||
await loginToElement(page, {
|
||||
url: elementURL,
|
||||
user,
|
||||
password,
|
||||
recoveryKey,
|
||||
});
|
||||
|
||||
await context.storageState({ path: STATE_PATH });
|
||||
console.log("[global-setup] Sesion guardada en", STATE_PATH);
|
||||
} finally {
|
||||
await browser.close();
|
||||
}
|
||||
}
|
||||
|
||||
/** Verifica si el archivo de estado existe y tiene menos de maxAge ms. */
|
||||
function isStateFresh(filePath: string, maxAge: number): boolean {
|
||||
try {
|
||||
const stat = fs.statSync(filePath);
|
||||
return Date.now() - stat.mtimeMs < maxAge;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export default globalSetup;
|
||||
Reference in New Issue
Block a user