ember.js: Test.adapter.exception forces acceptance test to fail (RSVP error fails test)
My workaround is here: https://github.com/emberjs/guides/issues/1157 at first I thought it may be best to address with an update to testing guides, but not so sure that is the best way to fix.
Steps to reproduce:
Here is an example repository with an Ember CLI app: https://github.com/pixelhandler/application-error-test (Can’t be done w/ a jsbin/fiddle/ember-twiddle - since this issue is with the testing env.)
Below are the steps I used to create the example app.
- Create an app with one of the model hooks making an XHR request.
- Create an application-error template, perhaps use
{{model.message}}since the error will become the model via application-error route’s setupController hook. - Create an acceptance test to test that the application-error template displays the error message.
- In the acceptance test, mock the XHR - to return a 502 response. (I used Sinon.js with ember-sinon addon)
- Write an assertion that checks the DOM, e.g.
visit('/'); andThen(function(){ assert.equal(find('.error-message').length(), 1); });
Expected Result:
The test passes even though an error was thrown in the route’s model hook by the mocked 502 response.
Actual Result:
The Assertion passes as the template is rendered, but the test fails since Test.adapter.exception is called. Which throws, and causes the test to fail - as a result of the “same” expected error that causes the application-error substate to render.
Attempts to solve:
- Tried 2.4.0-canary+10ab23d8 since a couple developer mentions this looks related: https://github.com/emberjs/ember.js/pull/12549
- Setup a custom error for the XHR failure that has a
nameproperty ofTransitionAborted. This is the code fails the test for the applicaiton-error.hbs template -> https://github.com/emberjs/ember.js/blob/master/packages/ember-runtime/lib/ext/rsvp.js#L66 (this works but is a hack) - Reopened
Ember.Test.QUnitAdapterand redefinedexceptionas the example below:
Because an error is thrown and the env is testing - Ember RSVP calls Test.adapter.exception. Which fails the test; because there was an error (we expected an error to be handled by the application-error route/controller/template and it was). In the acceptance test, using assert.throws will not help since it’s async.
I found that I had to reopen my test adapter in the acceptance test like so:
tests/acceptance/application-error-test.js
import { test } from 'qunit';
import Ember from 'ember';
import moduleForAcceptance from 'application-error-test/tests/helpers/module-for-acceptance';
import startApp from 'application-error-test/tests/helpers/start-app';
import sinon from 'sinon';
Ember.Test.QUnitAdapter.reopen({
/*
This is a hack, throwing an error in a route must use the error.name
`TransitionAborted`; otherwise, `Test.adapter.exception(error)` inside
`onerrorDefault` fails tests via the same error that results in rendering
the application-error template.
*/
exception: function(error) {
var makeItPass = false;
debugger; // FIXME… CHANGE ^ to true to work around bug
if (makeItPass /* we mocked a 502 so expected an error, it renders the application-error template… */) {
console.warn('Expected this error, ignoring (no reason to fail a test)…', error);
} else /* normal behavior… if (error.name !== 'TransitionAborted') */ {
return this._super.call(this, error);
}
}
});
moduleForAcceptance('Acceptance | application-error', {
beforeEach: function setup() {
this.sandbox = sinon.sandbox.create();
setupFakeServer.call(this);
mockFetchSession.call(this);
this.application = startApp();
},
afterEach: function teardown() {
Ember.run(this.application, 'destroy');
this.sandbox.restore();
delete this.sandbox;
}
});
test('with a server error, the application-error template renders', function(assert) {
let done = assert.async();
visit('/');
andThen(function() {
assert.equal(currentURL(), '/', 'URL is "/"');
assert.equal(find('.error-message').length, 1, 'Application error template rendered');
done();
});
});
function setupFakeServer() {
this.sandbox.stub(Ember.$, 'ajaxPrefilter');
this.server = this.sandbox.useFakeServer();
this.server.autoRespond = true;
}
function mockFetchSession() {
mockBadGatewayResponse.call(this);
}
function mockBadGatewayResponse() {
this.server.respondWith('GET', 'api/session', [
502,
{ 'Content-Type':'text/html; charset=utf-8' },
`<html>
<head><title>502 Bad Gateway</title></head>
<body><h1 class="error-message-content">Bad Gateway</h1></body>
</html>`
]);
}
Pseudo application code
templates/application-error.hbs
<h1>Oops, there was an error…</h1>
<p class="error-message">{{model.message}}</p>
import Ember from 'ember';
export default Ember.Route.extend({
model() {
return Ember.$.ajax({url: 'api/session', method: 'GET'});
}
});
Be sure to see the README of the example repo. This is the commit that shows the setup for the example app.
About this issue
- Original URL
- State: closed
- Created 8 years ago
- Reactions: 3
- Comments: 22 (15 by maintainers)
Commits related to this issue
- Example app for https://github.com/emberjs/ember.js/issues/12791 — committed to pixelhandler/application-error-test by deleted user 8 years ago
- Example app for https://github.com/emberjs/ember.js/issues/12791 — committed to pixelhandler/application-error-test by deleted user 8 years ago
- skip test cases for not-found record open issue in ember.js https://github.com/emberjs/ember.js/issues/12791 — committed to crossroads/app.goodcity by swatijadhav 8 years ago
- skip test cases for not-found record open issue in ember.js https://github.com/emberjs/ember.js/issues/12791 — committed to crossroads/app.goodcity by swatijadhav 8 years ago
- skip test cases for not-found record open issue in ember.js https://github.com/emberjs/ember.js/issues/12791 — committed to crossroads/app.goodcity by swatijadhav 8 years ago
I adapted this code and put it in
start-app.jsto apply it across all acceptance tests. This has also been causing problems for me in updating, in this case from 1.13 to 2.4. Some of our acceptance tests expect errors from the mock API to test error-handling.I’m only just encountering this fix now, but I hope I can come up with a way to mark an exception as expected for particular tests to still have the fail-on-error for unexpected exceptions.
overriding
Ember.Test.adapter.exceptionis fine but make tests pass even if an exception is thrown.With an helper like
You can target user interactions that will throw exceptions with
There is surely a better way to implement this but this works fine for me.
It may help someone: in my case I had to use
instead of
t
Thank you @pixelhandler and @aquamme. I have taken your code, generalised it into a module and published it as https://gist.github.com/pablobm/5ec0fee8a877badaca2c11bf4751e857