元素点击未生效(clicked=false)改为抛错, 按错误契约给出拾取建议

This commit is contained in:
yu 2026-11-04 17:41:58 +08:00
parent f95a24458e
commit abb3d26acd
2 changed files with 37 additions and 2 deletions

View File

@ -120,6 +120,24 @@ describe("desktop UIA selector compatibility", () => {
expect(script).toContain("Find-RpaWindow");
});
it("元素定位到但 clicked=false 时必须抛错,不允许静默成功(用户 NVIDIA 覆盖层踩坑场景)", async () => {
powershellMock.mockImplementation(async () => '{"clicked":false,"method":"invoke_pattern","name":"","x":0,"y":0,"w":1919,"h":1080}');
let error: any = null;
try {
await getHandler("Element_ClickGround")!(
context,
node,
{ selector: "window=NVIDIA GeForce Overlay DT;type=Document;id=RootWebArea" },
{} as any
);
} catch (e) {
error = e;
}
expect(error?.code).toBe("desktop_error");
// recommendation 必须给出可执行建议
expect(String(error?.recommendation ?? "")).toContain("桌面拾取");
});
it("dispatches screen setValue to coordinate paste", async () => {
await getHandler("Element_SetValueGround")!(context, node, {
selector: "screen=10,20,30,40",

View File

@ -690,8 +690,25 @@ function requireFound(result: Record<string, unknown> | null, t: UiaTarget, acti
const clickGround: CapabilityHandler = async (_ctx, node, args) => {
const t = target(args, node);
if (t.selector.screen) return runScript(clickScreenScript(t), t);
return runWithImplicitWait(t, "click", clickScript(t), runScript, args);
const result = t.selector.screen
? await runScript(clickScreenScript(t), t)
: await runWithImplicitWait(t, "click", clickScript(t), runScript, args);
// 元素定位到了但实际没点成(如拾取到全屏透明覆盖层:IsOffscreen=true 且无 Invoke/Toggle/Expand/Select 模式)。
// 这种"假成功"会掩盖问题,必须按错误契约抛出,让运行记录如实标红。
if (result && result.clicked === false) {
const s = t.selector;
throw new RuntimeError(
"desktop_error",
`元素点击未生效:已定位到目标(window=${s.window ?? ""}, name=${s.name ?? ""}, type=${s.type ?? ""}),但该元素不可见点击且不支持任何可调用模式`,
{
recommendation: "重新用「桌面拾取」选择真实可见的目标控件;若拾取结果落在全屏透明覆盖层上(如 NVIDIA 游戏内覆盖层、录屏悬浮条),先关闭覆盖层再拾取",
nodeId: node.id,
componentId: node.componentId,
detail: JSON.stringify(result)
}
);
}
return result;
};
const setValueGround: CapabilityHandler = async (_ctx, node, args) => {