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

107 lines
5.0 KiB
TypeScript

import { describe, expect, it } from "vitest";
import { WOW335_ABILITIES_BY_CLASS } from "./wow335AbilityCatalog";
import {
WOW335_PALADIN_ILLUMINATION_HEAL_ABILITY_IDS,
WOW335_PALADIN_ILLUMINATION_TALENT_ID,
wow335PaladinIlluminationRankMechanics,
wow335PaladinIlluminationRefundPlan,
} from "./wow335PaladinIlluminationRuntime";
const event = (overrides: Partial<Parameters<typeof wow335PaladinIlluminationRefundPlan>[1]> = {}) => ({
casterClassId: "paladin",
abilityId: WOW335_PALADIN_ILLUMINATION_HEAL_ABILITY_IDS["Holy Light"],
abilityName: "Holy Light",
criticalHeal: true,
spellBaseManaCost: 1_000,
roll: 0.5,
...overrides,
});
describe("WoW 3.3.5a Paladin Illumination", () => {
it("reads the exact generated rank chance and 50% base-mana refund", () => {
expect(WOW335_PALADIN_ILLUMINATION_TALENT_ID).toBe("talent-1461");
expect(WOW335_PALADIN_ILLUMINATION_HEAL_ABILITY_IDS).toEqual({
"Flash of Light": "wow335-paladin-flash-of-light",
"Holy Light": "wow335-paladin-holy-light",
"Holy Shock": "wow335-paladin-holy-shock",
});
expect([1, 2, 3].map(wow335PaladinIlluminationRankMechanics)).toEqual([
expect.objectContaining({ procChancePercent: 33, baseManaRefundFraction: 0.5 }),
expect.objectContaining({ procChancePercent: 66, baseManaRefundFraction: 0.5 }),
expect.objectContaining({ procChancePercent: 100, baseManaRefundFraction: 0.5 }),
]);
expect(wow335PaladinIlluminationRankMechanics(0)).toBeNull();
expect(wow335PaladinIlluminationRankMechanics(4)).toBeNull();
});
it("binds each tooltip heal name to a local 3.3.5a Paladin catalog row", () => {
const rows = new Map(WOW335_ABILITIES_BY_CLASS.paladin.map((ability) => [ability.name, ability]));
const rankOneSpellId = { "Flash of Light": 19_750, "Holy Light": 635, "Holy Shock": 20_473 };
for (const [name, id] of Object.entries(WOW335_PALADIN_ILLUMINATION_HEAL_ABILITY_IDS)) {
expect(rows.get(name)?.id).toBe(id);
expect(rows.get(name)?.source).toBe("wow335-progression");
expect(rows.get(name)?.dbcSpellId).toBe(rankOneSpellId[name as keyof typeof rankOneSpellId]);
expect(rows.get(name)?.ranks?.length).toBeGreaterThan(0);
expect(rows.get(name)?.ranks?.[0]?.cost.resource).toBe("mana");
}
});
it("uses only Flash of Light, Holy Light, and Holy Shock critical heals", () => {
const mechanics = wow335PaladinIlluminationRankMechanics(3)!;
expect(mechanics.eligibleHealNames).toEqual(["Flash of Light", "Holy Light", "Holy Shock"]);
for (const abilityName of mechanics.eligibleHealNames) {
expect(wow335PaladinIlluminationRefundPlan(3, event({
abilityName,
abilityId: WOW335_PALADIN_ILLUMINATION_HEAL_ABILITY_IDS[
abilityName as keyof typeof WOW335_PALADIN_ILLUMINATION_HEAL_ABILITY_IDS
],
}))).toEqual({
manaRefund: 500,
procChancePercent: 100,
});
}
expect(wow335PaladinIlluminationRefundPlan(3, event({ abilityName: "Divine Light" }))).toBeNull();
expect(wow335PaladinIlluminationRefundPlan(3, event({
casterClassId: "mage",
abilityId: "wow335-mage-holy-light",
}))).toBeNull();
expect(wow335PaladinIlluminationRefundPlan(3, event({ abilityId: "rom-priest-flash-of-light" }))).toBeNull();
});
it("applies rank chance to critical heals and treats the upper boundary as exclusive", () => {
expect(wow335PaladinIlluminationRefundPlan(1, event({ roll: 0.3299 }))).toEqual({
manaRefund: 500,
procChancePercent: 33,
});
expect(wow335PaladinIlluminationRefundPlan(1, event({ roll: 0.33 }))).toBeNull();
expect(wow335PaladinIlluminationRefundPlan(2, event({ roll: 0.6599 }))).not.toBeNull();
expect(wow335PaladinIlluminationRefundPlan(2, event({ roll: 0.66 }))).toBeNull();
expect(wow335PaladinIlluminationRefundPlan(3, event({ roll: 0.9999 }))).not.toBeNull();
});
it("requires a critical heal but does not require effective healing above zero", () => {
expect(wow335PaladinIlluminationRefundPlan(3, event({ criticalHeal: false }))).toBeNull();
// The source trigger is a critical heal, so an overheal remains eligible.
expect(wow335PaladinIlluminationRefundPlan(3, event())).toEqual({
manaRefund: 500,
procChancePercent: 100,
});
});
it("rejects invalid rank, base cost, and random inputs", () => {
expect(wow335PaladinIlluminationRefundPlan(0, event())).toBeNull();
expect(wow335PaladinIlluminationRefundPlan(3, event({ spellBaseManaCost: 0 }))).toBeNull();
expect(wow335PaladinIlluminationRefundPlan(3, event({ spellBaseManaCost: Number.NaN }))).toBeNull();
for (const roll of [-0.01, 1, Number.NaN, Number.POSITIVE_INFINITY]) {
expect(wow335PaladinIlluminationRefundPlan(3, event({ roll }))).toBeNull();
}
});
it("calculates the refund from the DBC-derived base cost without inventing odd-cost rounding", () => {
expect(wow335PaladinIlluminationRefundPlan(3, event({ spellBaseManaCost: 703 }))).toEqual({
manaRefund: 351.5,
procChancePercent: 100,
});
});
});