Skip to content

Commit

Permalink
[BUGFIX beta] Update Backburner.js to 2.5.0.
Browse files Browse the repository at this point in the history
The primary change in Backburner.js is to use the Promise microtask
queue primarily and falling back to MutationObserver when Promise is not
present.

The test changes here are to migrate from `window.onerror` to
`window.onunhandledrejection` hooks (due to moving the microtask
delivery from `MutationObserver` to native `Promise`). The cross
platform support for `onunhandledrejection` is a tad spotty (Chrome,
Edge, and _soon_ Firefox), so I had to guard in other browsers.
  • Loading branch information
rwjblue committed Feb 20, 2019
1 parent 3e8a133 commit 5596d27
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 56 deletions.
2 changes: 1 addition & 1 deletion package.json
Expand Up @@ -108,7 +108,7 @@
"babel-plugin-filter-imports": "^2.0.4",
"babel-plugin-module-resolver": "^3.2.0",
"babel-template": "^6.26.0",
"backburner.js": "^2.4.2",
"backburner.js": "^2.5.0",
"broccoli-babel-transpiler": "^7.1.2",
"broccoli-concat": "^3.7.3",
"broccoli-debug": "^0.6.4",
Expand Down
29 changes: 20 additions & 9 deletions packages/ember-testing/tests/adapters_test.js
Expand Up @@ -8,10 +8,12 @@ import { moduleFor, AbstractTestCase } from 'internal-test-helpers';
import { RSVP } from '@ember/-internals/runtime';
import { getDebugFunction, setDebugFunction } from '@ember/debug';

const HAS_UNHANDLED_REJECTION_HANDLER = 'onunhandledrejection' in window;

const originalDebug = getDebugFunction('debug');
const noop = function() {};

var App, originalAdapter, originalQUnit, originalWindowOnerror;
var App, originalAdapter, originalQUnit, originalWindowOnerror, originalQUnitUnhandledRejection;

var originalConsoleError = console.error; // eslint-disable-line no-console

Expand All @@ -32,15 +34,14 @@ class AdapterSetupAndTearDown extends AbstractTestCase {
setDebugFunction('debug', noop);
super();
originalAdapter = Test.adapter;
originalQUnit = window.QUnit;
originalQUnit = QUnit;
originalWindowOnerror = window.onerror;
originalQUnitUnhandledRejection = QUnit.onUnhandledRejection;
}

afterEach() {
console.error = originalConsoleError; // eslint-disable-line no-console
}
super.afterEach();

