Implements AlertDialog with compound component pattern (Root, Content, Title, Description, Trigger, Cancel, Action, Portal, Overlay). Content uses role=alertdialog, aria-modal, aria-labelledby/describedby, focus trap, and scroll lock. Does not dismiss on Escape key. 8 tests passing.
109 lines
3.6 KiB
TypeScript
109 lines
3.6 KiB
TypeScript
// packages/core/tests/components/alert-dialog/alert-dialog.test.tsx
|
|
import { fireEvent, render, screen } from "@solidjs/testing-library";
|
|
import { describe, expect, it } from "vitest";
|
|
import { AlertDialog } from "../../../src/components/alert-dialog/index";
|
|
|
|
describe("AlertDialog", () => {
|
|
it("content has role=alertdialog", () => {
|
|
render(() => (
|
|
<AlertDialog defaultOpen>
|
|
<AlertDialog.Content>
|
|
<AlertDialog.Title>Confirm</AlertDialog.Title>
|
|
<AlertDialog.Description>Are you sure?</AlertDialog.Description>
|
|
</AlertDialog.Content>
|
|
</AlertDialog>
|
|
));
|
|
expect(screen.getByRole("alertdialog")).toBeTruthy();
|
|
});
|
|
|
|
it("content has aria-modal=true", () => {
|
|
render(() => (
|
|
<AlertDialog defaultOpen>
|
|
<AlertDialog.Content>
|
|
<AlertDialog.Title>Confirm</AlertDialog.Title>
|
|
</AlertDialog.Content>
|
|
</AlertDialog>
|
|
));
|
|
expect(screen.getByRole("alertdialog").getAttribute("aria-modal")).toBe("true");
|
|
});
|
|
|
|
it("content is linked to title via aria-labelledby", () => {
|
|
render(() => (
|
|
<AlertDialog defaultOpen>
|
|
<AlertDialog.Content>
|
|
<AlertDialog.Title>Delete file?</AlertDialog.Title>
|
|
</AlertDialog.Content>
|
|
</AlertDialog>
|
|
));
|
|
const dialog = screen.getByRole("alertdialog");
|
|
const title = screen.getByText("Delete file?");
|
|
expect(dialog.getAttribute("aria-labelledby")).toBe(title.id);
|
|
});
|
|
|
|
it("content is linked to description via aria-describedby", () => {
|
|
render(() => (
|
|
<AlertDialog defaultOpen>
|
|
<AlertDialog.Content>
|
|
<AlertDialog.Title>Confirm</AlertDialog.Title>
|
|
<AlertDialog.Description>This cannot be undone.</AlertDialog.Description>
|
|
</AlertDialog.Content>
|
|
</AlertDialog>
|
|
));
|
|
const dialog = screen.getByRole("alertdialog");
|
|
const desc = screen.getByText("This cannot be undone.");
|
|
expect(dialog.getAttribute("aria-describedby")).toBe(desc.id);
|
|
});
|
|
|
|
it("trigger opens the dialog", () => {
|
|
render(() => (
|
|
<AlertDialog>
|
|
<AlertDialog.Trigger>Delete</AlertDialog.Trigger>
|
|
<AlertDialog.Content>
|
|
<AlertDialog.Title>Confirm</AlertDialog.Title>
|
|
</AlertDialog.Content>
|
|
</AlertDialog>
|
|
));
|
|
expect(screen.queryByRole("alertdialog")).toBeNull();
|
|
fireEvent.click(screen.getByText("Delete"));
|
|
expect(screen.getByRole("alertdialog")).toBeTruthy();
|
|
});
|
|
|
|
it("Cancel button closes the dialog", () => {
|
|
render(() => (
|
|
<AlertDialog defaultOpen>
|
|
<AlertDialog.Content>
|
|
<AlertDialog.Title>Confirm</AlertDialog.Title>
|
|
<AlertDialog.Cancel>Cancel</AlertDialog.Cancel>
|
|
</AlertDialog.Content>
|
|
</AlertDialog>
|
|
));
|
|
fireEvent.click(screen.getByText("Cancel"));
|
|
expect(screen.queryByRole("alertdialog")).toBeNull();
|
|
});
|
|
|
|
it("Action button closes the dialog", () => {
|
|
render(() => (
|
|
<AlertDialog defaultOpen>
|
|
<AlertDialog.Content>
|
|
<AlertDialog.Title>Are you sure?</AlertDialog.Title>
|
|
<AlertDialog.Action>Confirm</AlertDialog.Action>
|
|
</AlertDialog.Content>
|
|
</AlertDialog>
|
|
));
|
|
fireEvent.click(screen.getByText("Confirm"));
|
|
expect(screen.queryByRole("alertdialog")).toBeNull();
|
|
});
|
|
|
|
it("Escape key does NOT close alert dialog", () => {
|
|
render(() => (
|
|
<AlertDialog defaultOpen>
|
|
<AlertDialog.Content>
|
|
<AlertDialog.Title>Confirm</AlertDialog.Title>
|
|
</AlertDialog.Content>
|
|
</AlertDialog>
|
|
));
|
|
fireEvent.keyDown(document, { key: "Escape" });
|
|
expect(screen.getByRole("alertdialog")).toBeTruthy();
|
|
});
|
|
});
|