qunit: Add assert method for rejection of promises

This would support the following:

QUnit.test('does stuff', function(assert) {
  assert.throws(() => {
    return new Promise((resolve, reject) => {
      setTimeout(reject, 10, new Error('NOOOOOOOO!!!!!');
    });
  }, /NOOOOOO/);
});

An alternative would be to add a assert.rejects, but I feel like transparently supporting this case in assert.throws is more aligned with how we handle things in other areas.

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Reactions: 2
  • Comments: 17 (17 by maintainers)

Most upvoted comments

TL;DR: LGTM!

I agree the current workaround is worth trying to avoid by providing a built-in convenience method. (The workaround being the idea of returning the promise to QUnit.test after swapping the meaning of resolved and rejected.)

At first, I wasn’t sure whether assert is the best object for the method to exist on. We do have other assert methods that don’t (immediately) assert something (such as async, and expect). But if the method merely provides the inverted promise with an asynchronous assertion chained, that would create a potential usability hazard as the user would need to make sure to still either return the result from assert.reject to QUnit.test or manually attach assert.async to it.

However, I see now that the implementation goes beyond inverting the promise and attaching an assertion to the chain, it also adds async tracking. That was the missing puzzle piece. It does make for a more complex method, but I think in this case that overhead is worth it and makes for a very intuitive method.

One thing to keep in mind here is that this further increases the number of async-tracking methods we have in the public API.

Projects aiming to reduce or avoid multiple async things during tests, will need to keep in mind that assert.rejects is now one more additional pattern to look out for as being indicative of an asynchronous test (e.g. as part of code review). I don’t expect that to be a problem, but something to keep in mind (adding complexity is never cost-free).

Could we create new APIs for promises around asserting that a promise resolves or rejects (possibly supporting a predicate that could be given the resolve/reject arguments and could further validate the result)? That way we can just keep the APIs for promise rejection and exception catching separate.