Forward press handlers as testOnly_* in PressableWithTouchable - #4416
Conversation
`Pressable` dispatches to `StatefulPressable` when a relation prop is passed and to `PressableWithTouchable` otherwise. Only the former sets `testOnly_onPress`/`onPressIn`/`onPressOut`/`onLongPress` on the button, so in the common case (no relation props) React Native Testing Library finds no handler and `fireEvent(element, 'press')` silently does nothing. The press state machine runs natively, so a test environment has no other way to reach the handlers. Forward them from `PressableWithTouchable` too, guarded by `isTestEnv()`, exactly as `StatefulPressable` does. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
📝 WalkthroughSummary by CodeRabbit
WalkthroughChangesPressable test callback forwarding
Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Pull request overview
This PR fixes a testing regression in the v3 Pressable implementation where the common (relation-free) engine (PressableWithTouchable) did not forward press handlers via testOnly_* props, preventing React Native Testing Library from reaching user handlers in a Jest environment.
Changes:
- Forward
onPress/onPressIn/onPressOut/onLongPressfromPressableWithTouchableonto the underlying button astestOnly_*props, gated byisTestEnv(). - Add a Jest regression test asserting these
testOnly_*props are present for a relation-free v3Pressable.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| packages/react-native-gesture-handler/src/v3/components/PressableWithTouchable.tsx | Adds isTestEnv() gating and forwards testOnly_* handler props in the Touchable-based v3 Pressable engine. |
| packages/react-native-gesture-handler/src/tests/mocks.test.tsx | Adds a regression test verifying v3 Pressable exposes the four testOnly_* handler props on the rendered button. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
## Description Follow-up to #4416. None of the `Pressable` engines forwarded hover handlers as `testOnly_*` props, so `fireEvent(element, 'hoverIn')` from React Native Testing Library had no way to reach `onHoverIn`/`onHoverOut`. RNTL resolves `testOnly_on{EventName}` generically for any event, so exposing the props is all that's needed. This adds `testOnly_onHoverIn`/`testOnly_onHoverOut` to the button props and forwards them, guarded by `isTestEnv()`, from all three engines: legacy `Pressable`, `StatefulPressable` and `PressableWithTouchable`. Also widens the relation props (`simultaneousWith`/`requireToFail`/`block`) from `AnyGesture` to `AnyGesture | AnyGesture[]`. The JSDoc already promises a gesture object or an array of gesture objects and the runtime handles arrays in both directions (`relationUtils` flattens them into handler tags and pushes the symmetric relation onto each array element), only the prop type was narrowed. ## Test plan Added tests in `src/__tests__/mocks.test.tsx` asserting the hover props are wired on the button for both v3 engines — relation-free and routed to `StatefulPressable` via `simultaneousWith={[]}` (which the type widening makes legal). Both fail without the engine changes. In `packages/react-native-gesture-handler`: `yarn test`, `yarn ts-check` and `yarn lint:js` pass.
…4416) ## Description Fixes #4417. Since 3.2.0, `Pressable` dispatches between two engines: `StatefulPressable` when one of the relation props (`simultaneousWith` / `requireToFail` / `block`) is passed, and `PressableWithTouchable` otherwise — the common case. Only `StatefulPressable` sets `testOnly_onPress` / `testOnly_onPressIn` / `testOnly_onPressOut` / `testOnly_onLongPress` on the button. `PressableWithTouchable` doesn't, so for a plain `<Pressable onPress={...}>` React Native Testing Library finds no handler and `fireEvent(element, 'press')` silently does nothing. The press state machine runs natively, so in a test environment those props are the only way to reach the handlers. This makes the regression silent and fairly wide-reaching: no error is thrown, tests just stop observing presses. On 3.1.0 the single v3 `Pressable` always forwarded them, so this is a 3.1.0 → 3.2.0 regression for any app whose Jest suite drives a `Pressable`. The fix forwards the four handlers from `PressableWithTouchable` too, guarded by `isTestEnv()`, exactly as `StatefulPressable` does. `Touchable` spreads its remaining props onto `GestureHandlerButton`, which already declares them in `ButtonProps`, so nothing else needed to change and the props stay stripped outside a test environment. Note this is unrelated to #4414, which fixed the `testOnly_pressed` display state. ## Test plan Added a regression test in `src/__tests__/mocks.test.tsx` asserting the four `testOnly_*` props are wired on the button for a relation-free `Pressable`. It fails on `main` and passes with the fix. The test asserts the props rather than calling `fireEvent(element, 'press')` because this repo is on `@testing-library/react-native@12.9`, which predates the `testOnly_*` handler lookup (added in v13). Asserting the props keeps the test meaningful on the pinned version and independent of the RNTL version. In `packages/react-native-gesture-handler`: - `yarn test` — 16 suites, 135 tests passing - `yarn ts-check` — clean - `yarn lint:js` — 0 errors - `yarn format:js` — clean Also verified end-to-end in a real app (Expo 57 / RN 0.86, RNTL 14.0.1) that had ~3 suites broken by the 3.1.0 → 3.2.0 bump: with this change applied as a patch, the full suite is green again (136 suites, 1663 tests, 73 snapshots). Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
## Description Follow-up to #4416. None of the `Pressable` engines forwarded hover handlers as `testOnly_*` props, so `fireEvent(element, 'hoverIn')` from React Native Testing Library had no way to reach `onHoverIn`/`onHoverOut`. RNTL resolves `testOnly_on{EventName}` generically for any event, so exposing the props is all that's needed. This adds `testOnly_onHoverIn`/`testOnly_onHoverOut` to the button props and forwards them, guarded by `isTestEnv()`, from all three engines: legacy `Pressable`, `StatefulPressable` and `PressableWithTouchable`. Also widens the relation props (`simultaneousWith`/`requireToFail`/`block`) from `AnyGesture` to `AnyGesture | AnyGesture[]`. The JSDoc already promises a gesture object or an array of gesture objects and the runtime handles arrays in both directions (`relationUtils` flattens them into handler tags and pushes the symmetric relation onto each array element), only the prop type was narrowed. ## Test plan Added tests in `src/__tests__/mocks.test.tsx` asserting the hover props are wired on the button for both v3 engines — relation-free and routed to `StatefulPressable` via `simultaneousWith={[]}` (which the type widening makes legal). Both fail without the engine changes. In `packages/react-native-gesture-handler`: `yarn test`, `yarn ts-check` and `yarn lint:js` pass.
Description
Fixes #4417.
Since 3.2.0,
Pressabledispatches between two engines:StatefulPressablewhen one of therelation props (
simultaneousWith/requireToFail/block) is passed, andPressableWithTouchableotherwise — the common case.Only
StatefulPressablesetstestOnly_onPress/testOnly_onPressIn/testOnly_onPressOut/testOnly_onLongPresson the button.PressableWithTouchabledoesn't, so for a plain<Pressable onPress={...}>React Native Testing Library finds no handler andfireEvent(element, 'press')silently does nothing.The press state machine runs natively, so in a test environment those props are the only way to
reach the handlers. This makes the regression silent and fairly wide-reaching: no error is
thrown, tests just stop observing presses. On 3.1.0 the single v3
Pressablealways forwardedthem, so this is a 3.1.0 → 3.2.0 regression for any app whose Jest suite drives a
Pressable.The fix forwards the four handlers from
PressableWithTouchabletoo, guarded byisTestEnv(),exactly as
StatefulPressabledoes.Touchablespreads its remaining props ontoGestureHandlerButton, which already declares them inButtonProps, so nothing else needed tochange and the props stay stripped outside a test environment.
Note this is unrelated to #4414, which fixed the
testOnly_presseddisplay state.Test plan
Added a regression test in
src/__tests__/mocks.test.tsxasserting the fourtestOnly_*propsare wired on the button for a relation-free
Pressable. It fails onmainand passes with thefix.
The test asserts the props rather than calling
fireEvent(element, 'press')because this repo ison
@testing-library/react-native@12.9, which predates thetestOnly_*handler lookup (added inv13). Asserting the props keeps the test meaningful on the pinned version and independent of the
RNTL version.
In
packages/react-native-gesture-handler:yarn test— 16 suites, 135 tests passingyarn ts-check— cleanyarn lint:js— 0 errorsyarn format:js— cleanAlso verified end-to-end in a real app (Expo 57 / RN 0.86, RNTL 14.0.1) that had ~3 suites broken
by the 3.1.0 → 3.2.0 bump: with this change applied as a patch, the full suite is green again
(136 suites, 1663 tests, 73 snapshots).