import { beforeEach, describe, expect, it } from "vitest"; import { PLAYER_AGGRO_ID } from "./aggro"; import { clearMobRuntimeRegistry, setMobPosition } from "./mobRuntimeRegistry"; import { useCombatStore } from "./combatStore"; import { clearPartyRuntimeRegistry, registerPartyRuntimePosition } from "./partyRuntimeRegistry"; import { usePartyStore } from "./partyStore"; const NATURE_SWIFTNESS_ID = "wow335-shaman-nature-s-swiftness"; const ELEMENTAL_MASTERY_ID = "wow335-shaman-elemental-mastery"; const NON_NATURE_SPELL_ID = "shaman-flame-shock"; const HEALING_WAVE_ID = "shaman-healing-wave"; describe("WoW Shaman Nature's Swiftness runtime", () => { beforeEach(() => { clearMobRuntimeRegistry(); clearPartyRuntimeRegistry(); useCombatStore.getState().initializeCharacter({ classId: "shaman", level: 80, xp: 0 }); useCombatStore.getState().setPlayerPosition([0, 0, 0]); usePartyStore.getState().initializeParty("wow-nature-swiftness-test", 80, useCombatStore.getState().health); useCombatStore.setState((state) => ({ resource: state.maxResource, resourcePools: { ...state.resourcePools, mana: state.maxResourcePools.mana }, })); }); it("makes the next cast-time Nature spell instant, preserves the proc through Flame Shock, and shares the 3-minute cooldown", () => { useCombatStore.setState((state) => ({ talentRanks: { ...state.talentRanks, "talent-591": 1, "talent-573": 1 }, })); const member = usePartyStore.getState().members[0]!; usePartyStore.setState((state) => ({ members: state.members.map((candidate) => candidate.id === member.id ? { ...candidate, health: 1 } : candidate), })); usePartyStore.getState().selectMember(member.id); registerPartyRuntimePosition(member.id, [5, 0, 0]); useCombatStore.getState().registerMob("nature-swiftness-target", { name: "Target", maxHealth: 10_000 }); setMobPosition("nature-swiftness-target", [10, 0, 0]); useCombatStore.getState().selectMob("nature-swiftness-target"); const activation = useCombatStore.getState().castAbility(NATURE_SWIFTNESS_ID, undefined, 1_000); expect(activation.ok, JSON.stringify(activation)).toBe(true); expect(useCombatStore.getState().cooldowns[ELEMENTAL_MASTERY_ID]).toBe(181_000); expect(useCombatStore.getState().castAbility(ELEMENTAL_MASTERY_ID, undefined, 2_000)) .toMatchObject({ ok: false, reason: "cooldown" }); expect(useCombatStore.getState().castAbility(NON_NATURE_SPELL_ID, undefined, 2_000)).toMatchObject({ ok: true }); const natureSwiftnessAura = useCombatStore.getState().auras.find((aura) => ( aura.targetId === PLAYER_AGGRO_ID && aura.definition.utilityTags?.includes("wow335-next-nature-instant") )); expect(natureSwiftnessAura).toBeDefined(); expect(natureSwiftnessAura?.definition.durationMs).toBeNull(); expect(natureSwiftnessAura?.definition.modifiers ?? []).not.toContainEqual( expect.objectContaining({ kind: "stat", stat: "haste" }), ); const healed = useCombatStore.getState().castAbility(HEALING_WAVE_ID, [0, 0, 0], 4_000); expect(healed.ok, JSON.stringify(healed)).toBe(true); expect(useCombatStore.getState().activeCast).toBeNull(); expect(useCombatStore.getState().auras.some((aura) => ( aura.targetId === PLAYER_AGGRO_ID && aura.definition.utilityTags?.includes("wow335-next-nature-instant") ))).toBe(false); expect(useCombatStore.getState().combatEvents.some((event) => ( event.kind === "healing" && event.sourceActorId === PLAYER_AGGRO_ID && event.abilityId === HEALING_WAVE_ID && event.targetActorId === member.id ))).toBe(true); }); });