import { describe, expect, it } from "vitest"; import { ROM_PRIEST_CHAMPION_BEACON_OF_REGENERATION_DURATION_MS, ROM_PRIEST_CHAMPION_BEACON_OF_REGENERATION_HEAL_AT_SKILL_LEVEL_105, ROM_PRIEST_CHAMPION_BEACON_OF_REGENERATION_SPELL_ID, ROM_PRIEST_CHAMPION_BEACON_OF_REGENERATION_SOURCE_SKILL_LEVEL, createRomPriestChampionBeaconState, resolveRomPriestChampionBeaconHeal, } from "./romPriestChampionBeaconRuntime"; describe("current CoA Priest/Champion Beacon of Regeneration", () => { it("records the source-described skill, duration, and published +105 healing amount", () => { expect(ROM_PRIEST_CHAMPION_BEACON_OF_REGENERATION_SPELL_ID).toBe(498620); expect(ROM_PRIEST_CHAMPION_BEACON_OF_REGENERATION_DURATION_MS).toBe(30_000); expect(ROM_PRIEST_CHAMPION_BEACON_OF_REGENERATION_SOURCE_SKILL_LEVEL).toBe(105); expect(ROM_PRIEST_CHAMPION_BEACON_OF_REGENERATION_HEAL_AT_SKILL_LEVEL_105).toBe(770); }); it("heals the marked party member once for each caster direct-heal cast at sourced skill level 105", () => { const beacon = createRomPriestChampionBeaconState("priest", "ally", 1_000); expect(resolveRomPriestChampionBeaconHeal(beacon, { casterId: "priest", occurredAtMs: 1_001, kind: "direct-cast", }, 105)).toEqual({ targetId: "ally", amount: 770 }); expect(resolveRomPriestChampionBeaconHeal(beacon, { casterId: "priest", occurredAtMs: 15_000, kind: "direct-cast", }, 105)).toEqual({ targetId: "ally", amount: 770 }); }); it("does not extrapolate the +105 amount to unknown or lower skill levels", () => { const beacon = createRomPriestChampionBeaconState("priest", "ally", 1_000); const event = { casterId: "priest", occurredAtMs: 2_000, kind: "direct-cast" as const }; expect(resolveRomPriestChampionBeaconHeal(beacon, event, null)).toBeNull(); expect(resolveRomPriestChampionBeaconHeal(beacon, event, 50)).toBeNull(); expect(resolveRomPriestChampionBeaconHeal(beacon, event, 104)).toBeNull(); }); it("requires a direct-heal cast from the Beacon caster and excludes other actors, HoT ticks, and channel pulses", () => { const beacon = createRomPriestChampionBeaconState("priest", "ally", 1_000); expect(resolveRomPriestChampionBeaconHeal(beacon, { casterId: "companion", occurredAtMs: 2_000, kind: "direct-cast", }, 105)).toBeNull(); expect(resolveRomPriestChampionBeaconHeal(beacon, { casterId: "priest", occurredAtMs: 2_000, kind: "hot-tick", }, 105)).toBeNull(); expect(resolveRomPriestChampionBeaconHeal(beacon, { casterId: "priest", occurredAtMs: 2_000, kind: "channel-pulse", }, 105)).toBeNull(); }); it("expires at 30 seconds and ignores events before Beacon creation", () => { const beacon = createRomPriestChampionBeaconState("priest", "ally", 1_000); expect(resolveRomPriestChampionBeaconHeal(beacon, { casterId: "priest", occurredAtMs: 30_999, kind: "direct-cast", }, 105)).toEqual({ targetId: "ally", amount: 770 }); expect(resolveRomPriestChampionBeaconHeal(beacon, { casterId: "priest", occurredAtMs: 31_000, kind: "direct-cast", }, 105)).toBeNull(); expect(resolveRomPriestChampionBeaconHeal(beacon, { casterId: "priest", occurredAtMs: 999, kind: "direct-cast", }, 105)).toBeNull(); }); it("rejects incomplete cast state and invalid event times", () => { expect(createRomPriestChampionBeaconState("", "ally", 0)).toBeNull(); expect(createRomPriestChampionBeaconState("priest", " ", 0)).toBeNull(); expect(createRomPriestChampionBeaconState("priest", "ally", Number.NaN)).toBeNull(); const beacon = createRomPriestChampionBeaconState("priest", "ally", 0); expect(resolveRomPriestChampionBeaconHeal(beacon, { casterId: "priest", occurredAtMs: Number.NaN, kind: "direct-cast", }, 105)).toBeNull(); }); });