@@ -22,6 +22,23 @@ describe('Error handling', () => {
22
22
} )
23
23
} )
24
24
25
+ // hooks that can return rejected promise
26
+ ; [
27
+ [ 'beforeCreate' , 'beforeCreate hook' ] ,
28
+ [ 'created' , 'created hook' ] ,
29
+ [ 'beforeMount' , 'beforeMount hook' ] ,
30
+ [ 'mounted' , 'mounted hook' ] ,
31
+ [ 'event' , 'event handler for "e"' ]
32
+ ] . forEach ( ( [ type , description ] ) => {
33
+ it ( `should recover from promise errors in ${ type } ` , done => {
34
+ createTestInstance ( components [ `${ type } Async` ] )
35
+ waitForUpdate ( ( ) => {
36
+ expect ( `Error in ${ description } ` ) . toHaveBeenWarned ( )
37
+ expect ( `Error: ${ type } ` ) . toHaveBeenWarned ( )
38
+ } ) . then ( done )
39
+ } )
40
+ } )
41
+
25
42
// error in mounted hook should affect neither child nor parent
26
43
it ( 'should recover from errors in mounted hook' , done => {
27
44
const vm = createTestInstance ( components . mounted )
@@ -45,6 +62,20 @@ describe('Error handling', () => {
45
62
} )
46
63
} )
47
64
65
+ // hooks that can return rejected promise
66
+ ; [
67
+ [ 'beforeUpdate' , 'beforeUpdate hook' ] ,
68
+ [ 'updated' , 'updated hook' ]
69
+ ] . forEach ( ( [ type , description ] ) => {
70
+ it ( `should recover from promise errors in ${ type } hook` , done => {
71
+ const vm = createTestInstance ( components [ `${ type } Async` ] )
72
+ assertBothInstancesActive ( vm ) . then ( ( ) => {
73
+ expect ( `Error in ${ description } ` ) . toHaveBeenWarned ( )
74
+ expect ( `Error: ${ type } ` ) . toHaveBeenWarned ( )
75
+ } ) . then ( done )
76
+ } )
77
+ } )
78
+
48
79
; [
49
80
[ 'beforeDestroy' , 'beforeDestroy hook' ] ,
50
81
[ 'destroyed' , 'destroyed hook' ] ,
@@ -62,6 +93,21 @@ describe('Error handling', () => {
62
93
} )
63
94
} )
64
95
96
+ ; [
97
+ [ 'beforeDestroy' , 'beforeDestroy hook' ] ,
98
+ [ 'destroyed' , 'destroyed hook' ]
99
+ ] . forEach ( ( [ type , description ] ) => {
100
+ it ( `should recover from promise errors in ${ type } hook` , done => {
101
+ const vm = createTestInstance ( components [ `${ type } Async` ] )
102
+ vm . ok = false
103
+ setTimeout ( ( ) => {
104
+ expect ( `Error in ${ description } ` ) . toHaveBeenWarned ( )
105
+ expect ( `Error: ${ type } ` ) . toHaveBeenWarned ( )
106
+ assertRootInstanceActive ( vm ) . then ( done )
107
+ } )
108
+ } )
109
+ } )
110
+
65
111
it ( 'should recover from errors in user watcher getter' , done => {
66
112
const vm = createTestInstance ( components . userWatcherGetter )
67
113
vm . n ++
@@ -152,6 +198,40 @@ describe('Error handling', () => {
152
198
expect ( vm . $el . textContent ) . toContain ( 'error in render' )
153
199
Vue . config . errorHandler = null
154
200
} )
201
+
202
+ // event handlers that can throw errors or return rejected promise
203
+ ; [
204
+ [ 'single handler' , '<div v-on:click="bork"></div>' ] ,
205
+ [ 'multiple handlers' , '<div v-on="{ click: [bork, function test() {}] }"></div>' ]
206
+ ] . forEach ( ( [ type , template ] ) => {
207
+ it ( `should recover from v-on errors for ${ type } registered` , ( ) => {
208
+ const vm = new Vue ( {
209
+ template,
210
+ methods : { bork ( ) { throw new Error ( 'v-on' ) } }
211
+ } ) . $mount ( )
212
+ document . body . appendChild ( vm . $el )
213
+ triggerEvent ( vm . $el , 'click' )
214
+ expect ( 'Error in v-on' ) . toHaveBeenWarned ( )
215
+ expect ( 'Error: v-on' ) . toHaveBeenWarned ( )
216
+ document . body . removeChild ( vm . $el )
217
+ } )
218
+
219
+ it ( `should recover from v-on async errors for ${ type } registered` , ( done ) => {
220
+ const vm = new Vue ( {
221
+ template,
222
+ methods : { bork ( ) {
223
+ return new Promise ( ( resolve , reject ) => reject ( new Error ( 'v-on async' ) ) )
224
+ } }
225
+ } ) . $mount ( )
226
+ document . body . appendChild ( vm . $el )
227
+ triggerEvent ( vm . $el , 'click' )
228
+ waitForUpdate ( ( ) => {
229
+ expect ( 'Error in v-on async' ) . toHaveBeenWarned ( )
230
+ expect ( 'Error: v-on async' ) . toHaveBeenWarned ( )
231
+ document . body . removeChild ( vm . $el )
232
+ } ) . then ( done )
233
+ } )
234
+ } )
155
235
} )
156
236
157
237
function createErrorTestComponents ( ) {
@@ -188,6 +268,16 @@ function createErrorTestComponents () {
188
268
throw new Error ( before )
189
269
}
190
270
271
+ const beforeCompAsync = components [ `${ before } Async` ] = {
272
+ props : [ 'n' ] ,
273
+ render ( h ) {
274
+ return h ( 'div' , this . n )
275
+ }
276
+ }
277
+ beforeCompAsync [ before ] = function ( ) {
278
+ return new Promise ( ( resolve , reject ) => reject ( new Error ( before ) ) )
279
+ }
280
+
191
281
// after
192
282
const after = hook . replace ( / e ? $ / , 'ed' )
193
283
const afterComp = components [ after ] = {
@@ -199,6 +289,16 @@ function createErrorTestComponents () {
199
289
afterComp [ after ] = function ( ) {
200
290
throw new Error ( after )
201
291
}
292
+
293
+ const afterCompAsync = components [ `${ after } Async` ] = {
294
+ props : [ 'n' ] ,
295
+ render ( h ) {
296
+ return h ( 'div' , this . n )
297
+ }
298
+ }
299
+ afterCompAsync [ after ] = function ( ) {
300
+ return new Promise ( ( resolve , reject ) => reject ( new Error ( after ) ) )
301
+ }
202
302
} )
203
303
204
304
// directive hooks errors
@@ -272,6 +372,18 @@ function createErrorTestComponents () {
272
372
}
273
373
}
274
374
375
+ components . eventAsync = {
376
+ beforeCreate ( ) {
377
+ this . $on ( 'e' , ( ) => new Promise ( ( resolve , reject ) => reject ( new Error ( 'event' ) ) ) )
378
+ } ,
379
+ mounted ( ) {
380
+ this . $emit ( 'e' )
381
+ } ,
382
+ render ( h ) {
383
+ return h ( 'div' )
384
+ }
385
+ }
386
+
275
387
return components
276
388
}
277
389
0 commit comments