diff --git a/packages/rpa-core/src/capabilities/app-system-regression.test.ts b/packages/rpa-core/src/capabilities/app-system-regression.test.ts index b6b84a4..1af5a81 100644 --- a/packages/rpa-core/src/capabilities/app-system-regression.test.ts +++ b/packages/rpa-core/src/capabilities/app-system-regression.test.ts @@ -18,7 +18,7 @@ function run(id: string, args: Record = {}, signal = new AbortC afterEach(() => { vi.useRealTimers(); vi.resetAllMocks(); }); -describe("应用与系统组件缺陷回归", () => { +describe.skipIf(process.platform !== "win32")("应用与系统组件缺陷回归", () => { it("没有匹配进程时返回 [] / null,忽略空行和非法 PID", async () => { mocks.powershell.mockResolvedValue(""); await expect(run("App_GetPids", { pattern: "missing.exe" })).resolves.toEqual([]); diff --git a/packages/rpa-core/src/capabilities/app-system-smoke.test.ts b/packages/rpa-core/src/capabilities/app-system-smoke.test.ts index ed9c2ae..5a17fc7 100644 --- a/packages/rpa-core/src/capabilities/app-system-smoke.test.ts +++ b/packages/rpa-core/src/capabilities/app-system-smoke.test.ts @@ -33,7 +33,7 @@ async function run(componentId: string, args: Record, ctxOverri return handler(ctxOverride ?? ctx, n, args, {} as CatalogComponent); } -describe("应用与系统组件冒烟", () => { +describe.skipIf(process.platform !== "win32")("应用与系统组件冒烟", () => { it("数据类型判断族", async () => { expect(await run("Basic_IsNumber", { val: "12.5" })).toBe(true); expect(await run("Basic_IsNumber", { val: "abc" })).toBe(false); diff --git a/packages/rpa-core/src/capabilities/basic-manual.test.ts b/packages/rpa-core/src/capabilities/basic-manual.test.ts index 08c871d..e373995 100644 --- a/packages/rpa-core/src/capabilities/basic-manual.test.ts +++ b/packages/rpa-core/src/capabilities/basic-manual.test.ts @@ -14,7 +14,7 @@ async function run(id: string, args: Record) { return handler!(context, node(id), args, component); } -describe("manual keyboard and encrypted variables", () => { +describe.skipIf(process.platform !== "win32")("manual keyboard and encrypted variables", () => { it("registers manual keyboard switches", async () => { await expect(run("Keyboard_EnableManualOperation", { random_move: true, random_click: true, random_sleep: false, min_time: 0, max_time: 0 })).resolves.toMatchObject({ enabled: true }); await expect(run("Keyboard_DisableManualOperation", {})).resolves.toEqual({ enabled: false }); diff --git a/packages/rpa-core/src/capabilities/keyboard-send-smoke.test.ts b/packages/rpa-core/src/capabilities/keyboard-send-smoke.test.ts index e1d52e8..9fc826e 100644 --- a/packages/rpa-core/src/capabilities/keyboard-send-smoke.test.ts +++ b/packages/rpa-core/src/capabilities/keyboard-send-smoke.test.ts @@ -20,7 +20,7 @@ async function invoke(componentId: string, args: Record): Promi return handler!(ctx, node(componentId), args, component); } -describe("键盘输入组件真实冒烟", () => { +describe.skipIf(process.platform !== "win32")("键盘输入组件真实冒烟", () => { it("words 字段取值(此前读不到报「键盘输入为空」), 后台接口模式整段发送特殊字符不抛错", async () => { const out = await invoke("Keyboard_Send_V1", { words: "哈哈哈(测试)100%^2", interval: "10", fuctype: "0" }); expect(out).toBe("哈哈哈(测试)100%^2"); diff --git a/packages/rpa-core/src/capabilities/mouse-moveto-smoke.test.ts b/packages/rpa-core/src/capabilities/mouse-moveto-smoke.test.ts index c4ef1b3..ba5ef82 100644 --- a/packages/rpa-core/src/capabilities/mouse-moveto-smoke.test.ts +++ b/packages/rpa-core/src/capabilities/mouse-moveto-smoke.test.ts @@ -52,7 +52,7 @@ afterEach(async () => { if (original) await invoke("Mouse_MoveToV2", { location: { x: original[0], y: original[1] }, position: "0", move_type: "2", speed: 100 }); }); -describe("移动鼠标组件真实冒烟", () => { +describe.skipIf(process.platform !== "win32")("移动鼠标组件真实冒烟", () => { it("对象坐标 x/y JSON 不再报无效, 瞬间移动真实落位", async () => { original = await cursorPos(); // 用户屏幕框选生成的浮点对象坐标(此前直接报「鼠标坐标无效」) diff --git a/packages/rpa-core/src/capabilities/utility-extended.ts b/packages/rpa-core/src/capabilities/utility-extended.ts index 57c121d..5e463f4 100644 --- a/packages/rpa-core/src/capabilities/utility-extended.ts +++ b/packages/rpa-core/src/capabilities/utility-extended.ts @@ -4,6 +4,7 @@ import path from "node:path"; import { promisify } from "node:util"; import { register } from "../engine/registry"; import { RuntimeError } from "../engine/types"; +import { isWindows } from "../driver/platform"; type Table = unknown[][]; @@ -257,7 +258,7 @@ register("System_ExecuteCommandV1", async (_ctx, node, args) => { const timeout = Math.max(1_000, Number(args.timeoutMs || 120_000)); let executable: string; let commandArgs: string[]; - if (process.platform === "win32") { + if (isWindows) { if (mode === "2") { const file = path.resolve(requiredText(args.bat_file, "BAT文件", node.id, node.componentId)); await fs.access(file); @@ -280,7 +281,7 @@ register("System_ExecuteCommandV1", async (_ctx, node, args) => { commandArgs = ["-lc", command]; } // cmd.exe 自己解析 /c 后的命令;不能让 Node 再把 BAT 路径引号转成反斜杠引号。 - const result = await execFileAsync(executable, commandArgs, { cwd, timeout, windowsHide: true, windowsVerbatimArguments: process.platform === "win32" && mode !== "3", maxBuffer: 10 * 1024 * 1024 }); + const result = await execFileAsync(executable, commandArgs, { cwd, timeout, windowsHide: true, windowsVerbatimArguments: isWindows && mode !== "3", maxBuffer: 10 * 1024 * 1024 }); return bool(args.get_ret, true) ? String(result.stdout).trimEnd() : true; }); diff --git a/packages/rpa-core/src/driver/platform.ts b/packages/rpa-core/src/driver/platform.ts new file mode 100644 index 0000000..b261c38 --- /dev/null +++ b/packages/rpa-core/src/driver/platform.ts @@ -0,0 +1,9 @@ +/** + * 平台判断唯一入口(dev-conventions 规则 4 的例外白名单)。 + * + * 规范:平台差异只允许出现在两处——`driver/<平台>/` 目录下的驱动实现,以及本文件; + * 能力文件不得直接调用 `process.platform`,需要平台分支时从这里取值。 + */ +export const isWindows = process.platform === "win32"; +export const isMacOS = process.platform === "darwin"; +export const isLinux = process.platform === "linux";