import test from 'node:test' import assert from 'node:assert/strict' import path from 'node:path' import { fileURLToPath } from 'node:url' import esbuild from 'esbuild' // Die Boundary ist JSX mit React: gebündelt wird mit eigenem automatischem JSX-Laufzeitpaket (load.mjs kennt kein JSX). // Gezeichnet wird mit renderToStaticMarkup; der Fehlerzustand kommt über eine Unterklasse, die ihn vorab setzt // (der Server-Renderer selbst fängt keine Fehler in Boundaries ab). const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../..') async function load() { const result = await esbuild.build({ stdin: { contents: [ "import { createElement } from 'react'", "import { renderToStaticMarkup } from 'react-dom/server'", "import Boundary from './src/components/RouteErrorBoundary.jsx'", 'export { createElement, renderToStaticMarkup, Boundary }', ].join('\n'), resolveDir: repoRoot, loader: 'js', }, bundle: true, format: 'esm', platform: 'browser', jsx: 'automatic', define: { 'process.env.NODE_ENV': '"production"' }, write: false, }) const code = result.outputFiles[0].text return import(`data:text/javascript;base64,${Buffer.from(code).toString('base64')}`) } test('RouteErrorBoundary: ohne Fehler bleiben die Kinder unverändert', async () => { const { createElement, renderToStaticMarkup, Boundary } = await load() const html = renderToStaticMarkup(createElement(Boundary, { resetKey: '/hustler' }, createElement('p', null, 'Inhalt'))) assert.equal(html, '

Inhalt

') }) test('RouteErrorBoundary: im Fehlerfall Hinweis mit Knopf „Seite neu laden“ statt der Kinder, als Alarm ausgezeichnet', async () => { const { createElement, renderToStaticMarkup, Boundary } = await load() class Probe extends Boundary { constructor(props) { super(props) this.state = { error: new TypeError('Failed to fetch dynamically imported module'), resetKey: props.resetKey } } } const html = renderToStaticMarkup(createElement(Probe, { resetKey: '/hustler' }, createElement('p', null, 'Inhalt'))) assert.doesNotMatch(html, /Inhalt/) assert.match(html, /role="alert"/) assert.match(html, /Diese Seite konnte nicht angezeigt werden\./) assert.match(html, /]*type="button"[^>]*>Seite neu laden<\/button>/) assert.match(html, /neue Version von WOMS/) }) test('RouteErrorBoundary: getDerivedStateFromError merkt den Fehler, ein Pfadwechsel räumt ihn weg, gleicher Pfad nicht', async () => { const { Boundary } = await load() const err = new TypeError('Failed to fetch dynamically imported module') assert.deepEqual(Boundary.getDerivedStateFromError(err), { error: err }) const stuck = { error: err, resetKey: '/hustler' } assert.equal(Boundary.getDerivedStateFromProps({ resetKey: '/hustler' }, stuck), null) assert.deepEqual(Boundary.getDerivedStateFromProps({ resetKey: '/tickets' }, stuck), { error: null, resetKey: '/tickets' }) assert.deepEqual(Boundary.getDerivedStateFromProps({ resetKey: '/tickets' }, { error: null, resetKey: '/hustler' }), { error: null, resetKey: '/tickets' }) })