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.  * @noflow
    
  8.  */
    
  9. 
    
  10. import * as React from 'react';
    
  11. import * as ReactDOM from 'react-dom';
    
  12. import {findCurrentFiberUsingSlowPath} from 'react-reconciler/src/ReactFiberTreeReflection';
    
  13. import {get as getInstance} from 'shared/ReactInstanceMap';
    
  14. import {
    
  15.   ClassComponent,
    
  16.   FunctionComponent,
    
  17.   HostComponent,
    
  18.   HostHoistable,
    
  19.   HostSingleton,
    
  20.   HostText,
    
  21. } from 'react-reconciler/src/ReactWorkTags';
    
  22. import {SyntheticEvent} from 'react-dom-bindings/src/events/SyntheticEvent';
    
  23. import {ELEMENT_NODE} from 'react-dom-bindings/src/client/HTMLNodeType';
    
  24. import {
    
  25.   rethrowCaughtError,
    
  26.   invokeGuardedCallbackAndCatchFirstError,
    
  27. } from 'shared/ReactErrorUtils';
    
  28. import {enableFloat, enableHostSingletons} from 'shared/ReactFeatureFlags';
    
  29. import assign from 'shared/assign';
    
  30. import isArray from 'shared/isArray';
    
  31. 
    
  32. // Keep in sync with ReactDOM.js:
    
  33. const SecretInternals =
    
  34.   ReactDOM.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
    
  35. const EventInternals = SecretInternals.Events;
    
  36. const getInstanceFromNode = EventInternals[0];
    
  37. const getNodeFromInstance = EventInternals[1];
    
  38. const getFiberCurrentPropsFromNode = EventInternals[2];
    
  39. const enqueueStateRestore = EventInternals[3];
    
  40. const restoreStateIfNeeded = EventInternals[4];
    
  41. 
    
  42. const act = React.unstable_act;
    
  43. 
    
  44. function Event(suffix) {}
    
  45. 
    
  46. let hasWarnedAboutDeprecatedMockComponent = false;
    
  47. 
    
  48. /**
    
  49.  * @class ReactTestUtils
    
  50.  */
    
  51. 
    
  52. function findAllInRenderedFiberTreeInternal(fiber, test) {
    
  53.   if (!fiber) {
    
  54.     return [];
    
  55.   }
    
  56.   const currentParent = findCurrentFiberUsingSlowPath(fiber);
    
  57.   if (!currentParent) {
    
  58.     return [];
    
  59.   }
    
  60.   let node = currentParent;
    
  61.   const ret = [];
    
  62.   while (true) {
    
  63.     if (
    
  64.       node.tag === HostComponent ||
    
  65.       node.tag === HostText ||
    
  66.       node.tag === ClassComponent ||
    
  67.       node.tag === FunctionComponent ||
    
  68.       (enableFloat ? node.tag === HostHoistable : false) ||
    
  69.       (enableHostSingletons ? node.tag === HostSingleton : false)
    
  70.     ) {
    
  71.       const publicInst = node.stateNode;
    
  72.       if (test(publicInst)) {
    
  73.         ret.push(publicInst);
    
  74.       }
    
  75.     }
    
  76.     if (node.child) {
    
  77.       node.child.return = node;
    
  78.       node = node.child;
    
  79.       continue;
    
  80.     }
    
  81.     if (node === currentParent) {
    
  82.       return ret;
    
  83.     }
    
  84.     while (!node.sibling) {
    
  85.       if (!node.return || node.return === currentParent) {
    
  86.         return ret;
    
  87.       }
    
  88.       node = node.return;
    
  89.     }
    
  90.     node.sibling.return = node.return;
    
  91.     node = node.sibling;
    
  92.   }
    
  93. }
    
  94. 
    
  95. function validateClassInstance(inst, methodName) {
    
  96.   if (!inst) {
    
  97.     // This is probably too relaxed but it's existing behavior.
    
  98.     return;
    
  99.   }
    
  100.   if (getInstance(inst)) {
    
  101.     // This is a public instance indeed.
    
  102.     return;
    
  103.   }
    
  104.   let received;
    
  105.   const stringified = String(inst);
    
  106.   if (isArray(inst)) {
    
  107.     received = 'an array';
    
  108.   } else if (inst && inst.nodeType === ELEMENT_NODE && inst.tagName) {
    
  109.     received = 'a DOM node';
    
  110.   } else if (stringified === '[object Object]') {
    
  111.     received = 'object with keys {' + Object.keys(inst).join(', ') + '}';
    
  112.   } else {
    
  113.     received = stringified;
    
  114.   }
    
  115. 
    
  116.   throw new Error(
    
  117.     `${methodName}(...): the first argument must be a React class instance. ` +
    
  118.       `Instead received: ${received}.`,
    
  119.   );
    
  120. }
    
  121. 
    
  122. /**
    
  123.  * Utilities for making it easy to test React components.
    
  124.  *
    
  125.  * See https://reactjs.org/docs/test-utils.html
    
  126.  *
    
  127.  * Todo: Support the entire DOM.scry query syntax. For now, these simple
    
  128.  * utilities will suffice for testing purposes.
    
  129.  * @lends ReactTestUtils
    
  130.  */
    
  131. function renderIntoDocument(element) {
    
  132.   const div = document.createElement('div');
    
  133.   // None of our tests actually require attaching the container to the
    
  134.   // DOM, and doing so creates a mess that we rely on test isolation to
    
  135.   // clean up, so we're going to stop honoring the name of this method
    
  136.   // (and probably rename it eventually) if no problems arise.
    
  137.   // document.documentElement.appendChild(div);
    
  138.   return ReactDOM.render(element, div);
    
  139. }
    
  140. 
    
  141. function isElement(element) {
    
  142.   return React.isValidElement(element);
    
  143. }
    
  144. 
    
  145. function isElementOfType(inst, convenienceConstructor) {
    
  146.   return React.isValidElement(inst) && inst.type === convenienceConstructor;
    
  147. }
    
  148. 
    
  149. function isDOMComponent(inst) {
    
  150.   return !!(inst && inst.nodeType === ELEMENT_NODE && inst.tagName);
    
  151. }
    
  152. 
    
  153. function isDOMComponentElement(inst) {
    
  154.   return !!(inst && React.isValidElement(inst) && !!inst.tagName);
    
  155. }
    
  156. 
    
  157. function isCompositeComponent(inst) {
    
  158.   if (isDOMComponent(inst)) {
    
  159.     // Accessing inst.setState warns; just return false as that'll be what
    
  160.     // this returns when we have DOM nodes as refs directly
    
  161.     return false;
    
  162.   }
    
  163.   return (
    
  164.     inst != null &&
    
  165.     typeof inst.render === 'function' &&
    
  166.     typeof inst.setState === 'function'
    
  167.   );
    
  168. }
    
  169. 
    
  170. function isCompositeComponentWithType(inst, type) {
    
  171.   if (!isCompositeComponent(inst)) {
    
  172.     return false;
    
  173.   }
    
  174.   const internalInstance = getInstance(inst);
    
  175.   const constructor = internalInstance.type;
    
  176.   return constructor === type;
    
  177. }
    
  178. 
    
  179. function findAllInRenderedTree(inst, test) {
    
  180.   validateClassInstance(inst, 'findAllInRenderedTree');
    
  181.   if (!inst) {
    
  182.     return [];
    
  183.   }
    
  184.   const internalInstance = getInstance(inst);
    
  185.   return findAllInRenderedFiberTreeInternal(internalInstance, test);
    
  186. }
    
  187. 
    
  188. /**
    
  189.  * Finds all instances of components in the rendered tree that are DOM
    
  190.  * components with the class name matching `className`.
    
  191.  * @return {array} an array of all the matches.
    
  192.  */
    
  193. function scryRenderedDOMComponentsWithClass(root, classNames) {
    
  194.   validateClassInstance(root, 'scryRenderedDOMComponentsWithClass');
    
  195.   return findAllInRenderedTree(root, function (inst) {
    
  196.     if (isDOMComponent(inst)) {
    
  197.       let className = inst.className;
    
  198.       if (typeof className !== 'string') {
    
  199.         // SVG, probably.
    
  200.         className = inst.getAttribute('class') || '';
    
  201.       }
    
  202.       const classList = className.split(/\s+/);
    
  203. 
    
  204.       if (!isArray(classNames)) {
    
  205.         if (classNames === undefined) {
    
  206.           throw new Error(
    
  207.             'TestUtils.scryRenderedDOMComponentsWithClass expects a ' +
    
  208.               'className as a second argument.',
    
  209.           );
    
  210.         }
    
  211. 
    
  212.         classNames = classNames.split(/\s+/);
    
  213.       }
    
  214.       return classNames.every(function (name) {
    
  215.         return classList.indexOf(name) !== -1;
    
  216.       });
    
  217.     }
    
  218.     return false;
    
  219.   });
    
  220. }
    
  221. 
    
  222. /**
    
  223.  * Like scryRenderedDOMComponentsWithClass but expects there to be one result,
    
  224.  * and returns that one result, or throws exception if there is any other
    
  225.  * number of matches besides one.
    
  226.  * @return {!ReactDOMComponent} The one match.
    
  227.  */
    
  228. function findRenderedDOMComponentWithClass(root, className) {
    
  229.   validateClassInstance(root, 'findRenderedDOMComponentWithClass');
    
  230.   const all = scryRenderedDOMComponentsWithClass(root, className);
    
  231.   if (all.length !== 1) {
    
  232.     throw new Error(
    
  233.       'Did not find exactly one match (found: ' +
    
  234.         all.length +
    
  235.         ') ' +
    
  236.         'for class:' +
    
  237.         className,
    
  238.     );
    
  239.   }
    
  240.   return all[0];
    
  241. }
    
  242. 
    
  243. /**
    
  244.  * Finds all instances of components in the rendered tree that are DOM
    
  245.  * components with the tag name matching `tagName`.
    
  246.  * @return {array} an array of all the matches.
    
  247.  */
    
  248. function scryRenderedDOMComponentsWithTag(root, tagName) {
    
  249.   validateClassInstance(root, 'scryRenderedDOMComponentsWithTag');
    
  250.   return findAllInRenderedTree(root, function (inst) {
    
  251.     return (
    
  252.       isDOMComponent(inst) &&
    
  253.       inst.tagName.toUpperCase() === tagName.toUpperCase()
    
  254.     );
    
  255.   });
    
  256. }
    
  257. 
    
  258. /**
    
  259.  * Like scryRenderedDOMComponentsWithTag but expects there to be one result,
    
  260.  * and returns that one result, or throws exception if there is any other
    
  261.  * number of matches besides one.
    
  262.  * @return {!ReactDOMComponent} The one match.
    
  263.  */
    
  264. function findRenderedDOMComponentWithTag(root, tagName) {
    
  265.   validateClassInstance(root, 'findRenderedDOMComponentWithTag');
    
  266.   const all = scryRenderedDOMComponentsWithTag(root, tagName);
    
  267.   if (all.length !== 1) {
    
  268.     throw new Error(
    
  269.       'Did not find exactly one match (found: ' +
    
  270.         all.length +
    
  271.         ') ' +
    
  272.         'for tag:' +
    
  273.         tagName,
    
  274.     );
    
  275.   }
    
  276.   return all[0];
    
  277. }
    
  278. 
    
  279. /**
    
  280.  * Finds all instances of components with type equal to `componentType`.
    
  281.  * @return {array} an array of all the matches.
    
  282.  */
    
  283. function scryRenderedComponentsWithType(root, componentType) {
    
  284.   validateClassInstance(root, 'scryRenderedComponentsWithType');
    
  285.   return findAllInRenderedTree(root, function (inst) {
    
  286.     return isCompositeComponentWithType(inst, componentType);
    
  287.   });
    
  288. }
    
  289. 
    
  290. /**
    
  291.  * Same as `scryRenderedComponentsWithType` but expects there to be one result
    
  292.  * and returns that one result, or throws exception if there is any other
    
  293.  * number of matches besides one.
    
  294.  * @return {!ReactComponent} The one match.
    
  295.  */
    
  296. function findRenderedComponentWithType(root, componentType) {
    
  297.   validateClassInstance(root, 'findRenderedComponentWithType');
    
  298.   const all = scryRenderedComponentsWithType(root, componentType);
    
  299.   if (all.length !== 1) {
    
  300.     throw new Error(
    
  301.       'Did not find exactly one match (found: ' +
    
  302.         all.length +
    
  303.         ') ' +
    
  304.         'for componentType:' +
    
  305.         componentType,
    
  306.     );
    
  307.   }
    
  308.   return all[0];
    
  309. }
    
  310. 
    
  311. /**
    
  312.  * Pass a mocked component module to this method to augment it with
    
  313.  * useful methods that allow it to be used as a dummy React component.
    
  314.  * Instead of rendering as usual, the component will become a simple
    
  315.  * <div> containing any provided children.
    
  316.  *
    
  317.  * @param {object} module the mock function object exported from a
    
  318.  *                        module that defines the component to be mocked
    
  319.  * @param {?string} mockTagName optional dummy root tag name to return
    
  320.  *                              from render method (overrides
    
  321.  *                              module.mockTagName if provided)
    
  322.  * @return {object} the ReactTestUtils object (for chaining)
    
  323.  */
    
  324. function mockComponent(module, mockTagName) {
    
  325.   if (__DEV__) {
    
  326.     if (!hasWarnedAboutDeprecatedMockComponent) {
    
  327.       hasWarnedAboutDeprecatedMockComponent = true;
    
  328.       console.warn(
    
  329.         'ReactTestUtils.mockComponent() is deprecated. ' +
    
  330.           'Use shallow rendering or jest.mock() instead.\n\n' +
    
  331.           'See https://reactjs.org/link/test-utils-mock-component for more information.',
    
  332.       );
    
  333.     }
    
  334.   }
    
  335. 
    
  336.   mockTagName = mockTagName || module.mockTagName || 'div';
    
  337. 
    
  338.   module.prototype.render.mockImplementation(function () {
    
  339.     return React.createElement(mockTagName, null, this.props.children);
    
  340.   });
    
  341. 
    
  342.   return this;
    
  343. }
    
  344. 
    
  345. function nativeTouchData(x, y) {
    
  346.   return {
    
  347.     touches: [{pageX: x, pageY: y}],
    
  348.   };
    
  349. }
    
  350. 
    
  351. // Start of inline: the below functions were inlined from
    
  352. // EventPropagator.js, as they deviated from ReactDOM's newer
    
  353. // implementations.
    
  354. 
    
  355. /**
    
  356.  * Dispatch the event to the listener.
    
  357.  * @param {SyntheticEvent} event SyntheticEvent to handle
    
  358.  * @param {function} listener Application-level callback
    
  359.  * @param {*} inst Internal component instance
    
  360.  */
    
  361. function executeDispatch(event, listener, inst) {
    
  362.   const type = event.type || 'unknown-event';
    
  363.   event.currentTarget = getNodeFromInstance(inst);
    
  364.   invokeGuardedCallbackAndCatchFirstError(type, listener, undefined, event);
    
  365.   event.currentTarget = null;
    
  366. }
    
  367. 
    
  368. /**
    
  369.  * Standard/simple iteration through an event's collected dispatches.
    
  370.  */
    
  371. function executeDispatchesInOrder(event) {
    
  372.   const dispatchListeners = event._dispatchListeners;
    
  373.   const dispatchInstances = event._dispatchInstances;
    
  374.   if (isArray(dispatchListeners)) {
    
  375.     for (let i = 0; i < dispatchListeners.length; i++) {
    
  376.       if (event.isPropagationStopped()) {
    
  377.         break;
    
  378.       }
    
  379.       // Listeners and Instances are two parallel arrays that are always in sync.
    
  380.       executeDispatch(event, dispatchListeners[i], dispatchInstances[i]);
    
  381.     }
    
  382.   } else if (dispatchListeners) {
    
  383.     executeDispatch(event, dispatchListeners, dispatchInstances);
    
  384.   }
    
  385.   event._dispatchListeners = null;
    
  386.   event._dispatchInstances = null;
    
  387. }
    
  388. 
    
  389. /**
    
  390.  * Dispatches an event and releases it back into the pool, unless persistent.
    
  391.  *
    
  392.  * @param {?object} event Synthetic event to be dispatched.
    
  393.  * @private
    
  394.  */
    
  395. function executeDispatchesAndRelease(event /* ReactSyntheticEvent */) {
    
  396.   if (event) {
    
  397.     executeDispatchesInOrder(event);
    
  398. 
    
  399.     if (!event.isPersistent()) {
    
  400.       event.constructor.release(event);
    
  401.     }
    
  402.   }
    
  403. }
    
  404. 
    
  405. function isInteractive(tag) {
    
  406.   return (
    
  407.     tag === 'button' ||
    
  408.     tag === 'input' ||
    
  409.     tag === 'select' ||
    
  410.     tag === 'textarea'
    
  411.   );
    
  412. }
    
  413. 
    
  414. function getParent(inst) {
    
  415.   do {
    
  416.     inst = inst.return;
    
  417.     // TODO: If this is a HostRoot we might want to bail out.
    
  418.     // That is depending on if we want nested subtrees (layers) to bubble
    
  419.     // events to their parent. We could also go through parentNode on the
    
  420.     // host node but that wouldn't work for React Native and doesn't let us
    
  421.     // do the portal feature.
    
  422.   } while (
    
  423.     inst &&
    
  424.     inst.tag !== HostComponent &&
    
  425.     (!enableHostSingletons ? true : inst.tag !== HostSingleton)
    
  426.   );
    
  427.   if (inst) {
    
  428.     return inst;
    
  429.   }
    
  430.   return null;
    
  431. }
    
  432. 
    
  433. /**
    
  434.  * Simulates the traversal of a two-phase, capture/bubble event dispatch.
    
  435.  */
    
  436. export function traverseTwoPhase(inst, fn, arg) {
    
  437.   const path = [];
    
  438.   while (inst) {
    
  439.     path.push(inst);
    
  440.     inst = getParent(inst);
    
  441.   }
    
  442.   let i;
    
  443.   for (i = path.length; i-- > 0; ) {
    
  444.     fn(path[i], 'captured', arg);
    
  445.   }
    
  446.   for (i = 0; i < path.length; i++) {
    
  447.     fn(path[i], 'bubbled', arg);
    
  448.   }
    
  449. }
    
  450. 
    
  451. function shouldPreventMouseEvent(name, type, props) {
    
  452.   switch (name) {
    
  453.     case 'onClick':
    
  454.     case 'onClickCapture':
    
  455.     case 'onDoubleClick':
    
  456.     case 'onDoubleClickCapture':
    
  457.     case 'onMouseDown':
    
  458.     case 'onMouseDownCapture':
    
  459.     case 'onMouseMove':
    
  460.     case 'onMouseMoveCapture':
    
  461.     case 'onMouseUp':
    
  462.     case 'onMouseUpCapture':
    
  463.     case 'onMouseEnter':
    
  464.       return !!(props.disabled && isInteractive(type));
    
  465.     default:
    
  466.       return false;
    
  467.   }
    
  468. }
    
  469. 
    
  470. /**
    
  471.  * @param {object} inst The instance, which is the source of events.
    
  472.  * @param {string} registrationName Name of listener (e.g. `onClick`).
    
  473.  * @return {?function} The stored callback.
    
  474.  */
    
  475. function getListener(inst /* Fiber */, registrationName: string) {
    
  476.   // TODO: shouldPreventMouseEvent is DOM-specific and definitely should not
    
  477.   // live here; needs to be moved to a better place soon
    
  478.   const stateNode = inst.stateNode;
    
  479.   if (!stateNode) {
    
  480.     // Work in progress (ex: onload events in incremental mode).
    
  481.     return null;
    
  482.   }
    
  483.   const props = getFiberCurrentPropsFromNode(stateNode);
    
  484.   if (!props) {
    
  485.     // Work in progress.
    
  486.     return null;
    
  487.   }
    
  488.   const listener = props[registrationName];
    
  489.   if (shouldPreventMouseEvent(registrationName, inst.type, props)) {
    
  490.     return null;
    
  491.   }
    
  492. 
    
  493.   if (listener && typeof listener !== 'function') {
    
  494.     throw new Error(
    
  495.       `Expected \`${registrationName}\` listener to be a function, instead got a value of \`${typeof listener}\` type.`,
    
  496.     );
    
  497.   }
    
  498. 
    
  499.   return listener;
    
  500. }
    
  501. 
    
  502. function listenerAtPhase(inst, event, propagationPhase: PropagationPhases) {
    
  503.   let registrationName = event._reactName;
    
  504.   if (propagationPhase === 'captured') {
    
  505.     registrationName += 'Capture';
    
  506.   }
    
  507.   return getListener(inst, registrationName);
    
  508. }
    
  509. 
    
  510. function accumulateDispatches(inst, ignoredDirection, event) {
    
  511.   if (inst && event && event._reactName) {
    
  512.     const registrationName = event._reactName;
    
  513.     const listener = getListener(inst, registrationName);
    
  514.     if (listener) {
    
  515.       if (event._dispatchListeners == null) {
    
  516.         event._dispatchListeners = [];
    
  517.       }
    
  518.       if (event._dispatchInstances == null) {
    
  519.         event._dispatchInstances = [];
    
  520.       }
    
  521.       event._dispatchListeners.push(listener);
    
  522.       event._dispatchInstances.push(inst);
    
  523.     }
    
  524.   }
    
  525. }
    
  526. 
    
  527. function accumulateDirectionalDispatches(inst, phase, event) {
    
  528.   if (__DEV__) {
    
  529.     if (!inst) {
    
  530.       console.error('Dispatching inst must not be null');
    
  531.     }
    
  532.   }
    
  533.   const listener = listenerAtPhase(inst, event, phase);
    
  534.   if (listener) {
    
  535.     if (event._dispatchListeners == null) {
    
  536.       event._dispatchListeners = [];
    
  537.     }
    
  538.     if (event._dispatchInstances == null) {
    
  539.       event._dispatchInstances = [];
    
  540.     }
    
  541.     event._dispatchListeners.push(listener);
    
  542.     event._dispatchInstances.push(inst);
    
  543.   }
    
  544. }
    
  545. 
    
  546. function accumulateDirectDispatchesSingle(event) {
    
  547.   if (event && event._reactName) {
    
  548.     accumulateDispatches(event._targetInst, null, event);
    
  549.   }
    
  550. }
    
  551. 
    
  552. function accumulateTwoPhaseDispatchesSingle(event) {
    
  553.   if (event && event._reactName) {
    
  554.     traverseTwoPhase(event._targetInst, accumulateDirectionalDispatches, event);
    
  555.   }
    
  556. }
    
  557. 
    
  558. // End of inline
    
  559. 
    
  560. const Simulate = {};
    
  561. 
    
  562. const directDispatchEventTypes = new Set([
    
  563.   'mouseEnter',
    
  564.   'mouseLeave',
    
  565.   'pointerEnter',
    
  566.   'pointerLeave',
    
  567. ]);
    
  568. 
    
  569. /**
    
  570.  * Exports:
    
  571.  *
    
  572.  * - `Simulate.click(Element)`
    
  573.  * - `Simulate.mouseMove(Element)`
    
  574.  * - `Simulate.change(Element)`
    
  575.  * - ... (All keys from event plugin `eventTypes` objects)
    
  576.  */
    
  577. function makeSimulator(eventType) {
    
  578.   return function (domNode, eventData) {
    
  579.     if (React.isValidElement(domNode)) {
    
  580.       throw new Error(
    
  581.         'TestUtils.Simulate expected a DOM node as the first argument but received ' +
    
  582.           'a React element. Pass the DOM node you wish to simulate the event on instead. ' +
    
  583.           'Note that TestUtils.Simulate will not work if you are using shallow rendering.',
    
  584.       );
    
  585.     }
    
  586. 
    
  587.     if (isCompositeComponent(domNode)) {
    
  588.       throw new Error(
    
  589.         'TestUtils.Simulate expected a DOM node as the first argument but received ' +
    
  590.           'a component instance. Pass the DOM node you wish to simulate the event on instead.',
    
  591.       );
    
  592.     }
    
  593. 
    
  594.     const reactName = 'on' + eventType[0].toUpperCase() + eventType.slice(1);
    
  595.     const fakeNativeEvent = new Event();
    
  596.     fakeNativeEvent.target = domNode;
    
  597.     fakeNativeEvent.type = eventType.toLowerCase();
    
  598. 
    
  599.     const targetInst = getInstanceFromNode(domNode);
    
  600.     const event = new SyntheticEvent(
    
  601.       reactName,
    
  602.       fakeNativeEvent.type,
    
  603.       targetInst,
    
  604.       fakeNativeEvent,
    
  605.       domNode,
    
  606.     );
    
  607. 
    
  608.     // Since we aren't using pooling, always persist the event. This will make
    
  609.     // sure it's marked and won't warn when setting additional properties.
    
  610.     event.persist();
    
  611.     assign(event, eventData);
    
  612. 
    
  613.     if (directDispatchEventTypes.has(eventType)) {
    
  614.       accumulateDirectDispatchesSingle(event);
    
  615.     } else {
    
  616.       accumulateTwoPhaseDispatchesSingle(event);
    
  617.     }
    
  618. 
    
  619.     ReactDOM.unstable_batchedUpdates(function () {
    
  620.       // Normally extractEvent enqueues a state restore, but we'll just always
    
  621.       // do that since we're by-passing it here.
    
  622.       enqueueStateRestore(domNode);
    
  623.       executeDispatchesAndRelease(event);
    
  624.       rethrowCaughtError();
    
  625.     });
    
  626.     restoreStateIfNeeded();
    
  627.   };
    
  628. }
    
  629. 
    
  630. // A one-time snapshot with no plans to update. We'll probably want to deprecate Simulate API.
    
  631. const simulatedEventTypes = [
    
  632.   'blur',
    
  633.   'cancel',
    
  634.   'click',
    
  635.   'close',
    
  636.   'contextMenu',
    
  637.   'copy',
    
  638.   'cut',
    
  639.   'auxClick',
    
  640.   'doubleClick',
    
  641.   'dragEnd',
    
  642.   'dragStart',
    
  643.   'drop',
    
  644.   'focus',
    
  645.   'input',
    
  646.   'invalid',
    
  647.   'keyDown',
    
  648.   'keyPress',
    
  649.   'keyUp',
    
  650.   'mouseDown',
    
  651.   'mouseUp',
    
  652.   'paste',
    
  653.   'pause',
    
  654.   'play',
    
  655.   'pointerCancel',
    
  656.   'pointerDown',
    
  657.   'pointerUp',
    
  658.   'rateChange',
    
  659.   'reset',
    
  660.   'resize',
    
  661.   'seeked',
    
  662.   'submit',
    
  663.   'touchCancel',
    
  664.   'touchEnd',
    
  665.   'touchStart',
    
  666.   'volumeChange',
    
  667.   'drag',
    
  668.   'dragEnter',
    
  669.   'dragExit',
    
  670.   'dragLeave',
    
  671.   'dragOver',
    
  672.   'mouseMove',
    
  673.   'mouseOut',
    
  674.   'mouseOver',
    
  675.   'pointerMove',
    
  676.   'pointerOut',
    
  677.   'pointerOver',
    
  678.   'scroll',
    
  679.   'toggle',
    
  680.   'touchMove',
    
  681.   'wheel',
    
  682.   'abort',
    
  683.   'animationEnd',
    
  684.   'animationIteration',
    
  685.   'animationStart',
    
  686.   'canPlay',
    
  687.   'canPlayThrough',
    
  688.   'durationChange',
    
  689.   'emptied',
    
  690.   'encrypted',
    
  691.   'ended',
    
  692.   'error',
    
  693.   'gotPointerCapture',
    
  694.   'load',
    
  695.   'loadedData',
    
  696.   'loadedMetadata',
    
  697.   'loadStart',
    
  698.   'lostPointerCapture',
    
  699.   'playing',
    
  700.   'progress',
    
  701.   'seeking',
    
  702.   'stalled',
    
  703.   'suspend',
    
  704.   'timeUpdate',
    
  705.   'transitionEnd',
    
  706.   'waiting',
    
  707.   'mouseEnter',
    
  708.   'mouseLeave',
    
  709.   'pointerEnter',
    
  710.   'pointerLeave',
    
  711.   'change',
    
  712.   'select',
    
  713.   'beforeInput',
    
  714.   'compositionEnd',
    
  715.   'compositionStart',
    
  716.   'compositionUpdate',
    
  717. ];
    
  718. function buildSimulators() {
    
  719.   simulatedEventTypes.forEach(eventType => {
    
  720.     Simulate[eventType] = makeSimulator(eventType);
    
  721.   });
    
  722. }
    
  723. buildSimulators();
    
  724. 
    
  725. export {
    
  726.   renderIntoDocument,
    
  727.   isElement,
    
  728.   isElementOfType,
    
  729.   isDOMComponent,
    
  730.   isDOMComponentElement,
    
  731.   isCompositeComponent,
    
  732.   isCompositeComponentWithType,
    
  733.   findAllInRenderedTree,
    
  734.   scryRenderedDOMComponentsWithClass,
    
  735.   findRenderedDOMComponentWithClass,
    
  736.   scryRenderedDOMComponentsWithTag,
    
  737.   findRenderedDOMComponentWithTag,
    
  738.   scryRenderedComponentsWithType,
    
  739.   findRenderedComponentWithType,
    
  740.   mockComponent,
    
  741.   nativeTouchData,
    
  742.   Simulate,
    
  743.   act,
    
  744. };