Skip to content

test(e2e): Code-Splitting an der Quelle prüfen statt einen Import stoppen - #24

Merged
Baldri merged 1 commit into
mainfrom
claude/session/fix/mingly-code-splitting-flake
Aug 27, 2026
Merged

test(e2e): Code-Splitting an der Quelle prüfen statt einen Import stoppen#24
Baldri merged 1 commit into
mainfrom
claude/session/fix/mingly-code-splitting-flake

Conversation

@Baldri

@Baldri Baldri commented Aug 27, 2026

Copy link
Copy Markdown
Owner

Was

Der Test Code Splitting > should have lazy-loadable components defined as dynamic imports prüft nicht mehr, wie lange ein dynamischer Import braucht, sondern ob die App überhaupt code-splittet.

Warum

Der Test wartete auf einen echten dynamischen Import von MarkdownRenderer. Der zieht react-markdown, react-syntax-highlighter und ein Prism-Theme durch Vites Transformation — und lief gegen Vitests 5-Sekunden-Standard.

Gemessen am 2026-08-27:

Bedingung Ergebnis
isoliert, ruhige Maschine 576 ms, 5 von 5 grün
vier volle Suiten gleichzeitig 4 von 4 rot, 5002–5005 ms

Ein Zeitlimit gegen die Wanduhr ist in einer parallel laufenden Suite keine belastbare Bedingung.

Das Timeout wurde nicht hochgesetzt. Der Test kodierte die Anforderung falsch: er belegte, dass der Testrunner eine Datei importieren kann — eine Eigenschaft des Bundlers, nicht der Anwendung. Er wäre auch dann grün geblieben, wenn MessageList den MarkdownRenderer statisch importiert hätte, also wenn genau das Code-Splitting, nach dem er benannt ist, entfernt worden wäre.

Änderungen

tests/e2e/app.spec.ts — ein Test ersetzt durch drei, alle quellbasiert:

  1. Fundstellen-Wächter — es gibt mindestens einen lazy(() => import(...))-Aufruf und MarkdownRenderer ist darunter. Ohne ihn könnte der Rest auf einer leeren Menge grün laufen.
  2. Kein statischer Import der schweren Komponente an der Stelle, die sie lazy lädt.
  3. Jedes lazy geladene Modul kann React.lazy bedienenexport default, oder der Adapter .then(m => ({ default: m.X })) zeigt auf einen Export, den es gibt.

Punkt 3 sichert eine echte Fehlerklasse ab, die vorher nichts geprüft hat: ein lazy geladenes Modul ohne passenden Export scheitert erst zur Laufzeit, und nur dann, wenn ein Nutzer diese Ansicht öffnet.

Tests

npm test1327 passed | 29 skipped, Exit 0
npm run typecheck → Exit 0

Drei Sabotagen, jede gefangen — keine davon hätte der alte Test bemerkt:

Sabotage Ergebnis
MarkdownRenderer statisch importieren 2 Tests rot
export default daraus entfernen 1 Test rot
Export umbenennen, auf den ein Adapter zeigt 1 Test rot

Gegenprobe unter derselben Last, die den alten Test umwarf: vier gleichzeitige Suiten, 4 von 4 grün, Exit 0. Die drei neuen Tests laufen in 0, 0 und 4 ms statt 576 ms.

Review-Punkte

Ein bestehender Test wurde verändert — nach eurer Regel nur zulässig, wenn er den Bug kodierte. Das ist hier der Fall und oben begründet: er prüfte die Implementierung gegen sich selbst statt gegen die Anforderung. Die neue Anforderung, gegen die geprüft wird, steht im Testkommentar.

Die Prüfung ist quellbasiert, arbeitet also mit einem regulären Ausdruck über TypeScript-Quelltext. Das ist bewusst: es liest eine Handvoll Dateien, braucht keine Transformation und hängt an keiner Uhr. Ein ungewöhnlich formatierter lazy-Aufruf würde übersehen — dagegen steht der Fundstellen-Wächter, der leer laufende Prüfungen ausschliesst.

Nicht abgedeckt: die manualChunks-Konfiguration in vite.config.ts (vendor-markdown) ist die zweite Hälfte des Code-Splittings und wird hier nicht geprüft. Das bräuchte einen Build und gehört nicht in eine Unit-Suite.

🤖 Generated with Claude Code

The Code Splitting test awaited a real dynamic import of MarkdownRenderer,
which pulls react-markdown and react-syntax-highlighter through Vite's
transform. That cost is wall-clock and ran against vitest's 5 s default:
576 ms on an idle machine, but over the limit under parallel load. Measured
2026-08-27 with four full suites in flight — reproduced in 4 of 4 runs at
5002-5005 ms, while the same test passed 5 of 5 in isolation.

The timeout is not raised. The test encoded the requirement wrongly: it
proved that the test runner can import a file, which is a property of the
bundler, not of the app. It would have stayed green if MessageList had
imported MarkdownRenderer statically — that is, if the code splitting it is
named after had been removed entirely.

It now checks the requirement against the source: every renderer component
reached through lazy(() => import(...)) must resolve to a file that can
satisfy React.lazy — a default export, or the .then(m => ({ default: m.X }))
adapter naming an export that exists. A guard test asserts the site list is
non-empty and contains MarkdownRenderer, so the suite cannot pass vacuously.

Three sabotages, each caught, none of which the old test would have noticed:
importing MarkdownRenderer statically (2 tests red), dropping its default
export (1 red), renaming an export an adapter points at (1 red).

Same load that broke the old test: 4 of 4 suites green, exit 0. The three
new tests run in 0, 0 and 4 ms instead of 576 ms.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@Baldri
Baldri merged commit 7e02858 into main Aug 27, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant