fix(nextcloud-files): WR-07 Merkzettel angelegter Ordner gilt nur fuer eine Ablage
- der Merkzettel wird geleert, wenn neu abgelegt wird und nichts mehr laeuft, nach jedem Loeschen, Verschieben und Umbenennen in der Ansicht und wenn ein Hochladen mit pathConflict/notFound scheitert (dann legt "Erneut versuchen" den Ordner wieder an) - innerhalb einer Ablage wird jeder Ordner weiter nur einmal angelegt - Hook-Tests fuer alle drei Wege Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
import { act, renderHook, waitFor } from '@testing-library/react';
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
import { NextcloudFilesRequestError } from '@/lib/nextcloud-files-api';
|
||||
import { useTransfers } from './use-transfers';
|
||||
|
||||
const mockCreate = vi.fn();
|
||||
const mockUpload = vi.fn();
|
||||
|
||||
vi.mock('@/lib/nextcloud-files-api', async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import('@/lib/nextcloud-files-api')>();
|
||||
return {
|
||||
...actual,
|
||||
createFolder: (...a: unknown[]) => mockCreate(...a),
|
||||
listFolder: vi.fn(),
|
||||
};
|
||||
});
|
||||
vi.mock('@/lib/nextcloud-files-upload', () => ({
|
||||
uploadFile: (...a: unknown[]) => mockUpload(...a),
|
||||
}));
|
||||
|
||||
const file = (name: string) => new File(['x'], name);
|
||||
|
||||
beforeEach(() => {
|
||||
mockCreate.mockReset().mockResolvedValue({ path: '/A' });
|
||||
mockUpload.mockReset().mockResolvedValue({ path: '/A/a.txt', size: 1 });
|
||||
});
|
||||
|
||||
describe('useTransfers — Ordner-Merkzettel (WR-07)', () => {
|
||||
it('eine neue Ablage nach dem Ende der vorigen legt den Ordner erneut an (er kann inzwischen geloescht sein)', async () => {
|
||||
const { result } = renderHook(() => useTransfers({ quotaAvailable: null }));
|
||||
act(() => result.current.enqueue([{ file: file('a.txt'), relativeDir: 'A' }], '/'));
|
||||
await waitFor(() => expect(result.current.transfers[0]?.status).toBe('done'));
|
||||
expect(mockCreate).toHaveBeenCalledTimes(1);
|
||||
expect(mockCreate).toHaveBeenLastCalledWith('/A');
|
||||
|
||||
act(() => result.current.enqueue([{ file: file('b.txt'), relativeDir: 'A' }], '/'));
|
||||
await waitFor(() => expect(result.current.transfers[1]?.status).toBe('done'));
|
||||
expect(mockCreate).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
|
||||
it('innerhalb einer Ablage wird jeder Ordner nur einmal angelegt', async () => {
|
||||
const { result } = renderHook(() => useTransfers({ quotaAvailable: null }));
|
||||
act(() =>
|
||||
result.current.enqueue(
|
||||
[
|
||||
{ file: file('a.txt'), relativeDir: 'A' },
|
||||
{ file: file('b.txt'), relativeDir: 'A' },
|
||||
{ file: file('c.txt'), relativeDir: 'A' },
|
||||
],
|
||||
'/',
|
||||
),
|
||||
);
|
||||
await waitFor(() =>
|
||||
expect(result.current.transfers.every((t) => t.status === 'done')).toBe(true),
|
||||
);
|
||||
expect(mockCreate).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('forgetFolders und ein Hochladen mit pathConflict leeren den Merkzettel', async () => {
|
||||
let release!: () => void;
|
||||
const hold = new Promise<void>((r) => {
|
||||
release = r;
|
||||
});
|
||||
mockUpload
|
||||
.mockImplementationOnce(async () => {
|
||||
await hold;
|
||||
return { path: '/A/a.txt', size: 1 };
|
||||
})
|
||||
.mockRejectedValueOnce(new NextcloudFilesRequestError(409, 'pathConflict', 'fehlt'))
|
||||
.mockResolvedValue({ path: '/A/c.txt', size: 1 });
|
||||
const { result } = renderHook(() => useTransfers({ quotaAvailable: null }));
|
||||
// Die erste Datei laeuft noch: die zweite Ablage nutzt den Merkzettel.
|
||||
act(() => result.current.enqueue([{ file: file('a.txt'), relativeDir: 'A' }], '/'));
|
||||
await waitFor(() => expect(mockUpload).toHaveBeenCalledTimes(1));
|
||||
act(() => result.current.enqueue([{ file: file('b.txt'), relativeDir: 'A' }], '/'));
|
||||
await waitFor(() => expect(result.current.transfers[1]?.status).toBe('error'));
|
||||
expect(mockCreate).toHaveBeenCalledTimes(1);
|
||||
// pathConflict: "Erneut versuchen" legt den Ordner wieder an.
|
||||
act(() => result.current.retry(result.current.transfers[1].id));
|
||||
await waitFor(() => expect(result.current.transfers[1]?.status).toBe('done'));
|
||||
expect(mockCreate).toHaveBeenCalledTimes(2);
|
||||
|
||||
act(() => result.current.forgetFolders());
|
||||
act(() => result.current.enqueue([{ file: file('c.txt'), relativeDir: 'A' }], '/'));
|
||||
await waitFor(() => expect(result.current.transfers[2]?.status).toBe('done'));
|
||||
expect(mockCreate).toHaveBeenCalledTimes(3);
|
||||
release();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user