Skip to content

Commit

Permalink
feat(sharing-article): users should be able to share an article
Browse files Browse the repository at this point in the history
- create the endpoints of social networks sharing with validation as middleware
- unit test and swagger documention

[Finishes #166789890]
  • Loading branch information
Dom58 committed Jul 22, 2019
1 parent 71dbc80 commit 77e7802
Show file tree
Hide file tree
Showing 6 changed files with 304 additions and 0 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
"node-cron": "^2.0.3",
"nodemailer": "^6.2.1",
"nyc": "^14.1.1",
"open": "^6.4.0",
"passport": "^0.4.0",
"passport-facebook": "^3.0.0",
"passport-google-oauth20": "^2.0.0",
Expand Down
66 changes: 66 additions & 0 deletions src/controllers/shareArticleController.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import open from 'open';

/**
* share article controller
*/
class ShareArticleManager {
/**
*
* @param {object} req
* @param {object} res
* @returns{object} object of response with open new email window
*/
static async shareOnEmail(req, res) {
const { title, link } = req.article;
res.status(200).send({
message: 'Article shared on E-mail',
link
});
open(`mailto:?subject=${title}&body=${link}`);
}

/**
*
* @param {object} req
* @param {object} res
* @returns{object} object of response with open new twitter window
*/
static async shareOnTwitter(req, res) {
const { link } = req.article;
res.status(200).send({
message: 'Article shared on Twitter',
link
});
open(`https://twitter.com/intent/tweet?url=${link}`);
}

/**
*
* @param {object} req
* @param {object} res
* @returns{object} object of response with open new facebook window
*/
static async shareOnFacebook(req, res) {
const { link: shareLink } = req.article;
res.status(200).send({
message: 'Post shared on Facebook',
shareLink
});
open(`https:www.facebook.com/sharer/sharer.php?u=${shareLink}`);
}

/**
*
* @param {object} req
* @param {object} res
* @returns{object} object of response with open new Whatsapp window
*/
static async shareOnWhatsapp(req, res) {
res.status(200).send({
message: 'Article shared on Whatsapp',
whatsapp: req.article.link
});
open(`https://wa.me/?text=${req.article.link}`);
}
}
export default ShareArticleManager;
22 changes: 22 additions & 0 deletions src/middlewares/articleValidation.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import Joi from '@hapi/joi';
import model from '../db/models/index';
import config from '../db/config/envirnoment';

const { Articles } = model;

Expand Down Expand Up @@ -48,5 +49,26 @@ class ArticleRatingValidation {
if (!findArticle) { return res.status(404).json({ error: 'article not found' }); }
next();
}

/**
* @param {object} req
* @param {object} res
* @param {object} next
* @returns {Object} error message
*/
static async validArticle(req, res, next) {
const { slug } = req.params;
const link = `${config.host}/articles/${slug}`;
const findOneArticle = await Articles
.findOne({ where: { slug } });
if (!findOneArticle) {
return res.status(404).send({
error: 'Article not found, please create an article first'
});
}
findOneArticle.link = link;
req.article = findOneArticle;
next();
}
}
export default ArticleRatingValidation;
6 changes: 6 additions & 0 deletions src/routes/api/articles.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import express from 'express';
import articleController from '../../controllers/articleController';
import shareArticleController from '../../controllers/shareArticleController';
import auth from '../../middlewares/auth';
import checkUser from '../../middlewares/checkUser';
import { multerUploads } from '../../middlewares/multer';
Expand All @@ -21,4 +22,9 @@ router.get('/ratings/:articleId', articleRatingControllers.ratingAverage);
router.post('/articles/like/:slug', auth.checkAuthentication, articleValidation.checkSlug, likeDislikeController.likeArticle);
router.post('/articles/dislike/:slug', auth.checkAuthentication, articleValidation.checkSlug, likeDislikeController.dislikeArticle);

router.get('/articles/:slug/email-share', auth.checkAuthentication, articleValidation.validArticle, shareArticleController.shareOnEmail);
router.get('/articles/:slug/twitter-share', auth.checkAuthentication, articleValidation.validArticle, shareArticleController.shareOnTwitter);
router.get('/articles/:slug/facebook-share', auth.checkAuthentication, articleValidation.validArticle, shareArticleController.shareOnFacebook);
router.get('/articles/:slug/whatsapp-share', auth.checkAuthentication, articleValidation.validArticle, shareArticleController.shareOnWhatsapp);

