feat: add block description to mobile curriculum (#45370)
* feat: add block description to mobile curriculum * feat: add superblock names
This commit is contained in:
@ -177,10 +177,15 @@ async function buildBlocks({ basename: blockName }, curriculum, superBlock) {
|
||||
__dirname,
|
||||
`./challenges/_meta/${blockName}/meta.json`
|
||||
);
|
||||
let blockMeta;
|
||||
try {
|
||||
blockMeta = require(metaPath);
|
||||
|
||||
if (fs.existsSync(metaPath)) {
|
||||
// try to read the file, if the meta path does not exist it should be a certification.
|
||||
// As they do not have meta files.
|
||||
|
||||
const blockMeta = JSON.parse(fs.readFileSync(metaPath));
|
||||
|
||||
const { isUpcomingChange } = blockMeta;
|
||||
|
||||
if (typeof isUpcomingChange !== 'boolean') {
|
||||
throw Error(
|
||||
`meta file at ${metaPath} is missing 'isUpcomingChange', it must be 'true' or 'false'`
|
||||
@ -192,10 +197,7 @@ async function buildBlocks({ basename: blockName }, curriculum, superBlock) {
|
||||
const blockInfo = { meta: blockMeta, challenges: [] };
|
||||
curriculum[superBlock].blocks[blockName] = blockInfo;
|
||||
}
|
||||
} catch (e) {
|
||||
if (e.code !== 'MODULE_NOT_FOUND') {
|
||||
throw e;
|
||||
}
|
||||
} else {
|
||||
curriculum['certifications'].blocks[blockName] = { challenges: [] };
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,10 @@ const path = require('path');
|
||||
|
||||
exports.buildMobileCurriculum = function buildMobileCurriculum(json) {
|
||||
const mobileStaticPath = path.resolve(__dirname, '../../../client/static');
|
||||
const blockIntroPath = path.resolve(
|
||||
__dirname,
|
||||
'../../../client/i18n/locales/english/intro.json'
|
||||
);
|
||||
|
||||
fs.mkdirSync(`${mobileStaticPath}/mobile`, { recursive: true });
|
||||
writeAndParseCurriculumJson(json);
|
||||
@ -12,7 +16,14 @@ exports.buildMobileCurriculum = function buildMobileCurriculum(json) {
|
||||
key => key !== 'certifications'
|
||||
);
|
||||
|
||||
writeToFile('availableSuperblocks', { superblocks: superBlockKeys });
|
||||
writeToFile('availableSuperblocks', {
|
||||
// removing "/" as it will create an extra sub-path when accessed via an endpoint
|
||||
|
||||
superblocks: [
|
||||
superBlockKeys.map(key => key.replace(/\//, '-')),
|
||||
getSuperBlockNames(superBlockKeys)
|
||||
]
|
||||
});
|
||||
|
||||
for (let i = 0; i < superBlockKeys.length; i++) {
|
||||
const superBlock = {};
|
||||
@ -25,16 +36,32 @@ exports.buildMobileCurriculum = function buildMobileCurriculum(json) {
|
||||
|
||||
for (let j = 0; j < blockNames.length; j++) {
|
||||
superBlock[superBlockKeys[i]]['blocks'][blockNames[j]] = {};
|
||||
|
||||
superBlock[superBlockKeys[i]]['blocks'][blockNames[j]]['desc'] =
|
||||
getBlockDescription(superBlockKeys[i], blockNames[j]);
|
||||
|
||||
superBlock[superBlockKeys[i]]['blocks'][blockNames[j]]['challenges'] =
|
||||
curriculum[superBlockKeys[i]]['blocks'][blockNames[j]]['meta'];
|
||||
}
|
||||
|
||||
writeToFile(superBlockKeys[i], superBlock);
|
||||
writeToFile(superBlockKeys[i].replace(/\//, '-'), superBlock);
|
||||
}
|
||||
}
|
||||
|
||||
function writeToFile(filename, json) {
|
||||
const fullPath = `${mobileStaticPath}/mobile/${filename}.json`;
|
||||
function getBlockDescription(superBlockKey, blockKey) {
|
||||
const intros = JSON.parse(fs.readFileSync(blockIntroPath));
|
||||
|
||||
return intros[superBlockKey]['blocks'][blockKey]['intro'];
|
||||
}
|
||||
|
||||
function getSuperBlockNames(superBlockKeys) {
|
||||
const superBlocks = JSON.parse(fs.readFileSync(blockIntroPath));
|
||||
|
||||
return superBlockKeys.map(key => superBlocks[key].title);
|
||||
}
|
||||
|
||||
function writeToFile(fileName, json) {
|
||||
const fullPath = `${mobileStaticPath}/mobile/${fileName}.json`;
|
||||
fs.mkdirSync(path.dirname(fullPath), { recursive: true });
|
||||
fs.writeFileSync(fullPath, JSON.stringify(json, null, 2));
|
||||
}
|
||||
|
53
tools/scripts/build/mobile-curriculum.test.js
Normal file
53
tools/scripts/build/mobile-curriculum.test.js
Normal file
@ -0,0 +1,53 @@
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
const { AssertionError } = require('chai');
|
||||
const { getChallengesForLang } = require('../../../curriculum/getChallenges');
|
||||
const { buildMobileCurriculum } = require('./build-mobile-curriculum');
|
||||
const { mobileSchemaValidator } = require('./mobileSchema');
|
||||
|
||||
describe('mobile curriculum build', () => {
|
||||
const mobileStaticPath = path.resolve(__dirname, '../../../client/static');
|
||||
const blockIntroPath = path.resolve(
|
||||
__dirname,
|
||||
'../../../client/i18n/locales/english/intro.json'
|
||||
);
|
||||
|
||||
const validateMobileSuperBlock = mobileSchemaValidator();
|
||||
|
||||
let curriculum;
|
||||
|
||||
beforeAll(async () => {
|
||||
curriculum = await getChallengesForLang('english');
|
||||
await buildMobileCurriculum(curriculum);
|
||||
}, 20000);
|
||||
|
||||
test('the mobile curriculum should have a static folder with multiple files', () => {
|
||||
expect(fs.existsSync(`${mobileStaticPath}/mobile`)).toBe(true);
|
||||
|
||||
expect(fs.readdirSync(`${mobileStaticPath}/mobile`).length).toBeGreaterThan(
|
||||
0
|
||||
);
|
||||
});
|
||||
|
||||
test('the mobile curriculum should have access to the intro.json file', () => {
|
||||
expect(fs.existsSync(blockIntroPath)).toBe(true);
|
||||
});
|
||||
|
||||
test('the files generated should have the correct schema', () => {
|
||||
const fileArray = fs.readdirSync(`${mobileStaticPath}/mobile`);
|
||||
|
||||
fileArray
|
||||
.filter(fileInArray => fileInArray !== 'availableSuperblocks.json')
|
||||
.forEach(fileInArray => {
|
||||
const fileContent = fs.readFileSync(
|
||||
`${mobileStaticPath}/mobile/${fileInArray}`
|
||||
);
|
||||
|
||||
const result = validateMobileSuperBlock(JSON.parse(fileContent));
|
||||
|
||||
if (result.error) {
|
||||
throw new AssertionError(result.error, `file: ${fileInArray}`);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
32
tools/scripts/build/mobileSchema.js
Normal file
32
tools/scripts/build/mobileSchema.js
Normal file
@ -0,0 +1,32 @@
|
||||
const Joi = require('joi');
|
||||
|
||||
const blockSchema = Joi.object({}).keys({
|
||||
desc: Joi.array().min(1),
|
||||
challenges: Joi.object({}).keys({
|
||||
name: Joi.string(),
|
||||
isUpcomingChange: Joi.bool(),
|
||||
usesMultifileEditor: Joi.bool().optional(),
|
||||
hasEditableBoundaries: Joi.bool().optional(),
|
||||
isBeta: Joi.bool().optional(),
|
||||
dashedName: Joi.string(),
|
||||
order: Joi.number(),
|
||||
time: Joi.string().allow(''),
|
||||
template: Joi.string().allow(''),
|
||||
required: Joi.array(),
|
||||
superBlock: Joi.string(),
|
||||
challengeOrder: Joi.array().items(Joi.array().min(1))
|
||||
})
|
||||
});
|
||||
|
||||
const subSchema = Joi.object({}).keys({
|
||||
blocks: Joi.object({}).pattern(Joi.string(), Joi.object().concat(blockSchema))
|
||||
});
|
||||
|
||||
const schema = Joi.object({}).pattern(
|
||||
Joi.string(),
|
||||
Joi.object().concat(subSchema)
|
||||
);
|
||||
|
||||
exports.mobileSchemaValidator = () => {
|
||||
return superblock => schema.validate(superblock);
|
||||
};
|
Reference in New Issue
Block a user