@@ -8,7 +8,10 @@ import {
88 getCurrentInstance ,
99 insert ,
1010 nextTick ,
11+ prepend ,
1112 ref ,
13+ renderEffect ,
14+ setText ,
1215 template ,
1316} from '../src'
1417import { makeRender } from './_utils'
@@ -43,13 +46,11 @@ describe('component: slots', () => {
4346 const t0 = template ( '<div></div>' )
4447 const n0 = t0 ( )
4548 instance = getCurrentInstance ( )
46- const n1 = createSlot ( 'header' )
47- insert ( n1 , n0 as any as ParentNode )
4849 return n0
4950 } ,
5051 } )
5152
52- const { render, host } = define ( {
53+ const { render } = define ( {
5354 render ( ) {
5455 return createComponent ( Comp , { } , { header : ( ) => template ( 'header' ) ( ) } )
5556 } ,
@@ -60,8 +61,6 @@ describe('component: slots', () => {
6061 expect ( instance . slots . header ( ) ) . toMatchObject (
6162 document . createTextNode ( 'header' ) ,
6263 )
63-
64- expect ( host . innerHTML ) . toBe ( '<div>header</div>' )
6564 } )
6665
6766 // NOTE: slot normalization is not supported
@@ -243,4 +242,190 @@ describe('component: slots', () => {
243242 'Slot "default" invoked outside of the render function' ,
244243 ) . not . toHaveBeenWarned ( )
245244 } )
245+
246+ describe ( 'createSlot' , ( ) => {
247+ test ( 'slot should be render correctly' , ( ) => {
248+ const Comp = defineComponent ( ( ) => {
249+ const n0 = template ( '<div></div>' ) ( )
250+ insert ( createSlot ( 'header' ) , n0 as any as ParentNode )
251+ return n0
252+ } )
253+
254+ const { host } = define ( ( ) => {
255+ return createComponent ( Comp , { } , { header : ( ) => template ( 'header' ) ( ) } )
256+ } ) . render ( )
257+
258+ expect ( host . innerHTML ) . toBe ( '<div>header</div>' )
259+ } )
260+
261+ test ( 'slot should be render correctly with binds' , async ( ) => {
262+ const Comp = defineComponent ( ( ) => {
263+ const n0 = template ( '<div></div>' ) ( )
264+ insert (
265+ createSlot ( 'header' , { title : ( ) => 'header' } ) ,
266+ n0 as any as ParentNode ,
267+ )
268+ return n0
269+ } )
270+
271+ const { host } = define ( ( ) => {
272+ return createComponent (
273+ Comp ,
274+ { } ,
275+ {
276+ header : ( { title } ) => {
277+ const el = template ( '<h1></h1>' ) ( )
278+ renderEffect ( ( ) => {
279+ setText ( el , title ( ) )
280+ } )
281+ return el
282+ } ,
283+ } ,
284+ )
285+ } ) . render ( )
286+
287+ expect ( host . innerHTML ) . toBe ( '<div><h1>header</h1></div>' )
288+ } )
289+
290+ test ( 'dynamic slot should be render correctly with binds' , async ( ) => {
291+ const Comp = defineComponent ( ( ) => {
292+ const n0 = template ( '<div></div>' ) ( )
293+ prepend (
294+ n0 as any as ParentNode ,
295+ createSlot ( 'header' , { title : ( ) => 'header' } ) ,
296+ )
297+ return n0
298+ } )
299+
300+ const { host } = define ( ( ) => {
301+ // dynamic slot
302+ return createComponent ( Comp , { } , { } , ( ) => [
303+ { name : 'header' , fn : ( { title } ) => template ( `${ title ( ) } ` ) ( ) } ,
304+ ] )
305+ } ) . render ( )
306+
307+ expect ( host . innerHTML ) . toBe ( '<div>header<!--slot--></div>' )
308+ } )
309+
310+ test ( 'dynamic slot outlet should be render correctly with binds' , async ( ) => {
311+ const Comp = defineComponent ( ( ) => {
312+ const n0 = template ( '<div></div>' ) ( )
313+ prepend (
314+ n0 as any as ParentNode ,
315+ createSlot (
316+ ( ) => 'header' , // dynamic slot outlet name
317+ { title : ( ) => 'header' } ,
318+ ) ,
319+ )
320+ return n0
321+ } )
322+
323+ const { host } = define ( ( ) => {
324+ return createComponent (
325+ Comp ,
326+ { } ,
327+ { header : ( { title } ) => template ( `${ title ( ) } ` ) ( ) } ,
328+ )
329+ } ) . render ( )
330+
331+ expect ( host . innerHTML ) . toBe ( '<div>header<!--slot--></div>' )
332+ } )
333+
334+ test ( 'fallback should be render correctly' , ( ) => {
335+ const Comp = defineComponent ( ( ) => {
336+ const n0 = template ( '<div></div>' ) ( )
337+ insert (
338+ createSlot ( 'header' , { } , ( ) => template ( 'fallback' ) ( ) ) ,
339+ n0 as any as ParentNode ,
340+ )
341+ return n0
342+ } )
343+
344+ const { host } = define ( ( ) => {
345+ return createComponent ( Comp , { } , { } )
346+ } ) . render ( )
347+
348+ expect ( host . innerHTML ) . toBe ( '<div>fallback</div>' )
349+ } )
350+
351+ test ( 'dynamic slot should be updated correctly' , async ( ) => {
352+ const flag1 = ref ( true )
353+
354+ const Child = defineComponent ( ( ) => {
355+ const temp0 = template ( '<p></p>' )
356+ const el0 = temp0 ( )
357+ const el1 = temp0 ( )
358+ const slot1 = createSlot ( 'one' , { } , ( ) => template ( 'one fallback' ) ( ) )
359+ const slot2 = createSlot ( 'two' , { } , ( ) => template ( 'two fallback' ) ( ) )
360+ insert ( slot1 , el0 as any as ParentNode )
361+ insert ( slot2 , el1 as any as ParentNode )
362+ return [ el0 , el1 ]
363+ } )
364+
365+ const { host } = define ( ( ) => {
366+ return createComponent ( Child , { } , { } , ( ) => [
367+ flag1 . value
368+ ? { name : 'one' , fn : ( ) => template ( 'one content' ) ( ) }
369+ : { name : 'two' , fn : ( ) => template ( 'two content' ) ( ) } ,
370+ ] )
371+ } ) . render ( )
372+
373+ expect ( host . innerHTML ) . toBe (
374+ '<p>one content<!--slot--></p><p>two fallback<!--slot--></p>' ,
375+ )
376+
377+ flag1 . value = false
378+ await nextTick ( )
379+
380+ expect ( host . innerHTML ) . toBe (
381+ '<p>one fallback<!--slot--></p><p>two content<!--slot--></p>' ,
382+ )
383+
384+ flag1 . value = true
385+ await nextTick ( )
386+
387+ expect ( host . innerHTML ) . toBe (
388+ '<p>one content<!--slot--></p><p>two fallback<!--slot--></p>' ,
389+ )
390+ } )
391+
392+ test ( 'dynamic slot outlet should be updated correctly' , async ( ) => {
393+ const slotOutletName = ref ( 'one' )
394+
395+ const Child = defineComponent ( ( ) => {
396+ const temp0 = template ( '<p></p>' )
397+ const el0 = temp0 ( )
398+ const slot1 = createSlot (
399+ ( ) => slotOutletName . value ,
400+ { } ,
401+ ( ) => template ( 'fallback' ) ( ) ,
402+ )
403+ insert ( slot1 , el0 as any as ParentNode )
404+ return el0
405+ } )
406+
407+ const { host } = define ( ( ) => {
408+ return createComponent (
409+ Child ,
410+ { } ,
411+ {
412+ one : ( ) => template ( 'one content' ) ( ) ,
413+ two : ( ) => template ( 'two content' ) ( ) ,
414+ } ,
415+ )
416+ } ) . render ( )
417+
418+ expect ( host . innerHTML ) . toBe ( '<p>one content<!--slot--></p>' )
419+
420+ slotOutletName . value = 'two'
421+ await nextTick ( )
422+
423+ expect ( host . innerHTML ) . toBe ( '<p>two content<!--slot--></p>' )
424+
425+ slotOutletName . value = 'none'
426+ await nextTick ( )
427+
428+ expect ( host . innerHTML ) . toBe ( '<p>fallback<!--slot--></p>' )
429+ } )
430+ } )
246431} )
0 commit comments