Add quick-win tests for components and hooks

Adds tests for DifficultyIndicator, Toast, RollModeMenu, OverflowMenu,
useTheme, and useRulesEdition. Covers rendering, user interactions,
auto-dismiss timers, external store sync, and localStorage persistence.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Lukas
2026-03-28 19:28:58 +01:00
parent d8c8a0c44d
commit a77db0eeee
7 changed files with 385 additions and 6 deletions

View File

@@ -0,0 +1,89 @@
// @vitest-environment jsdom
import { cleanup, render, screen } from "@testing-library/react";
import { userEvent } from "@testing-library/user-event";
import { Circle } from "lucide-react";
import { afterEach, describe, expect, it, vi } from "vitest";
import { OverflowMenu } from "../ui/overflow-menu.js";
afterEach(cleanup);
const items = [
{ icon: <Circle />, label: "Action A", onClick: vi.fn() },
{ icon: <Circle />, label: "Action B", onClick: vi.fn() },
];
describe("OverflowMenu", () => {
it("renders toggle button", () => {
render(<OverflowMenu items={items} />);
expect(screen.getByRole("button", { name: "More actions" })).toBeDefined();
});
it("does not show menu items when closed", () => {
render(<OverflowMenu items={items} />);
expect(screen.queryByText("Action A")).toBeNull();
});
it("shows menu items when toggled open", async () => {
render(<OverflowMenu items={items} />);
await userEvent.click(screen.getByRole("button", { name: "More actions" }));
expect(screen.getByText("Action A")).toBeDefined();
expect(screen.getByText("Action B")).toBeDefined();
});
it("closes menu after clicking an item", async () => {
const onClick = vi.fn();
render(
<OverflowMenu items={[{ icon: <Circle />, label: "Do it", onClick }]} />,
);
await userEvent.click(screen.getByRole("button", { name: "More actions" }));
await userEvent.click(screen.getByText("Do it"));
expect(onClick).toHaveBeenCalledOnce();
expect(screen.queryByText("Do it")).toBeNull();
});
it("keeps menu open when keepOpen is true", async () => {
const onClick = vi.fn();
render(
<OverflowMenu
items={[
{
icon: <Circle />,
label: "Stay",
onClick,
keepOpen: true,
},
]}
/>,
);
await userEvent.click(screen.getByRole("button", { name: "More actions" }));
await userEvent.click(screen.getByText("Stay"));
expect(onClick).toHaveBeenCalledOnce();
expect(screen.getByText("Stay")).toBeDefined();
});
it("disables items when disabled is true", async () => {
const onClick = vi.fn();
render(
<OverflowMenu
items={[
{
icon: <Circle />,
label: "Nope",
onClick,
disabled: true,
},
]}
/>,
);
await userEvent.click(screen.getByRole("button", { name: "More actions" }));
const item = screen.getByText("Nope");
expect(item.closest("button")?.hasAttribute("disabled")).toBe(true);
});
});