From 4c5900611b30ded1698539c3daf4de3598c43be4 Mon Sep 17 00:00:00 2001 From: Ayelegun Kayode Michael Date: Fri, 20 Apr 2018 16:01:10 +0100 Subject: [PATCH] feature/rate-center - write controller for rating center - write tests for ratings controller --- server/controllers/rating.js | 85 +++++++++++++++++++ .../20180420014644-create-ratings.js | 45 ++++++++++ server/models/center.js | 5 ++ server/models/rating.js | 18 ++++ server/models/user.js | 5 ++ server/routes/index.js | 10 ++- server/tests/index.js | 1 + server/tests/rating.test.js | 45 ++++++++++ 8 files changed, 212 insertions(+), 2 deletions(-) create mode 100644 server/controllers/rating.js create mode 100644 server/migrations/20180420014644-create-ratings.js create mode 100644 server/models/rating.js create mode 100644 server/tests/rating.test.js diff --git a/server/controllers/rating.js b/server/controllers/rating.js new file mode 100644 index 0000000..63ee9a9 --- /dev/null +++ b/server/controllers/rating.js @@ -0,0 +1,85 @@ +import db from '../models'; +import serverError from '../errorHandler/serverError'; + +const { Center, Rating } = db; + +/** + * Controller for handling ratings + */ +class Ratings { + /** + * Rate a center + * + * @param {object} request - The request object + * @param {object} response - The response object + * + * @returns The rated center + */ + static rateCenter(request, response) { + Center.findById(request.params.centerId) + .then((foundCenter) => { + if (!foundCenter) { + return response.status(400).json({ + message: 'No center found.' + }); + } + return Rating.findAll({ + where: { + centerId: request.params.centerId + } + }).then((ratedCenter) => { + if (ratedCenter.length == 0) { + return Rating.create({ + rating: request.body.rating, + userId: request.userDetails.id, + centerId: request.params.centerId + }).then((centerRated) => { + return response.status(201).json({ + message: 'Successfully rated this center.', + centerDetails: { + centerRated + } + }); + }); + } + const usersArray = []; + ratedCenter.forEach(center => usersArray + .push(center.dataValues.userId)); + if (usersArray.includes(request.userDetails.id)) { + return Rating.findOne({ + where: { + userId: request.userDetails.id + } + }).then(updateCenterRating => updateCenterRating + .update({ rating: request.body.rating })) + .then((ratingUpdated) => { + return response.status(201).json({ + message: 'Your rating has been updated.', + centerDetails: { + ratingUpdated + } + }); + }); + } + return Rating.create({ + rating: request.body.rating, + userId: request.userDetails.id, + centerId: request.params.centerId + }).then((ratedCenter) => { + return response.status(201).json({ + message: '>>>>><<<< Successfully', + centerDetails: { + ratedCenter + } + }); + }); + }); + }).catch(() => { + return response.status(500).json({ + message: serverError + }); + }); + } +} + +export default Ratings; diff --git a/server/migrations/20180420014644-create-ratings.js b/server/migrations/20180420014644-create-ratings.js new file mode 100644 index 0000000..fd7eaf0 --- /dev/null +++ b/server/migrations/20180420014644-create-ratings.js @@ -0,0 +1,45 @@ +'use strict'; +module.exports = { + up: (queryInterface, Sequelize) => { + return queryInterface.createTable('Ratings', { + id: { + allowNull: false, + autoIncrement: true, + primaryKey: true, + type: Sequelize.INTEGER + }, + rating: { + type: Sequelize.FLOAT + }, + createdAt: { + allowNull: false, + type: Sequelize.DATE + }, + updatedAt: { + allowNull: false, + type: Sequelize.DATE + }, + centerId: { + type: Sequelize.INTEGER, + allowNull: false, + references: { + model: 'Centers', + key: 'id', + as: 'centerId' + } + }, + userId: { + type: Sequelize.INTEGER, + allowNull: false, + references: { + model: 'Users', + key: 'id', + as: 'userId' + } + } + }); + }, + down: (queryInterface, Sequelize) => { + return queryInterface.dropTable('Ratings'); + } +}; diff --git a/server/models/center.js b/server/models/center.js index 88dcc51..57bd2e8 100644 --- a/server/models/center.js +++ b/server/models/center.js @@ -48,6 +48,11 @@ module.exports = (sequelize, DataTypes) => { foreignKey: 'venue', as: 'events' }); + + models.Center.hasMany(models.Rating, { + foreignKey: 'centerId', + as: 'centerId' + }); }; return Center; }; diff --git a/server/models/rating.js b/server/models/rating.js new file mode 100644 index 0000000..e4dbaa8 --- /dev/null +++ b/server/models/rating.js @@ -0,0 +1,18 @@ +module.exports = (sequelize, DataTypes) => { + const Rating = sequelize.define('Rating', { + rating: { + type: DataTypes.FLOAT, + defaultValue: 0 + } + }); + Rating.associate = (models) => { + models.Rating.belongsTo(models.Center, { + foreignKey: 'centerId', + onDelete: 'cascade' + }); + models.Rating.belongsTo(models.User, { + foreignKey: 'userId' + }); + }; + return Rating; +}; diff --git a/server/models/user.js b/server/models/user.js index b97a046..4e9ea9e 100644 --- a/server/models/user.js +++ b/server/models/user.js @@ -31,6 +31,11 @@ module.exports = (sequelize, DataTypes) => { foreignKey: 'organizer', as: 'events' }); + + models.User.hasMany(models.Rating, { + foreignKey: 'userId', + as: 'userId' + }); }; return User; diff --git a/server/routes/index.js b/server/routes/index.js index 2a634a2..64c9398 100644 --- a/server/routes/index.js +++ b/server/routes/index.js @@ -1,7 +1,8 @@ -import userController from '../controllers/user'; +import eventController from '../controllers/event'; import centerController from '../controllers/center'; +import ratingController from '../controllers/rating'; import sessionControl from '../middleware/SessionControl'; -import eventController from '../controllers/event'; +import userController from '../controllers/user'; module.exports = (app) => { app.get('/api', (request, response) => @@ -55,4 +56,9 @@ module.exports = (app) => { sessionControl.isLoggedIn, sessionControl.isUser, userController.modifyUserDetails ); + app.post( + '/api/v1/center/rating/:centerId', + sessionControl.isLoggedIn, sessionControl.isUser, + ratingController.rateCenter + ); }; diff --git a/server/tests/index.js b/server/tests/index.js index f11b491..3fd1320 100644 --- a/server/tests/index.js +++ b/server/tests/index.js @@ -1,3 +1,4 @@ import './user.test'; import './center.test'; import './event.test'; +import './rating.test'; diff --git a/server/tests/rating.test.js b/server/tests/rating.test.js new file mode 100644 index 0000000..b2201d3 --- /dev/null +++ b/server/tests/rating.test.js @@ -0,0 +1,45 @@ +import { expect } from 'chai'; +import supertest from 'supertest'; +import app from '../app'; +import dummyUser from './seed/userseed'; + +const request = supertest(app); + +describe('Integration tests for Ratings functionality', () => { + it('should create a rating for a center', (done) => { + request.post(`/api/v1/center/rating/1?token=${dummyUser.token}`) + .set('Connection', 'keep alive') + .set('Content-Type', 'application/json') + .type('form') + .send(4) + .end((error, response) => { + expect(response.status).to.equal(201); + done(); + }); + }); + it( + 'should update the ratings of a user who has rated the same center previously', + (done) => { + request.post(`/api/v1/center/rating/1?token=${dummyUser.token}`) + .set('Connection', 'keep alive') + .set('Content-Type', 'application/json') + .type('form') + .send(3.5) + .end((error, response) => { + expect(response.status).to.equal(201); + done(); + }); + } + ); + it('should fail if the center is not found', (done) => { + request.post(`/api/v1/center/rating/100?token=${dummyUser.token}`) + .set('Connection', 'keep alive') + .set('Content-Type', 'application/json') + .type('form') + .send(3) + .end((error, response) => { + expect(response.status).to.equal(400); + done(); + }); + }); +});