@@ -341,6 +341,45 @@ describe('ErrorBoundary', () => {
341
341
expect ( cause . message ) . toEqual ( thirdError . message ) ;
342
342
} ) ;
343
343
344
+ it ( 'handles when `error.cause` is recursive' , ( ) => {
345
+ const mockOnError = jest . fn ( ) ;
346
+
347
+ function CustomBam ( ) : JSX . Element {
348
+ const firstError = new Error ( 'bam' ) ;
349
+ const secondError = new Error ( 'bam2' ) ;
350
+ // @ts -ignore Need to set cause on error
351
+ firstError . cause = secondError ;
352
+ // @ts -ignore Need to set cause on error
353
+ secondError . cause = firstError ;
354
+ throw firstError ;
355
+ }
356
+
357
+ render (
358
+ < TestApp fallback = { < p > You have hit an error</ p > } onError = { mockOnError } errorComp = { < CustomBam /> } >
359
+ < h1 > children</ h1 >
360
+ </ TestApp > ,
361
+ ) ;
362
+
363
+ expect ( mockOnError ) . toHaveBeenCalledTimes ( 0 ) ;
364
+ expect ( mockCaptureException ) . toHaveBeenCalledTimes ( 0 ) ;
365
+
366
+ const btn = screen . getByTestId ( 'errorBtn' ) ;
367
+ fireEvent . click ( btn ) ;
368
+
369
+ expect ( mockCaptureException ) . toHaveBeenCalledTimes ( 1 ) ;
370
+ expect ( mockCaptureException ) . toHaveBeenLastCalledWith ( expect . any ( Error ) , {
371
+ contexts : { react : { componentStack : expect . any ( String ) } } ,
372
+ } ) ;
373
+
374
+ expect ( mockOnError . mock . calls [ 0 ] [ 0 ] ) . toEqual ( mockCaptureException . mock . calls [ 0 ] [ 0 ] ) ;
375
+
376
+ const error = mockCaptureException . mock . calls [ 0 ] [ 0 ] ;
377
+ const cause = error . cause ;
378
+ // We need to make sure that recursive error.cause does not cause infinite loop
379
+ expect ( cause . stack ) . not . toEqual ( mockCaptureException . mock . calls [ 0 ] [ 1 ] . contexts . react . componentStack ) ;
380
+ expect ( cause . name ) . not . toContain ( 'React ErrorBoundary' ) ;
381
+ } ) ;
382
+
344
383
it ( 'calls `beforeCapture()` when an error occurs' , ( ) => {
345
384
const mockBeforeCapture = jest . fn ( ) ;
346
385
0 commit comments