Skip to content

Commit 2dda510

Browse files
authored
cherry-pick(Reanimated): fix useHandler not working on web without babel plugin (#8960)
Cherry-pick of the #8883
1 parent cd4a66e commit 2dda510

File tree

6 files changed

+648
-23
lines changed

6 files changed

+648
-23
lines changed
Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
'use strict';
2+
import { renderHook } from '@testing-library/react-native';
3+
4+
import { worklet } from '../../jestUtils';
5+
import { useHandler } from '../useHandler';
6+
import {
7+
createHandlers,
8+
createUseHandlerError,
9+
renderHookWithHandlers,
10+
} from './useHandlerHelpers';
11+
12+
describe('useHandler (native)', () => {
13+
describe('valid cases', () => {
14+
describe('worklets without dependencies', () => {
15+
test('should indicate dependencies differ on initial render', () => {
16+
const { handlers } = createHandlers();
17+
18+
const { result } = renderHook(() => useHandler(handlers));
19+
20+
expect(result.current.doDependenciesDiffer).toBe(true);
21+
expect(result.current.useWeb).toBeDefined();
22+
});
23+
24+
test('should indicate no change when re-rendering with same handlers object or worklet references', () => {
25+
const { worklets, handlers } = createHandlers();
26+
27+
const { result, rerender } = renderHookWithHandlers(handlers);
28+
29+
// Initial render
30+
expect(result.current.doDependenciesDiffer).toBe(true);
31+
32+
// Re-render with same handlers object
33+
rerender({ handlers });
34+
expect(result.current.doDependenciesDiffer).toBe(false);
35+
36+
// Re-render with new handlers object but same worklet references
37+
rerender({
38+
handlers: { onScroll: worklets.worklet1, onPress: worklets.worklet2 },
39+
});
40+
expect(result.current.doDependenciesDiffer).toBe(false);
41+
});
42+
});
43+
44+
describe('worklets with dependencies', () => {
45+
test('should indicate dependencies differ on initial render', () => {
46+
const { handlers } = createHandlers();
47+
const dependencies = ['someValue'];
48+
49+
const { result } = renderHook(() => useHandler(handlers, dependencies));
50+
51+
expect(result.current.doDependenciesDiffer).toBe(true);
52+
});
53+
54+
test('should indicate change when handler is replaced', () => {
55+
const { worklets, handlers } = createHandlers();
56+
57+
const { result, rerender } = renderHookWithHandlers(handlers);
58+
59+
expect(result.current.doDependenciesDiffer).toBe(true);
60+
61+
// Replace one handler with a new worklet
62+
const newWorklet1 = worklet();
63+
64+
rerender({
65+
handlers: { onScroll: newWorklet1, onPress: worklets.worklet2 },
66+
});
67+
expect(result.current.doDependenciesDiffer).toBe(true);
68+
});
69+
70+
test('should indicate change when handler is added', () => {
71+
const { worklets } = createHandlers();
72+
const handlers = {
73+
onScroll: worklets.worklet1,
74+
};
75+
76+
const { result, rerender } = renderHookWithHandlers(handlers);
77+
78+
// Add a new handler
79+
rerender({
80+
handlers: { onScroll: worklets.worklet1, onPress: worklets.worklet2 },
81+
});
82+
expect(result.current.doDependenciesDiffer).toBe(true);
83+
});
84+
85+
test('should indicate change when handler is removed', () => {
86+
const { worklets, handlers } = createHandlers();
87+
88+
const { result, rerender } = renderHookWithHandlers(handlers);
89+
90+
// Remove a handler
91+
rerender({
92+
handlers: { onScroll: worklets.worklet1 },
93+
});
94+
expect(result.current.doDependenciesDiffer).toBe(true);
95+
});
96+
97+
test('should track dependency changes', () => {
98+
const { handlers } = createHandlers();
99+
const dependencies = ['value1'];
100+
101+
const { result, rerender } = renderHookWithHandlers(
102+
handlers,
103+
dependencies
104+
);
105+
106+
expect(result.current.doDependenciesDiffer).toBe(true);
107+
rerender({ handlers, deps: dependencies });
108+
expect(result.current.doDependenciesDiffer).toBe(false);
109+
rerender({ handlers, deps: ['value2'] });
110+
expect(result.current.doDependenciesDiffer).toBe(true);
111+
});
112+
});
113+
});
114+
115+
describe('invalid cases (native only allows worklets)', () => {
116+
test('should throw error when non-worklet function is passed without dependencies', () => {
117+
const regularHandler = jest.fn();
118+
const handlers = {
119+
onPress: regularHandler,
120+
};
121+
122+
expect(() => {
123+
renderHook(() => useHandler(handlers));
124+
}).toThrow(createUseHandlerError('onPress', false));
125+
});
126+
127+
test('should throw error when non-worklet function is passed with dependencies', () => {
128+
const regularHandler = jest.fn();
129+
const handlers = {
130+
onPress: regularHandler,
131+
};
132+
const dependencies = [regularHandler];
133+
134+
// On native, even with dependencies, non-worklets are not allowed
135+
expect(() => {
136+
renderHook(() => useHandler(handlers, dependencies));
137+
}).toThrow(createUseHandlerError('onPress', false));
138+
});
139+
140+
test('should throw error when mixed worklet and non-worklet functions are passed', () => {
141+
const workletHandler = worklet();
142+
const regularHandler = jest.fn();
143+
const handlers = {
144+
onScroll: workletHandler,
145+
onPress: regularHandler,
146+
};
147+
148+
expect(() => {
149+
renderHook(() => useHandler(handlers));
150+
}).toThrow(createUseHandlerError('onPress', false));
151+
});
152+
153+
test('should throw error when mixed worklet and non-worklet functions are passed with dependencies', () => {
154+
const workletHandler = worklet();
155+
const regularHandler = jest.fn();
156+
const handlers = {
157+
onScroll: workletHandler,
158+
onPress: regularHandler,
159+
};
160+
const dependencies = [regularHandler];
161+
162+
// On native, even with dependencies, non-worklets are not allowed
163+
expect(() => {
164+
renderHook(() => useHandler(handlers, dependencies));
165+
}).toThrow(createUseHandlerError('onPress', false));
166+
});
167+
168+
test('should throw error with handler names in error message (multiple handlers)', () => {
169+
const regularHandler1 = jest.fn();
170+
const regularHandler2 = jest.fn();
171+
const handlers = {
172+
onScroll: regularHandler1,
173+
onPress: regularHandler2,
174+
};
175+
176+
expect(() => {
177+
renderHook(() => useHandler(handlers));
178+
}).toThrow(createUseHandlerError(['onScroll', 'onPress'], false));
179+
});
180+
});
181+
});

0 commit comments

Comments
 (0)