diff --git a/tests/browser/play.mjs b/tests/browser/play.mjs index be3b5dd..30e35be 100644 --- a/tests/browser/play.mjs +++ b/tests/browser/play.mjs @@ -626,17 +626,41 @@ async function checkTraces() { * (les dés en ont une de chaque côté du plateau), chacune un bouton * accessible d'au moins 44 px de côté. Renvoie le locator de la zone index. */ async function touchTarget(action, label, count = 1, index = 0) { - const zones = page.locator(`[data-action="${action}"]`); - check((await zones.count()) === count, - `zone ${action} : ${await zones.count()} sur le plateau, ${count} attendues`); - for (const zone of await zones.all()) { - check((await zone.getAttribute("role")) === (action === "menu" ? "link" : "button") && - (await zone.getAttribute("aria-label")) === label, `zone ${action} sans rôle accessible`); - const box = await zone.boundingBox(); - check(box.width >= 44 && box.height >= 44, - `zone ${action} trop petite : ${Math.round(box.width)} x ${Math.round(box.height)} px`); + // Les zones sont relevées d'un coup dans la page, où le plateau ne peut + // pas se redessiner entre deux lectures : mesurées une à une depuis + // Playwright (boundingBox), une zone remplacée entre-temps par un + // nouveau dessin du plateau n'avait plus de boîte (null, vu sous + // Firefox). On attend l'état observable : le nombre de zones attendu, + // toutes dessinées (5 s au plus). + const read = () => + page.evaluate( + (name) => + [...document.querySelectorAll(`[data-action="${name}"]`)].map((zone) => { + const box = zone.getBoundingClientRect(); + return { + role: zone.getAttribute("role"), + label: zone.getAttribute("aria-label"), + width: box.width, + height: box.height, + }; + }), + action, + ); + let zones = await read(); + const start = Date.now(); + while ((zones.length !== count || zones.some((z) => z.width === 0 && z.height === 0)) && + Date.now() - start < 5000) { + await sleep(100); + zones = await read(); } - return zones.nth(index); + check(zones.length === count, `zone ${action} : ${zones.length} sur le plateau, ${count} attendues`); + for (const zone of zones) { + check(zone.role === (action === "menu" ? "link" : "button") && zone.label === label, + `zone ${action} sans rôle accessible`); + check(zone.width >= 44 && zone.height >= 44, + `zone ${action} trop petite : ${Math.round(zone.width)} x ${Math.round(zone.height)} px`); + } + return page.locator(`[data-action="${action}"]`).nth(index); } /** Le nombre de dés montrés, et de dés estompés (déjà joués). */