Some checks are pending
Deploy to Test Environment / deploy-to-test (push) Has started running
- Implement tests for `useFlyers`, `useMasterItems`, `useModal`, `useUserData` hooks to ensure correct functionality and error handling. - Create tests for `fileUpload.middleware` and `validation.middleware` to validate file uploads and request data. - Add tests for `AddressForm` and `AuthView` components to verify rendering, user interactions, and API calls. - Develop tests for `deals.routes` to check authentication and response for best prices on watched items.
140 lines
5.0 KiB
TypeScript
140 lines
5.0 KiB
TypeScript
// src/hooks/useFlyers.test.tsx
|
|
import React, { ReactNode } from 'react';
|
|
import { renderHook, act } from '@testing-library/react';
|
|
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
import { FlyersProvider, useFlyers } from './useFlyers';
|
|
import { useInfiniteQuery } from './useInfiniteQuery';
|
|
import type { Flyer } from '../types';
|
|
|
|
// 1. Mock the useInfiniteQuery hook, which is the dependency of our FlyersProvider.
|
|
vi.mock('./useInfiniteQuery');
|
|
|
|
// 2. Create a typed mock of the hook for type safety and autocompletion.
|
|
const mockedUseInfiniteQuery = vi.mocked(useInfiniteQuery);
|
|
|
|
// 3. A simple wrapper component that renders our provider.
|
|
// This is necessary because the useFlyers hook needs to be a child of FlyersProvider.
|
|
const wrapper = ({ children }: { children: ReactNode }) => <FlyersProvider>{children}</FlyersProvider>;
|
|
|
|
describe('useFlyers Hook and FlyersProvider', () => {
|
|
// Create mock functions that we can spy on to see if they are called.
|
|
const mockFetchNextPage = vi.fn();
|
|
const mockRefetch = vi.fn();
|
|
|
|
beforeEach(() => {
|
|
// Clear mock history before each test to ensure test isolation.
|
|
vi.clearAllMocks();
|
|
});
|
|
|
|
it('should throw an error if useFlyers is used outside of FlyersProvider', () => {
|
|
// Suppress the expected console.error for this test to keep the output clean.
|
|
const originalError = console.error;
|
|
console.error = vi.fn();
|
|
|
|
// Expecting renderHook to throw an error because there's no provider.
|
|
expect(() => renderHook(() => useFlyers())).toThrow('useFlyers must be used within a FlyersProvider');
|
|
|
|
// Restore the original console.error function.
|
|
console.error = originalError;
|
|
});
|
|
|
|
it('should return the initial loading state correctly', () => {
|
|
// Arrange: Configure the mocked hook to return a loading state.
|
|
mockedUseInfiniteQuery.mockReturnValue({
|
|
data: [],
|
|
isLoading: true,
|
|
error: null,
|
|
fetchNextPage: mockFetchNextPage,
|
|
hasNextPage: false,
|
|
refetch: mockRefetch,
|
|
isRefetching: false,
|
|
isFetchingNextPage: false,
|
|
});
|
|
|
|
// Act: Render the hook within the provider wrapper.
|
|
const { result } = renderHook(() => useFlyers(), { wrapper });
|
|
|
|
// Assert: Check that the context values match the loading state.
|
|
expect(result.current.isLoadingFlyers).toBe(true);
|
|
expect(result.current.flyers).toEqual([]);
|
|
expect(result.current.flyersError).toBeNull();
|
|
});
|
|
|
|
it('should return flyers data and hasNextPage on successful fetch', () => {
|
|
// Arrange: Mock a successful data fetch.
|
|
const mockFlyers: Flyer[] = [
|
|
{ flyer_id: 1, file_name: 'flyer1.jpg', image_url: 'url1', item_count: 5, created_at: '2024-01-01' },
|
|
];
|
|
mockedUseInfiniteQuery.mockReturnValue({
|
|
data: mockFlyers,
|
|
isLoading: false,
|
|
error: null,
|
|
fetchNextPage: mockFetchNextPage,
|
|
hasNextPage: true,
|
|
refetch: mockRefetch,
|
|
isRefetching: false,
|
|
isFetchingNextPage: false,
|
|
});
|
|
|
|
// Act
|
|
const { result } = renderHook(() => useFlyers(), { wrapper });
|
|
|
|
// Assert
|
|
expect(result.current.isLoadingFlyers).toBe(false);
|
|
expect(result.current.flyers).toEqual(mockFlyers);
|
|
expect(result.current.hasNextFlyersPage).toBe(true);
|
|
});
|
|
|
|
it('should return an error state if the fetch fails', () => {
|
|
// Arrange: Mock a failed data fetch.
|
|
const mockError = new Error('Failed to fetch');
|
|
mockedUseInfiniteQuery.mockReturnValue({
|
|
data: [],
|
|
isLoading: false,
|
|
error: mockError,
|
|
fetchNextPage: mockFetchNextPage,
|
|
hasNextPage: false,
|
|
refetch: mockRefetch,
|
|
isRefetching: false,
|
|
isFetchingNextPage: false,
|
|
});
|
|
|
|
// Act
|
|
const { result } = renderHook(() => useFlyers(), { wrapper });
|
|
|
|
// Assert
|
|
expect(result.current.isLoadingFlyers).toBe(false);
|
|
expect(result.current.flyers).toEqual([]);
|
|
expect(result.current.flyersError).toBe(mockError);
|
|
});
|
|
|
|
it('should call fetchNextFlyersPage when the context function is invoked', () => {
|
|
// Arrange
|
|
mockedUseInfiniteQuery.mockReturnValue({
|
|
data: [], isLoading: false, error: null, hasNextPage: true, isRefetching: false, isFetchingNextPage: false,
|
|
fetchNextPage: mockFetchNextPage, // Pass the mock function
|
|
refetch: mockRefetch,
|
|
});
|
|
const { result } = renderHook(() => useFlyers(), { wrapper });
|
|
|
|
// Act: Use `act` to wrap state updates.
|
|
act(() => {
|
|
result.current.fetchNextFlyersPage();
|
|
});
|
|
|
|
// Assert
|
|
expect(mockFetchNextPage).toHaveBeenCalledTimes(1);
|
|
});
|
|
|
|
it('should call refetchFlyers when the context function is invoked', () => {
|
|
// Arrange
|
|
mockedUseInfiniteQuery.mockReturnValue({ data: [], isLoading: false, error: null, hasNextPage: false, isRefetching: false, isFetchingNextPage: false, fetchNextPage: mockFetchNextPage, refetch: mockRefetch });
|
|
const { result } = renderHook(() => useFlyers(), { wrapper });
|
|
|
|
// Act
|
|
act(() => { result.current.refetchFlyers(); });
|
|
|
|
// Assert
|
|
expect(mockRefetch).toHaveBeenCalledTimes(1);
|
|
});
|
|
}); |