diff --git a/api/src/routes/protected/certificate.ts b/api/src/routes/protected/certificate.ts index 538de1c2200..14610599b53 100644 --- a/api/src/routes/protected/certificate.ts +++ b/api/src/routes/protected/certificate.ts @@ -5,9 +5,9 @@ import type { FastifyPluginCallbackTypebox } from '@fastify/type-provider-typebo import { getChallenges } from '../../utils/get-challenges.js'; import { certIds, + Certification, certSlugTypeMap, certToTitleMap, - certTypes, currentCertifications, legacyCertifications, legacyFullStackCertification, @@ -20,31 +20,6 @@ import { normalizeChallenges, removeNulls } from '../../utils/normalize.js'; import { SHOW_UPCOMING_CHANGES } from '../../utils/env.js'; import { isKnownCertSlug } from '../helpers/certificate-utils.js'; -const { - a2EnglishId, - legacyFrontEndChallengeId, - legacyBackEndChallengeId, - legacyDataVisId, - legacyInfosecQaId, - legacyFullStackId, - respWebDesignId, - frontEndDevLibsId, - javascriptV9Id, - jsAlgoDataStructId, - jsAlgoDataStructV8Id, - dataVis2018Id, - apisMicroservicesId, - qaV7Id, - infosecV7Id, - sciCompPyV7Id, - dataAnalysisPyV7Id, - machineLearningPyV7Id, - relationalDatabaseV8Id, - respWebDesignV9Id, - collegeAlgebraPyV8Id, - foundationalCSharpV8Id -} = certIds; - function isCertAllowed(certSlug: string): boolean { if ( currentCertifications.includes(certSlug) || @@ -121,50 +96,111 @@ function getCertById( return { id, tests, challengeType }; } -function createCertTypeIds(challenges: ReturnType) { +function createCertLookup( + challenges: ReturnType +): Record< + Certification, + { id: string; tests: { id: string }[]; challengeType: number } +> { return { // legacy - [certTypes.frontEnd]: getCertById(legacyFrontEndChallengeId, challenges), - [certTypes.jsAlgoDataStruct]: getCertById(jsAlgoDataStructId, challenges), - [certTypes.backEnd]: getCertById(legacyBackEndChallengeId, challenges), - [certTypes.dataVis]: getCertById(legacyDataVisId, challenges), - [certTypes.infosecQa]: getCertById(legacyInfosecQaId, challenges), - [certTypes.fullStack]: getCertById(legacyFullStackId, challenges), + [Certification.LegacyFrontEnd]: getCertById( + certIds.legacyFrontEndChallengeId, + challenges + ), + [Certification.JsAlgoDataStruct]: getCertById( + certIds.jsAlgoDataStructId, + challenges + ), + + [Certification.LegacyBackEnd]: getCertById( + certIds.legacyBackEndChallengeId, + challenges + ), + [Certification.LegacyDataVis]: getCertById( + certIds.legacyDataVisId, + challenges + ), + [Certification.LegacyInfoSecQa]: getCertById( + certIds.legacyInfosecQaId, + challenges + ), + [Certification.LegacyFullStack]: getCertById( + certIds.legacyFullStackId, + challenges + ), // modern - [certTypes.respWebDesign]: getCertById(respWebDesignId, challenges), - [certTypes.frontEndDevLibs]: getCertById(frontEndDevLibsId, challenges), - [certTypes.dataVis2018]: getCertById(dataVis2018Id, challenges), - [certTypes.jsAlgoDataStructV8]: getCertById( - jsAlgoDataStructV8Id, + [Certification.RespWebDesign]: getCertById( + certIds.respWebDesignId, challenges ), - [certTypes.apisMicroservices]: getCertById(apisMicroservicesId, challenges), - [certTypes.qaV7]: getCertById(qaV7Id, challenges), - [certTypes.infosecV7]: getCertById(infosecV7Id, challenges), - [certTypes.sciCompPyV7]: getCertById(sciCompPyV7Id, challenges), - [certTypes.dataAnalysisPyV7]: getCertById(dataAnalysisPyV7Id, challenges), - [certTypes.machineLearningPyV7]: getCertById( - machineLearningPyV7Id, + [Certification.FrontEndDevLibs]: getCertById( + certIds.frontEndDevLibsId, challenges ), - [certTypes.relationalDatabaseV8]: getCertById( - relationalDatabaseV8Id, + [Certification.DataVis]: getCertById(certIds.dataVis2018Id, challenges), + [Certification.JsAlgoDataStructNew]: getCertById( + certIds.jsAlgoDataStructV8Id, challenges ), - [certTypes.collegeAlgebraPyV8]: getCertById( - collegeAlgebraPyV8Id, + [Certification.BackEndDevApis]: getCertById( + certIds.apisMicroservicesId, challenges ), - [certTypes.foundationalCSharpV8]: getCertById( - foundationalCSharpV8Id, + [Certification.QualityAssurance]: getCertById(certIds.qaV7Id, challenges), + [Certification.InfoSec]: getCertById(certIds.infosecV7Id, challenges), + [Certification.SciCompPy]: getCertById(certIds.sciCompPyV7Id, challenges), + [Certification.DataAnalysisPy]: getCertById( + certIds.dataAnalysisPyV7Id, challenges ), - [certTypes.javascriptV9]: getCertById(javascriptV9Id, challenges), - [certTypes.respWebDesignV9]: getCertById(respWebDesignV9Id, challenges), + [Certification.MachineLearningPy]: getCertById( + certIds.machineLearningPyV7Id, + challenges + ), + [Certification.RelationalDb]: getCertById( + certIds.relationalDatabaseV8Id, + challenges + ), + [Certification.CollegeAlgebraPy]: getCertById( + certIds.collegeAlgebraPyV8Id, + challenges + ), + [Certification.FoundationalCSharp]: getCertById( + certIds.foundationalCSharpV8Id, + challenges + ), + + [Certification.JsV9]: getCertById(certIds.javascriptV9Id, challenges), + [Certification.RespWebDesignV9]: getCertById( + certIds.respWebDesignV9Id, + challenges + ), + [Certification.A2English]: getCertById(certIds.a2EnglishId, challenges), // upcoming - [certTypes.a2English]: getCertById(a2EnglishId, challenges) + [Certification.FrontEndDevLibsV9]: getCertById( + certIds.frontEndLibsV9Id, + challenges + ), + [Certification.PythonV9]: getCertById(certIds.pythonV9Id, challenges), + [Certification.RelationalDbV9]: getCertById( + certIds.relationalDbV9Id, + challenges + ), + [Certification.BackEndDevApisV9]: getCertById( + certIds.backEndDevApisV9Id, + challenges + ), + [Certification.FullStackDeveloperV9]: getCertById( + certIds.fullStackDeveloperV9Id, + challenges + ), + [Certification.B1English]: getCertById(certIds.b1EnglishId, challenges), + [Certification.A2Spanish]: getCertById(certIds.a2SpanishId, challenges), + [Certification.A1Chinese]: getCertById(certIds.a1ChineseId, challenges), + [Certification.A2Chinese]: getCertById(certIds.a2ChineseId, challenges) }; } @@ -258,7 +294,7 @@ export const protectedCertificateRoutes: FastifyPluginCallbackTypebox = ( done ) => { const challenges = getChallenges(); - const certTypeIds = createCertTypeIds(challenges); + const certLookup = createCertLookup(challenges); // TODO(POST_MVP): Response should not include updated user. If a client wants the updated user, it should make a separate request // OR: Always respond with current user - full user object - not random pieces. @@ -347,7 +383,7 @@ export const protectedCertificateRoutes: FastifyPluginCallbackTypebox = ( } as const; } - const { id, tests, challengeType } = certTypeIds[certType]; + const { id, tests, challengeType } = certLookup[certSlug]; const hasCompletedTestRequirements = hasCompletedTests( tests, user.completedChallenges diff --git a/curriculum/challenges/english/certifications/a1-professional-chinese.yml b/curriculum/challenges/english/certifications/a1-professional-chinese.yml index 1c9a35159a6..18e2cfcb69d 100644 --- a/curriculum/challenges/english/certifications/a1-professional-chinese.yml +++ b/curriculum/challenges/english/certifications/a1-professional-chinese.yml @@ -1,8 +1,8 @@ --- id: 68f1268149f045a650d4229e title: A1 Professional Chinese Certification -certification: a1-professional-chinese-certification +certification: a1-professional-chinese-v8 challengeType: 7 tests: - id: 688f1daf0133dbe2a36b140b - title: "Dialogue 1: PLACEHOLDER" + title: 'Dialogue 1: PLACEHOLDER' diff --git a/curriculum/challenges/english/certifications/a2-professional-chinese.yml b/curriculum/challenges/english/certifications/a2-professional-chinese.yml index 10c76ddfa80..6c99a86a971 100644 --- a/curriculum/challenges/english/certifications/a2-professional-chinese.yml +++ b/curriculum/challenges/english/certifications/a2-professional-chinese.yml @@ -1,8 +1,8 @@ --- id: 682c3153086dd7cabe7f48bc title: A2 Professional Chinese Certification -certification: a2-professional-chinese-certification +certification: a2-professional-chinese-v8 challengeType: 7 tests: - id: 682c2753317b88f1ecdad894 - title: "Dialogue 1: PLACEHOLDER" + title: 'Dialogue 1: PLACEHOLDER' diff --git a/curriculum/challenges/english/certifications/a2-professional-spanish.yml b/curriculum/challenges/english/certifications/a2-professional-spanish.yml index e29f461d655..60d88b7baaf 100644 --- a/curriculum/challenges/english/certifications/a2-professional-spanish.yml +++ b/curriculum/challenges/english/certifications/a2-professional-spanish.yml @@ -1,8 +1,8 @@ --- id: 681a6b22e5a782fe3459984a title: A2 Professional Spanish Certification -certification: a2-professional-spanish-certification +certification: a2-professional-spanish-v8 challengeType: 7 tests: - id: 681a8796e5a782fe3459984b - title: "Dialogue 1: PLACEHOLDER" + title: 'Dialogue 1: PLACEHOLDER' diff --git a/curriculum/challenges/english/certifications/b1-english-for-developers.yml b/curriculum/challenges/english/certifications/b1-english-for-developers.yml index 721dc3489f6..ac8ae334788 100644 --- a/curriculum/challenges/english/certifications/b1-english-for-developers.yml +++ b/curriculum/challenges/english/certifications/b1-english-for-developers.yml @@ -1,7 +1,7 @@ --- id: 66607e53317411dd5e8aae21 title: B1 English for Developers Certification -certification: b1-english-for-developers +certification: b1-english-for-developers-v8 challengeType: 7 tests: - id: 66607e5b317411dd5e8aae22 diff --git a/shared/config/certification-settings.test.ts b/shared/config/certification-settings.test.ts index 132840506a2..f1dd690d79c 100644 --- a/shared/config/certification-settings.test.ts +++ b/shared/config/certification-settings.test.ts @@ -2,7 +2,8 @@ import { describe, it, expect } from 'vitest'; import { Certification, linkedInCredentialIds, - certToTitleMap + certToTitleMap, + certIds } from './certification-settings'; describe('linkedInCredentialIds', () => { @@ -22,3 +23,12 @@ describe('certToTitleMap', () => { expect(titles.length).toBe(uniqueTitles.length); }); }); + +describe('certIds', () => { + it('should have no duplicate values', () => { + const ids = Object.values(certIds).sort(); + const uniqueIds = Array.from(new Set(ids)).sort(); + + expect(uniqueIds).toEqual(ids); + }); +}); diff --git a/shared/config/certification-settings.ts b/shared/config/certification-settings.ts index 07c7b90f1a5..5c611f2c7a7 100644 --- a/shared/config/certification-settings.ts +++ b/shared/config/certification-settings.ts @@ -154,7 +154,11 @@ export const certIds = { relationalDbV9Id: '68e6bd5120effa1586e79856', backEndDevApisV9Id: '68e6bd5120effa1586e79857', fullStackDeveloperV9Id: '64514fda6c245de4d11eb7bb', - a2EnglishId: '651dd7e01d697d0aab7833b7' + a2EnglishId: '651dd7e01d697d0aab7833b7', + b1EnglishId: '66607e53317411dd5e8aae21', + a2SpanishId: '681a6b22e5a782fe3459984a', + a1ChineseId: '68f1268149f045a650d4229e', + a2ChineseId: '682c3153086dd7cabe7f48bc' }; export const completionHours = {