From d12e2f8dc2c2d680f576666593fb437efa15f852 Mon Sep 17 00:00:00 2001 From: Georgi Parlakov Date: Sun, 29 Sep 2024 10:58:12 +0300 Subject: [PATCH] chore: add tests for campaign application file fetch --- .../campaign-application.service.spec.ts | 81 +++++++++++++++++++ apps/api/src/email/template.interface.ts | 3 +- 2 files changed, 82 insertions(+), 2 deletions(-) diff --git a/apps/api/src/campaign-application/campaign-application.service.spec.ts b/apps/api/src/campaign-application/campaign-application.service.spec.ts index a157126a..09cbdda2 100644 --- a/apps/api/src/campaign-application/campaign-application.service.spec.ts +++ b/apps/api/src/campaign-application/campaign-application.service.spec.ts @@ -46,6 +46,7 @@ describe('CampaignApplicationService', () => { const mockS3Service = { uploadObject: jest.fn(), deleteObject: jest.fn(), + streamFile: jest.fn().mockResolvedValue(1234), } const mockEmailService = { @@ -290,6 +291,18 @@ describe('CampaignApplicationService', () => { expect(result).toEqual(mockSingleCampaignApplication) expect(prismaMock.campaignApplication.findUnique).toHaveBeenCalledTimes(1) + expect(prismaMock.campaignApplication.findUnique).toHaveBeenCalledWith({ + where: { id: 'id' }, + include: { + documents: { + select: { + id: true, + filename: true, + mimetype: true, + }, + }, + }, + }) }) it('should throw a NotFoundException if no campaign-application is found', async () => { @@ -422,4 +435,72 @@ describe('CampaignApplicationService', () => { }) }) }) + + describe('getFile', () => { + it('should return a single campaign-application file', async () => { + prismaMock.campaignApplication.findFirst.mockResolvedValue(mockSingleCampaignApplication) + prismaMock.campaignApplicationFile.findFirst.mockResolvedValue({ + id: '123', + filename: 'my-file', + } as File) + + const result = await service.getFile('id', false, mockPerson) + + expect(result).toEqual({ + filename: 'my-file', + stream: 1234, + }) + expect(prismaMock.campaignApplication.findFirst).toHaveBeenCalledTimes(1) + expect(prismaMock.campaignApplication.findFirst).toHaveBeenCalledWith({ + where: { + documents: { + some: { + id: 'id', + }, + }, + }, + }) + + expect(prismaMock.campaignApplicationFile.findFirst).toHaveBeenNthCalledWith(1, { + where: { id: 'id' }, + }) + }) + + it('should throw a NotFoundException if no campaign-application is found', async () => { + prismaMock.campaignApplication.findUnique.mockResolvedValue(null) + + await expect(service.getFile('id', false, mockPerson)).rejects.toThrow( + new NotFoundException('File does not exist'), + ) + }) + + it('should handle errors and throw an exception', async () => { + const errorMessage = 'error' + prismaMock.campaignApplication.findFirst.mockRejectedValue(new Error(errorMessage)) + + await expect(service.getFile('id', false, mockPerson)).rejects.toThrow(errorMessage) + }) + + it('should not allow non-admin users to see files belonging to other users', async () => { + prismaMock.campaignApplication.findFirst.mockResolvedValue(mockSingleCampaignApplication) + await expect( + service.getFile('id', false, { ...mockPerson, organizer: { id: 'different-id' } }), + ).rejects.toThrow( + new ForbiddenException('User is not admin or organizer of the campaignApplication'), + ) + }) + + it('should allow admin users to see files belonging to other users', async () => { + prismaMock.campaignApplication.findFirst.mockResolvedValue(mockSingleCampaignApplication) + prismaMock.campaignApplicationFile.findFirst.mockResolvedValue({ + id: '123', + filename: 'my-file', + } as File) + await expect( + service.getFile('id', true, { ...mockPerson, organizer: { id: 'different-id' } }), + ).resolves.not.toThrow( + new ForbiddenException('User is not admin or organizer of the campaignApplication'), + ) + }) + }) }) diff --git a/apps/api/src/email/template.interface.ts b/apps/api/src/email/template.interface.ts index 12059d83..f3a44594 100644 --- a/apps/api/src/email/template.interface.ts +++ b/apps/api/src/email/template.interface.ts @@ -113,7 +113,6 @@ export class CreateCampaignApplicationAdminEmailDto extends EmailTemplate<{ name = TemplateType.createCampaignApplicationAdmin } - export class CreateCampaignApplicationOrganizerEmailDto extends EmailTemplate<{ campaignApplicationName: string editLink?: string @@ -122,4 +121,4 @@ export class CreateCampaignApplicationOrganizerEmailDto extends EmailTemplate<{ firstName: string }> { name = TemplateType.createCampaignApplicationOrganizer -} \ No newline at end of file +}