Skip to content

Commit

Permalink
Merge 84aaeed into fe5fa63
Browse files Browse the repository at this point in the history
  • Loading branch information
GodswillOnuoha committed Sep 21, 2018
2 parents fe5fa63 + 84aaeed commit a46fc7f
Show file tree
Hide file tree
Showing 4 changed files with 249 additions and 26 deletions.
136 changes: 110 additions & 26 deletions server/controllers/comments.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,102 @@ import Notification from './notifications';
import {
Article, Comment, User, Reply, CommentLikesDislike, CommentHistory
} from '../models';
import isEmpty from '../utils/is_empty';

/**
*
*
* @class Comments
*/
class CommentsController {
/**
* createComment
*
* @static
* @param {object} article article promise
* @param {string} articleBody article body to update with
* @param {string} highlighted highlighted text
* @param {string} cssId
* @param {object} commentObj
* @param {object} res
* @param {objec} next
* @returns {boolean} true if diff btwn new and current article body is expected, false otherwise
* @memberof CommentsController
*/
static processHighlighted(article, articleBody, highlighted, cssId, commentObj, res, next) {
// returns true if article should be saved, else false
const injectionCheck = () => {
const closingTagLength = 7; // '</span>'.length
const openingTag = `<span id=“${cssId}” class=“highlighted”>`;
const stripped = articleBody.replace(openingTag, ''); //
return (stripped.length - article.body.length) === closingTagLength;
};

const error = {};

if (isEmpty(highlighted)) {
error.highlighted = 'highlighted text missing';
}

if (isEmpty(cssId)) {
error.cssId = 'cssId missing';
}

if (isEmpty(articleBody)) {
error.articleBody = 'injected article body missing';
} else if (!injectionCheck()) {
error.articleBody = 'injected article body: characters mismatch';
}

if (Object.keys(error).length !== 0) {
return res.status(400).json({
status: 'error',
error
});
}
article.update({ body: articleBody }).then(() => {
commentObj.highlighted = highlighted;
commentObj.cssId = cssId;
CommentsController.saveComment(res, next, commentObj);
}).catch(next);
}


/**
* createComment
*
* @static
* @param {object} res
* @param {object} next
* @param {object} comment
* @returns {object} jsonResponse
* @memberof CommentsController
*/
static saveComment(res, next, comment) {
Comment.create(comment)
.then(newComment => Comment
.findById(newComment.id, {
include: [{
model: User,
as: 'commenter',
attributes: {
exclude: ['hash', 'emailVerified', 'email', 'role', 'createdAt', 'updatedAt']
}
}, {
model: Article,
as: 'article',
attributes: {
exclude: ['authorId', 'createdAt', 'updatedAt']
}
}],
}))
.then(newComment => res.status(201).json({
status: 'success',
comment: newComment,
}))
.catch(next);
}

/**
* createComment
*
Expand All @@ -22,7 +111,13 @@ class CommentsController {
static createComment(req, res, next) {
const slug = req.params.article_slug;
const { userId } = req;
const { comment } = req.body;
const {
comment,
articleBody,
highlighted,
cssId
} = req.body;

Article.findOne({
where: {
slug,
Expand All @@ -34,33 +129,19 @@ class CommentsController {
error.status = 404;
next(error);
}
// create comment
Comment.create({

const commentObj = {
articleId: article.id,
commenterId: userId,
body: comment,
})
.then(newComment => Comment
.findById(newComment.id, {
include: [{
model: User,
as: 'commenter',
attributes: {
exclude: ['hash', 'emailVerified', 'email', 'role', 'createdAt', 'updatedAt']
}
}, {
model: Article,
as: 'article',
attributes: {
exclude: ['authorId', 'createdAt', 'updatedAt']
}
}],
}))
.then(newComment => res.status(201).json({
status: 'success',
comment: newComment,
}))
.catch(next);
};

if (highlighted || cssId || articleBody) {
CommentsController.processHighlighted(article, articleBody, highlighted, cssId,
commentObj, res, next);
} else {
CommentsController.saveComment(res, next, commentObj);
}
})
.catch(next);
}
Expand Down Expand Up @@ -471,11 +552,14 @@ class CommentsController {
.then((comments) => {
const commentsResponse = comments.map((comment) => {
const {
id, body, isEdited, createdAt, updatedAt, commenter, Replies, likes, dislikes
id, body, isEdited, createdAt, updatedAt, commenter, Replies, likes, dislikes,
highlighted, cssId
} = comment;
return {
id,
body,
highlighted,
cssId,
isEdited,
createdAt,
updatedAt,
Expand Down
27 changes: 27 additions & 0 deletions server/migrations/20180920120924-create-highlighted-comments.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
module.exports = {
up: (queryInterface, Sequelize) => [
queryInterface.addColumn(
'Comments',
'highlighted', {
type: Sequelize.BOOLEAN,
}
),
queryInterface.addColumn(
'Comments',
'cssId', {
type: Sequelize.STRING,
}
)
],

down: queryInterface => [
queryInterface.removeColumn(
'Comments',
'cssId'
),
queryInterface.removeColumn(
'Comments',
'highlighted'
)
]
};
6 changes: 6 additions & 0 deletions server/models/comment.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@ module.exports = (sequelize, DataTypes) => {
isEdited: {
type: DataTypes.BOOLEAN,
defaultValue: false,
},
highlighted: {
type: DataTypes.TEXT,
},
cssId: {
type: DataTypes.STRING,
}
}, {
hooks: {
Expand Down
106 changes: 106 additions & 0 deletions server/tests/controllers/comments.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,36 @@ const commentUpdatePayload = {
comment: 'updated the content of insightful comment'
};

const highlightedComment = {
noArticleBody: {
comment: 'Some insightful comment',
cssId: 'someVal12',
highlighted: 'test article'
},
noHighlightedText: {
comment: 'Some insightful comment',
cssId: 'someVal12',
articleBody: 'test article body'
},
noCssId: {
comment: 'Some insightful comment',
highlighted: 'test article',
articleBody: 'test article body'
},
mismatch: {
comment: 'Some insightful comment',
cssId: 'someVal12',
highlighted: 'test article',
articleBody: 'test article body'
},
complete: {
comment: 'Some insightful comment',
cssId: 'someVal12',
highlighted: 'test article',
articleBody: 'test <span id=“someVal12” class=“highlighted”>article </span>body'
}
};

describe('Comment Controller', () => {
// drop(if exists) and create user table
before((done) => {
Expand Down Expand Up @@ -118,6 +148,82 @@ describe('Comment Controller', () => {
done();
});
});

// for highlighted comment
it('should return error if articleBody is missing', (done) => {
request(app)
.post('/api/articles/test-article-slug12345/comments')
.set('Authorization', token)
.send(highlightedComment.noArticleBody)
.end((err, res) => {
expect(err).to.not.exist;
expect(res.type).to.equal('application/json');
expect(res.status).to.equal(400);
expect(res.body.status).to.equal('error');
expect(res.body.error.articleBody).to.equal('injected article body missing');
done();
});
});

it('should return error if highlighted text is missing', (done) => {
request(app)
.post('/api/articles/test-article-slug12345/comments')
.set('Authorization', token)
.send(highlightedComment.noHighlightedText)
.end((err, res) => {
expect(err).to.not.exist;
expect(res.type).to.equal('application/json');
expect(res.status).to.equal(400);
expect(res.body.status).to.equal('error');
expect(res.body.error.highlighted).to.equal('highlighted text missing');
done();
});
});

it('should return error if cssId is missing', (done) => {
request(app)
.post('/api/articles/test-article-slug12345/comments')
.set('Authorization', token)
.send(highlightedComment.noCssId)
.end((err, res) => {
expect(err).to.not.exist;
expect(res.type).to.equal('application/json');
expect(res.status).to.equal(400);
expect(res.body.status).to.equal('error');
expect(res.body.error.cssId).to.equal('cssId missing');
done();
});
});

it('should return error if injected body mismatch', (done) => {
request(app)
.post('/api/articles/test-article-slug12345/comments')
.set('Authorization', token)
.send(highlightedComment.mismatch)
.end((err, res) => {
expect(err).to.not.exist;
expect(res.type).to.equal('application/json');
expect(res.status).to.equal(400);
expect(res.body.status).to.equal('error');
expect(res.body.error.articleBody).to.equal('injected article body: characters mismatch');
done();
});
});

it('should create a highlighted-comment to an article', (done) => {
request(app)
.post('/api/articles/test-article-slug12345/comments')
.set('Authorization', token)
.send(highlightedComment.complete)
.end((err, res) => {
expect(err).to.not.exist;
expect(res.type).to.equal('application/json');
expect(res.status).to.equal(201);
expect(res.body.status).to.equal('success');
done();
});
});
// end of highloighted comment specific
});

describe('createCommentReply', () => {
Expand Down

0 comments on commit a46fc7f

Please sign in to comment.