-
Notifications
You must be signed in to change notification settings - Fork 3
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
spawk.spawn.exit needs await #26
Comments
Yes jest appears to be buggy in how it deals with events. It only listens for I'm not familiar enough w/ jest to suggest a fix for them, but maybe the research in the other issue could help? As far as documentation yes I agree it could be better. I'm not sure that the results of exit or any other spawk method need to be awaited though. They all return |
The decision in spawk to fire the exit event BEFORE the stdout/stderr writes and the close event was 100% intentional in this module. Lines 287 to 303 in 7700f03
This is because the node documentation is very clear on the matter and I wanted spawk to be able to trigger bugs in code that wasn't properly following the spec: https://nodejs.org/api/child_process.html#event-close
At this point though I don't know if I can rely on jest to fix this, and may have to add a jest compatibility mode. |
If you can test this using the git source instead of the published version that'd be great. I added a jest compatibility flag and would like to know it works before publishing. |
so the test would be without the await right? |
Yes you don't need to await the results of |
I tried it in my machine and it kept giving me open handles. It did not work. Here is part of the package.json
Here is the test (with obscure values)
Here is the code (I had to change it from my original code, but it keeps the same essence)
|
Thank you, that code helped me. The problem with your code is likely that you're requiring Once I swapped the requires so spawk came first, your test worked. Coincidentally it worked with and without the new compatibility mode. When I changed the code to listen for Looking into the old issue more it had to do with how jest itself was spawning things. The person was testing the Your code should work, and works for me locally provided spawk is required first. I am going to update the README to be more specific about the use case that compatibility mode is fixing, and cut a release. However you don't need to wait on that release as far as I can tell. This code works for me, the only two things I have installed are const spawk = require('spawk')
const { spawn } = require('child_process')
it("should run with arg string", async () => {
spawk.preventUnmatched()
spawk
.spawn("mybin", ["myarg"])
.stdout("OK")
.exit(0);
const stdout = await spawnProcessAndWait("mybin", ["myarg"]);
expect(stdout).toBe("OK");
});
async function spawnProcessAndWait(procPath, procArgs) {
const promise = new Promise((resolve, reject) => {
const child = spawn(procPath, procArgs, {
timeout: 20 * 60 * 1000,
});
let stdOutStr = "";
child.stdout.on("data", (data) => {
stdOutStr += data.toString();
});
child.stderr.on("data", (data) => {
reject(new Error(data.toString()));
});
child.on("error", (error) => {
reject(new Error(error.message));
});
child.on("close", () => {
if (!process.env.JEST_WORKER_ID) {
console.debug(`child process finished`);
}
resolve(stdOutStr);
});
});
return promise;
} $ npx jest test.js
PASS ./test.js
✓ should run with arg string (7 ms)
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 0.191 s, estimated 1 s
Ran all test suites matching /test.js/i. |
After reading the jest code again it appears to use |
Actually my code did import spawk BEFORE child_process therefore the await is still needed (I know it doesnt make sense but it works). I dont know further details on jest to comment about the specifics of fork and spawn, but it does seem to me that shouldn't impact on your library right? unless jest is already hijacking spawn or fork. |
I was able to use your example and write a test that passed in jest. Without something I can use that shows broken behavior I can't fix it. The exit (code) {
this.#interceptor.exitCode = code
return this
} The only thing I can think of is that adding that await moves the result to the next event loop and you have a race condition somewhere. This is definitely not a spawk bug though, so I'm gonna close this. If you have some code that doesn't work with spawk that I can use to reproduce this please make an issue or reopen this one and I'll look into it. |
ok thats fair. |
Maybe this is just something to add to the documentation, but I was banging my head for several hours because of jest open handles when running spawk.
So my friend reviewed this further, and so he found that, instead of:
it had to be:
The text was updated successfully, but these errors were encountered: