Skip to content

Commit

Permalink
Feature(Search):Searching items
Browse files Browse the repository at this point in the history
- search from users table
- search from articles table
- search by article tags

[Delivers #164489942]
  • Loading branch information
Jaman-dedy authored and Itsgracian committed Apr 18, 2019
1 parent ba3b463 commit b4bdadf
Show file tree
Hide file tree
Showing 10 changed files with 196 additions and 7 deletions.
3 changes: 1 addition & 2 deletions controllers/article.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,7 @@ class ArticleController {
article.dataValues.readingTime = readingTime(article.title + article.body);
// @return article
return res.status(200).json({ status: 200, article });
})
.catch(error => res.status(500).json({ error: `Something wrong please try again later. ${error}` }));
});
}
}

Expand Down
46 changes: 46 additions & 0 deletions controllers/search.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import Sequelize from 'sequelize';
import model from '../models/index';
import TagData from '../helpers/tags';

const { Op } = Sequelize;
// @assign model
const User = model.user;
const Article = model.article;
/**
* @param {class} --Search controller
*/
class searchController {
/**
*
* @param {Object} req
* @param {Object} res
* @returns {Object} all item related to item
*/
static async searchItem(req, res) {
// item from req.query
const { search } = req.query;
try {
// first lets search from user
const user = await User.findAll({
attributes: { exclude: ['password', 'isAdmin', 'isActivated', 'createdAt', 'updatedAt'] },
where: { username: { [Op.like]: `%${search}%` } },
include: [{ model: Article }]
});
const article = await Article.findAll({
where: { title: { [Op.like]: `%${search}%` } },
include: [{
model: User,
as: 'authorfkey',
attributes: { exclude: ['password', 'isAdmin', 'isActivated', 'createdAt', 'updatedAt'] }
}]
});
const tags = await TagData(req);
return res.status(200).json({
status: 200, user, article, tags
});
} catch (error) {
return res.status(500).json({ error: `something wrong try again later ${error}` });
}
}
}
export default searchController;
9 changes: 9 additions & 0 deletions helpers/search.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import Validator from './validateUser';

const search = (req, res, next) => {
if (Validator.isEmpty(req.query.search)) {
return res.status(400).json({ error: ' no result found.'});
}
next();
};
export default search;
24 changes: 24 additions & 0 deletions helpers/tags.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import model from '../models/index';

const Article = model.article;
const tagFetch = async (req) => {
const { search } = req.query;
const arr = [];
const taglist = [];
const tag = await Article.findAll({ attributes: ['taglist'] });
tag.forEach((element) => {
const list = element.taglist;
list.forEach((ls) => {
arr.push(ls);
});
});
// find in tags
for (let i = 0; i < arr.length; i++) {
if (arr[i].indexOf(search) !== -1) {
taglist.push(arr[i]);
}
}
return taglist;
};

export default tagFetch;
13 changes: 13 additions & 0 deletions routes/api/search.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import express from 'express';
import Search from '../../controllers/search';
import validation from '../../helpers/search';

const router = express.Router();

// @method POST
// @desc search item
// @access public

router.post('/', validation, Search.searchItem);

export default router;
2 changes: 2 additions & 0 deletions routes/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import twitterAuth from './api/auth/twitter';

import users from './api/users';
import article from './api/article';
import search from './api/search';

