import { describe, expect, it } from "vitest"; import { clearEncounter } from "../clear-encounter.js"; import type { DomainError, Encounter } from "../types.js"; import { combatantId, createEncounter, isDomainError } from "../types.js"; function makeEncounter( count: number, overrides?: Partial, ): Encounter { const combatants = Array.from({ length: count }, (_, i) => ({ id: combatantId(`c-${i + 1}`), name: `Combatant ${i + 1}`, })); const result = createEncounter(combatants); if (isDomainError(result)) { throw new Error("Failed to create encounter in test helper"); } return { ...result, ...overrides }; } describe("clearEncounter", () => { it("clears encounter with multiple combatants at round 3 — returns empty encounter with roundNumber 1 and activeIndex 0", () => { const encounter = makeEncounter(4, { roundNumber: 3, activeIndex: 2 }); const result = clearEncounter(encounter); expect(isDomainError(result)).toBe(false); const success = result as Exclude; expect(success.encounter.combatants).toEqual([]); expect(success.encounter.roundNumber).toBe(1); expect(success.encounter.activeIndex).toBe(0); }); it("clears encounter with a single combatant", () => { const encounter = makeEncounter(1); const result = clearEncounter(encounter); expect(isDomainError(result)).toBe(false); const success = result as Exclude; expect(success.encounter.combatants).toEqual([]); expect(success.encounter.activeIndex).toBe(0); expect(success.encounter.roundNumber).toBe(1); }); it("clears encounter with combatants that have HP/AC/conditions/concentration", () => { const encounter: Encounter = { combatants: [ { id: combatantId("c-1"), name: "Fighter", maxHp: 50, currentHp: 30, ac: 18, conditions: ["blinded", "poisoned"], isConcentrating: true, }, { id: combatantId("c-2"), name: "Wizard", maxHp: 25, currentHp: 0, ac: 12, conditions: ["unconscious"], }, ], activeIndex: 0, roundNumber: 5, }; const result = clearEncounter(encounter); expect(isDomainError(result)).toBe(false); const success = result as Exclude; expect(success.encounter.combatants).toEqual([]); }); it("returns DomainError with code 'encounter-already-empty' when encounter has no combatants", () => { const encounter: Encounter = { combatants: [], activeIndex: 0, roundNumber: 1, }; const result = clearEncounter(encounter); expect(isDomainError(result)).toBe(true); const error = result as DomainError; expect(error.code).toBe("encounter-already-empty"); }); it("emits EncounterCleared event with correct combatantCount", () => { const encounter = makeEncounter(3); const result = clearEncounter(encounter); expect(isDomainError(result)).toBe(false); const success = result as Exclude; expect(success.events).toEqual([ { type: "EncounterCleared", combatantCount: 3 }, ]); }); it("is deterministic — same input always produces same output", () => { const encounter = makeEncounter(2, { roundNumber: 4, activeIndex: 1 }); const result1 = clearEncounter(encounter); const result2 = clearEncounter(encounter); expect(result1).toEqual(result2); }); });