import React from "react"; import { BrandButton } from "./index"; import { fireEvent, render, screen } from "@testing-library/react"; import "@testing-library/jest-dom"; describe("BrandButton", () => { describe("Rendering", () => { it("renders as a button by default", () => { render(); expect(screen.getByRole("button")).toBeInTheDocument(); expect(screen.getByRole("button")).toHaveTextContent("Click me"); }); it("renders as an anchor when as='a'", () => { render(); const link = screen.getByRole("link"); expect(link).toBeInTheDocument(); expect(link).toHaveAttribute("href", "/test"); expect(link).toHaveTextContent("Link"); }); it("has correct displayName", () => { expect(BrandButton.displayName).toBe("BrandButton"); }); it("renders text prop content", () => { render(); expect(screen.getByText("Submit")).toBeInTheDocument(); }); }); describe("Variants", () => { it("applies primary_brand variant classes by default", () => { render(); const btn = screen.getByRole("button"); expect(btn.className).toContain("button--primary_brand"); }); it("applies primary_inverse variant classes", () => { render(); const btn = screen.getByRole("button"); expect(btn.className).toContain("button--primary_inverse"); }); it("applies secondary variant classes", () => { render(); const btn = screen.getByRole("button"); expect(btn.className).toContain("button--secondary"); }); }); describe("Loading state", () => { it("shows spinner icon when isLoading is true", () => { render(); expect(screen.getByText("progress_activity")).toBeInTheDocument(); }); it("disables button when isLoading is true", () => { render(); expect(screen.getByRole("button")).toBeDisabled(); }); it("adds loading class when isLoading", () => { render(); const btn = screen.getByRole("button"); expect(btn.className).toContain("button--loading"); }); it("does not show spinner when isLoading is false", () => { render(); expect(screen.queryByText("progress_activity")).not.toBeInTheDocument(); }); }); describe("Disabled state", () => { it("disables button when disabled prop is true", () => { render(); expect(screen.getByRole("button")).toBeDisabled(); }); it("adds disabled class when disabled", () => { render(); const btn = screen.getByRole("button"); expect(btn.className).toContain("button--disabled"); }); it("applies cursor-not-allowed when disabled", () => { render(); const btn = screen.getByRole("button"); expect(btn.className).toContain("cursor-not-allowed"); }); }); describe("Label prop", () => { it("renders label and text when label is provided", () => { render(); expect(screen.getByText("Starting at")).toBeInTheDocument(); expect(screen.getByText("$49/mo")).toBeInTheDocument(); }); it("wraps label in a span with size class", () => { const { container } = render(); const labelSpan = container.querySelector("span span"); expect(labelSpan).toHaveTextContent("Label"); }); }); describe("Size prop", () => { it("applies base size class", () => { render(); const btn = screen.getByRole("button"); expect(btn.className).toContain("btn-small"); }); it("applies medium size by default", () => { render(); const btn = screen.getByRole("button"); expect(btn.className).toContain("btn-medium"); }); it("applies responsive md size class for small", () => { render(); const btn = screen.getByRole("button"); expect(btn.className).toContain("md:btn-small"); }); it("applies responsive md size class for medium", () => { render( ); const btn = screen.getByRole("button"); expect(btn.className).toContain("md:btn-medium"); }); it("applies responsive md size class for large", () => { render(); const btn = screen.getByRole("button"); expect(btn.className).toContain("md:btn-large"); }); it("applies responsive md size class for x-large", () => { render( ); const btn = screen.getByRole("button"); expect(btn.className).toContain("md:btn-x-large"); }); it("applies responsive lg size class", () => { render( ); const btn = screen.getByRole("button"); expect(btn.className).toContain("lg:btn-x-large"); }); it("applies x-large label size with label3 class", () => { const { container } = render( ); const labelSpan = container.querySelector("span span"); expect(labelSpan?.className).toContain("label3"); }); it("applies non-x-large label size with label4 class", () => { const { container } = render( ); const labelSpan = container.querySelector("span span"); expect(labelSpan?.className).toContain("label4"); }); it("applies md label3 for x-large md size", () => { const { container } = render( ); const labelSpan = container.querySelector("span span"); expect(labelSpan?.className).toContain("md:label3"); }); it("applies md label4 for non-x-large md size", () => { const { container } = render( ); const labelSpan = container.querySelector("span span"); expect(labelSpan?.className).toContain("md:label4"); }); it("applies lg label3 for x-large lg size", () => { const { container } = render( ); const labelSpan = container.querySelector("span span"); expect(labelSpan?.className).toContain("lg:label3"); }); it("applies lg label4 for non-x-large lg size", () => { const { container } = render( ); const labelSpan = container.querySelector("span span"); expect(labelSpan?.className).toContain("lg:label4"); }); }); describe("fullWidth", () => { it("applies w-full when fullWidth is true", () => { render(); const btn = screen.getByRole("button"); expect(btn.className).toContain("w-full"); }); it("applies w-auto when fullWidth is false", () => { render(); const btn = screen.getByRole("button"); expect(btn.className).toContain("w-auto"); }); }); describe("buttonClassName", () => { it("applies custom buttonClassName", () => { render(); const btn = screen.getByRole("button"); expect(btn.className).toContain("my-custom-class"); }); }); describe("Ref forwarding", () => { it("forwards ref to button element", () => { const ref = React.createRef(); render(); expect(ref.current).toBeInstanceOf(HTMLButtonElement); }); it("forwards ref to anchor element", () => { const ref = React.createRef(); render(); expect(ref.current).toBeInstanceOf(HTMLAnchorElement); }); }); describe("Event handling", () => { it("calls onClick handler when clicked", () => { const onClick = jest.fn(); render(); fireEvent.click(screen.getByRole("button")); expect(onClick).toHaveBeenCalledTimes(1); }); it("does not call onClick when disabled", () => { const onClick = jest.fn(); render(); fireEvent.click(screen.getByRole("button")); expect(onClick).not.toHaveBeenCalled(); }); }); describe("Anchor props", () => { it("passes anchor-specific props when as='a'", () => { render( ); const link = screen.getByRole("link"); expect(link).toHaveAttribute("target", "_blank"); expect(link).toHaveAttribute("rel", "noopener"); }); }); });