Files
community-rule/tests/unit/Button.test.jsx
T
2025-08-30 13:46:35 -06:00

113 lines
3.9 KiB
React

import { render, screen, cleanup } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { vi, describe, test, expect, afterEach } from "vitest";
import Button from "../../app/components/Button";
afterEach(() => {
cleanup();
});
describe("Button Component", () => {
test("renders button with children", () => {
render(<Button>Click me</Button>);
const button = screen.getByRole("button", { name: "Click me" });
expect(button).toBeInTheDocument();
});
test("handles click events", async () => {
const user = userEvent.setup();
const onClick = vi.fn();
render(<Button onClick={onClick}>Click me</Button>);
const button = screen.getByRole("button", { name: "Click me" });
await user.click(button);
expect(onClick).toHaveBeenCalledTimes(1);
});
test("renders as link when href is provided", () => {
render(<Button href="/test">Link Button</Button>);
const link = screen.getByRole("link", { name: "Link Button" });
expect(link).toBeInTheDocument();
expect(link).toHaveAttribute("href", "/test");
});
test("applies different variants", () => {
const { rerender } = render(<Button variant="default">Default</Button>);
let button = screen.getByRole("button", { name: "Default" });
expect(button.className).toContain(
"bg-[var(--color-surface-inverse-primary)]",
);
rerender(<Button variant="secondary">Secondary</Button>);
button = screen.getByRole("button", { name: "Secondary" });
expect(button.className).toContain("bg-transparent");
});
test("applies different sizes", () => {
const { rerender } = render(<Button size="xsmall">Small</Button>);
let button = screen.getByRole("button", { name: "Small" });
expect(button.className).toContain("px-[var(--spacing-scale-006)]");
rerender(<Button size="large">Large</Button>);
button = screen.getByRole("button", { name: "Large" });
expect(button.className).toContain("px-[var(--spacing-scale-012)]");
});
test("handles disabled state", () => {
render(<Button disabled>Disabled</Button>);
const button = screen.getByRole("button", { name: "Disabled" });
expect(button).toBeDisabled();
expect(button).toHaveAttribute("aria-disabled", "true");
expect(button).toHaveAttribute("tabindex", "-1");
});
test("applies custom className", () => {
render(<Button className="custom-class">Custom</Button>);
const button = screen.getByRole("button", { name: "Custom" });
expect(button.className).toContain("custom-class");
});
test("applies aria-label for accessibility", () => {
render(<Button aria-label="Custom label">Button</Button>);
const button = screen.getByRole("button", { name: "Custom label" });
expect(button).toHaveAttribute("aria-label", "Custom label");
});
test("renders with design tokens", () => {
render(<Button>Token Test</Button>);
const button = screen.getByRole("button", { name: "Token Test" });
// Check that design tokens are applied
expect(button.className).toContain(
"rounded-[var(--radius-measures-radius-full)]",
);
expect(button.className).toContain(
"bg-[var(--color-surface-inverse-primary)]",
);
});
test("handles keyboard navigation", async () => {
const user = userEvent.setup();
const onClick = vi.fn();
render(<Button onClick={onClick}>Keyboard</Button>);
const button = screen.getByRole("button", { name: "Keyboard" });
button.focus();
expect(button).toHaveFocus();
await user.keyboard("{Enter}");
expect(onClick).toHaveBeenCalledTimes(1);
});
test("does not render as link when disabled and href provided", () => {
render(
<Button href="/test" disabled>
Disabled Link
</Button>,
);
const button = screen.getByRole("button", { name: "Disabled Link" });
expect(button).toBeInTheDocument();
expect(button).toBeDisabled();
});
});