import { describe, expect, it } from "vitest"; import { createDeathKnightRunes } from "./combatActors"; import { applyAura, resolveDamageValue } from "./combatAuras"; import { wow335DeathKnightBladeBarrierAuraDefinition, wow335DeathKnightBladeBarrierProfile, wow335DeathKnightBladeBarrierShouldActivate, } from "./wow335DeathKnightBladeBarrierRuntime"; describe("WoW Death Knight Blade Barrier", () => { it("reads all generated ranks, ten-second duration, and linked child IDs", () => { expect([1, 2, 3, 4, 5].map(wow335DeathKnightBladeBarrierProfile)).toEqual([ { rank: 1, damageTakenReduction: 0.01, durationMs: 10_000, triggerSpellId: 51_789 }, { rank: 2, damageTakenReduction: 0.02, durationMs: 10_000, triggerSpellId: 64_855 }, { rank: 3, damageTakenReduction: 0.03, durationMs: 10_000, triggerSpellId: 64_856 }, { rank: 4, damageTakenReduction: 0.04, durationMs: 10_000, triggerSpellId: 64_858 }, { rank: 5, damageTakenReduction: 0.05, durationMs: 10_000, triggerSpellId: 64_859 }, ]); expect(wow335DeathKnightBladeBarrierProfile(0)).toBeNull(); expect(wow335DeathKnightBladeBarrierProfile(6)).toBeNull(); }); it("requires a Blood rune spend while both original Blood runes are recharging", () => { const readyRunes = createDeathKnightRunes(1_000); const bothBloodRunesCooling = readyRunes.map((rune) => ( rune.baseType === "blood" ? { ...rune, readyAt: 11_000 } : rune )); expect(wow335DeathKnightBladeBarrierShouldActivate(5, readyRunes, bothBloodRunesCooling, 1_000)).toBe(true); expect(wow335DeathKnightBladeBarrierShouldActivate(0, readyRunes, bothBloodRunesCooling, 1_000)).toBe(false); expect(wow335DeathKnightBladeBarrierShouldActivate(5, bothBloodRunesCooling, bothBloodRunesCooling, 1_000)) .toBe(false); expect(wow335DeathKnightBladeBarrierShouldActivate(5, readyRunes, bothBloodRunesCooling, 11_000)).toBe(false); const oneBloodRuneReady = bothBloodRunesCooling.map((rune) => ( rune.baseType === "blood" && rune.slot === 0 ? { ...rune, readyAt: 1_000 } : rune )); expect(wow335DeathKnightBladeBarrierShouldActivate(5, readyRunes, oneBloodRuneReady, 1_000)).toBe(false); }); it("does not refresh from a Death Rune cast while both base Blood runes were already cooling", () => { const runesBefore = createDeathKnightRunes(1_000).map((rune) => { if (rune.baseType === "blood") return { ...rune, readyAt: 11_000 }; if (rune.slot === 2) return { ...rune, type: "death" as const }; return rune; }); const runesAfter = runesBefore.map((rune) => ( rune.slot === 2 ? { ...rune, readyAt: 11_000 } : rune )); expect(wow335DeathKnightBladeBarrierShouldActivate(5, runesBefore, runesAfter, 1_000)).toBe(false); }); it("reduces all incoming schools and refreshes one nonstacking aura", () => { const definition = wow335DeathKnightBladeBarrierAuraDefinition(4); expect(definition).not.toBeNull(); let auras = applyAura([], { definition: definition!, sourceId: "dk", targetId: "dk", now: 2_000 }).auras; expect(resolveDamageValue(100, auras, { direction: "taken", school: "physical", attackKind: "melee" })) .toBe(96); expect(resolveDamageValue(100, auras, { direction: "taken", school: "shadow", attackKind: "spell" })) .toBe(96); const refreshed = applyAura(auras, { definition: definition!, sourceId: "dk", targetId: "dk", now: 4_000 }); auras = refreshed.auras; expect(auras).toHaveLength(1); expect(refreshed.aura).toMatchObject({ stacks: 1, appliedAt: 4_000, expiresAt: 14_000 }); }); });