From c3f3601d84f58399cc6b84c411ab2c7fb903875e Mon Sep 17 00:00:00 2001 From: entholzer Date: Sun, 1 Dec 2024 10:17:25 +0100 Subject: [PATCH] fix tests and improve coverage --- .../AttachmentResourceIntegrationTest.java | 8 +- .../attachment-unit.component.spec.ts | 4 +- .../shared/http/file.service.spec.ts | 154 ++++++++++++++++++ 3 files changed, 162 insertions(+), 4 deletions(-) diff --git a/src/test/java/de/tum/cit/aet/artemis/lecture/AttachmentResourceIntegrationTest.java b/src/test/java/de/tum/cit/aet/artemis/lecture/AttachmentResourceIntegrationTest.java index 001b2ea8cda3..1bae5e4927f6 100644 --- a/src/test/java/de/tum/cit/aet/artemis/lecture/AttachmentResourceIntegrationTest.java +++ b/src/test/java/de/tum/cit/aet/artemis/lecture/AttachmentResourceIntegrationTest.java @@ -1,5 +1,6 @@ package de.tum.cit.aet.artemis.lecture; +import static org.apache.velocity.shaded.commons.io.FilenameUtils.getExtension; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.verify; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; @@ -69,8 +70,11 @@ void initTestCase() { void createAttachment() throws Exception { Attachment actualAttachment = request.postWithMultipartFile("/api/attachments", attachment, "attachment", new MockMultipartFile("file", "test.txt", MediaType.TEXT_PLAIN_VALUE, "testContent".getBytes()), Attachment.class, HttpStatus.CREATED); - assertThat(actualAttachment.getLink()).isNotNull(); - MvcResult file = request.performMvcRequest(get(actualAttachment.getLink())).andExpect(status().isOk()).andExpect(content().contentType(MediaType.TEXT_PLAIN_VALUE)) + String actualLink = actualAttachment.getLink(); + assertThat(actualLink).isNotNull(); + // getLectureAttachment uses the provided file name to fetch the attachment which has that attachment name (not filename) + String linkWithCorrectFileName = actualLink.substring(0, actualLink.lastIndexOf('/') + 1) + attachment.getName() + "." + getExtension(actualAttachment.getLink()); + MvcResult file = request.performMvcRequest(get(linkWithCorrectFileName)).andExpect(status().isOk()).andExpect(content().contentType(MediaType.TEXT_PLAIN_VALUE)) .andReturn(); assertThat(file.getResponse().getContentAsByteArray()).isNotEmpty(); var expectedAttachment = attachmentRepository.findById(actualAttachment.getId()).orElseThrow(); diff --git a/src/test/javascript/spec/component/lecture-unit/attachment-unit/attachment-unit.component.spec.ts b/src/test/javascript/spec/component/lecture-unit/attachment-unit/attachment-unit.component.spec.ts index a65980b3725a..287b08031ac1 100644 --- a/src/test/javascript/spec/component/lecture-unit/attachment-unit/attachment-unit.component.spec.ts +++ b/src/test/javascript/spec/component/lecture-unit/attachment-unit/attachment-unit.component.spec.ts @@ -82,7 +82,7 @@ describe('AttachmentUnitComponent', () => { }); it('should handle download', () => { - const downloadFileSpy = jest.spyOn(fileService, 'downloadFile'); + const downloadFileSpy = jest.spyOn(fileService, 'downloadFileByAttachmentName'); const onCompletionEmitSpy = jest.spyOn(component.onCompletion, 'emit'); fixture.detectChanges(); @@ -113,7 +113,7 @@ describe('AttachmentUnitComponent', () => { }); it('should download attachment when clicked', () => { - const downloadFileSpy = jest.spyOn(fileService, 'downloadFile'); + const downloadFileSpy = jest.spyOn(fileService, 'downloadFileByAttachmentName'); fixture.detectChanges(); diff --git a/src/test/javascript/spec/component/shared/http/file.service.spec.ts b/src/test/javascript/spec/component/shared/http/file.service.spec.ts index 68a2b56a7faf..843fd61a12d3 100644 --- a/src/test/javascript/spec/component/shared/http/file.service.spec.ts +++ b/src/test/javascript/spec/component/shared/http/file.service.spec.ts @@ -3,6 +3,7 @@ import { HttpTestingController, provideHttpClientTesting } from '@angular/common import { TestBed } from '@angular/core/testing'; import { v4 as uuid } from 'uuid'; import { provideHttpClient } from '@angular/common/http'; +import { ProgrammingLanguage, ProjectType } from 'app/entities/programming/programming-exercise.model'; jest.mock('uuid', () => ({ v4: jest.fn(), @@ -77,4 +78,157 @@ describe('FileService', () => { expect(v4Mock).toHaveBeenCalledTimes(3); }); }); + + describe('getTemplateFile', () => { + it('should fetch the template file without project type', () => { + const language = ProgrammingLanguage.JAVA; + const expectedUrl = `api/files/templates/JAVA`; + const response = 'template content'; + + fileService.getTemplateFile(language).subscribe((data) => { + expect(data).toEqual(response); + }); + + const req = httpMock.expectOne({ + url: expectedUrl, + method: 'GET', + }); + expect(req.request.responseType).toBe('text'); + req.flush(response); + }); + + it('should fetch the template file with project type', () => { + const language = ProgrammingLanguage.JAVA; + const projectType = ProjectType.PLAIN_MAVEN; + const expectedUrl = `api/files/templates/JAVA/PLAIN_MAVEN`; + const response = 'template content'; + + fileService.getTemplateFile(language, projectType).subscribe((data) => { + expect(data).toEqual(response); + }); + + const req = httpMock.expectOne({ + url: expectedUrl, + method: 'GET', + }); + expect(req.request.responseType).toBe('text'); + req.flush(response); + }); + }); + + describe('downloadMergedFile', () => { + it('should download the merged PDF file', () => { + const lectureId = 123; + const expectedUrl = `api/files/attachments/lecture/${lectureId}/merge-pdf`; + const blobResponse = new Blob(['PDF content'], { type: 'application/pdf' }); + + fileService.downloadMergedFile(lectureId).subscribe((response) => { + expect(response.body).toEqual(blobResponse); + expect(response.status).toBe(200); + }); + + const req = httpMock.expectOne({ + url: expectedUrl, + method: 'GET', + }); + expect(req.request.responseType).toBe('blob'); + req.flush(blobResponse, { status: 200, statusText: 'OK' }); + }); + }); + + describe('getAeolusTemplateFile', () => { + it('should fetch the aeolus template file with all parameters', () => { + const language = ProgrammingLanguage.PYTHON; + const projectType = ProjectType.PLAIN; + const staticAnalysis = true; + const sequentialRuns = false; + const coverage = true; + const expectedUrl = `api/files/aeolus/templates/PYTHON/PLAIN?staticAnalysis=true&sequentialRuns=false&testCoverage=true`; + const response = 'aeolus template content'; + + fileService.getAeolusTemplateFile(language, projectType, staticAnalysis, sequentialRuns, coverage).subscribe((data) => { + expect(data).toEqual(response); + }); + + const req = httpMock.expectOne({ + url: expectedUrl, + method: 'GET', + }); + expect(req.request.responseType).toBe('text'); + req.flush(response); + }); + + it('should fetch the aeolus template file with missing optional parameters', () => { + const expectedUrl = `api/files/aeolus/templates/PYTHON?staticAnalysis=false&sequentialRuns=false&testCoverage=false`; + const response = 'aeolus template content'; + + fileService.getAeolusTemplateFile(ProgrammingLanguage.PYTHON).subscribe((data) => { + expect(data).toEqual(response); + }); + + const req = httpMock.expectOne({ + url: expectedUrl, + method: 'GET', + }); + expect(req.request.responseType).toBe('text'); + req.flush(response); + }); + }); + + describe('getTemplateCodeOfConduct', () => { + it('should fetch the template code of conduct', () => { + const expectedUrl = `api/files/templates/code-of-conduct`; + const response = 'code of conduct content'; + + fileService.getTemplateCodeOfCondcut().subscribe((data) => { + expect(data.body).toEqual(response); + }); + + const req = httpMock.expectOne({ + url: expectedUrl, + method: 'GET', + }); + expect(req.request.responseType).toBe('text'); + req.flush(response); + }); + }); + + describe('downloadFile', () => { + it('should open a new window with the normalized URL', () => { + const downloadUrl = 'http://example.com/files/some file name.txt'; + const encodedUrl = 'http://example.com/files/some%20file%20name.txt'; + const newWindowMock = { location: { href: '' } } as Window; + + jest.spyOn(window, 'open').mockReturnValue(newWindowMock); + + const newWindow = fileService.downloadFile(downloadUrl); + expect(newWindow).not.toBeNull(); + expect(newWindow!.location.href).toBe(encodedUrl); + }); + }); + + describe('downloadFileByAttachmentName', () => { + it('should open a new window with the normalized URL and attachment name', () => { + const downloadUrl = 'http://example.com/files/attachment.txt'; + const downloadName = 'newAttachment'; + const encodedUrl = 'http://example.com/files/newAttachment.txt'; + const newWindowMock = { location: { href: '' } } as Window; + + jest.spyOn(window, 'open').mockReturnValue(newWindowMock); + + const newWindow = fileService.downloadFileByAttachmentName(downloadUrl, downloadName); + expect(newWindow).not.toBeNull(); + expect(newWindow!.location.href).toBe(encodedUrl); + }); + }); + + describe('replaceAttachmentPrefixAndUnderscores', () => { + it('should replace the prefix and underscores in a file name', () => { + const fileName = 'AttachmentUnit_2023-01-01T00-00-00-000_some_file_name'; + const expected = 'some file name'; + + const result = fileService.replaceAttachmentPrefixAndUnderscores(fileName); + expect(result).toBe(expected); + }); + }); });