import { expect, test } from "bun:test"; import { renderDocument, renderDocumentStream, renderStoreHydration } from "../src/index.ts"; import type { StoreContainer } from "@wrnexus/store"; test("store hydration is HTML-safe, bounded, redacted, and JSON-compatible", () => { const container = { serialize: () => ({ ProfileStore: { display: "", accessToken: "never-render-this", }, }), } as unknown as StoreContainer; const html = renderStoreHydration(container, 'safe" onload="bad'); expect(html).not.toContain("", accessToken: "[REDACTED]" }, }); const oversized = { serialize: () => ({ value: "x".repeat(300_000) }), } as unknown as StoreContainer; expect(() => renderStoreHydration(oversized)).toThrow("exceeds 262144 bytes"); }); test("escapes metadata and script URLs while preserving trusted rendered body", () => { const html = renderDocument({ meta: { title: '', description: '" onload="x' }, body: "
trusted
", scripts: ['">'], }); expect(html).not.toContain(''); expect(html).toContain("</title>"); expect(html).toContain("
trusted
"); expect(html).not.toContain(""); }); test("deduplicates runtime scripts and module preloads", () => { const html = renderDocument({ meta: { title: "Page" }, body: "", scripts: ["/app.js", "/app.js"], }); expect(html.match(/rel="modulepreload"/g)).toHaveLength(1); expect(html.match(/src="\/app\.js"/g)).toHaveLength(1); }); test("always emits a document language and preserves an explicit language", () => { const fallback = renderDocument({ meta: {}, body: "" }); expect(fallback).toContain(''); const explicit = renderDocument({ meta: {}, body: "", htmlAttrs: ' data-theme="dark" lang="fr"', }); expect(explicit).toContain(''); expect(explicit).not.toContain('lang="en"'); }); test("merges framework head and scripts into an application document template", () => { const html = renderDocument({ meta: { title: "Document layout" }, body: "", htmlAttrs: ' data-theme="dark"', scripts: ["/page.js"], documentTemplate: '
Page
', }); expect(html).toStartWith(""); expect(html).toContain(''); expect(html).toContain("Document layout"); expect(html).toContain(''); expect(html).toContain(''); expect(html.match(/ { async function* body() { yield "

Shell

"; yield "

Later

"; } const html = await new Response( renderDocumentStream({ meta: { title: "Stream" }, body: body() }), ).text(); expect(html).toContain('

Shell

Later

'); }); test("renders rich script metadata and deduplicates by source", () => { const html = renderDocument({ meta: { title: "Runtime" }, body: '
', scripts: [ { src: "/__wrnexus/assets/captcha.abc.js", type: "classic", defer: true, integrity: "sha256-test", crossOrigin: "anonymous", attributes: { "data-wrnexus-runtime-src": "captcha" }, }, { src: "/__wrnexus/assets/captcha.abc.js", type: "classic" }, ], }); expect(html.match(/captcha\.abc\.js/g)).toHaveLength(1); expect(html).toContain("defer"); expect(html).toContain('integrity="sha256-test"'); expect(html).toContain('crossorigin="anonymous"'); expect(html).toContain('data-wrnexus-runtime-src="captcha"'); expect(html).not.toContain('rel="modulepreload" href="/__wrnexus/assets/captcha.abc.js"'); }); test("promotes WRN style blocks into head after global CSS with CSP nonce", () => { const html = renderDocument({ meta: { title: "Styled" }, extraHead: '', styleNonce: "nonce-123", body: '' + '' + '' + '
Styled
', }); expect(html).not.toContain('
Styled'); expect(html.match(/data-wrnexus-style-id=/g)).toHaveLength(3); expect(html.match(/nonce="nonce-123"/g)).toHaveLength(3); const globalIndex = html.indexOf("/global.css"); const layoutIndex = html.indexOf('data-wrnexus-style-id="layout"'); const pageIndex = html.indexOf('data-wrnexus-style-id="page"'); const componentIndex = html.indexOf('data-wrnexus-style-id="card"'); expect(globalIndex).toBeLessThan(layoutIndex); expect(layoutIndex).toBeLessThan(pageIndex); expect(pageIndex).toBeLessThan(componentIndex); }); test("deduplicates repeated component style blocks", () => { const style = ''; const html = renderDocument({ meta: { title: "Repeated" }, body: `${style}
One
${style}
Two
`, }); expect(html.match(/data-wrnexus-style-id="card"/g)).toHaveLength(1); expect(html).toContain("
One
Two
"); }); test("places document-layout WRN styles at the end of head", () => { const html = renderDocument({ meta: { title: "Document styles" }, styleNonce: "document-nonce", body: "", documentTemplate: '' + '' + '
Page
', }); const globalIndex = html.indexOf("/document-global.css"); const styleIndex = html.indexOf('data-wrnexus-style-id="document-layout"'); const headEnd = html.indexOf(""); expect(globalIndex).toBeLessThan(styleIndex); expect(styleIndex).toBeLessThan(headEnd); expect(html).not.toContain("