Recette design : consigne en texte nu, cases d'arrivée en triangle et anneau, flèches sous les pions, panneau de fin structuré
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
ebaa3b0020
commit
b8c2997ec0
+64
-1
@@ -308,6 +308,7 @@ async function checkView(width, height, when) {
|
||||
scroll: [scroller.scrollWidth, scroller.scrollHeight],
|
||||
topbar: visible(document.querySelector(".topbar")),
|
||||
overscroll: getComputedStyle(document.documentElement).overscrollBehaviorY,
|
||||
promptBackground: getComputedStyle(document.getElementById("prompt")).backgroundColor,
|
||||
pointHits: [...document.querySelectorAll('#board [data-place^="p"]')].map(
|
||||
(el) => el.getBoundingClientRect().width,
|
||||
),
|
||||
@@ -326,6 +327,8 @@ async function checkView(width, height, when) {
|
||||
`${where} : couleurs des flèches ${JSON.stringify(seen.fills)}`);
|
||||
check(seen.primaries.length <= 1, `${where} : plusieurs actions principales : ${seen.primaries}`);
|
||||
check(seen.overscroll === "none", `${where} : overscroll-behavior ${seen.overscroll}`);
|
||||
check(/^(transparent|rgba\(0, 0, 0, 0\))$/.test(seen.promptBackground),
|
||||
`${where} : la consigne a un fond (${seen.promptBackground})`);
|
||||
const landscape = width > height && height <= 640;
|
||||
check(seen.landscape === landscape, `${where} : mise en page ${seen.landscape ? "paysage" : "portrait"}`);
|
||||
if (landscape) {
|
||||
@@ -439,6 +442,21 @@ async function checkTraces() {
|
||||
}
|
||||
check(traces.arrows === move.halfMoves.length && traces.landed > 0 && traces.ghosts > 0 &&
|
||||
traces.replay, `coup de l'ordinateur mal montré : ${JSON.stringify(traces)}`);
|
||||
// Flèches de 2,5 px, sous les pions.
|
||||
const arrows = await page.evaluate(() => {
|
||||
const firstChecker = document.querySelector("#board .checker");
|
||||
return [...document.querySelectorAll("#board .trace-arrow")].map((line) => {
|
||||
const m = line.getScreenCTM();
|
||||
return {
|
||||
px: parseFloat(getComputedStyle(line).strokeWidth) * Math.hypot(m.a, m.b),
|
||||
under: Boolean(line.compareDocumentPosition(firstChecker) &
|
||||
Node.DOCUMENT_POSITION_FOLLOWING),
|
||||
};
|
||||
});
|
||||
});
|
||||
check(arrows.every((a) => Math.abs(a.px - 2.5) < 0.2 && a.under),
|
||||
`flèches du coup de l'ordinateur : ${JSON.stringify(arrows)}`);
|
||||
arrowsChecked++;
|
||||
return traces;
|
||||
}
|
||||
|
||||
@@ -575,7 +593,9 @@ await page.waitForSelector("#board polygon[data-point]");
|
||||
checkers: document.querySelectorAll("#board .checker").length,
|
||||
info: document.getElementById("info").textContent,
|
||||
moves: document.querySelectorAll(".hit.can-move, [data-action=roll]").length,
|
||||
prompt: document.getElementById("prompt").textContent,
|
||||
}));
|
||||
check(loading.prompt === "", `chargement : consigne affichée « ${loading.prompt} »`);
|
||||
check(loading.busy && loading.points === 24 && loading.checkers === 30,
|
||||
`chargement : plateau incomplet ${JSON.stringify(loading)}`);
|
||||
check(loading.info === "Chargement du moteur…", `chargement : « ${loading.info} »`);
|
||||
@@ -619,6 +639,9 @@ let confirms = 0;
|
||||
let undone = 0;
|
||||
let doubles = 0;
|
||||
let responseMs = 0;
|
||||
let confirmButtonSeen = 0;
|
||||
let landingsSeen = 0;
|
||||
let arrowsChecked = 0;
|
||||
const moments = new Set();
|
||||
// Vrai dès que le joueur a touché un pion ou « Annuler » pendant son coup :
|
||||
// le coup de l'ordinateur n'est plus montré.
|
||||
@@ -811,6 +834,20 @@ for (let actions = 0; ; actions++) {
|
||||
const dice = await shownDice();
|
||||
check(dice.used === halfMoves && dice.used > 0,
|
||||
`dés estompés : ${dice.used} pour ${halfMoves} demi-coups`);
|
||||
// « Jouer ce coup » : l'action principale de la barre, à droite.
|
||||
const bar = await page.evaluate(() => {
|
||||
const confirm = document.getElementById("confirm");
|
||||
const cancel = document.getElementById("cancel");
|
||||
return {
|
||||
text: confirm.textContent,
|
||||
primary: !confirm.classList.contains("secondary"),
|
||||
right: confirm.getBoundingClientRect().x > cancel.getBoundingClientRect().x,
|
||||
inBar: confirm.closest("#actions .slot.primary") !== null,
|
||||
};
|
||||
});
|
||||
check(await page.isVisible("#confirm") && bar.text === "Jouer ce coup" && bar.primary &&
|
||||
bar.right && bar.inBar, `coup complet : « Jouer ce coup » mal placé ${JSON.stringify(bar)}`);
|
||||
confirmButtonSeen++;
|
||||
if (undone === 0 && halfMoves >= 2) {
|
||||
// Une fois : « Annuler » défait les demi-coups un par un.
|
||||
if (confirms === 0) {
|
||||
@@ -883,6 +920,17 @@ for (let actions = 0; ; actions++) {
|
||||
responseMs = Math.max(responseMs, ms);
|
||||
check(ms < 100, `toucher d'un pion : pas d'effet visible en moins de 100 ms (${ms})`);
|
||||
if ((await page.locator(".hit.can-land").count()) > 0) {
|
||||
// Cases d'arrivée : le triangle de la flèche voilé, et un anneau
|
||||
// pointillé là où le pion se posera.
|
||||
const marks = await page.evaluate(() => ({
|
||||
lands: document.querySelectorAll(".hit.can-land").length,
|
||||
rings: document.querySelectorAll("#board .landing").length,
|
||||
zones: [...document.querySelectorAll("#board .target-zone")].map((z) => z.tagName),
|
||||
}));
|
||||
check(marks.rings === marks.lands &&
|
||||
marks.zones.filter((t) => t === "polygon").length >= marks.lands - 1,
|
||||
`cases d'arrivée mal marquées : ${JSON.stringify(marks)}`);
|
||||
landingsSeen++;
|
||||
twoTouches++;
|
||||
if (!selectionShot) {
|
||||
selectionShot = true;
|
||||
@@ -963,7 +1011,13 @@ for (let actions = 0; ; actions++) {
|
||||
// --------------------------------------------------------- Fin de partie
|
||||
|
||||
const journal = await savedJournal();
|
||||
const result = await page.textContent("#panel-text");
|
||||
const result = `${await page.textContent("#panel-text")}, ${await page.textContent("#panel-detail")}`;
|
||||
check((await page.textContent("#panel-overline")) === "Fin de partie" &&
|
||||
/^(Vous gagnez|L'ordinateur gagne|Vous passez|L'ordinateur passe)/.test(
|
||||
await page.textContent("#panel-text")) &&
|
||||
/^\d+ points? pour (vous|lui)(, videau à \d+)?\.$/.test(await page.textContent("#panel-detail")),
|
||||
`panneau de fin de partie : ${result}`);
|
||||
check((await page.textContent("#prompt")) === "", "fin de partie : la consigne répète le panneau");
|
||||
log(
|
||||
`partie finie : ${result} (${countMoves(journal, "player")} coups du joueur, ` +
|
||||
`${countMoves(journal, "computer")} de l'ordinateur, ${journal.events.length} événements)`,
|
||||
@@ -975,6 +1029,11 @@ check((await page.textContent("#panel-secondary")) === "Revoir la partie" &&
|
||||
(await page.textContent("#panel-primary")) === "Nouvelle partie",
|
||||
"fin de partie : panneau sans « Revoir la partie » et « Nouvelle partie »");
|
||||
await review("6-fin-de-partie");
|
||||
await page.setViewportSize({ width: 844, height: 320 });
|
||||
await sleep(150);
|
||||
check((await page.locator("#band-text").count()) === 0, "fin de partie : consigne sous le panneau en paysage");
|
||||
await page.setViewportSize(PORTRAIT);
|
||||
await sleep(150);
|
||||
check(countMoves(journal, "player") >= 3 && countMoves(journal, "computer") >= 3, "trop peu de coups");
|
||||
check(reloaded && resumed, "rechargement ou reprise de l'ancienne partie non essayés");
|
||||
check(replays === 2, "le coup de l'ordinateur n'a pas été revu");
|
||||
@@ -986,6 +1045,10 @@ check(singleTouch > 0 && twoTouches > 0,
|
||||
check(undone >= 2, "Annuler n'a pas été essayé sur un coup complet");
|
||||
check(confirms >= 3, "trop peu de coups joués pour essayer dés et bouton");
|
||||
check(moments.size === 2 && selectionShot, `moments de la recette manquants : ${[...moments]}`);
|
||||
check(confirmButtonSeen >= 3 && landingsSeen > 0 && arrowsChecked > 0,
|
||||
"« Jouer ce coup », cases d'arrivée ou flèches non vérifiés");
|
||||
log(`« Jouer ce coup » vu ${confirmButtonSeen} fois à droite de la barre d'actions ; ` +
|
||||
`cases d'arrivée marquées ${landingsSeen} fois ; flèches vérifiées sur ${arrowsChecked} coups`);
|
||||
log(`dés lancés ${rolls} fois (${keyboardRolls} au clavier), dont la moitié en les touchant`);
|
||||
log(`demi-coups : ${singleTouch} d'un seul toucher, ${twoTouches} en deux touchers ; ` +
|
||||
`${confirms} coups joués ; ${doubles} doubles montrés en quatre dés`);
|
||||
|
||||
Reference in New Issue
Block a user