Keep subprocess regression tests independent of terminal colors (#6648)

* test(server): isolate subprocess regressions from terminal colors

Inherited NO_COLOR and FORCE_COLOR make Node emit an unrelated warning. It contaminates argv-fixture stderr and fails the closed-output supervisor fixture before its pipe handlers are installed. Clear both settings only in these fixture subprocesses, preserving their output and lifecycle assertions.

* test(server): exercise conflicting colors regardless of parent environment

Run the closed-output and spaced-executable regressions with explicit conflicting color inputs as well as the inherited environment, so removing fixture isolation fails on ordinary CI environments too.

---------

Co-authored-by: paseo-bot[bot] <266920839+paseo-bot[bot]@users.noreply.github.com>
This commit is contained in:
paseo-bot[bot]
2026-10-12 00:47:28 +02:00
committed by GitHub
parent b852ae920b
commit 166aabd57b
2 changed files with 48 additions and 24 deletions
@@ -29,6 +29,7 @@ async function runSupervisorFixture(options: {
blockLogPath?: boolean;
/** Close the reading end of the supervisor's stdout and stderr as soon as it starts. */
closeOutput?: boolean;
env?: NodeJS.ProcessEnv;
}): Promise<{
code: number | null;
signal: NodeJS.Signals | null;
@@ -84,7 +85,9 @@ async function runSupervisorFixture(options: {
];
const child = spawn(command, args, {
cwd: repoRoot,
env: { ...process.env },
// A Node color-conflict warning can hit closed stderr before runSupervisor installs
// its pipe-error handlers. This fixture exercises the supervisor's own output.
env: { ...process.env, ...options.env, NO_COLOR: undefined, FORCE_COLOR: undefined },
stdio: ["ignore", "pipe", "pipe"],
});
@@ -205,10 +208,16 @@ describe("supervisor durable logging", () => {
expect(result.stderr).toContain('"worker-json-stderr"');
});
test("keeps supervising the worker when nobody reads its stdout or stderr", async () => {
const result = await runSupervisorFixture({
closeOutput: true,
workerSource: `
test.each([
{ colors: "inherited", env: {} },
{ colors: "conflicting", env: { NO_COLOR: "1", FORCE_COLOR: "1" } },
])(
"keeps supervising the worker when nobody reads its stdout or stderr with $colors colors",
async ({ env }) => {
const result = await runSupervisorFixture({
closeOutput: true,
env,
workerSource: `
process.on("message", (message) => {
if (message?.type === "paseo:graceful-shutdown") process.exit(0);
});
@@ -220,14 +229,15 @@ describe("supervisor durable logging", () => {
}, 500);
setInterval(() => {}, 1000);
`,
});
});
expect(result.code).toBe(0);
expect(result.signal).toBeNull();
expect(result.log).toContain("first stderr line\n");
expect(result.log).toContain("later stdout line\n");
expect(result.log).toContain('"reason":"closed_output_probe"');
});
expect(result.code).toBe(0);
expect(result.signal).toBeNull();
expect(result.log).toContain("first stderr line\n");
expect(result.log).toContain("later stdout line\n");
expect(result.log).toContain('"reason":"closed_output_probe"');
},
);
test("preserves raw non-JSON stdout and stderr lines", async () => {
const result = await runSupervisorFixture({
@@ -126,10 +126,15 @@ async function runFixture(params: {
command: string;
args: string[];
shell?: boolean;
env?: NodeJS.ProcessEnv;
}): Promise<SpawnResult> {
const child = spawnProcess(params.command, params.args, {
env: {
...process.env,
...params.env,
// Terminal color settings must not add Node warnings to the argv fixture's stderr.
NO_COLOR: undefined,
FORCE_COLOR: undefined,
PASEO_EXPECTED_ARGV_JSON: JSON.stringify(["--config", JSON_ARG]),
},
stdio: ["ignore", "pipe", "pipe"],
@@ -216,6 +221,8 @@ async function findAndLaunch(fixture: LaunchFixture): Promise<{
const child = spawnProcess(found, fixture.args, {
env: {
...process.env,
NO_COLOR: undefined,
FORCE_COLOR: undefined,
PASEO_EXPECTED_ARGV_JSON: fixture.expectedArgvJson,
PASEO_ARGV_SLICE_FROM: String(fixture.sliceFrom),
},
@@ -331,18 +338,25 @@ describe.runIf(isPlatform("win32"))("Windows spawn launch regression", () => {
});
describe.skipIf(isPlatform("win32"))("spawn launch regression smoke", () => {
test("direct launch with a space-containing executable works on this platform", async () => {
const fixture = makeFixture();
test.each([
{ colors: "inherited", env: {} },
{ colors: "conflicting", env: { NO_COLOR: "1", FORCE_COLOR: "1" } },
])(
"direct launch with a space-containing executable works with $colors colors",
async ({ env }) => {
const fixture = makeFixture();
const result = await runFixture({
command: fixture.fakeDaemonNode,
args: [fixture.assertScript, ...fixture.expectedArgs],
shell: false,
});
const result = await runFixture({
command: fixture.fakeDaemonNode,
args: [fixture.assertScript, ...fixture.expectedArgs],
shell: false,
env,
});
expect(result.error).toBeNull();
expect(result.code).toBe(0);
expect(result.stderr).toBe("");
expect(result.stdout.trim()).toBe("ARGV_OK");
});
expect(result.error).toBeNull();
expect(result.code).toBe(0);
expect(result.stderr).toBe("");
expect(result.stdout.trim()).toBe("ARGV_OK");
},
);
});