Skip to content

Commit

Permalink
Merge pull request #89 from steniowagner/feat/movies-images
Browse files Browse the repository at this point in the history
Feat/movies images
  • Loading branch information
steniowagner authored Dec 3, 2023
2 parents b690b98 + 2fdb9f2 commit 4234a99
Show file tree
Hide file tree
Showing 12 changed files with 711 additions and 2 deletions.
510 changes: 510 additions & 0 deletions __test__/datasources/tmdb-api/fixtures.ts

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions __test__/datasources/tmdb-api/queries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -482,6 +482,7 @@ query Movie ($id: Int!, $language: ISO6391Language) {
}
type
}
images(id: $id, language: $language)
}
}
`;
Expand Down
53 changes: 53 additions & 0 deletions graphql.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -1930,6 +1930,59 @@
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "images",
"description": null,
"args": [
{
"name": "id",
"description": null,
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "Int",
"ofType": null
}
},
"defaultValue": null,
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "language",
"description": null,
"type": {
"kind": "ENUM",
"name": "ISO6391Language",
"ofType": null
},
"defaultValue": null,
"isDeprecated": false,
"deprecationReason": null
}
],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "LIST",
"name": null,
"ofType": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "String",
"ofType": null
}
}
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "imdbId",
"description": null,
Expand Down
8 changes: 8 additions & 0 deletions src/generated/graphql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,7 @@ export type Movie = {
genres: Array<Scalars['String']['output']>;
homepage?: Maybe<Scalars['String']['output']>;
id: Scalars['Int']['output'];
images: Array<Scalars['String']['output']>;
imdbId?: Maybe<Scalars['String']['output']>;
originalLanguage?: Maybe<Scalars['String']['output']>;
originalTitle?: Maybe<Scalars['String']['output']>;
Expand All @@ -240,6 +241,12 @@ export type Movie = {
};


export type MovieImagesArgs = {
id: Scalars['Int']['input'];
language?: InputMaybe<Iso6391Language>;
};


export type MovieVideosArgs = {
id: Scalars['Int']['input'];
language?: InputMaybe<Iso6391Language>;
Expand Down Expand Up @@ -1283,6 +1290,7 @@ export type MovieResolvers<ContextType = any, ParentType extends ResolversParent
genres?: Resolver<Array<ResolversTypes['String']>, ParentType, ContextType>;
homepage?: Resolver<Maybe<ResolversTypes['String']>, ParentType, ContextType>;
id?: Resolver<ResolversTypes['Int'], ParentType, ContextType>;
images?: Resolver<Array<ResolversTypes['String']>, ParentType, ContextType, RequireFields<MovieImagesArgs, 'id'>>;
imdbId?: Resolver<Maybe<ResolversTypes['String']>, ParentType, ContextType>;
originalLanguage?: Resolver<Maybe<ResolversTypes['String']>, ParentType, ContextType>;
originalTitle?: Resolver<Maybe<ResolversTypes['String']>, ParentType, ContextType>;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { handler } from "./movie-images.handler";
export * as types from "./movie-images.types";
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import TheMovieDBAPI from "@tmdb-api/tmdb-movie-db-api";
import { Iso6391Language } from "@generated-types";
import { CONSTANTS as TMDBAPI_CONSTANS } from "@tmdb-api/utils";

import * as fixtures from "../../../../../../../__test__/datasources/tmdb-api/fixtures";

import { handler } from "./movie-images.handler";

const ID = 1;

const mockGet = jest.fn();

jest.mock("@apollo/datasource-rest", () => {
class MockRESTDataSource {
baseUrl = "";
get = mockGet;
}
return {
RESTDataSource: MockRESTDataSource,
};
});

describe("DataSources/TheMovieDBApi/Movie-Images-Query-Handler", () => {
beforeEach(() => {
jest.clearAllMocks();
});

describe('When the "language" is defined', () => {
it('should call "RESTDatasource.get" correctly', async () => {
const tmdbAPI = new TheMovieDBAPI();
const language = Iso6391Language.Pt;
await handler(
{
language,
id: ID,
},
tmdbAPI,
);
expect(mockGet.mock.calls[0][0]).toEqual(`movie/${ID}/images`);
expect(mockGet.mock.calls[0][1].params).toEqual({
language,
});
expect(typeof mockGet.mock.calls[0][1].headers.Authorization).toEqual("string");
});
});

describe('When the "language" is not defined', () => {
it('should call "RESTDatasource.get" correctly', async () => {
const tmdbAPI = new TheMovieDBAPI();
await handler(
{
id: ID,
},
tmdbAPI,
);
expect(mockGet.mock.calls[0][0]).toEqual(`movie/${ID}/images`);
expect(mockGet.mock.calls[0][1].params).toEqual({
language: TMDBAPI_CONSTANS.FALLBACK_LANGUAGE,
});
expect(typeof mockGet.mock.calls[0][1].headers.Authorization).toEqual("string");
});
});

describe('When the response received is "undefined"', () => {
it("should return the data correctly", async () => {
mockGet.mockReturnValueOnce(undefined);
const tmdbAPI = new TheMovieDBAPI();
const result = await handler(
{
id: ID,
},
tmdbAPI,
);
expect(result).toEqual([]);
});
});

describe("When receive the data", () => {
it("should return the data correctly", async () => {
mockGet.mockReturnValueOnce(fixtures.movieImages);
const tmdbAPI = new TheMovieDBAPI();
const result = await handler(
{
id: ID,
},
tmdbAPI,
);
const images = fixtures.movieImages.backdrops.map((backdrop) => backdrop.file_path);
expect(result).toEqual(images);
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { CONSTANTS as TMDB_CONSTANS } from "@tmdb-api/utils";
import TheMovieDBAPI from "@tmdb-api/tmdb-movie-db-api";
import { TvShowImagesArgs } from "@generated-types";

import { Response } from "./movie-images.types";

export const handler = async (params: TvShowImagesArgs, tmdbAPI: TheMovieDBAPI) => {
const response = await tmdbAPI.handle<Response>(`movie/${params.id}/images`, {
language: params.language ?? TMDB_CONSTANS.FALLBACK_LANGUAGE,
});
if (!response) {
return [];
}
return response.backdrops
.filter((backdrop) => !!backdrop.file_path)
.map((backdrop) => backdrop.file_path);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
export type Response = {
backdrops: {
aspect_ratio: number;
height: number;
iso_639_1: string;
file_path: string;
vote_average: number;
vote_count: number;
width: number;
}[];
};
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import * as details from "./details";
import * as videos from "./videos";
import * as images from "./images";

export { details, videos };
export { details, videos, images };
Original file line number Diff line number Diff line change
Expand Up @@ -945,13 +945,16 @@ describe("DataSources/TheMovieDBApi/Integration", () => {
describe("Movies", () => {
describe("Querying Movie-details", () => {
describe("When query the data successfuly", () => {
it("should return data correctly", async () => {
it.only("should return data correctly", async () => {
jest
.spyOn(RESTDataSource.prototype as any, "get")
.mockImplementationOnce(async () => Promise.resolve(fixtures.movie));
jest
.spyOn(RESTDataSource.prototype as any, "get")
.mockImplementationOnce(async () => Promise.resolve(fixtures.movieVideos));
jest
.spyOn(RESTDataSource.prototype as any, "get")
.mockImplementationOnce(async () => Promise.resolve(fixtures.movieImages));
const response = await execDatasourceTestOperation<{
movie: Movie;
}>({
Expand Down Expand Up @@ -1030,6 +1033,10 @@ describe("DataSources/TheMovieDBApi/Integration", () => {
extraLarge: `${YOUTUBE_THUMBNAIL_URL}/${fixtures.movieVideos.results[i].key}/maxresdefault.jpg`,
});
}
// images
for (let i = 0; i < movie.images.length; i++) {
expect(movie.images[i]).toEqual(fixtures.movieImages.backdrops[i].file_path);
}
});
});
});
Expand Down
6 changes: 6 additions & 0 deletions src/graphql/resolvers/movie-details.resolvers.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { MovieImagesArgs } from "@generated-types";
import * as movies from "@/graphql/datasources/the-movie-db-api/handlers/movies";
import { QueryMovieArgs } from "@generated-types";
import { Context } from "@/types";
Expand Down Expand Up @@ -44,5 +45,10 @@ export const resolvers = {
params: movies.videos.types.Params,
context: Context,
) => movies.videos.handler(params, context.tmdbAPI),
images: (
_: movies.details.types.Response,
params: MovieImagesArgs,
context: Context,
): Promise<string[]> => movies.images.handler(params, context.tmdbAPI),
},
};
1 change: 1 addition & 0 deletions src/graphql/type-defs/schemas/tmdb/movie.schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,5 +40,6 @@ export default `#graphql
voteAverage: Float
voteCount: Int
videos(id: Int!, language: ISO6391Language): [MediaVideo!]!
images(id: Int!, language: ISO6391Language): [String!]!
}
`;

0 comments on commit 4234a99

Please sign in to comment.