# E2E-Tests (Playwright)

Ein Referenzszenario, gegen den ECHTEN Stack (kein Mocking) - siehe
[`golden-path.spec.ts`](golden-path.spec.ts): Login als Bibliothekarin → Mitglied anlegen → Buch
anlegen → im Katalog finden → ausleihen → in "Meine Ausleihen" sichtbar. Übt damit Signals-
Features (`my-loans`, `members-admin`), das NgRx-Feature (`catalog-admin`) und den
Keycloak-PKCE-Login zusammen in einem Durchlauf.

## Voraussetzungen

1. Komplette Infrastruktur + Backend laufend (Podman - unter Windows/macOS zuerst
   `podman machine start`):
   ```bash
   cd ../infra
   podman compose up -d
   ```
   (oder gezielt nur die für dieses Szenario nötigen Container, siehe
   [infra/README.md](../../infra/README.md))
2. Angular-Dev-Server laufend:
   ```bash
   cd ../library-frontend
   npx ng serve
   ```
3. Chromium-Browser für Playwright (einmalig):
   ```bash
   npx playwright install chromium
   ```

## Ausführen

```bash
npm run e2e          # headless
npm run e2e:ui       # interaktiver UI-Modus, gut zum Debuggen
```

## Status in diesem Repository

✅ **Läuft erfolgreich gegen den vollständig hochgefahrenen Stack** (Postgres, Kafka, Keycloak,
config-server, discovery-server, catalog-service, member-service, lending-service, api-gateway,
Angular-Dev-Server). `npm run e2e` → `1 passed`.

Das Hochfahren des kompletten Stacks (insbesondere der erste Container-Image-Build je Service,
siehe `library-platform/Dockerfile`) dauert auf einer normal ausgelasteten Maschine mehrere
Minuten - auf der Referenzmaschine dieses Projekts durch spürbare Ressourcen-Konkurrenz beim
gleichzeitigen Starten mehrerer Spring-Boot-Services deutlich länger (einzelne Services brauchten
über 200 Sekunden allein für die Spring-Kontext-Initialisierung). Das ist eine Eigenschaft dieser
konkreten Entwicklungsmaschine, kein Fehler im Code.

## Gefundene Bugs

Der erste vollständige Live-Lauf dieses Tests deckte mehrere reale, zuvor unentdeckte Bugs auf -
keiner davon war durch einen Unit- oder Integrationstest sichtbar, weil keiner von ihnen jemals
den kompletten Pfad "Browser → api-gateway → Fachservice → Postgres → zurück zum Browser"
durchlaufen hatte. Das ist der eigentliche Wert eines E2E-Tests gegen den echten Stack.

1. **MapStruct mappte stillschweigend `null`/`0` statt echter Werte** (der schwerwiegendste Fund):
   `BookDtoMapper`, `FineDtoMapper`, `LoanDtoMapper`, `MemberDtoMapper` und
   `ReservationDtoMapper` gingen davon aus, dass MapStruct fluent-benannte Accessor-Methoden
   (`title()`, `status()`, ... - bewusst ohne `get`-Präfix für ein reiches Domainmodell) genauso
   automatisch erkennt wie bei einem echten `record`. Das stimmt nicht: MapStructs automatische
   Zuordnung erkennt nur JavaBean-Getter oder echte `record`-Typen. Jedes NICHT explizit per
   `@Mapping(..., expression = ...)` gemappte Feld wurde still auf seinen Default-Wert gesetzt
   (`null` bei Objekten, `0` bei `int`) - nur eine Build-Warnung, kein Fehler, deshalb monatelang
   unbemerkt. Sichtbar wurde es erst, als dieser Test zum ersten Mal den Buchtitel im
   Katalog-Suchergebnis tatsächlich ansah. Betroffen waren `BookResponse.title/publisher`,
   `CopyResponse.status/acquiredAt`, `FineResponse.issuedAt/status`,
   `LoanResponse.borrowedAt/dueDate/returnedAt/status`,
   `MemberResponse.firstName/lastName/tier/status/registeredAt` und
   `ReservationResponse.queuePosition/createdAt/status` - fast jedes nicht-triviale Feld in JEDER
   API-Antwort des Backends. Fix: jedes Zielfeld bekommt jetzt eine explizite `@Mapping`-Expression
   (siehe die fünf Mapper-Klassen und deren Javadoc/Kommentare für die volle Erklärung).
2. **`authGuard` leitete unangefragt zu Keycloak weiter**: `role.guard.ts`s `authGuard` rief bei
   fehlendem Login sofort `authService.login()` auf, statt nur die Navigation zu verweigern -
   dadurch wurde `app.component.html`s eigene, freundliche "Bitte melde dich an"-Landingpage nie
   sichtbar (der Nutzer landete ungefragt sofort auf der Keycloak-Login-Seite). Fix: der Guard
   verweigert jetzt nur (`return authService.isLoggedIn()`), der Login-Klick bleibt eine bewusste
   Nutzeraktion.
3. **`book_authors`-Tabelle fehlte die von `@OrderColumn` verlangte Spalte** (`author_order`) -
   `catalog-service` konnte mit `ddl-auto: validate` gegen eine echte, frisch migrierte
   Postgres-Datenbank gar nicht erst starten. Fix: Spalte in
   `V1__init_catalog_schema.sql` ergänzt.
4. **`OutboxEntry.payload` war fälschlich `@Lob`**: Hibernate mappt ein `@Lob`-String-Feld auf
   Postgres per Default auf den Typ `oid` (Large Object), während die Migration die Spalte
   bewusst als einfaches `TEXT` anlegt - `lending-service` konnte ebenfalls nicht starten
   (`Schema-validation: wrong column type`). Fix: `@Lob` entfernt (nicht die Migration - `TEXT`
   war von Anfang an der richtige Typ für einen JSON-Payload-String).

Punkte 3 und 4 blieben bis zu diesem Testlauf unbemerkt, weil die Testcontainers-Integrationstests
(die genau das geprüft hätten) damals durch die dokumentierte Docker-Desktop-Einschränkung nie
erfolgreich liefen (inzwischen über Podman gelöst) - ein weiteres Argument dafür, warum ein
E2E-Test gegen den echten, per Flyway migrierten Stack einen eigenständigen Wert hat, den keine
andere Teststufe in diesem Projekt ersetzt.

## Warum bibliothekar:innen-assistiertes Ausleihen statt Self-Service?

Das Ausleihformular in `my-loans.component.html` fragt bewusst nach einer Member-Id, statt
automatisch "die eigene" Ausleihe zu meinen - es gibt (noch) keine Verknüpfung zwischen dem
Keycloak-Login-Nutzer und einer `member-service`-Mitglieds-ID (dokumentierte
Vertiefungsaufgabe, siehe [Pattern-Katalog](../../documentation/docs/07-pattern-katalog/pattern-katalog.md)).
Der Test bildet deshalb den tatsächlich implementierten Ablauf ab: eine Bibliothekarin am
Schalter, die für ein Mitglied ausleiht - nicht eine (noch nicht existierende) Self-Service-Ansicht.
