Skip to content

Commit e281a5e

Browse files
committed
tests: Added e2e testing for card endpoints
1 parent b49d710 commit e281a5e

File tree

4 files changed

+204
-10
lines changed

4 files changed

+204
-10
lines changed

api/src/application/use-cases/card/UpdateCardUseCase.js

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,28 @@ class UpdateCardUseCase {
1010

1111
async execute(cardId, cardData) {
1212
if (!cardId) throw new Error('cardId was not provided');
13-
if (!cardData) throw new Error('cardData was not provided');
13+
if (!cardData?.newName && !cardData?.description) {
14+
throw new Error('cardData was not provided');
15+
}
1416

15-
const cardName = new CardName(cardData.newName).value;
16-
const cardDescription = new CardDescription(cardData.description).value;
17+
let cardName = null;
18+
let cardDescription = null;
19+
20+
if (cardData?.newName) {
21+
cardName = new CardName(cardData.newName).value;
22+
}
23+
if (cardData?.description) {
24+
cardDescription = new CardDescription(cardData.description).value;
25+
}
26+
27+
const changes = {
28+
...(cardName && { name: cardName }),
29+
...(cardDescription && { description: cardDescription }),
30+
};
1731

1832
const [updatedRows, [updatedCard]] = await this.cardRepository.update(
1933
cardId,
20-
{ name: cardName, description: cardDescription },
34+
changes,
2135
);
2236
if (updatedRows === 0) throw boom.badRequest('Zero rows updated');
2337
return new CardDto(updatedCard);

api/src/interfaces/schemas/card.schema.js

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,15 @@
11
const Joi = require('joi');
22

33
const id = Joi.string().uuid();
4-
const name = Joi.string().min(3).max(50);
4+
const name = Joi.string()
5+
.min(3)
6+
.max(80)
7+
.pattern(/^[A-Za-z0-9 ]+$/)
8+
.messages({
9+
'string.pattern.base':
10+
'The name can only contain letters, numbers and spaces.',
11+
});
512
const description = Joi.string().max(255);
6-
const newName = Joi.string().min(3).max(50);
713

814
const cardIdSchema = Joi.object({
915
cardId: id.required(),
@@ -20,7 +26,7 @@ const createCardSchema = Joi.object({
2026
});
2127

2228
const updateCardSchema = Joi.object({
23-
newName: newName.required(),
29+
newName: name.optional(),
2430
description,
2531
});
2632

tests/e2e/cards.e2e.js

Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
const request = require('supertest');
2+
3+
const createApp = require('../../api/app');
4+
const { models } = require('../../api/src/infrastructure/store/db/sequelize');
5+
const { upSeed, downSeed } = require('./utils/umzug');
6+
7+
describe('tests for list endpoints', () => {
8+
let accessTokenUser1 = null;
9+
let accessTokenUser2 = null;
10+
let accessTokenUser4 = null;
11+
let list = null;
12+
let card = null;
13+
14+
let app = null;
15+
let server = null;
16+
let api = null;
17+
18+
beforeAll(async () => {
19+
app = createApp();
20+
server = app.listen(9000);
21+
api = request(app);
22+
23+
await upSeed();
24+
25+
const userData = {
26+
email: 'user1@email.com',
27+
password: 'Admin123@',
28+
};
29+
const { body } = await api.post('/api/v1/auth/login').send(userData);
30+
accessTokenUser1 = body.accessToken;
31+
32+
list = await models.List.findByPk('7f210809-184f-449d-8cb6-7bdca222201a');
33+
card = await models.Card.findByPk('4600a009-a471-4416-bf24-e857d23d2ab3');
34+
35+
const { body: authLogin } = await api
36+
.post('/api/v1/auth/login')
37+
.send({ email: 'user2@email.com', password: 'Customer123@' });
38+
accessTokenUser2 = authLogin.accessToken;
39+
40+
const { body: authLogin4 } = await api
41+
.post('/api/v1/auth/login')
42+
.send({ email: 'user4@email.com', password: 'Customer123@' });
43+
44+
accessTokenUser4 = authLogin4.accessToken;
45+
});
46+
47+
describe('GET /lists/{listId}/cards/{cardId}/information', () => {
48+
test('It should return all the information that belongs to a specific card', async () => {
49+
const { statusCode, body } = await api
50+
.get(`/api/v1/lists/${list.id}/cards/${card.id}/information`)
51+
.set({ Authorization: `Bearer ${accessTokenUser1}` });
52+
53+
expect(statusCode).toEqual(200);
54+
expect(Array.isArray(body.card.labels)).toBeTruthy();
55+
expect(Array.isArray(body.card.cardMembers)).toBeTruthy();
56+
expect(Array.isArray(body.card.attachments)).toBeTruthy();
57+
expect(Array.isArray(body.card.checklists)).toBeTruthy();
58+
expect(body.card.listId).toBe(list.id);
59+
});
60+
61+
test('It should return an error because the requester does not belong to the project', async () => {
62+
const { statusCode } = await api
63+
.get(`/api/v1/lists/${list.id}/cards/${card.id}/information`)
64+
.set({ Authorization: `Bearer ${accessTokenUser4}` });
65+
66+
expect(statusCode).toEqual(403);
67+
});
68+
});
69+
70+
describe('GET /lists/{listId}/cards', () => {
71+
test('It should return all the cards from a specific list', async () => {
72+
const { statusCode, body } = await api
73+
.get(`/api/v1/lists/${list.id}/cards`)
74+
.set({ Authorization: `Bearer ${accessTokenUser1}` });
75+
76+
expect(statusCode).toEqual(200);
77+
expect(body.cards[0].listId).toBe(list.id);
78+
});
79+
80+
test('It should return an error because the list does not exist', async () => {
81+
const { statusCode } = await api
82+
.get(`/api/v1/lists/4600a009-a471-4416-bf24-e857d23d2ab3/cards`)
83+
.set({ Authorization: `Bearer ${accessTokenUser1}` });
84+
85+
expect(statusCode).toEqual(404);
86+
});
87+
});
88+
89+
describe('POST /lists/{listId}/cards', () => {
90+
let inputBody = null;
91+
92+
beforeEach(() => {
93+
inputBody = {
94+
name: 'list 4',
95+
};
96+
});
97+
98+
test('It should return a created card', async () => {
99+
const { statusCode, body } = await api
100+
.post(`/api/v1/lists/${list.id}/cards`)
101+
.send(inputBody)
102+
.set({ Authorization: `Bearer ${accessTokenUser1}` });
103+
104+
expect(statusCode).toEqual(201);
105+
expect(body.newCard.id).toBeTruthy();
106+
expect(body.newCard.name).toEqual(inputBody.name);
107+
});
108+
109+
test('It should return an error because the name is invalid', async () => {
110+
inputBody.name = 'New name 15 @!**';
111+
112+
const { statusCode } = await api
113+
.post(`/api/v1/lists/${list.id}/cards`)
114+
.send(inputBody)
115+
.set({ Authorization: `Bearer ${accessTokenUser1}` });
116+
expect(statusCode).toEqual(400);
117+
});
118+
});
119+
120+
describe('PATCH /lists/{listId}/cards/{cardId}', () => {
121+
let inputBody = null;
122+
123+
beforeEach(() => {
124+
inputBody = {
125+
newName: 'In progress 4',
126+
};
127+
});
128+
129+
test('It should return an updated card', async () => {
130+
const { statusCode, body } = await api
131+
.patch(`/api/v1/lists/${list.id}/cards/${card.id}`)
132+
.send(inputBody)
133+
.set({ Authorization: `Bearer ${accessTokenUser1}` });
134+
expect(statusCode).toEqual(200);
135+
expect(body.updatedCard.id).toBe(card.id);
136+
expect(body.updatedCard.name).not.toEqual(card.name);
137+
});
138+
139+
test('It should return an error because the cardId does not belong to the list.', async () => {
140+
const { statusCode } = await api
141+
.patch(
142+
`/api/v1/lists/${list.id}/cards/57f74c73-e129-4d18-a319-cceae505ce47`,
143+
)
144+
.send(inputBody)
145+
.set({ Authorization: `Bearer ${accessTokenUser2}` });
146+
expect(statusCode).toEqual(404);
147+
});
148+
});
149+
150+
describe('DELETE /lists/{listId}/cards/{cardId}', () => {
151+
test('It should return an error because the card was not found', async () => {
152+
const { statusCode } = await api
153+
.delete(
154+
`/api/v1/lists/${list.id}/cards/57f74c73-e129-4d18-a319-cceae505ce47`,
155+
)
156+
.set({ Authorization: `Bearer ${accessTokenUser2}` });
157+
expect(statusCode).toEqual(404);
158+
});
159+
160+
test('It should return an success message', async () => {
161+
const { statusCode, body } = await api
162+
.delete(`/api/v1/lists/${list.id}/cards/${card.id}`)
163+
.set({ Authorization: `Bearer ${accessTokenUser2}` });
164+
165+
expect(statusCode).toEqual(200);
166+
expect(body.message).toMatch(/successfully|deleted/);
167+
});
168+
});
169+
170+
afterAll(async () => {
171+
await downSeed();
172+
server.close();
173+
});
174+
});

tests/e2e/lists.e2e.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ describe('tests for list endpoints', () => {
8484
};
8585
});
8686

87-
test('It should return a created workspace without description', async () => {
87+
test('It should return a created list', async () => {
8888
const { statusCode, body } = await api
8989
.post(`/api/v1/workspaces/${workspace.id}/projects/${project.id}/lists`)
9090
.send(inputBody)
@@ -115,7 +115,7 @@ describe('tests for list endpoints', () => {
115115
};
116116
});
117117

118-
test('It should return an updated workspace without description', async () => {
118+
test('It should return an updated list', async () => {
119119
const { statusCode, body } = await api
120120
.patch(
121121
`/api/v1/workspaces/${workspace.id}/projects/${project.id}/lists/${list.id}`,
@@ -141,7 +141,7 @@ describe('tests for list endpoints', () => {
141141
});
142142

143143
describe('DELETE /workspaces/{workspaceId}/projects/{projectId}/lists/{listId}', () => {
144-
test('It should return an error because the user(member role) does not have permissions to delete the workspace', async () => {
144+
test('It should return an error because the user(member role) does not have permissions to delete the list', async () => {
145145
const { statusCode } = await api
146146
.delete(
147147
`/api/v1/workspaces/${workspace.id}/projects/${project.id}/lists/${list.id}`,

0 commit comments

Comments
 (0)