Skip to content

Commit a3a3e80

Browse files
authored
fix: exclude Options API components with setup() from the proxy mock workaround
* test: add failing global mocks scenario * fix: exclude OAPI components with setup() from the proxy mock workaround * refactor: wrap <script setup> assertion into isScriptSetup util and use it - drop hasSetupState check, if a component is <script setup> it always has setup state - do note that isScriptSetup and hasSetupState check for different things. I tried to replaced hasSetupScript with isScriptSetup but some specs around expose started to fail so we are required to keep it for now.
1 parent 925f0ab commit a3a3e80

File tree

3 files changed

+41
-2
lines changed

3 files changed

+41
-2
lines changed

src/mount.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ import { MountingOptions, Slot } from './types'
3333
import {
3434
getComponentsFromStubs,
3535
getDirectivesFromStubs,
36-
hasSetupState,
36+
isScriptSetup,
3737
isFunctionalComponent,
3838
isObject,
3939
isObjectComponent,
@@ -482,7 +482,10 @@ export function mount(
482482
// otherwise we run into a proxy set error
483483
// due to https://github.com/vuejs/core/commit/f73925d76a76ee259749b8b48cb68895f539a00f#diff-ea4d1ddabb7e22e17e80ada458eef70679af4005df2a1a6b73418fec897603ceR404
484484
// introduced in Vue v3.2.45
485-
if (hasSetupState(this)) {
485+
// Also ensures not to include option API components in this block
486+
// since they can also have setup state but need to be patched using
487+
// the regular method.
488+
if (isScriptSetup(this)) {
486489
// add the mocks to setupState
487490
for (const [k, v] of Object.entries(
488491
global.mocks as { [key: string]: any }

src/utils.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,7 @@ export function getDirectivesFromStubs(
185185
.map(([key, value]) => [key.substring(1), value])
186186
) as Record<string, Directive>
187187
}
188+
188189
export function hasSetupState(
189190
vm: ComponentPublicInstance
190191
): vm is ComponentPublicInstance & {
@@ -195,3 +196,13 @@ export function hasSetupState(
195196
(vm.$ as unknown as { devtoolsRawSetupState: any }).devtoolsRawSetupState
196197
)
197198
}
199+
200+
export function isScriptSetup(
201+
vm: ComponentPublicInstance
202+
): vm is ComponentPublicInstance & {
203+
$: { setupState: Record<string, unknown> }
204+
} {
205+
return (
206+
vm && (vm.$ as unknown as { setupState: any }).setupState.__isScriptSetup
207+
)
208+
}

tests/mountingOptions/mocks.spec.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,4 +101,29 @@ describe('mocks', () => {
101101
expect(wrapper.text()).toContain('hello')
102102
expect(wrapper.text()).toContain('mocked')
103103
})
104+
105+
it('mocks a global function in an option component which includes the setup() option', () => {
106+
const ComponentWithI18nAndSetupOption = defineComponent({
107+
setup: () => ({
108+
hello: 'hello'
109+
}),
110+
template: `
111+
<div>{{ hello }}</div>
112+
<!-- this emulates components that use a global function like $t for i18n -->
113+
<!-- this function can be mocked using global.mocks -->
114+
<div>{{ $t('world') }}</div>
115+
`
116+
})
117+
118+
const wrapper = mount(ComponentWithI18nAndSetupOption, {
119+
global: {
120+
mocks: {
121+
$t: () => 'mocked'
122+
}
123+
}
124+
})
125+
126+
expect(wrapper.text()).toContain('hello')
127+
expect(wrapper.text()).toContain('mocked')
128+
})
104129
})

0 commit comments

Comments
 (0)