1. 'use strict';
    
  2. 
    
  3. const fs = require('fs');
    
  4. const nodePath = require('path');
    
  5. const inlinedHostConfigs = require('../shared/inlinedHostConfigs');
    
  6. 
    
  7. function resolveEntryFork(resolvedEntry, isFBBundle) {
    
  8.   // Pick which entry point fork to use:
    
  9.   // .modern.fb.js
    
  10.   // .classic.fb.js
    
  11.   // .fb.js
    
  12.   // .stable.js
    
  13.   // .experimental.js
    
  14.   // .js
    
  15. 
    
  16.   if (isFBBundle) {
    
  17.     if (__EXPERIMENTAL__) {
    
  18.       // We can't currently use the true modern entry point because too many tests fail.
    
  19.       // TODO: Fix tests to not use ReactDOM.render or gate them. Then we can remove this.
    
  20.       return resolvedEntry;
    
  21.     }
    
  22.     const resolvedFBEntry = resolvedEntry.replace(
    
  23.       '.js',
    
  24.       __EXPERIMENTAL__ ? '.modern.fb.js' : '.classic.fb.js'
    
  25.     );
    
  26.     if (fs.existsSync(resolvedFBEntry)) {
    
  27.       return resolvedFBEntry;
    
  28.     }
    
  29.     const resolvedGenericFBEntry = resolvedEntry.replace('.js', '.fb.js');
    
  30.     if (fs.existsSync(resolvedGenericFBEntry)) {
    
  31.       return resolvedGenericFBEntry;
    
  32.     }
    
  33.     // Even if it's a FB bundle we fallthrough to pick stable or experimental if we don't have an FB fork.
    
  34.   }
    
  35.   const resolvedForkedEntry = resolvedEntry.replace(
    
  36.     '.js',
    
  37.     __EXPERIMENTAL__ ? '.experimental.js' : '.stable.js'
    
  38.   );
    
  39.   if (fs.existsSync(resolvedForkedEntry)) {
    
  40.     return resolvedForkedEntry;
    
  41.   }
    
  42.   // Just use the plain .js one.
    
  43.   return resolvedEntry;
    
  44. }
    
  45. 
    
  46. function mockReact() {
    
  47.   jest.mock('react', () => {
    
  48.     const resolvedEntryPoint = resolveEntryFork(
    
  49.       require.resolve('react'),
    
  50.       global.__WWW__
    
  51.     );
    
  52.     return jest.requireActual(resolvedEntryPoint);
    
  53.   });
    
  54. }
    
  55. 
    
  56. // When we want to unmock React we really need to mock it again.
    
  57. global.__unmockReact = mockReact;
    
  58. 
    
  59. mockReact();
    
  60. 
    
  61. jest.mock('react/react.shared-subset', () => {
    
  62.   const resolvedEntryPoint = resolveEntryFork(
    
  63.     require.resolve('react/src/ReactSharedSubset'),
    
  64.     global.__WWW__
    
  65.   );
    
  66.   return jest.requireActual(resolvedEntryPoint);
    
  67. });
    
  68. 
    
  69. // When testing the custom renderer code path through `react-reconciler`,
    
  70. // turn the export into a function, and use the argument as host config.
    
  71. const shimHostConfigPath = 'react-reconciler/src/ReactFiberConfig';
    
  72. jest.mock('react-reconciler', () => {
    
  73.   return config => {
    
  74.     jest.mock(shimHostConfigPath, () => config);
    
  75.     return jest.requireActual('react-reconciler');
    
  76.   };
    
  77. });
    
  78. const shimServerStreamConfigPath = 'react-server/src/ReactServerStreamConfig';
    
  79. const shimServerConfigPath = 'react-server/src/ReactFizzConfig';
    
  80. const shimFlightServerConfigPath = 'react-server/src/ReactFlightServerConfig';
    
  81. jest.mock('react-server', () => {
    
  82.   return config => {
    
  83.     jest.mock(shimServerStreamConfigPath, () => config);
    
  84.     jest.mock(shimServerConfigPath, () => config);
    
  85.     return jest.requireActual('react-server');
    
  86.   };
    
  87. });
    
  88. jest.mock('react-server/flight', () => {
    
  89.   return config => {
    
  90.     jest.mock(shimServerStreamConfigPath, () => config);
    
  91.     jest.mock(shimServerConfigPath, () => config);
    
  92.     jest.mock('react-server/src/ReactFlightServerConfigBundlerCustom', () => ({
    
  93.       isClientReference: config.isClientReference,
    
  94.       isServerReference: config.isServerReference,
    
  95.       getClientReferenceKey: config.getClientReferenceKey,
    
  96.       resolveClientReferenceMetadata: config.resolveClientReferenceMetadata,
    
  97.     }));
    
  98.     jest.mock(shimFlightServerConfigPath, () =>
    
  99.       jest.requireActual(
    
  100.         'react-server/src/forks/ReactFlightServerConfig.custom'
    
  101.       )
    
  102.     );
    
  103.     return jest.requireActual('react-server/flight');
    
  104.   };
    
  105. });
    
  106. const shimFlightClientConfigPath = 'react-client/src/ReactFlightClientConfig';
    
  107. jest.mock('react-client/flight', () => {
    
  108.   return config => {
    
  109.     jest.mock(shimFlightClientConfigPath, () => config);
    
  110.     return jest.requireActual('react-client/flight');
    
  111.   };
    
  112. });
    
  113. 
    
  114. const configPaths = [
    
  115.   'react-reconciler/src/ReactFiberConfig',
    
  116.   'react-client/src/ReactFlightClientConfig',
    
  117.   'react-server/src/ReactServerStreamConfig',
    
  118.   'react-server/src/ReactFizzConfig',
    
  119.   'react-server/src/ReactFlightServerConfig',
    
  120. ];
    
  121. 
    
  122. function mockAllConfigs(rendererInfo) {
    
  123.   configPaths.forEach(path => {
    
  124.     // We want the reconciler to pick up the host config for this renderer.
    
  125.     jest.mock(path, () => {
    
  126.       let idx = path.lastIndexOf('/');
    
  127.       let forkPath = path.slice(0, idx) + '/forks' + path.slice(idx);
    
  128.       let parts = rendererInfo.shortName.split('-');
    
  129.       while (parts.length) {
    
  130.         try {
    
  131.           const candidate = `${forkPath}.${parts.join('-')}.js`;
    
  132.           fs.statSync(nodePath.join(process.cwd(), 'packages', candidate));
    
  133.           return jest.requireActual(candidate);
    
  134.         } catch (error) {
    
  135.           if (error.code !== 'ENOENT') {
    
  136.             throw error;
    
  137.           }
    
  138.           // try without a part
    
  139.         }
    
  140.         parts.pop();
    
  141.       }
    
  142.       throw new Error(
    
  143.         `Expected to find a fork for ${path} but did not find one.`
    
  144.       );
    
  145.     });
    
  146.   });
    
  147. }
    
  148. 
    
  149. // But for inlined host configs (such as React DOM, Native, etc), we
    
  150. // mock their named entry points to establish a host config mapping.
    
  151. inlinedHostConfigs.forEach(rendererInfo => {
    
  152.   if (rendererInfo.shortName === 'custom') {
    
  153.     // There is no inline entry point for the custom renderers.
    
  154.     // Instead, it's handled by the generic `react-reconciler` entry point above.
    
  155.     return;
    
  156.   }
    
  157.   rendererInfo.entryPoints.forEach(entryPoint => {
    
  158.     jest.mock(entryPoint, () => {
    
  159.       mockAllConfigs(rendererInfo);
    
  160.       const resolvedEntryPoint = resolveEntryFork(
    
  161.         require.resolve(entryPoint),
    
  162.         global.__WWW__
    
  163.       );
    
  164.       return jest.requireActual(resolvedEntryPoint);
    
  165.     });
    
  166.   });
    
  167. });
    
  168. 
    
  169. // Make it possible to import this module inside
    
  170. // the React package itself.
    
  171. jest.mock('shared/ReactSharedInternals', () =>
    
  172.   jest.requireActual('react/src/ReactSharedInternalsClient')
    
  173. );
    
  174. 
    
  175. // Make it possible to import this module inside
    
  176. // the ReactDOM package itself.
    
  177. jest.mock('shared/ReactDOMSharedInternals', () =>
    
  178.   jest.requireActual('react-dom/src/ReactDOMSharedInternals')
    
  179. );
    
  180. 
    
  181. jest.mock('scheduler', () => jest.requireActual('scheduler/unstable_mock'));