// Parcours d'interactions Playwright sur la fiche (mobile) : galerie plein // écran, panneau « Voir les N lieux », « Demander à Ka », accordéons — vérifie // l'absence d'erreur JS et que chaque panneau s'ouvre puis se ferme. // Usage : node frontend/scripts/interactions.mjs [baseUrl] import { chromium, devices } from "playwright"; const UID = process.argv[2]; const BASE = process.argv[3] || "http://127.0.0.1:8096"; if (!UID) { console.error("usage: node interactions.mjs [baseUrl]"); process.exit(2); } const browser = await chromium.launch(); const ctx = await browser.newContext({ ...devices["iPhone 14"] }); const page = await ctx.newPage(); const errs = []; page.on("pageerror", (e) => errs.push("PAGEERROR " + e.message)); page.on("console", (m) => { if (m.type() === "error") errs.push(m.text().slice(0, 160)); }); await page.goto(`${BASE}/propriete/${encodeURIComponent(UID)}`, { waitUntil: "networkidle" }); await page.waitForSelector(".ik-hero"); const step = async (name, fn) => { try { await fn(); console.log("OK ", name); } catch (e) { console.log("FAIL", name, String(e).split("\n")[0]); } }; await step("galerie → plein écran → fermer", async () => { await page.click(".ik-gallery-full"); await page.waitForSelector(".ik-lightbox", { timeout: 3000 }); await page.click(".ik-lightbox-close"); await page.waitForSelector(".ik-lightbox", { state: "detached", timeout: 3000 }); }); await step("accordéon score", async () => { await page.click("#score .ik-acc-btn"); await page.waitForSelector("#score .ik-acc-body.open", { timeout: 2000 }); }); await step("accordéon caractéristiques publiées", async () => { const b = page.locator("#propriete .ik-acc-btn").first(); await b.scrollIntoViewIfNeeded(); await b.click(); await page.waitForSelector("#propriete .ik-acc-body.open", { timeout: 2000 }); }); await step("financement : test de résistance", async () => { await page.locator("#financement").scrollIntoViewIfNeeded(); await page.waitForTimeout(1500); const b = page.locator("#financement .ik-acc-btn").first(); await b.click(); await page.waitForSelector("#financement .ik-acc-body.open", { timeout: 2000 }); }); await step("carte : filtre Épiceries", async () => { await page.locator("#carte").scrollIntoViewIfNeeded(); await page.waitForTimeout(2500); const chip = page.locator("#carte .ik-chip:not([disabled])").first(); await chip.click(); await page.waitForTimeout(800); }); await step("lieux : bottom sheet", async () => { await page.locator("#proximite").scrollIntoViewIfNeeded(); await page.waitForTimeout(800); await page.click("#proximite .ik-more"); await page.waitForSelector(".ik-sheet", { timeout: 3000 }); await page.click(".ik-sheet-x"); await page.waitForSelector(".ik-sheet", { state: "detached", timeout: 3000 }); }); await step("Demander à Ka : sheet", async () => { await page.evaluate(() => window.scrollTo(0, 1500)); await page.waitForTimeout(500); await page.click(".ik-ka-btn"); await page.waitForSelector(".ik-sheet", { timeout: 3000 }); await page.click(".ik-sheet-x"); await page.waitForSelector(".ik-sheet", { state: "detached", timeout: 3000 }); }); await step("404", async () => { await page.goto(`${BASE}/propriete/inexistant:0`, { waitUntil: "networkidle" }); await page.waitForSelector(".ik-page-error", { timeout: 8000 }); }); console.log("erreurs console:", errs.length, errs.slice(0, 5)); await browser.close(); process.exit(errs.filter((e) => !/Failed to fetch|api-ka|kaa/.test(e)).length ? 1 : 0);