diff --git a/app/tests/unit/controllers/note.spec.ts b/app/tests/unit/controllers/note.spec.ts index e9d8a658..fe2d9e53 100644 --- a/app/tests/unit/controllers/note.spec.ts +++ b/app/tests/unit/controllers/note.spec.ts @@ -257,3 +257,141 @@ describe('listNotes', () => { expect(next).toHaveBeenCalledTimes(1); }); }); + +describe('deleteNote', () => { + const next = jest.fn(); + + // Mock service calls + const deleteNoteSpy = jest.spyOn(noteService, 'deleteNote'); + + it('should return 200 if deletion is successful', async () => { + const req = { + params: { noteId: '123-123' }, + currentUser: CURRENT_USER + }; + + const deletedNote = { + noteId: '123-123', + activityId: '123', + bringForwardDate: null, + bringForwardState: null, + note: 'Some not text', + noteType: 'GENERAL', + title: 'Note title', + isDeleted: true + }; + + deleteNoteSpy.mockResolvedValue(deletedNote); + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + await noteController.deleteNote(req as any, res as any, next); + + expect(deleteNoteSpy).toHaveBeenCalledTimes(1); + expect(deleteNoteSpy).toHaveBeenCalledWith(req.params.noteId); + expect(res.status).toHaveBeenCalledWith(200); + expect(res.json).toHaveBeenCalledWith(deletedNote); + }); + + it('calls next if the note service fails to delete the note', async () => { + const req = { + params: { noteId: '123-123' }, + currentUser: CURRENT_USER + }; + + deleteNoteSpy.mockImplementationOnce(() => { + throw new Error(); + }); + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + await noteController.deleteNote(req as any, res as any, next); + + expect(deleteNoteSpy).toHaveBeenCalledTimes(1); + expect(deleteNoteSpy).toHaveBeenCalledWith(req.params.noteId); + expect(res.status).toHaveBeenCalledTimes(0); + expect(next).toHaveBeenCalledTimes(1); + }); +}); +describe('updateNote', () => { + const next = jest.fn(); + + // Mock service calls + const updateNoteSpy = jest.spyOn(noteService, 'updateNote'); + const getCurrentUserIdSpy = jest.spyOn(userService, 'getCurrentUserId'); + const getCurrentIdentitySpy = jest.spyOn(utils, 'getCurrentIdentity'); + + it('should return 200 if update is successful', async () => { + const req = { + body: { + noteId: '123-123', + activityId: '123', + bringForwardDate: null, + bringForwardState: null, + note: 'Updated note text', + noteType: 'GENERAL', + title: 'Updated Note title' + }, + currentUser: CURRENT_USER + }; + + const USR_IDENTITY = 'xxxy'; + const USR_ID = 'abc-123'; + + const updated = { + noteId: '123-123', + activityId: '123', + bringForwardDate: null, + bringForwardState: null, + note: 'Updated note text', + noteType: 'GENERAL', + title: 'Updated Note title', + isDeleted: false + }; + + updateNoteSpy.mockResolvedValue(updated); + getCurrentIdentitySpy.mockReturnValue(USR_IDENTITY); + getCurrentUserIdSpy.mockResolvedValue(USR_ID); + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + await noteController.updateNote(req as any, res as any, next); + + expect(getCurrentIdentitySpy).toHaveBeenCalledTimes(1); + expect(getCurrentIdentitySpy).toHaveBeenCalledWith(CURRENT_USER, NIL); + expect(getCurrentUserIdSpy).toHaveBeenCalledTimes(1); + expect(getCurrentUserIdSpy).toHaveBeenCalledWith(USR_IDENTITY, NIL); + expect(updateNoteSpy).toHaveBeenCalledTimes(1); + expect(updateNoteSpy).toHaveBeenCalledWith({ ...req.body, createdBy: USR_ID, updatedAt: expect.any(String) }); + expect(res.status).toHaveBeenCalledWith(200); + expect(res.json).toHaveBeenCalledWith(updated); + }); + + it('calls next if the note service fails to update the note', async () => { + const req = { + body: { + noteId: '123-123', + activityId: '123', + bringForwardDate: null, + bringForwardState: null, + note: 'Updated note text', + noteType: 'GENERAL', + title: 'Updated Note title' + }, + currentUser: CURRENT_USER + }; + + const USR_ID = 'abc-123'; + + getCurrentUserIdSpy.mockResolvedValue(USR_ID); + + updateNoteSpy.mockImplementationOnce(() => { + throw new Error(); + }); + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + await noteController.updateNote(req as any, res as any, next); + + expect(updateNoteSpy).toHaveBeenCalledTimes(1); + expect(updateNoteSpy).toHaveBeenCalledWith({ ...req.body, createdBy: USR_ID, updatedAt: expect.any(String) }); + expect(res.status).toHaveBeenCalledTimes(0); + expect(next).toHaveBeenCalledTimes(1); + }); +}); diff --git a/frontend/tests/unit/components/file/DocumentCard.spec.ts b/frontend/tests/unit/components/file/DocumentCard.spec.ts new file mode 100644 index 00000000..572c9b08 --- /dev/null +++ b/frontend/tests/unit/components/file/DocumentCard.spec.ts @@ -0,0 +1,85 @@ +import { createTestingPinia } from '@pinia/testing'; +import { mount } from '@vue/test-utils'; + +import DocumentCard from '@/components/file/DocumentCard.vue'; +import { userService } from '@/services'; +import { StorageKey } from '@/utils/enums/application'; +import PrimeVue from 'primevue/config'; +import ConfirmationService from 'primevue/confirmationservice'; +import ToastService from 'primevue/toastservice'; + +import type { AxiosResponse } from 'axios'; +import type { Document } from '@/types'; + +const useUserService = vi.spyOn(userService, 'searchUsers'); + +vi.mock('vue-router', () => ({ + useRouter: () => ({ + push: vi.fn(), + replace: vi.fn() + }) +})); + +const currentDate = new Date().toISOString(); + +const testDocument: Document = { + createdBy: 'testCreatedBy', + createdAt: currentDate, + updatedBy: 'testUpdatedAt', + updatedAt: currentDate, + documentId: 'documentUUID', // Primary Key + activityId: 'activityUUID', + filename: 'test file name', + mimeType: 'test mime type', + filesize: 123, + createdByFullName: 'test user' +}; + +const wrapperSettings = (testDocumentProp = testDocument) => ({ + props: { + document: testDocumentProp + }, + global: { + plugins: [ + () => + createTestingPinia({ + initialState: { + auth: { + user: {} + } + } + }), + PrimeVue, + ConfirmationService, + ToastService + ], + stubs: ['font-awesome-icon'] + } +}); + +beforeEach(() => { + sessionStorage.setItem( + StorageKey.CONFIG, + JSON.stringify({ + oidc: { + authority: 'abc', + clientId: '123' + } + }) + ); + + vi.clearAllMocks(); + + useUserService.mockResolvedValue({ data: [{ fullName: 'dummyName' }] } as AxiosResponse); +}); + +afterEach(() => { + sessionStorage.clear(); +}); + +describe('DocumentCard', () => { + it('renders component', async () => { + const wrapper = mount(DocumentCard, wrapperSettings()); + expect(wrapper).toBeTruthy(); + }); +}); diff --git a/frontend/tests/unit/components/file/FileSelectModal.spec.ts b/frontend/tests/unit/components/file/FileSelectModal.spec.ts new file mode 100644 index 00000000..79fceeb0 --- /dev/null +++ b/frontend/tests/unit/components/file/FileSelectModal.spec.ts @@ -0,0 +1,87 @@ +import { createTestingPinia } from '@pinia/testing'; +import { mount } from '@vue/test-utils'; + +import FileSelectModal from '@/components/file/FileSelectModal.vue'; +import { userService } from '@/services'; +import { StorageKey } from '@/utils/enums/application'; +import PrimeVue from 'primevue/config'; +import ConfirmationService from 'primevue/confirmationservice'; +import ToastService from 'primevue/toastservice'; + +import type { AxiosResponse } from 'axios'; +import type { Document } from '@/types'; + +const useUserService = vi.spyOn(userService, 'searchUsers'); + +vi.mock('vue-router', () => ({ + useRouter: () => ({ + push: vi.fn(), + replace: vi.fn() + }) +})); + +const currentDate = new Date().toISOString(); + +const testDocument: Array = [ + { + createdBy: 'testCreatedBy', + createdAt: currentDate, + updatedBy: 'testUpdatedAt', + updatedAt: currentDate, + documentId: 'documentUUID', // Primary Key + activityId: 'activityUUID', + filename: 'test file name', + mimeType: 'test mime type', + filesize: 123, + createdByFullName: 'test user' + } +]; + +const wrapperSettings = (testDocumentProp = testDocument) => ({ + props: { + documents: testDocumentProp + }, + global: { + plugins: [ + () => + createTestingPinia({ + initialState: { + auth: { + user: {} + } + } + }), + PrimeVue, + ConfirmationService, + ToastService + ], + stubs: ['font-awesome-icon'] + } +}); + +beforeEach(() => { + sessionStorage.setItem( + StorageKey.CONFIG, + JSON.stringify({ + oidc: { + authority: 'abc', + clientId: '123' + } + }) + ); + + vi.clearAllMocks(); + + useUserService.mockResolvedValue({ data: [{ fullName: 'dummyName' }] } as AxiosResponse); +}); + +afterEach(() => { + sessionStorage.clear(); +}); + +describe('DocumentCard', () => { + it('renders component', async () => { + const wrapper = mount(FileSelectModal, wrapperSettings()); + expect(wrapper).toBeTruthy(); + }); +}); diff --git a/frontend/tests/unit/components/file/FileUpload.spec.ts b/frontend/tests/unit/components/file/FileUpload.spec.ts new file mode 100644 index 00000000..fcf04f3f --- /dev/null +++ b/frontend/tests/unit/components/file/FileUpload.spec.ts @@ -0,0 +1,71 @@ +import { createTestingPinia } from '@pinia/testing'; +import { mount } from '@vue/test-utils'; + +import FileUpload from '@/components/file/FileUpload.vue'; +import { userService } from '@/services'; +import { StorageKey } from '@/utils/enums/application'; +import PrimeVue from 'primevue/config'; +import ConfirmationService from 'primevue/confirmationservice'; +import ToastService from 'primevue/toastservice'; + +import type { AxiosResponse } from 'axios'; + +const useUserService = vi.spyOn(userService, 'searchUsers'); + +vi.mock('vue-router', () => ({ + useRouter: () => ({ + push: vi.fn(), + replace: vi.fn() + }) +})); + +const activityId = 'activityUUID'; + +const wrapperSettings = () => ({ + props: { + activityId: activityId + }, + global: { + plugins: [ + () => + createTestingPinia({ + initialState: { + auth: { + user: {} + } + } + }), + PrimeVue, + ConfirmationService, + ToastService + ], + stubs: ['font-awesome-icon'] + } +}); + +beforeEach(() => { + sessionStorage.setItem( + StorageKey.CONFIG, + JSON.stringify({ + oidc: { + authority: 'abc', + clientId: '123' + } + }) + ); + + vi.clearAllMocks(); + + useUserService.mockResolvedValue({ data: [{ fullName: 'dummyName' }] } as AxiosResponse); +}); + +afterEach(() => { + sessionStorage.clear(); +}); + +describe('FileUpload', () => { + it('renders component', async () => { + const wrapper = mount(FileUpload, wrapperSettings()); + expect(wrapper).toBeTruthy(); + }); +}); diff --git a/frontend/tests/unit/components/form/CopyToClipboard.spec.ts b/frontend/tests/unit/components/form/CopyToClipboard.spec.ts new file mode 100644 index 00000000..57f9d4c3 --- /dev/null +++ b/frontend/tests/unit/components/form/CopyToClipboard.spec.ts @@ -0,0 +1,66 @@ +import { createTestingPinia } from '@pinia/testing'; +import { mount } from '@vue/test-utils'; + +import CopyToClipboard from '@/components/form/CopyToClipboard.vue'; +import { userService } from '@/services'; +import { StorageKey } from '@/utils/enums/application'; +import PrimeVue from 'primevue/config'; +import ConfirmationService from 'primevue/confirmationservice'; +import ToastService from 'primevue/toastservice'; + +import type { AxiosResponse } from 'axios'; + +const useUserService = vi.spyOn(userService, 'searchUsers'); + +vi.mock('vue-router', () => ({ + useRouter: () => ({ + push: vi.fn(), + replace: vi.fn() + }) +})); + +const wrapperSettings = () => ({ + global: { + plugins: [ + () => + createTestingPinia({ + initialState: { + auth: { + user: {} + } + } + }), + PrimeVue, + ConfirmationService, + ToastService + ], + stubs: ['font-awesome-icon'] + } +}); + +beforeEach(() => { + sessionStorage.setItem( + StorageKey.CONFIG, + JSON.stringify({ + oidc: { + authority: 'abc', + clientId: '123' + } + }) + ); + + vi.clearAllMocks(); + + useUserService.mockResolvedValue({ data: [{ fullName: 'dummyName' }] } as AxiosResponse); +}); + +afterEach(() => { + sessionStorage.clear(); +}); + +describe('CopyToClipboard', () => { + it('renders component', async () => { + const wrapper = mount(CopyToClipboard, wrapperSettings()); + expect(wrapper).toBeTruthy(); + }); +}); diff --git a/frontend/tests/unit/components/permit/PermitCard.spec.ts b/frontend/tests/unit/components/permit/PermitCard.spec.ts new file mode 100644 index 00000000..0561d9e1 --- /dev/null +++ b/frontend/tests/unit/components/permit/PermitCard.spec.ts @@ -0,0 +1,89 @@ +import { createTestingPinia } from '@pinia/testing'; +import { mount } from '@vue/test-utils'; + +import PermitCard from '@/components/permit/PermitCard.vue'; +import { userService } from '@/services'; +import { StorageKey } from '@/utils/enums/application'; +import PrimeVue from 'primevue/config'; +import ConfirmationService from 'primevue/confirmationservice'; +import ToastService from 'primevue/toastservice'; + +import type { AxiosResponse } from 'axios'; +import type { Permit } from '@/types'; + +const useUserService = vi.spyOn(userService, 'searchUsers'); + +vi.mock('vue-router', () => ({ + useRouter: () => ({ + push: vi.fn(), + replace: vi.fn() + }) +})); + +const currentDate = new Date().toISOString(); + +const testPermit: Permit = { + permitId: 'permitUUID', + permitTypeId: 123, + activityId: 'activityUUID', + needed: 'yes', + status: 'status', + issuedPermitId: 'issued Permit ID', + trackingId: 'test tracking ID', + authStatus: 'test auth status', + submittedDate: currentDate, + adjudicationDate: currentDate, + createdBy: 'testCreatedBy', + createdAt: currentDate, + updatedBy: 'testUpdatedAt', + updatedAt: currentDate +}; + +const wrapperSettings = (testPermitProp = testPermit) => ({ + props: { + permit: testPermitProp + }, + global: { + plugins: [ + () => + createTestingPinia({ + initialState: { + auth: { + user: {} + } + } + }), + PrimeVue, + ConfirmationService, + ToastService + ], + stubs: ['font-awesome-icon'] + } +}); + +beforeEach(() => { + sessionStorage.setItem( + StorageKey.CONFIG, + JSON.stringify({ + oidc: { + authority: 'abc', + clientId: '123' + } + }) + ); + + vi.clearAllMocks(); + + useUserService.mockResolvedValue({ data: [{ fullName: 'dummyName' }] } as AxiosResponse); +}); + +afterEach(() => { + sessionStorage.clear(); +}); + +describe('PermitCard', () => { + it('renders component', async () => { + const wrapper = mount(PermitCard, wrapperSettings()); + expect(wrapper).toBeTruthy(); + }); +}); diff --git a/frontend/tests/unit/components/permit/PermitModal.spec.ts b/frontend/tests/unit/components/permit/PermitModal.spec.ts new file mode 100644 index 00000000..737712bf --- /dev/null +++ b/frontend/tests/unit/components/permit/PermitModal.spec.ts @@ -0,0 +1,90 @@ +import { createTestingPinia } from '@pinia/testing'; +import { mount } from '@vue/test-utils'; + +import PermitModal from '@/components/permit/PermitModal.vue'; +import { userService } from '@/services'; +import { StorageKey } from '@/utils/enums/application'; +import PrimeVue from 'primevue/config'; +import ConfirmationService from 'primevue/confirmationservice'; +import ToastService from 'primevue/toastservice'; + +import type { AxiosResponse } from 'axios'; +import type { Permit } from '@/types'; + +const useUserService = vi.spyOn(userService, 'searchUsers'); + +vi.mock('vue-router', () => ({ + useRouter: () => ({ + push: vi.fn(), + replace: vi.fn() + }) +})); + +const currentDate = new Date().toISOString(); +const activityId = 'activityUUID'; +const testPermit: Permit = { + permitId: 'permitUUID', + permitTypeId: 123, + activityId: 'activityUUID', + needed: 'yes', + status: 'status', + issuedPermitId: 'issued Permit ID', + trackingId: 'test tracking ID', + authStatus: 'test auth status', + submittedDate: currentDate, + adjudicationDate: currentDate, + createdBy: 'testCreatedBy', + createdAt: currentDate, + updatedBy: 'testUpdatedAt', + updatedAt: currentDate +}; + +const wrapperSettings = (testPermitProp = testPermit) => ({ + props: { + permit: testPermitProp, + activityId + }, + global: { + plugins: [ + () => + createTestingPinia({ + initialState: { + auth: { + user: {} + } + } + }), + PrimeVue, + ConfirmationService, + ToastService + ], + stubs: ['font-awesome-icon'] + } +}); + +beforeEach(() => { + sessionStorage.setItem( + StorageKey.CONFIG, + JSON.stringify({ + oidc: { + authority: 'abc', + clientId: '123' + } + }) + ); + + vi.clearAllMocks(); + + useUserService.mockResolvedValue({ data: [{ fullName: 'dummyName' }] } as AxiosResponse); +}); + +afterEach(() => { + sessionStorage.clear(); +}); + +describe('PermitModal', () => { + it('renders component', async () => { + const wrapper = mount(PermitModal, wrapperSettings()); + expect(wrapper).toBeTruthy(); + }); +}); diff --git a/frontend/tests/unit/components/submission/SubmissionBringForwardCalendar.spec.ts b/frontend/tests/unit/components/submission/SubmissionBringForwardCalendar.spec.ts new file mode 100644 index 00000000..a2e68369 --- /dev/null +++ b/frontend/tests/unit/components/submission/SubmissionBringForwardCalendar.spec.ts @@ -0,0 +1,84 @@ +import { createTestingPinia } from '@pinia/testing'; +import { mount } from '@vue/test-utils'; + +import SubmissionBringForwardCalendar from '@/components/housing/submission/SubmissionBringForwardCalendar.vue'; +import { userService } from '@/services'; +import { StorageKey } from '@/utils/enums/application'; +import PrimeVue from 'primevue/config'; +import ConfirmationService from 'primevue/confirmationservice'; +import ToastService from 'primevue/toastservice'; + +import type { AxiosResponse } from 'axios'; +import type { BringForward } from '@/types'; + +const useUserService = vi.spyOn(userService, 'searchUsers'); + +vi.mock('vue-router', () => ({ + useRouter: () => ({ + push: vi.fn(), + replace: vi.fn() + }) +})); + +const currentDate = new Date().toISOString(); + +const bringForward: Array = [ + { + noteId: 'nodeUUID', + submissionId: '123', + title: 'test title', + projectName: 'test project name', + bringForwardDate: currentDate, + createdByFullName: 'test full name', + activityId: 'activityUUID' + } +]; + +const wrapperSettings = () => ({ + props: { + bringForward: bringForward + }, + global: { + plugins: [ + () => + createTestingPinia({ + initialState: { + auth: { + user: {} + } + } + }), + PrimeVue, + ConfirmationService, + ToastService + ], + stubs: ['font-awesome-icon'] + } +}); + +beforeEach(() => { + sessionStorage.setItem( + StorageKey.CONFIG, + JSON.stringify({ + oidc: { + authority: 'abc', + clientId: '123' + } + }) + ); + + vi.clearAllMocks(); + + useUserService.mockResolvedValue({ data: [{ fullName: 'dummyName' }] } as AxiosResponse); +}); + +afterEach(() => { + sessionStorage.clear(); +}); + +describe('SubmissionBringForwardCalendar', () => { + it('renders component', async () => { + const wrapper = mount(SubmissionBringForwardCalendar, wrapperSettings()); + expect(wrapper).toBeTruthy(); + }); +});