feat(web): API client modules for quarantine + admin quarantine
This commit is contained in:
@@ -0,0 +1,116 @@
|
||||
import { describe, expect, test, vi, beforeEach, afterEach } from 'vitest';
|
||||
|
||||
vi.mock('./client', () => ({
|
||||
api: {
|
||||
get: vi.fn(),
|
||||
post: vi.fn(),
|
||||
put: vi.fn(),
|
||||
del: vi.fn()
|
||||
},
|
||||
apiFetch: vi.fn()
|
||||
}));
|
||||
|
||||
import { flagTrack, unflagTrack, listMyQuarantine } from './quarantine';
|
||||
import { api, apiFetch } from './client';
|
||||
import { qk } from './queries';
|
||||
import type {
|
||||
LidarrQuarantineRow,
|
||||
LidarrQuarantineMineRow
|
||||
} from './types';
|
||||
|
||||
const mockRow: LidarrQuarantineRow = {
|
||||
user_id: 'u1',
|
||||
track_id: 't1',
|
||||
reason: 'bad_rip',
|
||||
notes: null,
|
||||
created_at: '2026-01-01T00:00:00Z'
|
||||
};
|
||||
|
||||
const mockMineRow: LidarrQuarantineMineRow = {
|
||||
track_id: 't1',
|
||||
reason: 'bad_rip',
|
||||
notes: null,
|
||||
created_at: '2026-01-01T00:00:00Z',
|
||||
track_title: 'Avril 14th',
|
||||
track_duration_ms: 120000,
|
||||
album_id: 'alb1',
|
||||
album_title: 'Drukqs',
|
||||
album_cover_art_path: null,
|
||||
artist_id: 'art1',
|
||||
artist_name: 'Aphex Twin'
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('flagTrack', () => {
|
||||
test('POSTs /api/quarantine without notes when none provided', async () => {
|
||||
(api.post as ReturnType<typeof vi.fn>).mockResolvedValueOnce(mockRow);
|
||||
const out = await flagTrack({ track_id: 't1', reason: 'bad_rip' });
|
||||
expect(api.post).toHaveBeenCalledWith('/api/quarantine', {
|
||||
track_id: 't1',
|
||||
reason: 'bad_rip'
|
||||
});
|
||||
const body = (api.post as ReturnType<typeof vi.fn>).mock.calls[0][1] as Record<
|
||||
string,
|
||||
unknown
|
||||
>;
|
||||
expect(body).not.toHaveProperty('notes');
|
||||
expect(out).toBe(mockRow);
|
||||
});
|
||||
|
||||
test('omits empty-string notes from the body', async () => {
|
||||
(api.post as ReturnType<typeof vi.fn>).mockResolvedValueOnce(mockRow);
|
||||
await flagTrack({ track_id: 't1', reason: 'wrong_tags', notes: '' });
|
||||
const body = (api.post as ReturnType<typeof vi.fn>).mock.calls[0][1] as Record<
|
||||
string,
|
||||
unknown
|
||||
>;
|
||||
expect(body).toEqual({ track_id: 't1', reason: 'wrong_tags' });
|
||||
expect(body).not.toHaveProperty('notes');
|
||||
});
|
||||
|
||||
test('includes notes when a non-empty string is provided', async () => {
|
||||
(api.post as ReturnType<typeof vi.fn>).mockResolvedValueOnce(mockRow);
|
||||
await flagTrack({
|
||||
track_id: 't1',
|
||||
reason: 'duplicate',
|
||||
notes: 'same as t0'
|
||||
});
|
||||
expect(api.post).toHaveBeenCalledWith('/api/quarantine', {
|
||||
track_id: 't1',
|
||||
reason: 'duplicate',
|
||||
notes: 'same as t0'
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('unflagTrack', () => {
|
||||
test('DELETEs /api/quarantine/:trackID', async () => {
|
||||
(apiFetch as ReturnType<typeof vi.fn>).mockResolvedValueOnce(null);
|
||||
await unflagTrack('t1');
|
||||
expect(apiFetch).toHaveBeenCalledWith('/api/quarantine/t1', {
|
||||
method: 'DELETE'
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('listMyQuarantine', () => {
|
||||
test('GETs /api/quarantine/mine', async () => {
|
||||
(api.get as ReturnType<typeof vi.fn>).mockResolvedValueOnce([mockMineRow]);
|
||||
const out = await listMyQuarantine();
|
||||
expect(api.get).toHaveBeenCalledWith('/api/quarantine/mine');
|
||||
expect(out).toEqual([mockMineRow]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('qk.myQuarantine', () => {
|
||||
test('returns the expected key tuple', () => {
|
||||
expect(qk.myQuarantine()).toEqual(['myQuarantine']);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user