import { render, screen } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; import { describe, it, expect, vi } from "vitest"; import { DialogField } from "./DialogField"; describe("DialogField - visibility", () => { it("returns null when showWhen is false", () => { const { container } = render(

Content

); expect(container.innerHTML).toBe(""); }); it("renders when showWhen is true (default)", () => { const { container } = render(

Content

); expect(container.innerHTML).not.toBe(""); }); }); describe("DialogField - content rendering", () => { it("renders title when open", () => { render(

Body

); expect(screen.getByText("My Dialog")).toBeInTheDocument(); }); it("renders description when open", () => { render(

Body

); expect(screen.getByText("Some description")).toBeInTheDocument(); }); it("renders children content when open", () => { render(

Dialog body content

); expect(screen.getByText("Dialog body content")).toBeInTheDocument(); }); it("does not render dialog content when closed", () => { render(

Hidden content

); expect(screen.queryByText("Hidden")).not.toBeInTheDocument(); expect(screen.queryByText("Hidden content")).not.toBeInTheDocument(); }); }); describe("DialogField - close button", () => { it("renders close button by default", () => { render(

Content

); expect(screen.getByRole("button", { name: "Close dialog" })).toBeInTheDocument(); }); it("hides close button when showCloseButton=false", () => { render(

Content

); expect(screen.queryByRole("button", { name: "Close dialog" })).not.toBeInTheDocument(); }); it("calls onOpenChange(false) when close button is clicked", async () => { const user = userEvent.setup(); const onOpenChange = vi.fn(); render(

Content

); await user.click(screen.getByRole("button", { name: "Close dialog" })); expect(onOpenChange).toHaveBeenCalledWith(false); }); it("calls onClose when close button is clicked", async () => { const user = userEvent.setup(); const onClose = vi.fn(); render(

Content

); await user.click(screen.getByRole("button", { name: "Close dialog" })); expect(onClose).toHaveBeenCalledTimes(1); }); }); describe("DialogField - trigger mode", () => { it("renders trigger element", () => { render( Open} title="T">

Content

); expect(screen.getByRole("button", { name: "Open" })).toBeInTheDocument(); }); it("opens dialog when trigger is clicked", async () => { const user = userEvent.setup(); render( Open} title="Triggered Dialog">

Dialog content

); expect(screen.queryByText("Triggered Dialog")).not.toBeInTheDocument(); await user.click(screen.getByRole("button", { name: "Open" })); expect(screen.getByText("Triggered Dialog")).toBeInTheDocument(); expect(screen.getByText("Dialog content")).toBeInTheDocument(); }); }); describe("DialogField - keyboard / outside click", () => { it("closes on Escape key by default", async () => { const user = userEvent.setup(); const onOpenChange = vi.fn(); render(

Content

); await user.keyboard("{Escape}"); expect(onOpenChange).toHaveBeenCalledWith(false); }); it("does not close on Escape when closeOnEscape=false", async () => { const user = userEvent.setup(); const onOpenChange = vi.fn(); render(

Content

); await user.keyboard("{Escape}"); expect(onOpenChange).not.toHaveBeenCalled(); }); }); describe("DialogField - width/height classes", () => { // Radix Dialog renders into a portal (document.body), not container const widthCases: Array<[string, string]> = [ ["NARROW", "max-w-sm"], ["MEDIUM", "max-w-md"], ["MEDIUM_PLUS", "max-w-lg"], ["WIDE", "max-w-2xl"], ]; widthCases.forEach(([width, expectedClass]) => { it(`width="${width}" applies ${expectedClass}`, () => { render(

Content

); const content = document.body.querySelector(`[class*="${expectedClass}"]`); expect(content).toBeInTheDocument(); }); }); const heightCases: Array<[string, string]> = [ ["SHORT", "h-[300px]"], ["MEDIUM", "h-[500px]"], ["TALL", "h-[700px]"], ]; heightCases.forEach(([height, expectedClass]) => { it(`height="${height}" applies ${expectedClass}`, () => { render(

Content

); expect(document.body.innerHTML).toContain(expectedClass); }); }); });