diff --git a/.eslintrc.js b/.eslintrc.js index 06567bf..04b7477 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -19,6 +19,7 @@ module.exports = { rules: { '@typescript-eslint/interface-name-prefix': 'off', '@typescript-eslint/explicit-function-return-type': 'off', - '@typescript-eslint/explicit-module-boundary-types': 'off' + '@typescript-eslint/explicit-module-boundary-types': 'off', + '@typescript-eslint/no-unused-vars': ['error', { varsIgnorePattern: '^_' }] }, }; diff --git a/src/integration/movies/omdb.spec.ts b/src/integration/movies/omdb/apiClient.spec.ts similarity index 83% rename from src/integration/movies/omdb.spec.ts rename to src/integration/movies/omdb/apiClient.spec.ts index c933254..2bc7af6 100644 --- a/src/integration/movies/omdb.spec.ts +++ b/src/integration/movies/omdb/apiClient.spec.ts @@ -1,11 +1,11 @@ import { describe, it, expect } from '@jest/globals'; -import { createOmdbClient } from './omdb'; +import { createOmdbApiClient } from './apiClient'; -describe('createOmdbClient', () => { - const client = createOmdbClient('68fd98ab'); +describe('createOmdbApiClient', () => { + const client = createOmdbApiClient('68fd98ab'); it('returns some data for the sample movie id', async () => { - const result = await client.getMovieMetadata('tt11873472'); + const result = await client.fetchMetadata('tt11873472'); expect(result).toMatchObject({ Actors: 'Cheryl Isheja, Elvis Ngabo, Diogène Ntarindwa', Awards: expect.any(String), @@ -35,7 +35,7 @@ describe('createOmdbClient', () => { }, 10_000); it('returns undefined for non-existend movie id', async () => { - const result = await client.getMovieMetadata('tt99999999999'); + const result = await client.fetchMetadata('tt99999999999'); expect(result).toBeUndefined(); }, 10_000); }); diff --git a/src/integration/movies/omdb.ts b/src/integration/movies/omdb/apiClient.ts similarity index 76% rename from src/integration/movies/omdb.ts rename to src/integration/movies/omdb/apiClient.ts index d343cd9..56cb037 100644 --- a/src/integration/movies/omdb.ts +++ b/src/integration/movies/omdb/apiClient.ts @@ -1,17 +1,8 @@ import fetch from 'node-fetch'; import PQueue from 'p-queue'; -import { OmdbMovieData, OmdbMoviesProvider } from './types'; +import { OmdbApiClient, OmdbResponse } from './types'; -type OmdbResponse = - | { - Response: 'False'; - Error: string; - } - | (OmdbMovieData & { - Response: 'True'; - }); - -export const createOmdbClient = (apiKey: string): OmdbMoviesProvider => { +export const createOmdbApiClient = (apiKey: string): OmdbApiClient => { // Rate limit (according to readme, it's 1k per day; // here we set it 1 per second, should be enough for the demo app goal) const queue = new PQueue({ @@ -22,7 +13,7 @@ export const createOmdbClient = (apiKey: string): OmdbMoviesProvider => { }); return { - getMovieMetadata: async (imdbId: string) => + fetchMetadata: async (imdbId: string) => queue.add(async () => { const url = new URL('https://www.omdbapi.com/'); url.searchParams.append('i', imdbId); @@ -45,7 +36,8 @@ export const createOmdbClient = (apiKey: string): OmdbMoviesProvider => { ); } - return body; + const { Response: _status, ...rawOmdbData } = body; + return rawOmdbData; }), }; }; diff --git a/src/integration/movies/omdb/converters.spec.ts b/src/integration/movies/omdb/converters.spec.ts new file mode 100644 index 0000000..e6fbba1 --- /dev/null +++ b/src/integration/movies/omdb/converters.spec.ts @@ -0,0 +1,276 @@ +import { describe, it, expect } from '@jest/globals'; + +import { normalizeRawOmdbData } from './converters'; + +describe('normalizeRawOmdbData', () => { + it('normalizes data correctly for tt19500164 (online-release animation)', () => { + const rawOmdbData = { + Title: 'Nimona', + Year: '2023', + Rated: 'PG', + Released: '30 Jun 2023', + Runtime: '101 min', + Genre: 'Animation, Action, Adventure', + Director: 'Nick Bruno, Troy Quane', + Writer: 'Robert L. Baird, Lloyd Taylor, Pamela Ribon', + Actors: 'Chloë Grace Moretz, Riz Ahmed, Eugene Lee Yang', + Plot: "When a knight in a futuristic medieval world is framed for a crime he didn't commit, the only one who can help him prove his innocence is Nimona -- a mischievous teen who happens to be a shapeshifting creature he's sworn to destroy.", + Language: 'English', + Country: 'United States', + Awards: '2 nominations', + Poster: 'https://m.media-amazon.com/images/M/MV5BNDJkNzQzODQtM2Q0MC00MWE4LTlkMjMtNWZmZWQyMTYwZGRmXkEyXkFqcGdeQXVyMTY1MTAyOTk1._V1_SX300.jpg', + Ratings: [ + { Source: 'Internet Movie Database', Value: '7.6/10' }, + { Source: 'Metacritic', Value: '75/100' }, + ], + Metascore: '75', + imdbRating: '7.6', + imdbVotes: '34,896', + imdbID: 'tt19500164', + Type: 'movie', + DVD: 'N/A', + BoxOffice: 'N/A', + Production: 'N/A', + Website: 'N/A', + } as const; + const result = normalizeRawOmdbData(rawOmdbData); + expect(result).toEqual({ + actors: ['Chloë Grace Moretz', 'Riz Ahmed', 'Eugene Lee Yang'], + awards: '2 nominations', + contentRating: 'PG', + description: + "When a knight in a futuristic medieval world is framed for a crime he didn't commit, the only one who can help him prove his innocence is Nimona -- a mischievous teen who happens to be a shapeshifting creature he's sworn to destroy.", + directors: ['Nick Bruno', 'Troy Quane'], + duration: 101, + genres: ['Animation', 'Action', 'Adventure'], + imdbId: 'tt19500164', + posterUrl: + 'https://m.media-amazon.com/images/M/MV5BNDJkNzQzODQtM2Q0MC00MWE4LTlkMjMtNWZmZWQyMTYwZGRmXkEyXkFqcGdeQXVyMTY1MTAyOTk1._V1_SX300.jpg', + productionCountries: ['United States'], + productionYear: 2023, + ratings: [ + { source: 'Internet Movie Database', value: '7.6/10' }, + { source: 'Metacritic', value: '75/100' }, + ], + releaseDate: '30 Jun 2023', + title: 'Nimona', + type: 'movie', + writers: ['Robert L. Baird', 'Lloyd Taylor', 'Pamela Ribon'], + }); + }); + + it('normalizes data correctly for tt10482560 (series)', () => { + const rawOmdbData = { + Title: 'Kipo and the Age of Wonderbeasts', + Year: '2020', + Rated: 'TV-Y7', + Released: '14 Jan 2020', + Runtime: '24 min', + Genre: 'Animation, Action, Adventure', + Director: 'N/A', + Writer: 'Bill Wolkoff, Radford Sechrist', + Actors: 'Karen Fukuhara, Sydney Mikayla, Dee Bradley Baker', + Plot: 'A girl explores the possibilities in a post-apocalyptic world.', + Language: 'English', + Country: 'United States', + Awards: '3 nominations', + Poster: 'https://m.media-amazon.com/images/M/MV5BZDczZDIxZjEtNDJiZS00NmQwLWJjMGEtN2UwNDY0ODdjODNiXkEyXkFqcGdeQXVyMTAwMzM3NDI3._V1_SX300.jpg', + Ratings: [{ Source: 'Internet Movie Database', Value: '8.3/10' }], + Metascore: 'N/A', + imdbRating: '8.3', + imdbVotes: '6,911', + imdbID: 'tt10482560', + Type: 'series', + totalSeasons: '3', + } as const; + const result = normalizeRawOmdbData(rawOmdbData); + expect(result).toEqual({ + actors: ['Karen Fukuhara', 'Sydney Mikayla', 'Dee Bradley Baker'], + awards: '3 nominations', + contentRating: 'TV-Y7', + description: + 'A girl explores the possibilities in a post-apocalyptic world.', + duration: 24, + genres: ['Animation', 'Action', 'Adventure'], + imdbId: 'tt10482560', + posterUrl: + 'https://m.media-amazon.com/images/M/MV5BZDczZDIxZjEtNDJiZS00NmQwLWJjMGEtN2UwNDY0ODdjODNiXkEyXkFqcGdeQXVyMTAwMzM3NDI3._V1_SX300.jpg', + productionCountries: ['United States'], + productionYear: 2020, + ratings: [{ source: 'Internet Movie Database', value: '8.3/10' }], + releaseDate: '14 Jan 2020', + title: 'Kipo and the Age of Wonderbeasts', + totalSeasons: 3, + type: 'series', + writers: ['Bill Wolkoff', 'Radford Sechrist'], + }); + }); + + it('normalizes data correctly for tt5580266 (cinema-release movie)', () => { + const rawOmdbData = { + Title: 'The Hate U Give', + Year: '2018', + Rated: 'PG-13', + Released: '19 Oct 2018', + Runtime: '133 min', + Genre: 'Crime, Drama', + Director: 'George Tillman Jr.', + Writer: 'Audrey Wells, Angie Thomas', + Actors: 'Amandla Stenberg, Regina Hall, Russell Hornsby', + Plot: "Starr Carter is constantly switching between two worlds: the poor, mostly black, neighborhood where she lives and the rich, mostly white, prep school she attends. The uneasy balance between these worlds is shattered when Starr witnesses the fatal shooting of her childhood best friend Khalil at the hands of a police officer. Now, facing pressures from all sides of the community, Starr must find her voice and stand up for what's right.", + Language: 'English', + Country: 'United States', + Awards: '22 wins & 38 nominations', + Poster: 'https://m.media-amazon.com/images/M/MV5BZDVkMWJiMzUtNjQyOS00MGVmLWJhYmMtN2IxYzU4MjY3MDRmXkEyXkFqcGdeQXVyNzA5NjIzODk@._V1_SX300.jpg', + Ratings: [ + { Source: 'Internet Movie Database', Value: '7.5/10' }, + { Source: 'Rotten Tomatoes', Value: '97%' }, + { Source: 'Metacritic', Value: '81/100' }, + ], + Metascore: '81', + imdbRating: '7.5', + imdbVotes: '39,280', + imdbID: 'tt5580266', + Type: 'movie', + DVD: '08 Jan 2019', + BoxOffice: '$29,719,483', + Production: 'N/A', + Website: 'N/A', + } as const; + const result = normalizeRawOmdbData(rawOmdbData); + expect(result).toEqual({ + actors: ['Amandla Stenberg', 'Regina Hall', 'Russell Hornsby'], + awards: '22 wins & 38 nominations', + boxOffice: '$29,719,483', + contentRating: 'PG-13', + description: + "Starr Carter is constantly switching between two worlds: the poor, mostly black, neighborhood where she lives and the rich, mostly white, prep school she attends. The uneasy balance between these worlds is shattered when Starr witnesses the fatal shooting of her childhood best friend Khalil at the hands of a police officer. Now, facing pressures from all sides of the community, Starr must find her voice and stand up for what's right.", + dvdReleaseDate: '08 Jan 2019', + directors: ['George Tillman Jr.'], + duration: 133, + genres: ['Crime', 'Drama'], + imdbId: 'tt5580266', + posterUrl: + 'https://m.media-amazon.com/images/M/MV5BZDVkMWJiMzUtNjQyOS00MGVmLWJhYmMtN2IxYzU4MjY3MDRmXkEyXkFqcGdeQXVyNzA5NjIzODk@._V1_SX300.jpg', + productionCountries: ['United States'], + productionYear: 2018, + ratings: [ + { source: 'Internet Movie Database', value: '7.5/10' }, + { source: 'Rotten Tomatoes', value: '97%' }, + { source: 'Metacritic', value: '81/100' }, + ], + releaseDate: '19 Oct 2018', + title: 'The Hate U Give', + type: 'movie', + writers: ['Audrey Wells', 'Angie Thomas'], + }); + }); + + it('normalizes data correctly for tt1508328 (foreign release)', () => { + const rawOmdbData = { + Title: 'Pumzi', + Year: '2009', + Rated: 'N/A', + Released: '01 Jan 2010', + Runtime: '21 min', + Genre: 'Short, Sci-Fi', + Director: 'Wanuri Kahiu', + Writer: 'Wanuri Kahiu', + Actors: 'Kudzani Moswela, Chantelle Burger, Tammy Richards', + Plot: 'As a result of the Third World War, the war for water, life died out on Earth. Asha lives and works as a curator of the Natural History Museum in one of the communities established in Africa. Once he receives a sample of the earth and tries to plant one of the seeds on it. It turns out that the land is not contaminated radioactive, the grain begins to germinate. He asks the Community Council to explore the possibility of recreating life on the planet. The answer is negative and the woman is arrested. He decides to escape to the surface, to the deadly desert, and plant his little tree somewhere.', + Language: 'English', + Country: 'South Africa, Kenya', + Awards: '3 wins & 2 nominations', + Poster: 'https://m.media-amazon.com/images/M/MV5BZTE4ODAzNzktNTBjZi00ZjBkLWFlYmYtZWZiZDJiNzEzMTBjXkEyXkFqcGdeQXVyNjkzNzg5Njg@._V1_SX300.jpg', + Ratings: [{ Source: 'Internet Movie Database', Value: '7.2/10' }], + Metascore: 'N/A', + imdbRating: '7.2', + imdbVotes: '345', + imdbID: 'tt1508328', + Type: 'movie', + DVD: 'N/A', + BoxOffice: 'N/A', + Production: 'N/A', + Website: 'N/A', + } as const; + const result = normalizeRawOmdbData(rawOmdbData); + expect(result).toEqual({ + actors: ['Kudzani Moswela', 'Chantelle Burger', 'Tammy Richards'], + awards: '3 wins & 2 nominations', + description: + 'As a result of the Third World War, the war for water, life died out on Earth. Asha lives and works as a curator of the Natural History Museum in one of the communities established in Africa. Once he receives a sample of the earth and tries to plant one of the seeds on it. It turns out that the land is not contaminated radioactive, the grain begins to germinate. He asks the Community Council to explore the possibility of recreating life on the planet. The answer is negative and the woman is arrested. He decides to escape to the surface, to the deadly desert, and plant his little tree somewhere.', + directors: ['Wanuri Kahiu'], + duration: 21, + genres: ['Short', 'Sci-Fi'], + imdbId: 'tt1508328', + posterUrl: + 'https://m.media-amazon.com/images/M/MV5BZTE4ODAzNzktNTBjZi00ZjBkLWFlYmYtZWZiZDJiNzEzMTBjXkEyXkFqcGdeQXVyNjkzNzg5Njg@._V1_SX300.jpg', + productionCountries: ['South Africa', 'Kenya'], + productionYear: 2009, + ratings: [{ source: 'Internet Movie Database', value: '7.2/10' }], + releaseDate: '01 Jan 2010', + title: 'Pumzi', + type: 'movie', + writers: ['Wanuri Kahiu'], + }); + }); + + it('normalizes data correctly for tt7224520 (local release)', () => { + const rawOmdbData = { + Title: 'Ever After', + Year: '2018', + Rated: 'Not Rated', + Released: '21 Jun 2019', + Runtime: '90 min', + Genre: 'Fantasy, Horror, Romance', + Director: 'Carolina Hellsgård', + Writer: 'Olivia Vieweg', + Actors: 'Gro Swantje Kohlhof, Maja Lehrer, Trine Dyrholm', + Plot: 'It has been two years since a zombie virus epidemic infected all but two German cities. Vivi and Eva flee the struggling community in Weimar for the one other safe-haven: Jena.', + Language: 'German', + Country: 'Germany', + Awards: '3 nominations', + Poster: 'https://m.media-amazon.com/images/M/MV5BZjRhZWRmZTItMjU4Zi00OTg5LTg2YjAtNmY2ODA2OGM2ZjZmXkEyXkFqcGdeQXVyNjEwNzcwNzU@._V1_SX300.jpg', + Ratings: [ + { Source: 'Internet Movie Database', Value: '4.9/10' }, + { Source: 'Rotten Tomatoes', Value: '80%' }, + { Source: 'Metacritic', Value: '63/100' }, + ], + Metascore: '63', + imdbRating: '4.9', + imdbVotes: '924', + imdbID: 'tt7224520', + Type: 'movie', + DVD: '15 Dec 2019', + BoxOffice: 'N/A', + Production: 'N/A', + Website: 'N/A', + } as const; + const result = normalizeRawOmdbData(rawOmdbData); + expect(result).toEqual({ + actors: ['Gro Swantje Kohlhof', 'Maja Lehrer', 'Trine Dyrholm'], + awards: '3 nominations', + contentRating: 'Not Rated', + description: + 'It has been two years since a zombie virus epidemic infected all but two German cities. Vivi and Eva flee the struggling community in Weimar for the one other safe-haven: Jena.', + directors: ['Carolina Hellsgård'], + duration: 90, + dvdReleaseDate: '15 Dec 2019', + genres: ['Fantasy', 'Horror', 'Romance'], + imdbId: 'tt7224520', + posterUrl: + 'https://m.media-amazon.com/images/M/MV5BZjRhZWRmZTItMjU4Zi00OTg5LTg2YjAtNmY2ODA2OGM2ZjZmXkEyXkFqcGdeQXVyNjEwNzcwNzU@._V1_SX300.jpg', + productionCountries: ['Germany'], + productionYear: 2018, + ratings: [ + { source: 'Internet Movie Database', value: '4.9/10' }, + { source: 'Rotten Tomatoes', value: '80%' }, + { source: 'Metacritic', value: '63/100' }, + ], + releaseDate: '21 Jun 2019', + title: 'Ever After', + type: 'movie', + writers: ['Olivia Vieweg'], + }); + }); +}); diff --git a/src/integration/movies/omdb/converters.ts b/src/integration/movies/omdb/converters.ts new file mode 100644 index 0000000..08b8034 --- /dev/null +++ b/src/integration/movies/omdb/converters.ts @@ -0,0 +1,121 @@ +import { NormalizedOmdbData } from '../types'; +import { RawOmdbData } from './types'; + +const identity = (value: T) => value; +const stringToArray = (value: string) => value.split(', '); +const stringToNumber = (value: string) => parseInt(value, 10); +const stringToDuration = (value: string) => { + const match = /^(?