/** * Component: Audiobooks Hooks Tests * Documentation: documentation/frontend/components.md */ // @vitest-environment jsdom import React from 'react'; import { render, screen } from '@testing-library/react'; import { beforeEach, describe, expect, it, vi } from 'vitest'; const useSWRMock = vi.hoisted(() => vi.fn()); const authenticatedFetcherMock = vi.hoisted(() => vi.fn()); vi.mock('swr', () => ({ default: useSWRMock, })); vi.mock('@/lib/utils/api', () => ({ authenticatedFetcher: authenticatedFetcherMock, })); const HookProbe = ({ label, value }: { label: string; value: any }) => (
{JSON.stringify(value)}
); describe('useAudiobooks hooks', () => { beforeEach(() => { useSWRMock.mockReset(); authenticatedFetcherMock.mockReset(); vi.resetModules(); }); it('builds the popular audiobooks endpoint and returns data', async () => { useSWRMock.mockReturnValue({ data: { audiobooks: [{ asin: 'a1' }], totalPages: 3, totalCount: 30, hasMore: true }, error: null, isLoading: false, }); const { useAudiobooks } = await import('@/lib/hooks/useAudiobooks'); const Probe = () => { const result = useAudiobooks('popular', 10, 2); return ; }; render(); expect(useSWRMock).toHaveBeenCalledWith( '/api/audiobooks/popular?page=2&limit=10', authenticatedFetcherMock, expect.objectContaining({ dedupingInterval: 60000 }) ); const parsed = JSON.parse(screen.getByTestId('popular').textContent || '{}'); expect(parsed.audiobooks).toHaveLength(1); expect(parsed.totalPages).toBe(3); expect(parsed.hasMore).toBe(true); }); it('skips search when the query is empty', async () => { useSWRMock.mockReturnValue({ data: null, error: null, isLoading: false }); const { useSearch } = await import('@/lib/hooks/useAudiobooks'); const Probe = () => { const result = useSearch('', 1); return ; }; render(); expect(useSWRMock).toHaveBeenCalledWith( null, authenticatedFetcherMock, expect.objectContaining({ dedupingInterval: 30000 }) ); const parsed = JSON.parse(screen.getByTestId('search').textContent || '{}'); expect(parsed.isLoading).toBeFalsy(); }); it('requests audiobook details when an ASIN is provided', async () => { useSWRMock.mockReturnValue({ data: { audiobook: { asin: 'a2', title: 'Details' } }, error: null, isLoading: false, }); const { useAudiobookDetails } = await import('@/lib/hooks/useAudiobooks'); const Probe = () => { const result = useAudiobookDetails('a2'); return ; }; render(); expect(useSWRMock).toHaveBeenCalledWith( '/api/audiobooks/a2', authenticatedFetcherMock, expect.objectContaining({ dedupingInterval: 300000 }) ); const parsed = JSON.parse(screen.getByTestId('details').textContent || '{}'); expect(parsed.audiobook.asin).toBe('a2'); }); });