-
Notifications
You must be signed in to change notification settings - Fork 7
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
1 parent
52f306e
commit 1d47424
Showing
14 changed files
with
733 additions
and
2 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 |
---|---|---|
@@ -0,0 +1,46 @@ | ||
import { getAllRatings, createRatings } from '../queries'; | ||
import status from '../config/status'; | ||
|
||
/** | ||
* A class to handle Reading Stats for users | ||
*/ | ||
export default class ReadingStat { | ||
/** | ||
* Save reading stats | ||
* @param {object} req | ||
* @param {object} res | ||
* @returns {object} stats object | ||
*/ | ||
static async create(req, res) { | ||
const userId = req.user.id; | ||
const { slug } = req.params; | ||
|
||
const saveStat = await createRatings({ | ||
userId, | ||
articleSlug: slug | ||
}); | ||
|
||
return res.status(status.OK).json({ | ||
saveStat | ||
}); | ||
} | ||
|
||
/** | ||
* Get reading stats | ||
* @param {Object} req express request | ||
* @param {Object} res express response | ||
* @returns {Array} user reading statistics | ||
*/ | ||
static async getAll(req, res) { | ||
const userId = req.user.id; | ||
|
||
const readingStats = await getAllRatings({ | ||
userId | ||
}); | ||
|
||
return res.status(status.OK).json({ | ||
message: 'Reading Stats fetched', | ||
readingStats | ||
}); | ||
} | ||
} |
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,34 @@ | ||
|
||
module.exports = { | ||
up: (queryInterface, Sequelize) => queryInterface.createTable('ReadingStats', { | ||
id: { | ||
allowNull: false, | ||
autoIncrement: true, | ||
primaryKey: true, | ||
type: Sequelize.INTEGER | ||
}, | ||
userId: { | ||
type: Sequelize.INTEGER, | ||
allowNull: true, | ||
references: { | ||
model: 'Users', | ||
key: 'id' | ||
}, | ||
onUpdate: 'CASCADE', | ||
onDelete: 'SET NULL' | ||
}, | ||
articleSlug: { | ||
type: Sequelize.STRING, | ||
allowNull: false | ||
}, | ||
createdAt: { | ||
allowNull: false, | ||
type: Sequelize.DATE | ||
}, | ||
updatedAt: { | ||
allowNull: false, | ||
type: Sequelize.DATE | ||
} | ||
}), | ||
down: (queryInterface, Sequelize) => queryInterface.dropTable('ReadingStats') | ||
}; |
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,47 @@ | ||
module.exports = (sequelize, DataTypes) => { | ||
const ReadingStat = sequelize.define( | ||
'ReadingStat', | ||
{ | ||
id: { | ||
allowNull: false, | ||
autoIncrement: true, | ||
primaryKey: true, | ||
type: DataTypes.INTEGER | ||
}, | ||
userId: { | ||
type: DataTypes.INTEGER, | ||
allowNull: false, | ||
references: { | ||
model: 'Users', | ||
key: 'id' | ||
}, | ||
onUpdate: 'CASCADE', | ||
onDelete: 'CASCADE' | ||
}, | ||
articleSlug: { | ||
type: DataTypes.STRING, | ||
allowNull: false | ||
}, | ||
createdAt: { | ||
allowNull: false, | ||
type: DataTypes.DATE | ||
}, | ||
updatedAt: { | ||
allowNull: false, | ||
type: DataTypes.DATE | ||
} | ||
}, | ||
{} | ||
); | ||
ReadingStat.associate = (models) => { | ||
ReadingStat.belongsTo(models.User, { | ||
foreignKey: 'userId', | ||
as: 'user' | ||
}); | ||
ReadingStat.belongsTo(models.Article, { | ||
foreignKey: 'articleSlug', | ||
as: 'article' | ||
}); | ||
}; | ||
return ReadingStat; | ||
}; |
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,11 @@ | ||
import db from '../../models'; | ||
|
||
/** | ||
* @param {object} data inputs data to be saved in db | ||
* @returns {object} Object representing the response returned | ||
*/ | ||
export default async (data) => { | ||
let stats = []; | ||
stats = await db.ReadingStat.create(data, { logging: false }); | ||
return stats; | ||
}; |
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,21 @@ | ||
import db from '../../models'; | ||
|
||
/** | ||
* Get user stats | ||
* @param {object} condition condition for query | ||
* @returns {object} Object representing the response returned | ||
*/ | ||
export default async (condition = {}) => db.ReadingStat.findAndCountAll({ | ||
where: condition, | ||
logging: false, | ||
include: [ | ||
{ | ||
model: db.User, | ||
as: 'user', | ||
attributes: { | ||
exclude: ['createdAt', 'updatedAt'] | ||
} | ||
} | ||
], | ||
order: [['createdAt', 'DESC']] | ||
}); |
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,4 @@ | ||
import getAllRatings from './getAll'; | ||
import createRatings from './create'; | ||
|
||
export { getAllRatings, createRatings }; |
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,18 @@ | ||
import { Router } from 'express'; | ||
import ReadingStat from '../../controllers/ReadingStatController'; | ||
import verifyToken from '../../middlewares/verifyToken'; | ||
import asyncHandler from '../../middlewares/asyncHandler'; | ||
import checkArticleBySlug from '../../middlewares/checkArticleBySlug'; | ||
|
||
const statsRouter = Router(); | ||
|
||
statsRouter.post( | ||
'/profile/:slug/stats', | ||
verifyToken, | ||
checkArticleBySlug, | ||
asyncHandler(ReadingStat.create) | ||
); | ||
|
||
statsRouter.get('/profile/stats', verifyToken, asyncHandler(ReadingStat.getAll)); | ||
|
||
export default statsRouter; |
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 |
---|---|---|
@@ -1,3 +1,4 @@ | ||
import './readingStats.test'; | ||
import './comments.test'; | ||
import './404.test'; | ||
import './auth.test'; | ||
|
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,66 @@ | ||
/* eslint-disable no-undef */ | ||
/* eslint-disable import/no-extraneous-dependencies */ | ||
import chai from 'chai'; | ||
import chaiHttp from 'chai-http'; | ||
import jwt from 'jsonwebtoken'; | ||
import * as Factory from '../../helpers/factory'; | ||
import status from '../../config/status'; | ||
import db from '../../models'; | ||
import app from '../../app'; | ||
|
||
chai.use(chaiHttp); | ||
chai.should(); | ||
let accessToken; | ||
let createdUser = {}; | ||
let createdArticle = {}; | ||
|
||
const newUser = Factory.user.build(); | ||
const newArticle = Factory.article.build(); | ||
|
||
delete newUser.id; | ||
delete newArticle.id; | ||
|
||
describe('Reading Stats', () => { | ||
before(async () => { | ||
try { | ||
await db.User.destroy({ | ||
truncate: true, | ||
cascade: true, | ||
logging: false | ||
}); | ||
|
||
createdUser = (await db.User.create(newUser, { logging: false })).dataValues; | ||
accessToken = jwt.sign( | ||
{ id: createdUser.id, role: createdUser.role, permissions: createdUser.permissions }, | ||
process.env.SECRET_KEY, | ||
{ expiresIn: '1d' } | ||
); | ||
newArticle.userId = createdUser.id; | ||
createdArticle = (await db.Article.create(newArticle, { logging: false })).dataValues; | ||
} catch (err) { | ||
throw err; | ||
} | ||
}); | ||
|
||
it('Should let the user save a reading stats', (done) => { | ||
chai | ||
.request(app) | ||
.post(`/api/v1/user/profile/${createdArticle.slug}/stats`) | ||
.set('access-token', accessToken) | ||
.end((err, res) => { | ||
res.should.have.status(status.OK); | ||
done(); | ||
}); | ||
}); | ||
|
||
it('Should let the user get reading stats', (done) => { | ||
chai | ||
.request(app) | ||
.get('/api/v1/user/profile/stats') | ||
.set('access-token', accessToken) | ||
.end((err, res) => { | ||
res.should.have.status(status.OK); | ||
done(); | ||
}); | ||
}); | ||
}); |
Oops, something went wrong.