chore(api,client): move most certs to legacy (#63140)

Co-authored-by: Huyen Nguyen <25715018+huyenltnguyen@users.noreply.github.com>
This commit is contained in:
Sem Bauke
2025-11-05 17:51:12 +01:00
committed by GitHub
parent ae9b5e45de
commit f5053b24cf
13 changed files with 123 additions and 107 deletions

View File

@@ -178,7 +178,7 @@ describe('certificate routes', () => {
type: 'info',
message: 'flash.already-claimed',
variables: {
name: 'Responsive Web Design'
name: 'Legacy Responsive Web Design V8'
}
});
@@ -209,7 +209,7 @@ describe('certificate routes', () => {
expect(response.body.response).toStrictEqual({
message: 'flash.incomplete-steps',
type: 'info',
variables: { name: 'Responsive Web Design' }
variables: { name: 'Legacy Responsive Web Design V8' }
});
expect(response.status).toBe(400);
});
@@ -287,7 +287,7 @@ describe('certificate routes', () => {
message: 'flash.cert-claim-success',
type: 'success',
variables: {
name: 'Responsive Web Design',
name: 'Legacy Responsive Web Design V8',
username: 'fcc'
}
},

View File

@@ -60,7 +60,7 @@
}
},
"2022/responsive-web-design": {
"title": "Responsive Web Design",
"title": "Legacy Responsive Web Design V8",
"intro": [
"In this Responsive Web Design Certification, you'll learn the languages that developers use to build webpages: HTML (Hypertext Markup Language) for content, and CSS (Cascading Style Sheets) for design.",
"First, you'll build a cat photo app to learn the basics of HTML and CSS. Later, you'll learn modern techniques like CSS variables by building a penguin, and best practices for accessibility by building a quiz site.",
@@ -217,7 +217,7 @@
}
},
"javascript-algorithms-and-data-structures": {
"title": "Legacy JavaScript Algorithms and Data Structures",
"title": "Legacy JavaScript Algorithms and Data Structures V7",
"intro": [
"While HTML and CSS control the content and styling of a page, JavaScript is used to make it interactive. In the JavaScript Algorithm and Data Structures Certification, you'll learn the fundamentals of JavaScript including variables, arrays, objects, loops, and functions.",
"Once you have the fundamentals down, you'll apply that knowledge by creating algorithms to manipulate strings, factorialize numbers, and even calculate the orbit of the International Space Station.",
@@ -300,7 +300,7 @@
}
},
"javascript-algorithms-and-data-structures-v8": {
"title": "JavaScript Algorithms and Data Structures",
"title": "Legacy JavaScript Algorithms and Data Structures V8",
"intro": [
"Developers use HTML and CSS to control the content and styling of a page. And they use JavaScript to make that page interactive.",
"In this JavaScript Algorithm and Data Structures Certification, you'll learn the JavaScript fundamentals like variables, arrays, objects, loops, functions, the DOM and more.",
@@ -490,7 +490,7 @@
}
},
"front-end-development-libraries": {
"title": "Front End Development Libraries",
"title": "Front End Development Libraries V8",
"intro": [
"Now that you're familiar with HTML, CSS, and JavaScript, level up your skills by learning some of the most popular front end libraries in the industry.",
"In the Front End Development Libraries Certification, you'll learn how to style your site quickly with Bootstrap. You'll also learn how to add logic to your CSS styles and extend them with Sass.",
@@ -553,7 +553,7 @@
}
},
"data-visualization": {
"title": "Data Visualization",
"title": "Data Visualization V8",
"intro": [
"Data is all around us, but it doesn't mean much without shape or context.",
"In the Data Visualization Certification, you'll build charts, graphs, and maps to present different types of data with the D3.js library.",
@@ -588,7 +588,7 @@
}
},
"relational-database": {
"title": "Relational Database",
"title": "Relational Database V8",
"intro": [
"For these courses, you will use real developer tools and software including VS Code, PostgreSQL, and the Linux / Unix command line to complete interactive tutorials and build projects.",
"These courses start off with basic Bash commands. Using the terminal, you will learn everything from navigating and manipulating a file system, scripting in Bash, all the way to advanced usage.",
@@ -696,7 +696,7 @@
}
},
"back-end-development-and-apis": {
"title": "Back End Development and APIs",
"title": "Back End Development and APIs V8",
"intro": [
"Until this point, you've only used JavaScript on the front end to add interactivity to a page, solve algorithm challenges, or build an SPA. But JavaScript can also be used on the back end, or server, to build entire web applications.",
"Today, one of the popular ways to build applications is through microservices, which are small, modular applications that work together to form a larger whole.",

View File

@@ -1194,20 +1194,20 @@
}
},
"title": {
"responsive-web-design": "Responsive Web Design",
"responsive-web-design-cert": "Responsive Web Design Certification",
"javascript-algorithms-and-data-structures": "Legacy JavaScript Algorithms and Data Structures",
"javascript-algorithms-and-data-structures-cert": "Legacy JavaScript Algorithms and Data Structures Certification",
"javascript-algorithms-and-data-structures-v8": "JavaScript Algorithms and Data Structures",
"javascript-algorithms-and-data-structures-v8-cert": "JavaScript Algorithms and Data Structures Certification",
"front-end-development-libraries": "Front End Development Libraries",
"front-end-development-libraries-cert": "Front End Development Libraries Certification",
"data-visualization": "Data Visualization",
"data-visualization-cert": "Data Visualization Certification",
"relational-database-v8": "Relational Database",
"relational-database-v8-cert": "Relational Database Certification",
"back-end-development-and-apis": "Back End Development and APIs",
"back-end-development-and-apis-cert": "Back End Development and APIs Certification",
"responsive-web-design": "Legacy Responsive Web Design V8",
"responsive-web-design-cert": "Legacy Responsive Web Design V8 Certification",
"javascript-algorithms-and-data-structures": "Legacy JavaScript Algorithms and Data Structures V7",
"javascript-algorithms-and-data-structures-cert": "Legacy JavaScript Algorithms and Data Structures V7 Certification",
"javascript-algorithms-and-data-structures-v8": "Legacy JavaScript Algorithms and Data Structures V8",
"javascript-algorithms-and-data-structures-v8-cert": "Legacy JavaScript Algorithms and Data Structures V8 Certification",
"front-end-development-libraries": "Front End Development Libraries V8",
"front-end-development-libraries-cert": "Front End Development Libraries V8 Certification",
"data-visualization": "Data Visualization V8",
"data-visualization-cert": "Data Visualization V8 Certification",
"relational-database-v8": "Relational Database V8",
"relational-database-v8-cert": "Relational Database V8 Certification",
"back-end-development-and-apis": "Back End Development and APIs V8",
"back-end-development-and-apis-cert": "Back End Development and APIs V8 Certification",
"quality-assurance-v7": "Quality Assurance",
"quality-assurance-v7-cert": "Quality Assurance Certification",
"scientific-computing-with-python-v7": "Scientific Computing with Python",

View File

@@ -30,8 +30,16 @@ export const getCertifications = (user: User) => {
return {
hasModernCert:
isA2EnglishCert ||
isRespWebDesignCert ||
isRespWebDesignCertV9 ||
isJavascriptCertV9 ||
isFoundationalCSharpCertV8,
hasLegacyCert:
isFrontEndCert ||
isJsAlgoDataStructCert ||
isBackEndCert ||
isDataVisCert ||
isInfosecQaCert ||
isRespWebDesignCert ||
is2018DataVisCert ||
isFrontEndLibsCert ||
isApisMicroservicesCert ||
@@ -43,15 +51,7 @@ export const getCertifications = (user: User) => {
isMachineLearningPyCertV7 ||
isRelationalDatabaseCertV8 ||
isCollegeAlgebraPyCertV8 ||
isFoundationalCSharpCertV8 ||
isJavascriptCertV9 ||
isJsAlgoDataStructCertV8,
hasLegacyCert:
isFrontEndCert ||
isJsAlgoDataStructCert ||
isBackEndCert ||
isDataVisCert ||
isInfosecQaCert,
isFullStackCert,
currentCerts: [
{
@@ -59,11 +59,6 @@ export const getCertifications = (user: User) => {
title: 'A2 English for Developers Certification',
certSlug: Certification.A2English
},
{
show: isRespWebDesignCert,
title: 'Responsive Web Design Certification',
certSlug: Certification.RespWebDesign
},
{
show: isRespWebDesignCertV9,
title: 'Responsive Web Design Certification',
@@ -74,29 +69,42 @@ export const getCertifications = (user: User) => {
title: 'JavaScript Certification',
certSlug: Certification.JsV9
},
{
show: isFoundationalCSharpCertV8,
title: 'Foundational C# with Microsoft Certification',
certSlug: Certification.FoundationalCSharp
}
],
legacyCerts: [
{
show: isRespWebDesignCert,
title: 'Legacy Responsive Web Design V8 Certification',
certSlug: Certification.RespWebDesign
},
{
show: isJsAlgoDataStructCertV8,
title: 'JavaScript Algorithms and Data Structures Certification',
title:
'Legacy JavaScript Algorithms and Data Structures V8 Certification',
certSlug: Certification.JsAlgoDataStructNew
},
{
show: isFrontEndLibsCert,
title: 'Front End Development Libraries Certification',
title: 'Front End Development Libraries V8 Certification',
certSlug: Certification.FrontEndDevLibs
},
{
show: is2018DataVisCert,
title: 'Data Visualization Certification',
title: 'Data Visualization V8 Certification',
certSlug: Certification.DataVis
},
{
show: isRelationalDatabaseCertV8,
title: 'Relational Database Certification',
title: 'Relational Database V8 Certification',
certSlug: Certification.RelationalDb
},
{
show: isApisMicroservicesCert,
title: 'Back End Development and APIs Certification',
title: 'Back End Development and APIs V8 Certification',
certSlug: Certification.BackEndDevApis
},
{
@@ -129,13 +137,6 @@ export const getCertifications = (user: User) => {
title: 'College Algebra with Python Certification',
certSlug: Certification.CollegeAlgebraPy
},
{
show: isFoundationalCSharpCertV8,
title: 'Foundational C# with Microsoft Certification',
certSlug: Certification.FoundationalCSharp
}
],
legacyCerts: [
{
show: isFrontEndCert,
title: 'Front End Certification',
@@ -143,7 +144,8 @@ export const getCertifications = (user: User) => {
},
{
show: isJsAlgoDataStructCert,
title: 'Legacy JavaScript Algorithms and Data Structures Certification',
title:
'Legacy JavaScript Algorithms and Data Structures V7 Certification',
certSlug: Certification.JsAlgoDataStruct
},
{

View File

@@ -169,8 +169,8 @@ const LegacyFullStack = (props: CertificationSettingsProps) => {
<ul>
<li>{t(`certification.title.${Certification.RespWebDesign}`)}</li>
<li>{t(`certification.title.${Certification.JsAlgoDataStruct}`)}</li>
<li>{t(`certification.title.${Certification.LegacyFrontEnd}`)}</li>
<li>{t(`certification.title.${Certification.LegacyDataVis}`)}</li>
<li>{t(`certification.title.${Certification.FrontEndDevLibs}`)}</li>
<li>{t(`certification.title.${Certification.DataVis}`)}</li>
<li>{t(`certification.title.${Certification.BackEndDevApis}`)}</li>
<li>{t(`certification.title.${Certification.LegacyInfoSecQa}`)}</li>
</ul>

View File

@@ -58,7 +58,7 @@ const CertChallenge = ({
const [isCertified, setIsCertified] = useState(false);
const [userLoaded, setUserLoaded] = useState(false);
const { currentCerts } = getCertifications(user);
const { currentCerts, legacyCerts } = getCertifications(user);
const { username } = user;
const cert = liveCerts.find(x => x.title === title);
@@ -78,15 +78,17 @@ const CertChallenge = ({
superBlockCertTypeMap;
useEffect(() => {
const allCerts = [...currentCerts, ...legacyCerts];
setIsCertified(
currentCerts?.find(
allCerts.find(
(cert: { certSlug: string }) =>
certSlugTypeMapTyped[cert.certSlug] ===
superBlockCertTypeMapTyped[superBlock]
)?.show ?? false
);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [currentCerts]);
}, [currentCerts, legacyCerts]);
const certLocation = `/certification/${username}/${certSlug}`;

View File

@@ -55,7 +55,7 @@ test.describe('When the user has not accepted the Academic Honesty Policy', () =
await page.goto('/settings#cert-responsive-web-design');
const claimCertButton = page.getByRole('button', {
name: 'Claim Certification Responsive Web Design'
name: 'Claim Certification Legacy Responsive Web Design V8'
});
await claimCertButton.click();

View File

@@ -25,7 +25,9 @@ test.describe('Claim a certification - almost certified user', () => {
}) => {
await page.goto('/settings#cert-front-end-development-libraries');
await page
.getByRole('button', { name: 'Claim Certification Front End' })
.getByRole('button', {
name: 'Claim Certification Front End Development Libraries V8'
})
.click();
// verify that an email is sent
await expect(async () => {
@@ -90,14 +92,14 @@ test.describe('Certification page - Non Microsoft', () => {
await expect(linkedinLink).toBeVisible();
await expect(linkedinLink).toHaveAttribute(
'href',
`https://www.linkedin.com/profile/add?startTask=CERTIFICATION_NAME&name=Responsive%20Web%20Design&organizationId=4831032&issueYear=2018&issueMonth=8&certUrl=https://freecodecamp.org/certification/certifieduser/responsive-web-design&certId=certifieduser-rwd`
`https://www.linkedin.com/profile/add?startTask=CERTIFICATION_NAME&name=Legacy%20Responsive%20Web%20Design%20V8&organizationId=4831032&issueYear=2018&issueMonth=8&certUrl=https://freecodecamp.org/certification/certifieduser/responsive-web-design&certId=certifieduser-rwd`
);
const twitterLink = certLink.getByTestId('twitter-share-btn');
await expect(twitterLink).toBeVisible();
await expect(twitterLink).toHaveAttribute(
'href',
`https://twitter.com/intent/tweet?text=I just earned the Responsive%20Web%20Design certification @freeCodeCamp! Check it out here: https://freecodecamp.org/certification/certifieduser/responsive-web-design`
`https://twitter.com/intent/tweet?text=I just earned the Legacy%20Responsive%20Web%20Design%20V8 certification @freeCodeCamp! Check it out here: https://freecodecamp.org/certification/certifieduser/responsive-web-design`
);
const projectLinks = certLink.getByTestId('project-links');

View File

@@ -20,7 +20,9 @@ test.describe('Certification intro page', () => {
await page.goto('/learn/2022/responsive-web-design');
await expect(page).toHaveTitle('Responsive Web Design | freeCodeCamp.org');
await expect(page).toHaveTitle(
'Legacy Responsive Web Design V8 | freeCodeCamp.org'
);
await expect(superBlockText).toBeVisible();
await expect(firstBlockText).toBeVisible();
await expect(secondBlockText).not.toBeVisible();

View File

@@ -4,27 +4,34 @@ import translations from '../client/i18n/locales/english/translations.json';
const certs = [
{
name: 'Responsive Web Design',
name: 'Foundational C# with Microsoft',
url: '/certification/certifieduser/foundational-c-sharp-with-microsoft'
}
];
const legacyCerts = [
{
name: 'Legacy Responsive Web Design V8',
url: '/certification/certifieduser/responsive-web-design'
},
{
name: 'JavaScript Algorithms and Data Structures',
name: 'Legacy JavaScript Algorithms and Data Structures V8',
url: '/certification/certifieduser/javascript-algorithms-and-data-structures-v8'
},
{
name: 'Front End Development Libraries',
name: 'Front End Development Libraries V8',
url: '/certification/certifieduser/front-end-development-libraries'
},
{
name: 'Data Visualization',
name: 'Data Visualization V8',
url: '/certification/certifieduser/data-visualization'
},
{
name: 'Relational Database',
name: 'Relational Database V8',
url: '/certification/certifieduser/relational-database-v8'
},
{
name: 'Back End Development and APIs',
name: 'Back End Development and APIs V8',
url: '/certification/certifieduser/back-end-development-and-apis'
},
{
@@ -51,19 +58,12 @@ const certs = [
name: 'College Algebra with Python',
url: '/certification/certifieduser/college-algebra-with-python-v8'
},
{
name: 'Foundational C# with Microsoft',
url: '/certification/certifieduser/foundational-c-sharp-with-microsoft'
}
];
const legacyCerts = [
{
name: 'Legacy Front End',
url: '/certification/certifieduser/legacy-front-end'
},
{
name: 'Legacy JavaScript Algorithms and Data Structures',
name: 'Legacy JavaScript Algorithms and Data Structures V7',
url: '/certification/certifieduser/javascript-algorithms-and-data-structures'
},
{
@@ -78,7 +78,10 @@ const legacyCerts = [
name: 'Legacy Information Security and Quality Assurance',
url: '/certification/certifieduser/information-security-and-quality-assurance'
},
{ name: 'Legacy Full Stack', url: '/certification/certifieduser/full-stack' }
{
name: 'Legacy Full Stack',
url: '/certification/certifieduser/full-stack'
}
];
test.describe('Profile component', () => {

View File

@@ -218,17 +218,17 @@ test.describe('JavaScript projects can be submitted and then viewed in /settings
await page
.getByRole('button', {
name: 'Claim Certification Legacy JavaScript Algorithms and Data Structures'
name: 'Claim Certification Legacy JavaScript Algorithms and Data Structures V7'
})
.click();
await alertToBeVisible(
page,
'@developmentuser, you have successfully claimed the Legacy JavaScript Algorithms and Data Structures Certification! Congratulations on behalf of the freeCodeCamp.org team!'
'@developmentuser, you have successfully claimed the Legacy JavaScript Algorithms and Data Structures V7 Certification! Congratulations on behalf of the freeCodeCamp.org team!'
);
const showCertLink = page.getByRole('link', {
name: 'Show Certification Legacy JavaScript Algorithms and Data Structures'
name: 'Show Certification Legacy JavaScript Algorithms and Data Structures V7'
});
await expect(showCertLink).toBeVisible();
await expect(showCertLink).toHaveAttribute(

View File

@@ -2,7 +2,10 @@ import { execSync } from 'child_process';
import { test, expect } from '@playwright/test';
import translations from '../client/i18n/locales/english/translations.json';
import { currentCertifications } from '../shared/config/certification-settings';
import {
currentCertifications,
legacyCertifications as legacyCerts
} from '../shared/config/certification-settings';
import { alertToBeVisible } from './utils/alerts';
const settingsTestIds = {
@@ -23,6 +26,10 @@ const settingsObject = {
};
const certifications = [
translations.certification.title['foundational-c-sharp-with-microsoft']
];
const legacyCertifications = [
translations.certification.title['responsive-web-design'],
translations.certification.title[
'javascript-algorithms-and-data-structures-v8'
@@ -37,10 +44,6 @@ const certifications = [
translations.certification.title['information-security-v7'],
translations.certification.title['machine-learning-with-python-v7'],
translations.certification.title['college-algebra-with-python-v8'],
translations.certification.title['foundational-c-sharp-with-microsoft']
];
const legacyCertifications = [
translations.certification.title['legacy-front-end'],
translations.certification.title['legacy-back-end'],
translations.certification.title['legacy-data-visualization'],
@@ -310,7 +313,7 @@ test.describe('Settings - New User', () => {
});
const claimRwdCertButton = page.getByRole('button', {
name: 'Claim Certification Responsive Web Design'
name: 'Claim Certification Legacy Responsive Web Design V8'
});
// Buttons for normal certs are enabled
@@ -327,7 +330,8 @@ test.describe('Setting - Hash Navigation', () => {
test('should scroll to certification sections when navigating with hash', async ({
page
}) => {
for (const certSlug of currentCertifications) {
const allCerts = [...currentCertifications, ...legacyCerts];
for (const certSlug of allCerts) {
await page.goto(`/settings#cert-${certSlug}`);
// Wait for scroll animation

View File

@@ -54,29 +54,29 @@ export function isCertification(x: string): x is Certification {
// "Current" certifications are the subset of standard certifications that are
// live and not legacy.
export const currentCertifications = [
Certification.RespWebDesign,
Certification.JsAlgoDataStructNew,
Certification.FrontEndDevLibs,
Certification.DataVis,
Certification.RelationalDb,
Certification.BackEndDevApis,
Certification.QualityAssurance,
Certification.SciCompPy,
Certification.DataAnalysisPy,
Certification.InfoSec,
Certification.MachineLearningPy,
Certification.CollegeAlgebraPy,
Certification.FoundationalCSharp
] as const;
// "Legacy" certifications are another class of standard certifications. They're
// still live and claimable, but some parts of the UI handle them differently.
export const legacyCertifications = [
Certification.LegacyFrontEnd,
Certification.RespWebDesign,
Certification.JsAlgoDataStruct,
Certification.FrontEndDevLibs,
Certification.DataVis,
Certification.BackEndDevApis,
Certification.LegacyInfoSecQa,
Certification.LegacyFrontEnd,
Certification.JsAlgoDataStructNew,
Certification.LegacyBackEnd,
Certification.LegacyDataVis,
Certification.LegacyInfoSecQa
Certification.RelationalDb,
Certification.QualityAssurance,
Certification.SciCompPy,
Certification.DataAnalysisPy,
Certification.InfoSec,
Certification.MachineLearningPy,
Certification.CollegeAlgebraPy
] as const;
// The Legacy Full Stack certification can only be claimed when specific
@@ -275,22 +275,23 @@ export const certTypeTitleMap = {
[certTypes.dataVis]: 'Legacy Data Visualization',
[certTypes.infosecQa]: 'Legacy Information Security and Quality Assurance',
[certTypes.fullStack]: 'Legacy Full Stack',
[certTypes.respWebDesign]: 'Responsive Web Design',
[certTypes.respWebDesign]: 'Legacy Responsive Web Design V8',
[certTypes.respWebDesignV9]: 'Responsive Web Design',
[certTypes.frontEndDevLibs]: 'Front End Development Libraries',
[certTypes.frontEndDevLibs]: 'Front End Development Libraries V8',
[certTypes.jsAlgoDataStruct]:
'Legacy JavaScript Algorithms and Data Structures',
[certTypes.dataVis2018]: 'Data Visualization',
[certTypes.apisMicroservices]: 'Back End Development and APIs',
'Legacy JavaScript Algorithms and Data Structures V7',
[certTypes.dataVis2018]: 'Data Visualization V8',
[certTypes.apisMicroservices]: 'Back End Development and APIs V8',
[certTypes.qaV7]: 'Quality Assurance',
[certTypes.infosecV7]: 'Information Security',
[certTypes.sciCompPyV7]: 'Scientific Computing with Python',
[certTypes.dataAnalysisPyV7]: 'Data Analysis with Python',
[certTypes.machineLearningPyV7]: 'Machine Learning with Python',
[certTypes.relationalDatabaseV8]: 'Relational Database',
[certTypes.relationalDatabaseV8]: 'Relational Database V8',
[certTypes.collegeAlgebraPyV8]: 'College Algebra with Python',
[certTypes.foundationalCSharpV8]: 'Foundational C# with Microsoft',
[certTypes.jsAlgoDataStructV8]: 'JavaScript Algorithms and Data Structures',
[certTypes.jsAlgoDataStructV8]:
'Legacy JavaScript Algorithms and Data Structures V8',
[certTypes.javascriptV9]: 'JavaScript',
[certTypes.a2English]: 'A2 English for Developers'
};