Ensure unhandled rejections cause test failure.#1241
Ensure unhandled rejections cause test failure.#1241trentmwillis merged 8 commits intoqunitjs:masterfrom
Conversation
| @@ -0,0 +1,35 @@ | |||
| // Currently (2017-12-18) only Chrome has implemented `unhandledRejection` | |||
| const IS_CHROME = !!window.chrome; | |||
There was a problem hiding this comment.
'onrejectionhandled' in window might be easier to maintain as a feature test, or are there false positives for that? That way when other browsers land support, our CI will verify them automatically.
There was a problem hiding this comment.
Awesome, thank you for that. Hard coding to Chrome definitely felt bad, but it was late and I ran out of ideas. 😝
There was a problem hiding this comment.
Also just confirmed that Safari also supports the unhandled rejection events, thanks again for the pointer on the feature detect!
Brings unhandled rejections in line with unhandled exceptions.
6249803 to
bc23a65
Compare
|
I took some time to experiment with the implementation (by polyfilling in emberjs/ember-qunit#306), and it seems that just using I also updated the tests to ensure that we are testing both inside and outside of a single test context, and modified to use a more appropriate feature detection (instead of only testing on Chrome). The new tests pass properly on both Chrome and Safari (which are the only two browsers which have implemented |
6d92642 to
93007ce
Compare
* Properly feature detect the browsers ability to report unhandled rejections * Ensure unhandled rejections are tested for both inside and outside of a test
93007ce to
bc32c4b
Compare
Unfortunately, we cannot use real errors here because the stack trace representation changes across Node versions (and therefore the expectations fail).
bc32c4b to
6a6fae8
Compare
|
Note: I'm happy to squash the commits down when we are ready to go on this one. It is easier to push new commits (e.g. maintainers have an easier time of reviewing the subset of the diff that is new). |
platinumazure
left a comment
There was a problem hiding this comment.
Just left a small comment. I promise to give this a full review later 😄
| var originalPushResult = assert.pushResult; | ||
| assert.pushResult = function( resultInfo ) { | ||
|
|
||
| // Inverts the result so we can test failing assertions |
There was a problem hiding this comment.
Curious to know why this comment is de-indented from the line below.
There was a problem hiding this comment.
Just a mistake, though I'm surprised that the otherwise aggressive indentation linting rules didn't catch it...
There was a problem hiding this comment.
No worries. The indent rule is slightly lenient about comments because in general it is hard to tell what lines of code a comment might be associated with, so ESLint generally allows comments to align with the next line of code, the previous line of code, or with the "correct" indentation (i.e., the indentation we would expect a token to actually be at if this were a token instead of a comment).
My guess is the indent rule is allowing this location due to aligning with line 9. That seems weird since line 10 is whitespace-only, so I wonder if we could improve the rule to not use the previous-line heuristic if the previous token is actually 2 lines above the comment instead of 1 (and similarly, not use the next-line heuristic if the next token is actually 2 lines below the comment instead of 1).
There was a problem hiding this comment.
Totally makes sense! (also cleaned up the indentation)
|
For what it's worth, I've opened eslint/eslint#9733 about the comment indent issue. |
trentmwillis
left a comment
There was a problem hiding this comment.
Overall, looks good to me. Just two minor comments.
| import { sourceFromStacktrace } from "./stacktrace"; | ||
|
|
||
| // Handle an unhandled rejection | ||
| export default function onUnhandledRejection( reason ) { |
There was a problem hiding this comment.
Is reason just an Error instance?
There was a problem hiding this comment.
No, reason is whatever the rejection value is. An Error instance is almost certainly the most common thing that reason would be, but it could also be a failed XHR, a string, undefined, null, etc. The value here is either whatever the argument to reject() or the argument tothrow is.
See small demo JSBin with the following content:
window.addEventListener('unhandledrejection', function(event) {
console.log('reason:', event.reason);
})
Promise.reject();
Promise.reject(null);
Promise.reject("asdf");
Promise.resolve().then(() => {
throw new Error('boom');
})There was a problem hiding this comment.
Ah okay, makes sense. Early-morning me couldn't quite make that connection.
|
|
||
| const done = assert.async(); | ||
|
|
||
| new Promise( function( resolve ) { |
There was a problem hiding this comment.
Correct me if I'm wrong, but can't this just be Promise.resolve().then( ... )? If so, can you change it here and below as well.
There was a problem hiding this comment.
Yep, you are absolutely correct. I have been working too much with Ember's internal Ember.RSVP.Promise which is configured to resolve in an "odd" way, sorry about that!
Updated to be much more idiomatic...
97eb1c3 to
4b955d1
Compare
|
Looks good to me. @Krinkle any other feedback before I merge? |
|
Thanks @rwjblue! |
Prior to this change, an unhandled exception in a promise that was not returned from the
testcallback would not cause test failure.For example, the following (using default out of the box settings) results in test failures:
And this (prior to this PR) would result in a passing test suite:
The reason that what we are doing already isn't good enough is:
unhandledRejectionhandler does not dispatch towindow.onerrorat all... 😩