mirror of
https://github.com/freeCodeCamp/freeCodeCamp.git
synced 2026-05-28 18:26:54 +00:00
refactor: remove certIds and the associated map (#64299)
This commit is contained in:
committed by
GitHub
parent
ff66ae89df
commit
a38caeca39
@@ -1,26 +1,18 @@
|
||||
import { Prisma } from '@prisma/client';
|
||||
import {
|
||||
certSlugTypeMap,
|
||||
certIds
|
||||
certToIdMap,
|
||||
Certification
|
||||
} from '../../../../shared/config/certification-settings.js';
|
||||
import { normalizeDate } from '../../utils/normalize.js';
|
||||
|
||||
const {
|
||||
legacyInfosecQaId,
|
||||
respWebDesignId,
|
||||
frontEndDevLibsId,
|
||||
jsAlgoDataStructId,
|
||||
dataVis2018Id,
|
||||
apisMicroservicesId
|
||||
} = certIds;
|
||||
|
||||
const fullStackCertificateIds = [
|
||||
respWebDesignId,
|
||||
jsAlgoDataStructId,
|
||||
frontEndDevLibsId,
|
||||
dataVis2018Id,
|
||||
apisMicroservicesId,
|
||||
legacyInfosecQaId
|
||||
certToIdMap[Certification.RespWebDesign],
|
||||
certToIdMap[Certification.JsAlgoDataStruct],
|
||||
certToIdMap[Certification.FrontEndDevLibs],
|
||||
certToIdMap[Certification.DataVis],
|
||||
certToIdMap[Certification.BackEndDevApis],
|
||||
certToIdMap[Certification.LegacyInfoSecQa]
|
||||
];
|
||||
|
||||
/**
|
||||
|
||||
@@ -16,6 +16,8 @@ import {
|
||||
setupServer,
|
||||
superRequest
|
||||
} from '../../../vitest.utils.js';
|
||||
import { getChallenges } from '../../utils/get-challenges.js';
|
||||
import { createCertLookup } from './certificate.js';
|
||||
|
||||
describe('certificate routes', () => {
|
||||
setupServer();
|
||||
@@ -461,3 +463,32 @@ describe('certificate routes', () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('createCertLookup', () => {
|
||||
let challenges: ReturnType<typeof getChallenges>;
|
||||
|
||||
beforeAll(() => {
|
||||
// TODO: create a mock challenges array specific to these tests.
|
||||
challenges = getChallenges();
|
||||
});
|
||||
|
||||
test('should create a lookup for all certifications', () => {
|
||||
const certLookup = createCertLookup(challenges);
|
||||
|
||||
for (const cert of Object.values(Certification)) {
|
||||
const certData = certLookup[cert];
|
||||
expect(certData).toHaveProperty('id');
|
||||
expect(certData).toHaveProperty('tests');
|
||||
expect(certData).toHaveProperty('challengeType');
|
||||
}
|
||||
});
|
||||
|
||||
test('each certification should have a unique challenge id', () => {
|
||||
const certLookup = createCertLookup(challenges);
|
||||
const ids = Object.values(certLookup)
|
||||
.map(({ id }) => id)
|
||||
.sort();
|
||||
const uniqueIds = Array.from(new Set(ids)).sort();
|
||||
expect(uniqueIds).toEqual(ids);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -4,9 +4,9 @@ import type { FastifyPluginCallbackTypebox } from '@fastify/type-provider-typebo
|
||||
|
||||
import { getChallenges } from '../../utils/get-challenges.js';
|
||||
import {
|
||||
certIds,
|
||||
Certification,
|
||||
certSlugTypeMap,
|
||||
certToIdMap,
|
||||
certToTitleMap,
|
||||
currentCertifications,
|
||||
legacyCertifications,
|
||||
@@ -83,10 +83,11 @@ function assertTestsExist(
|
||||
}
|
||||
}
|
||||
|
||||
function getCertById(
|
||||
challengeId: string,
|
||||
function getCertBySlug(
|
||||
cert: Certification,
|
||||
challenges: ReturnType<typeof getChallenges>
|
||||
): { id: string; tests: { id: string }[]; challengeType: number } {
|
||||
const challengeId = certToIdMap[cert];
|
||||
const challengeById = challenges.filter(({ id }) => id === challengeId)[0];
|
||||
if (!challengeById) {
|
||||
throw new Error(`Challenge with id '${challengeId}' not found`);
|
||||
@@ -96,112 +97,28 @@ function getCertById(
|
||||
return { id, tests, challengeType };
|
||||
}
|
||||
|
||||
function createCertLookup(
|
||||
challenges: ReturnType<typeof getChallenges>
|
||||
): Record<
|
||||
type CertLookup = Record<
|
||||
Certification,
|
||||
{ id: string; tests: { id: string }[]; challengeType: number }
|
||||
> {
|
||||
return {
|
||||
// legacy
|
||||
[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
|
||||
),
|
||||
/**
|
||||
* Create a lookup from Certification enum values to their corresponding
|
||||
* challenge metadata (id, tests and challengeType) using the provided
|
||||
* challenges array.
|
||||
*
|
||||
* @param challenges - The array returned by getChallenges().
|
||||
* @returns A record mapping each Certification to an object with id, tests and challengeType.
|
||||
*/
|
||||
export function createCertLookup(
|
||||
challenges: ReturnType<typeof getChallenges>
|
||||
): CertLookup {
|
||||
const certLookup = {} as CertLookup;
|
||||
|
||||
// modern
|
||||
[Certification.RespWebDesign]: getCertById(
|
||||
certIds.respWebDesignId,
|
||||
challenges
|
||||
),
|
||||
[Certification.FrontEndDevLibs]: getCertById(
|
||||
certIds.frontEndDevLibsId,
|
||||
challenges
|
||||
),
|
||||
[Certification.DataVis]: getCertById(certIds.dataVis2018Id, challenges),
|
||||
[Certification.JsAlgoDataStructNew]: getCertById(
|
||||
certIds.jsAlgoDataStructV8Id,
|
||||
challenges
|
||||
),
|
||||
[Certification.BackEndDevApis]: getCertById(
|
||||
certIds.apisMicroservicesId,
|
||||
challenges
|
||||
),
|
||||
[Certification.QualityAssurance]: getCertById(certIds.qaV7Id, challenges),
|
||||
[Certification.InfoSec]: getCertById(certIds.infosecV7Id, challenges),
|
||||
[Certification.SciCompPy]: getCertById(certIds.sciCompPyV7Id, challenges),
|
||||
[Certification.DataAnalysisPy]: getCertById(
|
||||
certIds.dataAnalysisPyV7Id,
|
||||
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
|
||||
[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)
|
||||
};
|
||||
for (const cert of Object.values(Certification)) {
|
||||
certLookup[cert] = getCertBySlug(cert, challenges);
|
||||
}
|
||||
return certLookup;
|
||||
}
|
||||
|
||||
interface CertI {
|
||||
|
||||
@@ -5,7 +5,7 @@ import * as schemas from '../../schemas.js';
|
||||
import {
|
||||
certSlugTypeMap,
|
||||
certToTitleMap,
|
||||
certTypeIdMap,
|
||||
certToIdMap,
|
||||
completionHours,
|
||||
oldDataVizId
|
||||
} from '../../../../shared/config/certification-settings.js';
|
||||
@@ -52,7 +52,7 @@ export const unprotectedCertificateRoutes: FastifyPluginCallbackTypebox = (
|
||||
}
|
||||
|
||||
const certType = certSlugTypeMap[certSlug];
|
||||
const certId = certTypeIdMap[certType];
|
||||
const certId = certToIdMap[certSlug];
|
||||
const certTitle = certToTitleMap[certSlug];
|
||||
const completionTime = completionHours[certType] || 300;
|
||||
const user = await fastify.prisma.user.findFirst({
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { createSelector } from 'reselect';
|
||||
import { liveCerts } from '../../config/cert-and-project-map';
|
||||
import {
|
||||
certTypeIdMap,
|
||||
certSlugTypeMap,
|
||||
certToTitleMap
|
||||
} from '../../../shared-dist/config/certification-settings.js';
|
||||
|
||||
@@ -231,9 +231,9 @@ export const claimableCertsSelector = createSelector([userSelector], user => {
|
||||
({ id }) => id
|
||||
);
|
||||
|
||||
const isClaimedById = Object.entries(certTypeIdMap).reduce(
|
||||
(acc, [userFlag, certId]) => {
|
||||
acc[certId] = Boolean(user[userFlag]);
|
||||
const isClaimedByCert = Object.entries(certSlugTypeMap).reduce(
|
||||
(acc, [cert, userFlag]) => {
|
||||
acc[cert] = Boolean(user[userFlag]);
|
||||
return acc;
|
||||
},
|
||||
{}
|
||||
@@ -241,9 +241,9 @@ export const claimableCertsSelector = createSelector([userSelector], user => {
|
||||
|
||||
const claimable = [];
|
||||
|
||||
for (const { id, projects, certSlug } of liveCerts) {
|
||||
for (const { projects, certSlug } of liveCerts) {
|
||||
if (!projects) continue;
|
||||
if (isClaimedById[id]) continue;
|
||||
if (isClaimedByCert[certSlug]) continue;
|
||||
|
||||
const projectIds = projects.map(p => p.id);
|
||||
const allProjectsComplete = projectIds.every(id =>
|
||||
|
||||
@@ -10,10 +10,7 @@ import {
|
||||
import store from 'store';
|
||||
import { navigate } from 'gatsby';
|
||||
|
||||
import {
|
||||
certTypeIdMap,
|
||||
certTypes
|
||||
} from '../../../../shared-dist/config/certification-settings';
|
||||
import { Certification } from '../../../../shared-dist/config/certification-settings';
|
||||
import { createFlashMessage } from '../../components/Flash/redux';
|
||||
import { liveCerts } from '../../../config/cert-and-project-map';
|
||||
import {
|
||||
@@ -191,7 +188,7 @@ function* verifyCertificationSaga({ payload }) {
|
||||
|
||||
// (20/06/2022) Full Stack client-side validation is already done here:
|
||||
// https://github.com/freeCodeCamp/freeCodeCamp/blob/main/client/src/components/settings/certification.js#L309
|
||||
if (currentCert?.id !== certTypeIdMap[certTypes.fullStack]) {
|
||||
if (currentCert?.certSlug !== Certification.LegacyFullStack) {
|
||||
const flash = {
|
||||
type: 'info',
|
||||
message: 'flash.incomplete-steps',
|
||||
|
||||
@@ -3,7 +3,7 @@ import {
|
||||
Certification,
|
||||
linkedInCredentialIds,
|
||||
certToTitleMap,
|
||||
certIds
|
||||
certToIdMap
|
||||
} from './certification-settings';
|
||||
|
||||
describe('linkedInCredentialIds', () => {
|
||||
@@ -24,9 +24,9 @@ describe('certToTitleMap', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('certIds', () => {
|
||||
describe('certToIdMap', () => {
|
||||
it('should have no duplicate values', () => {
|
||||
const ids = Object.values(certIds).sort();
|
||||
const ids = Object.values(certToIdMap).sort();
|
||||
const uniqueIds = Array.from(new Set(ids)).sort();
|
||||
|
||||
expect(uniqueIds).toEqual(ids);
|
||||
|
||||
@@ -127,38 +127,43 @@ export const certTypes = {
|
||||
a2English: 'isA2EnglishCert'
|
||||
} as const;
|
||||
|
||||
export const certIds = {
|
||||
legacyFrontEndChallengeId: '561add10cb82ac38a17513be',
|
||||
legacyBackEndChallengeId: '660add10cb82ac38a17513be',
|
||||
legacyDataVisId: '561add10cb82ac39a17513bc',
|
||||
legacyInfosecQaId: '561add10cb82ac38a17213bc',
|
||||
legacyFullStackId: '561add10cb82ac38a17213bd',
|
||||
respWebDesignId: '561add10cb82ac38a17513bc',
|
||||
frontEndDevLibsId: '561acd10cb82ac38a17513bc',
|
||||
dataVis2018Id: '5a553ca864b52e1d8bceea14',
|
||||
jsAlgoDataStructId: '561abd10cb81ac38a17513bc',
|
||||
apisMicroservicesId: '561add10cb82ac38a17523bc',
|
||||
qaV7Id: '5e611829481575a52dc59c0e',
|
||||
infosecV7Id: '5e6021435ac9d0ecd8b94b00',
|
||||
sciCompPyV7Id: '5e44431b903586ffb414c951',
|
||||
dataAnalysisPyV7Id: '5e46fc95ac417301a38fb934',
|
||||
machineLearningPyV7Id: '5e46fc95ac417301a38fb935',
|
||||
relationalDatabaseV8Id: '606243f50267e718b1e755f4',
|
||||
collegeAlgebraPyV8Id: '61531b20cc9dfa2741a5b800',
|
||||
foundationalCSharpV8Id: '647f7da207d29547b3bee1ba',
|
||||
jsAlgoDataStructV8Id: '658180220947283cdc0689ce',
|
||||
respWebDesignV9Id: '68db314d3c11a8bff07c7535',
|
||||
javascriptV9Id: '68c4069c1ef859270e17c495',
|
||||
frontEndLibsV9Id: '68e008aa5f80c6099d47b3a2',
|
||||
pythonV9Id: '68e6bd5020effa1586e79855',
|
||||
relationalDbV9Id: '68e6bd5120effa1586e79856',
|
||||
backEndDevApisV9Id: '68e6bd5120effa1586e79857',
|
||||
fullStackDeveloperV9Id: '64514fda6c245de4d11eb7bb',
|
||||
a2EnglishId: '651dd7e01d697d0aab7833b7',
|
||||
b1EnglishId: '66607e53317411dd5e8aae21',
|
||||
a2SpanishId: '681a6b22e5a782fe3459984a',
|
||||
a1ChineseId: '68f1268149f045a650d4229e',
|
||||
a2ChineseId: '682c3153086dd7cabe7f48bc'
|
||||
export const certToIdMap: Record<Certification, string> = {
|
||||
// Legacy certifications
|
||||
[Certification.LegacyFrontEnd]: '561add10cb82ac38a17513be',
|
||||
[Certification.JsAlgoDataStruct]: '561abd10cb81ac38a17513bc',
|
||||
[Certification.LegacyBackEnd]: '660add10cb82ac38a17513be',
|
||||
[Certification.LegacyDataVis]: '561add10cb82ac39a17513bc',
|
||||
[Certification.LegacyInfoSecQa]: '561add10cb82ac38a17213bc',
|
||||
[Certification.LegacyFullStack]: '561add10cb82ac38a17213bd',
|
||||
|
||||
// Current certifications
|
||||
[Certification.RespWebDesign]: '561add10cb82ac38a17513bc',
|
||||
[Certification.JsAlgoDataStructNew]: '658180220947283cdc0689ce',
|
||||
[Certification.FrontEndDevLibs]: '561acd10cb82ac38a17513bc',
|
||||
[Certification.DataVis]: '5a553ca864b52e1d8bceea14',
|
||||
[Certification.BackEndDevApis]: '561add10cb82ac38a17523bc',
|
||||
[Certification.QualityAssurance]: '5e611829481575a52dc59c0e',
|
||||
[Certification.InfoSec]: '5e6021435ac9d0ecd8b94b00',
|
||||
[Certification.SciCompPy]: '5e44431b903586ffb414c951',
|
||||
[Certification.DataAnalysisPy]: '5e46fc95ac417301a38fb934',
|
||||
[Certification.MachineLearningPy]: '5e46fc95ac417301a38fb935',
|
||||
[Certification.RelationalDb]: '606243f50267e718b1e755f4',
|
||||
[Certification.CollegeAlgebraPy]: '61531b20cc9dfa2741a5b800',
|
||||
[Certification.FoundationalCSharp]: '647f7da207d29547b3bee1ba',
|
||||
[Certification.A2English]: '651dd7e01d697d0aab7833b7',
|
||||
|
||||
// Upcoming certifications
|
||||
[Certification.RespWebDesignV9]: '68db314d3c11a8bff07c7535',
|
||||
[Certification.JsV9]: '68c4069c1ef859270e17c495',
|
||||
[Certification.FrontEndDevLibsV9]: '68e008aa5f80c6099d47b3a2',
|
||||
[Certification.PythonV9]: '68e6bd5020effa1586e79855',
|
||||
[Certification.RelationalDbV9]: '68e6bd5120effa1586e79856',
|
||||
[Certification.BackEndDevApisV9]: '68e6bd5120effa1586e79857',
|
||||
[Certification.FullStackDeveloperV9]: '64514fda6c245de4d11eb7bb',
|
||||
[Certification.B1English]: '66607e53317411dd5e8aae21',
|
||||
[Certification.A2Spanish]: '681a6b22e5a782fe3459984a',
|
||||
[Certification.A2Chinese]: '682c3153086dd7cabe7f48bc',
|
||||
[Certification.A1Chinese]: '68f1268149f045a650d4229e'
|
||||
};
|
||||
|
||||
export const completionHours = {
|
||||
@@ -248,31 +253,6 @@ export const superBlockCertTypeMap = {
|
||||
[SuperBlocks.A2English]: certTypes.a2English
|
||||
};
|
||||
|
||||
export const certTypeIdMap = {
|
||||
[certTypes.frontEnd]: certIds.legacyFrontEndChallengeId,
|
||||
[certTypes.backEnd]: certIds.legacyBackEndChallengeId,
|
||||
[certTypes.dataVis]: certIds.legacyDataVisId,
|
||||
[certTypes.infosecQa]: certIds.legacyInfosecQaId,
|
||||
[certTypes.fullStack]: certIds.legacyFullStackId,
|
||||
[certTypes.respWebDesign]: certIds.respWebDesignId,
|
||||
[certTypes.respWebDesignV9]: certIds.respWebDesignV9Id,
|
||||
[certTypes.frontEndDevLibs]: certIds.frontEndDevLibsId,
|
||||
[certTypes.jsAlgoDataStruct]: certIds.jsAlgoDataStructId,
|
||||
[certTypes.dataVis2018]: certIds.dataVis2018Id,
|
||||
[certTypes.apisMicroservices]: certIds.apisMicroservicesId,
|
||||
[certTypes.qaV7]: certIds.qaV7Id,
|
||||
[certTypes.infosecV7]: certIds.infosecV7Id,
|
||||
[certTypes.sciCompPyV7]: certIds.sciCompPyV7Id,
|
||||
[certTypes.dataAnalysisPyV7]: certIds.dataAnalysisPyV7Id,
|
||||
[certTypes.machineLearningPyV7]: certIds.machineLearningPyV7Id,
|
||||
[certTypes.relationalDatabaseV8]: certIds.relationalDatabaseV8Id,
|
||||
[certTypes.collegeAlgebraPyV8]: certIds.collegeAlgebraPyV8Id,
|
||||
[certTypes.foundationalCSharpV8]: certIds.foundationalCSharpV8Id,
|
||||
[certTypes.jsAlgoDataStructV8]: certIds.jsAlgoDataStructV8Id,
|
||||
[certTypes.javascriptV9]: certIds.javascriptV9Id,
|
||||
[certTypes.a2English]: certIds.a2EnglishId
|
||||
};
|
||||
|
||||
// TODO: use i18n keys instead of hardcoded titles
|
||||
export const certToTitleMap: Record<Certification, string> = {
|
||||
// Legacy certifications
|
||||
|
||||
Reference in New Issue
Block a user