Steuerkram an den e2e-runner angebunden (tests/e2e/, 44 Playwright-Tests). Der erste Smoke-Lauf fand zwei Seiten mit HTTP 500: AccountController::create las $_GET['from'] ungeprüft, assets/form.php nutzte $testMode und $defaultKontoId außerhalb des Bearbeiten-Zweigs. Beides war bis zur Fehler-Härtung (#142) nur eine stille Warning. Test 67 räumt sein Belegverzeichnis jetzt mit ab - es blieb als root-eigenes Verzeichnis liegen und blockierte spätere echte Uploads mit HTTP 500. Test 77 (neu) sichert die Löschsperre von Beleg::delete() ab.
5.2 KiB
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/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/e2e-cleanup.php # nur anzeigen
docker compose exec web php scripts/e2e-cleanup.php --force # löschen
Nicht umkehrbare Nebenwirkung
rechnung-export.spec.js finalisiert eine Rechnung und verbraucht dabei eine
Nummer aus dem laufenden Nummernkreis. Die Rechnung selbst wird wieder gelöscht,
die Nummer bleibt vergeben (GoBD — eine Rücknahme wäre auch nicht wünschenswert).
Wer das vermeiden will, lässt diesen Test weg:
... npx playwright test --grep-invert "Finalisieren"
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:
docker compose exec web php tests/run.phpläuft 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 finden:find data/belege -maxdepth 2 -user root