@@ -25,6 +25,7 @@ type MockFunctionState = {
2525 instances : Array < any > ,
2626 calls : Array < Array < any >> ,
2727 returnValues : Array < any > ,
28+ thrownErrors : Array < any > ,
2829 timestamps : Array < number > ,
2930} ;
3031
@@ -282,6 +283,7 @@ class ModuleMockerClass {
282283 calls : [ ] ,
283284 instances : [ ] ,
284285 returnValues : [ ] ,
286+ thrownErrors : [ ] ,
285287 timestamps : [ ] ,
286288 } ;
287289 }
@@ -319,67 +321,85 @@ class ModuleMockerClass {
319321 mockState . calls . push ( Array . prototype . slice . call ( arguments ) ) ;
320322 mockState . timestamps . push ( Date . now ( ) ) ;
321323
322- // The bulk of the implementation is wrapped in an immediately executed
323- // arrow function so the return value of the mock function can
324- // be easily captured and recorded, despite the many separate return
325- // points within the logic.
326- const finalReturnValue = ( ( ) => {
327- if ( this instanceof f ) {
328- // This is probably being called as a constructor
329- prototypeSlots . forEach ( slot => {
330- // Copy prototype methods to the instance to make
331- // it easier to interact with mock instance call and
332- // return values
333- if ( prototype [ slot ] . type === 'function' ) {
334- const protoImpl = this [ slot ] ;
335- this [ slot ] = mocker . generateFromMetadata ( prototype [ slot ] ) ;
336- this [ slot ] . _protoImpl = protoImpl ;
337- }
338- } ) ;
339-
340- // Run the mock constructor implementation
341- const mockImpl = mockConfig . specificMockImpls . length
342- ? mockConfig . specificMockImpls . shift ( )
343- : mockConfig . mockImpl ;
344- return mockImpl && mockImpl . apply ( this , arguments ) ;
345- }
346-
347- const returnValue = mockConfig . defaultReturnValue ;
348- // If return value is last set, either specific or default, i.e.
349- // mockReturnValueOnce()/mockReturnValue() is called and no
350- // mockImplementationOnce()/mockImplementation() is called after that.
351- // use the set return value.
352- if ( mockConfig . specificReturnValues . length ) {
353- return mockConfig . specificReturnValues . shift ( ) ;
354- }
324+ // Will be set to the return value of the mock if an error is not thrown
325+ let finalReturnValue ;
326+ // Will be set to the error that is thrown by the mock (if it throws)
327+ let thrownError ;
328+
329+ try {
330+ // The bulk of the implementation is wrapped in an immediately
331+ // executed arrow function so the return value of the mock function
332+ // can be easily captured and recorded, despite the many separate
333+ // return points within the logic.
334+ finalReturnValue = ( ( ) => {
335+ if ( this instanceof f ) {
336+ // This is probably being called as a constructor
337+ prototypeSlots . forEach ( slot => {
338+ // Copy prototype methods to the instance to make
339+ // it easier to interact with mock instance call and
340+ // return values
341+ if ( prototype [ slot ] . type === 'function' ) {
342+ const protoImpl = this [ slot ] ;
343+ this [ slot ] = mocker . generateFromMetadata ( prototype [ slot ] ) ;
344+ this [ slot ] . _protoImpl = protoImpl ;
345+ }
346+ } ) ;
347+
348+ // Run the mock constructor implementation
349+ const mockImpl = mockConfig . specificMockImpls . length
350+ ? mockConfig . specificMockImpls . shift ( )
351+ : mockConfig . mockImpl ;
352+ return mockImpl && mockImpl . apply ( this , arguments ) ;
353+ }
355354
356- if ( mockConfig . isReturnValueLastSet ) {
357- return mockConfig . defaultReturnValue ;
358- }
355+ const returnValue = mockConfig . defaultReturnValue ;
356+ // If return value is last set, either specific or default, i.e.
357+ // mockReturnValueOnce()/mockReturnValue() is called and no
358+ // mockImplementationOnce()/mockImplementation() is called after
359+ // that.
360+ // use the set return value.
361+ if ( mockConfig . specificReturnValues . length ) {
362+ return mockConfig . specificReturnValues . shift ( ) ;
363+ }
359364
360- // If mockImplementationOnce()/mockImplementation() is last set,
361- // or specific return values are used up, use the mock implementation.
362- let specificMockImpl ;
363- if ( returnValue === undefined ) {
364- specificMockImpl = mockConfig . specificMockImpls . shift ( ) ;
365- if ( specificMockImpl === undefined ) {
366- specificMockImpl = mockConfig . mockImpl ;
365+ if ( mockConfig . isReturnValueLastSet ) {
366+ return mockConfig . defaultReturnValue ;
367367 }
368- if ( specificMockImpl ) {
369- return specificMockImpl . apply ( this , arguments ) ;
368+
369+ // If mockImplementationOnce()/mockImplementation() is last set,
370+ // or specific return values are used up, use the mock
371+ // implementation.
372+ let specificMockImpl ;
373+ if ( returnValue === undefined ) {
374+ specificMockImpl = mockConfig . specificMockImpls . shift ( ) ;
375+ if ( specificMockImpl === undefined ) {
376+ specificMockImpl = mockConfig . mockImpl ;
377+ }
378+ if ( specificMockImpl ) {
379+ return specificMockImpl . apply ( this , arguments ) ;
380+ }
370381 }
371- }
372382
373- // Otherwise use prototype implementation
374- if ( returnValue === undefined && f . _protoImpl ) {
375- return f . _protoImpl . apply ( this , arguments ) ;
376- }
383+ // Otherwise use prototype implementation
384+ if ( returnValue === undefined && f . _protoImpl ) {
385+ return f . _protoImpl . apply ( this , arguments ) ;
386+ }
377387
378- return returnValue ;
379- } ) ( ) ;
388+ return returnValue ;
389+ } ) ( ) ;
390+ } catch ( error ) {
391+ // Store the thrown error so we can record it, then re-throw it.
392+ thrownError = error ;
393+ throw error ;
394+ } finally {
395+ // Record the return value of the mock function.
396+ // If the mock threw an error, then the value will be undefined.
397+ mockState . returnValues . push ( finalReturnValue ) ;
398+ // Record the error thrown by the mock function.
399+ // If no error was thrown, then the value will be udnefiend.
400+ mockState . thrownErrors . push ( thrownError ) ;
401+ }
380402
381- // Record the return value of the mock function before returning it.
382- mockState . returnValues . push ( finalReturnValue ) ;
383403 return finalReturnValue ;
384404 } , metadata . length || 0 ) ;
385405
0 commit comments