Steuerkram/tests/e2e
2026-08-02 16:50:18 +02:00
..
helpers Fix #e2e: E2E-Tests ergänzt, /accounts/new und /assets/new lieferten HTTP 500 2026-08-02 11:58:33 +02:00
specs Fix #165: Ereignisse zeigen Fehler und Warnungen aus dem ganzen System 2026-08-02 16:50:18 +02:00
.gitignore Fix #e2e: E2E-Tests ergänzt, /accounts/new und /assets/new lieferten HTTP 500 2026-08-02 11:58:33 +02:00
global-setup.js Fix #e2e: E2E-Tests ergänzt, /accounts/new und /assets/new lieferten HTTP 500 2026-08-02 11:58:33 +02:00
package-lock.json Fix #e2e: E2E-Tests ergänzt, /accounts/new und /assets/new lieferten HTTP 500 2026-08-02 11:58:33 +02:00
package.json Fix #e2e: E2E-Tests ergänzt, /accounts/new und /assets/new lieferten HTTP 500 2026-08-02 11:58:33 +02:00
playwright.config.js Fix #e2e: E2E-Tests ergänzt, /accounts/new und /assets/new lieferten HTTP 500 2026-08-02 11:58:33 +02:00
README.md Fix #170: Tests laufen als www-data und räumen angelegte Dateien selbst auf 2026-08-02 16:12:47 +02:00
run.sh Fix #e2e: E2E-Tests ergänzt, /accounts/new und /assets/new lieferten HTTP 500 2026-08-02 11:58:33 +02:00

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/new und /assets/new lieferten 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 einer fetch-Antwort gebaut.

Voraussetzungen

  1. Steuerkram läuft unter http://localhost:8080 (docker compose up -d).

  2. Testnutzer existiert (einmalig, idempotent wiederholbar):

    docker compose exec web php scripts/e2e-user.php
    

    Legt e2e / e2e-test-Pass123! an bzw. setzt Passwort und Sperrstatus zurück. Abweichende Zugangsdaten als Argumente oder per E2E_USER / E2E_PASSWORD (Defaults: helpers/env.js). Entfernen mit --delete.

  3. 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 im afterEach wieder 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

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/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 ungescopetes button[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 /login endet 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.php starten. Ohne -u www-data läuft sie als root und kann in data/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, scheitert move_uploaded_file() mit HTTP 500. Solche Leichen aus früheren Läufen finden: find data/belege -maxdepth 2 -user root