// @api
// @ initialize app
Expand All @@ -16,6 +17,7 @@ app.use('/api/users/auth', facebookAuth);
app.use('/api/users', twitterAuth);
app.use('/api/users', users);
app.use('/api/articles', article);
app.use('/api/search', search);
// @swagger UI
app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerDocument));
app.use('/api/users', users);
Expand Down
18 changes: 18 additions & 0 deletions test/2-user.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
signup1,
signup3,
signup4,
signup5,
login1,
login2,
login3,
Expand All @@ -29,6 +30,7 @@ let token;
describe('User ', () => {
before(async () => {
await User.destroy({ where: { email: signup1.email } });
await User.destroy({ where: { email: signup5.email } });
await User.destroy({ where: { email: 'pacifiqueclement@gmail.com' } });
await User.destroy({ where: { email: 'jeandedieuam@gmail.com' } });
});
Expand All @@ -46,6 +48,22 @@ describe('User ', () => {
done();
});
}).timeout(20000);
// @second user
it('Should create user and return status of 201', (done) => {
chai
.request(app)
.post('/api/users')
.set('Content-Type', 'application/json')
.send(signup5)
.end((err, res) => {
if (err) done(err);
res.should.have.status(201);
res.body.should.have.property('token');
res.body.should.have.property('username');
done();
});
}).timeout(50000);
//
it('Should return status of 409', (done) => {
chai
.request(app)
Expand Down
75 changes: 72 additions & 3 deletions test/3-artilcle.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@ import chai from 'chai';
import chaiHttp from 'chai-http';
import app from '../index';
import { article1 } from '../testingdata/article.json';
import { login1 } from '../testingdata/user.json';
import shareArticle from '../helpers/shareArticles';
import { login1, login4 } from '../testingdata/user.json';
import models from '../models/index';

chai.use(chaiHttp);
chai.should();
const Article = models.article;
let APItoken;
let APItoken2;
let articleId;
const facebookUrl = {
req: {
Expand Down Expand Up @@ -40,6 +41,8 @@ describe('Article', () => {
await Article.destroy({ where: { title: article1.title } });
const tokens = await chai.request(app).post('/api/users/login').set('Content-Type', 'application/json').send(login1);
APItoken = `Bearer ${tokens.body.token}`;
const login2 = await chai.request(app).post('/api/users/login').set('Content-Type', 'application/json').send(login4);
APItoken2 = `Bearer ${login2.body.token}`;
} catch (error) {
console.log(error);
}
Expand Down Expand Up @@ -142,11 +145,30 @@ describe('Article', () => {
done();
});
});
// should return status code of 403
it('Should return status code of 403', (done) => {
chai.request(app)
.put(`/api/articles/${articleId}`)
.set('Authorization', APItoken2)
.set('Content-Type', 'multipart/form-data')
.field('title', article1.title)
.field('body', article1.body)
.field('tag', article1.tag)
.attach('image', '')
.end((error, res) => {
if (error) {
done(error);
}
res.should.have.status(403);
res.body.should.have.property('error');
done();
});
});
// @should return 404
// @article not found
it('Should return status code of 404', (done) => {
chai.request(app)
.put('/api/articles/500')
.put('/api/articles/5007')
.set('Authorization', APItoken)
.set('Content-Type', 'multipart/form-data')
.field('title', article1.title)
Expand All @@ -161,6 +183,23 @@ describe('Article', () => {
done();
});
});
it('Should return status code of 500', (done) => {
chai.request(app)
.put('/api/articles/5007458674867495769456745')
.set('Authorization', APItoken)
.set('Content-Type', 'multipart/form-data')
.field('title', article1.title)
.field('body', article1.body)
.field('tag', article1.tag)
.attach('image', '')
.end((error, res) => {
if (error) {
done(error);
}
res.should.have.status(500);
done();
});
});
// @delete article
// @ return status code of 200
it('should return status code of 200 on deleting article', (done) => {
Expand Down Expand Up @@ -201,5 +240,35 @@ describe('Article', () => {
it('Should allow the user to share an articles across linkedin channel', async () => {
const result = await shareArticle.openChannelUrl(linkedUrl.req);
result.should.be.a('object');
});
});
// @search
// should return status of 400
it('Should return status code of 400', (done) => {
chai.request(app)
.post('/api/search/?search=')
.set('Content-Type', 'application/json')
.end((error, res) => {
if (error) {
done(error);
}
res.should.have.status(400);
res.body.should.have.property('error');
done();
});
});
it('Should return status code of 200', (done) => {
chai.request(app)
.post('/api/search/?search=a')
.set('Content-Type', 'application/json')
.end((error, res) => {
if (error) {
done(error);
}
res.should.have.status(200);
res.body.should.have.property('article');
res.body.should.have.property('user');
res.body.should.have.property('tags');
done();
});
});
})
2 changes: 1 addition & 1 deletion testingdata/article.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@
"article1": {
"title": "why i love javascript",
"body": " i love javascript so much?",
"tag":"laravel"
"tag":"laravel,programming"
}
}
11 changes: 10 additions & 1 deletion testingdata/user.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@
"email": "kaleb@gmail.com",
"password": "1Kig1L@20"
},
"signup5": {
"username": "gratian",
"email": "gratian@gmail.com",
"password": "1Kig1L@20"
},
"testMailer": {
"username": "badass",
"email": "badass.andela.test@gmail.com",
Expand All @@ -39,8 +44,12 @@
"login3": {
"email": "blaise@gmail.com"
},
"login4":{
"email": "gratian@gmail.com",
"password": "1Kig1L@20"
},
"googleValidToken": {
"access_token": "ya29.GlzvBsYBoHEEyCgpoljnA2IBEvb6IvbEvXUFnhGR1aakPOl0l3Kgfv6uuBtSCyRp69HeDpMbbc9pxZy1Lpy1dNUpDnwBzyI4p_WH1I_rKI3QchpiOTqDi42nxHhlOg"
"access_token": "ya29.GlvvBqe7M-RLlus5dSVWVvHjTRlsfHrqPfww-d9urRPLj0q18SMMdDcFcW4MeoY6tP0XwOSeKcjW2yzPGgqx7hL7-QgEiKnu40OdXHyPGFBt5CT2LnqKHju7Wko7"
},
"googleInvalidToken": {
"access_token": "ya29.GlvhBpzY2hl2ShgOMrpkni8obGgwyX0mr85Oendf2kmblu3BrRNTmYK2DVQiPciVOBFkLvR57YE90qDyffgJOqgzV68zutO3-Y9QDKooAPuxPvwsbsWM36wwVPHT"
Expand Down

0 comments on commit b4bdadf

Please sign in to comment.