Skip to content

Commit bbde386

Browse files
xiaodong2008sxzz
andauthored
test(runtime-vapor): add apiSetupContext unit test (#237)
Co-authored-by: 三咲智子 Kevin Deng <[email protected]>
1 parent bc04592 commit bbde386

File tree

3 files changed

+221
-3
lines changed

3 files changed

+221
-3
lines changed

packages/compiler-vapor/src/generate.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -123,10 +123,10 @@ export function generate(
123123
push('}')
124124
}
125125

126-
const deligates = genDeligates(context)
126+
const delegates = genDelegates(context)
127127
const templates = genTemplates(ir.template, context)
128128
const imports = genHelperImports(context)
129-
const preamble = imports + templates + deligates
129+
const preamble = imports + templates + delegates
130130

131131
const newlineCount = [...preamble].filter(c => c === '\n').length
132132
if (newlineCount && !inline) {
@@ -148,7 +148,7 @@ export function generate(
148148
}
149149
}
150150

151-
function genDeligates({ delegates, vaporHelper }: CodegenContext) {
151+
function genDelegates({ delegates, vaporHelper }: CodegenContext) {
152152
return delegates.size
153153
? genCall(
154154
vaporHelper('delegateEvents'),

packages/runtime-vapor/__tests__/_utils.ts

+5
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@ export function makeRender<Component = ObjectComponent | SetupFn>(
5252
return res()
5353
}
5454

55+
function html() {
56+
return host.innerHTML
57+
}
58+
5559
const res = () => ({
5660
component,
5761
host,
@@ -61,6 +65,7 @@ export function makeRender<Component = ObjectComponent | SetupFn>(
6165
mount,
6266
render,
6367
resetHost,
68+
html,
6469
})
6570

6671
return res()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,213 @@
1+
import {
2+
createComponent,
3+
createSlot,
4+
createTextNode,
5+
defineComponent,
6+
delegate,
7+
delegateEvents,
8+
insert,
9+
nextTick,
10+
reactive,
11+
ref,
12+
renderEffect,
13+
setDynamicProps,
14+
template,
15+
watchEffect,
16+
} from '../src'
17+
import { makeRender } from './_utils'
18+
19+
const define = makeRender()
20+
21+
describe('api: setup context', () => {
22+
it('should expose return values to template render context', () => {
23+
const { html } = define({
24+
setup() {
25+
return {
26+
ref: ref('foo'),
27+
object: reactive({ msg: 'bar' }),
28+
value: 'baz',
29+
}
30+
},
31+
render(ctx) {
32+
return createTextNode([`${ctx.ref} ${ctx.object.msg} ${ctx.value}`])
33+
},
34+
}).render()
35+
expect(html()).toMatch(`foo bar baz`)
36+
})
37+
38+
it('should support returning render function', () => {
39+
const { html } = define({
40+
setup() {
41+
return createTextNode([`hello`])
42+
},
43+
}).render()
44+
expect(html()).toMatch(`hello`)
45+
})
46+
47+
it('props', async () => {
48+
const count = ref(0)
49+
let dummy
50+
51+
const Child = defineComponent({
52+
props: { count: Number },
53+
setup(props) {
54+
watchEffect(() => {
55+
dummy = props.count
56+
})
57+
return createTextNode(() => [props.count])
58+
},
59+
})
60+
61+
const { html } = define({
62+
render: () => createComponent(Child, { count: () => count.value }),
63+
}).render()
64+
65+
expect(html()).toMatch(`0`)
66+
67+
count.value++
68+
await nextTick()
69+
expect(dummy).toBe(1)
70+
expect(html()).toMatch(`1`)
71+
})
72+
73+
it('context.attrs', async () => {
74+
const toggle = ref(true)
75+
76+
const Child = defineComponent({
77+
inheritAttrs: false,
78+
setup(props, { attrs }) {
79+
const el = document.createElement('div')
80+
renderEffect(() => {
81+
setDynamicProps(el, attrs)
82+
})
83+
return el
84+
},
85+
})
86+
87+
const { html } = define({
88+
render: () =>
89+
createComponent(Child, () =>
90+
toggle.value ? { id: 'foo' } : { class: 'baz' },
91+
),
92+
}).render()
93+
94+
expect(html()).toMatch(`<div id="foo"></div>`)
95+
96+
toggle.value = false
97+
await nextTick()
98+
expect(html()).toMatch(`<div class="baz"></div>`)
99+
})
100+
101+
// #4161
102+
it('context.attrs in child component slots', async () => {
103+
const toggle = ref(true)
104+
105+
const Wrapper = defineComponent({
106+
setup(_, { slots }) {
107+
return slots.default!()
108+
},
109+
})
110+
111+
const Child = defineComponent({
112+
inheritAttrs: false,
113+
setup(_: any, { attrs }: any) {
114+
return createComponent(Wrapper, null, {
115+
default: () => {
116+
const n0 = template('<div>')() as HTMLDivElement
117+
renderEffect(() => {
118+
setDynamicProps(n0, attrs)
119+
})
120+
return n0
121+
},
122+
})
123+
},
124+
})
125+
126+
const { html } = define({
127+
render: () =>
128+
createComponent(Child, () =>
129+
toggle.value ? { id: 'foo' } : { class: 'baz' },
130+
),
131+
}).render()
132+
133+
expect(html()).toMatch(`<div id="foo"></div>`)
134+
135+
// should update even though it's not reactive
136+
toggle.value = false
137+
await nextTick()
138+
expect(html()).toMatch(`<div class="baz"></div>`)
139+
})
140+
141+
it('context.slots', async () => {
142+
const id = ref('foo')
143+
144+
const Child = defineComponent({
145+
render() {
146+
return [createSlot('foo'), createSlot('bar')]
147+
},
148+
})
149+
150+
const { html } = define({
151+
render() {
152+
return createComponent(Child, null, null, [
153+
() => ({
154+
name: 'foo',
155+
fn: () => createTextNode(() => [id.value]),
156+
}),
157+
() => ({
158+
name: 'bar',
159+
fn: () => createTextNode(['bar']),
160+
}),
161+
])
162+
},
163+
}).render()
164+
165+
expect(html()).toMatch(`foo<!--slot-->bar<!--slot-->`)
166+
167+
id.value = 'baz'
168+
await nextTick()
169+
expect(html()).toMatch(`baz<!--slot-->bar<!--slot-->`)
170+
})
171+
172+
it('context.emit', async () => {
173+
const count = ref(0)
174+
const spy = vi.fn()
175+
176+
delegateEvents('click')
177+
178+
const Child = defineComponent({
179+
props: {
180+
count: { type: Number, default: 1 },
181+
},
182+
setup(props, { emit }) {
183+
const n0 = template('<div>')() as HTMLDivElement
184+
delegate(n0, 'click', () => () => {
185+
emit('inc', props.count + 1)
186+
})
187+
insert(
188+
createTextNode(() => [props.count]),
189+
n0,
190+
)
191+
return n0
192+
},
193+
})
194+
195+
const { host, html } = define({
196+
render: () =>
197+
createComponent(Child, {
198+
count: () => count.value,
199+
onInc: () => (newVal: number) => {
200+
spy()
201+
count.value = newVal
202+
},
203+
}),
204+
}).render()
205+
206+
expect(html()).toMatch(`<div>0</div>`)
207+
;(host.children[0] as HTMLDivElement).click()
208+
209+
expect(spy).toHaveBeenCalled()
210+
await nextTick()
211+
expect(html()).toMatch(`<div>1</div>`)
212+
})
213+
})

0 commit comments

Comments
 (0)