Stabilize early campaign QA flow

This commit is contained in:
2026-07-04 03:34:07 +09:00
parent 51ee60dc03
commit d064964c27
2 changed files with 94 additions and 26 deletions

View File

@@ -52,10 +52,11 @@ try {
assert(firstBattleProbe.battleId === 'first-battle-zhuo-commandery', `Expected first battle: ${JSON.stringify(firstBattleProbe)}`);
assert(firstBattleProbe.objectiveText?.startsWith('승리 목표:'), `Expected clear victory objective label: ${JSON.stringify(firstBattleProbe)}`);
assert(firstBattleProbe.objectiveSubText?.includes('패배 조건:'), `Expected clear defeat condition label: ${JSON.stringify(firstBattleProbe)}`);
assert(firstBattleProbe.objectiveSubText?.includes('진군:'), `Expected tactical route in objective tracker: ${JSON.stringify(firstBattleProbe)}`);
assert(
firstBattleProbe.sideTexts.some((text) => text.includes('황건적의 전열이 무너집니다.')) &&
firstBattleProbe.sideTexts.some((text) => text.includes('작전 목표')) &&
!firstBattleProbe.sideTexts.some((text) => text.includes('...')),
`Expected opening objective text without ASCII truncation: ${JSON.stringify(firstBattleProbe.sideTexts)}`
`Expected opening tactical message without ASCII truncation: ${JSON.stringify(firstBattleProbe.sideTexts)}`
);
await page.evaluate(() => window.__HEROS_DEBUG__?.forceBattleOutcome('victory'));
@@ -80,7 +81,7 @@ try {
assert(!resultProbe.resultTexts.some((text) => text.includes('미달')), `Expected result screen to avoid harsh optional-goal wording: ${JSON.stringify(resultProbe.resultTexts)}`);
await page.mouse.click(738, 642);
await waitForCamp(page);
await waitForCampAfterBattleResult(page);
await page.screenshot({ path: `${screenshotDir}/rc-first-camp.png`, fullPage: true });
const firstCampProbe = await page.evaluate(() => {
@@ -211,10 +212,16 @@ async function advanceUntilBattle(page, battleId) {
for (let i = 0; i < 48; i += 1) {
const ready = await page.evaluate((expectedBattleId) => {
const state = window.__HEROS_DEBUG__?.battle();
return state?.scene === 'BattleScene' && state?.battleId === expectedBattleId && state?.phase === 'idle' && state?.mapBackgroundReady === true;
return (
state?.scene === 'BattleScene' &&
state?.battleId === expectedBattleId &&
(state?.phase === 'deployment' || state?.phase === 'idle') &&
state?.mapBackgroundReady === true
);
}, battleId);
if (ready) {
await startDeploymentIfNeeded(page, battleId);
return;
}
@@ -228,8 +235,31 @@ async function advanceUntilBattle(page, battleId) {
async function waitForBattleReady(page, battleId) {
await page.waitForFunction((expectedBattleId) => {
const state = window.__HEROS_DEBUG__?.battle();
return state?.scene === 'BattleScene' && state?.battleId === expectedBattleId && state?.phase === 'idle' && state?.mapBackgroundReady === true;
return (
state?.scene === 'BattleScene' &&
state?.battleId === expectedBattleId &&
(state?.phase === 'deployment' || state?.phase === 'idle') &&
state?.mapBackgroundReady === true
);
}, battleId, { timeout: 90000 });
await startDeploymentIfNeeded(page, battleId);
}
async function startDeploymentIfNeeded(page, battleId) {
const state = await page.evaluate((expectedBattleId) => {
const battle = window.__HEROS_DEBUG__?.battle();
return battle?.battleId === expectedBattleId ? battle : undefined;
}, battleId);
if (state?.phase !== 'deployment') {
return;
}
assert(state.deployedAllyIds?.length >= 3, `Expected deployment to show the selected ally formation: ${JSON.stringify(state)}`);
await page.mouse.click(1085, 637);
await page.waitForFunction((expectedBattleId) => {
const battle = window.__HEROS_DEBUG__?.battle();
return battle?.battleId === expectedBattleId && battle?.phase === 'idle' && battle?.triggeredBattleEvents?.includes('opening');
}, battleId, { timeout: 30000 });
}
async function waitForBattleOutcome(page, outcome) {
@@ -251,6 +281,25 @@ async function waitForCamp(page) {
}, undefined, { timeout: 90000 });
}
async function waitForCampAfterBattleResult(page) {
await page.waitForFunction(() => {
const activeScenes = window.__HEROS_DEBUG__?.activeScenes() ?? [];
return activeScenes.includes('CampScene') || activeScenes.includes('StoryScene');
}, undefined, { timeout: 90000 });
for (let i = 0; i < 48; i += 1) {
const activeScenes = await page.evaluate(() => window.__HEROS_DEBUG__?.activeScenes() ?? []);
if (activeScenes.includes('CampScene')) {
await waitForCamp(page);
return;
}
await page.keyboard.press('Space');
await page.waitForTimeout(240);
}
await waitForCamp(page);
}
async function advanceStoryUntilEnding(page) {
for (let i = 0; i < 48; i += 1) {
const activeScenes = await page.evaluate(() => window.__HEROS_DEBUG__?.activeScenes() ?? []);