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("");
});
});