progress enforcing adr-0005
This commit is contained in:
@@ -2,14 +2,13 @@
|
||||
import { renderHook } from '@testing-library/react';
|
||||
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
||||
import { useFlyerItems } from './useFlyerItems';
|
||||
import { useApiOnMount } from './useApiOnMount';
|
||||
import * as apiClient from '../services/apiClient';
|
||||
import * as useFlyerItemsQueryModule from './queries/useFlyerItemsQuery';
|
||||
import { createMockFlyer, createMockFlyerItem } from '../tests/utils/mockFactories';
|
||||
|
||||
// Mock the underlying useApiOnMount hook to isolate the useFlyerItems hook's logic.
|
||||
vi.mock('./useApiOnMount');
|
||||
// Mock the underlying query hook to isolate the useFlyerItems hook's logic.
|
||||
vi.mock('./queries/useFlyerItemsQuery');
|
||||
|
||||
const mockedUseApiOnMount = vi.mocked(useApiOnMount);
|
||||
const mockedUseFlyerItemsQuery = vi.mocked(useFlyerItemsQueryModule.useFlyerItemsQuery);
|
||||
|
||||
describe('useFlyerItems Hook', () => {
|
||||
const mockFlyer = createMockFlyer({
|
||||
@@ -39,19 +38,16 @@ describe('useFlyerItems Hook', () => {
|
||||
];
|
||||
|
||||
beforeEach(() => {
|
||||
// Clear mock history before each test
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
it('should return initial state and not call useApiOnMount when flyer is null', () => {
|
||||
// Arrange: Mock the return value of the inner hook.
|
||||
mockedUseApiOnMount.mockReturnValue({
|
||||
data: null,
|
||||
loading: false,
|
||||
it('should return initial state when flyer is null', () => {
|
||||
// Arrange: Mock the return value of the query hook.
|
||||
mockedUseFlyerItemsQuery.mockReturnValue({
|
||||
data: undefined,
|
||||
isLoading: false,
|
||||
error: null,
|
||||
isRefetching: false,
|
||||
reset: vi.fn(),
|
||||
});
|
||||
} as ReturnType<typeof useFlyerItemsQueryModule.useFlyerItemsQuery>);
|
||||
|
||||
// Act: Render the hook with a null flyer.
|
||||
const { result } = renderHook(() => useFlyerItems(null));
|
||||
@@ -60,57 +56,41 @@ describe('useFlyerItems Hook', () => {
|
||||
expect(result.current.flyerItems).toEqual([]);
|
||||
expect(result.current.isLoading).toBe(false);
|
||||
expect(result.current.error).toBeNull();
|
||||
// Assert: Check that useApiOnMount was called with `enabled: false`.
|
||||
expect(mockedUseApiOnMount).toHaveBeenCalledWith(
|
||||
expect.any(Function), // the wrapped fetcher function
|
||||
[null], // dependencies array
|
||||
{ enabled: false }, // options object
|
||||
undefined, // flyer_id
|
||||
);
|
||||
// Assert: Check that useFlyerItemsQuery was called with undefined flyerId.
|
||||
expect(mockedUseFlyerItemsQuery).toHaveBeenCalledWith(undefined);
|
||||
});
|
||||
|
||||
it('should call useApiOnMount with enabled: true when a flyer is provided', () => {
|
||||
mockedUseApiOnMount.mockReturnValue({
|
||||
data: null,
|
||||
loading: true,
|
||||
it('should call useFlyerItemsQuery with flyerId when a flyer is provided', () => {
|
||||
mockedUseFlyerItemsQuery.mockReturnValue({
|
||||
data: undefined,
|
||||
isLoading: true,
|
||||
error: null,
|
||||
isRefetching: false,
|
||||
reset: vi.fn(),
|
||||
});
|
||||
} as ReturnType<typeof useFlyerItemsQueryModule.useFlyerItemsQuery>);
|
||||
|
||||
renderHook(() => useFlyerItems(mockFlyer));
|
||||
|
||||
// Assert: Check that useApiOnMount was called with the correct parameters.
|
||||
expect(mockedUseApiOnMount).toHaveBeenCalledWith(
|
||||
expect.any(Function),
|
||||
[mockFlyer],
|
||||
{ enabled: true },
|
||||
mockFlyer.flyer_id,
|
||||
);
|
||||
// Assert: Check that useFlyerItemsQuery was called with the correct flyerId.
|
||||
expect(mockedUseFlyerItemsQuery).toHaveBeenCalledWith(123);
|
||||
});
|
||||
|
||||
it('should return isLoading: true when the inner hook is loading', () => {
|
||||
mockedUseApiOnMount.mockReturnValue({
|
||||
data: null,
|
||||
loading: true,
|
||||
it('should return isLoading: true when the query is loading', () => {
|
||||
mockedUseFlyerItemsQuery.mockReturnValue({
|
||||
data: undefined,
|
||||
isLoading: true,
|
||||
error: null,
|
||||
isRefetching: false,
|
||||
reset: vi.fn(),
|
||||
});
|
||||
} as ReturnType<typeof useFlyerItemsQueryModule.useFlyerItemsQuery>);
|
||||
|
||||
const { result } = renderHook(() => useFlyerItems(mockFlyer));
|
||||
|
||||
expect(result.current.isLoading).toBe(true);
|
||||
});
|
||||
|
||||
it('should return flyerItems when the inner hook provides data', () => {
|
||||
mockedUseApiOnMount.mockReturnValue({
|
||||
data: { items: mockFlyerItems },
|
||||
loading: false,
|
||||
it('should return flyerItems when the query provides data', () => {
|
||||
mockedUseFlyerItemsQuery.mockReturnValue({
|
||||
data: mockFlyerItems,
|
||||
isLoading: false,
|
||||
error: null,
|
||||
isRefetching: false,
|
||||
reset: vi.fn(),
|
||||
});
|
||||
} as ReturnType<typeof useFlyerItemsQueryModule.useFlyerItemsQuery>);
|
||||
|
||||
const { result } = renderHook(() => useFlyerItems(mockFlyer));
|
||||
|
||||
@@ -119,15 +99,13 @@ describe('useFlyerItems Hook', () => {
|
||||
expect(result.current.error).toBeNull();
|
||||
});
|
||||
|
||||
it('should return an error when the inner hook returns an error', () => {
|
||||
it('should return an error when the query returns an error', () => {
|
||||
const mockError = new Error('Failed to fetch');
|
||||
mockedUseApiOnMount.mockReturnValue({
|
||||
data: null,
|
||||
loading: false,
|
||||
mockedUseFlyerItemsQuery.mockReturnValue({
|
||||
data: undefined,
|
||||
isLoading: false,
|
||||
error: mockError,
|
||||
isRefetching: false,
|
||||
reset: vi.fn(),
|
||||
});
|
||||
} as ReturnType<typeof useFlyerItemsQueryModule.useFlyerItemsQuery>);
|
||||
|
||||
const { result } = renderHook(() => useFlyerItems(mockFlyer));
|
||||
|
||||
@@ -135,46 +113,4 @@ describe('useFlyerItems Hook', () => {
|
||||
expect(result.current.flyerItems).toEqual([]);
|
||||
expect(result.current.error).toEqual(mockError);
|
||||
});
|
||||
|
||||
describe('wrappedFetcher behavior', () => {
|
||||
it('should reject if called with undefined flyerId', async () => {
|
||||
// We need to trigger the hook to get access to the internal wrappedFetcher
|
||||
mockedUseApiOnMount.mockReturnValue({
|
||||
data: null,
|
||||
loading: false,
|
||||
error: null,
|
||||
isRefetching: false,
|
||||
reset: vi.fn(),
|
||||
});
|
||||
renderHook(() => useFlyerItems(mockFlyer));
|
||||
|
||||
// The first argument passed to useApiOnMount is the wrappedFetcher function
|
||||
const wrappedFetcher = mockedUseApiOnMount.mock.calls[0][0];
|
||||
|
||||
// Verify the fetcher rejects when no ID is passed (which shouldn't happen in normal flow due to 'enabled')
|
||||
await expect(wrappedFetcher(undefined)).rejects.toThrow(
|
||||
'Cannot fetch items for an undefined flyer ID.',
|
||||
);
|
||||
});
|
||||
|
||||
it('should call apiClient.fetchFlyerItems when called with a valid ID', async () => {
|
||||
mockedUseApiOnMount.mockReturnValue({
|
||||
data: null,
|
||||
loading: false,
|
||||
error: null,
|
||||
isRefetching: false,
|
||||
reset: vi.fn(),
|
||||
});
|
||||
renderHook(() => useFlyerItems(mockFlyer));
|
||||
|
||||
const wrappedFetcher = mockedUseApiOnMount.mock.calls[0][0];
|
||||
const mockResponse = new Response();
|
||||
const mockedApiClient = vi.mocked(apiClient);
|
||||
mockedApiClient.fetchFlyerItems.mockResolvedValue(mockResponse);
|
||||
const response = await wrappedFetcher(123);
|
||||
|
||||
expect(mockedApiClient.fetchFlyerItems).toHaveBeenCalledWith(123);
|
||||
expect(response).toBe(mockResponse);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user