fix: handle missing solutions correctly

Rather than creating an [[]] the parser now creates [] which isEmpty().
This makes the test suite check the next challenge for a solution.

In addition, the logic for testing solutions was fixed.
This commit is contained in:
Oliver Eyton-Williams
2021-10-22 18:51:46 +02:00
parent edf3185b2b
commit 32c0995e47
3 changed files with 43 additions and 23 deletions

View File

@ -87,7 +87,7 @@ const schema = Joi.object()
crossDomain: Joi.bool() crossDomain: Joi.bool()
}) })
), ),
solutions: Joi.array().items(Joi.array().items(fileJoi)), solutions: Joi.array().items(Joi.array().items(fileJoi).min(1)),
superBlock: Joi.string().regex(slugRE), superBlock: Joi.string().regex(slugRE),
superOrder: Joi.number(), superOrder: Joi.number(),
suborder: Joi.number(), suborder: Joi.number(),

View File

@ -451,22 +451,26 @@ ${inspect(commentMap)}
// This is expected to happen in the project based curriculum. // This is expected to happen in the project based curriculum.
const nextChallenge = challenges[id + 1]; const nextChallenge = challenges[id + 1];
// TODO: can this be dried out, ideally by removing the redux
// handler?
if (nextChallenge) { if (nextChallenge) {
const solutionFiles = cloneDeep(nextChallenge.challengeFiles); const solutionFiles = cloneDeep(nextChallenge.challengeFiles);
solutionFiles.forEach(challengeFile => { const solutionFilesWithEditableContents = solutionFiles.map(
challengeFile.editableContents = getLines( file => ({
challengeFile.contents, ...file,
challenge.challengeFiles.find( editableContents: getLines(
x => x.fileKey === challengeFile.fileKey file.contents,
).editableRegionBoundaries file.editableRegionBoundaries
); )
}); })
solutions = [solutionFiles]; );
// Since there is only one seed, there can only be one solution,
// but the tests assume solutions is an array.
solutions = [solutionFilesWithEditableContents];
solutionFromNext = true; solutionFromNext = true;
} else { } else {
throw Error('solution omitted'); throw Error(
`solution omitted for ${challenge.superBlock} ${challenge.block} ${challenge.title}`
);
} }
} }
@ -519,15 +523,11 @@ async function createTestRunner(
solutionFromNext solutionFromNext
) { ) {
const { required = [], template, removeComments } = challenge; const { required = [], template, removeComments } = challenge;
// we should avoid modifying challenge, as it gets reused:
const challengeFiles = cloneDeep(challenge.challengeFiles); const challengeFiles = replaceChallengeFilesContentsWithSolutions(
solutionFiles.forEach(solutionFile => { challenge.challengeFiles,
const challengeFile = challengeFiles.find( solutionFiles
x => x.fileKey === solutionFile.fileKey );
);
challengeFile.contents = solutionFile.contents;
challengeFile.editableContents = solutionFile.editableContents;
});
const { build, sources, loadEnzyme } = await buildChallenge({ const { build, sources, loadEnzyme } = await buildChallenge({
challengeFiles, challengeFiles,
@ -567,6 +567,25 @@ async function createTestRunner(
}; };
} }
function replaceChallengeFilesContentsWithSolutions(
challengeFiles,
solutionFiles
) {
return challengeFiles.map(file => {
const matchingSolutionFile = solutionFiles.find(
({ ext }) => ext === file.ext
);
if (!matchingSolutionFile) {
throw Error(`No matching solution file found`);
}
return {
...file,
contents: matchingSolutionFile.contents,
editableContents: matchingSolutionFile.editableContents
};
});
}
async function getContextEvaluator(build, sources, code, loadEnzyme) { async function getContextEvaluator(build, sources, code, loadEnzyme) {
await initializeTestRunner(build, sources, code, loadEnzyme); await initializeTestRunner(build, sources, code, loadEnzyme);

View File

@ -1,3 +1,4 @@
const { isEmpty } = require('lodash');
const { root } = require('mdast-builder'); const { root } = require('mdast-builder');
const visitChildren = require('unist-util-visit-children'); const visitChildren = require('unist-util-visit-children');
@ -30,7 +31,7 @@ function createPlugin() {
); );
visitForContents(solutionTree); visitForContents(solutionTree);
solutions.push(Object.values(solution)); if (!isEmpty(solution)) solutions.push(Object.values(solution));
}); });
file.data = { file.data = {