Skip to content

Commit 1d9b74c

Browse files
[chore] rm old performPlaywrightMethod (#875)
# why - it is not good practice to maintain two separate implementations of the same function # what changed - removed a duplicate implementation of `performPlaywrightMethod` which was being used by the `observe_simple_google_search` eval - replaced the function call with a call to `page.act(ObserveResult)` which targets the implementation of `performPlaywrightMethod` that is actually being used (and is therefore the implementation that we should be testing # test plan - `regression` evals - `observe` evals
1 parent 6b4e6e3 commit 1d9b74c

File tree

2 files changed

+2
-332
lines changed

2 files changed

+2
-332
lines changed

evals/tasks/observe_simple_google_search.ts

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { EvalFunction } from "@/types/evals";
2-
import { performPlaywrightMethod } from "@/lib/a11y/utils";
32

43
export const observe_simple_google_search: EvalFunction = async ({
54
debugUrl,
@@ -18,27 +17,15 @@ export const observe_simple_google_search: EvalFunction = async ({
1817

1918
if (observation1.length > 0) {
2019
const action1 = observation1[0];
21-
await performPlaywrightMethod(
22-
stagehand.page,
23-
stagehand.logger,
24-
action1.method,
25-
action1.arguments,
26-
action1.selector.replace("xpath=", ""),
27-
);
20+
await stagehand.page.act(action1);
2821
}
2922
const observation2 = await stagehand.page.observe({
3023
instruction: "Click the search button in the suggestions dropdown",
3124
});
3225

3326
if (observation2.length > 0) {
3427
const action2 = observation2[0];
35-
await performPlaywrightMethod(
36-
stagehand.page,
37-
stagehand.logger,
38-
action2.method,
39-
action2.arguments,
40-
action2.selector.replace("xpath=", ""),
41-
);
28+
await stagehand.page.act(action2);
4229
}
4330

4431
const expectedUrl =

lib/a11y/utils.ts

Lines changed: 0 additions & 317 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,6 @@ import {
1414
} from "../../types/context";
1515
import { StagehandPage } from "../StagehandPage";
1616
import { LogLine } from "../../types/log";
17-
import { Page, Locator } from "playwright";
18-
import {
19-
PlaywrightCommandMethodNotSupportedException,
20-
PlaywrightCommandException,
21-
} from "@/types/playwright";
2217
import {
2318
ContentFrameNotFoundError,
2419
StagehandDomProcessError,
@@ -1210,315 +1205,3 @@ export async function resolveFrameChain(
12101205
}
12111206
}
12121207
}
1213-
1214-
export async function performPlaywrightMethod(
1215-
stagehandPage: Page,
1216-
logger: (logLine: LogLine) => void,
1217-
method: string,
1218-
args: unknown[],
1219-
xpath: string,
1220-
) {
1221-
const locator = stagehandPage.locator(`xpath=${xpath}`).first();
1222-
const initialUrl = stagehandPage.url();
1223-
1224-
logger({
1225-
category: "action",
1226-
message: "performing playwright method",
1227-
level: 2,
1228-
auxiliary: {
1229-
xpath: {
1230-
value: xpath,
1231-
type: "string",
1232-
},
1233-
method: {
1234-
value: method,
1235-
type: "string",
1236-
},
1237-
},
1238-
});
1239-
1240-
if (method === "scrollIntoView") {
1241-
logger({
1242-
category: "action",
1243-
message: "scrolling element into view",
1244-
level: 2,
1245-
auxiliary: {
1246-
xpath: {
1247-
value: xpath,
1248-
type: "string",
1249-
},
1250-
},
1251-
});
1252-
try {
1253-
await locator
1254-
.evaluate((element: HTMLElement) => {
1255-
element.scrollIntoView({ behavior: "smooth", block: "center" });
1256-
})
1257-
.catch((e: Error) => {
1258-
logger({
1259-
category: "action",
1260-
message: "error scrolling element into view",
1261-
level: 1,
1262-
auxiliary: {
1263-
error: {
1264-
value: e.message,
1265-
type: "string",
1266-
},
1267-
trace: {
1268-
value: e.stack,
1269-
type: "string",
1270-
},
1271-
xpath: {
1272-
value: xpath,
1273-
type: "string",
1274-
},
1275-
},
1276-
});
1277-
});
1278-
} catch (e) {
1279-
logger({
1280-
category: "action",
1281-
message: "error scrolling element into view",
1282-
level: 1,
1283-
auxiliary: {
1284-
error: {
1285-
value: e.message,
1286-
type: "string",
1287-
},
1288-
trace: {
1289-
value: e.stack,
1290-
type: "string",
1291-
},
1292-
xpath: {
1293-
value: xpath,
1294-
type: "string",
1295-
},
1296-
},
1297-
});
1298-
1299-
throw new PlaywrightCommandException(e.message);
1300-
}
1301-
} else if (method === "fill" || method === "type") {
1302-
try {
1303-
await locator.fill("");
1304-
await locator.click();
1305-
const text = args[0]?.toString();
1306-
for (const char of text) {
1307-
await stagehandPage.keyboard.type(char, {
1308-
delay: Math.random() * 50 + 25,
1309-
});
1310-
}
1311-
} catch (e) {
1312-
logger({
1313-
category: "action",
1314-
message: "error filling element",
1315-
level: 1,
1316-
auxiliary: {
1317-
error: {
1318-
value: e.message,
1319-
type: "string",
1320-
},
1321-
trace: {
1322-
value: e.stack,
1323-
type: "string",
1324-
},
1325-
xpath: {
1326-
value: xpath,
1327-
type: "string",
1328-
},
1329-
},
1330-
});
1331-
1332-
throw new PlaywrightCommandException(e.message);
1333-
}
1334-
} else if (method === "press") {
1335-
try {
1336-
const key = args[0]?.toString();
1337-
await stagehandPage.keyboard.press(key);
1338-
} catch (e) {
1339-
logger({
1340-
category: "action",
1341-
message: "error pressing key",
1342-
level: 1,
1343-
auxiliary: {
1344-
error: {
1345-
value: e.message,
1346-
type: "string",
1347-
},
1348-
trace: {
1349-
value: e.stack,
1350-
type: "string",
1351-
},
1352-
key: {
1353-
value: args[0]?.toString() ?? "unknown",
1354-
type: "string",
1355-
},
1356-
},
1357-
});
1358-
1359-
throw new PlaywrightCommandException(e.message);
1360-
}
1361-
} else if (typeof locator[method as keyof typeof locator] === "function") {
1362-
// Log current URL before action
1363-
logger({
1364-
category: "action",
1365-
message: "page URL before action",
1366-
level: 2,
1367-
auxiliary: {
1368-
url: {
1369-
value: stagehandPage.url(),
1370-
type: "string",
1371-
},
1372-
},
1373-
});
1374-
1375-
// Perform the action
1376-
try {
1377-
await (
1378-
locator[method as keyof Locator] as unknown as (
1379-
...args: string[]
1380-
) => Promise<void>
1381-
)(...args.map((arg) => arg?.toString() || ""));
1382-
} catch (e) {
1383-
logger({
1384-
category: "action",
1385-
message: "error performing method",
1386-
level: 1,
1387-
auxiliary: {
1388-
error: {
1389-
value: e.message,
1390-
type: "string",
1391-
},
1392-
trace: {
1393-
value: e.stack,
1394-
type: "string",
1395-
},
1396-
xpath: {
1397-
value: xpath,
1398-
type: "string",
1399-
},
1400-
method: {
1401-
value: method,
1402-
type: "string",
1403-
},
1404-
args: {
1405-
value: JSON.stringify(args),
1406-
type: "object",
1407-
},
1408-
},
1409-
});
1410-
1411-
throw new PlaywrightCommandException(e.message);
1412-
}
1413-
1414-
// Handle navigation if a new page is opened
1415-
if (method === "click") {
1416-
logger({
1417-
category: "action",
1418-
message: "clicking element, checking for page navigation",
1419-
level: 1,
1420-
auxiliary: {
1421-
xpath: {
1422-
value: xpath,
1423-
type: "string",
1424-
},
1425-
},
1426-
});
1427-
1428-
const newOpenedTab = await Promise.race([
1429-
new Promise<Page | null>((resolve) => {
1430-
Promise.resolve(stagehandPage.context()).then((context) => {
1431-
context.once("page", (page: Page) => resolve(page));
1432-
setTimeout(() => resolve(null), 1_500);
1433-
});
1434-
}),
1435-
]);
1436-
1437-
logger({
1438-
category: "action",
1439-
message: "clicked element",
1440-
level: 1,
1441-
auxiliary: {
1442-
newOpenedTab: {
1443-
value: newOpenedTab ? "opened a new tab" : "no new tabs opened",
1444-
type: "string",
1445-
},
1446-
},
1447-
});
1448-
1449-
if (newOpenedTab) {
1450-
logger({
1451-
category: "action",
1452-
message: "new page detected (new tab) with URL",
1453-
level: 1,
1454-
auxiliary: {
1455-
url: {
1456-
value: newOpenedTab.url(),
1457-
type: "string",
1458-
},
1459-
},
1460-
});
1461-
await newOpenedTab.close();
1462-
await stagehandPage.goto(newOpenedTab.url());
1463-
await stagehandPage.waitForLoadState("domcontentloaded");
1464-
}
1465-
1466-
await Promise.race([
1467-
stagehandPage.waitForLoadState("networkidle"),
1468-
new Promise((resolve) => setTimeout(resolve, 5_000)),
1469-
]).catch((e) => {
1470-
logger({
1471-
category: "action",
1472-
message: "network idle timeout hit",
1473-
level: 1,
1474-
auxiliary: {
1475-
trace: {
1476-
value: e.stack,
1477-
type: "string",
1478-
},
1479-
message: {
1480-
value: e.message,
1481-
type: "string",
1482-
},
1483-
},
1484-
});
1485-
});
1486-
1487-
logger({
1488-
category: "action",
1489-
message: "finished waiting for (possible) page navigation",
1490-
level: 1,
1491-
});
1492-
1493-
if (stagehandPage.url() !== initialUrl) {
1494-
logger({
1495-
category: "action",
1496-
message: "new page detected with URL",
1497-
level: 1,
1498-
auxiliary: {
1499-
url: {
1500-
value: stagehandPage.url(),
1501-
type: "string",
1502-
},
1503-
},
1504-
});
1505-
}
1506-
}
1507-
} else {
1508-
logger({
1509-
category: "action",
1510-
message: "chosen method is invalid",
1511-
level: 1,
1512-
auxiliary: {
1513-
method: {
1514-
value: method,
1515-
type: "string",
1516-
},
1517-
},
1518-
});
1519-
1520-
throw new PlaywrightCommandMethodNotSupportedException(
1521-
`Method ${method} not supported`,
1522-
);
1523-
}
1524-
}

0 commit comments

Comments
 (0)