Implements headless RadioGroup with root + item sub-components, keyboard navigation (ArrowDown/Up/Left/Right), controlled/uncontrolled value via createControllableSignal, and disabled state. 8 tests passing.
91 lines
2.9 KiB
TypeScript
91 lines
2.9 KiB
TypeScript
import { fireEvent, render, screen } from "@solidjs/testing-library";
|
|
import { describe, expect, it } from "vitest";
|
|
import { RadioGroup } from "../../../src/components/radio-group/index";
|
|
|
|
describe("RadioGroup", () => {
|
|
it("renders with role=radiogroup", () => {
|
|
render(() => (
|
|
<RadioGroup>
|
|
<RadioGroup.Item value="a">A</RadioGroup.Item>
|
|
</RadioGroup>
|
|
));
|
|
expect(screen.getByRole("radiogroup")).toBeTruthy();
|
|
});
|
|
|
|
it("items have role=radio", () => {
|
|
render(() => (
|
|
<RadioGroup>
|
|
<RadioGroup.Item value="a">A</RadioGroup.Item>
|
|
<RadioGroup.Item value="b">B</RadioGroup.Item>
|
|
</RadioGroup>
|
|
));
|
|
expect(screen.getAllByRole("radio")).toHaveLength(2);
|
|
});
|
|
|
|
it("no item is checked by default", () => {
|
|
render(() => (
|
|
<RadioGroup>
|
|
<RadioGroup.Item value="a">A</RadioGroup.Item>
|
|
</RadioGroup>
|
|
));
|
|
expect(screen.getByRole("radio").getAttribute("aria-checked")).toBe("false");
|
|
});
|
|
|
|
it("defaultValue pre-selects item", () => {
|
|
render(() => (
|
|
<RadioGroup defaultValue="b">
|
|
<RadioGroup.Item value="a">A</RadioGroup.Item>
|
|
<RadioGroup.Item value="b">B</RadioGroup.Item>
|
|
</RadioGroup>
|
|
));
|
|
const radios = screen.getAllByRole("radio");
|
|
expect(radios[0].getAttribute("aria-checked")).toBe("false");
|
|
expect(radios[1].getAttribute("aria-checked")).toBe("true");
|
|
});
|
|
|
|
it("clicking an item selects it", () => {
|
|
render(() => (
|
|
<RadioGroup>
|
|
<RadioGroup.Item value="a">A</RadioGroup.Item>
|
|
<RadioGroup.Item value="b">B</RadioGroup.Item>
|
|
</RadioGroup>
|
|
));
|
|
fireEvent.click(screen.getAllByRole("radio")[0]);
|
|
expect(screen.getAllByRole("radio")[0].getAttribute("aria-checked")).toBe("true");
|
|
expect(screen.getAllByRole("radio")[1].getAttribute("aria-checked")).toBe("false");
|
|
});
|
|
|
|
it("clicking a selected item keeps it selected", () => {
|
|
render(() => (
|
|
<RadioGroup defaultValue="a">
|
|
<RadioGroup.Item value="a">A</RadioGroup.Item>
|
|
</RadioGroup>
|
|
));
|
|
fireEvent.click(screen.getByRole("radio"));
|
|
expect(screen.getByRole("radio").getAttribute("aria-checked")).toBe("true");
|
|
});
|
|
|
|
it("ArrowDown moves to next radio", () => {
|
|
render(() => (
|
|
<RadioGroup>
|
|
<RadioGroup.Item value="a">A</RadioGroup.Item>
|
|
<RadioGroup.Item value="b">B</RadioGroup.Item>
|
|
</RadioGroup>
|
|
));
|
|
const [first] = screen.getAllByRole("radio");
|
|
first.focus();
|
|
fireEvent.keyDown(first, { key: "ArrowDown" });
|
|
expect(document.activeElement).toBe(screen.getAllByRole("radio")[1]);
|
|
});
|
|
|
|
it("disabled item is not selectable", () => {
|
|
render(() => (
|
|
<RadioGroup>
|
|
<RadioGroup.Item value="a" disabled>A</RadioGroup.Item>
|
|
</RadioGroup>
|
|
));
|
|
fireEvent.click(screen.getByRole("radio"));
|
|
expect(screen.getByRole("radio").getAttribute("aria-checked")).toBe("false");
|
|
});
|
|
});
|