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('Store (legacy)', () => {
    
  11.   let React;
    
  12.   let ReactDOM;
    
  13.   let store;
    
  14. 
    
  15.   const act = (callback: Function) => {
    
  16.     callback();
    
  17. 
    
  18.     jest.runAllTimers(); // Flush Bridge operations
    
  19.   };
    
  20. 
    
  21.   beforeEach(() => {
    
  22.     store = global.store;
    
  23. 
    
  24.     // Redirect all React/ReactDOM requires to the v15 UMD.
    
  25.     // We use the UMD because Jest doesn't enable us to mock deep imports (e.g. "react/lib/Something").
    
  26.     jest.mock('react', () => jest.requireActual('react-15/dist/react.js'));
    
  27.     jest.mock('react-dom', () =>
    
  28.       jest.requireActual('react-dom-15/dist/react-dom.js'),
    
  29.     );
    
  30. 
    
  31.     React = require('react');
    
  32.     ReactDOM = require('react-dom');
    
  33.   });
    
  34. 
    
  35.   it('should not allow a root node to be collapsed', () => {
    
  36.     const Component = () => <div>Hi</div>;
    
  37. 
    
  38.     act(() =>
    
  39.       ReactDOM.render(<Component count={4} />, document.createElement('div')),
    
  40.     );
    
  41.     expect(store).toMatchInlineSnapshot(`
    
  42.       [root]
    
  43.         ▾ <Component>
    
  44.             <div>
    
  45.     `);
    
  46. 
    
  47.     expect(store.roots).toHaveLength(1);
    
  48. 
    
  49.     const rootID = store.roots[0];
    
  50. 
    
  51.     expect(() => store.toggleIsCollapsed(rootID, true)).toThrow(
    
  52.       'Root nodes cannot be collapsed',
    
  53.     );
    
  54.   });
    
  55. 
    
  56.   describe('collapseNodesByDefault:false', () => {
    
  57.     beforeEach(() => {
    
  58.       store.collapseNodesByDefault = false;
    
  59.     });
    
  60. 
    
  61.     it('should support mount and update operations', () => {
    
  62.       const Grandparent = ({count}) => (
    
  63.         <div>
    
  64.           <Parent count={count} />
    
  65.           <Parent count={count} />
    
  66.         </div>
    
  67.       );
    
  68.       const Parent = ({count}) => (
    
  69.         <div>
    
  70.           {new Array(count).fill(true).map((_, index) => (
    
  71.             <Child key={index} />
    
  72.           ))}
    
  73.         </div>
    
  74.       );
    
  75.       const Child = () => <div>Hi!</div>;
    
  76. 
    
  77.       const container = document.createElement('div');
    
  78. 
    
  79.       act(() => ReactDOM.render(<Grandparent count={4} />, container));
    
  80.       expect(store).toMatchInlineSnapshot(`
    
  81.         [root]
    
  82.           ▾ <Grandparent>
    
  83.             ▾ <div>
    
  84.               ▾ <Parent>
    
  85.                 ▾ <div>
    
  86.                   ▾ <Child key="0">
    
  87.                       <div>
    
  88.                   ▾ <Child key="1">
    
  89.                       <div>
    
  90.                   ▾ <Child key="2">
    
  91.                       <div>
    
  92.                   ▾ <Child key="3">
    
  93.                       <div>
    
  94.               ▾ <Parent>
    
  95.                 ▾ <div>
    
  96.                   ▾ <Child key="0">
    
  97.                       <div>
    
  98.                   ▾ <Child key="1">
    
  99.                       <div>
    
  100.                   ▾ <Child key="2">
    
  101.                       <div>
    
  102.                   ▾ <Child key="3">
    
  103.                       <div>
    
  104.       `);
    
  105. 
    
  106.       act(() => ReactDOM.render(<Grandparent count={2} />, container));
    
  107.       expect(store).toMatchInlineSnapshot(`
    
  108.         [root]
    
  109.           ▾ <Grandparent>
    
  110.             ▾ <div>
    
  111.               ▾ <Parent>
    
  112.                 ▾ <div>
    
  113.                   ▾ <Child key="0">
    
  114.                       <div>
    
  115.                   ▾ <Child key="1">
    
  116.                       <div>
    
  117.               ▾ <Parent>
    
  118.                 ▾ <div>
    
  119.                   ▾ <Child key="0">
    
  120.                       <div>
    
  121.                   ▾ <Child key="1">
    
  122.                       <div>
    
  123.       `);
    
  124. 
    
  125.       act(() => ReactDOM.unmountComponentAtNode(container));
    
  126.       expect(store).toMatchInlineSnapshot(``);
    
  127.     });
    
  128. 
    
  129.     it('should support mount and update operations for multiple roots', () => {
    
  130.       const Parent = ({count}) => (
    
  131.         <div>
    
  132.           {new Array(count).fill(true).map((_, index) => (
    
  133.             <Child key={index} />
    
  134.           ))}
    
  135.         </div>
    
  136.       );
    
  137.       const Child = () => <div>Hi!</div>;
    
  138. 
    
  139.       const containerA = document.createElement('div');
    
  140.       const containerB = document.createElement('div');
    
  141. 
    
  142.       act(() => {
    
  143.         ReactDOM.render(<Parent key="A" count={3} />, containerA);
    
  144.         ReactDOM.render(<Parent key="B" count={2} />, containerB);
    
  145.       });
    
  146.       expect(store).toMatchInlineSnapshot(`
    
  147.         [root]
    
  148.           ▾ <Parent key="A">
    
  149.             ▾ <div>
    
  150.               ▾ <Child key="0">
    
  151.                   <div>
    
  152.               ▾ <Child key="1">
    
  153.                   <div>
    
  154.               ▾ <Child key="2">
    
  155.                   <div>
    
  156.         [root]
    
  157.           ▾ <Parent key="B">
    
  158.             ▾ <div>
    
  159.               ▾ <Child key="0">
    
  160.                   <div>
    
  161.               ▾ <Child key="1">
    
  162.                   <div>
    
  163.       `);
    
  164. 
    
  165.       act(() => {
    
  166.         ReactDOM.render(<Parent key="A" count={4} />, containerA);
    
  167.         ReactDOM.render(<Parent key="B" count={1} />, containerB);
    
  168.       });
    
  169.       expect(store).toMatchInlineSnapshot(`
    
  170.         [root]
    
  171.           ▾ <Parent key="A">
    
  172.             ▾ <div>
    
  173.               ▾ <Child key="0">
    
  174.                   <div>
    
  175.               ▾ <Child key="1">
    
  176.                   <div>
    
  177.               ▾ <Child key="2">
    
  178.                   <div>
    
  179.               ▾ <Child key="3">
    
  180.                   <div>
    
  181.         [root]
    
  182.           ▾ <Parent key="B">
    
  183.             ▾ <div>
    
  184.               ▾ <Child key="0">
    
  185.                   <div>
    
  186.       `);
    
  187. 
    
  188.       act(() => ReactDOM.unmountComponentAtNode(containerB));
    
  189.       expect(store).toMatchInlineSnapshot(`
    
  190.         [root]
    
  191.           ▾ <Parent key="A">
    
  192.             ▾ <div>
    
  193.               ▾ <Child key="0">
    
  194.                   <div>
    
  195.               ▾ <Child key="1">
    
  196.                   <div>
    
  197.               ▾ <Child key="2">
    
  198.                   <div>
    
  199.               ▾ <Child key="3">
    
  200.                   <div>
    
  201.       `);
    
  202. 
    
  203.       act(() => ReactDOM.unmountComponentAtNode(containerA));
    
  204.       expect(store).toMatchInlineSnapshot(``);
    
  205.     });
    
  206. 
    
  207.     it('should not filter DOM nodes from the store tree', () => {
    
  208.       const Grandparent = ({flip}) => (
    
  209.         <div>
    
  210.           <div>
    
  211.             <Parent flip={flip} />
    
  212.           </div>
    
  213.           <Parent flip={flip} />
    
  214.           <Nothing />
    
  215.         </div>
    
  216.       );
    
  217.       const Parent = ({flip}) => (
    
  218.         <div>
    
  219.           {flip ? 'foo' : null}
    
  220.           <Child />
    
  221.           {flip && [null, 'hello', 42]}
    
  222.           {flip ? 'bar' : 'baz'}
    
  223.         </div>
    
  224.       );
    
  225.       const Child = () => <div>Hi!</div>;
    
  226.       const Nothing = () => null;
    
  227. 
    
  228.       const container = document.createElement('div');
    
  229.       act(() =>
    
  230.         ReactDOM.render(<Grandparent count={4} flip={false} />, container),
    
  231.       );
    
  232.       expect(store).toMatchInlineSnapshot(`
    
  233.         [root]
    
  234.           ▾ <Grandparent>
    
  235.             ▾ <div>
    
  236.               ▾ <div>
    
  237.                 ▾ <Parent>
    
  238.                   ▾ <div>
    
  239.                     ▾ <Child>
    
  240.                         <div>
    
  241.               ▾ <Parent>
    
  242.                 ▾ <div>
    
  243.                   ▾ <Child>
    
  244.                       <div>
    
  245.                 <Nothing>
    
  246.       `);
    
  247. 
    
  248.       act(() =>
    
  249.         ReactDOM.render(<Grandparent count={4} flip={true} />, container),
    
  250.       );
    
  251.       expect(store).toMatchInlineSnapshot(`
    
  252.         [root]
    
  253.           ▾ <Grandparent>
    
  254.             ▾ <div>
    
  255.               ▾ <div>
    
  256.                 ▾ <Parent>
    
  257.                   ▾ <div>
    
  258.                     ▾ <Child>
    
  259.                         <div>
    
  260.               ▾ <Parent>
    
  261.                 ▾ <div>
    
  262.                   ▾ <Child>
    
  263.                       <div>
    
  264.                 <Nothing>
    
  265.       `);
    
  266. 
    
  267.       act(() => ReactDOM.unmountComponentAtNode(container));
    
  268.       expect(store).toMatchInlineSnapshot(``);
    
  269.     });
    
  270. 
    
  271.     it('should support collapsing parts of the tree', () => {
    
  272.       const Grandparent = ({count}) => (
    
  273.         <div>
    
  274.           <Parent count={count} />
    
  275.           <Parent count={count} />
    
  276.         </div>
    
  277.       );
    
  278.       const Parent = ({count}) => (
    
  279.         <div>
    
  280.           {new Array(count).fill(true).map((_, index) => (
    
  281.             <Child key={index} />
    
  282.           ))}
    
  283.         </div>
    
  284.       );
    
  285.       const Child = () => <div>Hi!</div>;
    
  286. 
    
  287.       act(() =>
    
  288.         ReactDOM.render(
    
  289.           <Grandparent count={2} />,
    
  290.           document.createElement('div'),
    
  291.         ),
    
  292.       );
    
  293.       expect(store).toMatchInlineSnapshot(`
    
  294.         [root]
    
  295.           ▾ <Grandparent>
    
  296.             ▾ <div>
    
  297.               ▾ <Parent>
    
  298.                 ▾ <div>
    
  299.                   ▾ <Child key="0">
    
  300.                       <div>
    
  301.                   ▾ <Child key="1">
    
  302.                       <div>
    
  303.               ▾ <Parent>
    
  304.                 ▾ <div>
    
  305.                   ▾ <Child key="0">
    
  306.                       <div>
    
  307.                   ▾ <Child key="1">
    
  308.                       <div>
    
  309.       `);
    
  310. 
    
  311.       const grandparentID = store.getElementIDAtIndex(0);
    
  312.       const parentOneID = store.getElementIDAtIndex(2);
    
  313.       const parentTwoID = store.getElementIDAtIndex(8);
    
  314. 
    
  315.       act(() => store.toggleIsCollapsed(parentOneID, true));
    
  316.       expect(store).toMatchInlineSnapshot(`
    
  317.         [root]
    
  318.           ▾ <Grandparent>
    
  319.             ▾ <div>
    
  320.               ▸ <Parent>
    
  321.               ▾ <Parent>
    
  322.                 ▾ <div>
    
  323.                   ▾ <Child key="0">
    
  324.                       <div>
    
  325.                   ▾ <Child key="1">
    
  326.                       <div>
    
  327.       `);
    
  328. 
    
  329.       act(() => store.toggleIsCollapsed(parentTwoID, true));
    
  330.       expect(store).toMatchInlineSnapshot(`
    
  331.         [root]
    
  332.           ▾ <Grandparent>
    
  333.             ▾ <div>
    
  334.               ▸ <Parent>
    
  335.               ▸ <Parent>
    
  336.       `);
    
  337. 
    
  338.       act(() => store.toggleIsCollapsed(parentOneID, false));
    
  339.       expect(store).toMatchInlineSnapshot(`
    
  340.         [root]
    
  341.           ▾ <Grandparent>
    
  342.             ▾ <div>
    
  343.               ▾ <Parent>
    
  344.                 ▾ <div>
    
  345.                   ▾ <Child key="0">
    
  346.                       <div>
    
  347.                   ▾ <Child key="1">
    
  348.                       <div>
    
  349.               ▸ <Parent>
    
  350.       `);
    
  351. 
    
  352.       act(() => store.toggleIsCollapsed(grandparentID, true));
    
  353.       expect(store).toMatchInlineSnapshot(`
    
  354.         [root]
    
  355.           ▸ <Grandparent>
    
  356.       `);
    
  357. 
    
  358.       act(() => store.toggleIsCollapsed(grandparentID, false));
    
  359.       expect(store).toMatchInlineSnapshot(`
    
  360.         [root]
    
  361.           ▾ <Grandparent>
    
  362.             ▾ <div>
    
  363.               ▾ <Parent>
    
  364.                 ▾ <div>
    
  365.                   ▾ <Child key="0">
    
  366.                       <div>
    
  367.                   ▾ <Child key="1">
    
  368.                       <div>
    
  369.               ▸ <Parent>
    
  370.       `);
    
  371.     });
    
  372. 
    
  373.     it('should support adding and removing children', () => {
    
  374.       const Root = ({children}) => <div>{children}</div>;
    
  375.       const Component = () => <div />;
    
  376. 
    
  377.       const container = document.createElement('div');
    
  378. 
    
  379.       act(() =>
    
  380.         ReactDOM.render(
    
  381.           <Root>
    
  382.             <Component key="a" />
    
  383.           </Root>,
    
  384.           container,
    
  385.         ),
    
  386.       );
    
  387.       expect(store).toMatchInlineSnapshot(`
    
  388.         [root]
    
  389.           ▾ <Root>
    
  390.             ▾ <div>
    
  391.               ▾ <Component key="a">
    
  392.                   <div>
    
  393.       `);
    
  394. 
    
  395.       act(() =>
    
  396.         ReactDOM.render(
    
  397.           <Root>
    
  398.             <Component key="a" />
    
  399.             <Component key="b" />
    
  400.           </Root>,
    
  401.           container,
    
  402.         ),
    
  403.       );
    
  404.       expect(store).toMatchInlineSnapshot(`
    
  405.         [root]
    
  406.           ▾ <Root>
    
  407.             ▾ <div>
    
  408.               ▾ <Component key="a">
    
  409.                   <div>
    
  410.               ▾ <Component key="b">
    
  411.                   <div>
    
  412.       `);
    
  413. 
    
  414.       act(() =>
    
  415.         ReactDOM.render(
    
  416.           <Root>
    
  417.             <Component key="b" />
    
  418.           </Root>,
    
  419.           container,
    
  420.         ),
    
  421.       );
    
  422.       expect(store).toMatchInlineSnapshot(`
    
  423.         [root]
    
  424.           ▾ <Root>
    
  425.             ▾ <div>
    
  426.               ▾ <Component key="b">
    
  427.                   <div>
    
  428.       `);
    
  429.     });
    
  430. 
    
  431.     it('should support reordering of children', () => {
    
  432.       const Root = ({children}) => <div>{children}</div>;
    
  433.       const Component = () => <div />;
    
  434. 
    
  435.       const Foo = () => <div>{[<Component key="0" />]}</div>;
    
  436.       const Bar = () => (
    
  437.         <div>{[<Component key="0" />, <Component key="1" />]}</div>
    
  438.       );
    
  439.       const foo = <Foo key="foo" />;
    
  440.       const bar = <Bar key="bar" />;
    
  441. 
    
  442.       const container = document.createElement('div');
    
  443. 
    
  444.       act(() => ReactDOM.render(<Root>{[foo, bar]}</Root>, container));
    
  445.       expect(store).toMatchInlineSnapshot(`
    
  446.         [root]
    
  447.           ▾ <Root>
    
  448.             ▾ <div>
    
  449.               ▾ <Foo key="foo">
    
  450.                 ▾ <div>
    
  451.                   ▾ <Component key="0">
    
  452.                       <div>
    
  453.               ▾ <Bar key="bar">
    
  454.                 ▾ <div>
    
  455.                   ▾ <Component key="0">
    
  456.                       <div>
    
  457.                   ▾ <Component key="1">
    
  458.                       <div>
    
  459.       `);
    
  460. 
    
  461.       act(() => ReactDOM.render(<Root>{[bar, foo]}</Root>, container));
    
  462.       expect(store).toMatchInlineSnapshot(`
    
  463.         [root]
    
  464.           ▾ <Root>
    
  465.             ▾ <div>
    
  466.               ▾ <Bar key="bar">
    
  467.                 ▾ <div>
    
  468.                   ▾ <Component key="0">
    
  469.                       <div>
    
  470.                   ▾ <Component key="1">
    
  471.                       <div>
    
  472.               ▾ <Foo key="foo">
    
  473.                 ▾ <div>
    
  474.                   ▾ <Component key="0">
    
  475.                       <div>
    
  476.       `);
    
  477. 
    
  478.       act(() => store.toggleIsCollapsed(store.getElementIDAtIndex(0), true));
    
  479.       expect(store).toMatchInlineSnapshot(`
    
  480.         [root]
    
  481.           ▸ <Root>
    
  482.       `);
    
  483. 
    
  484.       act(() => store.toggleIsCollapsed(store.getElementIDAtIndex(0), false));
    
  485.       expect(store).toMatchInlineSnapshot(`
    
  486.         [root]
    
  487.           ▾ <Root>
    
  488.             ▾ <div>
    
  489.               ▾ <Bar key="bar">
    
  490.                 ▾ <div>
    
  491.                   ▾ <Component key="0">
    
  492.                       <div>
    
  493.                   ▾ <Component key="1">
    
  494.                       <div>
    
  495.               ▾ <Foo key="foo">
    
  496.                 ▾ <div>
    
  497.                   ▾ <Component key="0">
    
  498.                       <div>
    
  499.       `);
    
  500.     });
    
  501.   });
    
  502. 
    
  503.   describe('collapseNodesByDefault:true', () => {
    
  504.     beforeEach(() => {
    
  505.       store.collapseNodesByDefault = true;
    
  506.     });
    
  507. 
    
  508.     it('should support mount and update operations', () => {
    
  509.       const Parent = ({count}) => (
    
  510.         <div>
    
  511.           {new Array(count).fill(true).map((_, index) => (
    
  512.             <Child key={index} />
    
  513.           ))}
    
  514.         </div>
    
  515.       );
    
  516.       const Child = () => <div>Hi!</div>;
    
  517. 
    
  518.       const container = document.createElement('div');
    
  519. 
    
  520.       act(() =>
    
  521.         ReactDOM.render(
    
  522.           <div>
    
  523.             <Parent count={1} />
    
  524.             <Parent count={3} />
    
  525.           </div>,
    
  526.           container,
    
  527.         ),
    
  528.       );
    
  529.       expect(store).toMatchInlineSnapshot(`
    
  530.         [root]
    
  531.           ▸ <div>
    
  532.       `);
    
  533. 
    
  534.       act(() =>
    
  535.         ReactDOM.render(
    
  536.           <div>
    
  537.             <Parent count={2} />
    
  538.             <Parent count={1} />
    
  539.           </div>,
    
  540.           container,
    
  541.         ),
    
  542.       );
    
  543.       expect(store).toMatchInlineSnapshot(`
    
  544.         [root]
    
  545.           ▸ <div>
    
  546.       `);
    
  547. 
    
  548.       act(() => ReactDOM.unmountComponentAtNode(container));
    
  549.       expect(store).toMatchInlineSnapshot(``);
    
  550.     });
    
  551. 
    
  552.     it('should support mount and update operations for multiple roots', () => {
    
  553.       const Parent = ({count}) => (
    
  554.         <div>
    
  555.           {new Array(count).fill(true).map((_, index) => (
    
  556.             <Child key={index} />
    
  557.           ))}
    
  558.         </div>
    
  559.       );
    
  560.       const Child = () => <div>Hi!</div>;
    
  561. 
    
  562.       const containerA = document.createElement('div');
    
  563.       const containerB = document.createElement('div');
    
  564. 
    
  565.       act(() => {
    
  566.         ReactDOM.render(<Parent key="A" count={3} />, containerA);
    
  567.         ReactDOM.render(<Parent key="B" count={2} />, containerB);
    
  568.       });
    
  569.       expect(store).toMatchInlineSnapshot(`
    
  570.         [root]
    
  571.           ▸ <Parent key="A">
    
  572.         [root]
    
  573.           ▸ <Parent key="B">
    
  574.       `);
    
  575. 
    
  576.       act(() => {
    
  577.         ReactDOM.render(<Parent key="A" count={4} />, containerA);
    
  578.         ReactDOM.render(<Parent key="B" count={1} />, containerB);
    
  579.       });
    
  580.       expect(store).toMatchInlineSnapshot(`
    
  581.         [root]
    
  582.           ▸ <Parent key="A">
    
  583.         [root]
    
  584.           ▸ <Parent key="B">
    
  585.       `);
    
  586. 
    
  587.       act(() => ReactDOM.unmountComponentAtNode(containerB));
    
  588.       expect(store).toMatchInlineSnapshot(`
    
  589.         [root]
    
  590.           ▸ <Parent key="A">
    
  591.       `);
    
  592. 
    
  593.       act(() => ReactDOM.unmountComponentAtNode(containerA));
    
  594.       expect(store).toMatchInlineSnapshot(``);
    
  595.     });
    
  596. 
    
  597.     it('should not filter DOM nodes from the store tree', () => {
    
  598.       const Grandparent = ({flip}) => (
    
  599.         <div>
    
  600.           <div>
    
  601.             <Parent flip={flip} />
    
  602.           </div>
    
  603.           <Parent flip={flip} />
    
  604.           <Nothing />
    
  605.         </div>
    
  606.       );
    
  607.       const Parent = ({flip}) => (
    
  608.         <div>
    
  609.           {flip ? 'foo' : null}
    
  610.           <Child />
    
  611.           {flip && [null, 'hello', 42]}
    
  612.           {flip ? 'bar' : 'baz'}
    
  613.         </div>
    
  614.       );
    
  615.       const Child = () => <div>Hi!</div>;
    
  616.       const Nothing = () => null;
    
  617. 
    
  618.       const container = document.createElement('div');
    
  619.       act(() =>
    
  620.         ReactDOM.render(<Grandparent count={4} flip={false} />, container),
    
  621.       );
    
  622.       expect(store).toMatchInlineSnapshot(`
    
  623.         [root]
    
  624.           ▸ <Grandparent>
    
  625.       `);
    
  626. 
    
  627.       act(() => store.toggleIsCollapsed(store.getElementIDAtIndex(0), false));
    
  628.       expect(store).toMatchInlineSnapshot(`
    
  629.         [root]
    
  630.           ▾ <Grandparent>
    
  631.             ▸ <div>
    
  632.       `);
    
  633. 
    
  634.       act(() => store.toggleIsCollapsed(store.getElementIDAtIndex(1), false));
    
  635.       expect(store).toMatchInlineSnapshot(`
    
  636.         [root]
    
  637.           ▾ <Grandparent>
    
  638.             ▾ <div>
    
  639.               ▸ <div>
    
  640.               ▸ <Parent>
    
  641.                 <Nothing>
    
  642.       `);
    
  643. 
    
  644.       act(() =>
    
  645.         ReactDOM.render(<Grandparent count={4} flip={true} />, container),
    
  646.       );
    
  647.       expect(store).toMatchInlineSnapshot(`
    
  648.         [root]
    
  649.           ▾ <Grandparent>
    
  650.             ▾ <div>
    
  651.               ▸ <div>
    
  652.               ▸ <Parent>
    
  653.                 <Nothing>
    
  654.       `);
    
  655. 
    
  656.       act(() => ReactDOM.unmountComponentAtNode(container));
    
  657.       expect(store).toMatchInlineSnapshot(``);
    
  658.     });
    
  659. 
    
  660.     it('should support expanding parts of the tree', () => {
    
  661.       const Grandparent = ({count}) => (
    
  662.         <div>
    
  663.           <Parent count={count} />
    
  664.           <Parent count={count} />
    
  665.         </div>
    
  666.       );
    
  667.       const Parent = ({count}) => (
    
  668.         <div>
    
  669.           {new Array(count).fill(true).map((_, index) => (
    
  670.             <Child key={index} />
    
  671.           ))}
    
  672.         </div>
    
  673.       );
    
  674.       const Child = () => <div>Hi!</div>;
    
  675. 
    
  676.       act(() =>
    
  677.         ReactDOM.render(
    
  678.           <Grandparent count={2} />,
    
  679.           document.createElement('div'),
    
  680.         ),
    
  681.       );
    
  682.       expect(store).toMatchInlineSnapshot(`
    
  683.         [root]
    
  684.           ▸ <Grandparent>
    
  685.       `);
    
  686. 
    
  687.       const grandparentID = store.getElementIDAtIndex(0);
    
  688. 
    
  689.       act(() => store.toggleIsCollapsed(grandparentID, false));
    
  690.       expect(store).toMatchInlineSnapshot(`
    
  691.         [root]
    
  692.           ▾ <Grandparent>
    
  693.             ▸ <div>
    
  694.       `);
    
  695. 
    
  696.       const parentDivID = store.getElementIDAtIndex(1);
    
  697.       act(() => store.toggleIsCollapsed(parentDivID, false));
    
  698.       expect(store).toMatchInlineSnapshot(`
    
  699.         [root]
    
  700.           ▾ <Grandparent>
    
  701.             ▾ <div>
    
  702.               ▸ <Parent>
    
  703.               ▸ <Parent>
    
  704.       `);
    
  705. 
    
  706.       const parentOneID = store.getElementIDAtIndex(2);
    
  707.       const parentTwoID = store.getElementIDAtIndex(3);
    
  708. 
    
  709.       act(() => store.toggleIsCollapsed(parentOneID, false));
    
  710.       expect(store).toMatchInlineSnapshot(`
    
  711.         [root]
    
  712.           ▾ <Grandparent>
    
  713.             ▾ <div>
    
  714.               ▾ <Parent>
    
  715.                 ▸ <div>
    
  716.               ▸ <Parent>
    
  717.       `);
    
  718. 
    
  719.       act(() => store.toggleIsCollapsed(parentTwoID, false));
    
  720.       expect(store).toMatchInlineSnapshot(`
    
  721.         [root]
    
  722.           ▾ <Grandparent>
    
  723.             ▾ <div>
    
  724.               ▾ <Parent>
    
  725.                 ▸ <div>
    
  726.               ▾ <Parent>
    
  727.                 ▸ <div>
    
  728.       `);
    
  729. 
    
  730.       act(() => store.toggleIsCollapsed(parentOneID, true));
    
  731.       expect(store).toMatchInlineSnapshot(`
    
  732.         [root]
    
  733.           ▾ <Grandparent>
    
  734.             ▾ <div>
    
  735.               ▸ <Parent>
    
  736.               ▾ <Parent>
    
  737.                 ▸ <div>
    
  738.       `);
    
  739. 
    
  740.       act(() => store.toggleIsCollapsed(parentTwoID, true));
    
  741.       expect(store).toMatchInlineSnapshot(`
    
  742.         [root]
    
  743.           ▾ <Grandparent>
    
  744.             ▾ <div>
    
  745.               ▸ <Parent>
    
  746.               ▸ <Parent>
    
  747.       `);
    
  748. 
    
  749.       act(() => store.toggleIsCollapsed(grandparentID, true));
    
  750.       expect(store).toMatchInlineSnapshot(`
    
  751.         [root]
    
  752.           ▸ <Grandparent>
    
  753.       `);
    
  754.     });
    
  755. 
    
  756.     it('should support expanding deep parts of the tree', () => {
    
  757.       const Wrapper = ({forwardedRef}) => (
    
  758.         <Nested depth={3} forwardedRef={forwardedRef} />
    
  759.       );
    
  760.       const Nested = ({depth, forwardedRef}) =>
    
  761.         depth > 0 ? (
    
  762.           <Nested depth={depth - 1} forwardedRef={forwardedRef} />
    
  763.         ) : (
    
  764.           <div ref={forwardedRef} />
    
  765.         );
    
  766. 
    
  767.       let ref = null;
    
  768.       const refSetter = value => {
    
  769.         ref = value;
    
  770.       };
    
  771. 
    
  772.       act(() =>
    
  773.         ReactDOM.render(
    
  774.           <Wrapper forwardedRef={refSetter} />,
    
  775.           document.createElement('div'),
    
  776.         ),
    
  777.       );
    
  778.       expect(store).toMatchInlineSnapshot(`
    
  779.         [root]
    
  780.           ▸ <Wrapper>
    
  781.       `);
    
  782. 
    
  783.       const deepestedNodeID = global.agent.getIDForNode(ref);
    
  784. 
    
  785.       act(() => store.toggleIsCollapsed(deepestedNodeID, false));
    
  786.       expect(store).toMatchInlineSnapshot(`
    
  787.         [root]
    
  788.           ▾ <Wrapper>
    
  789.             ▾ <Nested>
    
  790.               ▾ <Nested>
    
  791.                 ▾ <Nested>
    
  792.                   ▾ <Nested>
    
  793.                       <div>
    
  794.       `);
    
  795. 
    
  796.       const rootID = store.getElementIDAtIndex(0);
    
  797. 
    
  798.       act(() => store.toggleIsCollapsed(rootID, true));
    
  799.       expect(store).toMatchInlineSnapshot(`
    
  800.         [root]
    
  801.           ▸ <Wrapper>
    
  802.       `);
    
  803. 
    
  804.       act(() => store.toggleIsCollapsed(rootID, false));
    
  805.       expect(store).toMatchInlineSnapshot(`
    
  806.         [root]
    
  807.           ▾ <Wrapper>
    
  808.             ▾ <Nested>
    
  809.               ▾ <Nested>
    
  810.                 ▾ <Nested>
    
  811.                   ▾ <Nested>
    
  812.                       <div>
    
  813.       `);
    
  814. 
    
  815.       const id = store.getElementIDAtIndex(1);
    
  816. 
    
  817.       act(() => store.toggleIsCollapsed(id, true));
    
  818.       expect(store).toMatchInlineSnapshot(`
    
  819.         [root]
    
  820.           ▾ <Wrapper>
    
  821.             ▸ <Nested>
    
  822.       `);
    
  823. 
    
  824.       act(() => store.toggleIsCollapsed(id, false));
    
  825.       expect(store).toMatchInlineSnapshot(`
    
  826.         [root]
    
  827.           ▾ <Wrapper>
    
  828.             ▾ <Nested>
    
  829.               ▾ <Nested>
    
  830.                 ▾ <Nested>
    
  831.                   ▾ <Nested>
    
  832.                       <div>
    
  833.       `);
    
  834.     });
    
  835. 
    
  836.     it('should support reordering of children', () => {
    
  837.       const Root = ({children}) => <div>{children}</div>;
    
  838.       const Component = () => <div />;
    
  839. 
    
  840.       const Foo = () => <div>{[<Component key="0" />]}</div>;
    
  841.       const Bar = () => (
    
  842.         <div>{[<Component key="0" />, <Component key="1" />]}</div>
    
  843.       );
    
  844.       const foo = <Foo key="foo" />;
    
  845.       const bar = <Bar key="bar" />;
    
  846. 
    
  847.       const container = document.createElement('div');
    
  848. 
    
  849.       act(() => ReactDOM.render(<Root>{[foo, bar]}</Root>, container));
    
  850.       expect(store).toMatchInlineSnapshot(`
    
  851.         [root]
    
  852.           ▸ <Root>
    
  853.       `);
    
  854. 
    
  855.       act(() => ReactDOM.render(<Root>{[bar, foo]}</Root>, container));
    
  856.       expect(store).toMatchInlineSnapshot(`
    
  857.         [root]
    
  858.           ▸ <Root>
    
  859.       `);
    
  860. 
    
  861.       act(() => store.toggleIsCollapsed(store.getElementIDAtIndex(0), false));
    
  862.       expect(store).toMatchInlineSnapshot(`
    
  863.         [root]
    
  864.           ▾ <Root>
    
  865.             ▸ <div>
    
  866.       `);
    
  867. 
    
  868.       act(() => store.toggleIsCollapsed(store.getElementIDAtIndex(1), false));
    
  869.       expect(store).toMatchInlineSnapshot(`
    
  870.         [root]
    
  871.           ▾ <Root>
    
  872.             ▾ <div>
    
  873.               ▸ <Bar key="bar">
    
  874.               ▸ <Foo key="foo">
    
  875.       `);
    
  876. 
    
  877.       act(() => {
    
  878.         store.toggleIsCollapsed(store.getElementIDAtIndex(3), false);
    
  879.         store.toggleIsCollapsed(store.getElementIDAtIndex(2), false);
    
  880.       });
    
  881.       expect(store).toMatchInlineSnapshot(`
    
  882.         [root]
    
  883.           ▾ <Root>
    
  884.             ▾ <div>
    
  885.               ▾ <Bar key="bar">
    
  886.                 ▸ <div>
    
  887.               ▾ <Foo key="foo">
    
  888.                 ▸ <div>
    
  889.       `);
    
  890. 
    
  891.       act(() => store.toggleIsCollapsed(store.getElementIDAtIndex(0), true));
    
  892.       expect(store).toMatchInlineSnapshot(`
    
  893.         [root]
    
  894.           ▸ <Root>
    
  895.       `);
    
  896.     });
    
  897.   });
    
  898. 
    
  899.   describe('StrictMode compliance', () => {
    
  900.     it('should mark all elements as strict mode compliant', () => {
    
  901.       const App = () => null;
    
  902. 
    
  903.       const container = document.createElement('div');
    
  904.       act(() => ReactDOM.render(<App />, container));
    
  905. 
    
  906.       expect(store.getElementAtIndex(0).isStrictModeNonCompliant).toBe(false);
    
  907.     });
    
  908.   });
    
  909. });