qa(evidence): live production verification report (#2)
This commit was merged in pull request #2.
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
// Post-login EA2 trace + screenshot bundle. Uses dev-login (the SSO 502 is
|
||||
// the user's actual issue) and walks Mission Control so polling fires.
|
||||
import { chromium } from "playwright";
|
||||
import { writeFileSync, mkdirSync } from "node:fs";
|
||||
|
||||
const URL = "https://canvas.flow-master.ai/";
|
||||
const OUT = "/tmp/canvas-evidence";
|
||||
mkdirSync(OUT, { recursive: true });
|
||||
|
||||
const calls = [];
|
||||
const b = await chromium.launch({ headless: true });
|
||||
const ctx = await b.newContext({ viewport: { width: 1440, height: 900 } });
|
||||
const p = await ctx.newPage();
|
||||
|
||||
p.on("response", async (res) => {
|
||||
const u = res.url();
|
||||
if (!u.includes("/api/")) return;
|
||||
calls.push({ url: u, status: res.status(), ts: Date.now() });
|
||||
});
|
||||
|
||||
console.log("[1/5] goto landing");
|
||||
await p.goto(URL, { waitUntil: "domcontentloaded" });
|
||||
await p.waitForTimeout(2000);
|
||||
await p.screenshot({ path: `${OUT}/01-login.png`, fullPage: false });
|
||||
|
||||
console.log("[2/5] try dev-login as CEO persona");
|
||||
const ceoChip = p.locator(".persona-chip").filter({ hasText: /Mariana/ });
|
||||
const ceoVisible = await ceoChip.count();
|
||||
console.log(` CEO persona chip count: ${ceoVisible}`);
|
||||
if (ceoVisible) {
|
||||
await ceoChip.first().click();
|
||||
await p.waitForTimeout(3000);
|
||||
}
|
||||
await p.screenshot({ path: `${OUT}/02-after-login.png`, fullPage: false });
|
||||
|
||||
console.log("[3/5] check URL + page title");
|
||||
console.log(` url: ${p.url()}`);
|
||||
console.log(` title: ${await p.title()}`);
|
||||
const headers = await p.evaluate(() => ({
|
||||
body: document.body?.innerText?.slice(0, 200) ?? "",
|
||||
scenes: document.querySelector("[class*='shell']")?.className ?? "n/a",
|
||||
}));
|
||||
console.log(` scene: ${headers.scenes}`);
|
||||
console.log(` body[0..200]: ${JSON.stringify(headers.body)}`);
|
||||
|
||||
console.log("[4/5] try to reach Mission Control");
|
||||
const missionLink = p.locator("a, button").filter({ hasText: /mission control/i }).first();
|
||||
if (await missionLink.count()) {
|
||||
await missionLink.click();
|
||||
await p.waitForTimeout(4000);
|
||||
}
|
||||
await p.screenshot({ path: `${OUT}/03-mission.png`, fullPage: false });
|
||||
|
||||
console.log("[5/5] dump network");
|
||||
const byStatus = {};
|
||||
const byHost = {};
|
||||
const byPath = {};
|
||||
for (const c of calls) {
|
||||
byStatus[c.status] = (byStatus[c.status] || 0) + 1;
|
||||
const url = new URL(c.url);
|
||||
byHost[url.host] = (byHost[url.host] || 0) + 1;
|
||||
const path = url.pathname.split("/").slice(0, 4).join("/");
|
||||
byPath[path] = (byPath[path] || 0) + 1;
|
||||
}
|
||||
|
||||
const report = {
|
||||
ts: new Date().toISOString(),
|
||||
url: URL,
|
||||
total: calls.length,
|
||||
byStatus,
|
||||
byHost,
|
||||
byPath,
|
||||
ea2Calls: calls.filter((c) => c.url.includes("/api/ea2/")).length,
|
||||
ea2Ok: calls.filter((c) => c.url.includes("/api/ea2/") && c.status === 200).length,
|
||||
authCalls: calls.filter((c) => c.url.includes("/api/v1/auth/")).length,
|
||||
authOk: calls.filter((c) => c.url.includes("/api/v1/auth/") && c.status === 200).length,
|
||||
first10: calls.slice(0, 10),
|
||||
last10: calls.slice(-10),
|
||||
};
|
||||
|
||||
writeFileSync(`${OUT}/network-report.json`, JSON.stringify(report, null, 2));
|
||||
|
||||
console.log("\n=== SUMMARY ===");
|
||||
console.log(`total /api/ calls: ${report.total}`);
|
||||
console.log(`by status: ${JSON.stringify(report.byStatus)}`);
|
||||
console.log(`by path (top):`);
|
||||
for (const [pa, n] of Object.entries(byPath).sort((a, b) => b[1] - a[1]).slice(0, 8)) {
|
||||
console.log(` ${n}\t${pa}`);
|
||||
}
|
||||
console.log(`EA2 200/total: ${report.ea2Ok}/${report.ea2Calls}`);
|
||||
console.log(`auth 200/total: ${report.authOk}/${report.authCalls}`);
|
||||
console.log(`screenshots → ${OUT}`);
|
||||
|
||||
await b.close();
|
||||
Reference in New Issue
Block a user