teardown() {
setDebugFunction('debug', originalDebug);
if (App) {
run(App, App.destroy);
Expand All @@ -52,6 +53,8 @@ class AdapterSetupAndTearDown extends AbstractTestCase {
window.QUnit = originalQUnit;
window.onerror = originalWindowOnerror;
setOnerror(undefined);
console.error = originalConsoleError; // eslint-disable-line no-console
QUnit.onUnhandledRejection = originalQUnitUnhandledRejection;
}
}

Expand Down Expand Up @@ -240,20 +243,28 @@ moduleFor(
function testAdapter(message, generatePromise, timeout = 10) {
return class PromiseFailureTests extends AdapterSetupAndTearDown {
[`@test ${message} when TestAdapter without \`exception\` method is present - rsvp`](assert) {
if (!HAS_UNHANDLED_REJECTION_HANDLER) {
assert.expect(0);
return;
}

assert.expect(1);

let thrown = new Error('the error');
Test.adapter = QUnitAdapter.create({
exception: undefined,
});

window.onerror = function(message) {
// prevent QUnit handler from failing test
QUnit.onUnhandledRejection = () => {};

window.onunhandledrejection = function(rejection) {
assert.pushResult({
result: /the error/.test(message),
actual: message,
result: /the error/.test(rejection.reason),
actual: rejection.reason,
expected: 'to include `the error`',
message:
'error should bubble out to window.onerror, and therefore fail tests (due to QUnit implementing window.onerror)',
'error should bubble out to window.onunhandledrejection, and therefore fail tests (due to QUnit implementing window.onunhandledrejection)',
});

// prevent "bubbling" and therefore failing the test
Expand Down
116 changes: 74 additions & 42 deletions packages/ember/tests/error_handler_test.js
Expand Up @@ -4,6 +4,8 @@ import { getOnerror, setOnerror } from '@ember/-internals/error-handling';
import RSVP from 'rsvp';
import { moduleFor, AbstractTestCase } from 'internal-test-helpers';

const HAS_UNHANDLED_REJECTION_HANDLER = 'onunhandledrejection' in window;
let QUNIT_ON_UNHANDLED_REJECTION = QUnit.onUnhandledRejection;
let WINDOW_ONERROR;

function runThatThrowsSync(message = 'Error for testing error handling') {
Expand All @@ -26,6 +28,7 @@ moduleFor(
window.onerror = WINDOW_ONERROR;

setOnerror(undefined);
QUnit.onUnhandledRejection = QUNIT_ON_UNHANDLED_REJECTION;
}

['@test by default there is no onerror - sync run'](assert) {
Expand Down Expand Up @@ -238,6 +241,11 @@ moduleFor(
[`@test errors in promise constructor when Ember.onerror which does rethrow is present - rsvp`](
assert
) {
if (!HAS_UNHANDLED_REJECTION_HANDLER) {
assert.expect(0);
return;
}

assert.expect(2);

let thrown = new Error('the error');
Expand All @@ -250,17 +258,17 @@ moduleFor(
throw error;
});

window.onerror = function(message) {
// prevent QUnit handler from failing test
QUnit.onUnhandledRejection = () => {};

window.onunhandledrejection = function(event) {
assert.pushResult({
result: /the error/.test(message),
actual: message,
result: /the error/.test(event.reason),
actual: event.reason,
expected: 'to include `the error`',
message:
'error should bubble out to window.onerror, and therefore fail tests (due to QUnit implementing window.onerror)',
'error should bubble out to window.onunhandledrejection, and therefore fail tests (due to QUnit implementing window.onunhandledrejection)',
});

// prevent "bubbling" and therefore failing the test
return true;
};

new RSVP.Promise(() => {
Expand Down Expand Up @@ -299,6 +307,11 @@ moduleFor(
[`@test errors in promise constructor when Ember.onerror which does rethrow is present (Ember.testing = false) - rsvp`](
assert
) {
if (!HAS_UNHANDLED_REJECTION_HANDLER) {
assert.expect(0);
return;
}

assert.expect(2);

setTesting(false);
Expand All @@ -312,17 +325,17 @@ moduleFor(
throw error;
});

window.onerror = function(message) {
// prevent QUnit handler from failing test
QUnit.onUnhandledRejection = () => {};

window.onunhandledrejection = function(event) {
assert.pushResult({
result: /the error/.test(message),
actual: message,
result: /the error/.test(event.reason),
actual: event.reason,
expected: 'to include `the error`',
message:
'error should bubble out to window.onerror, and therefore fail tests (due to QUnit implementing window.onerror)',
'error should bubble out to window.onunhandledrejection, and therefore fail tests (due to QUnit implementing window.onunhandledrejection)',
});

// prevent "bubbling" and therefore failing the test
return true;
};

new RSVP.Promise(() => {
Expand Down Expand Up @@ -360,6 +373,11 @@ moduleFor(
[`@test errors in promise .then callback when Ember.onerror which does rethrow is present - rsvp`](
assert
) {
if (!HAS_UNHANDLED_REJECTION_HANDLER) {
assert.expect(0);
return;
}

assert.expect(2);

let thrown = new Error('the error');
Expand All @@ -372,17 +390,17 @@ moduleFor(
throw error;
});

window.onerror = function(message) {
// prevent QUnit handler from failing test
QUnit.onUnhandledRejection = () => {};

window.onunhandledrejection = function(event) {
assert.pushResult({
result: /the error/.test(message),
actual: message,
result: /the error/.test(event.reason),
actual: event.reason,
expected: 'to include `the error`',
message:
'error should bubble out to window.onerror, and therefore fail tests (due to QUnit implementing window.onerror)',
'error should bubble out to window.onunhandledrejection, and therefore fail tests (due to QUnit implementing window.onunhandledrejection)',
});

// prevent "bubbling" and therefore failing the test
return true;
};

RSVP.resolve().then(() => {
Expand Down Expand Up @@ -421,6 +439,11 @@ moduleFor(
[`@test errors in promise .then callback when Ember.onerror which does rethrow is present (Ember.testing = false) - rsvp`](
assert
) {
if (!HAS_UNHANDLED_REJECTION_HANDLER) {
assert.expect(0);
return;
}

assert.expect(2);

setTesting(false);
Expand All @@ -434,17 +457,17 @@ moduleFor(
throw error;
});

window.onerror = function(message) {
// prevent QUnit handler from failing test
QUnit.onUnhandledRejection = () => {};

window.onunhandledrejection = function(event) {
assert.pushResult({
result: /the error/.test(message),
actual: message,
result: /the error/.test(event.reason),
actual: event.reason,
expected: 'to include `the error`',
message:
'error should bubble out to window.onerror, and therefore fail tests (due to QUnit implementing window.onerror)',
'error should bubble out to window.onunhandledrejection, and therefore fail tests (due to QUnit implementing window.onunhandledrejection)',
});

// prevent "bubbling" and therefore failing the test
return true;
};

RSVP.resolve().then(() => {
Expand Down Expand Up @@ -482,6 +505,11 @@ moduleFor(
[`@test errors in async promise .then callback when Ember.onerror which does rethrow is present - rsvp`](
assert
) {
if (!HAS_UNHANDLED_REJECTION_HANDLER) {
assert.expect(0);
return;
}

assert.expect(2);

let thrown = new Error('the error');
Expand All @@ -494,17 +522,17 @@ moduleFor(
throw error;
});

window.onerror = function(message) {
// prevent QUnit handler from failing test
QUnit.onUnhandledRejection = () => {};

window.onunhandledrejection = function(event) {
assert.pushResult({
result: /the error/.test(message),
actual: message,
result: /the error/.test(event.reason),
actual: event.reason,
expected: 'to include `the error`',
message:
'error should bubble out to window.onerror, and therefore fail tests (due to QUnit implementing window.onerror)',
'error should bubble out to window.onunhandledrejection, and therefore fail tests (due to QUnit implementing window.onunhandledrejection)',
});

// prevent "bubbling" and therefore failing the test
return true;
};

new RSVP.Promise(resolve => setTimeout(resolve, 10)).then(() => {
Expand Down Expand Up @@ -543,6 +571,10 @@ moduleFor(
[`@test errors in async promise .then callback when Ember.onerror which does rethrow is present (Ember.testing = false) - rsvp`](
assert
) {
if (!HAS_UNHANDLED_REJECTION_HANDLER) {
assert.expect(0);
return;
}
assert.expect(2);

setTesting(false);
Expand All @@ -556,17 +588,17 @@ moduleFor(
throw error;
});

window.onerror = function(message) {
// prevent QUnit handler from failing test
QUnit.onUnhandledRejection = () => {};

window.onunhandledrejection = function(event) {
assert.pushResult({
result: /the error/.test(message),
actual: message,
result: /the error/.test(event.reason),
actual: event.reason,
expected: 'to include `the error`',
message:
'error should bubble out to window.onerror, and therefore fail tests (due to QUnit implementing window.onerror)',
'error should bubble out to window.onunhandledrejection, and therefore fail tests (due to QUnit implementing window.onunhandledrejection)',
});

// prevent "bubbling" and therefore failing the test
return true;
};

new RSVP.Promise(resolve => setTimeout(resolve, 10)).then(() => {
Expand Down
8 changes: 4 additions & 4 deletions yarn.lock
Expand Up @@ -1339,10 +1339,10 @@ backbone@^1.1.2:
dependencies:
underscore ">=1.8.3"

backburner.js@^2.4.2:
version "2.4.2"
resolved "https://registry.yarnpkg.com/backburner.js/-/backburner.js-2.4.2.tgz#4cc2d3e78592ddd46ae9a48cfc168ca883b56e6b"
integrity sha512-YFgfwWvelbJ9JxsVF+sph7nLB2qQfwDyUXCr+ZPyeU6HOXGAT0Rt+ro+mU1zRMnUfYG57nwaTiz1yqvqNO6jQQ==
backburner.js@^2.5.0:
version "2.5.0"
resolved "https://registry.yarnpkg.com/backburner.js/-/backburner.js-2.5.0.tgz#d03ab8f7b77e708ac4bc7bea2258aa57177b560d"
integrity sha512-YkLvnh0jEA67NNJ+NqJrX4Yb/isanR7XHlb+Y+cMXkGtXzlgx2tHEnZPIWi2kbW9EwtCq3HTRcAF+mbzIhfoqg==

backo2@1.0.2:
version "1.0.2"
Expand Down

0 comments on commit 5596d27

Please sign in to comment.