134 lines
4.0 KiB
TypeScript
134 lines
4.0 KiB
TypeScript
import { render, screen, waitFor, within } from "@testing-library/react";
|
|
import userEvent from "@testing-library/user-event";
|
|
import { describe, expect, it, vi } from "vitest";
|
|
|
|
import {
|
|
Dialog,
|
|
DialogClose,
|
|
DialogContent,
|
|
DialogDescription,
|
|
DialogFooter,
|
|
DialogHeader,
|
|
DialogTitle,
|
|
DialogTrigger
|
|
} from "./dialog";
|
|
|
|
describe("Dialog", () => {
|
|
it("opens from the trigger and closes from the close control", async () => {
|
|
const user = userEvent.setup();
|
|
|
|
render(
|
|
<Dialog>
|
|
<DialogTrigger>Open dialog</DialogTrigger>
|
|
<DialogContent size="lg">
|
|
<DialogHeader>
|
|
<DialogTitle>Review launch</DialogTitle>
|
|
<DialogDescription>Check the launch checklist before shipping.</DialogDescription>
|
|
</DialogHeader>
|
|
<DialogFooter>
|
|
<DialogClose>Done</DialogClose>
|
|
</DialogFooter>
|
|
</DialogContent>
|
|
</Dialog>
|
|
);
|
|
|
|
expect(screen.queryByRole("dialog")).not.toBeInTheDocument();
|
|
|
|
await user.click(screen.getByRole("button", { name: "Open dialog" }));
|
|
|
|
const dialog = await screen.findByRole("dialog");
|
|
expect(dialog).toHaveAttribute("data-slot", "content");
|
|
expect(dialog).toHaveAttribute("data-size", "lg");
|
|
expect(screen.getByText("Review launch")).toHaveAttribute("data-slot", "label");
|
|
expect(screen.getByText("Check the launch checklist before shipping.")).toHaveAttribute(
|
|
"data-slot",
|
|
"description"
|
|
);
|
|
expect(document.querySelector('[data-slot="overlay"]')).toBeInTheDocument();
|
|
|
|
await user.click(screen.getByRole("button", { name: "Close dialog" }));
|
|
|
|
await waitFor(() => {
|
|
expect(screen.queryByRole("dialog")).not.toBeInTheDocument();
|
|
});
|
|
});
|
|
|
|
it("notifies controlled open state changes from trigger and Escape", async () => {
|
|
const user = userEvent.setup();
|
|
const onOpenChange = vi.fn();
|
|
|
|
render(
|
|
<Dialog open={false} onOpenChange={onOpenChange}>
|
|
<DialogTrigger>Launch dialog</DialogTrigger>
|
|
<DialogContent>
|
|
<DialogTitle>Controlled</DialogTitle>
|
|
</DialogContent>
|
|
</Dialog>
|
|
);
|
|
|
|
await user.click(screen.getByRole("button", { name: "Launch dialog" }));
|
|
expect(onOpenChange).toHaveBeenCalledWith(true);
|
|
|
|
render(
|
|
<Dialog open onOpenChange={onOpenChange}>
|
|
<DialogTrigger>Launch dialog</DialogTrigger>
|
|
<DialogContent>
|
|
<DialogTitle>Controlled</DialogTitle>
|
|
</DialogContent>
|
|
</Dialog>
|
|
);
|
|
|
|
await user.keyboard("{Escape}");
|
|
expect(onOpenChange).toHaveBeenCalledWith(false);
|
|
});
|
|
|
|
it("renders header and footer slots when provided", async () => {
|
|
const user = userEvent.setup();
|
|
|
|
render(
|
|
<Dialog>
|
|
<DialogTrigger>Open summary</DialogTrigger>
|
|
<DialogContent>
|
|
<DialogHeader>
|
|
<DialogTitle>Summary</DialogTitle>
|
|
</DialogHeader>
|
|
<DialogFooter>
|
|
<DialogClose>Close</DialogClose>
|
|
</DialogFooter>
|
|
</DialogContent>
|
|
</Dialog>
|
|
);
|
|
|
|
await user.click(screen.getByRole("button", { name: "Open summary" }));
|
|
|
|
const dialog = await screen.findByRole("dialog");
|
|
expect(within(dialog).getByText("Summary").closest('[data-slot="header"]')).toBeInTheDocument();
|
|
expect(within(dialog).getByRole("button", { name: "Close" }).closest('[data-slot="footer"]')).toBeInTheDocument();
|
|
});
|
|
|
|
it("returns focus to the trigger after Escape closes the dialog", async () => {
|
|
const user = userEvent.setup();
|
|
|
|
render(
|
|
<Dialog>
|
|
<DialogTrigger>Open accessible dialog</DialogTrigger>
|
|
<DialogContent>
|
|
<DialogTitle>Accessibility</DialogTitle>
|
|
</DialogContent>
|
|
</Dialog>
|
|
);
|
|
|
|
const trigger = screen.getByRole("button", { name: "Open accessible dialog" });
|
|
|
|
await user.click(trigger);
|
|
expect(await screen.findByRole("dialog")).toBeInTheDocument();
|
|
|
|
await user.keyboard("{Escape}");
|
|
|
|
await waitFor(() => {
|
|
expect(screen.queryByRole("dialog")).not.toBeInTheDocument();
|
|
expect(trigger).toHaveFocus();
|
|
});
|
|
});
|
|
});
|