import assert from "node:assert/strict"; import test from "node:test"; import { DEFAULT_COMPANION_COOLDOWN_POLICY, normalizeCompanionCooldownPolicy, } from "./companion-cooldown-policy.mjs"; test("normalizes valid generic and boss-mechanic cooldown rules", () => { const policy = normalizeCompanionCooldownPolicy({ ...DEFAULT_COMPANION_COOLDOWN_POLICY, generic: { ...DEFAULT_COMPANION_COOLDOWN_POLICY.generic, defensiveHealthPercent: 62 }, mechanics: [{ id: "tank-buster", enabled: true, bossKey: "test/boss", bossName: "Test Boss", bossServerEntry: 123, attackId: "heavy-strike", attackName: "Heavy Strike", scope: "tank", leadTimeMs: 2_500, minimumCooldownSeconds: 20, }], }); assert.equal(policy.generic.defensiveHealthPercent, 62); assert.equal(policy.mechanics[0].attackId, "heavy-strike"); }); test("rejects duplicate mechanic ids and out-of-range thresholds", () => { const rule = { id: "duplicate", enabled: true, bossKey: "", bossName: "Boss", bossServerEntry: null, attackId: "attack", attackName: "Attack", scope: "party", leadTimeMs: 1_000, minimumCooldownSeconds: 20, }; assert.throws(() => normalizeCompanionCooldownPolicy({ ...DEFAULT_COMPANION_COOLDOWN_POLICY, mechanics: [rule, rule], }), /duplicated/); assert.throws(() => normalizeCompanionCooldownPolicy({ ...DEFAULT_COMPANION_COOLDOWN_POLICY, generic: { ...DEFAULT_COMPANION_COOLDOWN_POLICY.generic, defensiveHealthPercent: 101 }, }), /1 through 100/); assert.throws(() => normalizeCompanionCooldownPolicy({ ...DEFAULT_COMPANION_COOLDOWN_POLICY, generic: { ...DEFAULT_COMPANION_COOLDOWN_POLICY.generic, conserveOffensiveCooldownsForDurableTargets: "yes" }, }), /must be boolean/); assert.throws(() => normalizeCompanionCooldownPolicy({ ...DEFAULT_COMPANION_COOLDOWN_POLICY, mechanics: [{ ...rule, id: "missing-boss", bossName: "" }], }), /bossName is required/); });