Commit 2ea032bd authored by Daniel Shumway's avatar Daniel Shumway

feat: `attachPostResolve` error and option

 - probably needs a rename
parent 3c37e061
Pipeline #8461549 passed with stage
in 1 minute
......@@ -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
reporter : options.reporter || function () {},
reporter : options.reporter,
//TRAVERSAL
parent : options.parent || null,
......@@ -92,9 +92,11 @@ 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
timeout : options.timeout || 2500, //How long before a promise is auto-rejected
attachPostResolve : !!options.attachPostResolve, //Can you call `test` on a suite that's already finished?
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.
boundReporter : options.reporter.bind(that, that) //@HACK I would prefer not to define another variable here.
};
_that[PRIVATE] = _that;
......@@ -112,10 +114,8 @@ var Suite = (function () {
return Promise.reject(error);
});
//Auto-attach reporter to `that` callback.
that.then(function () {
_that.reporter.apply(this, arguments);
});
// Auto-attach reporter
that.then(_that.boundReporter);
}
Suite._prototype = {
......@@ -172,25 +172,31 @@ var Suite = (function () {
_that.callbacks.push(callback);
}
if (!_that.pendingChildren) {
if (_that.pendingChildren) {
return;
}
/*
* 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();
/*
* 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.
* When possible, make the reporter the last callback to fire off. Helps with extensions.
*/
while (_that.callbacks.length > 0) {
let priorCallback = _that.callbacks.shift();
if (_that.callbacks.length !== 0 && priorCallback === _that.boundReporter) {
_that.callbacks.push(priorCallback);
} else {
priorCallback();
}
//Reporters are ALWAYS called last.
//_that.reporter(); //#!%$&, need a reference to the public context here, don't I?
}
}
},
};
Suite.prototype = {
......@@ -208,16 +214,30 @@ var Suite = (function () {
var that = this,
_that = this[PRIVATE];
assertion = _that.wrap(assertion);
var suite,
promise = _that.promise.then(function () {
//No need to catch exceptions since the promise we're in will handle them.
//https://promisesaplus.com/#point-34 - both `promise` and `suite` will be set by execution time
return assertion.call(suite, suite);
}, function (error) {
_that.skip.call(suite);
throw error;
});
/*
* A suite is considered "finished" if:
* - it isn't pending
* - it has no unresolved `then` calls
* - the user hasn't turned off the "finished" state
*/
var autoReject = !(_that.status === STATUS.PENDING || _that.callbacks.length || _that.attachPostResolve);
assertion = autoReject ?
_that.wrap(
Promise.reject(
new Error('Test attached after suite has already finished. Usually, this is a mistake. Set `options.attachPostResolve` to override this behavior.')
)
) : _that.wrap(assertion);
var suite; //Used in later closure
var promise = _that.promise.then(function () {
//No need to catch exceptions since the promise we're in will handle them.
//https://promisesaplus.com/#point-34 - both `promise` and `suite` will be set by execution time
return assertion.call(suite, suite);
}, function (error) {
_that.skip.call(suite);
throw error;
});
suite = Object.create(that.constructor.prototype);
......@@ -233,7 +253,9 @@ var Suite = (function () {
/* Whenever a child suite finishes its callback, decrement the child count by 1 */
suite.then(function () {
_that.pendingChildren--;
_that.tryCallbacks();
/* If the reporter has already fired off, retrigger it for the new test. */
_that.tryCallbacks(_that.callbacks.length ? null : _that.boundReporter);
});
_that.children.push(suite);
......@@ -273,6 +295,7 @@ function Distilled(reporter, options) {
promise : null,
parent : null,
timeout : options.timeout,
attachPostResolve : options.attachPostResolve,
reporter : reporter || REPORTERS.default,
});
}
......
......@@ -95,7 +95,7 @@ suite.test('advanced recursion', function () {
if (test === _func_exception) {
def.resolve(assertion);
}
});
}, { attachPostResolve : true });
var _res_undefined = _suite.test('res undefined', Promise.resolve()),
_res_false = _suite.test('res false', Promise.resolve(false)),
......
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