diff --git a/api/lib/domain/usecases/get-assessment.js b/api/lib/domain/usecases/get-assessment.js index a5e9439a000..378d46e38f2 100644 --- a/api/lib/domain/usecases/get-assessment.js +++ b/api/lib/domain/usecases/get-assessment.js @@ -1,7 +1,7 @@ import { NotFoundError } from '../../../src/shared/domain/errors.js'; import { Assessment } from '../../../src/shared/domain/models/index.js'; -const getAssessment = async function ({ +export async function getAssessment({ assessmentId, locale, assessmentRepository, @@ -12,42 +12,73 @@ const getAssessment = async function ({ certificationCompanionAlertRepository, }) { const assessment = await assessmentRepository.getWithAnswers(assessmentId); + switch (assessment.type) { + case Assessment.types.CERTIFICATION: { + await _addCertificationRelatedAttributes({ + assessment, + certificationChallengeLiveAlertRepository, + certificationCompanionAlertRepository, + }); + assessment.showProgressBar = false; + assessment.hasCheckpoints = false; + assessment.showLevelup = false; + assessment.title = assessment.certificationCourseId; + break; + } - assessment.title = await _fetchAssessmentTitle({ - assessment, - locale, - competenceRepository, - courseRepository, - campaignRepository, - }); - - await _addCampaignRelatedAttributes(assessment, campaignRepository); - await _addDemoRelatedAttributes(assessment, courseRepository); - await _addCertificationRelatedAttributes({ - assessment, - certificationChallengeLiveAlertRepository, - certificationCompanionAlertRepository, - }); - return assessment; -}; - -export { getAssessment }; + case Assessment.types.COMPETENCE_EVALUATION: { + assessment.showProgressBar = true; + assessment.hasCheckpoints = true; + assessment.showLevelup = true; + assessment.title = await competenceRepository.getCompetenceName({ id: assessment.competenceId, locale }); + break; + } -async function _addCampaignRelatedAttributes(assessment, campaignRepository) { - if (assessment.type === Assessment.types.CAMPAIGN) { - assessment.campaignCode = await campaignRepository.getCampaignCodeByCampaignParticipationId( - assessment.campaignParticipationId, - ); - } -} + case Assessment.types.DEMO: { + const course = await courseRepository.get(assessment.courseId); + if (!course.canBePlayed) { + throw new NotFoundError("Le test demandé n'existe pas"); + } + assessment.showProgressBar = true; + assessment.hasCheckpoints = false; + assessment.showLevelup = false; + assessment.title = await courseRepository.getCourseName(assessment.courseId); + break; + } + case Assessment.types.PREVIEW: { + assessment.showProgressBar = false; + assessment.hasCheckpoints = false; + assessment.showLevelup = false; + assessment.title = 'Preview'; + break; + } + case Assessment.types.CAMPAIGN: { + const campaignId = await campaignRepository.getCampaignIdByCampaignParticipationId( + assessment.campaignParticipationId, + ); + const campaign = await campaignRepository.get(campaignId); + assessment.campaignCode = campaign.code; + assessment.showProgressBar = false; + assessment.hasCheckpoints = false; + assessment.showLevelup = false; + if (!assessment.isFlash() && (campaign.isAssessment() || campaign.isExam())) { + assessment.showProgressBar = true; + assessment.hasCheckpoints = true; + assessment.showLevelup = true; + } + assessment.title = campaign.title; + break; + } -async function _addDemoRelatedAttributes(assessment, courseRepository) { - if (assessment.type === Assessment.types.DEMO) { - const course = await courseRepository.get(assessment.courseId); - if (!course.canBePlayed) { - throw new NotFoundError("Le test demandé n'existe pas"); + default: { + assessment.showProgressBar = false; + assessment.hasCheckpoints = false; + assessment.showLevelup = false; + assessment.title = ''; } } + + return assessment; } async function _addCertificationRelatedAttributes({ @@ -68,28 +99,3 @@ async function _addCertificationRelatedAttributes({ assessment.attachLiveAlerts({ challengeLiveAlerts, companionLiveAlerts }); } - -function _fetchAssessmentTitle({ assessment, locale, competenceRepository, courseRepository, campaignRepository }) { - switch (assessment.type) { - case Assessment.types.CERTIFICATION: { - return assessment.certificationCourseId; - } - - case Assessment.types.COMPETENCE_EVALUATION: { - return competenceRepository.getCompetenceName({ id: assessment.competenceId, locale }); - } - - case Assessment.types.DEMO: { - return courseRepository.getCourseName(assessment.courseId); - } - case Assessment.types.PREVIEW: { - return 'Preview'; - } - case Assessment.types.CAMPAIGN: { - return campaignRepository.getCampaignTitleByCampaignParticipationId(assessment.campaignParticipationId); - } - - default: - return ''; - } -} diff --git a/api/src/prescription/campaign/infrastructure/repositories/campaign-repository.js b/api/src/prescription/campaign/infrastructure/repositories/campaign-repository.js index 496f7ceeb28..89a485fbf4a 100644 --- a/api/src/prescription/campaign/infrastructure/repositories/campaign-repository.js +++ b/api/src/prescription/campaign/infrastructure/repositories/campaign-repository.js @@ -57,28 +57,6 @@ const checkIfUserOrganizationHasAccessToCampaign = async function (campaignId, u return Boolean(campaign); }; -const getCampaignTitleByCampaignParticipationId = async function (campaignParticipationId) { - const campaign = await knex('campaigns') - .select('title') - .join('campaign-participations', 'campaign-participations.campaignId', 'campaigns.id') - .where({ 'campaign-participations.id': campaignParticipationId }) - .first(); - - if (!campaign) return null; - return campaign.title; -}; - -const getCampaignCodeByCampaignParticipationId = async function (campaignParticipationId) { - const campaign = await knex('campaigns') - .select('code') - .join('campaign-participations', 'campaign-participations.campaignId', 'campaigns.id') - .where({ 'campaign-participations.id': campaignParticipationId }) - .first(); - - if (!campaign) return null; - return campaign.code; -}; - const getCampaignIdByCampaignParticipationId = async function (campaignParticipationId) { const knexConn = DomainTransaction.getConnection(); const campaign = await knexConn('campaigns') @@ -143,9 +121,7 @@ export { findTubes, get, getByCode, - getCampaignCodeByCampaignParticipationId, getCampaignIdByCampaignParticipationId, - getCampaignTitleByCampaignParticipationId, }; async function _findSkills({ campaignId, filterByStatus = 'operative' }) { diff --git a/api/src/shared/domain/models/Assessment.js b/api/src/shared/domain/models/Assessment.js index f0860709ed6..5f97afa1355 100644 --- a/api/src/shared/domain/models/Assessment.js +++ b/api/src/shared/domain/models/Assessment.js @@ -91,6 +91,9 @@ class Assessment { this.campaignCode = campaignCode; this.challengeLiveAlerts = challengeLiveAlerts; this.companionLiveAlerts = companionLiveAlerts; + this.showProgressBar = null; + this.hasCheckpoints = null; + this.showLevelup = null; } isCompleted() { diff --git a/api/src/shared/domain/models/Campaign.js b/api/src/shared/domain/models/Campaign.js index c44e7c9f939..9096167ee6d 100644 --- a/api/src/shared/domain/models/Campaign.js +++ b/api/src/shared/domain/models/Campaign.js @@ -69,6 +69,10 @@ class Campaign { return this.type === CampaignTypes.ASSESSMENT; } + isExam() { + return this.type === CampaignTypes.EXAM; + } + isProfilesCollection() { return this.type === CampaignTypes.PROFILES_COLLECTION; } diff --git a/api/src/shared/infrastructure/repositories/assessment-repository.js b/api/src/shared/infrastructure/repositories/assessment-repository.js index a054b5a61a6..1242658d7da 100644 --- a/api/src/shared/infrastructure/repositories/assessment-repository.js +++ b/api/src/shared/infrastructure/repositories/assessment-repository.js @@ -184,5 +184,8 @@ function _adaptModelToDb(assessment) { 'campaignCode', 'challengeLiveAlerts', 'companionLiveAlerts', + 'showProgressBar', + 'hasCheckpoints', + 'showLevelup', ]); } diff --git a/api/src/shared/infrastructure/serializers/jsonapi/assessment-serializer.js b/api/src/shared/infrastructure/serializers/jsonapi/assessment-serializer.js index 9e32dd2c28f..22a1fea2129 100644 --- a/api/src/shared/infrastructure/serializers/jsonapi/assessment-serializer.js +++ b/api/src/shared/infrastructure/serializers/jsonapi/assessment-serializer.js @@ -21,15 +21,13 @@ const serialize = function (assessments) { } // Same here for isForCampaign() and isCompetenceEvaluation() - if ([Assessment.types.CAMPAIGN, Assessment.types.COMPETENCE_EVALUATION].includes(currentAssessment.type)) { + if (currentAssessment.hasCheckpoints) { assessment.progression = { id: Progression.generateIdFromAssessmentId(currentAssessment.id), }; } - if (currentAssessment.type === Assessment.types.CAMPAIGN) { - assessment.codeCampaign = currentAssessment.campaignCode; - } + assessment.codeCampaign = currentAssessment.campaignCode; if (!currentAssessment.course) { assessment.course = { id: currentAssessment.courseId }; @@ -52,6 +50,9 @@ const serialize = function (assessments) { 'competenceId', 'lastQuestionState', 'method', + 'showProgressBar', + 'hasCheckpoints', + 'showLevelup', ], answers: { ref: 'id', diff --git a/api/tests/prescription/campaign/integration/infrastructure/repositories/campaign-repository_test.js b/api/tests/prescription/campaign/integration/infrastructure/repositories/campaign-repository_test.js index ba5491490fb..2f51b2c473a 100644 --- a/api/tests/prescription/campaign/integration/infrastructure/repositories/campaign-repository_test.js +++ b/api/tests/prescription/campaign/integration/infrastructure/repositories/campaign-repository_test.js @@ -306,101 +306,6 @@ describe('Integration | Repository | Campaign', function () { }); }); - describe('#getCampaignTitleByCampaignParticipationId', function () { - it('should return campaign title when campaign has one', async function () { - // given - const campaignId = databaseBuilder.factory.buildCampaign({ title: 'Parcours trop bien' }).id; - const campaignParticipationId = databaseBuilder.factory.buildCampaignParticipation({ campaignId }).id; - await databaseBuilder.commit(); - - // when - const title = await campaignRepository.getCampaignTitleByCampaignParticipationId(campaignParticipationId); - - // then - expect(title).to.equal('Parcours trop bien'); - }); - - it('should return null when campaign has no title', async function () { - // given - const campaignId = databaseBuilder.factory.buildCampaign({ title: null }).id; - const campaignParticipationId = databaseBuilder.factory.buildCampaignParticipation({ campaignId }).id; - await databaseBuilder.commit(); - - // when - const title = await campaignRepository.getCampaignTitleByCampaignParticipationId(campaignParticipationId); - - // then - expect(title).to.be.null; - }); - - it('should return null when campaignParticipationId does not exist', async function () { - // when - const title = await campaignRepository.getCampaignTitleByCampaignParticipationId(123); - - // then - expect(title).to.be.null; - }); - - it('should return the title from the given campaignParticipationId', async function () { - // given - const campaignId = databaseBuilder.factory.buildCampaign({ title: 'Parcours trop bien' }).id; - databaseBuilder.factory.buildCampaignParticipation({ campaignId }); - - const otherCampaignId = databaseBuilder.factory.buildCampaign({ title: 'Autre' }).id; - const otherCampaignParticipationId = databaseBuilder.factory.buildCampaignParticipation({ - campaignId: otherCampaignId, - }).id; - await databaseBuilder.commit(); - - // when - const title = await campaignRepository.getCampaignTitleByCampaignParticipationId(otherCampaignParticipationId); - - // then - expect(title).to.equal('Autre'); - }); - }); - - describe('#getCampaignCodeByCampaignParticipationId', function () { - it('should return campaign code when campaign has one', async function () { - // given - const campaignId = databaseBuilder.factory.buildCampaign({ code: 'CAMPAIGN1' }).id; - const campaignParticipationId = databaseBuilder.factory.buildCampaignParticipation({ campaignId }).id; - await databaseBuilder.commit(); - - // when - const code = await campaignRepository.getCampaignCodeByCampaignParticipationId(campaignParticipationId); - - // then - expect(code).to.equal('CAMPAIGN1'); - }); - - it('should return null when campaignParticipationId does not exist', async function () { - // when - const code = await campaignRepository.getCampaignCodeByCampaignParticipationId(123); - - // then - expect(code).to.be.null; - }); - - it('should return the code from the given campaignParticipationId', async function () { - // given - const campaignId = databaseBuilder.factory.buildCampaign({ code: 'CAMPAIGN1' }).id; - databaseBuilder.factory.buildCampaignParticipation({ campaignId }); - - const otherCampaignId = databaseBuilder.factory.buildCampaign({ code: 'CAMPAIGN2' }).id; - const otherCampaignParticipationId = databaseBuilder.factory.buildCampaignParticipation({ - campaignId: otherCampaignId, - }).id; - await databaseBuilder.commit(); - - // when - const code = await campaignRepository.getCampaignCodeByCampaignParticipationId(otherCampaignParticipationId); - - // then - expect(code).to.equal('CAMPAIGN2'); - }); - }); - describe('#getCampaignIdByCampaignParticipationId', function () { it('should return campaign id', async function () { // given diff --git a/api/tests/shared/acceptance/application/assessments/assessment-controller-get_test.js b/api/tests/shared/acceptance/application/assessments/assessment-controller-get_test.js index b4f23d46157..f510f4f2129 100644 --- a/api/tests/shared/acceptance/application/assessments/assessment-controller-get_test.js +++ b/api/tests/shared/acceptance/application/assessments/assessment-controller-get_test.js @@ -32,11 +32,16 @@ describe('Acceptance | API | assessment-controller-get', function () { // given server = await createServer(); const userId = databaseBuilder.factory.buildUser({}).id; + const campaignId = databaseBuilder.factory.buildCampaign().id; + const campaignParticipationId = databaseBuilder.factory.buildCampaignParticipation({ + campaignId, + }).id; const assessmentId = databaseBuilder.factory.buildAssessment({ userId, courseId, state: Assessment.states.STARTED, type, + campaignParticipationId, }).id; await databaseBuilder.commit(); @@ -163,6 +168,10 @@ describe('Acceptance | API | assessment-controller-get', function () { 'last-question-state': Assessment.statesOfLastQuestion.ASKED, 'competence-id': 'recCompetenceId', method: Assessment.methods.CHOSEN, + 'code-campaign': undefined, + 'has-checkpoints': false, + 'show-levelup': false, + 'show-progress-bar': false, }, relationships: { course: { @@ -285,6 +294,10 @@ describe('Acceptance | API | assessment-controller-get', function () { 'competence-id': 'recCompetenceId', 'last-question-state': Assessment.statesOfLastQuestion.ASKED, method: Assessment.methods.CHOSEN, + 'code-campaign': undefined, + 'has-checkpoints': false, + 'show-levelup': false, + 'show-progress-bar': false, }, relationships: { course: { data: { type: 'courses', id: courseId } }, diff --git a/api/tests/shared/unit/infrastructure/serializers/jsonapi/assessment-serializer_test.js b/api/tests/shared/unit/infrastructure/serializers/jsonapi/assessment-serializer_test.js index 52cee0d1791..a0251902cbd 100644 --- a/api/tests/shared/unit/infrastructure/serializers/jsonapi/assessment-serializer_test.js +++ b/api/tests/shared/unit/infrastructure/serializers/jsonapi/assessment-serializer_test.js @@ -3,11 +3,14 @@ import * as serializer from '../../../../../../src/shared/infrastructure/seriali import { domainBuilder, expect } from '../../../../../test-helper.js'; describe('Unit | Serializer | JSONAPI | assessment-serializer', function () { - describe('#serialize()', function () { + describe('#serialize', function () { it('should convert an Assessment model object (of type CERTIFICATION) into JSON API data', function () { //given const certificationCourseId = 1; - const assessment = domainBuilder.buildAssessment({ certificationCourseId }); + const assessment = domainBuilder.buildAssessment({ type: Assessment.types.CERTIFICATION, certificationCourseId }); + assessment.hasCheckpoints = false; + assessment.showProgressBar = false; + assessment.showLevelup = false; const expectedJson = { data: { id: assessment.id.toString(), @@ -22,6 +25,10 @@ describe('Unit | Serializer | JSONAPI | assessment-serializer', function () { 'competence-id': assessment.competenceId, 'last-question-state': Assessment.statesOfLastQuestion.ASKED, method: Assessment.methods.CERTIFICATION_DETERMINED, + 'show-progress-bar': false, + 'show-levelup': false, + 'has-checkpoints': false, + 'code-campaign': undefined, }, relationships: { answers: { @@ -74,6 +81,8 @@ describe('Unit | Serializer | JSONAPI | assessment-serializer', function () { type: Assessment.types.COMPETENCE_EVALUATION, title: 'Traiter des données', }); + assessment.hasCheckpoints = true; + assessment.showProgressBar = true; const expectedProgressionJson = { data: { @@ -102,6 +111,8 @@ describe('Unit | Serializer | JSONAPI | assessment-serializer', function () { title: 'Parcours', campaignCode: 'CAMPAGNE1', }); + assessment.hasCheckpoints = true; + assessment.showProgressBar = true; const expectedProgressionJson = { data: { id: `progression-${assessment.id}`, @@ -122,29 +133,6 @@ describe('Unit | Serializer | JSONAPI | assessment-serializer', function () { expect(json.data.attributes['title']).to.equal('Parcours'); }); - it('should convert an Assessment model object with type CAMPAIGN and method FLASH into JSON API data', function () { - //given - const assessment = domainBuilder.buildAssessment.ofTypeCampaign({ - method: Assessment.methods.FLASH, - }); - const expectedProgressionJson = { - data: { - id: `progression-${assessment.id}`, - type: 'progressions', - }, - links: { - related: `/api/progressions/progression-${assessment.id}`, - }, - }; - - // when - const json = serializer.serialize(assessment); - - // then - expect(json.data.relationships['progression']).to.deep.equal(expectedProgressionJson); - expect(json.data.attributes['method']).to.equal(Assessment.methods.FLASH); - }); - it('should convert an Assessment model object without course into JSON API data', function () { //given const assessment = domainBuilder.buildAssessment({ diff --git a/api/tests/unit/domain/models/Campaign_test.js b/api/tests/unit/domain/models/Campaign_test.js index ea77e8ba897..b878e617257 100644 --- a/api/tests/unit/domain/models/Campaign_test.js +++ b/api/tests/unit/domain/models/Campaign_test.js @@ -1,3 +1,4 @@ +import { CampaignTypes } from '../../../../src/prescription/shared/domain/constants.js'; import { domainBuilder, expect } from '../../../test-helper.js'; describe('Unit | Domain | Models | Campaign', function () { @@ -49,6 +50,24 @@ describe('Unit | Domain | Models | Campaign', function () { }); }); + describe('isExam', function () { + it('should return true when campaign is of type exam', function () { + // given + const campaign = domainBuilder.buildCampaign({ type: CampaignTypes.EXAM }); + + // when / then + expect(campaign.isExam()).to.be.true; + }); + + it('should return false when campaign is not of type exam', function () { + // given + const campaign = domainBuilder.buildCampaign.ofTypeProfilesCollection(); + + // when / then + expect(campaign.isExam()).to.be.false; + }); + }); + describe('isAssessment', function () { it('should return true when campaign is of type assessment', function () { // given diff --git a/api/tests/unit/domain/usecases/get-assessment_test.js b/api/tests/unit/domain/usecases/get-assessment_test.js index 9cd10cafec9..cc13a6c5019 100644 --- a/api/tests/unit/domain/usecases/get-assessment_test.js +++ b/api/tests/unit/domain/usecases/get-assessment_test.js @@ -1,13 +1,11 @@ import { getAssessment } from '../../../../lib/domain/usecases/get-assessment.js'; import { CertificationChallengeLiveAlertStatus } from '../../../../src/certification/shared/domain/models/CertificationChallengeLiveAlert.js'; import { NotFoundError } from '../../../../src/shared/domain/errors.js'; -import { Assessment } from '../../../../src/shared/domain/models/index.js'; +import { Assessment, CampaignTypes } from '../../../../src/shared/domain/models/index.js'; import { catchErr, domainBuilder, expect, sinon } from '../../../test-helper.js'; describe('Unit | UseCase | get-assessment', function () { let assessment; - let campaign; - let campaignParticipation; let competence; let course; let assessmentRepository; @@ -25,17 +23,11 @@ describe('Unit | UseCase | get-assessment', function () { const expectedAssessmentTitle = 'Traiter des données'; beforeEach(function () { - campaign = domainBuilder.buildCampaign.ofTypeAssessment({ - title: expectedCampaignTitle, - code: expectedCampaignCode, - }); - campaignParticipation = domainBuilder.buildCampaignParticipation({ campaign }); competence = domainBuilder.buildCompetence({ id: 'recsvLz0W2ShyfD63', name: expectedAssessmentTitle }); course = domainBuilder.buildCourse({ id: 'ABC123', name: expectedCourseName }); assessment = domainBuilder.buildAssessment({ type: Assessment.types.PREVIEW, - campaignParticipation, competenceId: competence.id, courseId: course.id, certificationCourseId, @@ -43,13 +35,15 @@ describe('Unit | UseCase | get-assessment', function () { assessmentRepository = { getWithAnswers: sinon.stub() }; campaignRepository = { - getCampaignTitleByCampaignParticipationId: sinon.stub(), - getCampaignCodeByCampaignParticipationId: sinon.stub(), + get: sinon.stub(), + getCampaignIdByCampaignParticipationId: sinon.stub(), }; competenceRepository = { getCompetenceName: sinon.stub() }; courseRepository = { getCourseName: sinon.stub(), get: sinon.stub() }; certificationChallengeLiveAlertRepository = { getByAssessmentId: sinon.stub() }; certificationCompanionAlertRepository = { getAllByAssessmentId: sinon.stub() }; + campaignRepository.get.rejects(new Error('I should not be called')); + campaignRepository.getCampaignIdByCampaignParticipationId.rejects(new Error('I should not be called')); }); it('should resolve the Assessment domain object matching the given assessment ID', async function () { @@ -70,7 +64,7 @@ describe('Unit | UseCase | get-assessment', function () { expect(result.id).to.equal(assessment.id); }); - it('should resolve the Assessment domain object with COMPETENCE_EVALUATION title matching the given assessment ID', async function () { + it('should resolve the Assessment domain object with COMPETENCE_EVALUATION title matching the given assessment ID, along with hasCheckpoints and showProgressBar', async function () { // given const locale = 'fr'; assessment.type = Assessment.types.COMPETENCE_EVALUATION; @@ -91,10 +85,13 @@ describe('Unit | UseCase | get-assessment', function () { expect(result).to.be.an.instanceOf(Assessment); expect(result.id).to.equal(assessment.id); expect(result.title).to.equal(expectedAssessmentTitle); + expect(result.hasCheckpoints).to.equal(true); + expect(result.showProgressBar).to.equal(true); + expect(result.showLevelup).to.equal(true); }); context('Assessment of type DEMO', function () { - it('should resolve the Assessment domain object with DEMO title matching the given assessment ID when course is playable', async function () { + it('should resolve the Assessment domain object with DEMO title matching the given assessment ID when course is playable, along with hasCheckpoints and showProgressBar', async function () { // given const playableCourse = domainBuilder.buildCourse({ name: 'Course Àpieds', isActive: true }); assessment.type = Assessment.types.DEMO; @@ -115,6 +112,9 @@ describe('Unit | UseCase | get-assessment', function () { expect(result).to.be.an.instanceOf(Assessment); expect(result.id).to.equal(assessment.id); expect(result.title).to.equal(course.name); + expect(result.hasCheckpoints).to.equal(false); + expect(result.showProgressBar).to.equal(true); + expect(result.showLevelup).to.equal(false); }); it('should throw a NotFoundError when course is not playable', async function () { @@ -145,7 +145,7 @@ describe('Unit | UseCase | get-assessment', function () { assessment.type = Assessment.types.CERTIFICATION; }); - it('should resolve the Assessment domain object with CERTIFICATION title matching the given assessment ID', async function () { + it('should resolve the Assessment domain object with CERTIFICATION title matching the given assessment ID, along with hasCheckpoints and showProgressBar', async function () { // given assessmentRepository.getWithAnswers.resolves(assessment); certificationChallengeLiveAlertRepository.getByAssessmentId.withArgs(assessment.id).resolves([]); @@ -165,6 +165,9 @@ describe('Unit | UseCase | get-assessment', function () { expect(result).to.be.an.instanceOf(Assessment); expect(result.id).to.equal(assessment.id); expect(result.title).to.equal(certificationCourseId); + expect(result.hasCheckpoints).to.equal(false); + expect(result.showProgressBar).to.equal(false); + expect(result.showLevelup).to.equal(false); }); context('when no liveAlert is attached to the assessment', function () { @@ -264,34 +267,118 @@ describe('Unit | UseCase | get-assessment', function () { }); }); - it('should resolve the Assessment domain object with CAMPAIGN title matching the given assessment ID', async function () { - // given - assessment.type = Assessment.types.CAMPAIGN; - assessmentRepository.getWithAnswers.withArgs(assessment.id).resolves(assessment); - campaignRepository.getCampaignTitleByCampaignParticipationId - .withArgs(assessment.campaignParticipationId) - .resolves(expectedCampaignTitle); - campaignRepository.getCampaignCodeByCampaignParticipationId - .withArgs(assessment.campaignParticipationId) - .resolves(expectedCampaignCode); + context('Assessment of type CAMPAIGN', function () { + context('when campaign is assessment and assessment is FLASH', function () { + it('should return the assessment with expected title, hasCheckpoints and showProgressBar', async function () { + // given + assessment.type = Assessment.types.CAMPAIGN; + assessment.method = Assessment.methods.FLASH; + assessment.campaignParticipationId = 123; + campaignRepository.getCampaignIdByCampaignParticipationId.withArgs(123).resolves(456); + campaignRepository.get.withArgs(456).resolves( + domainBuilder.buildCampaign({ + id: 456, + type: CampaignTypes.ASSESSMENT, + title: expectedCampaignTitle, + code: expectedCampaignCode, + }), + ); + assessmentRepository.getWithAnswers.withArgs(assessment.id).resolves(assessment); - // when - const result = await getAssessment({ - assessmentId: assessment.id, - assessmentRepository, - campaignRepository, - competenceRepository, - courseRepository, + // when + const result = await getAssessment({ + assessmentId: assessment.id, + assessmentRepository, + campaignRepository, + competenceRepository, + courseRepository, + }); + + // then + expect(result).to.be.an.instanceOf(Assessment); + expect(result.id).to.equal(assessment.id); + expect(result.title).to.equal(expectedCampaignTitle); + expect(result.campaignCode).to.equal(expectedCampaignCode); + expect(result.hasCheckpoints).to.equal(false); + expect(result.showProgressBar).to.equal(false); + expect(result.showLevelup).to.equal(false); + }); }); + context('when campaign is assessment and assessment is NOT FLASH', function () { + it('should return the assessment with expected title, hasCheckpoints and showProgressBar', async function () { + // given + assessment.type = Assessment.types.CAMPAIGN; + assessment.method = Assessment.methods.SMART_RANDOM; + assessment.campaignParticipationId = 123; + campaignRepository.getCampaignIdByCampaignParticipationId.withArgs(123).resolves(456); + campaignRepository.get.withArgs(456).resolves( + domainBuilder.buildCampaign({ + id: 456, + type: CampaignTypes.ASSESSMENT, + title: expectedCampaignTitle, + code: expectedCampaignCode, + }), + ); + assessmentRepository.getWithAnswers.withArgs(assessment.id).resolves(assessment); - // then - expect(result).to.be.an.instanceOf(Assessment); - expect(result.id).to.equal(assessment.id); - expect(result.title).to.equal(expectedCampaignTitle); - expect(result.campaignCode).to.equal(expectedCampaignCode); + // when + const result = await getAssessment({ + assessmentId: assessment.id, + assessmentRepository, + campaignRepository, + competenceRepository, + courseRepository, + }); + + // then + expect(result).to.be.an.instanceOf(Assessment); + expect(result.id).to.equal(assessment.id); + expect(result.title).to.equal(expectedCampaignTitle); + expect(result.campaignCode).to.equal(expectedCampaignCode); + expect(result.hasCheckpoints).to.equal(true); + expect(result.showProgressBar).to.equal(true); + expect(result.showLevelup).to.equal(true); + }); + }); + context('when campaign is exam', function () { + it('should return the assessment with expected title, hasCheckpoints and showProgressBar', async function () { + // given + assessment.type = Assessment.types.CAMPAIGN; + assessment.method = Assessment.methods.SMART_RANDOM; + assessment.campaignParticipationId = 123; + campaignRepository.getCampaignIdByCampaignParticipationId.withArgs(123).resolves(456); + campaignRepository.get.withArgs(456).resolves( + domainBuilder.buildCampaign({ + id: 456, + type: CampaignTypes.EXAM, + title: expectedCampaignTitle, + code: expectedCampaignCode, + }), + ); + assessmentRepository.getWithAnswers.withArgs(assessment.id).resolves(assessment); + + // when + const result = await getAssessment({ + assessmentId: assessment.id, + assessmentRepository, + campaignRepository, + competenceRepository, + courseRepository, + }); + + // then + expect(result).to.be.an.instanceOf(Assessment); + expect(result.id).to.equal(assessment.id); + expect(result.title).to.equal(expectedCampaignTitle); + expect(result.campaignCode).to.equal(expectedCampaignCode); + expect(result.hasCheckpoints).to.equal(true); + expect(result.showProgressBar).to.equal(true); + expect(result.showLevelup).to.equal(true); + }); + }); }); - it('should resolve the Assessment domain object without title matching the given assessment ID', async function () { + it('should resolve the Assessment domain object without title matching the given assessment ID, along with hasCheckpoints and showProgressBar', async function () { // given assessment.type = 'NO TYPE'; assessmentRepository.getWithAnswers.withArgs(assessment.id).resolves(assessment); @@ -312,9 +399,12 @@ describe('Unit | UseCase | get-assessment', function () { expect(result).to.be.an.instanceOf(Assessment); expect(result.id).to.equal(assessment.id); expect(result.title).to.equal(''); + expect(result.hasCheckpoints).to.equal(false); + expect(result.showProgressBar).to.equal(false); + expect(result.showLevelup).to.equal(false); }); - it('should resolve the Assessment domain object with Preview title matching the given assessment ID', async function () { + it('should resolve the Assessment domain object with Preview title matching the given assessment ID, along with hasCheckpoints and showProgressBar', async function () { // given assessment.type = Assessment.types.PREVIEW; assessmentRepository.getWithAnswers.withArgs(assessment.id).resolves(assessment); @@ -332,5 +422,8 @@ describe('Unit | UseCase | get-assessment', function () { expect(result).to.be.an.instanceOf(Assessment); expect(result.id).to.equal(assessment.id); expect(result.title).to.equal('Preview'); + expect(result.hasCheckpoints).to.equal(false); + expect(result.showProgressBar).to.equal(false); + expect(result.showLevelup).to.equal(false); }); }); diff --git a/mon-pix/app/models/assessment.js b/mon-pix/app/models/assessment.js index 22aee48a6ae..295e60329a8 100644 --- a/mon-pix/app/models/assessment.js +++ b/mon-pix/app/models/assessment.js @@ -1,6 +1,6 @@ /* eslint ember/no-computed-properties-in-native-classes: 0 */ -import { and, equal, not, or } from '@ember/object/computed'; +import { equal } from '@ember/object/computed'; import Model, { attr, belongsTo, hasMany } from '@ember-data/model'; import ENV from 'mon-pix/config/environment'; @@ -22,6 +22,9 @@ export default class Assessment extends Model { @attr('string') method; @attr('boolean', { defaultValue: false }) hasOngoingChallengeLiveAlert; @attr('boolean') hasOngoingCompanionLiveAlert; + @attr('boolean') hasCheckpoints; + @attr('boolean') showProgressBar; + @attr('boolean') showLevelup; // references @attr('string') competenceId; @@ -40,8 +43,6 @@ export default class Assessment extends Model { @equal('type', 'CAMPAIGN') isForCampaign; @equal('method', 'FLASH') isFlash; - @not('isFlash') isNotFlash; - @and('isForCampaign', 'isNotFlash') isForNotFlashCampaign; @equal('state', 'aborted') isAborted; @equal('state', 'completed') isCompleted; @@ -50,10 +51,6 @@ export default class Assessment extends Model { @equal('lastQuestionState', 'timeout') hasTimeoutChallenge; @equal('lastQuestionState', 'focusedout') hasFocusedOutChallenge; - @or('isCompetenceEvaluation', 'isForNotFlashCampaign') hasCheckpoints; - @or('isCompetenceEvaluation', 'isForNotFlashCampaign') showLevelup; - @or('isCompetenceEvaluation', 'isForNotFlashCampaign', 'isDemo') showProgressBar; - get answersSinceLastCheckpoints() { const howManyAnswersSinceTheLastCheckpoint = this.currentChallengeNumber % ENV.APP.NUMBER_OF_CHALLENGES_BETWEEN_TWO_CHECKPOINTS; diff --git a/mon-pix/mirage/factories/assessment.js b/mon-pix/mirage/factories/assessment.js index 50656b9dcb3..2cba202a4de 100644 --- a/mon-pix/mirage/factories/assessment.js +++ b/mon-pix/mirage/factories/assessment.js @@ -9,6 +9,18 @@ export default Factory.extend({ return 'COMPETENCE_EVALUATION'; }, + hasCheckpoints() { + return true; + }, + + showLevelup() { + return true; + }, + + showProgressBar() { + return true; + }, + withStartedState: trait({ state: 'started', }), @@ -41,6 +53,7 @@ export default Factory.extend({ ofFlashCampaignType: trait({ type: 'CAMPAIGN', method: 'FLASH', + showProgressBar: false, }), withCurrentChallengeTimeout: trait({ diff --git a/mon-pix/mirage/factories/certification-course.js b/mon-pix/mirage/factories/certification-course.js index 70d45a9eed4..ff2aa13f14b 100644 --- a/mon-pix/mirage/factories/certification-course.js +++ b/mon-pix/mirage/factories/certification-course.js @@ -20,6 +20,9 @@ export default Factory.extend({ type: 'CERTIFICATION', certificationNumber: certificationCourse.id, certificationCourse, + hasCheckpoints: false, + showProgressBar: false, + showLevelup: false, }), }); } diff --git a/mon-pix/mirage/routes/assessments/post-assessments.js b/mon-pix/mirage/routes/assessments/post-assessments.js index a7a3a3f7567..46001e73358 100644 --- a/mon-pix/mirage/routes/assessments/post-assessments.js +++ b/mon-pix/mirage/routes/assessments/post-assessments.js @@ -8,7 +8,14 @@ export default function (schema, request) { } if (courseData && courseData.id.startsWith('rec')) { const course = schema.challenges.find(courseData.id); - return schema.assessments.create({ course, state: 'started', type: 'DEMO' }); + return schema.assessments.create({ + course, + state: 'started', + type: 'DEMO', + hasCheckpoints: false, + showProgressBar: true, + showLevelup: false, + }); } return new Response(500); diff --git a/mon-pix/mirage/routes/campaign-participations/post-campaign-participation.js b/mon-pix/mirage/routes/campaign-participations/post-campaign-participation.js index d2a47b08dc0..3b419eb0756 100644 --- a/mon-pix/mirage/routes/campaign-participations/post-campaign-participation.js +++ b/mon-pix/mirage/routes/campaign-participations/post-campaign-participation.js @@ -43,6 +43,9 @@ export default function (schema, request) { const newAssessment = { type: 'CAMPAIGN', codeCampaign: campaign.code, + hasCheckpoints: true, + showProgressBar: true, + showLevelup: true, }; const assessment = schema.assessments.create(newAssessment); diff --git a/mon-pix/mirage/routes/post-competence-evaluation.js b/mon-pix/mirage/routes/post-competence-evaluation.js index 88a0d229573..ed61cab27c2 100644 --- a/mon-pix/mirage/routes/post-competence-evaluation.js +++ b/mon-pix/mirage/routes/post-competence-evaluation.js @@ -10,6 +10,11 @@ export default function (schema, request) { if (existingCompetenceEvaluation) { return existingCompetenceEvaluation; } - const assessment = schema.assessments.create({ type: 'COMPETENCE_EVALUATION' }); + const assessment = schema.assessments.create({ + type: 'COMPETENCE_EVALUATION', + hasCheckpoints: true, + showProgressBar: true, + showLevelup: true, + }); return schema.competenceEvaluations.create({ assessment, competenceId }); } diff --git a/mon-pix/tests/integration/components/progress-bar-test.js b/mon-pix/tests/integration/components/progress-bar-test.js index c0be772db48..3ce51999434 100644 --- a/mon-pix/tests/integration/components/progress-bar-test.js +++ b/mon-pix/tests/integration/components/progress-bar-test.js @@ -20,6 +20,8 @@ module('Integration | Component | progress-bar', function (hooks) { ]; const mockAssessment = store.createRecord('assessment', { type: 'CAMPAIGN', + showProgressBar: true, + hasCheckpoints: true, }); mockAssessment.answers = answers; diff --git a/mon-pix/tests/unit/models/assessment-test.js b/mon-pix/tests/unit/models/assessment-test.js index 3dcf7fcd8a5..f768822b198 100644 --- a/mon-pix/tests/unit/models/assessment-test.js +++ b/mon-pix/tests/unit/models/assessment-test.js @@ -199,189 +199,4 @@ module('Unit | Model | Assessment', function (hooks) { assert.false(model.isFlash); }); }); - - module('#hasCheckpoints', function () { - test('should return false when the assessment type is CERTIFICATION', function (assert) { - // given - const model = store.createRecord('assessment'); - - // when - model.type = 'CERTIFICATION'; - - //then - assert.false(model.hasCheckpoints); - }); - - test('should return false when the assessment type is PREVIEW', function (assert) { - // given - const model = store.createRecord('assessment'); - - // when - model.type = 'PREVIEW'; - - //then - assert.false(model.hasCheckpoints); - }); - - test('should return true when the assessment type is COMPETENCE_EVALUATION', function (assert) { - // given - const model = store.createRecord('assessment'); - - // when - model.type = 'COMPETENCE_EVALUATION'; - - //then - assert.true(model.hasCheckpoints); - }); - - test('should return true when the assessment type is CAMPAIGN and method is not FLASH', function (assert) { - // given - const model = store.createRecord('assessment'); - - // when - model.type = 'CAMPAIGN'; - - //then - assert.true(model.hasCheckpoints); - }); - - test('should return false when the assessment type is CAMPAIGN and method is FLASH', function (assert) { - // given - const model = store.createRecord('assessment'); - - // when - model.type = 'CAMPAIGN'; - model.method = 'FLASH'; - - //then - assert.false(model.hasCheckpoints); - }); - }); - - module('#showLevelup', function () { - test('should return false when the assessment type is CERTIFICATION', function (assert) { - // given - const model = store.createRecord('assessment'); - - // when - model.type = 'CERTIFICATION'; - - //then - assert.false(model.showLevelup); - }); - - test('should return false when the assessment type is PREVIEW', function (assert) { - // given - const model = store.createRecord('assessment'); - - // when - model.type = 'PREVIEW'; - - //then - assert.false(model.showLevelup); - }); - - test('should return true when the assessment type is COMPETENCE_EVALUATION', function (assert) { - // given - const model = store.createRecord('assessment'); - - // when - model.type = 'COMPETENCE_EVALUATION'; - - //then - assert.true(model.showLevelup); - }); - - test('should return true when the assessment type is CAMPAIGN and method is not FLASH', function (assert) { - // given - const model = store.createRecord('assessment'); - - // when - model.type = 'CAMPAIGN'; - - //then - assert.true(model.showLevelup); - }); - - test('should return false when the assessment type is CAMPAIGN and method is FLASH', function (assert) { - // given - const model = store.createRecord('assessment'); - - // when - model.type = 'CAMPAIGN'; - model.method = 'FLASH'; - - //then - assert.false(model.showLevelup); - }); - }); - - module('#showProgressBar', function () { - test('should return false when the assessment type is CERTIFICATION', function (assert) { - // given - const model = store.createRecord('assessment'); - - // when - model.type = 'CERTIFICATION'; - - //then - assert.false(model.showProgressBar); - }); - - test('should return false when the assessment type is PREVIEW', function (assert) { - // given - const model = store.createRecord('assessment'); - - // when - model.type = 'PREVIEW'; - - //then - assert.false(model.showProgressBar); - }); - - test('should return true when the assessment type is COMPETENCE_EVALUATION', function (assert) { - // given - const model = store.createRecord('assessment'); - - // when - model.type = 'COMPETENCE_EVALUATION'; - - //then - assert.true(model.showProgressBar); - }); - - test('should return true when the assessment type is CAMPAIGN and method is not FLASH', function (assert) { - // given - const model = store.createRecord('assessment'); - - // when - model.type = 'CAMPAIGN'; - - //then - assert.true(model.showProgressBar); - }); - - test('should return false when the assessment type is CAMPAIGN and method is FLASH', function (assert) { - // given - const model = store.createRecord('assessment'); - - // when - model.type = 'CAMPAIGN'; - model.method = 'FLASH'; - - //then - assert.false(model.showProgressBar); - }); - - test('should return true when the assessment type is DEMO', function (assert) { - // given - const model = store.createRecord('assessment'); - - // when - model.type = 'DEMO'; - - //then - assert.true(model.showProgressBar); - }); - }); });