import { describe, it, expect } from 'vitest'
import { createRangeRoot } from './vdom.ts'
import type { Remix } from './component.ts'
describe('createRangeRoot', () => {
it('renders', () => {
let container = document.createElement('div')
let start = document.createComment('range')
let end = document.createComment('/range')
let div = document.createElement('div')
div.innerHTML = 'Hello, world!'
container.appendChild(start)
container.appendChild(div)
container.appendChild(end)
let root = createRangeRoot([start, end])
root.render(
Hello, world!
)
expect(container.innerHTML).toBe('Hello, world!
')
expect(container.firstChild).toBe(start)
expect(container.lastChild).toBe(end)
expect(container.querySelector('div')).toBe(div)
})
it('updates', () => {
let container = document.createElement('div')
let start = document.createComment('range')
let end = document.createComment('/range')
let div = document.createElement('div')
div.innerHTML = 'Hello, world!'
container.appendChild(start)
container.appendChild(div)
container.appendChild(end)
let root = createRangeRoot([start, end])
root.render(Hello, world!
)
expect(container.innerHTML).toBe('Hello, world!
')
expect(container.firstChild).toBe(start)
expect(container.lastChild).toBe(end)
expect(container.querySelector('div')).toBe(div)
root.render(Goodbye, world!
)
expect(container.innerHTML).toBe('Goodbye, world!
')
expect(container.firstChild).toBe(start)
expect(container.lastChild).toBe(end)
expect(container.querySelector('div')).toBe(div)
})
it('adds grows fragments', () => {
let container = document.createElement('div')
let start = document.createComment('range')
let end = document.createComment('/range')
let div = document.createElement('div')
div.innerHTML = 'one'
container.appendChild(start)
container.appendChild(div)
container.appendChild(end)
let root = createRangeRoot([start, end])
root.render(
<>
one
>,
)
expect(container.innerHTML).toBe('one
')
expect(container.firstChild).toBe(start)
expect(container.lastChild).toBe(end)
expect(container.querySelector('div')).toBe(div)
root.render(
<>
one
two
>,
)
expect(container.innerHTML).toBe('one
two
')
expect(container.firstChild).toBe(start)
expect(container.lastChild).toBe(end)
expect(container.querySelector('div')).toBe(div)
})
it('updates components', () => {
let container = document.createElement('div')
let start = document.createComment('range')
let end = document.createComment('/range')
let div = document.createElement('div')
div.innerHTML = '1'
container.appendChild(start)
container.appendChild(div)
container.appendChild(end)
let root = createRangeRoot([start, end])
let capturedUpdate = () => {}
function App(this: Remix.Handle) {
let count = 1
capturedUpdate = () => {
count++
this.render()
}
return () => (
<>
{Array.from({ length: count }).map((_, i) => (
{i}
))}
>
)
}
root.render()
expect(container.innerHTML).toBe('0
')
expect(container.querySelector('div')).toBe(div)
capturedUpdate()
root.flush()
expect(container.innerHTML).toBe('0
1
')
})
it('replaces nodes at the end', () => {
let container = document.createElement('div')
let start = document.createComment('range')
let end = document.createComment('/range')
let div = document.createElement('div')
div.innerHTML = 'one'
container.appendChild(start)
container.appendChild(div)
container.appendChild(end)
let root = createRangeRoot([start, end])
root.render(
<>
one
two
>,
)
expect(container.innerHTML).toBe('one
two
')
expect(container.firstChild).toBe(start)
expect(container.lastChild).toBe(end)
expect(container.querySelector('div')).toBe(div)
root.render(
<>
one
main
>,
)
expect(container.innerHTML).toBe('one
main')
expect(container.firstChild).toBe(start)
expect(container.lastChild).toBe(end)
expect(container.querySelector('div')).toBe(div)
})
it('updates nested children', () => {
let container = document.createElement('div')
let start = document.createComment('range')
let end = document.createComment('/range')
let div = document.createElement('div')
div.innerHTML = '0'
container.appendChild(start)
container.appendChild(div)
container.appendChild(end)
let root = createRangeRoot([start, end])
let capturedUpdate = () => {}
function Nested(this: Remix.Handle) {
let count = 0
capturedUpdate = () => {
count++
this.render()
}
return () => {count}
}
function App(this: Remix.Handle) {
return () => (
)
}
root.render()
expect(container.innerHTML).toBe('0
')
expect(container.querySelector('div')).toBe(div)
capturedUpdate()
root.flush()
expect(container.innerHTML).toBe('1
')
})
it('works w/o hydration', () => {
let container = document.createElement('div')
let start = document.createComment('range')
let end = document.createComment('/range')
container.appendChild(start)
container.appendChild(end)
let root = createRangeRoot([start, end])
root.render(Hello, world!
)
expect(container.innerHTML).toBe('Hello, world!
')
expect(container.firstChild).toBe(start)
expect(container.lastChild).toBe(end)
})
})