Skip to content

Commit

Permalink
Main fix test error + upd (#1142)
Browse files Browse the repository at this point in the history
* test mocks

* test mocks

* test mocks

* test mocks

* test mocks

* test mocks

* upd deps

* upd dev deps

* lint

* upd yarn

* try downgrade mongoose

* updated omdb replies

* updated omdb replies

* updated omdb replies

* updated omdb replies

* updated omdb replies

* log debug

* log more

* added first tmdb mocks

* remove logs
remove tmdb mocks
added get series IMDbID from tmdb as omdb seems to give wrong value

* set local tmdb

* set local tmdb

* set local tmdb

* set local tmdb

* set local tmdb

* omdb-mocks

* update deps

* remove comment

* lint

* remove log

* mongoose strictQuery now default to false

* mongoose strictQuery true to throw
(see Automattic/mongoose#11861)

set MovieDb baseUrl to undefined as null is a value

* clean omdb mocks

* added omdb mocks saison 2

* added omdb mocks saison 3
  • Loading branch information
SurfaceS committed Dec 15, 2022
1 parent 6de0db8 commit 85f0332
Show file tree
Hide file tree
Showing 14 changed files with 2,291 additions and 2,168 deletions.
6 changes: 5 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -57,15 +57,19 @@ typings/
# dotenv environment variables file
.env

# netbean environment variables file
nbproject

# next.js build output
.next

**/*.js

!jest-mongodb-config.js
!jest.config.js
!test/mocks.js
!test/omdb-mocks.js
!test/opensubtitles-mocks.js
!test/tmdb-mocks.js
!ecosystem.config.js

# yarn 3
Expand Down
554 changes: 280 additions & 274 deletions .yarn/releases/yarn-3.2.4.cjs → .yarn/releases/yarn-3.3.0.cjs
100755 → 100644

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion .yarnrc.yml
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
yarnPath: .yarn/releases/yarn-3.2.4.cjs
yarnPath: .yarn/releases/yarn-3.3.0.cjs
nodeLinker: node-modules
35 changes: 18 additions & 17 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,16 +45,16 @@
"debug": "4.3.4",
"episode-parser": "2.0.2",
"escape-string-regexp": "5.0.0",
"koa": "2.13.4",
"koa": "2.14.1",
"koa-bodyparser": "4.3.0",
"koa-helmet": "6.1.0",
"koa-prometheus-adv": "1.0.1",
"koa-qs": "3.0.0",
"koa-router": "12.0.0",
"lodash": "4.17.21",
"mongoose": "6.7.2",
"moviedb-promise": "3.2.1",
"natural": "5.2.3",
"mongoose": "6.8.0",
"moviedb-promise": "3.3.1",
"natural": "5.2.4",
"object-mapper": "6.2.0",
"opensubtitles-api": "https://github.com/UniversalMediaServer/opensubtitles-api#94e2339b2e38533e518e6556f49b65e541bbe9e3",
"pm2": "5.2.2",
Expand All @@ -63,27 +63,28 @@
"ts-node": "10.9.1"
},
"devDependencies": {
"@types/jest": "29.2.2",
"@types/jest": "29.2.4",
"@types/koa": "2.13.5",
"@types/koa-bodyparser": "4.3.9",
"@types/koa-bodyparser": "4.3.10",
"@types/koa-helmet": "6.0.4",
"@types/koa-router": "7.4.4",
"@types/lodash": "4.14.186",
"@types/lodash": "4.14.191",
"@types/natural": "5.1.1",
"@types/node": "16.18.3",
"@types/node": "16.18.8",
"@types/object-mapper": "6.2.0",
"@typescript-eslint/eslint-plugin": "5.43.0",
"@typescript-eslint/parser": "5.43.0",
"axios": "0.27.2",
"eslint": "8.27.0",
"inquirer": "8.2.5",
"jest": "29.3.0",
"mongodb-memory-server": "8.10.0",
"@typescript-eslint/eslint-plugin": "5.46.0",
"@typescript-eslint/parser": "5.46.0",
"axios": "1.2.1",
"eslint": "8.29.0",
"inquirer": "9.1.4",
"jest": "29.3.1",
"ky": "0.33.0",
"mongodb-memory-server": "8.10.2",
"nock": "13.2.9",
"nodemon": "2.0.20",
"stoppable": "1.1.0",
"ts-jest": "29.0.3",
"typescript": "4.8.4"
"typescript": "4.9.4"
},
"packageManager": "yarn@3.2.4"
"packageManager": "yarn@3.3.0"
}
4 changes: 3 additions & 1 deletion src/models/connection.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import * as mongoose from 'mongoose';
import { Mongoose } from 'mongoose';
mongoose.set('bufferCommands', false);
mongoose.set('strictQuery', true);
mongoose.set('strict', 'throw')

export default (db: string): void => {
if (!db) {
Expand All @@ -19,7 +21,7 @@ export default (db: string): void => {
mongoose.connection.on('connected', () => {
console.log(`Successfully connected to ${new URL(db).hostname}`);
});

mongoose.connection.on('disconnected', () => {
console.log(`Disconnected from ${new URL(db).hostname}, reconnecting`);
connect().catch(error => console.error(error));
Expand Down
7 changes: 6 additions & 1 deletion src/services/external-api-helper.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Movie, SearchRequest, TVShow } from '@universalmediaserver/imdb-api';
import * as _ from 'lodash';
import * as episodeParser from 'episode-parser';
import { Episode, EpisodeRequest, ExternalId, SearchMovieRequest, SearchTvRequest } from 'moviedb-promise/dist/request-types';
import { Episode, EpisodeRequest, ExternalId, SearchMovieRequest, SearchTvRequest, TvExternalIdsResponse } from 'moviedb-promise/dist/request-types';
import * as natural from 'natural';

import osAPI from './opensubtitles';
Expand Down Expand Up @@ -399,6 +399,11 @@ export const getFromTMDBAPI = async(movieOrSeriesTitle?: string, movieOrEpisodeI
if (tmdbData) {
if (i === 0) {
metadata = mapper.parseTMDBAPIEpisodeResponse(tmdbData);
//get series IMDbID from tmdb as omdb seems to give wrong value
const tmdbSeriesData: TvExternalIdsResponse = await tmdb.tvExternalIds(seriesTMDBID);
if (tmdbSeriesData?.imdb_id) {
metadata.seriesIMDbID = tmdbSeriesData.imdb_id;
}
} else {
metadata.title = metadata.title ? metadata.title + ' & ' + tmdbData.name : tmdbData.name;
}
Expand Down
7 changes: 5 additions & 2 deletions src/services/tmdb-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,17 @@ const tvInfoCounter = new client.Counter({ name: 'tmdb_api_tvInfo', help: 'Count
if (process.env.NODE_ENV === 'production' && !process.env.TMDB_API_KEY) {
throw new Error('TMDB_API_KEY not set');
}
const originalModule = new MovieDb(process.env.TMDB_API_KEY);

const apiKey = process.env.TMDB_API_KEY || 'foo';
const baseUrl = apiKey === 'foo' ? 'https://local.themoviedb.org/3/' : undefined;
const originalModule = new MovieDb(apiKey, baseUrl);
export const tmdb = _.cloneDeep(originalModule);

const handleError = (err: Error): void => {
const responseStatus = _.get(err, 'response.status');
let responseStatusString: string;
if (responseStatus) {
responseStatusString = responseStatus.toString();
responseStatusString = String(responseStatus);
}
if (responseStatusString && /^5/.exec(responseStatusString)) {
throw new ExternalAPIError('TMDB API is offline');
Expand Down
3 changes: 2 additions & 1 deletion test/e2e/info.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@ let server;

describe('Info endpoint', () => {
beforeAll((done) => {
require('../mocks');
require('../omdb-mocks');
require('../opensubtitles-mocks');
require('../tmdb-mocks');
MongoMemoryServer.create()
.then((value) => {
mongod = value;
Expand Down
65 changes: 34 additions & 31 deletions test/e2e/media-video.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,20 +23,22 @@ const MOVIE_INTERSTELLAR = {

const EPISODE_LOST = {
'imdbId': 'tt0994359',
'title': 'Lost',
'title': 'Confirmed Dead',
'season': '4',
'episode': '2',
'seriesTitle': 'Lost',
'seriesIMDbID': 'tt0411008',
};

const EPISODE_PRISONBREAK = {
'osdbHash': '35acba68a9dcfc8f',
'filebytesize': '271224190',
'title': 'Behind the Eyes',
'season': '5',
'episode': '9',
'imdbId': 'tt5538198',
'year': 2017,
'seriesIMDbID': 'tt0455275',
'title': 'Behind the Eyes',
};

const EPISODE_AVATAR = {
Expand All @@ -48,7 +50,7 @@ const EPISODE_AVATAR = {
'imdbId': 'tt1176477',
'year': 2005,
'seriesIMDbID': 'tt0417299',
'title': 'Avatar: The Last Airbender',
'seriesTitle': 'Avatar: The Last Airbender',
};

interface UmsApiAxiosResponse {
Expand All @@ -59,8 +61,9 @@ interface UmsApiAxiosResponse {

describe('get by all', () => {
beforeAll((done) => {
require('../mocks');
require('../omdb-mocks');
require('../opensubtitles-mocks');
require('../tmdb-mocks');
MongoMemoryServer.create()
.then((value) => {
mongod = value;
Expand Down Expand Up @@ -91,7 +94,7 @@ describe('get by all', () => {
const spy = jest.spyOn(apihelper, 'getFromOMDbAPIV2');
let response = await axios.get(`${appUrl}/api/media/video/v2?imdbID=${MOVIE_INTERSTELLAR.imdbId}`) as UmsApiAxiosResponse;
expect(response.headers['x-api-subversion']).toBeTruthy();
expect(response.data.title).toEqual('Interstellar');
expect(response.data.title).toEqual(MOVIE_INTERSTELLAR.title);
expect(response.data.type).toEqual('movie');
expect(response.data.poster).toContain('https://');
expect(response.data.searchMatches).toBeUndefined();
Expand All @@ -100,7 +103,7 @@ describe('get by all', () => {

// subsequent calls should return MongoDB result rather than calling external apis
response = await axios.get(`${appUrl}/api/media/video/v2?imdbID=${MOVIE_INTERSTELLAR.imdbId}`);
expect(response.data.title).toEqual('Interstellar');
expect(response.data.title).toEqual(MOVIE_INTERSTELLAR.title);
expect(response.data.type).toEqual('movie');
expect(spy).toHaveBeenCalledTimes(0);
});
Expand All @@ -109,13 +112,13 @@ describe('get by all', () => {
const spy = jest.spyOn(apihelper, 'getFromOMDbAPIV2');
const spy2 = jest.spyOn(apihelper, 'getFromTMDBAPI');
let response = await axios.get(`${appUrl}/api/media/video/v2?title=${MOVIE_INTERSTELLAR.title}`) as UmsApiAxiosResponse;
expect(response.data.title).toEqual('Interstellar');
expect(response.data.title).toEqual(MOVIE_INTERSTELLAR.title);
expect(response.data.type).toEqual('movie');
expect(spy).toHaveBeenCalledTimes(1);

// subsequent calls should return MongoDB result rather than calling external apis
response = await axios.get(`${appUrl}/api/media/video/v2?title=${MOVIE_INTERSTELLAR.title}`);
expect(response.data.title).toEqual('Interstellar');
expect(response.data.title).toEqual(MOVIE_INTERSTELLAR.title);
expect(response.data.type).toEqual('movie');
expect(spy).toHaveBeenCalledTimes(1);
expect(spy2).toHaveBeenCalledTimes(1);
Expand All @@ -125,7 +128,7 @@ describe('get by all', () => {
* when the returned result from the external API matches an existing IMDb ID.
*/
response = await axios.get(`${appUrl}/api/media/video/v2?title=${MOVIE_INTERSTELLAR.title.toLowerCase()}`);
expect(response.data.title).toEqual('Interstellar');
expect(response.data.title).toEqual(MOVIE_INTERSTELLAR.title);
expect(response.data.type).toEqual('movie');
expect(spy).toHaveBeenCalledTimes(1);
expect(spy2).toHaveBeenCalledTimes(2);
Expand All @@ -134,14 +137,14 @@ describe('get by all', () => {
test('should return a movie by title AND imdbId from source APIs then store', async() => {
const spy = jest.spyOn(apihelper, 'getFromOMDbAPIV2');
let response = await axios.get(`${appUrl}/api/media/video/v2?title=${MOVIE_INTERSTELLAR.title}&imdbID=${MOVIE_INTERSTELLAR.imdbId}`) as UmsApiAxiosResponse;
expect(response.data.title).toEqual('Interstellar');
expect(response.data.title).toEqual(MOVIE_INTERSTELLAR.title);
expect(response.data.type).toEqual('movie');
expect(spy).toHaveBeenCalledTimes(1);
spy.mockReset();

// subsequent calls should return MongoDB result rather than calling external apis
response = await axios.get(`${appUrl}/api/media/video/v2?title=${MOVIE_INTERSTELLAR.title}&imdbID=${MOVIE_INTERSTELLAR.imdbId}`);
expect(response.data.title).toEqual('Interstellar');
expect(response.data.title).toEqual(MOVIE_INTERSTELLAR.title);
expect(response.data.type).toEqual('movie');
expect(spy).toHaveBeenCalledTimes(0);
});
Expand All @@ -150,7 +153,7 @@ describe('get by all', () => {
const omdbSpy = jest.spyOn(apihelper, 'getFromOMDbAPIV2');
const openSubsSpy = jest.spyOn(apihelper, 'getFromOpenSubtitles');
let response = await axios.get(`${appUrl}/api/media/video/v2?osdbHash=${MOVIE_INTERSTELLAR.osdbHash}&filebytesize=${MOVIE_INTERSTELLAR.filebytesize}&title=${MOVIE_INTERSTELLAR.title}&imdbID=${MOVIE_INTERSTELLAR.imdbId}`) as UmsApiAxiosResponse;
expect(response.data.title).toEqual('Interstellar');
expect(response.data.title).toEqual(MOVIE_INTERSTELLAR.title);
expect(response.data.type).toEqual('movie');
expect(omdbSpy).toHaveBeenCalledTimes(1);
expect(openSubsSpy).toHaveBeenCalledTimes(1);
Expand All @@ -159,7 +162,7 @@ describe('get by all', () => {

// subsequent calls should return MongoDB result rather than calling external apis
response = await axios.get(`${appUrl}/api/media/video/v2?osdbHash=${MOVIE_INTERSTELLAR.osdbHash}&filebytesize=${MOVIE_INTERSTELLAR.filebytesize}&title=${MOVIE_INTERSTELLAR.title}&imdbID=${MOVIE_INTERSTELLAR.imdbId}`);
expect(response.data.title).toEqual('Interstellar');
expect(response.data.title).toEqual(MOVIE_INTERSTELLAR.title);
expect(response.data.type).toEqual('movie');
expect(omdbSpy).toHaveBeenCalledTimes(0);
expect(openSubsSpy).toHaveBeenCalledTimes(0);
Expand All @@ -170,7 +173,7 @@ describe('get by all', () => {
test('should return an episode by imdbid, from source APIs then store', async() => {
const spy = jest.spyOn(apihelper, 'getFromOMDbAPIV2');
let response = await axios.get(`${appUrl}/api/media/video/v2?imdbID=${EPISODE_LOST.imdbId}&season=${EPISODE_LOST.season}&episode=${EPISODE_LOST.episode}`) as UmsApiAxiosResponse;
expect(response.data.title).toEqual('Confirmed Dead');
expect(response.data.title).toEqual(EPISODE_LOST.title);
expect(response.data.type).toEqual('episode');
expect(response.data.poster).toContain('https://');
expect(spy).toHaveBeenCalledTimes(1);
Expand All @@ -179,50 +182,50 @@ describe('get by all', () => {
// subsequent calls should return MongoDB result rather than calling external apis
response = await axios.get(`${appUrl}/api/media/video/v2?imdbID=${EPISODE_LOST.imdbId}&season=${EPISODE_LOST.season}&episode=${EPISODE_LOST.episode}`);
expect(spy).toHaveBeenCalledTimes(0);
expect(response.data.title).toEqual('Confirmed Dead');
expect(response.data.title).toEqual(EPISODE_LOST.title);
expect(response.data.type).toEqual('episode');
});

test('should return an episode by title, from source APIs then store', async() => {
test('should return an episode by series title, from source APIs then store', async() => {
const spy = jest.spyOn(apihelper, 'getFromOMDbAPIV2');
let response = await axios.get(`${appUrl}/api/media/video/v2?title=${EPISODE_LOST.title}&season=${EPISODE_LOST.season}&episode=${EPISODE_LOST.episode}`) as UmsApiAxiosResponse;
expect(response.data.title).toEqual('Confirmed Dead');
let response = await axios.get(`${appUrl}/api/media/video/v2?title=${EPISODE_LOST.seriesTitle}&season=${EPISODE_LOST.season}&episode=${EPISODE_LOST.episode}`) as UmsApiAxiosResponse;
expect(response.data.title).toEqual(EPISODE_LOST.title);
expect(response.data.type).toEqual('episode');
expect(response.data.seriesIMDbID).toEqual('tt0411008');
expect(response.data.seriesIMDbID).toEqual(EPISODE_LOST.seriesIMDbID);
expect(spy).toHaveBeenCalledTimes(1);
spy.mockReset();

// subsequent calls should return MongoDB result rather than calling external apis
response = await axios.get(`${appUrl}/api/media/video/v2?title=${EPISODE_LOST.title}&season=${EPISODE_LOST.season}&episode=${EPISODE_LOST.episode}`);
response = await axios.get(`${appUrl}/api/media/video/v2?title=${EPISODE_LOST.seriesTitle}&season=${EPISODE_LOST.season}&episode=${EPISODE_LOST.episode}`);
expect(spy).toHaveBeenCalledTimes(0);
expect(response.data.title).toEqual('Confirmed Dead');
expect(response.data.title).toEqual(EPISODE_LOST.title);
expect(response.data.type).toEqual('episode');
expect(response.data.seriesIMDbID).toEqual('tt0411008');
expect(response.data.seriesIMDbID).toEqual(EPISODE_LOST.seriesIMDbID);
});

test('should return an episode by osdbHash, from source APIs then store', async() => {
const spy = jest.spyOn(apihelper, 'getFromOMDbAPIV2');
let response = await axios.get(`${appUrl}/api/media/video/v2?osdbHash=${EPISODE_PRISONBREAK.osdbHash}&filebytesize=${EPISODE_PRISONBREAK.filebytesize}`) as UmsApiAxiosResponse;
expect(response.data.title).toEqual('Behind the Eyes');
expect(response.data.title).toEqual(EPISODE_PRISONBREAK.title);
expect(response.data.type).toEqual('episode');
expect(response.data.seriesIMDbID).toEqual('tt0455275');
expect(response.data.seriesIMDbID).toEqual(EPISODE_PRISONBREAK.seriesIMDbID);
expect(spy).toHaveBeenCalledTimes(1);
spy.mockReset();

// subsequent calls should return MongoDB result rather than calling external apis
response = await axios.get(`${appUrl}/api/media/video/v2?osdbHash=${EPISODE_PRISONBREAK.osdbHash}&filebytesize=${EPISODE_PRISONBREAK.filebytesize}`);
expect(spy).toHaveBeenCalledTimes(0);
expect(response.data.title).toEqual('Behind the Eyes');
expect(response.data.title).toEqual(EPISODE_PRISONBREAK.title);
expect(response.data.type).toEqual('episode');
expect(response.data.seriesIMDbID).toEqual('tt0455275');
expect(response.data.seriesIMDbID).toEqual(EPISODE_PRISONBREAK.seriesIMDbID);
});
// tests that when a result is found by open subtitles, we first check if we already have a document for that id
test('should return an episode by osdbHash, but return existing metadata if found by imdbid', async() => {
const spy = jest.spyOn(apihelper, 'getFromOMDbAPIV2');
const MongoSpy = jest.spyOn(MediaMetadata, 'findOne');
await mongoose.connection.db.collection('media_metadata').insertOne({ imdbID: EPISODE_PRISONBREAK.imdbId, title: 'Behind the Eyes' });
await mongoose.connection.db.collection('media_metadata').insertOne({ imdbID: EPISODE_PRISONBREAK.imdbId, title: EPISODE_PRISONBREAK.title });
const response = await axios.get(`${appUrl}/api/media/video/v2?osdbHash=${EPISODE_PRISONBREAK.osdbHash}&filebytesize=${EPISODE_PRISONBREAK.filebytesize}`) as UmsApiAxiosResponse;
expect(response.data.title).toEqual('Behind the Eyes');
expect(response.data.title).toEqual(EPISODE_PRISONBREAK.title);
expect(MongoSpy).toHaveBeenCalledTimes(2);
expect(spy).toHaveBeenCalledTimes(0);
});
Expand Down Expand Up @@ -263,7 +266,7 @@ describe('get by all', () => {
const url = `${appUrl}/api/media/video/v2?`+
`osdbHash=${EPISODE_AVATAR.osdbHash}`+
`&filebytesize=${EPISODE_AVATAR.filebytesize}`+
`&title=${EPISODE_AVATAR.title}`+
`&title=${EPISODE_AVATAR.seriesTitle}`+
`&season=${EPISODE_AVATAR.season}`+
`&episode=${EPISODE_AVATAR.episode}`+
`&year=${EPISODE_AVATAR.year}`;
Expand Down Expand Up @@ -319,7 +322,7 @@ describe('get by all', () => {
const spy = jest.spyOn(apihelper, 'getFromOMDbAPIV2');
let error;
try {
await axios.get(`${appUrl}/api/media/video/v2?title=${EPISODE_LOST.title}&season=999&episode=999`);
await axios.get(`${appUrl}/api/media/video/v2?title=${EPISODE_LOST.seriesTitle}&season=999&episode=999`);
} catch (e) {
error = e;
}
Expand All @@ -329,7 +332,7 @@ describe('get by all', () => {
spy.mockReset();

try {
await axios.get(`${appUrl}/api/media/video/v2?title=${EPISODE_LOST.title}&season=999&episode=999`);
await axios.get(`${appUrl}/api/media/video/v2?title=${EPISODE_LOST.seriesTitle}&season=999&episode=999`);
} catch (e) {
error = e;
}
Expand Down
3 changes: 2 additions & 1 deletion test/e2e/media.deprecated.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,9 @@ let server;

describe('Media Metadata endpoints', () => {
beforeAll((done) => {
require('../mocks');
require('../omdb-mocks');
require('../opensubtitles-mocks');
require('../tmdb-mocks');
MongoMemoryServer.create()
.then((value) => {
mongod = value;
Expand Down

0 comments on commit 85f0332

Please sign in to comment.