// Streaming SSR, proven at two levels: raw chunk timing over HTTP, and // progressive DOM construction in real Chromium. import { test, before, after } from 'node:test' import assert from 'node:assert' import { chromium } from 'playwright' import { startServer } from './serve.js' const DELAY = 500 let browser, srv before(async () => { srv = await startServer() browser = await chromium.launch() }) after(async () => { await browser?.close() await srv?.close() }) test('HTTP level: shell bytes arrive before the slow section resolves', async () => { const started = performance.now() const res = await fetch(`${srv.origin}/stream?delay=${DELAY}`) const decoder = new TextDecoder() let sawShellAt = null let text = '' for await (const chunk of res.body) { text += decoder.decode(chunk, { stream: true }) if (sawShellAt === null && text.includes('

choo streams

')) { sawShellAt = performance.now() - started assert.ok(!text.includes('id="slow"'), 'slow section not in the early bytes') } } assert.ok(sawShellAt !== null, 'shell was seen') assert.ok(sawShellAt < DELAY, `shell arrived at ${sawShellAt.toFixed(0)}ms, before the ${DELAY}ms hole`) assert.match(text, /id="slow"/, 'slow section arrived in the same response') assert.match(text, /<\/html>/, 'document completed') }) test('browser level: Chromium builds the shell DOM before the stream ends', async () => { const page = await browser.newPage() await page.goto(`${srv.origin}/stream?delay=${DELAY}`, { waitUntil: 'commit' }) // the shell must be in the DOM while the slow section is still absent await page.waitForSelector('h1', { timeout: DELAY - 100 }) assert.strictEqual(await page.$('#slow'), null, 'slow section not parsed yet') // then the same document grows the slow section without navigation await page.waitForSelector('#slow', { timeout: DELAY * 4 }) assert.match(await page.textContent('#slow'), /500ms later/) await page.close() })