If buildLiveScenariosFromApi hangs or errors on any EA2 read, loginAs would await it forever, leaving the user stuck on 'VERIFYING...' even after auth+identity succeed. Make refreshLive fire-and-forget after the toast; the Mission scene re-fetches on mount and surfaces failures via liveError.
66 lines
2.5 KiB
JavaScript
66 lines
2.5 KiB
JavaScript
// DOM-introspection — measure topbar item count, sizes, overlap.
|
|
import { chromium } from "playwright";
|
|
|
|
const URL = "https://canvas.flow-master.ai/";
|
|
const b = await chromium.launch({ headless: true });
|
|
const ctx = await b.newContext({ viewport: { width: 1440, height: 900 } });
|
|
const p = await ctx.newPage();
|
|
await ctx.addInitScript(() => localStorage.setItem("fm.canvas.tour.seen", String(Date.now())));
|
|
|
|
await p.goto(URL, { waitUntil: "domcontentloaded" });
|
|
await p.waitForTimeout(2500);
|
|
|
|
console.log("=== LOGIN PAGE ===");
|
|
const loginHas = await p.evaluate(() => ({
|
|
topbar: !!document.querySelector(".topbar"),
|
|
personaChips: document.querySelectorAll(".persona-chip").length,
|
|
ssoBtn: !!document.querySelector(".sso-btn"),
|
|
emailInput: !!document.querySelector("input[type='email']"),
|
|
banner: document.querySelector(".global-banner, .login-banner")?.textContent?.slice(0, 100) || null,
|
|
}));
|
|
console.log(JSON.stringify(loginHas, null, 2));
|
|
|
|
console.log("\n=== POST-LOGIN ===");
|
|
await p.locator(".persona-chip").filter({ hasText: /Mariana/ }).click();
|
|
await p.waitForSelector(".topbar", { timeout: 15000 }).catch(() => {});
|
|
await p.waitForTimeout(3000);
|
|
|
|
const topbar = await p.evaluate(() => {
|
|
const tb = document.querySelector(".topbar");
|
|
if (!tb) return null;
|
|
const items = Array.from(tb.children).map((el) => ({
|
|
tag: el.tagName.toLowerCase(),
|
|
class: el.className,
|
|
text: el.textContent?.trim().slice(0, 50),
|
|
width: el.getBoundingClientRect().width,
|
|
}));
|
|
const tabs = Array.from(tb.querySelectorAll(".tab")).map((el) => el.textContent?.trim());
|
|
const actions = Array.from(tb.querySelectorAll(".topbar-actions > *")).map((el) => ({
|
|
tag: el.tagName.toLowerCase(),
|
|
class: el.className.slice(0, 40),
|
|
text: el.textContent?.trim().slice(0, 30),
|
|
}));
|
|
return {
|
|
totalWidth: tb.getBoundingClientRect().width,
|
|
children: items,
|
|
tabs,
|
|
actionsCount: actions.length,
|
|
actions,
|
|
overflows: tb.scrollWidth > tb.clientWidth,
|
|
};
|
|
});
|
|
console.log(JSON.stringify(topbar, null, 2));
|
|
|
|
console.log("\n=== USER MENU ===");
|
|
await p.locator(".user-avatar").first().click().catch(() => {});
|
|
await p.waitForTimeout(800);
|
|
const menu = await p.evaluate(() => {
|
|
const m = document.querySelector(".user-menu-pop");
|
|
if (!m) return { open: false };
|
|
const items = Array.from(m.querySelectorAll(".user-menu-item")).map((el) => el.textContent?.trim().slice(0, 50));
|
|
return { open: true, items, width: m.getBoundingClientRect().width };
|
|
});
|
|
console.log(JSON.stringify(menu, null, 2));
|
|
|
|
await b.close();
|