Skip to content

Commit

Permalink
Add testing-library compatibility props (#3357)
Browse files Browse the repository at this point in the history
## Description

This PR adds 3 props to the `Pressable` used for compatibility with
[react-native-testing-library](https://github.com/callstack/react-native-testing-library)

Full discussion:
callstack/react-native-testing-library#1738

## Test plan

<!--
Describe how did you test this change here.
-->
  • Loading branch information
latekvo authored Feb 3, 2025
1 parent b3d8fd9 commit e36eada
Show file tree
Hide file tree
Showing 7 changed files with 43 additions and 14 deletions.
24 changes: 24 additions & 0 deletions src/components/GestureButtonsProps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,30 @@ export interface RawButtonProps
* Style object, use it to set additional styles.
*/
style?: StyleProp<ViewStyle>;

/**
* Used for testing-library compatibility, not passed to the native component.
*/
// eslint-disable-next-line @typescript-eslint/ban-types
testOnly_onPress?: Function | null;

/**
* Used for testing-library compatibility, not passed to the native component.
*/
// eslint-disable-next-line @typescript-eslint/ban-types
testOnly_onPressIn?: Function | null;

/**
* Used for testing-library compatibility, not passed to the native component.
*/
// eslint-disable-next-line @typescript-eslint/ban-types
testOnly_onPressOut?: Function | null;

/**
* Used for testing-library compatibility, not passed to the native component.
*/
// eslint-disable-next-line @typescript-eslint/ban-types
testOnly_onLongPress?: Function | null;
}
interface ButtonWithRefProps {
innerRef?: React.ForwardedRef<React.ComponentType<any>>;
Expand Down
9 changes: 7 additions & 2 deletions src/components/Pressable/Pressable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,10 @@ import {
} from './utils';
import { PressabilityDebugView } from '../../handlers/PressabilityDebugView';
import { GestureTouchEvent } from '../../handlers/gestureHandlerCommon';
import { INT32_MAX } from '../../utils';
import { INT32_MAX, isTestEnv } from '../../utils';

const DEFAULT_LONG_PRESS_DURATION = 500;
const IS_TEST_ENV = isTestEnv();

export default function Pressable(props: PressableProps) {
const {
Expand Down Expand Up @@ -390,7 +391,11 @@ export default function Pressable(props: PressableProps) {
touchSoundDisabled={android_disableSound ?? undefined}
rippleColor={processColor(android_ripple?.color ?? defaultRippleColor)}
rippleRadius={android_ripple?.radius ?? undefined}
style={[pointerStyle, styleProp]}>
style={[pointerStyle, styleProp]}
testOnly_onPress={IS_TEST_ENV ? onPress : undefined}
testOnly_onPressIn={IS_TEST_ENV ? onPressIn : undefined}
testOnly_onPressOut={IS_TEST_ENV ? onPressOut : undefined}
testOnly_onLongPress={IS_TEST_ENV ? onLongPress : undefined}>
{childrenProp}
{__DEV__ ? (
<PressabilityDebugView color="red" hitSlop={normalizedHitSlop} />
Expand Down
6 changes: 3 additions & 3 deletions src/handlers/createHandler.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import {
import { filterConfig, scheduleFlushOperations } from './utils';
import findNodeHandle from '../findNodeHandle';
import { ValueOf } from '../typeUtils';
import { deepEqual, isFabric, isJestEnv, tagMessage } from '../utils';
import { deepEqual, isFabric, isTestEnv, tagMessage } from '../utils';
import { ActionType } from '../ActionType';
import { PressabilityDebugView } from './PressabilityDebugView';
import GestureHandlerRootViewContext from '../GestureHandlerRootViewContext';
Expand Down Expand Up @@ -428,7 +428,7 @@ export default function createHandler<
}

render() {
if (__DEV__ && !this.context && !isJestEnv() && Platform.OS !== 'web') {
if (__DEV__ && !this.context && !isTestEnv() && Platform.OS !== 'web') {
throw new Error(
name +
' must be used as a descendant of GestureHandlerRootView. Otherwise the gestures will not be recognized. See https://docs.swmansion.com/react-native-gesture-handler/docs/installation for more details.'
Expand Down Expand Up @@ -539,7 +539,7 @@ export default function createHandler<
{
ref: this.refHandler,
collapsable: false,
...(isJestEnv()
...(isTestEnv()
? {
handlerType: name,
handlerTag: this.handlerTag,
Expand Down
4 changes: 2 additions & 2 deletions src/handlers/gestures/GestureDetector/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import findNodeHandle from '../../../findNodeHandle';
import { GestureType } from '../gesture';
import { UserSelect, TouchAction } from '../../gestureHandlerCommon';
import { ComposedGesture } from '../gestureComposition';
import { isJestEnv } from '../../../utils';
import { isTestEnv } from '../../../utils';

import GestureHandlerRootViewContext from '../../../GestureHandlerRootViewContext';
import { AttachedGestureState, GestureDetectorState } from './types';
Expand Down Expand Up @@ -94,7 +94,7 @@ interface GestureDetectorProps {
*/
export const GestureDetector = (props: GestureDetectorProps) => {
const rootViewContext = useContext(GestureHandlerRootViewContext);
if (__DEV__ && !rootViewContext && !isJestEnv() && Platform.OS !== 'web') {
if (__DEV__ && !rootViewContext && !isTestEnv() && Platform.OS !== 'web') {
throw new Error(
'GestureDetector must be used as a descendant of GestureHandlerRootView. Otherwise the gestures will not be recognized. See https://docs.swmansion.com/react-native-gesture-handler/docs/installation for more details.'
);
Expand Down
4 changes: 2 additions & 2 deletions src/handlers/gestures/GestureDetector/utils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Platform } from 'react-native';

import { isJestEnv, tagMessage } from '../../../utils';
import { isTestEnv, tagMessage } from '../../../utils';
import { GestureRef, BaseGesture, GestureType } from '../gesture';

import { flingGestureHandlerProps } from '../../FlingGestureHandler';
Expand Down Expand Up @@ -100,7 +100,7 @@ export function checkGestureCallbacksForWorklets(gesture: GestureType) {
const areAllNotWorklets = !areSomeWorklets && areSomeNotWorklets;
// If none of the callbacks are worklets and the gesture is not explicitly marked with
// `.runOnJS(true)` show a warning
if (areAllNotWorklets && !isJestEnv()) {
if (areAllNotWorklets && !isTestEnv()) {
console.warn(
tagMessage(
`None of the callbacks in the gesture are worklets. If you wish to run them on the JS thread use '.runOnJS(true)' modifier on the gesture to make this explicit. Otherwise, mark the callbacks as 'worklet' to run them on the UI thread.`
Expand Down
6 changes: 3 additions & 3 deletions src/handlers/handlersRegistry.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { isJestEnv } from '../utils';
import { isTestEnv } from '../utils';
import { GestureType } from './gestures/gesture';
import { GestureEvent, HandlerStateChangeEvent } from './gestureHandlerCommon';

Expand All @@ -13,7 +13,7 @@ export function registerHandler(
testID?: string
) {
gestures.set(handlerTag, handler);
if (isJestEnv() && testID) {
if (isTestEnv() && testID) {
testIDs.set(testID, handlerTag);
}
}
Expand All @@ -27,7 +27,7 @@ export function registerOldGestureHandler(

export function unregisterHandler(handlerTag: number, testID?: string) {
gestures.delete(handlerTag);
if (isJestEnv() && testID) {
if (isTestEnv() && testID) {
testIDs.delete(testID);
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@ export function hasProperty(object: object, key: string) {
return Object.prototype.hasOwnProperty.call(object, key);
}

export function isJestEnv(): boolean {
export function isTestEnv(): boolean {
// @ts-ignore Do not use `@types/node` because it will prioritise Node types over RN types which breaks the types (ex. setTimeout) in React Native projects.
return hasProperty(global, 'process') && !!process.env.JEST_WORKER_ID;
return hasProperty(global, 'process') && process.env.NODE_ENV === 'test';
}

export function tagMessage(msg: string) {
Expand Down

0 comments on commit e36eada

Please sign in to comment.