Print a checklist without printing the application around it
The checklist gets a print view: one A4 page, header carrying personnel number, name, date of extract, entry date and position, the items in two flowing columns so twenty-five fit, and two signature lines at the foot. It prints the *state*, dated — not a blank form. The default filename in the save dialog comes from the document title, which is set to the agreed convention: 20260818_2884_Aigner-Manuel_Onboarding-Checklist Surname first, like everywhere else in the application, so a folder of these sorts by person and within a person by date. Umlauts are resolved rather than stripped: the naive route (NFKD, then every non-ASCII to a dash) turns "Müller" into "Mu-ller", because decomposition splits the umlaut and the diaeresis becomes the dash. "Weiß" needs its own rule — it has no decomposition and would otherwise vanish. The reported defect: the printout carried the application's own top bar — hamburger, bell, "Neueinstellung", sign-out. Those are controls; on paper they are decoration, and on a checklist filed in a personnel record, misleading. The rule now sits on AppShell rather than on this one page, so the org-chart print view — which had the same problem — gets it too, along with anything printed later. The shell's padding goes with it: the type area is set by @page on the print page itself, and the shell's would have been added on top. The browser's own header line (date, title, URL) is separate — that is a checkbox in the print dialog, not something CSS can reach. 440 tests pass, including 13 new ones pinning the filename convention. Not yet seen in a browser. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
92
tests/unit/checklist-print.test.ts
Normal file
92
tests/unit/checklist-print.test.ts
Normal file
@@ -0,0 +1,92 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { artLabel, artTitel, checklistDateiname, dateiSicher, parseArt } from "@/lib/checklist-print";
|
||||
|
||||
// Der Dateiname ist eine Absprache, nicht eine Laune: die Dateien landen in
|
||||
// einer Personalakte, und dort sortiert und findet man sie nur, wenn alle
|
||||
// gleich heissen. Deshalb steht die Konvention hier fest und wird geprüft.
|
||||
|
||||
const PERSON = { personnel_number: 2884, first_name: "Manuel", last_name: "Aigner" };
|
||||
|
||||
describe("checklistDateiname", () => {
|
||||
it("folgt der Konvention YYYYMMDD_PersNr_Name_Liste", () => {
|
||||
expect(checklistDateiname("onboarding", PERSON, "2026-08-18")).toBe("20260818_2884_Aigner-Manuel_Onboarding-Checklist");
|
||||
});
|
||||
|
||||
it("unterscheidet Ein- und Ausstieg", () => {
|
||||
expect(checklistDateiname("offboarding", PERSON, "2026-08-18")).toBe(
|
||||
"20260818_2884_Aigner-Manuel_Offboarding-Checklist"
|
||||
);
|
||||
});
|
||||
|
||||
it("stellt den Nachnamen voran — wie überall in der Anwendung", () => {
|
||||
// So sortiert sich ein Ordner voller solcher Dateien nach Person, und
|
||||
// innerhalb einer Person nach Datum, weil das Datum vorne steht.
|
||||
const name = checklistDateiname("onboarding", PERSON, "2026-08-18");
|
||||
expect(name.indexOf("Aigner")).toBeLessThan(name.indexOf("Manuel"));
|
||||
});
|
||||
|
||||
it("nimmt das Auszugsdatum, nicht das Eintrittsdatum", () => {
|
||||
expect(checklistDateiname("onboarding", PERSON, "2012-08-07")).toContain("20120807");
|
||||
});
|
||||
|
||||
it("verträgt einen Zeitstempel als Datum", () => {
|
||||
expect(checklistDateiname("onboarding", PERSON, "2026-08-18T09:31:00.000Z")).toContain("20260818");
|
||||
});
|
||||
});
|
||||
|
||||
describe("dateiSicher", () => {
|
||||
it("löst Umlaute auf, ohne einen Trennstrich hineinzuschmuggeln", () => {
|
||||
// Der naive Weg (NFKD, dann alles Nicht-ASCII zu „-") macht aus „Müller"
|
||||
// ein „Mu-ller": die Zerlegung trennt den Umlaut in u + Trema, und der
|
||||
// Trema wird zum Strich.
|
||||
expect(dateiSicher("Müller")).toBe("Muller");
|
||||
expect(dateiSicher("Öztürk")).toBe("Ozturk");
|
||||
expect(dateiSicher("Šimić")).toBe("Simic");
|
||||
});
|
||||
|
||||
it("schreibt das scharfe S aus", () => {
|
||||
// Es hat keine Zerlegung — ohne eigene Regel fiele es ganz weg.
|
||||
expect(dateiSicher("Weiß")).toBe("Weiss");
|
||||
});
|
||||
|
||||
it("ersetzt Zeichen, die in Dateinamen Ärger machen", () => {
|
||||
expect(dateiSicher("O'Brien")).toBe("O-Brien");
|
||||
expect(dateiSicher("van der Berg")).toBe("van-der-Berg");
|
||||
expect(dateiSicher("Meier/Huber")).toBe("Meier-Huber");
|
||||
});
|
||||
|
||||
it("lässt keine Striche am Rand stehen", () => {
|
||||
expect(dateiSicher(" Aigner ")).toBe("Aigner");
|
||||
expect(dateiSicher("-Aigner-")).toBe("Aigner");
|
||||
});
|
||||
|
||||
it("zieht mehrere Sonderzeichen zu einem Strich zusammen", () => {
|
||||
expect(dateiSicher("Aigner Maier")).toBe("Aigner-Maier");
|
||||
});
|
||||
});
|
||||
|
||||
describe("parseArt", () => {
|
||||
it("nimmt offboarding, wenn es dasteht", () => {
|
||||
expect(parseArt("offboarding")).toBe("offboarding");
|
||||
});
|
||||
|
||||
it("fällt auf onboarding zurück — auch bei Unsinn in der Adresse", () => {
|
||||
// Der Wert landet in einem Tabellennamen und im Dateinamen; was nicht in
|
||||
// der Liste steht, kommt nicht durch.
|
||||
expect(parseArt(undefined)).toBe("onboarding");
|
||||
expect(parseArt("")).toBe("onboarding");
|
||||
expect(parseArt("offboarding_tasks; drop")).toBe("onboarding");
|
||||
expect(parseArt("ONBOARDING")).toBe("onboarding");
|
||||
});
|
||||
});
|
||||
|
||||
describe("Beschriftungen", () => {
|
||||
it("nennt die Liste im Dateinamen englisch, im Titel deutsch", () => {
|
||||
// Der Dateiname folgt der Vorgabe („Onboarding-Checklist"), die Seite
|
||||
// spricht die Sprache der Anwendung.
|
||||
expect(artLabel("onboarding")).toBe("Onboarding-Checklist");
|
||||
expect(artTitel("onboarding")).toBe("Onboarding-Checkliste");
|
||||
expect(artLabel("offboarding")).toBe("Offboarding-Checklist");
|
||||
expect(artTitel("offboarding")).toBe("Offboarding-Checkliste");
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user