Food-Ka — agrégateur de produits d'épicerie du Québec — www.food-ka.com
Python 53.9%
TypeScript 24%
CSS 14.9%
JavaScript 5.8%
HTML 1.4%
1// Validation UX filtres — barre compacte + panneau (mobile iPhone d'abord)2import { chromium, devices } from "playwright";34const BASE = process.env.BASE || "http://localhost:8097";5const SHOTS = process.env.SHOTS || "/tmp/foodka-filtres";67async function run(name, ctxOpts, mobile) {8 const browser = await chromium.launch();9 const ctx = await browser.newContext(ctxOpts);10 const page = await ctx.newPage();11 const errors = [];12 page.on("pageerror", (e) => errors.push(String(e)));13 await page.goto(BASE, { waitUntil: "networkidle" });14 // écarter le bandeau de témoins (il intercepte les clics)15 const cookieBtn = page.locator(".cookie-banner button", { hasText: /accepter|ok/i }).first();16 if (await cookieBtn.isVisible().catch(() => false)) await cookieBtn.click();17 await page.waitForSelector(".toolbar", { timeout: 15000 });18 await page.waitForSelector(".grid .card", { timeout: 15000 });1920 const count0 = await page.textContent(".tb-count");21 console.log(`\n=== ${name} === compteur: ${count0.trim()}`);2223 // 1. ouvrir le panneau de filtres24 await page.click(".tb-filters");25 await page.waitForSelector(".fsheet", { timeout: 5000 });26 const sheetBox = await page.locator(".fsheet").boundingBox();27 const vp = page.viewportSize();28 console.log(`panneau: ${Math.round(sheetBox.width)}x${Math.round(sheetBox.height)} @ y=${Math.round(sheetBox.y)} (viewport ${vp.width}x${vp.height})`);29 await page.screenshot({ path: `${SHOTS}-${mobile ? "mobile" : "desktop"}-sheet.png` });3031 // 2. activer « en solde », une bannière, un format32 await page.click(".fs-sale");33 await page.locator(".fs-sec .opt", { hasText: "Metro" }).first().click();34 await page.locator(".fs-sec .opt", { hasText: "Volume" }).first().click();35 await page.waitForTimeout(900);36 const applyTxt = (await page.textContent(".fs-apply")).trim();37 console.log(`bouton sticky: « ${applyTxt} »`);38 const footVisible = await page.locator(".fs-foot").isVisible();3940 // 3. plus de filtres -> mention Bio41 await page.click(".fs-more");42 await page.locator(".fs-sec .opt", { hasText: "Bio" }).first().click();43 await page.waitForTimeout(900);44 await page.screenshot({ path: `${SHOTS}-${mobile ? "mobile" : "desktop"}-actifs.png` });4546 // 4. fermer via le bouton sticky, vérifier chips actifs + badge47 await page.click(".fs-apply");48 await page.waitForTimeout(400);49 const pills = await page.locator(".pills .pill").allTextContents();50 const badge = await page.textContent(".tb-badge").catch(() => "");51 const count1 = (await page.textContent(".tb-count")).trim();52 console.log(`chips actifs: ${JSON.stringify(pills)}`);53 console.log(`badge filtres: ${badge} · compteur: ${count1}`);5455 // 5. retirer un chip individuellement56 await page.locator(".pills .pill").first().click();57 await page.waitForTimeout(700);58 const pills2 = await page.locator(".pills .pill").allTextContents();59 console.log(`après retrait 1 chip: ${JSON.stringify(pills2)}`);6061 // 6. tri via la barre62 await page.selectOption(".tb-sort select", "price_asc");63 await page.waitForTimeout(700);64 await page.screenshot({ path: `${SHOTS}-${mobile ? "mobile" : "desktop"}-final.png`, fullPage: false });6566 const ok = footVisible && pills.length >= 4 && pills2.length === pills.length - 167 && errors.length === 0 && applyTxt.startsWith("Voir");68 console.log(`erreurs JS: ${errors.length} ${errors.join(" | ")}`);69 console.log(ok ? "VALIDATION OK" : "VALIDATION ÉCHEC");70 await browser.close();71 return ok;72}7374const a = await run("iPhone 14 (mobile)", { ...devices["iPhone 14"] }, true);75const b = await run("Desktop 1440px", { viewport: { width: 1440, height: 900 } }, false);76process.exit(a && b ? 0 : 1);77