microduck-reachy-simulator / app /test /keyboard-layout.test.js
vbonnet's picture
Default keyboard labels to QWERTY
20ce68e
Raw History Blame
3.12 kB
import test from "node:test";
import assert from "node:assert/strict";
import { readLayoutMap, resolveKeycaps } from "../src/ui/keyboard-layout.js";
const AZERTY = new Map(
Object.entries({ KeyW: "z", KeyA: "q", KeyS: "s", KeyD: "d", KeyQ: "a", KeyE: "e" }),
);
const QWERTY = new Map(
Object.entries({ KeyW: "w", KeyA: "a", KeyS: "s", KeyD: "d", KeyQ: "q", KeyE: "e" }),
);
const DVORAK = new Map(
Object.entries({ KeyW: ",", KeyA: "a", KeyS: "o", KeyD: "e", KeyQ: "'", KeyE: "." }),
);
const CODES = ["KeyQ", "KeyE"];
test("resolves caps and the movement hint from the active layout", () => {
assert.deepEqual(resolveKeycaps(CODES, QWERTY), {
labels: { KeyW: "W", KeyA: "A", KeyS: "S", KeyD: "D", KeyQ: "Q", KeyE: "E" },
moveHint: "arrows or WASD",
});
const azerty = resolveKeycaps(CODES, AZERTY);
assert.deepEqual(azerty.labels, {
KeyW: "Z", KeyA: "Q", KeyS: "S", KeyD: "D", KeyQ: "A", KeyE: "E",
});
assert.equal(azerty.moveHint, "arrows or ZQSD");
const dvorak = resolveKeycaps(CODES, DVORAK);
assert.equal(dvorak.labels.KeyQ, "'");
assert.equal(dvorak.moveHint, "arrows or ,AOE");
});
test("falls back to QWERTY labels without a map", () => {
assert.deepEqual(resolveKeycaps(CODES, null), {
labels: { KeyW: "W", KeyA: "A", KeyS: "S", KeyD: "D", KeyQ: "Q", KeyE: "E" },
moveHint: "arrows or WASD",
});
assert.equal(resolveKeycaps(["KeyX"], null).labels.KeyX, "X");
});
const ALL_QWERTY = {
labels: { KeyW: "W", KeyA: "A", KeyS: "S", KeyD: "D", KeyQ: "Q", KeyE: "E" },
moveHint: "arrows or WASD",
};
test("falls back entirely to QWERTY when the map misses a movement key", () => {
const partial = new Map([["KeyW", "z"], ["KeyA", "q"], ["KeyS", "s"]]);
assert.deepEqual(resolveKeycaps(CODES, partial), ALL_QWERTY);
});
test("falls back entirely to QWERTY when the map misses a requested key", () => {
const partial = new Map([...AZERTY].filter(([code]) => code !== "KeyE"));
assert.deepEqual(resolveKeycaps(CODES, partial), ALL_QWERTY);
});
test("rejects layout values that cannot sit on a keycap", () => {
const junk = new Map(
Object.entries({ KeyQ: "", KeyE: " ", KeyW: "Dead", KeyA: "́", KeyS: 7 }),
);
assert.deepEqual(resolveKeycaps(CODES, junk), ALL_QWERTY);
});
test("a throwing map cannot break the menu", () => {
const hostile = { get: () => { throw new Error("nope"); } };
assert.deepEqual(resolveKeycaps(CODES, hostile), ALL_QWERTY);
});
test("readLayoutMap yields null when the API is absent or refuses", async () => {
assert.equal(await readLayoutMap({}), null);
assert.equal(await readLayoutMap({ keyboard: {} }), null);
const rejects = { keyboard: { getLayoutMap: () => Promise.reject(new Error("blocked")) } };
assert.equal(await readLayoutMap(rejects), null);
const throws = { keyboard: { getLayoutMap: () => { throw new Error("framed"); } } };
assert.equal(await readLayoutMap(throws), null);
});
test("readLayoutMap returns the map where the API is supported", async () => {
const nav = { keyboard: { getLayoutMap: async () => AZERTY } };
assert.equal(await readLayoutMap(nav), AZERTY);
});