feat: stage sortie preparation across campaign
This commit is contained in:
@@ -170,7 +170,15 @@ try {
|
||||
await waitForSortiePrep(page);
|
||||
await page.screenshot({ path: `${screenshotDir}/rc-first-camp-sortie-prep.png`, fullPage: true });
|
||||
await assertCanvasPainted(page, 'first camp sortie prep');
|
||||
await advanceFirstSortiePrepStep(page, 'formation');
|
||||
const firstSortieBriefingState = await page.evaluate(() => window.__HEROS_DEBUG__?.camp());
|
||||
assert(
|
||||
firstSortieBriefingState?.stagedSortiePrep === true &&
|
||||
firstSortieBriefingState?.sortiePrepStep === 'briefing' &&
|
||||
firstSortieBriefingState?.sortiePrimaryAction?.kind === 'next' &&
|
||||
firstSortieBriefingState?.sortiePrimaryAction?.nextStep === 'formation',
|
||||
`Expected the first sortie to open at the staged battlefield briefing: ${JSON.stringify(firstSortieBriefingState)}`
|
||||
);
|
||||
await advanceSortiePrepStep(page, 'formation');
|
||||
await page.screenshot({ path: `${screenshotDir}/rc-first-camp-sortie-formation.png`, fullPage: true });
|
||||
await assertCanvasPainted(page, 'first camp sortie formation');
|
||||
const firstSortieSynergy = await page.evaluate(() => window.__HEROS_DEBUG__?.camp()?.sortieSynergyPreview);
|
||||
@@ -182,7 +190,7 @@ try {
|
||||
firstSortieSynergy?.firstPursuitTrinityConfigured === true,
|
||||
`Expected first sortie to preview three bonds, the strongest effect, and trinity: ${JSON.stringify(firstSortieSynergy)}`
|
||||
);
|
||||
await advanceFirstSortiePrepStep(page, 'loadout');
|
||||
await advanceSortiePrepStep(page, 'loadout');
|
||||
await page.mouse.click(1116, 656);
|
||||
await advanceUntilBattle(page, 'second-battle-yellow-turban-pursuit');
|
||||
await page.screenshot({ path: `${screenshotDir}/rc-second-battle-from-first-camp.png`, fullPage: true });
|
||||
@@ -360,6 +368,42 @@ try {
|
||||
await page.screenshot({ path: `${screenshotDir}/rc-mid-camp-sortie-prep.png`, fullPage: true });
|
||||
await assertCanvasPainted(page, 'mid camp sortie prep');
|
||||
|
||||
const midBriefingState = await page.evaluate(() => window.__HEROS_DEBUG__?.camp());
|
||||
assert(
|
||||
midBriefingState?.stagedSortiePrep === true &&
|
||||
midBriefingState?.firstSortiePrep === false &&
|
||||
midBriefingState?.sortiePrepStep === 'briefing' &&
|
||||
midBriefingState?.sortiePrimaryAction?.kind === 'next' &&
|
||||
midBriefingState?.sortiePrimaryAction?.nextStep === 'formation',
|
||||
`Expected a mid-campaign battle sortie to open at the staged briefing: ${JSON.stringify(midBriefingState)}`
|
||||
);
|
||||
assert(
|
||||
midBriefingState?.sortiePortraitRosterView?.enabled === true &&
|
||||
midBriefingState?.sortiePortraitRosterView?.total > 8 &&
|
||||
midBriefingState?.sortiePortraitRosterView?.visibleCount === 8 &&
|
||||
midBriefingState?.sortiePortraitRosterView?.start === 1 &&
|
||||
midBriefingState?.sortiePortraitRosterView?.end === 8,
|
||||
`Expected the mid-campaign staged formation to expose an eight-card portrait roster window: ${JSON.stringify(midBriefingState?.sortiePortraitRosterView)}`
|
||||
);
|
||||
|
||||
await advanceSortiePrepStep(page, 'formation');
|
||||
await page.screenshot({ path: `${screenshotDir}/rc-mid-camp-sortie-formation.png`, fullPage: true });
|
||||
await assertCanvasPainted(page, 'mid camp sortie formation');
|
||||
|
||||
const midFormationFirstPage = await page.evaluate(() => window.__HEROS_DEBUG__?.camp()?.sortiePortraitRosterView);
|
||||
await page.mouse.click(658, 196);
|
||||
await page.waitForFunction((previousScroll) => {
|
||||
const view = window.__HEROS_DEBUG__?.camp()?.sortiePortraitRosterView;
|
||||
return view?.scroll > previousScroll;
|
||||
}, midFormationFirstPage?.scroll ?? 0, { timeout: 30000 });
|
||||
const midFormationSecondPage = await page.evaluate(() => window.__HEROS_DEBUG__?.camp()?.sortiePortraitRosterView);
|
||||
assert(
|
||||
midFormationSecondPage?.start > 1 && midFormationSecondPage?.end > 8,
|
||||
`Expected the portrait roster next-page control to reveal later officers: ${JSON.stringify(midFormationSecondPage)}`
|
||||
);
|
||||
await page.mouse.click(610, 196);
|
||||
await page.waitForFunction(() => window.__HEROS_DEBUG__?.camp()?.sortiePortraitRosterView?.scroll === 0, undefined, { timeout: 30000 });
|
||||
|
||||
const fullRosterCandidateProbe = await page.evaluate(() => {
|
||||
const scene = window.__HEROS_GAME__?.scene.getScene('CampScene');
|
||||
const state = window.__HEROS_DEBUG__?.camp();
|
||||
@@ -374,6 +418,7 @@ try {
|
||||
await page.waitForFunction((probe) => {
|
||||
const state = window.__HEROS_DEBUG__?.camp();
|
||||
return state?.sortieFocusedUnitId === probe.candidateId &&
|
||||
state?.sortiePrepStep === 'formation' &&
|
||||
state?.sortieFocusedSynergyPreview?.mode === 'waiting' &&
|
||||
state?.selectedSortieUnitIds?.length === probe.selectedBefore.length &&
|
||||
!state.selectedSortieUnitIds.includes(probe.candidateId);
|
||||
@@ -393,6 +438,7 @@ try {
|
||||
await page.waitForFunction((probe) => {
|
||||
const state = window.__HEROS_DEBUG__?.camp();
|
||||
return state?.sortieVisible === true &&
|
||||
state?.sortiePrepStep === 'formation' &&
|
||||
state?.selectedSortieUnitIds?.length === probe.selectedBefore.length - 1 &&
|
||||
!state.selectedSortieUnitIds.includes(probe.removedUnitId) &&
|
||||
state?.sortieFocusedSynergyPreview?.mode === 'add';
|
||||
@@ -429,8 +475,35 @@ try {
|
||||
|
||||
const midCampSelectedSortieUnitIds = reserveDoctrineSetup.state?.selectedSortieUnitIds ?? [];
|
||||
const midCampDeploymentPreview = reserveDoctrineSetup.state?.sortieDeploymentPreview ?? [];
|
||||
const midCampFormationAssignments = reserveDoctrineSetup.state?.sortieFormationAssignments ?? {};
|
||||
const midCampItemAssignments = reserveDoctrineSetup.state?.sortieItemAssignments ?? {};
|
||||
await page.mouse.click(1160, 38);
|
||||
await waitForSortiePrep(page);
|
||||
const restoredMidBriefingState = await page.evaluate(() => window.__HEROS_DEBUG__?.camp());
|
||||
assert(
|
||||
restoredMidBriefingState?.stagedSortiePrep === true && restoredMidBriefingState?.sortiePrepStep === 'briefing',
|
||||
`Expected reopening the mid-campaign sortie to restart at briefing: ${JSON.stringify(restoredMidBriefingState)}`
|
||||
);
|
||||
const restoredMidFormationState = await advanceSortiePrepStep(page, 'formation');
|
||||
assert(
|
||||
restoredMidFormationState?.sortiePlan?.formationCoverageComplete === false &&
|
||||
JSON.stringify(restoredMidFormationState?.sortieFormationAssignments) === JSON.stringify(midCampFormationAssignments) &&
|
||||
JSON.stringify(restoredMidFormationState?.sortieItemAssignments) === JSON.stringify(midCampItemAssignments),
|
||||
`Expected the staged formation screen to preserve role and supply assignments: ${JSON.stringify(restoredMidFormationState)}`
|
||||
);
|
||||
const restoredMidLoadoutState = await advanceSortiePrepStep(page, 'loadout');
|
||||
assertSameMembers(
|
||||
restoredMidLoadoutState?.selectedSortieUnitIds,
|
||||
midCampSelectedSortieUnitIds,
|
||||
`Expected briefing, formation, and loadout steps to preserve the selected mid-campaign roster: ${JSON.stringify(restoredMidLoadoutState?.selectedSortieUnitIds)}`
|
||||
);
|
||||
assert(
|
||||
JSON.stringify(restoredMidLoadoutState?.sortieFormationAssignments) === JSON.stringify(midCampFormationAssignments) &&
|
||||
JSON.stringify(restoredMidLoadoutState?.sortieItemAssignments) === JSON.stringify(midCampItemAssignments),
|
||||
`Expected loadout navigation to preserve role and supply assignments: ${JSON.stringify(restoredMidLoadoutState)}`
|
||||
);
|
||||
await page.screenshot({ path: `${screenshotDir}/rc-mid-camp-sortie-loadout.png`, fullPage: true });
|
||||
await assertCanvasPainted(page, 'mid camp sortie loadout');
|
||||
await page.mouse.click(1116, 656);
|
||||
await advanceUntilBattle(page, midCampNextBattleId);
|
||||
await page.screenshot({ path: `${screenshotDir}/rc-mid-camp-next-battle.png`, fullPage: true });
|
||||
@@ -489,6 +562,7 @@ try {
|
||||
const finalCampState = await page.evaluate(() => window.__HEROS_DEBUG__?.camp());
|
||||
assert(finalCampState?.campaign?.step === 'sixty-sixth-camp', `Expected final camp save to continue: ${JSON.stringify(finalCampState)}`);
|
||||
assert(finalCampState.sortieHasBattle === false, `Expected final camp to expose no playable sortie target: ${JSON.stringify(finalCampState)}`);
|
||||
assert(finalCampState.stagedSortiePrep === false, `Expected the non-battle final camp to avoid the three-stage sortie flow: ${JSON.stringify(finalCampState)}`);
|
||||
assert(finalCampState.nextSortieBattleId === null, `Expected final camp to route to ending instead of a battle: ${JSON.stringify(finalCampState)}`);
|
||||
assert(
|
||||
Array.isArray(finalCampState.sortieDeploymentPreview) && finalCampState.sortieDeploymentPreview.length === 0,
|
||||
@@ -675,12 +749,24 @@ async function waitForSortiePrep(page) {
|
||||
}, undefined, { timeout: 30000 });
|
||||
}
|
||||
|
||||
async function advanceFirstSortiePrepStep(page, expectedStep) {
|
||||
async function advanceSortiePrepStep(page, expectedStep) {
|
||||
await page.mouse.click(1116, 656);
|
||||
await page.waitForFunction((step) => {
|
||||
const camp = window.__HEROS_DEBUG__?.camp?.();
|
||||
return camp?.sortieVisible === true && camp?.sortiePrepStep === step;
|
||||
}, expectedStep, { timeout: 30000 });
|
||||
await page.waitForTimeout(1000);
|
||||
const state = await page.evaluate(() => window.__HEROS_DEBUG__?.camp?.());
|
||||
const expectedNextStep = expectedStep === 'formation' ? 'loadout' : null;
|
||||
assert(
|
||||
state?.stagedSortiePrep === true &&
|
||||
state?.sortiePrepSteps?.filter((step) => step.active).length === 1 &&
|
||||
state?.sortiePrepSteps?.some((step) => step.id === expectedStep && step.active) &&
|
||||
state?.sortiePrimaryAction?.kind === (expectedNextStep ? 'next' : 'launch') &&
|
||||
state?.sortiePrimaryAction?.nextStep === expectedNextStep,
|
||||
`Expected staged sortie navigation to reach ${expectedStep}: ${JSON.stringify(state)}`
|
||||
);
|
||||
return state;
|
||||
}
|
||||
|
||||
async function waitForCampAfterBattleResult(page) {
|
||||
|
||||
Reference in New Issue
Block a user