// Validation ordre des sections — fiche Lou-Ka (ordre DOM = ordre visuel) // Refonte 2026-09-04 : sections `.lk-*` / ids ; vérifie sur mobile que // l'ordre visuel est croissant, que la page s'ouvre en haut (scrollY 0), que // le héro (prix + galerie) est le premier contenu, qu'aucune section ne porte // un `order` CSS et qu'il n'y a pas de débordement horizontal. // Usage : node frontend/scripts/check-order.mjs [uid] [baseUrl] import { chromium, devices } from "playwright"; const UID = process.argv[2] || "zumper:60608306"; const BASE = process.argv[3] || "http://localhost:8095"; const URL = `${BASE}/logement/${encodeURIComponent(UID)}`; async function check(name, ctxOpts) { const browser = await chromium.launch(); const ctx = await browser.newContext(ctxOpts); const page = await ctx.newPage(); const errors = []; page.on("pageerror", (e) => errors.push(String(e))); page.on("console", (m) => { if (m.type() === "error") errors.push(m.text()); }); await page.goto(URL, { waitUntil: "networkidle" }); await page.waitForSelector(".lk-hero", { timeout: 20000 }); await page.waitForTimeout(2500); const data = await page.evaluate(() => { const sel = [".lk-hero", "#score", "#resume", ".lk-nav", "#prix", "#logement", "#description", "#inclusions", "#carte", "#proximite", "#transport", "#quartier", "#ka-scores", "#loyers", "#cout", "#risques", "#air", "#essence", "#dossier", "#sources"]; const out = []; for (const s of sel) { const el = document.querySelector(s); if (!el) { out.push({ s, missing: true }); continue; } const r = el.getBoundingClientRect(); out.push({ s, hidden: r.height === 0 && r.width === 0, top: Math.round(r.top + window.scrollY), left: Math.round(r.left), order: getComputedStyle(el).order }); } return { out, scrollY: window.scrollY, overflow: document.documentElement.scrollWidth - window.innerWidth }; }); console.log(`\n=== ${name} === scrollY initial: ${data.scrollY} · débordement horizontal: ${data.overflow}px`); for (const b of data.out) console.log(b.missing ? `${b.s.padEnd(14)} (non rendue)` : b.hidden ? `${b.s.padEnd(14)} (vide/masquée)` : `${b.s.padEnd(14)} top=${String(b.top).padStart(6)} left=${String(b.left).padStart(4)} order=${b.order}`); if (errors.length) console.log("console errors:", errors.slice(0, 5)); await browser.close(); return { ...data, errors }; } const mob = await check("iPhone 14 (mobile)", { ...devices["iPhone 14"] }); const desk = await check("Desktop 1440px", { viewport: { width: 1440, height: 900 } }); const vis = mob.out.filter((b) => !b.missing && !b.hidden); const sorted = vis.every((b, i) => i === 0 || b.top >= vis[i - 1].top); const noOrder = vis.every((b) => b.order === "0"); const ok = sorted && mob.scrollY === 0 && vis[0].s === ".lk-hero" && vis[0].top < 200 && noOrder && mob.overflow <= 0 && desk.overflow <= 0; console.log(`\nMOBILE: ordre visuel ${sorted ? "CROISSANT ✓" : "DÉSORDONNÉ ✗"} · scrollY=${mob.scrollY} · 1re section=${vis[0].s} top=${vis[0].top} · sans order CSS=${noOrder} · overflow mobile=${mob.overflow} desktop=${desk.overflow}`); console.log(ok ? "VALIDATION OK" : "VALIDATION ÉCHEC"); process.exit(ok ? 0 : 1);