diff --git a/tools/scripts/build/build-external-curricula-data-v2.test.ts b/tools/scripts/build/build-external-curricula-data-v2.test.ts index 1ad4930a40b..0154bc582e9 100644 --- a/tools/scripts/build/build-external-curricula-data-v2.test.ts +++ b/tools/scripts/build/build-external-curricula-data-v2.test.ts @@ -20,7 +20,8 @@ import { type GeneratedBlockBasedCurriculumProps, type GeneratedChapterBasedCurriculumProps, type ChapterBasedCurriculumIntros, - orderedSuperBlockInfo + orderedSuperBlockInfo, + OrderedSuperBlocks } from './build-external-curricula-data-v2'; const VERSION = 'v2'; @@ -55,16 +56,29 @@ describe('external curriculum data build', () => { }); test('the available-superblocks file should have the correct structure', async () => { + const filteredSuperBlockStages: string[] = Object.keys(SuperBlockStage) + .filter(key => isNaN(Number(key))) // Filter out numeric keys to get only the names + .filter(name => name !== 'Upcoming' && name !== 'Next') // Filter out 'Upcoming' and 'Next' + .map(name => name.toLowerCase()); + const validateAvailableSuperBlocks = availableSuperBlocksValidator(); - const availableSuperblocks: unknown = JSON.parse( + const availableSuperblocks = JSON.parse( await fs.promises.readFile( `${clientStaticPath}/curriculum-data/${VERSION}/available-superblocks.json`, 'utf-8' ) - ); + ) as { superblocks: OrderedSuperBlocks }; const result = validateAvailableSuperBlocks(availableSuperblocks); + expect(Object.keys(availableSuperblocks.superblocks)).toHaveLength( + filteredSuperBlockStages.length + ); + + expect(Object.keys(availableSuperblocks.superblocks)).toEqual( + expect.arrayContaining(filteredSuperBlockStages) + ); + if (result.error) { throw Error( `file: available-superblocks.json @@ -263,23 +277,35 @@ ${result.error.message}`); }); test('All public SuperBlocks should be present in the SuperBlock object', () => { - const stages = Object.keys(orderedSuperBlockInfo).map( - key => Number(key) as SuperBlockStage - ); + // Create a mapping from string to shared/config SuperBlockStage enum value + // so we can look up the enum value by string. + const superBlockStageStringMap: Record = { + core: SuperBlockStage.Core, + english: SuperBlockStage.English, + professional: SuperBlockStage.Professional, + extra: SuperBlockStage.Extra, + legacy: SuperBlockStage.Legacy, + upcoming: SuperBlockStage.Upcoming, + next: SuperBlockStage.Next + }; - expect(stages).not.toContain(SuperBlockStage.Next); - expect(stages).not.toContain(SuperBlockStage.Upcoming); + const stages = Object.keys(orderedSuperBlockInfo); + + expect(stages).not.toContain('next'); + expect(stages).not.toContain('upcoming'); for (const stage of stages) { const superBlockDashedNames = orderedSuperBlockInfo[stage].map( superBlock => superBlock.dashedName ); + const stageValueInNum = superBlockStageStringMap[stage]; + expect(superBlockDashedNames).toEqual( - expect.arrayContaining(superBlockStages[stage]) + expect.arrayContaining(superBlockStages[stageValueInNum]) ); expect(superBlockDashedNames).toHaveLength( - superBlockStages[stage].length + superBlockStages[stageValueInNum].length ); } }); diff --git a/tools/scripts/build/build-external-curricula-data-v2.ts b/tools/scripts/build/build-external-curricula-data-v2.ts index 82b9b47cf83..dd98c7699ef 100644 --- a/tools/scripts/build/build-external-curricula-data-v2.ts +++ b/tools/scripts/build/build-external-curricula-data-v2.ts @@ -2,10 +2,7 @@ import { mkdirSync, writeFileSync, readFileSync } from 'fs'; import { resolve, dirname } from 'path'; import { submitTypes } from '../../../shared/config/challenge-types'; import { type ChallengeNode } from '../../../client/src/redux/prop-types'; -import { - SuperBlocks, - SuperBlockStage -} from '../../../shared/config/curriculum'; +import { SuperBlocks } from '../../../shared/config/curriculum'; import fullStackSuperBlockStructure from '../../../curriculum/superblock-structure/full-stack.json'; import type { Chapter } from '../../../shared/config/chapters'; @@ -85,6 +82,21 @@ interface GeneratedBlock { meta: Record; } +// This enum is based on the `SuperBlockStage` enum in shared/config, +// but with string value instead of number. +enum SuperBlockStage { + Core = 'core', + English = 'english', + Professional = 'professional', + Extra = 'extra', + Legacy = 'legacy' +} + +export type OrderedSuperBlocks = Record< + string, + Array<{ dashedName: SuperBlocks; public: boolean; title: string }> +>; + const ver = 'v2'; const staticFolderPath = resolve(__dirname, '../../../client/static'); @@ -97,10 +109,7 @@ const intros = JSON.parse( readFileSync(blockIntroPath, 'utf-8') ) as CurriculumIntros; -export const orderedSuperBlockInfo: Record< - string, - Array<{ dashedName: SuperBlocks; public: boolean; title: string }> -> = { +export const orderedSuperBlockInfo: OrderedSuperBlocks = { [SuperBlockStage.Core]: [ { dashedName: SuperBlocks.FullStackDeveloper,