-
-
Notifications
You must be signed in to change notification settings - Fork 3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix for async hook error handling issue #1802
Fix for async hook error handling issue #1802
Conversation
This PR is in relation to this filed issue - #1769 |
Hm, not your fault, but the pattern used for integration tests in https://github.com/ajaykodali/mocha/blob/fix/1769-asynchronous-error-handling/test/integration/hook.err.js is resulting in some pretty verbose tests. It's hard to follow what's being tested. Perhaps some of this could get moved into fixtures? |
Are you recommending it for this PR or general observation? I ask cause I am not entirely familiar with the testing setup (and a lot of the rest of the code :)) but if it needs to be addressed in this PR I will give it a try. Some background on the intent of fixtures etc. would probably help. |
@danielstjules, seemed straight forward so I moved some of the code to 'fixtures' to make this hook.err.js file more readable. |
Awesome! Thank you :) Would you mind squashing? Also, is there maybe some unnecessary code in some of the fixtures? Could they be slimmed down a bit? For example, couldn't describe('spec 1', function () {
describe('spec 1 nested', function () {
it('should not be called, because hook error will happen in parent suite', function () {
console.log('test nested');
});
});
beforeEach(function () {
console.log('before');
});
afterEach(function (done) {
console.log('after');
process.nextTick(function () {
throw new Error('after each hook error');
});
});
it('should be called because error is in after each hook', function () {
console.log('test');
});
});
describe('spec 2', function () {
before(function () {
console.log('before 2');
});
after(function () {
console.log('after 2');
});
it('should be called, because hook error was in a sibling suite', function () {
console.log('test 2');
});
});
// =>
describe('spec 1', function () {
afterEach(function (done) {
console.log('afterEach');
process.nextTick(function () {
throw new Error('after each hook error');
});
});
it('should be called because error is in after each hook', function () {
console.log('test');
});
it('should not be called', function () {
console.log('test nested');
});
});
describe('spec 2', function () {
it('should be called, because hook error was in a sibling suite', function () {
console.log('test 2');
});
}); If you agree, but don't have time, I'd be happy to make those changes. Either way, really appreciate your help with this! |
Yeah, I agree. I can work on this later today, will squash and update. |
Done. I trimmed the fixture code for the hook errors and squashed the commits. Note: I did not touch the multiple.hook.error.js and multiple.hook.async.error.js files and that is intentional. This fixture code does some pretty thorough usage of the different hooks and errors thrown at the different layers which seems like a good idea. Let me know what you think. |
Agreed :)
Oh, sorry, could you try squashing again? I'm still seeing 4 commits. Also, thanks a lot for this PR. Looks solid! :) That test coverage will be extremely helpful in avoiding any future regressions. |
3ffa9dc
to
9bee81b
Compare
Ok, think I did the squashing right, second time around. |
Awesome, thanks again! @mochajs/mocha |
Not a problem :). This looks like an issue that more than a few people are waiting on. |
@danielstjules , any estimate on when this might be merged? |
@ajaykodali You've got a +1 from me! Just hoping to get a second from the team before hitting the merge button, since it is touching core runner logic. Sorry for the wait! |
Makes sense, thanks! |
self.emit('suite end', suite); | ||
self.nextSuite = next; | ||
|
||
if (afterAllHookCalledOnce) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some small nitpicks that I'll fix in the merge if you don't have time:
Renaming afterAllHookCalledOnce => afterAllCalled or afterAllHookCalled
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
…s bailing sibling suites too * Added unit test cases for async hook error handling * Fixed minor issue in existing sync hook error test case * Moving code to fixtures dir to make the hook.err.js tests more readable * Trimming the hook error test cases by removing hooks not under test * Fix indentation * Rename var to afterAllHookCalled
9bee81b
to
ebc6aee
Compare
Addressed the feedback changes |
Is there a better way to detect an |
As of right now, it doesn't look like it {
"title": "\"after each\" hook",
"async": 1,
"sync": false,
"timedOut": false,
"type": "hook",
"parent": "#<Suite>",
"ctx": "#<Context>",
"timer": {
"0": null
},
"state": "failed",
"err": {
"uncaught": true
}
} At least not from the |
Yeah, I agree. I couldn't figure out a better way to handle this within the current implementation. |
@mochajs/mocha @boneskull +1 from anyone else :) While the PR is large, the change to mocha is 36 loc. The rest are some awesome tests verifying its functionality. |
Any update on this? |
I'll try reviewing this tomorrow. |
For reference, here's an example of what this fixes. Note that the third spec isn't invoked prior to this PR. $ cat test/integration/fixtures/hooks/afterEach.hook.async.error.js
describe('spec 1', function () {
afterEach(function (done) {
console.log('after');
process.nextTick(function () {
throw new Error('after each hook error');
});
});
it('should be called because error is in after each hook', function () {
console.log('test 1');
});
it('should not be called', function () {
console.log('test 2');
});
});
describe('spec 2', function () {
it('should be called, because hook error was in a sibling suite', function () {
console.log('test 3');
});
});
// --------------------------
// BEFORE PR
// --------------------------
$ ./bin/mocha test/integration/fixtures/hooks/afterEach.hook.async.error.js
test 1
․after
․
1 passing (12ms)
1 failing
1) spec 1 "after each" hook:
Uncaught Error: after each hook error
at test/integration/fixtures/hooks/afterEach.hook.async.error.js:5:13
// --------------------------
// AFTER PR
// --------------------------
$ ./bin/mocha test/integration/fixtures/hooks/afterEach.hook.async.error.js
test 1
․after
․test 3
․
2 passing (13ms)
1 failing
1) spec 1 "after each" hook:
Uncaught Error: after each hook error
at test/integration/fixtures/hooks/afterEach.hook.async.error.js:5:13 |
@mochajs/mocha Unless anyone objects, I'm hoping to merge this weekend. |
I don't object. What I'm wondering is whether we plan on a minor or major at this point. |
cc @mochajs/mocha |
what warrants a major upgrade? |
Did you mean minor vs patch? I think master has enough functionality and changes to warrant a minor (as does the 2.3.0 branch) So maybe we could consolidate the changes in those two branches and release a new minor? If you did mean minor/major, then I didn't think it was worth a new major yet? I thought the big goal for that was the plugin system. |
yeah i look at the commit list after i wrote that. looks like minor to me |
dunno, I heard some rumblings about trying for v3.0.0. please let me look at the commit list as well |
No one objected, so merging in :) Thanks again @ajaykodali - Awesome work, really appreciate it! |
…handling Fix for async hook error handling issue
Awesome! Thanks for pulling this in. Is there a decision made on whether this will come out soon as a patch or in a major version bump? |
Not yet, will likely move that discussion to another issue :) |
ok, can you point me to that discussion so I can keep track as to when this might come out. |
I just now ran into this bug, so I'm excited to see it's already been fixed in |
Thanks for the reminder! :) |
Just stumbled across these changes, and wanted to mention that the choice to have the tests included in the file instead of in a fixture was a conscious one, discussed in #1781 (comment) Personally I find the fixture approach in this case to be rather opaque, as you have to flick between the fixture file and the test itself to see why the assertion expects Anyway, not a huge issue either way - but I wanted to explain why they seemed so weird before 😄 |
You may have to click back and forth, but I prefer the distinction. Skimming through the original tests, it was difficult to tell at a glance what was an actual integration test, and what was an "inlined fixture" to be ran in a spawned process. E.g. https://github.com/glenjamin/mocha/blob/092ea4684478aa99e32f3acaa0e5963ee5c0cb7d/test/integration/hook.err.js#L166-L332 But I do appreciate your work in adding those tests in the first place - they've been really helpful! :) |
Fair point - the fixtures did look exactly like the tests themselves! |
Detail:
Hook failures are handled in the same manner as outlines in this PR - #1043
This fix simply ensures that uncaught aysnc errors are being handled appropriately rather than bailing.
This fix should also resolve issue - #534