Spaces:
Running
Running
File size: 3,548 Bytes
88d2f2a | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | // V2: Per-browser trigger test — waits for hydration via networkidle (best
// effort), captures the POST response, and uses waitForURL with a 90s
// budget. Sequential per browser to avoid hammering the backend.
const fs = require("fs");
const path = require("path");
const { chromium, firefox, webkit } = require("playwright");
const BASE_URL = process.env.BASE_URL || "http://localhost:3001";
const OUT_DIR = path.resolve(__dirname, "..", "..", "outputs");
const SHOT_DIR = path.join(OUT_DIR, "screenshots");
const ENGINES = [
{ name: "chromium", launcher: chromium },
{ name: "firefox", launcher: firefox },
{ name: "webkit", launcher: webkit },
];
async function run(engine) {
const browser = await engine.launcher.launch({ headless: true });
const ctx = await browser.newContext({ viewport: { width: 1280, height: 800 }, colorScheme: "dark" });
const page = await ctx.newPage();
const errors = [];
const triggerPosts = [];
page.on("console", (m) => m.type() === "error" && errors.push(m.text()));
page.on("pageerror", (e) => errors.push(`pageerror: ${e.message}`));
page.on("requestfinished", async (req) => {
if (req.method() === "POST" && /trigger\/event/.test(req.url())) {
try {
const resp = await req.response();
const status = resp?.status();
let body = null;
try { body = await resp?.text(); } catch (_) {}
triggerPosts.push({ url: req.url(), status, body: body?.slice(0, 200) });
} catch (e) { triggerPosts.push({ url: req.url(), error: e.message }); }
}
});
const out = {
browser: engine.name, postCount: 0, postStatus: null, postBody: null,
waitForURLSucceeded: false, finalUrl: null, msToNavigate: null,
spinnerSeen: false, errors: [],
};
try {
await page.goto(`${BASE_URL}/`, { waitUntil: "domcontentloaded", timeout: 30000 });
// Wait for hydration: either networkidle within 5s or 1500ms grace if SSE keeps it open.
await page.waitForLoadState("networkidle", { timeout: 5000 }).catch(async () => {
await page.waitForTimeout(1500);
});
const btn = page.getByRole("button", { name: /trigger.*live demo/i });
await btn.waitFor({ state: "visible", timeout: 10000 });
const t0 = Date.now();
await btn.click();
try { await page.waitForSelector(".animate-spin", { timeout: 2500 }); out.spinnerSeen = true; } catch (_) {}
try {
await page.waitForURL(/\/events\/\d+/, { timeout: 90000 });
out.waitForURLSucceeded = true;
out.finalUrl = page.url();
out.msToNavigate = Date.now() - t0;
} catch (err) {
out.errors.push(`waitForURL: ${err.message.split("\n")[0]}`);
}
out.postCount = triggerPosts.length;
if (triggerPosts.length) {
out.postStatus = triggerPosts[0].status;
out.postBody = triggerPosts[0].body;
}
const shot = path.join(SHOT_DIR, `xbrowser_${engine.name}_trigger_v2.png`);
await page.screenshot({ path: shot });
out.screenshot = path.relative(OUT_DIR, shot);
} catch (err) {
out.errors.push(err.message);
} finally {
out.errors.push(...errors.slice(0, 3));
await ctx.close();
await browser.close();
}
return out;
}
(async () => {
const all = [];
for (const engine of ENGINES) {
console.log(`-- ${engine.name} --`);
const r = await run(engine);
console.log(JSON.stringify(r));
all.push(r);
}
const out = path.join(OUT_DIR, "cross_browser_trigger_v2.json");
fs.writeFileSync(out, JSON.stringify(all, null, 2));
console.log(`Wrote ${out}`);
})();
|