a post-component library for building user-interfaces on the web.
1import { mock, test } from 'bun:test'
2import { html } from 'dhtml'
3import { renderToReadableStream, renderToString } from 'dhtml/server'
4import assert from 'node:assert/strict'
5
6const dev_test = test.skipIf(!__DEV__)
7
8test('basic html renders correctly', () => {
9 assert.equal(renderToString(html`<h1>Hello, world!</h1>`), '<h1>Hello, world!</h1>')
10})
11
12test('basic html renders correctly via stream', async () => {
13 const stream = renderToReadableStream(html`<h1>Hello, world!</h1>`)
14 assert.equal(await new Response(stream).text(), '<h1>Hello, world!</h1>')
15})
16
17test('inner content renders correctly', () => {
18 assert.equal(renderToString(html`<h1>${html`Inner content!`}</h1>`), '<h1>Inner content!</h1>')
19})
20
21test('template with number renders correctly', () => {
22 const template = (n: number) => html`<h1>Hello, ${n}!</h1>`
23 assert.equal(renderToString(template(1)), '<h1>Hello, 1!</h1>')
24 assert.equal(renderToString(template(2)), '<h1>Hello, 2!</h1>')
25})
26
27test('lists of items', () => {
28 assert.equal(renderToString([1, 'a', html`<span>thing</span>`]), '1a<span>thing</span>')
29})
30
31test('basic children render correctly', () => {
32 assert.equal(
33 renderToString(html`<span>${'This is a'}</span> ${html`test`} ${html`test`} ${html`test`}`),
34 '<span>This is a</span> test test test',
35 )
36})
37
38dev_test('invalid part placement raises error', () => {
39 assert.throws(() => renderToString(html`<${'div'}>${'text'}</${'div'}>`))
40})
41
42test('parts in comments do not throw', () => {
43 renderToString(html`<!-- ${'text'} -->`)
44})
45
46dev_test('manually specifying internal template syntax throws', () => {
47 assert.throws(() => {
48 renderToString(html`${1} dyn-$0$`)
49 })
50})
51
52test('syntax close but not exact does not throw', () => {
53 assert.equal(renderToString(html`dyn-$${0}1$`), 'dyn-$01$')
54})
55
56test('directives', () => {
57 const directive = mock()
58 assert.equal(renderToString(html`<p ${directive}></p>`), '<p ></p>')
59 assert.equal(directive.mock.calls.length, 1)
60 assert.deepEqual(directive.mock.calls[0], [])
61})
62
63test('attributes', () => {
64 assert.equal(renderToString(html`<a href=${'/url'}></a>`), '<a href="/url"></a>')
65 assert.equal(renderToString(html`<details hidden=${false}></details>`), '<details ></details>')
66 assert.equal(renderToString(html`<details hidden=${true}></details>`), '<details hidden></details>')
67})
68
69test('collapses whitespace', () => {
70 // prettier-ignore
71 assert.equal(renderToString(html` <p> </p> `), ' <p> </p> ')
72
73 // prettier-ignore
74 assert.equal(renderToString(html` <p> x </p> `), ' <p> x </p> ')
75})