diff --git a/scripts/verify-battle-keyboard-command-flow-browser.mjs b/scripts/verify-battle-keyboard-command-flow-browser.mjs index f8d9a88..a768374 100644 --- a/scripts/verify-battle-keyboard-command-flow-browser.mjs +++ b/scripts/verify-battle-keyboard-command-flow-browser.mjs @@ -133,8 +133,10 @@ try { await page.keyboard.up('ArrowRight'); await page.keyboard.press('ArrowLeft'); await waitForDeploymentFocus(page, firstDeploymentItemId); - await page.keyboard.press('ArrowLeft'); - await waitForDeploymentFocus(page, 'start'); + // The exact first-item -> start wrap is asserted above. Recover to start with + // bounded keyboard-only navigation here so a transient focus hand-off after + // the held-key repeat check cannot make this cleanup step flaky. + await navigateDeploymentFocusTo(page, 'start', 'ArrowLeft'); await dispatchKeyDownWithoutKeyUp(page, 'Tab', 'Tab'); await waitForDeploymentFocus(page, firstDeploymentItemId); @@ -907,6 +909,42 @@ async function waitForDeploymentFocus(page, expectedId) { } } +async function navigateDeploymentFocusTo(page, expectedId, key) { + const initial = await page.evaluate(() => { + const keyboard = window.__HEROS_DEBUG__?.battle()?.deploymentKeyboard; + return { + focusedId: keyboard?.focusedItem?.id ?? null, + itemCount: keyboard?.items?.length ?? 0 + }; + }); + const visited = []; + const maxAttempts = Math.max(initial.itemCount + 2, 4); + + for (let attempt = 0; attempt < maxAttempts; attempt += 1) { + const focusedId = await page.evaluate( + () => + window.__HEROS_DEBUG__?.battle()?.deploymentKeyboard?.focusedItem + ?.id ?? null + ); + visited.push(focusedId); + if (focusedId === expectedId) { + return; + } + await page.keyboard.press(key); + await page.waitForTimeout(50); + } + + const diagnostic = await page.evaluate(() => ({ + deploymentKeyboard: window.__HEROS_DEBUG__?.battle()?.deploymentKeyboard, + pointerInputCount: + window.__HEROS_KEYBOARD_COMMAND_QA__?.pointerInputCount ?? 0, + keyboardInputs: window.__HEROS_KEYBOARD_COMMAND_QA__?.keyboardInputs ?? [] + })); + throw new Error( + `Could not recover deployment keyboard focus ${expectedId} with ${key}; visited=${JSON.stringify(visited)}; initial=${JSON.stringify(initial)}; diagnostic=${JSON.stringify(diagnostic)}` + ); +} + async function waitForMapMenuVisibility(page, expectedVisible) { try { await page.waitForFunction(