Skip to content

Commit

Permalink
feat(rating): fetch all ratings related to an article
Browse files Browse the repository at this point in the history
- Created an endpoint for fetching all rating related to an article slug
- Wrote unit test
- Documented the api using swagger
[Delivers #165413108]
  • Loading branch information
ericnyirimana committed May 20, 2019
1 parent 554819c commit 9e89d3a
Show file tree
Hide file tree
Showing 6 changed files with 159 additions and 7 deletions.
15 changes: 15 additions & 0 deletions controllers/rating.controller.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import db from '../models';
import RateHelper from '../helpers/articleRatevalidator';
import PassportHelper from '../helpers/passport';

const { Rating, User } = db;
Expand Down Expand Up @@ -48,5 +49,19 @@ class RatingController {
data: { rating, Author: userData }
});
}

/**
* Check the environment
* @function getArticleRating
* @param {object} req - accept object with user info
* @param {object} res - accept object with user info
* @return {json} Returns json object
* @static
*/
static async getArticleRating(req, res) {
const allRates = await RateHelper.getRating(req);
const statusCode = allRates.status ? allRates.status : 200;
return res.status(statusCode).send({ status: res.statusCode, Ratings: allRates });
}
}
export default RatingController;
25 changes: 24 additions & 1 deletion helpers/articleRatevalidator.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import db from '../models';

const { Article } = db;
const { Article, User, Rating } = db;

/**
* @exports ArticRatelehelper
Expand Down Expand Up @@ -44,6 +44,29 @@ class ArticRatelehelper {
}
return true;
}

/**
* get all ratings
* @param {object} req - an object
*@return {object} Return ratings of an aricle
*/
static async getRating(req) {
const { slug } = req.params;
const getArticle = await Article.findOne({
where: { slug }
});
if (getArticle == null) {
return { status: 404, message: 'This article does not exist' };
}
const getRate = await Rating.findAll({
where: { articleSlug: slug },
include: [{ model: User, as: 'author', attributes: ['username', 'bio', 'image'] }]
});
if (!getRate.length) {
return { status: 200, message: 'This article has no ratings' };
}
return getRate;
}
}

