1. describe('ErrorBoundaryReconciliation', () => {
    
  2.   let BrokenRender;
    
  3.   let DidCatchErrorBoundary;
    
  4.   let GetDerivedErrorBoundary;
    
  5.   let React;
    
  6.   let ReactFeatureFlags;
    
  7.   let ReactTestRenderer;
    
  8.   let span;
    
  9.   let act;
    
  10. 
    
  11.   beforeEach(() => {
    
  12.     jest.resetModules();
    
  13. 
    
  14.     ReactFeatureFlags = require('shared/ReactFeatureFlags');
    
  15. 
    
  16.     ReactFeatureFlags.replayFailedUnitOfWorkWithInvokeGuardedCallback = false;
    
  17.     ReactTestRenderer = require('react-test-renderer');
    
  18.     React = require('react');
    
  19.     act = require('internal-test-utils').act;
    
  20.     DidCatchErrorBoundary = class extends React.Component {
    
  21.       state = {error: null};
    
  22.       componentDidCatch(error) {
    
  23.         this.setState({error});
    
  24.       }
    
  25.       render() {
    
  26.         return this.state.error
    
  27.           ? React.createElement(this.props.fallbackTagName, {
    
  28.               prop: 'ErrorBoundary',
    
  29.             })
    
  30.           : this.props.children;
    
  31.       }
    
  32.     };
    
  33. 
    
  34.     GetDerivedErrorBoundary = class extends React.Component {
    
  35.       state = {error: null};
    
  36.       static getDerivedStateFromError(error) {
    
  37.         return {error};
    
  38.       }
    
  39.       render() {
    
  40.         return this.state.error
    
  41.           ? React.createElement(this.props.fallbackTagName, {
    
  42.               prop: 'ErrorBoundary',
    
  43.             })
    
  44.           : this.props.children;
    
  45.       }
    
  46.     };
    
  47. 
    
  48.     const InvalidType = undefined;
    
  49.     BrokenRender = ({fail}) =>
    
  50.       fail ? <InvalidType /> : <span prop="BrokenRender" />;
    
  51.   });
    
  52. 
    
  53.   [true, false].forEach(isConcurrent => {
    
  54.     async function sharedTest(ErrorBoundary, fallbackTagName) {
    
  55.       let renderer;
    
  56. 
    
  57.       await act(() => {
    
  58.         renderer = ReactTestRenderer.create(
    
  59.           <ErrorBoundary fallbackTagName={fallbackTagName}>
    
  60.             <BrokenRender fail={false} />
    
  61.           </ErrorBoundary>,
    
  62.           {unstable_isConcurrent: isConcurrent},
    
  63.         );
    
  64.       });
    
  65.       expect(renderer).toMatchRenderedOutput(<span prop="BrokenRender" />);
    
  66. 
    
  67.       await expect(async () => {
    
  68.         await act(() => {
    
  69.           renderer.update(
    
  70.             <ErrorBoundary fallbackTagName={fallbackTagName}>
    
  71.               <BrokenRender fail={true} />
    
  72.             </ErrorBoundary>,
    
  73.           );
    
  74.         });
    
  75.       }).toErrorDev(isConcurrent ? ['invalid', 'invalid'] : ['invalid']);
    
  76.       const Fallback = fallbackTagName;
    
  77.       expect(renderer).toMatchRenderedOutput(<Fallback prop="ErrorBoundary" />);
    
  78.     }
    
  79. 
    
  80.     describe(isConcurrent ? 'concurrent' : 'sync', () => {
    
  81.       it('componentDidCatch can recover by rendering an element of the same type', () =>
    
  82.         sharedTest(DidCatchErrorBoundary, 'span'));
    
  83. 
    
  84.       it('componentDidCatch can recover by rendering an element of a different type', () =>
    
  85.         sharedTest(DidCatchErrorBoundary, 'div'));
    
  86. 
    
  87.       it('getDerivedStateFromError can recover by rendering an element of the same type', () =>
    
  88.         sharedTest(GetDerivedErrorBoundary, 'span'));
    
  89. 
    
  90.       it('getDerivedStateFromError can recover by rendering an element of a different type', () =>
    
  91.         sharedTest(GetDerivedErrorBoundary, 'div'));
    
  92.     });
    
  93.   });
    
  94. });