Skip to content

Commit

Permalink
end integration tests, review int test done
Browse files Browse the repository at this point in the history
  • Loading branch information
Iván García Laverde committed Aug 11, 2023
1 parent 73e36a4 commit 4e42c27
Show file tree
Hide file tree
Showing 6 changed files with 174 additions and 14 deletions.
5 changes: 1 addition & 4 deletions .vscode/movie-reviewer.code-workspace
Original file line number Diff line number Diff line change
Expand Up @@ -166,14 +166,11 @@
"internalConsoleOptions": "openOnSessionStart",
"console": "internalConsole",
"outputCapture": "std",
"port": 5858,
"sourceMaps": true,
"smartStep": true,
"env": {
"IS_INTEGRATION": "false",
"DB_NAME": "db_test",
"IS_TEST": "test",
"NODE_OPTIONS": "--max-old-space-size=16384"
"NODE_OPTIONS": "--max-old-space-size=16384",
},
"envFile": "${fileWorkspaceFolder}/.env",
"runtimeArgs": [
Expand Down
2 changes: 1 addition & 1 deletion jest.config.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
const testMatch = ['**/*.test.ts'];
/* eslint-disable */
module.exports = {
displayName: 'web-scraper-test',
displayName: 'movire-reviewer-test',
roots: ['src/', 'node_modules/'],
globals: {},
transform: {
Expand Down
2 changes: 1 addition & 1 deletion src/database/db.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ export class DatabaseConnection {
'SELECT * FROM information_schema.sequences',
);
const restartSequences: Promise<any>[] = [];
sequences.forEach(seq => {
sequences.forEach((seq) => {
if (seq.sequence_name !== 'migrations_id_seq') {
restartSequences.push(
this.dataSource.manager.query(`ALTER SEQUENCE ${seq.sequence_name} RESTART;`),
Expand Down
39 changes: 32 additions & 7 deletions src/entities/Review.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,32 @@
import { Check, Column, CreateDateColumn, Entity, Index, JoinColumn, ManyToOne, PrimaryGeneratedColumn, Unique, UpdateDateColumn } from 'typeorm';
import { User } from './User';
import {
Check,
Column,
CreateDateColumn,
Entity,
Index,
JoinColumn,
ManyToOne,
PrimaryGeneratedColumn,
UpdateDateColumn,
ValueTransformer,
} from 'typeorm';
import { Movie } from './Movie';
import { User } from './User';

/**
* Transformer to convert string to number
*/
class ColumnNumericTransformer implements ValueTransformer {
to(data: number): number {
return data;
}

from(data: string): number {
if (data === null) return null;

return Number(data);
}
}

@Entity()
export class Review {
Expand Down Expand Up @@ -34,7 +60,7 @@ export class Review {
/**
* Rating of the movie
*/
@Column('numeric', { precision: 4, scale: 2, default: 1.0 })
@Column('numeric', { precision: 4, scale: 2, default: 1.0, transformer: new ColumnNumericTransformer() })
@Check('rating >= 1.0 AND rating <= 10.0')
rating: number;

Expand Down Expand Up @@ -67,10 +93,10 @@ export class Review {
* Movie which the review is made to
*/
@ManyToOne(() => Movie, (movie) => movie.reviews)
@JoinColumn({ referencedColumnName: 'tmdbId', name: 'movie_tmdb_id' })
@JoinColumn({ referencedColumnName: 'tmdbId', name: 'movie_tmdb_id' })
movie: Movie;

constructor(payload?: { rating: number; comment: string; movieTMDBId: number; username: string, userId: string }) {
constructor(payload?: { rating: number; comment: string; movieTMDBId: number; username: string; userId: string }) {
if (payload) {
this.rating = payload.rating;
this.comment = payload.comment;
Expand All @@ -79,5 +105,4 @@ export class Review {
this.userId = payload.userId;
}
}

}
}
137 changes: 137 additions & 0 deletions src/services/review/__test__/reviewService.int.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
import * as Chance from 'chance';
import { DateTime } from 'luxon';
import * as request from 'supertest';
import { EntityManager } from 'typeorm';
import App from '../../../app';
import { AppServicePath } from '../../../common/appCommonTypes';
import { Review } from '../../../entities/Review';
import { User, UserRoles } from '../../../entities/User';
import { MovieFactory } from '../../../factories/MovieFactory';
import { ReviewFactory } from '../../../factories/ReviewFactory';
import { UserFactory } from '../../../factories/UserFactory';
import * as Encryption from '../../../utils/encryption';
import { ReviewController } from '../reviewController';

const app = new App([new ReviewController()]);
const server = app.getServer();
let manager: EntityManager;

beforeAll(async () => {
await app.listen();
await app.databaseConnection.resetConnections();
manager = app.getDatabaseManager();
});

beforeEach(async () => {
await app.databaseConnection.resetConnections();
});

afterAll(async () => {
await app.databaseConnection.resetConnections();
await app.databaseConnection.closeConnection();
await app.close();
});

describe('When sending a request', () => {
let user: User;
beforeEach(async () => {
user = await UserFactory.createUser(
{
email: '[email protected]',
role: UserRoles.USER,
password: await Encryption.getHashedPassword('very-secret-password'),
},
manager,
);

jest.spyOn(Encryption, 'decodeToken').mockReturnValue({
userId: user.id,
role: UserRoles.USER,
email: user.email,
exp: DateTime.local().plus({ hours: 1 }).toJSDate(),
});
});
describe('POST /reviews, then', () => {
test('it should save in the database the review information', async () => {
const movie = await MovieFactory.createMovie(
{
title: 'The Matrix',
releaseDate: DateTime.fromISO('1999-03-31').toJSDate(),
overview:
'A computer hacker learns from mysterious rebels about the true nature of his reality and his role in the war against its controllers.',
},
manager,
);

const response = await request(server).post(AppServicePath.REVIEW).send({
tmdbId: movie.tmdbId,
userName: user.username,
rating: 9.8,
comment: 'This is a comment',
});

expect(response.error).toBeFalsy();
expect(response.status).toBe(201);

expect(response.body.message).toBe('Review created successfully');
expect(response.body.review).toBeDefined();
expect(response.body.review.tmdbId).toBe(movie.tmdbId);
expect(response.body.review.username).toBe(user.username);

const review = await manager.findOne(Review, {
where: { movieTmdbId: movie.tmdbId, username: user.username },
});

expect(review).toBeDefined();
expect(review.movieTmdbId).toBe(movie.tmdbId);
expect(review.username).toBe(user.username);
expect(review.rating).toBe(9.8);
expect(review.comment).toBe('This is a comment');
});
test('if the user has already reviewed the movie, it should update the review', async () => {
const movie = await MovieFactory.createMovie(
{
title: 'The Matrix',
releaseDate: DateTime.fromISO('1999-03-31').toJSDate(),
overview:
'A computer hacker learns from mysterious rebels about the true nature of his reality and his role in the war against its controllers.',
},
manager,
);

await ReviewFactory.createReview(
{
movieTmdbId: movie.tmdbId,
username: user.username,
rating: 2.0,
comment: 'Meh',
},
user,
movie,
manager,
);

const response = await request(server).post(AppServicePath.REVIEW).send({
tmdbId: movie.tmdbId,
userName: user.username,
rating: 9.8,
comment: 'Awesome movie!',
});

expect(response.error).toBeFalsy();
expect(response.status).toBe(200);

expect(response.body.message).toBe('Review updated successfully');

const review = await manager.findOne(Review, {
where: { movieTmdbId: movie.tmdbId, username: user.username },
});

expect(review).toBeDefined();
expect(review.movieTmdbId).toBe(movie.tmdbId);
expect(review.username).toBe(user.username);
expect(review.rating).toBe(9.8);
expect(review.comment).toBe('Awesome movie!');
});
});
});
3 changes: 2 additions & 1 deletion src/services/review/reviewService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { middleware } from '../../middlewares/auth';
import HttpError from '../../utils/exception';
import { TheMovieDBAPIClient } from '../../utils/tmdb';
import { mapReview } from './reviewMappers';
import { isTestEnv } from '../../utils/environment';

export default class ReviewService {
/**
Expand Down Expand Up @@ -54,7 +55,7 @@ export default class ReviewService {
handler: async (req: AuthRequest, res: Response, manager: EntityManager) => {
if (!req.body) throw new HttpError(400, 'Invalid request body parameters');

const saveReviewsInTMDB = process.env.TMDB_PERSIST_REVIEWS;
const saveReviewsInTMDB = isTestEnv() ? false :process.env.TMDB_PERSIST_REVIEWS;
const { tmdbId, userName, rating, comment } = req.body;
const existingReview = await manager.findOne(Review, {
where: {
Expand Down

0 comments on commit 4e42c27

Please sign in to comment.