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. const ReactDOMServerIntegrationUtils = require('./utils/ReactDOMServerIntegrationTestUtils');
    
  13. 
    
  14. let React;
    
  15. let ReactDOM;
    
  16. let ReactDOMServer;
    
  17. let ReactTestUtils;
    
  18. 
    
  19. function initModules() {
    
  20.   // Reset warning cache.
    
  21.   jest.resetModules();
    
  22.   React = require('react');
    
  23.   ReactDOM = require('react-dom');
    
  24.   ReactDOMServer = require('react-dom/server');
    
  25.   ReactTestUtils = require('react-dom/test-utils');
    
  26. 
    
  27.   // Make them available to the helpers.
    
  28.   return {
    
  29.     ReactDOM,
    
  30.     ReactDOMServer,
    
  31.     ReactTestUtils,
    
  32.   };
    
  33. }
    
  34. 
    
  35. const {
    
  36.   resetModules,
    
  37.   asyncReactDOMRender,
    
  38.   clientRenderOnServerString,
    
  39.   expectMarkupMatch,
    
  40. } = ReactDOMServerIntegrationUtils(initModules);
    
  41. 
    
  42. describe('ReactDOMServerIntegration', () => {
    
  43.   beforeEach(() => {
    
  44.     resetModules();
    
  45.   });
    
  46. 
    
  47.   describe('refs', function () {
    
  48.     it('should not run ref code on server', async () => {
    
  49.       let refCount = 0;
    
  50.       class RefsComponent extends React.Component {
    
  51.         render() {
    
  52.           return <div ref={e => refCount++} />;
    
  53.         }
    
  54.       }
    
  55.       await expectMarkupMatch(<RefsComponent />, <div />);
    
  56.       expect(refCount).toBe(0);
    
  57.     });
    
  58. 
    
  59.     it('should run ref code on client', async () => {
    
  60.       let refCount = 0;
    
  61.       class RefsComponent extends React.Component {
    
  62.         render() {
    
  63.           return <div ref={e => refCount++} />;
    
  64.         }
    
  65.       }
    
  66.       await expectMarkupMatch(<div />, <RefsComponent />);
    
  67.       expect(refCount).toBe(1);
    
  68.     });
    
  69. 
    
  70.     it('should send the correct element to ref functions on client', async () => {
    
  71.       let refElement = null;
    
  72.       class RefsComponent extends React.Component {
    
  73.         render() {
    
  74.           return <div ref={e => (refElement = e)} />;
    
  75.         }
    
  76.       }
    
  77.       const e = await clientRenderOnServerString(<RefsComponent />);
    
  78.       expect(refElement).not.toBe(null);
    
  79.       expect(refElement).toBe(e);
    
  80.     });
    
  81. 
    
  82.     it('should have string refs on client when rendered over server markup', async () => {
    
  83.       class RefsComponent extends React.Component {
    
  84.         render() {
    
  85.           return <div ref="myDiv" />;
    
  86.         }
    
  87.       }
    
  88. 
    
  89.       const markup = ReactDOMServer.renderToString(<RefsComponent />);
    
  90.       const root = document.createElement('div');
    
  91.       root.innerHTML = markup;
    
  92.       let component = null;
    
  93.       resetModules();
    
  94.       await expect(async () => {
    
  95.         await asyncReactDOMRender(
    
  96.           <RefsComponent ref={e => (component = e)} />,
    
  97.           root,
    
  98.           true,
    
  99.         );
    
  100.       }).toErrorDev([
    
  101.         'Warning: Component "RefsComponent" contains the string ref "myDiv". ' +
    
  102.           'Support for string refs will be removed in a future major release. ' +
    
  103.           'We recommend using useRef() or createRef() instead. ' +
    
  104.           'Learn more about using refs safely here: https://reactjs.org/link/strict-mode-string-ref\n' +
    
  105.           '    in RefsComponent (at **)',
    
  106.       ]);
    
  107.       expect(component.refs.myDiv).toBe(root.firstChild);
    
  108.     });
    
  109.   });
    
  110. 
    
  111.   it('should forward refs', async () => {
    
  112.     const divRef = React.createRef();
    
  113. 
    
  114.     class InnerComponent extends React.Component {
    
  115.       render() {
    
  116.         return <div ref={this.props.forwardedRef}>{this.props.value}</div>;
    
  117.       }
    
  118.     }
    
  119. 
    
  120.     const OuterComponent = React.forwardRef((props, ref) => (
    
  121.       <InnerComponent {...props} forwardedRef={ref} />
    
  122.     ));
    
  123. 
    
  124.     await clientRenderOnServerString(
    
  125.       <OuterComponent ref={divRef} value="hello" />,
    
  126.     );
    
  127. 
    
  128.     expect(divRef.current).not.toBe(null);
    
  129.     expect(divRef.current.textContent).toBe('hello');
    
  130.   });
    
  131. });