From 47d5fcf047ff39da093d2e7ad6bc30d21bf040da Mon Sep 17 00:00:00 2001 From: Alexandre Monney Date: Thu, 14 Nov 2024 16:22:05 +0100 Subject: [PATCH] fix(api): reassign campaignParticipation getter in Eligibility object --- ...uest-results-for-campaign-participation.js | 12 +++-- ...results-for-campaign-participation_test.js | 48 +++++++++++++++++++ 2 files changed, 55 insertions(+), 5 deletions(-) diff --git a/api/src/quest/domain/usecases/get-quest-results-for-campaign-participation.js b/api/src/quest/domain/usecases/get-quest-results-for-campaign-participation.js index 30c89b5ca6e..daa3eb1d964 100644 --- a/api/src/quest/domain/usecases/get-quest-results-for-campaign-participation.js +++ b/api/src/quest/domain/usecases/get-quest-results-for-campaign-participation.js @@ -16,11 +16,13 @@ export const getQuestResultsForCampaignParticipation = async ({ if (!eligibility) return []; - eligibility.campaignParticipations.targetProfileIds = [ - // getTargetProfileForCampaignParticipation returns null but this usecase is used for campaign participation result page for now, so the campaign participation ID always exists - // if this usecase is to be used in another context, the edge case must be handled - eligibility.getTargetProfileForCampaignParticipation(campaignParticipationId), - ]; + /* + This effectively overrides the existing campaignParticipations property with a new getter that always returns the updated targetProfileIds array based on the provided campaignParticipationId. + We can't just reassign the getter with the new value, because the getter will still be called and the new value would be ignored + */ + Object.defineProperty(eligibility, 'campaignParticipations', { + get: () => ({ targetProfileIds: [eligibility.getTargetProfileForCampaignParticipation(campaignParticipationId)] }), + }); const questResults = []; for (const quest of quests) { diff --git a/api/tests/quest/integration/domain/usecases/get-quest-results-for-campaign-participation_test.js b/api/tests/quest/integration/domain/usecases/get-quest-results-for-campaign-participation_test.js index 8878a43969f..a520065e220 100644 --- a/api/tests/quest/integration/domain/usecases/get-quest-results-for-campaign-participation_test.js +++ b/api/tests/quest/integration/domain/usecases/get-quest-results-for-campaign-participation_test.js @@ -35,4 +35,52 @@ describe('Quest | Integration | Domain | Usecases | getQuestResultsForCampaignPa expect(result[0].id).to.equal(questId); expect(result[0].reward.id).to.equal(rewardId); }); + + it('should not return quest results for other campaign participation', async function () { + const organizationId = databaseBuilder.factory.buildOrganization({ type: 'SCO' }).id; + const { id: organizationLearnerId, userId } = databaseBuilder.factory.buildOrganizationLearner({ organizationId }); + + const { id: notEligibleParticipationId } = databaseBuilder.factory.buildCampaignParticipation({ + organizationLearnerId, + userId, + }); + const targetProfileId = databaseBuilder.factory.buildTargetProfile({ ownerOrganizationId: organizationId }).id; + const campaignId = databaseBuilder.factory.buildCampaign({ organizationId, targetProfileId }).id; + databaseBuilder.factory.buildCampaignParticipation({ + organizationLearnerId, + campaignId, + userId, + }); + const rewardId = databaseBuilder.factory.buildAttestation().id; + databaseBuilder.factory.buildQuest({ + rewardType: 'attestations', + rewardId, + eligibilityRequirements: [ + { + type: 'organization', + data: { + type: 'SCO', + }, + comparison: COMPARISON.ALL, + }, + { + type: 'campaignParticipations', + data: { + targetProfileIds: [targetProfileId], + }, + comparison: COMPARISON.ALL, + }, + ], + successRequirements: [], + }).id; + + await databaseBuilder.commit(); + + const result = await usecases.getQuestResultsForCampaignParticipation({ + userId, + campaignParticipationId: notEligibleParticipationId, + }); + + expect(result).to.be.empty; + }); });