feat(web): API client modules for quarantine + admin quarantine

This commit is contained in:
2026-04-30 20:26:07 -04:00
parent b7f8136502
commit b653e83478
6 changed files with 395 additions and 1 deletions
+118 -1
View File
@@ -17,13 +17,21 @@ import {
listRootFolders,
listAdminRequests,
approveRequest,
rejectRequest
rejectRequest,
listAdminQuarantine,
resolveQuarantine,
deleteQuarantineFile,
deleteQuarantineViaLidarr,
listQuarantineActions
} from './admin';
import { api } from './client';
import { qk } from './queries';
import type {
ActionResult,
AdminQuarantineRow,
LidarrConfig,
LidarrQualityProfile,
LidarrQuarantineActionRow,
LidarrRequest,
LidarrRootFolder
} from './types';
@@ -228,3 +236,112 @@ describe('qk admin keys', () => {
]);
});
});
const baseQuarantineRow: AdminQuarantineRow = {
track_id: 't1',
track_title: 'Avril 14th',
artist_name: 'Aphex Twin',
album_title: 'Drukqs',
album_id: 'alb1',
lidarr_album_mbid: null,
report_count: 1,
latest_at: '2026-01-01T00:00:00Z',
reason_counts: { bad_rip: 1 },
reports: []
};
const baseAction: ActionResult = {
action_id: 'a1',
affected_users: 1
};
const baseActionRow: LidarrQuarantineActionRow = {
id: 'a1',
track_id: 't1',
track_title: 'Avril 14th',
artist_name: 'Aphex Twin',
album_title: 'Drukqs',
action: 'resolved',
admin_id: 'admin1',
lidarr_album_mbid: null,
affected_users: 1,
created_at: '2026-01-01T00:00:00Z'
};
describe('listAdminQuarantine', () => {
test('GETs /api/admin/quarantine', async () => {
(api.get as ReturnType<typeof vi.fn>).mockResolvedValueOnce([baseQuarantineRow]);
const out = await listAdminQuarantine();
expect(api.get).toHaveBeenCalledWith('/api/admin/quarantine');
expect(out).toEqual([baseQuarantineRow]);
});
});
describe('resolveQuarantine', () => {
test('POSTs /api/admin/quarantine/:trackID/resolve with empty body', async () => {
(api.post as ReturnType<typeof vi.fn>).mockResolvedValueOnce(baseAction);
const out = await resolveQuarantine('t1');
expect(api.post).toHaveBeenCalledWith('/api/admin/quarantine/t1/resolve', {});
expect(out).toBe(baseAction);
});
});
describe('deleteQuarantineFile', () => {
test('POSTs /api/admin/quarantine/:trackID/delete-file with empty body', async () => {
(api.post as ReturnType<typeof vi.fn>).mockResolvedValueOnce(baseAction);
const out = await deleteQuarantineFile('t1');
expect(api.post).toHaveBeenCalledWith(
'/api/admin/quarantine/t1/delete-file',
{}
);
expect(out).toBe(baseAction);
});
});
describe('deleteQuarantineViaLidarr', () => {
test('POSTs /api/admin/quarantine/:trackID/delete-via-lidarr with empty body', async () => {
(api.post as ReturnType<typeof vi.fn>).mockResolvedValueOnce(baseAction);
const out = await deleteQuarantineViaLidarr('t1');
expect(api.post).toHaveBeenCalledWith(
'/api/admin/quarantine/t1/delete-via-lidarr',
{}
);
expect(out).toBe(baseAction);
});
});
describe('listQuarantineActions', () => {
test('defaults to limit=50 when no argument', async () => {
(api.get as ReturnType<typeof vi.fn>).mockResolvedValueOnce([baseActionRow]);
await listQuarantineActions();
expect(api.get).toHaveBeenCalledWith(
'/api/admin/quarantine/actions?limit=50'
);
});
test('forwards explicit limit', async () => {
(api.get as ReturnType<typeof vi.fn>).mockResolvedValueOnce([baseActionRow]);
await listQuarantineActions(10);
expect(api.get).toHaveBeenCalledWith(
'/api/admin/quarantine/actions?limit=10'
);
});
});
describe('qk admin quarantine keys', () => {
test('adminQuarantine key', () => {
expect(qk.adminQuarantine()).toEqual(['adminQuarantine']);
});
test('adminQuarantineActions key defaults to limit 50', () => {
expect(qk.adminQuarantineActions()).toEqual([
'adminQuarantineActions',
{ limit: 50 }
]);
});
test('adminQuarantineActions key reflects custom limit', () => {
expect(qk.adminQuarantineActions(25)).toEqual([
'adminQuarantineActions',
{ limit: 25 }
]);
});
});