Zum Inhalt springen
Farbschema wählenSprache wählen

E2E-Spec-Wahrheitstabelle

Das Blockworx Engineering Handbook hat seine Real-Flow-Anforderung für E2E-Tests am 2026-09-04 verbindlich gemacht (docs/70-standards/testing/e2e.md). Regel 8 dieses Standards verlangt von jedem Repository eine Spec-Wahrheitstabelle: eine Zeile je Spec, ihre Oberfläche und die Klasse der Abkürzung, die sie noch nimmt — mit Zeilenbezug und Zählung —, damit die verbleibenden Abkürzungen sichtbar sind statt angenommen. Diese Seite ist diese Tabelle für SupaCloud. Sie wird von Hand gepflegt und bei jeder Spec-Änderung neu gezählt; die Zahlen unten stammen vom 2026-09-04 aus web/tests/e2e und web/tests/e2e-real.

Die Klassen des Handbuchs, plus eine, die dieses Repository braucht:

Klasse Bedeutung
A Echter Ablauf durch die echte Oberfläche: gebootetes Backend, gebautes Web-Bundle, UI-Klicks oder öffentliche API-Aufrufe, kein direkter Datenbankschreibzugriff im Ablauf.
B Ein Datenbankschritt im Ablauf: etwas, das der Ablauf erzeugen sollte, wird direkt geschrieben (Seed, Stempel, UPDATE).
C Das Ergebnis wird aus der Datenbank gelesen statt vom Artefakt.
D Übersprungene Zellen (test.skip / fixme).
E Zeitstempel-Manipulation in Zeilen statt einer E2E-gesteuerten Uhr.
F Eine Route, die kein Nutzer erreicht.
M Gemockte API: der Browser fährt das gebaute Web-Bundle, aber jeder /api/**-Aufruf wird von page.route-Fixtures beantwortet (web/tests/e2e/vite-mock-api.ts, fixtures.ts). Nach der Definition des Handbuchs („trifft die echte laufende App”) ist das kein E2E-Test; es ist das Contract-Konformitäts-Geschirr über den ADR-0047-Fixtures (fixtures.contract.test.ts prüft die Fixtures gegen das OpenAPI-Schema). Die Mechanik-Regeln (kein Sleep, kein Skip, Retries, Video) gelten trotzdem; die Real-Flow-Regeln 1–4 kann es nicht erfüllen und beansprucht sie nicht.
Lane Konfiguration Spec-Verzeichnis Zellen Läuft in Browser
Mock (Smoke) web/playwright.config.ts tests/e2e 208 (113 chromium-desktop, 95 mobile-chrome) pr-checks.yml (Core-Loop-Netz, @pr-core-loop), e2e-nightly.yml mock-smoke + mock-full Chromium
Echt (Nightly) web/playwright.nightly.config.ts (lokal: playwright.real.config.ts) tests/e2e-real 41 (1 auth-setup, 20 chromium-desktop, 20 mobile-chrome) e2e-nightly.yml Real-Backend-Job, 06:00 UTC Chromium

Layout-Steuerung ist seit 2026-09-04 eine Eigenschaft des Projekts: ein Test mit @desktop-only im Titel betritt das Projekt mobile-chrome nie, @mobile-only nie chromium-desktop (grepInvert am Projekt). Die 19 test.skip-Zellen, die das vorher ausdrückten, sind weg — ein gesteuerter Test wird nicht gelistet, ein übersprungener wurde gelistet und schwieg.

Die Selektor-Spalten zählen Aufrufstellen in der Spec-Datei: testid = getByTestId / data-testid; role = getByRole; text = getByText / getByLabel / getByPlaceholder; locator = .locator(; css = ein .locator(, das an einer Klasse oder Id hängt. Regel 6 des Standards lässt nur data-testid zu, also ist jede Zahl ungleich null unter role, text und css offene Schuld — hier aufgeführt, damit sie sich nicht wegdenken lässt.

Mock-Lane, umgestellt am 05.09.2026. Jede Mock-Spec selektiert jetzt per data-testid; die Zahlen unten sind der Stand nach dieser Umstellung. Zwei .locator(-Aufrufe bleiben absichtlich, es ist Bibliotheks-DOM UNTER einem Element, das wir markieren: .cm-content in memory-editor-body (CodeMirror) und .xterm-screen in log-terminal (xterm.js). visual.spec.ts behält zwei Dokument-Sonden (html[data-theme] und die Screenshot-Maske über time-Elemente) - das Dokument ist kein Produktelement. Attribut-Selektoren, die bei einer data-testid BEGINNEN ([data-testid="backlog-column"] [data-state=queued], [data-testid][data-variant=nav]), zählen als locator, nicht als Schuld. marketplace-subscription.spec.ts war die letzte Spec mit Rollen-Mischung und ist seit demselben Tag auf Ids.

Spec Zellen (Desktop / Mobil) Klasse Abkürzung, mit Bezug testid / role / text / locator / css Gefahrene Routen
accessibility.spec.ts 8 / 8 M gemockte API 1 / 0 / 0 / 0 / 0 ein axe-Durchlauf je gelistetem Pfad
app-flows.spec.ts 8 / 14 M gemockte API; 6 Tests @mobile-only 64 / 0 / 0 / 0 / 0 /, /inbox, /inbox?lang=de, /inbox?modal=…, /login?lang=de, …
badge-coordinator.spec.ts 2 / 2 M gemockte API; prüft die Fetch-Zählung des Leader-Tabs über page.route 1 / 0 / 0 / 0 / 0 / in drei Tabs
core-loop.spec.ts 5 / 0 M gemockte API; describe @desktop-only 17 / 0 / 0 / 0 / 0 /backlog, /cli, /runs/{id}, /tasks/{id}
crud-matrix.spec.ts 9 / 0 M gemockte API; describe @desktop-only 82 / 0 / 0 / 1 / 1 /projects, /projects/new, /resources, /reports/schedules, /intelligence/memory, …
delivery-debt-surfaces.spec.ts 14 / 5 M gemockte API; 9 Tests @desktop-only 72 / 0 / 0 / 1 / 1 /inbox?source=governor, /reports/usage, /settings?tab=…, /admin?tab=payouts…, /cli
marketplace-subscription.spec.ts 7 / 7 M gemockte API 25 / 0 / 0 / 3 / 3 /marketplace/{item}, /admin/marketplace/payouts?tab=fees
memory.spec.ts 1 / 1 M gemockte API 15 / 0 / 0 / 0 / 0 /intelligence/memory
mobile-capture.spec.ts 19 / 19 M gemockte API; Screenshot-Geschirr, keine DOM-Prüfung über die Aufnahme hinaus 0 / 0 / 0 / 0 / 0 die 19 Capture-Routen
mobile-feed-scroll.spec.ts 0 / 1 M gemockte API; @mobile-only 3 / 0 / 0 / 0 / 0 /runs/{id}
mock-capture-desktop.spec.ts 9 / 9 M gemockte API; Screenshot-Geschirr 0 / 0 / 0 / 0 / 0 die 9 Desktop-Capture-Routen
mock-conformance.spec.ts 9 / 9 M gemockte API; Konformität der Screens zu den Fixtures 4 / 0 / 0 / 2 / 0 die 9 Konformitäts-Routen
optimistic-conflicts.spec.ts 2 / 0 M gemockte API; describe @desktop-only 11 / 0 / 0 / 2 / 0 /runs, /projects/{id}/backlog
visual.spec.ts 20 / 20 M gemockte API; toHaveScreenshot 6 / 0 / 0 / 2 / 2 die 20 Visual-Routen
Spec Zellen (Desktop / Mobil) Klasse Abkürzung, mit Bezug testid / role / text / locator / css Gefahrene Routen
auth.setup.ts 1 (Projekt auth-setup) A registriert und meldet sich über die öffentliche API an (/api/auth/register Zeile 13, /api/auth/login Zeile 19) und speichert die Sitzung — Stammdaten, nach Regel 1 erlaubt
app-real-flows.spec.ts 7 / 7 D im CI (geparkt), A ×6 + B ×1 wenn sie läuft Selektoren seit dem Abend-Durchgang Test-Ids (übrig: fünf locator("body")-Inhaltsprüfungen und eine a[href]-Aufzählung, keine Steuerelement-Selektoren); der Run-Detail-Test (Zeile 373, S4_NIGHTLY_SEEDED) betrachtet einen Run, den scripts/ui-capture/seed.sql per psql im Workflow-Schritt „Seed nightly data” geschrieben hat (.forgejo/workflows/e2e-nightly.yml Zeilen 115–137). Der Run ist das geprüfte Artefakt und wird geseedet, nicht von einem Ablauf erzeugt — Klasse B. Die anderen sechs fahren Login, Workspace- und Projektanlage, jede erreichbare Routenoberfläche, die Legacy-Umleitungen und die mobile Bottom-Bar durch die UI. 0 / 18 / 6 / 13 / 2 /build, /projects, /settings?tab=workspace, /runs/{id}, jede nutzererreichbare Route, die Legacy-Stubs
app-negative-flows.spec.ts 13 / 13 D im CI (geparkt), A ×13 wenn sie läuft Selektoren seit dem zweiten Abend-Durchgang Test-Ids (übrig: vier locator("body")-Inhaltsprüfungen und eine Statustext-Prüfung); API-Lesezugriffe über page.request.get (Zeilen 84–110, 488, 580) sind zusätzliche Konsistenzprüfungen über die öffentliche API (Regel 3 erlaubt sie neben einer DOM-Prüfung); der Admin-Request-Kontext (Zeile 135) und request.delete (Zeile 455) sind Aufrufe, die ein angemeldeter Admin machen kann (Regel 1). Kein Datenbankzugriff. 12 / 26 / 9 / 38 / 29 /login, /, /admin, /build/apps/new, Projekt- / Run- / Deploy- / Marketplace- / Einladungs-Abläufe

Die #1161-Messtreiber laufen von der Kommandozeile gegen einen gebooteten Stack. Sie stehen hier, weil Regel 1 auch für sie gilt.

Treiber Klasse Abkürzung, mit Bezug Aufrufer
raise-gate.mjs A prägt die Aufgabensitzung über das Produkt (POST /api/workspaces/{id}/tasks/{task_id}/e2e-session, Owner/Admin, nur mit SUPACLOUD_E2E_TASK_SESSION_MINT auf dem Bench-Server; MODE=prod lehnt das Flag beim Start ab). Bis 2026-09-04 war das der eine Klasse-B-Stempel im Treiberbestand (UPDATE tasks SET session_id per psql); alles danach (der MCP-Handler, der Insert in task_tool_approvals, das Hub-Ereignis, der Telegram-Push) war schon der echte Weg, jetzt ist es auch der Eintritt. telegram-surface-check.mjs, form-surface-check.mjs
alle anderen Treiber A nur öffentliche API und die Chat-Oberflächen; telegram-surface-check.mjs liest eine Zählung per psql (Zeile 468) als zusätzliche Prüfung neben der Oberflächenprüfung

Die frühere B-Zeile wurde durch eine Produktfähigkeit ersetzt, nicht durch eine Treiberänderung: die E2E-gesteuerte Sitzungsprägung (dieselbe Form wie die E2E-Uhr des Handbuchs, eine Fähigkeit, die nur der E2E-Modus freigibt). Der Bench-Server setzt das Flag in boot-nightly-stack.sh.

Die erste Fassung dieser Seite zählte die Mock-Lane und schrieb „A” über die echte Lane. Das war falsch: beide Spec-Dateien der echten Lane begannen mit test.skip(!process.env.E2E_REAL_QUALIFICATION, …), und nichts setzt diese Variable — nicht der Nightly-Workflow, nicht package.json, keine Konfiguration. Der letzte grüne Nachtlauf (2026-08-29, Task 206965) lief „41 tests: 40 skipped, 1 passed” — die eine bestandene Zelle ist auth.setup. Die Lane war seit 2026-08-06 ein leeres Grün (Commit 34d95957a: die #791-Qualifikationsklassen C2/C3/E1 ritten in jedem Nachtlauf rot, #840, und wurden geparkt; #791 hält fest, dass die Reaktivierung je Lane und vom Owner entschieden wird). Die Parkung bleibt, bis der Owner entscheidet; der MECHANISMUS änderte sich auf feat/e2e-real-lane-testids: jede geparkte Zelle trägt @qualification, die Konfigurationen schließen das Tag auf Projektebene aus, solange E2E_REAL_QUALIFICATION=1 nicht gesetzt ist, und die Auflistung zeigt 1 Test (geparkt) oder 39 (Qualifikation an) statt 40 stiller Skips. Derselbe Durchgang machte die Seed-Vorbedingung zu @nightly-seeded, die zwei Layout-Skips zu Projekt-Tags und entfernte die eigenen Sleeps der echten Lane (drei 100-ms-Pacing-Sleeps und zwei Retry-Backoffs), die die erste Fassung ebenfalls nicht gezählt hatte.

Klasse Zellen / Stellen Wo
A 40 Zellen der echten Lane + auth.setupnur mit E2E_REAL_QUALIFICATION=1; im heutigen Nachtlauf sind sie D tests/e2e-real
B 1 app-real-flows.spec.ts:373 (geseedeter Run)
C 0
D 40 im CI (die geparkte echte Lane, siehe Korrektur oben); 0 test.skip-Aufrufe verbleiben in beiden Lanes 19 Mock-Lane-Skips wurden am 2026-09-04 zu Projekt-Tags (app-flows 6 @mobile-only, delivery-debt-surfaces 9 @desktop-only, core-loop / crud-matrix / optimistic-conflicts describe-weit @desktop-only, mobile-feed-scroll @mobile-only)
E 0 kein created_at- / updated_at-Schreibzugriff in scripts/e2e oder den Specs
F 0 jede gefahrene Route ist die Route eines angemeldeten Nutzers oder Admins; die Legacy-Stubs werden absichtlich gefahren, um die Umleitung zu prüfen
M 208 Zellen tests/e2e
Regel-6-Schuld echte Lane: am 2026-09-04 getilgt (Inhaltsprüfungen ausgenommen); Mock-Lane: role 178, text 70, .locator( 46 (27 an Klasse oder Id verankert) noch offen — die Mock-Lane ist nach dem Standard kein E2E, die Migration dort ist Hygiene je Spec oben
Handbuch-Regel Stand 2026-09-04
Playwright, Chromium primär Ja. Firefox- und WebKit-Smoke-Projekte fehlen: das CI-Image bringt seine Browser vorinstalliert mit (PLAYWRIGHT_BROWSERS_PATH, kein npx playwright install in den Workflows), also kommen die beiden weiteren Browser mit dem Image (bw-infra scripts/ci-images), und die Konfigurationen ergänzen dann die zwei Projekte.
trace: on-first-retry, video: retain-on-failure Ja, alle drei Konfigurationen.
Auto-Retry höchstens einmal Ja: retries: process.env.CI ? 1 : 0 in allen drei Konfigurationen (vorher 2).
Kein waitForTimeout / Sleep Ja: 0 Aufrufe in tests/e2e und tests/e2e-real. Sieben Stellen wurden am 2026-09-04 umgeschrieben: badge-coordinator.spec.ts (drei Sleeps → expect.poll auf den Fetch-Zähler je Tab), core-loop.spec.ts (ein Sleep → page.waitForResponse auf das Snapshot-GET, das der Route-Handler des Tests selbst vorbereitet), mobile-capture / mock-capture-desktop / mock-conformance (je ein Sleep → settleForCapture in route-helpers.ts: Netzwerk ruhig, Schriften geladen, kein aria-busy, zwei gemalte Frames).
Kein test.skip / fixme; gepinnte Defekte über test.fail() + Ticket Ja: 0 Skips; heute ist kein Defekt gepinnt, also 0 test.fail().
Nur data-testid Nein — siehe die Zeile zur Regel-6-Schuld; die Migration sind additive Commits am Produkt (eine Test-Id kommt dorthin, wo der Test hinschaut), Spec für Spec.
Falsifikationsnachweis für jede umgeschriebene Spec Unten festgehalten für die Umschreibung vom 2026-09-04.
Spec-Wahrheitstabelle Diese Seite.
≤ 10 Minuten Wanduhr Mock-Lane: lokal 3,5 min (208 Zellen, 8 Worker); 9,8 min im nächtlichen mock-e2e-full-Job auf dem 4-CPU-Runner, Build eingeschlossen — am Rand des Budgets, also gehört der Build in einen eigenen Schritt, bevor Playwrights Uhr läuft. Echte Lane: der Playwright-Schritt des Nightly-Jobs; seine Dauer wird aus dem Workflow-Lauf gelesen, sobald die Lane wieder startet (PR #1265).
Nur lokal, nie Staging Ja: die echte Lane bootet ihren eigenen Stack (scripts/e2e/boot-nightly-stack.sh), die Mock-Lane braucht kein Backend. Keine Konfiguration zeigt auf einen Stage- oder Produktions-Origin.
Jeder Produktionsvorfall nennt die Spec, die ihn gefangen hätte 2026-09-01: die nächtliche Real-Backend-Lane startete nicht mehr (act prüfte das --memory=12g des Workflows gegen die 6-GiB-Kappe der Runner-Lane und lehnte den Job vor seinem ersten Schritt ab). Keine Spec kann eine Lane fangen, die nicht startet; die Sicherung ist die Workflow-Deklaration (--memory=6g, PR #1265) plus die konsumentenseitige Speicher-Sicherung in bw-infra.

Falsifikationsprotokoll — Mechanik-Umschreibung 2026-09-04

Abschnitt betitelt „Falsifikationsprotokoll — Mechanik-Umschreibung 2026-09-04“

Regel 7 verlangt drei Läufe je umgeschriebener Spec: (a) die alte Spec bleibt grün mit absichtlich gebrochenem Produktpfad, (b) die neue Spec wird auf demselben Bruch rot, (c) die neue Spec ist auf dem intakten Pfad grün. Die Umschreibung vom 2026-09-04 hat Wartebedingungen geändert, nicht Zusicherungen — die alten Specs prüften bereits die Fetch-Zählung und den Follow-Snapshot, sie schliefen nur eine feste Zeit, bevor sie es taten. Lauf (a) kann darum keine Lücke zeigen, die die alte Spec hatte; was die Läufe belegen, ist, dass die neuen Wartebedingungen echte Bedingungen sind (rot, wenn der Pfad gebrochen ist) und dass der intakte Pfad grün ist.

Lauf Was Ergebnis
(c) intakt volle Mock-Lane, beide Projekte, vorgebautes Web (PLAYWRIGHT_PREBUILT_WEB=1), --ignore-snapshots wie im CI-Job siehe Lane-Historie unten: der Lauf vor dem Fixture-Fix reproduzierte den CI-Fehler exakt (204 grün, 4 rot, 2,1 min); der letzte Lauf nach dem Fix steht dort
(b) gebrochen, Badge der Badge-Fetch des Produkts (inbox-actionable.ts, beide Fetch-Stellen) passiert nie; neu gebaut; badge-coordinator.spec.ts rot in beiden Tests: expect.poll auf den Fetch-Zähler je Tab läuft nach 10 s aus („no tab fetched … hits=[0,0,0]“)
(a) alt, Badge die Spec vor der Umschreibung auf demselben gebrochenen Build ebenfalls rot: nach ihrem festen 2,5-s-Sleep scheitert dieselbe Zähler-Zusicherung — die Umschreibung hat das Warten geändert, nicht die Zusicherung, also gibt es keine Lücke, die (a) zeigen könnte
(b) gebrochen, Follow das kalte Snapshot-GET wird nie beantwortet (das Mock-Backend hält es); Follow-Test in core-loop.spec.ts rot: page.waitForResponse auf den Snapshot löst nie auf (Test-Timeout 30 s) — das Warten ist eine echte Bedingung, kein No-op
(a) alt, Follow die Spec vor der Umschreibung auf demselben Hänger auch rot, später und unschärfer: ihr expect.poll auf den Request-Zähler besteht (der Request ging raus), der 400-ms-Sleep verstreicht, und die Backfill-Zusicherung nach dem Resync scheitert

Lane-Historie, am 2026-09-04 aus der Forgejo-Actions-Datenbank gelesen

Abschnitt betitelt „Lane-Historie, am 2026-09-04 aus der Forgejo-Actions-Datenbank gelesen“
Lane Zustand Seit Ursache Behebung
Mock voll (mock-e2e-full) rot 2026-09-02 (grün am 31.08. und 01.09.) marketplace-subscription.spec.ts trug ein festes Bezahlt-bis-Datum (2026-09-01); ab 02.09. sagte die Karte „access has ended” — 4 Zellen rot in beiden Projekten, 204 grün, 9,8 min auf dem 4-CPU-Runner inklusive Build Fixture-Daten und die zwei Datums-Erwartungen folgen der Lauf-Uhr (daysFromNow, calendarDay) — lokal 14/14
Mock voll, lokal rot auf jedem Entwicklerrechner mit einem Backend auf :8080 das SSR-Auth-Tor der Preview löste das Cookie gegen ein fremdes lokales Backend auf und leitete nach /login um, bevor die In-Page-Mocks erreicht wurden (≈60 Zellen) webServer.env.BACKEND_URL in playwright.config.ts auf einen toten Port gepinnt
Echt nächtlich (e2e-nightly) rot 2026-08-30 30./31.08.: ein Kommentar in der fortgesetzten docker run-Kette von boot-nightly-stack.sh beendete das Kommando vor dem Image-Namen (auf main bereits behoben, das Skript dokumentiert es); ab 01.09.: act lehnte den Job vor dem ersten Schritt ab (--memory=12g gegen die 6-GiB-Kappe der Lane) PR #1265 (--memory=6g) plus die konsumentenseitige Sicherung in bw-infra
Smoke Core-Loop (smoke-e2e, PR-Netz) grün
Mock voll, lokal final grün 2026-09-04 der letzte intakte Lauf nach den Korrekturen, beide Projekte, --ignore-snapshots wie im CI 208 von 208 Zellen bestanden in 3,5 min (Lauf vor dem Fix: 204 / 4 in 2,1 min)