Anforderung 1 — Freiwilliger vs unfreiwilliger Austritt. Die Liste der Beendigungsarten zieht aus TerminatePanel.tsx nach lib/beendigung.ts um: der Berichtemanager braucht sie ebenso, und zwei Listen liefen auseinander. Zwei neue Arten (Beendigung in der Probezeit, je Seite). Auf wessen Betreiben beendet wurde, wird aus der Art **abgeleitet** und nicht daneben gespeichert — als zweites freies Feld liesse sich "Entlassung, freiwillig" erfassen. Das Dropdown im Formular schraenkt die Auswahl darunter ein. Drei Gruppen statt zwei: Befristungsablauf geschieht auf niemandes Betreiben, ein Nichtantritt ist kein Austritt. Beide einer Seite zuzuschlagen wuerde jede Fluktuationsquote verfaelschen. Anforderung 2 — Namensfilter in "Anstehend", ab neun Eintraegen. Anforderung 3 — die zwei Unterschriftenfelder im gedruckten Blatt sind weg; "Firmenfahrzeug" steht in beiden Checklisten. has_dienstwagen sagt, ob eines zusteht, nicht ob es uebergeben wurde. Anforderung 4 — "+794 weitere" ist ein Knopf geworden; die Namen waren vorher nur ueber den Export erreichbar. Stammdatenaenderung und Gehaltsanpassung stehen nicht mehr zur Auswahl: die eine entsteht bei jeder geaenderten Telefonnummer, die andere ist ein totes Ereignis, seit das Gehalt in Loga liegt. Neu ist der Untertyp — Beendigungsart beim Austritt, Art der Abwesenheit bei der Langzeitabwesenheit, im Bericht und im Export. Anforderung 10 — zwei Kacheln. "Aktives Dienstverhaeltnis" ist nicht dasselbe wie "Aktive Mitarbeiter:innen": dort steht, wer heute arbeitet, hier, mit wem ein Vertrag laeuft. Sichtbar waren 806 und 10, addieren musste man selbst.
133 lines
5.2 KiB
TypeScript
133 lines
5.2 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import {
|
|
ONBOARDING_GRUPPEN,
|
|
ONBOARDING_PUNKTE,
|
|
fortschritt,
|
|
istErledigt,
|
|
punktZu,
|
|
wertIstGueltig,
|
|
type AufgabenStand,
|
|
} from "@/lib/onboarding";
|
|
|
|
// Die Checkliste kommt von einem Blatt Papier. Was dort ein Kästchen war, ist
|
|
// hier nicht überall eines: „Prämienanspruch" hatte zwei Kästchen (ja | nein),
|
|
// und die Grössen waren Felder zum Hineinschreiben. Die Feldart trägt also
|
|
// eine fachliche Aussage — deshalb wird sie hier festgehalten.
|
|
|
|
function stand(teil: Partial<AufgabenStand> & { item_key: string }): AufgabenStand {
|
|
return { erledigt: false, wert: null, kommentar: null, updated_at: null, updated_by_name: null, ...teil };
|
|
}
|
|
|
|
describe("Das Verzeichnis", () => {
|
|
it("hat eindeutige Schlüssel — sie stehen in den Daten", () => {
|
|
const keys = ONBOARDING_PUNKTE.map((p) => p.key);
|
|
expect(new Set(keys).size).toBe(keys.length);
|
|
});
|
|
|
|
it("bildet jeden Punkt aus dem Blatt ab", () => {
|
|
// 25 vom Blatt, dazu „Firmenfahrzeug" aus dem Workshop.
|
|
expect(ONBOARDING_PUNKTE).toHaveLength(26);
|
|
for (const key of ["dienstzettel", "meldezettel", "salmonellenbefund", "willkommensmappe", "webreise", "firmenfahrzeug"]) {
|
|
expect(punktZu(key), key).toBeDefined();
|
|
}
|
|
});
|
|
|
|
it("führt Prämienanspruch als Ja/Nein, nicht als Haken", () => {
|
|
// Zwei Kästchen im Blatt, und das ist kein Zufall: „nein" ist ein
|
|
// erhobener Befund, „noch nicht gefragt" nicht.
|
|
expect(punktZu("praemienanspruch")?.art).toBe("janein");
|
|
});
|
|
|
|
it("führt die Grössen als Text", () => {
|
|
// Abgehakt wäre eine Schuhgrösse wertlos.
|
|
for (const key of ["groesse_schuhe", "groesse_tshirt", "groesse_hose"]) {
|
|
expect(punktZu(key)?.art, key).toBe("text");
|
|
}
|
|
});
|
|
|
|
it("gruppiert vollständig — kein Punkt fällt zwischen die Gruppen", () => {
|
|
const ausGruppen = ONBOARDING_GRUPPEN.flatMap((g) => g.punkte.map((p) => p.key));
|
|
expect(new Set(ausGruppen)).toEqual(new Set(ONBOARDING_PUNKTE.map((p) => p.key)));
|
|
});
|
|
});
|
|
|
|
describe("istErledigt", () => {
|
|
const haken = punktZu("meldezettel")!;
|
|
const janein = punktZu("praemienanspruch")!;
|
|
const text = punktZu("groesse_schuhe")!;
|
|
|
|
it("zählt einen gesetzten Haken", () => {
|
|
expect(istErledigt(haken, stand({ item_key: haken.key, erledigt: true }))).toBe(true);
|
|
expect(istErledigt(haken, stand({ item_key: haken.key }))).toBe(false);
|
|
});
|
|
|
|
it("zählt bei Ja/Nein auch ein Nein als erledigt", () => {
|
|
// Die Aufgabe war, die Frage zu beantworten — nicht, sie zu bejahen.
|
|
expect(istErledigt(janein, stand({ item_key: janein.key, wert: "nein" }))).toBe(true);
|
|
expect(istErledigt(janein, stand({ item_key: janein.key, wert: "ja" }))).toBe(true);
|
|
expect(istErledigt(janein, stand({ item_key: janein.key }))).toBe(false);
|
|
});
|
|
|
|
it("zählt bei Text die Angabe selbst, nicht den Haken", () => {
|
|
expect(istErledigt(text, stand({ item_key: text.key, wert: "43" }))).toBe(true);
|
|
expect(istErledigt(text, stand({ item_key: text.key, wert: " " }))).toBe(false);
|
|
// Ein Haken ohne Angabe wäre eine leere Behauptung.
|
|
expect(istErledigt(text, stand({ item_key: text.key, erledigt: true }))).toBe(false);
|
|
});
|
|
|
|
it("hält eine fehlende Zeile für offen", () => {
|
|
expect(istErledigt(haken, undefined)).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe("fortschritt", () => {
|
|
it("ist auf einer leeren Liste vollständig offen", () => {
|
|
const f = fortschritt([]);
|
|
expect(f.erledigt).toBe(0);
|
|
expect(f.gesamt).toBe(ONBOARDING_PUNKTE.length);
|
|
expect(f.offen).toHaveLength(ONBOARDING_PUNKTE.length);
|
|
});
|
|
|
|
it("nennt die offenen Punkte beim Namen, nicht beim Schlüssel", () => {
|
|
// Die Zahl allein sagt nicht, worauf noch gewartet wird.
|
|
expect(fortschritt([]).offen).toContain("Meldezettel");
|
|
expect(fortschritt([]).offen).not.toContain("meldezettel");
|
|
});
|
|
|
|
it("zählt gemischte Arten zusammen", () => {
|
|
const f = fortschritt([
|
|
stand({ item_key: "meldezettel", erledigt: true }),
|
|
stand({ item_key: "praemienanspruch", wert: "nein" }),
|
|
stand({ item_key: "groesse_schuhe", wert: "43" }),
|
|
]);
|
|
expect(f.erledigt).toBe(3);
|
|
expect(f.offen).not.toContain("Meldezettel");
|
|
});
|
|
|
|
it("stört sich nicht an Zeilen zu Punkten, die es nicht mehr gibt", () => {
|
|
// Ein gestrichener Punkt lässt seine Antworten stehen — sie sollen die
|
|
// Zählung weder erhöhen noch zum Absturz führen.
|
|
const f = fortschritt([stand({ item_key: "gibt_es_nicht_mehr", erledigt: true })]);
|
|
expect(f.erledigt).toBe(0);
|
|
expect(f.gesamt).toBe(ONBOARDING_PUNKTE.length);
|
|
});
|
|
});
|
|
|
|
describe("wertIstGueltig", () => {
|
|
it("lässt bei Ja/Nein nur ja, nein oder nichts zu", () => {
|
|
const janein = punktZu("praemienanspruch")!;
|
|
expect(wertIstGueltig(janein, "ja")).toBe(true);
|
|
expect(wertIstGueltig(janein, "nein")).toBe(true);
|
|
expect(wertIstGueltig(janein, null)).toBe(true);
|
|
expect(wertIstGueltig(janein, "vielleicht")).toBe(false);
|
|
});
|
|
|
|
it("lässt bei einem Haken keinen Wert zu", () => {
|
|
expect(wertIstGueltig(punktZu("meldezettel")!, "irgendwas")).toBe(false);
|
|
});
|
|
|
|
it("lässt bei Text alles zu — eine Grösse ist keine Auswahlliste", () => {
|
|
expect(wertIstGueltig(punktZu("groesse_hose")!, "W32/L34")).toBe(true);
|
|
});
|
|
});
|