Skip to content

Commit

Permalink
Merge 6a51430 into ffba8cf
Browse files Browse the repository at this point in the history
  • Loading branch information
ssanusi committed Apr 25, 2019
2 parents ffba8cf + 6a51430 commit dd85711
Show file tree
Hide file tree
Showing 11 changed files with 190 additions and 24 deletions.
4 changes: 0 additions & 4 deletions src/config/emailConfig.js

This file was deleted.

33 changes: 33 additions & 0 deletions src/controllers/likeComment.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { likeDislike } from '../utils/comment';
import { LikeComment } from '../models';
import { responseFormat, errorResponseFormat } from '../utils';

export const likeComment = async (req, res) => {
const { id: userId } = req.user;
const { id: commentId } = req.params;
const condition = { userId, commentId };
try {
const likeCommentResult = await likeDislike(LikeComment, condition);
const { like, likeCount } = likeCommentResult;
if (like) {
return res.status(200).json(
responseFormat({
status: 'success',
data: { message: 'you successfully liked the comment', Like: likeCount },
}),
);
}
return res.status(200).json(
responseFormat({
status: 'success',
data: { message: 'you successfully un-liked the comment', Like: likeCount },
}),
);
} catch (error) {
if (error.parent.constraint === 'like_comments_commentId_fkey') {
return res
.status(400)
.json(errorResponseFormat({ message: 'commentId is not on comment Table' }));
}
}
};
15 changes: 1 addition & 14 deletions src/middlewares/articles.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { findById } from '../utils/query';
import { Article } from '../models';
import { responseHandler, parseErrorResponse, checkIDParamType } from '../utils';
import { getAllArticles, getAnArticleByID } from '../controllers/article';
import { validateComment } from '../utils/comment';


/**
*@name articleValidation
Expand Down Expand Up @@ -127,19 +127,6 @@ export const articleRatingValidation = async (req, res, next) => {
next();
};

export const commentValidation = async (req, res, next) => {
const validate = await validateComment(req.body);
if (validate.fails()) {
const validationErrors = validate.errors.all();
const errorMessages = parseErrorResponse(validationErrors);
return res.status(400).json({
status: 'fail',
data: errorMessages
});
}
next();
};

/**
*@name getArticleHandler
*@description Middleware for handling requests for an article
Expand Down
30 changes: 30 additions & 0 deletions src/middlewares/comments.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { Comment } from '../models';
import { validateComment } from '../utils/comment';
import { parseErrorResponse, responseHandler } from '../utils';
import { findById } from '../utils/query';

export const commentValidation = async (req, res, next) => {
const validate = await validateComment(req.body);
if (validate.fails()) {
const validationErrors = validate.errors.all();
const errorMessages = parseErrorResponse(validationErrors);
return res.status(400).json({
status: 'fail',
data: errorMessages,
});
}
next();
};

export const verifyComment = async (req, res, next) => {
const { id } = req.params;
const comment = await findById(Comment, id);
if (!comment) {
return responseHandler(res, 404, { status: 'fail', message: 'Comment not found!' });
}
const {
dataValues: { userId: authorId },
} = comment;
req.authorId = authorId;
next();
};
7 changes: 7 additions & 0 deletions src/migrations/20190331200856-create-like-comment.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { LikeComment } from '../models';

export default {
up: queryInterface => queryInterface.createTable(LikeComment.tableName,
LikeComment.rawAttributes),
down: queryInterface => queryInterface.dropTable('like_comments'),
};
43 changes: 43 additions & 0 deletions src/models/like_comment.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/**
* @name init
* @param {sequelize} sequelize
* @param {DataTypes} DataTypes
* @returns {Model} Returns LikeArticle model
*/
export default (sequelize, DataTypes) => {
const LikeComment = sequelize.define(
'LikeComment',
{
id: {
type: DataTypes.UUID,
defaultValue: DataTypes.UUIDV4,
allowNull: false,
primaryKey: true,
},
userId: {
type: DataTypes.UUID,
allowNull: false,
},
commentId: {
type: DataTypes.UUID,
allowNull: false,
},
},
{
tableName: 'like_comments',
},
);
LikeComment.associate = (models) => {
LikeComment.belongsTo(models.Comment, {
foreignKey: 'commentId',
as: 'comment',
onDelete: 'CASCADE',
});
LikeComment.belongsTo(models.User, {
foreignKey: 'userId',
as: 'user',
onDelete: 'CASCADE',
});
};
return LikeComment;
};
7 changes: 6 additions & 1 deletion src/routers/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ import {
articleReportValidation,
articleTagValidation,
articleRatingValidation,
commentValidation,
checkQueryParams,
} from '../middlewares/articles';
import { checkParam } from '../middlewares/checkParam';
Expand All @@ -42,6 +41,8 @@ import { editUser } from '../controllers/editUser';
import { followUser } from '../controllers/follower';
import getAuthors from '../controllers/authors';
import highlightArticle from '../controllers/highlight';
import { commentValidation, verifyComment } from '../middlewares/comments';
import { likeComment } from '../controllers/likeComment';
import { forgotPassword, resetPassword } from '../controllers/authentication/passwordReset';
import resetFieldValidation from '../middlewares/auth/resetPassword';

