-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
14 changed files
with
268 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -136,6 +136,9 @@ class ArticleController { | |
'totalClaps', | ||
'createdAt', | ||
'updatedAt' | ||
], | ||
order: [ | ||
['id', 'ASC'], | ||
] | ||
}; | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
import dotenv from 'dotenv'; | ||
import db from '../database/models'; | ||
import { response } from '../utils'; | ||
|
||
const { Article, ArticleClap } = db; | ||
dotenv.config(); | ||
|
||
/** | ||
* @description Class to implement clap and unclap | ||
*/ | ||
export default class ArticleClapToggle { | ||
/** | ||
* @description claps and retrieves claap from articles | ||
* @param {object} req | ||
* @param {object} res | ||
* @returns {object} response object | ||
*/ | ||
static async clapToggle(req, res) { | ||
const { id } = req.user; | ||
const { slug } = req.params; | ||
|
||
const getArticle = await Article.findOne({ where: { slug } }); | ||
|
||
if (!getArticle) response(res).notFound({ message: 'article not found' }); | ||
|
||
else if (getArticle.userId === id) response(res).forbidden({ message: 'you cannot rate your own article' }); | ||
|
||
else { | ||
const clap = await ArticleClap.findOrCreate({ | ||
where: { userId: id, articleId: getArticle.id }, | ||
defaults: { clap: true } | ||
}); | ||
|
||
if (clap[1] === true) response(res).created({ message: 'you just clapped for this article' }); | ||
|
||
else { | ||
await ArticleClap.destroy({ | ||
where: { userId: id, articleId: getArticle.id } | ||
}); | ||
|
||
response(res).success({ message: 'you just retrieved your clap' }); | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
30 changes: 30 additions & 0 deletions
30
server/database/migrations/20190305175826-create-article-clap.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
/* eslint no-unused-vars: "off" */ | ||
|
||
module.exports = { | ||
up: (queryInterface, Sequelize) => queryInterface.createTable('ArticleClaps', { | ||
id: { | ||
allowNull: false, | ||
autoIncrement: true, | ||
primaryKey: true, | ||
type: Sequelize.INTEGER | ||
}, | ||
userId: { | ||
type: Sequelize.INTEGER | ||
}, | ||
articleId: { | ||
type: Sequelize.INTEGER | ||
}, | ||
clap: { | ||
type: Sequelize.BOOLEAN | ||
}, | ||
createdAt: { | ||
allowNull: false, | ||
type: Sequelize.DATE | ||
}, | ||
updatedAt: { | ||
allowNull: false, | ||
type: Sequelize.DATE | ||
} | ||
}), | ||
down: (queryInterface, Sequelize) => queryInterface.dropTable('ArticleClaps') | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
export default (sequelize, DataTypes) => { | ||
const ArticleClap = sequelize.define('ArticleClap', { | ||
userId: { | ||
type: DataTypes.INTEGER, | ||
allowNull: false | ||
}, | ||
articleId: { | ||
type: DataTypes.INTEGER, | ||
allowNull: false | ||
}, | ||
clap: { | ||
type: DataTypes.BOOLEAN, | ||
} | ||
}, {}); | ||
ArticleClap.associate = (models) => { | ||
// associations can be defined here | ||
const { User, Article } = models; | ||
|
||
ArticleClap.belongsTo(User, { | ||
foreignKey: 'userId', | ||
onDelete: 'CASCADE' | ||
}); | ||
|
||
ArticleClap.belongsTo(Article, { | ||
foreignKey: 'articleId', | ||
onDelete: 'CASCADE' | ||
}); | ||
}; | ||
return ArticleClap; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import express from 'express'; | ||
import { ArticleClap } from '../controllers'; | ||
import { AuthenticateUser } from '../middlewares'; | ||
|
||
const articleClapRoute = express.Router(); | ||
|
||
// Article toggle route | ||
articleClapRoute.post('/articles/:slug/clapToggle', AuthenticateUser.verifyUser, ArticleClap.clapToggle); | ||
|
||
export default articleClapRoute; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
import chaiHttp from 'chai-http'; | ||
import chai, { expect } from 'chai'; | ||
import dotenv from 'dotenv'; | ||
import app from '../app'; | ||
|
||
dotenv.config(); | ||
|
||
|
||
const articleURL = '/api/articles'; | ||
const signupURL = '/api/users'; | ||
let userToken; | ||
let secondUserToken; | ||
let anArticleSlug = ''; | ||
const data = { | ||
firstUser: { | ||
firstname: 'John', | ||
lastname: 'Doe', | ||
email: 'obiora44@gmail.com', | ||
username: 'john466', | ||
password: '1234567122' | ||
}, | ||
secondUser: { | ||
firstname: 'adaeze', | ||
lastname: 'Doe', | ||
email: 'adaezeboo@gmail.com', | ||
username: 'john500', | ||
password: '1234536719' | ||
}, | ||
createArticle: { | ||
title: 'some title', | ||
description: 'some weird talk', | ||
body: 'article body' | ||
} | ||
}; | ||
|
||
chai.use(chaiHttp); | ||
|
||
describe('Clap endpoint test', () => { | ||
// SignUp first user | ||
before('should create user', (done) => { | ||
chai | ||
.request(app) | ||
.post(signupURL) | ||
.send(data.firstUser) | ||
.end((err, res) => { | ||
userToken = res.body.user.token; | ||
done(); | ||
}); | ||
}); | ||
// SignUp second user | ||
before('should create user', (done) => { | ||
chai | ||
.request(app) | ||
.post(signupURL) | ||
.send(data.secondUser) | ||
.end((err, res) => { | ||
secondUserToken = res.body.user.token; | ||
done(); | ||
}); | ||
}); | ||
// Create article | ||
|
||
it('should create an article', (done) => { | ||
chai | ||
.request(app) | ||
.post(articleURL) | ||
.set('Authorization', `Bearer ${userToken}`) | ||
.send(data.createArticle) | ||
.end((err, res) => { | ||
anArticleSlug = res.body.article.slug; | ||
done(); | ||
}); | ||
}); | ||
// Test for article not found | ||
it('should return 404 for article not found', (done) => { | ||
chai | ||
.request(app) | ||
.post(`${articleURL}/somenewarticleSlug/clapToggle`) | ||
.set('Authorization', `Bearer ${secondUserToken}`) | ||
.end((err, res) => { | ||
expect(res.status).to.equal(404); | ||
expect(res.body.message).to.be.a('string'); | ||
expect(res.body.message).to.equal('article not found'); | ||
done(); | ||
}); | ||
}); | ||
|
||
// Test article clap | ||
it('should like an article and return 200', (done) => { | ||
chai | ||
.request(app) | ||
.post(`${articleURL}/${anArticleSlug}/clapToggle`) | ||
.set('Authorization', `Bearer ${secondUserToken}`) | ||
.end((err, res) => { | ||
expect(res.status).to.equal(201); | ||
expect(res.body.message).to.be.a('string'); | ||
expect(res.body.message).to.equal('you just clapped for this article'); | ||
done(); | ||
}); | ||
}); | ||
|
||
// Test for article belonging to the user | ||
it('user should be unable to clap for own article', (done) => { | ||
chai | ||
.request(app) | ||
.post(`${articleURL}/${anArticleSlug}/clapToggle`) | ||
.set('Authorization', `Bearer ${userToken}`) | ||
.end((err, res) => { | ||
expect(res.status).to.equal(403); | ||
expect(res.body.message).to.be.a('string'); | ||
expect(res.body.message).to.equal('you cannot rate your own article'); | ||
done(); | ||
}); | ||
}); | ||
|
||
// Test clap retrieval | ||
it('should retrieve clap from an article and return 200', (done) => { | ||
chai | ||
.request(app) | ||
.post(`${articleURL}/${anArticleSlug}/clapToggle`) | ||
.set('Authorization', `Bearer ${secondUserToken}`) | ||
.end((err, res) => { | ||
expect(res.status).to.equal(200); | ||
expect(res.body.message).to.be.a('string'); | ||
expect(res.body.message).to.equal('you just retrieved your clap'); | ||
done(); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters