-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
166816219-feat(search): implement search feature
- create search routes - write test - create swagger documentation [Delivers #166816219]
- Loading branch information
Showing
14 changed files
with
220 additions
and
30 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
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,57 @@ | ||
import Sequelize from 'sequelize'; | ||
import db from '../../db/models'; | ||
|
||
const { Op } = Sequelize; | ||
let include = []; | ||
const setInclude = association => [...include, association]; | ||
|
||
export const tagFilter = async (req, res, next) => { | ||
const { tag } = req.query; | ||
|
||
const tagObj = { | ||
model: db.Tag, | ||
as: 'tags', | ||
}; | ||
|
||
include = setInclude( | ||
tag ? { | ||
...tagObj, | ||
where: { | ||
name: { [Op.iLike]: `%${tag}%` } | ||
} | ||
} : tagObj | ||
); | ||
return next(); | ||
}; | ||
|
||
export const authorFilter = async (req, res, next) => { | ||
const { author } = req.query; | ||
include = setInclude({ | ||
model: db.User, | ||
as: 'author', | ||
where: | ||
(author) ? { | ||
[Op.or]: [ | ||
{ firstName: { [Op.iLike]: `%${author}%` } }, | ||
{ lastName: { [Op.iLike]: `%${author}%` } }, | ||
{ username: { [Op.iLike]: `%${author}%` } } | ||
] | ||
} | ||
: {}, | ||
attributes: ['username', 'firstName', 'lastName'] | ||
}); | ||
return next(); | ||
}; | ||
|
||
export const end = async (req, res) => { | ||
const { title } = req.query; | ||
const search = await db.Article.findAll( | ||
{ | ||
where: !title ? {} : { title: { [Op.iLike]: `%${title}%` } }, | ||
include | ||
} | ||
); | ||
|
||
include = []; | ||
res.status(200).json({ search }); | ||
}; |
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
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,13 @@ | ||
import express from 'express'; | ||
import * as Search from '../../controllers/search'; | ||
import Validator from '../../validators/search'; | ||
|
||
const router = express.Router(); | ||
|
||
router.get('/', | ||
Validator.search, | ||
Search.tagFilter, | ||
Search.authorFilter, | ||
Search.end); | ||
|
||
export default router; |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
import chai from 'chai'; | ||
import chaiHttp from 'chai-http'; | ||
import { app, db } from '../../server'; | ||
import { | ||
createUser, createArticle, createTag, createArticleTag | ||
} from '../helpers'; | ||
|
||
const { expect } = chai; | ||
|
||
chai.use(chaiHttp); | ||
let user, article, newUser, newArticle, newTag = {}; | ||
describe('USER PROFILE', () => { | ||
before(async () => { | ||
await db.Article.destroy({ truncate: true, cascade: true }); | ||
user = { | ||
firstName: 'vincent', | ||
lastName: 'hamza', | ||
username: 'damy', | ||
password: '12345678', | ||
email: 'pronew@gmail.com' | ||
}; | ||
article = { | ||
title: 'React course by hamza', | ||
description: 'very good book', | ||
body: 'learning react is good for your career...' | ||
}; | ||
newUser = await createUser(user); | ||
newArticle = await createArticle({ ...article, authorId: newUser.id }); | ||
newTag = await createTag({ name: 'react' }); | ||
await createArticleTag({ articleId: newArticle.id, tagId: newTag.id }); | ||
}); | ||
after(async () => { | ||
await db.Article.destroy({ truncate: true, cascade: true }); | ||
}); | ||
describe('SEARCH', () => { | ||
it('Should not get articles if no filter is entered', async () => { | ||
const res = await chai | ||
.request(app) | ||
.get('/api/v1/search'); | ||
expect(res.body).to.be.an('object'); | ||
expect(res.body).to.include.all.keys('message'); | ||
expect(res.body.message).to.be.an('array'); | ||
}); | ||
it('Should get article with tag filter entered', async () => { | ||
const res = await chai | ||
.request(app) | ||
.get('/api/v1/search?tag=react'); | ||
expect(res.body).to.be.an('object'); | ||
expect(res.body.search).to.be.an('array'); | ||
expect(res.body.search[0]).to.be.an('object'); | ||
expect(res.body.search[0].tags[0].name).to.include('react'); | ||
}); | ||
it('Should get article with author filter entered', async () => { | ||
const res = await chai | ||
.request(app) | ||
.get('/api/v1/search?author=vincent'); | ||
expect(res.body).to.be.an('object'); | ||
expect(res.body.search).to.be.an('array'); | ||
expect(res.body.search[0]).to.be.an('object'); | ||
expect(res.body.search[0].author.username).to.include('damy'); | ||
}); | ||
it('Should get article with title filter entered', async () => { | ||
const res = await chai | ||
.request(app) | ||
.get('/api/v1/search?title=React'); | ||
expect(res.body).to.be.an('object'); | ||
expect(res.body.search).to.be.an('array'); | ||
expect(res.body.search[0]).to.be.an('object'); | ||
expect(res.body.search[0].title).to.include('React course by hamza'); | ||
}); | ||
}); | ||
}); |
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,25 @@ | ||
import { sanitize } from 'indicative'; | ||
import { messages, validatorInstance, sanitizeRules } from '../../utils'; | ||
|
||
export default { | ||
search: async (req, res, next) => { | ||
const rules = { | ||
tag: 'string', | ||
author: 'string', | ||
title: 'string|requiredWithoutAll:tag,author' | ||
}; | ||
|
||
const data = { ...req.query }; | ||
|
||
sanitize(data, sanitizeRules); | ||
try { | ||
await validatorInstance.validateAll(data, rules, messages); | ||
req.search = []; | ||
next(); | ||
} catch (e) { | ||
return res.status(400).json({ | ||
message: e, | ||
}); | ||
} | ||
} | ||
}; |