Die Historie bekommt ihre eigenen Farben
In "Letzte Aktivitaeten" stand "Eintritt" weiter auf Rosa, waehrend die Karte daneben ihn laengst gruen zeigte. Dieselbe Ursache wie bei den Anstehend-Chips, nur eine Ecke weiter: die Uebersicht zeigt Ereignisse aus employee_history, holte ihre Farbe aber aus ACTION_CATEGORY — und das ist die Sprache des Protokolls. Dort heisst es "Neueinstellung" und "Wiedereinstellung", in der Historie "Eintritt" und "Wiedereintritt". Genau diese zwei von elf standen nicht darin und fielen auf den neutralen Chip zurueck; die uebrigen neun trafen zufaellig. EVENT_CATEGORY ist jetzt die Zuordnung fuer die Historie, als Record<HistoryEventType, …> und damit vollzaehlig: ein zwoelftes Ereignis laesst der Typpruefer nicht durch, ohne dass jemand eine Farbe dafuer bestimmt. Ein Nachschlagen mit Rueckfall haette auch dann wieder still etwas Plausibles geliefert. Betroffen war nicht nur die Uebersicht — der Historie-Reiter in der Personalakte faerbte seine Chips und seine Filterknoepfe aus derselben falschen Tabelle. Auch die sind umgestellt. Die Punkte vor den Zeilen lagen in einer zweiten Tabelle in page.tsx und sagten fuer "Eintritt" bereits gruen — Punkt und Chip derselben Zeile kamen also aus zwei Verzeichnissen, von denen eines das falsche war. Beide leiten jetzt aus EVENT_CATEGORY ab. Die Rueckkehr ist dabei violett geworden, auch in der Historie: auf der Uebersicht steht sie neben dem Eintritt, und zwei Gruentoene nebeneinander sind keine zwei Dinge. ANSTEHEND_STYLES leitet fuer Eintritt, Austritt und Rueckkehr aus derselben Tabelle ab — die beiden Karten koennen nicht mehr auseinanderlaufen. ACTION_CATEGORY behaelt seinen Rueckfall, und das bleibt richtig: die Aktionen schreiben die SQL-Funktionen als freien Text, eine neue kann jederzeit dazukommen, und ihr neutraler Chip ist dann eine ehrliche Aussage. Fuer eine geschlossene Aufzaehlung war derselbe Rueckfall ein Fehler. Acht Tests, aus EVENT_TYPE_LABELS abgeleitet statt abgeschrieben: dass jedes Ereignis eine Farbe hat, dass keines den neutralen Chip bekommt, dass Punkt und Chip derselben Zeile zusammenpassen und dass die beiden Karten der Uebersicht dasselbe meinen. Lint, Typen, Schemaabgleich, 575 Tests und der Build sind sauber. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,16 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { actionBadgeStyle, avatarColorFor, CATEGORY_STYLES, STATUS_STYLES } from "@/lib/colors";
|
||||
import {
|
||||
actionBadgeStyle,
|
||||
ANSTEHEND_STYLES,
|
||||
avatarColorFor,
|
||||
CATEGORY_STYLES,
|
||||
EVENT_CATEGORY,
|
||||
eventBadgeStyle,
|
||||
eventDotStyle,
|
||||
STATUS_STYLES,
|
||||
} from "@/lib/colors";
|
||||
import { EVENT_TYPE_LABELS } from "@/lib/reports";
|
||||
import type { HistoryEventType } from "@/lib/types";
|
||||
|
||||
describe("avatarColorFor", () => {
|
||||
it("is deterministic for the same seed", () => {
|
||||
@@ -31,3 +42,76 @@ describe("actionBadgeStyle", () => {
|
||||
expect(actionBadgeStyle("Irgendwas Unbekanntes")).toBe(CATEGORY_STYLES.brand);
|
||||
});
|
||||
});
|
||||
|
||||
// ═══ Historie: die Sprache von employee_history, nicht die des Protokolls ═══
|
||||
//
|
||||
// Die Uebersicht und der Historie-Reiter zeigen Ereignisse der Personalakte,
|
||||
// holten ihre Farbe aber aus der Tabelle der Protokoll-Aktionen. Die kennt
|
||||
// „Neueinstellung" und „Wiedereinstellung"; die Historie sagt „Eintritt" und
|
||||
// „Wiedereintritt". Genau diese zwei standen dort nicht und bekamen den
|
||||
// neutralen Chip — in „Letzte Aktivitaeten" war „Eintritt" rosa, waehrend die
|
||||
// Karte daneben ihn laengst gruen zeigte.
|
||||
describe("eventBadgeStyle", () => {
|
||||
// Aus EVENT_TYPE_LABELS abgeleitet und nicht abgeschrieben: kaeme ein
|
||||
// zwoelftes Ereignis dazu, prueft dieser Test es mit.
|
||||
const ALLE = Object.keys(EVENT_TYPE_LABELS) as HistoryEventType[];
|
||||
|
||||
it("kennt jedes Ereignis der Personalakte", () => {
|
||||
expect(ALLE.length).toBeGreaterThan(0);
|
||||
for (const typ of ALLE) {
|
||||
expect(EVENT_CATEGORY[typ], typ).toBeDefined();
|
||||
}
|
||||
});
|
||||
|
||||
it("gibt keinem Ereignis den neutralen Chip", () => {
|
||||
// Der neutrale Chip heisst „keine eigene Bedeutung". Fuer ein Ereignis
|
||||
// der Personalakte ist das nie die Wahrheit, sondern immer ein
|
||||
// Nachschlagen, das danebengegriffen hat.
|
||||
for (const typ of ALLE) {
|
||||
expect(eventBadgeStyle(typ), typ).not.toBe(CATEGORY_STYLES.brand);
|
||||
}
|
||||
});
|
||||
|
||||
it("faerbt Eintritt und Wiedereintritt gruen", () => {
|
||||
expect(eventBadgeStyle("Eintritt")).toBe(CATEGORY_STYLES.success);
|
||||
expect(eventBadgeStyle("Wiedereintritt")).toBe(CATEGORY_STYLES.success);
|
||||
});
|
||||
|
||||
it("faerbt den Austritt rot", () => {
|
||||
expect(eventBadgeStyle("Austritt")).toBe(CATEGORY_STYLES.danger);
|
||||
});
|
||||
|
||||
it("gibt Punkt und Chip derselben Zeile dieselbe Kategorie", () => {
|
||||
// Beide leiten aus EVENT_CATEGORY ab; vorher lagen sie in zwei
|
||||
// getrennten Verzeichnissen und eines davon war das falsche.
|
||||
for (const typ of ALLE) {
|
||||
expect(eventDotStyle(typ), typ).toContain(
|
||||
eventBadgeStyle(typ).match(/text-([a-z]+)-text/)?.[1] ?? "###"
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe("Uebersicht: beide Karten meinen dasselbe", () => {
|
||||
// Anstehend und Letzte Aktivitaeten stehen nebeneinander. Ein Eintritt darf
|
||||
// links nicht anders aussehen als rechts — genau das war zu sehen.
|
||||
it("Eintritt, Austritt und Rueckkehr stimmen ueberein", () => {
|
||||
expect(ANSTEHEND_STYLES.hire).toBe(eventBadgeStyle("Eintritt"));
|
||||
expect(ANSTEHEND_STYLES.exit).toBe(eventBadgeStyle("Austritt"));
|
||||
expect(ANSTEHEND_STYLES.return).toBe(eventBadgeStyle("Rückkehr"));
|
||||
});
|
||||
|
||||
it("haelt die vier Arten voneinander getrennt", () => {
|
||||
const werte = Object.values(ANSTEHEND_STYLES);
|
||||
expect(new Set(werte).size).toBe(werte.length);
|
||||
});
|
||||
});
|
||||
|
||||
// Das Protokoll behaelt seinen Rueckfall, und das ist richtig: die Aktionen
|
||||
// schreiben die SQL-Funktionen als freien Text, eine neue kann jederzeit
|
||||
// dazukommen. Ihr neutraler Chip ist dann eine ehrliche Aussage.
|
||||
describe("actionBadgeStyle bleibt offen", () => {
|
||||
it("faengt eine unbekannte Aktion mit dem neutralen Chip auf", () => {
|
||||
expect(actionBadgeStyle("Eine neue Aktion aus einer Migration")).toBe(CATEGORY_STYLES.brand);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user