Files
healer-man/src/game/actionBindings.test.ts
T
2026-08-14 15:56:39 -04:00

74 lines
3.2 KiB
TypeScript

import { describe, expect, it } from "vitest";
import {
ACTION_CONTROLS,
ACTION_LAYERS,
actionBindingChordLabel,
actionBindingId,
actionControlForControllerToken,
actionControlForKeyboardCode,
actionLayerForModifiers,
defaultActionBindings,
normalizeActionBindings,
resetActionBindingLayer,
withActionBinding,
} from "./actionBindings";
import { defaultActionBarForClass } from "./abilityCatalog";
describe("controller action bindings", () => {
it("creates all twenty-four slots and maps the first four abilities to the face diamond", () => {
const bindings = defaultActionBindings(["one", "two", "three", "four"]);
expect(Object.keys(bindings)).toHaveLength(ACTION_LAYERS.length * ACTION_CONTROLS.length);
expect(bindings["primary:face-bottom"]).toBe("one");
expect(bindings["primary:face-left"]).toBe("two");
expect(bindings["primary:face-top"]).toBe("three");
expect(bindings["primary:face-right"]).toBe("four");
expect(bindings["primary:r1"]).toBeNull();
expect(bindings["secondary:face-bottom"]).toBeNull();
});
it("normalizes partial and corrupt saved data against known class abilities", () => {
const bindings = normalizeActionBindings({
"primary:face-bottom": "other-class-spell",
"primary:face-left": "known-two",
madeUp: "known-one",
}, ["known-one", "known-two", "known-three"]);
expect(bindings["primary:face-bottom"]).toBeNull();
expect(bindings["primary:face-left"]).toBe("known-two");
expect(bindings["primary:face-top"]).toBe("known-three");
expect(Object.keys(bindings)).toHaveLength(24);
});
it("places each primary class taunt in the fifth default R1 slot", () => {
for (const [classId, tauntId] of [
["warrior", "warrior-taunt"],
["paladin", "paladin-hand-of-reckoning"],
["death-knight", "death-knight-dark-command"],
["druid", "druid-growl"],
] as const) {
const abilities = defaultActionBarForClass(classId);
expect(abilities[4]).toBe(tauntId);
expect(defaultActionBindings(abilities)["primary:r1"]).toBe(tauntId);
}
});
it("updates and restores one layer without disturbing the other layers", () => {
const defaults = defaultActionBindings(["one", "two", "three", "four"]);
const edited = withActionBinding(defaults, "secondary", "r2", "one");
const reset = resetActionBindingLayer(edited, "primary", ["one", "two", "three", "four"]);
expect(reset[actionBindingId("secondary", "r2")]).toBe("one");
expect(reset[actionBindingId("primary", "face-bottom")]).toBe("one");
});
it("resolves physical inputs and modifier precedence", () => {
expect(actionControlForControllerToken("Button3")).toBe("face-top");
expect(actionControlForControllerToken("Button7")).toBe("r2");
expect(actionControlForControllerToken("Button14")).toBe("dpad-left");
expect(actionControlForKeyboardCode("Digit8")).toBe("dpad-right");
expect(actionLayerForModifiers(true, false)).toBe("secondary");
expect(actionLayerForModifiers(false, true)).toBe("tertiary");
expect(actionLayerForModifiers(true, true)).toBe("tertiary");
expect(actionBindingChordLabel("secondary", "face-top")).toBe("L1 + Triangle");
expect(actionBindingChordLabel("tertiary", "r1", "keyboard")).toBe("Alt + 5");
});
});