Qunit executes the async tests one by one, but how does it know a test is complete, since the tests does not return a Promise which the qunit can await?
In this demo example https://jsfiddle.net/6bnLmyof/
function squareAfter1Second(x) {
const timeout = x * 1000;
console.log("squareAfter1Second x:", x);
return new Promise(resolve => {
setTimeout(() => {
resolve(x * x);
}, timeout);
});
}
const { test } = QUnit;
test( "an async test", async t => {
console.log("starting test1");
t.equal( await squareAfter1Second(3), 9 );
t.equal( await squareAfter1Second(4), 16 );
});
test( "an async test2", async t => {
console.log("starting test2");
t.equal( await squareAfter1Second(1), 1 );
});
There are 2 async tests that run one by one. The tests post a macro task (setTimeout) to the event loop, but somehow qunit is able to wait for the test to complete despite the tests not returning promise. Also, in the souce code of qunit there are no await keywords present.
Async functions always return Promises which resolve once the end of their block is reached (or a return
is reached). So even though nothing is explicitly returned, the await
s mean that both async callbacks implicitly return Promises that resolve after all await
s in the function complete. So test
just needs to iterate through each callback function it's called with, and await
each call.
Here's an example of how you can implement this yourself too, without changing any of the code inside squareAfter1Second
or the test
calls:
const queue = []
const test = (_, callback) => {
queue.push(callback);
};
function squareAfter1Second(x) {
const timeout = x * 1000;
console.log("squareAfter1Second x:", x);
return new Promise(resolve => {
setTimeout(() => {
resolve(x * x);
}, timeout);
});
}
test( "an async test", async t => {
console.log("starting test1");
t.equal( await squareAfter1Second(3), 9 );
t.equal( await squareAfter1Second(4), 16 );
});
test( "an async test2", async t => {
console.log("starting test2");
t.equal( await squareAfter1Second(1), 1 );
});
(async () => {
for (const callback of queue) {
console.log('Awaiting callback...');
await callback({ equal: () => void 0 });
console.log('Callback done');
}
})();