Reject unknown campaign battle reports
This commit is contained in:
@@ -494,6 +494,37 @@ try {
|
|||||||
`Expected malformed report fields to be normalized without discarding the report: ${JSON.stringify(malformedReport)}`
|
`Expected malformed report fields to be normalized without discarding the report: ${JSON.stringify(malformedReport)}`
|
||||||
);
|
);
|
||||||
|
|
||||||
|
storage.clear();
|
||||||
|
storage.set(
|
||||||
|
campaignStorageKey,
|
||||||
|
JSON.stringify({
|
||||||
|
version: 1,
|
||||||
|
updatedAt: '2026-07-04T00:30:00.000Z',
|
||||||
|
step: 'fourth-camp',
|
||||||
|
firstBattleReport: {
|
||||||
|
battleId: 'unknown-battle-id',
|
||||||
|
battleTitle: 'Unknown Battle',
|
||||||
|
outcome: 'victory',
|
||||||
|
turnNumber: 4,
|
||||||
|
rewardGold: 120,
|
||||||
|
defeatedEnemies: 3,
|
||||||
|
totalEnemies: 5,
|
||||||
|
objectives: [],
|
||||||
|
units: [],
|
||||||
|
bonds: [],
|
||||||
|
itemRewards: [],
|
||||||
|
completedCampDialogues: [],
|
||||||
|
completedCampVisits: [],
|
||||||
|
createdAt: '2026-07-04T00:30:00.000Z'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
const unknownReport = loadCampaignState();
|
||||||
|
assert(
|
||||||
|
unknownReport.step === 'fourth-camp' && unknownReport.firstBattleReport === undefined,
|
||||||
|
`Expected first battle report with unknown battle id to be discarded safely: ${JSON.stringify(unknownReport)}`
|
||||||
|
);
|
||||||
|
|
||||||
storage.clear();
|
storage.clear();
|
||||||
storage.set(
|
storage.set(
|
||||||
campaignStorageKey,
|
campaignStorageKey,
|
||||||
@@ -552,6 +583,19 @@ try {
|
|||||||
],
|
],
|
||||||
completedAt: '2026-07-04T01:00:00.000Z'
|
completedAt: '2026-07-04T01:00:00.000Z'
|
||||||
},
|
},
|
||||||
|
'unknown-battle-key': {
|
||||||
|
battleId: 'unknown-battle-id',
|
||||||
|
battleTitle: 'Unknown Battle',
|
||||||
|
outcome: 'victory',
|
||||||
|
rewardGold: 999,
|
||||||
|
itemRewards: [],
|
||||||
|
campaignRewards: { supplies: [], equipment: [], reputation: [], recruits: [], unlocks: [] },
|
||||||
|
objectives: [],
|
||||||
|
units: [],
|
||||||
|
bonds: [],
|
||||||
|
reserveTraining: [],
|
||||||
|
completedAt: '2026-07-04T02:00:00.000Z'
|
||||||
|
},
|
||||||
corrupted: 'not-a-settlement'
|
corrupted: 'not-a-settlement'
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -950,9 +950,10 @@ function normalizeCampaignBattleSettlement(value: unknown): CampaignBattleSettle
|
|||||||
}
|
}
|
||||||
|
|
||||||
const settlement = value as Partial<CampaignBattleSettlement>;
|
const settlement = value as Partial<CampaignBattleSettlement>;
|
||||||
|
const battleId = typeof settlement.battleId === 'string' ? settlement.battleId : '';
|
||||||
if (
|
if (
|
||||||
typeof settlement.battleId !== 'string' ||
|
battleId.length === 0 ||
|
||||||
settlement.battleId.length === 0 ||
|
!(battleId in battleScenarios) ||
|
||||||
typeof settlement.battleTitle !== 'string' ||
|
typeof settlement.battleTitle !== 'string' ||
|
||||||
settlement.battleTitle.length === 0 ||
|
settlement.battleTitle.length === 0 ||
|
||||||
(settlement.outcome !== 'victory' && settlement.outcome !== 'defeat') ||
|
(settlement.outcome !== 'victory' && settlement.outcome !== 'defeat') ||
|
||||||
@@ -963,7 +964,7 @@ function normalizeCampaignBattleSettlement(value: unknown): CampaignBattleSettle
|
|||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
battleId: settlement.battleId,
|
battleId,
|
||||||
battleTitle: settlement.battleTitle,
|
battleTitle: settlement.battleTitle,
|
||||||
outcome: settlement.outcome,
|
outcome: settlement.outcome,
|
||||||
rewardGold: normalizeNonNegativeInteger(settlement.rewardGold),
|
rewardGold: normalizeNonNegativeInteger(settlement.rewardGold),
|
||||||
@@ -1112,9 +1113,10 @@ function normalizeFirstBattleReport(report: unknown): FirstBattleReport | undefi
|
|||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const battleId = typeof report.battleId === 'string' ? report.battleId : '';
|
||||||
if (
|
if (
|
||||||
typeof report.battleId !== 'string' ||
|
battleId.length === 0 ||
|
||||||
report.battleId.length === 0 ||
|
!(battleId in battleScenarios) ||
|
||||||
(report.outcome !== 'victory' && report.outcome !== 'defeat')
|
(report.outcome !== 'victory' && report.outcome !== 'defeat')
|
||||||
) {
|
) {
|
||||||
return undefined;
|
return undefined;
|
||||||
@@ -1123,13 +1125,13 @@ function normalizeFirstBattleReport(report: unknown): FirstBattleReport | undefi
|
|||||||
const battleTitle =
|
const battleTitle =
|
||||||
typeof report.battleTitle === 'string' && report.battleTitle.length > 0
|
typeof report.battleTitle === 'string' && report.battleTitle.length > 0
|
||||||
? report.battleTitle
|
? report.battleTitle
|
||||||
: battleScenarios[report.battleId as BattleScenarioId]?.title;
|
: battleScenarios[battleId as BattleScenarioId]?.title;
|
||||||
if (!battleTitle) {
|
if (!battleTitle) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
battleId: report.battleId,
|
battleId,
|
||||||
battleTitle,
|
battleTitle,
|
||||||
outcome: report.outcome,
|
outcome: report.outcome,
|
||||||
turnNumber: normalizeNonNegativeInteger(report.turnNumber),
|
turnNumber: normalizeNonNegativeInteger(report.turnNumber),
|
||||||
|
|||||||
Reference in New Issue
Block a user