import React from "react";
import { Button } from "./index";
import { beforeEach, describe, expect, it, jest } from "@jest/globals";
import "@testing-library/jest-dom/jest-globals";
import { fireEvent, render, screen } from "@testing-library/react";
jest.mock("@shared/components/brand-button", () => ({
BrandButton: ({
as,
href,
text,
label,
iconName,
iconSize,
iconFill,
onClick,
id,
variant,
fullWidth,
size,
buttonClassName,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
...rest
}: any) => {
const Tag = as || "button";
return (
{label} {text}
);
},
}));
jest.mock("@shared/components/button", () => ({
// eslint-disable-next-line @typescript-eslint/no-unused-vars
Button: ({ onClick, className, children, ...rest }: any) => (
),
}));
jest.mock("@shared/components/link", () => ({
Link: ({
children,
href,
target,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
variant,
className,
title,
onClick,
}: any) => (
{children}
),
}));
jest.mock("@shared/components/material-icon", () => ({
MaterialIcon: ({ name, size, fill }: any) => (
),
}));
jest.mock("@shared/utils/utm", () => ({
buildPreservedQueryHref: (href: string, search: string) => `${href}${search}`,
}));
describe("Button", () => {
beforeEach(() => {
jest.clearAllMocks();
});
describe("showButtonAs='solid' (default)", () => {
it("renders BrandButton as anchor when href is provided", () => {
render();
const btn = screen.getByTestId("brand-button");
expect(btn.tagName).toBe("A");
expect(btn).toHaveAttribute("href", "/page");
expect(btn).toHaveTextContent("Click");
});
it("renders BrandButton as button when href is not provided", () => {
render();
const btn = screen.getByTestId("brand-button");
expect(btn.tagName).toBe("BUTTON");
});
it("passes variant, anchorId, fullWidth, size, buttonClassName", () => {
render(
);
const btn = screen.getByTestId("brand-button");
expect(btn).toHaveAttribute("data-variant", "secondary");
expect(btn).toHaveAttribute("id", "test-id");
expect(btn).toHaveAttribute("data-full-width", "true");
expect(btn).toHaveAttribute("data-size", "lg");
expect(btn).toHaveClass("custom");
});
it("passes buttonPrefix as label", () => {
render();
expect(screen.getByTestId("brand-button")).toHaveTextContent(
"Prefix Main"
);
});
});
describe("showButtonAs='text'", () => {
it("renders Link with buttonLabel and target", () => {
render(
);
const link = screen.getByTestId("link");
expect(link).toHaveAttribute("href", "/info");
expect(link).toHaveAttribute("target", "_self");
expect(link).toHaveAttribute("title", "Learn more");
});
it("applies linkClassName and linkVariant", () => {
render(
);
const link = screen.getByTestId("link");
expect(link.className).toContain("extra");
});
it("renders MaterialIcon when buttonIconName is provided", () => {
render(
);
const icon = screen.getByTestId("material-icon");
expect(icon).toHaveAttribute("data-name", "arrow_forward");
expect(icon).toHaveAttribute("data-size", "20");
expect(icon).toHaveAttribute("data-fill", "1");
});
it("does not render MaterialIcon when buttonIconName is absent", () => {
render(
);
expect(screen.queryByTestId("material-icon")).not.toBeInTheDocument();
});
it("does not render MaterialIcon when iconName is not provided", () => {
render();
expect(screen.queryByTestId("material-icon")).not.toBeInTheDocument();
});
it("renders buttonIconName icon before label when buttonIconPosition is left", () => {
render(
);
const link = screen.getByTestId("link");
const icon = screen.getByTestId("material-icon");
expect(icon).toBeInTheDocument();
expect(link.firstElementChild).toBe(icon);
});
it("renders buttonIconName icon after label by default", () => {
render(
);
const link = screen.getByTestId("link");
const icon = screen.getByTestId("material-icon");
expect(icon).toBeInTheDocument();
expect(link.lastElementChild).toBe(icon);
expect(link.className).toContain("no-underline");
expect(link.className).toContain("inline-flex");
});
});
describe("buttonIconName behavior", () => {
it("renders solid CTA icon before label when buttonIconPosition is left", () => {
render(
);
const link = screen.getByRole("link", { name: /see jobs/i });
expect(link).toHaveAttribute("data-icon-name", "expand_circle_right");
expect(link).toHaveAttribute("data-icon-size", "20");
expect(link).toHaveAttribute("data-icon-fill", "1");
expect(link).toHaveClass("flex-row-reverse");
});
it("renders solid CTA icon after label when buttonIconPosition is right", () => {
render(
);
const link = screen.getByRole("link", { name: /see jobs/i });
expect(link).toHaveAttribute("data-icon-name", "expand_circle_right");
expect(link).not.toHaveClass("flex-row-reverse");
});
it("passes through non-standard variant values", () => {
render(
);
const button = screen.getByTestId("brand-button");
expect(button).toHaveAttribute("data-variant", "primary_navy");
});
});
describe("showButtonAs='unstyled'", () => {
it("renders CoreButton", () => {
render();
expect(screen.getByTestId("core-button")).toBeInTheDocument();
});
});
describe("showButtonAs default case", () => {
it("renders CoreButton for unknown showButtonAs value", () => {
render();
expect(screen.getByTestId("core-button")).toBeInTheDocument();
});
});
describe("preDefinedFunctionExecution", () => {
it("renders checkPlans when preDefinedFunctionExecution is 'check availability'", () => {
const renderCheckPlans = jest.fn(() => (
Plans
));
render(
);
expect(screen.getByTestId("check-plans")).toBeInTheDocument();
expect(renderCheckPlans).toHaveBeenCalledWith(
expect.objectContaining({ ctaText: "Check" })
);
});
it("falls back to normal CTA when renderCheckPlans is not provided", () => {
render();
expect(screen.getByTestId("brand-button")).toBeInTheDocument();
});
});
describe("onClick and modal handling", () => {
it("calls onClick on solid button click (no href)", () => {
const onClick = jest.fn();
render();
fireEvent.click(screen.getByTestId("brand-button"));
expect(onClick).toHaveBeenCalled();
});
it("calls onClick on solid link click (with href)", () => {
const onClick = jest.fn();
render();
fireEvent.click(screen.getByTestId("brand-button"));
expect(onClick).toHaveBeenCalled();
});
it("calls onClick on text link click", () => {
const onClick = jest.fn();
render();
fireEvent.click(screen.getByTestId("link"));
expect(onClick).toHaveBeenCalled();
});
it("calls onModalButtonClick when clickToOpen is 'modal'", () => {
const onModalButtonClick = jest.fn();
render(
);
fireEvent.click(screen.getByTestId("brand-button"));
expect(onModalButtonClick).toHaveBeenCalledWith("my-modal");
});
it("does not call onModalButtonClick when clickToOpen is not 'modal'", () => {
const onModalButtonClick = jest.fn();
render(
);
fireEvent.click(screen.getByTestId("brand-button"));
expect(onModalButtonClick).not.toHaveBeenCalled();
});
it("calls onModalButtonClick on text link click when clickToOpen is 'modal'", () => {
const onModalButtonClick = jest.fn();
render(
);
fireEvent.click(screen.getByTestId("link"));
expect(onModalButtonClick).toHaveBeenCalledWith("tab1");
});
it("prevents anchor navigation and opens modal when href is present and clickToOpen is 'modal'", () => {
const onModalButtonClick = jest.fn();
render(
);
// fireEvent.click returns false when a handler called preventDefault().
const notCancelled = fireEvent.click(screen.getByTestId("brand-button"));
expect(notCancelled).toBe(false);
expect(onModalButtonClick).toHaveBeenCalledWith("my-modal");
});
it("prevents anchor navigation when href is present and clickToOpen is 'clickId'", () => {
const scrollIntoView = jest.fn();
const targetEl = document.createElement("div");
targetEl.scrollIntoView = scrollIntoView;
const getElementByIdSpy = jest
.spyOn(document, "getElementById")
.mockReturnValue(targetEl);
render(
);
const notCancelled = fireEvent.click(screen.getByTestId("brand-button"));
expect(notCancelled).toBe(false);
expect(scrollIntoView).toHaveBeenCalled();
getElementByIdSpy.mockRestore();
});
it("does not prevent anchor navigation for a normal href link", () => {
const onModalButtonClick = jest.fn();
render(
);
const notCancelled = fireEvent.click(screen.getByTestId("brand-button"));
expect(notCancelled).toBe(true);
expect(onModalButtonClick).not.toHaveBeenCalled();
});
});
describe("preserveQueryParameters", () => {
it("uses buildPreservedQueryHref when preserveQueryParameters is true and search exists", () => {
Object.defineProperty(window, "location", {
value: { search: "?foo=bar" },
writable: true,
});
render(
);
expect(screen.getByTestId("brand-button")).toHaveAttribute(
"href",
"/page?foo=bar"
);
});
it("uses original href when preserveQueryParameters is false", () => {
Object.defineProperty(window, "location", {
value: { search: "?foo=bar" },
writable: true,
});
render();
expect(screen.getByTestId("brand-button")).toHaveAttribute(
"href",
"/page"
);
});
it("uses original href when search is empty", () => {
Object.defineProperty(window, "location", {
value: { search: "" },
writable: true,
});
render(
);
expect(screen.getByTestId("brand-button")).toHaveAttribute(
"href",
"/page"
);
});
});
});