Skip to content

Commit f47bd32

Browse files
committed
test: createSlot
1 parent 9afaf0d commit f47bd32

File tree

2 files changed

+192
-7
lines changed

2 files changed

+192
-7
lines changed

packages/runtime-vapor/__tests__/componentSlots.spec.ts

+190-5
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,10 @@ import {
88
getCurrentInstance,
99
insert,
1010
nextTick,
11+
prepend,
1112
ref,
13+
renderEffect,
14+
setText,
1215
template,
1316
} from '../src'
1417
import { 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
})

packages/runtime-vapor/src/componentSlots.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ export function createSlot(
103103
}
104104
}
105105

106-
const getName = isDynamicName ? name : () => name
106+
const getSlot = isDynamicName ? () => slots[name()] : () => slots[name]
107107
const anchor = __DEV__ ? createComment('slot') : createTextNode()
108108
const fragment: Fragment = {
109109
nodes: [],
@@ -113,7 +113,7 @@ export function createSlot(
113113

114114
// TODO lifecycle hooks
115115
renderEffect(() => {
116-
if ((branch = slots[getName()] || fallback) !== oldBranch) {
116+
if ((branch = getSlot() || fallback) !== oldBranch) {
117117
parent ||= anchor.parentNode
118118
if (block) {
119119
scope!.stop()

0 commit comments

Comments
 (0)