Implementiert den auf die eigene brigadeId beschränkten Wehr-Bereich: Profil (inkl. Inline-Geocoding via geocodeAddress), Fuhrpark (Fahrzeug per Vorlage oder frei, typisierter Merkmal-Editor), Geräte (Kategorie, Werte, Zuordnung Fahrzeug/„im Gerätehaus") und Benutzerkonten (wehr_admin/wehr_read). - Schema importiert (nicht neu definiert); ASCII-Property wehrfuehrer. - Default-deny dreifach: Layout-Guard requireWehrAdmin() + jede Server Action beginnt mit requireWehrAdmin(); fremde Entities -> notFound() (404). - Validierung an der Grenze (Zod): buildMerkmalValuesSchema validiert Werte typgerecht gegen die serverseitig aufgelösten Definitionen; Rolle auf wehr_admin|wehr_read beschränkt (platform_admin abgelehnt). - upsertMerkmalValues delete-then-insert mit typisierter Drizzle-Tx (kein any); boolean false/num 0 gelten als gesetzt. - argon2id-Einmalpasswort beim Benutzeranlegen; Selbst-Deaktivierung verhindert. - Audit vollständig: brigade.profile_update, vehicle.create/update/delete/status, equipment.create/update/delete/status, user.create/deactivate. - Vorgabewerte aus drei typisierten Spalten (vorgabewert_num/_text/_bool). - i18n via zentraler de.ts; loading/empty/error-konforme Listen. Tests: 22 neue Unit-Tests (vehicle/equipment/brigade-user-Validierung, upsertMerkmalValues) grün; Playwright-Specs verwaltung-fuhrpark + -scoping geschrieben (deferred: kein Server/DB in der Sandbox). Verifikation offline: tsc --noEmit clean, eslint clean, vitest 147 passed, next build exit 0 (alle /verwaltung/*-Routen), drizzle-kit check ohne Drift. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
64 lines
2.6 KiB
TypeScript
64 lines
2.6 KiB
TypeScript
import { test, expect } from "@playwright/test";
|
|
|
|
/**
|
|
* Happy-Path des Wehr-Bereichs: Fuhrpark, Geräte, Profil, Benutzer
|
|
* (Workstream 7).
|
|
*
|
|
* NICHT in der Sandbox ausführbar (kein Server/DB) — deferred. Erwartet einen
|
|
* angemeldeten `wehr_admin` (Fixture aus dem Test-Workstream) und befüllte
|
|
* Taxonomie (Seed/Admin).
|
|
*/
|
|
|
|
test.describe("Verwaltung: Fuhrpark & Benutzer (Happy-Path)", () => {
|
|
test.skip(
|
|
!process.env.E2E_WEHR_ADMIN_STATE,
|
|
"benötigt wehr_admin-Fixture (Test-Workstream)",
|
|
);
|
|
test.use({
|
|
storageState: process.env.E2E_WEHR_ADMIN_STATE ?? { cookies: [], origins: [] },
|
|
});
|
|
|
|
test("Fahrzeug per Vorlage anlegen befüllt typisierte Merkmale", async ({
|
|
page,
|
|
}) => {
|
|
await page.goto("/verwaltung/fahrzeuge/neu");
|
|
await page.getByLabel("Fahrzeug-Vorlage").selectOption({ label: /HLF 2/ });
|
|
// Vorlagen-Merkmale werden nachgeladen (Löschwassertank, Feuerlöschpumpe …).
|
|
await expect(page.getByText("Löschwassertank")).toBeVisible();
|
|
await page.getByLabel("Name").fill("HLF 2 Musterdorf");
|
|
await page.getByRole("button", { name: "Speichern" }).click();
|
|
await expect(page).toHaveURL(/\/verwaltung\/fahrzeuge$/);
|
|
await expect(page.getByText("HLF 2 Musterdorf")).toBeVisible();
|
|
});
|
|
|
|
test("Gerät 'im Gerätehaus' anlegen (keine Fahrzeug-Zuordnung)", async ({
|
|
page,
|
|
}) => {
|
|
await page.goto("/verwaltung/geraete/neu");
|
|
await page.getByLabel("Name").fill("Tragkraftspritze 1");
|
|
await page.getByLabel("Kategorie").selectOption({ index: 1 });
|
|
// Zuordnung bleibt auf 'im Gerätehaus'.
|
|
await page.getByRole("button", { name: "Speichern" }).click();
|
|
await expect(page).toHaveURL(/\/verwaltung\/geraete$/);
|
|
await expect(page.getByText("im Gerätehaus").first()).toBeVisible();
|
|
});
|
|
|
|
test("Profil speichern zeigt Bestätigung", async ({ page }) => {
|
|
await page.goto("/verwaltung/profil");
|
|
await page.getByLabel("Straße").fill("Hauptstraße 1");
|
|
await page.getByLabel("PLZ").fill("3100");
|
|
await page.getByLabel("Ort").fill("St. Pölten");
|
|
await page.getByRole("button", { name: "Speichern" }).click();
|
|
await expect(page.getByText(/gespeichert|geokodiert|geokodiert werden/)).toBeVisible();
|
|
});
|
|
|
|
test("Benutzer anlegen zeigt Einmal-Passwort", async ({ page }) => {
|
|
await page.goto("/verwaltung/benutzer");
|
|
await page.getByLabel("Name").fill("Neue Person");
|
|
await page.getByLabel("E-Mail").fill("neu@ff-musterdorf.at");
|
|
await page.getByLabel("Rolle").selectOption("wehr_read");
|
|
await page.getByRole("button", { name: "Benutzer anlegen" }).click();
|
|
await expect(page.getByText(/Einmal-Passwort/)).toBeVisible();
|
|
});
|
|
});
|