import React from 'react'; import { renderHook } from '@testing-library/react-native'; import { useDragGesture } from '../../hooks/drag/useDragGesture'; import { DragStateProvider } from '../../contexts/DragStateContext'; import { createMockAnimatedRef } from '../utils/test-utils'; // Mock scheduleOnRN to execute synchronously in tests jest.mock('react-native-worklets', () => ({ scheduleOnRN: jest.fn((fn, ...args) => fn(...args)), })); describe('useDragGesture', () => { const createWrapper = () => { const Wrapper = ({ children }: { children: React.ReactNode }) => ( {children} ); return Wrapper; }; const defaultConfig = { itemId: 'item-1', index: 0, totalItems: 5, enabled: true, containerRef: createMockAnimatedRef(), }; const defaultCallbacks = { onReorderByDelta: jest.fn(), onHapticFeedback: jest.fn(), }; beforeEach(() => { jest.clearAllMocks(); }); it('returns panGesture, isDragging, and translateY', async () => { const { result } = await renderHook( () => useDragGesture(defaultConfig, defaultCallbacks), { wrapper: createWrapper() }, ); expect(result.current.panGesture).toBeDefined(); expect(result.current.isDragging).toBeDefined(); expect(result.current.translateY).toBeDefined(); }); it('initializes isDragging to false', async () => { const { result } = await renderHook( () => useDragGesture(defaultConfig, defaultCallbacks), { wrapper: createWrapper() }, ); expect(result.current.isDragging.value).toBe(false); }); it('initializes translateY to 0', async () => { const { result } = await renderHook( () => useDragGesture(defaultConfig, defaultCallbacks), { wrapper: createWrapper() }, ); expect(result.current.translateY.value).toBe(0); }); it('creates a Pan gesture with long press activation', async () => { const { result } = await renderHook( () => useDragGesture(defaultConfig, defaultCallbacks), { wrapper: createWrapper() }, ); // Gesture should be created by Gesture.Pan() expect(result.current.panGesture).toBeDefined(); }); it('respects the enabled config', async () => { const { result } = await renderHook( () => useDragGesture( { ...defaultConfig, enabled: false }, defaultCallbacks, ), { wrapper: createWrapper() }, ); // Gesture is still created but enabled is set via config expect(result.current.panGesture).toBeDefined(); }); it('uses the containerRef for measuring', async () => { const containerRef = createMockAnimatedRef(); const { result } = await renderHook( () => useDragGesture( { ...defaultConfig, containerRef }, defaultCallbacks, ), { wrapper: createWrapper() }, ); expect(result.current.panGesture).toBeDefined(); }); it('updates gesture when config changes', async () => { const { result, rerender } = await renderHook( ({ config }) => useDragGesture(config, defaultCallbacks), { wrapper: createWrapper(), initialProps: { config: defaultConfig }, }, ); const initialGesture = result.current.panGesture; await rerender({ config: { ...defaultConfig, enabled: false }, }); // Gesture should be recreated when enabled changes expect(result.current.panGesture).toBeDefined(); }); it('accepts different item indices', async () => { // Test with different indices sequentially to avoid overlapping act() calls for (const index of [0, 2, 4]) { const { result } = await renderHook( () => useDragGesture( { ...defaultConfig, index, itemId: `item-${index}` }, defaultCallbacks, ), { wrapper: createWrapper() }, ); expect(result.current.panGesture).toBeDefined(); expect(result.current.isDragging.value).toBe(false); expect(result.current.translateY.value).toBe(0); } }); it('handles haptic feedback callback', async () => { const onHapticFeedback = jest.fn(); const { result } = await renderHook( () => useDragGesture(defaultConfig, { ...defaultCallbacks, onHapticFeedback }), { wrapper: createWrapper() }, ); // Callback should be storable and gesture should be created expect(result.current.panGesture).toBeDefined(); }); it('handles reorder callback', async () => { const onReorderByDelta = jest.fn(); const { result } = await renderHook( () => useDragGesture(defaultConfig, { ...defaultCallbacks, onReorderByDelta }), { wrapper: createWrapper() }, ); // Callback should be storable and gesture should be created expect(result.current.panGesture).toBeDefined(); }); });