This repository has been archived on 2026-10-08. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
maestro/web/src/help.test.ts
T
Miguel PalhasandClaude Sonnet 5 c9562ab5eb Closes #252: port vanilla-DOM tests to React Testing Library
Rewrites the 27 DOM-behavior test files (dialogs, sidebar, spawn form,
command bar, structured pane, catalog, multiview, theme, etc.) to use
screen/within/fireEvent/waitFor instead of manual querySelector and
dispatchEvent. Pure-logic test files (matcher, tree, activity, paths,
reconnect, keys, webgl, paneTitle, commands, daemonLink, events, layout,
persistence, previewSchedule, projectList, spawnSimilar, structuredDiff,
toolIcon, fastForward, spawnForm) are untouched, and preview.test.ts
needed no changes.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-09 02:06:31 +01:00

128 lines
4.2 KiB
TypeScript

// @vitest-environment happy-dom
import { afterEach, beforeEach, describe, expect, it } from "vitest";
import { fireEvent, screen } from "@testing-library/react";
import { defineCommands, keyCaps, publishCommands, publishedCommands } from "./commands.js";
import { closeHelp, groupedCommands, installHelpKeybind, isHelpOpen, openHelp } from "./help.js";
beforeEach(() => {
installHelpKeybind();
});
afterEach(() => {
closeHelp();
document.body.replaceChildren();
});
function press(key: string, init: KeyboardEventInit = {}): void {
fireEvent.keyDown(window, { key, ...init });
}
function overlay(): HTMLElement {
return screen.getByRole("dialog", { name: "Keyboard shortcuts" });
}
function rows(root: HTMLElement): string[] {
return [...root.querySelectorAll(".help-row")].map((r) =>
[...r.querySelectorAll("kbd")].map((k) => k.textContent).join(" "),
);
}
describe("help overlay", () => {
it("renders exactly the commands the registry has bound, grouped", () => {
openHelp();
const dialog = overlay();
const groups = groupedCommands();
expect([...dialog.querySelectorAll(".help-group-title")].map((h) => h.textContent)).toEqual(
groups.map((g) => g.title),
);
expect(rows(dialog)).toEqual(groups.flatMap((g) => g.items.map((c) => keyCaps(c.keys[0]).join(" "))));
expect([...dialog.querySelectorAll(".help-desc")].map((d) => d.textContent)).toEqual(
groups.flatMap((g) => g.items.map((c) => c.label)),
);
});
it("names each row by its command id, so a row can't drift from its command", () => {
openHelp();
const dialog = overlay();
expect(
[...dialog.querySelectorAll<HTMLElement>(".help-row")].map((r) => r.dataset.commandId),
).toEqual(publishedCommands().map((c) => c.id));
});
// #159: the leader comes from the daemon, so the overlay must render the
// configured chord — a hardcoded `Ctrl A` is the visible half of the bug.
it("renders the configured leader's chord, not a hardcoded Ctrl A", () => {
const bound = defineCommands(
{ "pane.literalCtrlK": () => {}, "pane.literalLeader": () => {} },
"ctrl-b",
);
publishCommands(bound);
try {
openHelp();
const dialog = overlay();
const keysOf = (id: string) =>
[...dialog.querySelectorAll(`.help-row[data-command-id="${id}"] kbd`)]
.map((k) => k.textContent)
.join(" ");
expect(keysOf("pane.literalCtrlK")).toBe("Ctrl B then Ctrl K");
expect(keysOf("pane.literalLeader")).toBe("Ctrl B then Ctrl B");
} finally {
// Leave the registry as the rest of the suite expects it.
publishCommands(
defineCommands({ "pane.literalCtrlK": () => {}, "pane.literalLeader": () => {} }),
);
}
});
it("opens on ? and closes on a second ?", () => {
press("?", { shiftKey: true });
expect(isHelpOpen()).toBe(true);
press("?", { shiftKey: true });
expect(isHelpOpen()).toBe(false);
});
it("closes on Escape, on the close button, and on a click outside the panel", () => {
openHelp();
press("Escape");
expect(isHelpOpen()).toBe(false);
openHelp();
fireEvent.click(screen.getByRole("button", { name: "Close" }));
expect(isHelpOpen()).toBe(false);
openHelp();
fireEvent.click(overlay());
expect(isHelpOpen()).toBe(false);
});
it("stays open for a click inside the panel", () => {
openHelp();
fireEvent.click(screen.getByRole("heading", { name: "Keyboard shortcuts", level: 2 }));
expect(isHelpOpen()).toBe(true);
});
it("opening twice leaves one overlay", () => {
openHelp();
openHelp();
expect(screen.getAllByRole("dialog")).toHaveLength(1);
});
it("ignores ? while typing and when a non-shift modifier is held", () => {
const input = document.createElement("input");
document.body.appendChild(input);
fireEvent.keyDown(input, { key: "?", shiftKey: true });
expect(isHelpOpen()).toBe(false);
press("?", { ctrlKey: true });
expect(isHelpOpen()).toBe(false);
});
it("installing the keybind twice still toggles once", () => {
installHelpKeybind();
press("?", { shiftKey: true });
expect(isHelpOpen()).toBe(true);
expect(screen.getAllByRole("dialog")).toHaveLength(1);
});
});