// @vitest-environment nodeimport { describe, expect, it } from "vitest";import { runSubprocess, SubprocessError } from "./subprocess"; describe("subprocess runtime", () => { it("captures bounded stdout and stderr", async () => { const result = await runSubprocess({ command: process.execPath, args: ["-e", "process.stdout.write('out'); process.stderr.write('err')"], maxBufferBytes: 1024, }); expect(result).toMatchObject({ stdout: "out", stderr: "err", exitCode: 0 }); }); it("fails when output exceeds the configured bound", async () => { await expect( runSubprocess({ command: process.execPath, args: ["-e", "process.stdout.write('x'.repeat(4096))"], maxBufferBytes: 32, }), ).rejects.toMatchObject({ code: "ERR_CHILD_PROCESS_STDIO_MAXBUFFER" }); }); it("accepts configured nonzero exit codes", async () => { const result = await runSubprocess({ command: process.execPath, args: ["-e", "process.stderr.write('expected'); process.exit(7)"], acceptedExitCodes: [0, 7], }); expect(result).toMatchObject({ stderr: "expected", exitCode: 7 }); }); it("terminates commands on timeout", async () => { await expect( runSubprocess({ command: process.execPath, args: ["-e", "setInterval(() => {}, 1000)"], timeoutMs: 20, }), ).rejects.toMatchObject({ timedOut: true, aborted: false }); }); it("honors external abort signals", async () => { const controller = new AbortController(); const pending = runSubprocess({ command: process.execPath, args: ["-e", "setInterval(() => {}, 1000)"], signal: controller.signal, }); controller.abort(); await expect(pending).rejects.toMatchObject({ aborted: true }); }); it("redacts secrets from command errors", async () => { const secret = "super-secret-token"; let error: unknown; try { await runSubprocess({ command: process.execPath, args: [ "-e", `process.stderr.write('${secret} https://user:password@example.com'); process.exit(2)`, ], redactValues: [secret], }); } catch (cause) { error = cause; } expect(error).toBeInstanceOf(SubprocessError); expect(JSON.stringify(error)).not.toContain(secret); expect(JSON.stringify(error)).not.toContain("password"); expect(error).toMatchObject({ stderr: expect.stringContaining("[REDACTED]"), }); });});
// @vitest-environment node
import { describe, expect, it } from "vitest";
import { runSubprocess, SubprocessError } from "./subprocess";
describe("subprocess runtime", () => {
it("captures bounded stdout and stderr", async () => {
const result = await runSubprocess({
command: process.execPath,
args: ["-e", "process.stdout.write('out'); process.stderr.write('err')"],
maxBufferBytes: 1024,
});
expect(result).toMatchObject({ stdout: "out", stderr: "err", exitCode: 0 });
});
it("fails when output exceeds the configured bound", async () => {
await expect(
runSubprocess({
command: process.execPath,
args: ["-e", "process.stdout.write('x'.repeat(4096))"],
maxBufferBytes: 32,
}),
).rejects.toMatchObject({ code: "ERR_CHILD_PROCESS_STDIO_MAXBUFFER" });
});
it("accepts configured nonzero exit codes", async () => {
const result = await runSubprocess({
command: process.execPath,
args: ["-e", "process.stderr.write('expected'); process.exit(7)"],
acceptedExitCodes: [0, 7],
});
expect(result).toMatchObject({ stderr: "expected", exitCode: 7 });
});
it("terminates commands on timeout", async () => {
await expect(
runSubprocess({
command: process.execPath,
args: ["-e", "setInterval(() => {}, 1000)"],
timeoutMs: 20,
}),
).rejects.toMatchObject({ timedOut: true, aborted: false });
});
it("honors external abort signals", async () => {
const controller = new AbortController();
const pending = runSubprocess({
command: process.execPath,
args: ["-e", "setInterval(() => {}, 1000)"],
signal: controller.signal,
});
controller.abort();
await expect(pending).rejects.toMatchObject({ aborted: true });
});
it("redacts secrets from command errors", async () => {
const secret = "super-secret-token";
let error: unknown;
try {
await runSubprocess({
command: process.execPath,
args: [
"-e",
`process.stderr.write('${secret} https://user:password@example.com'); process.exit(2)`,
],
redactValues: [secret],
});
} catch (cause) {
error = cause;
}
expect(error).toBeInstanceOf(SubprocessError);
expect(JSON.stringify(error)).not.toContain(secret);
expect(JSON.stringify(error)).not.toContain("password");
expect(error).toMatchObject({
stderr: expect.stringContaining("[REDACTED]"),
});
});
});