import { beforeEach, describe, expect, it } from "vitest"; import { useCombatStore } from "./combatStore"; import { clearMobRuntimeRegistry, setMobPosition } from "./mobRuntimeRegistry"; import { advanceDungeonPartyCombat, resetPartyRuntimeClock } from "./partyRuntime"; import { clearPartyRuntimeRegistry, registerPartyRuntimePosition, updatePartyRuntimeTargetVisibility } from "./partyRuntimeRegistry"; import { createConfiguredPartyMember, usePartyStore } from "./partyStore"; import { ROM_MAGE_DRUID_GREEN_GUARDIAN_AURA_TAG, ROM_MAGE_DRUID_GREEN_GUARDIAN_SKILL_ID } from "./romMageDruidGreenGuardianRuntime"; describe("CoA Mage/Druid Green Guardian companion cast selection", () => { beforeEach(() => { resetPartyRuntimeClock(); clearMobRuntimeRegistry(); clearPartyRuntimeRegistry(); useCombatStore.getState().initializeCharacter({ classId: "rom-priest", raceId: "rom-elf", level: 45, role: "healer", }); usePartyStore.getState().initializeParty( "green-guardian-party-test", 45, useCombatStore.getState().health, "damage", 2, "rom", ); }); it("casts the learned zero-cost self skill through party combat and starts at zero stacks", () => { const seed = "green-guardian-party-cast"; const companion = createConfiguredPartyMember({ name: "Green Guardian Mage", classId: "rom-mage", secondaryClassId: "rom-druid", specialization: "Primary", role: "damage", }, 45, 0, seed); usePartyStore.setState({ members: [companion], command: "attack", activeMobId: "guardian-target", }); registerPartyRuntimePosition(companion.id, [0, 0, 0]); useCombatStore.getState().synchronizeActors(); useCombatStore.getState().registerMob("guardian-target", { name: "Guardian target", level: 1, maxHealth: 1_000, xpReward: 0, }); setMobPosition("guardian-target", [2, 0, 0]); useCombatStore.getState().damageMob("guardian-target", 1, 500); updatePartyRuntimeTargetVisibility(companion.id, "guardian-target", true); advanceDungeonPartyCombat(1_000); const aura = useCombatStore.getState().auras.find((candidate) => candidate.targetId === companion.id && candidate.definition.utilityTags?.includes(ROM_MAGE_DRUID_GREEN_GUARDIAN_AURA_TAG)); expect(aura?.stacks).toBe(0); expect(aura?.sourceId).toBe(companion.id); const committed = usePartyStore.getState().members[0]; expect(committed.globalCooldownEndsAt).toBe(2_500); expect(committed.cooldowns).not.toHaveProperty(String(ROM_MAGE_DRUID_GREEN_GUARDIAN_SKILL_ID)); }); it("does not auto-cast Green Guardian for the reverse Druid/Mage pair", () => { const seed = "green-guardian-party-reverse"; const companion = createConfiguredPartyMember({ name: "Reverse Pair Druid", classId: "rom-druid", secondaryClassId: "rom-mage", specialization: "Primary", role: "damage", }, 45, 0, seed); usePartyStore.setState({ members: [companion], command: "attack", activeMobId: "guardian-target", }); registerPartyRuntimePosition(companion.id, [0, 0, 0]); useCombatStore.getState().synchronizeActors(); useCombatStore.getState().registerMob("guardian-target", { name: "Guardian target", level: 1, maxHealth: 1_000, xpReward: 0, }); setMobPosition("guardian-target", [2, 0, 0]); useCombatStore.getState().damageMob("guardian-target", 1, 500); updatePartyRuntimeTargetVisibility(companion.id, "guardian-target", true); advanceDungeonPartyCombat(1_000); expect(useCombatStore.getState().auras.some((candidate) => candidate.targetId === companion.id && candidate.definition.utilityTags?.includes(ROM_MAGE_DRUID_GREEN_GUARDIAN_AURA_TAG))).toBe(false); }); });