Files
suaveplan/packages/ui/react/react-ui/src/components/toggle/toggle.test.tsx
2026-05-27 23:47:53 +01:00

155 lines
5.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { TranslationProvider } from "@suaveplan/react-i18n";
import { describe, expect, it } from "@suaveplan/testing/runner";
import { renderComponent } from "@suaveplan/testing-dom";
import { createRef, useState } from "react";
import { createTestI18n } from "../../../tests/setup/test-i18n.js";
import { ThemeProvider } from "../../theme/theme-provider/theme-provider.js";
import { lightTheme } from "../../theme/themes/light.js";
import { Toggle } from "./toggle.js";
import { toggleVariants } from "./toggle.variants.js";
async function withProviders(
node: React.ReactElement
): Promise<React.ReactElement> {
const i18n = await createTestI18n({ locale: "en-GB" });
return (
<TranslationProvider i18n={i18n}>
<ThemeProvider themes={[lightTheme]} defaultTheme="light">
{node}
</ThemeProvider>
</TranslationProvider>
);
}
describe("<Toggle>", () => {
it("renders a button with default classes", { timeout: 5000 }, async () => {
const tree = await withProviders(<Toggle aria-label="bold">B</Toggle>);
const { getByRole } = renderComponent(tree);
const t = getByRole("button");
expect(t.tagName).toBe("BUTTON");
expect(t.className).toContain("rounded-md");
});
it("forwards refs to the radix root", { timeout: 5000 }, async () => {
const ref = createRef<HTMLButtonElement>();
const tree = await withProviders(
<Toggle ref={ref} aria-label="ref">
R
</Toggle>
);
renderComponent(tree);
expect(ref.current).not.toBeNull();
expect(ref.current?.tagName).toBe("BUTTON");
});
it("toggles pressed state when clicked (controlled)", {
timeout: 5000,
}, async () => {
function Controlled(): React.ReactElement {
const [pressed, setPressed] = useState(false);
return (
<Toggle
aria-label="t"
pressed={pressed}
onPressedChange={setPressed}
>
T
</Toggle>
);
}
const tree = await withProviders(<Controlled />);
const { getByRole, user } = renderComponent(tree);
const t = getByRole("button");
expect(t.getAttribute("aria-pressed")).toBe("false");
await user.click(t);
expect(t.getAttribute("aria-pressed")).toBe("true");
});
it("activates via Enter key", { timeout: 5000 }, async () => {
let count = 0;
const tree = await withProviders(
<Toggle
aria-label="enter"
onPressedChange={() => {
count += 1;
}}
>
E
</Toggle>
);
const { getByRole, user } = renderComponent(tree);
const t = getByRole("button");
t.focus();
await user.keyboard("[Enter]");
expect(count).toBe(1);
});
it("respects the disabled prop", { timeout: 5000 }, async () => {
let count = 0;
const tree = await withProviders(
<Toggle
aria-label="dis"
disabled
onPressedChange={() => {
count += 1;
}}
>
D
</Toggle>
);
const { getByRole, user } = renderComponent(tree);
const t = getByRole("button");
expect(t.hasAttribute("disabled")).toBe(true);
await user.click(t);
expect(count).toBe(0);
});
it("renders every variant × size combination from cva", {
timeout: 5000,
}, () => {
const variants = ["default", "outline"] as const;
const sizes = ["sm", "default", "lg"] as const;
for (const v of variants) {
for (const s of sizes) {
const cls = toggleVariants({ variant: v, size: s });
expect(typeof cls).toBe("string");
expect(cls.length).toBeGreaterThan(0);
}
}
});
it("applies the outline variant", { timeout: 5000 }, async () => {
const tree = await withProviders(
<Toggle aria-label="o" variant="outline">
O
</Toggle>
);
const { getByRole } = renderComponent(tree);
const t = getByRole("button");
expect(t.className).toContain("border");
expect(t.className).toContain("border-input");
});
it("merges custom className alongside variant classes", {
timeout: 5000,
}, async () => {
const tree = await withProviders(
<Toggle aria-label="cls" className="custom-extra-class">
C
</Toggle>
);
const { getByRole } = renderComponent(tree);
const t = getByRole("button");
expect(t.className).toContain("custom-extra-class");
expect(t.className).toContain("rounded-md");
});
it("exposes toggleVariants as a callable resolver", {
timeout: 5000,
}, () => {
const cls = toggleVariants({ variant: "default", size: "default" });
expect(typeof cls).toBe("string");
expect(cls.length).toBeGreaterThan(0);
});
});