import { act, fireEvent, render, screen } from "@testing-library/react"; import { describe, expect, it, vi } from "vitest"; import { Sheet, SheetContent, SheetDescription, SheetPageContent, SheetHeader, SheetTitle, } from "@/components/ui/sheet"; function renderSheet(props: { dismissOnOutsideClick?: boolean } = {}) { const onOpenChange = vi.fn(); render( <> Drawer body , ); return { onOpenChange }; } /** Radix 在下一帧才开始听外部 pointerdown:先让它挂上,再点遮罩外面 */ async function clickOutside() { await act(async () => { await new Promise((resolve) => setTimeout(resolve, 0)); }); await act(async () => { const target = screen.getByRole("button", { name: "outside", hidden: true, }); fireEvent.pointerDown(target, { button: 0, pointerType: "mouse" }); fireEvent.click(target); }); } describe("SheetContent", () => { it("ignores clicks on the overlay by default so drafts aren't lost", async () => { const { onOpenChange } = renderSheet(); await clickOutside(); expect(onOpenChange).not.toHaveBeenCalled(); expect(screen.getByRole("dialog")).toBeInTheDocument(); }); it("closes on an outside click only when the drawer opts in", async () => { const { onOpenChange } = renderSheet({ dismissOnOutsideClick: true }); await clickOutside(); expect(onOpenChange).toHaveBeenCalledWith(false); }); it("page mode renders a page header whose back button closes the sheet", () => { const onOpenChange = vi.fn(); render( body , ); expect( screen.getByRole("dialog", { name: "Edit prompt" }), ).toBeInTheDocument(); fireEvent.click(screen.getByRole("button", { name: "back" })); expect(onOpenChange).toHaveBeenCalledWith(false); }); it("non-modal page mode leaves the rest of the window interactive", () => { const onOpenChange = vi.fn(); const onOutside = vi.fn(); render( <> body , ); expect(document.body.style.pointerEvents).not.toBe("none"); fireEvent.pointerDown(screen.getByRole("button", { name: "sidebar" })); fireEvent.click(screen.getByRole("button", { name: "sidebar" })); expect(onOutside).toHaveBeenCalled(); expect(onOpenChange).not.toHaveBeenCalled(); }); });