1. /**
    
  2.  * Copyright (c) Meta Platforms, Inc. and affiliates.
    
  3.  *
    
  4.  * This source code is licensed under the MIT license found in the
    
  5.  * LICENSE file in the root directory of this source tree.
    
  6.  *
    
  7.  * @emails react-core
    
  8.  * @jest-environment node
    
  9.  */
    
  10. 
    
  11. // This is a regression test for https://github.com/facebook/react/issues/13188.
    
  12. // It reproduces a combination of conditions that led to a problem.
    
  13. 
    
  14. if (global.window) {
    
  15.   throw new Error('This test must run in a Node environment.');
    
  16. }
    
  17. 
    
  18. // The issue only reproduced when React was loaded before JSDOM.
    
  19. const React = require('react');
    
  20. const ReactDOM = require('react-dom');
    
  21. 
    
  22. // Initialize JSDOM separately.
    
  23. // We don't use our normal JSDOM setup because we want to load React first.
    
  24. const {JSDOM} = require('jsdom');
    
  25. global.requestAnimationFrame = setTimeout;
    
  26. global.cancelAnimationFrame = clearTimeout;
    
  27. const jsdom = new JSDOM(`<div id="app-root"></div>`);
    
  28. global.window = jsdom.window;
    
  29. global.document = jsdom.window.document;
    
  30. global.navigator = jsdom.window.navigator;
    
  31. 
    
  32. class Bad extends React.Component {
    
  33.   componentDidUpdate() {
    
  34.     throw new Error('no');
    
  35.   }
    
  36.   render() {
    
  37.     return null;
    
  38.   }
    
  39. }
    
  40. 
    
  41. describe('ReactErrorLoggingRecovery', () => {
    
  42.   const originalConsoleError = console.error;
    
  43. 
    
  44.   beforeEach(() => {
    
  45.     console.error = error => {
    
  46.       if (
    
  47.         typeof error === 'string' &&
    
  48.         error.includes('ReactDOM.render is no longer supported in React 18')
    
  49.       ) {
    
  50.         // Ignore legacy root deprecation warning
    
  51.         return;
    
  52.       }
    
  53.       throw new Error('Buggy console.error');
    
  54.     };
    
  55.   });
    
  56. 
    
  57.   afterEach(() => {
    
  58.     console.error = originalConsoleError;
    
  59.   });
    
  60. 
    
  61.   it('should recover from errors in console.error', function () {
    
  62.     const div = document.createElement('div');
    
  63.     let didCatch = false;
    
  64.     try {
    
  65.       ReactDOM.render(<Bad />, div);
    
  66.       ReactDOM.render(<Bad />, div);
    
  67.     } catch (e) {
    
  68.       expect(e.message).toBe('no');
    
  69.       didCatch = true;
    
  70.     }
    
  71.     expect(didCatch).toBe(true);
    
  72.     ReactDOM.render(<span>Hello</span>, div);
    
  73.     expect(div.firstChild.textContent).toBe('Hello');
    
  74. 
    
  75.     // Verify the console.error bug is surfaced
    
  76.     expect(() => {
    
  77.       jest.runAllTimers();
    
  78.     }).toThrow('Buggy console.error');
    
  79.   });
    
  80. });