1. /** @flow */
    
  2. 
    
  3. // This test harness mounts each test app as a separate root to test multi-root applications.
    
  4. 
    
  5. import {createElement} from 'react';
    
  6. import {createRoot} from 'react-dom/client';
    
  7. import {render, unmountComponentAtNode} from 'react-dom';
    
  8. import DeeplyNestedComponents from './DeeplyNestedComponents';
    
  9. import Iframe from './Iframe';
    
  10. import EditableProps from './EditableProps';
    
  11. import ElementTypes from './ElementTypes';
    
  12. import Hydration from './Hydration';
    
  13. import InspectableElements from './InspectableElements';
    
  14. import ReactNativeWeb from './ReactNativeWeb';
    
  15. import ToDoList from './ToDoList';
    
  16. import Toggle from './Toggle';
    
  17. import ErrorBoundaries from './ErrorBoundaries';
    
  18. import PartiallyStrictApp from './PartiallyStrictApp';
    
  19. import SuspenseTree from './SuspenseTree';
    
  20. import {ignoreErrors, ignoreLogs, ignoreWarnings} from './console';
    
  21. 
    
  22. import './styles.css';
    
  23. 
    
  24. // DevTools intentionally tests compatibility with certain legacy APIs.
    
  25. // Suppress their error messages in the local dev shell,
    
  26. // because they might mask other more serious error messages.
    
  27. ignoreErrors([
    
  28.   'Warning: Legacy context API',
    
  29.   'Warning: Unsafe lifecycle methods',
    
  30.   'Warning: %s is deprecated in StrictMode.', // findDOMNode
    
  31.   'Warning: ReactDOM.render is no longer supported in React 18',
    
  32. ]);
    
  33. ignoreWarnings(['Warning: componentWillReceiveProps has been renamed']);
    
  34. ignoreLogs([]);
    
  35. 
    
  36. const unmountFunctions: Array<() => void | boolean> = [];
    
  37. 
    
  38. function createContainer() {
    
  39.   const container = document.createElement('div');
    
  40. 
    
  41.   ((document.body: any): HTMLBodyElement).appendChild(container);
    
  42. 
    
  43.   return container;
    
  44. }
    
  45. 
    
  46. function mountApp(App: () => React$Node) {
    
  47.   const container = createContainer();
    
  48. 
    
  49.   const root = createRoot(container);
    
  50.   root.render(createElement(App));
    
  51. 
    
  52.   unmountFunctions.push(() => root.unmount());
    
  53. }
    
  54. 
    
  55. // $FlowFixMe[missing-local-annot]
    
  56. function mountStrictApp(App) {
    
  57.   function StrictRoot() {
    
  58.     return createElement(App);
    
  59.   }
    
  60. 
    
  61.   const container = createContainer();
    
  62. 
    
  63.   const root = createRoot(container, {unstable_strictMode: true});
    
  64.   root.render(createElement(StrictRoot));
    
  65. 
    
  66.   unmountFunctions.push(() => root.unmount());
    
  67. }
    
  68. 
    
  69. function mountLegacyApp(App: () => React$Node) {
    
  70.   function LegacyRender() {
    
  71.     return createElement(App);
    
  72.   }
    
  73. 
    
  74.   const container = createContainer();
    
  75. 
    
  76.   render(createElement(LegacyRender), container);
    
  77. 
    
  78.   unmountFunctions.push(() => unmountComponentAtNode(container));
    
  79. }
    
  80. 
    
  81. function mountTestApp() {
    
  82.   mountStrictApp(ToDoList);
    
  83.   mountApp(InspectableElements);
    
  84.   mountApp(Hydration);
    
  85.   mountApp(ElementTypes);
    
  86.   mountApp(EditableProps);
    
  87.   mountApp(ReactNativeWeb);
    
  88.   mountApp(Toggle);
    
  89.   mountApp(ErrorBoundaries);
    
  90.   mountApp(SuspenseTree);
    
  91.   mountApp(DeeplyNestedComponents);
    
  92.   mountApp(Iframe);
    
  93.   mountLegacyApp(PartiallyStrictApp);
    
  94. }
    
  95. 
    
  96. function unmountTestApp() {
    
  97.   unmountFunctions.forEach(fn => fn());
    
  98. }
    
  99. 
    
  100. mountTestApp();
    
  101. 
    
  102. window.parent.mountTestApp = mountTestApp;
    
  103. window.parent.unmountTestApp = unmountTestApp;