refactor(multi) move preparation into curriculum

This commit is contained in:
Oliver Eyton-Williams
2020-06-08 15:01:48 +02:00
committed by Mrugesh Mohapatra
parent 88de5bc602
commit 754a33970e
3 changed files with 53 additions and 43 deletions

View File

@ -5,18 +5,13 @@ const {
createChallenge, createChallenge,
getChallengesDirForLang getChallengesDirForLang
} = require('../../curriculum/getChallenges'); } = require('../../curriculum/getChallenges');
const { dasherize, nameify } = require('../../utils/slugs');
const { locale } = require('../config/env.json'); const { locale } = require('../config/env.json');
const { blockNameify } = require('../../utils/block-nameify');
const arrToString = arr =>
Array.isArray(arr) ? arr.join('\n') : _.toString(arr);
exports.localeChallengesRootDir = getChallengesDirForLang(locale); exports.localeChallengesRootDir = getChallengesDirForLang(locale);
exports.replaceChallengeNode = locale => { exports.replaceChallengeNode = locale => {
return async function replaceChallengeNode(fullFilePath) { return async function replaceChallengeNode(fullFilePath) {
return prepareChallenge(await createChallenge(fullFilePath, null, locale)); return await createChallenge(fullFilePath, null, locale);
}; };
}; };
@ -32,29 +27,7 @@ exports.buildChallenges = async function buildChallenges() {
const builtChallenges = blocks const builtChallenges = blocks
.filter(block => !block.isPrivate) .filter(block => !block.isPrivate)
.map(({ challenges }) => challenges.map(prepareChallenge)) .map(({ challenges }) => challenges)
.reduce((accu, current) => accu.concat(current), []); .reduce((accu, current) => accu.concat(current), []);
return builtChallenges; return builtChallenges;
}; };
function prepareChallenge(challenge) {
challenge.name = nameify(challenge.title);
if (challenge.files) {
challenge.files = _.reduce(
challenge.files,
(map, file) => {
map[file.key] = {
...file,
head: arrToString(file.head),
contents: arrToString(file.contents),
tail: arrToString(file.tail)
};
return map;
},
{}
);
}
challenge.block = dasherize(challenge.block);
challenge.superBlock = blockNameify(challenge.superBlock);
return challenge;
}

View File

