import { describe, expect, it } from "vitest"; import type { StructuredCombatEvent } from "../game/combatEvents"; import { MAX_PARTY_HEAL_POPUPS, addedPartyHealPopups, appendPartyHealPopups, } from "./partyHealPopups"; function event( id: number, kind: StructuredCombatEvent["kind"] = "healing", effectiveAmount = 125, ): StructuredCombatEvent { return { id, occurredAt: 1_000 + id, kind, sourceActorId: "healer", targetActorId: `party-${id}`, rawAmount: effectiveAmount, effectiveAmount, overheal: 0, absorbed: 0, critical: id % 2 === 0, }; } describe("party-frame healing popups", () => { it("turns newly committed effective heals into rounded green-number events", () => { const previous = [event(1)]; const next = [...previous, event(2, "damage", 80), event(3, "healing", 149.6)]; expect(addedPartyHealPopups(previous, next, true)).toEqual([{ key: "1003:3", targetActorId: "party-3", amount: 150, critical: false, horizontalOffset: -14, }]); }); it("ignores old heals, pure overheal, and all healing outside combat", () => { const previous = [event(1)]; const overheal = event(2, "healing", 0); expect(addedPartyHealPopups(previous, [...previous, overheal], true)).toEqual([]); expect(addedPartyHealPopups(previous, [...previous, event(3)], false)).toEqual([]); }); it("deduplicates replayed keys and bounds the active burst", () => { const first = addedPartyHealPopups([], [event(1)], true)[0]; const burst = Array.from({ length: MAX_PARTY_HEAL_POPUPS + 4 }, (_, index) => ( addedPartyHealPopups([], [event(index + 2)], true)[0] )); const result = appendPartyHealPopups([first], [first, ...burst]); expect(result).toHaveLength(MAX_PARTY_HEAL_POPUPS); expect(new Set(result.map((popup) => popup.key)).size).toBe(MAX_PARTY_HEAL_POPUPS); expect(result.at(-1)?.key).toBe(`${1_000 + MAX_PARTY_HEAL_POPUPS + 5}:${MAX_PARTY_HEAL_POPUPS + 5}`); }); });