Spaces:
Runtime error
Runtime error
| import { describe, it, expect, vi, beforeEach } from 'vitest'; | |
| import { renderHook, waitFor } from '@testing-library/react'; | |
| import { useChapterPages } from './useChapterPages'; | |
| import * as lib from './offlineLibrary'; | |
| import * as apiMod from '../../../utils/apiClient'; | |
| beforeEach(() => { | |
| vi.restoreAllMocks(); | |
| vi.stubGlobal('URL', { | |
| ...URL, | |
| createObjectURL: vi.fn(() => 'blob:fake'), | |
| revokeObjectURL: vi.fn(), | |
| }); | |
| }); | |
| describe('useChapterPages', () => { | |
| it('serves pages from IndexedDB blobs when downloaded (no network)', async () => { | |
| vi.spyOn(lib, 'isChapterDownloaded').mockResolvedValue(true); | |
| vi.spyOn(lib, 'getChapterPageBlobs').mockResolvedValue([new Blob(['a']), new Blob(['b'])]); | |
| const api = vi.spyOn(apiMod, 'apiClient'); | |
| const { result } = renderHook(() => useChapterPages('m1', '3')); | |
| await waitFor(() => expect(result.current.source).toBe('offline')); | |
| expect(result.current.pages).toHaveLength(2); | |
| expect(result.current.pages[0]).toEqual({ url: 'blob:fake', index: 0 }); | |
| expect(api).not.toHaveBeenCalled(); | |
| }); | |
| it('falls back to the network fetch when not downloaded', async () => { | |
| vi.spyOn(lib, 'isChapterDownloaded').mockResolvedValue(false); | |
| vi.spyOn(apiMod, 'apiClient').mockResolvedValue({ | |
| pages: [{ image_url: 'http://h/p0.jpg', number: 0 }], | |
| }); | |
| const { result } = renderHook(() => useChapterPages('m1', '3')); | |
| await waitFor(() => expect(result.current.source).toBe('network')); | |
| expect(result.current.pages[0]).toEqual({ url: 'http://h/p0.jpg', index: 0 }); | |
| // The hook owns error presentation, so it must suppress apiClient's global toast. | |
| expect(apiMod.apiClient).toHaveBeenCalledWith( | |
| '/api/v1/media/Manga/m1/chapters/3/', | |
| { skipToast: true }, | |
| ); | |
| }); | |
| it('reports unavailable when offline and not downloaded', async () => { | |
| vi.spyOn(lib, 'isChapterDownloaded').mockResolvedValue(false); | |
| vi.spyOn(apiMod, 'apiClient').mockRejectedValue(new TypeError('Failed to fetch')); | |
| const { result } = renderHook(() => useChapterPages('m1', '3')); | |
| await waitFor(() => expect(result.current.source).toBe('unavailable')); | |
| expect(result.current.pages).toHaveLength(0); | |
| }); | |
| }); | |