import React from "react"; import { render, screen } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; import { Button } from "../Button"; describe("Button", () => { // Basic rendering tests describe("Rendering", () => { it("renders button with children", () => { render(); expect( screen.getByRole("button", { name: "Click me" }) ).toBeInTheDocument(); }); it("renders with custom className", () => { render(); const button = screen.getByRole("button"); expect(button).toHaveClass("custom-class"); }); it("renders with different variants", () => { const { rerender } = render(); let button = screen.getByRole("button"); expect(button).toHaveClass("bg-primary"); rerender(); button = screen.getByRole("button"); expect(button).toHaveClass("bg-secondary"); rerender(); button = screen.getByRole("button"); expect(button).toHaveClass("border-input"); rerender(); button = screen.getByRole("button"); expect(button).toHaveClass("hover:bg-accent"); rerender(); button = screen.getByRole("button"); expect(button).toHaveClass("bg-destructive"); }); it("renders with different sizes", () => { const { rerender } = render(); let button = screen.getByRole("button"); expect(button).toHaveClass("h-9"); rerender(); button = screen.getByRole("button"); expect(button).toHaveClass("h-10"); rerender(); button = screen.getByRole("button"); expect(button).toHaveClass("h-11"); }); }); // Props tests describe("Props", () => { it("handles disabled state", () => { render(); const button = screen.getByRole("button"); expect(button).toBeDisabled(); expect(button).toHaveClass("disabled:opacity-50"); }); it("handles loading state", () => { render(); const button = screen.getByRole("button"); expect(button).toBeDisabled(); expect(screen.getByRole("status")).toBeInTheDocument(); }); it("renders with fullWidth", () => { render(); const button = screen.getByRole("button"); expect(button).toHaveClass("w-full"); }); it("renders with leftIcon", () => { const icon = ; render(); expect(screen.getByTestId("left-icon")).toBeInTheDocument(); }); it("renders with rightIcon", () => { const icon = ; render(); expect(screen.getByTestId("right-icon")).toBeInTheDocument(); }); it("renders with both icons", () => { const leftIcon = ; const rightIcon = ; render( ); expect(screen.getByTestId("left-icon")).toBeInTheDocument(); expect(screen.getByTestId("right-icon")).toBeInTheDocument(); }); }); // Accessibility tests describe("Accessibility", () => { it("supports aria-label", () => { render(); const button = screen.getByRole("button"); expect(button).toHaveAttribute("aria-label", "Custom label"); }); it("supports aria-describedby", () => { render(); const button = screen.getByRole("button"); expect(button).toHaveAttribute("aria-describedby", "description"); }); it("supports aria-expanded", () => { render(); const button = screen.getByRole("button"); expect(button).toHaveAttribute("aria-expanded", "true"); }); it("supports aria-pressed", () => { render(); const button = screen.getByRole("button"); expect(button).toHaveAttribute("aria-pressed", "true"); }); it("has proper focus management", async () => { const user = userEvent.setup(); render(); const button = screen.getByRole("button"); await user.tab(); expect(button).toHaveFocus(); }); it("announces loading state to screen readers", () => { render(); const loadingIndicator = screen.getByRole("status"); expect(loadingIndicator).toHaveAttribute("aria-label", "Loading"); }); }); // Interaction tests describe("Interactions", () => { it("calls onClick when clicked", async () => { const handleClick = jest.fn(); const user = userEvent.setup(); render(); await user.click(screen.getByRole("button")); expect(handleClick).toHaveBeenCalledTimes(1); }); it("does not call onClick when disabled", async () => { const handleClick = jest.fn(); const user = userEvent.setup(); render( ); await user.click(screen.getByRole("button")); expect(handleClick).not.toHaveBeenCalled(); }); it("does not call onClick when loading", async () => { const handleClick = jest.fn(); const user = userEvent.setup(); render( ); await user.click(screen.getByRole("button")); expect(handleClick).not.toHaveBeenCalled(); }); it("supports keyboard navigation (Enter)", async () => { const handleClick = jest.fn(); const user = userEvent.setup(); render(); const button = screen.getByRole("button"); button.focus(); await user.keyboard("{Enter}"); expect(handleClick).toHaveBeenCalledTimes(1); }); it("supports keyboard navigation (Space)", async () => { const handleClick = jest.fn(); const user = userEvent.setup(); render(); const button = screen.getByRole("button"); button.focus(); await user.keyboard(" "); expect(handleClick).toHaveBeenCalledTimes(1); }); }); // Button type tests describe("Button types", () => { it("renders as submit button", () => { render(); const button = screen.getByRole("button"); expect(button).toHaveAttribute("type", "submit"); }); it("renders as reset button", () => { render(); const button = screen.getByRole("button"); expect(button).toHaveAttribute("type", "reset"); }); it("defaults to button type", () => { render(); const button = screen.getByRole("button"); expect(button).toHaveAttribute("type", "button"); }); }); // Edge cases describe("Edge cases", () => { it("handles empty children", () => { render(); const button = screen.getByRole("button"); expect(button).toHaveClass("class1", "class2"); }); it("forwards ref correctly", () => { const ref = React.createRef(); render(); expect(ref.current).toBeInstanceOf(HTMLButtonElement); }); }); });