diff --git a/scripts/verify-battle-result-persistence-retry-browser.mjs b/scripts/verify-battle-result-persistence-retry-browser.mjs index be70078..58ad1e8 100644 --- a/scripts/verify-battle-result-persistence-retry-browser.mjs +++ b/scripts/verify-battle-result-persistence-retry-browser.mjs @@ -44,6 +44,10 @@ assert( ); const battleId = 'first-battle-zhuo-commandery'; +const firstPursuitAutoEntryTutorialIds = [ + 'first-pursuit-camp-auto-enter-scout-tent-scheduled', + 'first-pursuit-camp-auto-enter-scout-tent' +]; const canonicalCampaignKey = 'heros-web:campaign-state:slot-1'; const currentCampaignKey = 'heros-web:campaign-state'; @@ -331,6 +335,46 @@ try { await completeActiveStoryToCamp(page); await waitForCamp(page); + const autoEntryFixture = await page.evaluate( + ({ + currentKey, + canonicalKey, + tutorialIds + }) => { + window.__HEROS_GAME__?.loop?.sleep?.(); + const canonicalRaw = + window.localStorage.getItem(canonicalKey); + if (!canonicalRaw) { + throw new Error( + 'Canonical campaign save is unavailable.' + ); + } + const campaign = JSON.parse(canonicalRaw); + campaign.completedTutorialIds = [ + ...new Set([ + ...(campaign.completedTutorialIds ?? []), + ...tutorialIds + ]) + ]; + campaign.updatedAt = new Date().toISOString(); + const serialized = JSON.stringify(campaign); + window.localStorage.setItem(currentKey, serialized); + window.localStorage.setItem(canonicalKey, serialized); + return tutorialIds.every((tutorialId) => + campaign.completedTutorialIds.includes(tutorialId) + ); + }, + { + currentKey: currentCampaignKey, + canonicalKey: canonicalCampaignKey, + tutorialIds: firstPursuitAutoEntryTutorialIds + } + ); + assert.equal( + autoEntryFixture, + true, + `${renderer}: the sortie-improvement fixture did not complete the separate automatic scout entry` + ); await reloadToTitle(page, renderer); await triggerTitleContinue(page); const restoredVictoryPreparation = diff --git a/scripts/verify-campaign-objective-journal-browser.mjs b/scripts/verify-campaign-objective-journal-browser.mjs index 1ed1ebc..a00e0bc 100644 --- a/scripts/verify-campaign-objective-journal-browser.mjs +++ b/scripts/verify-campaign-objective-journal-browser.mjs @@ -146,6 +146,7 @@ try { await page.evaluate(async () => { await window.__HEROS_DEBUG__.goToCamp(); }); + await suppressFirstPursuitAutoEntryForJournalQa(page); await waitForCampJournalReady(page); const runtime = await readRuntimeProbe(page, 'CampScene'); @@ -289,6 +290,85 @@ async function waitForDebugApi(page) { ); } +async function suppressFirstPursuitAutoEntryForJournalQa(page) { + let result; + try { + const handle = await page.waitForFunction( + () => { + const debug = window.__HEROS_DEBUG__; + const camp = debug?.camp?.(); + if ( + !debug?.activeScenes?.().includes('CampScene') || + camp?.firstPursuitAutoEntry?.cueVisible !== true + ) { + return false; + } + + const loop = window.__HEROS_GAME__?.loop; + const scene = debug.scene('CampScene'); + if ( + !loop || + typeof loop.sleep !== 'function' || + typeof loop.wake !== 'function' || + typeof scene?.debugSuppressFirstPursuitAutoEntry !== + 'function' + ) { + return { + suppressed: false, + reason: 'Required debug suppression controls are unavailable.' + }; + } + + loop.sleep(); + try { + return { + suppressed: + scene.debugSuppressFirstPursuitAutoEntry(), + reason: null + }; + } finally { + loop.wake(); + } + }, + undefined, + { timeout: 90000 } + ); + result = await handle.jsonValue(); + } catch (error) { + const diagnostic = await page.evaluate(() => ({ + activeScenes: + window.__HEROS_DEBUG__?.activeScenes?.() ?? [], + camp: window.__HEROS_DEBUG__?.camp?.() ?? null + })); + throw new Error( + `First-pursuit automatic entry could not be held for ` + + `campaign journal QA: ${JSON.stringify(diagnostic)}`, + { cause: error } + ); + } + + assert.equal( + result?.suppressed, + true, + `${renderer}: failed to hold the first-victory camp for ` + + `campaign journal QA: ${JSON.stringify(result)}` + ); + await page.waitForFunction( + () => { + const debug = window.__HEROS_DEBUG__; + const autoEntry = + debug?.camp?.()?.firstPursuitAutoEntry; + return ( + debug?.activeScenes?.().includes('CampScene') && + autoEntry?.cueVisible === false && + autoEntry?.suppressedForDebug === true + ); + }, + undefined, + { timeout: 30000 } + ); +} + async function seedFirstVictoryCamp(page) { return page.evaluate(async (battleId) => { const campaignModule = await import(