fix(runtime-core): allow spying on proxy methods (#4216)
Since Jest v26.6.1, the mock method changed (see this commit 30e8020362
) to rely on `Object.defineProperty` in some cases.
This breaks spying on proxy's methods, because even if Jest is properly calling `Object.defineProperty`, the cached value in the `get` section of the proxy is never updated, and the spy is in fact never used.
This is easily reproducible as vue-next already uses a version of jest with these changes.
This is blocking projects (like vue-test-utils-next and vue-cli) to update to recent Jest versions.
This commit adds a `defineProperty` method to the proxy handler, that properly updates the defined value in the cache.
This commit is contained in:
parent
436c500d2c
commit
8457d8b980
@ -214,6 +214,74 @@ describe('component: proxy', () => {
|
|||||||
])
|
])
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('allow updating proxy with Object.defineProperty', () => {
|
||||||
|
let instanceProxy: any
|
||||||
|
const Comp = {
|
||||||
|
render() {},
|
||||||
|
setup() {
|
||||||
|
return {
|
||||||
|
isDisplayed: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
instanceProxy = this
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const app = createApp(Comp)
|
||||||
|
|
||||||
|
app.mount(nodeOps.createElement('div'))
|
||||||
|
|
||||||
|
Object.defineProperty(instanceProxy, 'isDisplayed', { value: false })
|
||||||
|
|
||||||
|
expect(instanceProxy.isDisplayed).toBe(false)
|
||||||
|
|
||||||
|
Object.defineProperty(instanceProxy, 'isDisplayed', { value: true })
|
||||||
|
|
||||||
|
expect(instanceProxy.isDisplayed).toBe(true)
|
||||||
|
|
||||||
|
Object.defineProperty(instanceProxy, 'isDisplayed', {
|
||||||
|
get() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(instanceProxy.isDisplayed).toBe(false)
|
||||||
|
|
||||||
|
Object.defineProperty(instanceProxy, 'isDisplayed', {
|
||||||
|
get() {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(instanceProxy.isDisplayed).toBe(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('allow spying on proxy methods', () => {
|
||||||
|
let instanceProxy: any
|
||||||
|
const Comp = {
|
||||||
|
render() {},
|
||||||
|
setup() {
|
||||||
|
return {
|
||||||
|
toggle() {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
instanceProxy = this
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const app = createApp(Comp)
|
||||||
|
|
||||||
|
app.mount(nodeOps.createElement('div'))
|
||||||
|
|
||||||
|
const spy = jest.spyOn(instanceProxy, 'toggle')
|
||||||
|
|
||||||
|
instanceProxy.toggle()
|
||||||
|
|
||||||
|
expect(spy).toHaveBeenCalled()
|
||||||
|
})
|
||||||
|
|
||||||
// #864
|
// #864
|
||||||
test('should not warn declared but absent props', () => {
|
test('should not warn declared but absent props', () => {
|
||||||
const Comp = {
|
const Comp = {
|
||||||
|
@ -397,8 +397,10 @@ export const PublicInstanceProxyHandlers: ProxyHandler<any> = {
|
|||||||
const { data, setupState, ctx } = instance
|
const { data, setupState, ctx } = instance
|
||||||
if (setupState !== EMPTY_OBJ && hasOwn(setupState, key)) {
|
if (setupState !== EMPTY_OBJ && hasOwn(setupState, key)) {
|
||||||
setupState[key] = value
|
setupState[key] = value
|
||||||
|
return true
|
||||||
} else if (data !== EMPTY_OBJ && hasOwn(data, key)) {
|
} else if (data !== EMPTY_OBJ && hasOwn(data, key)) {
|
||||||
data[key] = value
|
data[key] = value
|
||||||
|
return true
|
||||||
} else if (hasOwn(instance.props, key)) {
|
} else if (hasOwn(instance.props, key)) {
|
||||||
__DEV__ &&
|
__DEV__ &&
|
||||||
warn(
|
warn(
|
||||||
@ -445,6 +447,19 @@ export const PublicInstanceProxyHandlers: ProxyHandler<any> = {
|
|||||||
hasOwn(publicPropertiesMap, key) ||
|
hasOwn(publicPropertiesMap, key) ||
|
||||||
hasOwn(appContext.config.globalProperties, key)
|
hasOwn(appContext.config.globalProperties, key)
|
||||||
)
|
)
|
||||||
|
},
|
||||||
|
|
||||||
|
defineProperty(
|
||||||
|
target: ComponentRenderContext,
|
||||||
|
key: string,
|
||||||
|
descriptor: PropertyDescriptor
|
||||||
|
) {
|
||||||
|
if (descriptor.get != null) {
|
||||||
|
this.set!(target, key, descriptor.get(), null)
|
||||||
|
} else if (descriptor.value != null) {
|
||||||
|
this.set!(target, key, descriptor.value, null)
|
||||||
|
}
|
||||||
|
return Reflect.defineProperty(target, key, descriptor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user