Skip to content

Commit d0cc4b3

Browse files
authored
test(runtime-core): add tests for componentSlots (vuejs#1940)
1 parent 97bc30e commit d0cc4b3

File tree

1 file changed

+196
-2
lines changed

1 file changed

+196
-2
lines changed

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

Lines changed: 196 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,201 @@
1-
import { ref, render, h, nodeOps, nextTick } from '@vue/runtime-test'
1+
import {
2+
ref,
3+
render,
4+
h,
5+
nodeOps,
6+
nextTick,
7+
getCurrentInstance
8+
} from '@vue/runtime-test'
9+
import { normalizeVNode } from '../src/vnode'
10+
import { createSlots } from '../src/helpers/createSlots'
211

312
describe('component: slots', () => {
4-
// TODO more tests for slots normalization etc.
13+
function renderWithSlots(slots: any): any {
14+
let instance: any
15+
const Comp = {
16+
render() {
17+
instance = getCurrentInstance()
18+
return h('div')
19+
}
20+
}
21+
22+
render(h(Comp, null, slots), nodeOps.createElement('div'))
23+
return instance
24+
}
25+
26+
test('initSlots: instance.slots should be set correctly', () => {
27+
const { slots } = renderWithSlots({ _: 1 })
28+
expect(slots).toMatchObject({ _: 1 })
29+
})
30+
31+
test('initSlots: should normalize object slots (when value is null, string, array)', () => {
32+
const { slots } = renderWithSlots({
33+
_inner: '_inner',
34+
foo: null,
35+
header: 'header',
36+
footer: ['f1', 'f2']
37+
})
38+
39+
expect(
40+
'[Vue warn]: Non-function value encountered for slot "header". Prefer function slots for better performance.'
41+
).toHaveBeenWarned()
42+
43+
expect(
44+
'[Vue warn]: Non-function value encountered for slot "footer". Prefer function slots for better performance.'
45+
).toHaveBeenWarned()
46+
47+
expect(slots).not.toHaveProperty('_inner')
48+
expect(slots).not.toHaveProperty('foo')
49+
expect(slots.header()).toMatchObject([normalizeVNode('header')])
50+
expect(slots.footer()).toMatchObject([
51+
normalizeVNode('f1'),
52+
normalizeVNode('f2')
53+
])
54+
})
55+
56+
test('initSlots: should normalize object slots (when value is function)', () => {
57+
let proxy: any
58+
const Comp = {
59+
render() {
60+
proxy = getCurrentInstance()
61+
return h('div')
62+
}
63+
}
64+
65+
render(
66+
h(Comp, null, {
67+
header: () => 'header'
68+
}),
69+
nodeOps.createElement('div')
70+
)
71+
72+
expect(proxy.slots.header()).toMatchObject([normalizeVNode('header')])
73+
})
74+
75+
test('initSlots: instance.slots should be set correctly (when vnode.shapeFlag is not SLOTS_CHILDREN)', () => {
76+
const { slots } = renderWithSlots([h('span')])
77+
78+
expect(
79+
'[Vue warn]: Non-function value encountered for default slot. Prefer function slots for better performance.'
80+
).toHaveBeenWarned()
81+
82+
expect(slots.default()).toMatchObject([normalizeVNode(h('span'))])
83+
})
84+
85+
test('updateSlots: instance.slots should be update correctly (when slotType is number)', async () => {
86+
const flag1 = ref(true)
87+
88+
let instance: any
89+
const Child = () => {
90+
instance = getCurrentInstance()
91+
return 'child'
92+
}
93+
94+
const Comp = {
95+
setup() {
96+
return () => [
97+
h(
98+
Child,
99+
null,
100+
createSlots({ _: 2 as any }, [
101+
flag1.value
102+
? {
103+
name: 'one',
104+
fn: () => [h('span')]
105+
}
106+
: {
107+
name: 'two',
108+
fn: () => [h('div')]
109+
}
110+
])
111+
)
112+
]
113+
}
114+
}
115+
render(h(Comp), nodeOps.createElement('div'))
116+
117+
expect(instance.slots).toHaveProperty('one')
118+
expect(instance.slots).not.toHaveProperty('two')
119+
120+
flag1.value = false
121+
await nextTick()
122+
123+
expect(instance.slots).not.toHaveProperty('one')
124+
expect(instance.slots).toHaveProperty('two')
125+
})
126+
127+
test('updateSlots: instance.slots should be update correctly (when slotType is null)', async () => {
128+
const flag1 = ref(true)
129+
130+
let instance: any
131+
const Child = () => {
132+
instance = getCurrentInstance()
133+
return 'child'
134+
}
135+
136+
const oldSlots = {
137+
header: 'header'
138+
}
139+
const newSlots = {
140+
footer: 'footer'
141+
}
142+
143+
const Comp = {
144+
setup() {
145+
return () => [
146+
h(Child, { n: flag1.value }, flag1.value ? oldSlots : newSlots)
147+
]
148+
}
149+
}
150+
render(h(Comp), nodeOps.createElement('div'))
151+
152+
expect(instance.slots).toHaveProperty('header')
153+
expect(instance.slots).not.toHaveProperty('footer')
154+
155+
flag1.value = false
156+
await nextTick()
157+
158+
expect(
159+
'[Vue warn]: Non-function value encountered for slot "header". Prefer function slots for better performance.'
160+
).toHaveBeenWarned()
161+
162+
expect(
163+
'[Vue warn]: Non-function value encountered for slot "footer". Prefer function slots for better performance.'
164+
).toHaveBeenWarned()
165+
166+
expect(instance.slots).not.toHaveProperty('header')
167+
expect(instance.slots.footer()).toMatchObject([normalizeVNode('footer')])
168+
})
169+
170+
test('updateSlots: instance.slots should be update correctly (when vnode.shapeFlag is not SLOTS_CHILDREN)', async () => {
171+
const flag1 = ref(true)
172+
173+
let instance: any
174+
const Child = () => {
175+
instance = getCurrentInstance()
176+
return 'child'
177+
}
178+
179+
const Comp = {
180+
setup() {
181+
return () => [
182+
h(Child, { n: flag1.value }, flag1.value ? ['header'] : ['footer'])
183+
]
184+
}
185+
}
186+
render(h(Comp), nodeOps.createElement('div'))
187+
188+
expect(instance.slots.default()).toMatchObject([normalizeVNode('header')])
189+
190+
flag1.value = false
191+
await nextTick()
192+
193+
expect(
194+
'[Vue warn]: Non-function value encountered for default slot. Prefer function slots for better performance.'
195+
).toHaveBeenWarned()
196+
197+
expect(instance.slots.default()).toMatchObject([normalizeVNode('footer')])
198+
})
5199

6200
test('should respect $stable flag', async () => {
7201
const flag1 = ref(1)

0 commit comments

Comments
 (0)