import { describe, it, expect, vi, afterEach } from "vitest"; import { render, screen, fireEvent } from "@testing-library/react"; import { FilterBar } from "../../src/components/FilterBar"; // Force the mobile media query so FilterBar renders the Filters-button + sheet path. function setMobile(matches: boolean) { window.matchMedia = vi.fn().mockImplementation((query: string) => ({ matches, media: query, onchange: null, addEventListener: vi.fn(), removeEventListener: vi.fn(), addListener: vi.fn(), removeListener: vi.fn(), dispatchEvent: vi.fn(), })) as unknown as typeof window.matchMedia; } afterEach(() => vi.restoreAllMocks()); const baseProps = { typeOptions: [{ value: "ADVERT", label: "ADVERT" }], routeOptions: [{ value: "0", label: "Flood" }], observerOptions: [{ value: "o1", label: "YVR" }], scopeOptions: [], activeTypes: [] as string[], activeRoutes: [] as string[], activeObservers: [] as string[], activeScopes: [] as string[], onTypesChange: () => {}, onRoutesChange: () => {}, onObserversChange: () => {}, onScopesChange: () => {}, search: "", onSearchChange: () => {}, searchField: "hash" as const, onSearchFieldChange: () => {}, onClear: () => {}, }; describe("FilterBar (mobile)", () => { it.each([true, false])("offers latest-path search on mobile=%s", (mobile) => { setMobile(mobile); const onSearchFieldChange = vi.fn(); render(); fireEvent.click(screen.getByRole("button", { name: /Hash/ })); fireEvent.click(screen.getByRole("button", { name: "Latest path", exact: true })); expect(onSearchFieldChange).toHaveBeenCalledWith("path"); expect(screen.queryByRole("button", { name: "Latest path", exact: true })).not.toBeInTheDocument(); }); it("hides the inline dropdowns behind a Filters button until opened", () => { setMobile(true); render(); // dropdowns are not inline on mobile expect(screen.queryByRole("button", { name: /Types/ })).not.toBeInTheDocument(); const filtersBtn = screen.getByText("Filters"); expect(filtersBtn).toBeInTheDocument(); fireEvent.click(filtersBtn); // the sheet now exposes the dropdown controls expect(screen.getByText("Types")).toBeInTheDocument(); expect(screen.getByText("Routes")).toBeInTheDocument(); expect(screen.getByText("Observers")).toBeInTheDocument(); }); it("shows the active-filter count on the Filters button", () => { setMobile(true); render(); expect(screen.getByText("2")).toBeInTheDocument(); }); it("offers Clear all in the sheet only when filters are active, and calls onClear", () => { setMobile(true); const onClear = vi.fn(); render(); fireEvent.click(screen.getByText("Filters")); fireEvent.click(screen.getByRole("button", { name: "Clear all" })); expect(onClear).toHaveBeenCalledTimes(1); }); it("renders the inline toolbar (not a Filters button) on desktop", () => { setMobile(false); render(); expect(screen.queryByText("Filters")).not.toBeInTheDocument(); expect(screen.getByRole("button", { name: /Types/ })).toBeInTheDocument(); }); });