Commit c4194e4a authored by Daniel Shumway's avatar Daniel Shumway

feat: change behavior of `then` to depend on child tests

- still needs additional testing
- need to play with it a bit more and think about asynchronously attached tests
parent a00a7eb4
......@@ -79,7 +79,7 @@ var Suite = (function () {
var _that = this[PRIVATE] = {
__proto__ : Suite._prototype, //TODO: how many browsers do I lock out with this? Do I care?
promise : options.promise || Promise.resolve(), //Group will run tests once parent promise has resolved
callback : options.callback || function () {},
reporter : options.reporter || function () {},
//TRAVERSAL
parent : options.parent || null,
......@@ -93,6 +93,8 @@ var Suite = (function () {
//RANDOM EXTRAS
// - should keep these to a minimum, but some things are just too handy
timeout : options.timeout || 5000, //How long before a promise is auto-rejected
callbacks : [], //Pending callbacks that haven't fired off yet...
pendingChildren : 0, //How many children haven't resolved yet? Track as a number because that's enough, you don't need to track specifics.
};
_that[PRIVATE] = _that;
......@@ -111,7 +113,9 @@ var Suite = (function () {
});
//Auto-attach reporter to `that` callback.
that.then(_that.callback);
that.then(function () {
_that.reporter.apply(this, arguments);
});
}
Suite._prototype = {
......@@ -160,6 +164,33 @@ var Suite = (function () {
var _that = this[PRIVATE];
_that.status = STATUS.SKIPPED;
},
tryCallbacks : function (callback) {
var _that = this[PRIVATE];
if (callback) {
_that.callbacks.push(callback);
}
if (!_that.pendingChildren) {
/*
* While loops are always dangerous, but in this case called for.
* - a user might attach a new callback as part of a callback.
* - in which case, they'd either not get called or re-call everything.
* - instead, we modify the array in place to make sure things can only get called once.
*
* As a result, you can do some awful, recursive stuff if you want. I won't judge.
*/
while (_that.callbacks.length > 0) {
let priorCallback = _that.callbacks.shift();
priorCallback();
}
//Reporters are ALWAYS called last.
//_that.reporter(); //#!%$&, need a reference to the public context here, don't I?
}
}
};
Suite.prototype = {
......@@ -188,12 +219,21 @@ var Suite = (function () {
throw error;
});
suite = Object.create(that.constructor.prototype);
Suite.call(suite, {
label : message,
promise : promise,
parent : that,
callback : _that.callback
reporter : _that.reporter
});
_that.pendingChildren++; /* whenever you add a new child, increment it */
/* Whenever a child suite finishes its callback, decrement the child count by 1 */
suite.then(function () {
_that.pendingChildren--;
_that.tryCallbacks();
});
_that.children.push(suite);
......@@ -204,16 +244,16 @@ var Suite = (function () {
var that = this,
_that = this[PRIVATE];
//Allow passing blank? Not sure why, but I'll allow it.
if (typeof callback !== 'function') {
if (typeof callback !== 'function') { //Allow passing blank? Not sure why, but sure.
callback = function () {};
}
callback = callback.bind(that, that); //Pre-assign the correct context/parameters
_that.promise.then(function () {
callback.call(that, that);
_that.tryCallbacks(callback);
}, function () {
if (_that.status === STATUS.SKIPPED) { return; }
callback.call(that, that);
_that.tryCallbacks(callback);
}).catch(function (err) { //Polyfill while waiting for https://github.com/nodejs/node/pull/8217
console.log('Uncaught error in suite callback:\n', err);
process.exit(1);
......@@ -226,14 +266,14 @@ var Suite = (function () {
return Suite;
}());
function Distilled(callback, options) {
function Distilled(reporter, options) {
options = options || {};
Suite.call(this, {
label : null,
promise : null,
parent : null,
timeout : options.timeout,
callback : callback || REPORTERS.default,
reporter : reporter || REPORTERS.default,
});
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment