Open History to see the last commit
1import * as NodeEvents from "node:events";
2import * as NodeModule from "node:module";
3
4import { afterEach, describe, expect, it } from "vite-plus/test";
5
6// The agent forks via the shared CJS module at call time; replace it to stub the helper on every platform.
7const requireCjs = NodeModule.createRequire(import.meta.url);
8const childProcess: typeof import("node:child_process") = requireCjs("child_process");
9const {
10 WindowsPtyAgent,
11}: {
12 WindowsPtyAgent: {
13 prototype: { _getConsoleProcessList(this: { _innerPid: number }): Promise<number[]> };
14 };
15} = requireCjs("node-pty/lib/windowsPtyAgent.js");
16const originalFork = childProcess.fork;
17
18const SHELL_PID = 4242;
19
20function getConsoleProcessList(
21 driveHelper: (helper: NodeEvents.EventEmitter) => void,
22): Promise<number[]> {
23 const helper = Object.assign(new NodeEvents.EventEmitter(), { kill: () => true });
24 childProcess.fork = (() => {
25 queueMicrotask(() => driveHelper(helper));
26 return helper;
27 }) as unknown as typeof childProcess.fork;
28 return WindowsPtyAgent.prototype._getConsoleProcessList.call({ _innerPid: SHELL_PID });
29}
30
31describe("node-pty console process list helper", () => {
32 afterEach(() => {
33 childProcess.fork = originalFork;
34 });
35
36 it("returns the helper's list when it replies and then closes", async () => {
37 const list = await getConsoleProcessList((helper) => {
38 helper.emit("message", { consoleProcessList: [SHELL_PID, 5001, 5002] });
39 helper.emit("exit", 0, null);
40 helper.emit("close", 0, null);
41 });
42 expect(list).toEqual([SHELL_PID, 5001, 5002]);
43 });
44
45 it("keeps waiting for the reply when exit arrives before the IPC message", async () => {
46 const list = await getConsoleProcessList((helper) => {
47 helper.emit("exit", 0, null);
48 helper.emit("message", { consoleProcessList: [SHELL_PID, 5001] });
49 helper.emit("close", 0, null);
50 });
51 expect(list).toEqual([SHELL_PID, 5001]);
52 });
53
54 it("falls back to the shell PID when the helper closes without replying", async () => {
55 const list = await getConsoleProcessList((helper) => {
56 helper.emit("exit", 1, null);
57 helper.emit("close", 1, null);
58 });
59 expect(list).toEqual([SHELL_PID]);
60 });
61
62 // regression: #18519 Windows terminal kill waited on timeouts
63 it("falls back to the shell PID when the helper fails to spawn", async () => {
64 const list = await getConsoleProcessList((helper) => {
65 helper.emit("error", Object.assign(new Error("spawn ENOENT"), { code: "ENOENT" }));
66 });
67 expect(list).toEqual([SHELL_PID]);
68 });
69});