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