Skip to content

Commit

Permalink
#164796894 implement user comment on article (#33)
Browse files Browse the repository at this point in the history
* 164796894 comment on article

user can comment on articles

[finishes #164796894]

* 1647968964 format response format

* rebase changes

* #164796894 comment on article

registered user can comment on article

[finishes 164796894]

* 164796894 comment on article

user can comment on article

[finishes #164796894]

* #164796894 comment on aticle

registered users can comment on article

[finishes #164796894]

* #164796894 impoving test coverage

impoving test coverage

[finishes $#164796894]

* #164796894 comment on article

user can comment on article

[finishes #164796894]

* #164796894 comment on article

fixing error

[finishes #164796894]
  • Loading branch information
Oluwaseyi000 authored and Temmyogunbo committed Apr 18, 2019
1 parent 6a8a6a3 commit 3850568
Show file tree
Hide file tree
Showing 8 changed files with 138 additions and 3 deletions.
37 changes: 37 additions & 0 deletions src/controllers/comment.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { Comment } from '../models';
import { errorResponseFormat } from '../utils/index';
/**
* @method comment
* @description enable authenticated users to comment on existing article
* @param {object} req - The Request Object
* @param {object} res - The Response Object
* @returns {object} - JSON new comment response object
*/

export const addComment = async (req, res) => {
const { articleId } = req.params;
const { body } = req;
const { id } = req.user;

try {
const comment = await Comment.create({ ...body, articleId, userId: id });

return res.status(201).json({
data: comment,
status: 'success',
});
} catch (error) {
if (error.parent.constraint === 'comments_articleId_fkey') {
return res.status(404).json(errorResponseFormat({
status: 'error',
message: 'invalid article id'
}));
}
if (error.parent.file === 'uuid.c') {
return res.status(404).json(errorResponseFormat({
status: 'fail',
message: 'invalid id of type UUID'
}));
}
}
};
14 changes: 14 additions & 0 deletions src/middlewares/articles.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +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 @@ -128,3 +129,16 @@ export const articleRatingValidation = async (req, res, next) => {
};

export default articleValidation;

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
});
}
return next();
};
6 changes: 5 additions & 1 deletion src/routers/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
editArticleTag,
rateArticle
} from '../controllers/article';
import { addComment } from '../controllers/comment';
import checkFields from '../middlewares/auth/loginValidator';
import Auth from '../middlewares/authenticator';
import socialRedirect from '../controllers/authentication/socialRedirect';
Expand All @@ -31,14 +32,16 @@ import {
getArticleHandler,
articleReportValidation,
articleTagValidation,
articleRatingValidation
articleRatingValidation,
commentValidation
} from '../middlewares/articles';
import { checkParam } from '../middlewares/checkParam';
import checkEditBody from '../middlewares/editProfileValidator';
import { editUser } from '../controllers/editUser';
import { followUser } from '../controllers/follower';
import getAuthors from '../controllers/authors';


const router = Router();

router.get('/', (req, res) => res.status(200).json({
Expand Down Expand Up @@ -110,6 +113,7 @@ router.get(

router.get('/auth/linkedin/callback', linkedinCallback);
router.get('/auth/linkedin', linkedinUser);
router.post('/articles/:articleId/comments', Auth.authenticateUser, commentValidation, addComment);

// Route for user following and unfollowing
router.post('/followers/:id/follow', checkParam, Auth.authenticateUser, followUser);
Expand Down
2 changes: 1 addition & 1 deletion src/utils/article.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ export const getArticleReportValidator = (payload) => {
* @param {object} payload The request object
* @returns {function} Returns validation object
*/
export const validateArticleTag = async (payload) => {
export const validateArticleTag = (payload) => {
const rules = {
tags: ['array'],
};
Expand Down
19 changes: 19 additions & 0 deletions src/utils/comment.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import Validator from 'validatorjs';

/**
* @description This is the method for validating comment before inserting
* @param {object} payload The request object
* @returns {function} Returns validation object
*/

export const validateComment = (payload) => {
const rules = {
body: 'required',
};

const errorMessages = {
'required.body': 'comment body is required'

};
return new Validator(payload, rules, errorMessages);
};
46 changes: 46 additions & 0 deletions tests/integration/comment.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import 'chai/register-should';
import chai from 'chai';
import chaiHttp from 'chai-http';
import { startServer } from '../../src/server';
import { articleId } from '../mock/bookmark';
import { comment } from '../mock/comment';
import { JWT_TOKEN } from '../mock/user';

const { assert } = chai;
let app = null;
let agent = null;

chai.use(chaiHttp);

describe('POST comment on article', () => {
beforeEach(async () => {
app = await startServer(5500);
agent = chai.request(app);
});

it('comment added successfully', (done) => {
agent.post(`/api/v1/articles/${articleId}/comments`)
.set('Authorization', JWT_TOKEN)
.send(comment)
.end((_err, res) => {
const { status, body } = res;
assert.equal(status, 201);
assert.isObject(body);
assert.equal(body.status, 'success');
assert.property(body, 'data');
done();
});
});

it('empty body content ', (done) => {
agent.post(`/api/v1/articles/${articleId}/comments`)
.set('Authorization', JWT_TOKEN)
.end((_err, res) => {
const { status, body } = res;
assert.equal(status, 400);
assert.isObject(body);
assert.equal(body.status, 'fail');
done();
});
});
});
2 changes: 1 addition & 1 deletion tests/integration/tags.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ let app = null;
let agent = null;

before(async () => {
app = await startServer(4000);
app = await startServer(5100);
agent = chai.request(app);
});

Expand Down
15 changes: 15 additions & 0 deletions tests/mock/comment.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
export const comment = {
body: 'Lorem ipsum dolor sit amet, sit ut dolor alterum, sed malis referrentur cu. Aperiam fabulas eos ea. Sea mazim senserit tincidunt te. Mei volutpat delicatissimi ut, id mollis alienum argumentum has, semper efficiendi sed ea. Ius decore consul forensibus ne, enim verear corpora sit ut. Usu eu possit equidem menandri, quo et noster officiis iracundia.',
};

export const uncompleteCommentBody = {
body: '',
};

export const invalidComment = {
articleId: '1839374c-53ea-438c-815d-1fe301422120',
};

export const invalidarticleUUID = {
articleId: '1839374c-53ea-438c-xxxxxxxxx',
};

0 comments on commit 3850568

Please sign in to comment.