test: Zusagen pruefbar machen, die nur von Hand hielten (#038, #037)
Prüfung / pruefung (push) Canceled after 0s
Prüfung / e2e (push) Canceled after 0s

#038: Die E2E-Ablaeufe laufen ab jetzt vor jedem Merge nach main, nicht vor
jedem Commit. Gemessen: Bau 14 s, Start 7 s, Ablaeufe 256 s — zu den vier
Minuten des bestehenden Tores. Neun Minuten vor jedem Commit ist ein Tor, das
umgangen wird. Vor jedem Merge waeren es in Phase 2 acht Laeufe gewesen, und
jeder der vier Befunde aus #027 waere am Tag seiner Entstehung aufgefallen.

Geprueft wurde jeder der 16 Ablaeufe gegen die Frage, ob es ein
Vitest-Gegenstueck gibt. Neun Zusagen haengen ausschliesslich dort, und keine
laesst sich holen: alle brauchen einen echten Browser. Die Liste steht in
CLAUDE.md.

Der eigentliche Fund dabei war keine Testluecke, sondern eine Konvention ohne
Pruefer: "jede Seite prueft selbst" steht seit #007 in CLAUDE.md, und geprueft
hat es bis hierher nur ein Mensch, der nachsieht. Der Review von Phase 2 hat
alle 27 Seiten durchgesehen — ein Ergebnis, das fuer genau einen Tag gilt.
tests/zugang.test.ts liest sie jetzt, samt jedem Route Handler; die Ausnahmen
(Auth, Healthcheck) stehen namentlich mit Begruendung, und ein Test prueft auch
die Gegenrichtung.

#037: Das Lesemodell der Anhaenge liegt in queries/ und engt selbst ein — vorher
hing das daran, dass beide Aufrufer den Lauf vorher pruefen. /meine-geraete wird
bei 390 px gemessen, mit einem echten MITARBEITER-Konto aus dem E2E-Vorlauf,
dazu ein Test, dass dort kein Link in die Verwaltung angeboten wird.

Dabei selbst einen Fehler gemacht, der die neue Regel begruendet: fuer das
zweite Konto brauchte `anmelden` eine Variante, die nicht auf / wartet, und ich
habe das Warten fuer alle gelockert. Das machte zwei unverwandte Ablaeufe
unzuverlaessig — sichtbar nur im vollen Durchgang, einzeln waren beide gruen.
Ein gemeinsamer Helfer in einer Testsuite ist geteilter Zustand. Ohne vollen
Durchgang haette ich zwei rote Ablaeufe gemergt.

1457 Vitest-Tests (vorher 1454), 115 E2E-Ablaeufe (vorher 113). Offen bleibt nur
noch #024, und das verlangt einen echten Proxmox-Host.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Florian Wilde
2026-10-11 06:05:29 +02:00
co-authored by Claude Opus 5
parent 80d97467da
commit 75c335df23
16 changed files with 639 additions and 80 deletions
+48 -14
View File
@@ -1,10 +1,10 @@
# #037 Zwei Nachzügler aus der Durchsicht von Phase 2
**Status:** offen
**Status:** erledigt
**Im Tracker:** –
**Meilenstein:** v0.3.0
**Meilenstein:** v0.2.0
**Labels:** phase-2, backend, test
**Geschätzt:** 2 h **Tatsächlich:** –
**Geschätzt:** 2 h **Tatsächlich:** 1 h 50 min
## Ziel
@@ -23,11 +23,11 @@ Es steht aber gegen die Regel aus `CLAUDE.md` und `docs/architektur.md` §2: Les
Aufrufer in zwei Schichten gibt es schon; der dritte ist der, der es vergisst — und er wird nicht
auffallen, weil die zwei bestehenden korrekt sind.
- [ ] Nach `src/server/queries/anhaenge.ts` ziehen, mit `HandelnderBenutzer` als Parameter
- [ ] Mandanten- und Rollensicht dort anwenden, nicht beim Aufrufer
- [ ] Test: ein Benutzer, der auf andere Kunden beschränkt ist, bekommt eine leere Liste — **ohne**
- [x] Nach `src/server/queries/anhaenge.ts` ziehen, mit `HandelnderBenutzer` als Parameter
- [x] Mandanten- und Rollensicht dort anwenden, nicht beim Aufrufer
- [x] Test: ein Benutzer, der auf andere Kunden beschränkt ist, bekommt eine leere Liste — **ohne**
dass der Aufrufer vorher geprüft hat
- [ ] Gegenprobe: die Sicht entfernen, der Test muss rot werden
- [x] Gegenprobe: die Sicht entfernen, der Test muss rot werden
## 2. `/meine-geraete` fehlt in der 390-px-Prüfung
@@ -37,17 +37,51 @@ einfach ergänzt werden: sie verlangt das Recht `selbstauskunft`, und das hat nu
Ablauf meldet sich als Admin an und würde die Verweigerungsseite messen — die scrollt garantiert
nicht.
- [ ] Ein `MITARBEITER`-Konto für die Abläufe: lokales Passwort, verknüpft mit einer
- [x] Ein `MITARBEITER`-Konto für die Abläufe: lokales Passwort, verknüpft mit einer
`Mitarbeiter`-Zeile (der CHECK `Benutzer_mitarbeiter_nur_bei_rolle` verlangt die Verknüpfung)
- [ ] Im Seed oder im E2E-Vorlauf? **Im Vorlauf**, denn ein Konto mit bekanntem Passwort gehört
- [x] Im Seed oder im E2E-Vorlauf? **Im Vorlauf**, denn ein Konto mit bekanntem Passwort gehört
nicht in einen Seed, der auch produktiv läuft
- [ ] `/meine-geraete` in die Seitenliste von `mobil.spec.ts`
- [ ] Dabei prüfen, was ein `MITARBEITER` auf den **anderen** Seiten sieht: die Rollenmatrix ist in
- [x] `/meine-geraete` in die Seitenliste von `mobil.spec.ts`
- [x] Dabei prüfen, was ein `MITARBEITER` auf den **anderen** Seiten sieht: die Rollenmatrix ist in
Vitest vollständig, aber kein Ablauf klickt sie durch
## Akzeptanzkriterien
- [ ] `anhaengeDesLaufs` liegt in `queries/`, und ein Test belegt die Sicht ohne Vorprüfung des
- [x] `anhaengeDesLaufs` liegt in `queries/`, und ein Test belegt die Sicht ohne Vorprüfung des
Aufrufers
- [ ] `/meine-geraete` wird bei 390 px gemessen, mit einem echten `MITARBEITER`
- [ ] Beide Gegenproben werden rot
- [x] `/meine-geraete` wird bei 390 px gemessen, mit einem echten `MITARBEITER`
- [x] Beide Gegenproben werden rot
## Beim Umsetzen dazugekommen
- **Das Konto liegt im E2E-Vorlauf, nicht im Seed** — wie im Issue vorgezeichnet, und der Grund hat
sich beim Schreiben bestätigt: ein Konto mit bekanntem Passwort gehört nicht in einen Seed, der
auch produktiv läuft. Es trägt `ZZ` im Namen und fällt damit unter das Aufräumen aus
[#027](027-e2e-reste-vorlagen.md); der Nachlauf meldet es mit („1 Benutzer“).
- **Die Person wird gewählt, nicht gesetzt:** die erste aktive mit mindestens einem Gerät. Eine
feste Kennung wäre eine Annahme über den Seed, und ohne Gerät zeigte die Seite nur ihren
Leerzustand — der Test hätte dann nichts gemessen. Der Vorlauf bricht mit einer Erklärung ab, wenn
es keine solche Person gibt.
- **Ein zweiter Test dazu, den das Issue nicht verlangte:** dass ein `MITARBEITER` auf
`/meine-geraete` **keinen** Link in die Verwaltung angeboten bekommt. Die Rollenmatrix ist in
Vitest vollständig, und seit #035 nennt jeder Navigationseintrag sein Recht — dass das im
**gerenderten** DOM ankommt, prüfte nichts. Gegenprobe: ein Eintrag ohne `recht`, und der Test
wird rot.
## Was dabei schiefging, und warum es hier steht
Für das zweite Konto brauchte `anmelden` eine Variante, die nicht auf `/` wartet — ein
`MITARBEITER` landet auf `/meine-geraete`, weil `startseite(rolle)` das Ziel an der Rolle
entscheidet (#035). Dabei habe ich das Warten für **alle** gelockert: „irgendeine Adresse außer
`/anmelden`“.
Das sah harmlos aus und machte **zwei unverwandte Abläufe** unzuverlässig — und zwar nur im vollen
Durchgang, nicht beim Einzellauf: der nächste Schritt begann, bevor die Übersicht stand. Einer davon
war `laeufe.spec.ts` („verlangt für nicht zutreffend eine Begründung“), der mit dem Thema nichts zu
tun hat.
Behoben: `anmelden` wartet wieder streng auf `/`, `anmeldenMit` nimmt das Ziel als Parameter, und
beide warten zusätzlich auf `load` — ein `waitForURL` endet an der Adresse, nicht am geladenen
Dokument. **Die Lehre:** ein gemeinsamer Helfer in einer Testsuite ist geteilter Zustand. Ihn für
einen neuen Fall aufzuweichen kostet die Zuverlässigkeit aller alten, und das zeigt sich erst im
vollen Lauf.