fix: add warnings (#82)
* fix: add warnings - invalid watch handler path - attempting to mutate readonly computed value - attempt of mutating public property - attempt of mutating prop * fix: more descriptive warnings + details * fix: test apiOptions warnings * fix: update warning in componentProxy * fix: update warnings in componentProxy & apiOptions * fix: update warning in componentProxy * fix: implemented tests for componentProxy * fix: remove comment + small refactor
This commit is contained in:
parent
def27239bd
commit
0177355242
@ -8,7 +8,8 @@ import {
|
||||
nextTick,
|
||||
renderToString,
|
||||
ref,
|
||||
createComponent
|
||||
createComponent,
|
||||
mockWarn
|
||||
} from '@vue/runtime-test'
|
||||
|
||||
describe('api: options', () => {
|
||||
@ -505,4 +506,37 @@ describe('api: options', () => {
|
||||
await nextTick()
|
||||
expect(serializeInner(root)).toBe(`<div>1,1,3</div>`)
|
||||
})
|
||||
|
||||
describe('warnings', () => {
|
||||
mockWarn()
|
||||
|
||||
test('Expected a function as watch handler', () => {
|
||||
const Comp = {
|
||||
watch: {
|
||||
foo: 'notExistingMethod'
|
||||
},
|
||||
render() {}
|
||||
}
|
||||
|
||||
const root = nodeOps.createElement('div')
|
||||
render(h(Comp), root)
|
||||
|
||||
expect(
|
||||
'Invalid watch handler specified by key "notExistingMethod"'
|
||||
).toHaveBeenWarned()
|
||||
})
|
||||
|
||||
test('Invalid watch option', () => {
|
||||
const Comp = {
|
||||
watch: { foo: true },
|
||||
render() {}
|
||||
}
|
||||
|
||||
const root = nodeOps.createElement('div')
|
||||
// @ts-ignore
|
||||
render(h(Comp), root)
|
||||
|
||||
expect('Invalid watch option: "foo"').toHaveBeenWarned()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
40
packages/runtime-core/__tests__/componentProxy.spec.ts
Normal file
40
packages/runtime-core/__tests__/componentProxy.spec.ts
Normal file
@ -0,0 +1,40 @@
|
||||
import { createApp, nodeOps, mockWarn } from '@vue/runtime-test'
|
||||
|
||||
const createTestInstance = (props?: any) => {
|
||||
const component = {
|
||||
render() {}
|
||||
}
|
||||
const root = nodeOps.createElement('div')
|
||||
return createApp().mount(component, root, props)
|
||||
}
|
||||
|
||||
describe('component proxy', () => {
|
||||
describe('warnings', () => {
|
||||
mockWarn()
|
||||
|
||||
test('Attempting to mutate public property', () => {
|
||||
const app = createTestInstance()
|
||||
|
||||
try {
|
||||
app.$props = { foo: 'bar' }
|
||||
} catch {
|
||||
expect(
|
||||
'Attempting to mutate public property "$props". ' +
|
||||
'Properties starting with $ are reserved and readonly.'
|
||||
).toHaveBeenWarned()
|
||||
}
|
||||
})
|
||||
|
||||
test('Attempting to mutate prop', () => {
|
||||
const app = createTestInstance({ foo: 'foo' })
|
||||
|
||||
try {
|
||||
app.foo = 'bar'
|
||||
} catch {
|
||||
expect(
|
||||
'Attempting to mutate prop "foo". Props are readonly.'
|
||||
).toHaveBeenWarned()
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
@ -267,7 +267,7 @@ export function applyOptions(
|
||||
if (isFunction(handler)) {
|
||||
watch(getter, handler as WatchHandler)
|
||||
} else if (__DEV__) {
|
||||
// TODO warn invalid watch handler path
|
||||
warn(`Invalid watch handler specified by key "${raw}"`, handler)
|
||||
}
|
||||
} else if (isFunction(raw)) {
|
||||
watch(getter, raw.bind(ctx))
|
||||
@ -275,7 +275,7 @@ export function applyOptions(
|
||||
// TODO 2.x compat
|
||||
watch(getter, raw.handler.bind(ctx), raw)
|
||||
} else if (__DEV__) {
|
||||
// TODO warn invalid watch options
|
||||
warn(`Invalid watch option: "${key}"`)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ import { instanceWatch } from './apiWatch'
|
||||
import { EMPTY_OBJ, hasOwn, globalsWhitelist } from '@vue/shared'
|
||||
import { ExtractComputedReturns } from './apiOptions'
|
||||
import { UnwrapRef } from '@vue/reactivity'
|
||||
import { warn } from './warning'
|
||||
|
||||
// public properties exposed on the proxy, which is used as the render context
|
||||
// in templates (as `this` in the render option)
|
||||
@ -91,10 +92,16 @@ export const PublicInstanceProxyHandlers = {
|
||||
} else if (hasOwn(renderContext, key)) {
|
||||
renderContext[key] = value
|
||||
} else if (key[0] === '$' && key.slice(1) in target) {
|
||||
// TODO warn attempt of mutating public property
|
||||
__DEV__ &&
|
||||
warn(
|
||||
`Attempting to mutate public property "${key}". ` +
|
||||
`Properties starting with $ are reserved and readonly.`,
|
||||
target
|
||||
)
|
||||
return false
|
||||
} else if (key in target.props) {
|
||||
// TODO warn attempt of mutating prop
|
||||
__DEV__ &&
|
||||
warn(`Attempting to mutate prop "${key}". Props are readonly.`, target)
|
||||
return false
|
||||
} else {
|
||||
target.user[key] = value
|
||||
|
Loading…
Reference in New Issue
Block a user