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()
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)
+ })
}