From 2971d32f4559867b761c59e86d20c4d37fca62fb Mon Sep 17 00:00:00 2001 From: Lukas Date: Sun, 29 Mar 2026 03:26:57 +0200 Subject: [PATCH] Add action-bar tests for overflow menu, dialogs, and custom stats Tests browse mode toggle, export/import dialog opening, overflow menu callbacks (manage players, settings), and custom stat field submission. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../components/__tests__/action-bar.test.tsx | 67 +++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/apps/web/src/components/__tests__/action-bar.test.tsx b/apps/web/src/components/__tests__/action-bar.test.tsx index bbb7e6b..ae9e1b5 100644 --- a/apps/web/src/components/__tests__/action-bar.test.tsx +++ b/apps/web/src/components/__tests__/action-bar.test.tsx @@ -50,6 +50,16 @@ beforeAll(() => { dispatchEvent: vi.fn(), })), }); + HTMLDialogElement.prototype.showModal = + HTMLDialogElement.prototype.showModal || + function showModal(this: HTMLDialogElement) { + this.setAttribute("open", ""); + }; + HTMLDialogElement.prototype.close = + HTMLDialogElement.prototype.close || + function close(this: HTMLDialogElement) { + this.removeAttribute("open"); + }; }); afterEach(cleanup); @@ -118,4 +128,61 @@ describe("ActionBar", () => { screen.getByRole("button", { name: "More actions" }), ).toBeInTheDocument(); }); + + it("opens export method dialog via overflow menu", async () => { + const user = userEvent.setup(); + renderBar(); + await user.click(screen.getByRole("button", { name: "More actions" })); + // Click the menu item + const items = screen.getAllByText("Export Encounter"); + await user.click(items[0]); + // Dialog should now be open — it renders a second "Export Encounter" as heading + expect( + screen.getAllByText("Export Encounter").length, + ).toBeGreaterThanOrEqual(1); + }); + + it("opens import method dialog via overflow menu", async () => { + const user = userEvent.setup(); + renderBar(); + await user.click(screen.getByRole("button", { name: "More actions" })); + const items = screen.getAllByText("Import Encounter"); + await user.click(items[0]); + expect( + screen.getAllByText("Import Encounter").length, + ).toBeGreaterThanOrEqual(1); + }); + + it("calls onManagePlayers from overflow menu", async () => { + const onManagePlayers = vi.fn(); + const user = userEvent.setup(); + renderBar({ onManagePlayers }); + await user.click(screen.getByRole("button", { name: "More actions" })); + await user.click(screen.getByText("Player Characters")); + expect(onManagePlayers).toHaveBeenCalledOnce(); + }); + + it("calls onOpenSettings from overflow menu", async () => { + const onOpenSettings = vi.fn(); + const user = userEvent.setup(); + renderBar({ onOpenSettings }); + await user.click(screen.getByRole("button", { name: "More actions" })); + await user.click(screen.getByText("Settings")); + expect(onOpenSettings).toHaveBeenCalledOnce(); + }); + + it("submits custom stats with combatant", async () => { + const user = userEvent.setup(); + renderBar(); + const input = screen.getByPlaceholderText("+ Add combatants"); + await user.type(input, "Fighter"); + const initInput = screen.getByPlaceholderText("Init"); + const acInput = screen.getByPlaceholderText("AC"); + const hpInput = screen.getByPlaceholderText("MaxHP"); + await user.type(initInput, "15"); + await user.type(acInput, "18"); + await user.type(hpInput, "45"); + await user.click(screen.getByRole("button", { name: "Add" })); + expect(input).toHaveValue(""); + }); });