Add Imperative Gesture Handler Testing API#4309
Conversation
There was a problem hiding this comment.
Pull request overview
This PR introduces an imperative testing helper (createGestureController) to simplify gesture lifecycle testing in RNGH Jest utilities, enabling step-by-step state transitions and assertions without manually crafting low-level state/oldState events.
Changes:
- Added
createGestureController,GestureController, andGestureControllerEventto drive gesture lifecycles imperatively in tests. - Exported the new controller API from
src/jestUtils/index.ts. - Added Jest tests covering lifecycle sequencing, validation, testID resolution, and disabled-gesture behavior.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| packages/react-native-gesture-handler/src/jestUtils/jestUtils.ts | Adds the gesture controller implementation and public API surface. |
| packages/react-native-gesture-handler/src/jestUtils/index.ts | Re-exports the controller types and factory function. |
| packages/react-native-gesture-handler/src/tests/gestureController.test.tsx | Adds tests validating the new imperative controller behavior. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| ```ts | ||
| import { createGestureController } from 'react-native-gesture-handler/jest-utils'; | ||
|
|
||
| createGestureController: (componentOrGesture) => GestureController; |
There was a problem hiding this comment.
Does GestureController work with older APIs or only V3?
There was a problem hiding this comment.
Technically it should work with older APIs but not sure if we need to add test examples for them.
Co-authored-by: Jakub Piasecki <jakubpiasecki67@gmail.com> Co-authored-by: Michał Bert <63123542+m-bert@users.noreply.github.com>
|
LGTM, please fix the CI failing, and I'll leave it to @m-bert in case he has some more comments. |
m-bert
left a comment
There was a problem hiding this comment.
One more thing before 🟢 Now we have to set disableReanimated every time we create gesture in tests. That may be annoying, but more important, it can break with components. The solution would be to set it on our side when we are in test environment.
- Default gesture hooks to `disableReanimated` in test env when unset - Update controller tests to exercise the new API without explicit test flags
| if (isTestEnv() && config.disableReanimated === undefined) { | ||
| config.disableReanimated = true; | ||
| } |
There was a problem hiding this comment.
Hmm, is the second condition necessary? Maybe we want to override it anyway? (cc @j-piasecki)
Description
The goal is to make gesture lifecycle tests easier to write when we want to assert application state after each gesture step, without requiring users to manually construct RNGH state events with
state,oldState, orhandlerTag.Instead of this lower-level style:
tests can now use imperative controller:
Hook gesture rerenders
Hook-based gestures can be recreated when their callbacks or configuration change during a React rerender while retaining the same handler tag. The controller now resolves the latest registered gesture before every lifecycle operation. This ensures that subsequent steps use the newest callback closures and configuration, including the current enabled value.
For example, if a rerender occurs between
begin()andactivate(),activate()invokes the callback from the latest render rather than the callback captured when the controller was created.Reusing a controller for another stream
A controller can now run multiple gesture streams.
After
end(),fail(), orcancel(), the terminal state remains available for assertions throughgetState(). Callingbegin()again resets the finished controller internally and starts a new stream.Test plan
Added tests using new API.