Right-clicking a card opens a custom context menu (rename, spawn similar, kill). Rename swaps the name for an inline field; Enter commits, Escape and blur cancel. The tree stops rebuilding while the field is open, so a catalog delta cannot replace what is being typed into. Refs #125 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
59 lines
2.3 KiB
TypeScript
59 lines
2.3 KiB
TypeScript
// @vitest-environment happy-dom
|
|
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
|
|
import { closeContextMenu, openContextMenu } from "./contextMenu.js";
|
|
|
|
afterEach(() => {
|
|
closeContextMenu();
|
|
document.body.replaceChildren();
|
|
});
|
|
|
|
function labels(): string[] {
|
|
return [...document.querySelectorAll(".context-menu-item")].map((b) => b.textContent ?? "");
|
|
}
|
|
|
|
describe("context menu (#125)", () => {
|
|
it("renders one item per entry, in order", () => {
|
|
openContextMenu(10, 20, [
|
|
{ label: "Rename…", onSelect: () => {} },
|
|
{ label: "Kill session", onSelect: () => {}, danger: true },
|
|
]);
|
|
expect(labels()).toEqual(["Rename…", "Kill session"]);
|
|
expect(document.querySelector(".context-menu-item.is-danger")?.textContent).toBe(
|
|
"Kill session",
|
|
);
|
|
});
|
|
|
|
it("runs the selected entry and closes", () => {
|
|
const chosen = vi.fn();
|
|
openContextMenu(0, 0, [{ label: "Rename…", onSelect: chosen }]);
|
|
(document.querySelector(".context-menu-item") as HTMLButtonElement).click();
|
|
expect(chosen).toHaveBeenCalledOnce();
|
|
expect(document.querySelector(".context-menu")).toBeNull();
|
|
});
|
|
|
|
it("opening a second menu replaces the first", () => {
|
|
openContextMenu(0, 0, [{ label: "first", onSelect: () => {} }]);
|
|
openContextMenu(0, 0, [{ label: "second", onSelect: () => {} }]);
|
|
expect(document.querySelectorAll(".context-menu")).toHaveLength(1);
|
|
expect(labels()).toEqual(["second"]);
|
|
});
|
|
|
|
it("closes on Escape and on a press outside it", () => {
|
|
openContextMenu(0, 0, [{ label: "Rename…", onSelect: () => {} }]);
|
|
window.dispatchEvent(new KeyboardEvent("keydown", { key: "Escape" }));
|
|
expect(document.querySelector(".context-menu")).toBeNull();
|
|
|
|
openContextMenu(0, 0, [{ label: "Rename…", onSelect: () => {} }]);
|
|
document.body.dispatchEvent(new Event("pointerdown", { bubbles: true }));
|
|
expect(document.querySelector(".context-menu")).toBeNull();
|
|
});
|
|
|
|
it("stays open for a press inside itself", () => {
|
|
openContextMenu(0, 0, [{ label: "Rename…", onSelect: () => {} }]);
|
|
const menu = document.querySelector(".context-menu") as HTMLElement;
|
|
menu.dispatchEvent(new Event("pointerdown", { bubbles: true }));
|
|
expect(document.querySelector(".context-menu")).not.toBeNull();
|
|
});
|
|
});
|