@testing-library/react-native
Version:
Simple and complete React Native testing utilities that encourage good testing practices.
110 lines (105 loc) • 5.08 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.DEFAULT_MIN_PRESS_DURATION = exports.DEFAULT_LONG_PRESS_DELAY_MS = void 0;
exports.longPress = longPress;
exports.press = press;
var _act = _interopRequireDefault(require("../../act"));
var _eventHandler = require("../../event-handler");
var _componentTree = require("../../helpers/component-tree");
var _errors = require("../../helpers/errors");
var _hostComponentNames = require("../../helpers/host-component-names");
var _pointerEvents = require("../../helpers/pointer-events");
var _eventBuilder = require("../event-builder");
var _utils = require("../utils");
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
// These are constants defined in the React Native repo
// See: https://github.com/facebook/react-native/blob/50e38cc9f1e6713228a91ad50f426c4f65e65e1a/packages/react-native/Libraries/Pressability/Pressability.js#L264
const DEFAULT_MIN_PRESS_DURATION = exports.DEFAULT_MIN_PRESS_DURATION = 130;
const DEFAULT_LONG_PRESS_DELAY_MS = exports.DEFAULT_LONG_PRESS_DELAY_MS = 500;
async function press(element) {
if (!(0, _componentTree.isHostElement)(element)) {
throw new _errors.ErrorWithStack(`press() works only with host elements. Passed element has type "${element.type}".`, press);
}
await basePress(this.config, element, {
type: 'press'
});
}
async function longPress(element, options) {
if (!(0, _componentTree.isHostElement)(element)) {
throw new _errors.ErrorWithStack(`longPress() works only with host elements. Passed element has type "${element.type}".`, longPress);
}
await basePress(this.config, element, {
type: 'longPress',
duration: options?.duration ?? DEFAULT_LONG_PRESS_DELAY_MS
});
}
const basePress = async (config, element, options) => {
if (isEnabledHostElement(element) && hasPressEventHandler(element)) {
await emitDirectPressEvents(config, element, options);
return;
}
if (isEnabledTouchResponder(element)) {
await emitPressabilityPressEvents(config, element, options);
return;
}
const hostParentElement = (0, _componentTree.getHostParent)(element);
if (!hostParentElement) {
return;
}
await basePress(config, hostParentElement, options);
};
function isEnabledHostElement(element) {
if (!(0, _pointerEvents.isPointerEventEnabled)(element)) {
return false;
}
if ((0, _hostComponentNames.isHostText)(element)) {
return element.props.disabled !== true;
}
if ((0, _hostComponentNames.isHostTextInput)(element)) {
// @ts-expect-error - workaround incorrect ReactTestInstance type
return element.props.editable !== false;
}
return true;
}
function isEnabledTouchResponder(element) {
return (0, _pointerEvents.isPointerEventEnabled)(element) && element.props.onStartShouldSetResponder?.();
}
function hasPressEventHandler(element) {
return (0, _eventHandler.getEventHandler)(element, 'press') || (0, _eventHandler.getEventHandler)(element, 'longPress') || (0, _eventHandler.getEventHandler)(element, 'pressIn') || (0, _eventHandler.getEventHandler)(element, 'pressOut');
}
/**
* Dispatches a press event sequence for host elements that have `onPress*` event handlers.
*/
async function emitDirectPressEvents(config, element, options) {
await (0, _utils.wait)(config);
(0, _utils.dispatchEvent)(element, 'pressIn', _eventBuilder.EventBuilder.Common.touch());
await (0, _utils.wait)(config, options.duration);
// Long press events are emitted before `pressOut`.
if (options.type === 'longPress') {
(0, _utils.dispatchEvent)(element, 'longPress', _eventBuilder.EventBuilder.Common.touch());
}
(0, _utils.dispatchEvent)(element, 'pressOut', _eventBuilder.EventBuilder.Common.touch());
// Regular press events are emitted after `pressOut` according to the React Native docs.
// See: https://reactnative.dev/docs/pressable#onpress
// Experimentally for very short presses (< 130ms) `press` events are actually emitted before `onPressOut`, but
// we will ignore that as in reality most pressed would be above the 130ms threshold.
if (options.type === 'press') {
(0, _utils.dispatchEvent)(element, 'press', _eventBuilder.EventBuilder.Common.touch());
}
}
async function emitPressabilityPressEvents(config, element, options) {
await (0, _utils.wait)(config);
(0, _utils.dispatchEvent)(element, 'responderGrant', _eventBuilder.EventBuilder.Common.responderGrant());
const duration = options.duration ?? DEFAULT_MIN_PRESS_DURATION;
await (0, _utils.wait)(config, duration);
(0, _utils.dispatchEvent)(element, 'responderRelease', _eventBuilder.EventBuilder.Common.responderRelease());
// React Native will wait for minimal delay of DEFAULT_MIN_PRESS_DURATION
// before emitting the `pressOut` event. We need to wait here, so that
// `press()` function does not return before that.
if (DEFAULT_MIN_PRESS_DURATION - duration > 0) {
await (0, _act.default)(() => (0, _utils.wait)(config, DEFAULT_MIN_PRESS_DURATION - duration));
}
}
//# sourceMappingURL=press.js.map