|
|
||
|---|---|---|
| .. | ||
| helpers | ||
| specs | ||
| .gitignore | ||
| global-setup.js | ||
| package-lock.json | ||
| package.json | ||
| playwright.config.js | ||
| README.md | ||
| run.sh | ||
Steuerkram — E2E-Tests (Playwright)
Browser-Tests für die Ebene, die die PHP-Testsuite nicht erreicht: Routing, Controller, Views und das JavaScript in den Formularen.
Sie laufen im Container des generischen
e2e-runner-Projekts (~/projects/e2e-runner/) — auf dem
Host wird nichts installiert (kein Node, kein Browser, kein npm).
Warum diese Ebene
Die PHP-Suite (tests/NN_*.php) prüft Models und Services und ist dort gründlich.
Sie ruft aber nie einen Controller über HTTP auf. Genau dort saßen die zuletzt
aufgetretenen Fehler:
/accounts/newund/assets/newlieferten HTTP 500 — gefunden vom ersten Smoke-Lauf. Ursache: undefinierte Variablen, die seit der Fehler-Härtung (Fix #142) keine stille Warning mehr sind, sondern eine Exception.- Netto/Brutto-Umschalter (
Fix #137): Ein submit-Handler rechnet den eingegebenen Bruttowert vor dem Absenden in Netto um. Serverseitig ist nur das Ergebnis sichtbar — eine kaputte Umrechnung fiele nie auf. - DOM-XSS in der Bankimport-Vorschau (
Fix #133): Die Vorschau wird vollständig im Browser aus einerfetch-Antwort gebaut.
Voraussetzungen
-
Steuerkram läuft unter
http://localhost:8080(docker compose up -d). -
Testnutzer existiert (einmalig, idempotent wiederholbar):
docker compose exec web php scripts/container/e2e-user.phpLegt
e2e/e2e-test-Pass123!an bzw. setzt Passwort und Sperrstatus zurück. Abweichende Zugangsdaten als Argumente oder perE2E_USER/E2E_PASSWORD(Defaults:helpers/env.js). Entfernen mit--delete. -
Testmodus aktiv — sonst lassen sich Testbuchungen und -rechnungen nicht wieder löschen (Einstellungen → Testmodus).
Ausführen
tests/e2e/run.sh
Das Skript prüft vorab, ob Docker, das e2e-runner-Projekt (Pfad überschreibbar
via E2E_RUNNER_DIR) und das Playwright-Image vorhanden sind. Fehlt etwas, wird
nur gewarnt und übersprungen (Exit 0) — die E2E-Tests sind optional und
blockieren keine Umgebung ohne Runner.
Andere Zielinstanz: BASE_URL=http://host.docker.internal:9000 tests/e2e/run.sh
Einzelne Datei oder UI-Modus zum Debuggen:
cd ~/projects/e2e-runner
TEST_DIR=~/projects/Steuerkram/tests/e2e docker compose run --rm playwright \
sh -c "npm ci && npx playwright test smoke.spec.js"
# UI-Modus, danach http://localhost:8077 öffnen:
TEST_DIR=~/projects/Steuerkram/tests/e2e docker compose run --rm --service-ports playwright-ui
HTML-Report, Screenshots und Traces landen in playwright-report/ und
test-results/.
Umgang mit Testdaten
Die Tests laufen gegen eine Instanz mit echten Arbeitsdaten. Deshalb gilt:
- Sie legen ausschließlich eigene Datensätze an, markiert mit
E2E-TEST-<zeit>-<n>(helpers/app.js,uniqueTag), und räumen sie imafterEachwieder ab. - Bestehende Belege, Buchungen und Rechnungen werden nie verändert oder gelöscht.
- Der Bankimport-Test bricht vor dem Bestätigen ab — die Vorschau allein legt keine Transaktionen an.
Reste nach einem abgebrochenen Lauf entfernen:
docker compose exec web php scripts/container/e2e-cleanup.php # nur anzeigen
docker compose exec web php scripts/container/e2e-cleanup.php --force # löschen
Nummernkreise
rechnung-export.spec.js finalisiert eine Rechnung und vergibt dabei eine
Rechnungs- und eine Belegnummer. Beide gehen beim Aufräumen wieder zurück:
Invoice::delete() und Beleg::delete() zählen den jeweiligen Nummernkreis
zurück, wenn der gelöschte Datensatz die zuletzt vergebene Nummer trug.
Nach einem vollständigen Testlauf stehen die Zähler also wieder auf ihrem
Ausgangswert; der Test Löschen einer finalisierten Rechnung gibt die Nummer wieder frei weist das nach.
War die Nummer nicht die letzte (z.B. weil parallel eine echte Rechnung finalisiert wurde), bleibt der Zähler stehen — eine Nummer wird nie zweimal vergeben. In dem Fall entsteht wie bisher eine Lücke im Nummernkreis.
Bricht ein Lauf mittendrin ab, bleiben Testdatensätze liegen;
scripts/container/e2e-cleanup.php --force räumt sie nachträglich ab und arbeitet dabei
absteigend, damit möglichst viele Nummern zurückwandern.
Aufbau
| Datei | Inhalt |
|---|---|
specs/smoke.spec.js |
Alle Hauptseiten rendern ohne Serverfehler; 404, Login-Zwang, CSV-Export |
specs/beleg-buchung.spec.js |
Upload → Buchungsmaske → gespeicherte Buchung, inkl. Netto/Brutto-Umschalter |
specs/rechnung-export.spec.js |
Entwurf → Finalisieren → PDF- und XML-Export (XRechnung 3.0) |
specs/bank-import.spec.js |
Bankimport-Vorschau inkl. XSS-Regression |
helpers/app.js |
Upload, Aufräumen, Betragsparsing, gotoOk |
helpers/env.js |
Zugangsdaten und Basis-URL |
global-setup.js |
Einmaliger Login, legt .auth/user.json an |
Fallstricke
- Submit-Buttons immer auf ihr Formular scopen. In der Sidebar steht das
Logout-Formular (
layout/nav.php); ein ungescopetesbutton[type="submit"]trifft dessen Button zuerst und beendet die Session — alle folgenden Tests laufen dann gegen die Login-Seite. - Reihenfolge in der Buchungsmaske: Die Auswahl des Kategorie-Kontos ruft
updateAutoUst()und setzt den USt-Satz passend zum Steuercode. Den Satz deshalb nach dem Konto setzen. - Ein Redirect auf
/loginendet mit Status 200.gotoOk()prüft deshalb zusätzlich den Pfad — sonst schlagen Tests mit irreführenden Meldungen fehl. - Belegverzeichnisse aus PHP-Testläufen: Die PHP-Suite immer mit
docker compose exec -u www-data web php tests/run.phpstarten. Ohne-u www-dataläuft sie als root und kann indata/belege/<Jahr>/ein Verzeichnis anlegen, das root gehört, während die Transaktion die Belegnummer zurückrollt. Trifft später ein echter Upload auf dieselbe Nummer, scheitertmove_uploaded_file()mit HTTP 500. Solche Leichen aus früheren Läufen finden:find data/belege -maxdepth 2 -user root