test: more coverage for error handling

This commit is contained in:
Evan You 2019-08-30 16:20:32 -04:00
parent be28f976af
commit 6801885f57
2 changed files with 79 additions and 7 deletions

View File

@ -6,10 +6,13 @@ import {
nodeOps,
watch,
ref,
nextTick
nextTick,
mockWarn
} from '@vue/runtime-test'
describe('error handling', () => {
mockWarn()
test('propagtaion', () => {
const err = new Error('foo')
const fn = jest.fn()
@ -86,6 +89,35 @@ describe('error handling', () => {
expect(fn).toHaveBeenCalledWith(err, 'mounted hook', 'child')
})
test('async error handling', async () => {
const err = new Error('foo')
const fn = jest.fn()
const Comp = {
setup() {
onErrorCaptured((err, instance, info) => {
fn(err, info)
return true
})
return () => h(Child)
}
}
const Child = {
setup() {
onMounted(async () => {
throw err
})
},
render() {}
}
render(h(Comp), nodeOps.createElement('div'))
expect(fn).not.toHaveBeenCalled()
await new Promise(r => setTimeout(r))
expect(fn).toHaveBeenCalledWith(err, 'mounted hook')
})
test('error thrown in onErrorCaptured', () => {
const err = new Error('foo')
const err2 = new Error('bar')
@ -327,5 +359,36 @@ describe('error handling', () => {
expect(fn).toHaveBeenCalledWith(err, 'component event handler')
})
it('should warn unhandled', () => {
const onError = jest.spyOn(console, 'error')
onError.mockImplementation(() => {})
const err = new Error('foo')
const fn = jest.fn()
const Comp = {
setup() {
onErrorCaptured((err, instance, info) => {
fn(err, info)
})
return () => h(Child)
}
}
const Child = {
setup() {
throw err
},
render() {}
}
render(h(Comp), nodeOps.createElement('div'))
expect(fn).toHaveBeenCalledWith(err, 'setup function')
expect(
`Unhandled error during execution of setup function`
).toHaveBeenWarned()
expect(onError).toHaveBeenCalledWith(err)
onError.mockRestore()
})
// native event handler handling should be tested in respective renderers
})

View File

@ -296,15 +296,24 @@ export function setupStatefulComponent(instance: ComponentInstance) {
// setup returned an inline render function
instance.render = setupResult
} else {
// setup returned bindings.
// assuming a render function compiled from template is present.
instance.data = reactive(setupResult || {})
if (__DEV__ && !Component.render) {
if (__DEV__) {
if (!Component.render) {
warn(
`Component is missing render function. Either provide a template or ` +
`return a render function from setup().`
)
}
if (
setupResult &&
typeof setupResult.then === 'function' &&
typeof setupResult.catch === 'function'
) {
warn(`setup() returned a Promise. setup() cannot be async.`)
}
}
// setup returned bindings.
// assuming a render function compiled from template is present.
instance.data = reactive(setupResult || {})
instance.render = (Component.render || NOOP) as RenderFunction
}
} else {