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. // NOTE: We're explicitly not using JSX here. This is intended to test
    
  11. // the current stack addendum without having source location added by babel.
    
  12. 
    
  13. 'use strict';
    
  14. 
    
  15. let React;
    
  16. let ReactTestUtils;
    
  17. 
    
  18. describe('ReactChildReconciler', () => {
    
  19.   beforeEach(() => {
    
  20.     jest.resetModules();
    
  21. 
    
  22.     React = require('react');
    
  23.     ReactTestUtils = require('react-dom/test-utils');
    
  24.   });
    
  25. 
    
  26.   function createIterable(array) {
    
  27.     return {
    
  28.       '@@iterator': function () {
    
  29.         let i = 0;
    
  30.         return {
    
  31.           next() {
    
  32.             const next = {
    
  33.               value: i < array.length ? array[i] : undefined,
    
  34.               done: i === array.length,
    
  35.             };
    
  36.             i++;
    
  37.             return next;
    
  38.           },
    
  39.         };
    
  40.       },
    
  41.     };
    
  42.   }
    
  43. 
    
  44.   function makeIterableFunction(value) {
    
  45.     const fn = () => {};
    
  46.     fn['@@iterator'] = function iterator() {
    
  47.       let timesCalled = 0;
    
  48.       return {
    
  49.         next() {
    
  50.           const done = timesCalled++ > 0;
    
  51.           return {done, value: done ? undefined : value};
    
  52.         },
    
  53.       };
    
  54.     };
    
  55.     return fn;
    
  56.   }
    
  57. 
    
  58.   it('does not treat functions as iterables', () => {
    
  59.     let node;
    
  60.     const iterableFunction = makeIterableFunction('foo');
    
  61. 
    
  62.     expect(() => {
    
  63.       node = ReactTestUtils.renderIntoDocument(
    
  64.         <div>
    
  65.           <h1>{iterableFunction}</h1>
    
  66.         </div>,
    
  67.       );
    
  68.     }).toErrorDev('Functions are not valid as a React child');
    
  69. 
    
  70.     expect(node.innerHTML).toContain(''); // h1
    
  71.   });
    
  72. 
    
  73.   it('warns for duplicated array keys', () => {
    
  74.     class Component extends React.Component {
    
  75.       render() {
    
  76.         return <div>{[<div key="1" />, <div key="1" />]}</div>;
    
  77.       }
    
  78.     }
    
  79. 
    
  80.     expect(() => ReactTestUtils.renderIntoDocument(<Component />)).toErrorDev(
    
  81.       'Keys should be unique so that components maintain their identity ' +
    
  82.         'across updates. Non-unique keys may cause children to be ' +
    
  83.         'duplicated and/or omitted — the behavior is unsupported and ' +
    
  84.         'could change in a future version.',
    
  85.     );
    
  86.   });
    
  87. 
    
  88.   it('warns for duplicated array keys with component stack info', () => {
    
  89.     class Component extends React.Component {
    
  90.       render() {
    
  91.         return <div>{[<div key="1" />, <div key="1" />]}</div>;
    
  92.       }
    
  93.     }
    
  94. 
    
  95.     class Parent extends React.Component {
    
  96.       render() {
    
  97.         return React.cloneElement(this.props.child);
    
  98.       }
    
  99.     }
    
  100. 
    
  101.     class GrandParent extends React.Component {
    
  102.       render() {
    
  103.         return <Parent child={<Component />} />;
    
  104.       }
    
  105.     }
    
  106. 
    
  107.     expect(() => ReactTestUtils.renderIntoDocument(<GrandParent />)).toErrorDev(
    
  108.       'Encountered two children with the same key, `1`. ' +
    
  109.         'Keys should be unique so that components maintain their identity ' +
    
  110.         'across updates. Non-unique keys may cause children to be ' +
    
  111.         'duplicated and/or omitted — the behavior is unsupported and ' +
    
  112.         'could change in a future version.\n' +
    
  113.         '    in div (at **)\n' +
    
  114.         '    in Component (at **)\n' +
    
  115.         '    in Parent (at **)\n' +
    
  116.         '    in GrandParent (at **)',
    
  117.     );
    
  118.   });
    
  119. 
    
  120.   it('warns for duplicated iterable keys', () => {
    
  121.     class Component extends React.Component {
    
  122.       render() {
    
  123.         return <div>{createIterable([<div key="1" />, <div key="1" />])}</div>;
    
  124.       }
    
  125.     }
    
  126. 
    
  127.     expect(() => ReactTestUtils.renderIntoDocument(<Component />)).toErrorDev(
    
  128.       'Keys should be unique so that components maintain their identity ' +
    
  129.         'across updates. Non-unique keys may cause children to be ' +
    
  130.         'duplicated and/or omitted — the behavior is unsupported and ' +
    
  131.         'could change in a future version.',
    
  132.     );
    
  133.   });
    
  134. 
    
  135.   it('warns for duplicated iterable keys with component stack info', () => {
    
  136.     class Component extends React.Component {
    
  137.       render() {
    
  138.         return <div>{createIterable([<div key="1" />, <div key="1" />])}</div>;
    
  139.       }
    
  140.     }
    
  141. 
    
  142.     class Parent extends React.Component {
    
  143.       render() {
    
  144.         return React.cloneElement(this.props.child);
    
  145.       }
    
  146.     }
    
  147. 
    
  148.     class GrandParent extends React.Component {
    
  149.       render() {
    
  150.         return <Parent child={<Component />} />;
    
  151.       }
    
  152.     }
    
  153. 
    
  154.     expect(() => ReactTestUtils.renderIntoDocument(<GrandParent />)).toErrorDev(
    
  155.       'Encountered two children with the same key, `1`. ' +
    
  156.         'Keys should be unique so that components maintain their identity ' +
    
  157.         'across updates. Non-unique keys may cause children to be ' +
    
  158.         'duplicated and/or omitted — the behavior is unsupported and ' +
    
  159.         'could change in a future version.\n' +
    
  160.         '    in div (at **)\n' +
    
  161.         '    in Component (at **)\n' +
    
  162.         '    in Parent (at **)\n' +
    
  163.         '    in GrandParent (at **)',
    
  164.     );
    
  165.   });
    
  166. });