import { expect, test } from "bun:test"; import { resolveDocumentVariables, type BlockDocument } from "@wrnexus/blocks"; import { renderEmail } from "../src/index.ts"; const document: BlockDocument = { schemaVersion: 1, kind: "email", meta: { subject: "Hi {{recipientName|friend}}", lang: "en" }, theme: { tokens: {} }, root: { id: "root", type: "layout.email-document", version: 1, props: {}, styles: {}, slots: { content: [{ id: "text", type: "content.text", version: 1, props: { text: "Hello {{recipientName|friend}}" }, styles: {}, slots: {} }], } }, }; test("template rendering preserves fallback tokens rather than baking in sample or fallback values", async () => { const before = structuredClone(document); const rendered = await renderEmail(document, { preserveVariables: true, mjml: true, variables: { recipientName: "Preview only" } }); expect(rendered.ok).toBe(true); if (!rendered.ok) return; expect(rendered.value.subject).toBe("Hi {{recipientName|friend}}"); expect(rendered.value.parts.html.content).toContain("Hello {{recipientName|friend}}"); expect(rendered.value.parts.text.content).toContain("Hello {{recipientName|friend}}"); expect(rendered.value.exports?.mjml).toContain("Hello {{recipientName|friend}}"); expect(document).toEqual(before); const resolved = await renderEmail(document, { variables: { recipientName: "Ada" }, requireVariables: true }); expect(resolved.ok && resolved.value.subject).toBe("Hi Ada"); }); test("preservation still validates token allowlists and cannot masquerade as resolved delivery", () => { const unknown = structuredClone(document); unknown.meta.subject = "{{unregistered}}"; expect(resolveDocumentVariables(unknown, { recipientName: "string" }, {}, { preserveTokens: true }).ok).toBe(false); expect(resolveDocumentVariables(document, { recipientName: "string" }, {}, { preserveTokens: true, requireValues: true }).ok).toBe(false); });