Skip to content

Commit 5568ba7

Browse files
committed
[add] Test cases of Team API
[fix] Enumeration compatibility bugs in Test cases Signed-off-by: TechQuery <shiy2008@gmail.com>
1 parent 19b07a5 commit 5568ba7

File tree

3 files changed

+147
-57
lines changed

3 files changed

+147
-57
lines changed

source/controller/Team.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,6 @@ export class TeamController {
9797
@ResponseSchema(Team)
9898
async updateOne(
9999
@CurrentUser() updatedBy: User,
100-
@Param('name') name: string,
101100
@Param('id') id: number,
102101
@Body() newData: Team
103102
) {
@@ -138,7 +137,10 @@ export class TeamController {
138137
@OnNull(404)
139138
@ResponseSchema(Team)
140139
getOne(@Param('id') id: number) {
141-
return store.findOneBy({ id });
140+
return store.findOne({
141+
where: { id },
142+
relations: ['createdBy', 'hackathon']
143+
});
142144
}
143145

144146
@Get()
@@ -155,7 +157,8 @@ export class TeamController {
155157
const [list, count] = await store.findAndCount({
156158
where,
157159
skip: pageSize * (pageIndex - 1),
158-
take: pageSize
160+
take: pageSize,
161+
relations: ['createdBy', 'hackathon']
159162
});
160163
return { list, count };
161164
}

source/model/Team.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,17 @@ export class Team extends HackathonBase {
2424

2525
@IsBoolean()
2626
@Column()
27-
autoApprove: boolean;
27+
@IsOptional()
28+
autoApprove?: boolean = false;
2829

2930
@IsInt()
3031
@Min(1)
3132
@VirtualColumn({
3233
query: alias =>
3334
`SELECT COUNT(*) FROM "team_member" WHERE "team_member"."teamId" = ${alias}.id`
3435
})
35-
membersCount: number;
36+
@IsOptional()
37+
membersCount?: number = 1;
3638
}
3739

3840
export abstract class TeamBase extends HackathonBase {

test/main.test.ts

Lines changed: 137 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,26 @@
11
import { Day, formatDate } from 'web-utility';
22

3-
import {
4-
AwardTarget,
5-
Hackathon,
6-
HackathonStatus,
7-
Operation,
8-
StaffType
9-
} from '../source/model';
10-
import { Award, HttpResponse, User } from './client';
3+
import { Award, Hackathon, HttpResponse, Team, User } from './client';
114
import { client, GITHUB_PAT } from './shared';
125

6+
const baseData = {
7+
id: expect.any(Number),
8+
createdAt: expect.any(String),
9+
updatedAt: expect.any(String)
10+
};
1311
let platformAdmin: User,
1412
hackathonCreator: User,
1513
testHackathon: Hackathon,
1614
teamLeader1: User,
17-
testAward: Award;
15+
testAward: Award,
16+
testTeam: Team;
1817

1918
describe('Main business logic', () => {
2019
it('should response 401 error with invalid token', async () => {
2120
try {
2221
await client.user.userControllerGetSession();
22+
23+
fail('it should have thrown a 403 error');
2324
} catch (error) {
2425
expect((error as HttpResponse<unknown>).status).toBe(401);
2526
}
@@ -101,22 +102,19 @@ describe('Main business logic', () => {
101102
it('should record 2 activities of a signed-up & edited User', async () => {
102103
const UID = hackathonCreator.id;
103104
const activityLog = {
104-
id: expect.any(Number),
105+
...baseData,
105106
tableName: 'User',
106107
recordId: UID,
107-
record: expect.any(Object),
108-
createdAt: expect.any(String),
109-
createdBy: expect.any(Object),
110-
updatedAt: expect.any(String)
108+
record: expect.any(Object)
111109
},
112110
{ data } =
113111
await client.activityLog.activityLogControllerGetUserList(UID);
114112

115113
expect(data).toMatchObject({
116114
count: 2,
117115
list: [
118-
{ ...activityLog, operation: Operation.Create },
119-
{ ...activityLog, operation: Operation.Update }
116+
{ ...activityLog, operation: 'create' },
117+
{ ...activityLog, operation: 'update' }
120118
]
121119
});
122120
});
@@ -141,8 +139,8 @@ describe('Main business logic', () => {
141139
});
142140

143141
it('should create a new hackathon by every user', async () => {
144-
const eventStartedAt = formatDate(new Date(), 'YYYY-MM-DD'),
145-
eventEndedAt = formatDate(+new Date() + Day, 'YYYY-MM-DD'),
142+
const eventStartedAt = formatDate(Date.now() - Day, 'YYYY-MM-DD'),
143+
eventEndedAt = formatDate(Date.now() + Day, 'YYYY-MM-DD'),
146144
hackathonMeta = {
147145
name: 'test-hackathon',
148146
displayName: 'Test Hackathon',
@@ -177,36 +175,30 @@ describe('Main business logic', () => {
177175
}
178176
);
179177
expect(hackathon).toMatchObject({
178+
...baseData,
180179
...hackathonMeta,
181180
autoApprove: true,
182181
readOnly: false,
183-
status: HackathonStatus.Planning,
184-
id: expect.any(Number),
185-
createdAt: expect.any(String),
186-
createdBy: expect.any(Object),
187-
updatedAt: expect.any(String)
182+
status: 'planning'
188183
});
189-
// @ts-expect-error Enum compatibility
190184
testHackathon = hackathon;
191185
});
192186

193187
it('should auto set the creator as an admin of this hackathon', async () => {
194188
const { data: staffList } =
195189
await client.hackathon.staffControllerGetList(
196190
testHackathon.name,
197-
StaffType.Admin
191+
'admin'
198192
);
199193
expect(staffList).toMatchObject({
200194
count: 1,
201195
list: [
202196
{
203-
id: expect.any(Number),
204-
type: StaffType.Admin,
197+
...baseData,
198+
type: 'admin',
205199
user: expect.any(Object),
206200
description: 'Hackathon Creator',
207-
hackathon: expect.any(Object),
208-
createdAt: expect.any(String),
209-
updatedAt: expect.any(String)
201+
hackathon: expect.any(Object)
210202
}
211203
]
212204
});
@@ -226,7 +218,6 @@ describe('Main business logic', () => {
226218
isJudge: false,
227219
isEnrolled: false
228220
});
229-
// @ts-expect-error Enum compatibility
230221
testHackathon = { ...testHackathon, ...data };
231222
delete testHackathon.roles;
232223
});
@@ -237,15 +228,13 @@ describe('Main business logic', () => {
237228

238229
const { data } = await client.hackathon.hackathonControllerUpdateOne(
239230
testHackathon.name,
240-
// @ts-expect-error Enum compatibility
241231
testHackathon,
242232
{ headers: { Authorization: `Bearer ${hackathonCreator.token}` } }
243233
);
244234
expect(data.detail).toBe(testHackathon.detail);
245235
expect(data.updatedAt).toStrictEqual(expect.any(String));
246236
expect(data.updatedBy.id).toBe(hackathonCreator.id);
247237

248-
// @ts-expect-error Enum compatibility
249238
testHackathon = { ...testHackathon, ...data };
250239
delete testHackathon.updatedBy;
251240
delete testHackathon.deletedAt;
@@ -293,14 +282,12 @@ describe('Main business logic', () => {
293282
expect(status).toBe(201);
294283

295284
expect(session).toMatchObject({
296-
id: expect.any(Number),
285+
...baseData,
297286
email: expect.any(String),
298287
name: expect.any(String),
299288
avatar: expect.any(String),
300289
password: null,
301-
token: expect.any(String),
302-
createdAt: expect.any(String),
303-
updatedAt: expect.any(String)
290+
token: expect.any(String)
304291
});
305292

306293
const { deletedAt, password, token, ...user } = session;
@@ -330,7 +317,7 @@ describe('Main business logic', () => {
330317
name: 'Best Innovation Award',
331318
description: 'Award for the most innovative project',
332319
quantity: 1,
333-
target: AwardTarget.Team,
320+
target: 'team' as const,
334321
pictures: [
335322
{
336323
name: 'award-image',
@@ -347,10 +334,8 @@ describe('Main business logic', () => {
347334
testAward = award;
348335

349336
expect(award).toMatchObject({
337+
...baseData,
350338
...awardData,
351-
id: expect.any(Number),
352-
createdAt: expect.any(String),
353-
updatedAt: expect.any(String),
354339
hackathon: expect.any(Object)
355340
});
356341
expect(award.hackathon.id).toBe(testHackathon.id);
@@ -392,6 +377,24 @@ describe('Main business logic', () => {
392377
expect(award.id).toBe(testAward.id);
393378
});
394379

380+
it('should not allow unauthorized users to manage awards', async () => {
381+
try {
382+
await client.hackathon.awardControllerCreateOne(
383+
testHackathon.name,
384+
{
385+
name: 'Unauthorized Award',
386+
description: 'Test award description',
387+
quantity: 1,
388+
target: 'team' as const,
389+
pictures: []
390+
}
391+
);
392+
fail('Should have thrown a 401 error');
393+
} catch (error) {
394+
expect((error as HttpResponse<unknown>).status).toBe(401);
395+
}
396+
});
397+
395398
it('should delete an award', async () => {
396399
await client.hackathon.awardControllerDeleteOne(
397400
testHackathon.name,
@@ -405,29 +408,109 @@ describe('Main business logic', () => {
405408
testAward.id
406409
);
407410
fail('Should have thrown a 404 error');
408-
} catch (error: unknown) {
411+
} catch (error) {
409412
expect((error as HttpResponse<unknown>).status).toBe(404);
410413
}
411414
});
412415

413-
it('should not allow unauthorized users to manage awards', async () => {
416+
it('should enroll a user in the hackathon', async () => {
417+
const { data: enrollment } =
418+
await client.hackathon.enrollmentControllerCreateOne(
419+
testHackathon.name,
420+
{ form: [] },
421+
{ headers: { Authorization: `Bearer ${teamLeader1.token}` } }
422+
);
423+
expect(enrollment).toMatchObject({
424+
...baseData,
425+
hackathon: expect.any(Object)
426+
});
427+
const { data: hackathon } =
428+
await client.hackathon.hackathonControllerGetOne(
429+
testHackathon.name
430+
);
431+
expect(hackathon.enrollment).toBe(1);
432+
});
433+
434+
it('should create a hackathon team by a participant', async () => {
435+
const newTeam = {
436+
displayName: 'New Team',
437+
description: 'A new team for the hackathon'
438+
};
439+
const { data: team } = await client.hackathon.teamControllerCreateOne(
440+
testHackathon.name,
441+
newTeam,
442+
{
443+
headers: {
444+
Authorization: `Bearer ${teamLeader1.token}`
445+
}
446+
}
447+
);
448+
expect(team).toMatchObject({ ...baseData, ...newTeam });
449+
450+
testTeam = team;
451+
delete testTeam.deletedAt;
452+
});
453+
454+
it('should get the created team by its Hackathon Name & ID', async () => {
455+
const { data: team } = await client.hackathon.teamControllerGetOne(
456+
testHackathon.name,
457+
testTeam.id
458+
);
459+
expect(team).toMatchObject({
460+
...baseData,
461+
...testTeam,
462+
createdBy: expect.any(Object),
463+
hackathon: expect.any(Object)
464+
});
465+
});
466+
467+
it('should update the team by its members', async () => {
468+
const updateData = {
469+
displayName: 'Updated Team Name',
470+
description: 'Updated team description'
471+
};
472+
const { data: team } = await client.hackathon.teamControllerUpdateOne(
473+
testHackathon.name,
474+
testTeam.id,
475+
updateData,
476+
{ headers: { Authorization: `Bearer ${teamLeader1.token}` } }
477+
);
478+
expect(team).toMatchObject({
479+
...baseData,
480+
...updateData,
481+
updatedBy: expect.any(Object)
482+
});
483+
});
484+
485+
it('should not allow unauthorized users to update a team', async () => {
414486
try {
415-
await client.hackathon.awardControllerCreateOne(
487+
await client.hackathon.teamControllerUpdateOne(
416488
testHackathon.name,
489+
testTeam.id,
417490
{
418-
name: 'Unauthorized Award',
419-
description: 'Test award description',
420-
quantity: 1,
421-
target: AwardTarget.Team,
422-
pictures: []
491+
displayName: 'Unauthorized Update',
492+
description: 'This should not be allowed'
493+
},
494+
{
495+
headers: {
496+
Authorization: `Bearer ${hackathonCreator.token}`
497+
}
423498
}
424499
);
425-
fail('Should have thrown a 401 error');
426-
} catch (error: unknown) {
427-
expect((error as HttpResponse<unknown>).status).toBe(401);
500+
fail('it should have thrown a 403 error');
501+
} catch (error) {
502+
expect((error as HttpResponse<unknown>).status).toBe(403);
428503
}
429504
});
430505

506+
it('should get the list of teams in the hackathon', async () => {
507+
const { data: teamList } = await client.hackathon.teamControllerGetList(
508+
testHackathon.name
509+
);
510+
expect(teamList.count).toBe(1);
511+
expect(teamList.list[0].id).toBe(testTeam.id);
512+
});
513+
431514
it('should delete a hackathon by its admin', async () => {
432515
const { name } = testHackathon;
433516
const { status, data } =
@@ -439,6 +522,8 @@ describe('Main business logic', () => {
439522

440523
try {
441524
await client.hackathon.hackathonControllerGetOne(name);
525+
526+
fail('it should have thrown a 403 error');
442527
} catch (error) {
443528
expect((error as HttpResponse<unknown>).status).toBe(404);
444529
}

0 commit comments

Comments
 (0)