diff --git a/api/src/routes/certificate.test.ts b/api/src/routes/certificate.test.ts index 2a33fb477c2..46380bf0100 100644 --- a/api/src/routes/certificate.test.ts +++ b/api/src/routes/certificate.test.ts @@ -8,6 +8,7 @@ import { superRequest } from '../../jest.utils'; import { SHOW_UPCOMING_CHANGES } from '../utils/env'; +import { getFallbackFullStackDate } from './certificate'; describe('certificate routes', () => { setupServer(); @@ -629,3 +630,50 @@ describe('certificate routes', () => { }); }); }); + +const fullStackChallenges = [ + { + completedDate: 1585210952511, + id: '5a553ca864b52e1d8bceea14' + }, + { + completedDate: 1585210952511, + id: '561add10cb82ac38a17513bc' + }, + { + completedDate: 1588665778679, + id: '561acd10cb82ac38a17513bc' + }, + { + completedDate: 1685210952511, + id: '561abd10cb81ac38a17513bc' + }, + { + completedDate: 1585210952511, + id: '561add10cb82ac38a17523bc' + }, + { + completedDate: 1588665778679, + id: '561add10cb82ac38a17213bc' + } +]; + +describe('helper functions', () => { + describe('getFallbackFullStackDate', () => { + it('should return the date of the latest completed challenge', () => { + expect(getFallbackFullStackDate(fullStackChallenges, 123)).toBe( + 1685210952511 + ); + }); + + it('should fall back to completedDate if no certifications are provided', () => { + expect(getFallbackFullStackDate([], 123)).toBe(123); + }); + + it('should fall back to completedDate if none of the certifications have been completed', () => { + expect( + getFallbackFullStackDate([{ completedDate: 567, id: 'abc' }], 123) + ).toBe(123); + }); + }); +}); diff --git a/api/src/routes/certificate.ts b/api/src/routes/certificate.ts index c117b2556a6..4208923b517 100644 --- a/api/src/routes/certificate.ts +++ b/api/src/routes/certificate.ts @@ -87,10 +87,7 @@ export const protectedCertificateRoutes: FastifyPluginCallbackTypebox = ( async (req, reply) => { const { certSlug } = req.body; - if ( - !assertCertSlugIsKeyofCertSlugTypeMap(certSlug) || - !isCertAllowed(certSlug) - ) { + if (!isKnownCertSlug(certSlug) || !isCertAllowed(certSlug)) { void reply.code(400); return { response: { @@ -302,13 +299,12 @@ export const unprotectedCertificateRoutes: FastifyPluginCallbackTypebox = ( }, async (req, reply) => { try { - let username = req.params.username; + const username = req.params.username.toLowerCase(); const certSlug = req.params.certSlug; - username = username.toLowerCase(); fastify.log.info(`certSlug: ${certSlug}`); - if (!assertCertSlugIsKeyofCertSlugTypeMap(certSlug)) { + if (!isKnownCertSlug(certSlug)) { void reply.code(404); return reply.send({ type: 'info', @@ -436,58 +432,7 @@ export const unprotectedCertificateRoutes: FastifyPluginCallbackTypebox = ( }); } - if (user[certType]) { - const { completedChallenges } = user; - const certChallenge = find( - completedChallenges, - ({ id }) => certId === id - ); - - let { completedDate = Date.now() } = certChallenge || {}; - - // the challenge id has been rotated for isDataVisCert - if (certType === 'isDataVisCert' && !certChallenge) { - const oldDataVisIdChall = find( - completedChallenges, - ({ id }) => oldDataVizId === id - ); - - if (oldDataVisIdChall) { - completedDate = oldDataVisIdChall.completedDate || completedDate; - } - } - - // if fullcert is not found, return the latest completedDate - if (certType === 'isFullStackCert' && !certChallenge) { - completedDate = getFallbackFullStackDate( - completedChallenges, - completedDate - ); - } - - const { username, name } = user; - - if (!user.profileUI.showName) { - void reply.code(200); - return reply.send({ - certSlug, - certTitle, - username, - date: completedDate, - completionTime - }); - } - - void reply.code(200); - return reply.send({ - certSlug, - certTitle, - username, - name, - date: completedDate, - completionTime - }); - } else { + if (!user[certType]) { return reply.send({ messages: [ { @@ -498,6 +443,57 @@ export const unprotectedCertificateRoutes: FastifyPluginCallbackTypebox = ( ] }); } + + const { completedChallenges } = user; + const certChallenge = find( + completedChallenges, + ({ id }) => certId === id + ); + + let { completedDate = Date.now() } = certChallenge || {}; + + // the challenge id has been rotated for isDataVisCert + if (certType === 'isDataVisCert' && !certChallenge) { + const oldDataVisIdChall = find( + completedChallenges, + ({ id }) => oldDataVizId === id + ); + + if (oldDataVisIdChall) { + completedDate = oldDataVisIdChall.completedDate || completedDate; + } + } + + // if fullcert is not found, return the latest completedDate + if (certType === 'isFullStackCert' && !certChallenge) { + completedDate = getFallbackFullStackDate( + completedChallenges, + completedDate + ); + } + + const { name } = user; + + if (!user.profileUI.showName) { + void reply.code(200); + return reply.send({ + certSlug, + certTitle, + username, + date: completedDate, + completionTime + }); + } + + void reply.code(200); + return reply.send({ + certSlug, + certTitle, + username, + name, + date: completedDate, + completionTime + }); } catch (err) { fastify.log.error(err); void reply.code(500); @@ -562,7 +558,7 @@ function hasCompletedTests( ); } -function assertCertSlugIsKeyofCertSlugTypeMap( +function isKnownCertSlug( certSlug: string ): certSlug is keyof typeof certSlugTypeMap { return certSlug in certSlugTypeMap; @@ -711,8 +707,15 @@ function getUserIsCertMap(user: CertI) { }; } -function getFallbackFullStackDate( - completedChallenges: CompletedChallenge[], +/** + * Retrieves the completion date for the full stack certification, if it exists. + * + * @param completedChallenges - The array of completed challenges. + * @param completedDate - The fallback completed date. + * @returns The latest certification date or the completed date if no certification is found. + */ +export function getFallbackFullStackDate( + completedChallenges: { id: string; completedDate: number }[], completedDate: number ) { const chalIds = [ @@ -728,5 +731,5 @@ function getFallbackFullStackDate( .filter(chal => chalIds.includes(chal.id)) .sort((a, b) => b.completedDate - a.completedDate)[0]?.completedDate; - return latestCertDate ? latestCertDate : completedDate; + return latestCertDate ?? completedDate; }