Skip to content

Instantly share code, notes, and snippets.

@samselikoff
Last active June 24, 2020 19:56
Show Gist options
  • Save samselikoff/ad5e3695383b91599ee428bf9a2d22ca to your computer and use it in GitHub Desktop.
Save samselikoff/ad5e3695383b91599ee428bf9a2d22ca to your computer and use it in GitHub Desktop.
How to use an `asyncThrows` custom helper.

This assert.asyncThrows custom assertion allows us to write tests against failing async code, usually as a result of a server error (4xx/5xx response).

test('If the index route errors, I see a message', async function(assert) {
  server.create('post');
  server.get('/posts/:id', { errors: ['The site is down'] }, 500); // force Mirage to error

  await assert.asyncThrows(() => {
    return visit('/posts/1');
  }, 'GET /posts/1 returned a 500');

  assert.ok(find(':contains(The site is down)').length > 1);
});

Without this helper, a failed XHR request would trigger an exception in QUnit's test suite.

How to use

  1. Install Ember CLI Custom Assertions
  2. Add the file below under /tests/assertions/async-throws.js

Now you can use assert.asyncThrows in your test. The first argument is a function that's expected to return a promise; the second is a string that must match the exception you expect to be thrown.

import Ember from 'ember';
let originalLoggerError;
let originalTestAdapterException;
let originalEmberOnError;
let originalWindowOnError;
function intercept(f = () => {}) {
originalLoggerError = Ember.Logger.error;
originalTestAdapterException = Ember.Test.adapter.exception;
originalWindowOnError = window.onerror;
originalEmberOnError = Ember.onerror;
Ember.Logger.error = () => {};
Ember.Test.adapter.exception = () => {};
Ember.onerror = f;
window.onerror = () => {};
}
function restore() {
Ember.Logger.error = originalLoggerError;
Ember.Test.adapter.exception = originalTestAdapterException;
Ember.onerror = originalEmberOnError;
window.onerror = originalWindowOnError;
}
export default function asyncThrows(context, f, text) {
let done = this.async();
let loggedErrorArgs;
intercept((...args) => {
loggedErrorArgs = args;
});
return f()
.then(() => {
let errorText = (loggedErrorArgs || []).join(' ');
if (text) {
let result = errorText.match(text);
this.pushResult({
result,
expected: text,
actual: errorText,
message: `Expected to see error '${text}'`
});
} else {
this.pushResult({
result: false,
expected: '',
actual: errorText,
message: `You're using asyncThrows but you didn't add text to the assertion. Add some text as the second argument so the actual exception being thrown is what you expect it is.`
});
}
return done();
})
.then(() => {
return restore();
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment