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()
})
),
solutions: Joi.array().items(Joi.array().items(fileJoi)),
solutions: Joi.array().items(Joi.array().items(fileJoi).min(1)),
superBlock: Joi.string().regex(slugRE),
superOrder: Joi.number(),
suborder: Joi.number(),

View File

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

View File

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