Server lassen sich anlegen, prüfen, bearbeiten und löschen. Proxmox liefert ab Werk ein selbst signiertes Zertifikat; der Admin sieht es vor dem Speichern und bestätigt den SHA-256-Fingerprint. Der Pin wird in einem eigenen undici-Connector geprüft, sodass eine fremde Gegenstelle das Token nie zu sehen bekommt. Weder Prüfung noch Pin ist im Schema, im Client und per CHECK ausgeschlossen. Fehler von Proxmox werden zu Ursache und Hinweis; bei 403 nennt der Hinweis das fehlende Recht samt Pfad. Getestet gegen einen HTTPS-Mock und im gebauten Stand auf Desktop und 390 px. Closes #002 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
52 lines
2.2 KiB
TypeScript
52 lines
2.2 KiB
TypeScript
import { expect, test } from "@playwright/test";
|
||
import { anmelden as anmeldenZu, keinQuerscrollen } from "./helfer";
|
||
|
||
async function anmelden(page: import("@playwright/test").Page) {
|
||
await anmeldenZu(page);
|
||
await expect(page.getByRole("heading", { name: "Übersicht" })).toBeVisible();
|
||
}
|
||
|
||
test("falsches Passwort zeigt eine Meldung mit Symbol und Text", async ({ page }) => {
|
||
await page.goto("/anmelden");
|
||
// Eigener Name: Fehlversuche zählen je Benutzer, der echte Admin soll nie gesperrt werden.
|
||
await page.getByLabel("Benutzername").fill("e2e-unbekannt");
|
||
await page.getByLabel("Passwort").fill("falsch-falsch");
|
||
await page.getByRole("button", { name: "Anmelden" }).click();
|
||
// Wenn die Seite nicht hydriert, passiert hier nichts – das ist die eigentliche Prüfung.
|
||
await expect(page.getByText("Benutzername oder Passwort ist falsch.")).toBeVisible();
|
||
await expect(page.getByText("✗")).toBeVisible();
|
||
});
|
||
|
||
test("Anmelden, Übersicht, Abmelden", async ({ page }) => {
|
||
await anmelden(page);
|
||
await keinQuerscrollen(page);
|
||
await page.screenshot({ path: `test-results/uebersicht-${test.info().project.name}.png`, fullPage: true });
|
||
|
||
if (test.info().project.name === "handy") {
|
||
await page.getByRole("button", { name: "Navigation öffnen" }).click();
|
||
}
|
||
await page.getByRole("button", { name: "Abmelden" }).click();
|
||
await expect(page).toHaveURL(/\/anmelden/);
|
||
});
|
||
|
||
test("Theme-Wechsel bleibt nach dem Neuladen erhalten", async ({ page }) => {
|
||
await anmelden(page);
|
||
await expect(page.locator("html")).toHaveAttribute("data-theme", "dunkel");
|
||
if (test.info().project.name === "handy") {
|
||
await page.getByRole("button", { name: "Navigation öffnen" }).click();
|
||
}
|
||
await page.getByRole("button", { name: "Helles Theme einschalten" }).click();
|
||
await expect(page.locator("html")).toHaveAttribute("data-theme", "hell");
|
||
await page.reload();
|
||
await expect(page.locator("html")).toHaveAttribute("data-theme", "hell");
|
||
await page.screenshot({
|
||
path: `test-results/uebersicht-hell-${test.info().project.name}.png`,
|
||
fullPage: true,
|
||
});
|
||
});
|
||
|
||
test("Anmeldeseite ohne Querscrollen", async ({ page }) => {
|
||
await page.goto("/anmelden");
|
||
await keinQuerscrollen(page);
|
||
});
|