Files
Laufzettel/docs/issues/037-anhaenge-lesemodell.md
T
Florian WildeandClaude Opus 5 75c335df23
Prüfung / pruefung (push) Canceled after 0s
Prüfung / e2e (push) Canceled after 0s
test: Zusagen pruefbar machen, die nur von Hand hielten (#038, #037)
#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>
2026-10-11 06:05:29 +02:00

4.9 KiB
Raw Blame History

#037 Zwei Nachzügler aus der Durchsicht von Phase 2

Status: erledigt Im Tracker: – Meilenstein: v0.2.0 Labels: phase-2, backend, test Geschätzt: 2 h Tatsächlich: 1 h 50 min

Ziel

Zwei Befunde aus #036, die mehr sind als eine Korrektur: beide verlangen einen Umbau, und beide sind heute kein Schaden, sondern eine offene Flanke.

1. anhaengeDesLaufs ist ein Lesemodell am falschen Ort

anhaengeDesLaufs(laufId) liegt in src/server/services/anhaenge.ts, nimmt nur eine Lauf-Kennung und wendet weder Rollen- noch Mandantensicht an. Beide Aufrufer (src/app/(app)/laeufe/[id]/page.tsx und src/server/queries/druck.ts) prüfen den Lauf vorher, und die Kommentare sagen das auch — es ist also heute kein Fehler.

Es steht aber gegen die Regel aus CLAUDE.md und docs/architektur.md §2: Lesemodelle liegen in queries/* und wenden ihre Sicht selbst an, damit kein Aufrufer sie vergessen kann. Zwei 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 dass der Aufrufer vorher geprüft hat
  • Gegenprobe: die Sicht entfernen, der Test muss rot werden

2. /meine-geraete fehlt in der 390-px-Prüfung

Die Seite ist das Ergebnis von #035 und ausdrücklich mit „am Handy kein horizontales Scrollen“ abgenommen — von Hand. In tests/e2e/mobil.spec.ts steht sie nicht, und sie kann dort nicht einfach ergänzt werden: sie verlangt das Recht selbstauskunft, und das hat nur MITARBEITER. Der 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 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 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 Vitest vollständig, aber kein Ablauf klickt sie durch

Akzeptanzkriterien

  • 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

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; 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.