From 22eabf6aa6945f3034568a045dc9f4ac8106a812 Mon Sep 17 00:00:00 2001 From: Robert Jackson Date: Mon, 27 Nov 2017 14:19:14 -0500 Subject: [PATCH] [BUGFIX lts] Allow Ember.Test.adapter to opt out of `exception` handling. In the majority of testing frameworks (e.g. Mocha, QUnit, Jasmine) a global error handler is attached to `window.onerror`. When an uncaught exception is thrown, this global handler is invoked and the test suite will properly fail. Requiring that the provided test adapter provide an exception method is strictly worse in nearly all cases than allowing the error to be bubbled upwards and caught/handled by either `Ember.onerror` (if present) or `window.onerror` (generally from the test framework). This commit makes `Ember.Test.adapter.exception` optional. When not present, errors during testing will be handled by existing "normal" means. --- packages/ember-testing/lib/test/adapter.js | 2 +- packages/ember/tests/error_handler_test.js | 51 ++++++++++++++++++++++ 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/packages/ember-testing/lib/test/adapter.js b/packages/ember-testing/lib/test/adapter.js index 6bbe1df7a35..ca431790ea9 100644 --- a/packages/ember-testing/lib/test/adapter.js +++ b/packages/ember-testing/lib/test/adapter.js @@ -8,7 +8,7 @@ export function getAdapter() { export function setAdapter(value) { adapter = value; - if (value) { + if (value && typeof value.exception === 'function') { setDispatchOverride(adapterDispatch); } else { setDispatchOverride(null); diff --git a/packages/ember/tests/error_handler_test.js b/packages/ember/tests/error_handler_test.js index 0501a3a1c12..8a7898f1e88 100644 --- a/packages/ember/tests/error_handler_test.js +++ b/packages/ember/tests/error_handler_test.js @@ -397,6 +397,57 @@ function generateRSVPErrorHandlingTests(message, generatePromise, timeout = 10) }); if (DEBUG) { + test(`${message} when Ember.Test.adapter without \`exception\` method is present - rsvp`, function(assert) { + assert.expect(1); + + let thrown = new Error('the error'); + Ember.Test.adapter = Ember.Test.QUnitAdapter.create({ + exception: undefined + }); + + window.onerror = function(message) { + assert.pushResult({ + result: /the error/.test(message), + actual: message, + expected: 'to include `the error`', + message: 'error should bubble out to window.onerror, and therefore fail tests (due to QUnit implementing window.onerror)' + }); + + // prevent "bubbling" and therefore failing the test + return true; + }; + + generatePromise(thrown); + + // RSVP.Promise's are configured to settle within the run loop, this + // ensures that run loop has completed + return new Ember.RSVP.Promise((resolve) => setTimeout(resolve, timeout)); + }); + + test(`${message} when both Ember.onerror and Ember.Test.adapter without \`exception\` method are present - rsvp`, function(assert) { + assert.expect(1); + + let thrown = new Error('the error'); + Ember.Test.adapter = Ember.Test.QUnitAdapter.create({ + exception: undefined + }); + + Ember.onerror = function(error) { + assert.pushResult({ + result: /the error/.test(error.message), + actual: error.message, + expected: 'to include `the error`', + message: 'error should bubble out to window.onerror, and therefore fail tests (due to QUnit implementing window.onerror)' + }); + }; + + generatePromise(thrown); + + // RSVP.Promise's are configured to settle within the run loop, this + // ensures that run loop has completed + return new Ember.RSVP.Promise((resolve) => setTimeout(resolve, timeout)); + }); + test(`${message} when Ember.Test.adapter is present - rsvp`, function(assert) { assert.expect(1);