mirror of
https://github.com/facebook/react.git
synced 2026-02-26 17:35:05 +00:00
* Remove redundant initial of isArray (#21163) * Reapply prettier * Type the isArray function with refinement support This ensures that an argument gets refined just like it does if isArray is used directly. I'm not sure how to express with just a direct reference so I added a function wrapper and confirmed that this does get inlined properly by closure compiler. * A few more * Rename unit test to internal This is not testing a bundle. Co-authored-by: Behnam Mohammadi <itten@live.com>
732 lines
20 KiB
JavaScript
732 lines
20 KiB
JavaScript
/**
|
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
*
|
|
* This source code is licensed under the MIT license found in the
|
|
* LICENSE file in the root directory of this source tree.
|
|
*/
|
|
|
|
import * as React from 'react';
|
|
import * as ReactDOM from 'react-dom';
|
|
import {findCurrentFiberUsingSlowPath} from 'react-reconciler/src/ReactFiberTreeReflection';
|
|
import {get as getInstance} from 'shared/ReactInstanceMap';
|
|
import {
|
|
ClassComponent,
|
|
FunctionComponent,
|
|
HostComponent,
|
|
HostText,
|
|
} from 'react-reconciler/src/ReactWorkTags';
|
|
import {SyntheticEvent} from '../events/SyntheticEvent';
|
|
import invariant from 'shared/invariant';
|
|
import {ELEMENT_NODE} from '../shared/HTMLNodeType';
|
|
import {act} from './ReactTestUtilsPublicAct';
|
|
import {unstable_concurrentAct} from './ReactTestUtilsInternalAct';
|
|
import {
|
|
rethrowCaughtError,
|
|
invokeGuardedCallbackAndCatchFirstError,
|
|
} from 'shared/ReactErrorUtils';
|
|
import isArray from 'shared/isArray';
|
|
|
|
// Keep in sync with ReactDOM.js, and ReactTestUtilsAct.js:
|
|
const EventInternals =
|
|
ReactDOM.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.Events;
|
|
const getInstanceFromNode = EventInternals[0];
|
|
const getNodeFromInstance = EventInternals[1];
|
|
const getFiberCurrentPropsFromNode = EventInternals[2];
|
|
const enqueueStateRestore = EventInternals[3];
|
|
const restoreStateIfNeeded = EventInternals[4];
|
|
// const flushPassiveEffects = EventInternals[5];
|
|
// TODO: This is related to `act`, not events. Move to separate key?
|
|
// const IsThisRendererActing = EventInternals[6];
|
|
|
|
function Event(suffix) {}
|
|
|
|
let hasWarnedAboutDeprecatedMockComponent = false;
|
|
|
|
/**
|
|
* @class ReactTestUtils
|
|
*/
|
|
|
|
function findAllInRenderedFiberTreeInternal(fiber, test) {
|
|
if (!fiber) {
|
|
return [];
|
|
}
|
|
const currentParent = findCurrentFiberUsingSlowPath(fiber);
|
|
if (!currentParent) {
|
|
return [];
|
|
}
|
|
let node = currentParent;
|
|
const ret = [];
|
|
while (true) {
|
|
if (
|
|
node.tag === HostComponent ||
|
|
node.tag === HostText ||
|
|
node.tag === ClassComponent ||
|
|
node.tag === FunctionComponent
|
|
) {
|
|
const publicInst = node.stateNode;
|
|
if (test(publicInst)) {
|
|
ret.push(publicInst);
|
|
}
|
|
}
|
|
if (node.child) {
|
|
node.child.return = node;
|
|
node = node.child;
|
|
continue;
|
|
}
|
|
if (node === currentParent) {
|
|
return ret;
|
|
}
|
|
while (!node.sibling) {
|
|
if (!node.return || node.return === currentParent) {
|
|
return ret;
|
|
}
|
|
node = node.return;
|
|
}
|
|
node.sibling.return = node.return;
|
|
node = node.sibling;
|
|
}
|
|
}
|
|
|
|
function validateClassInstance(inst, methodName) {
|
|
if (!inst) {
|
|
// This is probably too relaxed but it's existing behavior.
|
|
return;
|
|
}
|
|
if (getInstance(inst)) {
|
|
// This is a public instance indeed.
|
|
return;
|
|
}
|
|
let received;
|
|
const stringified = '' + inst;
|
|
if (isArray(inst)) {
|
|
received = 'an array';
|
|
} else if (inst && inst.nodeType === ELEMENT_NODE && inst.tagName) {
|
|
received = 'a DOM node';
|
|
} else if (stringified === '[object Object]') {
|
|
received = 'object with keys {' + Object.keys(inst).join(', ') + '}';
|
|
} else {
|
|
received = stringified;
|
|
}
|
|
invariant(
|
|
false,
|
|
'%s(...): the first argument must be a React class instance. ' +
|
|
'Instead received: %s.',
|
|
methodName,
|
|
received,
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Utilities for making it easy to test React components.
|
|
*
|
|
* See https://reactjs.org/docs/test-utils.html
|
|
*
|
|
* Todo: Support the entire DOM.scry query syntax. For now, these simple
|
|
* utilities will suffice for testing purposes.
|
|
* @lends ReactTestUtils
|
|
*/
|
|
function renderIntoDocument(element) {
|
|
const div = document.createElement('div');
|
|
// None of our tests actually require attaching the container to the
|
|
// DOM, and doing so creates a mess that we rely on test isolation to
|
|
// clean up, so we're going to stop honoring the name of this method
|
|
// (and probably rename it eventually) if no problems arise.
|
|
// document.documentElement.appendChild(div);
|
|
return ReactDOM.render(element, div);
|
|
}
|
|
|
|
function isElement(element) {
|
|
return React.isValidElement(element);
|
|
}
|
|
|
|
function isElementOfType(inst, convenienceConstructor) {
|
|
return React.isValidElement(inst) && inst.type === convenienceConstructor;
|
|
}
|
|
|
|
function isDOMComponent(inst) {
|
|
return !!(inst && inst.nodeType === ELEMENT_NODE && inst.tagName);
|
|
}
|
|
|
|
function isDOMComponentElement(inst) {
|
|
return !!(inst && React.isValidElement(inst) && !!inst.tagName);
|
|
}
|
|
|
|
function isCompositeComponent(inst) {
|
|
if (isDOMComponent(inst)) {
|
|
// Accessing inst.setState warns; just return false as that'll be what
|
|
// this returns when we have DOM nodes as refs directly
|
|
return false;
|
|
}
|
|
return (
|
|
inst != null &&
|
|
typeof inst.render === 'function' &&
|
|
typeof inst.setState === 'function'
|
|
);
|
|
}
|
|
|
|
function isCompositeComponentWithType(inst, type) {
|
|
if (!isCompositeComponent(inst)) {
|
|
return false;
|
|
}
|
|
const internalInstance = getInstance(inst);
|
|
const constructor = internalInstance.type;
|
|
return constructor === type;
|
|
}
|
|
|
|
function findAllInRenderedTree(inst, test) {
|
|
validateClassInstance(inst, 'findAllInRenderedTree');
|
|
if (!inst) {
|
|
return [];
|
|
}
|
|
const internalInstance = getInstance(inst);
|
|
return findAllInRenderedFiberTreeInternal(internalInstance, test);
|
|
}
|
|
|
|
/**
|
|
* Finds all instance of components in the rendered tree that are DOM
|
|
* components with the class name matching `className`.
|
|
* @return {array} an array of all the matches.
|
|
*/
|
|
function scryRenderedDOMComponentsWithClass(root, classNames) {
|
|
validateClassInstance(root, 'scryRenderedDOMComponentsWithClass');
|
|
return findAllInRenderedTree(root, function(inst) {
|
|
if (isDOMComponent(inst)) {
|
|
let className = inst.className;
|
|
if (typeof className !== 'string') {
|
|
// SVG, probably.
|
|
className = inst.getAttribute('class') || '';
|
|
}
|
|
const classList = className.split(/\s+/);
|
|
|
|
if (!isArray(classNames)) {
|
|
invariant(
|
|
classNames !== undefined,
|
|
'TestUtils.scryRenderedDOMComponentsWithClass expects a ' +
|
|
'className as a second argument.',
|
|
);
|
|
classNames = classNames.split(/\s+/);
|
|
}
|
|
return classNames.every(function(name) {
|
|
return classList.indexOf(name) !== -1;
|
|
});
|
|
}
|
|
return false;
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Like scryRenderedDOMComponentsWithClass but expects there to be one result,
|
|
* and returns that one result, or throws exception if there is any other
|
|
* number of matches besides one.
|
|
* @return {!ReactDOMComponent} The one match.
|
|
*/
|
|
function findRenderedDOMComponentWithClass(root, className) {
|
|
validateClassInstance(root, 'findRenderedDOMComponentWithClass');
|
|
const all = scryRenderedDOMComponentsWithClass(root, className);
|
|
if (all.length !== 1) {
|
|
throw new Error(
|
|
'Did not find exactly one match (found: ' +
|
|
all.length +
|
|
') ' +
|
|
'for class:' +
|
|
className,
|
|
);
|
|
}
|
|
return all[0];
|
|
}
|
|
|
|
/**
|
|
* Finds all instance of components in the rendered tree that are DOM
|
|
* components with the tag name matching `tagName`.
|
|
* @return {array} an array of all the matches.
|
|
*/
|
|
function scryRenderedDOMComponentsWithTag(root, tagName) {
|
|
validateClassInstance(root, 'scryRenderedDOMComponentsWithTag');
|
|
return findAllInRenderedTree(root, function(inst) {
|
|
return (
|
|
isDOMComponent(inst) &&
|
|
inst.tagName.toUpperCase() === tagName.toUpperCase()
|
|
);
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Like scryRenderedDOMComponentsWithTag but expects there to be one result,
|
|
* and returns that one result, or throws exception if there is any other
|
|
* number of matches besides one.
|
|
* @return {!ReactDOMComponent} The one match.
|
|
*/
|
|
function findRenderedDOMComponentWithTag(root, tagName) {
|
|
validateClassInstance(root, 'findRenderedDOMComponentWithTag');
|
|
const all = scryRenderedDOMComponentsWithTag(root, tagName);
|
|
if (all.length !== 1) {
|
|
throw new Error(
|
|
'Did not find exactly one match (found: ' +
|
|
all.length +
|
|
') ' +
|
|
'for tag:' +
|
|
tagName,
|
|
);
|
|
}
|
|
return all[0];
|
|
}
|
|
|
|
/**
|
|
* Finds all instances of components with type equal to `componentType`.
|
|
* @return {array} an array of all the matches.
|
|
*/
|
|
function scryRenderedComponentsWithType(root, componentType) {
|
|
validateClassInstance(root, 'scryRenderedComponentsWithType');
|
|
return findAllInRenderedTree(root, function(inst) {
|
|
return isCompositeComponentWithType(inst, componentType);
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Same as `scryRenderedComponentsWithType` but expects there to be one result
|
|
* and returns that one result, or throws exception if there is any other
|
|
* number of matches besides one.
|
|
* @return {!ReactComponent} The one match.
|
|
*/
|
|
function findRenderedComponentWithType(root, componentType) {
|
|
validateClassInstance(root, 'findRenderedComponentWithType');
|
|
const all = scryRenderedComponentsWithType(root, componentType);
|
|
if (all.length !== 1) {
|
|
throw new Error(
|
|
'Did not find exactly one match (found: ' +
|
|
all.length +
|
|
') ' +
|
|
'for componentType:' +
|
|
componentType,
|
|
);
|
|
}
|
|
return all[0];
|
|
}
|
|
|
|
/**
|
|
* Pass a mocked component module to this method to augment it with
|
|
* useful methods that allow it to be used as a dummy React component.
|
|
* Instead of rendering as usual, the component will become a simple
|
|
* <div> containing any provided children.
|
|
*
|
|
* @param {object} module the mock function object exported from a
|
|
* module that defines the component to be mocked
|
|
* @param {?string} mockTagName optional dummy root tag name to return
|
|
* from render method (overrides
|
|
* module.mockTagName if provided)
|
|
* @return {object} the ReactTestUtils object (for chaining)
|
|
*/
|
|
function mockComponent(module, mockTagName) {
|
|
if (__DEV__) {
|
|
if (!hasWarnedAboutDeprecatedMockComponent) {
|
|
hasWarnedAboutDeprecatedMockComponent = true;
|
|
console.warn(
|
|
'ReactTestUtils.mockComponent() is deprecated. ' +
|
|
'Use shallow rendering or jest.mock() instead.\n\n' +
|
|
'See https://reactjs.org/link/test-utils-mock-component for more information.',
|
|
);
|
|
}
|
|
}
|
|
|
|
mockTagName = mockTagName || module.mockTagName || 'div';
|
|
|
|
module.prototype.render.mockImplementation(function() {
|
|
return React.createElement(mockTagName, null, this.props.children);
|
|
});
|
|
|
|
return this;
|
|
}
|
|
|
|
function nativeTouchData(x, y) {
|
|
return {
|
|
touches: [{pageX: x, pageY: y}],
|
|
};
|
|
}
|
|
|
|
// Start of inline: the below functions were inlined from
|
|
// EventPropagator.js, as they deviated from ReactDOM's newer
|
|
// implementations.
|
|
|
|
/**
|
|
* Dispatch the event to the listener.
|
|
* @param {SyntheticEvent} event SyntheticEvent to handle
|
|
* @param {function} listener Application-level callback
|
|
* @param {*} inst Internal component instance
|
|
*/
|
|
function executeDispatch(event, listener, inst) {
|
|
const type = event.type || 'unknown-event';
|
|
event.currentTarget = getNodeFromInstance(inst);
|
|
invokeGuardedCallbackAndCatchFirstError(type, listener, undefined, event);
|
|
event.currentTarget = null;
|
|
}
|
|
|
|
/**
|
|
* Standard/simple iteration through an event's collected dispatches.
|
|
*/
|
|
function executeDispatchesInOrder(event) {
|
|
const dispatchListeners = event._dispatchListeners;
|
|
const dispatchInstances = event._dispatchInstances;
|
|
if (isArray(dispatchListeners)) {
|
|
for (let i = 0; i < dispatchListeners.length; i++) {
|
|
if (event.isPropagationStopped()) {
|
|
break;
|
|
}
|
|
// Listeners and Instances are two parallel arrays that are always in sync.
|
|
executeDispatch(event, dispatchListeners[i], dispatchInstances[i]);
|
|
}
|
|
} else if (dispatchListeners) {
|
|
executeDispatch(event, dispatchListeners, dispatchInstances);
|
|
}
|
|
event._dispatchListeners = null;
|
|
event._dispatchInstances = null;
|
|
}
|
|
|
|
/**
|
|
* Dispatches an event and releases it back into the pool, unless persistent.
|
|
*
|
|
* @param {?object} event Synthetic event to be dispatched.
|
|
* @private
|
|
*/
|
|
const executeDispatchesAndRelease = function(event: ReactSyntheticEvent) {
|
|
if (event) {
|
|
executeDispatchesInOrder(event);
|
|
|
|
if (!event.isPersistent()) {
|
|
event.constructor.release(event);
|
|
}
|
|
}
|
|
};
|
|
|
|
function isInteractive(tag) {
|
|
return (
|
|
tag === 'button' ||
|
|
tag === 'input' ||
|
|
tag === 'select' ||
|
|
tag === 'textarea'
|
|
);
|
|
}
|
|
|
|
function getParent(inst) {
|
|
do {
|
|
inst = inst.return;
|
|
// TODO: If this is a HostRoot we might want to bail out.
|
|
// That is depending on if we want nested subtrees (layers) to bubble
|
|
// events to their parent. We could also go through parentNode on the
|
|
// host node but that wouldn't work for React Native and doesn't let us
|
|
// do the portal feature.
|
|
} while (inst && inst.tag !== HostComponent);
|
|
if (inst) {
|
|
return inst;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Simulates the traversal of a two-phase, capture/bubble event dispatch.
|
|
*/
|
|
export function traverseTwoPhase(inst, fn, arg) {
|
|
const path = [];
|
|
while (inst) {
|
|
path.push(inst);
|
|
inst = getParent(inst);
|
|
}
|
|
let i;
|
|
for (i = path.length; i-- > 0; ) {
|
|
fn(path[i], 'captured', arg);
|
|
}
|
|
for (i = 0; i < path.length; i++) {
|
|
fn(path[i], 'bubbled', arg);
|
|
}
|
|
}
|
|
|
|
function shouldPreventMouseEvent(name, type, props) {
|
|
switch (name) {
|
|
case 'onClick':
|
|
case 'onClickCapture':
|
|
case 'onDoubleClick':
|
|
case 'onDoubleClickCapture':
|
|
case 'onMouseDown':
|
|
case 'onMouseDownCapture':
|
|
case 'onMouseMove':
|
|
case 'onMouseMoveCapture':
|
|
case 'onMouseUp':
|
|
case 'onMouseUpCapture':
|
|
case 'onMouseEnter':
|
|
return !!(props.disabled && isInteractive(type));
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param {object} inst The instance, which is the source of events.
|
|
* @param {string} registrationName Name of listener (e.g. `onClick`).
|
|
* @return {?function} The stored callback.
|
|
*/
|
|
function getListener(inst: Fiber, registrationName: string) {
|
|
// TODO: shouldPreventMouseEvent is DOM-specific and definitely should not
|
|
// live here; needs to be moved to a better place soon
|
|
const stateNode = inst.stateNode;
|
|
if (!stateNode) {
|
|
// Work in progress (ex: onload events in incremental mode).
|
|
return null;
|
|
}
|
|
const props = getFiberCurrentPropsFromNode(stateNode);
|
|
if (!props) {
|
|
// Work in progress.
|
|
return null;
|
|
}
|
|
const listener = props[registrationName];
|
|
if (shouldPreventMouseEvent(registrationName, inst.type, props)) {
|
|
return null;
|
|
}
|
|
invariant(
|
|
!listener || typeof listener === 'function',
|
|
'Expected `%s` listener to be a function, instead got a value of `%s` type.',
|
|
registrationName,
|
|
typeof listener,
|
|
);
|
|
return listener;
|
|
}
|
|
|
|
function listenerAtPhase(inst, event, propagationPhase: PropagationPhases) {
|
|
let registrationName = event._reactName;
|
|
if (propagationPhase === 'captured') {
|
|
registrationName += 'Capture';
|
|
}
|
|
return getListener(inst, registrationName);
|
|
}
|
|
|
|
function accumulateDispatches(inst, ignoredDirection, event) {
|
|
if (inst && event && event._reactName) {
|
|
const registrationName = event._reactName;
|
|
const listener = getListener(inst, registrationName);
|
|
if (listener) {
|
|
if (event._dispatchListeners == null) {
|
|
event._dispatchListeners = [];
|
|
}
|
|
if (event._dispatchInstances == null) {
|
|
event._dispatchInstances = [];
|
|
}
|
|
event._dispatchListeners.push(listener);
|
|
event._dispatchInstances.push(inst);
|
|
}
|
|
}
|
|
}
|
|
|
|
function accumulateDirectionalDispatches(inst, phase, event) {
|
|
if (__DEV__) {
|
|
if (!inst) {
|
|
console.error('Dispatching inst must not be null');
|
|
}
|
|
}
|
|
const listener = listenerAtPhase(inst, event, phase);
|
|
if (listener) {
|
|
if (event._dispatchListeners == null) {
|
|
event._dispatchListeners = [];
|
|
}
|
|
if (event._dispatchInstances == null) {
|
|
event._dispatchInstances = [];
|
|
}
|
|
event._dispatchListeners.push(listener);
|
|
event._dispatchInstances.push(inst);
|
|
}
|
|
}
|
|
|
|
function accumulateDirectDispatchesSingle(event) {
|
|
if (event && event._reactName) {
|
|
accumulateDispatches(event._targetInst, null, event);
|
|
}
|
|
}
|
|
|
|
function accumulateTwoPhaseDispatchesSingle(event) {
|
|
if (event && event._reactName) {
|
|
traverseTwoPhase(event._targetInst, accumulateDirectionalDispatches, event);
|
|
}
|
|
}
|
|
|
|
// End of inline
|
|
|
|
const Simulate = {};
|
|
|
|
const directDispatchEventTypes = new Set([
|
|
'mouseEnter',
|
|
'mouseLeave',
|
|
'pointerEnter',
|
|
'pointerLeave',
|
|
]);
|
|
|
|
/**
|
|
* Exports:
|
|
*
|
|
* - `Simulate.click(Element)`
|
|
* - `Simulate.mouseMove(Element)`
|
|
* - `Simulate.change(Element)`
|
|
* - ... (All keys from event plugin `eventTypes` objects)
|
|
*/
|
|
function makeSimulator(eventType) {
|
|
return function(domNode, eventData) {
|
|
invariant(
|
|
!React.isValidElement(domNode),
|
|
'TestUtils.Simulate expected a DOM node as the first argument but received ' +
|
|
'a React element. Pass the DOM node you wish to simulate the event on instead. ' +
|
|
'Note that TestUtils.Simulate will not work if you are using shallow rendering.',
|
|
);
|
|
invariant(
|
|
!isCompositeComponent(domNode),
|
|
'TestUtils.Simulate expected a DOM node as the first argument but received ' +
|
|
'a component instance. Pass the DOM node you wish to simulate the event on instead.',
|
|
);
|
|
|
|
const reactName = 'on' + eventType[0].toUpperCase() + eventType.slice(1);
|
|
const fakeNativeEvent = new Event();
|
|
fakeNativeEvent.target = domNode;
|
|
fakeNativeEvent.type = eventType.toLowerCase();
|
|
|
|
const targetInst = getInstanceFromNode(domNode);
|
|
const event = new SyntheticEvent(
|
|
reactName,
|
|
fakeNativeEvent.type,
|
|
targetInst,
|
|
fakeNativeEvent,
|
|
domNode,
|
|
);
|
|
|
|
// Since we aren't using pooling, always persist the event. This will make
|
|
// sure it's marked and won't warn when setting additional properties.
|
|
event.persist();
|
|
Object.assign(event, eventData);
|
|
|
|
if (directDispatchEventTypes.has(eventType)) {
|
|
accumulateDirectDispatchesSingle(event);
|
|
} else {
|
|
accumulateTwoPhaseDispatchesSingle(event);
|
|
}
|
|
|
|
ReactDOM.unstable_batchedUpdates(function() {
|
|
// Normally extractEvent enqueues a state restore, but we'll just always
|
|
// do that since we're by-passing it here.
|
|
enqueueStateRestore(domNode);
|
|
executeDispatchesAndRelease(event);
|
|
rethrowCaughtError();
|
|
});
|
|
restoreStateIfNeeded();
|
|
};
|
|
}
|
|
|
|
// A one-time snapshot with no plans to update. We'll probably want to deprecate Simulate API.
|
|
const simulatedEventTypes = [
|
|
'blur',
|
|
'cancel',
|
|
'click',
|
|
'close',
|
|
'contextMenu',
|
|
'copy',
|
|
'cut',
|
|
'auxClick',
|
|
'doubleClick',
|
|
'dragEnd',
|
|
'dragStart',
|
|
'drop',
|
|
'focus',
|
|
'input',
|
|
'invalid',
|
|
'keyDown',
|
|
'keyPress',
|
|
'keyUp',
|
|
'mouseDown',
|
|
'mouseUp',
|
|
'paste',
|
|
'pause',
|
|
'play',
|
|
'pointerCancel',
|
|
'pointerDown',
|
|
'pointerUp',
|
|
'rateChange',
|
|
'reset',
|
|
'seeked',
|
|
'submit',
|
|
'touchCancel',
|
|
'touchEnd',
|
|
'touchStart',
|
|
'volumeChange',
|
|
'drag',
|
|
'dragEnter',
|
|
'dragExit',
|
|
'dragLeave',
|
|
'dragOver',
|
|
'mouseMove',
|
|
'mouseOut',
|
|
'mouseOver',
|
|
'pointerMove',
|
|
'pointerOut',
|
|
'pointerOver',
|
|
'scroll',
|
|
'toggle',
|
|
'touchMove',
|
|
'wheel',
|
|
'abort',
|
|
'animationEnd',
|
|
'animationIteration',
|
|
'animationStart',
|
|
'canPlay',
|
|
'canPlayThrough',
|
|
'durationChange',
|
|
'emptied',
|
|
'encrypted',
|
|
'ended',
|
|
'error',
|
|
'gotPointerCapture',
|
|
'load',
|
|
'loadedData',
|
|
'loadedMetadata',
|
|
'loadStart',
|
|
'lostPointerCapture',
|
|
'playing',
|
|
'progress',
|
|
'seeking',
|
|
'stalled',
|
|
'suspend',
|
|
'timeUpdate',
|
|
'transitionEnd',
|
|
'waiting',
|
|
'mouseEnter',
|
|
'mouseLeave',
|
|
'pointerEnter',
|
|
'pointerLeave',
|
|
'change',
|
|
'select',
|
|
'beforeInput',
|
|
'compositionEnd',
|
|
'compositionStart',
|
|
'compositionUpdate',
|
|
];
|
|
function buildSimulators() {
|
|
simulatedEventTypes.forEach(eventType => {
|
|
Simulate[eventType] = makeSimulator(eventType);
|
|
});
|
|
}
|
|
buildSimulators();
|
|
|
|
export {
|
|
renderIntoDocument,
|
|
isElement,
|
|
isElementOfType,
|
|
isDOMComponent,
|
|
isDOMComponentElement,
|
|
isCompositeComponent,
|
|
isCompositeComponentWithType,
|
|
findAllInRenderedTree,
|
|
scryRenderedDOMComponentsWithClass,
|
|
findRenderedDOMComponentWithClass,
|
|
scryRenderedDOMComponentsWithTag,
|
|
findRenderedDOMComponentWithTag,
|
|
scryRenderedComponentsWithType,
|
|
findRenderedComponentWithType,
|
|
mockComponent,
|
|
nativeTouchData,
|
|
Simulate,
|
|
act,
|
|
unstable_concurrentAct,
|
|
};
|