Skip to content

Commit bf1fbe9

Browse files
committed
fix: expose props on vm for script setup components
Fixes #1863 It turns out `vm` is not enough, and we need to proxy to `vm.$.ctx` which contains the props as well.
1 parent 87625ec commit bf1fbe9

File tree

3 files changed

+31
-1
lines changed

3 files changed

+31
-1
lines changed

src/vueWrapper.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,9 @@ function createVMProxy<T extends ComponentPublicInstance>(
3535
if (key in setupState) {
3636
return Reflect.get(setupState, key, receiver)
3737
} else {
38-
return (vm as any)[key]
38+
// vm.$.ctx is the internal context of the vm
39+
// with all variables, methods and props
40+
return (vm as any).$.ctx[key]
3941
}
4042
},
4143
set(vm, key, value, receiver) {
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<script setup lang="ts">
2+
import { ref } from 'vue';
3+
4+
const props = defineProps<{ count: number }>()
5+
const internalCount = ref(props.count);
6+
const inc = () => {
7+
internalCount.value++
8+
}
9+
</script>
10+
11+
<template>
12+
<button @click="inc">{{ internalCount }}</button>
13+
</template>

tests/expose.spec.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import DefineExpose from './components/DefineExpose.vue'
66
import DefineExposeWithRenderFunction from './components/DefineExposeWithRenderFunction.vue'
77
import ScriptSetupExpose from './components/ScriptSetup_Expose.vue'
88
import ScriptSetup from './components/ScriptSetup.vue'
9+
import ScriptSetupWithProps from './components/ScriptSetupWithProps.vue'
910

1011
describe('expose', () => {
1112
it('access vm on simple components', async () => {
@@ -76,4 +77,18 @@ describe('expose', () => {
7677
expect(spiedIncrement).toHaveBeenCalled()
7778
expect(wrapper.html()).toContain('0')
7879
})
80+
81+
it('access props on vm with <script setup>', async () => {
82+
const wrapper = mount(ScriptSetupWithProps, {
83+
props: {
84+
count: 2
85+
}
86+
})
87+
// make sure that props are accessible on wrapper.vm
88+
expect(wrapper.vm.count).toBe(2)
89+
expect(wrapper.html()).toContain('2')
90+
91+
await wrapper.find('button').trigger('click')
92+
expect(wrapper.html()).toContain('3')
93+
})
7994
})

0 commit comments

Comments
 (0)