66 lines
3.5 KiB
TypeScript
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 });
|
|
});
|
|
});
|