///
import React from "react";
import { CallButton } from "./index";
import { render, screen } from "@testing-library/react";
// Mock dependencies
/* eslint-disable react/prop-types */
jest.mock("@shared/components/link", () => ({
Link: ({
children,
className,
href,
...props
}: React.AnchorHTMLAttributes & {
children: React.ReactNode;
}) => (
{children}
),
}));
/* eslint-enable react/prop-types */
jest.mock("@shared/components/material-icon", () => ({
MaterialIcon: ({ name, className }: { name: string; className?: string }) => (
{name}
),
}));
jest.mock("@shared/utils", () => ({
cx: (...args: unknown[]) => args.filter(Boolean).join(" "),
}));
describe("CallButton", () => {
describe("rendering", () => {
it("renders children text content", () => {
render(Call Us);
expect(screen.getByText("Call Us")).toBeInTheDocument();
});
it("renders the call icon", () => {
render(Call);
expect(screen.getByTestId("material-icon-call")).toBeInTheDocument();
});
it("renders an anchor element via Link", () => {
render(Call);
const link = screen.getByRole("link");
expect(link).toHaveAttribute("href", "tel:+1234567890");
});
it("applies displayName correctly", () => {
expect(CallButton.displayName).toBe("CallButton");
});
});
describe("size variants", () => {
it("applies sm size classes", () => {
render(
Call
);
const link = screen.getByRole("link");
expect(link.className).toContain("h-6");
expect(link.className).toContain("text-xs");
});
it("applies md size classes by default", () => {
render(Call);
const link = screen.getByRole("link");
expect(link.className).toContain("h-8");
expect(link.className).toContain("text-sm");
});
it("applies lg size classes", () => {
render(
Call
);
const link = screen.getByRole("link");
expect(link.className).toContain("h-10");
expect(link.className).toContain("text-base");
});
});
describe("buttonStyle variants", () => {
it("applies primary style classes by default", () => {
render(Call);
const link = screen.getByRole("link");
expect(link.className).toContain("border-border");
expect(link.className).toContain("text-text");
});
it("applies primary style classes when explicitly set", () => {
render(
Call
);
const link = screen.getByRole("link");
expect(link.className).toContain("border-border");
});
});
describe("blinking dot", () => {
it("does not render blinking dot by default", () => {
const { container } = render(
Call
);
const dot = container.querySelector(".animate-blink");
expect(dot).not.toBeInTheDocument();
});
it("renders blinking dot when showBlinkDot is true", () => {
const { container } = render(
Call
);
const dot = container.querySelector(".animate-blink");
expect(dot).toBeInTheDocument();
});
it("applies correct dot size for sm", () => {
const { container } = render(
Call
);
const dot = container.querySelector(".animate-blink");
expect(dot).toHaveClass("h-2", "w-2");
});
it("applies correct dot size for md", () => {
const { container } = render(
Call
);
const dot = container.querySelector(".animate-blink");
expect(dot).toHaveClass("h-3", "w-3");
});
it("applies correct dot size for lg", () => {
const { container } = render(
Call
);
const dot = container.querySelector(".animate-blink");
expect(dot).toHaveClass("h-4", "w-4");
});
});
describe("prefix", () => {
it("renders without prefix wrapper when prefix is null", () => {
const { container } = render(
Call
);
// Should not have the outer wrapper span
const wrapper = container.querySelector("span.flex.items-center.gap-2");
expect(wrapper).not.toBeInTheDocument();
});
it("renders without prefix wrapper when prefix is false", () => {
const { container } = render(
Call
);
const wrapper = container.querySelector("span.flex.items-center.gap-2");
expect(wrapper).not.toBeInTheDocument();
});
it("renders without prefix wrapper when prefix is empty string", () => {
const { container } = render(
Call
);
const wrapper = container.querySelector("span.flex.items-center.gap-2");
expect(wrapper).not.toBeInTheDocument();
});
it("renders string prefix in a span", () => {
render(
555-1234
);
expect(screen.getByText("Call now:")).toBeInTheDocument();
});
it("renders numeric prefix in a span", () => {
render(
Call
);
expect(screen.getByText("42")).toBeInTheDocument();
});
it("renders ReactNode prefix directly", () => {
render(
Custom}
>
Call
);
expect(screen.getByTestId("custom-prefix")).toBeInTheDocument();
});
it("applies containerClassName to the outer wrapper", () => {
const { container } = render(
Call
);
const wrapper = container.firstChild as HTMLElement;
expect(wrapper.className).toContain("my-container");
});
});
describe("custom className", () => {
it("applies custom className to the link", () => {
render(
Call
);
const link = screen.getByRole("link");
expect(link.className).toContain("custom-class");
});
});
describe("accessibility", () => {
it("passes aria attributes to the link", () => {
render(
Call
);
const link = screen.getByRole("link");
expect(link).toHaveAttribute("aria-label", "Call support");
});
});
});