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

95 lines
4.3 KiB
TypeScript

import { describe, expect, it } from "vitest";
import {
WOW335_SHAMAN_FLURRY_AURA_TAG,
WOW335_SHAMAN_FLURRY_DURATION_MS,
WOW335_SHAMAN_FLURRY_TALENT_ID,
wow335ShamanFlurryApplyProc,
wow335ShamanFlurryConsumeSwingCharge,
wow335ShamanFlurryGeneratedSource,
wow335ShamanFlurryProfileForRank,
wow335ShamanFlurryShouldProc,
} from "./wow335ShamanFlurryRuntime";
describe("WoW 3.3.5 Shaman Flurry source model", () => {
it("uses the local generated Flurry rank rows and their displayed values", () => {
const talent = wow335ShamanFlurryGeneratedSource();
expect(talent).toMatchObject({
id: WOW335_SHAMAN_FLURRY_TALENT_ID,
name: "Flurry",
treeId: "shaman-enhancement",
rankSpellIds: [16256, 16281, 16282],
});
expect(talent!.rankDescriptions).toEqual([
expect.stringContaining("melee attack speed by 4% for your next 3 swings"),
expect.stringContaining("melee attack speed by 6% for your next 3 swings"),
expect.stringContaining("melee attack speed by 10% for your next 3 swings"),
]);
expect([1, 2, 3].map(wow335ShamanFlurryProfileForRank)).toEqual([
{ rank: 1, meleeHastePercent: 4, swingCharges: 3 },
{ rank: 2, meleeHastePercent: 6, swingCharges: 3 },
{ rank: 3, meleeHastePercent: 10, swingCharges: 3 },
]);
});
it("normalizes ranks and returns no profile when no rank is trained", () => {
expect(wow335ShamanFlurryProfileForRank(0)).toBeNull();
expect(wow335ShamanFlurryProfileForRank(-1)).toBeNull();
expect(wow335ShamanFlurryProfileForRank(Number.NaN)).toBeNull();
expect(wow335ShamanFlurryProfileForRank(99)).toEqual({
rank: 3, meleeHastePercent: 10, swingCharges: 3,
});
});
it("triggers only for a landed melee critical strike with a trained rank", () => {
const landedMeleeCritical = { attackKind: "melee" as const, landed: true, critical: true };
expect(wow335ShamanFlurryShouldProc(1, landedMeleeCritical)).toBe(true);
expect(wow335ShamanFlurryShouldProc(0, landedMeleeCritical)).toBe(false);
expect(wow335ShamanFlurryShouldProc(1, { ...landedMeleeCritical, landed: false })).toBe(false);
expect(wow335ShamanFlurryShouldProc(1, { ...landedMeleeCritical, critical: false })).toBe(false);
expect(wow335ShamanFlurryShouldProc(1, { ...landedMeleeCritical, attackKind: "spell" })).toBe(false);
expect(wow335ShamanFlurryShouldProc(1, { ...landedMeleeCritical, attackKind: "ranged" })).toBe(false);
});
it("keeps the tooltip display value distinct from the raw rank-two aura payload", () => {
const talent = wow335ShamanFlurryGeneratedSource()!;
expect(wow335ShamanFlurryProfileForRank(2)?.meleeHastePercent).toBe(6);
expect(talent.rankEffects[1]?.effects[1]?.basePoints).toBe(7);
});
it("applies the rank haste for 15 seconds and refreshes to three charges", () => {
const applied = wow335ShamanFlurryApplyProc([], "shaman-1", 2, 1_000);
expect(applied).toHaveLength(1);
expect(applied[0]).toMatchObject({
sourceId: "shaman-1",
targetId: "shaman-1",
stacks: 3,
appliedAt: 1_000,
expiresAt: 1_000 + WOW335_SHAMAN_FLURRY_DURATION_MS,
definition: {
utilityTags: [WOW335_SHAMAN_FLURRY_AURA_TAG],
modifiers: [{ kind: "stat", stat: "melee-haste", operation: "flat", value: 6, perStack: false }],
},
});
const decremented = wow335ShamanFlurryConsumeSwingCharge(applied, "shaman-1", 2_000);
expect(decremented[0]?.stacks).toBe(2);
expect(wow335ShamanFlurryApplyProc(decremented, "shaman-1", 1, 3_000)[0]).toMatchObject({
stacks: 3,
appliedAt: 3_000,
expiresAt: 3_000 + WOW335_SHAMAN_FLURRY_DURATION_MS,
definition: { modifiers: [{ value: 4 }] },
});
});
it("does not consume another Shaman's charge or an expired aura", () => {
const active = wow335ShamanFlurryApplyProc([], "shaman-1", 1, 1_000);
const otherOwner = wow335ShamanFlurryApplyProc(active, "shaman-2", 1, 1_000);
expect(wow335ShamanFlurryConsumeSwingCharge(otherOwner, "shaman-1", 2_000))
.toEqual(expect.arrayContaining([
expect.objectContaining({ targetId: "shaman-1", stacks: 2 }),
expect.objectContaining({ targetId: "shaman-2", stacks: 3 }),
]));
expect(wow335ShamanFlurryConsumeSwingCharge(active, "shaman-1", 16_000)).toEqual(active);
});
});