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.  */
    
  9. 
    
  10. 'use strict';
    
  11. 
    
  12. // Don't wait before processing work on the server.
    
  13. // TODO: we can replace this with FlightServer.act().
    
  14. global.setImmediate = cb => cb();
    
  15. 
    
  16. let clientExports;
    
  17. let turbopackMap;
    
  18. let turbopackModules;
    
  19. let turbopackModuleLoading;
    
  20. let React;
    
  21. let ReactDOMServer;
    
  22. let ReactServerDOMServer;
    
  23. let ReactServerDOMClient;
    
  24. let Stream;
    
  25. let use;
    
  26. 
    
  27. describe('ReactFlightDOMNode', () => {
    
  28.   beforeEach(() => {
    
  29.     jest.resetModules();
    
  30. 
    
  31.     // Simulate the condition resolution
    
  32.     jest.mock('react', () => require('react/react.shared-subset'));
    
  33.     jest.mock('react-server-dom-turbopack/server', () =>
    
  34.       require('react-server-dom-turbopack/server.node'),
    
  35.     );
    
  36.     ReactServerDOMServer = require('react-server-dom-turbopack/server');
    
  37. 
    
  38.     const TurbopackMock = require('./utils/TurbopackMock');
    
  39.     clientExports = TurbopackMock.clientExports;
    
  40.     turbopackMap = TurbopackMock.turbopackMap;
    
  41.     turbopackModules = TurbopackMock.turbopackModules;
    
  42.     turbopackModuleLoading = TurbopackMock.moduleLoading;
    
  43. 
    
  44.     jest.resetModules();
    
  45.     __unmockReact();
    
  46.     jest.unmock('react-server-dom-turbopack/server');
    
  47.     jest.mock('react-server-dom-turbopack/client', () =>
    
  48.       require('react-server-dom-turbopack/client.node'),
    
  49.     );
    
  50. 
    
  51.     React = require('react');
    
  52.     ReactDOMServer = require('react-dom/server.node');
    
  53.     ReactServerDOMClient = require('react-server-dom-turbopack/client');
    
  54.     Stream = require('stream');
    
  55.     use = React.use;
    
  56.   });
    
  57. 
    
  58.   function readResult(stream) {
    
  59.     return new Promise((resolve, reject) => {
    
  60.       let buffer = '';
    
  61.       const writable = new Stream.PassThrough();
    
  62.       writable.setEncoding('utf8');
    
  63.       writable.on('data', chunk => {
    
  64.         buffer += chunk;
    
  65.       });
    
  66.       writable.on('error', error => {
    
  67.         reject(error);
    
  68.       });
    
  69.       writable.on('end', () => {
    
  70.         resolve(buffer);
    
  71.       });
    
  72.       stream.pipe(writable);
    
  73.     });
    
  74.   }
    
  75. 
    
  76.   it('should allow an alternative module mapping to be used for SSR', async () => {
    
  77.     function ClientComponent() {
    
  78.       return <span>Client Component</span>;
    
  79.     }
    
  80.     // The Client build may not have the same IDs as the Server bundles for the same
    
  81.     // component.
    
  82.     const ClientComponentOnTheClient = clientExports(
    
  83.       ClientComponent,
    
  84.       'path/to/chunk.js',
    
  85.     );
    
  86.     const ClientComponentOnTheServer = clientExports(ClientComponent);
    
  87. 
    
  88.     // In the SSR bundle this module won't exist. We simulate this by deleting it.
    
  89.     const clientId = turbopackMap[ClientComponentOnTheClient.$$id].id;
    
  90.     delete turbopackModules[clientId];
    
  91. 
    
  92.     // Instead, we have to provide a translation from the client meta data to the SSR
    
  93.     // meta data.
    
  94.     const ssrMetadata = turbopackMap[ClientComponentOnTheServer.$$id];
    
  95.     const translationMap = {
    
  96.       [clientId]: {
    
  97.         '*': ssrMetadata,
    
  98.       },
    
  99.     };
    
  100. 
    
  101.     function App() {
    
  102.       return <ClientComponentOnTheClient />;
    
  103.     }
    
  104. 
    
  105.     const stream = ReactServerDOMServer.renderToPipeableStream(
    
  106.       <App />,
    
  107.       turbopackMap,
    
  108.     );
    
  109.     const readable = new Stream.PassThrough();
    
  110. 
    
  111.     stream.pipe(readable);
    
  112. 
    
  113.     let response;
    
  114.     function ClientRoot() {
    
  115.       if (!response) {
    
  116.         response = ReactServerDOMClient.createFromNodeStream(readable, {
    
  117.           moduleMap: translationMap,
    
  118.           moduleLoading: turbopackModuleLoading,
    
  119.         });
    
  120.       }
    
  121.       return use(response);
    
  122.     }
    
  123. 
    
  124.     const ssrStream = await ReactDOMServer.renderToPipeableStream(
    
  125.       <ClientRoot />,
    
  126.     );
    
  127.     const result = await readResult(ssrStream);
    
  128.     expect(result).toEqual(
    
  129.       '<script src="/prefix/path/to/chunk.js" async=""></script><span>Client Component</span>',
    
  130.     );
    
  131.   });
    
  132. });