Expand All @@ -58,6 +59,10 @@ router
.patch(checkParam, Auth.authenticateUser, verifyArticle, likeArticle);
router.route('/articles/:id/highlight').post(Auth.authenticateUser, checkParam, highlightArticle);

router
.route('/comments/:id/like')
.patch(checkParam, Auth.authenticateUser, verifyComment, likeComment);

/**
* Resource handling articles
* @name router:/articles/:id?
Expand Down
15 changes: 15 additions & 0 deletions src/utils/comment.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,18 @@ export const validateComment = (payload) => {
};
return new Validator(payload, rules, errorMessages);
};

export const likeDislike = async (Model, condition) => {
const [, isNewRecord] = await Model.findOrCreate({ where: condition });
const { userId, ...countCondition } = condition;
if (!isNewRecord) {
const deleteRecord = await Model.destroy({ where: condition });
if (deleteRecord) {
const likeCount = await Model.count({ where: countCondition });
return { like: false, likeCount };
}
} else {
const likeCount = await Model.count({ where: countCondition });
return { like: true, likeCount };
}
};
4 changes: 1 addition & 3 deletions src/utils/mailContent/passwordReset.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
import baseUrl from '../../config/emailConfig';

export const subject = 'Password Reset Instruction';

export const content = resetToken => `
<div>
<p>Hi, </p>
<p>You requested for password reset for your account</p>
<p>Please click on the following link, or paste the link in your browser to complete this process within four hours of receiving this email.</p>
<p>${baseUrl}/api/v1/password-reset/${resetToken}</p>
<p>${process.env.BASE_URL}/password-reset/${resetToken}</p>
<p>If you did not request for this, please ignore this email.</p>
</div>`;
3 changes: 1 addition & 2 deletions src/utils/mailContent/verificationMail.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import baseUrl from '../../config/emailConfig';

export const subject = 'Welcome to Authors\' Haven';

export const content = (fullName, id, verificationToken) => `
<div>
<p>Hi ${fullName},</p>
<p>Welcome to Authors Haven, a place to be inspired! Your account was successfully created.</p>
<p>Please click this ${baseUrl}/api/v1/verify/${id}/${verificationToken} to confirm your account.</p>
<p>Please click this ${process.env.BASE_URL}/verify/${id}/${verificationToken} to confirm your account.</p>
</div>`;
53 changes: 53 additions & 0 deletions tests/integration/like.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,56 @@ describe('LIKE ARTICLE', () => {
});
});
});

describe('PATCH /api/v1/:commentId/like', () => {
beforeEach(async () => {
app = await startServer(5000);
agent = chai.request(app);
});
it('should like an comment', (done) => {
agent
.patch('/api/v1/comments/979eaa2e-5b8f-4103-8192-4639afae2bb9/like')
.set('Authorization', JWT_TOKEN)
.end((err, res) => {
expect(res.statusCode).to.equal(200);
expect(res.body.data.Like).to.equal(1);
done();
});
});

it('should unlike an comment', (done) => {
agent
.patch('/api/v1/comments/979eaa2e-5b8f-4103-8192-4639afae2bb9/like')
.set('Authorization', JWT_TOKEN)
.end((err, res) => {
expect(res.statusCode).to.equal(200);
expect(res.body.data.Like).to.equal(0);
done();
});
});

it('should unlike an comment', (done) => {
agent
.patch('/api/v1/comments/979eaa2e-5b8f-4103-8192-4639afae2bb6/like')
.set('Authorization', JWT_TOKEN)
.end((err, res) => {
expect(res.statusCode).to.equal(404);
done();
});
});

it('should respond with error invalid comment ID', (done) => {
agent
.patch('/api/v1/comments/7/like')
.set('Authorization', JWT_TOKEN)
.end((err, res) => {
expect(res.statusCode).to.equal(400);
done();
});
});
after(async (done) => {
app.close();
app = null;
done();
});
});

0 comments on commit dd85711

Please sign in to comment.