feat: extraer dismissAllToasts a element-utils.ts

Mueve la logica de cierre de toasts a un modulo compartido (element-utils.ts) para evitar duplicacion. persistent-context.ts importa dismissAllToasts desde ahi y la invoca despues de verificar el sidebar. Se mejora tambien la deteccion del sidebar usando multiples locators alternativos (mx_RoomList, mx_LeftPanel_roomListContainer, mx_RoomTile) para mayor compatibilidad con distintas versiones de Element Web.
This commit is contained in:
2026-03-08 17:33:29 +00:00
parent a4f3e77a4f
commit c370c189d2
2 changed files with 105 additions and 7 deletions
+53
View File
@@ -0,0 +1,53 @@
import { Page } from "@playwright/test";
/**
* Cierra todos los toasts/notificaciones de Element que bloquean clicks.
* Incluye: Notifications, Threads Activity Centre, y cualquier toast generico.
*/
export async function dismissAllToasts(page: Page) {
// Dar un momento para que los toasts aparezcan
await page.waitForTimeout(1_500);
// Estrategia directa: buscar botones conocidos de toasts de Element
const knownDismissButtons = [
page.getByRole("button", { name: "Dismiss" }),
page.locator("button").filter({ hasText: /^OK$/ }),
page.getByRole("button", { name: "Close" }),
page.getByRole("button", { name: "Not now" }),
page.getByRole("button", { name: "Got it" }),
page.getByRole("button", { name: "Skip" }),
];
for (const btn of knownDismissButtons) {
try {
if (await btn.first().isVisible()) {
const text = await btn.first().textContent().catch(() => "?");
console.log(`[element] Dismissing toast: clicking "${text}"`);
await btn.first().click({ force: true });
await page.waitForTimeout(500);
}
} catch {
// Ignorar errores — el boton pudo desaparecer entre check y click
}
}
// Segunda pasada: verificar si queda algun toast con boton visible
const remainingToastBtns = page.locator(
'.mx_ToastContainer button, .mx_Toast_buttons button'
);
const remaining = await remainingToastBtns.count();
if (remaining > 0) {
for (let i = 0; i < remaining; i++) {
try {
if (await remainingToastBtns.nth(i).isVisible()) {
const text = await remainingToastBtns.nth(i).textContent();
console.log(`[element] Closing remaining toast button: "${text}"`);
await remainingToastBtns.nth(i).click({ force: true });
await page.waitForTimeout(300);
}
} catch {
// Ignorar
}
}
}
}
+52 -7
View File
@@ -1,5 +1,6 @@
import { test as base, chromium, BrowserContext, Page } from "@playwright/test";
import * as path from "path";
import { dismissAllToasts } from "./element-utils";
/**
* Custom test fixture que usa un persistent browser context compartido.
@@ -50,10 +51,12 @@ export const test = base.extend<
});
/**
* Maneja dialogos de Element que bloquean la carga:
* Maneja dialogos y toasts de Element que bloquean la carga:
* - "Element is open in another window" → click Continue
* - Spinner de carga → esperar
* - "Missing session data" → error informativo
* - "Notifications" toast → click Dismiss
* - "Threads Activity Centre" toast → click OK
* - Cualquier otro toast → intentar cerrarlo
*
* Llamar despues de page.goto("/")
*/
@@ -84,11 +87,53 @@ export async function handleElementDialogs(page: Page) {
);
}
// 3. Esperar a que rooms sidebar aparezca (sesion cargada)
console.log("[element] Esperando rooms sidebar...");
const roomsTree = page.locator('[role="tree"][aria-label="Rooms"]');
await roomsTree.waitFor({ state: "visible", timeout: 30_000 });
console.log("[element] Rooms sidebar visible");
// 3. Esperar a que la sidebar aparezca (sesion cargada)
// Usamos multiples locators porque Element Web cambia la estructura entre versiones
console.log("[element] Esperando sidebar con rooms...");
const sidebarLocators = [
page.locator('[role="tree"][aria-label="Rooms"]'),
page.locator(".mx_RoomList"),
page.locator(".mx_LeftPanel_roomListContainer"),
page.locator('[role="treeitem"]'),
// Rooms visibles como items en el sidebar
page.locator(".mx_RoomTile"),
];
let sidebarFound = false;
for (const locator of sidebarLocators) {
const visible = await locator.first()
.waitFor({ state: "visible", timeout: 30_000 })
.then(() => true)
.catch(() => false);
if (visible) {
console.log("[element] Sidebar visible");
sidebarFound = true;
break;
}
}
if (!sidebarFound) {
// Verificar si estamos en la pagina de login
const onLoginPage = await page.locator('text="Welcome to Element!"').isVisible().catch(() => false)
|| await page.getByRole("link", { name: "Sign in" }).isVisible().catch(() => false);
if (onLoginPage) {
throw new Error(
"Sesion no cargada: se muestra la pagina de login. " +
"Borrar .auth/ y re-ejecutar: rm -rf e2e/.auth && ./dev-scripts/e2e/run.sh"
);
}
await page.screenshot({
path: "test-results/ERROR-no-sidebar.png",
fullPage: true,
});
throw new Error("Sidebar de rooms no encontrado despues de 30s");
}
// 4. Cerrar TODOS los toasts que bloquean interacciones
await dismissAllToasts(page);
}
export { dismissAllToasts } from "./element-utils";
export { expect } from "@playwright/test";