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.  * @flow
    
  8.  */
    
  9. 
    
  10. describe('Profiler change descriptions', () => {
    
  11.   let React;
    
  12.   let legacyRender;
    
  13.   let store;
    
  14.   let utils;
    
  15. 
    
  16.   beforeEach(() => {
    
  17.     utils = require('./utils');
    
  18.     utils.beforeEachProfiling();
    
  19. 
    
  20.     legacyRender = utils.legacyRender;
    
  21. 
    
  22.     store = global.store;
    
  23.     store.collapseNodesByDefault = false;
    
  24.     store.recordChangeDescriptions = true;
    
  25. 
    
  26.     React = require('react');
    
  27.   });
    
  28. 
    
  29.   // @reactVersion >=18.0
    
  30.   it('should identify useContext as the cause for a re-render', () => {
    
  31.     const Context = React.createContext(0);
    
  32. 
    
  33.     function Child() {
    
  34.       const context = React.useContext(Context);
    
  35.       return context;
    
  36.     }
    
  37. 
    
  38.     function areEqual() {
    
  39.       return true;
    
  40.     }
    
  41. 
    
  42.     const MemoizedChild = React.memo(Child, areEqual);
    
  43.     const ForwardRefChild = React.forwardRef(
    
  44.       function RefForwardingComponent(props, ref) {
    
  45.         return <Child />;
    
  46.       },
    
  47.     );
    
  48. 
    
  49.     let forceUpdate = null;
    
  50. 
    
  51.     const App = function App() {
    
  52.       const [val, dispatch] = React.useReducer(x => x + 1, 0);
    
  53. 
    
  54.       forceUpdate = dispatch;
    
  55. 
    
  56.       return (
    
  57.         <Context.Provider value={val}>
    
  58.           <Child />
    
  59.           <MemoizedChild />
    
  60.           <ForwardRefChild />
    
  61.         </Context.Provider>
    
  62.       );
    
  63.     };
    
  64. 
    
  65.     const container = document.createElement('div');
    
  66. 
    
  67.     utils.act(() => store.profilerStore.startProfiling());
    
  68.     utils.act(() => legacyRender(<App />, container));
    
  69.     utils.act(() => forceUpdate());
    
  70.     utils.act(() => store.profilerStore.stopProfiling());
    
  71. 
    
  72.     const rootID = store.roots[0];
    
  73.     const commitData = store.profilerStore.getCommitData(rootID, 1);
    
  74. 
    
  75.     expect(store).toMatchInlineSnapshot(`
    
  76.       [root]
    
  77.         ▾ <App>
    
  78.           ▾ <Context.Provider>
    
  79.               <Child>
    
  80.             ▾ <Child> [Memo]
    
  81.                 <Child>
    
  82.             ▾ <RefForwardingComponent> [ForwardRef]
    
  83.                 <Child>
    
  84.     `);
    
  85. 
    
  86.     let element = store.getElementAtIndex(2);
    
  87.     expect(element.displayName).toBe('Child');
    
  88.     expect(element.hocDisplayNames).toBeNull();
    
  89.     expect(commitData.changeDescriptions.get(element.id))
    
  90.       .toMatchInlineSnapshot(`
    
  91.       {
    
  92.         "context": true,
    
  93.         "didHooksChange": false,
    
  94.         "hooks": null,
    
  95.         "isFirstMount": false,
    
  96.         "props": [],
    
  97.         "state": null,
    
  98.       }
    
  99.     `);
    
  100. 
    
  101.     element = store.getElementAtIndex(3);
    
  102.     expect(element.displayName).toBe('Child');
    
  103.     expect(element.hocDisplayNames).toEqual(['Memo']);
    
  104.     expect(commitData.changeDescriptions.get(element.id)).toBeUndefined();
    
  105. 
    
  106.     element = store.getElementAtIndex(4);
    
  107.     expect(element.displayName).toBe('Child');
    
  108.     expect(element.hocDisplayNames).toBeNull();
    
  109.     expect(commitData.changeDescriptions.get(element.id))
    
  110.       .toMatchInlineSnapshot(`
    
  111.       {
    
  112.         "context": true,
    
  113.         "didHooksChange": false,
    
  114.         "hooks": null,
    
  115.         "isFirstMount": false,
    
  116.         "props": [],
    
  117.         "state": null,
    
  118.       }
    
  119.     `);
    
  120. 
    
  121.     element = store.getElementAtIndex(5);
    
  122.     expect(element.displayName).toBe('RefForwardingComponent');
    
  123.     expect(element.hocDisplayNames).toEqual(['ForwardRef']);
    
  124.     expect(commitData.changeDescriptions.get(element.id))
    
  125.       .toMatchInlineSnapshot(`
    
  126.       {
    
  127.         "context": null,
    
  128.         "didHooksChange": false,
    
  129.         "hooks": null,
    
  130.         "isFirstMount": false,
    
  131.         "props": [],
    
  132.         "state": null,
    
  133.       }
    
  134.     `);
    
  135. 
    
  136.     element = store.getElementAtIndex(6);
    
  137.     expect(element.displayName).toBe('Child');
    
  138.     expect(element.hocDisplayNames).toBeNull();
    
  139.     expect(commitData.changeDescriptions.get(element.id))
    
  140.       .toMatchInlineSnapshot(`
    
  141.       {
    
  142.         "context": true,
    
  143.         "didHooksChange": false,
    
  144.         "hooks": null,
    
  145.         "isFirstMount": false,
    
  146.         "props": [],
    
  147.         "state": null,
    
  148.       }
    
  149.     `);
    
  150.   });
    
  151. });