import { describe, expect, it } from "vitest"; import { ABSENCE_TYPES, absenceLabel, isAbsenceType, RUECKKEHR_GRUENDE, statusLabel, STUNDEN_GRUENDE } from "@/lib/absence"; // The stored employment status is still 'Karenz' — renaming the enum value // would mean rewriting every stored function that spells it. The rename // therefore lives entirely in this mapping, which makes it the one thing // standing between the database value and what an HR user reads. describe("statusLabel", () => { it("renders the stored 'Karenz' value as Langzeitabwesenheit", () => { expect(statusLabel("Karenz")).toBe("Langzeitabwesenheit"); }); it("leaves the other statuses alone", () => { expect(statusLabel("Aktiv")).toBe("Aktiv"); expect(statusLabel("Geplant")).toBe("Geplant"); expect(statusLabel("Ausgetreten")).toBe("Ausgetreten"); }); }); describe("absenceLabel", () => { it("shows the specific kind when one is recorded", () => { expect(absenceLabel("Karenz", "Bildungskarenz")).toBe("Bildungskarenz"); expect(absenceLabel("Karenz", "Präsenzdienst")).toBe("Präsenzdienst"); }); it("falls back to the generic name for absences recorded before the field existed", () => { expect(absenceLabel("Karenz", null)).toBe("Langzeitabwesenheit"); expect(absenceLabel("Karenz", "")).toBe("Langzeitabwesenheit"); }); it("ignores a type that is not on the list rather than displaying it", () => { // The column has a check constraint, but the value arrives here as a // plain string — echoing an unknown one would put unvalidated text in // the status chip. expect(absenceLabel("Karenz", "Ausgedachte Karenz")).toBe("Langzeitabwesenheit"); }); it("ignores the absence type entirely for any other status", () => { expect(absenceLabel("Aktiv", "Sabbatical")).toBe("Aktiv"); expect(absenceLabel("Ausgetreten", "Papamonat")).toBe("Ausgetreten"); }); }); describe("ABSENCE_TYPES", () => { it("holds the ten kinds, in the order they are offered", () => { // Waren dreizehn. Die vier Teilzeiten sind dorthin gewandert, wo sie // hingehören — siehe unten. expect(ABSENCE_TYPES).toHaveLength(10); expect(ABSENCE_TYPES[0]).toBe("Wochenhilfe (Mutterschutz)"); expect(ABSENCE_TYPES.at(-1)).toBe("Sabbatical"); }); it("guards every entry with isAbsenceType", () => { for (const t of ABSENCE_TYPES) expect(isAbsenceType(t)).toBe(true); expect(isAbsenceType("Karenz")).toBe(false); expect(isAbsenceType(null)).toBe(false); }); }); // Eine Teilzeit ist keine Abwesenheit. Wer in Bildungs-, Pflege-, Eltern- // oder Wiedereingliederungsteilzeit als „langzeitabwesend" geführt wurde, // verschwand aus dem Bestand, verlor die Berichtslinie an eine Vertretung und // zählte in Auswertungen nicht mehr mit — obwohl er jede Woche im Haus war, // nur kürzer. const TEILZEITEN = ["Bildungsteilzeit", "Elternteilzeit", "Wiedereingliederungsteilzeit", "Pflegeteilzeit"]; describe("Teilzeiten sind keine Abwesenheiten", () => { it("führt keine Teilzeit mehr als Abwesenheit", () => { for (const t of TEILZEITEN) { expect(ABSENCE_TYPES).not.toContain(t); expect(isAbsenceType(t)).toBe(false); } }); it("behält die Karenzen — sie setzen aus, statt zu reduzieren", () => { // Die Wörter ähneln sich, die Sachverhalte nicht: Bildungskarenz ist // eine Abwesenheit, Bildungsteilzeit sind weniger Stunden. for (const t of ["Elternkarenz (inkl. Väterkarenz)", "Bildungskarenz", "Pflegekarenz"]) { expect(ABSENCE_TYPES).toContain(t); } }); }); describe("Gründe für weniger Stunden", () => { it("bietet bei der Rückkehr die zwei an, die dort hingehören", () => { expect([...RUECKKEHR_GRUENDE]).toEqual(["Wiedereingliederungsteilzeit", "Elternteilzeit"]); }); it("bietet bei der Stundenänderung die übrigen an, mit dem Normalfall zuerst", () => { expect(STUNDEN_GRUENDE[0]).toBe("Vertragliche Stundenänderung"); expect([...STUNDEN_GRUENDE]).toContain("Bildungsteilzeit"); expect([...STUNDEN_GRUENDE]).toContain("Pflegeteilzeit"); }); it("verteilt die vier Teilzeiten vollständig und ohne Überschneidung", () => { // Keine darf verlorengehen, und keine an beiden Stellen auftauchen — // sonst hinge dieselbe Sache an zwei Vorgängen. const verteilt = [...RUECKKEHR_GRUENDE, ...STUNDEN_GRUENDE].filter((g) => TEILZEITEN.includes(g)); expect(new Set(verteilt)).toEqual(new Set(TEILZEITEN)); expect(verteilt.length).toBe(TEILZEITEN.length); }); });