---
name: project-sync-testing
description: Sync testen — Integrationssuite (Logikschleife, seit 2026-06-10) + Unit-Specs + manuelles node-Rig gegen den echten BE.
metadata: 
  node_type: memory
  type: project
  originSessionId: ff64bed0-7915-4ef2-bc0d-c7c4af6a44ac
---

Zum Testen von Sync-Änderungen (Outbox/Inflight/badBox) gibt es zwei eingespielte Wege:

**Weg 1 — Logik isoliert (Arbeitspferd, kein Auth/Build):**
```bash
npx nx test frontend-common --watch   # Unit-Specs + sync-loop.integration.spec.ts
npx nx test command-be                # BE-seitiges handle/sync
```
Seit 2026-06-10 gehört dazu die **Integrationssuite** `libs/common/frontend-common/src/lib/integration/sync-loop.integration.spec.ts`: echte FE-Singletons (Outbox/BackendSync/PersistentStorage/storage-core) gegen echten CommandService+CustomerCoreService auf In-Memory-better-sqlite3; HTTP-Grenze als Mock-Brücke mit doppeltem JSON-Roundtrip (handle() mutiert payload). 9 Szenarien: Happy-Path, SAP-FAILED-Rollback, Delete-Kaskade, SAP-Delete-Block, Offline-Flush, Transient-Retry, Batch-Partial-Failure, Crash-Recovery (2 Varianten). GEFIXT am 2026-06-10: Fehler-Taxonomie (TRANSIENT_CODES + 5xx in background-sync, Netz/5xx wirft der Web-Client roh weiter, deterministische Fehler → neues `outbox.fail()` = sofort badBox, Queue läuft weiter) und Partial-Batch (createOrUpdateList transaktional via gemeinsamem persistCustomer(repo,…)). Verbleibende `// OFFENE FRAGE:`-Pins: QUEUED-Aufgabe ohne Rollback, kein Versionsvergleich beim Reconcile (Last-Arrival-Wins), Doppel-Finalize wirft statt idempotent. frontend-common/vite.config.ts hat dafür explizite @plato/*-Aliase bekommen. Suite gesamt: 8 Projekte / 313 Tests.

**Weg 2 — echte BE/SAP-Stichprobe von Hand** über `scripts/sync-poke.mjs` (gitignored, pure Node, läuft auch unter Windows via `node scripts/sync-poke.mjs ...`):
```bash
node scripts/sync-poke.mjs customer.update '{"id":"cust-123","name":"Test"}' --cookie 'connect.sid=s%3A...'
node scripts/sync-poke.mjs --sync-all --cookie 'connect.sid=s%3A...'
```

**Why:** Die Routen `/commands`, `/commands/sync`, `/commands/sync/all` (`command.controller.ts`) hängen alle an `SessionAuthGuard`, der hart `req.session.user` verlangt — KEIN Dev-Bypass. Deshalb braucht jeder Hand-Test gegen den BE eine echte express-session: einmal im Browser einloggen, dann `connect.sid` aus den DevTools (Application → Cookies → http://localhost:3000) holen. `oidc-test.mjs` taugt NICHT als Cookie-Quelle — es redet direkt mit dem IdP, erzeugt nur Tokens (keine BE-Session) und belegt selbst Port 3000.

**How to apply:** Weg 1 als TDD-Schleife für die dokumentierten badBox/Inflight-Lücken (siehe [[project-naechste-schritte]]). Weg 2 als Stichprobe, wenn du den realen Reconcile + SAP-Enrichment sehen willst — taugt auch um `WARNING`/`QUEUED`-Antworten gegen den echten BE zu provozieren. Cookie geht per `--cookie` (plattformneutral) oder `PLATO_SESSION`-Env (PowerShell: `$env:PLATO_SESSION='...'`). Bei `401` ist das Cookie abgelaufen → neu einloggen. Detail für `--sync-all`: Body muss `{}` sein, nicht leer (`express.json()` lehnt `"null"` mit 400 ab, vermerkt in `plato-web-client.ts`). BE-Start siehe [[project-run-commands]].
