Files
alpenwerk-hr/tests/unit/employee-search.test.ts
Andrei Laas cf5ed5c6c6
Some checks failed
CI / Migrationen auf leerer Datenbank (push) Has been cancelled
CI / Lint, Typen, Tests, Build (push) Successful in 11m17s
Vier Befunde, die still falsche Ergebnisse lieferten
C.08 -- die Suche mit Bindestrich fand nichts. Das Feld wird per translate an
"-/:.," in Leerzeichen zerlegt, die Eingabe aber nicht: "Mueller-Weiss" erzeugte
das Muster mueller-weiss%, waehrend im Heuhaufen "mueller weiss" stand. Ohne
Bindestrich fand man dieselbe Person. Die Trennzeichen stehen jetzt einmal in
lib/employee-search.ts und werden von beiden Seiten des Vergleichs benutzt.

C.09 -- der Einheitenfilter verlor jede Person mit vorgemerktem Austritt.
"Laufend" war valid_to is null, aber terminate_employee setzt das Ende schon
beim Erfassen, Monate vor dem Tag. Jetzt zaehlt auch, was noch laeuft
(valid_to > heute). Bewusst ohne valid_from <= heute: ein geplanter Eintritt
gehoert in die Liste, sonst fiele er aus dem Filter, obwohl der Status
"Geplant" ihn ausdruecklich fuehrt.

E.07 -- nur die Kostenstelle zu aendern war unmoeglich. update_position weist
einen Aufruf ohne Aenderung ab, und die Umkontierung lief erst bei dessen
Erfolg. Sie wird jetzt uebersprungen, wenn sich an den Stammangaben nichts
geaendert hat.

H.06 -- jedes Speichern erzeugte zusaetzlich "Wochenstunden 30.0 -> 30". Der
Vergleich laeuft ueber Text, die Spalte ist numeric(4,1), und das Formular
schickt 30. Der Kommentar an der Zeile nannte die Absicht richtig, nur reicht
::numeric dafuer nicht -- es muss auf die Genauigkeit der Spalte gehen.
2026-09-29 19:47:48 +02:00

92 lines
3.6 KiB
TypeScript

import { describe, expect, it } from "vitest";
import { istPersonalnummer, suchMuster, TRENNZEICHEN, TRENNZEICHEN_ERSATZ } from "@/lib/employee-search";
// Der Anlass: „Winkler H" gab alle sieben Winkler zurück statt der einen
// Hannah. Das „H" wurde als Teilzeichenkette gesucht und traf damit T-h-omas,
// Kat-h-arina und CNC-Dre-h-er:in.
//
// Was hier geprüft wird, ist die Musterbildung. Dass „am Wortanfang" auch
// wirklich am Wortanfang trifft, entscheidet das SQL der Seite — und ist
// gegen die laufende Datenbank belegt: „winkler h" liefert dort genau Hannah
// Winkler, „winkler kat" die beiden Katharinas, „dreher" die CNC-Dreher:innen.
describe("istPersonalnummer", () => {
it("erkennt reine Ziffern", () => {
expect(istPersonalnummer("3038")).toBe(true);
expect(istPersonalnummer(" 3038 ")).toBe(true);
});
it("hält alles andere für einen Namen", () => {
for (const t of ["winkler", "winkler 3038", "3038a", "", " "]) {
expect(istPersonalnummer(t)).toBe(false);
}
});
});
describe("suchMuster", () => {
it("macht aus jedem Wort ein Paar: am Anfang, und nach einem Leerzeichen", () => {
expect(suchMuster("winkler")).toEqual([["winkler%", "% winkler%"]]);
});
it("behandelt jedes Wort einzeln", () => {
expect(suchMuster("winkler h")).toEqual([
["winkler%", "% winkler%"],
["h%", "% h%"],
]);
});
it("zerlegt an denselben Zeichen wie das Feld, gegen das verglichen wird", () => {
// Das Feld wird per translate an TRENNZEICHEN in Leerzeichen zerlegt. Tat
// es nur das Feld, erzeugte „Müller-Weiß" das Muster „müller-weiß%",
// während im Heuhaufen „müller weiß" stand: null Treffer, obwohl die
// Person da ist. Ohne Bindestrich fand man sie. (C.08, 29.09.)
expect(suchMuster("müller-weiß")).toEqual([
["müller%", "% müller%"],
["weiß%", "% weiß%"],
]);
});
it("zerlegt an jedem der Trennzeichen", () => {
for (const zeichen of [...TRENNZEICHEN]) {
expect(suchMuster(`abc${zeichen}def`), `„${zeichen}" trennt nicht`).toEqual([
["abc%", "% abc%"],
["def%", "% def%"],
]);
}
});
it("findet dieselbe Person mit und ohne Bindestrich", () => {
expect(suchMuster("müller-weiß")).toEqual(suchMuster("müller weiß"));
});
it("hält Trennzeichen und Ersatz gleich lang", () => {
// translate() ordnet Zeichen für Zeichen zu. Wäre der Ersatz kürzer,
// fielen die überzähligen Trennzeichen ersatzlos weg und „Müller-Weiß"
// würde im Feld zu „müllerweiß" — die Suche fände es dann wieder nicht.
expect(TRENNZEICHEN_ERSATZ).toHaveLength(TRENNZEICHEN.length);
expect(TRENNZEICHEN_ERSATZ.trim()).toBe("");
});
it("kennt keinen Platzhalter mitten im Wort", () => {
// Das ist der Kern: „h%" trifft Hannah, „%h%" träfe auch Thomas.
const [, [amAnfang]] = suchMuster("winkler h");
expect(amAnfang.startsWith("%")).toBe(false);
});
it("schreibt klein, damit der Vergleich unabhängig von der Schreibweise ist", () => {
expect(suchMuster("WINKLER")).toEqual([["winkler%", "% winkler%"]]);
});
it("verträgt beliebig viel Abstand und Rand", () => {
expect(suchMuster(" winkler h ")).toHaveLength(2);
expect(suchMuster(" ")).toEqual([]);
});
it("entschärft die Platzhalter von LIKE", () => {
// Sonst wäre „%" eine Suche nach allem und „_" nach beliebigem Zeichen.
expect(suchMuster("100%")).toEqual([["100\\%%", "% 100\\%%"]]);
expect(suchMuster("a_b")).toEqual([["a\\_b%", "% a\\_b%"]]);
expect(suchMuster("a\\b")).toEqual([["a\\\\b%", "% a\\\\b%"]]);
});
});