mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 05:40:44 +00:00
fix(browser): reject ax<N> refs in act path instead of timing out (#69924)
This commit is contained in:
@@ -296,6 +296,9 @@ export type AriaSnapshotNode = {
|
||||
depth: number;
|
||||
};
|
||||
|
||||
export const AX_REF_PREFIX = "ax";
|
||||
export const AX_REF_PATTERN = new RegExp(`^${AX_REF_PREFIX}\\d+$`);
|
||||
|
||||
export type RawAXNode = {
|
||||
nodeId?: string;
|
||||
role?: { value?: string };
|
||||
@@ -362,7 +365,7 @@ export function formatAriaSnapshot(nodes: RawAXNode[], limit: number): AriaSnaps
|
||||
const name = axValue(n.name);
|
||||
const value = axValue(n.value);
|
||||
const description = axValue(n.description);
|
||||
const ref = `ax${out.length + 1}`;
|
||||
const ref = `${AX_REF_PREFIX}${out.length + 1}`;
|
||||
out.push({
|
||||
ref,
|
||||
role: role || "unknown",
|
||||
|
||||
@@ -71,6 +71,13 @@ describe("pw-session refLocator", () => {
|
||||
|
||||
expect(mocks.locator).toHaveBeenCalledWith("aria-ref=e1");
|
||||
});
|
||||
|
||||
it("rejects axN refs from format=aria snapshots instead of timing out", () => {
|
||||
const { page, mocks } = fakePage();
|
||||
|
||||
expect(() => refLocator(page, "ax12")).toThrow(/format=aria snapshot/);
|
||||
expect(mocks.locator).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe("pw-session role refs cache", () => {
|
||||
|
||||
@@ -20,7 +20,7 @@ import {
|
||||
normalizeCdpHttpBaseForJsonEndpoints,
|
||||
withCdpSocket,
|
||||
} from "./cdp.helpers.js";
|
||||
import { normalizeCdpWsUrl } from "./cdp.js";
|
||||
import { AX_REF_PATTERN, normalizeCdpWsUrl } from "./cdp.js";
|
||||
import { getChromeWebSocketUrl } from "./chrome.js";
|
||||
import { BrowserTabNotFoundError } from "./errors.js";
|
||||
import {
|
||||
@@ -884,6 +884,13 @@ export function refLocator(page: Page, ref: string) {
|
||||
return info.nth !== undefined ? locator.nth(info.nth) : locator;
|
||||
}
|
||||
|
||||
if (AX_REF_PATTERN.test(normalized)) {
|
||||
throw new Error(
|
||||
`Ref "${normalized}" comes from a format=aria snapshot and cannot be used with act. ` +
|
||||
`Re-snapshot with format=ai and use the eN refs from that snapshot.`,
|
||||
);
|
||||
}
|
||||
|
||||
return page.locator(`aria-ref=${normalized}`);
|
||||
}
|
||||
|
||||
|
||||
@@ -60,6 +60,12 @@ describe("pw-tools-core", () => {
|
||||
errorMessage: 'Timeout 5000ms exceeded. waiting for locator("aria-ref=1") to be visible',
|
||||
expectedMessage: /not found or not visible/i,
|
||||
},
|
||||
{
|
||||
name: "bare locator timeouts into snapshot hints",
|
||||
errorMessage:
|
||||
"locator.click: Timeout 30000ms exceeded.\nCall log:\n - waiting for locator('aria-ref=ax13')",
|
||||
expectedMessage: /not found or not visible/i,
|
||||
},
|
||||
])("rewrites $name", async ({ errorMessage, expectedMessage }) => {
|
||||
const click = vi.fn(async () => {
|
||||
throw new Error(errorMessage);
|
||||
|
||||
@@ -64,7 +64,9 @@ export function toAIFriendlyError(error: unknown, selector: string): Error {
|
||||
|
||||
if (
|
||||
(message.includes("Timeout") || message.includes("waiting for")) &&
|
||||
(message.includes("to be visible") || message.includes("not visible"))
|
||||
(message.includes("to be visible") ||
|
||||
message.includes("not visible") ||
|
||||
message.includes("waiting for locator("))
|
||||
) {
|
||||
return new Error(
|
||||
`Element "${selector}" not found or not visible. ` +
|
||||
|
||||
Reference in New Issue
Block a user