import React from "react"; import { SimpleCard } from "./index"; import { render, screen } from "@testing-library/react"; jest.mock("@shared/components/next-image", () => ({ NextImage: ({ src, alt, width, height, className }: any) => ( {alt} ), })); jest.mock("@shared/components/text", () => ({ Text: ({ as: Tag = "span", children, className, style }: any) => ( {children} ), })); jest.mock("@shared/components/link", () => ({ Link: ({ children, href, className, ...rest }: any) => ( {children} ), })); jest.mock("@shared/components/material-icon", () => ({ MaterialIcon: ({ name, className }: any) => ( {name} ), })); jest.mock("../../button", () => ({ Button: ({ children, linkClassName, buttonLabel }: any) => ( ), })); jest.mock("@shared/utils", () => ({ cx: (...args: any[]) => args.filter(Boolean).join(" "), })); jest.mock("@shared/utils/speed-card-bg", () => ({ SpeedCardBg: (color: string) => `${color}`, })); describe("SimpleCard", () => { const defaultCard = { title: "Simple Card Title", body: "Card body content", image: "/image.jpg", imageAlt: "Card image", }; describe("Rendering", () => { it("renders the section element", () => { const { container } = render(); expect(container.querySelector("section")).toBeInTheDocument(); }); it("renders title", () => { render(); expect(screen.getByText("Simple Card Title")).toBeInTheDocument(); }); it("renders body", () => { render(); expect(screen.getByText("Card body content")).toBeInTheDocument(); }); it("renders aria-labelledby with title", () => { const { container } = render(); expect(container.querySelector("section")).toHaveAttribute( "aria-labelledby", "callout-Simple Card Title" ); }); it("does not set aria-labelledby when no title", () => { const { container } = render(); expect(container.querySelector("section")).not.toHaveAttribute( "aria-labelledby" ); }); }); describe("Image views", () => { it("renders icon-sized image by default when image is provided", () => { render(); const img = screen.getByTestId("next-image"); expect(img).toBeInTheDocument(); }); it("renders full image when imageView is 'full'", () => { const card = { ...defaultCard, imageView: "full" as const }; render(); expect(screen.getByTestId("next-image")).toBeInTheDocument(); }); it("renders margin image when imageView is 'margin'", () => { const card = { ...defaultCard, imageView: "margin" as const }; render(); expect(screen.getByTestId("next-image")).toBeInTheDocument(); }); it("renders standard-sized image", () => { const card = { ...defaultCard, imageView: "standard" as const, imageWidth: 120, imageHeight: 120, }; render(); const img = screen.getByTestId("next-image"); expect(img).toHaveAttribute("width", "120"); expect(img).toHaveAttribute("height", "120"); }); it("renders inset image view", () => { const card = { ...defaultCard, imageView: "inset" as const }; render(); expect(screen.getByTestId("next-image")).toBeInTheDocument(); }); it("does not render image when image is not provided", () => { render(); expect(screen.queryByTestId("next-image")).not.toBeInTheDocument(); }); }); describe("CTA", () => { it("renders CTA button when cta is provided", () => { const card = { ...defaultCard, cta: { buttonLabel: "Learn More", href: "/learn" }, }; render(); expect(screen.getByTestId("cta-button")).toBeInTheDocument(); }); it("does not render CTA when not provided", () => { render(); expect(screen.queryByTestId("cta-button")).not.toBeInTheDocument(); }); it("wraps title in link when cta has href", () => { const card = { ...defaultCard, cta: { buttonLabel: "Click", href: "/click" }, }; render(); const titleLink = screen.getByText("Simple Card Title").closest("a"); expect(titleLink).toHaveAttribute("href", "/click"); }); }); describe("CTA Bottom (location CTA)", () => { it("renders ctaBottom link when provided", () => { const card = { ...defaultCard, ctaBottom: { title: "Location", href: "/location" }, }; render(); expect(screen.getByText("Location")).toBeInTheDocument(); }); it("does not render ctaBottom when not provided", () => { render(); expect(screen.queryByText("location_on")).not.toBeInTheDocument(); }); it("renders location_on icon with ctaBottom", () => { const card = { ...defaultCard, ctaBottom: { title: "Store", href: "/store" }, }; render(); expect(screen.getByText("location_on")).toBeInTheDocument(); }); }); describe("Working hours and phone", () => { it("renders working hours table", () => { const card = { ...defaultCard, workingHours: ["Mon-Fri|9am-5pm", "Sat|10am-2pm"], }; render(); expect(screen.getByText("Mon-Fri")).toBeInTheDocument(); expect(screen.getByText("9am-5pm")).toBeInTheDocument(); }); it("renders phone numbers", () => { const card = { ...defaultCard, phoneNumber: ["(555) 123-4567"], }; render(); expect(screen.getByText("(555) 123-4567")).toBeInTheDocument(); }); it("creates tel: link for phone numbers", () => { const card = { ...defaultCard, phoneNumber: ["(555) 123-4567"], }; render(); const phoneLink = screen.getByText("(555) 123-4567").closest("a"); expect(phoneLink).toHaveAttribute("href", "tel:5551234567"); }); }); describe("Rich text", () => { it("renders richText when provided", () => { const card = { ...defaultCard, richText: "Rich text content" }; render(); expect(screen.getByText("Rich text content")).toBeInTheDocument(); }); }); describe("Title location", () => { it("renders titleLocation when provided", () => { const card = { ...defaultCard, titleLocation: "Downtown" }; render(); expect(screen.getByText("Downtown")).toBeInTheDocument(); }); }); describe("Shadow", () => { it("applies shadow class when shadow is true", () => { const card = { ...defaultCard, shadow: true }; const { container } = render(); expect(container.querySelector("section")?.className).toContain( "shadow-card" ); }); }); describe("Background colors", () => { it("applies background color class from map", () => { const card = { ...defaultCard, backgroundColor: "blue" }; const { container } = render(); expect(container.querySelector("section")?.className).toContain( "bg-fill-brand" ); }); it("applies dynamic background color when applyCardBackgroundColor is true", () => { const card = { ...defaultCard, applyCardBackgroundColor: true, backgroundColor: "#FF0000", imageView: "icon" as const, }; const { container } = render(); const section = container.querySelector("section") as HTMLElement; // jsdom doesn't fully support CSS variables in style, check the attribute directly const styleAttr = section.getAttribute("style") || ""; expect(styleAttr).toContain("--scc-bg"); }); it("applies dynamic text color when applyCardBackgroundColor is true", () => { const card = { ...defaultCard, applyCardBackgroundColor: true, textColor: "#FFFFFF", imageView: "icon" as const, }; const { container } = render(); const section = container.querySelector("section") as HTMLElement; const styleAttr = section.getAttribute("style") || ""; expect(styleAttr).toContain("--scc-fg"); }); }); describe("Background image (pinwheel)", () => { it("applies background image when showBackgroundImage and pinwheelColor", () => { const card = { ...defaultCard, applyCardBackgroundColor: true, backgroundColor: "#000", showBackgroundImage: true, pinwheelColor: "Blue-#307998", imageView: "icon" as const, }; const { container } = render(); const section = container.querySelector("section") as HTMLElement; expect(section.style.backgroundImage).toContain("data:image/svg+xml"); }); }); describe("Layout props", () => { it("applies lgWidth class", () => { const { container } = render( ); expect(container.querySelector("section")?.className).toContain( "lg:w-1/3" ); }); it("applies mdWidth class", () => { const { container } = render( ); expect(container.querySelector("section")?.className).toContain( "md:w-1/2" ); }); it("applies custom className", () => { const { container } = render( ); expect(container.querySelector("section")?.className).toContain( "custom-class" ); }); it("applies custom style", () => { const { container } = render( ); const section = container.querySelector("section") as HTMLElement; expect(section.style.margin).toBe("10px"); }); }); describe("Image alignment", () => { it("uses iconAlignment for icon position", () => { const card = { ...defaultCard, iconAlignment: "center" as const, imageView: "icon" as const, }; render(); const iconWrapper = screen.getByTestId("next-image").parentElement; expect(iconWrapper?.style.justifyContent).toBe("center"); }); it("falls back to imageAlignment when iconAlignment not set", () => { const card = { ...defaultCard, imageAlignment: "right" as const, imageView: "icon" as const, }; render(); const iconWrapper = screen.getByTestId("next-image").parentElement; expect(iconWrapper?.style.justifyContent).toBe("right"); }); }); });