Files
healer-man/src/game/wow335DeathKnightBladeBarrierRuntime.test.ts
T
2026-10-02 10:38:12 -04:00

66 lines
3.5 KiB
TypeScript

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 });
});
});