import { render, screen } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; import { beforeEach, describe, expect, it, vi } from "vitest"; import { AnstehendFilter } from "@/components/dashboard/AnstehendFilter"; import { ANSTEHEND_ARTEN, type AnstehendArt } from "@/lib/dashboard-filter"; // Die Auswahl muss in die Adresse, nicht in den Browser-Zustand: die // Übersicht wird auf dem Server gebaut, und ein längerer Zeitraum bringt // Zeilen ins Spiel, die im Browser gar nicht liegen. Geprüft wird deshalb // genau das — was in der Adresse landet. const replace = vi.fn(); let suchString = ""; vi.mock("next/navigation", () => ({ useRouter: () => ({ replace }), usePathname: () => "/", useSearchParams: () => new URLSearchParams(suchString), })); // Aus dem Verzeichnis abgeleitet, nicht abgeschrieben: eine neue Art hätte // diesen Test sonst stillschweigend am falschen Fall prüfen lassen — genau das // ist beim Hinzufügen der Wiedervorlage passiert. const ALLE: AnstehendArt[] = ANSTEHEND_ARTEN.map((a) => a.value); beforeEach(() => { replace.mockClear(); suchString = ""; }); describe("AnstehendFilter", () => { it("schreibt einen gewählten Zeitraum in die Adresse", async () => { const user = userEvent.setup(); render(); await user.click(screen.getByRole("button", { name: "90 Tage" })); expect(replace).toHaveBeenCalledWith("/?tage=90", { scroll: false }); }); it("lässt den Standard aus der Adresse verschwinden statt ihn hineinzuschreiben", async () => { // Sonst trüge jede geteilte Adresse einen Filter, den niemand gesetzt hat. const user = userEvent.setup(); suchString = "tage=90"; render(); await user.click(screen.getByRole("button", { name: "60 Tage" })); expect(replace).toHaveBeenCalledWith("/", { scroll: false }); }); it("nimmt eine abgewählte Art aus der Auswahl", async () => { const user = userEvent.setup(); render(); await user.click(screen.getByRole("button", { name: "Austritt" })); const erwartet = encodeURIComponent(ALLE.filter((a) => a !== "exit").join(",")); expect(replace).toHaveBeenCalledWith(`/?arten=${erwartet}`, { scroll: false }); }); it("nimmt eine wieder hinzugewählte Art auf", async () => { const user = userEvent.setup(); suchString = "arten=hire"; render(); await user.click(screen.getByRole("button", { name: "Rückkehr" })); expect(replace).toHaveBeenCalledWith("/?arten=hire%2Creturn", { scroll: false }); }); it("führt die letzte abgewählte Art auf alle zurück, nicht auf keine", async () => { // Eine leere Karte ist keine Antwort, und der Weg zurück wäre sonst ein // Klick zu weit. const user = userEvent.setup(); suchString = "arten=hire"; render(); await user.click(screen.getByRole("button", { name: "Eintritt" })); expect(replace).toHaveBeenCalledWith("/", { scroll: false }); }); it("lässt vollständige Auswahl gar nicht erst in der Adresse stehen", async () => { const user = userEvent.setup(); // Die letzte fehlende Art wieder dazu: dann ist wieder alles gewählt, und // das gehört nicht in die Adresse. Bewusst über ALLE gebildet statt // abgeschrieben — sonst prüft dieser Test nach der nächsten neuen Art die // falsche Bedingung. const bisAufEine = ALLE.slice(0, -1); suchString = `arten=${bisAufEine.join(",")}`; render(); await user.click(screen.getByRole("button", { name: "Wiedervorlage" })); expect(replace).toHaveBeenCalledWith("/", { scroll: false }); }); it("behält andere Angaben in der Adresse bei", async () => { const user = userEvent.setup(); suchString = "arten=hire"; render(); await user.click(screen.getByRole("button", { name: "30 Tage" })); expect(replace).toHaveBeenCalledWith("/?arten=hire&tage=30", { scroll: false }); }); it("zeigt am Knopf an, was gerade gewählt ist", () => { render(); expect(screen.getByRole("button", { name: "Eintritt" })).toHaveAttribute("aria-pressed", "true"); expect(screen.getByRole("button", { name: "Austritt" })).toHaveAttribute("aria-pressed", "false"); }); it("springt beim Filtern nicht an den Seitenanfang", async () => { // Die Karte steht in der unteren Hälfte; dorthin sieht gerade, wer klickt. const user = userEvent.setup(); render(); await user.click(screen.getByRole("button", { name: "30 Tage" })); expect(replace.mock.calls[0][1]).toEqual({ scroll: false }); }); });