diff --git a/client/commonFramework/add-faux-stream.js b/client/commonFramework/add-faux-stream.js index c25f69f75b..17a57e212c 100644 --- a/client/commonFramework/add-faux-stream.js +++ b/client/commonFramework/add-faux-stream.js @@ -1,35 +1,22 @@ window.common = (function(global) { const { - $, - Rx: { Observable, Disposable }, common = { init: [] } } = global; - function getFaux() { - return new Observable(function(observer) { - const jqXHR = $.get('/js/faux.js') - .success(data => observer.onNext(data)) - .fail(e => observer.onError(e)) - .always(() => observer.onCompleted()); + const faux$ = common.getScriptContent$('/js/faux.js').shareReplay(); - return new Disposable(() => { - jqXHR.abort(); - }); - }); - } - - const faux$ = getFaux().shareReplay(); - - common.safeHTMLRun = function safeHTMLRun(code) { - if (!code.match(/\/gi)) { - return Observable.just(code); - } + common.hasJs = function hasJs(code = '') { + return code.match(/\<\s?script\s?\>/gi) && + code.match(/\<\s?\/\s?script\s?\>/gi); + }; + common.addFaux$ = function addFaux$(code) { // grab user javaScript var scriptCode = code .split(/\<\s?script\s?\>/gi)[1] .split(/\<\s?\/\s?script\s?\>/gi)[0]; + return faux$.map(faux => faux + scriptCode); }; diff --git a/client/commonFramework/end.js b/client/commonFramework/end.js index 3f2dbdd689..7fa85bb830 100644 --- a/client/commonFramework/end.js +++ b/client/commonFramework/end.js @@ -71,24 +71,24 @@ $(document).ready(function() { } ); - var $preview = $('#preview'); - if ($preview.html()) { - $preview.load(function() { - common.executeChallenge() - .subscribe( - ({ output = '' }) => { - common.updateOutputDisplay(output); - }, - ({ err }) => { - common.updateOutputDisplay('' + err); - } - ); - }); - } else if ( - challengeType !== '2' && - challengeType !== '3' && - challengeType !== '4' && - challengeType !== '7' + if (challengeType === challengeTypes.HTML) { + var $preview = $('#preview'); + return Observable.fromCallback($preview.ready, $preview)() + .delay(500) + .flatMap(() => common.executeChallenge$()) + .subscribe( + ({ code, tests }) => { + common.displayTestResults(tests); + }, + ({ err }) => { + console.error(err); + } + ); + } + + if ( + challengeType === challengeTypes.BONFIRE && + challengeType === challengeTypes.JS ) { Observable.just({}) .delay(500) diff --git a/client/commonFramework/execute-challenge-stream.js b/client/commonFramework/execute-challenge-stream.js index dfcfdf0d9e..57196e2312 100644 --- a/client/commonFramework/execute-challenge-stream.js +++ b/client/commonFramework/execute-challenge-stream.js @@ -84,9 +84,28 @@ window.common = (function(global) { // add head and tail and detect loops return Observable.just({ code: head + code + tail, original: code }); }) - .map(data => { + .flatMap(data => { if (common.challengeType === common.challengeTypes.HTML) { - return common.getScriptCode(data); + + if (common.hasJs(code)) { + return common.addFaux$(data) + .flatMap(code => common.detectLoops$(code)) + .flatMap(({ err }) => { + if (err) { + return Observable.throw({ err }); + } + return common.runPreviewTests$({ + code: data.code, + tests: common.tests.slice() + }); + }); + } + + return common.updatePreview$(data.code) + .flatMap(code => common.runPreviewTests$({ + code, + tests: common.tests.slice() + })); } return common.addTestsToString(Object.assign( @@ -95,21 +114,21 @@ window.common = (function(global) { code: common.removeComments(code), tests: common.tests.slice() } - )); - }) - .flatMap(common.detectLoops$) - .flatMap(({ err, code, data, userTests, original }) => { - if (err) { - return Observable.throw({ err }); - } + )) + .flatMap(common.detectLoops$) + .flatMap(({ err, code, data, userTests, original }) => { + if (err) { + return Observable.throw({ err }); + } - return common.runTests$({ - data, - code, - userTests, - original, - output: data.output.replace(/\\\"/gi, '') - }); + return common.runTests$({ + data, + code, + userTests, + original, + output: data.output.replace(/\\\"/gi, '') + }); + }); }) .catch(e => { return e && e.err ? diff --git a/client/commonFramework/init.js b/client/commonFramework/init.js index 05bf8a520e..152bc3b71e 100644 --- a/client/commonFramework/init.js +++ b/client/commonFramework/init.js @@ -3,7 +3,7 @@ window.common = (function(global) { // all classes should be stored here // called at the beginning of dom ready const { - Rx: { config }, + Rx: { Disposable, Observable, config }, common = { init: [] } } = global; @@ -86,5 +86,21 @@ window.common = (function(global) { return code.replace(regexp, text); }; + common.getScriptContent$ = function getScriptContent$(script) { + return Observable.create(function(observer) { + const jqXHR = $.get(script) + .success(data => { + observer.onNext(data); + observer.onCompleted(); + }) + .fail(e => observer.onError(e)) + .always(() => observer.onCompleted()); + + return new Disposable(() => { + jqXHR.abort(); + }); + }); + }; + return common; })(window); diff --git a/client/commonFramework/output-display.js b/client/commonFramework/output-display.js index 3220510db8..7850435317 100644 --- a/client/commonFramework/output-display.js +++ b/client/commonFramework/output-display.js @@ -5,12 +5,12 @@ window.common = (function(global) { common = { init: [] } } = global; - const { challengeType = '0' } = common; + const { challengeTypes, challengeType = '0' } = common; if ( !CodeMirror || - challengeType === '0' || - challengeType === '7' + challengeType !== challengeTypes.JS || + challengeType !== challengeTypes.BONFIRE ) { common.updateOutputDisplay = () => {}; common.appendToOutputDisplay = () => {}; diff --git a/client/commonFramework/update-preview.js b/client/commonFramework/update-preview.js index 3608a65bd8..d6ee1a0743 100644 --- a/client/commonFramework/update-preview.js +++ b/client/commonFramework/update-preview.js @@ -1,4 +1,4 @@ -window.common = (function({ common = { init: [] } }) { +window.common = (function({ Rx: { Observable }, common = { init: [] } }) { var libraryIncludes = ` `; - var iFrameScript = ""; + const iFrameScript$ = + common.getScriptContent$('/js/iFrameScripts.js').shareReplay(); + // runPreviewTests$ should be set up in the preview window + common.runPreviewTests$ = + () => Observable.throw({ err: new Error('run preview not enabled') }); - common.updatePreview = function updatePreview(code = '', shouldTest = false) { + common.updatePreview$ = function updatePreview$(code = '') { const previewFrame = document.getElementById('preview'); const preview = previewFrame.contentDocument || previewFrame.contentWindow.document; if (!preview) { - return code; + return Observable.just(code); } - preview.open(); - preview.write(libraryIncludes + code + (shouldTest ? iFrameScript : '')); - preview.close(); - return code; + return iFrameScript$ + .map(script => ``) + .doOnNext(script => { + preview.open(); + preview.write(libraryIncludes + code + script); + preview.close(); + }) + .map(() => code); }; return common; diff --git a/client/iFrameScripts.js b/client/iFrameScripts.js index 66cb8554ba..5fbf663a11 100644 --- a/client/iFrameScripts.js +++ b/client/iFrameScripts.js @@ -2,27 +2,36 @@ window.$ = parent.$; window.$(function() { var _ = parent._; + var Rx = parent.Rx; var chai = parent.chai; - var expect = chai.expect; + var assert = chai.assert; var tests = parent.tests; var common = parent.common; - var editorValue = common.editor.getValue(); + var code = common.editor.getValue(); var editor = common.editor; - var userTests = common.tests.map(test => { - var userTest = {}; - try { - /* eslint-disable no-eval */ - eval(test); - /* eslint-enable no-eval */ - } catch (e) { - userTest.err = e.message.split(':').shift(); - } finally { - userTest.text = test - .split(',') - .pop() - .replace(/\'/g, '') - .replace(/\)/, ''); - } - }); + common.runPreviewTests$ = + function runPreviewTests$({ tests = [], ...rest }) { + return Rx.Observable.from(tests) + .map(test => { + const userTest = {}; + try { + /* eslint-disable no-eval */ + eval(test); + /* eslint-enable no-eval */ + } catch (e) { + userTest.err = e.message.split(':').shift(); + } finally { + userTest.text = test + .split(',') + .pop() + .replace(/\'/g, '') + .replace(/\)/, ''); + } + return userTest; + }) + .toArray() + .map(tests => ({ ...rest, tests })); + }; + });