79 lines
3.0 KiB
TypeScript
79 lines
3.0 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
||
import { existsSync } from "node:fs";
|
||
import { NAVIGATION, navigationFuer } from "@/lib/navigation";
|
||
import { darf } from "@/server/auth/rollen";
|
||
import type { Rolle } from "@/generated/prisma/enums";
|
||
|
||
/** Was die Seitenleiste je Betriebsmodus und Rolle zeigt (#005, #007). */
|
||
|
||
function pfadeFuer(modus: "INTERN" | "DIENSTLEISTUNG", rolle: Rolle): string[] {
|
||
return navigationFuer(modus, (recht) => darf(rolle, recht)).map((e) => e.pfad);
|
||
}
|
||
|
||
describe("Seitenleiste nach Betriebsmodus", () => {
|
||
it("zeigt im Modus Intern die Kunden-Ebene nicht", () => {
|
||
const pfade = pfadeFuer("INTERN", "ADMIN");
|
||
expect(pfade).not.toContain("/kunden");
|
||
expect(pfade).toContain("/mitarbeiter");
|
||
});
|
||
|
||
it("zeigt im Modus Dienstleistung Kunden statt Mitarbeiter & Geräte", () => {
|
||
const pfade = pfadeFuer("DIENSTLEISTUNG", "ADMIN");
|
||
expect(pfade).toContain("/kunden");
|
||
expect(pfade).not.toContain("/mitarbeiter");
|
||
});
|
||
});
|
||
|
||
describe("Seitenleiste nach Rolle", () => {
|
||
it("zeigt Admin nur dem Administrator", () => {
|
||
expect(pfadeFuer("INTERN", "ADMIN")).toContain("/admin");
|
||
for (const rolle of ["REDAKTEUR", "TECHNIKER", "LESER"] as const) {
|
||
expect(pfadeFuer("INTERN", rolle), `Rolle ${rolle}`).not.toContain("/admin");
|
||
}
|
||
});
|
||
|
||
it("zeigt einem Leser die fachlichen Bereiche, aber nichts Verwaltendes", () => {
|
||
const pfade = pfadeFuer("INTERN", "LESER");
|
||
expect(pfade).toContain("/");
|
||
expect(pfade).toContain("/laeufe");
|
||
expect(pfade).toContain("/archiv");
|
||
expect(pfade).not.toContain("/admin");
|
||
});
|
||
|
||
it("blendet ohne bekannte Rolle alles Rechtegebundene aus", () => {
|
||
// So sieht die Huelle aus, solange niemand angemeldet ist.
|
||
const pfade = navigationFuer("INTERN", () => false).map((e) => e.pfad);
|
||
expect(pfade).not.toContain("/admin");
|
||
});
|
||
});
|
||
|
||
describe("Aufbau der Eintraege", () => {
|
||
it("verlinkt keinen Eintrag, dessen Seite es noch nicht gibt", () => {
|
||
for (const eintrag of navigationFuer("INTERN")) {
|
||
if (!eintrag.verfuegbar) {
|
||
expect(eintrag.ausIssue, `${eintrag.pfad} braucht eine Issue-Nummer`).toBeGreaterThan(0);
|
||
}
|
||
}
|
||
});
|
||
|
||
it("hat zu jedem verfuegbaren Eintrag auch eine Seite", () => {
|
||
// Das Umstellen von `verfuegbar` ist ein Handgriff im Meilenstein, der die
|
||
// Seite liefert. Wird es zu frueh gemacht, zeigt die Navigation auf eine
|
||
// 404 – und genau das faellt beim Klicken selten auf, weil man die eigene
|
||
// neue Seite kennt und die anderen nicht anfasst.
|
||
for (const eintrag of NAVIGATION) {
|
||
if (!eintrag.verfuegbar) continue;
|
||
const teil = eintrag.pfad === "/" ? "" : eintrag.pfad;
|
||
const seite = new URL(`../src/app/(app)${teil}/page.tsx`, import.meta.url);
|
||
expect(existsSync(seite), `${eintrag.pfad} ist verfuegbar, hat aber keine page.tsx`).toBe(true);
|
||
}
|
||
});
|
||
|
||
it("hat keine doppelten Pfade je Modus", () => {
|
||
for (const modus of ["INTERN", "DIENSTLEISTUNG"] as const) {
|
||
const pfade = pfadeFuer(modus, "ADMIN");
|
||
expect(new Set(pfade).size).toBe(pfade.length);
|
||
}
|
||
});
|
||
});
|