import React from "react";
import { PrimaryHero } from "./index";
import { render, screen } from "@testing-library/react";
jest.mock("@shared/components/checklist", () => ({
Checklist: ({ items }: any) => (
{items?.map((i: string, idx: number) => (
- {i}
))}
),
}));
jest.mock("@shared/components/next-image", () => ({
NextImage: ({ src, alt, className }: any) => (
),
}));
jest.mock("@shared/components/text", () => ({
Text: ({ as: Tag = "span", children, className }: any) => (
{children}
),
}));
jest.mock("@shared/contentful/blocks/button", () => ({
Button: ({
children,
buttonLabel,
linkClassName,
buttonClassName,
...rest
}: any) => (
),
}));
jest.mock("@shared/utils", () => ({
cx: (...args: any[]) => args.filter(Boolean).join(" "),
}));
const baseProps = { title: "Fast Internet" };
describe("PrimaryHero", () => {
beforeEach(() => jest.clearAllMocks());
it("renders title as h2 by default", () => {
render();
expect(screen.getByText("Fast Internet").tagName).toBe("H2");
});
it("renders title as h1 when showAsHeading is true", () => {
render();
expect(screen.getByText("Fast Internet").tagName).toBe("H1");
});
it("does not render title section when title is empty", () => {
render();
expect(screen.queryByRole("heading")).not.toBeInTheDocument();
});
it("renders subtitle when provided", () => {
render();
expect(screen.getByText("Super fast speeds")).toBeInTheDocument();
});
it("does not render subtitle when not provided", () => {
const { container } = render();
expect(container.querySelectorAll("p.subheading3")).toHaveLength(0);
});
describe("Price section", () => {
it("renders price with dollar sign", () => {
render();
expect(screen.getByText("$")).toBeInTheDocument();
expect(screen.getByText("49.99")).toBeInTheDocument();
});
it("renders priceSuffix when provided", () => {
render();
expect(screen.getByText("/mo")).toBeInTheDocument();
});
it("does not render priceSuffix when not provided", () => {
render();
expect(screen.queryByText("/mo")).not.toBeInTheDocument();
});
it("renders priceCallout split by pipe", () => {
render(
);
expect(screen.getByText("Starting at")).toBeInTheDocument();
expect(screen.getByText("per month")).toBeInTheDocument();
});
it("does not render priceCallout when not provided", () => {
render();
expect(screen.queryByText("Starting at")).not.toBeInTheDocument();
});
it("does not render price section when price is not provided", () => {
render();
expect(screen.queryByText("$")).not.toBeInTheDocument();
});
});
describe("Checklist", () => {
it("renders checklist when provided", () => {
const checklist = [{ title: "No data caps" }, { title: "Free install" }];
render();
expect(screen.getByTestId("checklist")).toBeInTheDocument();
expect(screen.getByText("No data caps")).toBeInTheDocument();
expect(screen.getByText("Free install")).toBeInTheDocument();
});
it("does not render checklist when not provided", () => {
render();
expect(screen.queryByTestId("checklist")).not.toBeInTheDocument();
});
});
describe("Primary CTA", () => {
it("renders primaryCta1 button", () => {
render(
);
expect(screen.getByText("Get Started")).toBeInTheDocument();
});
it("hides primaryCta1 on mobile when hideOnMobileCta1 is true", () => {
const { container } = render(
);
const ctaWrapper = container.querySelector(".hidden.md\\:block");
expect(ctaWrapper).toBeInTheDocument();
});
it("does not render primaryCta1 when not provided", () => {
render();
expect(screen.queryByText("Get Started")).not.toBeInTheDocument();
});
it("renders both CTAs side by side when both are button type", () => {
const { container } = render(
);
expect(screen.getByText("Check plans")).toBeInTheDocument();
expect(screen.getByText("Shop AT&T deals")).toBeInTheDocument();
const row = container.querySelector(".sm\\:flex-row");
expect(row).toBeInTheDocument();
});
it("renders CTAs stacked when only primaryCta1 is present", () => {
const { container } = render(
);
expect(screen.getByText("Check plans")).toBeInTheDocument();
expect(container.querySelector(".sm\\:flex-row")).not.toBeInTheDocument();
});
it("renders CTAs stacked when one CTA is not a button type", () => {
const { container } = render(
);
expect(screen.getByText("Check plans")).toBeInTheDocument();
expect(screen.getByText("Learn more")).toBeInTheDocument();
expect(container.querySelector(".sm\\:flex-row")).not.toBeInTheDocument();
});
it("hides primaryCta2 on mobile when hideOnMobileCta2 is true", () => {
const { container } = render(
);
const ctaWrapper = container.querySelector(".hidden.md\\:block");
expect(ctaWrapper).toBeInTheDocument();
});
it("renders only primaryCta2 when primaryCta1 is not provided", () => {
render(
);
expect(screen.getByText("Shop deals")).toBeInTheDocument();
});
});
describe("Secondary CTA", () => {
it("renders secondaryCtaPrefix and secondaryCta", () => {
render(
);
expect(screen.getAllByText("Or").length).toBeGreaterThan(0);
expect(screen.getAllByText("Call us").length).toBeGreaterThan(0);
});
it("renders only secondaryCtaPrefix without secondaryCta", () => {
render();
expect(screen.getAllByText("Or").length).toBeGreaterThan(0);
});
it("renders only secondaryCta without prefix", () => {
render(
);
expect(screen.getAllByText("Call us").length).toBeGreaterThan(0);
});
it("does not render secondary section when neither provided", () => {
const { container } = render();
expect(container.querySelectorAll(".md\\:flex")).toHaveLength(0);
});
});
describe("Bottom link", () => {
it("renders bottom link when buttonLabel and href exist", () => {
render(
);
expect(screen.getAllByText("Learn more").length).toBeGreaterThan(0);
});
it("renders bottom link when only href exists (label is from label prop)", () => {
render(
);
expect(screen.getAllByText("Details").length).toBeGreaterThan(0);
});
it("does not render bottom link when no label and no href", () => {
render();
// No button rendered for bottom link
expect(screen.queryAllByTestId("button")).toHaveLength(0);
});
it("does not render bottom link when bottomLink is undefined", () => {
render();
expect(screen.queryByText("Learn more")).not.toBeInTheDocument();
});
});
describe("Pricing description disclaimer", () => {
it("renders pricingDescription with subheading and responsive alignment classes", () => {
render(
);
const pricingText = screen.getByText(
"Building a new home? Contact us to see if you're eligible for Kinetic Internet."
);
expect(pricingText).toBeInTheDocument();
expect(pricingText).toHaveClass("subheading1");
expect(pricingText).toHaveClass(
"text-left",
"sm:text-center",
"xl:text-left"
);
});
it("renders pricingDescriptionDisclaimer (desktop and mobile)", () => {
render(
);
expect(screen.getAllByText("Taxes apply")).toHaveLength(1);
});
it("does not render disclaimer when not provided", () => {
render();
expect(screen.queryByText("Taxes apply")).not.toBeInTheDocument();
});
});
describe("Images", () => {
it("renders carousel image (mobile and desktop)", () => {
render(
);
const imgs = screen.getAllByAltText("Hero");
expect(imgs).toHaveLength(2);
expect(imgs[0]).toHaveAttribute("src", "https://img.test/hero.jpg");
});
it("does not render carousel image when empty array", () => {
render();
expect(screen.queryByAltText("Hero")).not.toBeInTheDocument();
});
it("renders badge image (mobile and desktop)", () => {
render(
);
const badges = screen.getAllByAltText("Badge");
expect(badges).toHaveLength(2);
});
it("does not render badge image when not provided", () => {
render();
expect(screen.queryByAltText("Badge")).not.toBeInTheDocument();
});
it("renders desktop background video when heroVideo URL exists", () => {
render(
);
expect(
screen.getByTestId("hero-background-video-desktop")
).toHaveAttribute("aria-label", "Desktop hero video");
expect(screen.getAllByAltText("Hero")).toHaveLength(1);
});
it("falls back to images when heroVideo URL is missing", () => {
render(
);
expect(
screen.queryByTestId("hero-background-video-desktop")
).not.toBeInTheDocument();
expect(screen.getAllByAltText("Hero")).toHaveLength(2);
});
it("renders mobile video when heroVideoMobile URL exists", () => {
render(
);
expect(screen.getByTestId("hero-video-mobile")).toHaveAttribute(
"aria-label",
"Mobile hero video"
);
expect(screen.getAllByAltText("Hero")).toHaveLength(1);
});
it("uses the default desktop video label when no titles are provided", () => {
render(
);
expect(
screen.getByTestId("hero-background-video-desktop")
).toHaveAttribute("aria-label", "Hero background video");
});
});
describe("renderCheckPlans", () => {
it("passes renderCheckPlans to Button", () => {
const renderFn = jest.fn();
render(
);
expect(screen.getByText("Go")).toBeInTheDocument();
});
});
});