1e896adeaa
global-setup.ts: - Usa launchPersistentContext en vez de browser.newContext() - Reemplaza storageState por marker file para cache de sesion - Captura logs de consola del browser para debug - Screenshots y HTML dump en caso de error playwright.config.ts: - Elimina storageState (ahora via persistent context fixture) - Screenshots siempre activas, video y trace en failures Tests (login, assistant-bot, asistente-2): - Importan test/expect desde persistent-context fixture - Usan handleElementDialogs() en vez de espera manual de rooms - Nuevo test de threads en asistente-2: verifica que el bot responde dentro del thread cuando se le habla por thread Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
120 lines
3.8 KiB
TypeScript
120 lines
3.8 KiB
TypeScript
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 USER_DATA_DIR = path.resolve(__dirname, ".auth", "chrome-profile");
|
|
const MARKER_PATH = path.resolve(__dirname, ".auth", "login-done.marker");
|
|
const SCREENSHOTS_DIR = path.resolve(__dirname, "test-results", "global-setup");
|
|
|
|
/**
|
|
* Global setup: ejecuta login una vez usando persistent context.
|
|
*
|
|
* A diferencia de storageState, el persistent context preserva IndexedDB
|
|
* (crypto keys de E2EE). Los tests usan el mismo userDataDir via el
|
|
* custom fixture persistent-context.ts.
|
|
*
|
|
* Si el marker file existe y no esta expirado, asumimos que la sesion
|
|
* sigue activa y saltamos el login.
|
|
*/
|
|
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 el marker existe y tiene menos de 12 horas
|
|
if (isMarkerFresh(MARKER_PATH, 12 * 60 * 60 * 1000)) {
|
|
console.log("[global-setup] Reutilizando sesion de persistent context");
|
|
return;
|
|
}
|
|
|
|
console.log("[global-setup] Ejecutando login en Element Web con persistent context...");
|
|
console.log(`[global-setup] URL: ${elementURL}`);
|
|
console.log(`[global-setup] User: ${user}`);
|
|
console.log(`[global-setup] UserDataDir: ${USER_DATA_DIR}`);
|
|
|
|
// Limpiar perfil anterior para login fresco
|
|
if (fs.existsSync(USER_DATA_DIR)) {
|
|
fs.rmSync(USER_DATA_DIR, { recursive: true });
|
|
console.log("[global-setup] Perfil anterior eliminado");
|
|
}
|
|
|
|
// Asegurar que los directorios existen
|
|
fs.mkdirSync(USER_DATA_DIR, { recursive: true });
|
|
fs.mkdirSync(SCREENSHOTS_DIR, { recursive: true });
|
|
|
|
// Usar persistent context — preserva IndexedDB (crypto keys E2EE)
|
|
const context = await chromium.launchPersistentContext(USER_DATA_DIR, {
|
|
headless: true,
|
|
viewport: { width: 1280, height: 720 },
|
|
});
|
|
|
|
const page = context.pages()[0] || (await context.newPage());
|
|
|
|
// Capturar logs de consola del browser
|
|
page.on("console", (msg) => {
|
|
const type = msg.type();
|
|
if (type === "error" || type === "warning") {
|
|
console.log(`[browser-${type}] ${msg.text()}`);
|
|
}
|
|
});
|
|
page.on("pageerror", (err) => {
|
|
console.error(`[browser-error] ${err.message}`);
|
|
});
|
|
|
|
try {
|
|
await loginToElement(page, {
|
|
url: elementURL,
|
|
user,
|
|
password,
|
|
recoveryKey,
|
|
screenshotsDir: SCREENSHOTS_DIR,
|
|
});
|
|
|
|
// Crear marker de sesion exitosa
|
|
fs.writeFileSync(MARKER_PATH, new Date().toISOString());
|
|
console.log("[global-setup] Login completado, marker creado");
|
|
|
|
await page.screenshot({
|
|
path: path.join(SCREENSHOTS_DIR, "05-login-complete.png"),
|
|
fullPage: true,
|
|
});
|
|
} catch (err) {
|
|
console.error("[global-setup] ERROR durante login:", err);
|
|
await page.screenshot({
|
|
path: path.join(SCREENSHOTS_DIR, "ERROR-login-failed.png"),
|
|
fullPage: true,
|
|
});
|
|
const html = await page.content();
|
|
fs.writeFileSync(
|
|
path.join(SCREENSHOTS_DIR, "ERROR-page-content.html"),
|
|
html
|
|
);
|
|
throw err;
|
|
} finally {
|
|
await context.close();
|
|
}
|
|
}
|
|
|
|
/** Verifica si el marker file existe y tiene menos de maxAge ms. */
|
|
function isMarkerFresh(filePath: string, maxAge: number): boolean {
|
|
try {
|
|
const stat = fs.statSync(filePath);
|
|
return Date.now() - stat.mtimeMs < maxAge;
|
|
} catch {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
export default globalSetup;
|