@@ -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'
@@ -58,13 +61,11 @@ describe('component: slots', () => {
5861 const t0 = template ( '<div></div>' )
5962 const n0 = t0 ( )
6063 instance = getCurrentInstance ( )
61- const n1 = createSlot ( 'header' )
62- insert ( n1 , n0 as any as ParentNode )
6364 return n0
6465 } ,
6566 } )
6667
67- const { render, host } = define ( {
68+ const { render } = define ( {
6869 render ( ) {
6970 return createComponent ( Comp , { } , { header : ( ) => template ( 'header' ) ( ) } )
7071 } ,
@@ -75,8 +76,6 @@ describe('component: slots', () => {
7576 expect ( instance . slots . header ( ) ) . toMatchObject (
7677 document . createTextNode ( 'header' ) ,
7778 )
78-
79- expect ( host . innerHTML ) . toBe ( '<div>header</div>' )
8079 } )
8180
8281 // runtime-core's "initSlots: instance.slots should be set correctly (when vnode.shapeFlag is not SLOTS_CHILDREN)"
@@ -194,4 +193,190 @@ describe('component: slots', () => {
194193 'Slot "default" invoked outside of the render function' ,
195194 ) . not . toHaveBeenWarned ( )
196195 } )
196+
197+ describe ( 'createSlot' , ( ) => {
198+ test ( 'slot should be render correctly' , ( ) => {
199+ const Comp = defineComponent ( ( ) => {
200+ const n0 = template ( '<div></div>' ) ( )
201+ insert ( createSlot ( 'header' ) , n0 as any as ParentNode )
202+ return n0
203+ } )
204+
205+ const { host } = define ( ( ) => {
206+ return createComponent ( Comp , { } , { header : ( ) => template ( 'header' ) ( ) } )
207+ } ) . render ( )
208+
209+ expect ( host . innerHTML ) . toBe ( '<div>header</div>' )
210+ } )
211+
212+ test ( 'slot should be render correctly with binds' , async ( ) => {
213+ const Comp = defineComponent ( ( ) => {
214+ const n0 = template ( '<div></div>' ) ( )
215+ insert (
216+ createSlot ( 'header' , { title : ( ) => 'header' } ) ,
217+ n0 as any as ParentNode ,
218+ )
219+ return n0
220+ } )
221+
222+ const { host } = define ( ( ) => {
223+ return createComponent (
224+ Comp ,
225+ { } ,
226+ {
227+ header : ( { title } ) => {
228+ const el = template ( '<h1></h1>' ) ( )
229+ renderEffect ( ( ) => {
230+ setText ( el , title ( ) )
231+ } )
232+ return el
233+ } ,
234+ } ,
235+ )
236+ } ) . render ( )
237+
238+ expect ( host . innerHTML ) . toBe ( '<div><h1>header</h1></div>' )
239+ } )
240+
241+ test ( 'dynamic slot should be render correctly with binds' , async ( ) => {
242+ const Comp = defineComponent ( ( ) => {
243+ const n0 = template ( '<div></div>' ) ( )
244+ prepend (
245+ n0 as any as ParentNode ,
246+ createSlot ( 'header' , { title : ( ) => 'header' } ) ,
247+ )
248+ return n0
249+ } )
250+
251+ const { host } = define ( ( ) => {
252+ // dynamic slot
253+ return createComponent ( Comp , { } , { } , ( ) => [
254+ { name : 'header' , fn : ( { title } ) => template ( `${ title ( ) } ` ) ( ) } ,
255+ ] )
256+ } ) . render ( )
257+
258+ expect ( host . innerHTML ) . toBe ( '<div>header<!--slot--></div>' )
259+ } )
260+
261+ test ( 'dynamic slot outlet should be render correctly with binds' , async ( ) => {
262+ const Comp = defineComponent ( ( ) => {
263+ const n0 = template ( '<div></div>' ) ( )
264+ prepend (
265+ n0 as any as ParentNode ,
266+ createSlot (
267+ ( ) => 'header' , // dynamic slot outlet name
268+ { title : ( ) => 'header' } ,
269+ ) ,
270+ )
271+ return n0
272+ } )
273+
274+ const { host } = define ( ( ) => {
275+ return createComponent (
276+ Comp ,
277+ { } ,
278+ { header : ( { title } ) => template ( `${ title ( ) } ` ) ( ) } ,
279+ )
280+ } ) . render ( )
281+
282+ expect ( host . innerHTML ) . toBe ( '<div>header<!--slot--></div>' )
283+ } )
284+
285+ test ( 'fallback should be render correctly' , ( ) => {
286+ const Comp = defineComponent ( ( ) => {
287+ const n0 = template ( '<div></div>' ) ( )
288+ insert (
289+ createSlot ( 'header' , { } , ( ) => template ( 'fallback' ) ( ) ) ,
290+ n0 as any as ParentNode ,
291+ )
292+ return n0
293+ } )
294+
295+ const { host } = define ( ( ) => {
296+ return createComponent ( Comp , { } , { } )
297+ } ) . render ( )
298+
299+ expect ( host . innerHTML ) . toBe ( '<div>fallback</div>' )
300+ } )
301+
302+ test ( 'dynamic slot should be updated correctly' , async ( ) => {
303+ const flag1 = ref ( true )
304+
305+ const Child = defineComponent ( ( ) => {
306+ const temp0 = template ( '<p></p>' )
307+ const el0 = temp0 ( )
308+ const el1 = temp0 ( )
309+ const slot1 = createSlot ( 'one' , { } , ( ) => template ( 'one fallback' ) ( ) )
310+ const slot2 = createSlot ( 'two' , { } , ( ) => template ( 'two fallback' ) ( ) )
311+ insert ( slot1 , el0 as any as ParentNode )
312+ insert ( slot2 , el1 as any as ParentNode )
313+ return [ el0 , el1 ]
314+ } )
315+
316+ const { host } = define ( ( ) => {
317+ return createComponent ( Child , { } , { } , ( ) => [
318+ flag1 . value
319+ ? { name : 'one' , fn : ( ) => template ( 'one content' ) ( ) }
320+ : { name : 'two' , fn : ( ) => template ( 'two content' ) ( ) } ,
321+ ] )
322+ } ) . render ( )
323+
324+ expect ( host . innerHTML ) . toBe (
325+ '<p>one content<!--slot--></p><p>two fallback<!--slot--></p>' ,
326+ )
327+
328+ flag1 . value = false
329+ await nextTick ( )
330+
331+ expect ( host . innerHTML ) . toBe (
332+ '<p>one fallback<!--slot--></p><p>two content<!--slot--></p>' ,
333+ )
334+
335+ flag1 . value = true
336+ await nextTick ( )
337+
338+ expect ( host . innerHTML ) . toBe (
339+ '<p>one content<!--slot--></p><p>two fallback<!--slot--></p>' ,
340+ )
341+ } )
342+
343+ test ( 'dynamic slot outlet should be updated correctly' , async ( ) => {
344+ const slotOutletName = ref ( 'one' )
345+
346+ const Child = defineComponent ( ( ) => {
347+ const temp0 = template ( '<p></p>' )
348+ const el0 = temp0 ( )
349+ const slot1 = createSlot (
350+ ( ) => slotOutletName . value ,
351+ { } ,
352+ ( ) => template ( 'fallback' ) ( ) ,
353+ )
354+ insert ( slot1 , el0 as any as ParentNode )
355+ return el0
356+ } )
357+
358+ const { host } = define ( ( ) => {
359+ return createComponent (
360+ Child ,
361+ { } ,
362+ {
363+ one : ( ) => template ( 'one content' ) ( ) ,
364+ two : ( ) => template ( 'two content' ) ( ) ,
365+ } ,
366+ )
367+ } ) . render ( )
368+
369+ expect ( host . innerHTML ) . toBe ( '<p>one content<!--slot--></p>' )
370+
371+ slotOutletName . value = 'two'
372+ await nextTick ( )
373+
374+ expect ( host . innerHTML ) . toBe ( '<p>two content<!--slot--></p>' )
375+
376+ slotOutletName . value = 'none'
377+ await nextTick ( )
378+
379+ expect ( host . innerHTML ) . toBe ( '<p>fallback<!--slot--></p>' )
380+ } )
381+ } )
197382} )
0 commit comments