Skip to content

Commit c54d604

Browse files
authored
[General] Pass testID to native side in dev (#3883)
## Description In the past, there were cases where I needed to debug how multiple gestures influenced each other. Identifying which gesture is which was a bit challenging when there were multiple of the same type. I figured, since we already have a `testID` property on each gesture, we may as well propagate that to the native side. This should make debugging multi-gesture configs much easier. This is only set in development builds; the only cost in production is one more pointer in the gesture object. ## Test plan Verify that the test ID is set correctly on the native side.
1 parent 59c3de7 commit c54d604

File tree

8 files changed

+33
-1
lines changed

8 files changed

+33
-1
lines changed

packages/react-native-gesture-handler/android/src/main/java/com/swmansion/gesturehandler/core/GestureHandler.kt

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ open class GestureHandler {
3030
private var trackedPointersIDsCount = 0
3131
private val windowOffset = IntArray(2) { 0 }
3232
var tag = 0
33+
var testID: String? = null
3334
var view: View? = null
3435
private set
3536

@@ -126,6 +127,7 @@ open class GestureHandler {
126127
}
127128

128129
open fun resetConfig() {
130+
testID = null
129131
needsPointerData = DEFAULT_NEEDS_POINTER_DATA
130132
manualActivation = DEFAULT_MANUAL_ACTIVATION
131133
shouldCancelWhenOutside = DEFAULT_SHOULD_CANCEL_WHEN_OUTSIDE
@@ -844,7 +846,7 @@ open class GestureHandler {
844846
open fun wantsToAttachDirectlyToView() = false
845847

846848
override fun toString(): String {
847-
val viewString = if (view == null) null else view!!.javaClass.simpleName
849+
val viewString = testID ?: view?.javaClass?.simpleName
848850
return this.javaClass.simpleName + "@[" + tag + "]:" + viewString
849851
}
850852

@@ -896,6 +898,9 @@ open class GestureHandler {
896898
if (config.hasKey(KEY_MOUSE_BUTTON)) {
897899
handler.mouseButton = config.getInt(KEY_MOUSE_BUTTON)
898900
}
901+
if (config.hasKey(KEY_TEST_ID)) {
902+
handler.testID = config.getString(KEY_TEST_ID)
903+
}
899904
}
900905

901906
abstract fun createEventBuilder(handler: T): GestureHandlerEventDataBuilder<T>
@@ -917,6 +922,7 @@ open class GestureHandler {
917922
private const val KEY_HIT_SLOP_HORIZONTAL = "horizontal"
918923
private const val KEY_HIT_SLOP_WIDTH = "width"
919924
private const val KEY_HIT_SLOP_HEIGHT = "height"
925+
private const val KEY_TEST_ID = "testID"
920926

921927
private fun handleHitSlopProperty(handler: GestureHandler, config: ReadableMap) {
922928
if (config.getType(KEY_HIT_SLOP) == ReadableType.Number) {

packages/react-native-gesture-handler/apple/RNGestureHandler.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@
7474
@property (nonatomic, weak, nullable) id<RNGestureHandlerEventEmitter> emitter;
7575
@property (nonatomic, readonly, nullable) UIGestureRecognizer *recognizer;
7676
@property (nonatomic, readonly, nullable) RNGestureHandlerPointerTracker *pointerTracker;
77+
@property (nonatomic, nullable) NSString *testID;
7778
@property (nonatomic) BOOL enabled;
7879
@property (nonatomic) RNGestureHandlerActionType actionType;
7980
@property (nonatomic) BOOL shouldCancelWhenOutside;

packages/react-native-gesture-handler/apple/RNGestureHandler.mm

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ - (instancetype)initWithTag:(NSNumber *)tag
102102
- (void)resetConfig
103103
{
104104
self.enabled = YES;
105+
self.testID = nil;
105106
self.manualActivation = NO;
106107
_shouldCancelWhenOutside = NO;
107108
_hitSlop = RNGHHitSlopEmpty;
@@ -126,6 +127,11 @@ - (void)updateConfig:(NSDictionary *)config
126127
self.enabled = [RCTConvert BOOL:prop];
127128
}
128129

130+
prop = config[@"testID"];
131+
if (prop != nil) {
132+
self.testID = [RCTConvert NSString:prop];
133+
}
134+
129135
prop = config[@"shouldCancelWhenOutside"];
130136
if (prop != nil) {
131137
_shouldCancelWhenOutside = [RCTConvert BOOL:prop];

packages/react-native-gesture-handler/src/v3/createNativeWrapper.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ export default function createNativeWrapper<P>(
4242
childProps: {
4343
enabled: props.enabled,
4444
hitSlop: props.hitSlop,
45+
testID: props.testID,
4546
} as P,
4647
}
4748
);

packages/react-native-gesture-handler/src/v3/hooks/utils/propsWhiteList.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,11 @@ export const allowedNativeProps = new Set<
4444
'needsPointerData',
4545
]);
4646

47+
// Don't pass testID to the native side in production
48+
if (!__DEV__) {
49+
allowedNativeProps.delete('testID');
50+
}
51+
4752
export const HandlerCallbacks = new Set<
4853
keyof Required<GestureCallbacks<unknown>>
4954
>([

packages/react-native-gesture-handler/src/web/handlers/GestureHandler.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ export default abstract class GestureHandler implements IGestureHandler {
4848
private forAnimated: boolean = false;
4949
private forReanimated: boolean = false;
5050
private _handlerTag!: number;
51+
private _testID?: string = undefined;
5152

5253
private hitSlop?: HitSlop = undefined;
5354
private manualActivation: boolean = false;
@@ -743,6 +744,10 @@ export default abstract class GestureHandler implements IGestureHandler {
743744
this.validateHitSlops();
744745
}
745746

747+
if (config.testID !== undefined) {
748+
this._testID = config.testID;
749+
}
750+
746751
if (config.dispatchesAnimatedEvents !== undefined) {
747752
this.forAnimated = config.dispatchesAnimatedEvents;
748753
}
@@ -936,6 +941,7 @@ export default abstract class GestureHandler implements IGestureHandler {
936941
}
937942

938943
protected resetConfig(): void {
944+
this._testID = undefined;
939945
this.manualActivation = false;
940946
this.shouldCancelWhenOutside = false;
941947
this.mouseButton = undefined;
@@ -965,6 +971,10 @@ export default abstract class GestureHandler implements IGestureHandler {
965971
this._handlerTag = value;
966972
}
967973

974+
public get testID() {
975+
return this._testID;
976+
}
977+
968978
public get delegate() {
969979
return this._delegate;
970980
}

packages/react-native-gesture-handler/src/web/handlers/IGestureHandler.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ export default interface IGestureHandler {
1717
activationIndex: number;
1818
awaiting: boolean;
1919
handlerTag: number;
20+
readonly testID?: string;
2021
readonly delegate: GestureHandlerDelegate<unknown, this>;
2122
readonly tracker: PointerTracker;
2223
readonly name: SingleGestureName;

packages/react-native-gesture-handler/src/web/interfaces.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ export interface Handler {
3232
type ConfigArgs =
3333
| number
3434
| boolean
35+
| string
3536
| HitSlop
3637
| UserSelect
3738
| TouchAction
@@ -57,6 +58,7 @@ export interface Config extends Record<string, ConfigArgs> {
5758
dispatchesAnimatedEvents?: false;
5859
dispatchesReanimatedEvents?: boolean;
5960
needsPointerData?: false;
61+
testID?: string;
6062

6163
activateAfterLongPress?: number;
6264
failOffsetXStart?: number;

0 commit comments

Comments
 (0)