When writing acceptance tests, you often need to wait for something to happen. The easy thing to do is just wait for a certain period of time before checking, but that can make your tests slower than necessary. The accepted solution is to poll for whatever it is that you’re waiting for.
C# has a handy SpinWait.SpinUntil method, and I found this node module with similar behaviour. I needed it to work with promises though, so I ended up writing my own:
var DEFAULT_TIMEOUT = 5000;
function waitUntil (predicate, done, timeout, started) {
timeout = defaultParameter(timeout, DEFAULT_TIMEOUT);
started = defaultParameter(started, Date.now());
predicate().done(function(res) {
if (res) {
return done();
}
if ((started + timeout) < Date.now()) {
throw new Error("timed out");
}
setTimeout(function() {
waitUntil(predicate, done, timeout, started);
}, 100);
});
};
function defaultParameter (parameter, defaultValue) {
if (typeof(parameter) === 'undefined') {
return defaultValue;
}
return parameter;
};
module.exports.waitUntil = waitUntil;
The first argument needs to be a predicate function, that returns a promise; and the second will be called if the first ever succeeds. You can also change the default timeout (5s). Something like this:
SpinWait.waitUntil(function() {
return getAllTransactions(USER_ID).then(function(data) {
return data.rows.length > 0;
});
}, function() {
getAllTransactions(USER_ID).done(function(data) {
assert.equal(1, data.rows.length);
var transaction = data.rows[0];
assert.equal(1000, transaction.amount);
done();
});
});