Using asyncExpect() in tests

Do you have a use case where you need to wait for changes in UI for some time (say, wait for a debounce for 300 ms) before you can test the value change? You can use asyncExpect() instead of using setTimeout()!

Let’s say you have an input field in a page which has a 300ms debounce (which could change in the future) and you need to test whether the input to the field changes the value of the state. One way to solve this is by using setTimeout() in your test like this:

it('to be actual value', function(done) {
  ...
  setTimeout(function() {
    expect(actualValue).toEqual(this.testValue);
    done();
  }.bind(this), 500);
});

(actualValue is say, the value obtained from the state of an input)

Even though this is a valid solution, it might not necessarily be your best bet because anything that involves a hardcoded time element, can potentially lead to unstable tests. So it is good practice to use asyncExpect() like this:

it('to be actual value', function(done) {
  ...
  this.asyncExpect(
    function () { return actualValue; },
    'toEqual', [this.testValue], this
  ).then(done, done.fail);
});

This is much cleaner and you can set custom timeouts and retry intervals and can less likely break tests!

Note: You can currently us it in the jasmine context. asyncExpect() doesn’t work on enzyme tests yet.
PS: Thanks @leonzhu for helping me explore this!