// @vitest-environment jsdom // // Locks the container-query classes on the shared search box that fix the narrow-header // collapse — the box must WRAP to its own line (not shrink the input to ~0) when the content column // (@container/appmain) is narrow. jsdom does no layout, but the class presence is the contract these // rules depend on, so a refactor that drops them fails here instead of only on a hand-resized window. import { afterEach, describe, expect, it, vi } from "vitest"; import { cleanup, render } from "@testing-library/react"; import SearchBar from "./SearchBar"; vi.mock("react-i18next", async (importOriginal) => { const actual = await importOriginal(); return { ...actual, useTranslation: () => ({ t: (key: string) => key }) }; }); afterEach(cleanup); describe("SearchBar responsive wrapper", () => { it("carries the container-query classes that make it wrap instead of collapsing", () => { const { container } = render( {}} placeholder="Search…" />); const cls = (container.firstElementChild as HTMLElement).className; // A usable min-width floor once the column has room → the box wraps via flex-wrap, never ~0: expect(cls).toContain("@min-[420px]/appmain:min-w-[18rem]"); // On a narrow column it takes a full line of its own and sorts last (small pills share the row above): expect(cls).toContain("@max-[640px]/appmain:basis-full"); expect(cls).toContain("@max-[640px]/appmain:order-last"); }); }); // On a tablet the 44 px key cap and Go sat on the edge of a 44 px pill and crowded the text out. describe("SearchBar on a touch screen", () => { it("drops the key cap, and grows the pill past the 44 px Go so a ring shows round it", () => { const { container, getByRole } = render( {}} placeholder="Search…" onGo={() => {}} />, ); expect(getByRole("button", { name: /palette.open/ }).className).toContain( "pointer-coarse:hidden", ); const pill = container.querySelector("input")!.closest("[class*='h-10']")!; expect(pill.className).toContain("pointer-coarse:h-13"); }); it("shortens Go to its icon by the column's width, not the screen's", () => { const { getByText } = render( {}} placeholder="Search…" onGo={() => {}} goIcon={} goLabel="Go far" />, ); const label = getByText("Go far"); expect(label.className).toContain("@min-[900px]/appmain:inline"); expect(label.className).not.toMatch(/(^|\s)md:inline/); }); });