Skip to content

Commit e386b0c

Browse files
authored
Add legacy mocks (#4055)
## Description This PR: - Adds missing legacy mocks - Adds info to docs about how to import jest utility functions - Removes `react-native-worklets` mock from our `jestSetup` ## Test plan New `mock` test <details> <summary>Also tested on this test code in new app:</summary> ```tsx import React from 'react'; import { Text, View } from 'react-native'; import { render } from '@testing-library/react-native'; import { // v3 components RawButton, BaseButton, RectButton, BorderlessButton, Clickable, Pressable, ScrollView, FlatList, Switch, TextInput, RefreshControl, GestureHandlerRootView, // Legacy components LegacyRawButton, LegacyBaseButton, LegacyRectButton, LegacyBorderlessButton, LegacyPressable, LegacyScrollView, LegacyFlatList, LegacySwitch, LegacyTextInput, LegacyRefreshControl, } from 'react-native-gesture-handler'; import { fireGestureHandler, getByGestureTestId, } from 'react-native-gesture-handler/jest-utils'; import { State } from 'react-native-gesture-handler'; describe('v3 components render without crashing', () => { test('RawButton', () => { expect(() => render( <GestureHandlerRootView> <RawButton /> </GestureHandlerRootView>, ), ).not.toThrow(); }); test('BaseButton', () => { expect(() => render( <GestureHandlerRootView> <BaseButton /> </GestureHandlerRootView>, ), ).not.toThrow(); }); test('RectButton', () => { expect(() => render( <GestureHandlerRootView> <RectButton /> </GestureHandlerRootView>, ), ).not.toThrow(); }); test('BorderlessButton', () => { expect(() => render( <GestureHandlerRootView> <BorderlessButton /> </GestureHandlerRootView>, ), ).not.toThrow(); }); test('Clickable', () => { expect(() => render( <GestureHandlerRootView> <Clickable /> </GestureHandlerRootView>, ), ).not.toThrow(); }); test('Pressable', () => { expect(() => render( <GestureHandlerRootView> <Pressable /> </GestureHandlerRootView>, ), ).not.toThrow(); }); test('ScrollView', () => { expect(() => render( <GestureHandlerRootView> <ScrollView /> </GestureHandlerRootView>, ), ).not.toThrow(); }); test('FlatList', () => { expect(() => render( <GestureHandlerRootView> <FlatList data={[]} renderItem={() => null} /> </GestureHandlerRootView>, ), ).not.toThrow(); }); test('Switch', () => { expect(() => render( <GestureHandlerRootView> <Switch /> </GestureHandlerRootView>, ), ).not.toThrow(); }); test('TextInput', () => { expect(() => render( <GestureHandlerRootView> <TextInput /> </GestureHandlerRootView>, ), ).not.toThrow(); }); test('RefreshControl', () => { expect(() => render( <GestureHandlerRootView> <ScrollView refreshControl={<RefreshControl refreshing={false} />} /> </GestureHandlerRootView>, ), ).not.toThrow(); }); }); describe('Legacy components render without crashing', () => { test('LegacyRawButton', () => { expect(() => render(<LegacyRawButton />)).not.toThrow(); }); test('LegacyBaseButton', () => { expect(() => render(<LegacyBaseButton />)).not.toThrow(); }); test('LegacyRectButton', () => { expect(() => render(<LegacyRectButton />)).not.toThrow(); }); test('LegacyBorderlessButton', () => { expect(() => render(<LegacyBorderlessButton />)).not.toThrow(); }); test('LegacyPressable', () => { expect(() => render(<LegacyPressable />)).not.toThrow(); }); test('LegacyScrollView', () => { expect(() => render(<LegacyScrollView />)).not.toThrow(); }); test('LegacyFlatList', () => { expect(() => render(<LegacyFlatList data={[]} renderItem={() => null} />), ).not.toThrow(); }); test('LegacySwitch', () => { expect(() => render(<LegacySwitch />)).not.toThrow(); }); test('LegacyTextInput', () => { expect(() => render(<LegacyTextInput />)).not.toThrow(); }); test('LegacyRefreshControl', () => { expect(() => render(<LegacyRefreshControl refreshing={false} />), ).not.toThrow(); }); }); describe('fireGestureHandler works with v3 components', () => { test('Clickable onPress fires via gesture handler', () => { const onPress = jest.fn(); render( <GestureHandlerRootView> <Clickable testID="clickable" onPress={onPress}> <Text>Press Me</Text> </Clickable> </GestureHandlerRootView>, ); const gesture = getByGestureTestId('clickable'); fireGestureHandler(gesture, [ { oldState: State.UNDETERMINED, state: State.BEGAN }, { oldState: State.BEGAN, state: State.ACTIVE }, { oldState: State.ACTIVE, state: State.END }, ]); expect(onPress).toHaveBeenCalledTimes(1); }); test('RectButton onPress fires via gesture handler', () => { const onPress = jest.fn(); render( <GestureHandlerRootView> <RectButton testID="rect" onPress={onPress} /> </GestureHandlerRootView>, ); const gesture = getByGestureTestId('rect'); fireGestureHandler(gesture, [ { oldState: State.UNDETERMINED, state: State.BEGAN }, { oldState: State.BEGAN, state: State.ACTIVE }, { oldState: State.ACTIVE, state: State.END }, ]); expect(onPress).toHaveBeenCalledTimes(1); }); }); ``` </details>
1 parent d1096d5 commit e386b0c

7 files changed

Lines changed: 171 additions & 30 deletions

File tree

packages/docs-gesture-handler/docs/guides/testing.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ RNGH provides APIs, specifically [`fireGestureHandler`](#firegesturehandler) and
2828
### fireGestureHandler
2929

3030
```ts
31+
import { fireGestureHandler } from 'react-native-gesture-handler/jest-utils';
32+
3133
fireGestureHandler: (componentOrGesture, eventList) => void;
3234
```
3335

@@ -80,6 +82,8 @@ const allImplicits = []; // 3 events, one BEGIN, one ACTIVE, one END with defaul
8082
### getByGestureTestId
8183

8284
```tsx
85+
import { getByGestureTestId } from 'react-native-gesture-handler/jest-utils';
86+
8387
getByGestureTestId: (testID: string) => Gesture;
8488
```
8589

packages/react-native-gesture-handler/jestSetup.js

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ jest.mock('./src/components/Pressable/Pressable', () =>
88
jest.mock('./src/components/GestureComponents', () =>
99
require('./src/mocks/gestureComponents')
1010
);
11+
jest.mock('./src/components/touchables', () =>
12+
require('./src/mocks/Touchables')
13+
);
1114
jest.mock('./src/v3/detectors/HostGestureDetector', () =>
1215
require('./src/mocks/hostDetector')
1316
);
@@ -18,6 +21,9 @@ jest.mock('./lib/module/RNGestureHandlerModule', () =>
1821
jest.mock('./lib/module/components/GestureButtons', () =>
1922
require('./lib/module/mocks/GestureButtons')
2023
);
24+
jest.mock('./lib/module/components/touchables', () =>
25+
require('./lib/module/mocks/Touchables')
26+
);
2127
jest.mock('./lib/module/components/Pressable', () =>
2228
require('./lib/module/mocks/Pressable')
2329
);
@@ -27,7 +33,3 @@ jest.mock('./lib/module/components/GestureComponents', () =>
2733
jest.mock('./lib/module/v3/detectors/HostGestureDetector', () =>
2834
require('./lib/module/mocks/hostDetector')
2935
);
30-
31-
jest.mock('react-native-worklets', () =>
32-
require('react-native-worklets/src/mock')
33-
);

packages/react-native-gesture-handler/src/__tests__/Errors.test.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ import {
1010
import { findNodeHandle, View } from 'react-native';
1111
import { VirtualDetector } from '../v3/detectors/VirtualDetector/VirtualDetector';
1212

13+
jest.mock('react-native-worklets', () =>
14+
require('react-native-worklets/src/mock')
15+
);
16+
1317
beforeEach(() => cleanup());
1418
jest.mock('react-native/Libraries/ReactNative/RendererProxy', () => ({
1519
findNodeHandle: jest.fn(),
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
import React from 'react';
2+
import { Text } from 'react-native';
3+
import { render, fireEvent } from '@testing-library/react-native';
4+
5+
import {
6+
LegacyRawButton,
7+
LegacyBaseButton,
8+
LegacyRectButton,
9+
LegacyBorderlessButton,
10+
LegacyPureNativeButton,
11+
} from '../mocks/GestureButtons';
12+
13+
import {
14+
LegacyScrollView,
15+
LegacyFlatList,
16+
LegacySwitch,
17+
LegacyTextInput,
18+
LegacyRefreshControl,
19+
} from '../mocks/gestureComponents';
20+
21+
import {
22+
TouchableHighlight,
23+
TouchableNativeFeedback,
24+
TouchableOpacity,
25+
TouchableWithoutFeedback,
26+
} from '../mocks/Touchables';
27+
28+
import LegacyPressable from '../mocks/Pressable';
29+
30+
import GestureHandlerRootView from '../components/GestureHandlerRootView';
31+
import { Touchable } from '../v3/components';
32+
33+
describe('Jest mocks – legacy components render without crashing', () => {
34+
test('LegacyRawButton', () => {
35+
expect(() => render(<LegacyRawButton />)).not.toThrow();
36+
});
37+
38+
test('LegacyBaseButton', () => {
39+
expect(() => render(<LegacyBaseButton />)).not.toThrow();
40+
});
41+
42+
test('LegacyRectButton', () => {
43+
expect(() => render(<LegacyRectButton />)).not.toThrow();
44+
});
45+
46+
test('LegacyBorderlessButton', () => {
47+
expect(() => render(<LegacyBorderlessButton />)).not.toThrow();
48+
});
49+
50+
test('LegacyPureNativeButton', () => {
51+
expect(() => render(<LegacyPureNativeButton />)).not.toThrow();
52+
});
53+
54+
test('LegacyPressable', () => {
55+
expect(() => render(<LegacyPressable />)).not.toThrow();
56+
});
57+
58+
test('LegacyScrollView', () => {
59+
expect(() => render(<LegacyScrollView />)).not.toThrow();
60+
});
61+
62+
test('LegacyFlatList', () => {
63+
expect(() =>
64+
render(<LegacyFlatList data={[]} renderItem={() => null} />)
65+
).not.toThrow();
66+
});
67+
68+
test('LegacySwitch', () => {
69+
expect(() => render(<LegacySwitch />)).not.toThrow();
70+
});
71+
72+
test('LegacyTextInput', () => {
73+
expect(() => render(<LegacyTextInput />)).not.toThrow();
74+
});
75+
76+
test('LegacyRefreshControl', () => {
77+
expect(() =>
78+
render(<LegacyRefreshControl refreshing={false} />)
79+
).not.toThrow();
80+
});
81+
82+
test('TouchableHighlight', () => {
83+
expect(() =>
84+
render(
85+
<TouchableHighlight>
86+
<Text>Test</Text>
87+
</TouchableHighlight>
88+
)
89+
).not.toThrow();
90+
});
91+
92+
test('TouchableNativeFeedback', () => {
93+
expect(() =>
94+
render(
95+
<TouchableNativeFeedback>
96+
<Text>Test</Text>
97+
</TouchableNativeFeedback>
98+
)
99+
).not.toThrow();
100+
});
101+
102+
test('TouchableOpacity', () => {
103+
expect(() =>
104+
render(
105+
<TouchableOpacity>
106+
<Text>Test</Text>
107+
</TouchableOpacity>
108+
)
109+
).not.toThrow();
110+
});
111+
112+
test('TouchableWithoutFeedback', () => {
113+
expect(() =>
114+
render(
115+
<TouchableWithoutFeedback>
116+
<Text>Test</Text>
117+
</TouchableWithoutFeedback>
118+
)
119+
).not.toThrow();
120+
});
121+
});
122+
123+
test('Trigger press by text', () => {
124+
const onPress = jest.fn();
125+
const { getByText } = render(
126+
<GestureHandlerRootView>
127+
<Touchable activeOpacity={0.3} onPress={onPress}>
128+
<Text>Press Me</Text>
129+
</Touchable>
130+
</GestureHandlerRootView>
131+
);
132+
133+
fireEvent.press(getByText('Press Me'));
134+
135+
expect(onPress).toHaveBeenCalled();
136+
});
Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
import React from 'react';
22
import { TouchableNativeFeedback, View } from 'react-native';
3-
export const RawButton = ({ enabled, children, ...rest }: any) => (
3+
4+
const RawButton = ({ enabled, children, ...rest }: any) => (
45
<TouchableNativeFeedback disabled={enabled === false} {...rest}>
56
{children ?? <View />}
67
</TouchableNativeFeedback>
78
);
8-
export const BaseButton = RawButton;
9-
export const RectButton = RawButton;
10-
export const BorderlessButton = TouchableNativeFeedback;
9+
10+
export const LegacyRawButton = RawButton;
11+
export const LegacyBaseButton = RawButton;
12+
export const LegacyRectButton = RawButton;
13+
export const LegacyBorderlessButton = RawButton;
14+
export const LegacyPureNativeButton = RawButton;
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
export {
2+
TouchableHighlight,
3+
TouchableNativeFeedback,
4+
TouchableOpacity,
5+
TouchableWithoutFeedback,
6+
} from 'react-native';
Lines changed: 7 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,8 @@
1-
import {
2-
TouchableHighlight,
3-
TouchableNativeFeedback,
4-
TouchableOpacity,
5-
TouchableWithoutFeedback,
6-
ScrollView,
7-
FlatList,
8-
Switch,
9-
TextInput,
10-
DrawerLayoutAndroid,
1+
export {
2+
ScrollView as LegacyScrollView,
3+
FlatList as LegacyFlatList,
4+
Switch as LegacySwitch,
5+
TextInput as LegacyTextInput,
6+
DrawerLayoutAndroid as LegacyDrawerLayoutAndroid,
7+
RefreshControl as LegacyRefreshControl,
118
} from 'react-native';
12-
13-
export default {
14-
TouchableHighlight,
15-
TouchableNativeFeedback,
16-
TouchableOpacity,
17-
TouchableWithoutFeedback,
18-
ScrollView,
19-
FlatList,
20-
Switch,
21-
TextInput,
22-
DrawerLayoutAndroid,
23-
} as const;

0 commit comments

Comments
 (0)