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";
// 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),
}));
const ALLE = ["hire", "exit", "return"] as const;
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" }));
expect(replace).toHaveBeenCalledWith("/?arten=hire%2Creturn", { 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();
suchString = "arten=hire,exit";
render();
await user.click(screen.getByRole("button", { name: "Rückkehr" }));
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 });
});
});