You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The --detectOpenHandles option fails to detect/warn about handles that were opened in test functions with a done callback. (It seems to work fine for promise-returning or async test functions.) I noticed this while looking into issues with Supertest in #8554 (comment)
To Reproduce
Given the following test file:
consthttp=require("http");describe("detectOpenHandles",()=>{it("should detect an open server when using a `done` function",(done)=>{constserver=http.createServer((_request,response)=>response.end("ok"));server.listen(0,()=>done());});});
Running Jest with --detectOpenHandles hangs, but does not print any information about the open TCPSERVERWRAP handle:
$ jest --detectOpenHandles open-handles.test.js
PASS ./open-handles.test.js
detectOpenHandles
✓ should detect an open server when using a `done`function(7 ms)
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 1.297 s
Ran all test suites matching /open-handles.test.js/i
Expected Behavior
In contrast, using an async function or returning a promise works as expected. Given the following test file:
consthttp=require("http");describe("detectOpenHandles",()=>{it("should detect an open server when using a promise",()=>{constserver=http.createServer((_request,response)=>response.end("ok"));returnnewPromise(resolve=>server.listen(0,resolve));});});
Running it successfully detects and prints information about the open server:
$ jest --detectOpenHandles open-handles.test.js
PASS ./open-handles.test.js
detectOpenHandles
✓ should detect an open server when using a promise (6 ms)
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 1.956 s
Ran all test suites matching /open-handles.test.js/i.
Jest has detected the following 1 open handle potentially keeping Jest from exiting:
● TCPSERVERWRAP
89 | it("should detect an open server when using a promise", () => {
90 | const server = http.createServer((_request, response) => response.end("ok"));> 91 |return new Promise(resolve => server.listen(0, resolve));| ^
92 | });
93 | });
at open-handles.test.js:91:42
at Object.<anonymous> (open-handles.test.js:91:12)
It looks like lifecycle functions will experience the same issue (although I haven’t tested), given the similar code in promisifyLifeCycleFunction().
The simplest fix here might be to simply wrap functions that take a done callback with a function, too (e.g. asyncJestTestWithCallback) and add that to the list of things to watch for in stackIsFromUser().
Wrap test and lifecycle functions that take a `done` callback in a named function so that they can be detected as user code in the call stack. This lets the `collectHandles` module in jest-core know to track async resources created in those functions.
Fixesjestjs#11377.
This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.
Please note this issue tracker is not a help forum. We recommend using StackOverflow or our discord channel for questions.
🐛 Bug Report
The
--detectOpenHandles
option fails to detect/warn about handles that were opened in test functions with adone
callback. (It seems to work fine for promise-returning orasync
test functions.) I noticed this while looking into issues with Supertest in #8554 (comment)To Reproduce
Given the following test file:
Running Jest with
--detectOpenHandles
hangs, but does not print any information about the openTCPSERVERWRAP
handle:Expected Behavior
In contrast, using an async function or returning a promise works as expected. Given the following test file:
Running it successfully detects and prints information about the open server:
Cause
It looks like the issue is in how Jest decides which handles to track. In
jest-core/src/collectHandles.ts
, handles are only tracked ifstackIsFromUser()
returnstrue
. It checks for the names of wrappers that run the test functions: https://github.com/facebook/jest/blob/ba84480a5603aeeb94184ffc26f9b39024cdcd6c/packages/jest-core/src/collectHandles.ts#L18-L38That works great for functions that don’t take a
done
callback. They get wrapped with a function namedasyncJestTest
, whichstackIsFromUser()
looks for: https://github.com/facebook/jest/blob/ba84480a5603aeeb94184ffc26f9b39024cdcd6c/packages/jest-jasmine2/src/jasmineAsyncInstall.ts#L123-L153But functions that take a
done
callback don’t get wrapped at all, and are anonymous or have no name thatstackIsFromUser()
knows to look for: https://github.com/facebook/jest/blob/ba84480a5603aeeb94184ffc26f9b39024cdcd6c/packages/jest-jasmine2/src/jasmineAsyncInstall.ts#L111-L113It looks like lifecycle functions will experience the same issue (although I haven’t tested), given the similar code in
promisifyLifeCycleFunction()
.The simplest fix here might be to simply wrap functions that take a
done
callback with a function, too (e.g.asyncJestTestWithCallback
) and add that to the list of things to watch for instackIsFromUser()
.envinfo
The text was updated successfully, but these errors were encountered: