import { renderHook, act, waitFor } from '@testing-library/react'; import { useCompanies } from '@/hooks/useCompanies'; import { getAvailableCompanies } from '@/lib/api/csv-rates'; jest.mock('@/lib/api/csv-rates', () => ({ getAvailableCompanies: jest.fn(), })); const mockGetAvailableCompanies = jest.mocked(getAvailableCompanies); const MOCK_COMPANIES = ['Maersk', 'MSC', 'CMA CGM', 'Hapag-Lloyd']; beforeEach(() => { jest.clearAllMocks(); }); describe('useCompanies', () => { describe('initial state', () => { it('starts with loading=true', () => { mockGetAvailableCompanies.mockResolvedValue({ companies: MOCK_COMPANIES, total: 4 }); const { result } = renderHook(() => useCompanies()); expect(result.current.loading).toBe(true); }); it('starts with an empty companies array', () => { mockGetAvailableCompanies.mockResolvedValue({ companies: MOCK_COMPANIES, total: 4 }); const { result } = renderHook(() => useCompanies()); expect(result.current.companies).toEqual([]); }); it('starts with error=null', () => { mockGetAvailableCompanies.mockResolvedValue({ companies: MOCK_COMPANIES, total: 4 }); const { result } = renderHook(() => useCompanies()); expect(result.current.error).toBeNull(); }); }); describe('on mount — success', () => { it('fetches companies automatically on mount', async () => { mockGetAvailableCompanies.mockResolvedValue({ companies: MOCK_COMPANIES, total: 4 }); renderHook(() => useCompanies()); await waitFor(() => { expect(mockGetAvailableCompanies).toHaveBeenCalledTimes(1); }); }); it('populates companies after a successful fetch', async () => { mockGetAvailableCompanies.mockResolvedValue({ companies: MOCK_COMPANIES, total: 4 }); const { result } = renderHook(() => useCompanies()); await waitFor(() => { expect(result.current.loading).toBe(false); }); expect(result.current.companies).toEqual(MOCK_COMPANIES); expect(result.current.error).toBeNull(); }); it('handles an empty companies list', async () => { mockGetAvailableCompanies.mockResolvedValue({ companies: [], total: 0 }); const { result } = renderHook(() => useCompanies()); await waitFor(() => { expect(result.current.loading).toBe(false); }); expect(result.current.companies).toEqual([]); }); }); describe('on mount — error', () => { it('sets error when the API call fails', async () => { mockGetAvailableCompanies.mockRejectedValue(new Error('Service unavailable')); const { result } = renderHook(() => useCompanies()); await waitFor(() => { expect(result.current.loading).toBe(false); }); expect(result.current.error).toBe('Service unavailable'); expect(result.current.companies).toEqual([]); }); it('uses a default error message when the error has no message', async () => { mockGetAvailableCompanies.mockRejectedValue({}); const { result } = renderHook(() => useCompanies()); await waitFor(() => { expect(result.current.loading).toBe(false); }); expect(result.current.error).toBe('Failed to fetch companies'); }); }); describe('refetch', () => { it('exposes a refetch function', async () => { mockGetAvailableCompanies.mockResolvedValue({ companies: MOCK_COMPANIES, total: 4 }); const { result } = renderHook(() => useCompanies()); await waitFor(() => expect(result.current.loading).toBe(false)); expect(typeof result.current.refetch).toBe('function'); }); it('re-triggers the API call when refetch is invoked', async () => { mockGetAvailableCompanies.mockResolvedValue({ companies: MOCK_COMPANIES, total: 4 }); const { result } = renderHook(() => useCompanies()); await waitFor(() => expect(result.current.loading).toBe(false)); await act(async () => { await result.current.refetch(); }); expect(mockGetAvailableCompanies).toHaveBeenCalledTimes(2); }); it('updates companies with fresh data on refetch', async () => { mockGetAvailableCompanies .mockResolvedValueOnce({ companies: ['Maersk'], total: 1 }) .mockResolvedValueOnce({ companies: ['Maersk', 'MSC'], total: 2 }); const { result } = renderHook(() => useCompanies()); await waitFor(() => expect(result.current.companies).toEqual(['Maersk'])); await act(async () => { await result.current.refetch(); }); expect(result.current.companies).toEqual(['Maersk', 'MSC']); }); }); });