]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
wip: port tests
authordaiwei <daiwei521@126.com>
Mon, 24 Mar 2025 05:55:17 +0000 (13:55 +0800)
committerdaiwei <daiwei521@126.com>
Mon, 24 Mar 2025 05:55:17 +0000 (13:55 +0800)
packages/runtime-vapor/__tests__/components/Teleport.spec.ts

index bc77be2dc014b8369b380788278cf4cb2fe09e74..86b1ec62cf1ed2161eb85afd42b5dbc4f11369be 100644 (file)
@@ -4,14 +4,24 @@ import {
   createComponent as originalCreateComponent,
 } from '../../src/component'
 import {
+  type VaporDirective,
   VaporTeleport,
+  createIf,
   createTemplateRefSetter,
   setInsertionState,
   template,
+  withVaporDirectives,
 } from '@vue/runtime-vapor'
 
 import { makeRender } from '../_utils'
-import { nextTick, onBeforeUnmount, onUnmounted, ref, shallowRef } from 'vue'
+import {
+  nextTick,
+  onBeforeUnmount,
+  onMounted,
+  onUnmounted,
+  ref,
+  shallowRef,
+} from 'vue'
 
 const define = makeRender()
 
@@ -410,17 +420,254 @@ function runSharedTests(deferMode: boolean): void {
     expect(target.innerHTML).toBe('<div>teleported</div>')
   })
 
