mirror of
https://github.com/kikootwo/ReadMeABook.git
synced 2026-06-02 20:30:10 +00:00
Add Transmission/NZBGet and per-client paths and much more
Extend multi-download-client support to include Transmission and NZBGet and introduce per-client custom download paths. Adds protocol mapping and new client types, Transmission/NZBGet integration services, API CRUD and validation changes, UI components/modal updates and live path previews, and manager routing by protocol. Includes DB migrations (download_path on download_history, interactive_search_access on users), schema updates, and related processor/service fixes and tests to ensure backward compatibility and proper path resolution.
This commit is contained in:
@@ -346,6 +346,58 @@ describe('processOrganizeFiles', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('queues retry when organizer returns EPERM copy failure', async () => {
|
||||
prismaMock.request.update.mockResolvedValue({});
|
||||
prismaMock.audiobook.findUnique.mockResolvedValue({
|
||||
id: 'a-eperm',
|
||||
title: 'Theo of Golden',
|
||||
author: 'Allen Levi',
|
||||
narrator: null,
|
||||
coverArtUrl: null,
|
||||
audibleAsin: 'B0FTT6KFKR',
|
||||
});
|
||||
// Organizer returns success: false with EPERM error (the fixed behavior)
|
||||
organizerMock.organize.mockResolvedValue({
|
||||
success: false,
|
||||
targetPath: '/media/audiobooks/Fiction/Allen Levi/Theo of Golden B0FTT6KFKR',
|
||||
filesMovedCount: 0,
|
||||
errors: [
|
||||
'Failed to copy Theo of Golden [B0FTT6KFKR].m4b: EPERM: operation not permitted, copyfile',
|
||||
'No audio files were successfully copied to the target directory',
|
||||
],
|
||||
audioFiles: [],
|
||||
});
|
||||
prismaMock.request.findFirst.mockResolvedValue({
|
||||
importAttempts: 0,
|
||||
maxImportRetries: 3,
|
||||
deletedAt: null,
|
||||
});
|
||||
configMock.get.mockImplementation(async (key: string) => {
|
||||
if (key === 'audiobook_path_template') return '{author}/{title} {asin}';
|
||||
return null;
|
||||
});
|
||||
|
||||
const { processOrganizeFiles } = await import('@/lib/processors/organize-files.processor');
|
||||
const result = await processOrganizeFiles({
|
||||
requestId: 'req-eperm',
|
||||
audiobookId: 'a-eperm',
|
||||
downloadPath: '/data/torrents/bookbit',
|
||||
jobId: 'job-eperm',
|
||||
});
|
||||
|
||||
// Should be identified as retryable and queued for re-import
|
||||
expect(result.success).toBe(false);
|
||||
expect(prismaMock.request.update).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
data: expect.objectContaining({
|
||||
status: 'awaiting_import',
|
||||
importAttempts: 1,
|
||||
errorMessage: expect.stringContaining('EPERM'),
|
||||
}),
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it('generates and stores filesHash after successful organization', async () => {
|
||||
prismaMock.request.update.mockResolvedValue({});
|
||||
prismaMock.audiobook.findUnique.mockResolvedValue({
|
||||
|
||||
Reference in New Issue
Block a user