test: tests for error handling
This commit is contained in:
parent
d5684e1a9d
commit
be28f976af
@ -1,17 +1,331 @@
|
|||||||
|
import {
|
||||||
|
onMounted,
|
||||||
|
onErrorCaptured,
|
||||||
|
render,
|
||||||
|
h,
|
||||||
|
nodeOps,
|
||||||
|
watch,
|
||||||
|
ref,
|
||||||
|
nextTick
|
||||||
|
} from '@vue/runtime-test'
|
||||||
|
|
||||||
describe('error handling', () => {
|
describe('error handling', () => {
|
||||||
test.todo('in lifecycle hooks')
|
test('propagtaion', () => {
|
||||||
|
const err = new Error('foo')
|
||||||
|
const fn = jest.fn()
|
||||||
|
|
||||||
test.todo('in onErrorCaptured')
|
const Comp = {
|
||||||
|
setup() {
|
||||||
|
onErrorCaptured((err, instance, info) => {
|
||||||
|
fn(err, info, 'root')
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
return () => h(Child)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
test.todo('in setup function')
|
const Child = {
|
||||||
|
setup() {
|
||||||
|
onErrorCaptured((err, instance, info) => {
|
||||||
|
fn(err, info, 'child')
|
||||||
|
})
|
||||||
|
return () => h(GrandChild)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
test.todo('in render function')
|
const GrandChild = {
|
||||||
|
setup() {
|
||||||
|
onMounted(() => {
|
||||||
|
throw err
|
||||||
|
})
|
||||||
|
return () => null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
test.todo('in watch (simple usage)')
|
render(h(Comp), nodeOps.createElement('div'))
|
||||||
|
expect(fn).toHaveBeenCalledTimes(2)
|
||||||
|
expect(fn).toHaveBeenCalledWith(err, 'mounted hook', 'root')
|
||||||
|
expect(fn).toHaveBeenCalledWith(err, 'mounted hook', 'child')
|
||||||
|
})
|
||||||
|
|
||||||
test.todo('in watch (with source)')
|
test('propagation stoppage', () => {
|
||||||
|
const err = new Error('foo')
|
||||||
|
const fn = jest.fn()
|
||||||
|
|
||||||
test.todo('in component event handler')
|
const Comp = {
|
||||||
|
setup() {
|
||||||
|
onErrorCaptured((err, instance, info) => {
|
||||||
|
fn(err, info, 'root')
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
return () => h(Child)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const Child = {
|
||||||
|
setup() {
|
||||||
|
onErrorCaptured((err, instance, info) => {
|
||||||
|
fn(err, info, 'child')
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
return () => h(GrandChild)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const GrandChild = {
|
||||||
|
setup() {
|
||||||
|
onMounted(() => {
|
||||||
|
throw err
|
||||||
|
})
|
||||||
|
return () => null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render(h(Comp), nodeOps.createElement('div'))
|
||||||
|
expect(fn).toHaveBeenCalledTimes(1)
|
||||||
|
expect(fn).toHaveBeenCalledWith(err, 'mounted hook', 'child')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('error thrown in onErrorCaptured', () => {
|
||||||
|
const err = new Error('foo')
|
||||||
|
const err2 = new Error('bar')
|
||||||
|
const fn = jest.fn()
|
||||||
|
|
||||||
|
const Comp = {
|
||||||
|
setup() {
|
||||||
|
onErrorCaptured((err, instance, info) => {
|
||||||
|
fn(err, info)
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
return () => h(Child)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const Child = {
|
||||||
|
setup() {
|
||||||
|
onErrorCaptured(() => {
|
||||||
|
throw err2
|
||||||
|
})
|
||||||
|
return () => h(GrandChild)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const GrandChild = {
|
||||||
|
setup() {
|
||||||
|
onMounted(() => {
|
||||||
|
throw err
|
||||||
|
})
|
||||||
|
return () => null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render(h(Comp), nodeOps.createElement('div'))
|
||||||
|
expect(fn).toHaveBeenCalledTimes(2)
|
||||||
|
expect(fn).toHaveBeenCalledWith(err, 'mounted hook')
|
||||||
|
expect(fn).toHaveBeenCalledWith(err2, 'errorCaptured hook')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('setup function', () => {
|
||||||
|
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() {
|
||||||
|
throw err
|
||||||
|
},
|
||||||
|
render() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
render(h(Comp), nodeOps.createElement('div'))
|
||||||
|
expect(fn).toHaveBeenCalledWith(err, 'setup function')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('in render function', () => {
|
||||||
|
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() {
|
||||||
|
return () => {
|
||||||
|
throw err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render(h(Comp), nodeOps.createElement('div'))
|
||||||
|
expect(fn).toHaveBeenCalledWith(err, 'render function')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('in watch (simple usage)', () => {
|
||||||
|
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() {
|
||||||
|
watch(() => {
|
||||||
|
throw err
|
||||||
|
})
|
||||||
|
return () => null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render(h(Comp), nodeOps.createElement('div'))
|
||||||
|
expect(fn).toHaveBeenCalledWith(err, 'watcher callback')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('in watch getter', () => {
|
||||||
|
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() {
|
||||||
|
watch(
|
||||||
|
() => {
|
||||||
|
throw err
|
||||||
|
},
|
||||||
|
() => {}
|
||||||
|
)
|
||||||
|
return () => null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render(h(Comp), nodeOps.createElement('div'))
|
||||||
|
expect(fn).toHaveBeenCalledWith(err, 'watcher getter')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('in watch callback', () => {
|
||||||
|
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() {
|
||||||
|
watch(
|
||||||
|
() => 1,
|
||||||
|
() => {
|
||||||
|
throw err
|
||||||
|
}
|
||||||
|
)
|
||||||
|
return () => null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render(h(Comp), nodeOps.createElement('div'))
|
||||||
|
expect(fn).toHaveBeenCalledWith(err, 'watcher callback')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('in watch cleanup', async () => {
|
||||||
|
const err = new Error('foo')
|
||||||
|
const count = ref(0)
|
||||||
|
const fn = jest.fn()
|
||||||
|
|
||||||
|
const Comp = {
|
||||||
|
setup() {
|
||||||
|
onErrorCaptured((err, instance, info) => {
|
||||||
|
fn(err, info)
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
return () => h(Child)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const Child = {
|
||||||
|
setup() {
|
||||||
|
watch(onCleanup => {
|
||||||
|
count.value
|
||||||
|
onCleanup(() => {
|
||||||
|
throw err
|
||||||
|
})
|
||||||
|
})
|
||||||
|
return () => null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render(h(Comp), nodeOps.createElement('div'))
|
||||||
|
|
||||||
|
count.value++
|
||||||
|
await nextTick()
|
||||||
|
expect(fn).toHaveBeenCalledWith(err, 'watcher cleanup function')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('in component event handler', () => {
|
||||||
|
const err = new Error('foo')
|
||||||
|
const fn = jest.fn()
|
||||||
|
|
||||||
|
const Comp = {
|
||||||
|
setup() {
|
||||||
|
onErrorCaptured((err, instance, info) => {
|
||||||
|
fn(err, info)
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
return () =>
|
||||||
|
h(Child, {
|
||||||
|
onFoo: () => {
|
||||||
|
throw err
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const Child = {
|
||||||
|
setup(props: any, { emit }: any) {
|
||||||
|
emit('foo')
|
||||||
|
return () => null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render(h(Comp), nodeOps.createElement('div'))
|
||||||
|
expect(fn).toHaveBeenCalledWith(err, 'component event handler')
|
||||||
|
})
|
||||||
|
|
||||||
// native event handler handling should be tested in respective renderers
|
// native event handler handling should be tested in respective renderers
|
||||||
})
|
})
|
||||||
|
@ -2,7 +2,8 @@ import {
|
|||||||
ComponentInstance,
|
ComponentInstance,
|
||||||
LifecycleHooks,
|
LifecycleHooks,
|
||||||
currentInstance,
|
currentInstance,
|
||||||
setCurrentInstance
|
setCurrentInstance,
|
||||||
|
ComponentRenderProxy
|
||||||
} from './component'
|
} from './component'
|
||||||
import { callWithAsyncErrorHandling, ErrorTypeStrings } from './errorHandling'
|
import { callWithAsyncErrorHandling, ErrorTypeStrings } from './errorHandling'
|
||||||
import { warn } from './warning'
|
import { warn } from './warning'
|
||||||
@ -92,7 +93,11 @@ export function onRenderTracked(
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function onErrorCaptured(
|
export function onErrorCaptured(
|
||||||
hook: Function,
|
hook: (
|
||||||
|
err: Error,
|
||||||
|
instance: ComponentRenderProxy | null,
|
||||||
|
info: string
|
||||||
|
) => boolean | void,
|
||||||
target: ComponentInstance | null = currentInstance
|
target: ComponentInstance | null = currentInstance
|
||||||
) {
|
) {
|
||||||
injectHook(LifecycleHooks.ERROR_CAPTURED, hook, target)
|
injectHook(LifecycleHooks.ERROR_CAPTURED, hook, target)
|
||||||
|
@ -443,6 +443,5 @@ function hasPropsChanged(prevProps: Data, nextProps: Data): boolean {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
console.log(111)
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
@ -88,7 +88,7 @@ export function handleError(
|
|||||||
errorCapturedHooks[i](
|
errorCapturedHooks[i](
|
||||||
err,
|
err,
|
||||||
instance && instance.renderProxy,
|
instance && instance.renderProxy,
|
||||||
contextVNode
|
ErrorTypeStrings[type]
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
return
|
return
|
||||||
|
Loading…
Reference in New Issue
Block a user