From c3a80cd3439d5234d5156fbc2bd8101596e19029 Mon Sep 17 00:00:00 2001 From: Wickedness Date: Wed, 29 Jul 2026 04:39:18 +0900 Subject: [PATCH] test: target semantic turn prompt action --- scripts/verify-interaction-ux.mjs | 72 +++++++++++++++++++++++-------- 1 file changed, 54 insertions(+), 18 deletions(-) diff --git a/scripts/verify-interaction-ux.mjs b/scripts/verify-interaction-ux.mjs index d11f87a..5e7039e 100644 --- a/scripts/verify-interaction-ux.mjs +++ b/scripts/verify-interaction-ux.mjs @@ -508,8 +508,16 @@ async function verifyBattlePointerFlow(page) { ); await page.waitForTimeout(120); - await clickTurnPromptSecondary(page); - await page.waitForFunction(() => window.__HEROS_DEBUG__?.battle()?.turnPromptVisible === false); + const automaticTurnPromptSecondaryClick = await clickTurnPromptSecondary(page); + try { + await page.waitForFunction(() => window.__HEROS_DEBUG__?.battle()?.turnPromptVisible === false); + } catch (error) { + const diagnostic = await turnPromptPointerDiagnostic(page, automaticTurnPromptSecondaryClick); + throw new Error( + `The battlefield-review pointer click did not close the turn-end prompt: ${JSON.stringify(diagnostic)}`, + { cause: error } + ); + } const persistentTurnEndBounds = await page.evaluate(() => { const scene = window.__HEROS_GAME__?.scene.getScene('BattleScene'); const text = (scene?.sidePanelObjects ?? []).find((object) => ( @@ -1903,23 +1911,51 @@ async function startDeploymentIfNeeded(page, battleId) { } async function clickTurnPromptSecondary(page) { - const bounds = await page.evaluate(() => { - const scene = window.__HEROS_GAME__?.scene.getScene('BattleScene'); - const buttons = (scene?.turnPromptObjects ?? []) - .filter((object) => ( - object.type === 'Rectangle' && - object.active && - object.input?.enabled && - object.displayWidth < 500 && - object.displayHeight < 100 - )) - .map((object) => object.getBounds()) - .sort((left, right) => right.centerX - left.centerX); - const button = buttons[0]; - return button ? { x: button.x, y: button.y, width: button.width, height: button.height } : null; + const button = await page.evaluate(() => { + const prompt = window.__HEROS_DEBUG__?.battle()?.turnPrompt; + return prompt?.buttons?.find((candidate) => candidate.id === 'secondary') ?? null; }); - assert(bounds, 'Expected the battlefield-review button in the turn-end prompt.'); - await clickSceneBounds(page, 'BattleScene', bounds); + assert( + button?.bounds && button.meaning === 'review-battlefield', + `Expected the battlefield-review button in the turn-end prompt: ${JSON.stringify(button)}` + ); + const point = await clickSceneBounds(page, 'BattleScene', button.bounds); + return { button, point }; +} + +async function turnPromptPointerDiagnostic(page, click) { + return page.evaluate((requestedClick) => { + const scene = window.__HEROS_GAME__?.scene.getScene('BattleScene'); + const canvas = document.querySelector('canvas'); + const canvasBounds = canvas?.getBoundingClientRect(); + const pointer = scene?.input?.activePointer; + return { + click: requestedClick, + turnPrompt: window.__HEROS_DEBUG__?.battle()?.turnPrompt ?? null, + canvasBounds: canvasBounds + ? { + x: canvasBounds.x, + y: canvasBounds.y, + width: canvasBounds.width, + height: canvasBounds.height + } + : null, + sceneSize: scene + ? { width: scene.scale.width, height: scene.scale.height } + : null, + activePointer: pointer + ? { + x: pointer.x, + y: pointer.y, + downX: pointer.downX, + downY: pointer.downY, + upX: pointer.upX, + upY: pointer.upY, + isDown: pointer.isDown + } + : null + }; + }, click); } async function findRightmostEmptyBattleTile(page) {