@@ -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
813import { makeRender } from '../_utils'
914import { 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 (
0 commit comments