From 82acb0ca61529bfd7d50aeceb1ee7028461d2d48 Mon Sep 17 00:00:00 2001 From: Xavier Carron <33637571+xav-car@users.noreply.github.com> Date: Wed, 11 Sep 2024 15:25:52 +0200 Subject: [PATCH] =?UTF-8?q?[BUGFIX]=20D=C3=A9sactiver=20compl=C3=A8tement?= =?UTF-8?q?=20le=20push=20FT=20(#10090)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...ed-participation-results-to-pole-emploi.js | 58 +++++ ...ed-participation-results-to-pole-emploi.js | 54 ++++ .../participation-completed-job-controller.js | 69 +---- .../participation-started-job-controller.js | 63 +---- ...rticipation-results-to-pole-emploi_test.js | 80 ++++++ ...rticipation-results-to-pole-emploi_test.js | 80 ++++++ ...icipation-completed-job-controller_test.js | 76 ------ ...rticipation-started-job-controller_test.js | 76 ------ ...icipation-completed-job-controller_test.js | 230 ++--------------- ...rticipation-started-job-controller_test.js | 239 ++---------------- 10 files changed, 313 insertions(+), 712 deletions(-) create mode 100644 api/lib/domain/usecases/send-completed-participation-results-to-pole-emploi.js create mode 100644 api/lib/domain/usecases/send-started-participation-results-to-pole-emploi.js create mode 100644 api/tests/integration/domain/usecases/send-completed-participation-results-to-pole-emploi_test.js create mode 100644 api/tests/integration/domain/usecases/send-started-participation-results-to-pole-emploi_test.js delete mode 100644 api/tests/prescription/campaign-participation/integration/application/jobs/participation-completed-job-controller_test.js delete mode 100644 api/tests/prescription/campaign-participation/integration/application/jobs/participation-started-job-controller_test.js diff --git a/api/lib/domain/usecases/send-completed-participation-results-to-pole-emploi.js b/api/lib/domain/usecases/send-completed-participation-results-to-pole-emploi.js new file mode 100644 index 00000000000..19c4cc2e84c --- /dev/null +++ b/api/lib/domain/usecases/send-completed-participation-results-to-pole-emploi.js @@ -0,0 +1,58 @@ +import { PoleEmploiSending } from '../../../src/shared/domain/models/PoleEmploiSending.js'; +import { logger } from '../../../src/shared/infrastructure/utils/logger.js'; +import { PoleEmploiPayload } from '../../infrastructure/externals/pole-emploi/PoleEmploiPayload.js'; +import * as httpErrorsHelper from '../../infrastructure/http/errors-helper.js'; +import { httpAgent } from '../../infrastructure/http/http-agent.js'; + +const sendCompletedParticipationResultsToPoleEmploi = async ({ + campaignParticipationId, + assessmentRepository, + authenticationMethodRepository, + campaignParticipationRepository, + campaignRepository, + organizationRepository, + poleEmploiNotifier, + poleEmploiSendingRepository, + targetProfileRepository, + userRepository, + notifierDependencies = { + httpAgent, + httpErrorsHelper, + logger, + }, +}) => { + if (!campaignParticipationId) return; + + const participation = await campaignParticipationRepository.get(campaignParticipationId); + const campaign = await campaignRepository.get(participation.campaignId); + const organization = await organizationRepository.get(campaign.organizationId); + + if (campaign.isAssessment() && organization.isPoleEmploi) { + const user = await userRepository.get(participation.userId); + const targetProfile = await targetProfileRepository.get(campaign.targetProfileId); + const assessment = await assessmentRepository.get(participation.lastAssessment.id); + + const payload = PoleEmploiPayload.buildForParticipationFinished({ + user, + campaign, + targetProfile, + participation, + assessment, + }); + const response = await poleEmploiNotifier.notify(user.id, payload, { + authenticationMethodRepository: authenticationMethodRepository, + ...notifierDependencies, + }); + + const poleEmploiSending = PoleEmploiSending.buildForParticipationFinished({ + campaignParticipationId, + payload: payload.toString(), + isSuccessful: response.isSuccessful, + responseCode: response.code, + }); + + return poleEmploiSendingRepository.create({ poleEmploiSending }); + } +}; + +export { sendCompletedParticipationResultsToPoleEmploi }; diff --git a/api/lib/domain/usecases/send-started-participation-results-to-pole-emploi.js b/api/lib/domain/usecases/send-started-participation-results-to-pole-emploi.js new file mode 100644 index 00000000000..7f6961d3470 --- /dev/null +++ b/api/lib/domain/usecases/send-started-participation-results-to-pole-emploi.js @@ -0,0 +1,54 @@ +import { PoleEmploiSending } from '../../../src/shared/domain/models/PoleEmploiSending.js'; +import { logger } from '../../../src/shared/infrastructure/utils/logger.js'; +import { PoleEmploiPayload } from '../../infrastructure/externals/pole-emploi/PoleEmploiPayload.js'; +import * as httpErrorsHelper from '../../infrastructure/http/errors-helper.js'; +import { httpAgent } from '../../infrastructure/http/http-agent.js'; + +const sendStartedParticipationResultsToPoleEmploi = async ({ + campaignParticipationId, + authenticationMethodRepository, + campaignParticipationRepository, + campaignRepository, + organizationRepository, + poleEmploiNotifier, + poleEmploiSendingRepository, + targetProfileRepository, + userRepository, + notifierDependencies = { + httpAgent, + httpErrorsHelper, + logger, + }, +}) => { + const participation = await campaignParticipationRepository.get(campaignParticipationId); + const campaign = await campaignRepository.get(participation.campaignId); + const organization = await organizationRepository.get(campaign.organizationId); + + if (campaign.isAssessment() && organization.isPoleEmploi) { + const user = await userRepository.get(participation.userId); + const targetProfile = await targetProfileRepository.get(campaign.targetProfileId); + + const payload = PoleEmploiPayload.buildForParticipationStarted({ + user, + campaign, + targetProfile, + participation, + }); + + const response = await poleEmploiNotifier.notify(user.id, payload, { + authenticationMethodRepository: authenticationMethodRepository, + ...notifierDependencies, + }); + + const poleEmploiSending = PoleEmploiSending.buildForParticipationStarted({ + campaignParticipationId, + payload: payload.toString(), + isSuccessful: response.isSuccessful, + responseCode: response.code, + }); + + await poleEmploiSendingRepository.create({ poleEmploiSending }); + } +}; + +export { sendStartedParticipationResultsToPoleEmploi }; diff --git a/api/src/prescription/campaign-participation/application/jobs/participation-completed-job-controller.js b/api/src/prescription/campaign-participation/application/jobs/participation-completed-job-controller.js index d5d4bb6ee59..116ca4c94cc 100644 --- a/api/src/prescription/campaign-participation/application/jobs/participation-completed-job-controller.js +++ b/api/src/prescription/campaign-participation/application/jobs/participation-completed-job-controller.js @@ -1,20 +1,6 @@ -import * as poleEmploiNotifier from '../../../../../lib/infrastructure/externals/pole-emploi/pole-emploi-notifier.js'; -import { PoleEmploiPayload } from '../../../../../lib/infrastructure/externals/pole-emploi/PoleEmploiPayload.js'; -import * as httpErrorsHelper from '../../../../../lib/infrastructure/http/errors-helper.js'; -import { httpAgent } from '../../../../../lib/infrastructure/http/http-agent.js'; -import * as campaignParticipationRepository from '../../../../../lib/infrastructure/repositories/campaign-participation-repository.js'; -import * as campaignRepository from '../../../../../lib/infrastructure/repositories/campaign-repository.js'; -import * as poleEmploiSendingRepository from '../../../../../lib/infrastructure/repositories/pole-emploi-sending-repository.js'; -import * as targetProfileRepository from '../../../../../lib/infrastructure/repositories/target-profile-repository.js'; -import { logger } from '../../../../../src/shared/infrastructure/utils/logger.js'; -import { assessmentRepository } from '../../../../certification/session-management/infrastructure/repositories/index.js'; -import * as authenticationMethodRepository from '../../../../identity-access-management/infrastructure/repositories/authentication-method.repository.js'; -import * as userRepository from '../../../../identity-access-management/infrastructure/repositories/user.repository.js'; +import { usecases } from '../../../../../lib/domain/usecases/index.js'; import { JobController } from '../../../../shared/application/jobs/job-controller.js'; -import { PoleEmploiSending } from '../../../../shared/domain/models/index.js'; -import * as organizationRepository from '../../../../shared/infrastructure/repositories/organization-repository.js'; import { ParticipationCompletedJob } from '../../domain/models/ParticipationCompletedJob.js'; - export class ParticipationCompletedJobController extends JobController { constructor() { super(ParticipationCompletedJob.name); @@ -24,58 +10,9 @@ export class ParticipationCompletedJobController extends JobController { return 'PoleEmploiParticipationCompletedJob'; } - async handle({ - data, - dependencies = { - authenticationMethodRepository, - assessmentRepository, - campaignRepository, - campaignParticipationRepository, - organizationRepository, - poleEmploiSendingRepository, - targetProfileRepository, - userRepository, - poleEmploiNotifier, - logger, - httpAgent, - httpErrorsHelper, - }, - }) { + async handle({ data }) { const { campaignParticipationId } = data; - if (!campaignParticipationId) return; - - const participation = await dependencies.campaignParticipationRepository.get(campaignParticipationId); - const campaign = await dependencies.campaignRepository.get(participation.campaignId); - const organization = await dependencies.organizationRepository.get(campaign.organizationId); - - if (campaign.isAssessment() && organization.isPoleEmploi) { - const user = await dependencies.userRepository.get(participation.userId); - const targetProfile = await dependencies.targetProfileRepository.get(campaign.targetProfileId); - const assessment = await dependencies.assessmentRepository.get(participation.lastAssessment.id); - - const payload = PoleEmploiPayload.buildForParticipationFinished({ - user, - campaign, - targetProfile, - participation, - assessment, - }); - const response = await dependencies.poleEmploiNotifier.notify(user.id, payload, { - authenticationMethodRepository: dependencies.authenticationMethodRepository, - httpAgent: dependencies.httpAgent, - httpErrorsHelper: dependencies.httpErrorsHelper, - logger: dependencies.logger, - }); - - const poleEmploiSending = PoleEmploiSending.buildForParticipationFinished({ - campaignParticipationId, - payload: payload.toString(), - isSuccessful: response.isSuccessful, - responseCode: response.code, - }); - - return dependencies.poleEmploiSendingRepository.create({ poleEmploiSending }); - } + await usecases.sendCompletedParticipationResultsToPoleEmploi({ campaignParticipationId }); } } diff --git a/api/src/prescription/campaign-participation/application/jobs/participation-started-job-controller.js b/api/src/prescription/campaign-participation/application/jobs/participation-started-job-controller.js index 511e84ab987..54cf5e128eb 100644 --- a/api/src/prescription/campaign-participation/application/jobs/participation-started-job-controller.js +++ b/api/src/prescription/campaign-participation/application/jobs/participation-started-job-controller.js @@ -1,18 +1,6 @@ -import * as poleEmploiNotifier from '../../../../../lib/infrastructure/externals/pole-emploi/pole-emploi-notifier.js'; -import { PoleEmploiPayload } from '../../../../../lib/infrastructure/externals/pole-emploi/PoleEmploiPayload.js'; -import * as httpErrorsHelper from '../../../../../lib/infrastructure/http/errors-helper.js'; -import { httpAgent } from '../../../../../lib/infrastructure/http/http-agent.js'; -import * as campaignRepository from '../../../../../lib/infrastructure/repositories/campaign-repository.js'; -import * as poleEmploiSendingRepository from '../../../../../lib/infrastructure/repositories/pole-emploi-sending-repository.js'; -import * as targetProfileRepository from '../../../../../lib/infrastructure/repositories/target-profile-repository.js'; -import * as authenticationMethodRepository from '../../../../identity-access-management/infrastructure/repositories/authentication-method.repository.js'; -import * as userRepository from '../../../../identity-access-management/infrastructure/repositories/user.repository.js'; +import { usecases } from '../../../../../lib/domain/usecases/index.js'; import { JobController } from '../../../../shared/application/jobs/job-controller.js'; -import { PoleEmploiSending } from '../../../../shared/domain/models/index.js'; -import * as organizationRepository from '../../../../shared/infrastructure/repositories/organization-repository.js'; -import { logger } from '../../../../shared/infrastructure/utils/logger.js'; import { ParticipationStartedJob } from '../../domain/models/ParticipationStartedJob.js'; -import * as campaignParticipationRepository from '../../infrastructure/repositories/campaign-participation-repository.js'; export class ParticipationStartedJobController extends JobController { constructor() { @@ -23,54 +11,9 @@ export class ParticipationStartedJobController extends JobController { return 'PoleEmploiParticipationStartedJob'; } - async handle({ - data, - dependencies = { - authenticationMethodRepository, - campaignRepository, - campaignParticipationRepository, - organizationRepository, - poleEmploiSendingRepository, - targetProfileRepository, - userRepository, - poleEmploiNotifier, - httpAgent, - httpErrorsHelper, - logger, - }, - }) { + async handle({ data }) { const { campaignParticipationId } = data; - const participation = await dependencies.campaignParticipationRepository.get(campaignParticipationId); - const campaign = await dependencies.campaignRepository.get(participation.campaignId); - const organization = await dependencies.organizationRepository.get(campaign.organizationId); - - if (campaign.isAssessment() && organization.isPoleEmploi) { - const user = await dependencies.userRepository.get(participation.userId); - const targetProfile = await dependencies.targetProfileRepository.get(campaign.targetProfileId); - - const payload = PoleEmploiPayload.buildForParticipationStarted({ - user, - campaign, - targetProfile, - participation, - }); - - const response = await dependencies.poleEmploiNotifier.notify(user.id, payload, { - authenticationMethodRepository: dependencies.authenticationMethodRepository, - httpAgent: dependencies.httpAgent, - httpErrorsHelper: dependencies.httpErrorsHelper, - logger: dependencies.logger, - }); - - const poleEmploiSending = PoleEmploiSending.buildForParticipationStarted({ - campaignParticipationId, - payload: payload.toString(), - isSuccessful: response.isSuccessful, - responseCode: response.code, - }); - - await dependencies.poleEmploiSendingRepository.create({ poleEmploiSending }); - } + await usecases.sendSharedParticipationResultsToPoleEmploi({ campaignParticipationId }); } } diff --git a/api/tests/integration/domain/usecases/send-completed-participation-results-to-pole-emploi_test.js b/api/tests/integration/domain/usecases/send-completed-participation-results-to-pole-emploi_test.js new file mode 100644 index 00000000000..1d4031f8421 --- /dev/null +++ b/api/tests/integration/domain/usecases/send-completed-participation-results-to-pole-emploi_test.js @@ -0,0 +1,80 @@ +import { usecases } from '../../../../lib/domain/usecases/index.js'; +import * as poleEmploiNotifier from '../../../../lib/infrastructure/externals/pole-emploi/pole-emploi-notifier.js'; +import { + databaseBuilder, + expect, + knex, + learningContentBuilder, + mockLearningContent, + sinon, +} from '../../../test-helper.js'; + +describe('Integration | Domain | UseCases | send-completed-participation-results-to-pole-emploi', function () { + let campaignParticipationId, userId, responseCode; + let httpAgentStub, httpErrorsHelperStub, loggerStub; + + beforeEach(async function () { + httpAgentStub = { post: sinon.stub() }; + loggerStub = { info: sinon.stub(), error: sinon.stub() }; + httpErrorsHelperStub = { serializeHttpErrorResponse: sinon.stub() }; + responseCode = Symbol('responseCode'); + + userId = databaseBuilder.factory.buildUser().id; + databaseBuilder.factory.buildAuthenticationMethod.withPoleEmploiAsIdentityProvider({ userId }); + + const organizationId = databaseBuilder.factory.buildOrganization().id; + const tagId = databaseBuilder.factory.buildTag({ name: 'POLE EMPLOI' }).id; + databaseBuilder.factory.buildOrganizationTag({ organizationId, tagId }); + const campaignId = databaseBuilder.factory.buildCampaign({ organizationId }).id; + databaseBuilder.factory.buildCampaignSkill({ campaignId }); + campaignParticipationId = databaseBuilder.factory.buildCampaignParticipation({ campaignId, userId }).id; + databaseBuilder.factory.buildAssessment({ campaignParticipationId, userId }); + const learningContentObjects = learningContentBuilder.fromAreas([]); + mockLearningContent(learningContentObjects); + return databaseBuilder.commit(); + }); + + it('should save success of this notification', async function () { + // given + httpAgentStub.post.resolves({ + isSuccessful: true, + code: responseCode, + data: { + access_token: 'token', + expires_in: new Date(), + refresh_token: 'refresh_token', + }, + }); + + // when + await usecases.sendCompletedParticipationResultsToPoleEmploi({ + campaignParticipationId, + poleEmploiNotifier, + notifierDependencies: { + httpAgent: httpAgentStub, + httpErrorsHelper: httpErrorsHelperStub, + logger: loggerStub, + }, + }); + + // then + const poleEmploiSendings = await knex('pole-emploi-sendings').where({ campaignParticipationId }); + expect(poleEmploiSendings.length).to.equal(1); + expect(poleEmploiSendings[0].responseCode).to.equal(responseCode.toString()); + expect(poleEmploiSendings[0].type).to.equal('CAMPAIGN_PARTICIPATION_COMPLETION'); + }); + + it('should return a disable send notification by default (if push is disabled) ', async function () { + // when + await usecases.sendCompletedParticipationResultsToPoleEmploi({ + campaignParticipationId, + }); + + // then + const poleEmploiSendings = await knex('pole-emploi-sendings').where({ campaignParticipationId }); + expect(poleEmploiSendings.length).to.equal(1); + expect(poleEmploiSendings[0].isSuccessful).to.be.false; + expect(poleEmploiSendings[0].responseCode).to.equal('SENDING-DISABLED'); + expect(poleEmploiSendings[0].type).to.equal('CAMPAIGN_PARTICIPATION_COMPLETION'); + }); +}); diff --git a/api/tests/integration/domain/usecases/send-started-participation-results-to-pole-emploi_test.js b/api/tests/integration/domain/usecases/send-started-participation-results-to-pole-emploi_test.js new file mode 100644 index 00000000000..65b622ebad4 --- /dev/null +++ b/api/tests/integration/domain/usecases/send-started-participation-results-to-pole-emploi_test.js @@ -0,0 +1,80 @@ +import { usecases } from '../../../../lib/domain/usecases/index.js'; +import * as poleEmploiNotifier from '../../../../lib/infrastructure/externals/pole-emploi/pole-emploi-notifier.js'; +import { + databaseBuilder, + expect, + knex, + learningContentBuilder, + mockLearningContent, + sinon, +} from '../../../test-helper.js'; + +describe('Integration | Application | send-started-participation-results-to-pole-emploi', function () { + let campaignParticipationId, userId, responseCode; + let httpAgentStub, httpErrorsHelperStub, loggerStub; + + beforeEach(async function () { + httpAgentStub = { post: sinon.stub() }; + loggerStub = { info: sinon.stub(), error: sinon.stub() }; + httpErrorsHelperStub = { serializeHttpErrorResponse: sinon.stub() }; + responseCode = Symbol('responseCode'); + + userId = databaseBuilder.factory.buildUser().id; + databaseBuilder.factory.buildAuthenticationMethod.withPoleEmploiAsIdentityProvider({ userId }); + + const organizationId = databaseBuilder.factory.buildOrganization().id; + const tagId = databaseBuilder.factory.buildTag({ name: 'POLE EMPLOI' }).id; + databaseBuilder.factory.buildOrganizationTag({ organizationId, tagId }); + const campaignId = databaseBuilder.factory.buildCampaign({ organizationId }).id; + databaseBuilder.factory.buildCampaignSkill({ campaignId }); + campaignParticipationId = databaseBuilder.factory.buildCampaignParticipation({ campaignId, userId }).id; + databaseBuilder.factory.buildAssessment({ campaignParticipationId, userId }); + const learningContentObjects = learningContentBuilder.fromAreas([]); + mockLearningContent(learningContentObjects); + return databaseBuilder.commit(); + }); + + it('should save success of this notification', async function () { + // given + httpAgentStub.post.resolves({ + isSuccessful: true, + code: responseCode, + data: { + access_token: 'token', + expires_in: new Date(), + refresh_token: 'refresh_token', + }, + }); + + // when + await usecases.sendStartedParticipationResultsToPoleEmploi({ + campaignParticipationId, + poleEmploiNotifier, + notifierDependencies: { + httpAgent: httpAgentStub, + httpErrorsHelper: httpErrorsHelperStub, + logger: loggerStub, + }, + }); + + // then + const poleEmploiSendings = await knex('pole-emploi-sendings').where({ campaignParticipationId }); + expect(poleEmploiSendings.length).to.equal(1); + expect(poleEmploiSendings[0].responseCode).to.equal(responseCode.toString()); + expect(poleEmploiSendings[0].type).to.equal('CAMPAIGN_PARTICIPATION_START'); + }); + + it('should return a disable send notification by default (if push is disabled) ', async function () { + // when + await usecases.sendStartedParticipationResultsToPoleEmploi({ + campaignParticipationId, + }); + + // then + const poleEmploiSendings = await knex('pole-emploi-sendings').where({ campaignParticipationId }); + expect(poleEmploiSendings.length).to.equal(1); + expect(poleEmploiSendings[0].isSuccessful).to.be.false; + expect(poleEmploiSendings[0].responseCode).to.equal('SENDING-DISABLED'); + expect(poleEmploiSendings[0].type).to.equal('CAMPAIGN_PARTICIPATION_START'); + }); +}); diff --git a/api/tests/prescription/campaign-participation/integration/application/jobs/participation-completed-job-controller_test.js b/api/tests/prescription/campaign-participation/integration/application/jobs/participation-completed-job-controller_test.js deleted file mode 100644 index ae7f54ecd24..00000000000 --- a/api/tests/prescription/campaign-participation/integration/application/jobs/participation-completed-job-controller_test.js +++ /dev/null @@ -1,76 +0,0 @@ -import * as campaignParticipationRepository from '../../../../../../lib/infrastructure/repositories/campaign-participation-repository.js'; -import * as campaignRepository from '../../../../../../lib/infrastructure/repositories/campaign-repository.js'; -import * as poleEmploiSendingRepository from '../../../../../../lib/infrastructure/repositories/pole-emploi-sending-repository.js'; -import * as targetProfileRepository from '../../../../../../lib/infrastructure/repositories/target-profile-repository.js'; -import * as userRepository from '../../../../../../src/identity-access-management/infrastructure/repositories/user.repository.js'; -import { ParticipationCompletedJobController } from '../../../../../../src/prescription/campaign-participation/application/jobs/participation-completed-job-controller.js'; -import { ParticipationCompletedJob } from '../../../../../../src/prescription/campaign-participation/domain/models/ParticipationCompletedJob.js'; -import * as assessmentRepository from '../../../../../../src/shared/infrastructure/repositories/assessment-repository.js'; -import * as organizationRepository from '../../../../../../src/shared/infrastructure/repositories/organization-repository.js'; -import { - databaseBuilder, - expect, - knex, - learningContentBuilder, - mockLearningContent, - sinon, -} from '../../../../../test-helper.js'; - -describe('Integration | Prescription | Application | Jobs | ParticipationCompletedJobController', function () { - let campaignParticipationId, userId, data, poleEmploiNotifier, responseCode, logger, httpAgent, httpErrorsHelper; - - describe('#handle', function () { - beforeEach(async function () { - logger = sinon.stub(); - httpAgent = sinon.stub(); - httpErrorsHelper = sinon.stub(); - responseCode = Symbol('responseCode'); - poleEmploiNotifier = { notify: sinon.stub().resolves({ isSuccessful: true, code: responseCode }) }; - - userId = databaseBuilder.factory.buildUser().id; - databaseBuilder.factory.buildAuthenticationMethod.withPoleEmploiAsIdentityProvider({ userId }); - const targetProfileId = databaseBuilder.factory.buildTargetProfile().id; - - const organizationId = databaseBuilder.factory.buildOrganization().id; - const tagId = databaseBuilder.factory.buildTag({ name: 'POLE EMPLOI' }).id; - databaseBuilder.factory.buildOrganizationTag({ organizationId, tagId }); - const campaignId = databaseBuilder.factory.buildCampaign({ targetProfileId, organizationId }).id; - campaignParticipationId = databaseBuilder.factory.buildCampaignParticipation({ campaignId, userId }).id; - databaseBuilder.factory.buildAssessment({ campaignParticipationId, userId }); - data = new ParticipationCompletedJob({ campaignParticipationId }); - - const learningContentObjects = learningContentBuilder.fromAreas([]); - mockLearningContent(learningContentObjects); - - return databaseBuilder.commit(); - }); - - it('should notify pole emploi and save success of this notification', async function () { - // when - const campaignParticipationCompletedJobController = new ParticipationCompletedJobController(); - - await campaignParticipationCompletedJobController.handle({ - data, - dependencies: { - assessmentRepository, - campaignRepository, - campaignParticipationRepository, - organizationRepository, - poleEmploiSendingRepository, - targetProfileRepository, - userRepository, - poleEmploiNotifier, - httpErrorsHelper, - logger, - httpAgent, - }, - }); - - // then - const poleEmploiSendings = await knex('pole-emploi-sendings').where({ campaignParticipationId }); - expect(poleEmploiSendings.length).to.equal(1); - expect(poleEmploiSendings[0].responseCode).to.equal(responseCode.toString()); - expect(poleEmploiSendings[0].type).to.equal('CAMPAIGN_PARTICIPATION_COMPLETION'); - }); - }); -}); diff --git a/api/tests/prescription/campaign-participation/integration/application/jobs/participation-started-job-controller_test.js b/api/tests/prescription/campaign-participation/integration/application/jobs/participation-started-job-controller_test.js deleted file mode 100644 index be9d9aecaf9..00000000000 --- a/api/tests/prescription/campaign-participation/integration/application/jobs/participation-started-job-controller_test.js +++ /dev/null @@ -1,76 +0,0 @@ -import * as campaignParticipationRepository from '../../../../../../lib/infrastructure/repositories/campaign-participation-repository.js'; -import * as campaignRepository from '../../../../../../lib/infrastructure/repositories/campaign-repository.js'; -import * as poleEmploiSendingRepository from '../../../../../../lib/infrastructure/repositories/pole-emploi-sending-repository.js'; -import * as targetProfileRepository from '../../../../../../lib/infrastructure/repositories/target-profile-repository.js'; -import * as userRepository from '../../../../../../src/identity-access-management/infrastructure/repositories/user.repository.js'; -import { ParticipationStartedJobController } from '../../../../../../src/prescription/campaign-participation/application/jobs/participation-started-job-controller.js'; -import { ParticipationStartedJob } from '../../../../../../src/prescription/campaign-participation/domain/models/ParticipationStartedJob.js'; -import * as assessmentRepository from '../../../../../../src/shared/infrastructure/repositories/assessment-repository.js'; -import * as organizationRepository from '../../../../../../src/shared/infrastructure/repositories/organization-repository.js'; -import { - databaseBuilder, - expect, - knex, - learningContentBuilder, - mockLearningContent, - sinon, -} from '../../../../../test-helper.js'; - -describe('Integration | Application | pole-emploi-participation-started-job-controller', function () { - let campaignParticipationId, userId, poleEmploiNotifier, responseCode, data, logger, httpAgent, httpErrorsHelper; - - describe('#handle', function () { - beforeEach(async function () { - logger = sinon.stub(); - httpAgent = sinon.stub(); - httpErrorsHelper = sinon.stub(); - responseCode = Symbol('responseCode'); - poleEmploiNotifier = { notify: sinon.stub().resolves({ isSuccessful: true, code: responseCode }) }; - - userId = databaseBuilder.factory.buildUser().id; - databaseBuilder.factory.buildAuthenticationMethod.withPoleEmploiAsIdentityProvider({ userId }); - const targetProfileId = databaseBuilder.factory.buildTargetProfile().id; - - const organizationId = databaseBuilder.factory.buildOrganization().id; - const tagId = databaseBuilder.factory.buildTag({ name: 'POLE EMPLOI' }).id; - databaseBuilder.factory.buildOrganizationTag({ organizationId, tagId }); - const campaignId = databaseBuilder.factory.buildCampaign({ targetProfileId, organizationId }).id; - campaignParticipationId = databaseBuilder.factory.buildCampaignParticipation({ campaignId, userId }).id; - databaseBuilder.factory.buildAssessment({ campaignParticipationId, userId }); - - data = new ParticipationStartedJob({ campaignParticipationId }); - - const learningContentObjects = learningContentBuilder.fromAreas([]); - mockLearningContent(learningContentObjects); - - return databaseBuilder.commit(); - }); - - it('should notify pole emploi and save success of this notification', async function () { - // when - const handler = new ParticipationStartedJobController(); - await handler.handle({ - data, - dependencies: { - assessmentRepository, - campaignRepository, - campaignParticipationRepository, - organizationRepository, - poleEmploiSendingRepository, - targetProfileRepository, - userRepository, - poleEmploiNotifier, - httpErrorsHelper, - logger, - httpAgent, - }, - }); - - // then - const poleEmploiSendings = await knex('pole-emploi-sendings').where({ campaignParticipationId }); - expect(poleEmploiSendings.length).to.equal(1); - expect(poleEmploiSendings[0].responseCode).to.equal(responseCode.toString()); - expect(poleEmploiSendings[0].type).to.equal('CAMPAIGN_PARTICIPATION_START'); - }); - }); -}); diff --git a/api/tests/prescription/campaign-participation/unit/application/jobs/participation-completed-job-controller_test.js b/api/tests/prescription/campaign-participation/unit/application/jobs/participation-completed-job-controller_test.js index 262ed88f81a..206a9ae3391 100644 --- a/api/tests/prescription/campaign-participation/unit/application/jobs/participation-completed-job-controller_test.js +++ b/api/tests/prescription/campaign-participation/unit/application/jobs/participation-completed-job-controller_test.js @@ -1,220 +1,24 @@ -import { PoleEmploiPayload } from '../../../../../../lib/infrastructure/externals/pole-emploi/PoleEmploiPayload.js'; +import { usecases } from '../../../../../../lib/domain/usecases/index.js'; import { ParticipationCompletedJobController } from '../../../../../../src/prescription/campaign-participation/application/jobs/participation-completed-job-controller.js'; -import { ParticipationCompletedJob } from '../../../../../../src/prescription/campaign-participation/domain/models/ParticipationCompletedJob.js'; -import { PoleEmploiSending } from '../../../../../../src/shared/domain/models/PoleEmploiSending.js'; -import { domainBuilder, expect, sinon } from '../../../../../test-helper.js'; - -describe('Unit | Prescription | Application | Jobs | ParticipationCompletedJobController', function () { - context('#handle', function () { - let data, dependencies, expectedResults; - let campaignId, userId, organizationId, assessmentId; - let campaignParticipationCompletedJobController; - let httpAgent, logger, httpErrorsHelper; - let assessmentRepository, - campaignRepository, - campaignParticipationRepository, - organizationRepository, - targetProfileRepository, - userRepository, - poleEmploiNotifier, - poleEmploiSendingRepository, - authenticationMethodRepository; - - beforeEach(function () { - campaignId = Symbol('campaignId'); - userId = Symbol('userId'); - organizationId = Symbol('organizationId'); - assessmentId = Symbol('assessmentId'); - - httpAgent = sinon.stub(); - logger = sinon.stub(); - httpErrorsHelper = sinon.stub(); - assessmentRepository = { get: sinon.stub() }; - campaignRepository = { get: sinon.stub() }; - campaignParticipationRepository = { get: sinon.stub() }; - organizationRepository = { get: sinon.stub() }; - targetProfileRepository = { get: sinon.stub() }; - userRepository = { get: sinon.stub() }; - poleEmploiNotifier = { notify: sinon.stub() }; - poleEmploiSendingRepository = { create: sinon.stub() }; - authenticationMethodRepository = { - findOneByUserIdAndIdentityProvider: sinon.stub(), - updateAuthenticationComplementByUserIdAndIdentityProvider: sinon.stub(), +import { expect, sinon } from '../../../../../test-helper.js'; + +describe('Unit | Prescription | Application | Jobs | participationCompletedJobController', function () { + describe('#handle', function () { + it('should call usecase', async function () { + sinon.stub(usecases, 'sendCompletedParticipationResultsToPoleEmploi'); + // given + const handler = new ParticipationCompletedJobController(); + const data = { + campaignParticipationId: Symbol('campaignParticipationId'), }; - campaignParticipationCompletedJobController = new ParticipationCompletedJobController(); - - dependencies = { - assessmentRepository, - campaignRepository, - campaignParticipationRepository, - organizationRepository, - targetProfileRepository, - userRepository, - poleEmploiNotifier, - poleEmploiSendingRepository, - authenticationMethodRepository, - httpErrorsHelper, - httpAgent, - logger, - }; - - expectedResults = new PoleEmploiPayload({ - campagne: { - nom: 'Campagne Pôle Emploi', - dateDebut: new Date('2020-01-01'), - dateFin: new Date('2020-02-01'), - type: 'EVALUATION', - codeCampagne: 'CODEPE123', - urlCampagne: 'https://app.pix.fr/campagnes/CODEPE123', - nomOrganisme: 'Pix', - typeOrganisme: 'externe', - }, - individu: { - nom: 'Bonneau', - prenom: 'Jean', - }, - test: { - etat: 3, - progression: 100, - typeTest: 'DI', - referenceExterne: 55667788, - dateDebut: new Date('2020-01-02'), - dateProgression: new Date('2020-01-03'), - dateValidation: null, - evaluation: null, - uniteEvaluation: 'A', - elementsEvalues: [], - }, - }); - }); - - context('when campaign is of type ASSESSMENT and organization is Pole Emploi', function () { - beforeEach(function () { - const campaign = domainBuilder.buildCampaign({ - id: campaignId, - name: 'Campagne Pôle Emploi', - code: 'CODEPE123', - createdAt: new Date('2020-01-01'), - archivedAt: new Date('2020-02-01'), - type: 'ASSESSMENT', - targetProfile: { id: 'targetProfileId1' }, - organization: { id: organizationId }, - }); - const campaignParticipation = domainBuilder.buildCampaignParticipation({ - id: 55667788, - userId, - campaign, - assessments: [domainBuilder.buildAssessment({ id: assessmentId })], - createdAt: new Date('2020-01-02'), - }); - data = new ParticipationCompletedJob({ - campaignParticipationId: campaignParticipation.id, - }); - - campaignParticipationRepository.get.withArgs(campaignParticipation.id).resolves(campaignParticipation); - assessmentRepository.get.withArgs(assessmentId).resolves( - domainBuilder.buildAssessment({ - updatedAt: new Date('2020-01-03'), - }), - ); - organizationRepository.get.withArgs(organizationId).resolves({ isPoleEmploi: true }); - userRepository.get - .withArgs(userId) - .resolves(domainBuilder.buildUser({ id: userId, firstName: 'Jean', lastName: 'Bonneau' })); - campaignRepository.get.withArgs(campaignId).resolves(campaign); - targetProfileRepository.get.withArgs('targetProfileId1').resolves({ name: 'Diagnostic initial' }); - }); - - it('should notify pole emploi and create pole emploi sending accordingly', async function () { - // given - const expectedResponse = { isSuccessful: 'someValue', code: 'someCode' }; - poleEmploiNotifier.notify - .withArgs(userId, expectedResults, { - authenticationMethodRepository, - httpErrorsHelper, - httpAgent, - logger, - }) - .resolves(expectedResponse); - const poleEmploiSending = Symbol('Pole emploi sending'); - - sinon - .stub(PoleEmploiSending, 'buildForParticipationFinished') - .withArgs({ - campaignParticipationId: 55667788, - payload: expectedResults.toString(), - isSuccessful: expectedResponse.isSuccessful, - responseCode: expectedResponse.code, - }) - .returns(poleEmploiSending); - - // when - await campaignParticipationCompletedJobController.handle({ data, dependencies }); - - // then - expect(poleEmploiSendingRepository.create).to.have.been.calledWithExactly({ poleEmploiSending }); - }); - }); - - context('when campaign is of type ASSESSMENT but organization is not Pole Emploi', function () { - beforeEach(function () { - const campaign = domainBuilder.buildCampaign({ - id: campaignId, - type: 'ASSESSMENT', - organization: { id: organizationId }, - }); - const campaignParticipation = domainBuilder.buildCampaignParticipation({ - id: 55667788, - userId, - campaign, - createdAt: new Date('2020-01-02'), - }); - data = new ParticipationCompletedJob({ - campaignParticipationId: campaignParticipation.id, - }); - - campaignParticipationRepository.get.withArgs(campaignParticipation.id).resolves(campaignParticipation); - campaignRepository.get.withArgs(campaignId).resolves(domainBuilder.buildCampaign(campaign)); - organizationRepository.get.withArgs(organizationId).resolves({ isPoleEmploi: false }); - }); - - it('should not notify to Pole Emploi', async function () { - // when - await campaignParticipationCompletedJobController.handle({ data, dependencies }); - - // then - sinon.assert.notCalled(poleEmploiNotifier.notify); - }); - }); - - context('when organization is Pole Emploi but campaign is of type PROFILES_COLLECTION', function () { - beforeEach(function () { - const campaign = domainBuilder.buildCampaign({ - id: campaignId, - type: 'PROFILES_COLLECTION', - organization: { id: organizationId }, - }); - const campaignParticipation = domainBuilder.buildCampaignParticipation({ - id: 55667788, - userId, - campaign, - createdAt: new Date('2020-01-02'), - }); - data = new ParticipationCompletedJob({ - campaignParticipationId: campaignParticipation.id, - }); - - campaignParticipationRepository.get.withArgs(campaignParticipation.id).resolves(campaignParticipation); - campaignRepository.get.withArgs(campaignId).resolves(domainBuilder.buildCampaign(campaign)); - organizationRepository.get.withArgs(organizationId).resolves({ isPoleEmploi: true }); - }); - it('should not notify to Pole Emploi', async function () { - // when - await campaignParticipationCompletedJobController.handle({ data, dependencies }); + // when + await handler.handle({ data }); - // then - sinon.assert.notCalled(poleEmploiNotifier.notify); + // then + expect(usecases.sendCompletedParticipationResultsToPoleEmploi).to.have.been.calledOnce; + expect(usecases.sendCompletedParticipationResultsToPoleEmploi).to.have.been.calledWithExactly({ + campaignParticipationId: data.campaignParticipationId, }); }); }); diff --git a/api/tests/prescription/campaign-participation/unit/application/jobs/participation-started-job-controller_test.js b/api/tests/prescription/campaign-participation/unit/application/jobs/participation-started-job-controller_test.js index 5d10287e39f..c14b87797dc 100644 --- a/api/tests/prescription/campaign-participation/unit/application/jobs/participation-started-job-controller_test.js +++ b/api/tests/prescription/campaign-participation/unit/application/jobs/participation-started-job-controller_test.js @@ -1,227 +1,24 @@ -import { PoleEmploiPayload } from '../../../../../../lib/infrastructure/externals/pole-emploi/PoleEmploiPayload.js'; +import { usecases } from '../../../../../../lib/domain/usecases/index.js'; import { ParticipationStartedJobController } from '../../../../../../src/prescription/campaign-participation/application/jobs/participation-started-job-controller.js'; -import { ParticipationStartedJob } from '../../../../../../src/prescription/campaign-participation/domain/models/ParticipationStartedJob.js'; -import { PoleEmploiSending } from '../../../../../../src/shared/domain/models/PoleEmploiSending.js'; -import { catchErr, domainBuilder, expect, sinon } from '../../../../../test-helper.js'; +import { expect, sinon } from '../../../../../test-helper.js'; describe('Unit | Application | Controller | Jobs | participation-started-controller', function () { - let data, dependencies, expectedResults; - let httpAgent, - httpErrorsHelper, - logger, - campaignRepository, - campaignParticipationRepository, - organizationRepository, - targetProfileRepository, - userRepository, - poleEmploiNotifier, - poleEmploiSendingRepository, - authenticationMethodRepository; - - beforeEach(function () { - authenticationMethodRepository = { - findOneByUserIdAndIdentityProvider: sinon.stub(), - updateAuthenticationComplementByUserIdAndIdentityProvider: sinon.stub(), - }; - campaignRepository = { get: sinon.stub() }; - campaignParticipationRepository = { get: sinon.stub() }; - organizationRepository = { get: sinon.stub() }; - targetProfileRepository = { get: sinon.stub() }; - userRepository = { get: sinon.stub() }; - poleEmploiNotifier = { notify: sinon.stub() }; - poleEmploiSendingRepository = { create: sinon.stub() }; - - httpAgent = Symbol('httpAgent'); - logger = Symbol('logger'); - httpErrorsHelper = Symbol('httpErrorsHelper'); - - dependencies = { - authenticationMethodRepository, - campaignRepository, - campaignParticipationRepository, - organizationRepository, - poleEmploiSendingRepository, - targetProfileRepository, - userRepository, - poleEmploiNotifier, - httpAgent, - logger, - httpErrorsHelper, - }; - - expectedResults = new PoleEmploiPayload({ - campagne: { - nom: 'Campagne Pôle Emploi', - dateDebut: new Date('2020-01-01'), - dateFin: new Date('2020-02-01'), - type: 'EVALUATION', - codeCampagne: 'CODEPE123', - urlCampagne: 'https://app.pix.fr/campagnes/CODEPE123', - nomOrganisme: 'Pix', - typeOrganisme: 'externe', - }, - individu: { - nom: 'Bonneau', - prenom: 'Jean', - }, - test: { - etat: 2, - progression: 0, - typeTest: 'DI', - referenceExterne: 55667788, - dateDebut: new Date('2020-01-02'), - dateProgression: null, - dateValidation: null, - evaluation: null, - uniteEvaluation: 'A', - elementsEvalues: [], - }, - }); - }); - - it('fails when data is not of correct type', async function () { - // given - const data = 'not an data of the correct type'; - // when / then - const handler = new ParticipationStartedJobController(); - - const error = await catchErr(handler.handle)(data, { ...dependencies }); - - // then - expect(error).not.to.be.null; - }); - - context('#ParticipationStarted', function () { - let campaignParticipationId, campaignId, userId, organizationId; - - beforeEach(function () { - campaignParticipationId = 55667788; - campaignId = Symbol('campaignId'); - userId = Symbol('userId'); - organizationId = Symbol('organizationId'); - }); - - context('when campaign is of type ASSESSMENT and organization is Pole Emploi', function () { - beforeEach(function () { - const campaign = domainBuilder.buildCampaign({ - id: campaignId, - name: 'Campagne Pôle Emploi', - code: 'CODEPE123', - createdAt: new Date('2020-01-01'), - archivedAt: new Date('2020-02-01'), - type: 'ASSESSMENT', - targetProfile: { id: 'targetProfileId1' }, - organization: { id: organizationId }, - }); - const campaignParticipation = domainBuilder.buildCampaignParticipation({ - id: campaignParticipationId, - userId, - campaign, - createdAt: new Date('2020-01-02'), - }); - - campaignParticipationRepository.get.withArgs(campaignParticipationId).resolves(campaignParticipation); - campaignRepository.get.withArgs(campaignId).resolves(campaign); - organizationRepository.get.withArgs(organizationId).resolves({ isPoleEmploi: true }); - userRepository.get - .withArgs(userId) - .resolves(domainBuilder.buildUser({ id: userId, firstName: 'Jean', lastName: 'Bonneau' })); - targetProfileRepository.get.withArgs('targetProfileId1').resolves({ name: 'Diagnostic initial' }); - - data = new ParticipationStartedJob({ campaignParticipationId }); - }); - - it('should notify pole emploi and create pole emploi sending accordingly', async function () { - // given - const expectedResponse = { isSuccessful: 'someValue', code: 'someCode' }; - poleEmploiNotifier.notify - .withArgs(userId, expectedResults, { - authenticationMethodRepository, - httpAgent, - httpErrorsHelper, - logger, - }) - .resolves(expectedResponse); - const poleEmploiSending = Symbol('Pole emploi sending'); - sinon - .stub(PoleEmploiSending, 'buildForParticipationStarted') - .withArgs({ - campaignParticipationId, - payload: expectedResults.toString(), - isSuccessful: expectedResponse.isSuccessful, - responseCode: expectedResponse.code, - }) - .returns(poleEmploiSending); - - // when - const handler = new ParticipationStartedJobController(); - - await handler.handle({ data, dependencies }); - // then - expect(poleEmploiSendingRepository.create).to.have.been.calledWithExactly({ poleEmploiSending }); - }); - }); - - context('when campaign is of type ASSESSMENT but organization is not Pole Emploi', function () { - beforeEach(function () { - const campaign = domainBuilder.buildCampaign({ - id: campaignId, - type: 'ASSESSMENT', - organization: { id: organizationId }, - }); - const campaignParticipation = domainBuilder.buildCampaignParticipation({ - id: campaignParticipationId, - userId, - campaign, - createdAt: new Date('2020-01-02'), - }); - - campaignParticipationRepository.get.withArgs(campaignParticipationId).resolves(campaignParticipation); - campaignRepository.get.withArgs(campaignId).resolves(campaign); - organizationRepository.get.withArgs(organizationId).resolves({ isPoleEmploi: false }); - - data = new ParticipationStartedJob({ campaignParticipationId }); - }); - - it('should not notify to Pole Emploi', async function () { - // when - const handler = new ParticipationStartedJobController(); - - await handler.handle({ data, dependencies }); - - // then - sinon.assert.notCalled(poleEmploiNotifier.notify); - }); - }); - - context('when organization is Pole Emploi but campaign is of type PROFILES_COLLECTION', function () { - beforeEach(function () { - const campaign = domainBuilder.buildCampaign({ - id: campaignId, - type: 'PROFILES_COLLECTION', - organization: { id: organizationId }, - }); - const campaignParticipation = domainBuilder.buildCampaignParticipation({ - id: campaignParticipationId, - userId, - campaign, - createdAt: new Date('2020-01-02'), - }); - - campaignParticipationRepository.get.withArgs(campaignParticipationId).resolves(campaignParticipation); - campaignRepository.get.withArgs(campaignId).resolves(campaign); - organizationRepository.get.withArgs(organizationId).resolves({ isPoleEmploi: true }); - - data = new ParticipationStartedJob({ campaignParticipationId }); - }); - - it('should not notify to Pole Emploi', async function () { - // when - const handler = new ParticipationStartedJobController(); - - await handler.handle({ data, dependencies }); - - sinon.assert.notCalled(poleEmploiNotifier.notify); + describe('#handle', function () { + it('should call usecase', async function () { + sinon.stub(usecases, 'sendSharedParticipationResultsToPoleEmploi'); + // given + const handler = new ParticipationStartedJobController(); + const data = { + campaignParticipationId: Symbol('campaignParticipationId'), + }; + + // when + await handler.handle({ data }); + + // then + expect(usecases.sendSharedParticipationResultsToPoleEmploi).to.have.been.calledOnce; + expect(usecases.sendSharedParticipationResultsToPoleEmploi).to.have.been.calledWithExactly({ + campaignParticipationId: data.campaignParticipationId, }); }); });