From 24251132b4f7c6032e3cf7c4d6d79f4b2aeef705 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82?= Date: Mon, 2 Nov 2026 11:11:51 +0100 Subject: [PATCH 1/3] Add possibility to omit root view in Jest --- .../docs/guides/testing.mdx | 13 ++++++ .../jest-setup/disableRootViewCheck.js | 7 ++++ .../jest-setup/index.js | 41 ++++++++++++++++++ .../react-native-gesture-handler/jestSetup.js | 42 +------------------ .../react-native-gesture-handler/package.json | 1 + .../useEnsureGestureHandlerRootView.ts | 10 +++-- 6 files changed, 70 insertions(+), 44 deletions(-) create mode 100644 packages/react-native-gesture-handler/jest-setup/disableRootViewCheck.js create mode 100644 packages/react-native-gesture-handler/jest-setup/index.js diff --git a/packages/docs-gesture-handler/docs/guides/testing.mdx b/packages/docs-gesture-handler/docs/guides/testing.mdx index f91333708a..3c369c367a 100644 --- a/packages/docs-gesture-handler/docs/guides/testing.mdx +++ b/packages/docs-gesture-handler/docs/guides/testing.mdx @@ -31,6 +31,19 @@ In order to load mocks provided by RNGH, add the following to your jest config: "setupFiles": ["./node_modules/react-native-gesture-handler/jestSetup.js"] ``` + +### Rendering without GestureHandlerRootView + + +`GestureDetector` throws in development when it is not rendered inside `GestureHandlerRootView`, and this includes `Jest`. Wrap rendered trees in `GestureHandlerRootView`, or skip the check by adding the following file to `setupFiles`: + +```json +"setupFiles": [ + ..., + "./node_modules/react-native-gesture-handler/jest-setup/disableRootViewCheck.js" +] +``` + ### Example jest config diff --git a/packages/react-native-gesture-handler/jest-setup/disableRootViewCheck.js b/packages/react-native-gesture-handler/jest-setup/disableRootViewCheck.js new file mode 100644 index 0000000000..b18aea1227 --- /dev/null +++ b/packages/react-native-gesture-handler/jest-setup/disableRootViewCheck.js @@ -0,0 +1,7 @@ +jest.mock('../src/v3/detectors/useEnsureGestureHandlerRootView', () => ({ + useEnsureGestureHandlerRootView: () => {}, +})); + +jest.mock('../lib/module/v3/detectors/useEnsureGestureHandlerRootView', () => ({ + useEnsureGestureHandlerRootView: () => {}, +})); diff --git a/packages/react-native-gesture-handler/jest-setup/index.js b/packages/react-native-gesture-handler/jest-setup/index.js new file mode 100644 index 0000000000..10c6aeec2c --- /dev/null +++ b/packages/react-native-gesture-handler/jest-setup/index.js @@ -0,0 +1,41 @@ +jest.mock('../src/RNGestureHandlerModule', () => require('../src/mocks/module')); +jest.mock('../src/components/GestureButtons', () => + require('../src/mocks/GestureButtons') +); +jest.mock('../src/components/Pressable/Pressable', () => + require('../src/mocks/Pressable') +); +jest.mock('../src/components/GestureComponents', () => + require('../src/mocks/gestureComponents') +); +jest.mock('../src/components/touchables', () => + require('../src/mocks/Touchables') +); +jest.mock('../src/v3/detectors/HostGestureDetector', () => + require('../src/mocks/hostDetector') +); +jest.mock('../src/handlers/gestures/installUIRuntimeBindings', () => + require('../src/mocks/installUIRuntimeBindings') +); + +jest.mock('../lib/module/RNGestureHandlerModule', () => + require('../lib/module/mocks/module') +); +jest.mock('../lib/module/components/GestureButtons', () => + require('../lib/module/mocks/GestureButtons') +); +jest.mock('../lib/module/components/touchables', () => + require('../lib/module/mocks/Touchables') +); +jest.mock('../lib/module/components/Pressable', () => + require('../lib/module/mocks/Pressable') +); +jest.mock('../lib/module/components/GestureComponents', () => + require('../lib/module/mocks/gestureComponents') +); +jest.mock('../lib/module/v3/detectors/HostGestureDetector', () => + require('../lib/module/mocks/hostDetector') +); +jest.mock('../lib/module/handlers/gestures/installUIRuntimeBindings', () => + require('../lib/module/mocks/installUIRuntimeBindings') +); diff --git a/packages/react-native-gesture-handler/jestSetup.js b/packages/react-native-gesture-handler/jestSetup.js index 026f5b514d..b69f8e388d 100644 --- a/packages/react-native-gesture-handler/jestSetup.js +++ b/packages/react-native-gesture-handler/jestSetup.js @@ -1,41 +1 @@ -jest.mock('./src/RNGestureHandlerModule', () => require('./src/mocks/module')); -jest.mock('./src/components/GestureButtons', () => - require('./src/mocks/GestureButtons') -); -jest.mock('./src/components/Pressable/Pressable', () => - require('./src/mocks/Pressable') -); -jest.mock('./src/components/GestureComponents', () => - require('./src/mocks/gestureComponents') -); -jest.mock('./src/components/touchables', () => - require('./src/mocks/Touchables') -); -jest.mock('./src/v3/detectors/HostGestureDetector', () => - require('./src/mocks/hostDetector') -); -jest.mock('./src/handlers/gestures/installUIRuntimeBindings', () => - require('./src/mocks/installUIRuntimeBindings') -); - -jest.mock('./lib/module/RNGestureHandlerModule', () => - require('./lib/module/mocks/module') -); -jest.mock('./lib/module/components/GestureButtons', () => - require('./lib/module/mocks/GestureButtons') -); -jest.mock('./lib/module/components/touchables', () => - require('./lib/module/mocks/Touchables') -); -jest.mock('./lib/module/components/Pressable', () => - require('./lib/module/mocks/Pressable') -); -jest.mock('./lib/module/components/GestureComponents', () => - require('./lib/module/mocks/gestureComponents') -); -jest.mock('./lib/module/v3/detectors/HostGestureDetector', () => - require('./lib/module/mocks/hostDetector') -); -jest.mock('./lib/module/handlers/gestures/installUIRuntimeBindings', () => - require('./lib/module/mocks/installUIRuntimeBindings') -); +require('./jest-setup'); diff --git a/packages/react-native-gesture-handler/package.json b/packages/react-native-gesture-handler/package.json index f030903eb2..b88ad99ed5 100644 --- a/packages/react-native-gesture-handler/package.json +++ b/packages/react-native-gesture-handler/package.json @@ -50,6 +50,7 @@ "ReanimatedDrawerLayout/", "README.md", "jestSetup.js", + "jest-setup/", "RNGestureHandler.podspec", "react-native.config.js" ], diff --git a/packages/react-native-gesture-handler/src/v3/detectors/useEnsureGestureHandlerRootView.ts b/packages/react-native-gesture-handler/src/v3/detectors/useEnsureGestureHandlerRootView.ts index abb9c42e5c..24441caff0 100644 --- a/packages/react-native-gesture-handler/src/v3/detectors/useEnsureGestureHandlerRootView.ts +++ b/packages/react-native-gesture-handler/src/v3/detectors/useEnsureGestureHandlerRootView.ts @@ -2,13 +2,17 @@ import { use } from 'react'; import { Platform } from 'react-native'; import GestureHandlerRootViewContext from '../../GestureHandlerRootViewContext'; +import { isTestEnv } from '../../utils'; + +const ERROR_MESSAGE = + '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/fundamentals/installation for more details.'; + +const JEST_ERROR_MESSAGE = `${ERROR_MESSAGE} In Jest, wrap the rendered tree in GestureHandlerRootView or disable this check by adding 'react-native-gesture-handler/jest-setup/disableRootViewCheck.js' to setupFiles. See https://docs.swmansion.com/react-native-gesture-handler/docs/guides/testing#rendering-without-gesturehandlerrootview for more details.`; export function useEnsureGestureHandlerRootView() { const rootViewContext = use(GestureHandlerRootViewContext); if (__DEV__ && !rootViewContext && 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/fundamentals/installation for more details.' - ); + throw new Error(isTestEnv() ? JEST_ERROR_MESSAGE : ERROR_MESSAGE); } } From f2bdf9f48476773d419938fbe82d8ce8fce92b24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82?= Date: Mon, 2 Nov 2026 11:50:14 +0100 Subject: [PATCH 2/3] Update availability badge --- packages/docs-gesture-handler/docs/guides/testing.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/docs-gesture-handler/docs/guides/testing.mdx b/packages/docs-gesture-handler/docs/guides/testing.mdx index 3c369c367a..95e7992ca3 100644 --- a/packages/docs-gesture-handler/docs/guides/testing.mdx +++ b/packages/docs-gesture-handler/docs/guides/testing.mdx @@ -31,7 +31,7 @@ In order to load mocks provided by RNGH, add the following to your jest config: "setupFiles": ["./node_modules/react-native-gesture-handler/jestSetup.js"] ``` - + ### Rendering without GestureHandlerRootView From 1902fea262ebdda5abfeef4d52844775ed22bd9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82?= Date: Mon, 2 Nov 2026 12:05:51 +0100 Subject: [PATCH 3/3] Remove node_modules from setup path --- packages/docs-gesture-handler/docs/guides/testing.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/docs-gesture-handler/docs/guides/testing.mdx b/packages/docs-gesture-handler/docs/guides/testing.mdx index 95e7992ca3..24076ecefd 100644 --- a/packages/docs-gesture-handler/docs/guides/testing.mdx +++ b/packages/docs-gesture-handler/docs/guides/testing.mdx @@ -28,7 +28,7 @@ Be careful when adding multiple entries to `transformIgnorePatterns`. Since `Jes In order to load mocks provided by RNGH, add the following to your jest config: ```json -"setupFiles": ["./node_modules/react-native-gesture-handler/jestSetup.js"] +"setupFiles": ["react-native-gesture-handler/jestSetup.js"] ``` @@ -40,7 +40,7 @@ In order to load mocks provided by RNGH, add the following to your jest config: ```json "setupFiles": [ ..., - "./node_modules/react-native-gesture-handler/jest-setup/disableRootViewCheck.js" + "react-native-gesture-handler/jest-setup/disableRootViewCheck.js" ] ```