131 lines
5.9 KiB
Markdown
131 lines
5.9 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/container/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/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 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`
|