Skip to content

Commit

Permalink
fix: exclude Options API components with setup() from the proxy mock …
Browse files Browse the repository at this point in the history
…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.
  • Loading branch information
renatodeleao committed Jan 4, 2023
1 parent 925f0ab commit a3a3e80
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 2 deletions.
7 changes: 5 additions & 2 deletions src/mount.ts
Expand Up @@ -33,7 +33,7 @@ import { MountingOptions, Slot } from './types'
import {
getComponentsFromStubs,
getDirectivesFromStubs,
hasSetupState,
isScriptSetup,
isFunctionalComponent,
isObject,
isObjectComponent,
Expand Down Expand Up @@ -482,7 +482,10 @@ export function mount(
// otherwise we run into a proxy set error
// due to https://github.com/vuejs/core/commit/f73925d76a76ee259749b8b48cb68895f539a00f#diff-ea4d1ddabb7e22e17e80ada458eef70679af4005df2a1a6b73418fec897603ceR404
// introduced in Vue v3.2.45
if (hasSetupState(this)) {
// Also ensures not to include option API components in this block
// since they can also have setup state but need to be patched using
// the regular method.
if (isScriptSetup(this)) {
// add the mocks to setupState
for (const [k, v] of Object.entries(
global.mocks as { [key: string]: any }
Expand Down
11 changes: 11 additions & 0 deletions src/utils.ts
Expand Up @@ -185,6 +185,7 @@ export function getDirectivesFromStubs(
.map(([key, value]) => [key.substring(1), value])
) as Record<string, Directive>
}

export function hasSetupState(
vm: ComponentPublicInstance
): vm is ComponentPublicInstance & {
Expand All @@ -195,3 +196,13 @@ export function hasSetupState(
(vm.$ as unknown as { devtoolsRawSetupState: any }).devtoolsRawSetupState
)
}

export function isScriptSetup(
vm: ComponentPublicInstance
): vm is ComponentPublicInstance & {
$: { setupState: Record<string, unknown> }
} {
return (
vm && (vm.$ as unknown as { setupState: any }).setupState.__isScriptSetup
)
}
25 changes: 25 additions & 0 deletions tests/mountingOptions/mocks.spec.ts
Expand Up @@ -101,4 +101,29 @@ describe('mocks', () => {
expect(wrapper.text()).toContain('hello')
expect(wrapper.text()).toContain('mocked')
})

it('mocks a global function in an option component which includes the setup() option', () => {
const ComponentWithI18nAndSetupOption = defineComponent({
setup: () => ({
hello: 'hello'
}),
template: `
<div>{{ hello }}</div>
<!-- this emulates components that use a global function like $t for i18n -->
<!-- this function can be mocked using global.mocks -->
<div>{{ $t('world') }}</div>
`
})

const wrapper = mount(ComponentWithI18nAndSetupOption, {
global: {
mocks: {
$t: () => 'mocked'
}
}
})

expect(wrapper.text()).toContain('hello')
expect(wrapper.text()).toContain('mocked')
})
})

0 comments on commit a3a3e80

Please sign in to comment.