import { describe, expect, it } from "vitest"; import { KEYMAP, resolveShortcut, visibleKeymap } from "./audio-keys"; describe("resolveShortcut", () => { it("resolves every in-page binding", () => { expect(resolveShortcut(" ", false)).toBe("toggle-play"); expect(resolveShortcut("Enter", false)).toBe("toggle-play"); expect(resolveShortcut("h", false)).toBe("skip-back"); expect(resolveShortcut("H", false)).toBe("skip-back"); expect(resolveShortcut("ArrowLeft", false)).toBe("skip-back"); expect(resolveShortcut("l", false)).toBe("skip-forward"); expect(resolveShortcut("ArrowRight", false)).toBe("skip-forward"); expect(resolveShortcut("k", false)).toBe("prev-chapter"); expect(resolveShortcut("PageUp", false)).toBe("prev-chapter"); expect(resolveShortcut("j", false)).toBe("next-chapter"); expect(resolveShortcut("PageDown", false)).toBe("next-chapter"); expect(resolveShortcut("b", false)).toBe("bookmark"); expect(resolveShortcut("ArrowUp", false)).toBe("volume-up"); expect(resolveShortcut("ArrowDown", false)).toBe("volume-down"); expect(resolveShortcut("m", false)).toBe("toggle-mute"); expect(resolveShortcut("]", false)).toBe("cycle-skip-up"); expect(resolveShortcut("[", false)).toBe("cycle-skip-down"); expect(resolveShortcut("?", false)).toBe("toggle-help"); expect(resolveShortcut("Escape", false)).toBe("escape"); }); it("keeps Alt bindings distinct from their plain counterparts", () => { expect(resolveShortcut("l", true)).toBe("speed-up"); expect(resolveShortcut("l", false)).toBe("skip-forward"); expect(resolveShortcut("h", true)).toBe("speed-down"); expect(resolveShortcut("ArrowRight", true)).toBe("speed-up"); expect(resolveShortcut("ArrowLeft", true)).toBe("speed-down"); // Alt on an unbound key claims nothing. expect(resolveShortcut("ArrowUp", true)).toBeNull(); expect(resolveShortcut("m", true)).toBeNull(); }); it("resolves in-page media key events", () => { expect(resolveShortcut("MediaPlayPause", false)).toBe("media-toggle-play"); expect(resolveShortcut("MediaPlay", false)).toBe("media-play"); expect(resolveShortcut("MediaPause", false)).toBe("media-pause"); expect(resolveShortcut("MediaStop", false)).toBe("media-pause"); expect(resolveShortcut("MediaTrackNext", false)).toBe("media-next"); expect(resolveShortcut("MediaTrackPrevious", false)).toBe("media-prev"); }); it("returns null for unknown keys", () => { expect(resolveShortcut("x", false)).toBeNull(); expect(resolveShortcut("F5", false)).toBeNull(); expect(resolveShortcut("", false)).toBeNull(); }); }); describe("KEYMAP integrity", () => { it("has exactly one spec per action", () => { const actions = KEYMAP.map((spec) => spec.action); expect(new Set(actions).size).toBe(actions.length); }); it("has no conflicting (key, alt) combos across actions", () => { const seen = new Map(); for (const spec of KEYMAP) { for (const k of spec.keys) { const combo = `${k.alt ? "Alt+" : ""}${k.key}`; const owner = seen.get(combo); expect(owner, `${combo} bound by both ${owner} and ${spec.action}`).toBeUndefined(); seen.set(combo, spec.action); } } }); it("gives every spec at least one key, a label and a description", () => { for (const spec of KEYMAP) { expect(spec.keys.length, spec.action).toBeGreaterThan(0); expect(spec.label.length, spec.action).toBeGreaterThan(0); expect(spec.description.length, spec.action).toBeGreaterThan(0); } }); it("hides only media-key rows from the dialog", () => { const visible = new Set(visibleKeymap().map((spec) => spec.action)); for (const spec of KEYMAP) { if (spec.action.startsWith("media-")) { expect(visible.has(spec.action), spec.action).toBe(false); } else { expect(visible.has(spec.action), spec.action).toBe(true); } } }); });