From 105408bad17ff1474009a27bcb7060bca59fdc3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yannick=20Fran=C3=A7ois?= Date: Fri, 27 Dec 2024 14:37:55 +0100 Subject: [PATCH] :truck: chore(api): move student certification to `src` --- .../certification-center-controller.js | 20 --- .../certification-centers/index.js | 33 ---- api/lib/domain/usecases/index.js | 2 +- .../certification-center-controller.js | 24 +++ .../application/certification-center-route.js | 46 ++++++ .../usecases/find-students-for-enrolment.js | 4 +- .../enrolment/domain/usecases/index.js | 13 ++ .../infrastructure/repositories/index.js | 3 - .../student-certification-serializer.js | 0 api/src/certification/enrolment/routes.js | 2 + .../domain/usecases/index.js | 2 +- .../domain/usecases/index.js | 2 +- ...learners-certificability-job-controller.js | 2 +- .../domain/usecases/index.js | 2 +- .../organization-learner-repository.js | 2 +- .../domain/usecases/index.js | 2 +- .../domain/usecases/index.js | 2 +- api/src/privacy/domain/usecases/index.js | 2 +- .../organization-learner-repository.js | 14 +- .../certification-center-controller_test.js | 98 ----------- .../certification-center-controller_test.js | 124 ++++++++++++++ .../certification-center-route_test.js | 155 ++++++++++++++++++ .../find-students-for-enrolment_test.js | 8 +- .../student-certification-serializer_test.js | 6 +- ...ncile-user-to-organization-learner_test.js | 2 +- ...ers-certificability-job-controller_test.js | 2 +- .../organization-learner-repository_test.js | 2 +- ...ation-learners-with-participations_test.js | 6 +- ...ta-organizations-places-statistics_test.js | 2 +- .../domain/services/user-service_test.js | 2 +- .../organization-learner-repository_test.js | 12 +- .../certification-center-controller_test.js | 61 +------ .../certification-centers/index_test.js | 149 ----------------- 33 files changed, 404 insertions(+), 402 deletions(-) create mode 100644 api/src/certification/enrolment/application/certification-center-controller.js create mode 100644 api/src/certification/enrolment/application/certification-center-route.js rename api/{lib => src/certification/enrolment}/domain/usecases/find-students-for-enrolment.js (89%) rename api/{lib/infrastructure/serializers/jsonapi => src/certification/enrolment/infrastructure/serializers}/student-certification-serializer.js (100%) rename api/{lib => src/shared}/infrastructure/repositories/organization-learner-repository.js (94%) create mode 100644 api/tests/certification/enrolment/acceptance/application/certification-center-controller_test.js create mode 100644 api/tests/certification/enrolment/unit/application/certification-center-route_test.js rename api/tests/{ => certification/enrolment}/unit/domain/usecases/find-students-for-enrolment_test.js (92%) rename api/tests/{unit/infrastructure/serializers/jsonapi => certification/enrolment/unit/infrastructure/serializers}/student-certification-serializer_test.js (77%) rename api/tests/{ => shared}/integration/infrastructure/repositories/organization-learner-repository_test.js (99%) diff --git a/api/lib/application/certification-centers/certification-center-controller.js b/api/lib/application/certification-centers/certification-center-controller.js index 61c95d131f0..5df50c18908 100644 --- a/api/lib/application/certification-centers/certification-center-controller.js +++ b/api/lib/application/certification-centers/certification-center-controller.js @@ -2,25 +2,6 @@ import * as divisionSerializer from '../../../src/prescription/campaign/infrastr import * as certificationCenterMembershipSerializer from '../../../src/shared/infrastructure/serializers/jsonapi/certification-center-membership.serializer.js'; import { usecases as teamUsecases } from '../../../src/team/domain/usecases/index.js'; import { usecases } from '../../domain/usecases/index.js'; -import * as studentCertificationSerializer from '../../infrastructure/serializers/jsonapi/student-certification-serializer.js'; - -const getStudents = async function (request) { - const certificationCenterId = request.params.certificationCenterId; - const sessionId = request.params.sessionId; - - const { filter, page } = request.query; - if (filter.divisions && !Array.isArray(filter.divisions)) { - filter.divisions = [filter.divisions]; - } - - const { data, pagination } = await usecases.findStudentsForEnrolment({ - certificationCenterId, - sessionId, - page, - filter, - }); - return studentCertificationSerializer.serialize(data, pagination); -}; const getDivisions = async function (request) { const certificationCenterId = request.params.certificationCenterId; @@ -77,7 +58,6 @@ const certificationCenterController = { createCertificationCenterMembershipByEmail, findCertificationCenterMembershipsByCertificationCenter, getDivisions, - getStudents, updateReferer, }; diff --git a/api/lib/application/certification-centers/index.js b/api/lib/application/certification-centers/index.js index 4a8f3546825..a7c61a86d24 100644 --- a/api/lib/application/certification-centers/index.js +++ b/api/lib/application/certification-centers/index.js @@ -93,39 +93,6 @@ const register = async function (server) { server.route([ ...adminRoutes, ...certifRoutes, - { - method: 'GET', - path: '/api/certification-centers/{certificationCenterId}/sessions/{sessionId}/students', - config: { - validate: { - params: Joi.object({ - certificationCenterId: identifiersType.certificationCenterId, - sessionId: identifiersType.sessionId, - }), - query: Joi.object({ - filter: Joi.object({ - divisions: Joi.array().items(Joi.string()), - }).default({}), - page: { - number: Joi.number().integer(), - size: Joi.number().integer(), - }, - }), - }, - pre: [ - { - method: securityPreHandlers.checkUserIsMemberOfCertificationCenter, - assign: 'isMemberOfCertificationCenter', - }, - ], - handler: certificationCenterController.getStudents, - notes: [ - '- **Cette route est restreinte aux utilisateurs authentifiés**\n' + - "- Récupération d'une liste d'élèves SCO à partir d'un identifiant de centre de certification", - ], - tags: ['api', 'certification-center', 'students', 'session'], - }, - }, { method: 'GET', path: '/api/certification-centers/{certificationCenterId}/divisions', diff --git a/api/lib/domain/usecases/index.js b/api/lib/domain/usecases/index.js index d2499e6792f..cfd22568d60 100644 --- a/api/lib/domain/usecases/index.js +++ b/api/lib/domain/usecases/index.js @@ -103,6 +103,7 @@ import * as assessmentResultRepository from '../../../src/shared/infrastructure/ import * as challengeRepository from '../../../src/shared/infrastructure/repositories/challenge-repository.js'; import * as competenceRepository from '../../../src/shared/infrastructure/repositories/competence-repository.js'; import * as courseRepository from '../../../src/shared/infrastructure/repositories/course-repository.js'; +import * as organizationLearnerRepository from '../../../src/shared/infrastructure/repositories/organization-learner-repository.js'; import * as organizationRepository from '../../../src/shared/infrastructure/repositories/organization-repository.js'; import * as skillRepository from '../../../src/shared/infrastructure/repositories/skill-repository.js'; import * as userLoginRepository from '../../../src/shared/infrastructure/repositories/user-login-repository.js'; @@ -136,7 +137,6 @@ import { repositories } from '../../infrastructure/repositories/index.js'; import { certificationCompletedJobRepository } from '../../infrastructure/repositories/jobs/certification-completed-job-repository.js'; import * as knowledgeElementRepository from '../../infrastructure/repositories/knowledge-element-repository.js'; import * as learningContentRepository from '../../infrastructure/repositories/learning-content-repository.js'; -import * as organizationLearnerRepository from '../../infrastructure/repositories/organization-learner-repository.js'; import * as organizationMemberIdentityRepository from '../../infrastructure/repositories/organization-member-identity-repository.js'; import * as organizationTagRepository from '../../infrastructure/repositories/organization-tag-repository.js'; import * as targetProfileRepository from '../../infrastructure/repositories/target-profile-repository.js'; diff --git a/api/src/certification/enrolment/application/certification-center-controller.js b/api/src/certification/enrolment/application/certification-center-controller.js new file mode 100644 index 00000000000..a5078b2ab2f --- /dev/null +++ b/api/src/certification/enrolment/application/certification-center-controller.js @@ -0,0 +1,24 @@ +import { usecases } from '../domain/usecases/index.js'; +import * as studentCertificationSerializer from '../infrastructure/serializers/student-certification-serializer.js'; + +const getStudents = async function (request) { + const certificationCenterId = request.params.certificationCenterId; + const sessionId = request.params.sessionId; + + const { filter, page } = request.query; + if (filter.divisions && !Array.isArray(filter.divisions)) { + filter.divisions = [filter.divisions]; + } + + const { data, pagination } = await usecases.findStudentsForEnrolment({ + certificationCenterId, + sessionId, + page, + filter, + }); + return studentCertificationSerializer.serialize(data, pagination); +}; + +const certificationCenterController = { getStudents }; + +export { certificationCenterController }; diff --git a/api/src/certification/enrolment/application/certification-center-route.js b/api/src/certification/enrolment/application/certification-center-route.js new file mode 100644 index 00000000000..303f395354c --- /dev/null +++ b/api/src/certification/enrolment/application/certification-center-route.js @@ -0,0 +1,46 @@ +import Joi from 'joi'; + +import { securityPreHandlers } from '../../../shared/application/security-pre-handlers.js'; +import { identifiersType } from '../../../shared/domain/types/identifiers-type.js'; +import { certificationCenterController } from './certification-center-controller.js'; + +const register = async function (server) { + server.route([ + { + method: 'GET', + path: '/api/certification-centers/{certificationCenterId}/sessions/{sessionId}/students', + config: { + validate: { + params: Joi.object({ + certificationCenterId: identifiersType.certificationCenterId, + sessionId: identifiersType.sessionId, + }), + query: Joi.object({ + filter: Joi.object({ + divisions: Joi.array().items(Joi.string()), + }).default({}), + page: { + number: Joi.number().integer(), + size: Joi.number().integer(), + }, + }), + }, + pre: [ + { + method: securityPreHandlers.checkUserIsMemberOfCertificationCenter, + assign: 'isMemberOfCertificationCenter', + }, + ], + handler: certificationCenterController.getStudents, + notes: [ + '- **Cette route est restreinte aux utilisateurs authentifiés**\n' + + "- Récupération d'une liste d'élèves SCO à partir d'un identifiant de centre de certification", + ], + tags: ['api', 'certification-center', 'students', 'session'], + }, + }, + ]); +}; + +const name = 'certification-centers-session-students-api'; +export { name, register }; diff --git a/api/lib/domain/usecases/find-students-for-enrolment.js b/api/src/certification/enrolment/domain/usecases/find-students-for-enrolment.js similarity index 89% rename from api/lib/domain/usecases/find-students-for-enrolment.js rename to api/src/certification/enrolment/domain/usecases/find-students-for-enrolment.js index 99424715f85..5cfd2cefca7 100644 --- a/api/lib/domain/usecases/find-students-for-enrolment.js +++ b/api/src/certification/enrolment/domain/usecases/find-students-for-enrolment.js @@ -1,5 +1,5 @@ -import { NotFoundError } from '../../../src/shared/domain/errors.js'; -import { StudentForEnrolment } from '../../../src/shared/domain/read-models/StudentForEnrolment.js'; +import { NotFoundError } from '../../../../shared/domain/errors.js'; +import { StudentForEnrolment } from '../../../../shared/domain/read-models/StudentForEnrolment.js'; const findStudentsForEnrolment = async function ({ certificationCenterId, diff --git a/api/src/certification/enrolment/domain/usecases/index.js b/api/src/certification/enrolment/domain/usecases/index.js index ef7a9037d99..c8374b36c23 100644 --- a/api/src/certification/enrolment/domain/usecases/index.js +++ b/api/src/certification/enrolment/domain/usecases/index.js @@ -4,12 +4,15 @@ import { fileURLToPath } from 'node:url'; import * as languageService from '../../../../shared/domain/services/language-service.js'; import * as placementProfileService from '../../../../shared/domain/services/placement-profile-service.js'; +import * as organizationLearnerRepository from '../../../../shared/infrastructure/repositories/organization-learner-repository.js'; +import * as organizationRepository from '../../../../shared/infrastructure/repositories/organization-repository.js'; import { injectDependencies } from '../../../../shared/infrastructure/utils/dependency-injection.js'; import { importNamedExportsFromDirectory } from '../../../../shared/infrastructure/utils/import-named-exports-from-directory.js'; import * as attendanceSheetPdfUtils from '../../../enrolment/infrastructure/utils/pdf/attendance-sheet-pdf.js'; import * as certificationBadgesService from '../../../shared/domain/services/certification-badges-service.js'; import * as certificationCpfService from '../../../shared/domain/services/certification-cpf-service.js'; import * as sessionValidator from '../../../shared/domain/validators/session-validator.js'; +import * as certificationCandidateRepository from '../../../shared/infrastructure/repositories/certification-candidate-repository.js'; import * as complementaryCertificationBadgesRepository from '../../../shared/infrastructure/repositories/complementary-certification-badge-repository.js'; import { enrolmentRepositories } from '../../infrastructure/repositories/index.js'; import * as certificationCandidatesOdsService from '../services/certification-candidates-ods-service.js'; @@ -40,6 +43,9 @@ import * as temporarySessionsStorageForMassImportService from '../services/tempo * @typedef {import('../services/certification-candidates-ods-service.js')} CertificationCandidatesOdsService * @typedef {import('../../../../shared/domain/services/placement-profile-service.js')} PlacementProfileService * @typedef {import('../../../../shared/domain/services/language-service.js')} languageService + * @typedef {import('../../../../shared/infrastructure/repositories/organization-repository.js')} organizationRepository + * @typedef {import('../../infrastructure/repositories/organization-learner-repository.js')} organizationLearnerRepository + * @typedef {import('../../../shared/infrastructure/repositories/certification-candidate-repository.js')} certificationCandidateRepository **/ /** @@ -70,6 +76,10 @@ import * as temporarySessionsStorageForMassImportService from '../services/tempo * @typedef {PlacementProfileService} PlacementProfileService * @typedef {LanguageService} LanguageService * @typedef {complementaryCertificationBadgesRepository} ComplementaryCertificationBadgesRepository + * @typedef {organizationRepository} OrganizationRepository + * @typedef {organizationLearnerRepository} OrganizationLearnerRepository + * @typedef {certificationCandidateRepository} CertificationCandidateRepository + * **/ const dependencies = { certificationBadgesService, @@ -84,6 +94,9 @@ const dependencies = { placementProfileService, languageService, complementaryCertificationBadgesRepository, + organizationRepository, + organizationLearnerRepository, + certificationCandidateRepository, }; const path = dirname(fileURLToPath(import.meta.url)); diff --git a/api/src/certification/enrolment/infrastructure/repositories/index.js b/api/src/certification/enrolment/infrastructure/repositories/index.js index 11c94c03911..ad599ab0761 100644 --- a/api/src/certification/enrolment/infrastructure/repositories/index.js +++ b/api/src/certification/enrolment/infrastructure/repositories/index.js @@ -1,4 +1,3 @@ -import * as organizationLearnerRepository from '../../../../../lib/infrastructure/repositories/organization-learner-repository.js'; import * as dataProtectionOfficerRepository from '../../../../organizational-entities/infrastructure/repositories/data-protection-officer.repository.js'; import { injectDependencies } from '../../../../shared/infrastructure/utils/dependency-injection.js'; import * as complementaryCertificationApi from '../../../complementary-certification/application/api/complementary-certification-api.js'; @@ -38,7 +37,6 @@ import * as sessionRepository from './session-repository.js'; * @typedef {enrolledCandidateRepository} EnrolledCandidateRepository * @typedef {scoCertificationCandidateRepository} ScoCertificationCandidateRepository * @typedef {dataProtectionOfficerRepository} DataProtectionOfficerRepository - * @typedef {organizationLearnerRepository} OrganizationLearnerRepository * @typedef {userRepository} UserRepository * @typedef {targetProfileHistoryRepository} TargetProfileHistoryRepository * @typedef {complementaryCertificationCourseRepository} ComplementaryCertificationCourseRepository @@ -60,7 +58,6 @@ const repositoriesWithoutInjectedDependencies = { sessionForAttendanceSheetRepository, sessionManagementRepository, sessionRepository, - organizationLearnerRepository, userRepository, targetProfileHistoryRepository, complementaryCertificationCourseRepository, diff --git a/api/lib/infrastructure/serializers/jsonapi/student-certification-serializer.js b/api/src/certification/enrolment/infrastructure/serializers/student-certification-serializer.js similarity index 100% rename from api/lib/infrastructure/serializers/jsonapi/student-certification-serializer.js rename to api/src/certification/enrolment/infrastructure/serializers/student-certification-serializer.js diff --git a/api/src/certification/enrolment/routes.js b/api/src/certification/enrolment/routes.js index df4d312a548..27ccbfae12c 100644 --- a/api/src/certification/enrolment/routes.js +++ b/api/src/certification/enrolment/routes.js @@ -1,5 +1,6 @@ import * as attendanceSheet from './application/attendance-sheet-route.js'; import * as certificationCandidate from './application/certification-candidate-route.js'; +import * as certificationCenter from './application/certification-center-route.js'; import * as country from './application/country-route.js'; import * as enrolment from './application/enrolment-route.js'; import * as sessionMassImport from './application/session-mass-import-route.js'; @@ -14,6 +15,7 @@ const certificationEnrolmentRoutes = [ enrolment, session, sessionMassImport, + certificationCenter, subscription, user, ]; diff --git a/api/src/identity-access-management/domain/usecases/index.js b/api/src/identity-access-management/domain/usecases/index.js index 8235fda10b6..8643e2b80cc 100644 --- a/api/src/identity-access-management/domain/usecases/index.js +++ b/api/src/identity-access-management/domain/usecases/index.js @@ -6,7 +6,6 @@ import { mailService } from '../../../../lib/domain/services/mail-service.js'; import * as userReconciliationService from '../../../../lib/domain/services/user-reconciliation-service.js'; import { oidcAuthenticationServiceRegistry } from '../../../../lib/domain/usecases/index.js'; import * as campaignRepository from '../../../../lib/infrastructure/repositories/campaign-repository.js'; -import * as organizationLearnerRepository from '../../../../lib/infrastructure/repositories/organization-learner-repository.js'; import * as campaignParticipationRepository from '../../../../src/prescription/campaign-participation/infrastructure/repositories/campaign-participation-repository.js'; import * as centerRepository from '../../../certification/enrolment/infrastructure/repositories/center-repository.js'; import * as userRecommendedTrainingRepository from '../../../devcomp/infrastructure/repositories/user-recommended-training-repository.js'; @@ -19,6 +18,7 @@ import * as userService from '../../../shared/domain/services/user-service.js'; import * as passwordValidator from '../../../shared/domain/validators/password-validator.js'; import * as userValidator from '../../../shared/domain/validators/user-validator.js'; import { adminMemberRepository } from '../../../shared/infrastructure/repositories/admin-member.repository.js'; +import * as organizationLearnerRepository from '../../../shared/infrastructure/repositories/organization-learner-repository.js'; import * as userLoginRepository from '../../../shared/infrastructure/repositories/user-login-repository.js'; import * as codeUtils from '../../../shared/infrastructure/utils/code-utils.js'; import { injectDependencies } from '../../../shared/infrastructure/utils/dependency-injection.js'; diff --git a/api/src/prescription/campaign-participation/domain/usecases/index.js b/api/src/prescription/campaign-participation/domain/usecases/index.js index d596c0845dc..09bed1cb10d 100644 --- a/api/src/prescription/campaign-participation/domain/usecases/index.js +++ b/api/src/prescription/campaign-participation/domain/usecases/index.js @@ -6,7 +6,6 @@ import * as badgeForCalculationRepository from '../../../../../lib/infrastructur import * as campaignRepository from '../../../../../lib/infrastructure/repositories/campaign-repository.js'; import * as knowledgeElementRepository from '../../../../../lib/infrastructure/repositories/knowledge-element-repository.js'; import * as learningContentRepository from '../../../../../lib/infrastructure/repositories/learning-content-repository.js'; -import * as organizationLearnerRepository from '../../../../../lib/infrastructure/repositories/organization-learner-repository.js'; import * as targetProfileRepository from '../../../../../lib/infrastructure/repositories/target-profile-repository.js'; import * as stageCollectionRepository from '../../../../../lib/infrastructure/repositories/user-campaign-results/stage-collection-repository.js'; import * as badgeRepository from '../../../../../src/evaluation/infrastructure/repositories/badge-repository.js'; @@ -21,6 +20,7 @@ import { config } from '../../../../shared/config.js'; import * as areaRepository from '../../../../shared/infrastructure/repositories/area-repository.js'; import * as assessmentRepository from '../../../../shared/infrastructure/repositories/assessment-repository.js'; import * as competenceRepository from '../../../../shared/infrastructure/repositories/competence-repository.js'; +import * as organizationLearnerRepository from '../../../../shared/infrastructure/repositories/organization-learner-repository.js'; import * as organizationRepository from '../../../../shared/infrastructure/repositories/organization-repository.js'; import { injectDependencies } from '../../../../shared/infrastructure/utils/dependency-injection.js'; import { importNamedExportsFromDirectory } from '../../../../shared/infrastructure/utils/import-named-exports-from-directory.js'; diff --git a/api/src/prescription/learner-management/application/jobs/schedule-compute-organization-learners-certificability-job-controller.js b/api/src/prescription/learner-management/application/jobs/schedule-compute-organization-learners-certificability-job-controller.js index 5b20a28fe80..634ffe2b1bf 100644 --- a/api/src/prescription/learner-management/application/jobs/schedule-compute-organization-learners-certificability-job-controller.js +++ b/api/src/prescription/learner-management/application/jobs/schedule-compute-organization-learners-certificability-job-controller.js @@ -1,11 +1,11 @@ import cronParser from 'cron-parser'; import dayjs from 'dayjs'; -import * as organizationLearnerRepository from '../../../../../lib/infrastructure/repositories/organization-learner-repository.js'; import { ComputeCertificabilityJob } from '../../../../prescription/learner-management/domain/models/ComputeCertificabilityJob.js'; import { JobScheduleController } from '../../../../shared/application/jobs/job-schedule-controller.js'; import { config } from '../../../../shared/config.js'; import { DomainTransaction } from '../../../../shared/domain/DomainTransaction.js'; +import * as organizationLearnerRepository from '../../../../shared/infrastructure/repositories/organization-learner-repository.js'; import { logger } from '../../../../shared/infrastructure/utils/logger.js'; import { computeCertificabilityJobRepository } from '../../../learner-management/infrastructure/repositories/jobs/compute-certificability-job-repository.js'; diff --git a/api/src/prescription/learner-management/domain/usecases/index.js b/api/src/prescription/learner-management/domain/usecases/index.js index 573590c0b20..8fda0469a4a 100644 --- a/api/src/prescription/learner-management/domain/usecases/index.js +++ b/api/src/prescription/learner-management/domain/usecases/index.js @@ -4,11 +4,11 @@ import { fileURLToPath } from 'node:url'; import * as obfuscationService from '../../../../../lib/domain/services/obfuscation-service.js'; import * as userReconciliationService from '../../../../../lib/domain/services/user-reconciliation-service.js'; import * as campaignRepository from '../../../../../lib/infrastructure/repositories/campaign-repository.js'; -import * as libOrganizationLearnerRepository from '../../../../../lib/infrastructure/repositories/organization-learner-repository.js'; import * as userRepository from '../../../../identity-access-management/infrastructure/repositories/user.repository.js'; import * as organizationFeatureApi from '../../../../organizational-entities/application/api/organization-features-api.js'; import * as placementProfileService from '../../../../shared/domain/services/placement-profile-service.js'; import { logErrorWithCorrelationIds } from '../../../../shared/infrastructure/monitoring-tools.js'; +import * as libOrganizationLearnerRepository from '../../../../shared/infrastructure/repositories/organization-learner-repository.js'; import * as organizationRepository from '../../../../shared/infrastructure/repositories/organization-repository.js'; import { injectDependencies } from '../../../../shared/infrastructure/utils/dependency-injection.js'; import { importNamedExportsFromDirectory } from '../../../../shared/infrastructure/utils/import-named-exports-from-directory.js'; diff --git a/api/src/prescription/learner-management/infrastructure/repositories/organization-learner-repository.js b/api/src/prescription/learner-management/infrastructure/repositories/organization-learner-repository.js index 73889ccd90a..4d0c0270e99 100644 --- a/api/src/prescription/learner-management/infrastructure/repositories/organization-learner-repository.js +++ b/api/src/prescription/learner-management/infrastructure/repositories/organization-learner-repository.js @@ -1,6 +1,5 @@ import _ from 'lodash'; -import * as organizationLearnerRepository from '../../../../../lib/infrastructure/repositories/organization-learner-repository.js'; import { DomainTransaction } from '../../../../shared/domain/DomainTransaction.js'; import { NotFoundError, @@ -8,6 +7,7 @@ import { UserCouldNotBeReconciledError, } from '../../../../shared/domain/errors.js'; import { OrganizationLearner } from '../../../../shared/domain/models/index.js'; +import * as organizationLearnerRepository from '../../../../shared/infrastructure/repositories/organization-learner-repository.js'; import { OrganizationLearnerCertificabilityNotUpdatedError } from '../../domain/errors.js'; import { CommonOrganizationLearner } from '../../domain/models/CommonOrganizationLearner.js'; import { OrganizationLearnerForAdmin } from '../../domain/read-models/OrganizationLearnerForAdmin.js'; diff --git a/api/src/prescription/organization-learner/domain/usecases/index.js b/api/src/prescription/organization-learner/domain/usecases/index.js index 6f41fa0ed47..e2a8c5e40cd 100644 --- a/api/src/prescription/organization-learner/domain/usecases/index.js +++ b/api/src/prescription/organization-learner/domain/usecases/index.js @@ -7,9 +7,9 @@ import { fileURLToPath } from 'node:url'; * groupRepository.findByOrganizationId */ import * as campaignRepository from '../../../../../lib/infrastructure/repositories/campaign-repository.js'; -import * as libOrganizationLearnerRepository from '../../../../../lib/infrastructure/repositories/organization-learner-repository.js'; import * as organizationFeaturesAPI from '../../../../organizational-entities/application/api/organization-features-api.js'; import { tagRepository } from '../../../../organizational-entities/infrastructure/repositories/tag.repository.js'; +import * as libOrganizationLearnerRepository from '../../../../shared/infrastructure/repositories/organization-learner-repository.js'; import * as organizationRepository from '../../../../shared/infrastructure/repositories/organization-repository.js'; import { injectDependencies } from '../../../../shared/infrastructure/utils/dependency-injection.js'; import { importNamedExportsFromDirectory } from '../../../../shared/infrastructure/utils/import-named-exports-from-directory.js'; diff --git a/api/src/prescription/organization-place/domain/usecases/index.js b/api/src/prescription/organization-place/domain/usecases/index.js index a43c6fc68e5..4e942befc12 100644 --- a/api/src/prescription/organization-place/domain/usecases/index.js +++ b/api/src/prescription/organization-place/domain/usecases/index.js @@ -1,7 +1,7 @@ import { dirname, join } from 'node:path'; import { fileURLToPath } from 'node:url'; -import * as organizationLearnerRepository from '../../../../../lib/infrastructure/repositories/organization-learner-repository.js'; +import * as organizationLearnerRepository from '../../../../shared/infrastructure/repositories/organization-learner-repository.js'; import * as organizationRepository from '../../../../shared/infrastructure/repositories/organization-repository.js'; import { injectDependencies } from '../../../../shared/infrastructure/utils/dependency-injection.js'; import { importNamedExportsFromDirectory } from '../../../../shared/infrastructure/utils/import-named-exports-from-directory.js'; diff --git a/api/src/privacy/domain/usecases/index.js b/api/src/privacy/domain/usecases/index.js index 4e7b27f12b5..fe7765e5dce 100644 --- a/api/src/privacy/domain/usecases/index.js +++ b/api/src/privacy/domain/usecases/index.js @@ -1,12 +1,12 @@ import { dirname, join } from 'node:path'; import { fileURLToPath } from 'node:url'; -import * as organizationLearnerRepository from '../../../../lib/infrastructure/repositories/organization-learner-repository.js'; import * as authenticationMethodRepository from '../../../identity-access-management/infrastructure/repositories/authentication-method.repository.js'; import { userAnonymizedEventLoggingJobRepository } from '../../../identity-access-management/infrastructure/repositories/jobs/user-anonymized-event-logging-job-repository.js'; import { refreshTokenRepository } from '../../../identity-access-management/infrastructure/repositories/refresh-token.repository.js'; import { resetPasswordDemandRepository } from '../../../identity-access-management/infrastructure/repositories/reset-password-demand.repository.js'; import * as userRepository from '../../../identity-access-management/infrastructure/repositories/user.repository.js'; +import * as organizationLearnerRepository from '../../../shared/infrastructure/repositories/organization-learner-repository.js'; import * as userLoginRepository from '../../../shared/infrastructure/repositories/user-login-repository.js'; import { injectDependencies } from '../../../shared/infrastructure/utils/dependency-injection.js'; import { importNamedExportsFromDirectory } from '../../../shared/infrastructure/utils/import-named-exports-from-directory.js'; diff --git a/api/lib/infrastructure/repositories/organization-learner-repository.js b/api/src/shared/infrastructure/repositories/organization-learner-repository.js similarity index 94% rename from api/lib/infrastructure/repositories/organization-learner-repository.js rename to api/src/shared/infrastructure/repositories/organization-learner-repository.js index 63fdeedf750..de06dedd353 100644 --- a/api/lib/infrastructure/repositories/organization-learner-repository.js +++ b/api/src/shared/infrastructure/repositories/organization-learner-repository.js @@ -1,10 +1,10 @@ -import { knex } from '../../../db/knex-database-connection.js'; -import { ORGANIZATION_FEATURE } from '../../../src/shared/domain/constants.js'; -import { OrganizationLearnerNotFound, UserNotFoundError } from '../../../src/shared/domain/errors.js'; -import { OrganizationLearner } from '../../../src/shared/domain/models/OrganizationLearner.js'; -import { ParticipantRepartition } from '../../../src/shared/domain/models/ParticipantRepartition.js'; -import { fetchPage } from '../../../src/shared/infrastructure/utils/knex-utils.js'; -import { DomainTransaction } from '../DomainTransaction.js'; +import { knex } from '../../../../db/knex-database-connection.js'; +import { ORGANIZATION_FEATURE } from '../../domain/constants.js'; +import { DomainTransaction } from '../../domain/DomainTransaction.js'; +import { OrganizationLearnerNotFound, UserNotFoundError } from '../../domain/errors.js'; +import { OrganizationLearner } from '../../domain/models/OrganizationLearner.js'; +import { ParticipantRepartition } from '../../domain/models/ParticipantRepartition.js'; +import { fetchPage } from '../utils/knex-utils.js'; const findByIds = async function ({ ids }) { const rawOrganizationLearners = await knex diff --git a/api/tests/acceptance/application/certification-centers/certification-center-controller_test.js b/api/tests/acceptance/application/certification-centers/certification-center-controller_test.js index 5fd4993f9db..37638673e9c 100644 --- a/api/tests/acceptance/application/certification-centers/certification-center-controller_test.js +++ b/api/tests/acceptance/application/certification-centers/certification-center-controller_test.js @@ -49,104 +49,6 @@ describe('Acceptance | API | Certification Center', function () { }); }); - describe('GET /api/certification-centers/{certificationCenterId}/sessions/{sessionId}/students', function () { - let request; - const externalId = 'XXXX'; - - function _buildOrganizationLearnersWithConnectedUserRequest(user, certificationCenter, session) { - return { - method: 'GET', - url: - '/api/certification-centers/' + - certificationCenter.id + - '/sessions/' + - session.id + - '/students?page[size]=10&page[number]=1', - headers: { authorization: generateValidRequestAuthorizationHeader(user.id) }, - }; - } - function _buildOrganizationLearnersNotConnectedUserRequest(certificationCenter, session) { - return { - method: 'GET', - url: - '/api/certification-centers/' + - certificationCenter.id + - '/sessions/' + - session.id + - '/students?page[size]=10&page[number]=1', - }; - } - - context('when user is connected', function () { - it('should return 200 HTTP status', async function () { - // given - const { certificationCenter, user } = _buildUserWithCertificationCenterMemberShip(externalId); - const organization = databaseBuilder.factory.buildOrganization({ externalId, type: 'SCO' }); - const session = databaseBuilder.factory.buildSession({ certificationCenterId: certificationCenter.id }); - _buildOrganizationLearners(organization, { firstName: 'Laura', lastName: 'certifForEver', division: '2ndB' }); - await databaseBuilder.commit(); - - const request = _buildOrganizationLearnersWithConnectedUserRequest(user, certificationCenter, session); - - // when - const response = await server.inject(request); - - // then - expect(response.statusCode).to.equal(200); - }); - - it('should return the organization learners asked', async function () { - // given - const { certificationCenter, user } = _buildUserWithCertificationCenterMemberShip(externalId); - const organization = databaseBuilder.factory.buildOrganization({ type: 'SCO', externalId }); - const session = databaseBuilder.factory.buildSession({ certificationCenterId: certificationCenter.id }); - _buildOrganizationLearners( - organization, - { id: 1, division: '2ndB', firstName: 'Laura', lastName: 'Certif4Ever' }, - { id: 2, division: '2ndA', firstName: 'Laura', lastName: 'Booooo' }, - { id: 3, division: '2ndA', firstName: 'Laura', lastName: 'aaaaa' }, - { id: 4, division: '2ndA', firstName: 'Bart', lastName: 'Coucou' }, - { id: 5, division: '2ndA', firstName: 'Arthur', lastName: 'Coucou' }, - ); - await databaseBuilder.commit(); - - const request = _buildOrganizationLearnersWithConnectedUserRequest(user, certificationCenter, session); - - // when - const response = await server.inject(request); - - // then - expect(_.map(response.result.data, 'id')).to.deep.equal(['3', '2', '5', '4', '1']); - }); - }); - - context('when user is not connected', function () { - it('should return 401 HTTP status code if user is not authenticated', async function () { - // given - _buildUserWithCertificationCenterMemberShip(externalId); - databaseBuilder.factory.buildOrganization({ externalId }); - const certificationCenterWhereUserDoesNotHaveAccess = databaseBuilder.factory.buildCertificationCenter({ - externalId, - }); - const session = databaseBuilder.factory.buildSession({ - certificationCenterId: certificationCenterWhereUserDoesNotHaveAccess.id, - }); - await databaseBuilder.commit(); - - request = _buildOrganizationLearnersNotConnectedUserRequest( - certificationCenterWhereUserDoesNotHaveAccess, - session, - ); - - // when - const response = await server.inject(request); - - // then - expect(response.statusCode).to.equal(401); - }); - }); - }); - describe('GET /api/admin/certification-centers/{id}/certification-center-memberships', function () { context('when certification center membership is linked to the certification center', function () { it('should return 200 HTTP status', async function () { diff --git a/api/tests/certification/enrolment/acceptance/application/certification-center-controller_test.js b/api/tests/certification/enrolment/acceptance/application/certification-center-controller_test.js new file mode 100644 index 00000000000..8d828fb3429 --- /dev/null +++ b/api/tests/certification/enrolment/acceptance/application/certification-center-controller_test.js @@ -0,0 +1,124 @@ +import _ from 'lodash'; + +import { + createServer, + databaseBuilder, + expect, + generateValidRequestAuthorizationHeader, + insertUserWithRoleSuperAdmin, +} from '../../../../test-helper.js'; + +describe('Acceptance | API | Certification Center', function () { + let server; + + beforeEach(async function () { + server = await createServer(); + await insertUserWithRoleSuperAdmin(); + }); + + describe('GET /api/certification-centers/{certificationCenterId}/sessions/{sessionId}/students', function () { + let request; + const externalId = 'XXXX'; + + context('when user is connected', function () { + it('should return 200 HTTP status', async function () { + // given + const { certificationCenter, user } = _buildUserWithCertificationCenterMemberShip(externalId); + const organization = databaseBuilder.factory.buildOrganization({ externalId, type: 'SCO' }); + const session = databaseBuilder.factory.buildSession({ certificationCenterId: certificationCenter.id }); + _buildOrganizationLearners(organization, { firstName: 'Laura', lastName: 'certifForEver', division: '2ndB' }); + await databaseBuilder.commit(); + + const request = { + method: 'GET', + url: `/api/certification-centers/${certificationCenter.id}/sessions/${session.id}/students?page[size]=10&page[number]=1`, + headers: { authorization: generateValidRequestAuthorizationHeader(user.id) }, + }; + + // when + const response = await server.inject(request); + + // then + expect(response.statusCode).to.equal(200); + }); + + it('should return the organization learners asked', async function () { + // given + const { certificationCenter, user } = _buildUserWithCertificationCenterMemberShip(externalId); + const organization = databaseBuilder.factory.buildOrganization({ type: 'SCO', externalId }); + const session = databaseBuilder.factory.buildSession({ certificationCenterId: certificationCenter.id }); + _buildOrganizationLearners( + organization, + { id: 1, division: '2ndB', firstName: 'Laura', lastName: 'Certif4Ever' }, + { id: 2, division: '2ndA', firstName: 'Laura', lastName: 'Booooo' }, + { id: 3, division: '2ndA', firstName: 'Laura', lastName: 'aaaaa' }, + { id: 4, division: '2ndA', firstName: 'Bart', lastName: 'Coucou' }, + { id: 5, division: '2ndA', firstName: 'Arthur', lastName: 'Coucou' }, + ); + await databaseBuilder.commit(); + + const request = { + method: 'GET', + url: `/api/certification-centers/${certificationCenter.id}/sessions/${session.id}/students?page[size]=10&page[number]=1`, + headers: { authorization: generateValidRequestAuthorizationHeader(user.id) }, + }; + + // when + const response = await server.inject(request); + + // then + expect(_.map(response.result.data, 'id')).to.deep.equal(['3', '2', '5', '4', '1']); + }); + }); + + context('when user is not connected', function () { + it('should return 401 HTTP status code if user is not authenticated', async function () { + // given + _buildUserWithCertificationCenterMemberShip(externalId); + databaseBuilder.factory.buildOrganization({ externalId }); + const certificationCenterWhereUserDoesNotHaveAccess = databaseBuilder.factory.buildCertificationCenter({ + externalId, + }); + const session = databaseBuilder.factory.buildSession({ + certificationCenterId: certificationCenterWhereUserDoesNotHaveAccess.id, + }); + await databaseBuilder.commit(); + + request = { + method: 'GET', + url: `/api/certification-centers/${certificationCenterWhereUserDoesNotHaveAccess.id}/sessions/${session.id}/students?page[size]=10&page[number]=1`, + }; + + // when + const response = await server.inject(request); + + // then + expect(response.statusCode).to.equal(401); + }); + }); + }); + + function _buildOrganizationLearners(organization, ...students) { + const AFTER_BEGINNING_OF_THE_2020_SCHOOL_YEAR = '2020-10-15'; + return students.map((student) => + databaseBuilder.factory.buildOrganizationLearner({ + organizationId: organization.id, + ...student, + updatedAt: AFTER_BEGINNING_OF_THE_2020_SCHOOL_YEAR, + }), + ); + } + + function _buildUserWithCertificationCenterMemberShip(certificationCenterExternalId) { + const user = databaseBuilder.factory.buildUser({}); + const certificationCenter = databaseBuilder.factory.buildCertificationCenter({ + externalId: certificationCenterExternalId, + type: 'SCO', + }); + databaseBuilder.factory.buildCertificationCenterMembership({ + certificationCenterId: certificationCenter.id, + userId: user.id, + }); + return { user, certificationCenter }; + } +}); diff --git a/api/tests/certification/enrolment/unit/application/certification-center-route_test.js b/api/tests/certification/enrolment/unit/application/certification-center-route_test.js new file mode 100644 index 00000000000..f1638e4b27b --- /dev/null +++ b/api/tests/certification/enrolment/unit/application/certification-center-route_test.js @@ -0,0 +1,155 @@ +import { certificationCenterController } from '../../../../../src/certification/enrolment/application/certification-center-controller.js'; +import * as moduleUnderTest from '../../../../../src/certification/enrolment/application/certification-center-route.js'; +import { securityPreHandlers } from '../../../../../src/shared/application/security-pre-handlers.js'; +import { expect, HttpTestServer, sinon } from '../../../../test-helper.js'; + +describe('Certification | Enrolment | Unit | Application | Session Students Route', function () { + describe('GET /api/certification-centers/{certificationCenterId}/sessions/{sessionId}/students', function () { + it('should reject unexpected filters ', async function () { + // given + const httpTestServer = new HttpTestServer(); + await httpTestServer.register(moduleUnderTest); + + // when + const result = await httpTestServer.request( + 'GET', + '/api/certification-centers/1/sessions/2/students?filter[unexpected][]=5', + ); + + // then + expect(result.statusCode).to.equal(400); + }); + + it('should accept a string array of one element as division filter ', async function () { + // given + sinon.stub(certificationCenterController, 'getStudents').callsFake((request, h) => h.response().code(200)); + sinon.stub(securityPreHandlers, 'checkUserIsMemberOfCertificationCenter').returns(() => true); + const httpTestServer = new HttpTestServer(); + await httpTestServer.register(moduleUnderTest); + + // when + const result = await httpTestServer.request( + 'GET', + '/api/certification-centers/1/sessions/2/students?filter[divisions][]="3EMEB"', + ); + + // then + expect(result.statusCode).to.equal(200); + }); + + it('should accept a string array of several elements as division filter ', async function () { + // given + sinon.stub(certificationCenterController, 'getStudents').callsFake((request, h) => h.response().code(200)); + sinon.stub(securityPreHandlers, 'checkUserIsMemberOfCertificationCenter').returns(() => true); + const httpTestServer = new HttpTestServer(); + await httpTestServer.register(moduleUnderTest); + + // when + const result = await httpTestServer.request( + 'GET', + '/api/certification-centers/1/sessions/2/students?filter[divisions][]="3EMEB"&filter[divisions][]="3EMEA"', + ); + + // then + expect(result.statusCode).to.equal(200); + }); + + it('should reject a division filter if it is not an array', async function () { + // given + const httpTestServer = new HttpTestServer(); + await httpTestServer.register(moduleUnderTest); + + // when + const result = await httpTestServer.request( + 'GET', + '/api/certification-centers/1/sessions/2/students?filter[divisions]="3EMEA"', + ); + + // then + expect(result.statusCode).to.equal(400); + }); + + it('should accept a pagination', async function () { + // given + sinon.stub(certificationCenterController, 'getStudents').callsFake((request, h) => h.response().code(200)); + sinon.stub(securityPreHandlers, 'checkUserIsMemberOfCertificationCenter').returns(() => true); + const httpTestServer = new HttpTestServer(); + await httpTestServer.register(moduleUnderTest); + // when + const result = await httpTestServer.request( + 'GET', + '/api/certification-centers/1/sessions/2/students?page[number]=1&page[size]=25', + ); + + // then + expect(result.statusCode).to.equal(200); + }); + + it('should reject a page number which is not a number', async function () { + // given + const httpTestServer = new HttpTestServer(); + await httpTestServer.register(moduleUnderTest); + + // when + const result = await httpTestServer.request( + 'GET', + '/api/certification-centers/1/sessions/2/students?page[number]=a', + ); + + // then + expect(result.statusCode).to.equal(400); + }); + + it('should reject a page size which is not a number', async function () { + // given + const httpTestServer = new HttpTestServer(); + await httpTestServer.register(moduleUnderTest); + // when + const result = await httpTestServer.request( + 'GET', + '/api/certification-centers/1/sessions/2/students?page[size]=a', + ); + + // then + expect(result.statusCode).to.equal(400); + }); + + it('should accept an empty query string', async function () { + // given + sinon.stub(certificationCenterController, 'getStudents').returns('ok'); + sinon.stub(securityPreHandlers, 'checkUserIsMemberOfCertificationCenter').returns(() => true); + const httpTestServer = new HttpTestServer(); + await httpTestServer.register(moduleUnderTest); + + // when + const result = await httpTestServer.request('GET', '/api/certification-centers/1/sessions/2/students'); + + // then + expect(result.statusCode).to.equal(200); + }); + + it('should reject an invalid certification-centers id', async function () { + // given + const httpTestServer = new HttpTestServer(); + await httpTestServer.register(moduleUnderTest); + + // when + const result = await httpTestServer.request('GET', '/api/certification-centers/invalid/sessions/2/students'); + + // then + expect(result.statusCode).to.equal(400); + }); + + it('should reject an invalid session id', async function () { + // given + const httpTestServer = new HttpTestServer(); + await httpTestServer.register(moduleUnderTest); + + // when + const result = await httpTestServer.request('GET', '/api/certification-centers/1/sessions/invalid/students'); + + // then + expect(result.statusCode).to.equal(400); + }); + }); +}); diff --git a/api/tests/unit/domain/usecases/find-students-for-enrolment_test.js b/api/tests/certification/enrolment/unit/domain/usecases/find-students-for-enrolment_test.js similarity index 92% rename from api/tests/unit/domain/usecases/find-students-for-enrolment_test.js rename to api/tests/certification/enrolment/unit/domain/usecases/find-students-for-enrolment_test.js index 8b8806a13f8..23b2b5c42f2 100644 --- a/api/tests/unit/domain/usecases/find-students-for-enrolment_test.js +++ b/api/tests/certification/enrolment/unit/domain/usecases/find-students-for-enrolment_test.js @@ -1,9 +1,9 @@ import _ from 'lodash'; -import { findStudentsForEnrolment } from '../../../../lib/domain/usecases/find-students-for-enrolment.js'; -import { NotFoundError } from '../../../../src/shared/domain/errors.js'; -import { StudentForEnrolment } from '../../../../src/shared/domain/read-models/StudentForEnrolment.js'; -import { domainBuilder, expect, sinon } from '../../../test-helper.js'; +import { findStudentsForEnrolment } from '../../../../../../src/certification/enrolment/domain/usecases/find-students-for-enrolment.js'; +import { NotFoundError } from '../../../../../../src/shared/domain/errors.js'; +import { StudentForEnrolment } from '../../../../../../src/shared/domain/read-models/StudentForEnrolment.js'; +import { domainBuilder, expect, sinon } from '../../../../../test-helper.js'; describe('Unit | UseCase | find-students-for-enrolment', function () { const certificationCenterId = 1; diff --git a/api/tests/unit/infrastructure/serializers/jsonapi/student-certification-serializer_test.js b/api/tests/certification/enrolment/unit/infrastructure/serializers/student-certification-serializer_test.js similarity index 77% rename from api/tests/unit/infrastructure/serializers/jsonapi/student-certification-serializer_test.js rename to api/tests/certification/enrolment/unit/infrastructure/serializers/student-certification-serializer_test.js index 3de8e3f0a24..2320148c284 100644 --- a/api/tests/unit/infrastructure/serializers/jsonapi/student-certification-serializer_test.js +++ b/api/tests/certification/enrolment/unit/infrastructure/serializers/student-certification-serializer_test.js @@ -1,6 +1,6 @@ -import * as serializer from '../../../../../lib/infrastructure/serializers/jsonapi/student-certification-serializer.js'; -import { StudentForEnrolment } from '../../../../../src/shared/domain/read-models/StudentForEnrolment.js'; -import { domainBuilder, expect } from '../../../../test-helper.js'; +import * as serializer from '../../../../../../src/certification/enrolment/infrastructure/serializers/student-certification-serializer.js'; +import { StudentForEnrolment } from '../../../../../../src/shared/domain/read-models/StudentForEnrolment.js'; +import { domainBuilder, expect } from '../../../../../test-helper.js'; describe('Unit | Serializer | JSONAPI | student-certification-serializer', function () { describe('#serialize', function () { diff --git a/api/tests/integration/domain/usecases/create-and-reconcile-user-to-organization-learner_test.js b/api/tests/integration/domain/usecases/create-and-reconcile-user-to-organization-learner_test.js index c4d9d954ade..fba03d16a5c 100644 --- a/api/tests/integration/domain/usecases/create-and-reconcile-user-to-organization-learner_test.js +++ b/api/tests/integration/domain/usecases/create-and-reconcile-user-to-organization-learner_test.js @@ -7,7 +7,6 @@ import * as userReconciliationService from '../../../../lib/domain/services/user import { createAndReconcileUserToOrganizationLearner } from '../../../../lib/domain/usecases/create-and-reconcile-user-to-organization-learner.js'; import { usecases } from '../../../../lib/domain/usecases/index.js'; import * as campaignRepository from '../../../../lib/infrastructure/repositories/campaign-repository.js'; -import * as organizationLearnerRepository from '../../../../lib/infrastructure/repositories/organization-learner-repository.js'; import * as authenticationMethodRepository from '../../../../src/identity-access-management/infrastructure/repositories/authentication-method.repository.js'; import * as userRepository from '../../../../src/identity-access-management/infrastructure/repositories/user.repository.js'; import { userToCreateRepository } from '../../../../src/identity-access-management/infrastructure/repositories/user-to-create.repository.js'; @@ -22,6 +21,7 @@ import * as userService from '../../../../src/shared/domain/services/user-servic import * as passwordValidator from '../../../../src/shared/domain/validators/password-validator.js'; import * as userValidator from '../../../../src/shared/domain/validators/user-validator.js'; import { getI18n } from '../../../../src/shared/infrastructure/i18n/i18n.js'; +import * as organizationLearnerRepository from '../../../../src/shared/infrastructure/repositories/organization-learner-repository.js'; import { catchErr, databaseBuilder, expect } from '../../../test-helper.js'; const i18n = getI18n(); diff --git a/api/tests/prescription/learner-management/integration/application/jobs/schedule-compute-organization-learners-certificability-job-controller_test.js b/api/tests/prescription/learner-management/integration/application/jobs/schedule-compute-organization-learners-certificability-job-controller_test.js index e82cd408477..4a289aedc98 100644 --- a/api/tests/prescription/learner-management/integration/application/jobs/schedule-compute-organization-learners-certificability-job-controller_test.js +++ b/api/tests/prescription/learner-management/integration/application/jobs/schedule-compute-organization-learners-certificability-job-controller_test.js @@ -1,7 +1,7 @@ -import * as organizationLearnerRepository from '../../../../../../lib/infrastructure/repositories/organization-learner-repository.js'; import { ScheduleComputeOrganizationLearnersCertificabilityJobController } from '../../../../../../src/prescription/learner-management/application/jobs/schedule-compute-organization-learners-certificability-job-controller.js'; import { computeCertificabilityJobRepository } from '../../../../../../src/prescription/learner-management/infrastructure/repositories/jobs/compute-certificability-job-repository.js'; import { ORGANIZATION_FEATURE } from '../../../../../../src/shared/domain/constants.js'; +import * as organizationLearnerRepository from '../../../../../../src/shared/infrastructure/repositories/organization-learner-repository.js'; import { databaseBuilder, expect, sinon } from '../../../../../test-helper.js'; describe('Integration | Infrastructure | Jobs | scheduleComputeOrganizationLearnersCertificabilityJobController', function () { diff --git a/api/tests/prescription/learner-management/integration/infrastructure/repositories/organization-learner-repository_test.js b/api/tests/prescription/learner-management/integration/infrastructure/repositories/organization-learner-repository_test.js index 36f169f4e6d..4812707e5ec 100644 --- a/api/tests/prescription/learner-management/integration/infrastructure/repositories/organization-learner-repository_test.js +++ b/api/tests/prescription/learner-management/integration/infrastructure/repositories/organization-learner-repository_test.js @@ -1,6 +1,5 @@ import _ from 'lodash'; -import * as organizationLearnerRepository from '../../../../../../lib/infrastructure/repositories/organization-learner-repository.js'; import { OrganizationLearnerCertificabilityNotUpdatedError } from '../../../../../../src/prescription/learner-management/domain/errors.js'; import { CommonOrganizationLearner } from '../../../../../../src/prescription/learner-management/domain/models/CommonOrganizationLearner.js'; import { OrganizationLearnerForAdmin } from '../../../../../../src/prescription/learner-management/domain/read-models/OrganizationLearnerForAdmin.js'; @@ -29,6 +28,7 @@ import { UserCouldNotBeReconciledError, } from '../../../../../../src/shared/domain/errors.js'; import { OrganizationLearner } from '../../../../../../src/shared/domain/models/index.js'; +import * as organizationLearnerRepository from '../../../../../../src/shared/infrastructure/repositories/organization-learner-repository.js'; import { catchErr, databaseBuilder, domainBuilder, expect, knex, sinon } from '../../../../../test-helper.js'; describe('Integration | Repository | Organization Learner Management | Organization Learner', function () { diff --git a/api/tests/prescription/organization-learner/integration/domain/usecases/find-organization-learners-with-participations_test.js b/api/tests/prescription/organization-learner/integration/domain/usecases/find-organization-learners-with-participations_test.js index baf44d7ae0c..1bbb0730a6a 100644 --- a/api/tests/prescription/organization-learner/integration/domain/usecases/find-organization-learners-with-participations_test.js +++ b/api/tests/prescription/organization-learner/integration/domain/usecases/find-organization-learners-with-participations_test.js @@ -1,10 +1,10 @@ -import * as libOrganizationLearnerRepository from '../../../../../../lib/infrastructure/repositories/organization-learner-repository.js'; import { Organization } from '../../../../../../src/organizational-entities/domain/models/Organization.js'; import { tagRepository } from '../../../../../../src/organizational-entities/infrastructure/repositories/tag.repository.js'; import * as campaignParticipationOverviewRepository from '../../../../../../src/prescription/campaign-participation/infrastructure/repositories/campaign-participation-overview-repository.js'; import { findOrganizationLearnersWithParticipations } from '../../../../../../src/prescription/organization-learner/domain/usecases/find-organization-learners-with-participations.js'; import { OrganizationLearner } from '../../../../../../src/shared/domain/models/OrganizationLearner.js'; import { CampaignParticipationOverview } from '../../../../../../src/shared/domain/read-models/CampaignParticipationOverview.js'; +import * as organizationLearnerRepository from '../../../../../../src/shared/infrastructure/repositories/organization-learner-repository.js'; import * as organizationRepository from '../../../../../../src/shared/infrastructure/repositories/organization-repository.js'; import { databaseBuilder, expect } from '../../../../../test-helper.js'; @@ -40,7 +40,7 @@ describe('Integration | UseCases | find-organization-learners-with-participation userIds: [user1.id, user2.id], campaignParticipationOverviewRepository, organizationRepository, - libOrganizationLearnerRepository, + libOrganizationLearnerRepository: organizationLearnerRepository, tagRepository, }); @@ -87,7 +87,7 @@ describe('Integration | UseCases | find-organization-learners-with-participation userIds: [organizationLearner.userId], campaignParticipationOverviewRepository, organizationRepository, - libOrganizationLearnerRepository, + libOrganizationLearnerRepository: organizationLearnerRepository, tagRepository, }); diff --git a/api/tests/prescription/organization-place/integration/domain/usecases/get-data-organizations-places-statistics_test.js b/api/tests/prescription/organization-place/integration/domain/usecases/get-data-organizations-places-statistics_test.js index e09f2e680d9..e6f4eab22dc 100644 --- a/api/tests/prescription/organization-place/integration/domain/usecases/get-data-organizations-places-statistics_test.js +++ b/api/tests/prescription/organization-place/integration/domain/usecases/get-data-organizations-places-statistics_test.js @@ -1,7 +1,7 @@ -import * as organizationLearnerRepository from '../../../../../../lib/infrastructure/repositories/organization-learner-repository.js'; import { getDataOrganizationsPlacesStatistics } from '../../../../../../src/prescription/organization-place/domain/usecases/get-data-organizations-places-statistics.js'; import * as organizationPlacesLotRepository from '../../../../../../src/prescription/organization-place/infrastructure/repositories/organization-places-lot-repository.js'; import { ORGANIZATION_FEATURE } from '../../../../../../src/shared/domain/constants.js'; +import * as organizationLearnerRepository from '../../../../../../src/shared/infrastructure/repositories/organization-learner-repository.js'; import * as organizationRepository from '../../../../../../src/shared/infrastructure/repositories/organization-repository.js'; import { databaseBuilder, expect, sinon } from '../../../../../test-helper.js'; diff --git a/api/tests/shared/integration/domain/services/user-service_test.js b/api/tests/shared/integration/domain/services/user-service_test.js index c0e6a932574..dacb39907de 100644 --- a/api/tests/shared/integration/domain/services/user-service_test.js +++ b/api/tests/shared/integration/domain/services/user-service_test.js @@ -1,7 +1,6 @@ import lodash from 'lodash'; const { pick } = lodash; -import * as organizationLearnerRepository from '../../../../../lib/infrastructure/repositories/organization-learner-repository.js'; import { NON_OIDC_IDENTITY_PROVIDERS } from '../../../../../src/identity-access-management/domain/constants/identity-providers.js'; import * as authenticationMethodRepository from '../../../../../src/identity-access-management/infrastructure/repositories/authentication-method.repository.js'; import * as userRepository from '../../../../../src/identity-access-management/infrastructure/repositories/user.repository.js'; @@ -9,6 +8,7 @@ import { userToCreateRepository } from '../../../../../src/identity-access-manag import { getLearnerInfo } from '../../../../../src/prescription/learner-management/infrastructure/repositories/organization-learner-repository.js'; import { OrganizationLearnerNotFound } from '../../../../../src/shared/domain/errors.js'; import * as userService from '../../../../../src/shared/domain/services/user-service.js'; +import * as organizationLearnerRepository from '../../../../../src/shared/infrastructure/repositories/organization-learner-repository.js'; import { catchErr, databaseBuilder, domainBuilder, expect, knex } from '../../../../test-helper.js'; describe('Integration | Domain | Services | user-service', function () { diff --git a/api/tests/integration/infrastructure/repositories/organization-learner-repository_test.js b/api/tests/shared/integration/infrastructure/repositories/organization-learner-repository_test.js similarity index 99% rename from api/tests/integration/infrastructure/repositories/organization-learner-repository_test.js rename to api/tests/shared/integration/infrastructure/repositories/organization-learner-repository_test.js index 6d30ef907d2..55326353118 100644 --- a/api/tests/integration/infrastructure/repositories/organization-learner-repository_test.js +++ b/api/tests/shared/integration/infrastructure/repositories/organization-learner-repository_test.js @@ -1,12 +1,12 @@ import dayjs from 'dayjs'; import _ from 'lodash'; -import { DomainTransaction } from '../../../../lib/infrastructure/DomainTransaction.js'; -import * as organizationLearnerRepository from '../../../../lib/infrastructure/repositories/organization-learner-repository.js'; -import { ORGANIZATION_FEATURE } from '../../../../src/shared/domain/constants.js'; -import { OrganizationLearnerNotFound, UserNotFoundError } from '../../../../src/shared/domain/errors.js'; -import { OrganizationLearner } from '../../../../src/shared/domain/models/index.js'; -import { catchErr, databaseBuilder, domainBuilder, expect, knex, sinon } from '../../../test-helper.js'; +import { DomainTransaction } from '../../../../../lib/infrastructure/DomainTransaction.js'; +import { ORGANIZATION_FEATURE } from '../../../../../src/shared/domain/constants.js'; +import { OrganizationLearnerNotFound, UserNotFoundError } from '../../../../../src/shared/domain/errors.js'; +import { OrganizationLearner } from '../../../../../src/shared/domain/models/index.js'; +import * as organizationLearnerRepository from '../../../../../src/shared/infrastructure/repositories/organization-learner-repository.js'; +import { catchErr, databaseBuilder, domainBuilder, expect, knex, sinon } from '../../../../test-helper.js'; describe('Integration ¨| Infrastructure | Repository | organization-learner-repository', function () { describe('#findByIds', function () { diff --git a/api/tests/unit/application/certification-centers/certification-center-controller_test.js b/api/tests/unit/application/certification-centers/certification-center-controller_test.js index 14ed71d70f2..2d571d233d5 100644 --- a/api/tests/unit/application/certification-centers/certification-center-controller_test.js +++ b/api/tests/unit/application/certification-centers/certification-center-controller_test.js @@ -1,68 +1,9 @@ import { certificationCenterController } from '../../../../lib/application/certification-centers/certification-center-controller.js'; import { usecases } from '../../../../lib/domain/usecases/index.js'; import { usecases as teamUsecases } from '../../../../src/team/domain/usecases/index.js'; -import { domainBuilder, expect, hFake, sinon } from '../../../test-helper.js'; +import { expect, hFake, sinon } from '../../../test-helper.js'; describe('Unit | Controller | certifications-center-controller', function () { - describe('#getStudents', function () { - it('should return a paginated serialized list of students', async function () { - // given - const student = domainBuilder.buildOrganizationLearner({ division: '3A' }); - - const request = { - auth: { - credentials: { userId: '111' }, - }, - params: { - certificationCenterId: 99, - sessionId: 88, - }, - query: { - page: { - size: 10, - number: 1, - }, - filter: { - divisions: '3A', - }, - }, - }; - - sinon - .stub(usecases, 'findStudentsForEnrolment') - .withArgs({ - certificationCenterId: 99, - sessionId: 88, - page: { size: 10, number: 1 }, - filter: { divisions: ['3A'] }, - }) - .resolves({ - data: [student], - pagination: { page: 1, pageSize: 10, rowCount: 1, pageCount: 1 }, - }); - - // when - const response = await certificationCenterController.getStudents(request, hFake); - - // then - expect(response).to.deep.equal({ - data: [ - { - attributes: { - birthdate: student.birthdate, - division: student.division, - 'first-name': student.firstName, - 'last-name': student.lastName, - }, - id: `${student.id}`, - type: 'students', - }, - ], - meta: { page: 1, pageSize: 10, rowCount: 1, pageCount: 1 }, - }); - }); - }); - describe('#getDivisions', function () { it('Should return a serialized list of divisions', async function () { // given diff --git a/api/tests/unit/application/certification-centers/index_test.js b/api/tests/unit/application/certification-centers/index_test.js index 80e1c78afc1..b2e4a72a9df 100644 --- a/api/tests/unit/application/certification-centers/index_test.js +++ b/api/tests/unit/application/certification-centers/index_test.js @@ -39,155 +39,6 @@ describe('Unit | Router | certification-center-router', function () { }); }); - describe('GET /api/certification-centers/{certificationCenterId}/sessions/{sessionId}/students', function () { - it('should reject unexpected filters ', async function () { - // given - const httpTestServer = new HttpTestServer(); - await httpTestServer.register(moduleUnderTest); - - // when - const result = await httpTestServer.request( - 'GET', - '/api/certification-centers/1/sessions/2/students?filter[unexpected][]=5', - ); - - // then - expect(result.statusCode).to.equal(400); - }); - - it('should accept a string array of one element as division filter ', async function () { - // given - sinon.stub(certificationCenterController, 'getStudents').callsFake((request, h) => h.response().code(200)); - sinon.stub(securityPreHandlers, 'checkUserIsMemberOfCertificationCenter').returns(() => true); - const httpTestServer = new HttpTestServer(); - await httpTestServer.register(moduleUnderTest); - - // when - const result = await httpTestServer.request( - 'GET', - '/api/certification-centers/1/sessions/2/students?filter[divisions][]="3EMEB"', - ); - - // then - expect(result.statusCode).to.equal(200); - }); - - it('should accept a string array of several elements as division filter ', async function () { - // given - sinon.stub(certificationCenterController, 'getStudents').callsFake((request, h) => h.response().code(200)); - sinon.stub(securityPreHandlers, 'checkUserIsMemberOfCertificationCenter').returns(() => true); - const httpTestServer = new HttpTestServer(); - await httpTestServer.register(moduleUnderTest); - - // when - const result = await httpTestServer.request( - 'GET', - '/api/certification-centers/1/sessions/2/students?filter[divisions][]="3EMEB"&filter[divisions][]="3EMEA"', - ); - - // then - expect(result.statusCode).to.equal(200); - }); - - it('should reject a division filter if it is not an array', async function () { - // given - const httpTestServer = new HttpTestServer(); - await httpTestServer.register(moduleUnderTest); - - // when - const result = await httpTestServer.request( - 'GET', - '/api/certification-centers/1/sessions/2/students?filter[divisions]="3EMEA"', - ); - - // then - expect(result.statusCode).to.equal(400); - }); - - it('should accept a pagination', async function () { - // given - sinon.stub(certificationCenterController, 'getStudents').callsFake((request, h) => h.response().code(200)); - sinon.stub(securityPreHandlers, 'checkUserIsMemberOfCertificationCenter').returns(() => true); - const httpTestServer = new HttpTestServer(); - await httpTestServer.register(moduleUnderTest); - // when - const result = await httpTestServer.request( - 'GET', - '/api/certification-centers/1/sessions/2/students?page[number]=1&page[size]=25', - ); - - // then - expect(result.statusCode).to.equal(200); - }); - - it('should reject a page number which is not a number', async function () { - // given - const httpTestServer = new HttpTestServer(); - await httpTestServer.register(moduleUnderTest); - - // when - const result = await httpTestServer.request( - 'GET', - '/api/certification-centers/1/sessions/2/students?page[number]=a', - ); - - // then - expect(result.statusCode).to.equal(400); - }); - - it('should reject a page size which is not a number', async function () { - // given - const httpTestServer = new HttpTestServer(); - await httpTestServer.register(moduleUnderTest); - // when - const result = await httpTestServer.request( - 'GET', - '/api/certification-centers/1/sessions/2/students?page[size]=a', - ); - - // then - expect(result.statusCode).to.equal(400); - }); - - it('should accept an empty query string', async function () { - // given - sinon.stub(certificationCenterController, 'getStudents').returns('ok'); - sinon.stub(securityPreHandlers, 'checkUserIsMemberOfCertificationCenter').returns(() => true); - const httpTestServer = new HttpTestServer(); - await httpTestServer.register(moduleUnderTest); - - // when - const result = await httpTestServer.request('GET', '/api/certification-centers/1/sessions/2/students'); - - // then - expect(result.statusCode).to.equal(200); - }); - - it('should reject an invalid certification-centers id', async function () { - // given - const httpTestServer = new HttpTestServer(); - await httpTestServer.register(moduleUnderTest); - - // when - const result = await httpTestServer.request('GET', '/api/certification-centers/invalid/sessions/2/students'); - - // then - expect(result.statusCode).to.equal(400); - }); - - it('should reject an invalid session id', async function () { - // given - const httpTestServer = new HttpTestServer(); - await httpTestServer.register(moduleUnderTest); - - // when - const result = await httpTestServer.request('GET', '/api/certification-centers/1/sessions/invalid/students'); - - // then - expect(result.statusCode).to.equal(400); - }); - }); - describe('GET /api/admin/certification-centers/{certificationCenterId}/certification-center-memberships', function () { const method = 'GET'; const url = '/api/admin/certification-centers/1/certification-center-memberships';