Skip to content

Commit

Permalink
[O2B-505] Improve listTags API to accept filters (#537)
Browse files Browse the repository at this point in the history
* Builds on `listTags` to accept filters such as: `ids, texts, emails, mattermosts`
* Adds filter validation
* Returns 204 status if no data is found
* Adds corresponding tests
* Makes GET API `/api/tags/` public
  • Loading branch information
graduta authored Mar 24, 2022
1 parent 3d7e90c commit d666e71
Show file tree
Hide file tree
Showing 7 changed files with 97 additions and 30 deletions.
24 changes: 6 additions & 18 deletions lib/database/seeders/20200511151010-tags.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,24 +13,12 @@

module.exports = {
up: (queryInterface, _Sequelize) => queryInterface.bulkInsert('tags', [
{
text: 'FOOD',
},
{
text: 'RUN',
},
{
text: 'MAINTENANCE',
},
{
text: 'GLOBAL',
},
{
text: 'TEST',
},
{
text: 'OTHER',
},
{ text: 'FOOD', email: '[email protected]', mattermost: 'food' },
{ text: 'RUN', email: '[email protected]', mattermost: 'marathon' },
{ text: 'MAINTENANCE' },
{ text: 'GLOBAL' },
{ text: 'TEST' },
{ text: 'OTHER', email: '[email protected]', mattermost: 'other' },
{ text: 'TEST-TAG-1' },
{ text: 'TEST-TAG-2' },
{ text: 'TEST-TAG-3' },
Expand Down
8 changes: 8 additions & 0 deletions lib/domain/dtos/GetAllTagsDto.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,16 @@
const Joi = require('joi');
const PaginationDto = require('./PaginationDto');

const FilterDto = Joi.object({
ids: Joi.string().trim().optional(),
texts: Joi.string().trim().optional(),
emails: Joi.string().trim().optional(),
mattermosts: Joi.string().trim().optional(),
});

const QueryDto = Joi.object({
page: PaginationDto,
filter: FilterDto,
token: Joi.string(),
});

Expand Down
2 changes: 1 addition & 1 deletion lib/server/controllers/tags.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ const listTags = async (request, response, next) => {
const { query: { page: { limit = 100 } = {} } } = value;
const totalPages = Math.ceil(count / limit);

response.status(200).json({
response.status(count === 0 ? 204 : 200).json({
data: tags,
meta: {
page: {
Expand Down
1 change: 1 addition & 0 deletions lib/server/routers/tags.router.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ module.exports = {
{
method: 'get',
controller: TagsController.listTags,
args: { public: true },
},
{
method: 'post',
Expand Down
24 changes: 20 additions & 4 deletions lib/usecases/tag/GetAllTagsUseCase.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ class GetAllTagsUseCase {
async execute(dto = {}) {
const queryBuilder = new QueryBuilder();
const { query = {} } = dto;
const { page = {} } = query;
const { filter, limit = 100, offset = 0 } = page;
const { filter = {}, page = {} } = query;
const { limit = 100, offset = 0 } = page;

queryBuilder.limit(limit);
queryBuilder.offset(offset);
Expand All @@ -50,8 +50,24 @@ class GetAllTagsUseCase {
count,
rows,
} = await TransactionHelper.provide(async () => {
if (filter && filter.ids) {
queryBuilder.where('id').oneOf(...filter.ids);
if (filter) {
const { ids, texts, emails, mattermosts } = filter;
if (ids) {
const idList = ids.split(',').filter((id) => id !== '');
queryBuilder.where('id').oneOf(...idList);
}
if (texts) {
const textList = texts.split(',').filter((text) => text !== '');
queryBuilder.where('text').oneOf(...textList);
}
if (emails) {
const emailList = emails.split(',').filter((email) => email !== '');
queryBuilder.where('email').oneOf(...emailList);
}
if (mattermosts) {
const mattermostList = mattermosts.split(',').filter((mattermost) => mattermost !== '');
queryBuilder.where('mattermost').oneOf(...mattermostList);
}
}

return TagRepository.findAndCountAll(queryBuilder);
Expand Down
8 changes: 4 additions & 4 deletions test/e2e/logs.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1022,14 +1022,14 @@ module.exports = () => {
{
id: 1,
text: 'FOOD',
email: null,
mattermost: null,
email: '[email protected]',
mattermost: 'food',
},
{
id: 2,
text: 'RUN',
email: null,
mattermost: null,
email: '[email protected]',
mattermost: 'marathon',
},
]);
expect(res.body.data.rootLogId).to.equal(1);
Expand Down
60 changes: 57 additions & 3 deletions test/usecases/tag/GetAllTagsUseCase.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,69 @@
*/

const { tag: { GetAllTagsUseCase } } = require('../../../lib/usecases');
const { dtos: { GetAllTagsDto } } = require('../../../lib/domain');
const chai = require('chai');

const { expect } = chai;

module.exports = () => {
it('should return an array', async () => {
const { tags } = await new GetAllTagsUseCase()
.execute();
let getAllTagsDto;

beforeEach(async () => {
getAllTagsDto = await GetAllTagsDto.validateAsync({});
});
it('should successfully return an array with tags', async () => {
const { tags } = await new GetAllTagsUseCase().execute();

expect(tags).to.be.an('array');
});
it('should successfully return an array with tags with specified ids', async () => {
getAllTagsDto.query = { filter: { ids: '1,2' } };
const { tags } = await new GetAllTagsUseCase().execute(getAllTagsDto);

expect(tags).to.be.an('array');
expect(tags).to.have.lengthOf(2);
expect(tags[0].id).to.equal(1);
expect(tags[0].text).to.equal('FOOD');
expect(tags[1].id).to.equal(2);
expect(tags[1].text).to.equal('RUN');
});
it('should successfully return 204 status if no tag was found with specified ids', async () => {
getAllTagsDto.query = { filter: { ids: '5002' } };
const { tags } = await new GetAllTagsUseCase().execute(getAllTagsDto);

expect(tags).to.be.an('array');
expect(tags).to.have.lengthOf(0);
});
it('should successfully return an array with tags with specified texts', async () => {
getAllTagsDto.query = { filter: { texts: 'FOOD,OTHER' } };
const { tags } = await new GetAllTagsUseCase().execute(getAllTagsDto);

expect(tags).to.be.an('array');
expect(tags).to.have.lengthOf(2);
expect(tags[0].id).to.equal(1);
expect(tags[0].text).to.equal('FOOD');
expect(tags[1].id).to.equal(6);
expect(tags[1].text).to.equal('OTHER');
});
it('should successfully return an array with tags with specified emails', async () => {
getAllTagsDto.query = { filter: { emails: '[email protected]' } };
const { tags } = await new GetAllTagsUseCase().execute(getAllTagsDto);

expect(tags).to.be.an('array');
expect(tags).to.have.lengthOf(1);
expect(tags[0].id).to.equal(6);
expect(tags[0].text).to.equal('OTHER');
});
it('should successfully return an array with tags with specified mattermosts', async () => {
getAllTagsDto.query = { filter: { mattermosts: 'marathon,,food' } };
const { tags } = await new GetAllTagsUseCase().execute(getAllTagsDto);

expect(tags).to.be.an('array');
expect(tags).to.have.lengthOf(2);
expect(tags[0].id).to.equal(1);
expect(tags[0].text).to.equal('FOOD');
expect(tags[1].id).to.equal(2);
expect(tags[1].text).to.equal('RUN');
});
};

0 comments on commit d666e71

Please sign in to comment.