fix: use keys in curriculum.json (#45407)

* feat: add function to map from path to superblock

* fix: use superblocks as keys in curriculum.json

* fix: handle new superblock names

* fix: keep deleting relational-database
This commit is contained in:
Oliver Eyton-Williams
2022-03-10 21:41:33 +01:00
committed by GitHub
parent f485bc1c16
commit 8ee9b5761a
6 changed files with 97 additions and 17 deletions

View File

@ -41,7 +41,7 @@ exports.buildChallenges = async function buildChallenges() {
// temp removal of rdbms from production
if (deploymentEnv !== 'staging') {
delete curriculum['13-relational-databases'];
delete curriculum['relational-database'];
}
const superBlocks = Object.keys(curriculum);

View File

@ -18,7 +18,7 @@ const {
const { isAuditedCert } = require('../utils/is-audited');
const { createPoly } = require('../utils/polyvinyl');
const { dasherize } = require('../utils/slugs');
const { getSuperOrder } = require('./utils');
const { getSuperOrder, getSuperBlockFromDir } = require('./utils');
const access = util.promisify(fs.access);
@ -172,7 +172,7 @@ exports.getChallengesForLang = async function getChallengesForLang(lang) {
);
};
async function buildBlocks({ basename: blockName }, curriculum, baseDir) {
async function buildBlocks({ basename: blockName }, curriculum, superBlock) {
const metaPath = path.resolve(
__dirname,
`./challenges/_meta/${blockName}/meta.json`
@ -190,37 +190,41 @@ async function buildBlocks({ basename: blockName }, curriculum, baseDir) {
if (!isUpcomingChange || showUpcomingChanges) {
// add the block to the superBlock
const blockInfo = { meta: blockMeta, challenges: [] };
curriculum[baseDir].blocks[blockName] = blockInfo;
curriculum[superBlock].blocks[blockName] = blockInfo;
}
} catch (e) {
curriculum['00-certifications'].blocks[blockName] = { challenges: [] };
if (e.code !== 'MODULE_NOT_FOUND') {
throw e;
}
curriculum['certifications'].blocks[blockName] = { challenges: [] };
}
}
async function buildSuperBlocks({ path, fullPath }, curriculum) {
const baseDir = getBaseDir(path);
curriculum[baseDir] = { blocks: {} };
const superBlock = getSuperBlockFromDir(getBaseDir(path));
curriculum[superBlock] = { blocks: {} };
const cb = (file, curriculum) => buildBlocks(file, curriculum, baseDir);
const cb = (file, curriculum) => buildBlocks(file, curriculum, superBlock);
return walk(fullPath, curriculum, { depth: 1, type: 'directories' }, cb);
}
async function buildChallenges({ path: filePath }, curriculum, lang) {
// path is relative to getChallengesDirForLang(lang)
const block = getBlockNameFromPath(filePath);
const baseDir = getBaseDir(filePath);
const superBlockDir = getBaseDir(filePath);
const superBlock = getSuperBlockFromDir(superBlockDir);
let challengeBlock;
// TODO: this try block and process exit can all go once errors terminate the
// tests correctly.
try {
challengeBlock = curriculum[baseDir].blocks[block];
challengeBlock = curriculum[superBlock].blocks[block];
if (!challengeBlock) {
// this should only happen when a isUpcomingChange block is skipped
return;
}
} catch (e) {
console.log(`failed to create superBlock from ${baseDir}`);
console.log(`failed to create superBlock from ${superBlockDir}`);
// eslint-disable-next-line no-process-exit
process.exit(1);
}

View File

@ -53,4 +53,29 @@ function getSuperOrder(
return order;
}
const directoryToSuperblock = {
'00-certifications': 'certifications', // treating certifications as a superblock for simplicity
'01-responsive-web-design': 'responsive-web-design',
'02-javascript-algorithms-and-data-structures':
'javascript-algorithms-and-data-structures',
'03-front-end-development-libraries': 'front-end-development-libraries',
'04-data-visualization': 'data-visualization',
'05-back-end-development-and-apis': 'back-end-development-and-apis',
'06-quality-assurance': 'quality-assurance',
'07-scientific-computing-with-python': 'scientific-computing-with-python',
'08-data-analysis-with-python': 'data-analysis-with-python',
'09-information-security': 'information-security',
'10-coding-interview-prep': 'coding-interview-prep',
'11-machine-learning-with-python': 'machine-learning-with-python',
'13-relational-databases': 'relational-database',
'14-responsive-web-design-22': '2022/responsive-web-design'
};
function getSuperBlockFromDir(dir) {
const superBlock = directoryToSuperblock[dir];
if (!superBlock) throw Error(`${dir} does not map to a superblock`);
return directoryToSuperblock[dir];
}
exports.getSuperOrder = getSuperOrder;
exports.getSuperBlockFromDir = getSuperBlockFromDir;

View File

@ -1,4 +1,10 @@
import { getSuperOrder } from './utils';
// utils are not typed (yet), so we have to disable some checks
/* eslint-disable @typescript-eslint/no-unsafe-call */
/* eslint-disable @typescript-eslint/no-unsafe-return */
import fs from 'fs';
import path from 'path';
import { SuperBlocks } from '../config/certification-settings';
import { getSuperOrder, getSuperBlockFromDir } from './utils';
describe('getSuperOrder', () => {
it('returns a number for valid superblocks', () => {
@ -86,3 +92,48 @@ describe('getSuperOrder', () => {
).toBe(12);
});
});
describe('getSuperBlockFromPath', () => {
const directories = fs.readdirSync(
path.join(__dirname, './challenges/english')
);
it('handles all the directories in ./challenges/english', () => {
expect.assertions(14);
for (const directory of directories) {
expect(() => getSuperBlockFromDir(directory)).not.toThrow();
}
});
it("returns valid superblocks (or 'certifications') for all valid arguments", () => {
expect.assertions(14);
const superBlockPaths = directories.filter(x => x !== '00-certifications');
for (const directory of superBlockPaths) {
expect(Object.values(SuperBlocks)).toContain(
getSuperBlockFromDir(directory)
);
}
expect(getSuperBlockFromDir('00-certifications')).toBe('certifications');
});
it("returns all valid superblocks (and 'certifications')", () => {
expect.assertions(1);
const superBlocks = new Set();
for (const directory of directories) {
superBlocks.add(getSuperBlockFromDir(directory));
}
// + 1 for 'certifications'
expect(superBlocks.size).toBe(Object.values(SuperBlocks).length + 1);
});
it('throws if a directory is unknown', () => {
expect.assertions(1);
expect(() => getSuperBlockFromDir('unknown')).toThrow();
});
});

View File

@ -9,7 +9,7 @@ exports.buildMobileCurriculum = function buildMobileCurriculum(json) {
function writeAndParseCurriculumJson(curriculum) {
const superBlockKeys = Object.keys(curriculum).filter(
key => key !== '00-certifications'
key => key !== 'certifications'
);
writeToFile('availableSuperblocks', { superblocks: superBlockKeys });
@ -34,9 +34,8 @@ exports.buildMobileCurriculum = function buildMobileCurriculum(json) {
}
function writeToFile(filename, json) {
fs.writeFileSync(
`${mobileStaticPath}/mobile/${filename}.json`,
JSON.stringify(json, null, 2)
);
const fullPath = `${mobileStaticPath}/mobile/${filename}.json`;
fs.mkdirSync(path.dirname(fullPath), { recursive: true });
fs.writeFileSync(fullPath, JSON.stringify(json, null, 2));
}
};

View File

@ -4,6 +4,7 @@
"client/plugins/**/*",
"client/src/**/*",
"client/utils/**/*",
"curriculum/*.test.ts",
"tools/challenge-helper-scripts/**/*.ts",
"tools/scripts/**/*.ts"
],