Skip to content

Commit 676aff4

Browse files
committed
tests: Added unit test for deworming service
1 parent 0672fe3 commit 676aff4

File tree

7 files changed

+477
-16
lines changed

7 files changed

+477
-16
lines changed

api/app.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ const createApp = () => {
3434
app.use(ormErrorHandler);
3535
app.use(boomErrorHandler);
3636
app.use(errorHandler);
37+
38+
return app;
3739
};
3840

3941
module.exports = createApp;

api/src/modules/deworming/deworming.controllers.js

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,10 @@ const dewormingService = require('./deworming.service');
44

55
const getAllDeworming = async (req, res, next) => {
66
try {
7-
const { dewormer, animalId } = req.query;
7+
const { query } = req;
88
const userId = req.user.sub;
99

10-
const filters = {
11-
...(dewormer && { dewormer }),
12-
...(animalId && { animalId }),
13-
};
14-
15-
const deworming = await dewormingService.getAllDeworming(userId, filters);
10+
const deworming = await dewormingService.getAllDeworming(userId, query);
1611

1712
res.status(200).json({ deworming, sucess: true });
1813
} catch (error) {

api/src/modules/deworming/deworming.service.js

Lines changed: 51 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
const Boom = require('@hapi/boom');
2+
const { Op } = require('sequelize');
23
const { v4: uuidv4 } = require('uuid');
34

45
const dewormingRepository = require('./deworming.repository');
@@ -9,49 +10,84 @@ const formatDeworming = (dewormer) => {
910
id: dewormer.id,
1011
dewormer: dewormer.dewormer,
1112
description: dewormer.description || null,
12-
animalId: dewormer.animal ? dewormer.animal.code : null,
13+
animal: dewormer.animal ? dewormer.animal.code : null,
1314
registeredAt:
1415
dewormer.registeredAt.toISOString().split('T')[0] ||
1516
dewormer.registeredAt,
1617
};
1718
};
1819

19-
const getAllDeworming = async (userId, filters) => {
20+
const buildFilters = (query) => {
21+
const { dewormer, animalId } = query;
22+
23+
return {
24+
...(dewormer && { dewormer: { [Op.iLike]: `%${dewormer}%` } }),
25+
...(animalId && { animalId }),
26+
};
27+
};
28+
29+
const getAllDeworming = async (userId, query) => {
30+
if (!query || typeof query !== 'object') {
31+
throw Boom.badRequest('query was not provided');
32+
}
33+
34+
const filters = buildFilters(query);
35+
2036
const deworming = await dewormingRepository.findAllDewormings(
2137
userId,
2238
filters,
2339
);
2440

41+
if (deworming?.length === 0) return [];
42+
2543
return deworming.map((d) => formatDeworming(d));
2644
};
2745

2846
const getDeworming = async (userId, dewormingId) => {
47+
if (!userId) throw Boom.badRequest('userId was not provided');
48+
if (!dewormingId) throw Boom.badRequest('dewormingId was not provided');
49+
2950
const deworming = await dewormingRepository.findOne(userId, dewormingId);
3051
if (!deworming?.id) throw Boom.notFound('Deworming does not exist');
52+
3153
return formatDeworming(deworming);
3254
};
3355

3456
const createDeworming = async (userId, dewormingData) => {
57+
if (!userId) throw Boom.badRequest('userId was not provided');
58+
if (!dewormingData?.dewormer || !dewormingData?.animalId) {
59+
throw Boom.badRequest('dewormer was not provided');
60+
}
61+
3562
const animal = await animalRepository.findOne(userId, dewormingData.animalId);
36-
if (!animal?.id)
63+
if (!animal?.id) {
3764
throw Boom.notFound('Animal does not exist or does not belong to the user');
65+
}
3866

3967
const deworming = {
4068
id: uuidv4(),
4169
dewormer: dewormingData.dewormer,
42-
description: dewormingData.description || null,
70+
description: dewormingData?.description || null,
4371
animalId: dewormingData.animalId,
4472
registeredAt:
4573
dewormingData.registeredAt || new Date().toISOString().split('T')[0],
4674
};
4775

4876
const newdeworming = await dewormingRepository.create(deworming);
49-
if (!newdeworming?.id)
77+
if (!newdeworming?.id) {
5078
throw Boom.badRequest('Something went wrong creating the deworming');
79+
}
80+
5181
return newdeworming;
5282
};
5383

5484
const updateDeworming = async (userId, dewormingId, dewormingData) => {
85+
if (!userId) throw Boom.badRequest('userId was not provided');
86+
if (!dewormingId) throw Boom.badRequest('dewormingId was not provided');
87+
if (!dewormingData?.dewormer && !dewormingData.description) {
88+
throw Boom.badRequest('dewormingData was not provided');
89+
}
90+
5591
const deworming = await dewormingRepository.findOne(userId, dewormingId);
5692
if (!deworming?.id) throw Boom.conflict('deworming does not exists');
5793

@@ -73,10 +109,19 @@ const updateDeworming = async (userId, dewormingId, dewormingData) => {
73109
};
74110

75111
const deleteDeworming = async (userId, dewormingId) => {
112+
if (!userId) throw Boom.badRequest('userId was not provided');
113+
if (!dewormingId) throw Boom.badRequest('dewormingId was not provided');
114+
76115
const deworming = await dewormingRepository.findOne(userId, dewormingId);
77116
if (!deworming?.id) throw Boom.conflict('deworming does not exists');
78117

79-
return dewormingRepository.destroy(dewormingId);
118+
const affectedRows = await dewormingRepository.destroy(dewormingId);
119+
120+
if (affectedRows === 0) {
121+
throw Boom.badRequest('Something went wrong deleting the deworming');
122+
}
123+
124+
return affectedRows;
80125
};
81126

82127
module.exports = {

api/src/modules/user/user.schemas.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ const email = Joi.string().email();
66
const password = Joi.string()
77
.min(8)
88
.max(128)
9-
.pattern('^[a-zA-Z0-9!@#$%^&*()_+\\-=\\[\\]{};\'":|,.<>\\/?]+$');
9+
.pattern(/^[a-zA-Z0-9!@#$%^&*()_+\-=:|,.<>\\/?]+$/);
1010

1111
const userEmailSchema = Joi.object({
1212
email: email.required(),

api/src/store/db/sequelize.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ const setupModels = require('./models/index');
55

66
const options = {
77
dialect: 'postgres',
8-
logging: config.isProd ? false : console.info,
8+
logging: config.isProd ? false : (msg) => console.info(msg),
99
};
1010

1111
if (config.isProd) {

tests/unit/animal-service.test.js

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,13 @@ const {
1313
} = require('../../api/src/modules/animal/animal.service');
1414
const animalRepository = require('../../api/src/modules/animal/animal.repository');
1515

16-
const { animal1, animal2, animal3 } = require('./utils/fake-data');
16+
const {
17+
animal1,
18+
animal2,
19+
animal3,
20+
user2,
21+
animal4,
22+
} = require('./utils/fake-data');
1723

1824
jest.mock('../../api/src/modules/animal/animal.repository', () => ({
1925
findAllAnimals: jest.fn(),
@@ -146,6 +152,23 @@ describe('Animal service', () => {
146152
result.forEach((animal) => expect(animal.breed).toEqual('Angus'));
147153
});
148154

155+
test('It should return an animal filtered by user2', async () => {
156+
query = {
157+
userId: user2().id,
158+
};
159+
animalRepository.findAllAnimals.mockResolvedValue([animal4()]);
160+
161+
const result = await getAllAnimals(query);
162+
163+
expect(animalRepository.findAllAnimals).toHaveBeenCalledWith(
164+
expect.objectContaining({
165+
userId: query.userId,
166+
}),
167+
);
168+
expect(result.length).toBe(1);
169+
expect(result[0].code).toBe(animal4().code);
170+
});
171+
149172
afterEach(() => {
150173
jest.clearAllMocks();
151174
});

0 commit comments

Comments
 (0)