import { expect, test } from "bun:test"; import { createProductionHandlers } from "../src/prod.ts"; test("component resolution preserves JSON user/permission props and drops unresolved bindings", async () => { let received: Record = {}; const handlers = createProductionHandlers( { pages: [ { raw: "/", mod: { default: () => '

Account content

', }, }, ], api: [], realtime: [], middleware: [], layouts: [], components: [ { name: "AccountShell", mod: { render: (props: Record) => { received = props; const identity = JSON.parse(props.identity ?? "{}"); const permissions = JSON.parse(props.permissions ?? "{}"); return permissions.read ? "
" + identity.displayName + "
" : "
Denied
"; }, }, }, ], }, {}, ); const response = await handlers.fetch(new Request("http://localhost/"), { upgrade: () => false }); expect(response?.status).toBe(200); const html = await response!.text(); expect(html).toContain("Alice"); expect(html).toContain("Account content"); expect(JSON.parse(received.permissions!)).toEqual({ read: true, update: false }); expect(JSON.parse(received.preferences!)).toEqual({ theme: "dark" }); expect(received.pending).toBeUndefined(); expect(received.value).toBe("{{order}}"); }); test("recursive inert components reuse request-local control prototypes", async () => { const { encodeControlTemplate } = await import("@wrnexus/core"); let renders = 0; const handlers = createProductionHandlers( { pages: [{ raw: "/", mod: { default: () => '
' } }], api: [], realtime: [], middleware: [], layouts: [], components: [ { name: "Tree", mod: { render: () => { renders++; const control = encodeControlTemplate([ { cond: "open", body: '
' }, ]); return `
`; }, }, }, ], }, {}, ); for (let index = 0; index < 2; index++) { const before = renders; const response = await handlers.fetch(new Request("http://localhost/"), { upgrade: () => false, }); expect(response?.status).toBe(200); const html = await response!.text(); expect(renders - before).toBeLessThanOrEqual(3); expect(html.length).toBeLessThan(10000); expect(html).toContain("wrn-controls-"); } }); test("recursive mixed prop bindings do not grow inert prototypes", async () => { const { encodeControlTemplate } = await import("@wrnexus/core"); let renders = 0; const handlers = createProductionHandlers( { pages: [ { raw: "/", mod: { default: () => '
' } }, ], api: [], realtime: [], middleware: [], layouts: [], components: [ { name: "Branch", mod: { render: (props: Record) => { renders++; const prefix = props.prefix || ""; const binding = "["prefix","{prefix}-child"]"; const body = `
`; const control = encodeControlTemplate([{ cond: "open", body }]); return `

${prefix}

`; }, }, }, ], }, {}, ); const response = await handlers.fetch(new Request("http://localhost/"), { upgrade: () => false }); const html = await response!.text(); expect(renders).toBeLessThanOrEqual(3); expect(html.length).toBeLessThan(10000); expect(html).toContain("

live

"); }); test("loop-local bridge metadata does not multiply recursive prototypes", async () => { const { encodeControlTemplate } = await import("@wrnexus/core"); let renders = 0; const handlers = createProductionHandlers( { pages: [{ raw: "/", mod: { default: () => '
' } }], api: [], realtime: [], middleware: [], layouts: [], components: [ { name: "LoopTree", mod: { render: () => { renders++; const locals = Buffer.from(JSON.stringify({ row: renders })).toString("base64"); const control = encodeControlTemplate([ { cond: "open", body: `
`, }, ]); return `
`; }, }, }, ], }, {}, ); const response = await handlers.fetch(new Request("http://localhost/"), { upgrade: () => false }); expect(response?.status).toBe(200); expect(renders).toBeLessThanOrEqual(3); expect((await response!.text()).length).toBeLessThan(10000); }); test("inline compiler controls in recursive prototypes are hoisted once", async () => { let renders = 0; const encoded = Buffer.from( JSON.stringify([ { cond: "open", body: '
', }, ]), ).toString("base64"); const handlers = createProductionHandlers( { pages: [{ raw: "/", mod: { default: () => '
' } }], api: [], realtime: [], middleware: [], layouts: [], components: [ { name: "InlineTree", mod: { render: () => { renders++; return `
`; }, }, }, ], }, {}, ); const response = await handlers.fetch(new Request("http://localhost/"), { upgrade: () => false }); expect(response?.status).toBe(200); expect(renders).toBeLessThanOrEqual(3); expect((await response!.text()).length).toBeLessThan(10000); });