import React, { useState } from "react"; import { describe, it, expect, vi, beforeEach } from "vitest"; import { screen, fireEvent } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; import "@testing-library/jest-dom/vitest"; import { renderWithProviders } from "../utils/test-utils"; import Dialog from "../../app/components/modals/Dialog"; type Props = React.ComponentProps; const dialogCopy = { title: "Confirm action", description: "This cannot be undone.", }; function DialogOpenHarness() { const [open, setOpen] = useState(false); return ( <> setOpen(false)} title={dialogCopy.title} description={dialogCopy.description} footer={ } /> ); } function DialogFromMenuHarness() { const [menuOpen, setMenuOpen] = useState(false); const [dialogOpen, setDialogOpen] = useState(false); const menuId = "dialog-focus-restore-menu"; return ( <> {menuOpen ? ( ) : null} setDialogOpen(false)} title={dialogCopy.title} description={dialogCopy.description} footer={ } /> ); } describe("Dialog", () => { const defaultProps: Props = { isOpen: true, onClose: vi.fn(), title: "Confirm action", description: "This cannot be undone.", footer: ( <> ), }; beforeEach(() => { vi.clearAllMocks(); }); it("renders when isOpen is true", () => { renderWithProviders(); expect(screen.getByRole("dialog")).toBeInTheDocument(); expect(screen.getByText("Confirm action")).toBeInTheDocument(); expect(screen.getByText("This cannot be undone.")).toBeInTheDocument(); expect(screen.getByText("Cancel")).toBeInTheDocument(); expect(screen.getByText("Confirm")).toBeInTheDocument(); }); it("does not render when isOpen is false", () => { renderWithProviders(); expect(screen.queryByRole("dialog")).not.toBeInTheDocument(); }); it("calls onClose when close control is activated", () => { const onClose = vi.fn(); renderWithProviders(); fireEvent.click(screen.getByLabelText("Close dialog")); expect(onClose).toHaveBeenCalledTimes(1); }); it("calls onClose when Escape is pressed", () => { const onClose = vi.fn(); renderWithProviders(); fireEvent.keyDown(document, { key: "Escape" }); expect(onClose).toHaveBeenCalledTimes(1); }); it("locks body scroll when open", () => { renderWithProviders(); expect(document.body.style.overflow).toBe("hidden"); }); it("restores focus to the control that opened it", async () => { const user = userEvent.setup(); renderWithProviders(); const trigger = screen.getByRole("button", { name: "Open dialog" }); await user.click(trigger); expect(screen.getByRole("dialog")).toBeInTheDocument(); await user.keyboard("{Escape}"); expect(screen.queryByRole("dialog")).not.toBeInTheDocument(); expect(trigger).toHaveFocus(); }); it("restores focus to the opener when the opening click did not focus it", () => { renderWithProviders(); const trigger = screen.getByRole("button", { name: "Open dialog" }); fireEvent.pointerDown(trigger); fireEvent.click(trigger); expect(screen.getByRole("dialog")).toBeInTheDocument(); fireEvent.keyDown(document, { key: "Escape" }); expect(screen.queryByRole("dialog")).not.toBeInTheDocument(); expect(trigger).toHaveFocus(); }); it("restores focus to the menu trigger when a menu item opened the dialog", async () => { const user = userEvent.setup(); renderWithProviders(); const menuTrigger = screen.getByRole("button", { name: "More options" }); await user.click(menuTrigger); await user.click(screen.getByRole("menuitem", { name: "Remove" })); expect(screen.getByRole("dialog")).toBeInTheDocument(); expect( screen.queryByRole("menuitem", { name: "Remove" }), ).not.toBeInTheDocument(); await user.keyboard("{Escape}"); expect(screen.queryByRole("dialog")).not.toBeInTheDocument(); expect(menuTrigger).toHaveFocus(); }); });