| 
									
										
										
										
											2019-01-15 17:18:56 +03:00
										 |  |  | const path = require('path'); | 
					
						
							|  |  |  | const liveServer = require('live-server'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const spinner = require('ora')(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const clientPath = path.resolve(__dirname, '../../client'); | 
					
						
							|  |  |  | require('@babel/polyfill'); | 
					
						
							|  |  |  | require('@babel/register')({ | 
					
						
							|  |  |  |   root: clientPath, | 
					
						
							|  |  |  |   babelrc: false, | 
					
						
							|  |  |  |   presets: ['@babel/preset-env'], | 
					
						
							|  |  |  |   ignore: [/node_modules/], | 
					
						
							|  |  |  |   only: [clientPath] | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const createPseudoWorker = require('./utils/pseudo-worker'); | 
					
						
							|  |  |  | const { | 
					
						
							|  |  |  |   default: createWorker | 
					
						
							|  |  |  | } = require('../../client/src/templates/Challenges/utils/worker-executor'); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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'); | 
					
						
							| 
									
										
										
										
											2019-01-15 17:18:56 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | const jsdom = require('jsdom'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const dom = new jsdom.JSDOM(''); | 
					
						
							|  |  |  | global.document = dom.window.document; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-25 03:34:47 +03:00
										 |  |  | 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 { getChallengesForLang } = require('../getChallenges'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const MongoIds = require('./utils/mongoIds'); | 
					
						
							|  |  |  | const ChallengeTitles = require('./utils/challengeTitles'); | 
					
						
							| 
									
										
										
										
											2018-12-05 20:09:18 +03:00
										 |  |  | const { challengeSchemaValidator } = require('../schema/challengeSchema'); | 
					
						
							| 
									
										
										
										
											2018-10-25 03:34:47 +03:00
										 |  |  | const { challengeTypes } = require('../../client/utils/challengeTypes'); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-05 22:04:30 +03:00
										 |  |  | const { supportedLangs } = require('../utils'); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-15 17:18:56 +03:00
										 |  |  | const { | 
					
						
							|  |  |  |   buildDOMChallenge, | 
					
						
							|  |  |  |   buildJSChallenge | 
					
						
							|  |  |  | } = require('../../client/src/templates/Challenges/utils/build'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const { | 
					
						
							|  |  |  |   createPoly | 
					
						
							|  |  |  | } = require('../../client/src/templates/Challenges/utils/polyvinyl'); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-01 18:56:15 +03:00
										 |  |  | const oldRunnerFail = Mocha.Runner.prototype.fail; | 
					
						
							|  |  |  | Mocha.Runner.prototype.fail = function(test, err) { | 
					
						
							| 
									
										
										
										
											2018-12-05 22:04:30 +03:00
										 |  |  |   if (err instanceof AssertionError) { | 
					
						
							|  |  |  |     const errMessage = String(err.message || ''); | 
					
						
							|  |  |  |     const assertIndex = errMessage.indexOf(': expected'); | 
					
						
							| 
									
										
										
										
											2018-12-01 02:47:32 +03:00
										 |  |  |     if (assertIndex !== -1) { | 
					
						
							| 
									
										
										
										
											2018-12-05 22:04:30 +03:00
										 |  |  |       err.message = errMessage.slice(0, assertIndex); | 
					
						
							| 
									
										
										
										
											2018-12-01 02:47:32 +03:00
										 |  |  |     } | 
					
						
							|  |  |  |     // Don't show stacktrace for assertion errors.
 | 
					
						
							| 
									
										
										
										
											2018-12-05 22:04:30 +03:00
										 |  |  |     if (err.stack) { | 
					
						
							|  |  |  |       delete err.stack; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-11-01 18:56:15 +03:00
										 |  |  |   } | 
					
						
							|  |  |  |   return oldRunnerFail.call(this, test, err); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-15 17:18:56 +03:00
										 |  |  | async function newPageContext(browser) { | 
					
						
							|  |  |  |   const page = await browser.newPage(); | 
					
						
							|  |  |  |   // it's needed for workers as context.
 | 
					
						
							|  |  |  |   await page.goto('http://127.0.0.1:8080/index.html'); | 
					
						
							|  |  |  |   return page; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2018-10-25 03:34:47 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-15 17:18:56 +03:00
										 |  |  | spinner.start(); | 
					
						
							|  |  |  | spinner.text = 'Populate tests.'; | 
					
						
							| 
									
										
										
										
											2018-10-25 03:34:47 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-15 17:18:56 +03:00
										 |  |  | let browser; | 
					
						
							|  |  |  | let page; | 
					
						
							| 
									
										
										
										
											2018-10-25 03:34:47 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-05 22:04:30 +03:00
										 |  |  | runTests(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | async function runTests() { | 
					
						
							| 
									
										
										
										
											2018-12-07 14:06:07 +03:00
										 |  |  |   let testLangs = [...supportedLangs]; | 
					
						
							|  |  |  |   if (process.env.TEST_CHALLENGES_FOR_LANGS) { | 
					
						
							|  |  |  |     const filterLangs = process.env.TEST_CHALLENGES_FOR_LANGS.split(',').map( | 
					
						
							|  |  |  |       lang => lang.trim().toLowerCase() | 
					
						
							|  |  |  |     ); | 
					
						
							|  |  |  |     testLangs = testLangs.filter(lang => filterLangs.includes(lang)); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-15 17:18:56 +03:00
										 |  |  |   const challenges = await Promise.all( | 
					
						
							|  |  |  |     testLangs.map(lang => getChallenges(lang)) | 
					
						
							|  |  |  |   ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   describe('Check challenges', function() { | 
					
						
							|  |  |  |     before(async function() { | 
					
						
							|  |  |  |       spinner.text = 'Testing'; | 
					
						
							|  |  |  |       this.timeout(50000); | 
					
						
							|  |  |  |       liveServer.start({ | 
					
						
							|  |  |  |         host: '127.0.0.1', | 
					
						
							|  |  |  |         port: '8080', | 
					
						
							|  |  |  |         root: path.resolve(__dirname, 'stubs'), | 
					
						
							|  |  |  |         mount: [['/js', path.join(clientPath, 'static/js')]], | 
					
						
							|  |  |  |         open: false, | 
					
						
							|  |  |  |         logLevel: 0 | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |       browser = await puppeteer.launch({ | 
					
						
							|  |  |  |         args: ['--no-sandbox'] | 
					
						
							|  |  |  |         // dumpio: true
 | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |       global.Worker = createPseudoWorker(await newPageContext(browser)); | 
					
						
							|  |  |  |       page = await newPageContext(browser); | 
					
						
							|  |  |  |       await page.setViewport({ width: 300, height: 150 }); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |     after(async function() { | 
					
						
							|  |  |  |       this.timeout(30000); | 
					
						
							|  |  |  |       if (browser) { | 
					
						
							|  |  |  |         await browser.close(); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       liveServer.shutdown(); | 
					
						
							|  |  |  |       spinner.stop(); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     challenges.forEach(populateTestsForLang); | 
					
						
							|  |  |  |   }); | 
					
						
							| 
									
										
										
										
											2018-12-05 22:04:30 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  |   run(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-15 17:18:56 +03:00
										 |  |  | async function getChallenges(lang) { | 
					
						
							|  |  |  |   const challenges = 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)]; | 
					
						
							|  |  |  |       }, []) | 
					
						
							|  |  |  |   ); | 
					
						
							| 
									
										
										
										
											2019-01-15 17:18:56 +03:00
										 |  |  |   return { lang, challenges }; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2018-10-25 03:34:47 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-15 17:18:56 +03:00
										 |  |  | function populateTestsForLang({ lang, challenges }) { | 
					
						
							| 
									
										
										
										
											2018-12-05 22:04:30 +03:00
										 |  |  |   const mongoIds = new MongoIds(); | 
					
						
							|  |  |  |   const challengeTitles = new ChallengeTitles(); | 
					
						
							|  |  |  |   const validateChallenge = challengeSchemaValidator(lang); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-15 17:18:56 +03:00
										 |  |  |   describe(`Check challenges (${lang})`, function() { | 
					
						
							| 
									
										
										
										
											2018-11-16 21:16:27 +03:00
										 |  |  |     this.timeout(5000); | 
					
						
							| 
									
										
										
										
											2018-10-25 03:34:47 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-15 17:18:56 +03:00
										 |  |  |     challenges.forEach(challenge => { | 
					
						
							|  |  |  |       describe(challenge.title || 'No title', function() { | 
					
						
							| 
									
										
										
										
											2018-10-25 03:34:47 +03:00
										 |  |  |         it('Common checks', function() { | 
					
						
							|  |  |  |           const result = validateChallenge(challenge); | 
					
						
							|  |  |  |           if (result.error) { | 
					
						
							| 
									
										
										
										
											2018-12-05 22:04:30 +03:00
										 |  |  |             throw new AssertionError(result.error); | 
					
						
							| 
									
										
										
										
											2018-10-25 03:34:47 +03:00
										 |  |  |           } | 
					
						
							|  |  |  |           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
										 |  |  |             }); | 
					
						
							|  |  |  |           }); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-15 17:18:56 +03:00
										 |  |  |         let { files = [] } = challenge; | 
					
						
							| 
									
										
										
										
											2019-01-17 02:50:12 +03:00
										 |  |  |         let createTestRunner; | 
					
						
							| 
									
										
										
										
											2019-01-15 17:18:56 +03:00
										 |  |  |         if (challengeType === challengeTypes.backend) { | 
					
						
							|  |  |  |           it('Check tests is not implemented.'); | 
					
						
							|  |  |  |           return; | 
					
						
							|  |  |  |         } else if ( | 
					
						
							|  |  |  |           challengeType === challengeTypes.js || | 
					
						
							|  |  |  |           challengeType === challengeTypes.bonfire | 
					
						
							| 
									
										
										
										
											2018-11-26 10:47:33 +03:00
										 |  |  |         ) { | 
					
						
							| 
									
										
										
										
											2019-01-17 02:50:12 +03:00
										 |  |  |           createTestRunner = createTestRunnerForJSChallenge; | 
					
						
							| 
									
										
										
										
											2019-01-15 17:18:56 +03:00
										 |  |  |         } else if (files.length === 1) { | 
					
						
							| 
									
										
										
										
											2019-01-17 02:50:12 +03:00
										 |  |  |           createTestRunner = createTestRunnerForDOMChallenge; | 
					
						
							| 
									
										
										
										
											2018-10-25 03:34:47 +03:00
										 |  |  |         } else { | 
					
						
							| 
									
										
										
										
											2019-01-15 17:18:56 +03:00
										 |  |  |           it('Check tests.', () => { | 
					
						
							|  |  |  |             throw new Error('Seed file should be only the one.'); | 
					
						
							|  |  |  |           }); | 
					
						
							| 
									
										
										
										
											2018-10-25 17:23:00 +03:00
										 |  |  |           return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-15 17:18:56 +03:00
										 |  |  |         files = files.map(createPoly); | 
					
						
							| 
									
										
										
										
											2018-10-25 17:23:00 +03:00
										 |  |  |         it('Test suite must fail on the initial contents', async function() { | 
					
						
							| 
									
										
										
										
											2019-01-17 02:50:12 +03:00
										 |  |  |           this.timeout(5000 * tests.length + 1000); | 
					
						
							| 
									
										
										
										
											2018-11-01 18:56:15 +03:00
										 |  |  |           // suppress errors in the console.
 | 
					
						
							|  |  |  |           const oldConsoleError = console.error; | 
					
						
							|  |  |  |           console.error = () => {}; | 
					
						
							| 
									
										
										
										
											2019-01-17 02:50:12 +03:00
										 |  |  |           let fails = false; | 
					
						
							|  |  |  |           let testRunner; | 
					
						
							|  |  |  |           try { | 
					
						
							|  |  |  |             testRunner = await createTestRunner( | 
					
						
							|  |  |  |               { ...challenge, files }, | 
					
						
							|  |  |  |               '', | 
					
						
							|  |  |  |               page | 
					
						
							|  |  |  |             ); | 
					
						
							|  |  |  |           } catch { | 
					
						
							|  |  |  |             fails = true; | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |           if (!fails) { | 
					
						
							|  |  |  |             for (const test of tests) { | 
					
						
							| 
									
										
										
										
											2018-11-26 10:47:33 +03:00
										 |  |  |               try { | 
					
						
							| 
									
										
										
										
											2019-01-17 02:50:12 +03:00
										 |  |  |                 await testRunner(test); | 
					
						
							| 
									
										
										
										
											2018-11-26 10:47:33 +03:00
										 |  |  |               } catch (e) { | 
					
						
							| 
									
										
										
										
											2019-01-17 02:50:12 +03:00
										 |  |  |                 fails = true; | 
					
						
							|  |  |  |                 break; | 
					
						
							| 
									
										
										
										
											2018-11-26 10:47:33 +03:00
										 |  |  |               } | 
					
						
							| 
									
										
										
										
											2019-01-17 02:50:12 +03:00
										 |  |  |             } | 
					
						
							|  |  |  |           } | 
					
						
							| 
									
										
										
										
											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; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-15 17:18:56 +03:00
										 |  |  |         describe('Check tests against solutions', function() { | 
					
						
							| 
									
										
										
										
											2018-10-25 03:34:47 +03:00
										 |  |  |           solutions.forEach((solution, index) => { | 
					
						
							| 
									
										
										
										
											2019-01-17 02:50:12 +03:00
										 |  |  |             it(`Solution ${index + 1}`, async function() { | 
					
						
							|  |  |  |               this.timeout(5000 * tests.length + 1000); | 
					
						
							|  |  |  |               const testRunner = await createTestRunner( | 
					
						
							|  |  |  |                 { ...challenge, files }, | 
					
						
							|  |  |  |                 solution, | 
					
						
							|  |  |  |                 page | 
					
						
							|  |  |  |               ); | 
					
						
							|  |  |  |               for (const test of tests) { | 
					
						
							|  |  |  |                 await testRunner(test); | 
					
						
							|  |  |  |               } | 
					
						
							| 
									
										
										
										
											2018-10-25 03:34:47 +03:00
										 |  |  |             }); | 
					
						
							|  |  |  |           }); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							| 
									
										
										
										
											2018-12-05 22:04:30 +03:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2018-10-25 03:34:47 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-17 02:50:12 +03:00
										 |  |  | async function createTestRunnerForDOMChallenge( | 
					
						
							|  |  |  |   { required = [], template, files }, | 
					
						
							|  |  |  |   solution, | 
					
						
							| 
									
										
										
										
											2019-01-15 17:18:56 +03:00
										 |  |  |   context | 
					
						
							|  |  |  | ) { | 
					
						
							|  |  |  |   if (solution) { | 
					
						
							|  |  |  |     files[0].contents = solution; | 
					
						
							| 
									
										
										
										
											2018-10-25 17:23:00 +03:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2018-10-25 03:34:47 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-13 10:07:14 +03:00
										 |  |  |   const { build, sources, loadEnzyme } = await buildDOMChallenge({ | 
					
						
							|  |  |  |     files, | 
					
						
							| 
									
										
										
										
											2019-01-15 17:18:56 +03:00
										 |  |  |     required, | 
					
						
							|  |  |  |     template | 
					
						
							| 
									
										
										
										
											2018-12-01 02:47:32 +03:00
										 |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-15 17:18:56 +03:00
										 |  |  |   await context.reload(); | 
					
						
							|  |  |  |   await context.setContent(build); | 
					
						
							| 
									
										
										
										
											2019-01-17 02:50:12 +03:00
										 |  |  |   await context.evaluate( | 
					
						
							| 
									
										
										
										
											2019-02-19 01:59:12 +03:00
										 |  |  |     async (sources, loadEnzyme) => { | 
					
						
							| 
									
										
										
										
											2019-02-03 19:49:27 +03:00
										 |  |  |       const code = sources && 'index' in sources ? sources['index'] : ''; | 
					
						
							|  |  |  |       const getUserInput = fileName => sources[fileName]; | 
					
						
							|  |  |  |       await document.__initTestFrame({ code, getUserInput, loadEnzyme }); | 
					
						
							| 
									
										
										
										
											2018-12-01 02:47:32 +03:00
										 |  |  |     }, | 
					
						
							| 
									
										
										
										
											2019-01-15 17:18:56 +03:00
										 |  |  |     sources, | 
					
						
							|  |  |  |     loadEnzyme | 
					
						
							| 
									
										
										
										
											2018-12-01 02:47:32 +03:00
										 |  |  |   ); | 
					
						
							| 
									
										
										
										
											2019-01-17 02:50:12 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-19 01:59:12 +03:00
										 |  |  |   return async ({ text, testString }) => { | 
					
						
							| 
									
										
										
										
											2019-01-17 02:50:12 +03:00
										 |  |  |     try { | 
					
						
							|  |  |  |       const { pass, err } = await Promise.race([ | 
					
						
							|  |  |  |         new Promise((_, reject) => setTimeout(() => reject('timeout'), 5000)), | 
					
						
							|  |  |  |         await context.evaluate(async testString => { | 
					
						
							|  |  |  |           return await document.__runTest(testString); | 
					
						
							|  |  |  |         }, testString) | 
					
						
							|  |  |  |       ]); | 
					
						
							|  |  |  |       if (!pass) { | 
					
						
							|  |  |  |         throw AssertionError(`${text}\n${err.message}`); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } catch (err) { | 
					
						
							|  |  |  |       throw typeof err === 'string' | 
					
						
							|  |  |  |         ? `${text}\n${err}` | 
					
						
							|  |  |  |         : (err.message = `${text}
 | 
					
						
							|  |  |  |         ${err.message}`);
 | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   }; | 
					
						
							| 
									
										
										
										
											2018-10-25 03:34:47 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-17 02:50:12 +03:00
										 |  |  | async function createTestRunnerForJSChallenge({ files }, solution) { | 
					
						
							| 
									
										
										
										
											2019-01-15 17:18:56 +03:00
										 |  |  |   if (solution) { | 
					
						
							|  |  |  |     files[0].contents = solution; | 
					
						
							| 
									
										
										
										
											2018-10-25 17:23:00 +03:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-13 10:07:14 +03:00
										 |  |  |   const { build, sources } = await buildJSChallenge({ files }); | 
					
						
							| 
									
										
										
										
											2019-01-15 17:18:56 +03:00
										 |  |  |   const code = sources && 'index' in sources ? sources['index'] : ''; | 
					
						
							| 
									
										
										
										
											2018-10-25 03:34:47 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-15 17:18:56 +03:00
										 |  |  |   const testWorker = createWorker('test-evaluator'); | 
					
						
							| 
									
										
										
										
											2019-02-19 01:59:12 +03:00
										 |  |  |   return async ({ text, testString }) => { | 
					
						
							| 
									
										
										
										
											2019-01-17 02:50:12 +03:00
										 |  |  |     try { | 
					
						
							|  |  |  |       const { pass, err } = await testWorker.execute( | 
					
						
							|  |  |  |         { testString, build, code, sources }, | 
					
						
							|  |  |  |         5000 | 
					
						
							|  |  |  |       ); | 
					
						
							|  |  |  |       if (!pass) { | 
					
						
							|  |  |  |         throw new AssertionError(`${text}\n${err.message}`); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } catch (err) { | 
					
						
							|  |  |  |       throw typeof err === 'string' | 
					
						
							|  |  |  |         ? `${text}\n${err}` | 
					
						
							|  |  |  |         : (err.message = `${text}
 | 
					
						
							|  |  |  |         ${err.message}`);
 | 
					
						
							|  |  |  |     } finally { | 
					
						
							|  |  |  |       testWorker.killWorker(); | 
					
						
							| 
									
										
										
										
											2018-10-25 03:34:47 +03:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-01-17 02:50:12 +03:00
										 |  |  |   }; | 
					
						
							| 
									
										
										
										
											2018-10-25 03:34:47 +03:00
										 |  |  | } |