Skip to content

Commit c0cd7fc

Browse files
committed
wip: add tests
1 parent 2571388 commit c0cd7fc

File tree

2 files changed

+218
-44
lines changed

2 files changed

+218
-44
lines changed

packages/runtime-vapor/__tests__/components/Teleport.spec.ts

+215-41
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,12 @@ import {
33
type VaporComponent,
44
createComponent as originalCreateComponent,
55
} from '../../src/component'
6-
import { VaporTeleport, template } from '@vue/runtime-vapor'
6+
import {
7+
VaporTeleport,
8+
createTemplateRefSetter,
9+
setInsertionState,
10+
template,
11+
} from '@vue/runtime-vapor'
712

813
import { makeRender } from '../_utils'
914
import { nextTick, onBeforeUnmount, onUnmounted, ref, shallowRef } from 'vue'
@@ -192,50 +197,219 @@ function runSharedTests(deferMode: boolean): void {
192197
expect(target.innerHTML).toBe('')
193198
})
194199

195-
test.todo(
196-
'descendent component should be unmounted when teleport is disabled and unmounted',
197-
async () => {
198-
const root = document.createElement('div')
199-
const beforeUnmount = vi.fn()
200-
const unmounted = vi.fn()
201-
const { component: Comp } = define({
202-
setup() {
203-
onBeforeUnmount(beforeUnmount)
204-
onUnmounted(unmounted)
205-
return [template('<p>')(), template('<p>')()]
206-
},
207-
})
200+
test('descendent component should be unmounted when teleport is disabled and unmounted', async () => {
201+
const root = document.createElement('div')
202+
const beforeUnmount = vi.fn()
203+
const unmounted = vi.fn()
204+
const { component: Comp } = define({
205+
setup() {
206+
onBeforeUnmount(beforeUnmount)
207+
onUnmounted(unmounted)
208+
return [template('<p>')(), template('<p>')()]
209+
},
210+
})
208211

209-
const { app } = define({
210-
setup() {
211-
const n0 = createComponent(
212-
VaporTeleport,
213-
{
214-
to: () => null,
215-
disabled: () => true,
216-
},
217-
{
218-
default: () => createComponent(Comp),
219-
},
220-
)
221-
return [n0]
222-
},
223-
}).create()
224-
app.mount(root)
212+
const { app } = define({
213+
setup() {
214+
const n0 = createComponent(
215+
VaporTeleport,
216+
{
217+
to: () => null,
218+
disabled: () => true,
219+
},
220+
{
221+
default: () => createComponent(Comp),
222+
},
223+
)
224+
return [n0]
225+
},
226+
}).create()
227+
app.mount(root)
225228

226-
expect(beforeUnmount).toHaveBeenCalledTimes(0)
227-
expect(unmounted).toHaveBeenCalledTimes(0)
229+
expect(beforeUnmount).toHaveBeenCalledTimes(0)
230+
expect(unmounted).toHaveBeenCalledTimes(0)
228231

229-
app.unmount()
230-
expect(beforeUnmount).toHaveBeenCalledTimes(1)
231-
expect(unmounted).toHaveBeenCalledTimes(1)
232-
},
233-
)
232+
app.unmount()
233+
await nextTick()
234+
expect(beforeUnmount).toHaveBeenCalledTimes(1)
235+
expect(unmounted).toHaveBeenCalledTimes(1)
236+
})
237+
238+
test('multiple teleport with same target', async () => {
239+
const target = document.createElement('div')
240+
const root = document.createElement('div')
241+
242+
const child1 = shallowRef(template('<div>one</div>')())
243+
const child2 = shallowRef(template('two')())
244+
245+
const { mount } = define({
246+
setup() {
247+
const n0 = template('<div></div>')()
248+
setInsertionState(n0 as any)
249+
createComponent(
250+
VaporTeleport,
251+
{
252+
to: () => target,
253+
},
254+
{
255+
default: () => child1.value,
256+
},
257+
)
258+
createComponent(
259+
VaporTeleport,
260+
{
261+
to: () => target,
262+
},
263+
{
264+
default: () => child2.value,
265+
},
266+
)
267+
return [n0]
268+
},
269+
}).create()
270+
mount(root)
271+
expect(root.innerHTML).toBe('<div><!--teleport--><!--teleport--></div>')
272+
expect(target.innerHTML).toBe('<div>one</div>two')
273+
274+
// update existing content
275+
child1.value = [
276+
template('<div>one</div>')(),
277+
template('<div>two</div>')(),
278+
] as any
279+
child2.value = [template('three')()] as any
280+
await nextTick()
281+
expect(target.innerHTML).toBe('<div>one</div><div>two</div>three')
282+
283+
// toggling
284+
child1.value = [] as any
285+
await nextTick()
286+
expect(root.innerHTML).toBe('<div><!--teleport--><!--teleport--></div>')
287+
expect(target.innerHTML).toBe('three')
288+
289+
// toggle back
290+
child1.value = [
291+
template('<div>one</div>')(),
292+
template('<div>two</div>')(),
293+
] as any
294+
child2.value = [template('three')()] as any
295+
await nextTick()
296+
expect(root.innerHTML).toBe('<div><!--teleport--><!--teleport--></div>')
297+
// should append
298+
expect(target.innerHTML).toBe('<div>one</div><div>two</div>three')
299+
300+
// toggle the other teleport
301+
child2.value = [] as any
302+
await nextTick()
303+
expect(root.innerHTML).toBe('<div><!--teleport--><!--teleport--></div>')
304+
expect(target.innerHTML).toBe('<div>one</div><div>two</div>')
305+
})
306+
307+
test('should work when using template ref as target', async () => {
308+
const root = document.createElement('div')
309+
const target = ref<HTMLElement | null>(null)
310+
const disabled = ref(true)
311+
312+
const { mount } = define({
313+
setup() {
314+
const setTemplateRef = createTemplateRefSetter()
315+
const n0 = template('<div></div>')() as any
316+
setTemplateRef(n0, target)
317+
318+
const n1 = createComponent(
319+
VaporTeleport,
320+
{
321+
to: () => target.value,
322+
disabled: () => disabled.value,
323+
},
324+
{
325+
default: () => template('<div>teleported</div>')(),
326+
},
327+
)
328+
return [n0, n1]
329+
},
330+
}).create()
331+
mount(root)
332+
333+
expect(root.innerHTML).toBe(
334+
'<div></div><div>teleported</div><!--teleport-->',
335+
)
336+
disabled.value = false
337+
await nextTick()
338+
expect(root.innerHTML).toBe(
339+
'<div><div>teleported</div></div><!--teleport-->',
340+
)
341+
})
342+
343+
test('disabled', async () => {
344+
const target = document.createElement('div')
345+
const root = document.createElement('div')
346+
347+
const disabled = ref(false)
348+
const { mount } = define({
349+
setup() {
350+
const n0 = createComponent(
351+
VaporTeleport,
352+
{
353+
to: () => target,
354+
disabled: () => disabled.value,
355+
},
356+
{
357+
default: () => template('<div>teleported</div>')(),
358+
},
359+
)
360+
const n1 = template('<div>root</div>')()
361+
return [n0, n1]
362+
},
363+
}).create()
364+
mount(root)
365+
366+
expect(root.innerHTML).toBe('<!--teleport--><div>root</div>')
367+
expect(target.innerHTML).toBe('<div>teleported</div>')
368+
369+
disabled.value = true
370+
await nextTick()
371+
expect(root.innerHTML).toBe(
372+
'<!--teleport start--><div>teleported</div><!--teleport end--><!--teleport--><div>root</div>',
373+
)
374+
expect(target.innerHTML).toBe('')
375+
376+
// toggle back
377+
disabled.value = false
378+
await nextTick()
379+
expect(root.innerHTML).toBe(
380+
'<!--teleport start--><!--teleport end--><!--teleport--><div>root</div>',
381+
)
382+
expect(target.innerHTML).toBe('<div>teleported</div>')
383+
})
384+
385+
test.todo('moving teleport while enabled', async () => {
386+
const target = document.createElement('div')
387+
const root = document.createElement('div')
388+
389+
const child1 = createComponent(
390+
VaporTeleport,
391+
{ to: () => target },
392+
{ default: () => template('<div>teleported</div>')() },
393+
)
394+
const child2 = template('<div>root</div>')()
395+
396+
const children = shallowRef([child1, child2])
397+
const { mount } = define({
398+
setup() {
399+
return children.value
400+
},
401+
}).create()
402+
mount(root)
403+
404+
expect(root.innerHTML).toBe('<!--teleport--><div>root</div>')
405+
expect(target.innerHTML).toBe('<div>teleported</div>')
406+
407+
children.value = [child2, child1]
408+
await nextTick()
409+
expect(root.innerHTML).toBe('<div>root</div><!--teleport-->')
410+
expect(target.innerHTML).toBe('<div>teleported</div>')
411+
})
234412

235-
test.todo('multiple teleport with same target', async () => {})
236-
test.todo('should work when using template ref as target', async () => {})
237-
test.todo('disabled', async () => {})
238-
test.todo('moving teleport while enabled', async () => {})
239413
test.todo('moving teleport while disabled', async () => {})
240414
test.todo('should work with block tree', async () => {})
241415
test.todo(

packages/runtime-vapor/src/components/Teleport.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -59,14 +59,14 @@ export class TeleportFragment extends VaporFragment {
5959
}
6060

6161
update(props: TeleportProps, children: Block): void {
62+
const parent = this.anchor.parentNode
6263
// teardown previous
63-
if (this.currentParent && this.nodes) {
64-
remove(this.nodes, this.currentParent)
64+
if (this.nodes && (parent || this.currentParent)) {
65+
remove(this.nodes, this.currentParent! || parent)
6566
}
6667

6768
this.nodes = children
6869
const disabled = isTeleportDisabled(props)
69-
const parent = this.anchor.parentNode
7070

7171
const mount = (parent: ParentNode, anchor: Node | null) => {
7272
insert(this.nodes, (this.currentParent = parent), anchor)

0 commit comments

Comments
 (0)