|
|
@@ -265,7 +265,7 @@ describe('SSR hydration', () => {
|
|
|
const fn = vi.fn()
|
|
|
const teleportContainer = document.createElement('div')
|
|
|
teleportContainer.id = 'teleport'
|
|
|
- teleportContainer.innerHTML = `<span>foo</span><span class="foo"></span><!--teleport anchor-->`
|
|
|
+ teleportContainer.innerHTML = `<!--teleport start anchor--><span>foo</span><span class="foo"></span><!--teleport anchor-->`
|
|
|
document.body.appendChild(teleportContainer)
|
|
|
|
|
|
const { vnode, container } = mountWithHydration(
|
|
|
@@ -281,13 +281,14 @@ describe('SSR hydration', () => {
|
|
|
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[0],
|
|
|
+ teleportContainer.childNodes[1],
|
|
|
)
|
|
|
expect((vnode.children as VNode[])[1].el).toBe(
|
|
|
- teleportContainer.childNodes[1],
|
|
|
+ teleportContainer.childNodes[2],
|
|
|
)
|
|
|
- expect(vnode.targetAnchor).toBe(teleportContainer.childNodes[2])
|
|
|
+ expect(vnode.targetAnchor).toBe(teleportContainer.childNodes[3])
|
|
|
|
|
|
// event handler
|
|
|
triggerEvent('click', teleportContainer.querySelector('.foo')!)
|
|
|
@@ -296,7 +297,7 @@ describe('SSR hydration', () => {
|
|
|
msg.value = 'bar'
|
|
|
await nextTick()
|
|
|
expect(teleportContainer.innerHTML).toBe(
|
|
|
- `<span>bar</span><span class="bar"></span><!--teleport anchor-->`,
|
|
|
+ `<!--teleport start anchor--><span>bar</span><span class="bar"></span><!--teleport anchor-->`,
|
|
|
)
|
|
|
})
|
|
|
|
|
|
@@ -326,7 +327,7 @@ describe('SSR hydration', () => {
|
|
|
|
|
|
const teleportHtml = ctx.teleports!['#teleport2']
|
|
|
expect(teleportHtml).toMatchInlineSnapshot(
|
|
|
- `"<span>foo</span><span class="foo"></span><!--teleport anchor--><span>foo2</span><span class="foo2"></span><!--teleport anchor-->"`,
|
|
|
+ `"<!--teleport start anchor--><span>foo</span><span class="foo"></span><!--teleport anchor--><!--teleport start anchor--><span>foo2</span><span class="foo2"></span><!--teleport anchor-->"`,
|
|
|
)
|
|
|
|
|
|
teleportContainer.innerHTML = teleportHtml
|
|
|
@@ -342,16 +343,18 @@ describe('SSR hydration', () => {
|
|
|
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[0],
|
|
|
+ teleportContainer.childNodes[1],
|
|
|
)
|
|
|
- expect(teleportVnode1.targetAnchor).toBe(teleportContainer.childNodes[2])
|
|
|
+ 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[3],
|
|
|
+ teleportContainer.childNodes[5],
|
|
|
)
|
|
|
- expect(teleportVnode2.targetAnchor).toBe(teleportContainer.childNodes[5])
|
|
|
+ expect(teleportVnode2.targetAnchor).toBe(teleportContainer.childNodes[7])
|
|
|
|
|
|
// // event handler
|
|
|
triggerEvent('click', teleportContainer.querySelector('.foo')!)
|
|
|
@@ -363,7 +366,7 @@ describe('SSR hydration', () => {
|
|
|
msg.value = 'bar'
|
|
|
await nextTick()
|
|
|
expect(teleportContainer.innerHTML).toMatchInlineSnapshot(
|
|
|
- `"<span>bar</span><span class="bar"></span><!--teleport anchor--><span>bar2</span><span class="bar2"></span><!--teleport anchor-->"`,
|
|
|
+ `"<!--teleport start anchor--><span>bar</span><span class="bar"></span><!--teleport anchor--><!--teleport start anchor--><span>bar2</span><span class="bar2"></span><!--teleport anchor-->"`,
|
|
|
)
|
|
|
})
|
|
|
|
|
|
@@ -390,7 +393,9 @@ describe('SSR hydration', () => {
|
|
|
)
|
|
|
|
|
|
const teleportHtml = ctx.teleports!['#teleport3']
|
|
|
- expect(teleportHtml).toMatchInlineSnapshot(`"<!--teleport anchor-->"`)
|
|
|
+ expect(teleportHtml).toMatchInlineSnapshot(
|
|
|
+ `"<!--teleport start anchor--><!--teleport anchor-->"`,
|
|
|
+ )
|
|
|
|
|
|
teleportContainer.innerHTML = teleportHtml
|
|
|
document.body.appendChild(teleportContainer)
|
|
|
@@ -413,7 +418,8 @@ describe('SSR hydration', () => {
|
|
|
expect(children[2].el).toBe(container.childNodes[6])
|
|
|
|
|
|
expect(teleportVnode.target).toBe(teleportContainer)
|
|
|
- expect(teleportVnode.targetAnchor).toBe(teleportContainer.childNodes[0])
|
|
|
+ expect(teleportVnode.targetStart).toBe(teleportContainer.childNodes[0])
|
|
|
+ expect(teleportVnode.targetAnchor).toBe(teleportContainer.childNodes[1])
|
|
|
|
|
|
// // event handler
|
|
|
triggerEvent('click', container.querySelector('.foo')!)
|
|
|
@@ -454,7 +460,7 @@ describe('SSR hydration', () => {
|
|
|
test('Teleport (as component root)', () => {
|
|
|
const teleportContainer = document.createElement('div')
|
|
|
teleportContainer.id = 'teleport4'
|
|
|
- teleportContainer.innerHTML = `hello<!--teleport anchor-->`
|
|
|
+ teleportContainer.innerHTML = `<!--teleport start anchor-->hello<!--teleport anchor-->`
|
|
|
document.body.appendChild(teleportContainer)
|
|
|
|
|
|
const wrapper = {
|
|
|
@@ -483,7 +489,7 @@ describe('SSR hydration', () => {
|
|
|
test('Teleport (nested)', () => {
|
|
|
const teleportContainer = document.createElement('div')
|
|
|
teleportContainer.id = 'teleport5'
|
|
|
- teleportContainer.innerHTML = `<div><!--teleport start--><!--teleport end--></div><!--teleport anchor--><div>child</div><!--teleport anchor-->`
|
|
|
+ teleportContainer.innerHTML = `<!--teleport start anchor--><div><!--teleport start--><!--teleport end--></div><!--teleport anchor--><!--teleport start anchor--><div>child</div><!--teleport anchor-->`
|
|
|
document.body.appendChild(teleportContainer)
|
|
|
|
|
|
const { vnode, container } = mountWithHydration(
|
|
|
@@ -498,7 +504,7 @@ describe('SSR hydration', () => {
|
|
|
expect(vnode.anchor).toBe(container.lastChild)
|
|
|
|
|
|
const childDivVNode = (vnode as any).children[0]
|
|
|
- const div = teleportContainer.firstChild
|
|
|
+ const div = teleportContainer.childNodes[1]
|
|
|
expect(childDivVNode.el).toBe(div)
|
|
|
expect(vnode.targetAnchor).toBe(div?.nextSibling)
|
|
|
|
|
|
@@ -548,6 +554,66 @@ describe('SSR hydration', () => {
|
|
|
teleportContainer.id = 'target'
|
|
|
document.body.appendChild(teleportContainer)
|
|
|
|
|
|
+ // server render
|
|
|
+ const ctx: SSRContext = {}
|
|
|
+ container.innerHTML = await renderToString(h(App), ctx)
|
|
|
+ expect(container.innerHTML).toBe(
|
|
|
+ '<div><!--teleport start--><!--teleport end--></div>',
|
|
|
+ )
|
|
|
+ teleportContainer.innerHTML = ctx.teleports!['#target']
|
|
|
+
|
|
|
+ // hydrate
|
|
|
+ createSSRApp(App).mount(container)
|
|
|
+ expect(container.innerHTML).toBe(
|
|
|
+ '<div><!--teleport start--><!--teleport end--></div>',
|
|
|
+ )
|
|
|
+ expect(teleportContainer.innerHTML).toBe(
|
|
|
+ '<!--teleport start anchor--><span>Teleported Comp1</span><!--teleport anchor-->',
|
|
|
+ )
|
|
|
+ expect(`Hydration children mismatch`).not.toHaveBeenWarned()
|
|
|
+
|
|
|
+ toggle.value = false
|
|
|
+ await nextTick()
|
|
|
+ expect(container.innerHTML).toBe('<div><div>Comp2</div></div>')
|
|
|
+ expect(teleportContainer.innerHTML).toBe('')
|
|
|
+ })
|
|
|
+
|
|
|
+ test('Teleport unmount (mismatch + full integration)', async () => {
|
|
|
+ const Comp1 = {
|
|
|
+ template: `
|
|
|
+ <Teleport to="#target">
|
|
|
+ <span>Teleported Comp1</span>
|
|
|
+ </Teleport>
|
|
|
+ `,
|
|
|
+ }
|
|
|
+ const Comp2 = {
|
|
|
+ template: `
|
|
|
+ <div>Comp2</div>
|
|
|
+ `,
|
|
|
+ }
|
|
|
+
|
|
|
+ const toggle = ref(true)
|
|
|
+ const App = {
|
|
|
+ template: `
|
|
|
+ <div>
|
|
|
+ <Comp1 v-if="toggle"/>
|
|
|
+ <Comp2 v-else/>
|
|
|
+ </div>
|
|
|
+ `,
|
|
|
+ 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(
|
|
|
@@ -569,7 +635,7 @@ describe('SSR hydration', () => {
|
|
|
expect(teleportContainer.innerHTML).toBe('')
|
|
|
})
|
|
|
|
|
|
- test('Teleport target change (full integration)', async () => {
|
|
|
+ test('Teleport target change (mismatch + full integration)', async () => {
|
|
|
const target = ref('#target1')
|
|
|
const Comp = {
|
|
|
template: `
|