Steuerkram/tests/e2e/README.md
fds2610-bot 7cea573ffc Fix #e2e: E2E-Tests ergänzt, /accounts/new und /assets/new lieferten HTTP 500
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.
2026-08-02 11:58:33 +02:00

123 lines
5.2 KiB
Markdown

# 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](../../../e2e-runner/) (`~/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):
```bash
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
```bash
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:
```bash
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:
```bash
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:
```bash
... 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 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:** `docker compose exec web php tests/run.php`
läuft 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 finden:
`find data/belege -maxdepth 2 -user root`