@ -1,5 +1,5 @@
const path = require('path'); const path = require('path');
const { findIndex } = require('lodash'); const { findIndex, reduce, toString } = require('lodash');
const readDirP = require('readdirp-walk'); const readDirP = require('readdirp-walk');
const { parseMarkdown } = require('../tools/challenge-md-parser'); const { parseMarkdown } = require('../tools/challenge-md-parser');
const fs = require('fs'); const fs = require('fs');
@ -11,8 +11,10 @@ const {
/* eslint-enable max-len*/ /* eslint-enable max-len*/
const { COMMENT_TRANSLATIONS } = require('./comment-dictionary'); const { COMMENT_TRANSLATIONS } = require('./comment-dictionary');
const { dasherize } = require('../utils/slugs');
const { isAuditedCert } = require('../utils/is-audited'); const { isAuditedCert } = require('../utils/is-audited');
const { dasherize, nameify } = require('../utils/slugs');
const { createPoly } = require('../utils/polyvinyl');
const { blockNameify } = require('../utils/block-nameify');
const challengesDir = path.resolve(__dirname, './challenges'); const challengesDir = path.resolve(__dirname, './challenges');
const metaDir = path.resolve(challengesDir, '_meta'); const metaDir = path.resolve(challengesDir, '_meta');
@ -180,6 +182,43 @@ Trying to parse ${fullPath}`);
challenge.template = template; challenge.template = template;
challenge.time = time; challenge.time = time;
return prepareChallenge(challenge);
}
// gets the challenge ready for sourcing into Gatsby
function prepareChallenge(challenge) {
challenge.name = nameify(challenge.title);
if (challenge.files) {
challenge.files = reduce(
challenge.files,
(map, file) => {
map[file.key] = {
...file,
head: arrToString(file.head),
contents: arrToString(file.contents),
tail: arrToString(file.tail)
};
return map;
},
{}
);
// TODO: This should be something that can be folded into the above reduce
challenge.files = Object.keys(challenge.files)
.filter(key => challenge.files[key])
.map(key => challenge.files[key])
.reduce(
(files, file) => ({
...files,
[file.key]: {
...createPoly(file),
seed: file.contents.slice(0)
}
}),
{}
);
}
challenge.block = dasherize(challenge.block);
challenge.superBlock = blockNameify(challenge.superBlock);
return challenge; return challenge;
} }
@ -255,3 +294,7 @@ function getBlockNameFromFullPath(fullFilePath) {
const [, block] = fullFilePath.split(path.sep).reverse(); const [, block] = fullFilePath.split(path.sep).reverse();
return block; return block;
} }
function arrToString(arr) {
return Array.isArray(arr) ? arr.join('\n') : toString(arr);
}

View File

@ -42,6 +42,7 @@ const {
} = require('../../client/utils/challengeTypes'); } = require('../../client/utils/challengeTypes');
const { dasherize } = require('../../utils/slugs'); const { dasherize } = require('../../utils/slugs');
const { sortFiles } = require('../../utils/sort-files');
const { testedLang } = require('../utils'); const { testedLang } = require('../utils');
@ -50,7 +51,6 @@ const {
buildJSChallenge buildJSChallenge
} = require('../../client/src/templates/Challenges/utils/build'); } = require('../../client/src/templates/Challenges/utils/build');
const { createPoly } = require('../../utils/polyvinyl');
const { sortChallenges } = require('./utils/sort-challenges'); const { sortChallenges } = require('./utils/sort-challenges');
const testEvaluator = require('../../client/config/test-evaluator').filename; const testEvaluator = require('../../client/config/test-evaluator').filename;
@ -319,7 +319,6 @@ function populateTestsForLang({ lang, challenges, meta }) {
}); });
}); });
let { files = [] } = challenge;
if (challengeType === challengeTypes.backend) { if (challengeType === challengeTypes.backend) {
it('Check tests is not implemented.'); it('Check tests is not implemented.');
return; return;
@ -334,7 +333,6 @@ function populateTestsForLang({ lang, challenges, meta }) {
// TODO: create more sophisticated validation now we allow for more // TODO: create more sophisticated validation now we allow for more
// than one seed/solution file. // than one seed/solution file.
files = files.map(createPoly);
it('Test suite must fail on the initial contents', async function() { it('Test suite must fail on the initial contents', async function() {
this.timeout(5000 * tests.length + 1000); this.timeout(5000 * tests.length + 1000);
// suppress errors in the console. // suppress errors in the console.
@ -344,7 +342,7 @@ function populateTestsForLang({ lang, challenges, meta }) {
let testRunner; let testRunner;
try { try {
testRunner = await createTestRunner( testRunner = await createTestRunner(
{ ...challenge, files }, challenge,
'', '',
buildChallenge buildChallenge
); );
@ -390,7 +388,7 @@ function populateTestsForLang({ lang, challenges, meta }) {
it(`Solution ${index + 1} must pass the tests`, async function() { it(`Solution ${index + 1} must pass the tests`, async function() {
this.timeout(5000 * tests.length + 1000); this.timeout(5000 * tests.length + 1000);
const testRunner = await createTestRunner( const testRunner = await createTestRunner(
{ ...challenge, files }, challenge,
solution, solution,
buildChallenge buildChallenge
); );
@ -418,14 +416,10 @@ async function createTestRunner(
solution, solution,
buildChallenge buildChallenge
) { ) {
// TODO: solutions will need to be multi-file, too, with a fallback when there // fallback for single solution
// is only one file. const sortedFiles = sortFiles(files);
// we cannot simply use the solution instead of files, because the are not
// just the seed(s), they contain the head and tail code. The best approach
// is probably to separate out the head and tail from the files. Then the
// files can be entirely replaced by the solution.
if (solution) { if (solution) {
files[0].contents = solution; files[sortedFiles[0].key].contents = solution;
} }
const { build, sources, loadEnzyme } = await buildChallenge({ const { build, sources, loadEnzyme } = await buildChallenge({