Headless TextField with Label, Input, Description, and ErrorMessage parts. Supports invalid, disabled, and required states with full ARIA wiring (aria-invalid, aria-required, aria-describedby, aria-errormessage). 7 tests passing.
79 lines
2.3 KiB
TypeScript
79 lines
2.3 KiB
TypeScript
// packages/core/tests/components/text-field/text-field.test.tsx
|
|
import { render, screen } from "@solidjs/testing-library";
|
|
import { describe, expect, it } from "vitest";
|
|
import { TextField } from "../../../src/components/text-field/index";
|
|
|
|
describe("TextField", () => {
|
|
it("label is linked to input via htmlFor/id", () => {
|
|
render(() => (
|
|
<TextField>
|
|
<TextField.Label>Name</TextField.Label>
|
|
<TextField.Input />
|
|
</TextField>
|
|
));
|
|
const label = screen.getByText("Name");
|
|
const input = screen.getByRole("textbox");
|
|
expect(label.getAttribute("for")).toBe(input.id);
|
|
});
|
|
|
|
it("description is linked via aria-describedby", () => {
|
|
render(() => (
|
|
<TextField>
|
|
<TextField.Label>Name</TextField.Label>
|
|
<TextField.Input />
|
|
<TextField.Description>Enter your full name</TextField.Description>
|
|
</TextField>
|
|
));
|
|
const input = screen.getByRole("textbox");
|
|
const desc = screen.getByText("Enter your full name");
|
|
expect(input.getAttribute("aria-describedby")).toBe(desc.id);
|
|
});
|
|
|
|
it("error message not shown when not invalid", () => {
|
|
render(() => (
|
|
<TextField>
|
|
<TextField.Input />
|
|
<TextField.ErrorMessage>Required</TextField.ErrorMessage>
|
|
</TextField>
|
|
));
|
|
expect(screen.queryByText("Required")).toBeNull();
|
|
});
|
|
|
|
it("error message shown when invalid=true", () => {
|
|
render(() => (
|
|
<TextField invalid>
|
|
<TextField.Input />
|
|
<TextField.ErrorMessage>Required</TextField.ErrorMessage>
|
|
</TextField>
|
|
));
|
|
expect(screen.getByText("Required")).toBeTruthy();
|
|
});
|
|
|
|
it("input has aria-invalid when invalid=true", () => {
|
|
render(() => (
|
|
<TextField invalid>
|
|
<TextField.Input />
|
|
</TextField>
|
|
));
|
|
expect(screen.getByRole("textbox").getAttribute("aria-invalid")).toBe("true");
|
|
});
|
|
|
|
it("input is disabled when disabled=true", () => {
|
|
render(() => (
|
|
<TextField disabled>
|
|
<TextField.Input />
|
|
</TextField>
|
|
));
|
|
expect(screen.getByRole("textbox")).toBeDisabled();
|
|
});
|
|
|
|
it("input has aria-required when required=true", () => {
|
|
render(() => (
|
|
<TextField required>
|
|
<TextField.Input />
|
|
</TextField>
|
|
));
|
|
expect(screen.getByRole("textbox").getAttribute("aria-required")).toBe("true");
|
|
});
|
|
});
|