import React from "react"; import { ProductCard } from "./index"; import { fireEvent, render, screen } from "@testing-library/react"; jest.mock("@shared/components/button", () => ({ Button: ({ children, onClick, className }: any) => ( ), })); jest.mock("@shared/components/checklist", () => ({ Checklist: ({ items }: any) => ( ), })); jest.mock("@shared/components/image", () => ({ Image: ({ src, alt, width, height }: any) => ( {alt} ), })); jest.mock("@shared/components/material-icon", () => ({ MaterialIcon: ({ name, className }: any) => ( {name} ), })); jest.mock("@shared/components/select-plan-button", () => ({ SelectPlanButton: ({ onSelect, speed }: any) => ( ), })); jest.mock("@shared/components/text", () => ({ Text: ({ as: Tag = "span", children, className }: any) => ( {children} ), })); jest.mock("@shared/utils", () => ({ cx: (...args: any[]) => args.filter(Boolean).join(" "), })); describe("ProductCard", () => { const defaultProps = { planName: "Kinetic 500", planSubtext: "Up to 500 Mbps", speed: "500", price: "49.99", description: "Fast internet for your home", features: ["Wi-Fi included", "No data caps"], onCtaClick: jest.fn(), hostType: "residential" as const, }; beforeEach(() => { jest.clearAllMocks(); }); describe("Rendering", () => { it("renders the article element", () => { const { container } = render(); expect(container.querySelector("article")).toBeInTheDocument(); }); it("renders plan name", () => { render(); expect(screen.getByText("Kinetic 500")).toBeInTheDocument(); }); it("renders plan subtext", () => { render(); expect(screen.getByText("Up to 500 Mbps")).toBeInTheDocument(); }); it("renders price dollar sign", () => { render(); expect(screen.getByText("$")).toBeInTheDocument(); }); it("renders price whole number", () => { render(); expect(screen.getByText("49")).toBeInTheDocument(); }); it("renders price decimal and /mo", () => { render(); expect(screen.getByText("99/mo")).toBeInTheDocument(); }); it("renders description", () => { render(); expect( screen.getByText("Fast internet for your home") ).toBeInTheDocument(); }); }); describe("Best Value", () => { it("renders best value banner when bestValue is true", () => { render(); expect(screen.getByText("best value")).toBeInTheDocument(); }); it("renders custom best value text", () => { render( ); expect(screen.getByText("Top pick")).toBeInTheDocument(); }); it("does not render best value banner by default", () => { render(); expect(screen.queryByText("best value")).not.toBeInTheDocument(); }); }); describe("Theme", () => { it("applies light theme by default", () => { const { container } = render(); const card = container.querySelector("article > div"); expect(card?.className).toContain("bg-bg"); }); it("applies dark theme classes", () => { const { container } = render( ); const card = container.querySelector("article > div"); expect(card?.className).toContain("bg-bg-fill-inverse"); }); }); describe("Features", () => { it("renders features section when features are provided", () => { render(); expect(screen.getByTestId("checklist")).toBeInTheDocument(); }); it("does not render features section when features is empty", () => { render(); expect(screen.queryByTestId("checklist")).not.toBeInTheDocument(); }); it("renders features title", () => { render(); expect( screen.getByText("Business Ready Internet features") ).toBeInTheDocument(); }); it("renders custom features title", () => { render(); expect(screen.getByText("Custom features")).toBeInTheDocument(); }); }); describe("Expand/Collapse", () => { it("toggles internal expanded state on click", () => { const { container } = render(); const toggleBtn = screen.getByTestId("feature-toggle"); fireEvent.click(toggleBtn); // Check the features container shows opacity-100 const featuresDiv = container.querySelector(".opacity-100"); expect(featuresDiv).toBeInTheDocument(); }); it("uses controlled expanded state when provided", () => { const { container } = render( ); const featuresDiv = container.querySelector(".opacity-100"); expect(featuresDiv).toBeInTheDocument(); }); it("calls onToggleExpand when provided", () => { const onToggleExpand = jest.fn(); render(); fireEvent.click(screen.getByTestId("feature-toggle")); expect(onToggleExpand).toHaveBeenCalledTimes(1); }); }); describe("Gift Badge", () => { it("renders gift badges when provided", () => { const giftBadge = [{ title: "Free router", icon: "/router.png" }] as any; render(); expect(screen.getByText("Free router")).toBeInTheDocument(); expect(screen.getByAltText("Free router")).toBeInTheDocument(); }); it("does not render gift badges when not provided", () => { render(); expect(screen.queryByText("Free router")).not.toBeInTheDocument(); }); }); describe("Inner Badge", () => { it("renders inner badge with pipe-separated text", () => { const innerBadge = { badgeText: "Bold|Normal", badgeIcon: "/icon.png" }; render( ); expect(screen.getByText("Bold")).toBeInTheDocument(); expect(screen.getByText("Normal")).toBeInTheDocument(); }); it("renders inner badge without pipe as bold", () => { const innerBadge = { badgeText: "Simple Badge", badgeIcon: "/icon.png" }; render( ); expect(screen.getByText("Simple Badge")).toBeInTheDocument(); }); }); describe("CTA", () => { it("renders SelectPlanButton", () => { render(); expect(screen.getByTestId("select-plan-btn")).toBeInTheDocument(); }); it("calls onCtaClick when CTA is clicked", () => { render(); fireEvent.click(screen.getByTestId("select-plan-btn")); expect(defaultProps.onCtaClick).toHaveBeenCalledTimes(1); }); }); });