// QA screenshots: node apps/web/qa/shoot.mjs [suffix] (uses Playwright from ~/Desktop/uqo-eval) import { createRequire } from "node:module"; import { mkdirSync } from "node:fs"; import { dirname, resolve } from "node:path"; import { fileURLToPath } from "node:url"; const require = createRequire("/Users/simon-pierreboucher/Desktop/uqo-eval/package.json"); const { chromium } = require("playwright"); const out = dirname(fileURLToPath(import.meta.url)); mkdirSync(out, { recursive: true }); const suffix = process.argv[2] ? `-${process.argv[2]}` : ""; const BASE = process.env.BASE ?? "http://localhost:8310"; const PAGES = [ ["home", "/"], ["map", "/map"], ["search", "/search?q=montreal"], ["live", "/live"], ["datacenters", "/datacenters"], ["about", "/about"], ]; const WIDTHS = (process.env.WIDTHS ?? "320,360,390,430,768,1280").split(",").map(Number); const THEME = process.env.THEME ?? "light"; const ONLY = process.env.PAGES ? new Set(process.env.PAGES.split(",")) : null; const browser = await chromium.launch(); const report = []; for (const w of WIDTHS) { const ctx = await browser.newContext({ viewport: { width: w, height: w < 700 ? 800 : 900 }, deviceScaleFactor: 1, isMobile: w < 700, hasTouch: w < 700 }); await ctx.addInitScript((theme) => { try { window.localStorage.setItem("theme", theme); } catch {} }, THEME); const page = await ctx.newPage(); for (const [name, path] of PAGES) { if (ONLY && !ONLY.has(name)) continue; await page.goto(`${BASE}${path}`, { waitUntil: "load", timeout: 45000 }).catch((e) => console.log("goto failed", name, w, String(e).slice(0, 80))); await page.waitForTimeout(name === "map" ? 3500 : 1200); const overflow = await page.evaluate(() => { const doc = document.documentElement; const wide = []; for (const el of document.querySelectorAll("body *")) { const r = el.getBoundingClientRect(); if (r.right > doc.clientWidth + 1 && r.width > 0 && getComputedStyle(el).position !== "fixed") wide.push(`${el.tagName.toLowerCase()}.${(el.className && typeof el.className === "string" ? el.className : "").split(" ").slice(0, 2).join(".")}:${Math.round(r.right - doc.clientWidth)}`); } return { scrollWidth: doc.scrollWidth, clientWidth: doc.clientWidth, wide: wide.slice(0, 5) }; }); report.push({ w, name, overflow: overflow.scrollWidth > overflow.clientWidth ? overflow : "ok" }); await page.screenshot({ path: resolve(out, `${name}-${w}${suffix}.png`), fullPage: name !== "map" }); } await ctx.close(); } await browser.close(); for (const r of report) console.log(r.w, r.name, typeof r.overflow === "string" ? r.overflow : JSON.stringify(r.overflow));