import { describe, expect, it } from "vitest"; import { alsDauer, anfahrtszeit, ausrueckzeit, einsatzdauer, hilfsfrist, kennzahlen, naechsterStempel, zeitHinweise, } from "@/lib/einsatz/zeiten"; import { nummerBilden, nummerLesen, naechsteNummer } from "@/lib/nummernkreis"; /** * Einsatzzeiten und Nummernkreis. * * Die Hilfsfrist ist die Zahl, über die eine Wehr mit ihrer Gemeinde * diskutiert. Wenn sie falsch gerechnet wird, merkt es niemand — bis es * darauf ankommt. */ function uhr(stunde: number, minute: number): Date { return new Date(Date.UTC(2026, 5, 15, stunde, minute, 0)); } const EINSATZ = { alarmiertUm: uhr(3, 42), ausgeruecktUm: uhr(3, 47), eingetroffenUm: uhr(3, 51), einsatzendeUm: uhr(6, 5), eingeruecktUm: uhr(6, 30), einsatzbereitUm: uhr(7, 0), }; describe("Kennzahlen", () => { it("rechnet Ausrückzeit, Anfahrt und Hilfsfrist", () => { expect(ausrueckzeit(EINSATZ)).toBe(5); expect(anfahrtszeit(EINSATZ)).toBe(4); expect(hilfsfrist(EINSATZ)).toBe(9); }); it("rechnet die Einsatzdauer bis zum Einrücken", () => { expect(einsatzdauer(EINSATZ)).toBe(168); }); it("nimmt für die Dauer ersatzweise das Einsatzende", () => { expect(einsatzdauer({ ...EINSATZ, eingeruecktUm: null })).toBe(143); }); it("liefert null, wo ein Stempel fehlt", () => { expect(hilfsfrist({ alarmiertUm: uhr(3, 42) })).toBeNull(); expect(ausrueckzeit({})).toBeNull(); }); it("liefert alle vier Zahlen auf einmal", () => { expect(kennzahlen(EINSATZ)).toEqual({ ausrueckzeit: 5, anfahrtszeit: 4, hilfsfrist: 9, dauer: 168, }); }); it("gibt keine negative Zeit zurück, wenn Stempel verdreht sind", () => { // Die Reihenfolge stimmt nicht — dann lieber keine Zahl als eine falsche. expect(ausrueckzeit({ alarmiertUm: uhr(4, 0), ausgeruecktUm: uhr(3, 50) })).toBeNull(); }); }); describe("zeitHinweise", () => { it("schweigt bei einem stimmigen Ablauf", () => { expect(zeitHinweise(EINSATZ)).toHaveLength(0); }); it("meldet eine verdrehte Reihenfolge", () => { const hinweise = zeitHinweise({ ...EINSATZ, eingetroffenUm: uhr(3, 40) }); expect(hinweise.length).toBeGreaterThan(0); expect(hinweise[0]).toContain("eingetroffen"); }); it("meldet eine unplausibel lange Anfahrt", () => { const hinweise = zeitHinweise({ alarmiertUm: uhr(3, 0), eingetroffenUm: uhr(5, 0), }); expect(hinweise.some((hinweis) => hinweis.includes("120 Minuten"))).toBe(true); }); }); describe("naechsterStempel", () => { it("nennt den ersten offenen Stempel", () => { expect(naechsterStempel({})).toBe("alarmiertUm"); expect(naechsterStempel({ alarmiertUm: uhr(3, 42) })).toBe("ausgeruecktUm"); }); it("gibt null zurück, wenn alles gesetzt ist", () => { expect(naechsterStempel(EINSATZ)).toBeNull(); }); }); describe("alsDauer", () => { it("schreibt Minuten unter einer Stunde als Minuten", () => { expect(alsDauer(9)).toBe("9 min"); expect(alsDauer(59)).toBe("59 min"); }); it("schreibt längere Zeiten als Stunden", () => { expect(alsDauer(60)).toBe("1:00 h"); expect(alsDauer(168)).toBe("2:48 h"); }); it("kommt mit fehlenden Werten zurecht", () => { expect(alsDauer(null)).toBe("—"); expect(alsDauer(undefined)).toBe("—"); }); }); describe("Nummernkreis", () => { it("bildet und liest Nummern", () => { expect(nummerBilden(2026, 7)).toBe("2026-0007"); expect(nummerLesen("2026-0007")).toEqual({ jahr: 2026, laufend: 7 }); expect(nummerLesen("Unsinn")).toBeNull(); }); it("zählt von der bisher höchsten Nummer weiter", () => { expect(naechsteNummer(2026, "2026-0041")).toBe("2026-0042"); }); it("beginnt im leeren Jahr bei eins", () => { expect(naechsteNummer(2027, null)).toBe("2027-0001"); }); it("übernimmt keine Nummer aus einem anderen Jahr", () => { // Der Aufrufer sucht die höchste Nummer des Jahres; bekommt er keine, // beginnt das neue Jahr wieder bei eins. expect(naechsteNummer(2027, undefined)).toBe("2027-0001"); }); });