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(); }); });