test(combat): cover CombatService LOST persistence

CombatService only had engine-level coverage of the LOST transition.
Add service-level tests that force a loss (character.baseHp: 1) and
assert the persisted status, completedAt, further-action rejection,
and getCombat refresh behavior for a LOST combat.
This commit is contained in:
Bastian Wagner
2026-08-19 21:42:01 +02:00
parent aa8c374db0
commit 18f30a1ba1

View File

@@ -497,6 +497,27 @@ describe('CombatService', () => {
); );
}); });
it('ends the combat as LOST, stops persisting new rounds, and rejects further actions', async () => {
const state = createState({
characters: [character({ baseHp: 1 })],
});
const { dataSource, service, combatId } = await startedCombat(state);
const result = await service.performAction(
CHARACTER_ID,
combatId,
CombatAction.ATTACK,
);
expect(result.status).toBe('LOST');
expect(dataSource.state.combats[0].status).toBe(CombatStatus.LOST);
expect(dataSource.state.combats[0].completedAt).not.toBeNull();
await expectCombatDomainError(
service.performAction(CHARACTER_ID, combatId, CombatAction.ATTACK),
'COMBAT_ALREADY_FINISHED',
);
});
it('rejects actions on an unknown combat id', async () => { it('rejects actions on an unknown combat id', async () => {
const { service } = createService(); const { service } = createService();
@@ -565,5 +586,29 @@ describe('CombatService', () => {
'COMBAT_NOT_FOUND', 'COMBAT_NOT_FOUND',
); );
}); });
it('keeps returning LOST after the combat has ended', async () => {
const state = createState({
characters: [character({ baseHp: 1 })],
});
const context = createService({ state });
const started = await context.service.startCombat(
CHARACTER_ID,
ENCOUNTER_ID,
);
await context.service.performAction(
CHARACTER_ID,
started.id,
CombatAction.ATTACK,
);
const reloaded = await context.service.getCombat(
CHARACTER_ID,
started.id,
);
expect(reloaded.status).toBe('LOST');
expect(reloaded.player.currentHp).toBe(0);
});
}); });
}); });