-
-
Notifications
You must be signed in to change notification settings - Fork 153
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Ensure unhandled rejections cause test failure
Prior to this change, an unhandled exception in a native promise that was not returned from the `test` callback would not cause test failure. For example, prior to this change both of the following (using default out of the box settings) results in test failures: ```js test('native promises cause an unhandled rejection', function(assert) { // imagine this was "deep" inside various method calls setTimeout(function() { throw new Error('whoops!'); }); // other things that we are trying to test assert.deepEqual(someMethod(), ['one', 'two']); }); test('RSVP promises cause an unhandled rejection', function(assert) { // imagine this was "deep" inside various method calls Ember.RSVP.Promise.resolve().then(function() { throw new Error('whoops!'); }); // other things that we are trying to test assert.deepEqual(someMethod(), ['one', 'two']); }); ``` But this test (prior to this PR) would result in a passing test suite: ```js test('native promises cause an unhandled rejection', function(assert) { // imagine this was "deep" inside various method calls Promise.resolve().then(function() { throw new Error('whoops!'); }); // other things that we are trying to test assert.deepEqual(someMethod(), ['one', 'two']); }); ``` This is a polyfill of the general behavior being worked on upstream in QUnit itself, and can be removed once the feature is landed.
- Loading branch information
Showing
3 changed files
with
154 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
import { __unhandledRejectionHandler__ } from 'ember-qunit'; | ||
import { Promise as RSVPPromise } from 'rsvp'; | ||
import { module, test } from 'qunit'; | ||
|
||
const HAS_NATIVE_PROMISE = typeof Promise !== 'undefined'; | ||
const HAS_UNHANDLED_REJECTION_HANDLER = 'onunhandledrejection' in window; | ||
|
||
module('unhandle promise rejections', function(hooks) { | ||
hooks.beforeEach(function(assert) { | ||
let originalPushResult = assert.pushResult; | ||
assert.pushResult = function(resultInfo) { | ||
// Inverts the result so we can test failing assertions | ||
resultInfo.result = !resultInfo.result; | ||
resultInfo.message = `Failed: ${resultInfo.message}`; | ||
originalPushResult(resultInfo); | ||
}; | ||
}); | ||
|
||
test('RSVP promises cause an unhandled rejection', function(assert) { | ||
let done = assert.async(); | ||
|
||
// ensure we do not exit this test until the assertion has happened | ||
setTimeout(done, 10); | ||
|
||
new RSVPPromise(resolve => { | ||
setTimeout(resolve); | ||
}).then(function() { | ||
throw new Error('whoops!'); | ||
}); | ||
}); | ||
|
||
if (HAS_NATIVE_PROMISE && HAS_UNHANDLED_REJECTION_HANDLER) { | ||
test('native promises cause an unhandled rejection', function(assert) { | ||
let done = assert.async(); | ||
|
||
// ensure we do not exit this test until the assertion has happened | ||
setTimeout(done, 10); | ||
|
||
new self.Promise(resolve => { | ||
setTimeout(resolve); | ||
}).then(function() { | ||
throw new Error('whoops!'); | ||
}); | ||
}); | ||
} | ||
}); | ||
|
||
if (HAS_NATIVE_PROMISE && HAS_UNHANDLED_REJECTION_HANDLER) { | ||
module('unhandled native promise rejection outside of test context', function(hooks) { | ||
var originalPushResult; | ||
|
||
hooks.beforeEach(function(assert) { | ||
// Duck-punch pushResult so we can check test name and assert args. | ||
originalPushResult = assert.pushResult; | ||
|
||
assert.pushResult = function(resultInfo) { | ||
// Restore pushResult for this assert object, to allow following assertions. | ||
this.pushResult = originalPushResult; | ||
|
||
this.strictEqual(this.test.testName, 'global failure', 'Test is appropriately named'); | ||
|
||
this.deepEqual( | ||
resultInfo, | ||
{ | ||
message: 'Error message', | ||
source: 'filePath.js:1', | ||
result: false, | ||
actual: { | ||
message: 'Error message', | ||
fileName: 'filePath.js', | ||
lineNumber: 1, | ||
stack: 'filePath.js:1', | ||
}, | ||
}, | ||
'Expected assert.pushResult to be called with correct args' | ||
); | ||
}; | ||
}); | ||
|
||
hooks.afterEach(function() { | ||
QUnit.config.current.pushResult = originalPushResult; | ||
}); | ||
|
||
// Actual test (outside QUnit.test context) | ||
__unhandledRejectionHandler__({ | ||
reason: { | ||
message: 'Error message', | ||
fileName: 'filePath.js', | ||
lineNumber: 1, | ||
stack: 'filePath.js:1', | ||
}, | ||
}); | ||
}); | ||
} |