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:
committed by
GitHub
parent
f485bc1c16
commit
8ee9b5761a
@ -41,7 +41,7 @@ exports.buildChallenges = async function buildChallenges() {
|
|||||||
|
|
||||||
// temp removal of rdbms from production
|
// temp removal of rdbms from production
|
||||||
if (deploymentEnv !== 'staging') {
|
if (deploymentEnv !== 'staging') {
|
||||||
delete curriculum['13-relational-databases'];
|
delete curriculum['relational-database'];
|
||||||
}
|
}
|
||||||
|
|
||||||
const superBlocks = Object.keys(curriculum);
|
const superBlocks = Object.keys(curriculum);
|
||||||
|
@ -18,7 +18,7 @@ const {
|
|||||||
const { isAuditedCert } = require('../utils/is-audited');
|
const { isAuditedCert } = require('../utils/is-audited');
|
||||||
const { createPoly } = require('../utils/polyvinyl');
|
const { createPoly } = require('../utils/polyvinyl');
|
||||||
const { dasherize } = require('../utils/slugs');
|
const { dasherize } = require('../utils/slugs');
|
||||||
const { getSuperOrder } = require('./utils');
|
const { getSuperOrder, getSuperBlockFromDir } = require('./utils');
|
||||||
|
|
||||||
const access = util.promisify(fs.access);
|
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(
|
const metaPath = path.resolve(
|
||||||
__dirname,
|
__dirname,
|
||||||
`./challenges/_meta/${blockName}/meta.json`
|
`./challenges/_meta/${blockName}/meta.json`
|
||||||
@ -190,37 +190,41 @@ async function buildBlocks({ basename: blockName }, curriculum, baseDir) {
|
|||||||
if (!isUpcomingChange || showUpcomingChanges) {
|
if (!isUpcomingChange || showUpcomingChanges) {
|
||||||
// add the block to the superBlock
|
// add the block to the superBlock
|
||||||
const blockInfo = { meta: blockMeta, challenges: [] };
|
const blockInfo = { meta: blockMeta, challenges: [] };
|
||||||
curriculum[baseDir].blocks[blockName] = blockInfo;
|
curriculum[superBlock].blocks[blockName] = blockInfo;
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} 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) {
|
async function buildSuperBlocks({ path, fullPath }, curriculum) {
|
||||||
const baseDir = getBaseDir(path);
|
const superBlock = getSuperBlockFromDir(getBaseDir(path));
|
||||||
curriculum[baseDir] = { blocks: {} };
|
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);
|
return walk(fullPath, curriculum, { depth: 1, type: 'directories' }, cb);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function buildChallenges({ path: filePath }, curriculum, lang) {
|
async function buildChallenges({ path: filePath }, curriculum, lang) {
|
||||||
// path is relative to getChallengesDirForLang(lang)
|
// path is relative to getChallengesDirForLang(lang)
|
||||||
const block = getBlockNameFromPath(filePath);
|
const block = getBlockNameFromPath(filePath);
|
||||||
const baseDir = getBaseDir(filePath);
|
const superBlockDir = getBaseDir(filePath);
|
||||||
|
const superBlock = getSuperBlockFromDir(superBlockDir);
|
||||||
let challengeBlock;
|
let challengeBlock;
|
||||||
|
|
||||||
// TODO: this try block and process exit can all go once errors terminate the
|
// TODO: this try block and process exit can all go once errors terminate the
|
||||||
// tests correctly.
|
// tests correctly.
|
||||||
try {
|
try {
|
||||||
challengeBlock = curriculum[baseDir].blocks[block];
|
challengeBlock = curriculum[superBlock].blocks[block];
|
||||||
if (!challengeBlock) {
|
if (!challengeBlock) {
|
||||||
// this should only happen when a isUpcomingChange block is skipped
|
// this should only happen when a isUpcomingChange block is skipped
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} 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
|
// eslint-disable-next-line no-process-exit
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
@ -53,4 +53,29 @@ function getSuperOrder(
|
|||||||
return order;
|
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.getSuperOrder = getSuperOrder;
|
||||||
|
exports.getSuperBlockFromDir = getSuperBlockFromDir;
|
||||||
|
@ -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', () => {
|
describe('getSuperOrder', () => {
|
||||||
it('returns a number for valid superblocks', () => {
|
it('returns a number for valid superblocks', () => {
|
||||||
@ -86,3 +92,48 @@ describe('getSuperOrder', () => {
|
|||||||
).toBe(12);
|
).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();
|
||||||
|
});
|
||||||
|
});
|
@ -9,7 +9,7 @@ exports.buildMobileCurriculum = function buildMobileCurriculum(json) {
|
|||||||
|
|
||||||
function writeAndParseCurriculumJson(curriculum) {
|
function writeAndParseCurriculumJson(curriculum) {
|
||||||
const superBlockKeys = Object.keys(curriculum).filter(
|
const superBlockKeys = Object.keys(curriculum).filter(
|
||||||
key => key !== '00-certifications'
|
key => key !== 'certifications'
|
||||||
);
|
);
|
||||||
|
|
||||||
writeToFile('availableSuperblocks', { superblocks: superBlockKeys });
|
writeToFile('availableSuperblocks', { superblocks: superBlockKeys });
|
||||||
@ -34,9 +34,8 @@ exports.buildMobileCurriculum = function buildMobileCurriculum(json) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function writeToFile(filename, json) {
|
function writeToFile(filename, json) {
|
||||||
fs.writeFileSync(
|
const fullPath = `${mobileStaticPath}/mobile/${filename}.json`;
|
||||||
`${mobileStaticPath}/mobile/${filename}.json`,
|
fs.mkdirSync(path.dirname(fullPath), { recursive: true });
|
||||||
JSON.stringify(json, null, 2)
|
fs.writeFileSync(fullPath, JSON.stringify(json, null, 2));
|
||||||
);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
"client/plugins/**/*",
|
"client/plugins/**/*",
|
||||||
"client/src/**/*",
|
"client/src/**/*",
|
||||||
"client/utils/**/*",
|
"client/utils/**/*",
|
||||||
|
"curriculum/*.test.ts",
|
||||||
"tools/challenge-helper-scripts/**/*.ts",
|
"tools/challenge-helper-scripts/**/*.ts",
|
||||||
"tools/scripts/**/*.ts"
|
"tools/scripts/**/*.ts"
|
||||||
],
|
],
|
||||||
|
Reference in New Issue
Block a user