-  test.todo('moving teleport while disabled', async () => {})
-  test.todo('should work with block tree', async () => {})
-  test.todo(
-    `the dir hooks of the Teleport's children should be called correctly`,
-    async () => {},
-  )
-  test.todo(
-    `ensure that target changes when disabled are updated correctly when enabled`,
-    async () => {},
-  )
-  test.todo('toggle sibling node inside target node', async () => {})
-  test.todo('unmount previous sibling node inside target node', async () => {})
-  test.todo('accessing template refs inside teleport', async () => {})
+  test.todo('moving teleport while disabled', async () => {
+    const target = document.createElement('div')
+    const root = document.createElement('div')
+
+    const child1 = createComponent(
+      VaporTeleport,
+      { to: () => target, disabled: () => true },
+      { default: () => template('<div>teleported</div>')() },
+    )
+    const child2 = template('<div>root</div>')()
+
+    const children = shallowRef([child1, child2])
+    const { mount } = define({
+      setup() {
+        return children.value
+      },
+    }).create()
+    mount(root)
+
+    expect(root.innerHTML).toBe(
+      '<div>teleported</div><!--teleport--><div>root</div>',
+    )
+    expect(target.innerHTML).toBe('')
+
+    children.value = [child2, child1]
+    await nextTick()
+    expect(root.innerHTML).toBe(
+      '<div>root</div><div>teleported</div><!--teleport-->',
+    )
+    expect(target.innerHTML).toBe('')
+  })
+
+  test(`the dir hooks of the Teleport's children should be called correctly`, async () => {
+    const target = document.createElement('div')
+    const root = document.createElement('div')
+    const toggle = ref(true)
+
+    const spy = vi.fn()
+    const teardown = vi.fn()
+    const dir: VaporDirective = vi.fn((el, source) => {
+      spy()
+      return teardown
+    })
+
+    const { mount } = define({
+      setup() {
+        return createComponent(
+          VaporTeleport,
+          {
+            to: () => target,
+          },
+          {
+            default: () => {
+              return createIf(
+                () => toggle.value,
+                () => {
+                  const n1 = template('<div>foo</div>')() as any
+                  withVaporDirectives(n1, [[dir]])
+                  return n1
+                },
+              )
+            },
+          },
+        )
+      },
+    }).create()
+
+    mount(root)
+    expect(root.innerHTML).toBe('<!--teleport-->')
+    expect(target.innerHTML).toBe('<div>foo</div><!--if-->')
+    expect(spy).toHaveBeenCalledTimes(1)
+    expect(teardown).not.toHaveBeenCalled()
+
+    toggle.value = false
+    await nextTick()
+    expect(root.innerHTML).toBe('<!--teleport-->')
+    expect(target.innerHTML).toBe('<!--if-->')
+    expect(spy).toHaveBeenCalledTimes(1)
+    expect(teardown).toHaveBeenCalledTimes(1)
+  })
+
+  test(`ensure that target changes when disabled are updated correctly when enabled`, async () => {
+    const root = document.createElement('div')
+    const target1 = document.createElement('div')
+    const target2 = document.createElement('div')
+    const target3 = document.createElement('div')
+    const target = ref(target1)
+    const disabled = ref(true)
+
+    const { mount } = define({
+      setup() {
+        return createComponent(
+          VaporTeleport,
+          {
+            to: () => target.value,
+            disabled: () => disabled.value,
+          },
+          {
+            default: () => template('<div>teleported</div>')(),
+          },
+        )
+      },
+    }).create()
+    mount(root)
+
+    disabled.value = false
+    await nextTick()
+    expect(target1.innerHTML).toBe('<div>teleported</div>')
+    expect(target2.innerHTML).toBe('')
+    expect(target3.innerHTML).toBe('')
+
+    disabled.value = true
+    await nextTick()
+    target.value = target2
+    await nextTick()
+    expect(target1.innerHTML).toBe('')
+    expect(target2.innerHTML).toBe('')
+    expect(target3.innerHTML).toBe('')
+
+    target.value = target3
+    await nextTick()
+    expect(target1.innerHTML).toBe('')
+    expect(target2.innerHTML).toBe('')
+    expect(target3.innerHTML).toBe('')
+
+    disabled.value = false
+    await nextTick()
+    expect(target1.innerHTML).toBe('')
+    expect(target2.innerHTML).toBe('')
+    expect(target3.innerHTML).toBe('<div>teleported</div>')
+  })
+
+  test('toggle sibling node inside target node', async () => {
+    const root = document.createElement('div')
+    const show = ref(false)
+    const { mount } = define({
+      setup() {
+        return createIf(
+          () => show.value,
+          () => {
+            return createComponent(
+              VaporTeleport,
+              {
+                to: () => root,
+              },
+              {
+                default: () => template('<div>teleported</div>')(),
+              },
+            )
+          },
+          () => {
+            return template('<div>foo</div>')()
+          },
+        )
+      },
+    }).create()
+
+    mount(root)
+    expect(root.innerHTML).toBe('<div>foo</div><!--if-->')
+
+    show.value = true
+    await nextTick()
+    expect(root.innerHTML).toBe('<!--teleport--><!--if--><div>teleported</div>')
+
+    show.value = false
+    await nextTick()
+    expect(root.innerHTML).toBe('<div>foo</div><!--if-->')
+  })
+
+  test('unmount previous sibling node inside target node', async () => {
+    const root = document.createElement('div')
+    const parentShow = ref(false)
+    const childShow = ref(true)
+
+    const { component: Comp } = define({
+      setup() {
+        return createComponent(
+          VaporTeleport,
+          { to: () => root },
+          {
+            default: () => {
+              return template('<div>foo</div>')()
+            },
+          },
+        )
+      },
+    })
+
+    const { mount } = define({
+      setup() {
+        return createIf(
+          () => parentShow.value,
+          () =>
+            createIf(
+              () => childShow.value,
+              () => createComponent(Comp),
+              () => template('bar')(),
+            ),
+          () => template('foo')(),
+        )
+      },
+    }).create()
+
+    mount(root)
+    expect(root.innerHTML).toBe('foo<!--if-->')
+
+    parentShow.value = true
+    await nextTick()
+    expect(root.innerHTML).toBe(
+      '<!--teleport--><!--if--><!--if--><div>foo</div>',
+    )
+
+    parentShow.value = false
+    await nextTick()
+    expect(root.innerHTML).toBe('foo<!--if-->')
+  })
+
+  test('accessing template refs inside teleport', async () => {
+    const target = document.createElement('div')
+    const tRef = ref()
+    let tRefInMounted
+
+    const { mount } = define({
+      setup() {
+        onMounted(() => {
+          tRefInMounted = tRef.value
+        })
+        const n1 = createComponent(
+          VaporTeleport,
+          {
+            to: () => target,
+          },
+          {
+            default: () => {
+              const setTemplateRef = createTemplateRefSetter()
+              const n0 = template('<div>teleported</div>')() as any
+              setTemplateRef(n0, tRef)
+              return n0
+            },
+          },
+        )
+        return n1
+      },
+    }).create()
+    mount(target)
+
+    const child = target.children[0]
+    expect(child.outerHTML).toBe(`<div>teleported</div>`)
+    expect(tRefInMounted).toBe(child)
+  })
 }