Feat(challenges): Adds the ability to test with async methods

This commit is contained in:
Berkeley Martinez
2016-09-12 13:21:41 -07:00
parent 57565581fb
commit 97e0bc8e87

View File

@ -3,6 +3,7 @@ document.addEventListener('DOMContentLoaded', function() {
var frameId = window.__frameId; var frameId = window.__frameId;
var frameReady = common[frameId + 'Ready$'] || { onNext() {} }; var frameReady = common[frameId + 'Ready$'] || { onNext() {} };
var Rx = document.Rx; var Rx = document.Rx;
var helpers = Rx.helpers;
var chai = parent.chai; var chai = parent.chai;
var source = document.__source; var source = document.__source;
@ -37,32 +38,68 @@ document.addEventListener('DOMContentLoaded', function() {
// add delay here for firefox to catch up // add delay here for firefox to catch up
.delay(200) .delay(200)
/* eslint-disable no-unused-vars */ /* eslint-disable no-unused-vars */
.map(({ text, testString }) => { .flatMap(({ text, testString }) => {
const assert = chai.assert; const assert = chai.assert;
/* eslint-enable no-unused-vars */ /* eslint-enable no-unused-vars */
const newTest = { text, testString }; const newTest = { text, testString };
let test; let test;
let __result;
try { try {
/* eslint-disable no-eval */ /* eslint-disable no-eval */
// eval test string to actual JavaScript
// This return can be a function
// i.e. function() { assert(true, 'happy coding'); }
test = eval(testString); test = eval(testString);
/* eslint-enable no-eval */ /* eslint-enable no-eval */
if (typeof test === 'function') { if (typeof test === 'function') {
// maybe sync/promise/observable
// we know that the test eval'ed to a function
// the function could expect a callback
// or it could return a promise/observable
// or it could still be sync
if (test.length === 0) { if (test.length === 0) {
test(); // a function with length 0 means it expects 0 args
// We call it and store the result
// This result may be a promise or an observable or undefined
__result = test();
} else {
// if function takes arguments
// we expect it to be of the form
// function(cb) { /* ... */ }
// and callback has the following signature
// function(err) { /* ... */ }
__result = Rx.Observable.fromNodeCallback(test)();
} }
// callback test
if (test.length === 1) { if (helpers.isPromise(__result)) {
console.log('callback test'); // turn promise into an observable
__result = Rx.Observable.fromPromise(__result);
} }
} else {
// test is not a function
// fill result with for compatibility
__result = Rx.Observable.of(null);
} }
} catch (e) { } catch (e) {
newTest.err = e.message + '\n' + e.stack; // something threw an uncaught error
// we catch here and wrap it in an observable
__result = Rx.Observable.throw(e);
} }
if (!newTest.err) { return __result
newTest.pass = true; .map(() => {
} // we don't need the result of a promise/observable/cb here
return newTest; // all data asserts should happen further up the chain
// mark test as passing
newTest.pass = true;
return newTest;
})
.catch(err => {
// we catch the error here to prevent the error from bubbling up
// and collapsing the pipe
newTest.err = err.message + '\n' + err.stack;
// RxJS catch expects an observable as a return
return Rx.Observable.of(err);
});
}) })
// gather tests back into an array // gather tests back into an array
.toArray(); .toArray();