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
feat: Add lifecycle function to clear pending timeouts #1748
Conversation
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.
Couple of suggestions.
lib/common.js
Outdated
@@ -593,6 +593,22 @@ function deepEqual(expected, actual) { | |||
return expected === actual | |||
} | |||
|
|||
const timeouts = [] | |||
|
|||
function addTimeout(id) { |
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.
I think it would clean up the calling code if, instead of taking a timeout ID, we had a setTimeout
function that wrapped the native call and saved the id. eg:
function setTimeout(callback, delay, ...args) {
const id = timers.setTimeout(callback, delay, ...args)
timeouts.push(id)
return id
}
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.
if that is the approach you would like to take, i would also like to make the suggestion of adding our own timers module so we are able to follow the same pattern for all timers and not just setTimeout, but also setInterval(maybe used in the future) and setImmediate. As This will provide the opportunity to cover similar uses cases moving forward with less code changes. Dont think doing the same for nextTick is needed as there is no clear method.
tests/test_common.js
Outdated
}, 1) | ||
|
||
common.addTimeout(setTimeout(timeoutSpy, 0)) | ||
common.removeAllTimeouts() |
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.
Nock's strategy is to test as much as possible either through the public API or, when that is not possible, through the mock surface. Would it be possible to do that, maybe modeling the test after one of the tests in test_delay
and adding it to test_nock_lifecycle
?
(This has been discussed in a bunch of PRs but isn't really documented anywhere else; will open a PR to add it.)
lib/intercept.js
Outdated
@@ -124,6 +124,7 @@ function remove(interceptor) { | |||
} | |||
|
|||
function removeAll() { | |||
common.removeAllTimeouts() |
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.
I'm all for adding this functionality. 👍Thank you for picking this up! 💯
Though I'm not sure I think it belongs in the call to clearAll()
. That function's job is to remove interceptors from the list. In contrast, what's happening here is that we're cancelling playback of an interceptor that has already matched and is in process.
I'd suggest exporting this as a new function, maybe calling it nock.abortRequests()
or nock.abortPendingRequests()
. The test name in common
seems fine, "timeouts" being the implementation.
In RFC-001 I advocated creating a new lifecycle method to reset nock to its initial state.
I am not sure whether aborting current requests should be added to that reset. There is a bit of discussion in #1118 about Mocha leaving the process running until the pending request flushes, though I think I could use a bit more clarification about the use case and why aborting the requests is what's desirable. (It's not the behavior of real HTTP to abort pending requests when tests finish.) The reason Mocha doesn't quit the process anymore is to not paper over sloppy cleanup. I'm happy to let people force automatic cleanup if they want it, though others may prefer to clean things up on their own. Mocha's choice isn't everyone's cup of tea but it's arguably a good default.
That reset function doesn't exist yet; as of now you need to run nock.restore(); nock.cleanAll(); nock.enableNetConnect(); nock.activate()
and when we add nock.reset()
I'd suggest we stick with those four calls to start. And that developers call nock.abortPendingRequests()
followed by nock.reset()
if they're experiencing this problem. We can gather feedback on the use cases over time before deciding to include that reset function by default.
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.
This commit was created to close the original bug which complained about cleanAll not removing pending request. However, I agree with you that cleanAll should stay as is and a new method should be exposed I am partial to"abortPendingRequests". I dont see a current issue raised for nock.reset() be happy to work on that too. Sounds like it could be nocked out quickly.
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.
Cant clarify why this behavior is desirable, I personally am confused why someone needs it as well. I was just looking to contribute to your project because i was able to take the mocking approach and apply to one of my own projects. My way of saying thank you!
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.
Hey @TLPcoder I am really happy to have your help on the library. Nock is several years old – definitely a legacy project – and we've done a good job of getting it in shape to work on. @mastermatt has also done a lot of great work to clarify the ambiguous parts of the API. At the same time it still has a huge API surface, mostly because of the inclusionist way it was maintained, which was to merge many PRs that handled everyone's various niche use cases. A goal is to pare that back where possible, and I do want to be careful and thoughtful about expanding the API surface. Re the new lifecycle API, what I'd suggest is that we start by reviving #1441. Basically that PR got really big, and should be broken out into four separate RFCs. (The analysis of lifecycle methods RFC-001 came from the preamble that preceded the four proposals, via #1474.) The comments on the proposals also need to be incorporated.
In part the goal of the RFCs is to generate comments; and in part it's to have a thoughtful analysis and discussion that folks can read to understand the rationale as they migrate to the new APIs.
Would love to have your help on this!
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.
I think guys did a good job refactoring the code base and moving everything over to ES6.
Be happy to help where I can.
…mer ids to later delete when abortPendingRequests is called. Updated clear timer from recursion to a while up. Update from only timeout to covering all three timers, updated docs with new lifecycle method abortPendingRequests, updated types with new lifecycle method
Any objections to adding |
No objections, sounds good to me |
screen froze and i think i ended up trying to merge a branch my apologizes |
Hey @mastermatt are you satisfied with the code changes? |
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.
Even updated the type defs ❤️
🎉 This PR is included in version 11.6.0 🎉 The release is available on: Your semantic-release bot 📦🚀 |
Fixes: #1118