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) => (
{items?.map((item: any, i: number) => (
- {item}
))}
),
}));
jest.mock("@shared/components/image", () => ({
Image: ({ src, alt, width, height }: any) => (
),
}));
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);
});
});
});