Files
vue-tui/packages/runtime-tests/integration/pty/helpers/term.ts
T
Yunfei He dd4c5aa3e1 fix: replace node-pty with child_process.spawn + force-tty preload
node-pty's posix_spawnp is blocked in sandboxed environments.
child_process.spawn works everywhere. force-tty.cjs patches
stdout.isTTY so fixtures behave as if running in a real terminal.

Also fix setRawMode this-binding bug (acquireRawMode on undefined).

72/82 PTY tests now pass. Remaining 10 need timing/assertion fixes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-26 23:55:52 +08:00

75 lines
1.8 KiB
TypeScript

import process from "node:process";
import { spawn } from "node:child_process";
import path from "node:path";
import url from "node:url";
const fixturesDir = url.fileURLToPath(new URL("../fixtures", import.meta.url));
const term = (fixture: string, args: string[] = []) => {
let resolve: (value?: unknown) => void;
let reject: (error?: Error) => void;
const exitPromise = new Promise((res, rej) => {
resolve = res;
reject = rej;
});
let readyResolve: () => void;
const readyPromise = new Promise<void>((r) => {
readyResolve = r;
});
const env: Record<string, string> = {
...(process.env as Record<string, string>),
NODE_NO_WARNINGS: "1",
CI: "false",
FORCE_COLOR: "3",
};
const forceTty = url.fileURLToPath(new URL("./force-tty.cjs", import.meta.url));
const child = spawn(
"node",
["--require", forceTty, "--import=tsx", path.join(fixturesDir, `${fixture}.tsx`), ...args],
{ cwd: fixturesDir, env, stdio: ["pipe", "pipe", "pipe"] },
);
const result = {
write(input: string) {
void readyPromise.then(() => {
child.stdin!.write(input);
});
},
output: "",
waitForExit: async () => exitPromise,
};
child.stdout!.on("data", (data: Buffer) => {
result.output += data.toString();
if (result.output.includes("__READY__")) {
readyResolve();
}
});
child.stderr!.on("data", (data: Buffer) => {
const text = data.toString();
if (!text.includes("[Vue warn]: Non-function value encountered for default slot")) {
result.output += text;
}
});
child.on("exit", (exitCode) => {
if (exitCode === 0) {
resolve();
return;
}
reject(new Error(`Process exited with non-zero exit code: ${exitCode}`));
});
child.on("error", (err) => {
reject(err);
});
return result;
};
export default term;