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

172 lines
6.7 KiB
TypeScript

import { describe, expect, it } from "vitest";
import generatedData from "./wow335AbilityData.generated.json";
import {
WOW335_DEATH_KNIGHT_DANCING_RUNE_WEAPON_DURATION_MS,
WOW335_DEATH_KNIGHT_DANCING_RUNE_WEAPON_AURA,
WOW335_DEATH_KNIGHT_DANCING_RUNE_WEAPON_ABILITY_ID,
WOW335_DEATH_KNIGHT_DANCING_RUNE_WEAPON_EXCLUDED_UTILITY_SPELLS,
WOW335_DEATH_KNIGHT_DANCING_RUNE_WEAPON_DAMAGE_MULTIPLIER,
WOW335_DEATH_KNIGHT_DEATH_COIL_DAMAGE_SPELL_ID,
wow335DeathKnightDancingRuneWeaponCanMirrorEvent,
wow335DeathKnightDancingRuneWeaponDamage,
wow335DeathKnightDancingRuneWeaponExcludedUtilitySpellForName,
wow335DeathKnightDancingRuneWeaponIsActive,
type Wow335DeathKnightDancingRuneWeaponOwnerEvent,
} from "./wow335DeathKnightDancingRuneWeaponRuntime";
describe("WoW Death Knight Dancing Rune Weapon runtime", () => {
it("uses the sourced 12-second duration and 50% reduced-damage child payload", () => {
const dancingRuneWeapon = generatedData.classes["death-knight"].find((ability) =>
ability.ranks.some((rank) => rank.spellId === 49_028),
);
const rank = dancingRuneWeapon?.ranks.find((candidate) => candidate.spellId === 49_028);
expect(rank?.description).toContain("50% reduced damage");
expect(rank).toMatchObject({ durationMs: 12_000, cooldownMs: 90_000, powerCost: 600 });
expect(rank?.effects[2]).toMatchObject({
effectType: 6,
auraType: 4,
basePoints: 10,
});
expect(WOW335_DEATH_KNIGHT_DANCING_RUNE_WEAPON_DURATION_MS).toBe(12_000);
expect(WOW335_DEATH_KNIGHT_DANCING_RUNE_WEAPON_DAMAGE_MULTIPLIER).toBe(0.5);
expect(WOW335_DEATH_KNIGHT_DANCING_RUNE_WEAPON_ABILITY_ID)
.toBe("wow335-death-knight-dancing-rune-weapon");
expect(WOW335_DEATH_KNIGHT_DANCING_RUNE_WEAPON_AURA).toMatchObject({
durationMs: 12_000,
maxStacks: 1,
utilityTags: ["wow335-death-knight-dancing-rune-weapon"],
});
});
it("is active at summon and expires exactly at 12 seconds", () => {
expect(wow335DeathKnightDancingRuneWeaponIsActive(1_000, 1_000)).toBe(true);
expect(wow335DeathKnightDancingRuneWeaponIsActive(1_000, 12_999)).toBe(true);
expect(wow335DeathKnightDancingRuneWeaponIsActive(1_000, 13_000)).toBe(false);
expect(wow335DeathKnightDancingRuneWeaponIsActive(1_000, 999)).toBe(false);
expect(wow335DeathKnightDancingRuneWeaponIsActive(Number.NaN, 1_000)).toBe(false);
expect(wow335DeathKnightDancingRuneWeaponIsActive(1_000, Number.POSITIVE_INFINITY)).toBe(false);
});
it("allows a living hostile modeled melee event", () => {
const event: Wow335DeathKnightDancingRuneWeaponOwnerEvent = {
kind: "melee",
targetAlive: true,
targetHostile: true,
};
expect(wow335DeathKnightDancingRuneWeaponCanMirrorEvent(event)).toBe(true);
});
it("requires a living hostile target for every event kind", () => {
expect(wow335DeathKnightDancingRuneWeaponCanMirrorEvent({
kind: "melee",
targetAlive: false,
targetHostile: true,
})).toBe(false);
expect(wow335DeathKnightDancingRuneWeaponCanMirrorEvent({
kind: "melee",
targetAlive: true,
targetHostile: false,
})).toBe(false);
expect(wow335DeathKnightDancingRuneWeaponCanMirrorEvent({
kind: "spell",
spellId: 49_895,
ownerKnowsSpell: true,
targetAlive: true,
targetHostile: false,
isPositiveSpell: false,
hasSummonEffect: false,
isAreaTargeted: false,
actionTargetIsOwner: false,
})).toBe(false);
});
it("requires learned spells except for Death Coil's damage child", () => {
const event: Wow335DeathKnightDancingRuneWeaponOwnerEvent = {
kind: "spell",
spellId: 49_895,
ownerKnowsSpell: false,
targetAlive: true,
targetHostile: true,
isPositiveSpell: false,
hasSummonEffect: false,
isAreaTargeted: false,
actionTargetIsOwner: false,
};
expect(wow335DeathKnightDancingRuneWeaponCanMirrorEvent(event)).toBe(false);
expect(wow335DeathKnightDancingRuneWeaponCanMirrorEvent({
...event,
spellId: WOW335_DEATH_KNIGHT_DEATH_COIL_DAMAGE_SPELL_ID,
})).toBe(true);
});
it("rejects each source-listed DK utility spell", () => {
const baseEvent: Wow335DeathKnightDancingRuneWeaponOwnerEvent = {
kind: "spell",
spellId: 49_895,
ownerKnowsSpell: true,
targetAlive: true,
targetHostile: true,
isPositiveSpell: false,
hasSummonEffect: false,
isAreaTargeted: false,
actionTargetIsOwner: false,
};
for (const excludedUtilitySpell of WOW335_DEATH_KNIGHT_DANCING_RUNE_WEAPON_EXCLUDED_UTILITY_SPELLS) {
expect(wow335DeathKnightDancingRuneWeaponCanMirrorEvent({
...baseEvent,
excludedUtilitySpell,
})).toBe(false);
}
});
it("maps generated spell names to source utility exclusions", () => {
expect(wow335DeathKnightDancingRuneWeaponExcludedUtilitySpellForName("Death and Decay"))
.toBe("death-and-decay");
expect(wow335DeathKnightDancingRuneWeaponExcludedUtilitySpellForName("Anti-Magic Shell"))
.toBe("anti-magic-shell");
expect(wow335DeathKnightDancingRuneWeaponExcludedUtilitySpellForName("Death Strike")).toBeUndefined();
});
it("rejects positive spells, summons, and repeated area events on secondary targets", () => {
const baseEvent: Wow335DeathKnightDancingRuneWeaponOwnerEvent = {
kind: "spell",
spellId: 49_895,
ownerKnowsSpell: true,
targetAlive: true,
targetHostile: true,
isPositiveSpell: false,
hasSummonEffect: false,
isAreaTargeted: false,
actionTargetIsOwner: false,
};
expect(wow335DeathKnightDancingRuneWeaponCanMirrorEvent({ ...baseEvent, isPositiveSpell: true })).toBe(false);
expect(wow335DeathKnightDancingRuneWeaponCanMirrorEvent({ ...baseEvent, hasSummonEffect: true })).toBe(false);
expect(wow335DeathKnightDancingRuneWeaponCanMirrorEvent({
...baseEvent,
isAreaTargeted: true,
actionTargetIsOwner: false,
})).toBe(false);
expect(wow335DeathKnightDancingRuneWeaponCanMirrorEvent({
...baseEvent,
isAreaTargeted: true,
actionTargetIsOwner: true,
})).toBe(true);
});
it("mirrors an attack at half damage and floors to whole damage", () => {
expect(wow335DeathKnightDancingRuneWeaponDamage(101)).toBe(50);
expect(wow335DeathKnightDancingRuneWeaponDamage(100)).toBe(50);
expect(wow335DeathKnightDancingRuneWeaponDamage(1)).toBe(0);
});
it("returns zero for non-positive or non-finite attack damage", () => {
expect(wow335DeathKnightDancingRuneWeaponDamage(0)).toBe(0);
expect(wow335DeathKnightDancingRuneWeaponDamage(-2)).toBe(0);
expect(wow335DeathKnightDancingRuneWeaponDamage(Number.NaN)).toBe(0);
expect(wow335DeathKnightDancingRuneWeaponDamage(Number.POSITIVE_INFINITY)).toBe(0);
});
});