import { afterEach, describe, expect, it, vi } from "vitest"; import { cleanup, fireEvent, render, screen, waitFor } from "@testing-library/react"; import { MetadataForm } from "./MetadataForm"; import { FieldDTO } from "../lib/metadataApi"; afterEach(() => { cleanup(); vi.restoreAllMocks(); }); const fields: FieldDTO[] = [ { id: "f1", key: "betrag", label: "Betrag", type: "number", required: true, default_value: null }, { id: "f2", key: "faelligkeit", label: "Fälligkeit", type: "date", required: false, default_value: null }, ]; // Akzeptanzkriterium 1: Formular passt sich der Felddefinition automatisch an. it("rendert ein Eingabefeld je Felddefinition mit korrektem Typ", () => { render(); const betrag = screen.getByLabelText("Betrag *") as HTMLInputElement; const faelligkeit = screen.getByLabelText("Fälligkeit") as HTMLInputElement; expect(betrag.type).toBe("number"); expect(faelligkeit.type).toBe("date"); }); // Pflichtpruefung 2: Formular per Tastatur vollstaendig ausfuellbar — jedes // Feld ist ueber sein Label erreichbar und per Tastatur-Eingabe (change, // kein Mausklick noetig) befuellbar. it("ist ueber Labels erreichbar und ohne Maus befuellbar", () => { render(); const betrag = screen.getByLabelText("Betrag *"); fireEvent.change(betrag, { target: { value: "150" } }); expect((betrag as HTMLInputElement).value).toBe("150"); }); it("speichert per Speichern-Button", async () => { const onSave = vi.fn().mockResolvedValue(undefined); render(); fireEvent.change(screen.getByLabelText("Betrag *"), { target: { value: "99" } }); fireEvent.click(screen.getByRole("button", { name: "Speichern" })); await waitFor(() => expect(onSave).toHaveBeenCalledWith({ f1: "99" })); }); // Pflichtpruefung 1: ungespeicherte Aenderungen loesen eine Warnung aus. it("zeigt eine Bestaetigung, bevor ungespeicherte Aenderungen verworfen werden", () => { render(); const betrag = screen.getByLabelText("Betrag *"); fireEvent.change(betrag, { target: { value: "20" } }); fireEvent.click(screen.getByRole("button", { name: "Verwerfen" })); expect(screen.getByRole("alertdialog")).toBeTruthy(); expect((betrag as HTMLInputElement).value).toBe("20"); // noch nicht verworfen fireEvent.click(screen.getByRole("button", { name: "Ja, verwerfen" })); expect((betrag as HTMLInputElement).value).toBe("10"); expect(screen.queryByRole("alertdialog")).toBeNull(); }); it("Verwerfen-Button ist deaktiviert, solange nichts geaendert wurde", () => { render(); const discardButton = screen.getByRole("button", { name: "Verwerfen" }) as HTMLButtonElement; expect(discardButton.disabled).toBe(true); });