fix(login): do not block login completion on EA2 scenario fetch
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.
This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
// 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();
|
||||
@@ -0,0 +1,46 @@
|
||||
import { chromium } from "playwright";
|
||||
|
||||
const b = await chromium.launch({ headless: true });
|
||||
const ctx = await b.newContext({ viewport: { width: 1440, height: 900 } });
|
||||
const p = await ctx.newPage();
|
||||
const calls = [];
|
||||
p.on("response", async (r) => {
|
||||
const u = r.url();
|
||||
if (u.includes("/api/")) {
|
||||
calls.push({ status: r.status(), method: r.request().method(), url: u.replace("https://canvas.flow-master.ai", "") });
|
||||
}
|
||||
});
|
||||
p.on("console", (m) => { if (m.type() === "error") console.log("CONSOLE-ERR:", m.text().slice(0, 200)); });
|
||||
p.on("pageerror", (e) => console.log("PAGE-ERR:", e.message.slice(0, 200)));
|
||||
await ctx.addInitScript(() => localStorage.setItem("fm.canvas.tour.seen", String(Date.now())));
|
||||
|
||||
await p.goto("https://canvas.flow-master.ai/", { waitUntil: "domcontentloaded" });
|
||||
await p.waitForTimeout(2500);
|
||||
await p.locator(".persona-chip").filter({ hasText: /Mariana/ }).click();
|
||||
// Live auth can take 6-10s; wait for shell to flip
|
||||
await p.waitForFunction(() => !document.querySelector("[class*='shell-login']"), null, { timeout: 30000 }).catch(() => {});
|
||||
await p.waitForTimeout(3000);
|
||||
|
||||
const state = await p.evaluate(() => {
|
||||
const shell = document.querySelector("[class*='shell-']")?.className;
|
||||
const topbar = document.querySelector("header.topbar");
|
||||
const tabs = Array.from(document.querySelectorAll(".tab")).map(t => t.textContent?.trim());
|
||||
const headerByTag = document.querySelector("header")?.outerHTML?.slice(0, 200);
|
||||
return {
|
||||
shell,
|
||||
hasTopbar: !!topbar,
|
||||
headerByTag,
|
||||
tabCount: tabs.length,
|
||||
tabs,
|
||||
sceneText: document.querySelector(".scene")?.innerText?.slice(0, 300) || null,
|
||||
};
|
||||
});
|
||||
console.log(JSON.stringify(state, null, 2));
|
||||
|
||||
await p.screenshot({ path: "/tmp/canvas-evidence/measure.png", fullPage: false });
|
||||
console.log("screenshot /tmp/canvas-evidence/measure.png");
|
||||
|
||||
console.log("\n=== api calls ===");
|
||||
for (const c of calls) console.log(` ${c.status} ${c.method} ${c.url.slice(0, 100)}`);
|
||||
|
||||
await b.close();
|
||||
Reference in New Issue
Block a user