Mats Bosson c2422d2da0 RadioGroup component
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.
2026-03-29 07:50:21 +07:00

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");
});
});