Skip to content
This repository has been archived by the owner on May 9, 2021. It is now read-only.

Commit

Permalink
Merge b4da9ad into f5c443a
Browse files Browse the repository at this point in the history
  • Loading branch information
KvNGCzA authored Nov 12, 2018
2 parents f5c443a + b4da9ad commit 2828760
Show file tree
Hide file tree
Showing 8 changed files with 356 additions and 163 deletions.
302 changes: 151 additions & 151 deletions package-lock.json

Large diffs are not rendered by default.

32 changes: 26 additions & 6 deletions server/controllers/ArticleController.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import slugify from 'slugify';
import Sequelize from 'sequelize';

import models from '../models';
import numberOfArticles from '../helpers/numberOfArticles';

const { Article, User } = models;
const { Op } = Sequelize;
Expand Down Expand Up @@ -52,14 +53,18 @@ class ArticleController {
}

/**
* controller to fetch all articles
* @param {object} req - express request object
* @param {object} res - express response object
* @returns {void}
* @description controller to fetch all articles
* @param {object} req - request object
* @param {object} res - response object
* @returns {object} - returns all articles
*/
static fetchAllArticles(req, res) {
const { page, limit } = req.query;
const offset = (+page - 1) * +limit;
Article
.findAndCountAll({
offset,
limit,
include:
[{
model: User,
Expand All @@ -71,9 +76,24 @@ class ArticleController {
]
})
.then((result) => {
res.status(200).json({
const { rows, count } = result;
const pageCount = Math.ceil(count / +limit);
const articlesOnPage = numberOfArticles(count, +limit, +page);
if (+page > pageCount) {
return res.status(422).json({
errors: {
status: 'failure',
message: 'available number of page(s) exceeded'
}
});
}
return res.status(200).json({
status: 'success',
articles: result.rows
totalPages: pageCount,
currentPage: +page,
totalArticles: count,
articlesOnPage,
articles: rows
});
})
.catch(err => res.status(500)
Expand Down
19 changes: 19 additions & 0 deletions server/helpers/numberOfArticles.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/**
* @description controller to fetch all articles
* @param {number} count - total number of articles
* @param {number} limit - number of articles to be returned per page
* @param {number} page - current page
* @returns {number} - returns number of articles on current page
*/
const numberOfArticles = (count, limit, page) => {
let num;
const remainder = count % limit;
const lastPage = Math.ceil(count / limit);
if (remainder > 0 && page === lastPage) {
num = remainder;
return num;
}
return limit;
};

export default numberOfArticles;
55 changes: 55 additions & 0 deletions server/middlewares/ArticleValidation.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,61 @@ class ArticleValidation {
ArticleValidation.validateBody(req);
sendFormattedError(req, res, next);
}

/**
* This method validates the page query
* @param {object} req - The request object
* @returns {void}
*/
static validatePageQuery(req) {
req.checkQuery(
'page',
'please include a page query'
).exists();
req.checkQuery(
'page',
'page number must be an integer'
).isInt();
req.checkQuery(
'page',
'page number must be greater than 0'
).isInt({ gt: 0 });
}

/**
* This method validates the limit query
* @param {object} req - The request object
* @returns {void}
*/
static validateLimitQuery(req) {
req.checkQuery(
'limit',
'please include a limit query'
).exists();
req.checkQuery(
'limit',
'limit must be an integer'
).isInt();
req.checkQuery(
'limit',
'limit must be greater than 0'
).isInt({ gt: 0 });
}

/**
* @description - This method validates the article page queries.
* @param {object} req - The request object to be validated.
* @param {object} res - Th response object to be validated.
* @param {object} next - The callback function to the next middleware.
* @returns {object} - The error object with message.
* @memberOf ArticleValidators
* @static
*/
static validateQuery(req, res, next) {
ArticleValidation.validatePageQuery(req);
ArticleValidation.validateLimitQuery(req);
sendFormattedError(req, res, next, 400);
}
}

export default ArticleValidation;
5 changes: 3 additions & 2 deletions server/middlewares/UserValidation.js
Original file line number Diff line number Diff line change
Expand Up @@ -150,11 +150,12 @@ class UserValidation {
* @param {object} req - The request object to be validated.
* @param {object} res - Th response object.
* @param {object} next - The callback function to the next middleware.
* @param {number} statusCode - the status code for the error
* @returns {object} - The error object with message.
* @memberOf UserValidation
* @static
*/
static sendFormattedError(req, res, next) {
static sendFormattedError(req, res, next, statusCode) {
const newErrors = req.validationErrors();
const errors = {};
if (message.length) {
Expand All @@ -169,7 +170,7 @@ class UserValidation {
if (errors[`${err.param}`]) { errors[`${err.param}`].push(err.msg); }
});
}
if (newErrors || message.length) return res.status(422).json({ errors });
if (newErrors || message.length) return res.status(statusCode || 422).json({ errors });
if (!newErrors && !message.length) return next();
}

Expand Down
8 changes: 6 additions & 2 deletions server/routes/api/articles.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ import ArticleValidation from '../../middlewares/ArticleValidation';

const articles = express.Router();

const { validateArticleInput } = ArticleValidation;
const {
validateArticleInput,
validateQuery
} = ArticleValidation;
const {
createArticle,
getAnArticle,
Expand All @@ -17,6 +20,7 @@ articles.post('/articles', verifyToken, validateArticleInput, createArticle);

articles.get('/articles/:slug', getAnArticle);

articles.get('/articles', fetchAllArticles);
articles.get('/articles', validateQuery, fetchAllArticles);


export default articles;
80 changes: 78 additions & 2 deletions test/server/controllers/ArticleController.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -209,9 +209,9 @@ describe('Articles Controller Tests', () => {
});
});
describe('Fetch all articles', () => {
it('test /api/v1/articles route', (done) => {
it('should return paginated articles', (done) => {
chai.request(app)
.get('/api/v1/articles')
.get('/api/v1/articles?page=1&limit=10')
.end((err, res) => {
should.equal(res.body.articles[1].title, 'Valinor');
should.equal(res.body.articles[1]
Expand All @@ -224,4 +224,80 @@ describe('Fetch all articles', () => {
done();
});
});
it('should return error if page number & limit are not integers', (done) => {
chai.request(app)
.get('/api/v1/articles?page=a&limit=u')
.end((err, res) => {
res.body.should.deep.equal({
errors: {
page: [
'page number must be an integer',
'page number must be greater than 0'
],
limit: [
'limit must be an integer',
'limit must be greater than 0'
]
}
});
should.equal(res.status, 400);
done();
});
});
it('should return error if page number & limit are less than 1', (done) => {
chai.request(app)
.get('/api/v1/articles?page=0&limit=0')
.end((err, res) => {
res.body.should.deep.equal({
errors: {
page: [
'page number must be greater than 0'
],
limit: [
'limit must be greater than 0'
]
}
});
should.equal(res.status, 400);
done();
});
});
it('should return error if maximum pages are reached', (done) => {
chai.request(app)
.get('/api/v1/articles?page=9&limit=10')
.end((err, res) => {
should.equal(
res.body.errors.status,
'failure'
);
should.equal(
res.body.errors.message,
'available number of page(s) exceeded'
);
should.equal(res.status, 422);
done();
});
});
it('should return error if page & limit queries are not provided', (done) => {
chai.request(app)
.get('/api/v1/articles')
.end((err, res) => {
res.body.should.deep.equal({
errors: {
page: [
'please include a page query',
'page number must be an integer',
'page number must be greater than 0'
],
limit: [
'please include a limit query',
'limit must be an integer',
'limit must be greater than 0'
]
}
});
should.equal(res.status, 400);
done();
});
});
});
18 changes: 18 additions & 0 deletions test/server/helpers/numberOfArticles.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { assert } from 'chai';

import numberOfArticles from '../../../server/helpers/numberOfArticles';

const resultOne = numberOfArticles(32, 10, 1);
const resultTwo = numberOfArticles(28, 10, 3);
const resultThree = numberOfArticles(32, 10, 4);
describe('test numberOfArticles() function', () => {
it('should return 10', () => {
assert.equal(resultOne, 10);
});
it('should return 8', () => {
assert.equal(resultTwo, 8);
});
it('should return 2', () => {
assert.equal(resultThree, 2);
});
});

0 comments on commit 2828760

Please sign in to comment.