import React from "react";
import { SearchBlock } from "./index";
import { SearchBlockProps } from "./types";
import { fireEvent, render, screen } from "@testing-library/react";
// Mock dependencies
jest.mock("@shared/components/button", () => ({
Button: ({ children, onClick, type, className, ...rest }: any) => (
),
}));
jest.mock("@shared/components/input", () => ({
Input: ({
value,
onChange,
placeholder,
className,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
containerClassName,
...rest
}: any) => (
),
}));
jest.mock("@shared/components/material-icon", () => ({
MaterialIcon: ({ name, className }: any) => (
{name}
),
}));
jest.mock("@shared/components/text", () => ({
Text: ({ as: Tag = "span", children, className }: any) => (
{children}
),
}));
jest.mock("@shared/utils", () => ({
cx: (...args: any[]) => args.filter(Boolean).join(" "),
}));
const defaultProps: SearchBlockProps = {
title: "Search Our Plans",
backgroundColor: "white",
color: "dark",
};
describe("SearchBlock", () => {
describe("Rendering", () => {
it("renders with data-testid", () => {
render();
expect(screen.getByTestId("search-block")).toBeInTheDocument();
});
it("renders title", () => {
render();
expect(screen.getByText("Search Our Plans")).toBeInTheDocument();
});
it("renders with default anchorId", () => {
render();
expect(screen.getByTestId("search-block")).toHaveAttribute(
"id",
"SearchBlock"
);
});
it("renders with custom anchorId", () => {
render();
expect(screen.getByTestId("search-block")).toHaveAttribute(
"id",
"custom-search"
);
});
it("renders search input with placeholder", () => {
render(
);
expect(screen.getByTestId("search-input")).toHaveAttribute(
"placeholder",
"Enter your address"
);
});
it("renders search icon button", () => {
render();
expect(screen.getByTestId("icon-search")).toBeInTheDocument();
});
it("renders submit button with type submit", () => {
render();
const submitBtn = screen.getByTestId("icon-search").closest("button");
expect(submitBtn).toHaveAttribute("type", "submit");
});
});
describe("Optional content", () => {
it("renders subtitle when provided", () => {
render();
expect(screen.getByText("Find the best plan")).toBeInTheDocument();
});
it("does not render subtitle when not provided", () => {
render();
expect(screen.queryByText("Find the best plan")).not.toBeInTheDocument();
});
it("renders searchDescription when provided", () => {
render(
);
expect(screen.getByText("Enter your ZIP code")).toBeInTheDocument();
});
it("does not render searchDescription when not provided", () => {
render();
expect(screen.queryByText("Enter your ZIP code")).not.toBeInTheDocument();
});
it("renders caption ReactNode when provided", () => {
render(
Caption content}
/>
);
expect(screen.getByTestId("caption")).toBeInTheDocument();
});
it("does not render caption when not provided", () => {
render();
expect(screen.queryByTestId("caption")).not.toBeInTheDocument();
});
it("renders basicCaption ReactNode when provided", () => {
render(
Basic caption
}
/>
);
expect(screen.getByTestId("basic-caption")).toBeInTheDocument();
});
});
describe("Heading levels", () => {
it("renders title as h2 when enableHeading is false/undefined", () => {
render();
const el = screen.getByText("Search Our Plans");
expect(el.tagName).toBe("H2");
});
it("renders title as h1 when enableHeading is true", () => {
render();
const el = screen.getByText("Search Our Plans");
expect(el.tagName).toBe("H1");
});
});
describe("Background and color themes", () => {
it("applies supporting background class", () => {
render();
expect(screen.getByTestId("search-block")).toHaveClass(
"bg-bg-fill-brand-supporting"
);
});
it("applies white background class", () => {
render();
expect(screen.getByTestId("search-block")).toHaveClass("bg-bg");
});
it("applies brand background class", () => {
render();
expect(screen.getByTestId("search-block")).toHaveClass(
"bg-bg-fill-brand"
);
});
it("applies dark text color", () => {
render();
expect(screen.getByTestId("search-block")).toHaveClass("text-text");
});
it("applies light (white) text color", () => {
render();
expect(screen.getByTestId("search-block")).toHaveClass("text-white");
});
});
describe("Form submission", () => {
it("calls onSubmit with searchText on form submit", () => {
const mockSubmit = jest.fn();
render();
const input = screen.getByTestId("search-input");
fireEvent.change(input, { target: { value: "90210" } });
const form = input.closest("form")!;
fireEvent.submit(form);
expect(mockSubmit).toHaveBeenCalledWith({ searchText: "90210" });
});
it("calls onSubmit with empty string when no text entered", () => {
const mockSubmit = jest.fn();
render();
const form = screen.getByTestId("search-input").closest("form")!;
fireEvent.submit(form);
expect(mockSubmit).toHaveBeenCalledWith({ searchText: "" });
});
it("does not throw when onSubmit is not provided", () => {
render();
const form = screen.getByTestId("search-input").closest("form")!;
expect(() => fireEvent.submit(form)).not.toThrow();
});
it("prevents default form submission", () => {
const mockSubmit = jest.fn();
render();
const form = screen.getByTestId("search-input").closest("form")!;
const submitEvent = new Event("submit", {
bubbles: true,
cancelable: true,
});
const prevented = !form.dispatchEvent(submitEvent);
expect(prevented).toBe(true);
});
});
describe("Input interaction", () => {
it("updates input value on change", () => {
render();
const input = screen.getByTestId("search-input") as HTMLInputElement;
fireEvent.change(input, { target: { value: "test query" } });
expect(input.value).toBe("test query");
});
it("submits the latest typed value", () => {
const mockSubmit = jest.fn();
render();
const input = screen.getByTestId("search-input");
fireEvent.change(input, { target: { value: "first" } });
fireEvent.change(input, { target: { value: "second" } });
const form = input.closest("form")!;
fireEvent.submit(form);
expect(mockSubmit).toHaveBeenCalledWith({ searchText: "second" });
});
});
});