diff --git a/tools/scripts/build/build-external-curricula-data.test.ts b/tools/scripts/build/build-external-curricula-data.test.ts index 2a4d15401c7..a7e525198a5 100644 --- a/tools/scripts/build/build-external-curricula-data.test.ts +++ b/tools/scripts/build/build-external-curricula-data.test.ts @@ -1,5 +1,5 @@ import path from 'path'; -import fs from 'fs'; +import fs, { readFileSync } from 'fs'; import readdirp from 'readdirp'; @@ -8,9 +8,20 @@ import { superblockSchemaValidator, availableSuperBlocksValidator } from './external-data-schema'; -import { orderedSuperBlockInfo } from './build-external-curricula-data'; +import { + type Curriculum, + type CurriculumIntros, + type GeneratedCurriculumProps, + orderedSuperBlockInfo +} from './build-external-curricula-data'; const VERSION = 'v1'; +const intros = JSON.parse( + readFileSync( + path.resolve(__dirname, '../../../client/i18n/locales/english/intro.json'), + 'utf-8' + ) +) as CurriculumIntros; describe('external curriculum data build', () => { const clientStaticPath = path.resolve(__dirname, '../../../client/static'); @@ -52,28 +63,69 @@ ${result.error.message}` } }); - test('the files generated should have the correct schema', async () => { + test('the super block files generated should have the correct schema', async () => { const fileArray = ( await readdirp.promise(`${clientStaticPath}/curriculum-data/${VERSION}`, { - directoryFilter: ['!challenges'] + directoryFilter: ['!challenges'], + fileFilter: entry => { + // The directory contains super block files and other curriculum-related files. + // We're only interested in super block ones. + const superBlocks = Object.values(SuperBlocks); + return superBlocks.includes(entry.basename); + } }) ).map(file => file.path); - fileArray - .filter(fileInArray => fileInArray !== 'available-superblocks.json') - .forEach(fileInArray => { - const fileContent = fs.readFileSync( - `${clientStaticPath}/curriculum-data/${VERSION}/${fileInArray}`, - 'utf-8' - ); + fileArray.forEach(fileInArray => { + const fileContent = fs.readFileSync( + `${clientStaticPath}/curriculum-data/${VERSION}/${fileInArray}`, + 'utf-8' + ); - const result = validateSuperBlock(JSON.parse(fileContent)); + const result = validateSuperBlock(JSON.parse(fileContent)); - if (result.error) { - throw Error(`file: ${fileInArray} + if (result.error) { + throw Error(`file: ${fileInArray} ${result.error.message}`); + } + }); + }); + + test('super blocks and blocks should have the correct data', async () => { + const superBlockFiles = ( + await readdirp.promise(`${clientStaticPath}/curriculum-data/${VERSION}`, { + directoryFilter: ['!challenges'], + fileFilter: entry => { + // The directory contains super block files and other curriculum-related files. + // We're only interested in super block ones. + const superBlocks = Object.values(SuperBlocks); + return superBlocks.includes(entry.basename); } - }); + }) + ).map(file => file.path); + + superBlockFiles.forEach(file => { + const fileContentJson = fs.readFileSync( + `${clientStaticPath}/curriculum-data/${VERSION}/${file}`, + 'utf-8' + ); + + const fileContent = JSON.parse( + fileContentJson + ) as Curriculum; + + const superBlock = Object.keys(fileContent)[0] as SuperBlocks; + + // Randomly pick a block to check its data. + const blocks = Object.keys(fileContent[superBlock].blocks); + const randomBlockIndex = Math.floor(Math.random() * blocks.length); + const randomBlock = blocks[randomBlockIndex]; + + expect(fileContent[superBlock].intro).toEqual(intros[superBlock].intro); + expect(fileContent[superBlock].blocks[randomBlock].desc).toEqual( + intros[superBlock].blocks[randomBlock].intro + ); + }); }); test('All public SuperBlocks should be present in the SuperBlock object', () => { diff --git a/tools/scripts/build/build-external-curricula-data.ts b/tools/scripts/build/build-external-curricula-data.ts index c514920a240..ef8ee21f222 100644 --- a/tools/scripts/build/build-external-curricula-data.ts +++ b/tools/scripts/build/build-external-curricula-data.ts @@ -4,24 +4,26 @@ import { submitTypes } from '../../../shared/config/challenge-types'; import { type ChallengeNode } from '../../../client/src/redux/prop-types'; import { SuperBlocks } from '../../../shared/config/curriculum'; -type Intro = { [keyValue in SuperBlocks]: IntroProps }; +export type CurriculumIntros = { + [keyValue in SuperBlocks]: { + title: string; + intro: string[]; + blocks: Record; + }; +}; + export type Curriculum = { [keyValue in SuperBlocks]: T extends CurriculumProps ? CurriculumProps : GeneratedCurriculumProps; }; -interface IntroProps extends CurriculumProps { - title: string; - intro: string[]; -} - export interface CurriculumProps { intro: string[]; blocks: Record>; } -interface GeneratedCurriculumProps { +export interface GeneratedCurriculumProps { intro: string[]; blocks: Record>>; } @@ -71,6 +73,9 @@ export function buildExtCurriculumData( __dirname, '../../../client/i18n/locales/english/intro.json' ); + const intros = JSON.parse( + readFileSync(blockIntroPath, 'utf-8') + ) as CurriculumIntros; mkdirSync(dataPath, { recursive: true }); @@ -85,7 +90,7 @@ export function buildExtCurriculumData( writeToFile('available-superblocks', { superblocks: orderedSuperBlockInfo.map(x => ({ ...x, - title: getSuperBlockTitle(x.dashedName) + title: intros[x.dashedName].title })) }); @@ -96,7 +101,7 @@ export function buildExtCurriculumData( if (blockNames.length === 0) continue; superBlock[superBlockKey] = {}; - superBlock[superBlockKey].intro = getSuperBlockDescription(superBlockKey); + superBlock[superBlockKey].intro = intros[superBlockKey]['intro']; superBlock[superBlockKey].blocks = {}; for (const blockName of blockNames) { @@ -105,7 +110,7 @@ export function buildExtCurriculumData( >{}; superBlock[superBlockKey]['blocks'][blockName]['desc'] = - getBlockDescription(superBlockKey, blockName); + intros[superBlockKey]['blocks'][blockName]['intro']; superBlock[superBlockKey]['blocks'][blockName]['challenges'] = curriculum[superBlockKey]['blocks'][blockName]['meta']; @@ -131,30 +136,6 @@ export function buildExtCurriculumData( writeFileSync(filePath, JSON.stringify(data, null, 2)); } - function getBlockDescription( - superBlockKeys: SuperBlocks, - blockKey: string - ): string[] { - const intros = JSON.parse(readFileSync(blockIntroPath, 'utf-8')) as Intro; - - return intros[superBlockKeys]['blocks'][blockKey]['intro']; - } - - function getSuperBlockDescription(superBlockKey: SuperBlocks): string[] { - const superBlockIntro = JSON.parse( - readFileSync(blockIntroPath, 'utf-8') - ) as Intro; - return superBlockIntro[superBlockKey]['intro']; - } - - function getSuperBlockTitle(superBlock: SuperBlocks): string { - const superBlocks = JSON.parse( - readFileSync(blockIntroPath, 'utf-8') - ) as Intro; - - return superBlocks[superBlock].title; - } - function getSubmitTypes() { writeFileSync( `${dataPath}/submit-types.json`,