feat(doku): Anleitung, PDF und Ende-zu-Ende-Abnahme (#36)
This commit was merged in pull request #36.
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { expect, test, type Page } from "@playwright/test";
|
||||
import { expect, test } from "@playwright/test";
|
||||
import "dotenv/config";
|
||||
import { prisma } from "@/lib/db";
|
||||
import { anmelden, kundeWaehlen } from "./helfer";
|
||||
|
||||
/**
|
||||
* Personen und Abteilungen durch die Oberflaeche (#011).
|
||||
@@ -9,7 +10,10 @@ import { prisma } from "@/lib/db";
|
||||
* wirklich in der Datenbank steht: durch Neuladen. Ein Screenshot sagt darueber
|
||||
* nichts (siehe CLAUDE.md, „Oberflaeche pruefen“).
|
||||
*
|
||||
* Voraussetzung: ein **gebauter** Stand laeuft (`pnpm build && pnpm start`).
|
||||
* Voraussetzungen prueft `tests/e2e/global-setup.ts` vor dem ersten Ablauf: ein
|
||||
* **gebauter** Stand antwortet, der Seed-Bestand steht, und der Server liest
|
||||
* dieselbe Datenbank wie dieser Lauf. Alles, was die Ablaeufe hier darueber
|
||||
* hinaus brauchen, legen sie selbst an.
|
||||
*
|
||||
* Aufgeraeumt wird am Ende ueber die Datenbank und nicht ueber die Oberflaeche:
|
||||
* die Anwendung kennt bewusst keinen Loeschweg fuer Personen und Abteilungen
|
||||
@@ -21,20 +25,14 @@ import { prisma } from "@/lib/db";
|
||||
|
||||
const STEMPEL = Date.now();
|
||||
|
||||
async function anmelden(seite: Page) {
|
||||
const email = process.env["SEED_ADMIN_EMAIL"];
|
||||
const passwort = process.env["SEED_ADMIN_PASSWORD"];
|
||||
if (!email || !passwort) throw new Error("SEED_ADMIN_EMAIL und SEED_ADMIN_PASSWORD fehlen.");
|
||||
await seite.goto("/anmelden");
|
||||
await seite.fill('input[name="email"]', email);
|
||||
await seite.fill('input[name="passwort"]', passwort);
|
||||
await Promise.all([seite.waitForURL("**/"), seite.click('button[type="submit"]')]);
|
||||
}
|
||||
/** Nachnamen dieses Durchgangs. Beide Praefixe gehoeren dieser Datei allein. */
|
||||
const PRAEFIX_HAND = "ZZPruef";
|
||||
const PRAEFIX_QUELLE = "ZZQuelle";
|
||||
|
||||
test.describe("Personen", () => {
|
||||
test("legt an, findet über die Suche und deaktiviert", async ({ page }) => {
|
||||
test.slow();
|
||||
const nachname = `ZZPruef${STEMPEL}`;
|
||||
const nachname = `${PRAEFIX_HAND}${STEMPEL}`;
|
||||
await anmelden(page);
|
||||
await page.goto("/mitarbeiter");
|
||||
|
||||
@@ -43,6 +41,7 @@ test.describe("Personen", () => {
|
||||
await page.getByLabel("Vorname").fill("Testa");
|
||||
await page.getByLabel("Nachname").fill(nachname);
|
||||
await page.getByLabel("Mail-Adresse (optional)").fill(`testa.${STEMPEL}@firma.de`);
|
||||
await kundeWaehlen(page);
|
||||
await page.getByRole("button", { name: "Person anlegen" }).click();
|
||||
await expect(page.getByText(`„Testa ${nachname}“ wurde angelegt.`)).toBeVisible();
|
||||
|
||||
@@ -65,12 +64,51 @@ test.describe("Personen", () => {
|
||||
});
|
||||
|
||||
test("sperrt die Stammdaten einer Person aus dem Verzeichnis", async ({ page }) => {
|
||||
// Vorausgesetzt wird die Beispielperson aus `pnpm beispiel:stammdaten`.
|
||||
/*
|
||||
* Die Person legt dieser Ablauf selbst an.
|
||||
*
|
||||
* Vorher hing der Test an „Katrin Winter“ aus `pnpm beispiel:stammdaten` und
|
||||
* schaltete sich mit `test.skip` ab, wenn sie fehlte — gegen eine frisch
|
||||
* eingerichtete Installation also immer. Ein Test, der sich stillschweigend
|
||||
* selbst abschaltet, ist keiner (#018).
|
||||
*
|
||||
* Gesperrt wird an der **Herkunft**, nicht an der Quelle: `ABGLEICH` allein
|
||||
* entscheidet. Die Beispielquelle aus dem Seed kommt trotzdem dran, damit die
|
||||
* Zeile aussieht wie eine echte — sie gibt es nur im Modus INTERN, deshalb
|
||||
* bleibt `quelleId` ohne sie leer, statt den Ablauf rot zu faerben.
|
||||
*/
|
||||
test.slow();
|
||||
const nachname = `${PRAEFIX_QUELLE}${STEMPEL}`;
|
||||
const quelle = await prisma.verzeichnisquelle.findFirst({
|
||||
where: { name: "Firmen-AD (Beispiel)" },
|
||||
select: { id: true },
|
||||
});
|
||||
const kunde = await prisma.kunde.findFirstOrThrow({
|
||||
where: { istEigeneOrganisation: true },
|
||||
select: { id: true },
|
||||
});
|
||||
await prisma.mitarbeiter.create({
|
||||
data: {
|
||||
kundeId: kunde.id,
|
||||
quelleId: quelle?.id ?? null,
|
||||
externeId: quelle ? `e2e-${STEMPEL}` : null,
|
||||
vorname: "Katrin",
|
||||
nachname,
|
||||
anzeigename: `Katrin ${nachname}`,
|
||||
mail: `k.${nachname.toLowerCase()}@firma.example`,
|
||||
upn: `k.${nachname.toLowerCase()}@firma.example`,
|
||||
sam: `k${nachname.toLowerCase()}`,
|
||||
abteilung: "Buchhaltung",
|
||||
titel: "Sachbearbeiterin",
|
||||
herkunft: "ABGLEICH",
|
||||
aktiv: true,
|
||||
},
|
||||
});
|
||||
|
||||
await anmelden(page);
|
||||
await page.goto("/mitarbeiter?suche=kwinter");
|
||||
const treffer = page.getByRole("link", { name: /Katrin Winter/ });
|
||||
test.skip((await treffer.count()) === 0, "Beispiel-Stammdaten fehlen (pnpm beispiel:stammdaten).");
|
||||
await page.goto(`/mitarbeiter?suche=${nachname}`);
|
||||
const treffer = page.getByRole("link", { name: new RegExp(nachname) });
|
||||
await expect(treffer).toHaveCount(1);
|
||||
|
||||
await treffer.click();
|
||||
await page.waitForURL(/\/mitarbeiter\/[^/]+$/);
|
||||
@@ -94,6 +132,7 @@ test.describe("Abteilungen", () => {
|
||||
await formular.getByLabel("Name").fill(name);
|
||||
await formular.getByLabel("Ziel-OU (optional)").fill("OU=Test,DC=firma,DC=de");
|
||||
await formular.getByLabel("Standardgruppen, mit Komma getrennt").fill("G-Test, G-Alle");
|
||||
await kundeWaehlen(page);
|
||||
await formular.getByRole("button", { name: "Abteilung anlegen" }).click();
|
||||
await expect(page.getByText(`„${name}“ wurde angelegt.`)).toBeVisible();
|
||||
|
||||
@@ -105,6 +144,7 @@ test.describe("Abteilungen", () => {
|
||||
// Denselben Namen ein zweites Mal – mit lesbarer Meldung, nicht mit einem
|
||||
// Datenbankfehler.
|
||||
await formular.getByLabel("Name").fill(name);
|
||||
await kundeWaehlen(page);
|
||||
await formular.getByRole("button", { name: "Abteilung anlegen" }).click();
|
||||
await expect(page.getByText(/gibt es schon/)).toBeVisible();
|
||||
|
||||
@@ -116,7 +156,7 @@ test.describe("Abteilungen", () => {
|
||||
|
||||
test.afterAll(async () => {
|
||||
const personen = await prisma.mitarbeiter.findMany({
|
||||
where: { nachname: { startsWith: "ZZPruef" } },
|
||||
where: { OR: [{ nachname: { startsWith: PRAEFIX_HAND } }, { nachname: { startsWith: PRAEFIX_QUELLE } }] },
|
||||
select: { id: true },
|
||||
});
|
||||
const abteilungen = await prisma.abteilung.findMany({
|
||||
|
||||
Reference in New Issue
Block a user