From 4e31fbd39ce7e42cda448181ee15536076f1b7ce Mon Sep 17 00:00:00 2001 From: Eli White Date: Tue, 28 Jan 2020 15:11:53 -0800 Subject: [PATCH] Pressable: Update ReactTestTools to be able to tab on Pressable Summary: This was all yungsters idea. I blame him. :) Switching Pressable to be a functional component presents a new challenge. ReactNativeTestTools can no longer find its instance because there is no instance Pressable uses forwardRef. We need a way to both find a pressable, and then call the onPress callback if the pressable isn't also disabled. So in DEV (and thus test) we add the pressable config to a secret key on a function passed onto View. The TestTools look for this key on this function, and then can call onPress. Super hacky, but so is all of ReactNativeTestTools. We aren't proud of this. Changelog: [General][Changed]: Added support for Pressable to ReactNativeTestTools.tap Reviewed By: yungsters Differential Revision: D18849358 fbshipit-source-id: ea8880ceedfc04cda217ee17ba140475d003172c --- Libraries/Pressability/Pressability.js | 6 ++++++ Libraries/Utilities/ReactNativeTestTools.js | 20 +++++++++++++++++++- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/Libraries/Pressability/Pressability.js b/Libraries/Pressability/Pressability.js index fc1e00ad5d4..d77baa8c11e 100644 --- a/Libraries/Pressability/Pressability.js +++ b/Libraries/Pressability/Pressability.js @@ -546,6 +546,12 @@ export default class Pressability { }, }; + if (process.env.NODE_ENV === 'test') { + // We are setting this in order to find this node in ReactNativeTestTools + responderEventHandlers.onStartShouldSetResponder.testOnly_pressabilityConfig = () => + this._config; + } + const mouseEventHandlers = Platform.OS === 'ios' || Platform.OS === 'android' ? null diff --git a/Libraries/Utilities/ReactNativeTestTools.js b/Libraries/Utilities/ReactNativeTestTools.js index fbe4e094ca4..124437ae8ef 100644 --- a/Libraries/Utilities/ReactNativeTestTools.js +++ b/Libraries/Utilities/ReactNativeTestTools.js @@ -18,7 +18,13 @@ const ReactTestRenderer = require('react-test-renderer'); const ShallowRenderer = require('react-test-renderer/shallow'); const shallowRenderer = new ShallowRenderer(); -const {Switch, Text, TextInput, VirtualizedList} = require('react-native'); +const { + Switch, + Text, + TextInput, + View, + VirtualizedList, +} = require('react-native'); import type { ReactTestInstance, @@ -36,6 +42,8 @@ function byClickable(): Predicate { typeof node.props.onPress === 'function') || // note: Special casing since it doesn't use touchable (node.type === Switch && node.props && node.props.disabled !== true) || + (node.type === View && + node?.props?.onStartShouldSetResponder?.testOnly_pressabilityConfig) || // HACK: Find components that use `Pressability`. node.instance?.state?.pressability != null || // TODO: Remove this after deleting `Touchable`. @@ -177,6 +185,16 @@ function tap(instance: ReactTestInstance) { const {onChange, onValueChange} = touchable.props; onChange && onChange({nativeEvent: {value}}); onValueChange && onValueChange(value); + } else if ( + touchable?.props?.onStartShouldSetResponder?.testOnly_pressabilityConfig + ) { + const { + onPress, + disabled, + } = touchable.props.onStartShouldSetResponder.testOnly_pressabilityConfig(); + if (!disabled) { + onPress({nativeEvent: {}}); + } } else { // Only tap when props.disabled isn't set (or there aren't any props) if (!touchable.props || !touchable.props.disabled) {