Backend: geraet_instanz-CRUD (Liste/Anlegen/Status ändern inkl. optionalem Fehlbestand pro Gerät/Löschen), pruefintervall_monate in Objektposition- Schemas verdrahtet (Prüfdatum -> naechste_pruefung wird automatisch berechnet, Monatsrechnung ohne neue Dependency). Frontend: GeraeteInstanzenListe ersetzt das Einzel-SN-Feld im Admin-Portal (ObjektPositionenPanel) durch eine Instanz-Liste mit Status/Prüfdatum/ Bemerkung je Exemplar - löst das Karte-14-Kernproblem (mehrere Geräte pro Position). ObjektSection: Anhänger-Kopplung bei Anlage und nachträglich änderbar. Kontroll-Erfassung (PositionCard/KontrollPage) bleibt unverändert - die komplett neue Erfassungs-UI für geraet_sn (Umsetzungsschritt 4, Karte 14) ist bewusst nicht Teil dieses Commits. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
112 lines
3.2 KiB
TypeScript
112 lines
3.2 KiB
TypeScript
import type { Page } from "@playwright/test";
|
|
|
|
/**
|
|
* Gemeinsamer Backend-Mock für alle Kontroll-/Login-Szenarien. Jeder Test ruft
|
|
* nur die Bausteine auf, die er tatsächlich braucht - `mockGrundgeruest`
|
|
* deckt Login+Stammdaten ab, die Kontroll-Endpunkte werden gezielt pro Test
|
|
* überschrieben (z. B. für Sperre/Fehler-Szenarien).
|
|
*/
|
|
export const TEST_OBJEKT = {
|
|
id: 1,
|
|
code: "RK-00001",
|
|
name: "Testrucksack",
|
|
objekttyp_id: 1,
|
|
vorlage_id: 1,
|
|
standort_id: 1,
|
|
status: "aktiv",
|
|
gezogen_von_objekt_id: null,
|
|
};
|
|
|
|
export const TEST_MATERIAL = {
|
|
id: 10,
|
|
name: "Kompresse",
|
|
artikelnummer: null,
|
|
einheit: "Stück",
|
|
materialtyp: "standard",
|
|
kategorie_id: null,
|
|
hersteller: null,
|
|
beschreibung: null,
|
|
code: null,
|
|
warnzeitraum_tage: null,
|
|
aktiv: true,
|
|
};
|
|
|
|
export const TEST_POSITION = {
|
|
id: "pos-1",
|
|
objekt_id: 1,
|
|
material_id: 10,
|
|
sollmenge_override: null,
|
|
sollmenge_effektiv: "10",
|
|
ist_status: "aktiv",
|
|
istmenge: "10",
|
|
seriennummer: null,
|
|
ablaufdatum: null,
|
|
chargennummer: null,
|
|
code: null,
|
|
pruefintervall_monate: null,
|
|
};
|
|
|
|
export const TEST_VORLAGE = {
|
|
id: 1,
|
|
objekttyp_id: 1,
|
|
name: "Test-Vorlage",
|
|
version: 1,
|
|
status: "aktiv",
|
|
positionen: [{ id: 1, vorlage_id: 1, material_id: TEST_MATERIAL.id, fach: null, sollmenge: "10" }],
|
|
};
|
|
|
|
export const TEST_KONTROLLE = {
|
|
id: "kontrolle-1",
|
|
objekt_id: 1,
|
|
benutzer_id: 1,
|
|
status: "in_bearbeitung",
|
|
gestartet_am: new Date().toISOString(),
|
|
beendet_am: null,
|
|
abbruch_grund: null,
|
|
};
|
|
|
|
export async function mockLogin(page: Page, rollen: string[] = ["mitarbeiter"]): Promise<void> {
|
|
await page.route("**/api/v1/auth/login", (route) =>
|
|
route.fulfill({ json: { access_token: "test-token", token_type: "bearer" } })
|
|
);
|
|
await page.route("**/api/v1/auth/me", (route) =>
|
|
route.fulfill({ json: { id: 1, name: "Test", login: "test", rollen } })
|
|
);
|
|
}
|
|
|
|
export async function mockObjektliste(page: Page, objekte: unknown[] = [TEST_OBJEKT]): Promise<void> {
|
|
await page.route("**/api/v1/objekte", (route) => {
|
|
if (route.request().method() === "GET") {
|
|
route.fulfill({ json: objekte });
|
|
} else {
|
|
route.continue();
|
|
}
|
|
});
|
|
}
|
|
|
|
export async function mockKontrolleStart(
|
|
page: Page,
|
|
options: { status?: number; body?: unknown } = {}
|
|
): Promise<void> {
|
|
const { status = 201, body = TEST_KONTROLLE } = options;
|
|
await page.route("**/api/v1/objekte/*/kontrollen", (route) =>
|
|
route.fulfill({ status, json: body })
|
|
);
|
|
}
|
|
|
|
export async function mockKontrollGrundgeruest(page: Page): Promise<void> {
|
|
await page.route(`**/api/v1/objekte/${TEST_OBJEKT.id}`, (route) => route.fulfill({ json: TEST_OBJEKT }));
|
|
await page.route(`**/api/v1/objekte/${TEST_OBJEKT.id}/positionen`, (route) =>
|
|
route.fulfill({ json: [TEST_POSITION] })
|
|
);
|
|
await page.route("**/api/v1/materialien", (route) => route.fulfill({ json: [TEST_MATERIAL] }));
|
|
await page.route(`**/api/v1/vorlagen/${TEST_VORLAGE.id}`, (route) => route.fulfill({ json: TEST_VORLAGE }));
|
|
}
|
|
|
|
export async function login(page: Page): Promise<void> {
|
|
await page.goto("/login");
|
|
await page.getByLabel("Login").fill("mitarbeiter1");
|
|
await page.getByLabel("Passwort").fill("test-passwort-123");
|
|
await page.getByRole("button", { name: "Anmelden" }).click();
|
|
}
|