Statt eigener Off-Session-Einzüge durch den Worker legt die Anwendung nach bezahlter erster Rate einen Stripe Subscription Schedule an. Stripe übernimmt Einzug, Wiederholungen (Smart Retries), 3-D-Secure-Links und Mahnungen. - Gateway: Zeitplan anlegen/beenden, Rechnungen lesen; chargeOffSession entfällt - Webhook: invoice.paid, invoice.payment_failed, invoice.payment_action_required - Worker: fehlende Zeitpläne anlegen, überfällige Raten abgleichen, Zeitpläne stornierter Buchungen beenden - Storno beendet den Zeitplan und storniert offene Rechnungen - "Rate bezahlen" führt auf Stripes Rechnungsseite - Migration: Booking.stripeScheduleId, Installment.stripeInvoiceId Zeitplan-Form mit Stripe-Testuhr gegen die Test-API geprüft. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
5.0 KiB
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
/adminzur 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
totalCentswird ignoriert. - Sicherheitsheader (CSP mit Nonce, HSTS, X-Frame-Options) sind gesetzt.
- Der Standalone-Build läuft mit Datenbank. Worker-Lauf und
admin:createfunktionieren, eine doppelte Anlage wird abgewiesen. - Build, Typprüfung und ESLint laufen ohne Fehler, Kustomize rendert 17 Ressourcen.
Lauf 05.10.2026 nach Umstellung der Folgeraten auf Stripe Billing: 85/85 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).