test(curriculum): test suites must fail on the initial contents
This commit is contained in:
committed by
mrugesh mohapatra
parent
d8343aeb2f
commit
0aa6881508
@ -30,7 +30,7 @@ Work through the code and see if you can figure out the problem, then advance to
|
|||||||
```yml
|
```yml
|
||||||
tests:
|
tests:
|
||||||
- text: Move ahead to understand the error.
|
- text: Move ahead to understand the error.
|
||||||
testString: assert(true, 'Move ahead to understand the error.');
|
testString: '' # assert(true, 'Move ahead to understand the error.');
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -78,10 +78,10 @@ const jQueryScript = fs.readFileSync(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let { tests } = challenge;
|
let { tests = [] } = challenge;
|
||||||
tests = tests.filter(test => !!test.testString);
|
tests = tests.filter(test => !!test.testString);
|
||||||
if (tests.length === 0) {
|
if (tests.length === 0) {
|
||||||
it.skip('Check tests syntax. No tests.');
|
it('Check tests. No tests.');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,26 +95,16 @@ const jQueryScript = fs.readFileSync(
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
let { solutions } = challenge;
|
const { files = [], required = [] } = challenge;
|
||||||
const noSolution = new RegExp('// solution required');
|
|
||||||
solutions = solutions.filter(solution => (
|
|
||||||
!!solution && !noSolution.test(solution)
|
|
||||||
));
|
|
||||||
|
|
||||||
if (solutions.length === 0) {
|
|
||||||
it.skip('Check tests against solutions. No solutions');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const { files, required } = challenge;
|
|
||||||
const exts = Array.from(new Set(files.map(({ ext }) => ext)));
|
const exts = Array.from(new Set(files.map(({ ext }) => ext)));
|
||||||
const groupedFiles = exts.reduce((result, ext) => {
|
const groupedFiles = exts.reduce((result, ext) => {
|
||||||
const file = files.filter(file => file.ext === ext ).reduce(
|
const file = files.filter(file => file.ext === ext ).reduce(
|
||||||
(result, file) => ({
|
(result, file) => ({
|
||||||
head: result.head + '\n' + file.head,
|
head: result.head + '\n' + file.head,
|
||||||
|
contents: result.contents + '\n' + file.contents,
|
||||||
tail: result.tail + '\n' + file.tail
|
tail: result.tail + '\n' + file.tail
|
||||||
}),
|
}),
|
||||||
{ head: '', tail: '' }
|
{ head: '', contents: '', tail: '' }
|
||||||
);
|
);
|
||||||
return {
|
return {
|
||||||
...result,
|
...result,
|
||||||
@ -131,7 +121,36 @@ const jQueryScript = fs.readFileSync(
|
|||||||
} else if (groupedFiles.js) {
|
} else if (groupedFiles.js) {
|
||||||
evaluateTest = evaluateJsTest;
|
evaluateTest = evaluateJsTest;
|
||||||
} else {
|
} else {
|
||||||
it.skip('Check tests against solutions. Unknown file type.');
|
it('Check tests. Unknown file type.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
it('Test suite must fail on the initial contents', async function() {
|
||||||
|
let fails = (
|
||||||
|
await Promise.all(tests.map(async function(test) {
|
||||||
|
try {
|
||||||
|
await evaluateTest({
|
||||||
|
challengeType,
|
||||||
|
required,
|
||||||
|
files: groupedFiles,
|
||||||
|
test
|
||||||
|
});
|
||||||
|
return false;
|
||||||
|
} catch (e) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}))).some(v => v);
|
||||||
|
assert(fails, 'Test suit does not fail on the initial contents');
|
||||||
|
});
|
||||||
|
|
||||||
|
let { solutions = [] } = challenge;
|
||||||
|
const noSolution = new RegExp('// solution required');
|
||||||
|
solutions = solutions.filter(solution => (
|
||||||
|
!!solution && !noSolution.test(solution)
|
||||||
|
));
|
||||||
|
|
||||||
|
if (solutions.length === 0) {
|
||||||
|
it('Check tests. No solutions');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -242,13 +261,16 @@ function replaceColorNames(solution) {
|
|||||||
async function evaluateHtmlTest({
|
async function evaluateHtmlTest({
|
||||||
challengeType,
|
challengeType,
|
||||||
solution,
|
solution,
|
||||||
required = [],
|
required,
|
||||||
files,
|
files,
|
||||||
test
|
test
|
||||||
}) {
|
}) {
|
||||||
|
|
||||||
|
const { head = '', contents = '', tail = '' } = files.html;
|
||||||
|
if (!solution) {
|
||||||
|
solution = contents;
|
||||||
|
}
|
||||||
const code = solution;
|
const code = solution;
|
||||||
const { head = '', tail = '' } = files.html;
|
|
||||||
|
|
||||||
const options = {
|
const options = {
|
||||||
resources: 'usable',
|
resources: 'usable',
|
||||||
@ -298,7 +320,7 @@ A required file can not have both a src and a link: src = ${src}, link = ${link}
|
|||||||
}
|
}
|
||||||
|
|
||||||
dom.window.code = code;
|
dom.window.code = code;
|
||||||
runTestInJsdom(dom, test.testString);
|
await runTestInJsdom(dom, test.testString);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function evaluateJsTest({
|
async function evaluateJsTest({
|
||||||
@ -309,10 +331,23 @@ async function evaluateJsTest({
|
|||||||
|
|
||||||
const virtualConsole = new jsdom.VirtualConsole();
|
const virtualConsole = new jsdom.VirtualConsole();
|
||||||
const dom = new JSDOM('', { runScripts: 'dangerously', virtualConsole });
|
const dom = new JSDOM('', { runScripts: 'dangerously', virtualConsole });
|
||||||
dom.window.code = solution;
|
|
||||||
|
|
||||||
const { head = '', tail = '' } = files.js;
|
const { head = '', contents = '', tail = '' } = files.js;
|
||||||
const scriptString = head + '\n' + solution + '\n' + tail + '\n';
|
let scriptString = '';
|
||||||
|
if (!solution) {
|
||||||
|
solution = contents;
|
||||||
|
scriptString = head + '\n' + contents + '\n' + tail + '\n';
|
||||||
|
try {
|
||||||
|
// eslint-disable-next-line
|
||||||
|
new vm.Script(scriptString);
|
||||||
|
} catch (e) {
|
||||||
|
scriptString = '';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
scriptString = head + '\n' + solution + '\n' + tail + '\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
dom.window.code = solution;
|
||||||
|
|
||||||
await runTestInJsdom(dom, test.testString, scriptString);
|
await runTestInJsdom(dom, test.testString, scriptString);
|
||||||
}
|
}
|
||||||
@ -323,25 +358,40 @@ async function evaluateReactReduxTest({
|
|||||||
test
|
test
|
||||||
}) {
|
}) {
|
||||||
|
|
||||||
const code = solution;
|
|
||||||
/* Transpile ALL the code
|
|
||||||
* (we may use JSX in head or tail or tests, too): */
|
|
||||||
solution = Babel.transform(solution, babelOptions).code;
|
|
||||||
const testString = Babel.transform(test.testString, babelOptions).code;
|
|
||||||
|
|
||||||
let head = '', tail = '';
|
let head = '', tail = '';
|
||||||
if (files.js) {
|
if (files.js) {
|
||||||
const { head: headJs = '', tail: tailJs = '' } = files.js;
|
const { head: headJs = '', tail: tailJs = '' } = files.js;
|
||||||
head += Babel.transform(headJs, babelOptions).code + '\n';
|
head += headJs + '\n';
|
||||||
tail += Babel.transform(tailJs, babelOptions).code + '\n';
|
tail += tailJs + '\n';
|
||||||
}
|
}
|
||||||
if (files.jsx) {
|
if (files.jsx) {
|
||||||
const { head: headJsx = '', tail: tailJsx = '' } = files.jsx;
|
const { head: headJsx = '', tail: tailJsx = '' } = files.jsx;
|
||||||
head += Babel.transform(headJsx, babelOptions).code + '\n';
|
head += headJsx + '\n';
|
||||||
tail += Babel.transform(tailJsx, babelOptions).code + '\n';
|
tail += tailJsx + '\n';
|
||||||
}
|
}
|
||||||
|
|
||||||
const scriptString = head + '\n' + solution + '\n' + tail + '\n';
|
/* Transpile ALL the code
|
||||||
|
* (we may use JSX in head or tail or tests, too): */
|
||||||
|
|
||||||
|
let scriptString = '';
|
||||||
|
if (!solution) {
|
||||||
|
const contents = (files.js ? files.js.contents || '' : '') +
|
||||||
|
(files.jsx ? files.jsx.contents || '' : '');
|
||||||
|
solution = contents;
|
||||||
|
scriptString = head + '\n' + contents + '\n' + tail + '\n';
|
||||||
|
try {
|
||||||
|
scriptString = Babel.transform(scriptString, babelOptions).code;
|
||||||
|
} catch (e) {
|
||||||
|
scriptString = '';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
scriptString = head + '\n' + solution + '\n' + tail + '\n';
|
||||||
|
scriptString = Babel.transform(scriptString, babelOptions).code;
|
||||||
|
}
|
||||||
|
|
||||||
|
const code = solution;
|
||||||
|
|
||||||
|
const testString = Babel.transform(test.testString, babelOptions).code;
|
||||||
|
|
||||||
const virtualConsole = new jsdom.VirtualConsole();
|
const virtualConsole = new jsdom.VirtualConsole();
|
||||||
// Mock DOM document for ReactDOM.render method
|
// Mock DOM document for ReactDOM.render method
|
||||||
@ -402,6 +452,7 @@ async function runTestInJsdom(dom, testString, scriptString = '') {
|
|||||||
|
|
||||||
dom.window.__test = testString;
|
dom.window.__test = testString;
|
||||||
scriptString += `;
|
scriptString += `;
|
||||||
|
window.__result =
|
||||||
(async () => {
|
(async () => {
|
||||||
try {
|
try {
|
||||||
const testResult = eval(__test);
|
const testResult = eval(__test);
|
||||||
@ -417,6 +468,7 @@ async function runTestInJsdom(dom, testString, scriptString = '') {
|
|||||||
})();`;
|
})();`;
|
||||||
const script = new vm.Script(scriptString);
|
const script = new vm.Script(scriptString);
|
||||||
dom.runVMScript(script);
|
dom.runVMScript(script);
|
||||||
|
await dom.window.__result;
|
||||||
if (dom.window.__error) {
|
if (dom.window.__error) {
|
||||||
throw dom.window.__error;
|
throw dom.window.__error;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user