diff --git a/.vscode/settings.json b/.vscode/settings.json index f35b1a46b302e90ef0a82565ff335d5a4e0bec88..48a0ad264f26a4e7356332e050af6401acb8aed3 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -38,12 +38,14 @@ }, "editor.formatOnSave": true, "typescript.preferences.importModuleSpecifier": "relative", + "gitlens.remotes": [{ "type": "GitLab", "domain": "forge.grandlyon.com", "name": "Forge" }], "cSpell.words": [ "aidant", "aidants", "aptic", "cnfs", "courriel", + "cpam", "espace", "grandlyon", "nestjs", diff --git a/CHANGELOG.md b/CHANGELOG.md index bbf4a890347954d07c85931dfa9df973bd2d7305..28161407cfa59de01ab1d1691f0895654fb72c79 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,25 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +### [2.4.2](https://forge.grandlyon.com/web-et-numerique/pamn_plateforme-des-acteurs-de-la-mediation-numerique/pamn_server/compare/v2.4.1...v2.4.2) (2023-10-05) + + +### Features + +* **online-demarch:** remove cpam ([556658d](https://forge.grandlyon.com/web-et-numerique/pamn_plateforme-des-acteurs-de-la-mediation-numerique/pamn_server/commit/556658dd0b5de94c1359765ea1bbd89cfa527089)) +* remove pix label ([b306108](https://forge.grandlyon.com/web-et-numerique/pamn_plateforme-des-acteurs-de-la-mediation-numerique/pamn_server/commit/b306108ecec74efbc23d6c1dfcff798c988e381b)) +* **structureTypes:** new structure types list ([e7e1ae8](https://forge.grandlyon.com/web-et-numerique/pamn_plateforme-des-acteurs-de-la-mediation-numerique/pamn_server/commit/e7e1ae80276c77d3f9d9803b7d261f55f458dcb3)) + + +### Bug Fixes + +* **export:** exported structures now contain a unique id field ([8196f90](https://forge.grandlyon.com/web-et-numerique/pamn_plateforme-des-acteurs-de-la-mediation-numerique/pamn_server/commit/8196f9088362aaec553aec5642c6c6cf0d02506a)) +* **import:** handles osm "off" hours ([a804eda](https://forge.grandlyon.com/web-et-numerique/pamn_plateforme-des-acteurs-de-la-mediation-numerique/pamn_server/commit/a804eda7d1ea97d2db6046f174a9cea0d3d1e23b)) +* **indicator:** handle prescripteur profile when storing orientation event ([50d1821](https://forge.grandlyon.com/web-et-numerique/pamn_plateforme-des-acteurs-de-la-mediation-numerique/pamn_server/commit/50d1821d190a344f1f00c50f499639b0274b2937)) +* **map:** avoid error 500 if no structure position ([8dfdf08](https://forge.grandlyon.com/web-et-numerique/pamn_plateforme-des-acteurs-de-la-mediation-numerique/pamn_server/commit/8dfdf08c2b517b939a14cee76a7463f4537fc3c9)) +* **orientation:** only use personal offers for structure rdv ([0d6c66d](https://forge.grandlyon.com/web-et-numerique/pamn_plateforme-des-acteurs-de-la-mediation-numerique/pamn_server/commit/0d6c66d36fdafa1b35ebf2bceec8f60666cf1364)) +* **rdv:** filter offers of users with rdv ([4c29d54](https://forge.grandlyon.com/web-et-numerique/pamn_plateforme-des-acteurs-de-la-mediation-numerique/pamn_server/commit/4c29d540f06ff52ddda7b52dc55e72d4681fb708)) + ### [2.4.1](https://forge.grandlyon.com/web-et-numerique/factory/pamn_plateforme-des-acteurs-de-la-mediation-numerique/pamn_server/compare/v2.4.0...v2.4.1) (2023-08-25) diff --git a/package.json b/package.json index f2448f8cd587523a8dee70981c76eab072917e94..3e23fccf0463af7f89ebf108c931aa4e607dedf7 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "ram_server", "private": true, - "version": "2.4.1", + "version": "2.4.2", "description": "Nest TypeScript starter repository", "license": "MIT", "scripts": { diff --git a/scripts/data/users.js b/scripts/data/users.js index 2f353d3317e3cd052446066428a31221ae55d3a0..02ce86cdc4721512f1a05148465ed941f43eddef 100644 --- a/scripts/data/users.js +++ b/scripts/data/users.js @@ -18,6 +18,8 @@ module.exports = { email: 'admin@admin.com', structureOutdatedMailSent: [], unattachedSince: Date.now(), + job: null, + employer: null, }, { structureOutdatedMailSent: [], diff --git a/src/admin/admin.controller.spec.ts b/src/admin/admin.controller.spec.ts index 41fbf2e428f62ce58935f14a47897cd7d38bfece..1ac338e0ceda2614613b3de009de336a51793700 100644 --- a/src/admin/admin.controller.spec.ts +++ b/src/admin/admin.controller.spec.ts @@ -30,7 +30,7 @@ import { AdminService } from './admin.service'; import { PendingStructureDto } from './dto/pending-structure.dto'; describe('AdminController', () => { - let controller: AdminController; + let adminController: AdminController; let userService: UsersService; const mockEmployerSearchService = { @@ -147,30 +147,30 @@ describe('AdminController', () => { .useValue(mockRoleGuard) .compile(); - controller = module.get<AdminController>(AdminController); + adminController = module.get<AdminController>(AdminController); userService = module.get<UsersService>(UsersService); }); it('should be defined', () => { - expect(controller).toBeDefined(); + expect(adminController).toBeDefined(); }); it('should get pending attachments', async () => { mockStructureService.findOne.mockResolvedValue({ structureName: 'structure', updatedAt: '' }); - expect((await controller.getPendingAttachments()).length).toBe(2); - expect(Object.keys((await controller.getPendingAttachments())[0]).length).toBe(5); + expect((await adminController.getPendingAttachments()).length).toBe(2); + expect(Object.keys((await adminController.getPendingAttachments())[0]).length).toBe(5); }); describe('Pending structures validation', () => { it('should validate pending structure', async () => { mockStructureService.findOne.mockResolvedValue({ structureName: 'structure' }); - expect((await controller.validatePendingStructure(pendingStructureTest)).length).toBe(2); - expect(Object.keys((await controller.validatePendingStructure(pendingStructureTest))[0]).length).toBe(5); + expect((await adminController.validatePendingStructure(pendingStructureTest)).length).toBe(2); + expect(Object.keys((await adminController.validatePendingStructure(pendingStructureTest))[0]).length).toBe(5); }); it('should get structure does not exist', async () => { try { - await controller.validatePendingStructure(pendingStructureTest); + await adminController.validatePendingStructure(pendingStructureTest); } catch (e) { expect(e.message).toBe('Structure does not exist'); expect(e.status).toBe(404); @@ -181,13 +181,14 @@ describe('AdminController', () => { describe('Pending structures cancel', () => { it('should refuse pending structure', async () => { mockStructureService.findOne.mockResolvedValue({ structureName: 'structure' }); - expect((await controller.refusePendingStructure(pendingStructureTest)).length).toBe(2); - expect(Object.keys((await controller.refusePendingStructure(pendingStructureTest))[0]).length).toBe(5); + mockStructureService.findOne.mockResolvedValue({ structureName: 'structure' }); + expect((await adminController.refusePendingStructure(pendingStructureTest)).length).toBe(2); + expect(Object.keys((await adminController.refusePendingStructure(pendingStructureTest))[0]).length).toBe(5); }); it('should get structure does not exist', async () => { try { - await controller.refusePendingStructure(pendingStructureTest); + await adminController.refusePendingStructure(pendingStructureTest); } catch (e) { expect(e.message).toBe('Structure does not exist'); expect(e.status).toBe(404); @@ -198,12 +199,12 @@ describe('AdminController', () => { describe('Delete user', () => { it('should delete user', async () => { jest.spyOn(StructuresServiceMock.prototype, 'deleteOne').mockImplementationOnce(() => null); - const user = await controller.deleteUser({ id: 'tsfsf6296' }); + const user = await adminController.deleteUser({ id: 'tsfsf6296' }); expect(user.email).toBe('pauline.dupont@mii.com'); }); it('should return nonexisting user', async () => { try { - await controller.deleteUser({ id: 'userDoesNotExist' }); + await adminController.deleteUser({ id: 'userDoesNotExist' }); } catch (e) { expect(e.message).toBe('Invalid user id'); expect(e.status).toBe(400); @@ -221,7 +222,7 @@ describe('AdminController', () => { validated: true, }; mockEmployerService.findOne.mockResolvedValueOnce(mockEmployer); - const reply = await controller.setUserEmployer({ + const reply = await adminController.setUserEmployer({ userId: mockUserId, employerId: String(mockEmployer._id), }); @@ -240,7 +241,7 @@ describe('AdminController', () => { }; mockEmployerService.findOne.mockResolvedValueOnce(null); try { - await controller.setUserEmployer({ + await adminController.setUserEmployer({ userId: mockUserId, employerId: String(mockEmployer._id), }); @@ -262,7 +263,7 @@ describe('AdminController', () => { }; mockEmployerService.findOne.mockResolvedValueOnce(mockEmployer); try { - await controller.setUserEmployer({ + await adminController.setUserEmployer({ userId: mockUserId, employerId: String(mockEmployer._id), }); @@ -285,7 +286,7 @@ describe('AdminController', () => { validated: true, }; mockJobService.findOne.mockResolvedValueOnce(mockJob); - const reply = await controller.setUserJob({ + const reply = await adminController.setUserJob({ userId: mockUserId, jobId: String(mockJob._id), }); @@ -304,7 +305,7 @@ describe('AdminController', () => { }; mockJobService.findOne.mockResolvedValueOnce(null); try { - await controller.setUserJob({ + await adminController.setUserJob({ userId: mockUserId, jobId: String(mockJob._id), }); @@ -326,7 +327,7 @@ describe('AdminController', () => { }; mockJobService.findOne.mockResolvedValueOnce(mockJob); try { - await controller.setUserJob({ + await adminController.setUserJob({ userId: mockUserId, jobId: String(mockJob._id), }); @@ -341,28 +342,28 @@ describe('AdminController', () => { describe('Search user', () => { it('should return all users, empty string', async () => { - expect((await controller.searchUsers({ searchString: '' })).length).toBe(2); + expect((await adminController.searchUsers({ searchString: '' })).length).toBe(2); }); it('should return all users, null input', async () => { - expect((await controller.searchUsers({ searchString: null })).length).toBe(2); + expect((await adminController.searchUsers({ searchString: null })).length).toBe(2); }); it('should one user', async () => { - expect((await controller.searchUsers({ searchString: 'a@a.com' })).length).toBe(1); - expect((await controller.searchUsers({ searchString: 'a@a.com' }))[0].email).toBe('a@a.com'); + expect((await adminController.searchUsers({ searchString: 'a@a.com' })).length).toBe(1); + expect((await adminController.searchUsers({ searchString: 'a@a.com' }))[0].email).toBe('a@a.com'); }); it('should no user', async () => { - expect((await controller.searchUsers({ searchString: 'dfqfqsfqfqfa@a.com' })).length).toBe(0); + expect((await adminController.searchUsers({ searchString: 'dfqfqsfqfqfa@a.com' })).length).toBe(0); }); }); describe('Search delete a user subscription', () => { it('should return a deleted object', async () => { - expect((await controller.unsubscribeUserFromNewsletter('a@a.com')).email).toBe('a@a.com'); - expect(Object.keys(await controller.unsubscribeUserFromNewsletter('a@a.com')).length).toBe(4); + expect((await adminController.unsubscribeUserFromNewsletter('a@a.com')).email).toBe('a@a.com'); + expect(Object.keys(await adminController.unsubscribeUserFromNewsletter('a@a.com')).length).toBe(4); }); it('should throw an error', async () => { try { - await controller.unsubscribeUserFromNewsletter('test@test.com'); + await adminController.unsubscribeUserFromNewsletter('test@test.com'); } catch (e) { expect(e.message).toBe('Invalid email'); expect(e.status).toBe(401); @@ -388,7 +389,7 @@ describe('AdminController', () => { { structureName: 'name', structureId: 'f', id: 'f' }, ]); - const adminList = await controller.getAdminStructuresList(); + const adminList = await adminController.getAdminStructuresList(); expect(adminList.inClaim.length).toBe(2); expect(adminList.toClaim.length).toBe(2); expect(adminList.claimed.length).toBe(2); @@ -397,22 +398,22 @@ describe('AdminController', () => { it('should find attached users', async () => { mockStructureService.getAllUserCompletedStructures.mockResolvedValueOnce([]); - expect((await controller.findAttachedUsers()).length).toBe(0); + expect((await adminController.findAttachedUsers()).length).toBe(0); }); it('should find unattached users', async () => { - expect((await controller.findUnattachedUsers()).length).toBe(0); + expect((await adminController.findUnattachedUsers()).length).toBe(0); }); it('should find unverified users', async () => { mockStructureService.getAllUserCompletedStructures.mockResolvedValueOnce([]); - expect((await controller.findUnVerifiedUsers()).length).toBe(0); + expect((await adminController.findUnVerifiedUsers()).length).toBe(0); }); describe('should test getDeletedStructures()', () => { it('should find getDeletedStructures', async () => { mockStructureService.findAll.mockResolvedValue(structuresDocumentDataMock); - expect((await controller.getDeletedStructures()).length).toBeGreaterThan(0); + expect((await adminController.getDeletedStructures()).length).toBeGreaterThan(0); }); }); }); diff --git a/src/admin/admin.controller.ts b/src/admin/admin.controller.ts index 050a2d8a7894bdc04f381c5f9a878ad04430b446..951cd787b3f76dbb3ab7181e3845fe0127222a54 100644 --- a/src/admin/admin.controller.ts +++ b/src/admin/admin.controller.ts @@ -368,7 +368,7 @@ export class AdminController { @ApiOperation({ description: 'Get deleted structures' }) @Post('restoreDeletedStructure/:structureId') public async restoreDeletedStructures(@Param('structureId') structureId: string): Promise<void> { - this.logger.debug(`restoreDeletedStructures: ${structureId}`); + this.logger.log(`restoreDeletedStructures: ${structureId}`); await this.structuresService.restoreStructure(structureId); await this.structuresService.initiateStructureIndex(); } diff --git a/src/admin/admin.service.spec.ts b/src/admin/admin.service.spec.ts index 5e5e153df03a8437915bb59ff2861c9366e40f02..99d58a8c0c44ae7f6ce9907229234ef7a590b592 100644 --- a/src/admin/admin.service.spec.ts +++ b/src/admin/admin.service.spec.ts @@ -2,17 +2,17 @@ import { Test, TestingModule } from '@nestjs/testing'; import { AdminService } from './admin.service'; describe('AdminService', () => { - let service: AdminService; + let adminService: AdminService; beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ providers: [AdminService], }).compile(); - service = module.get<AdminService>(AdminService); + adminService = module.get<AdminService>(AdminService); }); it('should be defined', () => { - expect(service).toBeDefined(); + expect(adminService).toBeDefined(); }); }); diff --git a/src/appointment/appointment.controller.spec.ts b/src/appointment/appointment.controller.spec.ts index 805bfa31a616e8e4c19fd0fa7f91de202df29745..9b8d25cfae142cac4b743e54ca2332b40a960d3a 100644 --- a/src/appointment/appointment.controller.spec.ts +++ b/src/appointment/appointment.controller.spec.ts @@ -6,7 +6,7 @@ import { Appointment } from './appointment.schema'; import { AppointmentService } from './appointment.service'; describe('UserRegistryController', () => { - let controller: AppointmentController; + let appoinmentController: AppointmentController; const appointmentServiceMock = { findAll: jest.fn(), @@ -29,24 +29,24 @@ describe('UserRegistryController', () => { controllers: [AppointmentController], }).compile(); - controller = module.get<AppointmentController>(AppointmentController); + appoinmentController = module.get<AppointmentController>(AppointmentController); }); it('should be defined', () => { - expect(controller).toBeDefined(); + expect(appoinmentController).toBeDefined(); }); describe('findAll', () => { it('should findAll entries', async () => { appointmentServiceMock.findAll.mockResolvedValue(appointmentMockData); - const reply = await controller.findAll(); + const reply = await appoinmentController.findAll(); expect(reply).toStrictEqual(appointmentMockData); }); }); describe('createAppointment', () => { it('should create a new entry', async () => { appointmentServiceMock.create.mockResolvedValue(singleAppointmentMock); - const reply = await controller.createAppointment(singleAppointmentMock); + const reply = await appoinmentController.createAppointment(singleAppointmentMock); expect(reply).toStrictEqual(singleAppointmentMock); }); }); diff --git a/src/appointment/appointment.service.spec.ts b/src/appointment/appointment.service.spec.ts index f82483845b002f4798c93a7424862cd67a6560bd..11f6bb541e4d268e85e6b96361668a07270f39b9 100644 --- a/src/appointment/appointment.service.spec.ts +++ b/src/appointment/appointment.service.spec.ts @@ -1,18 +1,19 @@ +import { HttpModule } from '@nestjs/axios'; import { getModelToken } from '@nestjs/mongoose'; import { Test, TestingModule } from '@nestjs/testing'; -import { AppointmentService } from './appointment.service'; +import * as ejs from 'ejs'; import { appointmentMockData } from '../../test/mock/data/appointment.mock.data'; -import { MailerService } from '../mailer/mailer.service'; +import { StructuresServiceMock } from '../../test/mock/services/structures.mock.service'; +import { UsersServiceMock } from '../../test/mock/services/user.mock.service'; import { MailerModule } from '../mailer/mailer.module'; -import { HttpModule } from '@nestjs/axios'; -import { UsersService } from '../users/services/users.service'; +import { MailerService } from '../mailer/mailer.service'; import { StructuresService } from '../structures/services/structures.service'; -import { UsersServiceMock } from '../../test/mock/services/user.mock.service'; -import { StructuresServiceMock } from '../../test/mock/services/structures.mock.service'; -import * as ejs from 'ejs'; +import { UsersService } from '../users/services/users.service'; +import { AppointmentService } from './appointment.service'; describe('userRegistryService', () => { - let service: AppointmentService; + let appointmentService: AppointmentService; + const mockAppointmentModel = { find: jest.fn(() => mockAppointmentModel), create: jest.fn(() => mockAppointmentModel), @@ -56,17 +57,17 @@ describe('userRegistryService', () => { }, ], }).compile(); - service = module.get<AppointmentService>(AppointmentService); + appointmentService = module.get<AppointmentService>(AppointmentService); }); it('should be defined', () => { - expect(service).toBeDefined(); + expect(appointmentService).toBeDefined(); }); describe('findAll', () => { it('should findAll entries', async () => { mockAppointmentModel.exec.mockResolvedValueOnce(appointmentMockData); - expect(await service.findAll()).toBe(appointmentMockData); + expect(await appointmentService.findAll()).toBe(appointmentMockData); }); }); describe('create', () => { @@ -74,7 +75,7 @@ describe('userRegistryService', () => { const res = { accompanimentType: 'RDV Conseiller Numérique', name: 'test', - onlineDemarcheType: ['Démarches Métropolitaines', 'CPAM'], + onlineDemarcheType: ['Démarches Métropolitaines'], phone: '65 65', surname: 'teztrfzegfv', structureOrientator: { structureName: 'name', structureMail: 'mail@structure.org', structurePhone: '12 34' }, @@ -84,7 +85,7 @@ describe('userRegistryService', () => { mockMailService.loadJsonConfig.mockReturnValueOnce({ subject: 'Teste Mail' }); ejsSpy.mockResolvedValueOnce('coucou'); mockAppointmentModel.create.mockResolvedValueOnce(res); - expect(await service.create(res)).toStrictEqual(res); + expect(await appointmentService.create(res)).toStrictEqual(res); expect(mockMailService.send).toHaveBeenCalledTimes(1); }); }); diff --git a/src/appointment/dto/appointment.dto.ts b/src/appointment/dto/appointment.dto.ts index 0f6be8b4e47e6200432f9debb43a3ce9aa0a5948..ad729f2298741f60b83cbe550137ad9d741e0c1e 100644 --- a/src/appointment/dto/appointment.dto.ts +++ b/src/appointment/dto/appointment.dto.ts @@ -18,7 +18,7 @@ export class AppointmentDto { @IsNotEmpty() @ApiProperty({ - example: [{ text: 'CAF' }, { text: 'CPAM' }], + example: [{ text: 'CAF' }, { text: 'France Connect' }], }) readonly onlineDemarcheType: string[]; diff --git a/src/auth/auth.controller.spec.ts b/src/auth/auth.controller.spec.ts index c69a22cedef0473b462d16ad13b9ea84f61b90a3..3feefc99c2d1448c80bde58e026a0be4bff84858 100644 --- a/src/auth/auth.controller.spec.ts +++ b/src/auth/auth.controller.spec.ts @@ -1,26 +1,26 @@ +import { HttpService } from '@nestjs/axios'; import { JwtModule } from '@nestjs/jwt'; import { getModelToken } from '@nestjs/mongoose'; import { PassportModule } from '@nestjs/passport'; import { Test, TestingModule } from '@nestjs/testing'; import { AuthServiceMock } from '../../test/mock/services/auth.mock.service'; +import { StructuresServiceMock } from '../../test/mock/services/structures.mock.service'; +import { CategoriesService } from '../categories/services/categories.service'; import { ConfigurationModule } from '../configuration/configuration.module'; import { MailerModule } from '../mailer/mailer.module'; +import { StructuresSearchService } from '../structures/services/structures-search.service'; +import { StructuresService } from '../structures/services/structures.service'; +import { Job } from '../users/schemas/job.schema'; import { User } from '../users/schemas/user.schema'; +import { JobsService } from '../users/services/jobs.service'; import { UserRegistrySearchService } from '../users/services/userRegistry-search.service'; import { UsersService } from '../users/services/users.service'; import { AuthController } from './auth.controller'; import { AuthService } from './auth.service'; import { LoginDto } from './login-dto'; -import { JobsService } from '../users/services/jobs.service'; -import { Job } from '../users/schemas/job.schema'; -import { StructuresService } from '../structures/services/structures.service'; -import { HttpService } from '@nestjs/axios'; -import { StructuresSearchService } from '../structures/services/structures-search.service'; -import { CategoriesService } from '../categories/services/categories.service'; -import { StructuresServiceMock } from '../../test/mock/services/structures.mock.service'; describe('AuthController', () => { - let controller: AuthController; + let authController: AuthController; const httpServiceMock = { get: jest.fn(), @@ -83,16 +83,16 @@ describe('AuthController', () => { ], }).compile(); - controller = module.get<AuthController>(AuthController); + authController = module.get<AuthController>(AuthController); }); it('should be defined', () => { - expect(controller).toBeDefined(); + expect(authController).toBeDefined(); }); it('should login valid user', async () => { const loginCredentials: LoginDto = { email: 'paula.dubois@mii.com', password: process.env.USER_PWD }; - const result = await controller.login(loginCredentials); + const result = await authController.login(loginCredentials); expect(result).toStrictEqual({ _id: 'tsfsf6296', email: 'pauline.dupont@mii.com', @@ -109,7 +109,7 @@ describe('AuthController', () => { it('should not login invalid user', async () => { const loginCredentials: LoginDto = { email: 'jacques.dupont@mii.com', password: process.env.USER_PWD }; try { - await controller.login(loginCredentials); + await authController.login(loginCredentials); } catch (e) { expect(e.response).toBe('Invalid credentials'); expect(e.message).toBe('Invalid credentials'); diff --git a/src/auth/auth.service.spec.ts b/src/auth/auth.service.spec.ts index 134ae6351a8f5b607495244ce72f0c1458c2b1b1..a8784080413008e5be0f0dd37be15f5281c0851d 100644 --- a/src/auth/auth.service.spec.ts +++ b/src/auth/auth.service.spec.ts @@ -10,7 +10,7 @@ import { AuthService } from './auth.service'; import { LoginDto } from './login-dto'; describe('AuthService', () => { - let service: AuthService; + let authService: AuthService; beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ @@ -28,11 +28,11 @@ describe('AuthService', () => { ], }).compile(); - service = module.get<AuthService>(AuthService); + authService = module.get<AuthService>(AuthService); }); it('should be defined', () => { - expect(service).toBeDefined(); + expect(authService).toBeDefined(); }); describe('validateUser', () => { @@ -47,12 +47,12 @@ describe('AuthService', () => { personalOffers: [], }; const loginDto: LoginDto = { email: 'jacques.dupont@mii.com', password: 'test1A!!' }; //NOSONAR - expect(await service.validateUser(loginDto)).toStrictEqual(result); + expect(await authService.validateUser(loginDto)).toStrictEqual(result); }); it('should not validateUser', async () => { const loginDto: LoginDto = { email: 'tom.dupont@mii.com', password: 'test1A!!!' }; //NOSONAR - expect(await service.validateUser(loginDto)).toBe(null); + expect(await authService.validateUser(loginDto)).toBe(null); }); }); @@ -71,7 +71,7 @@ describe('AuthService', () => { _createToken.mockImplementation(() => token); const loginDto: LoginDto = { email: 'pauline.dupont@mii.com', password: 'test1A!!' }; //NOSONAR - expect(await service.login(loginDto)).toStrictEqual({ + expect(await authService.login(loginDto)).toStrictEqual({ accessToken: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6InBhdWxpbmUuZHVwb250QG1paS5jb20iLCJyb2xlIjowLCJpYXQiOjE2MjAwNDg5MDYsImV4cCI6MTYyMDEzNTMwNn0.jbLazQNJzU_X9Yp1S7XH1rYD5W7yyd1pdGebmkyTMB4', expiresAt: '2021-05-04T15:35:06.663+02:00', @@ -92,7 +92,7 @@ describe('AuthService', () => { const loginDto: LoginDto = { email: 'jacques.dupont@mii.com', password: 'test1A!!' }; //NOSONAR try { - await service.login(loginDto); + await authService.login(loginDto); } catch (e) { expect(e.response).toBe('Invalid credentials'); expect(e.message).toBe('Invalid credentials'); @@ -111,7 +111,7 @@ describe('AuthService', () => { const loginDto: LoginDto = { email: 'toto@mii.com', password: 'test1A!!' }; //NOSONAR try { - await service.login(loginDto); + await authService.login(loginDto); } catch (e) { expect(e.response).toBe('Invalid credentials'); expect(e.message).toBe('Invalid credentials'); @@ -130,7 +130,7 @@ describe('AuthService', () => { const loginDto: LoginDto = { email: 'jacques.dupont@mii.com', password: '1' }; //NOSONAR try { - await service.login(loginDto); + await authService.login(loginDto); } catch (e) { expect(e.response).toBe('Invalid credentials'); expect(e.message).toBe('Invalid credentials'); diff --git a/src/categories/controllers/categories.controller.spec.ts b/src/categories/controllers/categories.controller.spec.ts index b523580de9e5bbc1b4bc0b9722d1f97fa0fdea90..f4de5777e6eaf7cabb9f81d35167fb945402ca17 100644 --- a/src/categories/controllers/categories.controller.spec.ts +++ b/src/categories/controllers/categories.controller.spec.ts @@ -10,7 +10,7 @@ import { CategoriesService } from '../services/categories.service'; import { CategoriesController } from './categories.controller'; describe('CategoriesAccompagnementController', () => { - let controller: CategoriesController; + let categoriesController: CategoriesController; beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ @@ -33,15 +33,15 @@ describe('CategoriesAccompagnementController', () => { .useValue(mockRoleGuard) .compile(); - controller = module.get<CategoriesController>(CategoriesController); + categoriesController = module.get<CategoriesController>(CategoriesController); }); it('should be defined', () => { - expect(controller).toBeDefined(); + expect(categoriesController).toBeDefined(); }); it('should find all accompagnements', async () => { - expect((await controller.findAll()).length).toBe(1); - expect((await controller.findAll())[0].modules.length).toBe(8); + expect((await categoriesController.findAll()).length).toBe(1); + expect((await categoriesController.findAll())[0].modules.length).toBe(7); }); }); diff --git a/src/categories/services/categories.service.spec.ts b/src/categories/services/categories.service.spec.ts index 125760f11ae8bc904623916b72cbaa18d758912c..d1e2362cf82d90aa06b3afecb8efe949d20d04f5 100644 --- a/src/categories/services/categories.service.spec.ts +++ b/src/categories/services/categories.service.spec.ts @@ -5,7 +5,7 @@ import { CreateCategories } from '../dto/create-categories.dto'; import { CategoriesService } from './categories.service'; describe('CategoriesService', () => { - let service: CategoriesService; + let categoriesService: CategoriesService; const mockCategoriesModel = { create: jest.fn(), @@ -27,11 +27,11 @@ describe('CategoriesService', () => { ], }).compile(); - service = module.get<CategoriesService>(CategoriesService); + categoriesService = module.get<CategoriesService>(CategoriesService); }); it('should be defined', () => { - expect(service).toBeDefined(); + expect(categoriesService).toBeDefined(); }); it('should findAll structures', async () => { @@ -41,7 +41,7 @@ describe('CategoriesService', () => { ]; mockCategoriesModel.find.mockReturnThis(); mockCategoriesModel.exec.mockResolvedValueOnce(data); - expect(await service.findAll()).toEqual(data); + expect(await categoriesService.findAll()).toEqual(data); }); it('should findOneComplete structures', async () => { const data: CreateCategories[] = [ @@ -50,6 +50,6 @@ describe('CategoriesService', () => { ]; mockCategoriesModel.findOne.mockReturnThis(); mockCategoriesModel.exec.mockResolvedValueOnce(data); - expect(await service.findOneComplete('categoryId')).toEqual(data); + expect(await categoriesService.findOneComplete('categoryId')).toEqual(data); }); }); diff --git a/src/configuration/config.ts b/src/configuration/config.ts index 02caab30b42e7fec4430b2da891c8f79e60b6653..a0183191d28db8cb058061f6df19533c975d2f7d 100644 --- a/src/configuration/config.ts +++ b/src/configuration/config.ts @@ -25,6 +25,10 @@ export const config = { ejs: 'adminStructureCreate.ejs', json: 'adminStructureCreate.json', }, + adminStructureImport: { + ejs: 'adminStructureImport.ejs', + json: 'adminStructureImport.json', + }, adminUserCreate: { ejs: 'adminUserCreate.ejs', json: 'adminUserCreate.json', diff --git a/src/configuration/configuration.service.spec.ts b/src/configuration/configuration.service.spec.ts index a5ddba0b94c2d6b95b5846ca549160d01bf42275..7c48290aa1a810155c7b5bb227b3f52a3fc45a62 100644 --- a/src/configuration/configuration.service.spec.ts +++ b/src/configuration/configuration.service.spec.ts @@ -2,7 +2,7 @@ import { Test, TestingModule } from '@nestjs/testing'; import { ConfigurationService } from './configuration.service'; describe('ConfigurationService', () => { - let service: ConfigurationService; + let configurationService: ConfigurationService; process.env.NODE_ENV = 'local'; @@ -12,7 +12,7 @@ describe('ConfigurationService', () => { providers: [ConfigurationService], }).compile(); - service = module.get<ConfigurationService>(ConfigurationService); + configurationService = module.get<ConfigurationService>(ConfigurationService); }); describe('initialisation', () => { @@ -28,12 +28,12 @@ describe('ConfigurationService', () => { }); it('should be defined', () => { - expect(service).toBeDefined(); + expect(configurationService).toBeDefined(); }); it('should init with dev conf', () => { process.env.NODE_ENV = 'dev'; - expect(service.config.host).toBe('resin-dev.grandlyon.com'); + expect(configurationService.config.host).toBe('resin-dev.grandlyon.com'); }); }); @@ -50,25 +50,25 @@ describe('ConfigurationService', () => { }); it('should be defined', () => { - expect(service).toBeDefined(); + expect(configurationService).toBeDefined(); }); it('should init with prod conf', () => { process.env.NODE_ENV = 'production'; - expect(service.config.host).toBe('resin.grandlyon.com'); + expect(configurationService.config.host).toBe('resin.grandlyon.com'); }); }); describe('validateUser', () => { it('should be local conf', () => { process.env.NODE_ENV = 'local'; - expect(service.isLocalConf()).toBe(true); + expect(configurationService.isLocalConf()).toBe(true); }); }); describe('get config', () => { it('should get config', () => { - const config = service.config; + const config = configurationService.config; expect(Object.keys(config).length).toBe(9); expect(Object.keys(config)).toEqual( expect.arrayContaining([ diff --git a/src/contact/contact.controller.spec.ts b/src/contact/contact.controller.spec.ts index 7123437dd460c44b0e7858d71fd497cc5a421ffd..beb188f7c5dba07baa84d6520b37abe82f8370ac 100644 --- a/src/contact/contact.controller.spec.ts +++ b/src/contact/contact.controller.spec.ts @@ -1,11 +1,11 @@ import { Test, TestingModule } from '@nestjs/testing'; +import { MailerModule } from '../mailer/mailer.module'; import { ContactController } from './contact.controller'; import { ContactService } from './contact.service'; -import { MailerModule } from '../mailer/mailer.module'; import { ContactMessage } from './schemas/contact-message.schema'; describe('ContactController', () => { - let controller: ContactController; + let contactController: ContactController; const contactServiceMock = { sendMessage: jest.fn(), @@ -23,16 +23,16 @@ describe('ContactController', () => { controllers: [ContactController], }).compile(); - controller = module.get<ContactController>(ContactController); + contactController = module.get<ContactController>(ContactController); }); it('should be defined', () => { - expect(controller).toBeDefined(); + expect(contactController).toBeDefined(); }); it('should call sendMessage', async () => { const spyer = jest.spyOn(contactServiceMock, 'sendMessage'); - await controller.sendContactMessage({ contactMessage: new ContactMessage() }); + await contactController.sendContactMessage({ contactMessage: new ContactMessage() }); expect(spyer).toBeCalledTimes(1); expect(spyer).toBeCalledWith(new ContactMessage()); }); diff --git a/src/contact/contact.service.spec.ts b/src/contact/contact.service.spec.ts index c8558d105cac8fae27b7745225072f52a064f36d..259986b32c21506e74e8d9bd73eb9a37d79330a4 100644 --- a/src/contact/contact.service.spec.ts +++ b/src/contact/contact.service.spec.ts @@ -9,7 +9,7 @@ import { ContactService } from './contact.service'; import { ContactMessage } from './schemas/contact-message.schema'; describe('ContactService', () => { - let service: ContactService; + let contactService: ContactService; beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ @@ -17,15 +17,15 @@ describe('ContactService', () => { providers: [ContactService, ConfigurationService, { provide: MailerService, useClass: MailerMockService }], }).compile(); - service = module.get<ContactService>(ContactService); + contactService = module.get<ContactService>(ContactService); }); it('should be defined', () => { - expect(service).toBeDefined(); + expect(contactService).toBeDefined(); }); it('should send message with status OK', async () => { - const res = (await service.sendMessage(new ContactMessage())) as { data: { status: unknown } }; + const res = (await contactService.sendMessage(new ContactMessage())) as { data: { status: unknown } }; expect(res.data.status).toBe(HttpStatus.OK); }); }); diff --git a/src/espaceCoop/services/espaceCoop.service.spec.ts b/src/espaceCoop/services/espaceCoop.service.spec.ts index 24ba0e96bc371982228579da4bb4d4d65f4fc742..cb11ebbef934baaabffe8275cb5ee8f9b879b896 100644 --- a/src/espaceCoop/services/espaceCoop.service.spec.ts +++ b/src/espaceCoop/services/espaceCoop.service.spec.ts @@ -1,16 +1,16 @@ import { HttpService } from '@nestjs/axios'; import { getModelToken } from '@nestjs/mongoose'; import { Test, TestingModule } from '@nestjs/testing'; -import { UsersService } from '../../users/services/users.service'; import { espaceCoopCNFSMockData, espaceCoopPermanencesMockData, } from '../../../test/mock/data/espaceCoopCNFS.mock.data'; -import { EspaceCoopService } from './espaceCoop.service'; import { usersMockData } from '../../../test/mock/data/users.mock.data'; +import { UsersService } from '../../users/services/users.service'; +import { EspaceCoopService } from './espaceCoop.service'; describe('EspaceCoopCNFSService', () => { - let service: EspaceCoopService; + let espaceCoopService: EspaceCoopService; const mockEspaceCoopCNFSModel = { create: jest.fn(), @@ -44,18 +44,18 @@ describe('EspaceCoopCNFSService', () => { ], }).compile(); - service = module.get<EspaceCoopService>(EspaceCoopService); + espaceCoopService = module.get<EspaceCoopService>(EspaceCoopService); }); it('should be defined', () => { - expect(service).toBeDefined(); + expect(espaceCoopService).toBeDefined(); }); describe('parsePermanences', () => { it('should parse correctly permanences', async () => { // Mock finding first cnfs in user database jest.spyOn(usersServiceMock, 'findOne').mockImplementationOnce(() => usersMockData[0]); - const result = await service.parsePermanences(espaceCoopPermanencesMockData); + const result = await espaceCoopService.parsePermanences(espaceCoopPermanencesMockData); expect(result).toStrictEqual(espaceCoopCNFSMockData); }); }); diff --git a/src/indicator/dto/orientation-indicator.dto.ts b/src/indicator/dto/orientation-indicator.dto.ts index e922c498d2828286e1dbbac621ffd78ba2f65be8..f18c0383c449fb8cca82e9da0241b08b53e91f15 100644 --- a/src/indicator/dto/orientation-indicator.dto.ts +++ b/src/indicator/dto/orientation-indicator.dto.ts @@ -35,6 +35,7 @@ export class OrientationIndicator { @Type(() => StructureDto) origin: { nom: string; + prescripteur: string; adresse: Address; }; @@ -55,5 +56,5 @@ export class OrientationIndicator { @IsNumber() progress: number; - createdAt?: Date; + createdAt: Date; } diff --git a/src/indicator/schemas/orientation-indicator.schema.ts b/src/indicator/schemas/orientation-indicator.schema.ts index b4f715d8710b2236ac91350a73946ad215d3f143..3f672a8071d943be6ba2a3a6317dde052730a76f 100644 --- a/src/indicator/schemas/orientation-indicator.schema.ts +++ b/src/indicator/schemas/orientation-indicator.schema.ts @@ -35,11 +35,12 @@ export class Type { export type OrientationIndicatorDocument = OrientationIndicator & Document; -@Schema({ timestamps: true }) +@Schema() export class OrientationIndicator { @Prop({ type: Object }) origin: { nom: string; + prescripteur: string; adresse: Address; }; @@ -57,6 +58,9 @@ export class OrientationIndicator { @Prop({ required: true }) progress: number; + + @Prop({ type: Date, default: Date.now }) + createdAt: Date; } export const OrientationIndicatorSchema = SchemaFactory.createForClass(OrientationIndicator); diff --git a/src/indicator/services/indicator.service.spec.ts b/src/indicator/services/indicator.service.spec.ts index b1bcf859d247816a335e414a2de4eb3a7b616b77..68b9e3480ad4b049e016bc55602314fb46e11f59 100644 --- a/src/indicator/services/indicator.service.spec.ts +++ b/src/indicator/services/indicator.service.spec.ts @@ -1,12 +1,12 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { IndicatorService } from './indicator.service'; import { getModelToken } from '@nestjs/mongoose'; -import { OrientationIndicator } from '../schemas/orientation-indicator.schema'; +import { Test, TestingModule } from '@nestjs/testing'; import { mockIndicator, mockIndicators } from '../../../test/mock/data/indicators/orientationIndicators.mock.data'; import { User } from '../../users/schemas/user.schema'; +import { OrientationIndicator } from '../schemas/orientation-indicator.schema'; +import { IndicatorService } from './indicator.service'; describe('IndicatorService', () => { - let service: IndicatorService; + let indicatorService: IndicatorService; let mockModel; beforeEach(async () => { @@ -29,18 +29,18 @@ describe('IndicatorService', () => { ], }).compile(); - service = module.get<IndicatorService>(IndicatorService); + indicatorService = module.get<IndicatorService>(IndicatorService); }); it('should be defined', () => { - expect(service).toBeDefined(); + expect(indicatorService).toBeDefined(); }); describe('createOrientation', () => { it('should create orientation indicator', async () => { mockModel.create.mockResolvedValue(mockIndicator); - const result = await service.createOrientation(mockIndicator); + const result = await indicatorService.createOrientation(mockIndicator); expect(result).toBe(mockIndicator); expect(mockModel.create).toHaveBeenCalledWith(mockIndicator); }); @@ -48,7 +48,7 @@ describe('IndicatorService', () => { it('should handle errors when creating orientation indicator', async () => { mockModel.create.mockRejectedValue(new Error('Some error')); - await expect(service.createOrientation(mockIndicator)).rejects.toThrow('Some error'); + await expect(indicatorService.createOrientation(mockIndicator)).rejects.toThrow('Some error'); }); }); @@ -56,7 +56,7 @@ describe('IndicatorService', () => { it('should retrieve all orientation indicators', async () => { mockModel.find.mockResolvedValue(mockIndicators); - const result = await service.getAllOrientation(); + const result = await indicatorService.getAllOrientation(); expect(result).toBe(mockIndicators); expect(mockModel.find).toHaveBeenCalledWith({}); }); @@ -64,7 +64,7 @@ describe('IndicatorService', () => { it('should handle errors when fetching all orientation indicators', async () => { mockModel.find.mockRejectedValue(new Error('Some fetching error')); - await expect(service.getAllOrientation()).rejects.toThrow('Some fetching error'); + await expect(indicatorService.getAllOrientation()).rejects.toThrow('Some fetching error'); }); }); }); diff --git a/src/indicator/services/indicator.service.ts b/src/indicator/services/indicator.service.ts index f07f5f7a8c5cac9dc8184198d0408b7735674876..a77c3d9bac467ecf786d882cd74151f0315fb263 100644 --- a/src/indicator/services/indicator.service.ts +++ b/src/indicator/services/indicator.service.ts @@ -34,7 +34,7 @@ export class IndicatorService { const query = {}; if (startDate || endDate) { - query['createdAt'] = {}; // replace 'dateField' with the name of your date attribute in the collection + query['createdAt'] = {}; if (startDate) { query['createdAt']['$gte'] = new Date(startDate); } diff --git a/src/mailer/mail-templates/adminStructureImport.ejs b/src/mailer/mail-templates/adminStructureImport.ejs new file mode 100644 index 0000000000000000000000000000000000000000..e08c4612b9ae8e15bcac713678f160ea459e06a5 --- /dev/null +++ b/src/mailer/mail-templates/adminStructureImport.ejs @@ -0,0 +1,6 @@ +Bonjour,<br /> +<br /> +De nouvelles structures ont été importées: +<a href="<%= config.protocol %>://<%= config.host %><%= config.port ? ':' + config.port : '' %>/admin/structure-list" + >cliquez ici pour les consulter.</a +> diff --git a/src/mailer/mail-templates/adminStructureImport.json b/src/mailer/mail-templates/adminStructureImport.json new file mode 100644 index 0000000000000000000000000000000000000000..d5bec7768862a94dadebc2d9aaa63ca7a5872751 --- /dev/null +++ b/src/mailer/mail-templates/adminStructureImport.json @@ -0,0 +1,3 @@ +{ + "subject": "Nouvelles structures importées" +} diff --git a/src/mailer/mailer.service.spec.ts b/src/mailer/mailer.service.spec.ts index 1ebbe4a9cb4748423140b4816e8c209292a28460..c6798f184c998edc210040b14965b2bb01820f24 100644 --- a/src/mailer/mailer.service.spec.ts +++ b/src/mailer/mailer.service.spec.ts @@ -1,14 +1,14 @@ import { HttpModule, HttpService } from '@nestjs/axios'; import { Test, TestingModule } from '@nestjs/testing'; -import { of, throwError } from 'rxjs'; import { AxiosResponse } from 'axios'; -import { ConfigurationService } from '../configuration/configuration.service'; -import { MailerService } from './mailer.service'; import * as fs from 'fs'; import * as path from 'path'; +import { of, throwError } from 'rxjs'; +import { ConfigurationService } from '../configuration/configuration.service'; +import { MailerService } from './mailer.service'; describe('MailerService', () => { - let service: MailerService; + let mailerService: MailerService; let httpService: HttpService; beforeEach(async () => { @@ -17,12 +17,12 @@ describe('MailerService', () => { providers: [MailerService, ConfigurationService], }).compile(); - service = module.get<MailerService>(MailerService); + mailerService = module.get<MailerService>(MailerService); httpService = module.get<HttpService>(HttpService); }); it('should be defined', () => { - expect(service).toBeDefined(); + expect(mailerService).toBeDefined(); }); describe('email sending', () => { @@ -41,7 +41,7 @@ describe('MailerService', () => { config: {}, }; jest.spyOn(httpService, 'post').mockImplementationOnce(() => of(result)); - expect(await service.send('a@a.com', 'test', '<p>This is a test</p>')).toBe(result.data); + expect(await mailerService.send('a@a.com', 'test', '<p>This is a test</p>')).toBe(result.data); }); it('should not send email', async () => { @@ -60,7 +60,7 @@ describe('MailerService', () => { }; jest.spyOn(httpService, 'post').mockImplementationOnce(() => throwError(result)); try { - await service.send('a@a.com', 'test', '<p>This is a test</p>'); + await mailerService.send('a@a.com', 'test', '<p>This is a test</p>'); } catch (e) { expect(e.data.detail).toBe('There was a validation error'); expect(e.status).toBe(400); @@ -72,7 +72,7 @@ describe('MailerService', () => { it('should get template location', async () => { jest.spyOn(path, 'join').mockImplementationOnce(() => '/path/to/template'); jest.spyOn(fs, 'existsSync').mockImplementationOnce(() => true); - expect(service.getTemplateLocation('filename')).toBe('/path/to/template'); + expect(mailerService.getTemplateLocation('filename')).toBe('/path/to/template'); }); it('should not get template location', async () => { @@ -80,7 +80,7 @@ describe('MailerService', () => { jest.spyOn(path, 'join').mockImplementationOnce(() => '/path/to/filename'); jest.spyOn(fs, 'existsSync').mockImplementationOnce(() => false); try { - expect(service.getTemplateLocation(filename)).toBe('/path/to/template'); + expect(mailerService.getTemplateLocation(filename)).toBe('/path/to/template'); } catch (e) { expect(e.message).toBe(`Email template '${filename}' cannot be found in ./src/mailer/mail-templates`); } @@ -95,7 +95,7 @@ describe('MailerService', () => { const buf = Buffer.from(JSON.stringify(data), 'utf8'); jest.spyOn(fs, 'readFileSync').mockImplementationOnce(() => buf); jest.spyOn(JSON, 'parse').mockImplementationOnce(() => JSON.stringify(data)); - expect(service.loadJsonConfig('filename')).toStrictEqual(JSON.stringify(data)); + expect(mailerService.loadJsonConfig('filename')).toStrictEqual(JSON.stringify(data)); }); it('should not get template location', async () => { @@ -103,7 +103,7 @@ describe('MailerService', () => { jest.spyOn(path, 'join').mockImplementationOnce(() => '/path/to/filename'); jest.spyOn(fs, 'existsSync').mockImplementationOnce(() => false); try { - expect(service.loadJsonConfig(filename)).toBe('/path/to/template'); + expect(mailerService.loadJsonConfig(filename)).toBe('/path/to/template'); } catch (e) { expect(e.message).toBe( `Email json definition file '${filename}' cannot be found in ./src/mailer/mail-templates` @@ -114,7 +114,7 @@ describe('MailerService', () => { it('should add signature', async () => { const test = '<p>test email</p>'; - expect(service.addSignature(test)).toBe( + expect(mailerService.addSignature(test)).toBe( `<p>test email</p><br /><br /><p>L’équipe projet inclusion numérique.</p><p style="font-family:helvetica;font-size:24px;font-weight:bold;margin:0;">rés<span style="color:red;font-weight:400;">’in</span></p><br /><br /><p>Ce mail est automatique. Merci de ne pas y répondre.</p>` ); }); diff --git a/src/migrations/scripts/1695223467052-remove-pix-label.ts b/src/migrations/scripts/1695223467052-remove-pix-label.ts new file mode 100644 index 0000000000000000000000000000000000000000..4bbeeb0189aec877c1cad85163e564163f0d7481 --- /dev/null +++ b/src/migrations/scripts/1695223467052-remove-pix-label.ts @@ -0,0 +1,30 @@ +import { Db } from 'mongodb'; +import { getDb } from '../migrations-utils/db'; + +export const up = async () => { + const db: Db = await getDb(); + + await db.collection('categories').updateOne( + { id: 'labelsQualifications' }, + { + $pull: { modules: { id: 'pix' } }, + } + ); + + await db.collection('structures').updateMany({ 'categories.labelsQualifications': 'pix' }, { + $pull: { 'categories.labelsQualifications': 'pix' }, + } as unknown); + + console.log('Updated : Pix label removed'); +}; + +export const down = async () => { + const db: Db = await getDb(); + await db.collection('categories').updateOne( + { id: 'labelsQualifications' }, + { + $push: { modules: { id: 'pix', name: 'Pix' } }, + } + ); + console.log('Downgraded : Pix label added'); +}; diff --git a/src/migrations/scripts/1695282868772-remove-cpam.ts b/src/migrations/scripts/1695282868772-remove-cpam.ts new file mode 100644 index 0000000000000000000000000000000000000000..667ec3c71ff133810a9e2d4d3d2352cddebd122d --- /dev/null +++ b/src/migrations/scripts/1695282868772-remove-cpam.ts @@ -0,0 +1,55 @@ +import { Db } from 'mongodb'; +import { getDb } from '../migrations-utils/db'; + +export const up = async () => { + const db: Db = await getDb(); + + await db.collection('categories').updateOne( + { id: 'onlineProcedures' }, + { + $pull: { modules: { id: 'cpam' } }, + } + ); + + await db.collection('categories').updateOne( + { id: 'onlineProcedures', 'modules.id': 'health' }, + { + $set: { 'modules.$.name': 'Santé (Ameli, CPAM...)' }, + } + ); + + // Iterate through cpam structures, remove cpam from onlineProcedures and add health if not already present + const cursor = db.collection('structures').find({ 'categories.onlineProcedures': 'cpam' }); + let cpamStructure; + while ((cpamStructure = await cursor.next())) { + const updatedOnlineProcedures = cpamStructure.categories.onlineProcedures.filter((item) => item !== 'cpam'); + + if (!updatedOnlineProcedures.includes('health')) { + updatedOnlineProcedures.push('health'); + } + + await db + .collection('structures') + .updateOne({ _id: cpamStructure._id }, { $set: { 'categories.onlineProcedures': updatedOnlineProcedures } }); + } + console.log('Updated : replace cpam online procedure with health'); +}; + +export const down = async () => { + const db: Db = await getDb(); + + await db.collection('categories').updateOne( + { id: 'onlineProcedures' }, + { + $push: { modules: { id: 'cpam', name: 'CPAM' } }, + } + ); + + await db.collection('categories').updateOne( + { id: 'onlineProcedures', 'modules.id': 'health' }, + { + $set: { 'modules.$.name': 'Santé (Ameli...)' }, + } + ); + console.log('Downgraded : added cpam online procedure and renamed health'); +}; diff --git a/src/migrations/scripts/1695375219601-new-structure-types.ts b/src/migrations/scripts/1695375219601-new-structure-types.ts new file mode 100644 index 0000000000000000000000000000000000000000..8265a4eadf19b17b7e5f22974419214e8fd9f235 --- /dev/null +++ b/src/migrations/scripts/1695375219601-new-structure-types.ts @@ -0,0 +1,132 @@ +import { Db } from 'mongodb'; +import { getDb } from '../migrations-utils/db'; + +export const up = async () => { + try { + const db: Db = await getDb(); + + // Maison du Rhône will become the new type "administration" + await db + .collection('structuretype') + .findOneAndUpdate({ value: 'Maison du Rhône' }, { $set: { value: 'administration' } }); + + // Mapping of old values to new values + const mapping = [ + { value: 'bijPij', newValue: 'sij' }, + { value: 'CAF', newValue: 'administration' }, + { value: 'CARSAT', newValue: 'administration' }, + { value: 'CPAM', newValue: 'administration' }, + { value: 'centreDeGestion', newValue: 'administration' }, + { value: 'prefecture', newValue: 'administration' }, + { value: 'poleEmploi', newValue: 'administration' }, + { value: 'CCAS', newValue: 'mairie' }, + ]; + + for (const map of mapping) { + // Find the old and new _id for the given value + const newStructureType = await db.collection('structuretype').findOne({ value: map.newValue }); + const oldStructureType = await db.collection('structuretype').findOne({ value: map.value }); + // Update the "structures" collection with the new _id for structureType + if (oldStructureType && newStructureType) { + await db + .collection('structures') + .updateMany({ structureType: oldStructureType._id }, { $set: { structureType: newStructureType._id } }); + } + + // Delete the old "structureType" documents + await db.collection('structuretype').deleteMany({ value: map.value }); + } + + // Remove two other obsolete structure types and empty their references in the structure collection + const toDelete = [{ value: 'EPIC' }, { value: 'MaisonFranceService' }]; + for (const del of toDelete) { + // Find the _id + const structureType = await db.collection('structuretype').findOne({ value: del.value }); + // Remove the structureType id from the "structures" collection and delete the obsolete structureType + if (structureType) { + await db + .collection('structures') + .updateMany({ structureType: structureType._id }, { $set: { structureType: null } }); + await db.collection('structuretype').deleteOne({ _id: structureType._id }); + } + } + + // Add full names in database + const nameMapping = [ + { value: 'administration', name: 'Administration' }, + { value: 'formation', name: 'Structure de formation' }, + { value: 'sij', name: 'Structure information jeunesse' }, + { value: 'espaceEmploi', name: 'Espace emploi' }, + { value: 'laPoste', name: 'La Poste' }, + { value: 'mediatheque', name: 'Médiathèque/Bibliothèque' }, + { value: 'logement', name: 'Bailleur social' }, + { value: 'association', name: 'Association' }, + { value: 'insertion', name: "Structure d'insertion" }, + { value: 'centreSocio', name: 'Centre socio-culturel' }, + { value: 'AFPA', name: 'Organisme public de formation' }, + { value: 'mairie', name: 'Mairie' }, + { value: 'mjc', name: 'MJC' }, + { value: 'missionsLocales', name: 'Mission locale' }, + { value: 'Communauté de communes', name: 'Communauté de communes' }, + { value: 'mdm', name: 'Maison de la Métropole de Lyon' }, + { value: 'Université', name: 'Université' }, + { value: 'autre', name: 'Autre' }, + ]; + // Add name field to structure types + for (const nameMap of nameMapping) { + await db.collection('structuretype').updateMany({ value: nameMap.value }, { $set: { name: nameMap.name } }); + } + + // Keep the "value" field because it is useful for elastic search to find a structure type with another search string (ex if value='mdml toto' then 'mdml' or 'toto' = maison de la métropole de lyon) + + // Change value from mdm to mdml so that searches with 'mdm 'and 'mdml' both show structures with structureType name 'Maison de la Métropole de Lyon' + await db.collection('structuretype').updateOne({ value: 'mdm' }, { $set: { value: 'mdml' } }); + + console.log('Updated : "StructureType" collection updated'); + } catch (error) { + console.error('Error updating documents:', error); + } +}; + +export const down = async () => { + try { + const db: Db = await getDb(); + + await db.collection('structuretype').drop(); + + await db.collection('structuretype').insertMany([ + { category: 'Publique', value: 'mairie', selectable: 'true' }, + { category: 'Publique', value: 'CAF', selectable: 'true' }, + { category: 'Publique', value: 'CCAS', selectable: 'true' }, + { category: 'Publique', value: 'CARSAT', selectable: 'true' }, + { category: 'Publique', value: 'poleEmploi', selectable: 'true' }, + { category: 'Publique', value: 'mdml', selectable: 'true' }, + { category: 'Publique', value: 'mediatheque', selectable: 'true' }, + { category: 'Publique', value: 'prefecture', selectable: 'true' }, + { category: 'Publique', value: 'bijPij', selectable: 'true' }, + { category: 'Publique', value: 'logement', selectable: 'true' }, + { category: 'Publique', value: 'MaisonFranceService', selectable: 'true' }, + { category: 'Publique', value: 'autre', selectable: 'false' }, + { category: 'Publique', value: 'laPoste', selectable: 'true' }, + { category: 'Publique', value: 'espaceEmploi', selectable: 'true' }, + { category: 'Publique', value: 'CPAM', selectable: 'true' }, + { category: 'Publique', value: 'AFPA', selectable: 'true' }, + { category: 'Publique', value: 'centreDeGestion', selectable: 'true' }, + { category: 'Publique', value: 'EPIC', selectable: 'true' }, + { category: 'Publique', value: 'Communauté de communes', selectable: 'true' }, + { category: 'Publique', value: 'Maison du Rhône', selectable: 'true' }, + { category: 'Publique', value: 'Université', selectable: 'true' }, + { category: 'Privée à but non lucratif', value: 'association', selectable: 'true' }, + { category: 'Privée à but non lucratif', value: 'centreSocio', selectable: 'true' }, + { category: 'Privée à but non lucratif', value: 'mjc', selectable: 'true' }, + { category: 'Privée à but non lucratif', value: 'sij', selectable: 'true' }, + { category: 'Privée à but non lucratif', value: 'missionsLocales', selectable: 'true' }, + { category: 'Privée à but lucratif', value: 'formation', selectable: 'true' }, + { category: 'Privée à but lucratif', value: 'insertion', selectable: 'true' }, + ]); + + console.log('Downgrade : old structure types have been restored (but not attached to the appropriate structures)'); + } catch (error) { + console.error('Error downgrading documents:', error); + } +}; diff --git a/src/newsletter/newsletter.controller.spec.ts b/src/newsletter/newsletter.controller.spec.ts index a34e079996430365c3d7df51b8cb428cc9de789e..4f2e38748f2872166de6922732be5e5f74fa3182 100644 --- a/src/newsletter/newsletter.controller.spec.ts +++ b/src/newsletter/newsletter.controller.spec.ts @@ -6,7 +6,7 @@ import { NewsletterSubscription } from './newsletter-subscription.schema'; import { NewsletterController } from './newsletter.controller'; import { NewsletterService } from './newsletter.service'; describe('NewsletterController', () => { - let controller: NewsletterController; + let newsletterController: NewsletterController; beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ @@ -21,28 +21,28 @@ describe('NewsletterController', () => { controllers: [NewsletterController], }).compile(); - controller = module.get<NewsletterController>(NewsletterController); + newsletterController = module.get<NewsletterController>(NewsletterController); }); it('should be defined', () => { - expect(controller).toBeDefined(); + expect(newsletterController).toBeDefined(); }); it('should subscribe user', async () => { const result = { email: 'email@test.com', mailchimpId: 'test' }; jest - .spyOn(controller, 'newsletterSubscribe') + .spyOn(newsletterController, 'newsletterSubscribe') .mockImplementation(async (): Promise<{ email; mailchimpId }> => result); const email = { email: 'email@test.com', mailchimpId: 'test' }; - expect(await controller.newsletterSubscribe(email)).toBe(result); + expect(await newsletterController.newsletterSubscribe(email)).toBe(result); }); it('should unsubscribe user', async () => { const result = { email: 'email@test.com', mailchimpId: 'test' }; jest - .spyOn(controller, 'newsletterUnsubscribe') + .spyOn(newsletterController, 'newsletterUnsubscribe') .mockImplementation(async (): Promise<{ email; mailchimpId }> => result); const email = { email: 'email@test.com', mailchimpId: 'test' }; - expect(await controller.newsletterUnsubscribe(email)).toBe(result); + expect(await newsletterController.newsletterUnsubscribe(email)).toBe(result); }); }); diff --git a/src/newsletter/newsletter.service.spec.ts b/src/newsletter/newsletter.service.spec.ts index 3149f56e69eea96b918852e32ddb7e944fd8b82e..db882fda85bbc202c4a688bdd41311153bb9809c 100644 --- a/src/newsletter/newsletter.service.spec.ts +++ b/src/newsletter/newsletter.service.spec.ts @@ -10,7 +10,7 @@ const mailchimp = require('@mailchimp/mailchimp_marketing'); jest.mock('@mailchimp/mailchimp_marketing'); describe('NewsletterService', () => { const OLD_ENV = process.env; - let service: NewsletterService; + let newsletterService: NewsletterService; const mockNewsletterModel = { create: jest.fn(), @@ -34,7 +34,7 @@ describe('NewsletterService', () => { ], }).compile(); - service = module.get<NewsletterService>(NewsletterService); + newsletterService = module.get<NewsletterService>(NewsletterService); process.env = { ...OLD_ENV }; // Make a copy process.env.MC_LIST_ID = 'abcde'; @@ -48,7 +48,7 @@ describe('NewsletterService', () => { }); it('should be defined', () => { - expect(service).toBeDefined(); + expect(newsletterService).toBeDefined(); }); describe('newsletterSubscribe', () => { @@ -56,11 +56,11 @@ describe('NewsletterService', () => { const _doc = { _id: 'a1aaaaa1a1', email: 'test2@test.com' } as INewsletterSubscription; mailchimp.lists.setListMember.mockResolvedValueOnce({ email_address: 'test2@test.com' }); jest - .spyOn(service, 'findOne') + .spyOn(newsletterService, 'findOne') .mockImplementationOnce(async (): Promise<INewsletterSubscription | undefined> => _doc); mockNewsletterModel.create.mockResolvedValueOnce(_doc); - const subscription = await service.newsletterSubscribe('test2@test.com'); + const subscription = await newsletterService.newsletterSubscribe('test2@test.com'); expect(subscription).toEqual(_doc); }); it('it should add a subscription for email test2@test.com', async () => { @@ -68,12 +68,12 @@ describe('NewsletterService', () => { const _doc = { _id: 'a1aaaaa1a1', email: 'test2@test.com' }; mailchimp.lists.setListMember.mockResolvedValueOnce({ email_address: 'test2@test.com' }); jest - .spyOn(service, 'findOne') + .spyOn(newsletterService, 'findOne') .mockImplementationOnce(async (): Promise<INewsletterSubscription | undefined> => undefined) .mockImplementationOnce(async (): Promise<INewsletterSubscription | undefined> => result); mockNewsletterModel.create.mockResolvedValueOnce(_doc); - const subscription = await service.newsletterSubscribe('test2@test.com'); + const subscription = await newsletterService.newsletterSubscribe('test2@test.com'); expect(subscription).toEqual(_doc); }); it('it should return error if mailchimp 400 issue', async () => { @@ -81,13 +81,13 @@ describe('NewsletterService', () => { const _doc = { _id: 'a1aaaaa1a1', email: 'test2@test.com' }; mailchimp.lists.setListMember.mockRejectedValueOnce({ status: 400 }); jest - .spyOn(service, 'findOne') + .spyOn(newsletterService, 'findOne') .mockImplementationOnce(async (): Promise<INewsletterSubscription | undefined> => undefined) .mockImplementationOnce(async (): Promise<INewsletterSubscription | undefined> => result); mockNewsletterModel.create.mockResolvedValueOnce(_doc); try { - await service.newsletterSubscribe('test2@test.com'); + await newsletterService.newsletterSubscribe('test2@test.com'); expect(true).toBe(false); } catch (e) { expect(e.message).toBe('Subscribe error'); @@ -99,13 +99,13 @@ describe('NewsletterService', () => { const _doc = { _id: 'a1aaaaa1a1', email: 'test2@test.com' }; mailchimp.lists.setListMember.mockRejectedValueOnce({ status: 500 }); jest - .spyOn(service, 'findOne') + .spyOn(newsletterService, 'findOne') .mockImplementationOnce(async (): Promise<INewsletterSubscription | undefined> => undefined) .mockImplementationOnce(async (): Promise<INewsletterSubscription | undefined> => result); mockNewsletterModel.create.mockResolvedValueOnce(_doc); try { - await service.newsletterSubscribe('test2@test.com'); + await newsletterService.newsletterSubscribe('test2@test.com'); expect(true).toBe(false); } catch (e) { expect(e.message).toBe('Subscribe error'); @@ -119,7 +119,7 @@ describe('NewsletterService', () => { mockNewsletterModel.findOne.mockReturnThis(); mockNewsletterModel.exec.mockResolvedValueOnce(undefined); try { - await service.newsletterUnsubscribe('test@test.com'); + await newsletterService.newsletterUnsubscribe('test@test.com'); // Fail test if above expression doesn't throw anything. expect(true).toBe(false); } catch (e) { @@ -136,10 +136,10 @@ describe('NewsletterService', () => { deleteOne: async () => _doc, } as INewsletterSubscription; jest - .spyOn(service, 'findOne') + .spyOn(newsletterService, 'findOne') .mockImplementationOnce(async (): Promise<INewsletterSubscription | undefined> => result); - const subscription = await service.newsletterUnsubscribe('test2@test.com'); + const subscription = await newsletterService.newsletterUnsubscribe('test2@test.com'); expect(subscription).toEqual(_doc); }); }); @@ -148,14 +148,14 @@ describe('NewsletterService', () => { it('it should not find a subscription with email test@test.com', async () => { mockNewsletterModel.findOne.mockReturnThis(); mockNewsletterModel.exec.mockResolvedValueOnce(undefined); - const findOneEmail = await service.findOne('test@test.com'); + const findOneEmail = await newsletterService.findOne('test@test.com'); expect(findOneEmail).toEqual(undefined); }); it('it should find a subscription with email test2@test.com', async () => { const _doc = { _id: 'a1aaaaa1a1', email: 'test2@test.com' } as INewsletterSubscription; mockNewsletterModel.findOne.mockReturnThis(); mockNewsletterModel.exec.mockResolvedValueOnce(_doc); - const findOneEmail = await service.findOne('test2@test.com'); + const findOneEmail = await newsletterService.findOne('test2@test.com'); expect(findOneEmail).toEqual(_doc); }); }); @@ -164,7 +164,7 @@ describe('NewsletterService', () => { const _docs = [{ _id: 'a1aaaaa1a1', email: 'test2@test.com' } as INewsletterSubscription]; mockNewsletterModel.find.mockReturnThis(); mockNewsletterModel.exec.mockResolvedValueOnce(_docs); - const findOneEmail = await service.findAll(); + const findOneEmail = await newsletterService.findAll(); expect(findOneEmail).toEqual(_docs); }); }); @@ -180,7 +180,7 @@ describe('NewsletterService', () => { const result = { email: 'test2@test.com', deleteOne: jest.fn() }; mockNewsletterModel.findOne.mockReturnThis(); mockNewsletterModel.exec.mockResolvedValueOnce(result).mockResolvedValueOnce(null); - await service.updateNewsletterSubscription(); + await newsletterService.updateNewsletterSubscription(); expect(mockNewsletterModel.findOne).toBeCalledTimes(2); // Remove subscription is not tested // expect(spyerDelete).toBeCalledTimes(1); diff --git a/src/online-mediation/onlineMediation.controller.spec.ts b/src/online-mediation/onlineMediation.controller.spec.ts index 12da2f398fb7c8bfbfdee1abacb8bc4fa217b730..ed01cbd4e0f2d16ae1826882c2069ec041adc124 100644 --- a/src/online-mediation/onlineMediation.controller.spec.ts +++ b/src/online-mediation/onlineMediation.controller.spec.ts @@ -6,7 +6,7 @@ import { OnlineMediation } from './onlineMediation.schema'; import { OnlineMediationService } from './onlineMediation.service'; describe('UserRegistryController', () => { - let controller: OnlineMediationController; + let onlineMediationController: OnlineMediationController; const onlineMediationServiceMock = { getAll: jest.fn(), @@ -29,24 +29,24 @@ describe('UserRegistryController', () => { controllers: [OnlineMediationController], }).compile(); - controller = module.get<OnlineMediationController>(OnlineMediationController); + onlineMediationController = module.get<OnlineMediationController>(OnlineMediationController); }); it('should be defined', () => { - expect(controller).toBeDefined(); + expect(onlineMediationController).toBeDefined(); }); describe('findAll', () => { it('should findAll entries', async () => { onlineMediationServiceMock.getAll.mockResolvedValue(onlineMediationMockData); - const reply = await controller.findAll(); + const reply = await onlineMediationController.findAll(); expect(reply).toStrictEqual(onlineMediationMockData); }); }); describe('createOnlineMediation', () => { it('should create a new entry', async () => { onlineMediationServiceMock.create.mockResolvedValue(singleOnlineMediationMock); - const reply = await controller.createOnlineMediation(singleOnlineMediationMock); + const reply = await onlineMediationController.createOnlineMediation(singleOnlineMediationMock); expect(reply).toStrictEqual(singleOnlineMediationMock); }); }); diff --git a/src/online-mediation/onlineMediation.service.spec.ts b/src/online-mediation/onlineMediation.service.spec.ts index d1a530a8266564237375c6b4e22b75c5865d28f7..264fd8e4a92924cb115ea05c3da0236e9bdc5436 100644 --- a/src/online-mediation/onlineMediation.service.spec.ts +++ b/src/online-mediation/onlineMediation.service.spec.ts @@ -1,16 +1,16 @@ +import { HttpModule } from '@nestjs/axios'; import { getModelToken } from '@nestjs/mongoose'; import { Test, TestingModule } from '@nestjs/testing'; -import { OnlineMediationService } from './onlineMediation.service'; +import * as ejs from 'ejs'; import { onlineMediationMockData } from '../../test/mock/data/onlineMediation.mock.data'; -import { MailerService } from '../mailer/mailer.service'; import { ConfigurationService } from '../configuration/configuration.service'; import { MailerModule } from '../mailer/mailer.module'; -import { HttpModule } from '@nestjs/axios'; -import * as ejs from 'ejs'; +import { MailerService } from '../mailer/mailer.service'; +import { OnlineMediationService } from './onlineMediation.service'; jest.mock('ejs'); describe('userRegistryService', () => { - let service: OnlineMediationService; + let onlineMediationService: OnlineMediationService; const mockOnlineMediationModel = { find: jest.fn(() => mockOnlineMediationModel), create: jest.fn(() => mockOnlineMediationModel), @@ -51,17 +51,17 @@ describe('userRegistryService', () => { }, ], }).compile(); - service = module.get<OnlineMediationService>(OnlineMediationService); + onlineMediationService = module.get<OnlineMediationService>(OnlineMediationService); }); it('should be defined', () => { - expect(service).toBeDefined(); + expect(onlineMediationService).toBeDefined(); }); describe('findAll', () => { it('should findAll entries', async () => { mockOnlineMediationModel.exec.mockResolvedValueOnce(onlineMediationMockData); - expect(await service.getAll()).toBe(onlineMediationMockData); + expect(await onlineMediationService.getAll()).toBe(onlineMediationMockData); }); }); describe('create', () => { @@ -70,13 +70,13 @@ describe('userRegistryService', () => { accompanimentType: 'RDV Conseiller Numérique', dateSlot: { day: 'Vendredi', hours: '15h00-17h00' }, name: 'test', - onlineDemarcheType: ['Démarches Métropolitaines', 'CPAM'], + onlineDemarcheType: ['Démarches Métropolitaines'], phone: '65 65', surname: 'teztrfzegfv', preferredLanguage: 'Français', }; mockOnlineMediationModel.create.mockResolvedValueOnce(res); - expect(await service.create(res)).toStrictEqual(res); + expect(await onlineMediationService.create(res)).toStrictEqual(res); }); }); describe('sendMailAndResetDb', () => { @@ -90,7 +90,7 @@ describe('userRegistryService', () => { mockOnlineMediationModel.exec.mockResolvedValueOnce(onlineMediationMockData.length); mockMailService.loadJsonConfig.mockReturnValueOnce({ subject: 'Teste Mail' }); ejsSpy.mockResolvedValueOnce('coucou'); - const response = await service.sendMailAndResetDb(); + const response = await onlineMediationService.sendMailAndResetDb(); expect(mailerSpy).toHaveBeenCalledTimes(1); expect(response).toBe(onlineMediationMockData.length); }); @@ -99,7 +99,7 @@ describe('userRegistryService', () => { mockOnlineMediationModel.exec.mockResolvedValueOnce(onlineMediationMockData); mockOnlineMediationModel.deleteMany.mockReturnThis(); mockOnlineMediationModel.exec.mockResolvedValueOnce(onlineMediationMockData.length); - const response = await service.sendMailAndResetDb(); + const response = await onlineMediationService.sendMailAndResetDb(); expect(mailerSpy).toHaveBeenCalledTimes(0); expect(response).toBe(onlineMediationMockData.length); }); diff --git a/src/pages/pages.controller.spec.ts b/src/pages/pages.controller.spec.ts index 3588405e54ce64b00e919bbbbf2c1f7c055a2663..daa3523a230a3300d2b63c8331d7166a6b8136d5 100644 --- a/src/pages/pages.controller.spec.ts +++ b/src/pages/pages.controller.spec.ts @@ -1,12 +1,12 @@ import { HttpModule, HttpService } from '@nestjs/axios'; import { Test, TestingModule } from '@nestjs/testing'; +import { AxiosResponse } from 'axios'; import { of } from 'rxjs'; import { ConfigurationModule } from '../configuration/configuration.module'; import { PagesController } from './pages.controller'; -import { AxiosResponse } from 'axios'; describe('PagesController', () => { - let controller: PagesController; + let pagesController: PagesController; const httpServiceMock = { get: jest.fn(), @@ -23,11 +23,11 @@ describe('PagesController', () => { controllers: [PagesController], }).compile(); - controller = module.get<PagesController>(PagesController); + pagesController = module.get<PagesController>(PagesController); }); it('should be defined', () => { - expect(controller).toBeDefined(); + expect(pagesController).toBeDefined(); }); describe('getPagebySlug', () => { @@ -84,7 +84,7 @@ describe('PagesController', () => { config: {}, }; httpServiceMock.get.mockImplementationOnce(() => of(axiosResult)); - const result = await (await controller.getPagebySlug('hello')).toPromise(); + const result = await (await pagesController.getPagebySlug('hello')).toPromise(); expect(result.pages).toStrictEqual(data); }); }); diff --git a/src/parameters/parameters.controller.spec.ts b/src/parameters/parameters.controller.spec.ts index b78180d3a3a7150a7388a919eca13d330354cbcb..8cad9081044f7ce6b6ec2a7e9f2562fb9922647b 100644 --- a/src/parameters/parameters.controller.spec.ts +++ b/src/parameters/parameters.controller.spec.ts @@ -5,7 +5,7 @@ import { ParametersService } from './parameters.service'; import { Parameters } from './schemas/parameters.schema'; describe('ParametersController', () => { - let controller: ParametersController; + let parametersController: ParametersController; const parametersServiceMock = { getParameters: jest.fn(), @@ -27,16 +27,16 @@ describe('ParametersController', () => { controllers: [ParametersController], }).compile(); - controller = module.get<ParametersController>(ParametersController); + parametersController = module.get<ParametersController>(ParametersController); }); it('should be defined', async () => { - expect(controller).toBeDefined(); + expect(parametersController).toBeDefined(); }); it('should call getParameters', async () => { const spyer = jest.spyOn(parametersServiceMock, 'getParameters'); - await controller.getParameters(); + await parametersController.getParameters(); expect(spyer).toBeCalledTimes(1); }); @@ -44,13 +44,13 @@ describe('ParametersController', () => { const spyer = jest.spyOn(parametersServiceMock, 'setParameterLockdownInfoDisplay'); afterEach(() => spyer.mockClear()); it('should call setParameterLockdownInfoDisplay(false) ', async () => { - await controller.setParameterLockdownInfoDisplay({ lockdownInfoDisplay: false }); + await parametersController.setParameterLockdownInfoDisplay({ lockdownInfoDisplay: false }); expect(spyer).toBeCalledTimes(1); expect(spyer).toBeCalledWith(false); }); it('should call setParameterLockdownInfoDisplay(true)', async () => { - await controller.setParameterLockdownInfoDisplay({ lockdownInfoDisplay: true }); + await parametersController.setParameterLockdownInfoDisplay({ lockdownInfoDisplay: true }); expect(spyer).toBeCalledTimes(1); expect(spyer).toBeCalledWith(true); }); diff --git a/src/parameters/parameters.service.spec.ts b/src/parameters/parameters.service.spec.ts index aba665562985592bcc1560c89a00e9d647d7c7c5..3b0f1375445455690c9d834c20cc9cc0ac1dd5ef 100644 --- a/src/parameters/parameters.service.spec.ts +++ b/src/parameters/parameters.service.spec.ts @@ -5,7 +5,7 @@ import { ParametersService } from './parameters.service'; import { Parameters } from './schemas/parameters.schema'; describe('ParametersService', () => { - let service: ParametersService; + let parametersService: ParametersService; const parametersModelMock = { findOne: jest.fn(), @@ -23,14 +23,14 @@ describe('ParametersService', () => { ], }).compile(); - service = module.get<ParametersService>(ParametersService); + parametersService = module.get<ParametersService>(ParametersService); }); afterEach(() => { jest.clearAllMocks(); }); it('should be defined', () => { - expect(service).toBeDefined(); + expect(parametersService).toBeDefined(); }); describe('getParameters', () => { @@ -39,7 +39,7 @@ describe('ParametersService', () => { parametersModelMock.findOne.mockReturnThis(); parametersModelMock.exec.mockResolvedValueOnce({ lockdownInfoDisplay: false }); - const result = await service.getParameters(); + const result = await parametersService.getParameters(); expect(spyer).toBeCalledTimes(1); expect(result).toEqual({ lockdownInfoDisplay: false }); }); @@ -50,7 +50,7 @@ describe('ParametersService', () => { parametersModelMock.exec.mockResolvedValueOnce(null); try { - await service.getParameters(); + await parametersService.getParameters(); expect(true).toBe(false); } catch (error) { expect(error.message).toBe('Parameters not found'); @@ -66,7 +66,7 @@ describe('ParametersService', () => { parametersModelMock.findOne.mockReturnThis(); parametersModelMock.exec.mockResolvedValueOnce({ lockdownInfoDisplay: false, save: jest.fn() }); - const result = await service.setParameterLockdownInfoDisplay(true); + const result = await parametersService.setParameterLockdownInfoDisplay(true); expect(spyer).toBeCalledTimes(1); expect(result.lockdownInfoDisplay).toEqual(true); }); @@ -77,7 +77,7 @@ describe('ParametersService', () => { parametersModelMock.exec.mockResolvedValueOnce(null); try { - await service.setParameterLockdownInfoDisplay(true); + await parametersService.setParameterLockdownInfoDisplay(true); expect(true).toBe(false); } catch (error) { expect(error.message).toBe('Parameters not found'); diff --git a/src/personal-offers/personal-offers.controller.spec.ts b/src/personal-offers/personal-offers.controller.spec.ts index 6e5ce91d59c7c13504f47bf2dc63d1dd63ae2fa4..50fe471bbea755145c42964d1c2f442f2465f86e 100644 --- a/src/personal-offers/personal-offers.controller.spec.ts +++ b/src/personal-offers/personal-offers.controller.spec.ts @@ -1,23 +1,23 @@ import { Test, TestingModule } from '@nestjs/testing'; -import { PersonalOffersController } from './personal-offers.controller'; -import { PersonalOffersService } from './personal-offers.service'; -import { PersonalOffersServiceMock } from '../../test/mock/services/personalOffers.mock.service'; -import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard'; -import { mockJwtAuthGuard } from '../../test/mock/guards/jwt-auth.mock.guard'; -import { IsPersonalOfferOwnerGuard } from '../users/guards/isPersonalOfferOwner.guard'; -import { mockIsPersonalOfferOwnerGuard } from '../../test/mock/guards/isPersonalOfferOwner.mock.guard'; import { createPersonalOffersDtoDataMock, - updatePersonalOffersDtoDataMock, personalOffersDataMock, + updatePersonalOffersDtoDataMock, } from '../../test/mock/data/personalOffers.mock.data'; -import { UsersService } from '../users/services/users.service'; +import { mockIsPersonalOfferOwnerGuard } from '../../test/mock/guards/isPersonalOfferOwner.mock.guard'; +import { mockJwtAuthGuard } from '../../test/mock/guards/jwt-auth.mock.guard'; +import { PersonalOffersServiceMock } from '../../test/mock/services/personalOffers.mock.service'; +import { StructuresServiceMock } from '../../test/mock/services/structures.mock.service'; import { UsersServiceMock } from '../../test/mock/services/user.mock.service'; +import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard'; import { StructuresService } from '../structures/services/structures.service'; -import { StructuresServiceMock } from '../../test/mock/services/structures.mock.service'; +import { IsPersonalOfferOwnerGuard } from '../users/guards/isPersonalOfferOwner.guard'; +import { UsersService } from '../users/services/users.service'; +import { PersonalOffersController } from './personal-offers.controller'; +import { PersonalOffersService } from './personal-offers.service'; describe('PersonalOffersController', () => { - let controller: PersonalOffersController; + let personalOffersController: PersonalOffersController; beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ @@ -43,20 +43,20 @@ describe('PersonalOffersController', () => { .useValue(mockIsPersonalOfferOwnerGuard) .compile(); - controller = module.get<PersonalOffersController>(PersonalOffersController); + personalOffersController = module.get<PersonalOffersController>(PersonalOffersController); }); it('should be defined', () => { - expect(controller).toBeDefined(); + expect(personalOffersController).toBeDefined(); }); describe('find personal offer', () => { it('should get personal offer', async () => { - expect(await controller.find('1234ba0e2ab5775cfc01ed3e')).toBe(personalOffersDataMock[0]); + expect(await personalOffersController.find('1234ba0e2ab5775cfc01ed3e')).toBe(personalOffersDataMock[0]); }); it('should get personal offer does not exist', async () => { try { - await controller.find('abcd'); + await personalOffersController.find('abcd'); // Fail test if above expression doesn't throw anything. expect(true).toBe(false); } catch (e) { @@ -70,7 +70,7 @@ describe('PersonalOffersController', () => { it('should return 204 if personal offer is empty', async () => { const req = { user: { _id: '6036721022462b001334c4bb' } }; try { - await controller.create(req, createPersonalOffersDtoDataMock[3]); + await personalOffersController.create(req, createPersonalOffersDtoDataMock[3]); // Fail test if above expression doesn't throw anything. expect(true).toBe(false); } catch (e) { @@ -80,12 +80,14 @@ describe('PersonalOffersController', () => { }); it('should create personal offer for existing user and structure', async () => { const req = { user: { _id: '6036721022462b001334c4bb' } }; - expect(await controller.create(req, createPersonalOffersDtoDataMock[0])).toEqual(personalOffersDataMock[0]); + expect(await personalOffersController.create(req, createPersonalOffersDtoDataMock[0])).toEqual( + personalOffersDataMock[0] + ); }); it('should return personal offer already exist in the structure', async () => { const req = { user: { _id: '6036721022462b001334c4bb' } }; try { - await controller.create(req, createPersonalOffersDtoDataMock[1]); + await personalOffersController.create(req, createPersonalOffersDtoDataMock[1]); // Fail test if above expression doesn't throw anything. expect(true).toBe(false); } catch (e) { @@ -96,7 +98,7 @@ describe('PersonalOffersController', () => { it('should return structure not found for the personal offer attachment', async () => { const req = { user: { _id: '6036721022462b001334c4bb' } }; try { - await controller.create(req, createPersonalOffersDtoDataMock[2]); + await personalOffersController.create(req, createPersonalOffersDtoDataMock[2]); // Fail test if above expression doesn't throw anything. expect(true).toBe(false); } catch (e) { @@ -107,7 +109,7 @@ describe('PersonalOffersController', () => { it('should return user not found for the personal offer attachment', async () => { const req = { user: { _id: 'unIdQuiExistePasTropTrop' } }; try { - await controller.create(req, createPersonalOffersDtoDataMock[0]); + await personalOffersController.create(req, createPersonalOffersDtoDataMock[0]); // Fail test if above expression doesn't throw anything. expect(true).toBe(false); } catch (e) { @@ -119,13 +121,13 @@ describe('PersonalOffersController', () => { describe('update personal offer', () => { it('should get updated personal offer', async () => { - expect(await controller.update('2345ba0e2ab5775cfc01ed4d', updatePersonalOffersDtoDataMock[1])).toEqual( - personalOffersDataMock[1] - ); + expect( + await personalOffersController.update('2345ba0e2ab5775cfc01ed4d', updatePersonalOffersDtoDataMock[1]) + ).toEqual(personalOffersDataMock[1]); }); it('should get invalid personal offer id', async () => { try { - await controller.update('abcd', updatePersonalOffersDtoDataMock[1]); + await personalOffersController.update('abcd', updatePersonalOffersDtoDataMock[1]); // Fail test if above expression doesn't throw anything. expect(true).toBe(false); } catch (e) { @@ -137,11 +139,11 @@ describe('PersonalOffersController', () => { describe('update personal offer', () => { it('should get deleted personal offer', async () => { - expect(await controller.delete('2345ba0e2ab5775cfc01ed4d')).toEqual(personalOffersDataMock[1]); + expect(await personalOffersController.delete('2345ba0e2ab5775cfc01ed4d')).toEqual(personalOffersDataMock[1]); }); it('should get invalid personal offer id', async () => { try { - await controller.delete('abcd'); + await personalOffersController.delete('abcd'); // Fail test if above expression doesn't throw anything. expect(true).toBe(false); } catch (e) { diff --git a/src/personal-offers/personal-offers.service.spec.ts b/src/personal-offers/personal-offers.service.spec.ts index fba7491954d573b15cd0042c2032ba323e19317d..66dccda5110dc6e26ee1830901139bcfdd0d1499 100644 --- a/src/personal-offers/personal-offers.service.spec.ts +++ b/src/personal-offers/personal-offers.service.spec.ts @@ -12,7 +12,7 @@ import { StructuresService } from './../structures/services/structures.service'; import { PersonalOffersService } from './personal-offers.service'; describe('PersonalOffersService', () => { - let service: PersonalOffersService; + let personalOffersService: PersonalOffersService; const personalOfferModelMock = { findById: jest.fn(), @@ -41,7 +41,7 @@ describe('PersonalOffersService', () => { ], }).compile(); - service = module.get<PersonalOffersService>(PersonalOffersService); + personalOffersService = module.get<PersonalOffersService>(PersonalOffersService); }); afterEach(async () => { @@ -49,21 +49,21 @@ describe('PersonalOffersService', () => { }); it('should be defined', () => { - expect(service).toBeDefined(); + expect(personalOffersService).toBeDefined(); }); describe('findOne', () => { it('should return personal offer', async () => { personalOfferModelMock.findById.mockReturnThis(); personalOfferModelMock.exec.mockResolvedValueOnce(personalOffersDataMock[0]); - expect(await service.findOne('1234ba0e2ab5775cfc01ed3e')).toEqual(personalOffersDataMock[0]); + expect(await personalOffersService.findOne('1234ba0e2ab5775cfc01ed3e')).toEqual(personalOffersDataMock[0]); }); it('should return exception if personal offer is not found for given id', async () => { personalOfferModelMock.findById.mockReturnThis(); personalOfferModelMock.exec.mockResolvedValueOnce(null); let error; try { - await service.findOne('abcd'); + await personalOffersService.findOne('abcd'); } catch (e) { error = e; } @@ -75,7 +75,7 @@ describe('PersonalOffersService', () => { describe('create', () => { it('should create personal offer', async () => { personalOfferModelMock.create.mockResolvedValueOnce(personalOffersDataMock[0]); - expect(await service.create(createPersonalOffersDtoDataMock[0])).toEqual(personalOffersDataMock[0]); + expect(await personalOffersService.create(createPersonalOffersDtoDataMock[0])).toEqual(personalOffersDataMock[0]); }); }); @@ -83,16 +83,16 @@ describe('PersonalOffersService', () => { it('should update personal offer', async () => { personalOfferModelMock.findByIdAndUpdate.mockReturnThis(); personalOfferModelMock.exec.mockResolvedValueOnce(personalOffersDataMock[1]); - expect(await service.update('2345ba0e2ab5775cfc01ed4d', updatePersonalOffersDtoDataMock[1])).toEqual( - personalOffersDataMock[1] - ); + expect( + await personalOffersService.update('2345ba0e2ab5775cfc01ed4d', updatePersonalOffersDtoDataMock[1]) + ).toEqual(personalOffersDataMock[1]); }); it('should return exception if personal offer is not found for given id', async () => { personalOfferModelMock.findById.mockReturnThis(); personalOfferModelMock.exec.mockResolvedValueOnce(null); let error; try { - await service.update('abcd', updatePersonalOffersDtoDataMock[1]); + await personalOffersService.update('abcd', updatePersonalOffersDtoDataMock[1]); } catch (e) { error = e; } @@ -105,14 +105,14 @@ describe('PersonalOffersService', () => { it('should update personal offer', async () => { personalOfferModelMock.findByIdAndDelete.mockReturnThis(); personalOfferModelMock.exec.mockResolvedValueOnce(personalOffersDataMock[0]); - expect(await service.delete('2345ba0e2ab5775cfc01ed4d')).toEqual(personalOffersDataMock[0]); + expect(await personalOffersService.delete('2345ba0e2ab5775cfc01ed4d')).toEqual(personalOffersDataMock[0]); }); it('should return exception if personal offer is not found for given id', async () => { personalOfferModelMock.findById.mockReturnThis(); personalOfferModelMock.exec.mockResolvedValueOnce(null); let error; try { - await service.delete('abcd'); + await personalOffersService.delete('abcd'); } catch (e) { error = e; } diff --git a/src/posts/posts.controller.spec.ts b/src/posts/posts.controller.spec.ts index 6aedad0dd6f8f6759343881c9722bc596c662c59..6318983820eb9d566acf9d535bb4588fdff769bb 100644 --- a/src/posts/posts.controller.spec.ts +++ b/src/posts/posts.controller.spec.ts @@ -1,13 +1,13 @@ import { HttpModule, HttpService } from '@nestjs/axios'; import { Test, TestingModule } from '@nestjs/testing'; +import { AxiosResponse } from 'axios'; import { of } from 'rxjs'; import { ConfigurationModule } from '../configuration/configuration.module'; import { PostsController } from './posts.controller'; import { PostsService } from './posts.service'; -import { AxiosResponse } from 'axios'; describe('PostsController', () => { - let controller: PostsController; + let postsController: PostsController; const httpServiceMock = { get: jest.fn(), @@ -36,11 +36,11 @@ describe('PostsController', () => { controllers: [PostsController], }).compile(); - controller = module.get<PostsController>(PostsController); + postsController = module.get<PostsController>(PostsController); }); it('should be defined', () => { - expect(controller).toBeDefined(); + expect(postsController).toBeDefined(); }); describe('findAll', () => { @@ -196,7 +196,7 @@ describe('PostsController', () => { config: {}, }; jest.spyOn(httpServiceMock, 'get').mockImplementationOnce(() => of(result)); - const response = await controller.findAll(query); + const response = await postsController.findAll(query); expect(response.posts.length).toEqual(3); expect(response.meta.pagination.limit).toEqual(15); expect(response.meta.pagination.page).toEqual(1); @@ -350,7 +350,7 @@ describe('PostsController', () => { url: 'http://localhost:2368/tag/etudes/', }, ]); - const result = await controller.findAllTags(); + const result = await postsController.findAllTags(); expect(result.commune.length).toBe(3); expect(result.others.length).toBe(1); expect(result.public.length).toBe(2); @@ -418,7 +418,7 @@ describe('PostsController', () => { }; httpServiceMock.get.mockImplementationOnce(() => of(axiosResult)); postServiceMock.formatPosts.mockImplementationOnce(() => data); - const result = await (await controller.getPostbyId('61c4847b0ff4550001505090')).toPromise(); + const result = await (await postsController.getPostbyId('61c4847b0ff4550001505090')).toPromise(); expect(result).toStrictEqual({ posts: [data] }); }); }); diff --git a/src/posts/posts.service.spec.ts b/src/posts/posts.service.spec.ts index 2ea4199e9ac576930badfa139de5e64c3e9f30f3..39b93f32aee71e46e731f9b2bfad9aad05844587 100644 --- a/src/posts/posts.service.spec.ts +++ b/src/posts/posts.service.spec.ts @@ -1,14 +1,15 @@ import { HttpModule } from '@nestjs/axios'; import { Test, TestingModule } from '@nestjs/testing'; +import * as _ from 'lodash'; import { ConfigurationModule } from '../configuration/configuration.module'; import { TagEnum } from './enums/tag.enum'; import { PostsService } from './posts.service'; -import { Tag } from './schemas/tag.schema'; -import * as _ from 'lodash'; import { Post } from './schemas/post.schema'; +import { Tag } from './schemas/tag.schema'; describe('PostsService', () => { - let service: PostsService; + let postsService: PostsService; + // let configService: ConfigurationServiceMock; const locationtags = [ { @@ -211,38 +212,38 @@ describe('PostsService', () => { providers: [PostsService], }).compile(); - service = module.get<PostsService>(PostsService); - jest.spyOn(service, 'getTags').mockImplementationOnce(async (): Promise<Tag[]> => tagsData); + postsService = module.get<PostsService>(PostsService); + jest.spyOn(postsService, 'getTags').mockImplementationOnce(async (): Promise<Tag[]> => tagsData); }); it('should be defined', () => { - expect(service).toBeDefined(); + expect(postsService).toBeDefined(); }); it('should get tags', async () => { - expect(await service.getTags()).toEqual(tagsData); + expect(await postsService.getTags()).toEqual(tagsData); }); it('should get location tags', async () => { - expect(await service.getLocationTags()).toEqual(locationtags); + expect(await postsService.getLocationTags()).toEqual(locationtags); }); it('should get public tags', async () => { - expect(await service.getPublicTags()).toEqual(publictags); + expect(await postsService.getPublicTags()).toEqual(publictags); }); it('should get regular tags', async () => { - expect(await service.getRegularTags()).toEqual([otherTags[1], otherTags[2], otherTags[0]]); + expect(await postsService.getRegularTags()).toEqual([otherTags[1], otherTags[2], otherTags[0]]); }); describe('arraymove', () => { it('should order tags for display: A La Une tag should be set to first index', () => { const dataCopy = [...otherTags]; - service.arraymove(dataCopy, _.findIndex(dataCopy, { slug: TagEnum.aLaUne }), 0); + postsService.arraymove(dataCopy, _.findIndex(dataCopy, { slug: TagEnum.aLaUne }), 0); expect(dataCopy).toEqual([otherTags[1], otherTags[0], otherTags[2]]); }); it('should order tags for display: Info tag should be set to second index', () => { const dataCopy = [...otherTags]; - expect(service.arraymove(dataCopy, _.findIndex(dataCopy, { slug: TagEnum.infos }), 1)).toEqual([ + expect(postsService.arraymove(dataCopy, _.findIndex(dataCopy, { slug: TagEnum.infos }), 1)).toEqual([ otherTags[0], otherTags[2], otherTags[1], @@ -250,8 +251,8 @@ describe('PostsService', () => { }); it('should order tags for display: A La Une tag should be set to first index and Info to second', () => { const dataCopy = [...otherTags]; - service.arraymove(dataCopy, _.findIndex(dataCopy, { slug: TagEnum.aLaUne }), 0); - expect(service.arraymove(dataCopy, _.findIndex(dataCopy, { slug: TagEnum.infos }), 1)).toEqual([ + postsService.arraymove(dataCopy, _.findIndex(dataCopy, { slug: TagEnum.aLaUne }), 0); + expect(postsService.arraymove(dataCopy, _.findIndex(dataCopy, { slug: TagEnum.infos }), 1)).toEqual([ otherTags[1], otherTags[2], otherTags[0], @@ -311,7 +312,7 @@ describe('PostsService', () => { const result = { ...postToFormat }; result.excerpt = 'Inconnu'; result.feature_image = 'https://localhost/blog/content/images/2021/12/dacc-4.png'; - expect(service.formatPosts(objCp)).toEqual(result); + expect(postsService.formatPosts(objCp)).toEqual(result); }); it('should format post with custom expert', () => { const objCp = { ...postToFormat }; @@ -319,7 +320,7 @@ describe('PostsService', () => { const result = { ...postToFormat }; result.custom_excerpt = 'Toto'; result.feature_image = 'https://localhost/blog/content/images/2021/12/dacc-4.png'; - expect(service.formatPosts(objCp)).toEqual(result); + expect(postsService.formatPosts(objCp)).toEqual(result); }); }); }); diff --git a/src/structures/interfaces/structure-formatted.interface.ts b/src/structures/interfaces/structure-formatted.interface.ts index 4f1963f21e83fc0a32a17a4028b54d53bd700944..94bb4e31dc00f6f0efbb284c67865f38b7901b60 100644 --- a/src/structures/interfaces/structure-formatted.interface.ts +++ b/src/structures/interfaces/structure-formatted.interface.ts @@ -16,7 +16,7 @@ export interface StructureFormatted extends Partial<Structure>, Partial<Document courriel?: string; latitude?: number; longitude?: number; - presentation_resume?: string; + presentation_detail?: string; publics_accueillis?: string; site_web?: string; telephone?: string; diff --git a/src/structures/interfaces/structure-search-body.interface.ts b/src/structures/interfaces/structure-search-body.interface.ts index 14857a413f2cf9931baecb307a05fe92857667ee..2541e5bb42c243e76ee73b30303604b78bea12e6 100644 --- a/src/structures/interfaces/structure-search-body.interface.ts +++ b/src/structures/interfaces/structure-search-body.interface.ts @@ -3,7 +3,8 @@ import { Address } from '../schemas/address.schema'; export interface StructureSearchBody { structureId: string; structureName: string; - structureType: string; + structureTypeName: string; + structureTypeValue: string; address: Address; description: string; } diff --git a/src/structures/services/structures-export-configs/services-config.json b/src/structures/services/structures-export-configs/services-config.json index a1285ad6ac6f43cd9e0afa43a36a30698d0e328e..a38a529d8ecd78fc6d7d9dd9b84e4a3e966dfa43 100644 --- a/src/structures/services/structures-export-configs/services-config.json +++ b/src/structures/services/structures-export-configs/services-config.json @@ -3,7 +3,6 @@ "categories": ["onlineProcedures"], "values": [ "caf", - "cpam", "idDoc", "needs", "foreigners", @@ -20,7 +19,6 @@ "categories": ["onlineProcedures"], "values": [ "caf", - "cpam", "idDoc", "needs", "foreigners", @@ -85,7 +83,7 @@ }, "Accompagner les démarches de santé": { "categories": ["onlineProcedures"], - "values": ["cpam", "health"] + "values": ["health"] }, "Promouvoir la citoyenneté numérique": { "categories": ["advancedSkills"], diff --git a/src/structures/services/structures-export.service.spec.ts b/src/structures/services/structures-export.service.spec.ts index 4198874c100bf0a49fa22549284a6fa333155c96..d659ae40fc277efded2f46048606fb30b2e0109a 100644 --- a/src/structures/services/structures-export.service.spec.ts +++ b/src/structures/services/structures-export.service.spec.ts @@ -1,11 +1,11 @@ -import { Test, TestingModule } from '@nestjs/testing'; import { getModelToken } from '@nestjs/mongoose'; -import { StructuresExportService } from './structures-export.service'; +import { Test, TestingModule } from '@nestjs/testing'; import { Model, Query } from 'mongoose'; -import { StructureDocument } from '../schemas/structure.schema'; -import { StructureFormatted } from '../interfaces/structure-formatted.interface'; import { mockFormattedStructures } from '../../../test/mock/services/structures-export.mock.service'; +import { StructureFormatted } from '../interfaces/structure-formatted.interface'; +import { StructureDocument } from '../schemas/structure.schema'; import { StructureCategories } from '../schemas/structureCategories.schema'; +import { StructuresExportService } from './structures-export.service'; import { StructuresService } from './structures.service'; const mockStructureModel = { @@ -140,7 +140,7 @@ function createMockedStructure(overrides: Partial<StructureDocument> = {}) { } describe('StructuresExportService', () => { - let service: StructuresExportService; + let structureExportService: StructuresExportService; let structureModel: Model<StructureDocument>; beforeEach(async () => { @@ -160,7 +160,7 @@ describe('StructuresExportService', () => { ], }).compile(); - service = module.get<StructuresExportService>(StructuresExportService); + structureExportService = module.get<StructuresExportService>(StructuresExportService); structureModel = module.get<Model<StructureDocument>>(getModelToken('Structure')); }); @@ -177,7 +177,7 @@ describe('StructuresExportService', () => { jest.spyOn(structureModel, 'find').mockReturnValueOnce(mockQuery); const expectedFormattedStructure: StructureFormatted = mockFormattedStructures[0]; - const result: StructureFormatted[] = await service.exportFormatted(); + const result: StructureFormatted[] = await structureExportService.exportFormatted(); expect(structureModel.find).toHaveBeenCalledWith({ deletedAt: { $exists: false }, @@ -190,7 +190,7 @@ describe('StructuresExportService', () => { describe('checkPublic', () => { const invokeCheckPublic = (age: string[], handicaps: string[], languages: string[], other: string[]) => - (service as any).checkPublic(age, handicaps, languages, other); // any to bypass ts access checks on private method + (structureExportService as any).checkPublic(age, handicaps, languages, other); // any to bypass ts access checks on private method it('should return an empty string when no parameters are provided', () => { const result = invokeCheckPublic([], [], [], []); expect(result).toEqual(''); @@ -225,7 +225,7 @@ describe('StructuresExportService', () => { describe('checkAccessConditions', () => { const invokeCheckAccessConditions = (accessModality: string[]) => - (service as any).checkAccessConditions(accessModality); // any to bypass ts access checks on private method + (structureExportService as any).checkAccessConditions(accessModality); // any to bypass ts access checks on private method it('should return an empty string when no access modality is provided', () => { const result = invokeCheckAccessConditions([]); @@ -246,7 +246,8 @@ describe('StructuresExportService', () => { }); describe('formatServices', () => { - const invokeFormatServices = (structCat: StructureCategories) => (service as any).formatServices(structCat); // any to bypass ts access checks on private method + const invokeFormatServices = (structCat: StructureCategories) => + (structureExportService as any).formatServices(structCat); // any to bypass ts access checks on private method it('should return an empty string when no structure categories are provided', () => { const result = invokeFormatServices(null); @@ -286,7 +287,7 @@ describe('StructuresExportService', () => { describe('formatAddress', () => { const invokeFormatAddress = (address: { numero?: string; street: string }) => - (service as any).formatAddress(address); // any to bypass ts access checks on private method + (structureExportService as any).formatAddress(address); // any to bypass ts access checks on private method it('should return the formatted address with street only when no numero is provided', () => { const address = { street: 'Rue Robert et Reynier' }; @@ -303,7 +304,7 @@ describe('StructuresExportService', () => { describe('convertToOSMFormat', () => { const invokeConvertToOSMFormat = (openingHours: Record<string, any>) => - (service as any).convertToOSMFormat(openingHours); // any to bypass ts access checks on private method + (structureExportService as any).convertToOSMFormat(openingHours); // any to bypass ts access checks on private method it('should return empty string when openingHours is empty', () => { const openingHours = { diff --git a/src/structures/services/structures-export.service.ts b/src/structures/services/structures-export.service.ts index ca4b0613b579f2e02d051ad79ca700efc101f4f9..b7a41cc947ecddf30f6b9bb5882115ebcc95f336 100644 --- a/src/structures/services/structures-export.service.ts +++ b/src/structures/services/structures-export.service.ts @@ -23,24 +23,23 @@ export class StructuresExportService { const structures = await this.structureModel .find({ deletedAt: { $exists: false }, accountVerified: true, $where: 'this.dataShareConsentDate != null' }) .populate('personalOffers') - .select('-_id -accountVerified -otherDescription -dataShareConsentDate') + .select('-accountVerified -otherDescription -dataShareConsentDate') .exec(); return structures.map((structure) => { // Set the offers from the structure and from its personalOffers - this.structureService.setCategoriesWithPersonalOffers(structure); + this.structureService.setCategoriesWithPersonalOffers(structure, true); // Set the categories with personalOffers in structure.categories which is used in the services export below structure.categories.onlineProcedures = structure.categoriesWithPersonalOffers.onlineProcedures; structure.categories.baseSkills = structure.categoriesWithPersonalOffers.baseSkills; structure.categories.advancedSkills = structure.categoriesWithPersonalOffers.advancedSkills; - const formatted: StructureFormatted = { // TODO add antenne field + id: structure.id, adresse: this.formatAddress(structure.address), code_postal: structure.address?.postcode, commune: structure.address?.commune, date_maj: this.formatDate(structure.updatedAt), - id: structure.id, nom: structure.structureName, pivot: '00000000000000', // for now we don't have a pivot services: this.formatServices(structure.categories), @@ -50,7 +49,7 @@ export class StructuresExportService { ...(structure.contactMail && { courriel: structure.contactMail }), ...(structure.coord && { longitude: structure.coord[0] }), ...(structure.coord && { latitude: structure.coord[1] }), - ...(structure.description && { presentation_resume: structure.description }), + ...(structure.description && { presentation_detail: structure.description }), ...((structure.categories.age || structure.categories.handicaps || structure.categories.languageAndIlliteracy || diff --git a/src/structures/services/structures-import.service.spec.ts b/src/structures/services/structures-import.service.spec.ts index 4fce87cccc07c72c5032771a96e749fd0ab836d7..60d5d6e736730d45e3fbc61bcde5506aa914cfd7 100644 --- a/src/structures/services/structures-import.service.spec.ts +++ b/src/structures/services/structures-import.service.spec.ts @@ -1,15 +1,21 @@ -import { Test, TestingModule } from '@nestjs/testing'; import { getModelToken } from '@nestjs/mongoose'; -import { StructuresImportService } from './structures-import.service'; +import { Test, TestingModule } from '@nestjs/testing'; import { of } from 'rxjs'; import { DataGouvStructure } from '../interfaces/data-gouv-structure.interface'; import { HttpService } from '@nestjs/axios'; import { AxiosResponse } from 'axios'; import { mockGouvStructure, mockGouvStructureToResinFormat } from '../../../test/mock/data/gouvStructures.mock.data'; +import { StructuresSearchService } from './structures-search.service'; +import { StructuresService } from './structures.service'; +import { MailerService } from '../../mailer/mailer.service'; +import { StructuresImportService } from './structures-import.service'; describe('StructuresImportService', () => { - let service: StructuresImportService; + let structuresImportService: StructuresImportService; let httpService: HttpService; + let structuresSearchService: StructuresSearchService; + let structuresService: StructuresService; + let mailerService: MailerService; beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ @@ -21,6 +27,29 @@ describe('StructuresImportService', () => { get: jest.fn(), }, }, + { + provide: StructuresSearchService, + useValue: { + indexStructure: jest.fn().mockResolvedValue(undefined), + }, + }, + { + provide: StructuresService, + useValue: { + updateDenormalizedFields: jest.fn().mockResolvedValue(undefined), + sendAdminNotificationAfterImportingStructure: jest.fn().mockImplementation(() => of(undefined)), + }, + }, + { + provide: MailerService, + useValue: { + config: { + templates: { + adminStructureImport: { ejs: null, json: null }, + }, + }, + }, + }, { provide: getModelToken('Structure'), useValue: { @@ -32,8 +61,11 @@ describe('StructuresImportService', () => { ], }).compile(); - service = module.get<StructuresImportService>(StructuresImportService); + structuresImportService = module.get<StructuresImportService>(StructuresImportService); httpService = module.get<HttpService>(HttpService); + structuresSearchService = module.get<StructuresSearchService>(StructuresSearchService); + structuresService = module.get<StructuresService>(StructuresService); + mailerService = module.get<MailerService>(MailerService); }); describe('importDataGouvStructures', () => { @@ -45,15 +77,26 @@ describe('StructuresImportService', () => { headers: {}, config: {}, }; - const saveSpy = jest.fn(); + + const saveSpy = jest + .fn() + .mockResolvedValue({ id: 'b145231d-7388-4444-a54e-138298a4fff9|res-in-606715119f33ab0013a1cbad' }); const mockStructureModel = jest.fn().mockImplementation(() => ({ save: saveSpy })); - (service as any).structureModel = mockStructureModel; + (structuresImportService as any).structureModel = mockStructureModel; - const formatToResinSchemaSpy = jest.spyOn(service as any, 'formatToResinSchema').mockResolvedValueOnce('called'); - const doesAlreadyExistSpy = jest.spyOn(service as any, 'doesAlreadyExist').mockResolvedValueOnce(false); + const formatToResinSchemaSpy = jest + .spyOn(structuresImportService as any, 'formatToResinSchema') + .mockResolvedValueOnce('called'); + const doesAlreadyExistSpy = jest + .spyOn(structuresImportService as any, 'doesAlreadyExist') + .mockResolvedValueOnce(false); jest.spyOn(httpService, 'get').mockImplementationOnce(() => of(mockedAxiosResponse)); - await service.importDataGouvStructures(); + jest.spyOn(structuresSearchService, 'indexStructure').mockResolvedValueOnce(undefined); + + jest.spyOn(structuresService, 'updateDenormalizedFields').mockResolvedValueOnce(undefined); + + await structuresImportService.importDataGouvStructures(); expect(httpService.get).toBeCalled(); expect(formatToResinSchemaSpy).toBeCalled(); @@ -64,8 +107,87 @@ describe('StructuresImportService', () => { describe('formatToResinSchema', () => { it('should transform data.gouv structures to resin format', async () => { - const result = await service['formatToResinSchema'](mockGouvStructure); + const result = await structuresImportService['formatToResinSchema'](mockGouvStructure); expect(result).toEqual(mockGouvStructureToResinFormat); }); }); + + describe('convertFromOSMFormat', () => { + it('should convert simple weekday format', () => { + const osmFormat = 'Mo-Fr 08:30-12:30'; + const result = structuresImportService['convertFromOSMFormat'](osmFormat); + + expect(result.monday.open).toBe(true); + expect(result.monday.time).toEqual([{ opening: '08:30', closing: '12:30' }]); + expect(result.tuesday.time).toEqual([{ opening: '08:30', closing: '12:30' }]); + expect(result.wednesday.time).toEqual([{ opening: '08:30', closing: '12:30' }]); + expect(result.thursday.time).toEqual([{ opening: '08:30', closing: '12:30' }]); + expect(result.friday.time).toEqual([{ opening: '08:30', closing: '12:30' }]); + expect(result.saturday.open).toBe(false); + expect(result.sunday.open).toBe(false); + }); + + it('should handle a day marked as off', () => { + const osmFormat = 'Mo-Fr 08:30-12:30; We off'; + const result = structuresImportService['convertFromOSMFormat'](osmFormat); + + expect(result.wednesday.open).toBe(false); + }); + + it('should handle days marked as off', () => { + const osmFormat = 'Mo-Fr 08:30-12:30; We,Th off'; + const result = structuresImportService['convertFromOSMFormat'](osmFormat); + + expect(result.wednesday.open).toBe(false); + expect(result.thursday.open).toBe(false); + }); + + it('should handle multiple time ranges', () => { + const osmFormat = 'Mo-Fr 08:30-12:30,13:30-17:30'; + const result = structuresImportService['convertFromOSMFormat'](osmFormat); + + expect(result.monday.time).toEqual([ + { opening: '08:30', closing: '12:30' }, + { opening: '13:30', closing: '17:30' }, + ]); + }); + + it('should handle individual days with multiple time ranges', () => { + const osmFormat = 'Mo,We 08:30-12:30,13:30-17:30'; + const result = structuresImportService['convertFromOSMFormat'](osmFormat); + + expect(result.monday.time).toEqual([ + { opening: '08:30', closing: '12:30' }, + { opening: '13:30', closing: '17:30' }, + ]); + expect(result.wednesday.time).toEqual([ + { opening: '08:30', closing: '12:30' }, + { opening: '13:30', closing: '17:30' }, + ]); + }); + + it('should handle complex OSM format', () => { + const osmFormat = 'Mo-Fr 08:30-12:30,13:30-17:30; We,Th off'; + const result = structuresImportService['convertFromOSMFormat'](osmFormat); + + expect(result.monday.time).toEqual([ + { opening: '08:30', closing: '12:30' }, + { opening: '13:30', closing: '17:30' }, + ]); + expect(result.wednesday.open).toBe(false); + expect(result.thursday.open).toBe(false); + }); + + it('should handle a very complex OSM format', () => { + const osmFormat = 'Mo-Sa 08:30-11:45; Fr 08:30-11:45,14:30-16:45; We off '; + const result = structuresImportService['convertFromOSMFormat'](osmFormat); + + expect(result.monday.time).toEqual([{ opening: '08:30', closing: '11:45' }]); + expect(result.wednesday.open).toBe(false); + expect(result.friday.time).toEqual([ + { opening: '08:30', closing: '11:45' }, + { opening: '14:30', closing: '16:45' }, + ]); + }); + }); }); diff --git a/src/structures/services/structures-import.service.ts b/src/structures/services/structures-import.service.ts index fa83a7ecca1efe6fa82603c11bf9795db13f8c45..13290a2eec926c5a4be44d3007d826a3a72bc122 100644 --- a/src/structures/services/structures-import.service.ts +++ b/src/structures/services/structures-import.service.ts @@ -1,7 +1,7 @@ import { Injectable, Logger } from '@nestjs/common'; import { StructureFormatted } from '../interfaces/structure-formatted.interface'; import { HttpService } from '@nestjs/axios'; -import { Model } from 'mongoose'; +import { Model, Types } from 'mongoose'; import { Structure, StructureDocument } from '../schemas/structure.schema'; import { InjectModel } from '@nestjs/mongoose'; import { Cron, CronExpression } from '@nestjs/schedule'; @@ -11,6 +11,9 @@ import { Week } from '../../shared/schemas/week.schema'; import { Day } from '../schemas/day.schema'; import { Time } from '../schemas/time.schema'; import { DataGouvStructure } from '../interfaces/data-gouv-structure.interface'; +import { StructuresSearchService } from './structures-search.service'; +import { StructuresService } from './structures.service'; +import { MailerService } from '../../mailer/mailer.service'; interface Condition { address?: { street?: string; numero?: string }; contactMail?: string; @@ -23,6 +26,9 @@ export class StructuresImportService { private readonly logger = new Logger(StructuresImportService.name); constructor( private readonly httpService: HttpService, + private structuresSearchService: StructuresSearchService, + private structuresService: StructuresService, + private readonly mailerService: MailerService, @InjectModel(Structure.name) private structureModel: Model<StructureDocument> ) {} @@ -53,23 +59,50 @@ export class StructuresImportService { } private async processStructures(structures: DataGouvStructure[]): Promise<void> { - let newOne = 0; - let skipped = 0; + let newCount = 0; + let skippedCount = 0; + let errorCount = 0; + for (const structure of structures) { - if (await this.doesAlreadyExist(structure)) { - skipped++; - } else { - await this.createStructure(structure); - newOne++; + try { + if (await this.doesAlreadyExist(structure)) { + skippedCount++; + } else { + await this.createStructure(structure); + newCount++; + } + } catch (error) { + errorCount++; + this.logger.error( + `Failed to process structure with ID ${structure.id || 'unknown'}: ${error.message}`, + error.stack + ); + } + } + + this.logger.log( + `Created ${newCount} new structures, skipped ${skippedCount} structures, and encountered errors in ${errorCount} structures...` + ); + + if (newCount > 0) { + try { + await this.structuresService.sendAdminNotificationAfterImportingStructure( + this.mailerService.config.templates.adminStructureImport.ejs, + this.mailerService.config.templates.adminStructureImport.json + ); + } catch (notificationError) { + this.logger.error(`Failed to send admin notification: ${notificationError.message}`, notificationError.stack); } } - this.logger.log(`Created ${newOne} new structures and skipped ${skipped} structures...`); } private async createStructure(structure: DataGouvStructure): Promise<void> { const formattedStructure = await this.formatToResinSchema(structure); const newStructure = new this.structureModel(formattedStructure); - await newStructure.save(); + const createdStructure = await newStructure.save(); + // call indexStructure, updateDenormalizedFields accordingly when creating a new structure + await this.structuresSearchService.indexStructure(createdStructure); + await this.structuresService.updateDenormalizedFields(new Types.ObjectId(createdStructure._id)); } private async doesAlreadyExist(structure: DataGouvStructure): Promise<boolean> { @@ -117,8 +150,8 @@ export class StructuresImportService { structure.publics_accueillis ), coord: [structure.longitude, structure.latitude], - description: structure.presentation_resume ?? null, - contactPhone: structure.telephone ?? null, + description: structure.presentation_detail ?? null, + contactPhone: structure.telephone?.replace(/^\+33/, '0') ?? null, contactMail: structure.courriel ?? null, hours: this.convertFromOSMFormat(structure.horaires), accountVerified: true, @@ -260,54 +293,73 @@ export class StructuresImportService { week[day].time = []; }); - if (osmHours === undefined) { + if (!osmHours) { return week; } - const entries = osmHours.split(';'); - + // Normalize the osmHours string by removing any spaces after semicolons and then split it into individual time entries. + const entries = osmHours.replace(/;\s+/g, ';').split(';'); entries.forEach((entry) => { - // split by ',' to get individual time ranges for each day(s) - const timeRanges = entry.split(','); - - timeRanges.forEach((timeRange) => { - // split by ' ' to separate days and time - const [days, times] = timeRange.trim().split(' '); - - // check if days contains ',' then handle as individual days - if (days.includes(',')) { - const individualDays = days.split(','); - individualDays.forEach((day) => { - const startIndex = daysOfWeek.indexOf(day.toLowerCase()); - if (times) { - const [opening, closing] = times.split('-'); - week[fullDaysOfWeek[startIndex]].open = true; - week[fullDaysOfWeek[startIndex]].time.push({ opening, closing } as Time); - } - }); - } else { - // split days by '-' to handle ranges (Tu-We) - const [startDay, endDay] = days.toLowerCase().split('-'); + const trimmedEntry = entry.trim(); - // find start and end indexes in the week for the range - const startIndex = daysOfWeek.indexOf(startDay); - let endIndex = daysOfWeek.indexOf(endDay); + // Check for "off" conditions first + if (trimmedEntry.includes('off')) { + const daysToClose = trimmedEntry.replace(' off', ''); // remove 'off' - // if endDay is not provided, assume it's the same as startDay - if (endIndex === -1) { - endIndex = startIndex; - } + if (daysToClose.includes('-')) { + // Range of days + const [startDay, endDay] = daysToClose.split('-').map((d) => d.trim()); + const startIndex = daysOfWeek.indexOf(startDay.toLowerCase()); + const endIndex = daysOfWeek.indexOf(endDay.toLowerCase()); - // iterate over the range of days and set the hours - if (times) { - const [opening, closing] = times.split('-'); - for (let i = startIndex; i <= endIndex; i++) { - week[fullDaysOfWeek[i]].open = true; + for (let i = startIndex; i <= endIndex; i++) { + week[fullDaysOfWeek[i]].open = false; + week[fullDaysOfWeek[i]].time = []; + } + } else { + // Discrete days, split by comma + const splitDays = daysToClose.split(','); + splitDays.forEach((day) => { + const dayIndex = daysOfWeek.indexOf(day.trim().toLowerCase()); + week[fullDaysOfWeek[dayIndex]].open = false; + week[fullDaysOfWeek[dayIndex]].time = []; + }); + } + } else { + const [days, times] = trimmedEntry.split(' '); + + // Handle day ranges like Mo-Fr or individual days + if (days.includes('-')) { + const [startDay, endDay] = days.split('-'); + const startIndex = daysOfWeek.indexOf(startDay.toLowerCase()); + const endIndex = daysOfWeek.indexOf(endDay.toLowerCase()); + + const timeIntervals = times.split(','); + for (let i = startIndex; i <= endIndex; i++) { + week[fullDaysOfWeek[i]].open = true; + timeIntervals.forEach((interval) => { + const [opening, closing] = interval.trim().split('-'); week[fullDaysOfWeek[i]].time.push({ opening, closing } as Time); - } + }); } + } else { + // Discrete days, split by comma + const splitDays = days.split(','); + splitDays.forEach((day) => { + const dayIndex = daysOfWeek.indexOf(day.trim().toLowerCase()); + + // Clear previous timings for the day if they exist + week[fullDaysOfWeek[dayIndex]].time = []; + + const timeSplits = times.split(','); + timeSplits.forEach((time) => { + const [opening, closing] = time.split('-'); + week[fullDaysOfWeek[dayIndex]].open = true; + week[fullDaysOfWeek[dayIndex]].time.push({ opening, closing } as Time); + }); + }); } - }); + } }); return week; diff --git a/src/structures/services/structures-search.service.ts b/src/structures/services/structures-search.service.ts index 810e1bf20442df031f1f8a1bd87dcf245e2723a7..58011d63ca8089152699cc9f755deef13402bf65 100644 --- a/src/structures/services/structures-search.service.ts +++ b/src/structures/services/structures-search.service.ts @@ -19,7 +19,7 @@ export class StructuresSearchService { public async indexStructure(structure: StructureDocument): Promise<StructureDocument> { this.logger.debug(`indexStructure`); - this.elasticsearchService.index<StructureSearchBody>({ + await this.elasticsearchService.index<StructureSearchBody>({ index: this.index, id: structure._id, document: this.formatIndexBody(structure), @@ -30,7 +30,8 @@ export class StructuresSearchService { private formatIndexBody(structure: StructureDocument): StructureSearchBody { return { structureName: structure.structureName, - structureType: structure.structureType?.value, + structureTypeName: structure.structureType?.name, + structureTypeValue: structure.structureType?.value, structureId: structure._id, address: structure.address, description: structure.description, @@ -111,7 +112,14 @@ export class StructuresSearchService { query: escapeElasticsearchQuery(searchString), fields: fields ? fields - : ['structureName^5', 'structureType^5', 'address.commune^10', 'address.postcode^5', 'description'], + : [ + 'structureName^5', + 'structureTypeName^5', + 'structureTypeValue^5', + 'address.commune^10', + 'address.postcode^5', + 'description', + ], fuzziness: 'AUTO', }, }, @@ -124,7 +132,7 @@ export class StructuresSearchService { } public async update(structure: StructureDocument, id: string): Promise<UpdateResponse<unknown>> { - this.logger.debug('update'); + this.logger.debug(`Update ES structure: ${structure.structureName}`); return this.elasticsearchService.update({ index: this.index, id: id, diff --git a/src/structures/services/structures.service.spec.ts b/src/structures/services/structures.service.spec.ts index e7d60ff04f22172e0708c5d738a13157ca00202b..362e8df5110198fa4906041ab5575c77037fef0e 100644 --- a/src/structures/services/structures.service.spec.ts +++ b/src/structures/services/structures.service.spec.ts @@ -63,7 +63,7 @@ const mockStructuresSearchService = { socialAndProfessional: ['6', '20', '66', '67', '68', '69', '124', '125', '127'], accessRight: ['84', '85', '86', '87', '88', '89', '93', '95'], baseSkills: ['260', '1', '11', '38', '48', '74', '77'], - proceduresAccompaniment: ['cpam', 'impots', 'carsat', 'poleEmploi'], + proceduresAccompaniment: ['impots', 'carsat', 'poleEmploi'], publics: ['toutPublic'], labelsQualifications: ['passNumerique', 'espacePublicNumeriqueepn'], accessModality: ['accesLibre', 'telephoneVisio', 'surRdv'], @@ -239,7 +239,7 @@ const jobServiceMock = { }; describe('StructuresService', () => { - let service: StructuresService; + let structureService: StructuresService; beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ @@ -279,17 +279,17 @@ describe('StructuresService', () => { ], }).compile(); - service = module.get<StructuresService>(StructuresService); - service['structuresSearchService']['index'] = 'structures-unit-test'; - service['sendToBeDeletedNotification'] = jest.fn(); + structureService = module.get<StructuresService>(StructuresService); + structureService['structuresSearchService']['index'] = 'structures-unit-test'; + structureService['sendToBeDeletedNotification'] = jest.fn(); }); it('should be defined', () => { - expect(service).toBeDefined(); + expect(structureService).toBeDefined(); }); it('should Initiate structure index', async () => { - await service.initiateStructureIndex(); + await structureService.initiateStructureIndex(); expect(mockStructuresSearchService.createStructureIndex).toBeCalledTimes(1); expect(mockStructuresSearchService.dropIndex).toBeCalledTimes(1); expect(mockStructuresSearchService.indexStructure).toBeCalledTimes(1); @@ -310,7 +310,7 @@ describe('StructuresService', () => { socialAndProfessional: ['6', '20', '66', '67', '68', '69', '124', '125', '127'], accessRight: ['84', '85', '86', '87', '88', '89', '93', '95'], baseSkills: ['260', '1', '11', '38', '48', '74', '77'], - proceduresAccompaniment: ['cpam', 'impots', 'carsat', 'poleEmploi'], + proceduresAccompaniment: ['impots', 'carsat', 'poleEmploi'], publics: ['toutPublic'], labelsQualifications: ['passNumerique', 'espacePublicNumeriqueepn'], accessModality: ['accesLibre', 'telephoneVisio', 'surRdv'], @@ -365,23 +365,26 @@ describe('StructuresService', () => { nbScanners: 1, otherDescription: null, personalOffers: [], + categories: { + onlineProcedures: ['caf'], + }, }, ]); it('should find 1 structure', async () => { - const res = await service.searchForStructures('a', [[{ nbPrinters: '1' }]]); + const res = await structureService.searchForStructures('a', [[{ nbPrinters: '1' }]]); expect(res.length).toBe(1); }); it('should find 1 structure', async () => { - const res = await service.searchForStructures('a', [[{ nbPrinters: '1' }, { '': 'baseSkills' }]]); + const res = await structureService.searchForStructures('a', [[{ nbPrinters: '1' }, { onlineProcedures: 'caf' }]]); expect(res.length).toBe(1); }); - it('should find 1 structure', async () => { - const res = await service.searchForStructures('a', [[{ '': 'baseSkills' }]]); - expect(res.length).toBe(1); + it('should find 0 structure with personalOffer', async () => { + const res = await structureService.searchForStructures('a', [[{ onlineProcedures: 'caf' }]], null, true); + expect(res.length).toBe(0); }); it('should find 1 structure', async () => { - const res = await service.searchForStructures('a'); + const res = await structureService.searchForStructures('a'); expect(res.length).toBe(1); }); }); @@ -389,7 +392,7 @@ describe('StructuresService', () => { describe('create', () => { it('should return invalid profile', async () => { try { - await service.create('test@test.com', structureMockDto); + await structureService.create('test@test.com', structureMockDto); expect(true).toBe(false); } catch (e) { expect(e.message).toEqual('Invalid profile'); @@ -399,46 +402,46 @@ describe('StructuresService', () => { }); it('should set structure to be deleted', async () => { - const res = await service.setToBeDeleted(userDetails[0], structuresDocumentDataMock[0]); + const res = await structureService.setToBeDeleted(userDetails[0], structuresDocumentDataMock[0]); expect(res.toBeDeletedAt).toBeTruthy(); }); it('should cancel structure delete', async () => { - const res = await service.cancelDelete(userDetails[0], structuresDocumentDataMock[0]); + const res = await structureService.cancelDelete(userDetails[0], structuresDocumentDataMock[0]); expect(res.toBeDeletedAt).toBeNull(); }); it('should search structure', () => { const filters = [{ nbPrinters: '1' }]; - let res = service.search('', filters); + let res = structureService.search('', filters); expect(res).toBeTruthy(); - res = service.search(null, filters); + res = structureService.search(null, filters); expect(res).toBeTruthy(); - res = service.search(null); + res = structureService.search(null); expect(res).toBeTruthy(); }); describe('findAll', () => { it('should find all structures', () => { - expect(service.findAll()).toBeTruthy(); + expect(structureService.findAll()).toBeTruthy(); }); it('should find all deleted structures', () => { - expect(service.findAll(true)).toBeTruthy(); + expect(structureService.findAll(true)).toBeTruthy(); }); it('should find all unclaimed structures', () => { - expect(service.findAllUnclaimed()).toBeTruthy(); + expect(structureService.findAllUnclaimed()).toBeTruthy(); }); it('should find all formatted structures', () => { mockStructureModel.exec.mockResolvedValue([]); - expect(service.findConsentingStructures(null)).toBeTruthy(); + expect(structureService.findConsentingStructures(null)).toBeTruthy(); }); }); it('should populate ES', () => { - expect(service.populateES()).toBeTruthy(); + expect(structureService.populateES()).toBeTruthy(); }); describe('getAllDataConsentPendingStructures', () => { @@ -468,7 +471,7 @@ describe('StructuresService', () => { createdAt: new Date('2022-05-25T09:48:28.824Z'), } as IUser; jest - .spyOn(service, 'findOne') + .spyOn(structureService, 'findOne') .mockResolvedValueOnce({ _id: new Types.ObjectId('61e9260b2ac971550065e261'), coord: [4.844309, 45.865288], @@ -490,7 +493,7 @@ describe('StructuresService', () => { updatedAt: new Date('Thu Jan 20 2022 10:06:19 GMT+0100 (heure normale d’Europe centrale)'), dataShareConsentDate: new Date(), } as StructureDocument); - const res = await service.getAllDataConsentPendingStructures(user); + const res = await structureService.getAllDataConsentPendingStructures(user); expect(res.length).toBe(1); }); it('should get no consent', async () => { @@ -519,7 +522,7 @@ describe('StructuresService', () => { createdAt: new Date('2022-05-25T09:48:28.824Z'), } as IUser; jest - .spyOn(service, 'findOne') + .spyOn(structureService, 'findOne') .mockResolvedValueOnce({ _id: new Types.ObjectId('61e9260b2ac971550065e261'), coord: [4.844309, 45.865288], @@ -542,7 +545,7 @@ describe('StructuresService', () => { updatedAt: new Date('Thu Jan 20 2022 10:06:19 GMT+0100 (heure normale d’Europe centrale)'), dataShareConsentDate: new Date(), } as StructureDocument); - const res = await service.getAllDataConsentPendingStructures(user); + const res = await structureService.getAllDataConsentPendingStructures(user); expect(res.length).toBe(0); }); }); @@ -554,16 +557,16 @@ describe('StructuresService', () => { describe('addPersonalOffer', () => { const personalOfferDocumentMock: PersonalOfferDocument = personalOffersDataMock[0] as PersonalOfferDocument; it('should add personal offer to the structure', async () => { - jest.spyOn(service, 'findOne').mockResolvedValue(structuresDocumentDataMock[0]); + jest.spyOn(structureService, 'findOne').mockResolvedValue(structuresDocumentDataMock[0]); const expectedResult = { ...structuresDocumentDataMock[0], personalOffers: [personalOfferDocumentMock] }; - expect(await service.addPersonalOffer('6093ba0e2ab5775cfc01ed3e', personalOfferDocumentMock)).toEqual( + expect(await structureService.addPersonalOffer('6093ba0e2ab5775cfc01ed3e', personalOfferDocumentMock)).toEqual( expectedResult ); }); it('should return exception if structure is not found for given id', async () => { - jest.spyOn(service, 'findOne').mockResolvedValue(null); + jest.spyOn(structureService, 'findOne').mockResolvedValue(null); try { - await service.addPersonalOffer('abcd', personalOfferDocumentMock); + await structureService.addPersonalOffer('abcd', personalOfferDocumentMock); // Fail test if above expression doesn't throw anything. expect(true).toBe(false); } catch (e) { @@ -572,9 +575,9 @@ describe('StructuresService', () => { } }); it('should return exception if personal offer already exists in the structure', async () => { - jest.spyOn(service, 'findOne').mockResolvedValue(structuresDocumentDataMock[1]); + jest.spyOn(structureService, 'findOne').mockResolvedValue(structuresDocumentDataMock[1]); try { - await service.addPersonalOffer('6093ba0e2ab5775cfc01ed3e', personalOfferDocumentMock); + await structureService.addPersonalOffer('6093ba0e2ab5775cfc01ed3e', personalOfferDocumentMock); // Fail test if above expression doesn't throw anything. expect(true).toBe(false); } catch (e) { @@ -590,26 +593,26 @@ describe('StructuresService', () => { }); it('getCNFSStructuress(): should return 2 structures from the mock containing 4 structures', async () => { - expect((await service.getCNFSStructures()).length).toBe(2); + expect((await structureService.getCNFSStructures()).length).toBe(2); }); it('bindOneCNFSStructure(): should update ONE structure', async () => { const mockSetCNFSid = jest.fn().mockResolvedValue(mockResinStructures[0]); - jest.spyOn(service, 'findOne').mockResolvedValue(mockResinStructures[0] as StructureDocument); - jest.spyOn(service, 'setCNFSid').mockImplementation(mockSetCNFSid); + jest.spyOn(structureService, 'findOne').mockResolvedValue(mockResinStructures[0] as StructureDocument); + jest.spyOn(structureService, 'setCNFSid').mockImplementation(mockSetCNFSid); mockStructureModel.findByIdAndUpdate.mockReturnThis(); mockStructureModel.exec.mockResolvedValueOnce(mockResinStructures[0]); - expect(await service.bindOneCNFSStructure('mockId')).toBe('A match has been found, updating CNFSid'); + expect(await structureService.bindOneCNFSStructure('mockId')).toBe('A match has been found, updating CNFSid'); }); it('bindOneCNFSStructure(): should update ZERO structure, no match', async () => { - jest.spyOn(service, 'findOne').mockReturnThis(); - jest.spyOn(service, 'update').mockResolvedValue(mockResinStructures[2]); - expect(await service.bindOneCNFSStructure('mockId')).toBe('No match found'); + jest.spyOn(structureService, 'findOne').mockReturnThis(); + jest.spyOn(structureService, 'update').mockResolvedValue(mockResinStructures[2]); + expect(await structureService.bindOneCNFSStructure('mockId')).toBe('No match found'); }); it('bindCNFSids(): should update 2 structures (matching phone and mail)', async () => { const mockSetCNFSid = jest.fn().mockResolvedValue(mockResinStructures[0]); - jest.spyOn(service, 'findAll').mockResolvedValue(mockResinStructures as StructureDocument[]); - jest.spyOn(service, 'setCNFSid').mockImplementation(mockSetCNFSid); - expect(await service.bindCNFSids()).toBe(`2 structures affected`); + jest.spyOn(structureService, 'findAll').mockResolvedValue(mockResinStructures as StructureDocument[]); + jest.spyOn(structureService, 'setCNFSid').mockImplementation(mockSetCNFSid); + expect(await structureService.bindCNFSids()).toBe(`2 structures affected`); expect(mockSetCNFSid).toHaveBeenCalledTimes(2); }); }); @@ -618,7 +621,7 @@ describe('StructuresService', () => { it('should restore a structure', async () => { mockStructureModel.findByIdAndUpdate.mockReturnThis(); mockStructureModel.exec.mockImplementation(() => null); - await service.restoreStructure('someId'); + await structureService.restoreStructure('someId'); expect(mockStructureModel.findByIdAndUpdate).toBeCalled(); }); }); @@ -653,7 +656,7 @@ describe('StructuresService', () => { }, ], }; - const result = await service.searchAddress(data); + const result = await structureService.searchAddress(data); expect(httpServiceMock.get).toHaveBeenCalledTimes(2); expect(result).toEqual(expectedResult); diff --git a/src/structures/services/structures.service.ts b/src/structures/services/structures.service.ts index 95a0e558e34e20145d897f073c13daef0c8f14e6..16b22d0c3e52c090827f619ca8f63b0c8d0cb44d 100644 --- a/src/structures/services/structures.service.ts +++ b/src/structures/services/structures.service.ts @@ -26,6 +26,7 @@ import { Address } from '../schemas/address.schema'; import { Structure, StructureDocument } from '../schemas/structure.schema'; import { StructuresSearchService } from './structures-search.service'; import { JobsService } from '../../users/services/jobs.service'; +import { User } from '../../users/schemas/user.schema'; import { AxiosResponse } from 'axios'; @Injectable() @@ -53,6 +54,7 @@ export class StructuresService { text: string, filters?: Array<any>, fields?: string[], + onlyOffersWithAppointment?: boolean, limit?: number ): Promise<StructureDocument[]> { this.logger.debug( @@ -119,7 +121,9 @@ export class StructuresService { } // Filter offers using structure offers and structure members personalOffers - structures = this.filterOnOffers(structures, andFiltersOnOffers); + if (andFiltersOnOffers.length) { + structures = await this.filterOnOffers(structures, andFiltersOnOffers, onlyOffersWithAppointment); + } return structures.sort((a, b) => ids.indexOf(a.id) - ids.indexOf(b.id)); } @@ -130,12 +134,11 @@ export class StructuresService { * @param andFiltersOnOffers * @returns StructureDocument[] */ - private filterOnOffers(structures: StructureDocument[], andFiltersOnOffers: Array<any>): StructureDocument[] { - structures.forEach((structure) => { - // set structure offers and social workers personalOffers in structure.categoriesWithPersonalOffers - this.setCategoriesWithPersonalOffers(structure); - }); - + private async filterOnOffers( + structures: StructureDocument[], + andFiltersOnOffers: Array<any>, + onlyOffersWithAppointment: boolean + ): Promise<StructureDocument[]> { // Build filters on offers from andFiltersOnOffers const filtersOnOffers = { onlineProcedures: [], baseSkills: [], advancedSkills: [] }; andFiltersOnOffers.forEach((element) => { @@ -144,6 +147,12 @@ export class StructuresService { if ('advancedSkills' in element) filtersOnOffers.advancedSkills.push(element.advancedSkills); }); + // Set structure offers and social workers personalOffers in structure.categoriesWithPersonalOffers + const setCategoriesPromises = structures.map((structure) => + this.setCategoriesWithPersonalOffers(structure, onlyOffersWithAppointment) + ); + await Promise.all(setCategoriesPromises); + // Filter structures on offers checking structure offers and structure social workers offers return structures.filter( (structure) => @@ -163,34 +172,68 @@ export class StructuresService { * set structure offers and structure social workers personalOffers in non-persistant property structure.categoriesWithPersonalOffers * @param structure */ - public setCategoriesWithPersonalOffers(structure: StructureDocument) { - // Get structure offers - structure.categoriesWithPersonalOffers = { - onlineProcedures: structure.categories?.onlineProcedures || [], - baseSkills: structure.categories?.baseSkills || [], - advancedSkills: structure.categories?.advancedSkills || [], - }; + public async setCategoriesWithPersonalOffers(structure: StructureDocument, onlyOffersWithAppointment: boolean) { + if (onlyOffersWithAppointment) { + // Ignore structure offers (for orientation rdv, structure offers must be ignored: we filter only on personalOffers of the structure) + structure.categoriesWithPersonalOffers = { + onlineProcedures: [], + baseSkills: [], + advancedSkills: [], + }; + } else { + // Get structure offers + structure.categoriesWithPersonalOffers = { + onlineProcedures: structure.categories?.onlineProcedures || [], + baseSkills: structure.categories?.baseSkills || [], + advancedSkills: structure.categories?.advancedSkills || [], + }; + } - // Get offers for each structure social worker personalOffers - structure.personalOffers?.forEach((personalOffer) => { - if (!personalOffer.categories) { - throw new Error(`personalOffer not populated for structure ${structure.structureName} : ${personalOffer}`); - } + // Promise.all to wait for execution of all asynchronous operations + await Promise.all( + (structure.personalOffers || []).map(async (personalOffer) => { + if (!personalOffer.categories) { + throw new Error(`personalOffer not populated for structure ${structure.structureName} : ${personalOffer}`); + } - // use lodash _.union fonction to concat array without duplicates - structure.categoriesWithPersonalOffers.onlineProcedures = _.union( - structure.categoriesWithPersonalOffers.onlineProcedures, - personalOffer.categories.onlineProcedures - ); - structure.categoriesWithPersonalOffers.baseSkills = _.union( - structure.categoriesWithPersonalOffers.baseSkills, - personalOffer.categories.baseSkills - ); - structure.categoriesWithPersonalOffers.advancedSkills = _.union( - structure.categoriesWithPersonalOffers.advancedSkills, - personalOffer.categories.advancedSkills - ); - }); + // If we only want personalOffers from user with appointment + if (onlyOffersWithAppointment) { + const user = await this.userService.findByPersonalOfferId(personalOffer._id); + if (!user) { + Logger.log( + `No user with personalOffer ${personalOffer._id} for structure ${structure.structureName} (${structure._id}) !`, + StructuresService.name + ); + return; + } + if (!user.structuresLink.includes(structure._id)) { + Logger.log( + `Inconsistent personalOffer skipped: user ${user.name} ${user.surname} (${user._id}) has personalOffer ${personalOffer._id} for structure ${structure.structureName} (${structure._id}) but is not (anymore) member of the structure !`, + StructuresService.name + ); + return; + } + // If user is without appointment, skip this personalOffer + if (!User.getWithAppointment(user)) { + return; + } + } + + // use lodash _.union fonction to concat array without duplicates + structure.categoriesWithPersonalOffers.onlineProcedures = _.union( + structure.categoriesWithPersonalOffers.onlineProcedures, + personalOffer.categories.onlineProcedures + ); + structure.categoriesWithPersonalOffers.baseSkills = _.union( + structure.categoriesWithPersonalOffers.baseSkills, + personalOffer.categories.baseSkills + ); + structure.categoriesWithPersonalOffers.advancedSkills = _.union( + structure.categoriesWithPersonalOffers.advancedSkills, + personalOffer.categories.advancedSkills + ); + }) + ); } public async create(email: string, structure: StructureDto): Promise<Structure> { @@ -762,6 +805,27 @@ export class StructuresService { return structure; } + public async sendAdminNotificationAfterImportingStructure( + templateLocation: string, + jsonConfigLocation: string, + user = null + ) { + const uniqueAdminEmails = [...new Set((await this.userService.getAdmins()).map((admin) => admin.email))].map( + (item) => { + return { email: item }; + } + ); + + const config = this.mailerService.config; + const ejsPath = this.mailerService.getTemplateLocation(templateLocation); + const jsonConfig = this.mailerService.loadJsonConfig(jsonConfigLocation); + const html = await ejs.renderFile(ejsPath, { + config, + user: user, + }); + this.mailerService.send(uniqueAdminEmails, jsonConfig.subject, html); + } + public async sendAdminStructureNotification( structure: StructureDocument, templateLocation: string, @@ -1231,9 +1295,8 @@ export class StructuresService { structure.hasUserWithAppointmentDN = false; let conseillerNumFranceServices = false; - owners.forEach((owner) => { - // Check if owner has withAppointment and a job with personnalOffer (user may have changed his job after choosing withAppointment) - if (owner.withAppointment && owner.job?.hasPersonalOffer) { + owners.forEach((owner: User) => { + if (User.getWithAppointment(owner)) { structure.hasUserWithAppointmentDN = true; } // If user has job 'Conseiller numérique' ou 'Conseillère numérique' diff --git a/src/structures/structure-type/structure-type.schema.ts b/src/structures/structure-type/structure-type.schema.ts index 58564aa993de2735e48705921a2954ecb2185c3c..709af04f53569bc0d34dc3d9098b0d867b3bc04f 100644 --- a/src/structures/structure-type/structure-type.schema.ts +++ b/src/structures/structure-type/structure-type.schema.ts @@ -11,6 +11,9 @@ export class StructureType { @Prop() value: string; + @Prop() + name: string; + // Boolean set to false if user can't select this type during structure creation @Prop() selectable: boolean; diff --git a/src/structures/structures.controller.spec.ts b/src/structures/structures.controller.spec.ts index a24a262517f3bae42ca37e55d31a18638e61482c..4b35734e4df99f8d1bcaa8682291e8358d4ff7f7 100644 --- a/src/structures/structures.controller.spec.ts +++ b/src/structures/structures.controller.spec.ts @@ -6,10 +6,6 @@ import { of } from 'rxjs'; import { PhotonResponseMock } from '../../test/mock/data/dataPhoton.mock.data'; import { structureDtoMock } from '../../test/mock/data/structure.mock.dto'; import { CategoriesServiceMock } from '../../test/mock/services/categories.mock.service'; -import { - StructuresExportServiceMock, - mockFormattedStructures, -} from '../../test/mock/services/structures-export.mock.service'; import { UsersServiceMock } from '../../test/mock/services/user.mock.service'; import { CategoriesService } from '../categories/services/categories.service'; import { PersonalOffersService } from '../personal-offers/personal-offers.service'; @@ -26,9 +22,13 @@ import { StructuresService } from './services/structures.service'; import { StructuresController } from './structures.controller'; import { mockDeletedStructure, mockStructure } from '../../test/mock/data/structures.mock.data'; import { mockUser } from '../../test/mock/data/users.mock.data'; +import { + StructuresExportServiceMock, + mockFormattedStructures, +} from '../../test/mock/services/structures-export.mock.service'; describe('StructuresController', () => { - let controller: StructuresController; + let structuresController: StructuresController; let structuresExportService: StructuresExportService; const mockHttpService = { @@ -105,25 +105,24 @@ describe('StructuresController', () => { provide: StructuresExportService, useClass: StructuresExportServiceMock, }, - StructuresImportService, { provide: getModelToken(Structure.name), useValue: {}, }, ], }).compile(); - controller = module.get<StructuresController>(StructuresController); + structuresController = module.get<StructuresController>(StructuresController); structuresExportService = module.get<StructuresExportService>(StructuresExportService); jest.clearAllMocks(); }); it('should be defined', () => { - expect(controller).toBeDefined(); + expect(structuresController).toBeDefined(); }); it('should get structure coordinates', async () => { mockHttpService.get.mockImplementationOnce(() => of(PhotonResponseMock)); - const coords = await controller.getCoordinates('Lyon'); + const coords = await structuresController.getCoordinates('Lyon'); expect(coords).toBeTruthy(); }); @@ -132,18 +131,18 @@ describe('StructuresController', () => { userEmail: 'admin@admin.com', structure: structureDtoMock, }; - await controller.create(structure); + await structuresController.create(structure); expect(mockStructureService.create).toBeCalled(); }); it('should update structure after ownerVerify', async () => { const structureId = '1'; - const res = controller.updateAfterOwnerVerify(structureId); + const res = structuresController.updateAfterOwnerVerify(structureId); expect(res).toBeTruthy(); }); it('should update structure', async () => { - await controller.update('azerty', { + await structuresController.update('azerty', { deletedAt: null, remoteAccompaniment: null, dataShareConsentDate: null, @@ -154,7 +153,7 @@ describe('StructuresController', () => { it('should findAll', async () => { mockStructureService.findAll.mockResolvedValueOnce([{ structureName: 'a' }, { structureName: 'b' }]); - const res = await controller.findAll(); + const res = await structuresController.findAll(); expect(res.length).toBe(2); }); @@ -162,18 +161,18 @@ describe('StructuresController', () => { const mockResult: StructureFormatted[] = mockFormattedStructures; jest.spyOn(structuresExportService, 'exportFormatted').mockResolvedValueOnce(mockResult); - const result: StructureFormatted[] = await controller.findAllFormatted(); + const result: StructureFormatted[] = await structuresController.findAllFormatted(); expect(result).toEqual(mockResult); }); it('should search structure', async () => { - await controller.search({ query: 'test', filters: [] }, null); + await structuresController.search({ query: 'test', filters: [] }, null); expect(mockStructureService.searchForStructures).toBeCalled(); }); it('should reset Search Index', async () => { - await controller.resetES(); + await structuresController.resetES(); expect(mockStructureService.updateAllDenormalizedFields).toBeCalled(); expect(mockStructureService.initiateStructureIndex).toBeCalled(); }); @@ -181,7 +180,7 @@ describe('StructuresController', () => { it('should claim structure', async () => { const userMock = new UsersServiceMock(); const user = userMock.findOne('pauline.dupont@mii.com'); - const res = controller.claim('1', { + const res = structuresController.claim('1', { phone: null, resetPasswordToken: null, changeEmailToken: null, @@ -215,26 +214,26 @@ describe('StructuresController', () => { }); it('should search an address', async () => { - await controller.searchAddress({ searchQuery: 'Rue Alphonse Daudet' }); + await structuresController.searchAddress({ searchQuery: 'Rue Alphonse Daudet' }); expect(mockStructureService.searchAddress).toBeCalled(); }); describe('find(structureId)', () => { it('should find structure', async () => { mockStructureService.findOne.mockResolvedValue(mockStructure); - const res = await controller.find({ user: {} }, '6093ba0e2ab5775cfc01ed3e'); + const res = await structuresController.find({ user: {} }, '6093ba0e2ab5775cfc01ed3e'); expect(res).toBeTruthy(); }); it('should find deleted structure as an admin', async () => { mockStructureService.findOne.mockResolvedValue(mockDeletedStructure); - const response = await controller.find({ user: { role: UserRole.admin } }, '6093ba0e2ab5775cfc01ed33'); + const response = await structuresController.find({ user: { role: UserRole.admin } }, '6093ba0e2ab5775cfc01ed33'); expect(response.deletedAt).toBeTruthy(); }); it('should not find deleted structure as anonymous', async () => { try { - await controller.find({ user: {} }, '6093ba0e2ab5775cfc01ed33'); + await structuresController.find({ user: {} }, '6093ba0e2ab5775cfc01ed33'); expect(true).toBe(false); } catch (error) { expect(error.status).toEqual(HttpStatus.NOT_FOUND); @@ -243,7 +242,7 @@ describe('StructuresController', () => { }); it('should find struct with owners', async () => { - await controller.findWithOwners('6093ba0e2ab5775cfc01ed3e'); + await structuresController.findWithOwners('6093ba0e2ab5775cfc01ed3e'); expect(mockStructureService.findWithOwners).toHaveBeenCalled(); }); @@ -251,7 +250,7 @@ describe('StructuresController', () => { it('should delete structure without owners', async () => { mockStructureService.findOne.mockResolvedValue(mockStructure); mockUsersService.getStructureOwners.mockResolvedValue([]); - await controller.delete({ user: { _id: 'test' } }, 'test'); + await structuresController.delete({ user: { _id: 'test' } }, 'test'); expect(mockStructureService.deleteOne).toHaveBeenCalled(); }); @@ -260,7 +259,7 @@ describe('StructuresController', () => { it('should cancel struct delete', async () => { mockStructureService.findOne.mockResolvedValue(mockStructure); - await controller.cancelDelete({ user: { _id: 'id' } }, 'id'); + await structuresController.cancelDelete({ user: { _id: 'id' } }, 'id'); expect(mockStructureService.cancelDelete).toHaveBeenCalled(); }); @@ -272,7 +271,7 @@ describe('StructuresController', () => { it('should create temp user if it does not exists', async () => { mockStructureService.findOne.mockResolvedValue(mockStructure); mockUsersService.verifyUserExist.mockResolvedValue(null); - await controller.addOwner('6093ba0e2ab5775cfc01ed3e', { email: 'pauline.dupont@mii.com' }); + await structuresController.addOwner('6093ba0e2ab5775cfc01ed3e', { email: 'pauline.dupont@mii.com' }); expect(mockTempUserService.create).toHaveBeenCalled(); }); }); @@ -281,7 +280,7 @@ describe('StructuresController', () => { it('should return invalid structure', async () => { mockStructureService.findOne.mockResolvedValueOnce(null); try { - await controller.removeOwner('invalidstructure', '63639058685ba134c32bc495'); + await structuresController.removeOwner('invalidstructure', '63639058685ba134c32bc495'); expect(true).toBe(false); } catch (e) { expect(e.message).toEqual('Invalid Structure'); @@ -291,7 +290,7 @@ describe('StructuresController', () => { it('should return invalid user', async () => { mockStructureService.findOne.mockResolvedValue(mockStructure); try { - await controller.removeOwner('6093ba0e2ab5775cfc01ed3e', 'invaliduser'); + await structuresController.removeOwner('6093ba0e2ab5775cfc01ed3e', 'invaliduser'); expect(true).toBe(false); } catch (e) { expect(e.message).toEqual('Invalid User'); @@ -302,7 +301,7 @@ describe('StructuresController', () => { mockStructureService.findOne.mockResolvedValue(mockStructure); mockUsersService.findById.mockResolvedValue(mockUser); mockUsersService.getPersonalOfferInStructure.mockReturnValue(null); - await controller.removeOwner('6093ba0e2ab5775cfc01ed3e', '63639058685ba134c32bc495'); + await structuresController.removeOwner('6093ba0e2ab5775cfc01ed3e', '63639058685ba134c32bc495'); expect(mockUsersService.removeFromStructureLinked).toBeCalledTimes(1); expect(mockPersonalOffersService.delete).toBeCalledTimes(0); }); @@ -313,7 +312,7 @@ describe('StructuresController', () => { mockUsersService.getPersonalOfferInStructure.mockReturnValue({ _id: '2345ba0e2ab5775cfc01ed4d', categories: { - onlineProcedures: ['caf', 'cpam'], + onlineProcedures: ['caf'], baseSkills: [], advancedSkills: [], }, @@ -321,7 +320,7 @@ describe('StructuresController', () => { updatedAt: 'Wed Mar 16 2022 17:29:11 GMT+0100 (heure normale d’Europe centrale)', }); - await controller.removeOwner('6093ba0e2ab5775cfc01ed3e', '63639058685ba134c32bc495'); + await structuresController.removeOwner('6093ba0e2ab5775cfc01ed3e', '63639058685ba134c32bc495'); expect(mockUsersService.removeFromStructureLinked).toBeCalled(); expect(mockPersonalOffersService.delete).toBeCalled(); }); @@ -330,7 +329,7 @@ describe('StructuresController', () => { mockStructureService.findOne.mockResolvedValue(mockStructure); mockUsersService.findById.mockResolvedValue(mockUser); mockUsersService.getPersonalOfferInStructure.mockReturnValue(null); - await controller.removeOwner('6093ba0e2ab5775cfc01ed3e', '63639058685ba134c32bc495'); + await structuresController.removeOwner('6093ba0e2ab5775cfc01ed3e', '63639058685ba134c32bc495'); expect(mockUsersService.removeFromStructureLinked).toBeCalled(); }); @@ -346,7 +345,7 @@ describe('StructuresController', () => { }); it('should report any structure error', async () => { - await controller.reportStructureError({ structureId: '6093ba0e2ab5775cfc01ed3e', content: null }); + await structuresController.reportStructureError({ structureId: '6093ba0e2ab5775cfc01ed3e', content: null }); expect(mockStructureService.reportStructureError).toBeCalled(); }); }); diff --git a/src/structures/structures.controller.ts b/src/structures/structures.controller.ts index 503f4cdec7f01aca6700645e5f608cd0879f1886..7f467b9b7b4e7c085d6978352be2c729b74a96a9 100644 --- a/src/structures/structures.controller.ts +++ b/src/structures/structures.controller.ts @@ -43,7 +43,6 @@ import { Structure, StructureDocument } from './schemas/structure.schema'; import { StructuresExportService } from './services/structures-export.service'; import { StructuresService } from './services/structures.service'; import { StructureFormatted } from './interfaces/structure-formatted.interface'; -import { StructuresImportService } from './services/structures-import.service'; @ApiTags('structures') @Controller('structures') @@ -53,7 +52,6 @@ export class StructuresController { private readonly httpService: HttpService, private readonly structureService: StructuresService, private readonly structuresExportService: StructuresExportService, - private readonly structuresImportService: StructuresImportService, private readonly userService: UsersService, private readonly tempUserService: TempUserService, private readonly categoriesService: CategoriesService, @@ -103,6 +101,7 @@ export class StructuresController { query.query, body ? body.filters : null, null, + body?.onlyOffersWithAppointment || false, body?.limit || null ); } @@ -130,13 +129,6 @@ export class StructuresController { return this.structureService.updateAllDenormalizedFields(); } - @Post('importDataGouv') - @UseGuards(JwtAuthGuard, RolesGuard) - @Roles('admin') - public async importDataGouv(): Promise<void> { - return this.structuresImportService.importDataGouvStructures(); - } - @Put('updateAfterOwnerVerify/:id') public async updateAfterOwnerVerify(@Param('id') id: string): Promise<Structure> { Logger.debug(`updateAfterOwnerVerify | structure ${id}`, StructuresController.name); diff --git a/src/tcl/tclStopPoint.controller.ts b/src/tcl/tclStopPoint.controller.ts index e49137f1e18d16a53674ea3610115ed7b1002ccf..d35876c75b7858a246bb7910d10d85c6b85e2357 100644 --- a/src/tcl/tclStopPoint.controller.ts +++ b/src/tcl/tclStopPoint.controller.ts @@ -1,4 +1,4 @@ -import { Body, Controller, Logger, Post, UseGuards } from '@nestjs/common'; +import { Body, Controller, HttpException, HttpStatus, Logger, Post, UseGuards } from '@nestjs/common'; import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger'; import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard'; import { Roles } from '../users/decorators/roles.decorator'; @@ -37,6 +37,12 @@ export class TclStopPointController { }) @Post('/closest') public getClosestStopPoints(@Body() pgisCoord: PgisCoord): Promise<TclStopPoint[]> { + if (pgisCoord.coordinates.includes(null)) { + throw new HttpException( + `Invalid empty coordinate: ${JSON.stringify(pgisCoord.coordinates)}`, + HttpStatus.BAD_REQUEST + ); + } return this.tclStopPointService.getClosestStopPoints(pgisCoord); } } diff --git a/src/temp-user/temp-user.controller.spec.ts b/src/temp-user/temp-user.controller.spec.ts index ca61b3452d6b7671cce3c78412ec851d9c9eb24b..5bd3e66888865875e086fc36c376f02de54a5eed 100644 --- a/src/temp-user/temp-user.controller.spec.ts +++ b/src/temp-user/temp-user.controller.spec.ts @@ -6,7 +6,7 @@ import { TempUserController } from './temp-user.controller'; import { TempUserService } from './temp-user.service'; describe('TempUserService', () => { - let controller: TempUserController; + let tempUserController: TempUserController; const mockTempUserService = { findById: jest.fn(), @@ -19,24 +19,24 @@ describe('TempUserService', () => { controllers: [TempUserController], }).compile(); - controller = module.get<TempUserController>(TempUserController); + tempUserController = module.get<TempUserController>(TempUserController); }); it('should be defined', () => { - expect(controller).toBeDefined(); + expect(tempUserController).toBeDefined(); }); describe('getTempUser', () => { it('should get temporary users', async () => { const tmpUser = { email: 'test@test.com', pendingStructuresLink: [] }; mockTempUserService.findById.mockReturnValueOnce(tmpUser); - expect(await controller.getTempUser('addq651')).toEqual(tmpUser); + expect(await tempUserController.getTempUser('addq651')).toEqual(tmpUser); }); it('should throw error in cas of no users', async () => { const tmpUser = null; mockTempUserService.findById.mockReturnValueOnce(tmpUser); try { - await controller.getTempUser('addq651'); + await tempUserController.getTempUser('addq651'); // Fail test if above expression doesn't throw anything. expect(true).toBe(false); } catch (e) { diff --git a/src/temp-user/temp-user.service.spec.ts b/src/temp-user/temp-user.service.spec.ts index 6b867ef7071dcf8ff014369758b9762507cfdedb..227c55a73afef958c92334f231bca6e51a20471b 100644 --- a/src/temp-user/temp-user.service.spec.ts +++ b/src/temp-user/temp-user.service.spec.ts @@ -10,7 +10,7 @@ import { TempUserService } from './temp-user.service'; const ejsSpy = jest.spyOn(ejs, 'renderFile'); describe('TempUserService', () => { - let service: TempUserService; + let tempUserService: TempUserService; const tempUserModelMock = { create: jest.fn(), @@ -54,11 +54,11 @@ describe('TempUserService', () => { ], }).compile(); - service = module.get<TempUserService>(TempUserService); + tempUserService = module.get<TempUserService>(TempUserService); }); it('should be defined', () => { - expect(service).toBeDefined(); + expect(tempUserService).toBeDefined(); }); describe('create', () => { const tmpUser = { email: 'test@test.com', pendingStructuresLink: [] }; @@ -66,7 +66,7 @@ describe('TempUserService', () => { tempUserModelMock.findOne.mockReturnThis(); tempUserModelMock.exec.mockResolvedValueOnce(tmpUser); try { - await service.create(tmpUser, 'PIMMS Framboise'); + await tempUserService.create(tmpUser, 'PIMMS Framboise'); expect(true).toBe(false); } catch (e) { expect(e.message).toEqual('User already exists'); @@ -79,7 +79,7 @@ describe('TempUserService', () => { tempUserModelMock.create.mockResolvedValueOnce(tmpUser); tempUserModelMock.exec.mockResolvedValueOnce(tmpUser); ejsSpy.mockResolvedValue('mock'); - expect(await service.create(tmpUser, 'PIMMS Framboise')).toEqual(tmpUser); + expect(await tempUserService.create(tmpUser, 'PIMMS Framboise')).toEqual(tmpUser); expect(mockMailService.send).toHaveBeenCalled(); }); }); @@ -87,14 +87,14 @@ describe('TempUserService', () => { const tmpUser = { email: 'test2@test.com', pendingStructuresLink: [] }; tempUserModelMock.findOne.mockReturnThis(); tempUserModelMock.exec.mockResolvedValueOnce(tmpUser); - expect(await service.findOne('test2@test.com')).toEqual(tmpUser); + expect(await tempUserService.findOne('test2@test.com')).toEqual(tmpUser); }); it('should find one by id', async () => { const tmpUser = { email: 'test2@test.com', pendingStructuresLink: [] }; tempUserModelMock.findById.mockReturnThis(); tempUserModelMock.exec.mockResolvedValueOnce(tmpUser); - expect(await service.findById('5fbb92e480a5c257dc0161f0')).toEqual(tmpUser); + expect(await tempUserService.findById('5fbb92e480a5c257dc0161f0')).toEqual(tmpUser); }); describe('delete', () => { @@ -104,13 +104,13 @@ describe('TempUserService', () => { tempUserModelMock.exec.mockResolvedValueOnce(tmpUser); tempUserModelMock.deleteOne.mockReturnThis(); tempUserModelMock.exec.mockImplementationOnce(() => ({})); - expect(await service.delete('toto@test.com')).toEqual(tmpUser); + expect(await tempUserService.delete('toto@test.com')).toEqual(tmpUser); }); it('should return an error : user does not exist', async () => { tempUserModelMock.findOne.mockReturnThis(); tempUserModelMock.exec.mockResolvedValueOnce(null); try { - await service.delete('toto@test.com'); + await tempUserService.delete('toto@test.com'); expect(true).toBe(false); } catch (e) { expect(e.message).toEqual('User does not exists'); @@ -125,7 +125,7 @@ describe('TempUserService', () => { tempUserModelMock.find.mockReturnThis(); tempUserModelMock.exec.mockResolvedValueOnce([]).mockResolvedValueOnce(tmpUser); tempUserModelMock.findByIdAndUpdate.mockReturnThis(); - expect(await service.updateStructureLinked(tmpUser)).toEqual(tmpUser); + expect(await tempUserService.updateStructureLinked(tmpUser)).toEqual(tmpUser); }); it('should not update structure linked: User already linked', async () => { const tmpUser = { email: 'test2@test.com', structuresLink: [] }; @@ -133,7 +133,7 @@ describe('TempUserService', () => { tempUserModelMock.findByIdAndUpdate.mockReturnThis(); tempUserModelMock.exec.mockResolvedValueOnce([tmpUser]); try { - await service.updateStructureLinked(tmpUser); + await tempUserService.updateStructureLinked(tmpUser); } catch (e) { expect(e.message).toEqual('User already linked'); expect(e.status).toEqual(HttpStatus.UNPROCESSABLE_ENTITY); diff --git a/src/users/controllers/employer.controller.spec.ts b/src/users/controllers/employer.controller.spec.ts index 1eb82a3e9413b38a69a9949717640bd03744a271..d39b9f57002b96b422464dc55d7bfeffbee854a2 100644 --- a/src/users/controllers/employer.controller.spec.ts +++ b/src/users/controllers/employer.controller.spec.ts @@ -11,7 +11,7 @@ import { UsersService } from '../services/users.service'; import { EmployerController } from './employer.controller'; describe('EmployerController', () => { - let controller: EmployerController; + let employerController: EmployerController; let userService: UsersService; const employerServiceMock = { @@ -51,12 +51,12 @@ describe('EmployerController', () => { controllers: [EmployerController], }).compile(); - controller = module.get<EmployerController>(EmployerController); + employerController = module.get<EmployerController>(EmployerController); userService = module.get<UsersService>(UsersService); }); it('should be defined', () => { - expect(controller).toBeDefined(); + expect(employerController).toBeDefined(); }); describe('findAll', () => { @@ -73,7 +73,7 @@ describe('EmployerController', () => { validated: true, }, ]); - const findAllReply = await controller.findAll(); + const findAllReply = await employerController.findAll(); expect(findAllReply.length).toBe(2); }); it('should return searched elements with query `CA`', async () => { @@ -89,7 +89,7 @@ describe('EmployerController', () => { validated: true, }, ]); - const findAllReply = await controller.findAll({ search: 'CA' }); + const findAllReply = await employerController.findAll({ search: 'CA' }); expect(findAllReply.length).toBe(2); }); }); @@ -142,7 +142,7 @@ describe('EmployerController', () => { validated: true, }, ]); - const index = await controller.resetES(); + const index = await employerController.resetES(); expect(index.length).toBe(2); }); }); @@ -156,7 +156,7 @@ describe('EmployerController', () => { validated: true, }); const req = { user: { _id: '6036721022462b001334c4bb', role: 0 } }; - const reply = await controller.createEmployer({ name: 'Sopra' }, req); + const reply = await employerController.createEmployer({ name: 'Sopra' }, req); expect(reply).toBeTruthy(); }); it('should not create if employer already exists', async () => { @@ -167,7 +167,7 @@ describe('EmployerController', () => { }); const req = { user: { _id: '6036721022462b001334c4bb' }, role: 0 }; try { - await controller.createEmployer({ name: 'Sopra' }, req); + await employerController.createEmployer({ name: 'Sopra' }, req); expect; } catch (e) { expect(e.message).toBe('Employer already exist'); @@ -182,7 +182,7 @@ describe('EmployerController', () => { employerServiceMock.create.mockResolvedValueOnce({ ...employer, validated: true }); const req = { user: { _id: '6036721022462b001334c4bb', role: 1 } }; - const reply = await controller.createEmployer(employer, req); + const reply = await employerController.createEmployer(employer, req); expect(reply).toBeTruthy(); expect(employerServiceMock.create).toHaveBeenCalledWith(employer, true, false); }); @@ -194,7 +194,7 @@ describe('EmployerController', () => { name: 'Sopra', validated: true, }); - expect(await controller.validateEmployer({ id: '6231aefe76598527c8d0b5bc' })).toBeTruthy(); + expect(await employerController.validateEmployer({ id: '6231aefe76598527c8d0b5bc' })).toBeTruthy(); }); }); describe('Get Employers', () => { @@ -212,7 +212,7 @@ describe('EmployerController', () => { validated: true, }, ]); - await controller.findValidatedEmployers(); + await employerController.findValidatedEmployers(); expect(employerServiceMock.findAllValidated.mock.calls.length).toBe(1); expect(spyer.mock.calls.length).toBe(1); }); @@ -231,7 +231,7 @@ describe('EmployerController', () => { validated: false, }, ]); - await controller.findUnvalidatedEmployers(); + await employerController.findUnvalidatedEmployers(); expect(employerServiceMock.findAllUnvalidated.mock.calls.length).toBe(1); expect(spyer.mock.calls.length).toBe(1); }); @@ -243,7 +243,7 @@ describe('EmployerController', () => { name: 'SopraMod', validated: true, }); - expect(await controller.updateEmployer('6231aefe76598527c8d0b5bc', { name: 'SopraMod' })).toBeTruthy(); + expect(await employerController.updateEmployer('6231aefe76598527c8d0b5bc', { name: 'SopraMod' })).toBeTruthy(); }); it('should delete an unvalidated employer and replace all its occurence with a chosen validated employer', async () => { @@ -258,7 +258,7 @@ describe('EmployerController', () => { deletedCount: 1, }); - const reply = await controller.mergeEmployer({ + const reply = await employerController.mergeEmployer({ sourceEmployerId: '6231aefe76598527c8d0b5ba', targetEmployerId: '6231aefe76598527c8d0b5bc', }); @@ -278,7 +278,7 @@ describe('EmployerController', () => { name: 'Sopra', validated: true, }); - const reply = await controller.deleteEmployer({ id: '6231aefe76598527c8d0b5ba' }); + const reply = await employerController.deleteEmployer({ id: '6231aefe76598527c8d0b5ba' }); expect(reply).toBeTruthy(); }); @@ -289,7 +289,7 @@ describe('EmployerController', () => { validated: true, }); try { - await controller.deleteEmployer({ id: '6231aefe76598527c8d0b5bc' }); + await employerController.deleteEmployer({ id: '6231aefe76598527c8d0b5bc' }); expect(true).toBe(false); } catch (e) { expect(e.message).toEqual('Cannot delete employer. It has user(s) attached to it.'); diff --git a/src/users/controllers/jobs.controller.spec.ts b/src/users/controllers/jobs.controller.spec.ts index 89a11ad7fd9a96142cd6b652c1475408c8887603..28c9386d5d92fe85f654fb4e40ae09d5362df790 100644 --- a/src/users/controllers/jobs.controller.spec.ts +++ b/src/users/controllers/jobs.controller.spec.ts @@ -12,7 +12,7 @@ import { UsersService } from '../services/users.service'; import { JobsController } from './jobs.controller'; describe('JobsController', () => { - let controller: JobsController; + let jobsController: JobsController; const jobServiceMock = { findAll: jest.fn(), @@ -57,11 +57,11 @@ describe('JobsController', () => { controllers: [JobsController], }).compile(); - controller = module.get<JobsController>(JobsController); + jobsController = module.get<JobsController>(JobsController); }); it('should be defined', () => { - expect(controller).toBeDefined(); + expect(jobsController).toBeDefined(); }); describe('findAll', () => { @@ -82,7 +82,7 @@ describe('JobsController', () => { jobsGroup: null, }, ]); - const reply = await controller.findAll(); + const reply = await jobsController.findAll(); expect(reply.length).toBe(2); }); }); @@ -103,7 +103,7 @@ describe('JobsController', () => { jobServiceMock.findByName.mockResolvedValueOnce(null); jobServiceMock.create.mockResolvedValueOnce(newCreatedJob); const req = { user: { _id: '6036721022462b001334c4bb' } }; - const createReply = await controller.createJob(req, newJob); + const createReply = await jobsController.createJob(req, newJob); expect(createReply).toEqual(newCreatedJob); }); it('should throw error on already existing job `Dev`', async () => { @@ -121,7 +121,7 @@ describe('JobsController', () => { }); try { const req = { user: { _id: '6036721022462b001334c4bb' } }; - await controller.createJob(req, newJob); + await jobsController.createJob(req, newJob); expect(true).toBe(false); } catch (e) { expect(e.message).toBe('Job already exist'); @@ -139,7 +139,7 @@ describe('JobsController', () => { validated: true, }); const req = { user: { _id: '6036721022462b001334c4bb', role: 0 } }; - const reply = await controller.createJob(req, { name: 'Dev', hasPersonalOffer: true, jobsGroup: null }); + const reply = await jobsController.createJob(req, { name: 'Dev', hasPersonalOffer: true, jobsGroup: null }); expect(reply).toBeTruthy(); }); it('should not create if job already exists', async () => { @@ -150,7 +150,7 @@ describe('JobsController', () => { }); const req = { user: { _id: '6036721022462b001334c4bb', role: 0 } }; try { - await controller.createJob(req, { name: 'Dev', hasPersonalOffer: true, jobsGroup: null }); + await jobsController.createJob(req, { name: 'Dev', hasPersonalOffer: true, jobsGroup: null }); } catch (e) { expect(e.message).toBe('Job already exist'); expect(e.status).toBe(HttpStatus.UNPROCESSABLE_ENTITY); @@ -165,7 +165,7 @@ describe('JobsController', () => { }); const req = { user: { _id: '6036721022462b001334c4bb', role: 1 } }; const job = { name: 'Dev', hasPersonalOffer: true, jobsGroup: null }; - const reply = await controller.createJob(req, job); + const reply = await jobsController.createJob(req, job); expect(reply).toBeTruthy(); expect(jobServiceMock.create).toHaveBeenCalledWith(job, true, true, false); }); @@ -177,7 +177,7 @@ describe('JobsController', () => { name: 'Dev', validated: true, }); - expect(await controller.validateJob({ id: '6231aefe76598527c8d0b5bc' })).toBeTruthy(); + expect(await jobsController.validateJob({ id: '6231aefe76598527c8d0b5bc' })).toBeTruthy(); }); }); describe('Get Jobs', () => { @@ -195,7 +195,7 @@ describe('JobsController', () => { validated: true, }, ]); - await controller.findValidatedJobs(); + await jobsController.findValidatedJobs(); expect(jobServiceMock.findAll.mock.calls.length).toBe(2); expect(spyer.mock.calls.length).toBe(1); }); @@ -214,7 +214,7 @@ describe('JobsController', () => { validated: false, }, ]); - await controller.findUnvalidatedJobs(); + await jobsController.findUnvalidatedJobs(); expect(jobServiceMock.findAllUnvalidated.mock.calls.length).toBe(1); expect(spyer.mock.calls.length).toBe(2); }); @@ -227,7 +227,7 @@ describe('JobsController', () => { validated: true, }); expect( - await controller.updateJob('6231aefe76598527c8d0b5bc', { + await jobsController.updateJob('6231aefe76598527c8d0b5bc', { name: 'DevMod', hasPersonalOffer: false, jobsGroup: null, @@ -247,7 +247,7 @@ describe('JobsController', () => { deletedCount: 1, }); - const reply = await controller.mergeJob({ + const reply = await jobsController.mergeJob({ sourceJobId: '6231aefe76598527c8d0b5ba', targetJobId: '6231aefe76598527c8d0b5bc', }); @@ -268,7 +268,7 @@ describe('JobsController', () => { validated: true, }); userServiceMock.isJobLinkedtoUser.mockResolvedValueOnce(false); - const reply = await controller.deleteJob({ id: '6231aefe76598527c8d0b5ba' }); + const reply = await jobsController.deleteJob({ id: '6231aefe76598527c8d0b5ba' }); expect(reply).toBeTruthy(); }); @@ -280,7 +280,7 @@ describe('JobsController', () => { }); userServiceMock.isJobLinkedtoUser.mockResolvedValueOnce(true); try { - await controller.deleteJob({ id: '6231aefe76598527c8d0b5bc' }); + await jobsController.deleteJob({ id: '6231aefe76598527c8d0b5bc' }); expect(true).toBe(false); } catch (e) { expect(e.message).toEqual('Cannot delete job. It has user(s) attached to it.'); diff --git a/src/users/controllers/jobsGroups.controller.spec.ts b/src/users/controllers/jobsGroups.controller.spec.ts index f2a2a160bdf4db81ed040ca2573972015b0d4a23..66e89371235a9fc51b1efd440205e192f9556695 100644 --- a/src/users/controllers/jobsGroups.controller.spec.ts +++ b/src/users/controllers/jobsGroups.controller.spec.ts @@ -6,12 +6,12 @@ import { Types } from 'mongoose'; import { ConfigurationModule } from '../../configuration/configuration.module'; import { CreateJobsGroupsDto } from '../dto/create-jobsGroups.dto'; import { JobsGroups } from '../schemas/jobsGroups.schema'; +import { JobsService } from '../services/jobs.service'; import { JobsGroupsService } from '../services/jobsGroups.service'; import { JobsGroupsController } from './jobsGroups.controller'; -import { JobsService } from '../services/jobs.service'; describe('JobsGroupsController', () => { - let controller: JobsGroupsController; + let jobsGroupsController: JobsGroupsController; const jobsGroupsServiceMock = { findAll: jest.fn(), @@ -47,11 +47,11 @@ describe('JobsGroupsController', () => { controllers: [JobsGroupsController], }).compile(); - controller = module.get<JobsGroupsController>(JobsGroupsController); + jobsGroupsController = module.get<JobsGroupsController>(JobsGroupsController); }); it('should be defined', () => { - expect(controller).toBeDefined(); + expect(jobsGroupsController).toBeDefined(); }); describe('findAll', () => { @@ -66,7 +66,7 @@ describe('JobsGroupsController', () => { name: 'Coordination', }, ]); - const reply = await controller.findAll(); + const reply = await jobsGroupsController.findAll(); expect(reply.length).toBe(2); }); }); @@ -81,7 +81,7 @@ describe('JobsGroupsController', () => { }; jobsGroupsServiceMock.findByName.mockResolvedValueOnce(null); jobsGroupsServiceMock.create.mockResolvedValueOnce(newCreatedJobsGroups); - const createReply = await controller.createJobsGroups(newJobsGroups); + const createReply = await jobsGroupsController.createJobsGroups(newJobsGroups); expect(createReply).toEqual(newCreatedJobsGroups); }); it('should throw error on already existing job group `Dev`', async () => { @@ -93,7 +93,7 @@ describe('JobsGroupsController', () => { name: 'Dev', }); try { - await controller.createJobsGroups(newJobsGroups); + await jobsGroupsController.createJobsGroups(newJobsGroups); expect(true).toBe(false); } catch (e) { expect(e.message).toBe('Job group already exist'); @@ -108,7 +108,7 @@ describe('JobsGroupsController', () => { _id: new Types.ObjectId('6231aefe76598527c8d0b5bc'), name: 'DevMod', }); - expect(await controller.updateJobsGroups('6231aefe76598527c8d0b5bc', { name: 'DevMod' })).toBeTruthy(); + expect(await jobsGroupsController.updateJobsGroups('6231aefe76598527c8d0b5bc', { name: 'DevMod' })).toBeTruthy(); }); }); describe('Delete Job Group', () => { @@ -124,7 +124,7 @@ describe('JobsGroupsController', () => { name: 'Dev', }); jobServiceMock.getJobsGroupsAttachedJobs.mockResolvedValueOnce([]); - const reply = await controller.deleteJobsGroups({ id: '6231aefe76598527c8d0b5ba' }); + const reply = await jobsGroupsController.deleteJobsGroups({ id: '6231aefe76598527c8d0b5ba' }); expect(reply).toBeTruthy(); }); @@ -135,7 +135,7 @@ describe('JobsGroupsController', () => { }); jobServiceMock.getJobsGroupsAttachedJobs.mockResolvedValueOnce([{ test: 1 }]); try { - await controller.deleteJobsGroups({ id: '6231aefe76598527c8d0b5bc' }); + await jobsGroupsController.deleteJobsGroups({ id: '6231aefe76598527c8d0b5bc' }); expect(true).toBe(false); } catch (e) { expect(e.message).toEqual('Cannot delete job group. It has job(s) attached to it.'); diff --git a/src/users/controllers/userRegistry.controller.spec.ts b/src/users/controllers/userRegistry.controller.spec.ts index 115ed62a4e36ace249e61b185e4700a230384c26..64a6db269738868c0e04ce7e16c2eff0b111df51 100644 --- a/src/users/controllers/userRegistry.controller.spec.ts +++ b/src/users/controllers/userRegistry.controller.spec.ts @@ -11,7 +11,7 @@ import { UserRegistryService } from '../services/userRegistry.service'; import { UsersRegistryController } from './userRegistry.controller'; describe('UserRegistryController', () => { - let controller: UsersRegistryController; + let userRegistryController: UsersRegistryController; const userRegistryServiceMock = { findAllForIndexation: jest.fn(), @@ -44,17 +44,17 @@ describe('UserRegistryController', () => { .useValue(mockRoleGuard) .compile(); - controller = module.get<UsersRegistryController>(UsersRegistryController); + userRegistryController = module.get<UsersRegistryController>(UsersRegistryController); }); it('should be defined', () => { - expect(controller).toBeDefined(); + expect(userRegistryController).toBeDefined(); }); describe('findAll', () => { it('should findAll with searchTerm, job and employer', async () => { userRegistryServiceMock.findUsersByNameEmployerOrJobsGroup.mockResolvedValue([multipleUsers[0]]); - const reply = await controller.findAll( + const reply = await userRegistryController.findAll( { search: 'adm' }, { page: 1, jobsGroup: ['Technique'], employer: ['Pimms'] } ); @@ -62,66 +62,69 @@ describe('UserRegistryController', () => { }); it('should findAll with searchTerm, empty job and empty employer', async () => { userRegistryServiceMock.findUsersByNameEmployerOrJobsGroup.mockResolvedValue([multipleUsers[0]]); - const reply = await controller.findAll({ search: 'adm' }, { page: 1, jobsGroup: [], employer: [] }); + const reply = await userRegistryController.findAll({ search: 'adm' }, { page: 1, jobsGroup: [], employer: [] }); expect(reply).toStrictEqual([multipleUsers[0]]); }); it('should findAll with searchTerm and no filter arrays', async () => { userRegistryServiceMock.findUsersByNameEmployerOrJobsGroup.mockResolvedValue([multipleUsers[0]]); - const reply = await controller.findAll({ search: 'adm' }, { page: 1 }); + const reply = await userRegistryController.findAll({ search: 'adm' }, { page: 1 }); expect(reply).toStrictEqual([multipleUsers[0]]); }); it('should findAll with searchTerm and empty job', async () => { userRegistryServiceMock.findUsersByNameEmployerOrJobsGroup.mockResolvedValue([multipleUsers[0]]); - const reply = await controller.findAll({ search: 'adm' }, { page: 1, jobsGroup: [] }); + const reply = await userRegistryController.findAll({ search: 'adm' }, { page: 1, jobsGroup: [] }); expect(reply).toStrictEqual([multipleUsers[0]]); }); it('should findAll with searchTerm and empty employer', async () => { userRegistryServiceMock.findUsersByNameEmployerOrJobsGroup.mockResolvedValue([multipleUsers[0]]); - const reply = await controller.findAll({ search: 'adm' }, { page: 1, employer: [] }); + const reply = await userRegistryController.findAll({ search: 'adm' }, { page: 1, employer: [] }); expect(reply).toStrictEqual([multipleUsers[0]]); }); it('should findAll with no searchTerm and employer filter', async () => { userRegistryServiceMock.findUsersByNameEmployerOrJobsGroup.mockResolvedValue([multipleUsers[0]]); - const reply = await controller.findAll({ search: '' }, { page: 1, employer: ['CAF'] }); + const reply = await userRegistryController.findAll({ search: '' }, { page: 1, employer: ['CAF'] }); expect(reply).toStrictEqual([multipleUsers[0]]); }); it('should findAll with no searchTerm and job filter', async () => { userRegistryServiceMock.findUsersByNameEmployerOrJobsGroup.mockResolvedValue([multipleUsers[0]]); - const reply = await controller.findAll({ search: '' }, { page: 1, jobsGroup: ['Technique'] }); + const reply = await userRegistryController.findAll({ search: '' }, { page: 1, jobsGroup: ['Technique'] }); expect(reply).toStrictEqual([multipleUsers[0]]); }); it('should findAll with no searchTerm and filters', async () => { userRegistryServiceMock.findUsersByNameEmployerOrJobsGroup.mockResolvedValue([multipleUsers[0]]); - const reply = await controller.findAll({ search: '' }, { page: 1, jobsGroup: ['Technique'], employer: ['CAF'] }); + const reply = await userRegistryController.findAll( + { search: '' }, + { page: 1, jobsGroup: ['Technique'], employer: ['CAF'] } + ); expect(reply).toStrictEqual([multipleUsers[0]]); }); it('should findAll with searchTerm and undefined filters', async () => { userRegistryServiceMock.findUsersByNameEmployerOrJobsGroup.mockResolvedValue([multipleUsers[0]]); - const reply = await controller.findAll({ search: 'adm' }); + const reply = await userRegistryController.findAll({ search: 'adm' }); expect(reply).toStrictEqual([multipleUsers[0]]); }); it('should findAll with no searchTerm and no filter arrays', async () => { userRegistryServiceMock.findAllUserRegistry.mockResolvedValue(multipleUsers); - const reply = await controller.findAll({ search: '' }, { page: 1 }); + const reply = await userRegistryController.findAll({ search: '' }, { page: 1 }); expect(reply).toBe(multipleUsers); }); it('should findAll with empty search end undefined filters', async () => { userRegistryServiceMock.findAllUserRegistry.mockResolvedValue(multipleUsers); - const reply = await controller.findAll({ search: '' }); + const reply = await userRegistryController.findAll({ search: '' }); expect(reply).toBe(multipleUsers); }); }); describe('findAllCount', () => { it('should findAllCount', async () => { userRegistryServiceMock.countAllUserRegistry.mockResolvedValue(10); - const reply = await controller.findAllCount(); + const reply = await userRegistryController.findAllCount(); expect(reply).toStrictEqual(10); }); }); describe('resetES', () => { it('should reset elastic search indexes', async () => { userRegistryServiceMock.initUserRegistryIndex.mockResolvedValue(multipleUsers); - const reply = await controller.resetES(); + const reply = await userRegistryController.resetES(); expect(reply).toStrictEqual(multipleUsers); }); }); diff --git a/src/users/controllers/userRegistry.controller.ts b/src/users/controllers/userRegistry.controller.ts index 513f1c67aba9cc7585448248a6120f62adccd1d4..aceaad73b4ff92e0cae9358a1c9510b4bc582b3e 100644 --- a/src/users/controllers/userRegistry.controller.ts +++ b/src/users/controllers/userRegistry.controller.ts @@ -55,7 +55,8 @@ export class UsersRegistryController { @Post('searchIndex') @UseGuards(JwtAuthGuard, RolesGuard) @Roles('admin') - public async resetES(): Promise<IUserRegistry[]> { + public async resetES() { + this.logger.debug('reset ES UserRegistry'); return this.userRegistryService.initUserRegistryIndex(); } } diff --git a/src/users/controllers/users.controller.spec.ts b/src/users/controllers/users.controller.spec.ts index 6760594ee110717b2df4a5786829109fbeb1cda7..43739c000b54df25a50babf29be9d3d8107a7aae 100644 --- a/src/users/controllers/users.controller.spec.ts +++ b/src/users/controllers/users.controller.spec.ts @@ -30,7 +30,7 @@ import { PasswordResetDto } from './../dto/reset-password.dto'; import { UsersController } from './users.controller'; describe('UsersController', () => { - let controller: UsersController; + let usersController: UsersController; const employerServiceMock = { findByName: jest.fn(), @@ -127,19 +127,19 @@ describe('UsersController', () => { controllers: [UsersController], }).compile(); - controller = module.get<UsersController>(UsersController); + usersController = module.get<UsersController>(UsersController); }); afterEach(() => { jest.clearAllMocks(); }); it('should be defined', () => { - expect(controller).toBeDefined(); + expect(usersController).toBeDefined(); }); describe('getProfile', () => { it('should return user', () => { const user = { _id: '36', email: 'a@a.com' }; - const result = controller.getProfile({ user: user }); + const result = usersController.getProfile({ user: user }); expect(result).toEqual(user); }); }); @@ -152,7 +152,7 @@ describe('UsersController', () => { }; employerServiceMock.findByName.mockResolvedValueOnce(null); try { - await controller.setProfile({ user: { _id: '36', email: 'a@a.com' } }, profile); + await usersController.setProfile({ user: { _id: '36', email: 'a@a.com' } }, profile); expect(true).toBe(false); } catch (e) { expect(e.message).toBe('Employer does not exist'); @@ -171,7 +171,7 @@ describe('UsersController', () => { }); jobServiceMock.findByName.mockResolvedValue(null); try { - await controller.setProfile({ user: { _id: '36', email: 'a@a.com' } }, profile); + await usersController.setProfile({ user: { _id: '36', email: 'a@a.com' } }, profile); expect(true).toBe(false); } catch (e) { expect(e.message).toBe('Job does not exist'); @@ -214,7 +214,7 @@ describe('UsersController', () => { employer: new Types.ObjectId('6231aefe76598527c8d0b5a7'), job: new Types.ObjectId('6231aefe76598527c8d0b5be'), }); - const reply = await controller.setProfile({ user: { _id: '36', email: 'a@a.com' } }, profile); + const reply = await usersController.setProfile({ user: { _id: '36', email: 'a@a.com' } }, profile); expect(reply).toBeTruthy(); }); }); @@ -246,7 +246,7 @@ describe('UsersController', () => { employer: new Types.ObjectId('6231aefe76598527c8d0b5a7'), job: new Types.ObjectId('6231aefe76598527c8d0b5be'), }); - const reply = await controller.updateDetails({ user: { _id: '36', email: 'a@a.com' } }, newDetails); + const reply = await usersController.updateDetails({ user: { _id: '36', email: 'a@a.com' } }, newDetails); expect(reply).toBeTruthy(); }); }); @@ -262,7 +262,7 @@ describe('UsersController', () => { const createUserDto = new CreateUserDto(); userServiceMock.create.mockResolvedValueOnce(usersMockData[0]); - const result = await controller.create(createUserDto); + const result = await usersController.create(createUserDto); expect(userCreateSpyer).toBeCalledTimes(1); expect(structureFindOneSpyer).toBeCalledTimes(0); @@ -284,7 +284,7 @@ describe('UsersController', () => { const createUserDto = new CreateUserDto(); userServiceMock.create.mockResolvedValueOnce(usersMockData[0]); tempUserServiceMock.findOne.mockResolvedValueOnce({ email: 'test@test.com', pendingStructuresLink: [] }); - const result = await controller.create(createUserDto); + const result = await usersController.create(createUserDto); expect(userCreateSpyer).toBeCalledTimes(1); expect(structureFindOneSpyer).toBeCalledTimes(0); @@ -299,7 +299,7 @@ describe('UsersController', () => { describe('validateUser', () => { it('should call validateUser', async () => { const spyer = jest.spyOn(userServiceMock, 'validateUser'); - await controller.validateUser({ id: 1 }, 'token'); + await usersController.validateUser({ id: 1 }, 'token'); expect(spyer).toBeCalledTimes(1); }); }); @@ -307,7 +307,7 @@ describe('UsersController', () => { describe('changePassword', () => { it('should call changeUserPassword', async () => { const spyer = jest.spyOn(userServiceMock, 'changeUserPassword'); - await controller.changePassword({ user: { _id: '36', email: 'a@a.com' } }, new PasswordChangeDto()); + await usersController.changePassword({ user: { _id: '36', email: 'a@a.com' } }, new PasswordChangeDto()); expect(spyer).toBeCalledTimes(1); }); }); @@ -315,7 +315,7 @@ describe('UsersController', () => { describe('changeEmail', () => { it('should call changeUserEmail', async () => { const spyer = jest.spyOn(userServiceMock, 'changeUserEmail'); - await controller.changeEmail(new EmailChangeDto()); + await usersController.changeEmail(new EmailChangeDto()); expect(spyer).toBeCalledTimes(1); }); }); @@ -323,7 +323,7 @@ describe('UsersController', () => { describe('verifyAndUpdateEmail', () => { it('should call verifyAndUpdateUserEmail', async () => { const spyer = jest.spyOn(userServiceMock, 'verifyAndUpdateUserEmail'); - await controller.verifyAndUpdateEmail('token'); + await usersController.verifyAndUpdateEmail('token'); expect(spyer).toBeCalledTimes(1); }); }); @@ -331,7 +331,7 @@ describe('UsersController', () => { describe('resetPassword', () => { it('should call sendResetPasswordEmail', async () => { const spyer = jest.spyOn(userServiceMock, 'sendResetPasswordEmail'); - await controller.resetPassword(new PasswordResetDto()); + await usersController.resetPassword(new PasswordResetDto()); expect(spyer).toBeCalledTimes(1); }); }); @@ -339,7 +339,7 @@ describe('UsersController', () => { describe('resetPasswordApply', () => { it('should call validatePasswordResetToken', async () => { const spyer = jest.spyOn(userServiceMock, 'validatePasswordResetToken'); - await controller.resetPasswordApply(new PasswordResetApplyDto()); + await usersController.resetPasswordApply(new PasswordResetApplyDto()); expect(spyer).toBeCalledTimes(1); }); }); @@ -347,7 +347,7 @@ describe('UsersController', () => { describe('verifyUserExist', () => { it('should call verifyUserExist', async () => { const spyer = jest.spyOn(userServiceMock, 'verifyUserExist'); - await controller.verifyUserExist({ user: { _id: '36', email: 'a@a.com' } }, { newMail: 'test@test.com' }); + await usersController.verifyUserExist({ user: { _id: '36', email: 'a@a.com' } }, { newMail: 'test@test.com' }); expect(spyer).toBeCalledTimes(1); }); }); @@ -358,7 +358,7 @@ describe('UsersController', () => { const isStructureClaimedSpyer = jest.spyOn(userServiceMock, 'isStructureClaimed'); const userWithoutStructure = usersMockData[2]; userServiceMock.deleteOne.mockResolvedValueOnce(userWithoutStructure); - await controller.delete({ user: { _id: '36', email: 'a@a.com' } }); + await usersController.delete({ user: { _id: '36', email: 'a@a.com' } }); expect(deleteOneSpyer).toBeCalledTimes(1); expect(isStructureClaimedSpyer).toBeCalledTimes(0); }); @@ -371,7 +371,7 @@ describe('UsersController', () => { userServiceMock.deleteOne.mockResolvedValueOnce(userWithThreeStructures); userServiceMock.isStructureClaimed.mockResolvedValue(null); userServiceMock.isStructureClaimed.mockResolvedValueOnce(userWithThreeStructures); - await controller.delete({ user: { _id: '36', email: 'a@a.com' } }); + await usersController.delete({ user: { _id: '36', email: 'a@a.com' } }); expect(userDeleteOneSpyer).toBeCalledTimes(1); expect(isStructureClaimedSpyer).toBeCalledTimes(3); expect(structureFindOne).toBeCalledTimes(2); @@ -381,7 +381,7 @@ describe('UsersController', () => { describe('dataConsentValidation', () => { it('should call getAllDataConsentPendingStructures', async () => { const spyer = jest.spyOn(structureServiceMock, 'getAllDataConsentPendingStructures'); - await controller.dataConsentValidation({ user: { _id: '36', email: 'a@a.com' } }); + await usersController.dataConsentValidation({ user: { _id: '36', email: 'a@a.com' } }); expect(spyer).toBeCalledTimes(1); }); }); @@ -390,7 +390,7 @@ describe('UsersController', () => { it('should return user', async () => { const spyer = jest.spyOn(userServiceMock, 'findById'); userServiceMock.findById.mockResolvedValueOnce({ _id: '36', email: 'a@a.com' }); - const result = await controller.getUser(1); + const result = await usersController.getUser(1); expect(result).toEqual({ _id: '36', email: 'a@a.com' }); expect(spyer).toBeCalledTimes(1); }); @@ -400,7 +400,7 @@ describe('UsersController', () => { userServiceMock.findById.mockResolvedValueOnce(null); try { - await controller.getUser(1); + await usersController.getUser(1); expect(true).toBe(false); } catch (error) { expect(error.message).toBe('User does not exist'); @@ -413,7 +413,7 @@ describe('UsersController', () => { describe('update description', () => { it('should call updateDescription', async () => { const spyer = jest.spyOn(userServiceMock, 'updateDescription'); - await controller.updateDescription({ user: { _id: '36', email: 'a@a.com' } }, new DescriptionDto()); + await usersController.updateDescription({ user: { _id: '36', email: 'a@a.com' } }, new DescriptionDto()); expect(spyer).toBeCalledTimes(1); }); }); diff --git a/src/users/schemas/user.schema.ts b/src/users/schemas/user.schema.ts index 462e719803bc55a90de3577d85ea05a1323ab6f1..c850621c819deb256743bb8edaa1a4d18115c7a5 100644 --- a/src/users/schemas/user.schema.ts +++ b/src/users/schemas/user.schema.ts @@ -2,7 +2,7 @@ import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose'; import { Types } from 'mongoose'; import { PersonalOfferDocument } from '../../personal-offers/schemas/personal-offer.schema'; import { Employer } from './employer.schema'; -import { Job, JobDocument } from './job.schema'; +import { JobDocument } from './job.schema'; import { UserRole } from '../enum/user-role.enum'; import { pendingStructuresLink } from '../interfaces/pendingStructure'; @@ -73,6 +73,19 @@ export class User { @Prop({ default: null }) lastLoginDate: Date; + + // Document methods + // static because object method would need to create a constructor and get an actual User instance (cf. https://stackoverflow.com/a/42899705 ) + + // Get if owner can have appointment + static getWithAppointment(user: User) { + if (user.job && !user.job.name) { + throw new Error(`job not populated for user ${user.surname} : ${user.job}`); + } + // Also check user has a job with personnalOffer (user may have changed his job after choosing withAppointment) + // and also check if user has personalOffers (otherwise they can't have appointment) + return user.withAppointment && user.job?.hasPersonalOffer && user.personalOffers?.length; + } } export const UserSchema = SchemaFactory.createForClass(User); diff --git a/src/users/services/employer-search.service.spec.ts b/src/users/services/employer-search.service.spec.ts index e41a421f04f0d512337527a498ee8042d41b61fd..435428dee0036b8dc65527fa82f07ced79c32f56 100644 --- a/src/users/services/employer-search.service.spec.ts +++ b/src/users/services/employer-search.service.spec.ts @@ -18,22 +18,22 @@ const employers = [ } as EmployerDocument, { _id: new Types.ObjectId('6231aefe76598527c8d0b5bd'), - name: 'CAF', + name: 'CGI', validated: true, } as EmployerDocument, { _id: new Types.ObjectId('6231aefe76598527c8d0b5be'), - name: 'CARSAT', + name: 'Decathlon', validated: true, } as EmployerDocument, { _id: new Types.ObjectId('6231aefe76598527c8d0b5bf'), - name: 'CPAM', + name: 'Apollo', validated: true, } as EmployerDocument, ]; describe('EmployerSearchService Search cases', () => { - let service: EmployerSearchService; + let employerSearchService: EmployerSearchService; beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ @@ -41,21 +41,21 @@ describe('EmployerSearchService Search cases', () => { providers: [EmployerSearchService], }).compile(); - service = module.get<EmployerSearchService>(EmployerSearchService); - service['index'] = 'employer-unit-test'; + employerSearchService = module.get<EmployerSearchService>(EmployerSearchService); + employerSearchService['index'] = 'employer-unit-test'; // Init test cases - await service.dropIndex(); - await service.createEmployerIndex(); - await Promise.all(employers.map((employer) => service.indexEmployer(employer))); + await employerSearchService.dropIndex(); + await employerSearchService.createEmployerIndex(); + await Promise.all(employers.map((employer) => employerSearchService.indexEmployer(employer))); // wait for the new structures to be indexed before search - await service.refreshIndexStructure(); + await employerSearchService.refreshIndexStructure(); await new Promise((r) => setTimeout(r, 2000)); }, 10000); it('should be defined', async () => { // await new Promise((r) => setTimeout(r, 9000)); - expect(service).toBeDefined(); + expect(employerSearchService).toBeDefined(); }); // it('should index structures', async () => { @@ -63,37 +63,37 @@ describe('EmployerSearchService Search cases', () => { // await new Promise((r) => setTimeout(r, 2000)); // }, 10000); - it('should find CARSAT', async () => { - const res = await service.search('CARSAT'); - expect(res[0].name).toBe('CARSAT'); + it('should find Metro', async () => { + const res = await employerSearchService.search('Metro'); + expect(res[0].name).toBe('Metro'); expect(res.length).toBe(1); }); - it('should find CAF', async () => { - const res = await service.search('CAF'); - expect(res[0].name).toBe('CAF'); + it('should find Sopra', async () => { + const res = await employerSearchService.search('Sopra'); + expect(res[0].name).toBe('Sopra'); expect(res.length).toBe(1); }); it('should index structures', async () => { - const res = await Promise.all(employers.map((employer) => service.indexEmployer(employer))); + const res = await Promise.all(employers.map((employer) => employerSearchService.indexEmployer(employer))); expect(res).toBeTruthy(); expect(res.length).toBe(5); }); it('should update index', async () => { - const resCaf = await service.search('CAF'); - const res = await service.update( + const resCaf = await employerSearchService.search('Metro'); + const res = await employerSearchService.update( resCaf[0] as EmployerDocument, - new Types.ObjectId('6231aefe76598527c8d0b5bd').toHexString() + new Types.ObjectId('6231aefe76598527c8d0b5ba').toHexString() ); expect(res).toBeTruthy(); }); it('should delete index', async () => { - const resCaf = await service.search('CAF'); - const res = await service.deleteIndex( + const resCaf = await employerSearchService.search('Metro'); + const res = await employerSearchService.deleteIndex( resCaf[0] as EmployerDocument, - new Types.ObjectId('6231aefe76598527c8d0b5bd').toHexString() + new Types.ObjectId('6231aefe76598527c8d0b5ba').toHexString() ); expect(res).toBeTruthy(); }); diff --git a/src/users/services/employer.service.spec.ts b/src/users/services/employer.service.spec.ts index ee6e05392aeee2cdbe9ca6bcd9b04d04d70aabc4..02f28a7a92f375d6ea936f614ccd0f8cb16a5d1a 100644 --- a/src/users/services/employer.service.spec.ts +++ b/src/users/services/employer.service.spec.ts @@ -14,8 +14,8 @@ import { EmployerService } from './employer.service'; import { UsersService } from './users.service'; describe('EmployerService', () => { - let service: EmployerService; - let mailer: MailerService; + let employerService: EmployerService; + let mailerService: MailerService; const mockEmployerSearchService = { indexEmployer: jest.fn(), @@ -61,12 +61,12 @@ describe('EmployerService', () => { MailerService, ], }).compile(); - service = module.get<EmployerService>(EmployerService); - mailer = module.get<MailerService>(MailerService); + employerService = module.get<EmployerService>(EmployerService); + mailerService = module.get<MailerService>(MailerService); }); it('should be defined', () => { - expect(service).toBeDefined(); + expect(employerService).toBeDefined(); }); it('findAll', async () => { @@ -83,7 +83,7 @@ describe('EmployerService', () => { validated: true, }, ]); - const reply = await service.findAll(); + const reply = await employerService.findAll(); expect(reply.length).toBe(2); }); it('findOne', async () => { @@ -93,7 +93,7 @@ describe('EmployerService', () => { name: 'Sopra', validated: true, }); - const reply = await service.findOne('6231aefe76598527c8d0b5bc'); + const reply = await employerService.findOne('6231aefe76598527c8d0b5bc'); expect(reply).toBeTruthy(); }); it('findAllValidated', async () => { @@ -105,7 +105,7 @@ describe('EmployerService', () => { validated: true, }, ]); - const reply = await service.findAllValidated(); + const reply = await employerService.findAllValidated(); expect(reply.length).toBe(1); }); @@ -118,7 +118,7 @@ describe('EmployerService', () => { validated: false, }, ]); - const reply = await service.findAllValidated(); + const reply = await employerService.findAllValidated(); expect(reply.length).toBe(1); }); @@ -131,7 +131,7 @@ describe('EmployerService', () => { validated: false, }, ]); - const reply = await service.findAllUnvalidated(); + const reply = await employerService.findAllUnvalidated(); expect(reply[0].validated).toBeFalsy; }); @@ -149,7 +149,7 @@ describe('EmployerService', () => { validated: true, }, ]); - const reply = await service.findAllUnvalidated(); + const reply = await employerService.findAllUnvalidated(); expect(reply.length).toBe(2); }); @@ -160,7 +160,7 @@ describe('EmployerService', () => { name: 'Sopra', validated: true, }); - const reply = await service.findByName('Sopra'); + const reply = await employerService.findByName('Sopra'); expect(reply).toBeTruthy(); }); @@ -180,10 +180,10 @@ describe('EmployerService', () => { const createEmployer: CreateEmployerDto = { name: 'Sopra', }; - jest.spyOn(service, 'sendAdminCreateNotification').mockResolvedValueOnce(); - const reply = await service.create(createEmployer); + jest.spyOn(employerService, 'sendAdminCreateNotification').mockResolvedValueOnce(); + const reply = await employerService.create(createEmployer); expect(reply).toBeTruthy(); - expect(service.sendAdminCreateNotification).toBeCalledTimes(1); + expect(employerService.sendAdminCreateNotification).toBeCalledTimes(1); }); it('should create validated employer and not send email to admins', async () => { @@ -201,7 +201,7 @@ describe('EmployerService', () => { const createEmployer: CreateEmployerDto = { name: 'Sopra', }; - const reply = await service.create(createEmployer, true, false); + const reply = await employerService.create(createEmployer, true, false); expect(reply).toBeTruthy(); }); }); @@ -220,14 +220,14 @@ describe('EmployerService', () => { deletedCount: 1, }); mockEmployerSearchService.deleteIndex.mockResolvedValueOnce({}); - const reply = await service.deleteByName('Sopra'); + const reply = await employerService.deleteByName('Sopra'); expect(reply).toBeTruthy(); }); describe('Search', () => { it('searchByName', async () => { mockEmployerSearchService.search.mockResolvedValue({ name: 'Sopra' }); - const reply = await service.searchByName('Sopra'); + const reply = await employerService.searchByName('Sopra'); expect(reply).toBeTruthy(); }); @@ -258,7 +258,7 @@ describe('EmployerService', () => { name: 'Sopra', validated: true, } as EmployerDocument); - const reply = await service.initEmployerIndex(); + const reply = await employerService.initEmployerIndex(); expect(reply).toBeTruthy(); expect(reply.length).toBe(2); }); @@ -285,7 +285,7 @@ describe('EmployerService', () => { validated: false, }); mockUserService.replaceEmployers.mockResolvedValueOnce(null); - const reply = await service.mergeEmployer({ + const reply = await employerService.mergeEmployer({ sourceEmployerId: '623aed68c5d45b6fbbaa7e60', targetEmployerId: '623aed68c5d45b6fbbaa7e61', }); @@ -299,10 +299,10 @@ describe('EmployerService', () => { }; mockEmployerModel.findById.mockReturnThis(); mockEmployerModel.exec.mockResolvedValueOnce(null).mockResolvedValueOnce(result); - jest.spyOn(service, 'deleteInvalidEmployer').mockRejectedValueOnce({}); + jest.spyOn(employerService, 'deleteInvalidEmployer').mockRejectedValueOnce({}); mockUserService.replaceEmployers.mockResolvedValueOnce(null); try { - await service.mergeEmployer({ + await employerService.mergeEmployer({ sourceEmployerId: '623aed68c5d45b6fbbaa7e60', targetEmployerId: '623aed68c5d45b6fbbaa7e61', }); @@ -333,8 +333,8 @@ describe('EmployerService', () => { headers: {}, config: {}, }; - jest.spyOn(mailer, 'send').mockResolvedValueOnce(result); - const spyer = jest.spyOn(mailer, 'send'); + jest.spyOn(mailerService, 'send').mockResolvedValueOnce(result); + const spyer = jest.spyOn(mailerService, 'send'); mockUserService.getAdmins.mockResolvedValueOnce([ { _id: '6231aefe76598527c8d0b5bc', @@ -349,7 +349,7 @@ describe('EmployerService', () => { personalOffers: [], }, ]); - await service.sendAdminCreateNotification( + await employerService.sendAdminCreateNotification( employer as EmployerDocument, 'adminEmployerCreate.ejs', 'adminEmployerCreate.json' @@ -367,14 +367,14 @@ describe('EmployerService', () => { validated: false, save: jest.fn().mockResolvedValueOnce(null), }); - const employer = await service.validate('623aed68c5d45b6fbbaa7e60'); + const employer = await employerService.validate('623aed68c5d45b6fbbaa7e60'); expect(employer.validated).toBe(true); }); it('should throw exception', async () => { mockEmployerModel.findById.mockReturnThis(); mockEmployerModel.exec.mockResolvedValueOnce(null); try { - await service.validate('623aed68c5d45b6fbbaa7e60'); + await employerService.validate('623aed68c5d45b6fbbaa7e60'); expect(true).toBe(false); } catch (e) { expect(e.message).toBe('Cannot validate employer. It might have been already validate'); @@ -392,14 +392,14 @@ describe('EmployerService', () => { validated: false, save: jest.fn().mockResolvedValueOnce(null), }); - const employer = await service.update('623aed68c5d45b6fbbaa7e60', { name: 'Sopra' }); + const employer = await employerService.update('623aed68c5d45b6fbbaa7e60', { name: 'Sopra' }); expect(employer.name).toBe('Sopra'); }); it('should throw exception', async () => { mockEmployerModel.findById.mockReturnThis(); mockEmployerModel.exec.mockResolvedValueOnce(null); try { - await service.update('623aed68c5d45b6fbbaa7e60', { name: 'Sopra' }); + await employerService.update('623aed68c5d45b6fbbaa7e60', { name: 'Sopra' }); expect(true).toBe(false); } catch (e) { expect(e.message).toBe('Cannot edit employer. It was not found in database.'); @@ -425,7 +425,7 @@ describe('EmployerService', () => { validated: false, save: jest.fn().mockResolvedValueOnce(null), }); - await service.deleteInvalidEmployer('6231aefe76598527c8d0b5bc'); + await employerService.deleteInvalidEmployer('6231aefe76598527c8d0b5bc'); expect(mockEmployerSearchService.deleteIndex).toBeCalled(); expect(mockEmployerModel.deleteOne).toBeCalled(); }); @@ -458,7 +458,7 @@ describe('EmployerService', () => { personalOffers: [], }), }); - expect(await service.deleteOneId('6231aefe76598527c8d0b5bc')).toStrictEqual({ + expect(await employerService.deleteOneId('6231aefe76598527c8d0b5bc')).toStrictEqual({ _id: '6231aefe76598527c8d0b5bc', validationToken: 'cf1c74c22cedb6b575945098db42d2f493fb759c9142c6aff7980f252886f36ee086574ee99a06bc99119079257116c959c8ec870949cebdef2b293666dbca42', @@ -476,7 +476,7 @@ describe('EmployerService', () => { mockEmployerModel.exec.mockResolvedValueOnce(null); try { - expect(await service.deleteOneId('6231aefe76598527c8d0b5bc')).toStrictEqual({ + expect(await employerService.deleteOneId('6231aefe76598527c8d0b5bc')).toStrictEqual({ _id: '6231aefe76598527c8d0b5bc', validationToken: 'cf1c74c22cedb6b575945098db42d2f493fb759c9142c6aff7980f252886f36ee086574ee99a06bc99119079257116c959c8ec870949cebdef2b293666dbca42', diff --git a/src/users/services/jobs.service.spec.ts b/src/users/services/jobs.service.spec.ts index 1166d891ba238204a9c0ea446484723c293e4a4b..c6eb764f3575c4ab07651ae458d7f608a8e9323b 100644 --- a/src/users/services/jobs.service.spec.ts +++ b/src/users/services/jobs.service.spec.ts @@ -30,7 +30,7 @@ const mockSingleAdminResponse = [ ]; describe('JobsService', () => { - let service: JobsService; + let jobsService: JobsService; const mockJobModel = { create: jest.fn(), @@ -95,13 +95,13 @@ describe('JobsService', () => { { provide: MailerService, useValue: mockMailService }, ], }).compile(); - service = module.get<JobsService>(JobsService); + jobsService = module.get<JobsService>(JobsService); ejsSpy.mockResolvedValue('mock'); jest.clearAllMocks(); }); it('should be defined', () => { - expect(service).toBeDefined(); + expect(jobsService).toBeDefined(); }); describe('findAll', () => { @@ -116,7 +116,7 @@ describe('JobsService', () => { }, ]; mockJobModel.exec.mockResolvedValueOnce(result); - const reply = await service.findAll(); + const reply = await jobsService.findAll(); expect(reply.length).toBe(1); }); it('should findAll all jobs', async () => { @@ -130,7 +130,7 @@ describe('JobsService', () => { }, ]; mockJobModel.exec.mockResolvedValueOnce(result); - const reply = await service.findAll(false); + const reply = await jobsService.findAll(false); expect(reply.length).toBe(1); }); }); @@ -145,7 +145,7 @@ describe('JobsService', () => { jobsGroup: null, }, ]); - const reply = await service.findAllUnvalidated(); + const reply = await jobsService.findAllUnvalidated(); expect(reply[0].validated).toBeFalsy; }); @@ -157,7 +157,7 @@ describe('JobsService', () => { hasPersonalOffer: true, jobsGroup: null, }); - const reply = await service.findByName('CNFS'); + const reply = await jobsService.findByName('CNFS'); expect(reply).toBeTruthy(); }); it('findOne', async () => { @@ -168,7 +168,7 @@ describe('JobsService', () => { hasPersonalOffer: true, jobsGroup: null, }); - const reply = await service.findOne('6231aefe76598527c8d0b5bc'); + const reply = await jobsService.findOne('6231aefe76598527c8d0b5bc'); expect(reply).toBeTruthy(); }); @@ -187,7 +187,7 @@ describe('JobsService', () => { jobsGroup: null, }; mockUserService.getAdmins.mockResolvedValueOnce(mockSingleAdminResponse); - const reply = await service.create(createJob); + const reply = await jobsService.create(createJob); expect(reply).toBeTruthy(); }); }); @@ -206,7 +206,7 @@ describe('JobsService', () => { jobsGroup: null, }; mockUserService.getAdmins.mockResolvedValueOnce(mockSingleAdminResponse); - const reply = await service.create(createJob); + const reply = await jobsService.create(createJob); expect(reply).toBeTruthy(); }); @@ -218,7 +218,7 @@ describe('JobsService', () => { validated: true, }; mockUserService.getAdmins.mockResolvedValueOnce(mockSingleAdminResponse); - await service.sendAdminCreateNotification(job as JobDocument, 'adminJobCreate.ejs', 'adminJobCreate.json'); + await jobsService.sendAdminCreateNotification(job as JobDocument, 'adminJobCreate.ejs', 'adminJobCreate.json'); expect(mockMailService.send).toBeCalledTimes(1); }); }); @@ -231,13 +231,13 @@ describe('JobsService', () => { validated: false, save: jest.fn().mockResolvedValueOnce(null), }); - const job = await service.validate('623aed68c5d45b6fbbaa7e60'); + const job = await jobsService.validate('623aed68c5d45b6fbbaa7e60'); expect(job.validated).toBe(true); }); it('should throw exception', async () => { mockJobModel.exec.mockResolvedValueOnce(null); try { - await service.validate('623aed68c5d45b6fbbaa7e60'); + await jobsService.validate('623aed68c5d45b6fbbaa7e60'); expect(true).toBe(false); } catch (e) { expect(e.message).toBe('Cannot validate job. It might have been already validate'); @@ -266,7 +266,7 @@ describe('JobsService', () => { .mockResolvedValueOnce(result); try { - const reply = await service.mergeJob({ + const reply = await jobsService.mergeJob({ sourceJobId: '623aed68c5d45b6fbbaa7e60', targetJobId: '623aed68c5d45b6fbbaa7e61', }); @@ -286,7 +286,10 @@ describe('JobsService', () => { }) .mockResolvedValueOnce(null); try { - await service.mergeJob({ sourceJobId: '623aed68c5d45b6fbbaa7e60', targetJobId: '623aed68c5d45b6fbbaa7e61' }); + await jobsService.mergeJob({ + sourceJobId: '623aed68c5d45b6fbbaa7e60', + targetJobId: '623aed68c5d45b6fbbaa7e61', + }); expect(true).toBe(false); } catch (e) { expect(e.message).toBe('Cannot operate on job.'); @@ -302,7 +305,10 @@ describe('JobsService', () => { jobsGroup: null, }); try { - await service.mergeJob({ sourceJobId: '623aed68c5d45b6fbbaa7e60', targetJobId: '623aed68c5d45b6fbbaa7e61' }); + await jobsService.mergeJob({ + sourceJobId: '623aed68c5d45b6fbbaa7e60', + targetJobId: '623aed68c5d45b6fbbaa7e61', + }); expect(true).toBe(false); } catch (e) { expect(e.message).toBe('Cannot operate on job.'); @@ -313,8 +319,8 @@ describe('JobsService', () => { it('deleteInvalidJob', async () => { mockJobModel.exec.mockResolvedValueOnce(null); - const spyer = jest.spyOn(service, 'deleteInvalidJob'); - await service.deleteInvalidJob('623aed68c5d45b6fbbaa7e60'); + const spyer = jest.spyOn(jobsService, 'deleteInvalidJob'); + await jobsService.deleteInvalidJob('623aed68c5d45b6fbbaa7e60'); expect(spyer.mock.calls.length).toEqual(1); }); @@ -326,13 +332,13 @@ describe('JobsService', () => { validated: false, deleteOne: jest.fn().mockResolvedValueOnce('toto'), }); - const reply = await service.deleteOneId('623aed68c5d45b6fbbaa7e60'); + const reply = await jobsService.deleteOneId('623aed68c5d45b6fbbaa7e60'); expect(reply).toBe('toto'); }); it('should delete ', async () => { mockJobModel.exec.mockResolvedValueOnce(null); try { - await service.deleteOneId('623aed68c5d45b6fbbaa7e60'); + await jobsService.deleteOneId('623aed68c5d45b6fbbaa7e60'); expect(true).toBe(false); } catch (e) { expect(e.message).toBe('Invalid job id'); @@ -363,7 +369,7 @@ describe('JobsService', () => { jobsGroup: null, save: jest.fn().mockResolvedValueOnce(newJob), }); - const reply = await service.update('623aed68c5d45b6fbbaa7e60', newJobDto); + const reply = await jobsService.update('623aed68c5d45b6fbbaa7e60', newJobDto); expect(reply.name).toBe('CNFS'); expect(reply.hasPersonalOffer).toBe(true); }); @@ -377,7 +383,7 @@ describe('JobsService', () => { }; mockJobModel.exec.mockResolvedValueOnce(null); try { - await service.update('623aed68c5d45b6fbbaa7e60', newJobDto); + await jobsService.update('623aed68c5d45b6fbbaa7e60', newJobDto); expect(true).toBe(false); } catch (e) { expect(e.message).toBe('Cannot edit job. It was not found in database.'); diff --git a/src/users/services/jobsGroups.service.spec.ts b/src/users/services/jobsGroups.service.spec.ts index ee25b30ddf2196b67351dfb80629611f4b52ebcf..0efb723e8c35e6313c7ecc9c8a8c8fddff176c57 100644 --- a/src/users/services/jobsGroups.service.spec.ts +++ b/src/users/services/jobsGroups.service.spec.ts @@ -6,12 +6,12 @@ import { Types } from 'mongoose'; import { ConfigurationModule } from '../../configuration/configuration.module'; import { MailerService } from '../../mailer/mailer.service'; import { CreateJobsGroupsDto } from '../dto/create-jobsGroups.dto'; +import { JobsService } from './jobs.service'; import { JobsGroupsService } from './jobsGroups.service'; import { UsersService } from './users.service'; -import { JobsService } from './jobs.service'; describe('JobsGroupsService', () => { - let service: JobsGroupsService; + let jobsGroupsService: JobsGroupsService; const mockJobsGroupsModel = { create: jest.fn(), @@ -71,11 +71,11 @@ describe('JobsGroupsService', () => { MailerService, ], }).compile(); - service = module.get<JobsGroupsService>(JobsGroupsService); + jobsGroupsService = module.get<JobsGroupsService>(JobsGroupsService); }); it('should be defined', () => { - expect(service).toBeDefined(); + expect(jobsGroupsService).toBeDefined(); }); describe('findAll', () => { @@ -87,7 +87,7 @@ describe('JobsGroupsService', () => { }, ]; mockJobsGroupsModel.exec.mockResolvedValueOnce(result); - const reply = await service.findAll(false); + const reply = await jobsGroupsService.findAll(false); expect(reply.length).toBe(1); }); }); @@ -97,7 +97,7 @@ describe('JobsGroupsService', () => { _id: new Types.ObjectId('6231aefe76598527c8d0b5bc'), name: 'Technique', }); - const reply = await service.findByName('Technique'); + const reply = await jobsGroupsService.findByName('Technique'); expect(reply).toBeTruthy(); }); it('findOne', async () => { @@ -105,7 +105,7 @@ describe('JobsGroupsService', () => { _id: new Types.ObjectId('6231aefe76598527c8d0b5bc'), name: 'Technique', }); - const reply = await service.findOne('6231aefe76598527c8d0b5bc'); + const reply = await jobsGroupsService.findOne('6231aefe76598527c8d0b5bc'); expect(reply).toBeTruthy(); }); @@ -118,7 +118,7 @@ describe('JobsGroupsService', () => { const createJobsGroups: CreateJobsGroupsDto = { name: 'Technique', }; - const reply = await service.create(createJobsGroups); + const reply = await jobsGroupsService.create(createJobsGroups); expect(reply).toBeTruthy(); }); }); @@ -137,7 +137,7 @@ describe('JobsGroupsService', () => { name: 'Technique old', save: jest.fn().mockResolvedValueOnce(newJobsGroups), }); - const reply = await service.update('623aed68c5d45b6fbbaa7e60', newJobsGroupsDto); + const reply = await jobsGroupsService.update('623aed68c5d45b6fbbaa7e60', newJobsGroupsDto); expect(reply.name).toBe('Technique'); }); }); @@ -148,7 +148,7 @@ describe('JobsGroupsService', () => { }; mockJobsGroupsModel.exec.mockResolvedValueOnce(null); try { - await service.update('623aed68c5d45b6fbbaa7e60', newJobsGroupsDto); + await jobsGroupsService.update('623aed68c5d45b6fbbaa7e60', newJobsGroupsDto); expect(true).toBe(false); } catch (e) { expect(e.status).toBe(HttpStatus.NOT_FOUND); diff --git a/src/users/services/userRegistry-search.service.spec.ts b/src/users/services/userRegistry-search.service.spec.ts index 4fdd1dd21290ae5c264c2196429a01635ee8d6b6..75ce36518a2e5c60a131f091d53a59ede73a2d11 100644 --- a/src/users/services/userRegistry-search.service.spec.ts +++ b/src/users/services/userRegistry-search.service.spec.ts @@ -7,7 +7,7 @@ import { IUserRegistry } from '../interfaces/userRegistry.interface'; import { UserRegistrySearchService } from './userRegistry-search.service'; describe('UserRegistrySearchService Search cases', () => { - let service: UserRegistrySearchService; + let userRegistrySearchService: UserRegistrySearchService; beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ @@ -15,52 +15,52 @@ describe('UserRegistrySearchService Search cases', () => { providers: [UserRegistrySearchService], }).compile(); - service = module.get<UserRegistrySearchService>(UserRegistrySearchService); - service['index'] = 'user-unit-test'; + userRegistrySearchService = module.get<UserRegistrySearchService>(UserRegistrySearchService); + userRegistrySearchService['index'] = 'user-unit-test'; // Init test cases - await service.dropIndex(); - await service.createUserRegistryIndex(); - await Promise.all(multipleUsers.map((user) => service.indexUserRegistry(user))); + await userRegistrySearchService.dropIndex(); + await userRegistrySearchService.createUserRegistryIndex(); + await Promise.all(multipleUsers.map((user) => userRegistrySearchService.indexUserRegistry(user))); // wait for the new structures to be indexed before search - await service.refreshIndexUserRegistry(); + await userRegistrySearchService.refreshIndexUserRegistry(); await new Promise((r) => setTimeout(r, 2000)); }, 10000); it('should be defined', async () => { - expect(service).toBeDefined(); + expect(userRegistrySearchService).toBeDefined(); }); describe('Search method', () => { it('should find Guilhem', async () => { - const res = await service.search('Guilhem'); + const res = await userRegistrySearchService.search('Guilhem'); expect(res[0].surname).toBe('Guilhem'); expect(res.length).toBe(1); }); it('should find adm', async () => { - const res = await service.search('adm'); + const res = await userRegistrySearchService.search('adm'); expect(res[0].name).toBe('Admin'); expect(res.length).toBe(1); }); it('should find empty string', async () => { - const res = await service.search(''); + const res = await userRegistrySearchService.search(''); expect(res.length).toBe(6); }); }); describe('Indexation methods', () => { it('should index User', async () => { - const res = await Promise.all(multipleUsers.map((user) => service.indexUserRegistry(user))); + const res = await Promise.all(multipleUsers.map((user) => userRegistrySearchService.indexUserRegistry(user))); expect(res).toBeTruthy(); expect(res.length).toBe(6); }); it('should update index', async () => { - const res = await service.update(multipleUsers[0] as IUserRegistry); + const res = await userRegistrySearchService.update(multipleUsers[0] as IUserRegistry); expect(res).toBeTruthy(); }); it('should delete index', async () => { const mockDelete = jest.fn(); jest.spyOn(ElasticsearchService.prototype, 'delete').mockImplementation(mockDelete); - const resAdm = await service.search('adm'); - await service.deleteIndex(resAdm[0] as IUserRegistry); + const resAdm = await userRegistrySearchService.search('adm'); + await userRegistrySearchService.deleteIndex(resAdm[0] as IUserRegistry); expect(mockDelete).toBeCalled(); }); }); diff --git a/src/users/services/userRegistry-search.service.ts b/src/users/services/userRegistry-search.service.ts index 1b57967efbb958e0600ffcdcb7755d7a20f2c58b..267bebafa93712c58f6f6e214b53ea9d81eecc84 100644 --- a/src/users/services/userRegistry-search.service.ts +++ b/src/users/services/userRegistry-search.service.ts @@ -1,8 +1,4 @@ -import { - IndicesCreateResponse, - IndicesRefreshResponse, - IndicesResponseBase, -} from '@elastic/elasticsearch/lib/api/types'; +import { IndicesCreateResponse, IndicesRefreshResponse } from '@elastic/elasticsearch/lib/api/types'; import { Injectable, Logger } from '@nestjs/common'; import { ElasticsearchService } from '@nestjs/elasticsearch'; import { es_settings_homemade_french, escapeElasticsearchQuery } from '../../shared/utils'; @@ -54,7 +50,7 @@ export class UserRegistrySearchService { }); } - public async dropIndex(): Promise<IndicesResponseBase> { + public async dropIndex() { this.logger.debug('dropIndex'); const foundIndexes = await this.elasticsearchService.indices.exists({ index: this.index, @@ -105,20 +101,16 @@ export class UserRegistrySearchService { } public async update(user: IUserRegistry) { - this.logger.debug(`Updates user : ${user._id} `); - this.logger.debug(user); - const userParam: Partial<IUserRegistry> = { - name: user.name, - surname: user.surname, - }; - - if (user.job) userParam.job = user.job; - if (user.employer) userParam.employer = user.employer; - + this.logger.debug(`Updates user : ${user._id}`); return this.elasticsearchService.update<UserRegistrySearchBody>({ index: this.index, id: user._id, - doc: userParam, + doc: { + name: user.name, + surname: user.surname, + job: user.job ?? null, + employer: user.employer ?? null, + }, }); } } diff --git a/src/users/services/userRegistry.service.spec.ts b/src/users/services/userRegistry.service.spec.ts index 9680741baf340e2b8cfac5378fb779495f2b84b7..7cca791d156e5fd927081caedf7a68f161e4f333 100644 --- a/src/users/services/userRegistry.service.spec.ts +++ b/src/users/services/userRegistry.service.spec.ts @@ -11,7 +11,7 @@ import { UserRegistrySearchService } from './userRegistry-search.service'; import { UserRegistryService } from './userRegistry.service'; describe('userRegistryService', () => { - let service: UserRegistryService; + let userRegistryService: UserRegistryService; const mockUserRegistryModel = { find: jest.fn(() => mockUserRegistryModel), where: jest.fn(() => mockUserRegistryModel), @@ -62,11 +62,11 @@ describe('userRegistryService', () => { }, ], }).compile(); - service = module.get<UserRegistryService>(UserRegistryService); + userRegistryService = module.get<UserRegistryService>(UserRegistryService); }); it('should be defined', () => { - expect(service).toBeDefined(); + expect(userRegistryService).toBeDefined(); }); describe('findAll', () => { @@ -88,18 +88,18 @@ describe('userRegistryService', () => { ] as IUserRegistry[]; it('should findAll UserRegistry for indexation', async () => { mockUserRegistryModel.exec.mockResolvedValueOnce(result); - expect(await service.findAllForIndexation()).toBe(result); + expect(await userRegistryService.findAllForIndexation()).toBe(result); }); it('should findAll UserRegistry count', async () => { mockUserRegistryModel.exec.mockResolvedValueOnce(result.length); - expect(await service.countAllUserRegistry()).toBe(result.length); + expect(await userRegistryService.countAllUserRegistry()).toBe(result.length); }); it('should findAllUserRegistry with page number 1', async () => { const res = { count: 1, docs: result }; mockUserRegistryModel.exec.mockResolvedValueOnce(1); mockUserRegistryModel.exec.mockResolvedValueOnce(result); - expect(await service.findAllUserRegistry(1)).toStrictEqual(res); + expect(await userRegistryService.findAllUserRegistry(1)).toStrictEqual(res); }); }); describe('find with filter', () => { @@ -142,13 +142,13 @@ describe('userRegistryService', () => { it('should findUsersByNameEmployerOrJobsGroup with string param and get a result', async () => { mockUserRegistryModel.exec.mockResolvedValueOnce(result); mockUserRegistrySearchService.search.mockResolvedValueOnce(result); - expect(await service.findUsersByNameEmployerOrJobsGroup('adm', 1)).toStrictEqual(res); + expect(await userRegistryService.findUsersByNameEmployerOrJobsGroup('adm', 1)).toStrictEqual(res); }); it('should findUsersByNameEmployerOrJobsGroup with string param and get no result', async () => { const emptyRes = { count: 0, docs: [] }; mockUserRegistryModel.exec.mockResolvedValueOnce([]); mockUserRegistrySearchService.search.mockResolvedValueOnce([]); - expect(await service.findUsersByNameEmployerOrJobsGroup('azerty', 1)).toStrictEqual(emptyRes); + expect(await userRegistryService.findUsersByNameEmployerOrJobsGroup('azerty', 1)).toStrictEqual(emptyRes); }); it('should findUsersByNameEmployerOrJobsGroup with no string param and filters', async () => { const res = { count: 1, docs: [multipleUsers[1]] }; @@ -163,7 +163,9 @@ describe('userRegistryService', () => { mockJobsGroupsService.findByName.mockResolvedValueOnce(jobGroupList[0]); mockEmployersService.findByName.mockResolvedValueOnce(employerList[0]); mockUserRegistryModel.exec.mockResolvedValueOnce(multipleUsers); - expect(await service.findUsersByNameEmployerOrJobsGroup('', 1, ['Technique'], ['Métropole'])).toStrictEqual(res); + expect( + await userRegistryService.findUsersByNameEmployerOrJobsGroup('', 1, ['Technique'], ['Métropole']) + ).toStrictEqual(res); }); it('should findUsersByNameEmployerOrJobsGroup with string param and filters', async () => { @@ -179,9 +181,9 @@ describe('userRegistryService', () => { mockJobsGroupsService.findByName.mockResolvedValueOnce(jobGroupList[0]); mockEmployersService.findByName.mockResolvedValueOnce(employerList[0]); mockUserRegistryModel.exec.mockResolvedValueOnce(multipleUsers); - expect(await service.findUsersByNameEmployerOrJobsGroup('Guil', 1, ['Technique'], ['Métropole'])).toStrictEqual( - res - ); + expect( + await userRegistryService.findUsersByNameEmployerOrJobsGroup('Guil', 1, ['Technique'], ['Métropole']) + ).toStrictEqual(res); }); it('should findUsersByNameEmployerOrJobsGroup with string param and filters and return empty', async () => { const res = { count: 0, docs: [] }; @@ -197,7 +199,7 @@ describe('userRegistryService', () => { mockEmployersService.findByName.mockResolvedValueOnce(employerList[0]); mockUserRegistryModel.exec.mockResolvedValueOnce([]); expect( - await service.findUsersByNameEmployerOrJobsGroup('azerrttt', 1, ['Technique'], ['Métropole']) + await userRegistryService.findUsersByNameEmployerOrJobsGroup('azerrttt', 1, ['Technique'], ['Métropole']) ).toStrictEqual(res); }); it('should findUsersByNameEmployerOrJobsGroup with string param and one employer filter', async () => { @@ -206,7 +208,7 @@ describe('userRegistryService', () => { mockUserRegistrySearchService.search.mockResolvedValueOnce(multipleUsers); mockEmployersService.findByName.mockResolvedValueOnce(employerList[0]); mockUserRegistryModel.exec.mockResolvedValueOnce(multipleUsers); - expect(await service.findUsersByNameEmployerOrJobsGroup('a', 1, [], ['CAF'])).toStrictEqual(res); + expect(await userRegistryService.findUsersByNameEmployerOrJobsGroup('a', 1, [], ['CAF'])).toStrictEqual(res); }); it('should findUsersByNameEmployerOrJobsGroup with no string param and one jobsGroup filter', async () => { @@ -220,7 +222,7 @@ describe('userRegistryService', () => { mockUserRegistrySearchService.search.mockResolvedValueOnce(multipleUsers); mockJobsGroupsService.findByName.mockResolvedValueOnce(jobGroupList[0]); mockUserRegistryModel.exec.mockResolvedValueOnce(multipleUsers); - expect(await service.findUsersByNameEmployerOrJobsGroup('', 1, ['Technique'], [])).toStrictEqual(res); + expect(await userRegistryService.findUsersByNameEmployerOrJobsGroup('', 1, ['Technique'], [])).toStrictEqual(res); }); }); @@ -230,13 +232,13 @@ describe('userRegistryService', () => { mockUserRegistrySearchService.dropIndex.mockResolvedValueOnce({}); mockUserRegistrySearchService.createUserRegistryIndex.mockResolvedValueOnce({}); mockUserRegistrySearchService.indexUserRegistry.mockResolvedValueOnce({}); - expect(await service.initUserRegistryIndex()).toBe(multipleUsers); + expect(await userRegistryService.initUserRegistryIndex()).toBe(multipleUsers); }); it('should findAllUserRegistry with page number 1', async () => { mockUserRegistrySearchService.search.mockResolvedValueOnce([multipleUsers[0]]); - expect(await service.searchByNameAndSurname('adm')).toStrictEqual([multipleUsers[0]]); + expect(await userRegistryService.searchByNameAndSurname('adm')).toStrictEqual([multipleUsers[0]]); }); }); }); diff --git a/src/users/services/userRegistry.service.ts b/src/users/services/userRegistry.service.ts index a4eba6591907870d466f82dd2f926630eb31c14a..8d438cabe6c1113ebe912e93788c3b503eae9efd 100644 --- a/src/users/services/userRegistry.service.ts +++ b/src/users/services/userRegistry.service.ts @@ -130,8 +130,8 @@ export class UserRegistryService { return this.userRegistrySearchService.search(searchString); } - public async initUserRegistryIndex(): Promise<IUserRegistry[]> { - Logger.log('Reset structures indexes'); + public async initUserRegistryIndex() { + Logger.log('Reset users indexes'); await this.userRegistrySearchService.dropIndex(); await this.userRegistrySearchService.createUserRegistryIndex(); return this.populateES(); diff --git a/src/users/services/users.service.spec.ts b/src/users/services/users.service.spec.ts index 0b7bf0db046eacc859df151fff7093f3a6401b13..f3e695b9d69c4a0a3e522d05bfb16c9ca810c399 100644 --- a/src/users/services/users.service.spec.ts +++ b/src/users/services/users.service.spec.ts @@ -1,4 +1,3 @@ -import { cnfsJobMock } from './../../../test/mock/data/jobs.mock.data'; import { HttpModule } from '@nestjs/axios'; import { HttpException, HttpStatus } from '@nestjs/common'; import { JwtService } from '@nestjs/jwt'; @@ -10,11 +9,13 @@ import { employersMockData } from '../../../test/mock/data/employers.mock.data'; import { personalOffersDataMock } from '../../../test/mock/data/personalOffers.mock.data'; import { userDetails, userRegistryMockData, usersMockData } from '../../../test/mock/data/users.mock.data'; import { MailerMockService } from '../../../test/mock/services/mailer.mock.service'; +import { StructuresServiceMock } from '../../../test/mock/services/structures.mock.service'; import { LoginDto } from '../../auth/login-dto'; import { ConfigurationModule } from '../../configuration/configuration.module'; import { MailerModule } from '../../mailer/mailer.module'; import { MailerService } from '../../mailer/mailer.service'; import { PersonalOfferDocument } from '../../personal-offers/schemas/personal-offer.schema'; +import { StructuresService } from '../../structures/services/structures.service'; import { CreateUserDto } from '../dto/create-user.dto'; import { DescriptionDto } from '../dto/description.dto'; import { UpdateDetailsDto } from '../dto/update-details.dto'; @@ -22,11 +23,10 @@ import { IUser } from '../interfaces/user.interface'; import { EmployerDocument } from '../schemas/employer.schema'; import { JobDocument } from '../schemas/job.schema'; import { User } from '../schemas/user.schema'; +import { cnfsJobMock } from './../../../test/mock/data/jobs.mock.data'; +import { JobsService } from './jobs.service'; import { UserRegistrySearchService } from './userRegistry-search.service'; import { UsersService } from './users.service'; -import { JobsService } from './jobs.service'; -import { StructuresService } from '../../structures/services/structures.service'; -import { StructuresServiceMock } from '../../../test/mock/services/structures.mock.service'; function hashPassword() { return bcrypt.hashSync(process.env.USER_PWD, process.env.SALT); @@ -127,7 +127,7 @@ const mockJobsService = { }; describe('UsersService', () => { - let service: UsersService; + let usersService: UsersService; beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ @@ -159,21 +159,21 @@ describe('UsersService', () => { ], }).compile(); - service = module.get<UsersService>(UsersService); + usersService = module.get<UsersService>(UsersService); }); afterEach(() => { jest.clearAllMocks(); }); it('UsersService should be defined', () => { - expect(service).toBeDefined(); + expect(usersService).toBeDefined(); }); describe('create', () => { it('should not create a User, already exist', async () => { - jest.spyOn(service, 'findOne').mockImplementationOnce(async (): Promise<any> => createUserDto); + jest.spyOn(usersService, 'findOne').mockImplementationOnce(async (): Promise<any> => createUserDto); try { - await service.create(createUserDto); + await usersService.create(createUserDto); expect(true).toBe(false); } catch (error) { expect(error.status).toBe(HttpStatus.BAD_REQUEST); @@ -182,10 +182,10 @@ describe('UsersService', () => { }); it('should not create User, weak password', async () => { - jest.spyOn(service, 'findOne').mockImplementationOnce(async () => null); - jest.spyOn(service, 'isStrongPassword').mockImplementationOnce(() => false); + jest.spyOn(usersService, 'findOne').mockImplementationOnce(async () => null); + jest.spyOn(usersService, 'isStrongPassword').mockImplementationOnce(() => false); try { - await service.create(createUserDto); + await usersService.create(createUserDto); expect(true).toBe(false); } catch (error) { expect(error.status).toBe(HttpStatus.UNPROCESSABLE_ENTITY); @@ -195,59 +195,59 @@ describe('UsersService', () => { } }); it('should create a User', async () => { - jest.spyOn(service, 'findOne').mockImplementationOnce(async () => null); - jest.spyOn(service, 'isStrongPassword').mockImplementationOnce(() => true); + jest.spyOn(usersService, 'findOne').mockImplementationOnce(async () => null); + jest.spyOn(usersService, 'isStrongPassword').mockImplementationOnce(() => true); //TODO mock new userModal(createUserDto) return; - jest.spyOn(service, 'findOne').mockImplementationOnce(async (): Promise<any> => mockUser); - expect(await service.create(createUserDto)).toBe(mockUser); + jest.spyOn(usersService, 'findOne').mockImplementationOnce(async (): Promise<any> => mockUser); + expect(await usersService.create(createUserDto)).toBe(mockUser); }); }); describe('isStrongPassword', () => { it('should return false with "AZERTYU1" (no lowercase character)', () => { - expect(service.isStrongPassword('AZERTY')).toBe(false); + expect(usersService.isStrongPassword('AZERTY')).toBe(false); }); it('should return false with "azertyu1" (no uppercase character)', () => { - expect(service.isStrongPassword('azerty')).toBe(false); + expect(usersService.isStrongPassword('azerty')).toBe(false); }); it('should return false with "azertyui" (no number)', () => { - expect(service.isStrongPassword('azerty')).toBe(false); + expect(usersService.isStrongPassword('azerty')).toBe(false); }); it('should return false with "azertyu1" (no special character)', () => { - expect(service.isStrongPassword('azertyu1')).toBe(false); + expect(usersService.isStrongPassword('azertyu1')).toBe(false); }); it('should return false with "azertyu1" (no special character)', () => { - expect(service.isStrongPassword('azertyu1')).toBe(false); + expect(usersService.isStrongPassword('azertyu1')).toBe(false); }); it('should return false with "azer" (too short)', () => { - expect(service.isStrongPassword('azer')).toBe(false); + expect(usersService.isStrongPassword('azer')).toBe(false); }); it('should return true with "Azerty1!', () => { - expect(service.isStrongPassword('Azerty1!')).toBe(true); + expect(usersService.isStrongPassword('Azerty1!')).toBe(true); }); }); describe('findOne', () => { it('should find one user', async () => { mockUserModel.exec.mockResolvedValue(mockUser); - expect(await service.findOne('some@mail.com')).toBe(mockUser); + expect(await usersService.findOne('some@mail.com')).toBe(mockUser); }); }); describe('findAll', () => { it('should find all users', async () => { mockUserModel.exec.mockResolvedValue(usersMockData); - expect(await service.findAll()).toBe(usersMockData); + expect(await usersService.findAll()).toBe(usersMockData); }); }); describe('findByLogin', () => { const loginDto: LoginDto = { email: 'jacques.dupont@mii.com', password: 'test1A!!' }; it('should fail, no user found', async () => { - jest.spyOn(service, 'findOne').mockResolvedValue(null); + jest.spyOn(usersService, 'findOne').mockResolvedValue(null); try { - await service.findByLogin(loginDto); + await usersService.findByLogin(loginDto); expect(true).toBe(false); } catch (error) { expect(error.status).toBe(HttpStatus.UNAUTHORIZED); @@ -256,11 +256,11 @@ describe('UsersService', () => { }); it('should fail, wrong password', async () => { - jest.spyOn(service, 'findOne').mockResolvedValue(mockUser as IUser); + jest.spyOn(usersService, 'findOne').mockResolvedValue(mockUser as IUser); //TODO mock private function comparePassword ? -> false return true; try { - await service.findByLogin(loginDto); + await usersService.findByLogin(loginDto); expect(true).toBe(false); } catch (error) { expect(error.status).toBe(HttpStatus.UNAUTHORIZED); @@ -270,18 +270,18 @@ describe('UsersService', () => { it('should find', async () => { mockUserModel.findOne.mockResolvedValue(mockUser); - jest.spyOn(service, 'findOne').mockResolvedValue(mockUser as IUser); + jest.spyOn(usersService, 'findOne').mockResolvedValue(mockUser as IUser); //TODO mock private function comparePassword ? -> true return true; - expect(await service.findByLogin(loginDto)).toBe(mockUser); + expect(await usersService.findByLogin(loginDto)).toBe(mockUser); }); it('wrong password, should be unauthorized issue', async () => { const result: HttpException = new HttpException('Invalid credentials', HttpStatus.UNAUTHORIZED); const loginDto: LoginDto = { email: 'jacques.dupont@mii.com', password: 'test1A!!!' }; //NOSONAR - jest.spyOn(service, 'findOne').mockResolvedValue(null); + jest.spyOn(usersService, 'findOne').mockResolvedValue(null); try { - await service.findByLogin(loginDto); + await usersService.findByLogin(loginDto); expect(true).toBe(false); } catch (error) { expect(error.status).toBe(HttpStatus.UNAUTHORIZED); @@ -294,8 +294,8 @@ describe('UsersService', () => { // TODO implement correct tests it('should not validateUser', async () => { const result = new HttpException('Invalid token', HttpStatus.UNAUTHORIZED); - jest.spyOn(service, 'validateUser').mockImplementation(async (): Promise<HttpException> => result); - expect(await service.validateUser('add3d', 'qdqdqdqd185')).toBe(result); + jest.spyOn(usersService, 'validateUser').mockImplementation(async (): Promise<HttpException> => result); + expect(await usersService.validateUser('add3d', 'qdqdqdqd185')).toBe(result); }); }); @@ -330,16 +330,16 @@ describe('UsersService', () => { describe('addPersonalOffer', () => { const personalOfferDocumentMock: PersonalOfferDocument = personalOffersDataMock[0] as PersonalOfferDocument; it('should add personal offer to the user', async () => { - jest.spyOn(service, 'findById').mockResolvedValue(usersMockData[0]); + jest.spyOn(usersService, 'findById').mockResolvedValue(usersMockData[0]); const expectedResult = { ...usersMockData[0], personalOffers: [personalOfferDocumentMock] }; - expect(await service.addPersonalOffer('6036721022462b001334c4bb', personalOfferDocumentMock)).toEqual( + expect(await usersService.addPersonalOffer('6036721022462b001334c4bb', personalOfferDocumentMock)).toEqual( expectedResult ); }); it('should return exception if user is not found for given id', async () => { - jest.spyOn(service, 'findById').mockResolvedValue(null); + jest.spyOn(usersService, 'findById').mockResolvedValue(null); try { - await service.addPersonalOffer('abcd', personalOfferDocumentMock); + await usersService.addPersonalOffer('abcd', personalOfferDocumentMock); // Fail test if above expression doesn't throw anything. expect(true).toBe(false); } catch (e) { @@ -348,9 +348,9 @@ describe('UsersService', () => { } }); it('should return exception if personal offer already exists in the user', async () => { - jest.spyOn(service, 'findById').mockResolvedValue(usersMockData[1]); + jest.spyOn(usersService, 'findById').mockResolvedValue(usersMockData[1]); try { - await service.addPersonalOffer('6093ba0e2ab5775cfc01ed3e', personalOfferDocumentMock); + await usersService.addPersonalOffer('6093ba0e2ab5775cfc01ed3e', personalOfferDocumentMock); // Fail test if above expression doesn't throw anything. expect(true).toBe(false); } catch (e) { @@ -362,8 +362,8 @@ describe('UsersService', () => { describe('getStructureOwnersDetails', () => { const userDetailsMock: IUser[] = userDetails; it('should get Structure Owners Details', async () => { - jest.spyOn(service, 'getStructureOwnersDetails').mockResolvedValue(userDetails); - expect(await service.getStructureOwnersDetails('627b85aea0466f0f132e1599')).toEqual(userDetailsMock); + jest.spyOn(usersService, 'getStructureOwnersDetails').mockResolvedValue(userDetails); + expect(await usersService.getStructureOwnersDetails('627b85aea0466f0f132e1599')).toEqual(userDetailsMock); }); }); @@ -373,7 +373,7 @@ describe('UsersService', () => { mockUserModel.updateMany.mockReturnThis(); mockUserModel.exec.mockResolvedValueOnce([usersMockData[0]]); - await service.replaceEmployers(employersMockData[0], employersMockData[1]); + await usersService.replaceEmployers(employersMockData[0], employersMockData[1]); expect(spyer).toBeCalledTimes(1); }); @@ -425,10 +425,14 @@ describe('UsersService', () => { it('should updateUserProfile', async () => { const spyer = jest.spyOn(mockUserRegistrySearchService, 'update'); const spyerFindPopulate = jest - .spyOn(service, 'findPopulatedUserRegistryById') + .spyOn(usersService, 'findPopulatedUserRegistryById') .mockImplementationOnce(async () => userRegistryMockData); mockUserModel.exec.mockResolvedValueOnce(usersMockData[0]); - const result = await service.updateUserProfile(new Types.ObjectId('627b85aea0466f0f132e1599'), employer, job); + const result = await usersService.updateUserProfile( + new Types.ObjectId('627b85aea0466f0f132e1599'), + employer, + job + ); expect(spyer).toBeCalledTimes(1); expect(spyerFindPopulate).toBeCalledTimes(1); expect(result).toEqual(usersMockData[0]); @@ -436,7 +440,11 @@ describe('UsersService', () => { it('should not updateUserProfile', async () => { const spyer = jest.spyOn(mockUserRegistrySearchService, 'update'); mockUserModel.exec.mockResolvedValueOnce(null); - const result = await service.updateUserProfile(new Types.ObjectId('627b85aea0466f0f132e1599'), employer, job); + const result = await usersService.updateUserProfile( + new Types.ObjectId('627b85aea0466f0f132e1599'), + employer, + job + ); expect(spyer).toBeCalledTimes(0); expect(result).toEqual(null); }); @@ -451,10 +459,10 @@ describe('UsersService', () => { it('should updateUserJob', async () => { const spyer = jest.spyOn(mockUserRegistrySearchService, 'update'); const spyerFindPopulate = jest - .spyOn(service, 'findPopulatedUserRegistryById') + .spyOn(usersService, 'findPopulatedUserRegistryById') .mockImplementationOnce(async () => userRegistryMockData); mockUserModel.exec.mockResolvedValueOnce(usersMockData[0]); - const result = await service.updateUserJob(new Types.ObjectId('627b85aea0466f0f132e1599'), job); + const result = await usersService.updateUserJob(new Types.ObjectId('627b85aea0466f0f132e1599'), job); expect(spyer).toBeCalledTimes(1); expect(spyerFindPopulate).toBeCalledTimes(1); expect(result).toEqual(usersMockData[0]); @@ -462,7 +470,7 @@ describe('UsersService', () => { it('should not updateUserJob', async () => { const spyer = jest.spyOn(mockUserRegistrySearchService, 'update'); mockUserModel.exec.mockResolvedValueOnce(null); - const result = await service.updateUserJob(new Types.ObjectId('627b85aea0466f0f132e1599'), job); + const result = await usersService.updateUserJob(new Types.ObjectId('627b85aea0466f0f132e1599'), job); expect(spyer).toBeCalledTimes(0); expect(result).toEqual(null); }); @@ -477,10 +485,10 @@ describe('UsersService', () => { it('should updateUserEmployer', async () => { const spyer = jest.spyOn(mockUserRegistrySearchService, 'update'); const spyerFindPopulate = jest - .spyOn(service, 'findPopulatedUserRegistryById') + .spyOn(usersService, 'findPopulatedUserRegistryById') .mockImplementationOnce(async () => userRegistryMockData); mockUserModel.exec.mockResolvedValueOnce(usersMockData[0]); - const result = await service.updateUserEmployer(new Types.ObjectId('627b85aea0466f0f132e1599'), employer); + const result = await usersService.updateUserEmployer(new Types.ObjectId('627b85aea0466f0f132e1599'), employer); expect(spyer).toBeCalledTimes(1); expect(spyerFindPopulate).toBeCalledTimes(1); expect(result).toEqual(usersMockData[0]); @@ -488,7 +496,7 @@ describe('UsersService', () => { it('should not updateUserEmployer', async () => { const spyer = jest.spyOn(mockUserRegistrySearchService, 'update'); mockUserModel.exec.mockResolvedValueOnce(null); - const result = await service.updateUserEmployer(new Types.ObjectId('627b85aea0466f0f132e1599'), employer); + const result = await usersService.updateUserEmployer(new Types.ObjectId('627b85aea0466f0f132e1599'), employer); expect(spyer).toBeCalledTimes(0); expect(result).toEqual(null); }); @@ -500,9 +508,9 @@ describe('UsersService', () => { const detailsDto: UpdateDetailsDto = { name: 'Michel', surname: 'Chelmi', phone: '0601020304' }; mockUserModel.exec.mockResolvedValueOnce({ ...user, ...detailsDto }); const spyerFindPopulate = jest - .spyOn(service, 'findPopulatedUserRegistryById') + .spyOn(usersService, 'findPopulatedUserRegistryById') .mockImplementationOnce(async () => userRegistryMockData); - const updatedUser = await service.updateUserDetails('', { name: '', surname: '', phone: '' }); + const updatedUser = await usersService.updateUserDetails('', { name: '', surname: '', phone: '' }); expect(spyerFindPopulate).toBeCalledTimes(1); expect(updatedUser.name).toBe(detailsDto.name); expect(updatedUser.surname).toBe(detailsDto.surname); @@ -512,7 +520,7 @@ describe('UsersService', () => { mockUserModel.findByIdAndUpdate.mockReturnThis(); mockUserModel.exec.mockResolvedValueOnce(null); try { - await service.updateUserDetails('', { name: '', surname: '', phone: '' }); + await usersService.updateUserDetails('', { name: '', surname: '', phone: '' }); expect(true).toBe(false); } catch (error) { expect(error.message).toBe('User not found'); @@ -527,16 +535,16 @@ describe('UsersService', () => { const updatedDescription: DescriptionDto = { description: 'hello friend' }; mockUserModel.exec.mockResolvedValueOnce({ ...user, ...updatedDescription }); const spyerFindPopulate = jest - .spyOn(service, 'findPopulatedUserRegistryById') + .spyOn(usersService, 'findPopulatedUserRegistryById') .mockImplementationOnce(async () => userRegistryMockData); - const updatedUser = await service.updateDescription('', { description: '' }); + const updatedUser = await usersService.updateDescription('', { description: '' }); expect(spyerFindPopulate).toBeCalledTimes(1); expect(updatedUser.description).toBe(updatedDescription.description); }); it('should not found a user', async () => { mockUserModel.exec.mockResolvedValueOnce(null); try { - await service.updateDescription('', { description: '' }); + await usersService.updateDescription('', { description: '' }); expect(true).toBe(false); } catch (error) { expect(error.message).toBe('User not found'); @@ -549,14 +557,14 @@ describe('UsersService', () => { it('should call userModel.find if CNFS job found', async () => { mockJobsService.findByName.mockResolvedValueOnce(cnfsJobMock); const spyer = jest.spyOn(mockUserModel, 'find'); - await service.findAllCNFS(); + await usersService.findAllCNFS(); expect(spyer).toBeCalledTimes(1); }); it('should not call userModel.find if CNFS job not found', async () => { mockJobsService.findByName.mockResolvedValueOnce(null); const spyer = jest.spyOn(mockUserModel, 'find'); - await service.findAllCNFS(); + await usersService.findAllCNFS(); expect(spyer).toBeCalledTimes(0); }); }); diff --git a/src/users/services/users.service.ts b/src/users/services/users.service.ts index 9b3b235f309d6782cb6b5ea30f2193b4af418be0..f4100c58eb6b15bca86b58549dbd98f90f279ca3 100644 --- a/src/users/services/users.service.ts +++ b/src/users/services/users.service.ts @@ -955,9 +955,7 @@ export class UsersService { this.logger.debug(`updateLastLoginDate | ${user._id}`); const lastLoginDate = { lastLoginDate: new Date() }; await this.userModel.updateOne({ _id: user._id }, lastLoginDate).exec(); - - const populatedResult = await this.findPopulatedUserRegistryById(user._id); - this.userRegistrySearchService.update(populatedResult); + await this.findPopulatedUserRegistryById(user._id); } public getPersonalOfferInStructure(user: User, structure: Structure): PersonalOfferDocument { @@ -974,6 +972,7 @@ export class UsersService { .findOne({ personalOffers: { $all: [new Types.ObjectId(id)] }, }) + .populate('job') .populate('personalOffers') .exec(); } diff --git a/test/mock/data/appointment.mock.data.ts b/test/mock/data/appointment.mock.data.ts index 79904f88cbf89f12d89c3ed3c0d4b1daa0f0ca78..712ce1eedc973c54e5e2f8d29e434fcffebaa84e 100644 --- a/test/mock/data/appointment.mock.data.ts +++ b/test/mock/data/appointment.mock.data.ts @@ -10,7 +10,7 @@ export const appointmentMockData: IAppointment[] = [ __v: 0, }, { - onlineDemarcheType: ['CPAM', 'CARSAT'], + onlineDemarcheType: ['CARSAT'], _id: '6350fb490e75215f13f9f20c', name: 'czac', surname: 'cfezcfzc', diff --git a/test/mock/data/gouvStructures.mock.data.ts b/test/mock/data/gouvStructures.mock.data.ts index a78dc5cb570578672d7d75c1e31399810700c50e..ea84f0a899ed95c2a5a21b90b5c0621726c33e3f 100644 --- a/test/mock/data/gouvStructures.mock.data.ts +++ b/test/mock/data/gouvStructures.mock.data.ts @@ -40,7 +40,7 @@ export const mockGouvStructureToResinFormat = new Structure({ postcode: '69290', inseeCode: '69069', }, - contactPhone: '+33478578285', + contactPhone: '0478578285', contactMail: 'mediatheque@mairie-craponne.fr', pmrAccess: false, remoteAccompaniment: false, @@ -49,7 +49,6 @@ export const mockGouvStructureToResinFormat = new Structure({ accessModality: ['accesLibre'], onlineProcedures: [ 'caf', - 'cpam', 'idDoc', 'needs', 'foreigners', diff --git a/test/mock/data/indicators/orientationIndicators.mock.data.ts b/test/mock/data/indicators/orientationIndicators.mock.data.ts index b641bf90f7c808b67fa88370df1c5112e7953c50..8dd425a2c9ce53aae1fa27204a307208e872569c 100644 --- a/test/mock/data/indicators/orientationIndicators.mock.data.ts +++ b/test/mock/data/indicators/orientationIndicators.mock.data.ts @@ -3,6 +3,7 @@ import { OrientationIndicator } from '../../../../src/indicator/dto/orientation- export const mockIndicator: OrientationIndicator = { origin: { nom: 'Structure 1', + prescripteur: 'Prescripteur 1', adresse: { numero: '1', street: 'Rue de la structure 1', @@ -40,6 +41,7 @@ export const mockIndicators: OrientationIndicator[] = [ { origin: { nom: 'Structure 1', + prescripteur: 'Prescripteur 1', adresse: { numero: '1', street: 'Rue de la structure 1', @@ -75,6 +77,7 @@ export const mockIndicators: OrientationIndicator[] = [ { origin: { nom: 'Structure 3', + prescripteur: 'Prescripteur 3', adresse: { numero: '3', street: 'Rue de la structure 3', diff --git a/test/mock/data/onlineMediation.mock.data.ts b/test/mock/data/onlineMediation.mock.data.ts index 2fcf49bf7d87ff2a1851d71a2472a91870f067b1..f428e444ba199697d6969e48241e54aaee851994 100644 --- a/test/mock/data/onlineMediation.mock.data.ts +++ b/test/mock/data/onlineMediation.mock.data.ts @@ -16,7 +16,7 @@ export const onlineMediationMockData: IOnlineMediation[] = [ __v: 0, }, { - onlineDemarcheType: ['CPAM', 'CARSAT'], + onlineDemarcheType: ['CARSAT'], _id: '6350fb490e75215f13f9f20c', name: 'czac', surname: 'cfezcfzc', diff --git a/test/mock/data/personalOffers.mock.data.ts b/test/mock/data/personalOffers.mock.data.ts index 6af1b99d97b15e777ba14f65ff5c1875b739af9b..181622e1eda4f9258d3b8c60841e0dacb353878e 100644 --- a/test/mock/data/personalOffers.mock.data.ts +++ b/test/mock/data/personalOffers.mock.data.ts @@ -5,7 +5,7 @@ import { PersonalOffer } from '../../../src/personal-offers/schemas/personal-off export const personalOffersDtoDataMock: PersonalOfferDto[] = [ { categories: { - onlineProcedures: ['caf', 'cpam'], + onlineProcedures: ['caf'], baseSkills: [], advancedSkills: [], }, @@ -18,7 +18,6 @@ export const personalOffersDtoDataMock: PersonalOfferDto[] = [ 'health', 'work', 'caf', - 'cpam', 'foreigners', 'needs', 'franceConnect', @@ -77,7 +76,6 @@ export const updatePersonalOffersDtoDataMock: PersonalOfferDto[] = [ 'health', 'work', 'caf', - 'cpam', 'foreigners', 'needs', 'franceConnect', @@ -98,7 +96,7 @@ export const personalOffersDataMock: PersonalOffer[] = [ { _id: '1234ba0e2ab5775cfc01ed3e', categories: { - onlineProcedures: ['caf', 'cpam'], + onlineProcedures: ['caf'], baseSkills: [], advancedSkills: [], }, @@ -114,7 +112,6 @@ export const personalOffersDataMock: PersonalOffer[] = [ 'health', 'work', 'caf', - 'cpam', 'foreigners', 'needs', 'franceConnect', diff --git a/test/mock/data/structures.mock.data.ts b/test/mock/data/structures.mock.data.ts index 29daeb29a706d23e01fabbec3a979db2b2276223..5e9d892693c63bc67ab7b721a3c21950b68cb05a 100644 --- a/test/mock/data/structures.mock.data.ts +++ b/test/mock/data/structures.mock.data.ts @@ -258,7 +258,6 @@ export const mockStructureDocument = ({ 'health', 'work', 'caf', - 'cpam', 'foreigners', 'needs', 'franceConnect', @@ -371,7 +370,6 @@ export const mockStructure: Structure = { 'health', 'work', 'caf', - 'cpam', 'foreigners', 'needs', 'franceConnect', @@ -505,7 +503,6 @@ export const mockDeletedStructure: Structure = { 'health', 'work', 'caf', - 'cpam', 'foreigners', 'needs', 'franceConnect', diff --git a/test/mock/services/categories.mock.service.ts b/test/mock/services/categories.mock.service.ts index 1027ce5382aaf154140640831eb0e9fe6836135b..f02103c5ae377025f889a0af63ebebd57893246b 100644 --- a/test/mock/services/categories.mock.service.ts +++ b/test/mock/services/categories.mock.service.ts @@ -29,10 +29,6 @@ export class CategoriesServiceMock { id: 'poleEmploi', text: 'Pôle Emploi', }, - { - id: 'cpam', - text: 'CPAM', - }, { id: 'impots', text: 'Impôts', diff --git a/test/mock/services/structures-export.mock.service.ts b/test/mock/services/structures-export.mock.service.ts index dc93f9affa7729b00c6aab1c72f43c28a7a0eccc..29fb852807860a68f9244d51ac300bc5d8bbbc90 100644 --- a/test/mock/services/structures-export.mock.service.ts +++ b/test/mock/services/structures-export.mock.service.ts @@ -23,7 +23,7 @@ export const mockFormattedStructures: Array<StructureFormatted> = [ courriel: 'adzadadzadazd@pimms.org', longitude: 4.8608585, latitude: 45.7086482, - presentation_resume: + presentation_detail: "Entreprise de médiation numérique assurant l'animation d'atelier numériques en collectif ou l'accompagnement au numérique des particuliers en individuel. Structure agréée APTIC sur la métropole de Lyon, acceptant à ce titre le règlement de ses prestations en chèque PASS NUMERIQUE", publics_accueillis: 'Jeunes (16-26 ans);Seniors (+ 65 ans);Uniquement femmes', site_web: 'http://lesonduclic.fr/site1/', diff --git a/test/mock/services/structures.mock.service.ts b/test/mock/services/structures.mock.service.ts index ea3114fe841bd723152ec6d2242ec8dbac82fd6b..46b2b12c0badb401292181902d6848fa8bea692b 100644 --- a/test/mock/services/structures.mock.service.ts +++ b/test/mock/services/structures.mock.service.ts @@ -30,7 +30,6 @@ export class StructuresServiceMock { 'health', 'work', 'caf', - 'cpam', 'foreigners', 'needs', 'franceConnect', @@ -135,7 +134,6 @@ export class StructuresServiceMock { 'health', 'work', 'caf', - 'cpam', 'foreigners', 'needs', 'franceConnect', @@ -286,7 +284,6 @@ export class StructuresServiceMock { 'health', 'work', 'caf', - 'cpam', 'foreigners', 'needs', 'franceConnect', @@ -371,7 +368,6 @@ export class StructuresServiceMock { 'health', 'work', 'caf', - 'cpam', 'foreigners', 'needs', 'franceConnect', @@ -526,7 +522,6 @@ export class StructuresServiceMock { 'health', 'work', 'caf', - 'cpam', 'foreigners', 'needs', 'franceConnect', @@ -628,7 +623,6 @@ export class StructuresServiceMock { 'health', 'work', 'caf', - 'cpam', 'foreigners', 'needs', 'franceConnect', @@ -735,7 +729,6 @@ export class StructuresServiceMock { 'health', 'work', 'caf', - 'cpam', 'foreigners', 'needs', 'franceConnect', @@ -838,7 +831,6 @@ export class StructuresServiceMock { 'health', 'work', 'caf', - 'cpam', 'foreigners', 'needs', 'franceConnect', @@ -946,7 +938,6 @@ export class StructuresServiceMock { 'health', 'work', 'caf', - 'cpam', 'foreigners', 'needs', 'franceConnect', @@ -1050,7 +1041,6 @@ export class StructuresServiceMock { 'health', 'work', 'caf', - 'cpam', 'foreigners', 'needs', 'franceConnect', @@ -1243,7 +1233,6 @@ export class StructuresServiceMock { 'health', 'work', 'caf', - 'cpam', 'foreigners', 'needs', 'franceConnect', @@ -1517,7 +1506,6 @@ export const mockResinStructures: Array<Structure> = [ 'health', 'work', 'caf', - 'cpam', 'foreigners', 'needs', 'franceConnect', @@ -1623,7 +1611,6 @@ export const mockResinStructures: Array<Structure> = [ 'health', 'work', 'caf', - 'cpam', 'foreigners', 'needs', 'franceConnect', @@ -1729,7 +1716,6 @@ export const mockResinStructures: Array<Structure> = [ 'health', 'work', 'caf', - 'cpam', 'foreigners', 'needs', 'franceConnect',