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");
});
});
});