/** * @file use-swipe-navigation.test.ts * @description Tests for useSwipeNavigation hook * * This hook provides swipe gesture handling for tab navigation. * It calculates swipe direction and triggers tab changes based on gesture velocity and distance. */ import { renderHook, act } from '@testing-library/react-native' import { useSwipeNavigation } from './use-swipe-navigation' describe('useSwipeNavigation', () => { const mockOnSwipeLeft = jest.fn() const mockOnSwipeRight = jest.fn() beforeEach(() => { jest.clearAllMocks() }) describe('initialization', () => { it('should initialize with default values', () => { const { result } = renderHook(() => useSwipeNavigation({ onSwipeLeft: mockOnSwipeLeft, onSwipeRight: mockOnSwipeRight, }) ) expect(result.current.handleGestureEvent).toBeDefined() expect(result.current.handleGestureStateChange).toBeDefined() }) it('should accept custom threshold', () => { const { result } = renderHook(() => useSwipeNavigation({ onSwipeLeft: mockOnSwipeLeft, onSwipeRight: mockOnSwipeRight, threshold: 100, }) ) expect(result.current.handleGestureEvent).toBeDefined() }) it('should accept custom velocity threshold', () => { const { result } = renderHook(() => useSwipeNavigation({ onSwipeLeft: mockOnSwipeLeft, onSwipeRight: mockOnSwipeRight, velocityThreshold: 500, }) ) expect(result.current.handleGestureEvent).toBeDefined() }) }) describe('swipe detection', () => { it('should call onSwipeLeft when swiping left with sufficient distance', () => { const { result } = renderHook(() => useSwipeNavigation({ onSwipeLeft: mockOnSwipeLeft, onSwipeRight: mockOnSwipeRight, threshold: 50, }) ) // Simulate gesture state change with left swipe act(() => { result.current.handleGestureStateChange({ nativeEvent: { state: 5, // END state translationX: -100, velocityX: -200, }, } as any) }) expect(mockOnSwipeLeft).toHaveBeenCalledTimes(1) expect(mockOnSwipeRight).not.toHaveBeenCalled() }) it('should call onSwipeRight when swiping right with sufficient distance', () => { const { result } = renderHook(() => useSwipeNavigation({ onSwipeLeft: mockOnSwipeLeft, onSwipeRight: mockOnSwipeRight, threshold: 50, }) ) // Simulate gesture state change with right swipe act(() => { result.current.handleGestureStateChange({ nativeEvent: { state: 5, // END state translationX: 100, velocityX: 200, }, } as any) }) expect(mockOnSwipeRight).toHaveBeenCalledTimes(1) expect(mockOnSwipeLeft).not.toHaveBeenCalled() }) it('should call onSwipeLeft when velocity is high even with small distance', () => { const { result } = renderHook(() => useSwipeNavigation({ onSwipeLeft: mockOnSwipeLeft, onSwipeRight: mockOnSwipeRight, threshold: 100, velocityThreshold: 300, }) ) // Simulate gesture with high velocity but small distance act(() => { result.current.handleGestureStateChange({ nativeEvent: { state: 5, // END state translationX: -30, velocityX: -500, }, } as any) }) expect(mockOnSwipeLeft).toHaveBeenCalledTimes(1) }) it('should not trigger swipe when distance and velocity are below thresholds', () => { const { result } = renderHook(() => useSwipeNavigation({ onSwipeLeft: mockOnSwipeLeft, onSwipeRight: mockOnSwipeRight, threshold: 100, velocityThreshold: 500, }) ) // Simulate gesture with small distance and low velocity act(() => { result.current.handleGestureStateChange({ nativeEvent: { state: 5, // END state translationX: -30, velocityX: -100, }, } as any) }) expect(mockOnSwipeLeft).not.toHaveBeenCalled() expect(mockOnSwipeRight).not.toHaveBeenCalled() }) }) describe('disabled state', () => { it('should not trigger swipe when disabled', () => { const { result } = renderHook(() => useSwipeNavigation({ onSwipeLeft: mockOnSwipeLeft, onSwipeRight: mockOnSwipeRight, enabled: false, }) ) act(() => { result.current.handleGestureStateChange({ nativeEvent: { state: 5, // END state translationX: -100, velocityX: -500, }, } as any) }) expect(mockOnSwipeLeft).not.toHaveBeenCalled() expect(mockOnSwipeRight).not.toHaveBeenCalled() }) }) describe('boundary conditions', () => { it('should not call onSwipeLeft when canSwipeLeft is false', () => { const { result } = renderHook(() => useSwipeNavigation({ onSwipeLeft: mockOnSwipeLeft, onSwipeRight: mockOnSwipeRight, canSwipeLeft: false, }) ) act(() => { result.current.handleGestureStateChange({ nativeEvent: { state: 5, // END state translationX: -100, velocityX: -500, }, } as any) }) expect(mockOnSwipeLeft).not.toHaveBeenCalled() }) it('should not call onSwipeRight when canSwipeRight is false', () => { const { result } = renderHook(() => useSwipeNavigation({ onSwipeLeft: mockOnSwipeLeft, onSwipeRight: mockOnSwipeRight, canSwipeRight: false, }) ) act(() => { result.current.handleGestureStateChange({ nativeEvent: { state: 5, // END state translationX: 100, velocityX: 500, }, } as any) }) expect(mockOnSwipeRight).not.toHaveBeenCalled() }) }) })