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>
This commit is contained in:
Miguel Palhas
2026-09-09 02:06:31 +01:00
co-authored by Claude Sonnet 5
parent 8304ef9a49
commit c9562ab5eb
27 changed files with 894 additions and 846 deletions
+14 -14
View File
@@ -1,5 +1,7 @@
// @vitest-environment happy-dom
import { afterEach, describe, expect, it, vi } from "vitest";
import { fireEvent, screen } from "@testing-library/react";
import "@testing-library/jest-dom/vitest";
import { closeContextMenu, openContextMenu } from "./contextMenu.js";
@@ -9,7 +11,7 @@ afterEach(() => {
});
function labels(): string[] {
return [...document.querySelectorAll(".context-menu-item")].map((b) => b.textContent ?? "");
return screen.getAllByRole("menuitem").map((b) => b.textContent ?? "");
}
describe("context menu (#125)", () => {
@@ -19,40 +21,38 @@ describe("context menu (#125)", () => {
{ label: "Kill session", onSelect: () => {}, danger: true },
]);
expect(labels()).toEqual(["Rename…", "Kill session"]);
expect(document.querySelector(".context-menu-item.is-danger")?.textContent).toBe(
"Kill session",
);
expect(screen.getByRole("menuitem", { name: "Kill session" })).toHaveClass("is-danger");
});
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();
fireEvent.click(screen.getByRole("menuitem", { name: "Rename…" }));
expect(chosen).toHaveBeenCalledOnce();
expect(document.querySelector(".context-menu")).toBeNull();
expect(screen.queryByRole("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(screen.getAllByRole("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();
fireEvent.keyDown(window, { key: "Escape" });
expect(screen.queryByRole("menu")).toBeNull();
openContextMenu(0, 0, [{ label: "Rename…", onSelect: () => {} }]);
document.body.dispatchEvent(new Event("pointerdown", { bubbles: true }));
expect(document.querySelector(".context-menu")).toBeNull();
fireEvent.pointerDown(document.body);
expect(screen.queryByRole("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();
const menu = screen.getByRole("menu");
fireEvent.pointerDown(menu);
expect(screen.queryByRole("menu")).not.toBeNull();
});
});