Files
Artista-Filmcamp/docs/TESTS.md
T
Nick SzaunigandClaude Opus 5.5 1ce7947d93 fix: Stripe-Ratenplan bei Prüfung anhalten, doppelte Pläne verhindern
Befunde aus dem Sicherheits-Review des vorherigen Commits:

- Gerät eine Buchung in "Prüfung nötig" (Rückbuchung, Doppelzahlung ...),
  wird der Stripe-Plan beendet und offene Rechnungen storniert. Nach
  Bestätigung legt der Worker einen neuen Plan für die offenen Raten an.
  Vorher zog Stripe auch bei Buchungen in Prüfung weiter ein.
- Vor dem Anlegen wird bei Stripe nach einem laufenden Plan der Buchung
  gesucht; der Idempotenzschlüssel enthält Generation und Start. Verhindert
  einen zweiten Plan nach verlorener ID und die Rückgabe des alten,
  beendeten Plans nach einer Prüfung.
- Start bei bereits verstrichener Fälligkeit deterministisch am nächsten
  9-Uhr-Termin, letzte Rate bleibt am Stichtag.
- Rückbuchungs-Event meldet die betroffene Buchung zurück.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-10-06 06:28:41 +02:00

60 lines
5.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Tests und Abnahme
Stand 27.09.2026. Alle aufgeführten Läufe sind lokal ausgeführt und bestanden.
## Automatisierte Tests
`pnpm test` umfasst 72 Tests in 6 Dateien. Sie laufen gegen eine echte, frisch gestartete PostgreSQL-18-Instanz, damit Zeilensperren und Trigger mitgetestet werden.
| Geschäftsrisiko | Datei |
|---|---|
| Alle vier Gesamtpreise, 28 % statt 30 % | `tests/pricing.test.ts` |
| Alle zwölf Ratenbeträge exakt, einschließlich 1.237,50 € | `tests/payment-plan.test.ts` |
| Zeitgrenzen 01.11.2026 und 01.01.2027 in Europe/Berlin, Sommerzeit | `tests/pricing.test.ts`, `booking.integration.test.ts` |
| Ungültige, inaktive, abgelaufene, noch nicht gültige, fremd gebundene und ausgeschöpfte Gutscheine | `booking.integration.test.ts` |
| Gleichzeitige Einlösung eines begrenzten Codes (7 parallel, 2 erlaubt) und Gesamtkontingent | `booking.integration.test.ts` |
| Gleichzeitige Buchungen bei knapper Kapazität (8 parallel, 2 Plätze) | `booking.integration.test.ts` |
| Abgelaufene Reservierungen, verzögerte Zahlung (SEPA), verspätete Zahlung mit und ohne freien Platz, verlorener Webhook | `payments.integration.test.ts` |
| Doppelte und ungeordnete Stripe-Events, Livemodus-Event im Testbetrieb, Signaturprüfung | `payments.integration.test.ts` |
| Zahlungserfolg, Abbruch, Fehler, Teilzahlung, Authentifizierung, Erstattung | `payments.integration.test.ts`, `admin.integration.test.ts` |
| Sperre aller Live-Checkout-Zugänge ohne Freigabe, Vorschauphase | `sales-gate.test.ts`, `booking.integration.test.ts` |
| Keine weitere Abbuchung nach der letzten Rate oder nach Stornierung, Zahlungsmethode getrennt | `payments.integration.test.ts`, `admin.integration.test.ts` |
| Unveränderlicher Preis-Snapshot (DB-Trigger), Idempotenz bei Doppelklick | `booking.integration.test.ts` |
## End-to-End und Sicht
`pnpm test:e2e` umfasst 9 Tests auf den Profilen Smartphone (Pixel 7), Tablet (820 × 1180) und Desktop (1440 × 900):
- axe-Prüfung WCAG 2.1 AA ohne Verstöße
- kein horizontales Scrollen
- keine öffentliche Platzzahl
- Buchungsdialog: Pflichtfelder, Gutschein, Ratenplan 3 × 660 €, Erklärungen, Fokus beim Öffnen und Schließen per Escape
- Admin-Weiterleitung, Export mit gefälschtem Cookie ergibt 401, Statusseite mit `noindex`
Bildschirmfotos aller drei Größen wurden visuell geprüft.
Letzter Lauf 01.10.2026 nach Einbau von Team, Villa-Bildern und bestätigtem Termin: 81/81 Unit- und Integrationstests, 9/9 E2E-Tests, Produktionsbuild grün. Team und Unterkunft wurden zusätzlich per Bildschirmfoto auf Smartphone (390 px) und Desktop (1440 px) geprüft. Mit Termin 08.05.2027 fällt die letzte Rate auf den 08.04.2027.
Hinweis: Läuft der Testserver nicht unter der Adresse aus `APP_URL`, lehnt der Same-Origin-Schutz die Preisabfrage ab (403). Dann hängt der Buchungsdialog bei „Preise werden geladen …“. Server deshalb mit passender `APP_URL` starten, z. B. `APP_URL=http://localhost:3005 PORT=3005 pnpm start` und `E2E_BASE_URL=http://localhost:3005 pnpm test:e2e`.
## Manuell über HTTP geprüft
- Admin-Ablauf:
- Öffentliche Registrierung wird mit 400 abgelehnt, ein falsches Passwort mit 401.
- Ohne 2FA leitet `/admin` zur Einrichtung um, der Export antwortet 401.
- Nach der TOTP-Aktivierung sind Dashboard und CSV mit 200 erreichbar.
- CSRF: Anfragen ohne JSON bekommen 415, fremde Origins 403.
- Preismanipulation: Ein mitgeschicktes `totalCents` wird ignoriert.
- Sicherheitsheader (CSP mit Nonce, HSTS, X-Frame-Options) sind gesetzt.
- Der Standalone-Build läuft mit Datenbank. Worker-Lauf und `admin:create` funktionieren, eine doppelte Anlage wird abgewiesen.
- Build, Typprüfung und ESLint laufen ohne Fehler, Kustomize rendert 17 Ressourcen.
Lauf 06.10.2026 nach Umstellung der Folgeraten auf Stripe Billing (inkl. Anhalten bei Prüfung und Schutz vor doppeltem Plan): 88/88 Unit- und Integrationstests, Typprüfung und ESLint ohne Fehler. Zusätzlich `StripeGateway` gegen die echte Stripe-Test-API mit Testuhr geprüft: Zeitplan mit zwei Folgeraten erzeugt genau zwei bezahlte Rechnungen (je 700 €, Metadaten `bookingId`/`kind`, PaymentIntent mit Charge) und endet danach (`completed`); abgelehnte Karte ergibt offene Rechnung mit geplantem Wiederholungsversuch und Zahlungslink; Storno setzt den Zeitplan auf `canceled` und die offene Rechnung auf `void`, auch wiederholt und vor dem Start.
## Nicht ausgeführt / Einschränkungen
- **Echte Stripe-Testbuchung** gegen die Stripe-API: Ein Stripe-Testschlüssel lag nicht vor. Die Stripe-Logik ist gegen eine Attrappe mit Stripe-Semantik getestet (Idempotenz, Session-Zustände, Rechnungen des Ratenplans), die Webhook-Signatur mit der echten Stripe-Bibliothek. Mit Schlüssel: Anleitung in der README (`stripe listen`, Testkarten).
- **Docker-Image und Cluster:** Auf dem Entwicklungsrechner gibt es kein Docker und keinen Cluster-Zugang. Das Dockerfile ist nicht gebaut und nicht im Cluster ausgerollt. Geprüft sind der Standalone-Build und das Rendern der Manifeste.
- **SMTP-Versand:** nur über den Datei-Testausgang geprüft.
- **Referenzseite:** nur über eine Textzusammenfassung ausgewertet (siehe ARCHITEKTUR.md).