Skip to content

Commit

Permalink
bug(article-ratings):fix errors with article ratings
Browse files Browse the repository at this point in the history
  • Loading branch information
Halimah Oladosu authored and Halimah Oladosu committed Jul 23, 2019
1 parent 60e7b73 commit 44b355a
Show file tree
Hide file tree
Showing 9 changed files with 134 additions and 85 deletions.
15 changes: 0 additions & 15 deletions src/db/migrations/20190708085450-create-article.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,21 +40,6 @@ module.exports = {
type: Sequelize.TEXT,
allowNull: true
},
averageRating: {
type: Sequelize.FLOAT,
allowNull: false,
defaultValue: 0
},
numberOfRating: {
type: Sequelize.INTEGER,
allowNull: false,
defaultValue: 0
},
sumOfRating: {
type: Sequelize.INTEGER,
allowNull: false,
defaultValue: 0
},
likesCount: {
type: Sequelize.INTEGER,
defaultValue: 0
Expand Down
8 changes: 0 additions & 8 deletions src/db/models/article.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,14 +62,6 @@ export default (sequelize, DataTypes) => {
type: DataTypes.INTEGER,
default: 0
},
numberOfRating: {
type: DataTypes.INTEGER,
default: 0
},
sumOfRating: {
type: DataTypes.INTEGER,
default: 0
},
isPublished: {
type: DataTypes.BOOLEAN,
default: false
Expand Down
35 changes: 35 additions & 0 deletions src/helpers/average-ratings.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/**
* @method averageRatings
* - Helps update the article table
*
* @param {integer} articleId - Id of the article to be rated
*
* @return {Object} ratingDetails
*/

import model from '../db/models';

const { Rating } = model;

const averageRatings = async articleId => {
const allRatings = await Rating.findAndCountAll({
where: { articleId }
});

let totalSum = 0;

for (let i = 0; i < allRatings.count; i += 1) {
const eachRating = allRatings.rows[i].rating;
const newSum = eachRating + totalSum;
totalSum = newSum;
}
const averageRating =
parseFloat((totalSum / allRatings.count).toFixed(1)) || 0;
const ratingDetails = {
totalNumberOfRatings: allRatings.count,
sumOfRatings: totalSum,
averageRating
};
return ratingDetails;
};
export default averageRatings;
48 changes: 5 additions & 43 deletions src/services/article.service.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import model from '../db/models';
import Helper from './helper';
import { paginationQueryMetadata, pageMetadata } from '../helpers/pagination';
import readtime from '../helpers/read-time';
import averageRatings from '../helpers/average-ratings';

const { Comment, Article, User, Follow, Rating, CommentReaction } = model;
/** Istanbul ignore next */
Expand Down Expand Up @@ -52,7 +53,6 @@ export const createArticleService = async data => {
image: finalUploads,
readTime
});

return article;
};

Expand All @@ -77,7 +77,10 @@ export const getArticleService = async data => {
}
]
});
return article;
if (article) {
const articleRatingDetails = await averageRatings(article.id);
return { article, articleRatingDetails };
}
};

/**
Expand Down Expand Up @@ -486,31 +489,6 @@ export const deleteCommentService = async (slug, id, userId) => {
return response;
};

/**
* @method updateArticleRating
* - Helps update the article table
*
* @param {integer} articleId - Id of the article to be rated
* @param {integer} rating the rating value from from 1 - 5
* @param {integer} userId - id of the user rating the article
*
* @return {Promise}
*/

const updateArticlesRating = async (
sumOfRating,
numberOfRating,
averageRating,
id
) => {
const article = await Article.findByPk(id);
return article.update({
sumOfRating,
numberOfRating,
averageRating
});
};

