You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

375 lines
10 KiB

"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.fireGestureHandler = fireGestureHandler;
exports.getByGestureTestId = getByGestureTestId;
var _invariant = _interopRequireDefault(require("invariant"));
var _reactNative = require("react-native");
var _FlingGestureHandler = require("../handlers/FlingGestureHandler");
var _ForceTouchGestureHandler = require("../handlers/ForceTouchGestureHandler");
var _gesture = require("../handlers/gestures/gesture");
var _handlersRegistry = require("../handlers/handlersRegistry");
var _LongPressGestureHandler = require("../handlers/LongPressGestureHandler");
var _NativeViewGestureHandler = require("../handlers/NativeViewGestureHandler");
var _PanGestureHandler = require("../handlers/PanGestureHandler");
var _PinchGestureHandler = require("../handlers/PinchGestureHandler");
var _RotationGestureHandler = require("../handlers/RotationGestureHandler");
var _TapGestureHandler = require("../handlers/TapGestureHandler");
var _State = require("../State");
var _utils = require("../utils");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
// load fireEvent conditionally, so RNGH may be used in setups without testing-library
let fireEvent = (_element, _name, ..._data) => {// NOOP
};
try {
// eslint-disable-next-line @typescript-eslint/no-var-requires
fireEvent = require('@testing-library/react-native').fireEvent;
} catch (_e) {// do nothing if not available
}
const handlersDefaultEvents = {
[_FlingGestureHandler.flingHandlerName]: {
x: 0,
y: 0,
absoluteX: 0,
absoluteY: 0,
numberOfPointers: 1
},
[_ForceTouchGestureHandler.forceTouchHandlerName]: {
x: 0,
y: 0,
absoluteX: 0,
absoluteY: 0,
force: 1,
numberOfPointers: 1
},
[_LongPressGestureHandler.longPressHandlerName]: {
x: 0,
y: 0,
absoluteX: 0,
absoluteY: 0,
duration: 100,
numberOfPointers: 1
},
[_NativeViewGestureHandler.nativeViewHandlerName]: {
pointerInside: true,
numberOfPointers: 1
},
[_PanGestureHandler.panHandlerName]: {
x: 0,
y: 0,
absoluteX: 0,
absoluteY: 0,
translationX: 100,
translationY: 0,
velocityX: 3,
velocityY: 0,
numberOfPointers: 1
},
[_PinchGestureHandler.pinchHandlerName]: {
focalX: 0,
focalY: 0,
scale: 2,
velocity: 1,
numberOfPointers: 2
},
[_RotationGestureHandler.rotationHandlerName]: {
anchorX: 0,
anchorY: 0,
rotation: 3.14,
velocity: 2,
numberOfPointers: 2
},
[_TapGestureHandler.tapHandlerName]: {
x: 0,
y: 0,
absoluteX: 0,
absoluteY: 0,
numberOfPointers: 1
}
};
function isGesture(componentOrGesture) {
return componentOrGesture instanceof _gesture.BaseGesture;
}
function wrapWithNativeEvent(event) {
return {
nativeEvent: event
};
}
function fillOldStateChanges(previousEvent, currentEvent) {
const isFirstEvent = previousEvent === null;
if (isFirstEvent) {
return {
oldState: _State.State.UNDETERMINED,
...currentEvent
};
}
const isGestureStateEvent = previousEvent.state !== currentEvent.state;
if (isGestureStateEvent) {
return {
oldState: previousEvent === null || previousEvent === void 0 ? void 0 : previousEvent.state,
...currentEvent
};
} else {
return currentEvent;
}
}
function validateStateTransitions(previousEvent, currentEvent) {
function stringify(event) {
return JSON.stringify(event, null, 2);
}
function errorMsgWithBothEvents(description) {
return `${description}, invalid event: ${stringify(currentEvent)}, previous event: ${stringify(previousEvent)}`;
}
function errorMsgWithCurrentEvent(description) {
return `${description}, invalid event: ${stringify(currentEvent)}`;
}
(0, _invariant.default)((0, _utils.hasProperty)(currentEvent, 'state'), errorMsgWithCurrentEvent('every event must have state'));
const isFirstEvent = previousEvent === null;
if (isFirstEvent) {
(0, _invariant.default)(currentEvent.state === _State.State.BEGAN, errorMsgWithCurrentEvent('first event must have BEGAN state'));
}
if (previousEvent !== null) {
if (previousEvent.state !== currentEvent.state) {
(0, _invariant.default)((0, _utils.hasProperty)(currentEvent, 'oldState'), errorMsgWithCurrentEvent('when state changes, oldState field should be present'));
(0, _invariant.default)(currentEvent.oldState === previousEvent.state, errorMsgWithBothEvents("when state changes, oldState should be the same as previous event' state"));
}
}
return currentEvent;
}
function fillMissingDefaultsFor({
handlerType,
handlerTag
}) {
return event => {
return { ...handlersDefaultEvents[handlerType],
...event,
handlerTag
};
};
}
function isDiscreteHandler(handlerType) {
return handlerType === 'TapGestureHandler' || handlerType === 'LongPressGestureHandler';
}
function fillMissingStatesTransitions(events, isDiscreteHandler) {
var _events2, _events$;
const _events = [...events];
const lastEvent = (_events2 = _events[_events.length - 1]) !== null && _events2 !== void 0 ? _events2 : null;
const firstEvent = (_events$ = _events[0]) !== null && _events$ !== void 0 ? _events$ : null;
const shouldDuplicateFirstEvent = !isDiscreteHandler && !hasState(_State.State.BEGAN)(firstEvent);
if (shouldDuplicateFirstEvent) {
const duplicated = { ...firstEvent,
state: _State.State.BEGAN
}; // @ts-ignore badly typed, property may exist and we don't want to copy it
delete duplicated.oldState;
_events.unshift(duplicated);
}
const shouldDuplicateLastEvent = !hasState(_State.State.END)(lastEvent) || !hasState(_State.State.FAILED)(lastEvent) || !hasState(_State.State.CANCELLED)(lastEvent);
if (shouldDuplicateLastEvent) {
const duplicated = { ...lastEvent,
state: _State.State.END
}; // @ts-ignore badly typed, property may exist and we don't want to copy it
delete duplicated.oldState;
_events.push(duplicated);
}
function isWithoutState(event) {
return event !== null && !(0, _utils.hasProperty)(event, 'state');
}
function hasState(state) {
return event => event !== null && event.state === state;
}
function noEventsLeft(event) {
return event === null;
}
function trueFn() {
return true;
}
function fillEventsForCurrentState({
shouldConsumeEvent = trueFn,
shouldTransitionToNextState = trueFn
}) {
function peekCurrentEvent() {
var _events$2;
return (_events$2 = _events[0]) !== null && _events$2 !== void 0 ? _events$2 : null;
}
function peekNextEvent() {
var _events$3;
return (_events$3 = _events[1]) !== null && _events$3 !== void 0 ? _events$3 : null;
}
function consumeCurrentEvent() {
_events.shift();
}
const currentEvent = peekCurrentEvent();
const nextEvent = peekNextEvent();
const currentRequiredState = REQUIRED_EVENTS[currentStateIdx];
let eventData = {};
const shouldUseEvent = shouldConsumeEvent(currentEvent);
if (shouldUseEvent) {
eventData = currentEvent;
consumeCurrentEvent();
}
transformedEvents.push({
state: currentRequiredState,
...eventData
});
if (shouldTransitionToNextState(nextEvent)) {
currentStateIdx++;
}
}
const REQUIRED_EVENTS = [_State.State.BEGAN, _State.State.ACTIVE, _State.State.END];
let currentStateIdx = 0;
const transformedEvents = [];
let hasAllStates;
let iterations = 0;
do {
const nextRequiredState = REQUIRED_EVENTS[currentStateIdx];
if (nextRequiredState === _State.State.BEGAN) {
fillEventsForCurrentState({
shouldConsumeEvent: e => isWithoutState(e) || hasState(_State.State.BEGAN)(e)
});
} else if (nextRequiredState === _State.State.ACTIVE) {
const shouldConsumeEvent = e => isWithoutState(e) || hasState(_State.State.ACTIVE)(e);
const shouldTransitionToNextState = nextEvent => noEventsLeft(nextEvent) || hasState(_State.State.END)(nextEvent) || hasState(_State.State.FAILED)(nextEvent) || hasState(_State.State.CANCELLED)(nextEvent);
fillEventsForCurrentState({
shouldConsumeEvent,
shouldTransitionToNextState
});
} else if (nextRequiredState === _State.State.END) {
fillEventsForCurrentState({});
}
hasAllStates = currentStateIdx === REQUIRED_EVENTS.length;
(0, _invariant.default)(iterations++ <= 500, 'exceeded max number of iterations, please report a bug in RNGH repository with your test case');
} while (!hasAllStates);
return transformedEvents;
}
function getHandlerData(componentOrGesture) {
if (isGesture(componentOrGesture)) {
const gesture = componentOrGesture;
return {
emitEvent: (eventName, args) => {
_reactNative.DeviceEventEmitter.emit(eventName, args.nativeEvent);
},
handlerType: gesture.handlerName,
handlerTag: gesture.handlerTag
};
}
const gestureHandlerComponent = componentOrGesture;
return {
emitEvent: (eventName, args) => {
fireEvent(gestureHandlerComponent, eventName, args);
},
handlerType: gestureHandlerComponent.props.handlerType,
handlerTag: gestureHandlerComponent.props.handlerTag
};
}
function fireGestureHandler(componentOrGesture, eventList = []) {
const {
emitEvent,
handlerType,
handlerTag
} = getHandlerData(componentOrGesture);
let _ = fillMissingStatesTransitions(eventList, isDiscreteHandler(handlerType));
_ = _.map(fillMissingDefaultsFor({
handlerTag,
handlerType
}));
_ = (0, _utils.withPrevAndCurrent)(_, fillOldStateChanges);
_ = (0, _utils.withPrevAndCurrent)(_, validateStateTransitions); // @ts-ignore TODO
_ = _.map(wrapWithNativeEvent);
const events = _;
const firstEvent = events.shift();
emitEvent('onGestureHandlerStateChange', firstEvent);
let lastSentEvent = firstEvent;
for (const event of events) {
const hasChangedState = lastSentEvent.nativeEvent.state !== event.nativeEvent.state;
if (hasChangedState) {
emitEvent('onGestureHandlerStateChange', event);
} else {
emitEvent('onGestureHandlerEvent', event);
}
lastSentEvent = event;
}
}
function getByGestureTestId(testID) {
const handler = (0, _handlersRegistry.findHandlerByTestID)(testID);
if (handler === null) {
throw new Error(`Handler with id: '${testID}' cannot be found`);
}
return handler;
}
//# sourceMappingURL=jestUtils.js.map