import { describe, it, expect } from 'vitest'
import { createRoot } from '../lib/vdom.ts'
import type { Handle, RemixNode } from '../lib/component.ts'
describe('vnode rendering', () => {
describe('scheduling', () => {
it('skips descendant updates if ancestor is scheduled', () => {
let container = document.createElement('div')
let root = createRoot(container)
let capturedParentUpdate = () => {}
let appRenderCount = 0
function Parent(handle: Handle) {
capturedParentUpdate = () => {
handle.update()
}
return ({ children }: { children: RemixNode }) => {
appRenderCount++
return children
}
}
let childRenderCount = 0
let capturedChildUpdate = () => {}
function Child(handle: Handle) {
capturedChildUpdate = () => {
handle.update()
}
return () => {
childRenderCount++
return
Hello, world!
}
}
root.render(
,
)
expect(container.innerHTML).toBe('Hello, world!
')
expect(appRenderCount).toBe(1)
expect(childRenderCount).toBe(1)
capturedChildUpdate()
capturedParentUpdate()
root.flush()
expect(appRenderCount).toBe(2)
expect(childRenderCount).toBe(2)
// swap order
capturedParentUpdate()
capturedChildUpdate()
root.flush()
expect(appRenderCount).toBe(3)
expect(childRenderCount).toBe(3)
})
it('only runs tasks once', async () => {
let container = document.createElement('div')
let root = createRoot(container)
let taskCount = 0
let capturedUpdate = () => {}
function App(handle: Handle) {
handle.queueTask(() => {
taskCount++
})
capturedUpdate = () => {
handle.queueTask(() => {
taskCount++
})
handle.update()
}
return () => null
}
root.render()
root.flush()
expect(taskCount).toBe(1)
capturedUpdate()
root.flush()
expect(taskCount).toBe(2)
})
})
})