Files
seerr/server/api/servarr/radarr.test.ts

120 lines
3.8 KiB
TypeScript

import assert from 'node:assert/strict';
import { afterEach, describe, it, mock } from 'node:test';
import type { AxiosInstance } from 'axios';
import RadarrAPI from '@server/api/servarr/radarr';
function buildRadarr(): RadarrAPI {
return new RadarrAPI({ url: 'http://localhost:7878/api/v3', apiKey: 'test' });
}
function getAxios(radarr: RadarrAPI): AxiosInstance {
return (radarr as unknown as { axios: AxiosInstance }).axios;
}
describe('RadarrAPI removeMovie', () => {
afterEach(() => mock.restoreAll());
it('removes the movie when it exists in the library', async () => {
const radarr = buildRadarr();
mock.method(RadarrAPI.prototype, 'getMovieByTmdbId', async () => ({
id: 7,
title: 'Test Movie',
}));
const del = mock.method(getAxios(radarr), 'delete', async () => ({}));
await radarr.removeMovie(550);
assert.strictEqual(del.mock.callCount(), 1);
assert.strictEqual(del.mock.calls[0].arguments[0], '/movie/7');
});
it('does nothing when the movie is not in the library', async () => {
const radarr = buildRadarr();
mock.method(getAxios(radarr), 'get', async () => ({
data: [{ id: 0, title: 'Fight Club' }],
}));
const del = mock.method(getAxios(radarr), 'delete', async () => ({}));
await assert.doesNotReject(() => radarr.removeMovie(550));
assert.strictEqual(del.mock.callCount(), 0);
});
it('rejects when the tmdbId is unknown to the lookup', async () => {
const radarr = buildRadarr();
mock.method(getAxios(radarr), 'get', async () => ({ data: [] }));
const del = mock.method(getAxios(radarr), 'delete', async () => ({}));
await assert.rejects(() => radarr.removeMovie(550), /Movie not found/);
assert.strictEqual(del.mock.callCount(), 0);
});
it('ignores a 404 when the movie was already removed in Radarr', async () => {
const radarr = buildRadarr();
mock.method(RadarrAPI.prototype, 'getMovieByTmdbId', async () => ({
id: 7,
title: 'Test Movie',
}));
mock.method(getAxios(radarr), 'delete', async () => {
throw { response: { status: 404 } };
});
await assert.doesNotReject(() => radarr.removeMovie(550));
});
it('rethrows errors other than 404', async () => {
const radarr = buildRadarr();
mock.method(RadarrAPI.prototype, 'getMovieByTmdbId', async () => ({
id: 7,
title: 'Test Movie',
}));
mock.method(getAxios(radarr), 'delete', async () => {
throw { response: { status: 500 } };
});
await assert.rejects(() => radarr.removeMovie(550));
});
it('rethrows a 404 from the lookup instead of treating it as removed', async () => {
const radarr = buildRadarr();
mock.method(getAxios(radarr), 'get', async () => {
throw { response: { status: 404 } };
});
const del = mock.method(getAxios(radarr), 'delete', async () => ({}));
await assert.rejects(
() => radarr.removeMovie(550),
(e: unknown) =>
(e as { response?: { status?: number } }).response?.status === 404
);
assert.strictEqual(del.mock.callCount(), 0);
});
});
describe('RadarrAPI getMovieByTmdbId', () => {
afterEach(() => mock.restoreAll());
it('rethrows a 401 from the lookup with the status intact', async () => {
const radarr = buildRadarr();
mock.method(getAxios(radarr), 'get', async () => {
throw { response: { status: 401 } };
});
await assert.rejects(
() => radarr.getMovieByTmdbId(550),
(e: unknown) =>
(e as { response?: { status?: number } }).response?.status === 401
);
});
it('throws "Movie not found" when the lookup returns no results', async () => {
const radarr = buildRadarr();
mock.method(getAxios(radarr), 'get', async () => ({ data: [] }));
await assert.rejects(() => radarr.getMovieByTmdbId(550), {
message: 'Movie not found',
});
});
});