Implements headless Collapsible with Root, Trigger, and Content parts. Supports controlled/uncontrolled open state, disabled state, and full ARIA attributes (aria-expanded, aria-controls, hidden).
93 lines
3.3 KiB
TypeScript
93 lines
3.3 KiB
TypeScript
import { fireEvent, render, screen } from "@solidjs/testing-library";
|
|
import { describe, expect, it } from "vitest";
|
|
import { Collapsible } from "../../../src/components/collapsible/index";
|
|
|
|
describe("Collapsible", () => {
|
|
it("content is hidden by default", () => {
|
|
render(() => (
|
|
<Collapsible>
|
|
<Collapsible.Trigger>Toggle</Collapsible.Trigger>
|
|
<Collapsible.Content data-testid="content">Hidden</Collapsible.Content>
|
|
</Collapsible>
|
|
));
|
|
expect(screen.getByTestId("content")).toHaveAttribute("hidden");
|
|
});
|
|
|
|
it("content is shown when defaultOpen=true", () => {
|
|
render(() => (
|
|
<Collapsible defaultOpen>
|
|
<Collapsible.Trigger>Toggle</Collapsible.Trigger>
|
|
<Collapsible.Content data-testid="content">Visible</Collapsible.Content>
|
|
</Collapsible>
|
|
));
|
|
expect(screen.getByTestId("content")).not.toHaveAttribute("hidden");
|
|
});
|
|
|
|
it("trigger click opens content", () => {
|
|
render(() => (
|
|
<Collapsible>
|
|
<Collapsible.Trigger>Toggle</Collapsible.Trigger>
|
|
<Collapsible.Content data-testid="content">Content</Collapsible.Content>
|
|
</Collapsible>
|
|
));
|
|
fireEvent.click(screen.getByRole("button"));
|
|
expect(screen.getByTestId("content")).not.toHaveAttribute("hidden");
|
|
});
|
|
|
|
it("trigger click closes open content", () => {
|
|
render(() => (
|
|
<Collapsible defaultOpen>
|
|
<Collapsible.Trigger>Toggle</Collapsible.Trigger>
|
|
<Collapsible.Content data-testid="content">Content</Collapsible.Content>
|
|
</Collapsible>
|
|
));
|
|
fireEvent.click(screen.getByRole("button"));
|
|
expect(screen.getByTestId("content")).toHaveAttribute("hidden");
|
|
});
|
|
|
|
it("trigger has aria-expanded reflecting open state", () => {
|
|
render(() => (
|
|
<Collapsible>
|
|
<Collapsible.Trigger>Toggle</Collapsible.Trigger>
|
|
<Collapsible.Content>Content</Collapsible.Content>
|
|
</Collapsible>
|
|
));
|
|
expect(screen.getByRole("button").getAttribute("aria-expanded")).toBe("false");
|
|
fireEvent.click(screen.getByRole("button"));
|
|
expect(screen.getByRole("button").getAttribute("aria-expanded")).toBe("true");
|
|
});
|
|
|
|
it("trigger aria-controls matches content id", () => {
|
|
render(() => (
|
|
<Collapsible>
|
|
<Collapsible.Trigger>Toggle</Collapsible.Trigger>
|
|
<Collapsible.Content data-testid="content">Content</Collapsible.Content>
|
|
</Collapsible>
|
|
));
|
|
const trigger = screen.getByRole("button");
|
|
const content = screen.getByTestId("content");
|
|
expect(trigger.getAttribute("aria-controls")).toBe(content.id);
|
|
});
|
|
|
|
it("disabled trigger does not toggle", () => {
|
|
render(() => (
|
|
<Collapsible disabled>
|
|
<Collapsible.Trigger>Toggle</Collapsible.Trigger>
|
|
<Collapsible.Content data-testid="content">Content</Collapsible.Content>
|
|
</Collapsible>
|
|
));
|
|
fireEvent.click(screen.getByRole("button"));
|
|
expect(screen.getByTestId("content")).toHaveAttribute("hidden");
|
|
});
|
|
|
|
it("controlled open state", () => {
|
|
render(() => (
|
|
<Collapsible open={true} onOpenChange={() => {}}>
|
|
<Collapsible.Trigger>Toggle</Collapsible.Trigger>
|
|
<Collapsible.Content data-testid="content">Content</Collapsible.Content>
|
|
</Collapsible>
|
|
));
|
|
expect(screen.getByTestId("content")).not.toHaveAttribute("hidden");
|
|
});
|
|
});
|