diff --git a/.changeset/serious-apricots-sniff.md b/.changeset/serious-apricots-sniff.md new file mode 100644 index 0000000..69ff369 --- /dev/null +++ b/.changeset/serious-apricots-sniff.md @@ -0,0 +1,5 @@ +--- +'@untidy/thetvdb': minor +--- + +feat: support `/episodes/:id/translations/:language` endpoint diff --git a/src/main.ts b/src/main.ts index da345a3..bf436d2 100644 --- a/src/main.ts +++ b/src/main.ts @@ -447,6 +447,8 @@ type GetEpisode = O['extended'] extends true : Data : Data; +type GetEpisodeByLanguage = Data>; + type GetEpisodesByPage = DataLink; type GetMovie = O['extended'] extends true @@ -587,6 +589,15 @@ export class TheTVDB extends Base { return await this.fetcher>(endpoint); } + public async getEpisodeByLanguage(id: string, language: string): Promise { + this.validateInput(id, 'Required episode id'); + this.validateInput(language, 'Required language id'); + + const endpoint = this.api + '/v4/episodes/' + id + '/translations/' + language; + + return await this.fetcher(endpoint); + } + public async getEpisodesByPage(page?: string): Promise { let endpoint = this.api + '/v4/episodes'; if (typeof page === 'string' && page.length > 0 && page.length <= 5) { diff --git a/tests/main.test.ts b/tests/main.test.ts index ff469d0..0b54ab6 100644 --- a/tests/main.test.ts +++ b/tests/main.test.ts @@ -156,6 +156,24 @@ describe('getEpisode()', () => { }); }); +describe('getEpisodeByLanguage()', () => { + it('throws an error if no id is provided', async () => { + // @ts-expect-error: Required id + await expect(async () => await client.getEpisodeByLanguage()).rejects.toThrow('Required episode id'); + }); + + it('throws an error if no language is provided', async () => { + // @ts-expect-error: Required language + await expect(async () => await client.getEpisodeByLanguage('40')).rejects.toThrow('Required language id'); + }); + + it('returns a successful response', async () => { + const { data } = await client.getEpisodeByLanguage('40', 'spa'); + expect(data.name).toBe('El Baile'); + expect(data.language).toBe('spa'); + }); +}); + describe('getEpisodesByPage()', () => { it('returns a successful response', async () => { const { data } = await client.getEpisodesByPage(); diff --git a/tests/mocks/handlers/episodes.ts b/tests/mocks/handlers/episodes.ts index a82ff8c..fe5eb77 100644 --- a/tests/mocks/handlers/episodes.ts +++ b/tests/mocks/handlers/episodes.ts @@ -1,5 +1,13 @@ import { HttpResponse, http, type HttpHandler } from 'msw'; +// https://api4.thetvdb.com/v4/episodes/40/translations/spa +const episodeLang = { + data: { + name: 'El Baile', + language: 'spa', + }, +}; + // https://api4.thetvdb.com/v4/episodes/127396/extended?meta=translations const episodesEM = { data: { @@ -56,15 +64,16 @@ const episodes = { export const episodesHandlers: HttpHandler[] = [ http.get('https://api4.thetvdb.com/v4/episodes/*', ({ request }) => { const url = new URL(request.url); - const meta = url.searchParams.get('meta'); - if (meta === 'translations') { - return HttpResponse.json(episodesEM); - } - if (request.url === 'https://api4.thetvdb.com/v4/episodes/127396/extended') { - return HttpResponse.json(episodeE); - } else { - return HttpResponse.json(episode); + switch (url.href) { + case 'https://api4.thetvdb.com/v4/episodes/40/translations/spa': + return HttpResponse.json(episodeLang); + case 'https://api4.thetvdb.com/v4/episodes/127396/extended?meta=translations': + return HttpResponse.json(episodesEM); + case 'https://api4.thetvdb.com/v4/episodes/127396/extended': + return HttpResponse.json(episodeE); + default: + return HttpResponse.json(episode); } }),