// @vitest-environment happy-dom import { cleanup, fireEvent, render, screen } from "@testing-library/react"; import { afterEach, describe, expect, it, vi } from "vitest"; import { ContextMenu } from "./ContextMenu.js"; afterEach(() => { cleanup(); }); function labels(): string[] { return [...document.querySelectorAll(".context-menu-item")].map((b) => b.textContent ?? ""); } describe("ContextMenu (#125)", () => { it("renders one item per entry, in order", () => { render( {} }, { label: "Kill session", onSelect: () => {}, danger: true }, ]} onClose={vi.fn()} />, ); 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(); const onClose = vi.fn(); render(); fireEvent.click(screen.getByRole("menuitem")); expect(chosen).toHaveBeenCalledOnce(); expect(onClose).toHaveBeenCalledOnce(); }); it("closes on Escape and on a press outside it", () => { const onClose = vi.fn(); render( {} }]} onClose={onClose} />); fireEvent.keyDown(document, { key: "Escape" }); expect(onClose).toHaveBeenCalledTimes(1); fireEvent(document.body, new Event("pointerdown", { bubbles: true })); expect(onClose).toHaveBeenCalledTimes(2); }); it("stays open for a press inside itself", () => { const onClose = vi.fn(); render( {} }]} onClose={onClose} />); const menu = document.querySelector(".context-menu") as HTMLElement; fireEvent(menu, new Event("pointerdown", { bubbles: true })); expect(onClose).not.toHaveBeenCalled(); }); it("closes on scroll and on resize", () => { const onClose = vi.fn(); render( {} }]} onClose={onClose} />); fireEvent.scroll(window); expect(onClose).toHaveBeenCalledTimes(1); fireEvent.resize(window); expect(onClose).toHaveBeenCalledTimes(2); }); });