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. let React;
    
  13. let ReactDOM;
    
  14. let ReactIs;
    
  15. let SuspenseList;
    
  16. 
    
  17. describe('ReactIs', () => {
    
  18.   beforeEach(() => {
    
  19.     jest.resetModules();
    
  20. 
    
  21.     React = require('react');
    
  22.     ReactDOM = require('react-dom');
    
  23.     ReactIs = require('react-is');
    
  24. 
    
  25.     if (gate(flags => flags.enableSuspenseList)) {
    
  26.       SuspenseList = React.unstable_SuspenseList;
    
  27.     }
    
  28.   });
    
  29. 
    
  30.   it('should return undefined for unknown/invalid types', () => {
    
  31.     expect(ReactIs.typeOf('abc')).toBe(undefined);
    
  32.     expect(ReactIs.typeOf(true)).toBe(undefined);
    
  33.     expect(ReactIs.typeOf(123)).toBe(undefined);
    
  34.     expect(ReactIs.typeOf({})).toBe(undefined);
    
  35.     expect(ReactIs.typeOf(null)).toBe(undefined);
    
  36.     expect(ReactIs.typeOf(undefined)).toBe(undefined);
    
  37.     expect(ReactIs.typeOf(NaN)).toBe(undefined);
    
  38.     expect(ReactIs.typeOf(Symbol('def'))).toBe(undefined);
    
  39.   });
    
  40. 
    
  41.   it('identifies valid element types', () => {
    
  42.     class Component extends React.Component {
    
  43.       render() {
    
  44.         return React.createElement('div');
    
  45.       }
    
  46.     }
    
  47.     class PureComponent extends React.PureComponent {
    
  48.       render() {
    
  49.         return React.createElement('div');
    
  50.       }
    
  51.     }
    
  52. 
    
  53.     const FunctionComponent = () => React.createElement('div');
    
  54.     const ForwardRefComponent = React.forwardRef((props, ref) =>
    
  55.       React.createElement(Component, {forwardedRef: ref, ...props}),
    
  56.     );
    
  57.     const LazyComponent = React.lazy(() => Component);
    
  58.     const MemoComponent = React.memo(Component);
    
  59.     const Context = React.createContext(false);
    
  60. 
    
  61.     expect(ReactIs.isValidElementType('div')).toEqual(true);
    
  62.     expect(ReactIs.isValidElementType(Component)).toEqual(true);
    
  63.     expect(ReactIs.isValidElementType(PureComponent)).toEqual(true);
    
  64.     expect(ReactIs.isValidElementType(FunctionComponent)).toEqual(true);
    
  65.     expect(ReactIs.isValidElementType(ForwardRefComponent)).toEqual(true);
    
  66.     expect(ReactIs.isValidElementType(LazyComponent)).toEqual(true);
    
  67.     expect(ReactIs.isValidElementType(MemoComponent)).toEqual(true);
    
  68.     expect(ReactIs.isValidElementType(Context.Provider)).toEqual(true);
    
  69.     expect(ReactIs.isValidElementType(Context.Consumer)).toEqual(true);
    
  70.     if (!__EXPERIMENTAL__) {
    
  71.       let factory;
    
  72.       expect(() => {
    
  73.         factory = React.createFactory('div');
    
  74.       }).toWarnDev(
    
  75.         'Warning: React.createFactory() is deprecated and will be removed in a ' +
    
  76.           'future major release. Consider using JSX or use React.createElement() ' +
    
  77.           'directly instead.',
    
  78.         {withoutStack: true},
    
  79.       );
    
  80.       expect(ReactIs.isValidElementType(factory)).toEqual(true);
    
  81.     }
    
  82.     expect(ReactIs.isValidElementType(React.Fragment)).toEqual(true);
    
  83.     expect(ReactIs.isValidElementType(React.StrictMode)).toEqual(true);
    
  84.     expect(ReactIs.isValidElementType(React.Suspense)).toEqual(true);
    
  85. 
    
  86.     expect(ReactIs.isValidElementType(true)).toEqual(false);
    
  87.     expect(ReactIs.isValidElementType(123)).toEqual(false);
    
  88.     expect(ReactIs.isValidElementType({})).toEqual(false);
    
  89.     expect(ReactIs.isValidElementType(null)).toEqual(false);
    
  90.     expect(ReactIs.isValidElementType(undefined)).toEqual(false);
    
  91.     expect(ReactIs.isValidElementType({type: 'div', props: {}})).toEqual(false);
    
  92.   });
    
  93. 
    
  94.   it('should identify context consumers', () => {
    
  95.     const Context = React.createContext(false);
    
  96.     expect(ReactIs.isValidElementType(Context.Consumer)).toBe(true);
    
  97.     expect(ReactIs.typeOf(<Context.Consumer />)).toBe(ReactIs.ContextConsumer);
    
  98.     expect(ReactIs.isContextConsumer(<Context.Consumer />)).toBe(true);
    
  99.     expect(ReactIs.isContextConsumer(<Context.Provider />)).toBe(false);
    
  100.     expect(ReactIs.isContextConsumer(<div />)).toBe(false);
    
  101.   });
    
  102. 
    
  103.   it('should identify context providers', () => {
    
  104.     const Context = React.createContext(false);
    
  105.     expect(ReactIs.isValidElementType(Context.Provider)).toBe(true);
    
  106.     expect(ReactIs.typeOf(<Context.Provider />)).toBe(ReactIs.ContextProvider);
    
  107.     expect(ReactIs.isContextProvider(<Context.Provider />)).toBe(true);
    
  108.     expect(ReactIs.isContextProvider(<Context.Consumer />)).toBe(false);
    
  109.     expect(ReactIs.isContextProvider(<div />)).toBe(false);
    
  110.   });
    
  111. 
    
  112.   it('should identify elements', () => {
    
  113.     expect(ReactIs.typeOf(<div />)).toBe(ReactIs.Element);
    
  114.     expect(ReactIs.isElement(<div />)).toBe(true);
    
  115.     expect(ReactIs.isElement('div')).toBe(false);
    
  116.     expect(ReactIs.isElement(true)).toBe(false);
    
  117.     expect(ReactIs.isElement(123)).toBe(false);
    
  118.     expect(ReactIs.isElement(null)).toBe(false);
    
  119.     expect(ReactIs.isElement(undefined)).toBe(false);
    
  120.     expect(ReactIs.isElement({})).toBe(false);
    
  121. 
    
  122.     // It should also identify more specific types as elements
    
  123.     const Context = React.createContext(false);
    
  124.     expect(ReactIs.isElement(<Context.Provider />)).toBe(true);
    
  125.     expect(ReactIs.isElement(<Context.Consumer />)).toBe(true);
    
  126.     expect(ReactIs.isElement(<React.Fragment />)).toBe(true);
    
  127.     expect(ReactIs.isElement(<React.StrictMode />)).toBe(true);
    
  128.     expect(ReactIs.isElement(<React.Suspense />)).toBe(true);
    
  129.   });
    
  130. 
    
  131.   it('should identify ref forwarding component', () => {
    
  132.     const RefForwardingComponent = React.forwardRef((props, ref) => null);
    
  133.     expect(ReactIs.isValidElementType(RefForwardingComponent)).toBe(true);
    
  134.     expect(ReactIs.typeOf(<RefForwardingComponent />)).toBe(ReactIs.ForwardRef);
    
  135.     expect(ReactIs.isForwardRef(<RefForwardingComponent />)).toBe(true);
    
  136.     expect(ReactIs.isForwardRef({type: ReactIs.StrictMode})).toBe(false);
    
  137.     expect(ReactIs.isForwardRef(<div />)).toBe(false);
    
  138.   });
    
  139. 
    
  140.   it('should identify fragments', () => {
    
  141.     expect(ReactIs.isValidElementType(React.Fragment)).toBe(true);
    
  142.     expect(ReactIs.typeOf(<React.Fragment />)).toBe(ReactIs.Fragment);
    
  143.     expect(ReactIs.isFragment(<React.Fragment />)).toBe(true);
    
  144.     expect(ReactIs.isFragment({type: ReactIs.Fragment})).toBe(false);
    
  145.     expect(ReactIs.isFragment('React.Fragment')).toBe(false);
    
  146.     expect(ReactIs.isFragment(<div />)).toBe(false);
    
  147.     expect(ReactIs.isFragment([])).toBe(false);
    
  148.   });
    
  149. 
    
  150.   it('should identify portals', () => {
    
  151.     const div = document.createElement('div');
    
  152.     const portal = ReactDOM.createPortal(<div />, div);
    
  153.     expect(ReactIs.isValidElementType(portal)).toBe(false);
    
  154.     expect(ReactIs.typeOf(portal)).toBe(ReactIs.Portal);
    
  155.     expect(ReactIs.isPortal(portal)).toBe(true);
    
  156.     expect(ReactIs.isPortal(div)).toBe(false);
    
  157.   });
    
  158. 
    
  159.   it('should identify memo', () => {
    
  160.     const Component = () => React.createElement('div');
    
  161.     const Memoized = React.memo(Component);
    
  162.     expect(ReactIs.isValidElementType(Memoized)).toBe(true);
    
  163.     expect(ReactIs.typeOf(<Memoized />)).toBe(ReactIs.Memo);
    
  164.     expect(ReactIs.isMemo(<Memoized />)).toBe(true);
    
  165.     expect(ReactIs.isMemo(<Component />)).toBe(false);
    
  166.   });
    
  167. 
    
  168.   it('should identify lazy', () => {
    
  169.     const Component = () => React.createElement('div');
    
  170.     const LazyComponent = React.lazy(() => Component);
    
  171.     expect(ReactIs.isValidElementType(LazyComponent)).toBe(true);
    
  172.     expect(ReactIs.typeOf(<LazyComponent />)).toBe(ReactIs.Lazy);
    
  173.     expect(ReactIs.isLazy(<LazyComponent />)).toBe(true);
    
  174.     expect(ReactIs.isLazy(<Component />)).toBe(false);
    
  175.   });
    
  176. 
    
  177.   it('should identify strict mode', () => {
    
  178.     expect(ReactIs.isValidElementType(React.StrictMode)).toBe(true);
    
  179.     expect(ReactIs.typeOf(<React.StrictMode />)).toBe(ReactIs.StrictMode);
    
  180.     expect(ReactIs.isStrictMode(<React.StrictMode />)).toBe(true);
    
  181.     expect(ReactIs.isStrictMode({type: ReactIs.StrictMode})).toBe(false);
    
  182.     expect(ReactIs.isStrictMode(<div />)).toBe(false);
    
  183.   });
    
  184. 
    
  185.   it('should identify suspense', () => {
    
  186.     expect(ReactIs.isValidElementType(React.Suspense)).toBe(true);
    
  187.     expect(ReactIs.typeOf(<React.Suspense />)).toBe(ReactIs.Suspense);
    
  188.     expect(ReactIs.isSuspense(<React.Suspense />)).toBe(true);
    
  189.     expect(ReactIs.isSuspense({type: ReactIs.Suspense})).toBe(false);
    
  190.     expect(ReactIs.isSuspense('React.Suspense')).toBe(false);
    
  191.     expect(ReactIs.isSuspense(<div />)).toBe(false);
    
  192.   });
    
  193. 
    
  194.   // @gate enableSuspenseList
    
  195.   it('should identify suspense list', () => {
    
  196.     expect(ReactIs.isValidElementType(SuspenseList)).toBe(true);
    
  197.     expect(ReactIs.typeOf(<SuspenseList />)).toBe(ReactIs.SuspenseList);
    
  198.     expect(ReactIs.isSuspenseList(<SuspenseList />)).toBe(true);
    
  199.     expect(ReactIs.isSuspenseList({type: ReactIs.SuspenseList})).toBe(false);
    
  200.     expect(ReactIs.isSuspenseList('React.SuspenseList')).toBe(false);
    
  201.     expect(ReactIs.isSuspenseList(<div />)).toBe(false);
    
  202.   });
    
  203. 
    
  204.   it('should identify profile root', () => {
    
  205.     expect(ReactIs.isValidElementType(React.Profiler)).toBe(true);
    
  206.     expect(
    
  207.       ReactIs.typeOf(<React.Profiler id="foo" onRender={jest.fn()} />),
    
  208.     ).toBe(ReactIs.Profiler);
    
  209.     expect(
    
  210.       ReactIs.isProfiler(<React.Profiler id="foo" onRender={jest.fn()} />),
    
  211.     ).toBe(true);
    
  212.     expect(ReactIs.isProfiler({type: ReactIs.Profiler})).toBe(false);
    
  213.     expect(ReactIs.isProfiler(<div />)).toBe(false);
    
  214.   });
    
  215. });