Files
buuh/packages/html/test/hydrate.test.js
T

76 lines
2.6 KiB
JavaScript
Raw Normal View History

// Hydration: adoption semantics and mismatch detection.
import { test, before } from 'node:test'
import assert from 'node:assert'
import { Window } from 'happy-dom'
let html, hydrate
before(async () => {
const win = new Window()
globalThis.window = win
globalThis.document = win.document
;({ default: html } = await import('../browser.js'))
;({ default: hydrate } = await import('../hydrate.js'))
})
test('agreeing trees hydrate without a mismatch report', () => {
const a = html`<div class="x"><h1>hi</h1><p>body</p></div>`
const b = html`<div class="x"><h1>hi</h1><p>body</p></div>`
let reported = null
hydrate(a, b, { onMismatch: (d) => { reported = d } })
assert.strictEqual(reported, null)
})
test('adoption: matching child nodes keep their identity through hydrate', () => {
const server = html`<div><h1>hi</h1><input value="typed by user" /></div>`
const serverH1 = server.querySelector('h1')
const serverInput = server.querySelector('input')
const client = html`<div><h1>hi</h1><input value="typed by user" /></div>`
hydrate(server, client)
assert.strictEqual(server.querySelector('h1'), serverH1, 'h1 adopted in place')
assert.strictEqual(server.querySelector('input'), serverInput, 'input adopted in place')
})
test('text mismatches are reported with a path, client wins', () => {
const server = html`<div><h1>count is 0</h1></div>`
const client = html`<div><h1>count is 7</h1></div>`
let reported = null
hydrate(server, client, { onMismatch: (d) => { reported = d } })
assert.strictEqual(reported.reason, 'text')
assert.match(reported.path, /div > h1/)
assert.strictEqual(reported.server, 'count is 0')
assert.strictEqual(reported.client, 'count is 7')
assert.strictEqual(server.textContent, 'count is 7', 'client render won')
})
test('attribute mismatches are reported', () => {
const server = html`<div><a href="/old">go</a></div>`
const client = html`<div><a href="/new">go</a></div>`
let reported = null
hydrate(server, client, { onMismatch: (d) => { reported = d } })
assert.strictEqual(reported.reason, 'attribute')
assert.match(reported.server, /\/old/)
assert.match(reported.client, /\/new/)
})
test('child count mismatches are reported', () => {
const server = html`<ul><li>a</li></ul>`
const client = html`<ul><li>a</li><li>b</li></ul>`
let reported = null
hydrate(server, client, { onMismatch: (d) => { reported = d } })
assert.strictEqual(reported.reason, 'children')
})
test('mismatch detection is optional and hydrate still morphs without it', () => {
const server = html`<p>old</p>`
const client = html`<p>new</p>`
hydrate(server, client)
assert.strictEqual(server.textContent, 'new')
})