/**
* @method articleRatingsService
* @description Helps handle the ratings endpoint
Expand All @@ -531,15 +509,6 @@ export const articleRatingsService = async (articleId, rating, userId) => {
if (!article) {
return 'The article specified does not exist';
}

let { sumOfRating, numberOfRating, averageRating } = article.dataValues;

sumOfRating = sumOfRating ? sumOfRating + rating : rating;
numberOfRating = numberOfRating ? numberOfRating + 1 : 1;
averageRating = averageRating
? parseFloat((sumOfRating / numberOfRating).toFixed(1))
: sumOfRating;

const ratings = await Rating.findOne({ where: { userId, articleId } });
if (ratings) {
return null;
Expand All @@ -550,13 +519,6 @@ export const articleRatingsService = async (articleId, rating, userId) => {
articleId,
rating
});

await updateArticlesRating(
sumOfRating,
numberOfRating,
averageRating,
articleId
);
return result;
} catch (error) {
return error;
Expand Down
29 changes: 25 additions & 4 deletions src/tests/controller/article.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -616,22 +616,43 @@ describe('Article API endpoints', () => {
expect(response.status).to.have.been.calledWith(500);
});
});

describe('GET single article /articles/:slug', () => {
it('Should successfully publish articles by user', done => {
chai
.request(app)
.put(
`${process.env.API_VERSION}/articles/publish/${secondArticle.slug}`
)
.set({ Authorization: `Bearer ${userToken}` })
.end((error, response) => {
expect(response.status).to.equal(200);
expect(response).to.be.an('Object');
expect(response.body).to.have.property('status');
expect(response.body).to.have.property('data');
expect(response.body.status).to.equal('success');
expect(response.body.data.message).to.equal(
'Article published successfully'
);
done();
});
});

it('Should successfully fetch a single article', done => {
chai
.request(app)
.get(`${process.env.API_VERSION}/articles/${createdArticle.slug}`)
.get(`${process.env.API_VERSION}/articles/${secondArticle.slug}`)
.end((error, response) => {
expect(response.status).to.equal(200);
expect(response).to.be.an('Object');
expect(response.body).to.have.property('status');
expect(response.body).to.have.property('data');
expect(response.body.status).to.equal('success');
expect(response.body.data.title).to.equal('first article');
expect(response.body.data.description).to.equal(
expect(response.body.data.article.title).to.equal('new article');
expect(response.body.data.article.description).to.equal(
'this is a description'
);
expect(response.body.data.body).to.equal(
expect(response.body.data.article.body).to.equal(
'this is a description this is a description'
);
done();
Expand Down
31 changes: 19 additions & 12 deletions src/tests/controller/stats.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,13 @@ describe('Page View Count Tests', () => {
});
});

beforeEach(async () => {
await chai
.request(app)
.put(`${process.env.API_VERSION}/articles/publish/${firstArticle.slug}`)
.set({ Authorization: `Bearer ${userToken}` });
});

it('Should successfully increase the view count this article by 1', done => {
chai
.request(app)
Expand All @@ -53,14 +60,14 @@ describe('Page View Count Tests', () => {
expect(response.body).to.have.property('status');
expect(response.body).to.have.property('data');
expect(response.body.status).to.equal('success');
expect(response.body.data.title).to.equal('new article');
expect(response.body.data.description).to.equal(
expect(response.body.data.article.title).to.equal('new article');
expect(response.body.data.article.description).to.equal(
'this is a description'
);
expect(response.body.data.body).to.equal(
expect(response.body.data.article.body).to.equal(
'this is a description this is a description'
);
expect(response.body.data.viewsCount).to.equal(1);
expect(response.body.data.article.viewsCount).to.equal(1);
done();
});
});
Expand All @@ -74,14 +81,14 @@ describe('Page View Count Tests', () => {
expect(response.body).to.have.property('status');
expect(response.body).to.have.property('data');
expect(response.body.status).to.equal('success');
expect(response.body.data.title).to.equal('new article');
expect(response.body.data.description).to.equal(
expect(response.body.data.article.title).to.equal('new article');
expect(response.body.data.article.description).to.equal(
'this is a description'
);
expect(response.body.data.body).to.equal(
expect(response.body.data.article.body).to.equal(
'this is a description this is a description'
);
expect(response.body.data.viewsCount).to.equal(2);
expect(response.body.data.article.viewsCount).to.equal(2);
done();
});
});
Expand All @@ -97,14 +104,14 @@ describe('Page View Count Tests', () => {
expect(response.body).to.have.property('status');
expect(response.body).to.have.property('data');
expect(response.body.status).to.equal('success');
expect(response.body.data.title).to.equal('new article');
expect(response.body.data.description).to.equal(
expect(response.body.data.article.title).to.equal('new article');
expect(response.body.data.article.description).to.equal(
'this is a description'
);
expect(response.body.data.body).to.equal(
expect(response.body.data.article.body).to.equal(
'this is a description this is a description'
);
expect(response.body.data.viewsCount).to.equal(2);
expect(response.body.data.article.viewsCount).to.equal(2);
done();
});
});
Expand Down
49 changes: 49 additions & 0 deletions src/tests/helpers/average-ratings.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import sinon from 'sinon';
import sinonChai from 'sinon-chai';
import chai, { expect } from 'chai';
import averageRatings from '../../helpers/average-ratings';
import models from '../../db/models';

const { Rating } = models;

chai.use(sinonChai);

describe('Average Ratings', () => {
afterEach(() => sinon.restore());

describe('averageratings', () => {
it('get the article id', async () => {
const mockResult = {
totalNumberOfRatings: 5,
sumOfRatings: 15,
averageRating: 3
};

const allRatingsMock = {
rows: [
{
rating: 1
},
{
rating: 2
},
{
rating: 3
},
{
rating: 4
},
{
rating: 5
}
],
count: 5
};

sinon.stub(Rating, 'findAndCountAll').returns(allRatingsMock);
const result = await averageRatings(1);

expect(result).to.deep.equals(mockResult);
});
});
});
1 change: 1 addition & 0 deletions src/tests/index.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,4 @@ import './helpers/read-time.spec';
import './services/notification.service';
import './controller/reaction.spec';
import './controller/stats.spec';
import './helpers/average-ratings.spec';
3 changes: 0 additions & 3 deletions src/tests/models/article.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,6 @@ describe('src/models/article', () => {
'slug',
'isPublished',
'isDeleted',
'viewsCount',
'sumOfRating',
'numberOfRating',
'image'
].forEach(checkPropertyExists(article));
});
Expand Down

0 comments on commit 44b355a

Please sign in to comment.