diff --git a/packages/runtime-vapor/__tests__/hydration.spec.ts b/packages/runtime-vapor/__tests__/hydration.spec.ts
new file mode 100644
index 000000000..7422f6e6d
--- /dev/null
+++ b/packages/runtime-vapor/__tests__/hydration.spec.ts
@@ -0,0 +1,2314 @@
+// import { type SSRContext, renderToString } from '@vue/server-renderer'
+import { createVaporSSRApp, renderEffect, setText, template } from '../src'
+import { nextTick, ref } from '@vue/runtime-dom'
+
+function mountWithHydration(html: string, setup: () => any) {
+ const container = document.createElement('div')
+ container.innerHTML = html
+ const app = createVaporSSRApp({
+ setup,
+ })
+ app.mount(container)
+ return {
+ container,
+ }
+}
+
+// const triggerEvent = (type: string, el: Element) => {
+// const event = new Event(type)
+// el.dispatchEvent(event)
+// }
+
+describe('SSR hydration', () => {
+ beforeEach(() => {
+ document.body.innerHTML = ''
+ })
+
+ test('text', async () => {
+ const msg = ref('foo')
+ const t = template(' ')
+ const { container } = mountWithHydration('foo', () => {
+ const n = t()
+ renderEffect(() => setText(n as Text, msg.value))
+ return n
+ })
+ expect(container.textContent).toBe('foo')
+ msg.value = 'bar'
+ await nextTick()
+ expect(container.textContent).toBe('bar')
+ })
+
+ test('empty text', async () => {
+ const t0 = template('
`).not.toHaveBeenWarned()
+ })
+
+ test('comment', () => {
+ const t0 = template('')
+ const { container } = mountWithHydration('', () => t0())
+ expect(container.innerHTML).toBe('')
+ expect(`Hydration children mismatch in
`).not.toHaveBeenWarned()
+ })
+
+ // test('static before text', () => {
+ // const t0 = template(' A ')
+ // const t1 = template('
foo bar')
+ // const t2 = template(' ')
+ // const msg = ref('hello')
+ // const { container } = mountWithHydration(
+ // ' A
foo barhello',
+ // () => {
+ // const n0 = t0()
+ // const n1 = t1()
+ // const n2 = t2()
+ // const n3 = createTextNode()
+ // renderEffect(() => setText(n3, toDisplayString(msg.value)))
+ // return [n0, n1, n2, n3]
+ // },
+ // )
+ // })
+
+ // test('static (multiple elements)', () => {
+ // const staticContent = '
hello'
+ // const html = `
hi
` + staticContent + `
ho
`
+
+ // const n1 = h('div', 'hi')
+ // const s = createStaticVNode('', 2)
+ // const n2 = h('div', 'ho')
+
+ // const { container } = mountWithHydration(html, () => h('div', [n1, s, n2]))
+
+ // const div = container.firstChild!
+
+ // expect(n1.el).toBe(div.firstChild)
+ // expect(n2.el).toBe(div.lastChild)
+ // expect(s.el).toBe(div.childNodes[1])
+ // expect(s.anchor).toBe(div.childNodes[2])
+ // expect(s.children).toBe(staticContent)
+ // })
+
+ // // #6008
+ // test('static (with text node as starting node)', () => {
+ // const html = ` A
foo B`
+ // const { vnode, container } = mountWithHydration(html, () =>
+ // createStaticVNode(` A
foo B`, 3),
+ // )
+ // expect(vnode.el).toBe(container.firstChild)
+ // expect(vnode.anchor).toBe(container.lastChild)
+ // expect(`Hydration node mismatch`).not.toHaveBeenWarned()
+ // })
+
+ // test('static with content adoption', () => {
+ // const html = ` A
foo B`
+ // const { vnode, container } = mountWithHydration(html, () =>
+ // createStaticVNode(``, 3),
+ // )
+ // expect(vnode.el).toBe(container.firstChild)
+ // expect(vnode.anchor).toBe(container.lastChild)
+ // expect(vnode.children).toBe(html)
+ // expect(`Hydration node mismatch`).not.toHaveBeenWarned()
+ // })
+
+ // test('element with text children', async () => {
+ // const msg = ref('foo')
+ // const { vnode, container } = mountWithHydration(
+ // '
foo
',
+ // () => h('div', { class: msg.value }, msg.value),
+ // )
+ // expect(vnode.el).toBe(container.firstChild)
+ // expect(container.firstChild!.textContent).toBe('foo')
+ // msg.value = 'bar'
+ // await nextTick()
+ // expect(container.innerHTML).toBe(`
bar
`)
+ // })
+
+ // // #7285
+ // test('element with multiple continuous text vnodes', async () => {
+ // // should no mismatch warning
+ // const { container } = mountWithHydration('
foo0o
', () =>
+ // h('div', ['fo', createTextVNode('o'), 0, 'o']),
+ // )
+ // expect(container.textContent).toBe('foo0o')
+ // })
+
+ // test('element with elements children', async () => {
+ // const msg = ref('foo')
+ // const fn = vi.fn()
+ // const { vnode, container } = mountWithHydration(
+ // '
foo
',
+ // () =>
+ // h('div', [
+ // h('span', msg.value),
+ // h('span', { class: msg.value, onClick: fn }),
+ // ]),
+ // )
+ // expect(vnode.el).toBe(container.firstChild)
+ // expect((vnode.children as VNode[])[0].el).toBe(
+ // container.firstChild!.childNodes[0],
+ // )
+ // expect((vnode.children as VNode[])[1].el).toBe(
+ // container.firstChild!.childNodes[1],
+ // )
+
+ // // event handler
+ // triggerEvent('click', vnode.el.querySelector('.foo')!)
+ // expect(fn).toHaveBeenCalled()
+
+ // msg.value = 'bar'
+ // await nextTick()
+ // expect(vnode.el.innerHTML).toBe(`
bar`)
+ // })
+
+ // test('element with ref', () => {
+ // const el = ref()
+ // const { vnode, container } = mountWithHydration('
', () =>
+ // h('div', { ref: el }),
+ // )
+ // expect(vnode.el).toBe(container.firstChild)
+ // expect(el.value).toBe(vnode.el)
+ // })
+
+ // test('Fragment', async () => {
+ // const msg = ref('foo')
+ // const fn = vi.fn()
+ // const { vnode, container } = mountWithHydration(
+ // '
foo
',
+ // () =>
+ // h('div', [
+ // [
+ // h('span', msg.value),
+ // [h('span', { class: msg.value, onClick: fn })],
+ // ],
+ // ]),
+ // )
+ // expect(vnode.el).toBe(container.firstChild)
+
+ // expect(vnode.el.innerHTML).toBe(
+ // `
foo`,
+ // )
+
+ // // start fragment 1
+ // const fragment1 = (vnode.children as VNode[])[0]
+ // expect(fragment1.el).toBe(vnode.el.childNodes[0])
+ // const fragment1Children = fragment1.children as VNode[]
+
+ // // first
+ // expect(fragment1Children[0].el!.tagName).toBe('SPAN')
+ // expect(fragment1Children[0].el).toBe(vnode.el.childNodes[1])
+
+ // // start fragment 2
+ // const fragment2 = fragment1Children[1]
+ // expect(fragment2.el).toBe(vnode.el.childNodes[2])
+ // const fragment2Children = fragment2.children as VNode[]
+
+ // // second
+ // expect(fragment2Children[0].el!.tagName).toBe('SPAN')
+ // expect(fragment2Children[0].el).toBe(vnode.el.childNodes[3])
+
+ // // end fragment 2
+ // expect(fragment2.anchor).toBe(vnode.el.childNodes[4])
+
+ // // end fragment 1
+ // expect(fragment1.anchor).toBe(vnode.el.childNodes[5])
+
+ // // event handler
+ // triggerEvent('click', vnode.el.querySelector('.foo')!)
+ // expect(fn).toHaveBeenCalled()
+
+ // msg.value = 'bar'
+ // await nextTick()
+ // expect(vnode.el.innerHTML).toBe(
+ // `bar`,
+ // )
+ // })
+
+ // // #7285
+ // test('Fragment (multiple continuous text vnodes)', async () => {
+ // // should no mismatch warning
+ // const { container } = mountWithHydration('fooo', () => [
+ // 'fo',
+ // createTextVNode('o'),
+ // 'o',
+ // ])
+ // expect(container.textContent).toBe('fooo')
+ // })
+
+ // test('Teleport', async () => {
+ // const msg = ref('foo')
+ // const fn = vi.fn()
+ // const teleportContainer = document.createElement('div')
+ // teleportContainer.id = 'teleport'
+ // teleportContainer.innerHTML = `foo`
+ // document.body.appendChild(teleportContainer)
+
+ // const { vnode, container } = mountWithHydration(
+ // '',
+ // () =>
+ // h(Teleport, { to: '#teleport' }, [
+ // h('span', msg.value),
+ // h('span', { class: msg.value, onClick: fn }),
+ // ]),
+ // )
+
+ // expect(vnode.el).toBe(container.firstChild)
+ // expect(vnode.anchor).toBe(container.lastChild)
+
+ // expect(vnode.target).toBe(teleportContainer)
+ // expect(vnode.targetStart).toBe(teleportContainer.childNodes[0])
+ // expect((vnode.children as VNode[])[0].el).toBe(
+ // teleportContainer.childNodes[1],
+ // )
+ // expect((vnode.children as VNode[])[1].el).toBe(
+ // teleportContainer.childNodes[2],
+ // )
+ // expect(vnode.targetAnchor).toBe(teleportContainer.childNodes[3])
+
+ // // event handler
+ // triggerEvent('click', teleportContainer.querySelector('.foo')!)
+ // expect(fn).toHaveBeenCalled()
+
+ // msg.value = 'bar'
+ // await nextTick()
+ // expect(teleportContainer.innerHTML).toBe(
+ // `bar`,
+ // )
+ // })
+
+ // test('Teleport (multiple + integration)', async () => {
+ // const msg = ref('foo')
+ // const fn1 = vi.fn()
+ // const fn2 = vi.fn()
+
+ // const Comp = () => [
+ // h(Teleport, { to: '#teleport2' }, [
+ // h('span', msg.value),
+ // h('span', { class: msg.value, onClick: fn1 }),
+ // ]),
+ // h(Teleport, { to: '#teleport2' }, [
+ // h('span', msg.value + '2'),
+ // h('span', { class: msg.value + '2', onClick: fn2 }),
+ // ]),
+ // ]
+
+ // const teleportContainer = document.createElement('div')
+ // teleportContainer.id = 'teleport2'
+ // const ctx: SSRContext = {}
+ // const mainHtml = await renderToString(h(Comp), ctx)
+ // expect(mainHtml).toMatchInlineSnapshot(
+ // `""`,
+ // )
+
+ // const teleportHtml = ctx.teleports!['#teleport2']
+ // expect(teleportHtml).toMatchInlineSnapshot(
+ // `"foofoo2"`,
+ // )
+
+ // teleportContainer.innerHTML = teleportHtml
+ // document.body.appendChild(teleportContainer)
+
+ // const { vnode, container } = mountWithHydration(mainHtml, Comp)
+ // expect(vnode.el).toBe(container.firstChild)
+ // const teleportVnode1 = (vnode.children as VNode[])[0]
+ // const teleportVnode2 = (vnode.children as VNode[])[1]
+ // expect(teleportVnode1.el).toBe(container.childNodes[1])
+ // expect(teleportVnode1.anchor).toBe(container.childNodes[2])
+ // expect(teleportVnode2.el).toBe(container.childNodes[3])
+ // expect(teleportVnode2.anchor).toBe(container.childNodes[4])
+
+ // expect(teleportVnode1.target).toBe(teleportContainer)
+ // expect(teleportVnode1.targetStart).toBe(teleportContainer.childNodes[0])
+ // expect((teleportVnode1 as any).children[0].el).toBe(
+ // teleportContainer.childNodes[1],
+ // )
+ // expect(teleportVnode1.targetAnchor).toBe(teleportContainer.childNodes[3])
+
+ // expect(teleportVnode2.target).toBe(teleportContainer)
+ // expect(teleportVnode2.targetStart).toBe(teleportContainer.childNodes[4])
+ // expect((teleportVnode2 as any).children[0].el).toBe(
+ // teleportContainer.childNodes[5],
+ // )
+ // expect(teleportVnode2.targetAnchor).toBe(teleportContainer.childNodes[7])
+
+ // // // event handler
+ // triggerEvent('click', teleportContainer.querySelector('.foo')!)
+ // expect(fn1).toHaveBeenCalled()
+
+ // triggerEvent('click', teleportContainer.querySelector('.foo2')!)
+ // expect(fn2).toHaveBeenCalled()
+
+ // msg.value = 'bar'
+ // await nextTick()
+ // expect(teleportContainer.innerHTML).toMatchInlineSnapshot(
+ // `"barbar2"`,
+ // )
+ // })
+
+ // test('Teleport (disabled)', async () => {
+ // const msg = ref('foo')
+ // const fn1 = vi.fn()
+ // const fn2 = vi.fn()
+
+ // const Comp = () => [
+ // h('div', 'foo'),
+ // h(Teleport, { to: '#teleport3', disabled: true }, [
+ // h('span', msg.value),
+ // h('span', { class: msg.value, onClick: fn1 }),
+ // ]),
+ // h('div', { class: msg.value + '2', onClick: fn2 }, 'bar'),
+ // ]
+
+ // const teleportContainer = document.createElement('div')
+ // teleportContainer.id = 'teleport3'
+ // const ctx: SSRContext = {}
+ // const mainHtml = await renderToString(h(Comp), ctx)
+ // expect(mainHtml).toMatchInlineSnapshot(
+ // `"foo
foobar
"`,
+ // )
+
+ // const teleportHtml = ctx.teleports!['#teleport3']
+ // expect(teleportHtml).toMatchInlineSnapshot(
+ // `""`,
+ // )
+
+ // teleportContainer.innerHTML = teleportHtml
+ // document.body.appendChild(teleportContainer)
+
+ // const { vnode, container } = mountWithHydration(mainHtml, Comp)
+ // expect(vnode.el).toBe(container.firstChild)
+ // const children = vnode.children as VNode[]
+
+ // expect(children[0].el).toBe(container.childNodes[1])
+
+ // const teleportVnode = children[1]
+ // expect(teleportVnode.el).toBe(container.childNodes[2])
+ // expect((teleportVnode.children as VNode[])[0].el).toBe(
+ // container.childNodes[3],
+ // )
+ // expect((teleportVnode.children as VNode[])[1].el).toBe(
+ // container.childNodes[4],
+ // )
+ // expect(teleportVnode.anchor).toBe(container.childNodes[5])
+ // expect(children[2].el).toBe(container.childNodes[6])
+
+ // expect(teleportVnode.target).toBe(teleportContainer)
+ // expect(teleportVnode.targetStart).toBe(teleportContainer.childNodes[0])
+ // expect(teleportVnode.targetAnchor).toBe(teleportContainer.childNodes[1])
+
+ // // // event handler
+ // triggerEvent('click', container.querySelector('.foo')!)
+ // expect(fn1).toHaveBeenCalled()
+
+ // triggerEvent('click', container.querySelector('.foo2')!)
+ // expect(fn2).toHaveBeenCalled()
+
+ // msg.value = 'bar'
+ // await nextTick()
+ // expect(container.innerHTML).toMatchInlineSnapshot(
+ // `"foo
barbar
"`,
+ // )
+ // })
+
+ // // #6152
+ // test('Teleport (disabled + as component root)', () => {
+ // const { container } = mountWithHydration(
+ // 'Parent fragment
Teleport content
',
+ // () => [
+ // h('div', 'Parent fragment'),
+ // h(() =>
+ // h(Teleport, { to: 'body', disabled: true }, [
+ // h('div', 'Teleport content'),
+ // ]),
+ // ),
+ // ],
+ // )
+ // expect(document.body.innerHTML).toBe('')
+ // expect(container.innerHTML).toBe(
+ // 'Parent fragment
Teleport content
',
+ // )
+ // expect(
+ // `Hydration completed but contains mismatches.`,
+ // ).not.toHaveBeenWarned()
+ // })
+
+ // test('Teleport (as component root)', () => {
+ // const teleportContainer = document.createElement('div')
+ // teleportContainer.id = 'teleport4'
+ // teleportContainer.innerHTML = `hello`
+ // document.body.appendChild(teleportContainer)
+
+ // const wrapper = {
+ // render() {
+ // return h(Teleport, { to: '#teleport4' }, ['hello'])
+ // },
+ // }
+
+ // const { vnode, container } = mountWithHydration(
+ // '',
+ // () => h('div', [h(wrapper), h('div')]),
+ // )
+ // expect(vnode.el).toBe(container.firstChild)
+ // // component el
+ // const wrapperVNode = (vnode as any).children[0]
+ // const tpStart = container.firstChild?.firstChild
+ // const tpEnd = tpStart?.nextSibling
+ // expect(wrapperVNode.el).toBe(tpStart)
+ // expect(wrapperVNode.component.subTree.el).toBe(tpStart)
+ // expect(wrapperVNode.component.subTree.anchor).toBe(tpEnd)
+ // // next node hydrate properly
+ // const nextVNode = (vnode as any).children[1]
+ // expect(nextVNode.el).toBe(container.firstChild?.lastChild)
+ // })
+
+ // test('Teleport (nested)', () => {
+ // const teleportContainer = document.createElement('div')
+ // teleportContainer.id = 'teleport5'
+ // teleportContainer.innerHTML = `child
`
+ // document.body.appendChild(teleportContainer)
+
+ // const { vnode, container } = mountWithHydration(
+ // '',
+ // () =>
+ // h(Teleport, { to: '#teleport5' }, [
+ // h('div', [h(Teleport, { to: '#teleport5' }, [h('div', 'child')])]),
+ // ]),
+ // )
+
+ // expect(vnode.el).toBe(container.firstChild)
+ // expect(vnode.anchor).toBe(container.lastChild)
+
+ // const childDivVNode = (vnode as any).children[0]
+ // const div = teleportContainer.childNodes[1]
+ // expect(childDivVNode.el).toBe(div)
+ // expect(vnode.targetAnchor).toBe(div?.nextSibling)
+
+ // const childTeleportVNode = childDivVNode.children[0]
+ // expect(childTeleportVNode.el).toBe(div?.firstChild)
+ // expect(childTeleportVNode.anchor).toBe(div?.lastChild)
+
+ // expect(childTeleportVNode.targetAnchor).toBe(teleportContainer.lastChild)
+ // expect(childTeleportVNode.children[0].el).toBe(
+ // teleportContainer.lastChild?.previousSibling,
+ // )
+ // })
+
+ // test('with data-allow-mismatch component when using onServerPrefetch', async () => {
+ // const Comp = {
+ // template: `
+ // Comp2
+ // `,
+ // }
+ // let foo: any
+ // const App = {
+ // setup() {
+ // const flag = ref(true)
+ // foo = () => {
+ // flag.value = false
+ // }
+ // onServerPrefetch(() => (flag.value = false))
+ // return { flag }
+ // },
+ // components: {
+ // Comp,
+ // },
+ // template: `
+ //
+ //
+ //
+ // `,
+ // }
+ // // hydrate
+ // const container = document.createElement('div')
+ // container.innerHTML = await renderToString(h(App))
+ // createSSRApp(App).mount(container)
+ // expect(container.innerHTML).toBe(
+ // 'Comp2
',
+ // )
+ // foo()
+ // await nextTick()
+ // expect(container.innerHTML).toBe(
+ // '',
+ // )
+ // })
+
+ // test('Teleport unmount (full integration)', async () => {
+ // const Comp1 = {
+ // template: `
+ //
+ // Teleported Comp1
+ //
+ // `,
+ // }
+ // const Comp2 = {
+ // template: `
+ // Comp2
+ // `,
+ // }
+
+ // const toggle = ref(true)
+ // const App = {
+ // template: `
+ //
+ //
+ //
+ //
+ // `,
+ // components: {
+ // Comp1,
+ // Comp2,
+ // },
+ // setup() {
+ // return { toggle }
+ // },
+ // }
+
+ // const container = document.createElement('div')
+ // const teleportContainer = document.createElement('div')
+ // teleportContainer.id = 'target'
+ // document.body.appendChild(teleportContainer)
+
+ // // server render
+ // const ctx: SSRContext = {}
+ // container.innerHTML = await renderToString(h(App), ctx)
+ // expect(container.innerHTML).toBe(
+ // '',
+ // )
+ // teleportContainer.innerHTML = ctx.teleports!['#target']
+
+ // // hydrate
+ // createSSRApp(App).mount(container)
+ // expect(container.innerHTML).toBe(
+ // '',
+ // )
+ // expect(teleportContainer.innerHTML).toBe(
+ // 'Teleported Comp1',
+ // )
+ // expect(`Hydration children mismatch`).not.toHaveBeenWarned()
+
+ // toggle.value = false
+ // await nextTick()
+ // expect(container.innerHTML).toBe('')
+ // expect(teleportContainer.innerHTML).toBe('')
+ // })
+
+ // test('Teleport unmount (mismatch + full integration)', async () => {
+ // const Comp1 = {
+ // template: `
+ //
+ // Teleported Comp1
+ //
+ // `,
+ // }
+ // const Comp2 = {
+ // template: `
+ // Comp2
+ // `,
+ // }
+
+ // const toggle = ref(true)
+ // const App = {
+ // template: `
+ //
+ //
+ //
+ //
+ // `,
+ // components: {
+ // Comp1,
+ // Comp2,
+ // },
+ // setup() {
+ // return { toggle }
+ // },
+ // }
+
+ // const container = document.createElement('div')
+ // const teleportContainer = document.createElement('div')
+ // teleportContainer.id = 'target'
+ // document.body.appendChild(teleportContainer)
+
+ // // server render
+ // container.innerHTML = await renderToString(h(App))
+ // expect(container.innerHTML).toBe(
+ // '',
+ // )
+ // expect(teleportContainer.innerHTML).toBe('')
+
+ // // hydrate
+ // createSSRApp(App).mount(container)
+ // expect(container.innerHTML).toBe(
+ // '',
+ // )
+ // expect(teleportContainer.innerHTML).toBe('Teleported Comp1')
+ // expect(`Hydration children mismatch`).toHaveBeenWarned()
+
+ // toggle.value = false
+ // await nextTick()
+ // expect(container.innerHTML).toBe('')
+ // expect(teleportContainer.innerHTML).toBe('')
+ // })
+
+ // test('Teleport target change (mismatch + full integration)', async () => {
+ // const target = ref('#target1')
+ // const Comp = {
+ // template: `
+ //
+ // Teleported
+ //
+ // `,
+ // setup() {
+ // return { target }
+ // },
+ // }
+
+ // const App = {
+ // template: `
+ //
+ //
+ //
+ // `,
+ // components: {
+ // Comp,
+ // },
+ // }
+
+ // const container = document.createElement('div')
+ // const teleportContainer1 = document.createElement('div')
+ // teleportContainer1.id = 'target1'
+ // const teleportContainer2 = document.createElement('div')
+ // teleportContainer2.id = 'target2'
+ // document.body.appendChild(teleportContainer1)
+ // document.body.appendChild(teleportContainer2)
+
+ // // server render
+ // container.innerHTML = await renderToString(h(App))
+ // expect(container.innerHTML).toBe(
+ // '',
+ // )
+ // expect(teleportContainer1.innerHTML).toBe('')
+ // expect(teleportContainer2.innerHTML).toBe('')
+
+ // // hydrate
+ // createSSRApp(App).mount(container)
+ // expect(container.innerHTML).toBe(
+ // '',
+ // )
+ // expect(teleportContainer1.innerHTML).toBe('Teleported')
+ // expect(teleportContainer2.innerHTML).toBe('')
+ // expect(`Hydration children mismatch`).toHaveBeenWarned()
+
+ // target.value = '#target2'
+ // await nextTick()
+ // expect(teleportContainer1.innerHTML).toBe('')
+ // expect(teleportContainer2.innerHTML).toBe('Teleported')
+ // })
+
+ // // compile SSR + client render fn from the same template & hydrate
+ // test('full compiler integration', async () => {
+ // const mounted: string[] = []
+ // const log = vi.fn()
+ // const toggle = ref(true)
+
+ // const Child = {
+ // data() {
+ // return {
+ // count: 0,
+ // text: 'hello',
+ // style: {
+ // color: 'red',
+ // },
+ // }
+ // },
+ // mounted() {
+ // mounted.push('child')
+ // },
+ // template: `
+ //
+ // {{ count }}
+ //
+ //
+ //
+ // {{ text }}
+ //
+ //
+ // `,
+ // }
+
+ // const App = {
+ // setup() {
+ // return { toggle }
+ // },
+ // mounted() {
+ // mounted.push('parent')
+ // },
+ // template: `
+ //
+ // hello
+ //
+ //
+ //
+ //
+ //
+ //
+ // hello
+ //
`,
+ // components: {
+ // Child,
+ // },
+ // methods: {
+ // log,
+ // },
+ // }
+
+ // const container = document.createElement('div')
+ // // server render
+ // container.innerHTML = await renderToString(h(App))
+ // // hydrate
+ // createSSRApp(App).mount(container)
+
+ // // assert interactions
+ // // 1. parent button click
+ // triggerEvent('click', container.querySelector('.parent-click')!)
+ // expect(log).toHaveBeenCalledWith('click')
+
+ // // 2. child inc click + text interpolation
+ // const count = container.querySelector('.count') as HTMLElement
+ // expect(count.textContent).toBe(`0`)
+ // triggerEvent('click', container.querySelector('.inc')!)
+ // await nextTick()
+ // expect(count.textContent).toBe(`1`)
+
+ // // 3. child color click + style binding
+ // expect(count.style.color).toBe('red')
+ // triggerEvent('click', container.querySelector('.change')!)
+ // await nextTick()
+ // expect(count.style.color).toBe('green')
+
+ // // 4. child event emit
+ // triggerEvent('click', container.querySelector('.emit')!)
+ // expect(log).toHaveBeenCalledWith('child')
+
+ // // 5. child v-model
+ // const text = container.querySelector('.text')!
+ // const input = container.querySelector('input')!
+ // expect(text.textContent).toBe('hello')
+ // input.value = 'bye'
+ // triggerEvent('input', input)
+ // await nextTick()
+ // expect(text.textContent).toBe('bye')
+ // })
+
+ // test('handle click error in ssr mode', async () => {
+ // const App = {
+ // setup() {
+ // const throwError = () => {
+ // throw new Error('Sentry Error')
+ // }
+ // return { throwError }
+ // },
+ // template: `
+ //
+ //
+ //
`,
+ // }
+
+ // const container = document.createElement('div')
+ // // server render
+ // container.innerHTML = await renderToString(h(App))
+ // // hydrate
+ // const app = createSSRApp(App)
+ // const handler = (app.config.errorHandler = vi.fn())
+ // app.mount(container)
+ // // assert interactions
+ // // parent button click
+ // triggerEvent('click', container.querySelector('.parent-click')!)
+ // expect(handler).toHaveBeenCalled()
+ // })
+
+ // test('handle blur error in ssr mode', async () => {
+ // const App = {
+ // setup() {
+ // const throwError = () => {
+ // throw new Error('Sentry Error')
+ // }
+ // return { throwError }
+ // },
+ // template: `
+ //
+ //
+ //
`,
+ // }
+
+ // const container = document.createElement('div')
+ // // server render
+ // container.innerHTML = await renderToString(h(App))
+ // // hydrate
+ // const app = createSSRApp(App)
+ // const handler = (app.config.errorHandler = vi.fn())
+ // app.mount(container)
+ // // assert interactions
+ // // parent blur event
+ // triggerEvent('blur', container.querySelector('.parent-click')!)
+ // expect(handler).toHaveBeenCalled()
+ // })
+
+ // test('Suspense', async () => {
+ // const AsyncChild = {
+ // async setup() {
+ // const count = ref(0)
+ // return () =>
+ // h(
+ // 'span',
+ // {
+ // onClick: () => {
+ // count.value++
+ // },
+ // },
+ // count.value,
+ // )
+ // },
+ // }
+ // const { vnode, container } = mountWithHydration('0', () =>
+ // h(Suspense, () => h(AsyncChild)),
+ // )
+ // expect(vnode.el).toBe(container.firstChild)
+ // // wait for hydration to finish
+ // await new Promise(r => setTimeout(r))
+ // triggerEvent('click', container.querySelector('span')!)
+ // await nextTick()
+ // expect(container.innerHTML).toBe(`1`)
+ // })
+
+ // // #6638
+ // test('Suspense + async component', async () => {
+ // let isSuspenseResolved = false
+ // let isSuspenseResolvedInChild: any
+ // const AsyncChild = defineAsyncComponent(() =>
+ // Promise.resolve(
+ // defineComponent({
+ // setup() {
+ // isSuspenseResolvedInChild = isSuspenseResolved
+ // const count = ref(0)
+ // return () =>
+ // h(
+ // 'span',
+ // {
+ // onClick: () => {
+ // count.value++
+ // },
+ // },
+ // count.value,
+ // )
+ // },
+ // }),
+ // ),
+ // )
+ // const { vnode, container } = mountWithHydration('0', () =>
+ // h(
+ // Suspense,
+ // {
+ // onResolve() {
+ // isSuspenseResolved = true
+ // },
+ // },
+ // () => h(AsyncChild),
+ // ),
+ // )
+ // expect(vnode.el).toBe(container.firstChild)
+ // // wait for hydration to finish
+ // await new Promise(r => setTimeout(r))
+
+ // expect(isSuspenseResolvedInChild).toBe(false)
+ // expect(isSuspenseResolved).toBe(true)
+
+ // // assert interaction
+ // triggerEvent('click', container.querySelector('span')!)
+ // await nextTick()
+ // expect(container.innerHTML).toBe(`1`)
+ // })
+
+ // test('Suspense (full integration)', async () => {
+ // const mountedCalls: number[] = []
+ // const asyncDeps: Promise[] = []
+
+ // const AsyncChild = defineComponent({
+ // props: ['n'],
+ // async setup(props) {
+ // const count = ref(props.n)
+ // onMounted(() => {
+ // mountedCalls.push(props.n)
+ // })
+ // const p = new Promise(r => setTimeout(r, props.n * 10))
+ // asyncDeps.push(p)
+ // await p
+ // return () =>
+ // h(
+ // 'span',
+ // {
+ // onClick: () => {
+ // count.value++
+ // },
+ // },
+ // count.value,
+ // )
+ // },
+ // })
+
+ // const done = vi.fn()
+ // const App = {
+ // template: `
+ //
+ //
+ // `,
+ // components: {
+ // AsyncChild,
+ // },
+ // methods: {
+ // done,
+ // },
+ // }
+
+ // const container = document.createElement('div')
+ // // server render
+ // container.innerHTML = await renderToString(h(App))
+ // expect(container.innerHTML).toMatchInlineSnapshot(
+ // `"12
"`,
+ // )
+ // // reset asyncDeps from ssr
+ // asyncDeps.length = 0
+ // // hydrate
+ // createSSRApp(App).mount(container)
+
+ // expect(mountedCalls.length).toBe(0)
+ // expect(asyncDeps.length).toBe(2)
+
+ // // wait for hydration to complete
+ // await Promise.all(asyncDeps)
+ // await new Promise(r => setTimeout(r))
+
+ // // should flush buffered effects
+ // expect(mountedCalls).toMatchObject([1, 2])
+ // expect(container.innerHTML).toMatch(
+ // `12
`,
+ // )
+
+ // const span1 = container.querySelector('span')!
+ // triggerEvent('click', span1)
+ // await nextTick()
+ // expect(container.innerHTML).toMatch(
+ // `22
`,
+ // )
+
+ // const span2 = span1.nextSibling as Element
+ // triggerEvent('click', span2)
+ // await nextTick()
+ // expect(container.innerHTML).toMatch(
+ // `23
`,
+ // )
+ // })
+
+ // test('async component', async () => {
+ // const spy = vi.fn()
+ // const Comp = () =>
+ // h(
+ // 'button',
+ // {
+ // onClick: spy,
+ // },
+ // 'hello!',
+ // )
+
+ // let serverResolve: any
+ // let AsyncComp = defineAsyncComponent(
+ // () =>
+ // new Promise(r => {
+ // serverResolve = r
+ // }),
+ // )
+
+ // const App = {
+ // render() {
+ // return ['hello', h(AsyncComp), 'world']
+ // },
+ // }
+
+ // // server render
+ // const htmlPromise = renderToString(h(App))
+ // serverResolve(Comp)
+ // const html = await htmlPromise
+ // expect(html).toMatchInlineSnapshot(
+ // `"helloworld"`,
+ // )
+
+ // // hydration
+ // let clientResolve: any
+ // AsyncComp = defineAsyncComponent(
+ // () =>
+ // new Promise(r => {
+ // clientResolve = r
+ // }),
+ // )
+
+ // const container = document.createElement('div')
+ // container.innerHTML = html
+ // createSSRApp(App).mount(container)
+
+ // // hydration not complete yet
+ // triggerEvent('click', container.querySelector('button')!)
+ // expect(spy).not.toHaveBeenCalled()
+
+ // // resolve
+ // clientResolve(Comp)
+ // await new Promise(r => setTimeout(r))
+
+ // // should be hydrated now
+ // triggerEvent('click', container.querySelector('button')!)
+ // expect(spy).toHaveBeenCalled()
+ // })
+
+ // test('update async wrapper before resolve', async () => {
+ // const Comp = {
+ // render() {
+ // return h('h1', 'Async component')
+ // },
+ // }
+ // let serverResolve: any
+ // let AsyncComp = defineAsyncComponent(
+ // () =>
+ // new Promise(r => {
+ // serverResolve = r
+ // }),
+ // )
+
+ // const toggle = ref(true)
+ // const App = {
+ // setup() {
+ // onMounted(() => {
+ // // change state, this makes updateComponent(AsyncComp) execute before
+ // // the async component is resolved
+ // toggle.value = false
+ // })
+
+ // return () => {
+ // return [toggle.value ? 'hello' : 'world', h(AsyncComp)]
+ // }
+ // },
+ // }
+
+ // // server render
+ // const htmlPromise = renderToString(h(App))
+ // serverResolve(Comp)
+ // const html = await htmlPromise
+ // expect(html).toMatchInlineSnapshot(
+ // `"helloAsync component
"`,
+ // )
+
+ // // hydration
+ // let clientResolve: any
+ // AsyncComp = defineAsyncComponent(
+ // () =>
+ // new Promise(r => {
+ // clientResolve = r
+ // }),
+ // )
+
+ // const container = document.createElement('div')
+ // container.innerHTML = html
+ // createSSRApp(App).mount(container)
+
+ // // resolve
+ // clientResolve(Comp)
+ // await new Promise(r => setTimeout(r))
+
+ // // should be hydrated now
+ // expect(`Hydration node mismatch`).not.toHaveBeenWarned()
+ // expect(container.innerHTML).toMatchInlineSnapshot(
+ // `"worldAsync component
"`,
+ // )
+ // })
+
+ // test('hydrate safely when property used by async setup changed before render', async () => {
+ // const toggle = ref(true)
+
+ // const AsyncComp = {
+ // async setup() {
+ // await new Promise(r => setTimeout(r, 10))
+ // return () => h('h1', 'Async component')
+ // },
+ // }
+
+ // const AsyncWrapper = {
+ // render() {
+ // return h(AsyncComp)
+ // },
+ // }
+
+ // const SiblingComp = {
+ // setup() {
+ // toggle.value = false
+ // return () => h('span')
+ // },
+ // }
+
+ // const App = {
+ // setup() {
+ // return () =>
+ // h(
+ // Suspense,
+ // {},
+ // {
+ // default: () => [
+ // h('main', {}, [
+ // h(AsyncWrapper, {
+ // prop: toggle.value ? 'hello' : 'world',
+ // }),
+ // h(SiblingComp),
+ // ]),
+ // ],
+ // },
+ // )
+ // },
+ // }
+
+ // // server render
+ // const html = await renderToString(h(App))
+
+ // expect(html).toMatchInlineSnapshot(
+ // `"Async component
"`,
+ // )
+
+ // expect(toggle.value).toBe(false)
+
+ // // hydration
+
+ // // reset the value
+ // toggle.value = true
+ // expect(toggle.value).toBe(true)
+
+ // const container = document.createElement('div')
+ // container.innerHTML = html
+ // createSSRApp(App).mount(container)
+
+ // await new Promise(r => setTimeout(r, 10))
+
+ // expect(toggle.value).toBe(false)
+
+ // // should be hydrated now
+ // expect(container.innerHTML).toMatchInlineSnapshot(
+ // `"Async component
"`,
+ // )
+ // })
+
+ // test('hydrate safely when property used by deep nested async setup changed before render', async () => {
+ // const toggle = ref(true)
+
+ // const AsyncComp = {
+ // async setup() {
+ // await new Promise(r => setTimeout(r, 10))
+ // return () => h('h1', 'Async component')
+ // },
+ // }
+
+ // const AsyncWrapper = { render: () => h(AsyncComp) }
+ // const AsyncWrapperWrapper = { render: () => h(AsyncWrapper) }
+
+ // const SiblingComp = {
+ // setup() {
+ // toggle.value = false
+ // return () => h('span')
+ // },
+ // }
+
+ // const App = {
+ // setup() {
+ // return () =>
+ // h(
+ // Suspense,
+ // {},
+ // {
+ // default: () => [
+ // h('main', {}, [
+ // h(AsyncWrapperWrapper, {
+ // prop: toggle.value ? 'hello' : 'world',
+ // }),
+ // h(SiblingComp),
+ // ]),
+ // ],
+ // },
+ // )
+ // },
+ // }
+
+ // // server render
+ // const html = await renderToString(h(App))
+
+ // expect(html).toMatchInlineSnapshot(
+ // `"Async component
"`,
+ // )
+
+ // expect(toggle.value).toBe(false)
+
+ // // hydration
+
+ // // reset the value
+ // toggle.value = true
+ // expect(toggle.value).toBe(true)
+
+ // const container = document.createElement('div')
+ // container.innerHTML = html
+ // createSSRApp(App).mount(container)
+
+ // await new Promise(r => setTimeout(r, 10))
+
+ // expect(toggle.value).toBe(false)
+
+ // // should be hydrated now
+ // expect(container.innerHTML).toMatchInlineSnapshot(
+ // `"Async component
"`,
+ // )
+ // })
+
+ // // #3787
+ // test('unmount async wrapper before load', async () => {
+ // let resolve: any
+ // const AsyncComp = defineAsyncComponent(
+ // () =>
+ // new Promise(r => {
+ // resolve = r
+ // }),
+ // )
+
+ // const show = ref(true)
+ // const root = document.createElement('div')
+ // root.innerHTML = ''
+
+ // createSSRApp({
+ // render() {
+ // return h('div', [show.value ? h(AsyncComp) : h('div', 'hi')])
+ // },
+ // }).mount(root)
+
+ // show.value = false
+ // await nextTick()
+ // expect(root.innerHTML).toBe('')
+ // resolve({})
+ // })
+
+ // //#12362
+ // test('nested async wrapper', async () => {
+ // const Toggle = defineAsyncComponent(
+ // () =>
+ // new Promise(r => {
+ // r(
+ // defineComponent({
+ // setup(_, { slots }) {
+ // const show = ref(false)
+ // onMounted(() => {
+ // nextTick(() => {
+ // show.value = true
+ // })
+ // })
+ // return () =>
+ // withDirectives(
+ // h('div', null, [renderSlot(slots, 'default')]),
+ // [[vShow, show.value]],
+ // )
+ // },
+ // }) as any,
+ // )
+ // }),
+ // )
+
+ // const Wrapper = defineAsyncComponent(() => {
+ // return new Promise(r => {
+ // r(
+ // defineComponent({
+ // render(this: any) {
+ // return renderSlot(this.$slots, 'default')
+ // },
+ // }) as any,
+ // )
+ // })
+ // })
+
+ // const count = ref(0)
+ // const fn = vi.fn()
+ // const Child = {
+ // setup() {
+ // onMounted(() => {
+ // fn()
+ // count.value++
+ // })
+ // return () => h('div', count.value)
+ // },
+ // }
+
+ // const App = {
+ // render() {
+ // return h(Toggle, null, {
+ // default: () =>
+ // h(Wrapper, null, {
+ // default: () =>
+ // h(Wrapper, null, {
+ // default: () => h(Child),
+ // }),
+ // }),
+ // })
+ // },
+ // }
+
+ // const root = document.createElement('div')
+ // root.innerHTML = await renderToString(h(App))
+ // expect(root.innerHTML).toMatchInlineSnapshot(
+ // `""`,
+ // )
+
+ // createSSRApp(App).mount(root)
+ // await nextTick()
+ // await nextTick()
+ // expect(root.innerHTML).toMatchInlineSnapshot(
+ // `""`,
+ // )
+ // expect(fn).toBeCalledTimes(1)
+ // })
+
+ // test('unmount async wrapper before load (fragment)', async () => {
+ // let resolve: any
+ // const AsyncComp = defineAsyncComponent(
+ // () =>
+ // new Promise(r => {
+ // resolve = r
+ // }),
+ // )
+
+ // const show = ref(true)
+ // const root = document.createElement('div')
+ // root.innerHTML = 'async
'
+
+ // createSSRApp({
+ // render() {
+ // return h('div', [show.value ? h(AsyncComp) : h('div', 'hi')])
+ // },
+ // }).mount(root)
+
+ // show.value = false
+ // await nextTick()
+ // expect(root.innerHTML).toBe('')
+ // resolve({})
+ // })
+
+ // test('elements with camel-case in svg ', () => {
+ // const { vnode, container } = mountWithHydration(
+ // '',
+ // () => h('animateTransform'),
+ // )
+ // expect(vnode.el).toBe(container.firstChild)
+ // expect(`Hydration node mismatch`).not.toHaveBeenWarned()
+ // })
+
+ // test('SVG as a mount container', () => {
+ // const svgContainer = document.createElement('svg')
+ // svgContainer.innerHTML = ''
+ // const app = createSSRApp({
+ // render: () => h('g'),
+ // })
+
+ // expect(
+ // (
+ // app.mount(svgContainer).$.subTree as VNode & {
+ // el: Element
+ // }
+ // ).el instanceof SVGElement,
+ // )
+ // })
+
+ // test('force hydrate prop with `.prop` modifier', () => {
+ // const { container } = mountWithHydration('', () =>
+ // h('input', {
+ // type: 'checkbox',
+ // '.indeterminate': true,
+ // }),
+ // )
+ // expect((container.firstChild! as any).indeterminate).toBe(true)
+ // })
+
+ // test('force hydrate input v-model with non-string value bindings', () => {
+ // const { container } = mountWithHydration(
+ // '',
+ // () =>
+ // withDirectives(
+ // createVNode(
+ // 'input',
+ // { type: 'checkbox', 'true-value': true },
+ // null,
+ // PatchFlags.PROPS,
+ // ['true-value'],
+ // ),
+ // [[vModelCheckbox, true]],
+ // ),
+ // )
+ // expect((container.firstChild as any)._trueValue).toBe(true)
+ // })
+
+ // test('force hydrate checkbox with indeterminate', () => {
+ // const { container } = mountWithHydration(
+ // '',
+ // () =>
+ // createVNode(
+ // 'input',
+ // { type: 'checkbox', indeterminate: '' },
+ // null,
+ // PatchFlags.CACHED,
+ // ),
+ // )
+ // expect((container.firstChild as any).indeterminate).toBe(true)
+ // })
+
+ // test('force hydrate select option with non-string value bindings', () => {
+ // const { container } = mountWithHydration(
+ // '',
+ // () =>
+ // h('select', [
+ // // hoisted because bound value is a constant...
+ // createVNode('option', { value: true }, null, -1 /* HOISTED */),
+ // ]),
+ // )
+ // expect((container.firstChild!.firstChild as any)._value).toBe(true)
+ // })
+
+ // // #7203
+ // test('force hydrate custom element with dynamic props', () => {
+ // class MyElement extends HTMLElement {
+ // foo = ''
+ // constructor() {
+ // super()
+ // }
+ // }
+ // customElements.define('my-element-7203', MyElement)
+
+ // const msg = ref('bar')
+ // const container = document.createElement('div')
+ // container.innerHTML = ''
+ // const app = createSSRApp({
+ // render: () => h('my-element-7203', { foo: msg.value }),
+ // })
+ // app.mount(container)
+ // expect((container.firstChild as any).foo).toBe(msg.value)
+ // })
+
+ // // #5728
+ // test('empty text node in slot', () => {
+ // const Comp = {
+ // render(this: any) {
+ // return renderSlot(this.$slots, 'default', {}, () => [
+ // createTextVNode(''),
+ // ])
+ // },
+ // }
+ // const { container, vnode } = mountWithHydration('', () =>
+ // h(Comp),
+ // )
+ // expect(container.childNodes.length).toBe(3)
+ // const text = container.childNodes[1]
+ // expect(text.nodeType).toBe(3)
+ // expect(vnode.el).toBe(container.childNodes[0])
+ // // component => slot fragment => text node
+ // expect((vnode as any).component?.subTree.children[0].el).toBe(text)
+ // })
+
+ // // #7215
+ // test('empty text node', () => {
+ // const Comp = {
+ // render(this: any) {
+ // return h('p', [''])
+ // },
+ // }
+ // const { container } = mountWithHydration('', () => h(Comp))
+ // expect(container.childNodes.length).toBe(1)
+ // const p = container.childNodes[0]
+ // expect(p.childNodes.length).toBe(1)
+ // const text = p.childNodes[0]
+ // expect(text.nodeType).toBe(3)
+ // })
+
+ // // #11372
+ // test('object style value tracking in prod', async () => {
+ // __DEV__ = false
+ // try {
+ // const style = reactive({ color: 'red' })
+ // const Comp = {
+ // render(this: any) {
+ // return (
+ // openBlock(),
+ // createElementBlock(
+ // 'div',
+ // {
+ // style: normalizeStyle(style),
+ // },
+ // null,
+ // 4 /* STYLE */,
+ // )
+ // )
+ // },
+ // }
+ // const { container } = mountWithHydration(
+ // ``,
+ // () => h(Comp),
+ // )
+ // style.color = 'green'
+ // await nextTick()
+ // expect(container.innerHTML).toBe(``)
+ // } finally {
+ // __DEV__ = true
+ // }
+ // })
+
+ // test('app.unmount()', async () => {
+ // const container = document.createElement('DIV')
+ // container.innerHTML = ''
+ // const App = defineComponent({
+ // setup(_, { expose }) {
+ // const count = ref(0)
+
+ // expose({ count })
+
+ // return () =>
+ // h('button', {
+ // onClick: () => count.value++,
+ // })
+ // },
+ // })
+
+ // const app = createSSRApp(App)
+ // const vm = app.mount(container)
+ // await nextTick()
+ // expect((container as any)._vnode).toBeDefined()
+ // // @ts-expect-error - expose()'d properties are not available on vm type
+ // expect(vm.count).toBe(0)
+
+ // app.unmount()
+ // expect((container as any)._vnode).toBe(null)
+ // })
+
+ // // #6637
+ // test('stringified root fragment', () => {
+ // mountWithHydration(``, () =>
+ // createStaticVNode(``, 1),
+ // )
+ // expect(`mismatch`).not.toHaveBeenWarned()
+ // })
+
+ // test('transition appear', () => {
+ // const { vnode, container } = mountWithHydration(
+ // `foo
`,
+ // () =>
+ // h(
+ // Transition,
+ // { appear: true },
+ // {
+ // default: () => h('div', 'foo'),
+ // },
+ // ),
+ // )
+ // expect(container.firstChild).toMatchInlineSnapshot(`
+ //
+ // foo
+ //
+ // `)
+ // expect(vnode.el).toBe(container.firstChild)
+ // expect(`mismatch`).not.toHaveBeenWarned()
+ // })
+
+ // test('transition appear with v-if', () => {
+ // const show = false
+ // const { vnode, container } = mountWithHydration(
+ // ``,
+ // () =>
+ // h(
+ // Transition,
+ // { appear: true },
+ // {
+ // default: () => (show ? h('div', 'foo') : createCommentVNode('')),
+ // },
+ // ),
+ // )
+ // expect(container.firstChild).toMatchInlineSnapshot('')
+ // expect(vnode.el).toBe(container.firstChild)
+ // expect(`mismatch`).not.toHaveBeenWarned()
+ // })
+
+ // test('transition appear with v-show', () => {
+ // const show = false
+ // const { vnode, container } = mountWithHydration(
+ // `foo
`,
+ // () =>
+ // h(
+ // Transition,
+ // { appear: true },
+ // {
+ // default: () =>
+ // withDirectives(createVNode('div', null, 'foo'), [[vShow, show]]),
+ // },
+ // ),
+ // )
+ // expect(container.firstChild).toMatchInlineSnapshot(`
+ //
+ // foo
+ //
+ // `)
+ // expect((container.firstChild as any)[vShowOriginalDisplay]).toBe('')
+ // expect(vnode.el).toBe(container.firstChild)
+ // expect(`mismatch`).not.toHaveBeenWarned()
+ // })
+
+ // test('transition appear w/ event listener', async () => {
+ // const container = document.createElement('div')
+ // container.innerHTML = ``
+ // createSSRApp({
+ // data() {
+ // return {
+ // count: 0,
+ // }
+ // },
+ // template: `
+ //
+ //
+ //
+ // `,
+ // }).mount(container)
+
+ // expect(container.firstChild).toMatchInlineSnapshot(`
+ //
+ // `)
+
+ // triggerEvent('click', container.querySelector('button')!)
+ // await nextTick()
+ // expect(container.firstChild).toMatchInlineSnapshot(`
+ //
+ // `)
+ // })
+
+ // test('Suspense + transition appear', async () => {
+ // const { vnode, container } = mountWithHydration(
+ // `foo
`,
+ // () =>
+ // h(Suspense, {}, () =>
+ // h(
+ // Transition,
+ // { appear: true },
+ // {
+ // default: () => h('div', 'foo'),
+ // },
+ // ),
+ // ),
+ // )
+
+ // expect(vnode.el).toBe(container.firstChild)
+ // // wait for hydration to finish
+ // await new Promise(r => setTimeout(r))
+
+ // expect(container.firstChild).toMatchInlineSnapshot(`
+ //
+ // foo
+ //
+ // `)
+ // await nextTick()
+ // expect(vnode.el).toBe(container.firstChild)
+ // })
+
+ // // #10607
+ // test('update component stable slot (prod + optimized mode)', async () => {
+ // __DEV__ = false
+ // try {
+ // const container = document.createElement('div')
+ // container.innerHTML = ``
+ // const Comp = {
+ // render(this: any) {
+ // return (
+ // openBlock(),
+ // createElementBlock('div', null, [
+ // renderSlot(this.$slots, 'default'),
+ // ])
+ // )
+ // },
+ // }
+ // const show = ref(false)
+ // const clicked = ref(false)
+
+ // const Wrapper = {
+ // setup() {
+ // const items = ref([])
+ // onMounted(() => {
+ // items.value = [1]
+ // })
+ // return () => {
+ // return (
+ // openBlock(),
+ // createBlock(Comp, null, {
+ // default: withCtx(() => [
+ // createElementVNode('div', null, [
+ // createElementVNode('div', null, [
+ // clicked.value
+ // ? (openBlock(),
+ // createElementBlock('div', { key: 0 }, 'foo'))
+ // : createCommentVNode('v-if', true),
+ // ]),
+ // ]),
+ // createElementVNode(
+ // 'div',
+ // null,
+ // items.value.length,
+ // 1 /* TEXT */,
+ // ),
+ // ]),
+ // _: 1 /* STABLE */,
+ // })
+ // )
+ // }
+ // },
+ // }
+ // createSSRApp({
+ // components: { Wrapper },
+ // data() {
+ // return { show }
+ // },
+ // template: ``,
+ // }).mount(container)
+
+ // await nextTick()
+ // expect(container.innerHTML).toBe(
+ // ``,
+ // )
+
+ // show.value = true
+ // await nextTick()
+ // expect(async () => {
+ // clicked.value = true
+ // await nextTick()
+ // }).not.toThrow("Cannot read properties of null (reading 'insertBefore')")
+
+ // await nextTick()
+ // expect(container.innerHTML).toBe(
+ // ``,
+ // )
+ // } catch (e) {
+ // throw e
+ // } finally {
+ // __DEV__ = true
+ // }
+ // })
+
+ // describe('mismatch handling', () => {
+ // test('text node', () => {
+ // const { container } = mountWithHydration(`foo`, () => 'bar')
+ // expect(container.textContent).toBe('bar')
+ // expect(`Hydration text mismatch`).toHaveBeenWarned()
+ // })
+
+ // test('element text content', () => {
+ // const { container } = mountWithHydration(`foo
`, () =>
+ // h('div', 'bar'),
+ // )
+ // expect(container.innerHTML).toBe('bar
')
+ // expect(`Hydration text content mismatch`).toHaveBeenWarned()
+ // })
+
+ // test('not enough children', () => {
+ // const { container } = mountWithHydration(``, () =>
+ // h('div', [h('span', 'foo'), h('span', 'bar')]),
+ // )
+ // expect(container.innerHTML).toBe(
+ // 'foobar
',
+ // )
+ // expect(`Hydration children mismatch`).toHaveBeenWarned()
+ // })
+
+ // test('too many children', () => {
+ // const { container } = mountWithHydration(
+ // `foobar
`,
+ // () => h('div', [h('span', 'foo')]),
+ // )
+ // expect(container.innerHTML).toBe('foo
')
+ // expect(`Hydration children mismatch`).toHaveBeenWarned()
+ // })
+
+ // test('complete mismatch', () => {
+ // const { container } = mountWithHydration(
+ // `foobar
`,
+ // () => h('div', [h('div', 'foo'), h('p', 'bar')]),
+ // )
+ // expect(container.innerHTML).toBe('')
+ // expect(`Hydration node mismatch`).toHaveBeenWarnedTimes(2)
+ // })
+
+ // test('fragment mismatch removal', () => {
+ // const { container } = mountWithHydration(
+ // ``,
+ // () => h('div', [h('span', 'replaced')]),
+ // )
+ // expect(container.innerHTML).toBe('replaced
')
+ // expect(`Hydration node mismatch`).toHaveBeenWarned()
+ // })
+
+ // test('fragment not enough children', () => {
+ // const { container } = mountWithHydration(
+ // ``,
+ // () => h('div', [[h('div', 'foo'), h('div', 'bar')], h('div', 'baz')]),
+ // )
+ // expect(container.innerHTML).toBe(
+ // '',
+ // )
+ // expect(`Hydration node mismatch`).toHaveBeenWarned()
+ // })
+
+ // test('fragment too many children', () => {
+ // const { container } = mountWithHydration(
+ // ``,
+ // () => h('div', [[h('div', 'foo')], h('div', 'baz')]),
+ // )
+ // expect(container.innerHTML).toBe(
+ // '',
+ // )
+ // // fragment ends early and attempts to hydrate the extra bar
+ // // as 2nd fragment child.
+ // expect(`Hydration text content mismatch`).toHaveBeenWarned()
+ // // excessive children removal
+ // expect(`Hydration children mismatch`).toHaveBeenWarned()
+ // })
+
+ // test('Teleport target has empty children', () => {
+ // const teleportContainer = document.createElement('div')
+ // teleportContainer.id = 'teleport'
+ // document.body.appendChild(teleportContainer)
+
+ // mountWithHydration('', () =>
+ // h(Teleport, { to: '#teleport' }, [h('span', 'value')]),
+ // )
+ // expect(teleportContainer.innerHTML).toBe(`value`)
+ // expect(`Hydration children mismatch`).toHaveBeenWarned()
+ // })
+
+ // test('comment mismatch (element)', () => {
+ // const { container } = mountWithHydration(`
`, () =>
+ // h('div', [createCommentVNode('hi')]),
+ // )
+ // expect(container.innerHTML).toBe('')
+ // expect(`Hydration node mismatch`).toHaveBeenWarned()
+ // })
+
+ // test('comment mismatch (text)', () => {
+ // const { container } = mountWithHydration(`foobar
`, () =>
+ // h('div', [createCommentVNode('hi')]),
+ // )
+ // expect(container.innerHTML).toBe('')
+ // expect(`Hydration node mismatch`).toHaveBeenWarned()
+ // })
+
+ // test('class mismatch', () => {
+ // mountWithHydration(``, () =>
+ // h('div', { class: ['foo', 'bar'] }),
+ // )
+ // mountWithHydration(``, () =>
+ // h('div', { class: { foo: true, bar: true } }),
+ // )
+ // mountWithHydration(``, () =>
+ // h('div', { class: 'foo bar' }),
+ // )
+ // // SVG classes
+ // mountWithHydration(``, () =>
+ // h('svg', { class: 'foo bar' }),
+ // )
+ // // class with different order
+ // mountWithHydration(``, () =>
+ // h('div', { class: 'bar foo' }),
+ // )
+ // expect(`Hydration class mismatch`).not.toHaveBeenWarned()
+ // mountWithHydration(``, () =>
+ // h('div', { class: 'foo' }),
+ // )
+ // expect(`Hydration class mismatch`).toHaveBeenWarned()
+ // })
+
+ // test('style mismatch', () => {
+ // mountWithHydration(``, () =>
+ // h('div', { style: { color: 'red' } }),
+ // )
+ // mountWithHydration(``, () =>
+ // h('div', { style: `color:red;` }),
+ // )
+ // mountWithHydration(
+ // ``,
+ // () => h('div', { style: `font-size: 12px; color:red;` }),
+ // )
+ // mountWithHydration(``, () =>
+ // withDirectives(createVNode('div', { style: 'color: red' }, ''), [
+ // [vShow, false],
+ // ]),
+ // )
+ // expect(`Hydration style mismatch`).not.toHaveBeenWarned()
+ // mountWithHydration(``, () =>
+ // h('div', { style: { color: 'green' } }),
+ // )
+ // expect(`Hydration style mismatch`).toHaveBeenWarnedTimes(1)
+ // })
+
+ // test('style mismatch when no style attribute is present', () => {
+ // mountWithHydration(``, () =>
+ // h('div', { style: { color: 'red' } }),
+ // )
+ // expect(`Hydration style mismatch`).toHaveBeenWarnedTimes(1)
+ // })
+
+ // test('style mismatch w/ v-show', () => {
+ // mountWithHydration(``, () =>
+ // withDirectives(createVNode('div', { style: 'color: red' }, ''), [
+ // [vShow, false],
+ // ]),
+ // )
+ // expect(`Hydration style mismatch`).not.toHaveBeenWarned()
+ // mountWithHydration(``, () =>
+ // withDirectives(createVNode('div', { style: 'color: red' }, ''), [
+ // [vShow, false],
+ // ]),
+ // )
+ // expect(`Hydration style mismatch`).toHaveBeenWarnedTimes(1)
+ // })
+
+ // test('attr mismatch', () => {
+ // mountWithHydration(``, () => h('div', { id: 'foo' }))
+ // mountWithHydration(``, () =>
+ // h('div', { spellcheck: '' }),
+ // )
+ // mountWithHydration(``, () => h('div', { id: undefined }))
+ // // boolean
+ // mountWithHydration(``, () =>
+ // h('select', { multiple: true }),
+ // )
+ // mountWithHydration(`
`, () =>
+ // h('select', { multiple: 'multiple' }),
+ // )
+ // expect(`Hydration attribute mismatch`).not.toHaveBeenWarned()
+
+ // mountWithHydration(`