import { renderHook, act, waitFor } from '@testing-library/react'; import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; import { useRoutePreload, usePerformanceOptimization, useErrorHandler, useLoadingState, } from './useRoutePreload'; describe('useRoutePreload additional hooks', () => { beforeEach(() => { vi.clearAllMocks(); vi.useFakeTimers(); }); afterEach(() => { vi.useRealTimers(); }); describe('useRoutePreload', () => { it('should preload route with delay', async () => { const { result } = renderHook(() => useRoutePreload('/test-route', 100)); expect(result.current.isPreloading).toBe(false); expect(result.current.isPreloaded).toBe(false); act(() => { result.current.preloadRoute(); }); expect(result.current.isPreloading).toBe(true); await act(async () => { vi.advanceTimersByTime(100); await waitFor(() => { expect(result.current.isPreloaded).toBe(true); }); }); expect(result.current.isPreloading).toBe(false); }); }); describe('usePerformanceOptimization', () => { it('should return performance optimization hook', () => { const { result } = renderHook(() => usePerformanceOptimization()); expect(result.current).toBeDefined(); expect(result.current).toHaveProperty('isVisible'); expect(result.current).toHaveProperty('optimizeForVisibility'); expect(result.current).toHaveProperty('throttle'); expect(result.current).toHaveProperty('debounce'); }); it('should detect visibility changes', () => { const { result } = renderHook(() => usePerformanceOptimization()); expect(result.current.isVisible).toBe(true); Object.defineProperty(document, 'hidden', { writable: true, value: true, }); document.dispatchEvent(new Event('visibilitychange')); expect(result.current.isVisible).toBe(false); }); it('should throttle function calls', () => { const { result } = renderHook(() => usePerformanceOptimization()); const mockFn = vi.fn(); const throttled = result.current.throttle(mockFn, 100); throttled(); throttled(); throttled(); expect(mockFn).toHaveBeenCalledTimes(1); }); it('should debounce function calls', async () => { const { result } = renderHook(() => usePerformanceOptimization()); const mockFn = vi.fn(); const debounced = result.current.debounce(mockFn, 100); debounced(); debounced(); debounced(); expect(mockFn).not.toHaveBeenCalled(); await act(async () => { vi.advanceTimersByTime(100); }); expect(mockFn).toHaveBeenCalledTimes(1); }); }); describe('useErrorHandler', () => { it('should return error handler hook', () => { const { result } = renderHook(() => useErrorHandler()); expect(result.current).toBeDefined(); expect(result.current).toHaveProperty('error'); expect(result.current).toHaveProperty('handleError'); expect(result.current).toHaveProperty('clearError'); expect(result.current).toHaveProperty('withErrorHandling'); }); it('should handle errors', () => { const { result } = renderHook(() => useErrorHandler()); const testError = new Error('Test error'); act(() => { result.current.handleError(testError); }); expect(result.current.error).toEqual(testError); }); it('should clear errors', () => { const { result } = renderHook(() => useErrorHandler()); const testError = new Error('Test error'); act(() => { result.current.handleError(testError); }); expect(result.current.error).toEqual(testError); act(() => { result.current.clearError(); }); expect(result.current.error).toBeNull(); }); it('should wrap function with error handling', () => { const { result } = renderHook(() => useErrorHandler()); const testFn = vi.fn(() => { throw new Error('Test error'); }); const wrappedFn = result.current.withErrorHandling(testFn); expect(() => wrappedFn()).toThrow(); expect(result.current.error).toBeDefined(); }); }); describe('useLoadingState', () => { it('should return loading state hook', () => { const { result } = renderHook(() => useLoadingState()); expect(result.current).toBeDefined(); expect(result.current).toHaveProperty('isLoading'); expect(result.current).toHaveProperty('setLoading'); expect(result.current).toHaveProperty('setLoadingFor'); expect(result.current).toHaveProperty('isLoadingFor'); expect(result.current).toHaveProperty('withLoading'); }); it('should set loading state', () => { const { result } = renderHook(() => useLoadingState()); act(() => { result.current.setLoading(true); }); expect(result.current.isLoading).toBe(true); }); it('should set loading state for specific key', () => { const { result } = renderHook(() => useLoadingState()); act(() => { result.current.setLoadingFor('test-key', true); }); expect(result.current.isLoadingFor('test-key')).toBe(true); }); it('should handle async operations with loading', async () => { const { result } = renderHook(() => useLoadingState()); const asyncFn = vi.fn(async () => { await new Promise((resolve) => setTimeout(resolve, 100)); return 'result'; }); const promise = act(async () => { return await result.current.withLoading(asyncFn); }); expect(result.current.isLoading).toBe(true); await act(async () => { vi.advanceTimersByTime(100); await promise; }); expect(result.current.isLoading).toBe(false); }); }); });