animetix-web / frontend /src /features /manga-reader /offline /useChapterDownload.test.ts
MissawB's picture
Upload folder using huggingface_hub (part 4)
df2e14d verified
Raw
History Blame Contribute Delete
3.52 kB
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { renderHook, act, waitFor } from '@testing-library/react';
import { useChapterDownload } from './useChapterDownload';
import * as lib from './offlineLibrary';
import { useToastStore } from '../../../store/toastStore';
const META = { mediaId: 'm1', mediaTitle: 'T', chapterNumber: 1, chapterTitle: 'C1' };
const PAGES = [{ number: 0, image_url: 'u0' }];
describe('useChapterDownload', () => {
beforeEach(() => vi.restoreAllMocks());
it('starts idle when not downloaded', async () => {
vi.spyOn(lib, 'isChapterDownloaded').mockResolvedValue(false);
const { result } = renderHook(() => useChapterDownload(META, PAGES));
await waitFor(() => expect(result.current.status).toBe('idle'));
});
it('starts downloaded when already cached', async () => {
vi.spyOn(lib, 'isChapterDownloaded').mockResolvedValue(true);
const { result } = renderHook(() => useChapterDownload(META, PAGES));
await waitFor(() => expect(result.current.status).toBe('downloaded'));
});
it('transitions idle -> downloading -> downloaded and tracks progress', async () => {
vi.spyOn(lib, 'isChapterDownloaded').mockResolvedValue(false);
vi.spyOn(lib, 'downloadChapter').mockImplementation(async (_m, _p, onProgress) => {
onProgress?.(0.5);
onProgress?.(1);
return {} as lib.DownloadedChapter;
});
const { result } = renderHook(() => useChapterDownload(META, PAGES));
await waitFor(() => expect(result.current.status).toBe('idle'));
await act(async () => {
await result.current.download();
});
expect(result.current.status).toBe('downloaded');
expect(result.current.progress).toBe(1);
});
it('sets error status with message on failure', async () => {
vi.spyOn(lib, 'isChapterDownloaded').mockResolvedValue(false);
vi.spyOn(lib, 'downloadChapter').mockRejectedValue(new lib.OfflineQuotaError());
const { result } = renderHook(() => useChapterDownload(META, PAGES));
await waitFor(() => expect(result.current.status).toBe('idle'));
await act(async () => {
await result.current.download();
});
expect(result.current.status).toBe('error');
expect(result.current.error).toContain('stockage');
});
it('toasts an error on download failure', async () => {
vi.spyOn(lib, 'isChapterDownloaded').mockResolvedValue(false);
vi.spyOn(lib, 'downloadChapter').mockRejectedValue(new lib.OfflineQuotaError());
const addToast = vi
.spyOn(useToastStore.getState(), 'addToast')
.mockImplementation(() => {});
const { result } = renderHook(() => useChapterDownload(META, PAGES));
await waitFor(() => expect(result.current.status).toBe('idle'));
await act(async () => {
await result.current.download();
});
expect(addToast).toHaveBeenCalledWith(expect.stringContaining('stockage'), 'error');
});
it('remove() deletes and returns to idle', async () => {
vi.spyOn(lib, 'isChapterDownloaded').mockResolvedValue(true);
const del = vi.spyOn(lib, 'deleteChapter').mockResolvedValue();
const { result } = renderHook(() => useChapterDownload(META, PAGES));
await waitFor(() => expect(result.current.status).toBe('downloaded'));
await act(async () => {
await result.current.remove();
});
expect(del).toHaveBeenCalledWith('m1', 1);
expect(result.current.status).toBe('idle');
expect(result.current.progress).toBe(0);
expect(result.current.error).toBeNull();
});
});