feat: add core UI components and baseline tests

This commit is contained in:
2026-03-19 16:56:27 +08:00
parent 12642e0a92
commit 063179933c
73 changed files with 5756 additions and 2 deletions
@@ -0,0 +1,70 @@
import { useState } from "react";
import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { describe, expect, it, vi } from "vitest";
import { Switch } from "./switch";
describe("Switch", () => {
it("toggles by click and exposes slot/state hooks", async () => {
const user = userEvent.setup();
const onCheckedChange = vi.fn();
render(<Switch aria-label="Email alerts" onCheckedChange={onCheckedChange} />);
const control = screen.getByRole("switch", { name: "Email alerts" });
expect(control).toHaveAttribute("data-slot", "root");
expect(control).toHaveAttribute("data-state", "unchecked");
expect(control.querySelector('[data-slot="control"]')).not.toBeNull();
await user.click(control);
expect(control).toBeChecked();
expect(control).toHaveAttribute("data-state", "checked");
expect(onCheckedChange).toHaveBeenCalledWith(true);
});
it("supports controlled state updates", async () => {
const user = userEvent.setup();
function ControlledSwitch() {
const [checked, setChecked] = useState(false);
return <Switch aria-label="Controlled switch" checked={checked} onCheckedChange={setChecked} />;
}
render(<ControlledSwitch />);
const control = screen.getByRole("switch", { name: "Controlled switch" });
expect(control).not.toBeChecked();
await user.click(control);
expect(control).toBeChecked();
});
it("supports keyboard interaction and disabled/invalid states", async () => {
const user = userEvent.setup();
render(
<>
<Switch aria-label="Keyboard switch" />
<Switch aria-label="Disabled switch" disabled invalid />
</>
);
const keyboardSwitch = screen.getByRole("switch", { name: "Keyboard switch" });
const disabledSwitch = screen.getByRole("switch", { name: "Disabled switch" });
await user.tab();
expect(keyboardSwitch).toHaveFocus();
await user.keyboard(" ");
expect(keyboardSwitch).toBeChecked();
expect(disabledSwitch).toBeDisabled();
expect(disabledSwitch).toHaveAttribute("aria-invalid", "true");
expect(disabledSwitch).toHaveAttribute("data-disabled", "");
});
});