template-studio/server/templateEngine.test.js

83 lines
2.7 KiB
JavaScript

import test from 'node:test'
import assert from 'node:assert/strict'
import { interpolate, renderReportHtml, renderEmailHtml } from './templateEngine.js'
test('interpolates nested values', () => {
assert.equal(interpolate('Hello {{customer.name}}', { customer: { name: 'Kauri' } }), 'Hello Kauri')
})
test('report output escapes injected markup', () => {
const html = renderReportHtml({ blocks: [{ type: 'text', props: { text: '{{value}}' } }] }, { value: '<script>x</script>' })
assert.match(html, /&lt;script&gt;/)
assert.doesNotMatch(html, /<script>x/)
})
test('email renderer produces HTML', () => {
const html = renderEmailHtml({ blocks: [{ type: 'heading', props: { text: 'Hello' } }] }, {})
assert.match(html, /Hello/)
assert.match(html, /doctype/i)
})
test('report renderer applies constrained pack theme styling', () => {
const html = renderReportHtml({
theme: {
backgroundColor: '#f6f1e8',
accentColor: '#8b5e34',
pageBackgroundImage: 'https://templates.arrowstack.dev/media/token/bg.webp'
},
blocks: [{
type: 'heading',
props: { text: 'Styled' },
style: { backgroundColor: '#fffaf2', padding: 18, borderRadius: 12 }
}]
}, {})
assert.match(html, /#f6f1e8/)
assert.match(html, /#8b5e34/)
assert.match(html, /bg\.webp/)
assert.match(html, /padding:18px/)
})
test('report renderer constrains logo and hero images for print layout', () => {
const html = renderReportHtml({
blocks: [
{ id: 'logo', type: 'image', props: { url: 'https://example.com/logo.png', alt: 'Company logo' } },
{ id: 'hero', type: 'image', props: { url: 'https://example.com/hero.jpg', alt: 'Hero banner' } }
]
}, {})
assert.match(html, /image-logo/)
assert.match(html, /max-height:72px/)
assert.match(html, /image-hero/)
assert.match(html, /max-height:260px/)
assert.match(html, /object-fit:cover/)
})
test('report blocks avoid page breaks by default and support explicit page controls', () => {
const html = renderReportHtml({
blocks: [{
id: 'title',
type: 'heading',
props: { text: 'Title' },
style: { keepWithNext: true, pageBreakBefore: true }
}]
}, {})
assert.match(html, /break-before:page/)
assert.match(html, /break-after:avoid-page/)
assert.match(html, /page-break-inside:avoid/)
})
test('report renderer applies independent page margins in millimetres', () => {
const html = renderReportHtml({
theme: {
pageMarginTop: 8,
pageMarginRight: 10,
pageMarginBottom: 14,
pageMarginLeft: 16,
pagePadding: 22
},
blocks: [{ type: 'text', props: { text: 'Margins' } }]
}, {})
assert.match(html, /margin:8mm 10mm 14mm 16mm/)
assert.match(html, /min-height:calc\(297mm - 22mm\)/)
assert.match(html, /padding:22px/)
})