2018-12-01 02:47:32 +03:00
|
|
|
/* global browser, page */
|
2018-11-01 18:56:15 +03:00
|
|
|
const { assert, AssertionError } = require('chai');
|
|
|
|
const Mocha = require('mocha');
|
2018-10-25 03:34:47 +03:00
|
|
|
|
|
|
|
const { flatten } = require('lodash');
|
|
|
|
const path = require('path');
|
|
|
|
const fs = require('fs');
|
|
|
|
require('dotenv').config({ path: path.resolve(__dirname, '../../.env') });
|
|
|
|
|
|
|
|
const vm = require('vm');
|
|
|
|
|
2018-12-01 02:47:32 +03:00
|
|
|
const puppeteer = require('puppeteer');
|
|
|
|
|
2018-10-25 03:34:47 +03:00
|
|
|
const jsdom = require('jsdom');
|
|
|
|
const jQuery = require('jquery');
|
|
|
|
const Sass = require('node-sass');
|
|
|
|
const Babel = require('babel-standalone');
|
|
|
|
const presetEnv = require('babel-preset-env');
|
|
|
|
const presetReact = require('babel-preset-react');
|
|
|
|
|
|
|
|
const { getChallengesForLang } = require('../getChallenges');
|
|
|
|
|
|
|
|
const MongoIds = require('./utils/mongoIds');
|
|
|
|
const ChallengeTitles = require('./utils/challengeTitles');
|
|
|
|
const { validateChallenge } = require('../schema/challengeSchema');
|
|
|
|
const { challengeTypes } = require('../../client/utils/challengeTypes');
|
|
|
|
|
|
|
|
const { LOCALE: lang = 'english' } = process.env;
|
|
|
|
|
2018-11-01 18:56:15 +03:00
|
|
|
const oldRunnerFail = Mocha.Runner.prototype.fail;
|
|
|
|
Mocha.Runner.prototype.fail = function(test, err) {
|
|
|
|
if (err.stack && err instanceof AssertionError) {
|
2018-12-01 02:47:32 +03:00
|
|
|
const assertIndex = err.message.indexOf(': expected');
|
|
|
|
if (assertIndex !== -1) {
|
|
|
|
err.message = err.message.slice(0, assertIndex);
|
|
|
|
}
|
|
|
|
// Don't show stacktrace for assertion errors.
|
2018-11-01 18:56:15 +03:00
|
|
|
delete err.stack;
|
|
|
|
}
|
|
|
|
return oldRunnerFail.call(this, test, err);
|
|
|
|
};
|
|
|
|
|
2018-10-25 03:34:47 +03:00
|
|
|
let mongoIds = new MongoIds();
|
|
|
|
let challengeTitles = new ChallengeTitles();
|
|
|
|
|
|
|
|
const { JSDOM } = jsdom;
|
|
|
|
|
|
|
|
const babelOptions = {
|
|
|
|
plugins: ['transform-runtime'],
|
|
|
|
presets: [presetEnv, presetReact]
|
|
|
|
};
|
|
|
|
|
|
|
|
const jQueryScript = fs.readFileSync(
|
2018-12-01 02:47:32 +03:00
|
|
|
path.resolve('./node_modules/jquery/dist/jquery.slim.min.js'),
|
|
|
|
'utf8'
|
2018-10-25 03:34:47 +03:00
|
|
|
);
|
|
|
|
|
|
|
|
(async function() {
|
2018-11-26 10:47:33 +03:00
|
|
|
const allChallenges = await getChallengesForLang(lang).then(curriculum =>
|
2018-10-25 03:34:47 +03:00
|
|
|
Object.keys(curriculum)
|
2018-11-26 10:47:33 +03:00
|
|
|
.map(key => curriculum[key].blocks)
|
|
|
|
.reduce((challengeArray, superBlock) => {
|
|
|
|
const challengesForBlock = Object.keys(superBlock).map(
|
|
|
|
key => superBlock[key].challenges
|
|
|
|
);
|
|
|
|
return [...challengeArray, ...flatten(challengesForBlock)];
|
|
|
|
}, [])
|
|
|
|
);
|
2018-10-25 03:34:47 +03:00
|
|
|
|
|
|
|
describe('Check challenges tests', async function() {
|
2018-12-01 02:47:32 +03:00
|
|
|
before(async function() {
|
|
|
|
this.timeout(30000);
|
|
|
|
global.browser = await puppeteer.launch({ args: ['--no-sandbox'] });
|
|
|
|
global.page = await browser.newPage();
|
|
|
|
await page.setViewport({ width: 300, height: 150 });
|
|
|
|
});
|
|
|
|
after(async function() {
|
|
|
|
if (global.browser) {
|
|
|
|
await browser.close();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2018-11-16 21:16:27 +03:00
|
|
|
this.timeout(5000);
|
2018-10-25 03:34:47 +03:00
|
|
|
|
|
|
|
allChallenges.forEach(challenge => {
|
|
|
|
describe(challenge.title || 'No title', async function() {
|
|
|
|
it('Common checks', function() {
|
|
|
|
const result = validateChallenge(challenge);
|
|
|
|
if (result.error) {
|
|
|
|
console.log(result.value);
|
|
|
|
throw new Error(result.error);
|
|
|
|
}
|
|
|
|
const { id, title } = challenge;
|
|
|
|
mongoIds.check(id, title);
|
|
|
|
challengeTitles.check(title);
|
|
|
|
});
|
|
|
|
|
|
|
|
const { challengeType } = challenge;
|
2018-11-26 10:47:33 +03:00
|
|
|
if (
|
|
|
|
challengeType !== challengeTypes.html &&
|
|
|
|
challengeType !== challengeTypes.js &&
|
|
|
|
challengeType !== challengeTypes.bonfire &&
|
|
|
|
challengeType !== challengeTypes.modern &&
|
|
|
|
challengeType !== challengeTypes.backend
|
2018-10-25 03:34:47 +03:00
|
|
|
) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-10-25 17:23:00 +03:00
|
|
|
let { tests = [] } = challenge;
|
2018-10-25 03:34:47 +03:00
|
|
|
tests = tests.filter(test => !!test.testString);
|
|
|
|
if (tests.length === 0) {
|
2018-10-25 17:23:00 +03:00
|
|
|
it('Check tests. No tests.');
|
2018-10-25 03:34:47 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
describe('Check tests syntax', function() {
|
|
|
|
tests.forEach(test => {
|
|
|
|
it(`Check for: ${test.text}`, function() {
|
2018-11-26 10:47:33 +03:00
|
|
|
assert.doesNotThrow(() => new vm.Script(test.testString));
|
2018-10-25 03:34:47 +03:00
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2018-10-25 17:23:00 +03:00
|
|
|
const { files = [], required = [] } = challenge;
|
2018-10-25 03:34:47 +03:00
|
|
|
const exts = Array.from(new Set(files.map(({ ext }) => ext)));
|
|
|
|
const groupedFiles = exts.reduce((result, ext) => {
|
2018-11-26 10:47:33 +03:00
|
|
|
const file = files.filter(file => file.ext === ext).reduce(
|
2018-10-25 03:34:47 +03:00
|
|
|
(result, file) => ({
|
|
|
|
head: result.head + '\n' + file.head,
|
2018-10-25 17:23:00 +03:00
|
|
|
contents: result.contents + '\n' + file.contents,
|
2018-10-25 03:34:47 +03:00
|
|
|
tail: result.tail + '\n' + file.tail
|
|
|
|
}),
|
2018-10-25 17:23:00 +03:00
|
|
|
{ head: '', contents: '', tail: '' }
|
2018-10-25 03:34:47 +03:00
|
|
|
);
|
|
|
|
return {
|
|
|
|
...result,
|
|
|
|
[ext]: file
|
|
|
|
};
|
|
|
|
}, {});
|
|
|
|
|
|
|
|
let evaluateTest;
|
2018-11-26 10:47:33 +03:00
|
|
|
if (
|
|
|
|
challengeType === challengeTypes.modern &&
|
|
|
|
(groupedFiles.js || groupedFiles.jsx)
|
|
|
|
) {
|
2018-10-25 03:34:47 +03:00
|
|
|
evaluateTest = evaluateReactReduxTest;
|
|
|
|
} else if (groupedFiles.html) {
|
|
|
|
evaluateTest = evaluateHtmlTest;
|
|
|
|
} else if (groupedFiles.js) {
|
|
|
|
evaluateTest = evaluateJsTest;
|
|
|
|
} else {
|
2018-10-25 17:23:00 +03:00
|
|
|
it('Check tests. Unknown file type.');
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
it('Test suite must fail on the initial contents', async function() {
|
2018-11-18 21:38:47 +03:00
|
|
|
this.timeout(20000);
|
2018-11-01 18:56:15 +03:00
|
|
|
// suppress errors in the console.
|
|
|
|
const oldConsoleError = console.error;
|
|
|
|
console.error = () => {};
|
2018-11-26 10:47:33 +03:00
|
|
|
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);
|
2018-11-01 18:56:15 +03:00
|
|
|
console.error = oldConsoleError;
|
2018-10-25 17:23:00 +03:00
|
|
|
assert(fails, 'Test suit does not fail on the initial contents');
|
|
|
|
});
|
|
|
|
|
|
|
|
let { solutions = [] } = challenge;
|
|
|
|
const noSolution = new RegExp('// solution required');
|
2018-11-26 10:47:33 +03:00
|
|
|
solutions = solutions.filter(
|
|
|
|
solution => !!solution && !noSolution.test(solution)
|
|
|
|
);
|
2018-10-25 17:23:00 +03:00
|
|
|
|
|
|
|
if (solutions.length === 0) {
|
|
|
|
it('Check tests. No solutions');
|
2018-10-25 03:34:47 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
describe('Check tests against solutions', async function() {
|
|
|
|
solutions.forEach((solution, index) => {
|
|
|
|
describe(`Solution ${index + 1}`, async function() {
|
|
|
|
tests.forEach(test => {
|
|
|
|
it(test.text, async function() {
|
|
|
|
await evaluateTest({
|
|
|
|
challengeType,
|
|
|
|
solution,
|
|
|
|
required,
|
|
|
|
files: groupedFiles,
|
|
|
|
test
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
run();
|
|
|
|
})();
|
|
|
|
|
|
|
|
// Fake Deep Equal dependency
|
|
|
|
const DeepEqual = (a, b) => JSON.stringify(a) === JSON.stringify(b);
|
|
|
|
|
|
|
|
// Hardcode Deep Freeze dependency
|
|
|
|
const DeepFreeze = o => {
|
|
|
|
Object.freeze(o);
|
|
|
|
Object.getOwnPropertyNames(o).forEach(function(prop) {
|
|
|
|
if (
|
|
|
|
o.hasOwnProperty(prop) &&
|
|
|
|
o[prop] !== null &&
|
|
|
|
(typeof o[prop] === 'object' || typeof o[prop] === 'function') &&
|
|
|
|
!Object.isFrozen(o[prop])
|
|
|
|
) {
|
|
|
|
DeepFreeze(o[prop]);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
return o;
|
|
|
|
};
|
|
|
|
|
|
|
|
function transformSass(solution) {
|
|
|
|
const fragment = JSDOM.fragment(`<div>${solution}</div>`);
|
|
|
|
const styleTags = fragment.querySelectorAll('style[type="text/sass"]');
|
|
|
|
if (styleTags.length > 0) {
|
|
|
|
styleTags.forEach(styleTag => {
|
|
|
|
styleTag.innerHTML = Sass.renderSync({ data: styleTag.innerHTML }).css;
|
|
|
|
styleTag.type = 'text/css';
|
|
|
|
});
|
|
|
|
return fragment.children[0].innerHTML;
|
|
|
|
}
|
|
|
|
return solution;
|
|
|
|
}
|
|
|
|
|
2018-12-01 02:47:32 +03:00
|
|
|
async function evaluateHtmlTest({ solution, required, files, test }) {
|
2018-10-25 17:23:00 +03:00
|
|
|
const { head = '', contents = '', tail = '' } = files.html;
|
|
|
|
if (!solution) {
|
|
|
|
solution = contents;
|
|
|
|
}
|
2018-10-25 03:34:47 +03:00
|
|
|
const code = solution;
|
|
|
|
|
|
|
|
const links = required
|
|
|
|
.map(({ link, src }) => {
|
|
|
|
if (link && src) {
|
|
|
|
throw new Error(`
|
|
|
|
A required file can not have both a src and a link: src = ${src}, link = ${link}
|
|
|
|
`);
|
|
|
|
}
|
|
|
|
if (src) {
|
|
|
|
return `<script src='${src}' type='text/javascript'></script>`;
|
|
|
|
}
|
|
|
|
if (link) {
|
|
|
|
return `<link href='${link}' rel='stylesheet' />`;
|
|
|
|
}
|
|
|
|
return '';
|
|
|
|
})
|
|
|
|
.reduce((head, required) => head.concat(required), '');
|
|
|
|
|
|
|
|
const scripts = `
|
|
|
|
<head>
|
|
|
|
${links}
|
|
|
|
</head>
|
|
|
|
`;
|
|
|
|
|
2018-11-16 21:16:27 +03:00
|
|
|
const sandbox = { solution, transformSass };
|
|
|
|
const context = vm.createContext(sandbox);
|
2018-11-26 10:47:33 +03:00
|
|
|
vm.runInContext('solution = transformSass(solution);', context, {
|
|
|
|
timeout: 2000
|
|
|
|
});
|
2018-11-16 21:16:27 +03:00
|
|
|
solution = sandbox.solution;
|
2018-10-25 03:34:47 +03:00
|
|
|
|
2018-12-01 02:47:32 +03:00
|
|
|
await preparePageToTest();
|
|
|
|
|
|
|
|
await page.setContent(
|
2018-11-26 10:47:33 +03:00
|
|
|
`
|
2018-10-25 03:34:47 +03:00
|
|
|
<!doctype html>
|
|
|
|
<html>
|
|
|
|
${scripts}
|
|
|
|
${head}
|
|
|
|
${solution}
|
|
|
|
${tail}
|
|
|
|
</html>
|
2018-12-01 02:47:32 +03:00
|
|
|
`
|
2018-11-26 10:47:33 +03:00
|
|
|
);
|
2018-10-25 03:34:47 +03:00
|
|
|
|
2018-12-01 02:47:32 +03:00
|
|
|
await runTestInBrowser(code, test.testString);
|
|
|
|
}
|
2018-10-25 03:34:47 +03:00
|
|
|
|
2018-12-01 02:47:32 +03:00
|
|
|
async function preparePageToTest() {
|
|
|
|
await page.reload();
|
|
|
|
await page.addScriptTag({
|
|
|
|
url: 'https://cdnjs.cloudflare.com/ajax/libs/chai/4.2.0/chai.min.js'
|
|
|
|
});
|
|
|
|
await page.evaluate(() => {
|
|
|
|
window.assert = window.chai.assert;
|
|
|
|
});
|
|
|
|
await page.evaluate(jQueryScript);
|
|
|
|
}
|
|
|
|
|
|
|
|
async function runTestInBrowser(code, testString) {
|
|
|
|
const result = await page.evaluate(
|
|
|
|
async function(code, testString) {
|
|
|
|
/* eslint-disable no-unused-vars */
|
|
|
|
// Fake Deep Equal dependency
|
|
|
|
const DeepEqual = (a, b) => JSON.stringify(a) === JSON.stringify(b);
|
|
|
|
|
|
|
|
// Hardcode Deep Freeze dependency
|
|
|
|
const DeepFreeze = o => {
|
|
|
|
Object.freeze(o);
|
|
|
|
Object.getOwnPropertyNames(o).forEach(function(prop) {
|
|
|
|
if (
|
|
|
|
o.hasOwnProperty(prop) &&
|
|
|
|
o[prop] !== null &&
|
|
|
|
(typeof o[prop] === 'object' || typeof o[prop] === 'function') &&
|
|
|
|
!Object.isFrozen(o[prop])
|
|
|
|
) {
|
|
|
|
DeepFreeze(o[prop]);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
return o;
|
|
|
|
};
|
|
|
|
|
|
|
|
const editor = {
|
|
|
|
getValue() {
|
|
|
|
return code;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
/* eslint-enable no-unused-vars */
|
|
|
|
|
|
|
|
try {
|
|
|
|
// eslint-disable-next-line no-eval
|
|
|
|
const test = eval(testString);
|
|
|
|
if (typeof test === 'function') {
|
2018-12-02 00:54:25 +03:00
|
|
|
await test(() => code);
|
2018-12-01 02:47:32 +03:00
|
|
|
}
|
|
|
|
} catch (e) {
|
|
|
|
return {
|
|
|
|
message: e.message,
|
|
|
|
isAssertion: e instanceof window.chai.AssertionError
|
|
|
|
};
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
},
|
|
|
|
code,
|
|
|
|
testString
|
|
|
|
);
|
|
|
|
if (result !== true) {
|
|
|
|
throw result.isAssertion
|
|
|
|
? new AssertionError(result.message)
|
|
|
|
: new Error(result.message);
|
|
|
|
}
|
2018-10-25 03:34:47 +03:00
|
|
|
}
|
|
|
|
|
2018-11-26 10:47:33 +03:00
|
|
|
async function evaluateJsTest({ solution, files, test }) {
|
2018-10-25 03:34:47 +03:00
|
|
|
const virtualConsole = new jsdom.VirtualConsole();
|
|
|
|
const dom = new JSDOM('', { runScripts: 'dangerously', virtualConsole });
|
|
|
|
|
2018-10-25 17:23:00 +03:00
|
|
|
const { head = '', contents = '', tail = '' } = files.js;
|
|
|
|
let scriptString = '';
|
|
|
|
if (!solution) {
|
|
|
|
solution = contents;
|
|
|
|
try {
|
2018-11-26 10:47:33 +03:00
|
|
|
scriptString =
|
|
|
|
Babel.transform(head, babelOptions).code +
|
|
|
|
'\n' +
|
|
|
|
Babel.transform(contents, babelOptions).code +
|
|
|
|
'\n' +
|
|
|
|
Babel.transform(tail, babelOptions).code +
|
|
|
|
'\n';
|
2018-10-25 17:23:00 +03:00
|
|
|
} catch (e) {
|
|
|
|
scriptString = '';
|
|
|
|
}
|
|
|
|
} else {
|
2018-11-26 10:47:33 +03:00
|
|
|
scriptString =
|
|
|
|
Babel.transform(head, babelOptions).code +
|
|
|
|
'\n' +
|
|
|
|
Babel.transform(solution, babelOptions).code +
|
|
|
|
'\n' +
|
|
|
|
Babel.transform(tail, babelOptions).code +
|
|
|
|
'\n';
|
2018-10-25 17:23:00 +03:00
|
|
|
}
|
|
|
|
|
2018-11-26 10:47:33 +03:00
|
|
|
dom.window.require = require;
|
2018-10-25 17:23:00 +03:00
|
|
|
dom.window.code = solution;
|
2018-10-25 03:34:47 +03:00
|
|
|
await runTestInJsdom(dom, test.testString, scriptString);
|
|
|
|
}
|
|
|
|
|
2018-11-26 10:47:33 +03:00
|
|
|
async function evaluateReactReduxTest({ solution, files, test }) {
|
|
|
|
let head = '',
|
|
|
|
tail = '';
|
2018-10-25 03:34:47 +03:00
|
|
|
if (files.js) {
|
|
|
|
const { head: headJs = '', tail: tailJs = '' } = files.js;
|
2018-10-25 17:23:00 +03:00
|
|
|
head += headJs + '\n';
|
|
|
|
tail += tailJs + '\n';
|
2018-10-25 03:34:47 +03:00
|
|
|
}
|
|
|
|
if (files.jsx) {
|
|
|
|
const { head: headJsx = '', tail: tailJsx = '' } = files.jsx;
|
2018-10-25 17:23:00 +03:00
|
|
|
head += headJsx + '\n';
|
|
|
|
tail += tailJsx + '\n';
|
2018-10-25 03:34:47 +03:00
|
|
|
}
|
|
|
|
|
2018-10-25 17:23:00 +03:00
|
|
|
/* Transpile ALL the code
|
|
|
|
* (we may use JSX in head or tail or tests, too): */
|
|
|
|
|
|
|
|
let scriptString = '';
|
|
|
|
if (!solution) {
|
2018-11-26 10:47:33 +03:00
|
|
|
const contents =
|
|
|
|
(files.js ? files.js.contents || '' : '') +
|
2018-10-25 17:23:00 +03:00
|
|
|
(files.jsx ? files.jsx.contents || '' : '');
|
|
|
|
solution = contents;
|
|
|
|
try {
|
2018-11-26 10:47:33 +03:00
|
|
|
scriptString =
|
|
|
|
Babel.transform(head, babelOptions).code +
|
|
|
|
'\n' +
|
|
|
|
Babel.transform(contents, babelOptions).code +
|
|
|
|
'\n' +
|
|
|
|
Babel.transform(tail, babelOptions).code +
|
|
|
|
'\n';
|
2018-10-25 17:23:00 +03:00
|
|
|
} catch (e) {
|
|
|
|
scriptString = '';
|
|
|
|
}
|
|
|
|
} else {
|
2018-11-26 10:47:33 +03:00
|
|
|
scriptString =
|
|
|
|
Babel.transform(head, babelOptions).code +
|
|
|
|
'\n' +
|
|
|
|
Babel.transform(solution, babelOptions).code +
|
|
|
|
'\n' +
|
|
|
|
Babel.transform(tail, babelOptions).code +
|
|
|
|
'\n';
|
2018-10-25 17:23:00 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
const code = solution;
|
|
|
|
|
2018-10-25 03:34:47 +03:00
|
|
|
const virtualConsole = new jsdom.VirtualConsole();
|
|
|
|
// Mock DOM document for ReactDOM.render method
|
2018-11-26 10:47:33 +03:00
|
|
|
const dom = new JSDOM(
|
|
|
|
`
|
2018-10-25 03:34:47 +03:00
|
|
|
<!doctype html>
|
|
|
|
<html>
|
|
|
|
<body>
|
|
|
|
<div id="root"><div id="challenge-node"></div>
|
|
|
|
</body>
|
|
|
|
</html>
|
2018-11-26 10:47:33 +03:00
|
|
|
`,
|
|
|
|
{
|
|
|
|
runScripts: 'dangerously',
|
|
|
|
virtualConsole,
|
|
|
|
url: 'http://localhost'
|
|
|
|
}
|
|
|
|
);
|
2018-10-25 03:34:47 +03:00
|
|
|
|
|
|
|
const { window } = dom;
|
|
|
|
const document = window.document;
|
|
|
|
|
|
|
|
global.window = window;
|
|
|
|
global.document = document;
|
|
|
|
|
|
|
|
global.navigator = {
|
|
|
|
userAgent: 'node.js'
|
|
|
|
};
|
|
|
|
global.requestAnimationFrame = callback => setTimeout(callback, 0);
|
|
|
|
global.cancelAnimationFrame = id => clearTimeout(id);
|
|
|
|
|
|
|
|
// Provide dependencies, just provide all of them
|
|
|
|
dom.window.React = require('react');
|
|
|
|
dom.window.ReactDOM = require('react-dom');
|
|
|
|
dom.window.PropTypes = require('prop-types');
|
|
|
|
dom.window.Redux = require('redux');
|
|
|
|
dom.window.ReduxThunk = require('redux-thunk');
|
|
|
|
dom.window.ReactRedux = require('react-redux');
|
|
|
|
dom.window.Enzyme = require('enzyme');
|
|
|
|
const Adapter16 = require('enzyme-adapter-react-16');
|
|
|
|
dom.window.Enzyme.configure({ adapter: new Adapter16() });
|
|
|
|
|
|
|
|
dom.window.require = require;
|
|
|
|
dom.window.code = code;
|
|
|
|
dom.window.editor = {
|
|
|
|
getValue() {
|
|
|
|
return code;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2018-11-26 10:47:33 +03:00
|
|
|
await runTestInJsdom(dom, test.testString, scriptString);
|
2018-10-25 03:34:47 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
async function runTestInJsdom(dom, testString, scriptString = '') {
|
|
|
|
// jQuery used by tests
|
|
|
|
jQuery(dom.window);
|
|
|
|
|
|
|
|
dom.window.assert = assert;
|
|
|
|
dom.window.DeepEqual = DeepEqual;
|
|
|
|
dom.window.DeepFreeze = DeepFreeze;
|
|
|
|
|
|
|
|
dom.window.__test = testString;
|
|
|
|
scriptString += `;
|
2018-10-25 17:23:00 +03:00
|
|
|
window.__result =
|
2018-10-25 03:34:47 +03:00
|
|
|
(async () => {
|
|
|
|
try {
|
|
|
|
const testResult = eval(__test);
|
|
|
|
if (typeof testResult === 'function') {
|
2018-12-02 00:54:25 +03:00
|
|
|
await testResult(() => code);
|
2018-10-25 03:34:47 +03:00
|
|
|
}
|
|
|
|
}catch (e) {
|
|
|
|
window.__error = e;
|
|
|
|
}
|
|
|
|
})();`;
|
|
|
|
const script = new vm.Script(scriptString);
|
2018-11-16 21:16:27 +03:00
|
|
|
dom.runVMScript(script, { timeout: 5000 });
|
2018-10-25 17:23:00 +03:00
|
|
|
await dom.window.__result;
|
2018-10-25 03:34:47 +03:00
|
|
|
if (dom.window.__error) {
|
|
|
|
throw dom.window.__error;
|
|
|
|
}
|
|
|
|
}
|