export default router;
154 changes: 154 additions & 0 deletions swagger.json
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,20 @@
"type": "string"
}
}
},
"shareArticle": {
"required": [
"token",
"slug"
],
"properties": {
"token": {
"type": "string"
},
"slug": {
"type": "string"
}
}
}
},
"paths": {
Expand Down Expand Up @@ -1187,6 +1201,146 @@
}
}
}
},
"/api/articles/{slug}/email-share": {
"get": {
"tags": [
"share article"
],
"description": "Share article on email",
"parameters": [
{
"name": "token",
"in": "header",
"description": "user token",
"required":true,
"type":"string"
},
{
"name": "slug",
"in": "path",
"description": "Article slug",
"required":true,
"type":"string"
}
],
"produces": [
"application/json"
],
"responses": {
"200": {
"description": "Sharing on Email",
"schema": {
"$ref": "#/definitions/shareArticle"
}
}
}
}
},
"/api/articles/{slug}/twitter-share": {
"get": {
"tags": [
"share article"
],
"description": "Post article on twitter",
"parameters": [
{
"name": "token",
"in": "header",
"description": "user token",
"required":true,
"type":"string"
},
{
"name": "slug",
"in": "path",
"description": "Article slug",
"required":true,
"type":"string"
}
],
"produces": [
"application/json"
],
"responses": {
"200": {
"description": "Sharing on twitter",
"schema": {
"$ref": "#/definitions/shareArticle"
}
}
}
}
},
"/api/articles/{slug}/facebook-share": {
"get": {
"tags": [
"share article"
],
"description": "Post article on facebook",
"parameters": [
{
"name": "token",
"in": "header",
"description": "user token",
"required":true,
"type":"string"
},
{
"name": "slug",
"in": "path",
"description": "Article slug",
"required":true,
"type":"string"
}
],
"produces": [
"application/json"
],
"responses": {
"200": {
"description": "Sharing on facebook",
"schema": {
"$ref": "#/definitions/shareArticle"
}
}
}
}
},
"/api/articles/{slug}/whatsapp-share": {
"get": {
"tags": [
"share article"
],
"description": "Share article on whatsapp",
"parameters": [
{
"name": "token",
"in": "header",
"description": "user token",
"required":true,
"type":"string"
},
{
"name": "slug",
"in": "path",
"description": "Article slug",
"required":true,
"type":"string"
}
],
"produces": [
"application/json"
],
"responses": {
"200": {
"description": "Sharing on whatsapp",
"schema": {
"$ref": "#/definitions/shareArticle"
}
}
}
}
}
}
}
55 changes: 55 additions & 0 deletions tests/articlesTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -213,4 +213,59 @@ describe('Article test', () => {
});
done();
});

it('Should not share an invalid article', (done) => {
chai.request(index)
.get('/api/articles/TIA-588/facebook-share')
.set('token', userToken)
.end((err, res) => {
res.body.should.be.an('object');
res.status.should.be.equal(404);
done();
});
});

it('Should post an article on facebook', (done) => {
chai.request(index)
.get('/api/articles/TIA/facebook-share')
.set('token', userToken)
.end((err, res) => {
res.body.should.be.an('object');
res.status.should.be.equal(200);
done();
});
});

it('Should share an article on email', (done) => {
chai.request(index)
.get('/api/articles/TIA/email-share')
.set('token', userToken)
.end((err, res) => {
res.body.should.be.an('object');
res.status.should.be.equal(200);
done();
});
});

it('Should share an article on twitter', (done) => {
chai.request(index)
.get('/api/articles/TIA/twitter-share')
.set('token', userToken)
.end((err, res) => {
res.body.should.be.an('object');
res.status.should.be.equal(200);
done();
});
});

it('Should post an article on whatsapp', (done) => {
chai.request(index)
.get('/api/articles/TIA/whatsapp-share')
.set('token', userToken)
.end((err, res) => {
res.body.should.be.an('object');
res.status.should.be.equal(200);
done();
});
});
});

0 comments on commit 77e7802

Please sign in to comment.