export default ArticRatelehelper;
4 changes: 3 additions & 1 deletion models/rating.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ const ratings = (sequelize, DataTypes) => {
);
Rating.associate = (models) => {
// associations can be defined here
Rating.belongsTo(models.User, { foreignKey: 'reviewerId', onDelete: 'CASCADE', onUpdate: 'CASCADE' });
Rating.belongsTo(models.User, {
foreignKey: 'reviewerId', as: 'author', onDelete: 'CASCADE', onUpdate: 'CASCADE'
});
Rating.belongsTo(models.Article, {
foreignKey: 'articleSlug', targetKey: 'slug', onDelete: 'CASCADE', onUpdate: 'CASCADE'
});
Expand Down
1 change: 1 addition & 0 deletions routes/api/article/articles.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ router.delete('/:slug', Auth, ArticleHelper.isOwner, articleController.deleteArt
router.get('/:slug', articleController.getArticle);
router.get('/', articleController.getAllArticles);
router.post('/:slug/rate', Auth, ArticleMiddleware.checkRatedArticle, Ratingcontroller.rateArticle);
router.get('/:slug/rate', Auth, Ratingcontroller.getArticleRating);
router.post('/:slug/reaction/:option', Auth, ArticleHelper.isExisting, articleController.reactOnArticle);
router.get('/:slug/likes', Auth, ArticleHelper.likesNumber, articleController.getLikes);
router.get('/:slug/dislikes', Auth, ArticleHelper.dislikesNumber, articleController.getDislikes);
Expand Down
48 changes: 43 additions & 5 deletions routes/api/article/doc.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
* /articles/{slug}/rate:
* post:
* tags:
* - Article
* - Rating
* name: Rating
* summary: User rate an article
* produces:
Expand Down Expand Up @@ -55,12 +55,50 @@
* properties:
* name:
* type: string
* articleId:
* type: integer
* articleSlug:
* type: string
* required:
* - name
* - articleId
* - articleSlug
* @swagger
* /articles/{slug}/rate:
* get:
* tags:
* - Rating
* name: Rating
* summary: User get all rates given to an article
* produces:
* - application/json
* consumes:
* - application/json
* parameters:
* - name: slug
* in: path
* schema:
* type: integer
* required:
* - slug
* - name: authorization
* in: header
* schema:
* type: string
* required:
* - authorization
* responses:
* '201':
* description: Created
* '400':
* description: Bad Request
* Tag:
* type: object
* properties:
* name:
* type: string
* articleSlug:
* type: string
* required:
* - name
* - articleSlug
* @swagger
* /articles/{slug}/tag:
* post:
Expand Down
73 changes: 73 additions & 0 deletions tests/rate-article.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,18 @@ const articleTest = {
image: 'https/piimg.com/img.jpg'
};

const newArticleTest = {
title: 'This is the new title of the article',
description: 'This is the new description of the acrticle',
body: 'this is the new body of the article',
image: 'https/piimg.com/img.jpg'
};

const rateTest = { rate: 2 };

let toKen = null;
let articleSlug = null;
let articleNewSlug = null;
describe('Rate user posted article', () => {
it('User Signup', (done) => {
chai.request(app)
Expand Down Expand Up @@ -59,6 +67,25 @@ describe('Rate user posted article', () => {
done();
});
});
it('User create a new article', (done) => {
chai.request(app)
.post('/api/v1/articles')
.set('authorization', toKen)
.send(newArticleTest)
.end((error, res) => {
articleNewSlug = res.body.article.slug;
expect(res.body).to.have.property('article');
expect(res.body.article).to.have.property('author');
expect(res.body.article).to.have.property('title');
expect(res.body.article).to.have.property('body');
expect(res.body.article).to.have.property('description');
expect(res.body.article.title).equals('This is the new title of the article');
expect(res.body.article.description).equals('This is the new description of the acrticle');
expect(res.body.article.body).equals('this is the new body of the article');
expect(res.body.article.image).equals('https/piimg.com/img.jpg');
done();
});
});
it('User try to rate their article', (done) => {
chai.request(app)
.post(`/api/v1/articles/${articleSlug}/rate`)
Expand Down Expand Up @@ -144,4 +171,50 @@ describe('Rate user posted article', () => {
done();
});
});
it('Get all rating on an article', (done) => {
chai.request(app)
.get(`/api/v1/articles/${articleSlug}/rate`)
.set('authorization', toKen)
.end((error, res) => {
expect(res.body).to.have.status(200);
expect(res.body.Ratings[0]).to.have.property('id');
expect(res.body.Ratings[0]).to.have.property('reviewerId');
expect(res.body.Ratings[0]).to.have.property('articleSlug');
expect(res.body.Ratings[0]).to.have.property('rate');
expect(res.body.Ratings[0]).to.have.property('createdAt');
expect(res.body.Ratings[0]).to.have.property('updatedAt');
expect(res.body.Ratings[0]).to.have.property('author');
done();
});
});
it('Article has no rating', (done) => {
chai.request(app)
.get(`/api/v1/articles/${articleNewSlug}/rate`)
.set('authorization', toKen)
.end((error, res) => {
expect(res.body).to.have.status(200);
expect(res.body.Ratings).to.have.property('message').to.be.equal('This article has no ratings');
done();
});
});
it('Article has no rating', (done) => {
chai.request(app)
.get('/api/v1/articles/test-test/rate')
.set('authorization', toKen)
.end((error, res) => {
expect(res.body).to.have.status(404);
expect(res.body.Ratings).to.have.property('message').to.be.equal('This article does not exist');
done();
});
});
it('Article not found', (done) => {
chai.request(app)
.get('/api/v1/articles/rate')
.set('authorization', toKen)
.end((error, res) => {
expect(res.body).to.have.status(404);
expect(res.body).to.have.property('error').to.be.equal('Article Not found');
done();
});
});
});

0 comments on commit 9e89d3a

Please sign in to comment.