import { fireEvent, render, screen } from "@testing-library/react"; import { describe, expect, it, vi } from "vitest"; import { DateField, istMeldbaresDatum } from "@/components/ui/Field"; // Der Anlass: in den Berichten hängt jedes Datumsfeld an der Adresszeile, eine // Änderung heisst also neu laden. Ein `` meldet beim Tippen // der Jahreszahl aber viermal — 0002, 0020, 0202, 2026 —, und die ersten drei // setzten das Feld mitten im Tippen zurück. Mit dem Kalender ging es, weil der // in einem Zug ein fertiges Datum setzt. describe("istMeldbaresDatum", () => { it("nimmt ein vollständiges Datum an", () => { expect(istMeldbaresDatum("2026-09-30")).toBe(true); expect(istMeldbaresDatum("1980-01-01")).toBe(true); }); it("nimmt das leere Feld an, denn kein Datum ist auch eine Aussage", () => { expect(istMeldbaresDatum("")).toBe(true); }); it("weist die Zwischenstände beim Tippen ab", () => { for (const zwischen of ["0002-09-30", "0020-09-30", "0202-09-30"]) { expect(istMeldbaresDatum(zwischen), zwischen).toBe(false); } }); it("weist Bruchstücke ab", () => { expect(istMeldbaresDatum("2026-09")).toBe(false); expect(istMeldbaresDatum("2026")).toBe(false); }); }); describe("DateField", () => { function feld(onChange: (v: string) => void, value = "") { render(); return screen.getByLabelText("Von") as HTMLInputElement; } it("meldet den Zwischenstand nicht, zeigt ihn aber an", () => { const gemeldet = vi.fn(); const input = feld(gemeldet); fireEvent.change(input, { target: { value: "0002-09-30" } }); expect(gemeldet).not.toHaveBeenCalled(); // Der Tippstand bleibt stehen: würde das Feld ihn verwerfen, kämpfte es // gegen die Eingabe. expect(input.value).toBe("0002-09-30"); }); it("meldet, sobald die Jahreszahl vollständig ist", () => { const gemeldet = vi.fn(); const input = feld(gemeldet); fireEvent.change(input, { target: { value: "0002-09-30" } }); fireEvent.change(input, { target: { value: "2026-09-30" } }); expect(gemeldet).toHaveBeenCalledExactlyOnceWith("2026-09-30"); }); it("meldet das Leeren", () => { const gemeldet = vi.fn(); const input = feld(gemeldet, "2026-09-30"); fireEvent.change(input, { target: { value: "" } }); expect(gemeldet).toHaveBeenCalledExactlyOnceWith(""); }); it("reicht beim Verlassen nach, was liegengeblieben ist", () => { // Kommt in der Praxis kaum vor, ist aber der Rückfall: was nicht gemeldet // wurde, geht spätestens hier hinaus — sofern es eine Aussage ist. const gemeldet = vi.fn(); const input = feld(gemeldet); fireEvent.change(input, { target: { value: "0002-09-30" } }); fireEvent.blur(input); expect(gemeldet).not.toHaveBeenCalled(); }); it("übernimmt einen Wert, der von aussen kommt", () => { // „Zurücksetzen" in den Kriterien leert das Feld — der Tippstand darf // dann nicht stehenbleiben. const { rerender } = render(); const input = screen.getByLabelText("Von") as HTMLInputElement; expect(input.value).toBe("2026-09-30"); rerender(); expect(input.value).toBe(""); }); });