diff --git a/addon-test-support/@ember/test-helpers/index.ts b/addon-test-support/@ember/test-helpers/index.ts index 75f8957e5..1332ed877 100644 --- a/addon-test-support/@ember/test-helpers/index.ts +++ b/addon-test-support/@ember/test-helpers/index.ts @@ -7,6 +7,7 @@ export { unsetContext, pauseTest, resumeTest, + setupOnerror, } from './setup-context'; export { default as teardownContext } from './teardown-context'; export { default as setupRenderingContext, render, clearRender } from './setup-rendering-context'; diff --git a/addon-test-support/@ember/test-helpers/setup-context.ts b/addon-test-support/@ember/test-helpers/setup-context.ts index a9e26b1c0..eb48ddbd7 100644 --- a/addon-test-support/@ember/test-helpers/setup-context.ts +++ b/addon-test-support/@ember/test-helpers/setup-context.ts @@ -132,6 +132,29 @@ export function resumeTest(): void { context.resumeTest(); } +const ORIGINAL_EMBER_ONERROR: (error: Error) => void | undefined = Ember.onerror; + +/** + Sets the Ember.onerror function for the duration of a single test. This + value is reset after each test to ensure correct test isolation. + + @public + @param {Function} onError the onError function to be set on Ember.onerror +*/ +export function setupOnerror(onError: (error: Error) => void): void { + let context = getContext(); + let contextGuid = guidFor(context); + let contextCleanup = CLEANUP[contextGuid]; + + if (!Array.isArray(contextCleanup)) { + throw new Error( + 'You must use `setupContext` / `setupRenderingContext` / `setupApplicationContext` in order to use `setupOnerror`' + ); + } + + Ember.onerror = onError; +} + export const CLEANUP = Object.create(null); /** @@ -261,6 +284,10 @@ export default function( }, 'TestAdapter paused promise'); }; + CLEANUP[contextGuid].push(() => { + Ember.onerror = ORIGINAL_EMBER_ONERROR; + }); + _setupAJAXHooks(); return context as TestContext; diff --git a/tests/unit/setup-ember-onerror-test.js b/tests/unit/setup-ember-onerror-test.js new file mode 100644 index 000000000..cc903c378 --- /dev/null +++ b/tests/unit/setup-ember-onerror-test.js @@ -0,0 +1,60 @@ +import Ember from 'ember'; +import { module, test } from 'qunit'; +import hasEmberVersion from '@ember/test-helpers/has-ember-version'; +import { setupContext, teardownContext, setupOnerror } from '@ember/test-helpers'; + +module('setupOnerror', function() { + if (!hasEmberVersion(2, 4)) { + test('Will throw if on < Ember 2.4', function(assert) { + assert.expect(1); + + assert.throws(function() { + setupOnerror(); + }, 'The `setupOnerror` function requires that you be on a minimum version of Ember 2.4.'); + }); + } + + if (hasEmberVersion(2, 4)) { + test('Ember.onerror is undefined by default', function(assert) { + assert.expect(1); + + assert.equal(Ember.onerror, undefined); + }); + + test('Ember.onerror is set correctly when using setupOnerror', async function(assert) { + assert.expect(2); + + let context = {}; + let onerror = err => err; + + assert.equal(Ember.onerror, undefined); + + await setupContext(context); + + setupOnerror(onerror); + + assert.equal(Ember.onerror, onerror); + + await teardownContext(context); + }); + + test('Ember.onerror is reset correctly when teardownContext is invoked', async function(assert) { + assert.expect(3); + + let context = {}; + let onerror = err => err; + + assert.equal(Ember.onerror, undefined); + + await setupContext(context); + + setupOnerror(onerror); + + assert.equal(Ember.onerror, onerror); + + await teardownContext(context); + + assert.equal(Ember.onerror, undefined); + }); + } +});