import { spawn } from "node:child_process"; import os from "node:os"; import path from "node:path"; import { afterEach, describe, expect, it } from "vitest"; import type { CatalogComponent, FlowNode } from "../../src/types"; import type { RunContext } from "../../src/engine/types"; import { getHandler } from "../../src/engine/registry"; import "../../src/capabilities/system-extended"; const context = {} as RunContext; const component = {} as CatalogComponent; const children: Array> = []; const node = (componentId: string): FlowNode => ({ id: componentId, componentId, position: { x: 0, y: 0 }, values: {}, options: {} }); async function run(id: string, args: Record = {}) { const handler = getHandler(id); expect(handler, id).toBeTruthy(); return handler!(context, node(id), args, component); } afterEach(() => { for (const child of children.splice(0)) if (!child.killed) child.kill(); delete process.env.RPA_STUDIO_TEST_ENV; }); describe("system extended capabilities", () => { it("reads and writes process environment values and standard paths", async () => { await expect(run("System_SetEnv", { name: "RPA_STUDIO_TEST_ENV", value: "connected" })).resolves.toBe("connected"); await expect(run("System_GetEnv", { name: "RPA_STUDIO_TEST_ENV" })).resolves.toBe("connected"); await expect(run("System_GetTempPath")).resolves.toBe(os.tmpdir()); await expect(run("System_GetHomePath")).resolves.toBe(os.homedir()); await expect(run("System_GetSystemPath", { path_name: "documents" })).resolves.toBe(path.join(os.homedir(), "Documents")); }); it("finds and terminates a test child process by PID", async () => { const child = spawn(process.execPath, ["-e", "setInterval(()=>{},1000)"], { windowsHide: true }); children.push(child); await new Promise((resolve) => setTimeout(resolve, 300)); const pids = await run("App_GetPids", { pattern: "node.exe" }) as number[]; expect(pids).toContain(child.pid); const exited = new Promise((resolve) => child.once("exit", resolve)); await run("App_Kill", { pid: child.pid }); const exitCode = await exited; expect(exitCode).not.toBeUndefined(); }, 10000); it("registers safe clipboard and window variants", () => { for (const id of ["Clipboard_GetTextV1", "Clipboard_SetTextV1", "Clipboard_ClearClipboard", "Window_GetWindowRect", "Window_SetWindowState", "Window_SetWindowState_v1", "Window_SizeWindow_v1"]) { expect(getHandler(id), id).toBeTruthy(); } }); });