fix: support orphaned *arr queue items and improve download matching reliability (#73)
Build and Push Docker Image / build (push) Successful in 1m55s
Docs Check / Markdown lint (push) Successful in 2m14s
Licence Check / Licence compatibility and copyright header verification (push) Successful in 2m40s
CI / Security audit (push) Successful in 3m10s
CI / Swagger Validation & Coverage (push) Successful in 3m31s
Docs Check / Mermaid diagram parse check (push) Successful in 3m48s
CI / Tests & coverage (push) Failing after 4m7s

This commit is contained in:
2026-05-29 12:46:11 +01:00
parent bbc461ad6e
commit 50e1e09e55
8 changed files with 716 additions and 415 deletions
+154
View File
@@ -925,4 +925,158 @@ describe('buildUserDownloads', () => {
expect(result[0].arrLink).toBe('https://sonarr.test/series/test-series');
expect(result[1].arrLink).toBe('https://radarr.test/movie/test-movie');
});
describe('orphaned download integration in DownloadBuilder', () => {
it('returns orphaned queue records when no active client match is found', async () => {
const cacheSnapshot = {
sabnzbdQueue: { data: { queue: { slots: [] } } },
sabnzbdHistory: { data: { history: { slots: [] } } },
sonarrQueue: {
data: {
records: [{
id: 500,
title: 'Genuinely Orphaned Show',
sourceTitle: 'Genuinely Orphaned Show',
seriesId: 1,
series: seriesMap.get(1),
size: 200000000,
sizeleft: 100000000,
trackedDownloadState: 'importPending',
trackedDownloadStatus: 'warning',
statusMessages: [{ messages: ['Missing files'] }]
}]
}
},
sonarrHistory: { data: { records: [] } },
radarrQueue: { data: { records: [] } },
radarrHistory: { data: { records: [] } },
qbittorrentTorrents: []
};
const result = await buildUserDownloads(cacheSnapshot, {
username,
usernameSanitized,
isAdmin: true,
showAll,
seriesMap,
moviesMap,
sonarrTagMap,
radarrTagMap,
embyUserMap
});
expect(result).toHaveLength(1);
expect(result[0]).toMatchObject({
title: 'Genuinely Orphaned Show',
isOrphaned: true,
client: 'orphaned',
instanceId: 'orphaned',
instanceName: 'Orphaned (unconfigured client)',
progress: 50,
importIssues: ['Missing files']
});
});
it('strictly deduplicates so active matched items are NOT duplicated as orphans', async () => {
const cacheSnapshot = {
sabnzbdQueue: {
data: {
queue: {
status: 'Downloading',
speed: '5.0 MB/s',
kbpersec: 5120,
slots: [{
filename: 'Matched Active Show',
nzbname: 'Matched Active Show',
status: 'Downloading',
percentage: 50,
mb: 1000,
mbmissing: 500,
size: '1 GB',
timeleft: '10:00'
}]
}
}
},
sabnzbdHistory: { data: { history: { slots: [] } } },
sonarrQueue: {
data: {
records: [{
id: 100,
downloadId: '100', // matches slot by default mock (or slot.id/nzo_id)
title: 'Matched Active Show',
sourceTitle: 'Matched Active Show',
seriesId: 1,
series: seriesMap.get(1)
}]
}
},
sonarrHistory: { data: { records: [] } },
radarrQueue: { data: { records: [] } },
radarrHistory: { data: { records: [] } },
qbittorrentTorrents: []
};
// Set slot nzo_id to match the downloadId
cacheSnapshot.sabnzbdQueue.data.queue.slots[0].nzo_id = '100';
const result = await buildUserDownloads(cacheSnapshot, {
username,
usernameSanitized,
isAdmin: true,
showAll,
seriesMap,
moviesMap,
sonarrTagMap,
radarrTagMap,
embyUserMap
});
// Should match the download once via SABnzbd client; should NOT list it again as an orphan
expect(result).toHaveLength(1);
expect(result[0].isOrphaned).toBeUndefined();
expect(result[0].client).toBe('sabnzbd');
});
it('filters orphaned records based on user tag matches', async () => {
const cacheSnapshot = {
sabnzbdQueue: { data: { queue: { slots: [] } } },
sabnzbdHistory: { data: { history: { slots: [] } } },
sonarrQueue: {
data: {
records: [{
id: 600,
title: 'Bobs Orphaned Show',
sourceTitle: 'Bobs Orphaned Show',
seriesId: 2, // Bob's series (tag=2, username=bob)
series: {
id: 2,
title: 'Bob Show',
tags: [2],
images: []
}
}]
}
},
sonarrHistory: { data: { records: [] } },
radarrQueue: { data: { records: [] } },
radarrHistory: { data: { records: [] } },
qbittorrentTorrents: []
};
const result = await buildUserDownloads(cacheSnapshot, {
username: 'alice', // alice should not see bob's orphaned downloads
usernameSanitized: 'alice',
isAdmin: false,
showAll: false,
seriesMap: new Map([[2, { id: 2, title: 'Bob Show', tags: [2], images: [] }]]),
moviesMap,
sonarrTagMap: new Map([[1, 'alice'], [2, 'bob']]),
radarrTagMap,
embyUserMap
});
expect(result).toEqual([]);
});
});
});