veza/apps/web/src/hooks/useRoutePreload-additional.test.ts

206 lines
5.8 KiB
TypeScript

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);
});
});
});