@kritchoff/agent-browser 1.0.5 → 1.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.cjs +6 -8
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +6 -8
- package/dist/cli.js.map +1 -1
- package/dist/daemon.cjs +1102 -1086
- package/dist/daemon.cjs.map +1 -1
- package/dist/daemon.js +1102 -1086
- package/dist/daemon.js.map +1 -1
- package/dist/index.cjs +6 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -2
- package/dist/index.d.ts +1 -2
- package/dist/index.js +6 -8
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/daemon.js
CHANGED
|
@@ -30,15 +30,15 @@ function parseRef(arg) {
|
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
// src/taxtree.ts
|
|
33
|
-
async function getDualModeSnapshot(
|
|
34
|
-
const session = await
|
|
33
|
+
async function getDualModeSnapshot(page, options = {}) {
|
|
34
|
+
const session = await page.context().newCDPSession(page);
|
|
35
35
|
let nodes = [];
|
|
36
36
|
let isDualMode = false;
|
|
37
37
|
try {
|
|
38
38
|
const result = await session.send("Accessibility.getDualModeAXTree");
|
|
39
39
|
nodes = result.nodes;
|
|
40
40
|
isDualMode = true;
|
|
41
|
-
} catch
|
|
41
|
+
} catch {
|
|
42
42
|
try {
|
|
43
43
|
const result = await session.send("Accessibility.getFullAXTree");
|
|
44
44
|
nodes = result.nodes;
|
|
@@ -315,8 +315,8 @@ var BrowserManager = class {
|
|
|
315
315
|
* Get enhanced snapshot with refs and cache the ref map
|
|
316
316
|
*/
|
|
317
317
|
async getSnapshot(options) {
|
|
318
|
-
const
|
|
319
|
-
const snapshot = await getDualModeSnapshot(
|
|
318
|
+
const page = this.getPage();
|
|
319
|
+
const snapshot = await getDualModeSnapshot(page, options);
|
|
320
320
|
this.refMap = snapshot.refs;
|
|
321
321
|
this.lastSnapshot = snapshot.tree;
|
|
322
322
|
return snapshot;
|
|
@@ -336,20 +336,20 @@ var BrowserManager = class {
|
|
|
336
336
|
if (!ref) return null;
|
|
337
337
|
const refData = this.refMap[ref];
|
|
338
338
|
if (!refData) return null;
|
|
339
|
-
const
|
|
339
|
+
const page = this.getPage();
|
|
340
340
|
if (refData.role === "clickable" || refData.role === "focusable") {
|
|
341
|
-
return
|
|
341
|
+
return page.locator(refData.selector);
|
|
342
342
|
}
|
|
343
|
-
let
|
|
343
|
+
let locator;
|
|
344
344
|
if (refData.name) {
|
|
345
|
-
|
|
345
|
+
locator = page.getByRole(refData.role, { name: refData.name, exact: true });
|
|
346
346
|
} else {
|
|
347
|
-
|
|
347
|
+
locator = page.getByRole(refData.role);
|
|
348
348
|
}
|
|
349
349
|
if (refData.nth !== void 0) {
|
|
350
|
-
|
|
350
|
+
locator = locator.nth(refData.nth);
|
|
351
351
|
}
|
|
352
|
-
return
|
|
352
|
+
return locator;
|
|
353
353
|
}
|
|
354
354
|
/**
|
|
355
355
|
* Check if a selector looks like a ref
|
|
@@ -369,10 +369,10 @@ var BrowserManager = class {
|
|
|
369
369
|
* Get locator - supports both refs and regular selectors
|
|
370
370
|
*/
|
|
371
371
|
getLocator(selectorOrRef) {
|
|
372
|
-
const
|
|
373
|
-
if (
|
|
374
|
-
const
|
|
375
|
-
return
|
|
372
|
+
const locator = this.getLocatorFromRef(selectorOrRef);
|
|
373
|
+
if (locator) return locator;
|
|
374
|
+
const page = this.getPage();
|
|
375
|
+
return page.locator(selectorOrRef);
|
|
376
376
|
}
|
|
377
377
|
/**
|
|
378
378
|
* Get the current active page, throws if not launched
|
|
@@ -396,9 +396,9 @@ var BrowserManager = class {
|
|
|
396
396
|
* Switch to a frame by selector, name, or URL
|
|
397
397
|
*/
|
|
398
398
|
async switchToFrame(options) {
|
|
399
|
-
const
|
|
399
|
+
const page = this.getPage();
|
|
400
400
|
if (options.selector) {
|
|
401
|
-
const frameElement = await
|
|
401
|
+
const frameElement = await page.$(options.selector);
|
|
402
402
|
if (!frameElement) {
|
|
403
403
|
throw new Error(`Frame not found: ${options.selector}`);
|
|
404
404
|
}
|
|
@@ -408,13 +408,13 @@ var BrowserManager = class {
|
|
|
408
408
|
}
|
|
409
409
|
this.activeFrame = frame;
|
|
410
410
|
} else if (options.name) {
|
|
411
|
-
const frame =
|
|
411
|
+
const frame = page.frame({ name: options.name });
|
|
412
412
|
if (!frame) {
|
|
413
413
|
throw new Error(`Frame not found with name: ${options.name}`);
|
|
414
414
|
}
|
|
415
415
|
this.activeFrame = frame;
|
|
416
416
|
} else if (options.url) {
|
|
417
|
-
const frame =
|
|
417
|
+
const frame = page.frame({ url: options.url });
|
|
418
418
|
if (!frame) {
|
|
419
419
|
throw new Error(`Frame not found with URL: ${options.url}`);
|
|
420
420
|
}
|
|
@@ -431,9 +431,9 @@ var BrowserManager = class {
|
|
|
431
431
|
* Set up dialog handler
|
|
432
432
|
*/
|
|
433
433
|
setDialogHandler(response, promptText) {
|
|
434
|
-
const
|
|
434
|
+
const page = this.getPage();
|
|
435
435
|
if (this.dialogHandler) {
|
|
436
|
-
|
|
436
|
+
page.removeListener("dialog", this.dialogHandler);
|
|
437
437
|
}
|
|
438
438
|
this.dialogHandler = async (dialog) => {
|
|
439
439
|
if (response === "accept") {
|
|
@@ -442,15 +442,15 @@ var BrowserManager = class {
|
|
|
442
442
|
await dialog.dismiss();
|
|
443
443
|
}
|
|
444
444
|
};
|
|
445
|
-
|
|
445
|
+
page.on("dialog", this.dialogHandler);
|
|
446
446
|
}
|
|
447
447
|
/**
|
|
448
448
|
* Clear dialog handler
|
|
449
449
|
*/
|
|
450
450
|
clearDialogHandler() {
|
|
451
451
|
if (this.dialogHandler) {
|
|
452
|
-
const
|
|
453
|
-
|
|
452
|
+
const page = this.getPage();
|
|
453
|
+
page.removeListener("dialog", this.dialogHandler);
|
|
454
454
|
this.dialogHandler = null;
|
|
455
455
|
}
|
|
456
456
|
}
|
|
@@ -458,8 +458,8 @@ var BrowserManager = class {
|
|
|
458
458
|
* Start tracking requests
|
|
459
459
|
*/
|
|
460
460
|
startRequestTracking() {
|
|
461
|
-
const
|
|
462
|
-
|
|
461
|
+
const page = this.getPage();
|
|
462
|
+
page.on("request", (request) => {
|
|
463
463
|
this.trackedRequests.push({
|
|
464
464
|
url: request.url(),
|
|
465
465
|
method: request.method(),
|
|
@@ -488,7 +488,7 @@ var BrowserManager = class {
|
|
|
488
488
|
* Add a route to intercept requests
|
|
489
489
|
*/
|
|
490
490
|
async addRoute(url, options) {
|
|
491
|
-
const
|
|
491
|
+
const page = this.getPage();
|
|
492
492
|
const handler = async (route) => {
|
|
493
493
|
if (options.abort) {
|
|
494
494
|
await route.abort();
|
|
@@ -504,22 +504,22 @@ var BrowserManager = class {
|
|
|
504
504
|
}
|
|
505
505
|
};
|
|
506
506
|
this.routes.set(url, handler);
|
|
507
|
-
await
|
|
507
|
+
await page.route(url, handler);
|
|
508
508
|
}
|
|
509
509
|
/**
|
|
510
510
|
* Remove a route
|
|
511
511
|
*/
|
|
512
512
|
async removeRoute(url) {
|
|
513
|
-
const
|
|
513
|
+
const page = this.getPage();
|
|
514
514
|
if (url) {
|
|
515
515
|
const handler = this.routes.get(url);
|
|
516
516
|
if (handler) {
|
|
517
|
-
await
|
|
517
|
+
await page.unroute(url, handler);
|
|
518
518
|
this.routes.delete(url);
|
|
519
519
|
}
|
|
520
520
|
} else {
|
|
521
521
|
for (const [routeUrl, handler] of this.routes) {
|
|
522
|
-
await
|
|
522
|
+
await page.unroute(routeUrl, handler);
|
|
523
523
|
}
|
|
524
524
|
this.routes.clear();
|
|
525
525
|
}
|
|
@@ -550,8 +550,8 @@ var BrowserManager = class {
|
|
|
550
550
|
* Set viewport
|
|
551
551
|
*/
|
|
552
552
|
async setViewport(width, height) {
|
|
553
|
-
const
|
|
554
|
-
await
|
|
553
|
+
const page = this.getPage();
|
|
554
|
+
await page.setViewportSize({ width, height });
|
|
555
555
|
}
|
|
556
556
|
/**
|
|
557
557
|
* Set device scale factor (devicePixelRatio) via CDP
|
|
@@ -596,8 +596,8 @@ var BrowserManager = class {
|
|
|
596
596
|
* Start console message tracking
|
|
597
597
|
*/
|
|
598
598
|
startConsoleTracking() {
|
|
599
|
-
const
|
|
600
|
-
|
|
599
|
+
const page = this.getPage();
|
|
600
|
+
page.on("console", (msg) => {
|
|
601
601
|
this.consoleMessages.push({
|
|
602
602
|
type: msg.type(),
|
|
603
603
|
text: msg.text(),
|
|
@@ -621,8 +621,8 @@ var BrowserManager = class {
|
|
|
621
621
|
* Start error tracking
|
|
622
622
|
*/
|
|
623
623
|
startErrorTracking() {
|
|
624
|
-
const
|
|
625
|
-
|
|
624
|
+
const page = this.getPage();
|
|
625
|
+
page.on("pageerror", (error) => {
|
|
626
626
|
this.pageErrors.push({
|
|
627
627
|
message: error.message,
|
|
628
628
|
timestamp: Date.now()
|
|
@@ -676,7 +676,7 @@ var BrowserManager = class {
|
|
|
676
676
|
* Uses route interception to add headers only to matching requests
|
|
677
677
|
*/
|
|
678
678
|
async setScopedHeaders(origin, headers) {
|
|
679
|
-
const
|
|
679
|
+
const page = this.getPage();
|
|
680
680
|
let urlPattern;
|
|
681
681
|
try {
|
|
682
682
|
const url = new URL(origin.startsWith("http") ? origin : `https://${origin}`);
|
|
@@ -686,7 +686,7 @@ var BrowserManager = class {
|
|
|
686
686
|
}
|
|
687
687
|
const existingHandler = this.scopedHeaderRoutes.get(urlPattern);
|
|
688
688
|
if (existingHandler) {
|
|
689
|
-
await
|
|
689
|
+
await page.unroute(urlPattern, existingHandler);
|
|
690
690
|
}
|
|
691
691
|
const handler = async (route) => {
|
|
692
692
|
const requestHeaders = route.request().headers();
|
|
@@ -698,13 +698,13 @@ var BrowserManager = class {
|
|
|
698
698
|
});
|
|
699
699
|
};
|
|
700
700
|
this.scopedHeaderRoutes.set(urlPattern, handler);
|
|
701
|
-
await
|
|
701
|
+
await page.route(urlPattern, handler);
|
|
702
702
|
}
|
|
703
703
|
/**
|
|
704
704
|
* Clear scoped headers for an origin (or all if no origin specified)
|
|
705
705
|
*/
|
|
706
706
|
async clearScopedHeaders(origin) {
|
|
707
|
-
const
|
|
707
|
+
const page = this.getPage();
|
|
708
708
|
if (origin) {
|
|
709
709
|
let urlPattern;
|
|
710
710
|
try {
|
|
@@ -715,12 +715,12 @@ var BrowserManager = class {
|
|
|
715
715
|
}
|
|
716
716
|
const handler = this.scopedHeaderRoutes.get(urlPattern);
|
|
717
717
|
if (handler) {
|
|
718
|
-
await
|
|
718
|
+
await page.unroute(urlPattern, handler);
|
|
719
719
|
this.scopedHeaderRoutes.delete(urlPattern);
|
|
720
720
|
}
|
|
721
721
|
} else {
|
|
722
722
|
for (const [pattern, handler] of this.scopedHeaderRoutes) {
|
|
723
|
-
await
|
|
723
|
+
await page.unroute(pattern, handler);
|
|
724
724
|
}
|
|
725
725
|
this.scopedHeaderRoutes.clear();
|
|
726
726
|
}
|
|
@@ -863,26 +863,26 @@ var BrowserManager = class {
|
|
|
863
863
|
throw new Error(`Failed to create Browserbase session: ${response.statusText}`);
|
|
864
864
|
}
|
|
865
865
|
const session = await response.json();
|
|
866
|
-
const
|
|
866
|
+
const browser = await chromium.connectOverCDP(session.connectUrl).catch(() => {
|
|
867
867
|
throw new Error("Failed to connect to Browserbase session via CDP");
|
|
868
868
|
});
|
|
869
869
|
try {
|
|
870
|
-
const contexts =
|
|
870
|
+
const contexts = browser.contexts();
|
|
871
871
|
if (contexts.length === 0) {
|
|
872
872
|
throw new Error("No browser context found in Browserbase session");
|
|
873
873
|
}
|
|
874
874
|
const context = contexts[0];
|
|
875
875
|
const pages = context.pages();
|
|
876
|
-
const
|
|
876
|
+
const page = pages[0] ?? await context.newPage();
|
|
877
877
|
this.browserbaseSessionId = session.id;
|
|
878
878
|
this.browserbaseApiKey = browserbaseApiKey;
|
|
879
|
-
this.browser =
|
|
879
|
+
this.browser = browser;
|
|
880
880
|
context.setDefaultTimeout(1e4);
|
|
881
881
|
this.contexts.push(context);
|
|
882
882
|
this.setupContextTracking(context);
|
|
883
|
-
this.pages.push(
|
|
883
|
+
this.pages.push(page);
|
|
884
884
|
this.activePageIndex = 0;
|
|
885
|
-
this.setupPageTracking(
|
|
885
|
+
this.setupPageTracking(page);
|
|
886
886
|
} catch (error) {
|
|
887
887
|
await this.closeBrowserbaseSession(session.id, browserbaseApiKey).catch((sessionError) => {
|
|
888
888
|
console.error("Failed to close Browserbase session during cleanup:", sessionError);
|
|
@@ -977,29 +977,29 @@ var BrowserManager = class {
|
|
|
977
977
|
`Invalid Kernel session response: missing ${!session.session_id ? "session_id" : "cdp_ws_url"}`
|
|
978
978
|
);
|
|
979
979
|
}
|
|
980
|
-
const
|
|
980
|
+
const browser = await chromium.connectOverCDP(session.cdp_ws_url).catch(() => {
|
|
981
981
|
throw new Error("Failed to connect to Kernel session via CDP");
|
|
982
982
|
});
|
|
983
983
|
try {
|
|
984
|
-
const contexts =
|
|
984
|
+
const contexts = browser.contexts();
|
|
985
985
|
let context;
|
|
986
|
-
let
|
|
986
|
+
let page;
|
|
987
987
|
if (contexts.length === 0) {
|
|
988
|
-
context = await
|
|
989
|
-
|
|
988
|
+
context = await browser.newContext();
|
|
989
|
+
page = await context.newPage();
|
|
990
990
|
} else {
|
|
991
991
|
context = contexts[0];
|
|
992
992
|
const pages = context.pages();
|
|
993
|
-
|
|
993
|
+
page = pages[0] ?? await context.newPage();
|
|
994
994
|
}
|
|
995
995
|
this.kernelSessionId = session.session_id;
|
|
996
996
|
this.kernelApiKey = kernelApiKey;
|
|
997
|
-
this.browser =
|
|
997
|
+
this.browser = browser;
|
|
998
998
|
context.setDefaultTimeout(6e4);
|
|
999
999
|
this.contexts.push(context);
|
|
1000
|
-
this.pages.push(
|
|
1000
|
+
this.pages.push(page);
|
|
1001
1001
|
this.activePageIndex = 0;
|
|
1002
|
-
this.setupPageTracking(
|
|
1002
|
+
this.setupPageTracking(page);
|
|
1003
1003
|
this.setupContextTracking(context);
|
|
1004
1004
|
} catch (error) {
|
|
1005
1005
|
await this.closeKernelSession(session.session_id, kernelApiKey).catch((sessionError) => {
|
|
@@ -1041,29 +1041,29 @@ var BrowserManager = class {
|
|
|
1041
1041
|
`Invalid Browser Use session response: missing ${!session.id ? "id" : "cdpUrl"}`
|
|
1042
1042
|
);
|
|
1043
1043
|
}
|
|
1044
|
-
const
|
|
1044
|
+
const browser = await chromium.connectOverCDP(session.cdpUrl).catch(() => {
|
|
1045
1045
|
throw new Error("Failed to connect to Browser Use session via CDP");
|
|
1046
1046
|
});
|
|
1047
1047
|
try {
|
|
1048
|
-
const contexts =
|
|
1048
|
+
const contexts = browser.contexts();
|
|
1049
1049
|
let context;
|
|
1050
|
-
let
|
|
1050
|
+
let page;
|
|
1051
1051
|
if (contexts.length === 0) {
|
|
1052
|
-
context = await
|
|
1053
|
-
|
|
1052
|
+
context = await browser.newContext();
|
|
1053
|
+
page = await context.newPage();
|
|
1054
1054
|
} else {
|
|
1055
1055
|
context = contexts[0];
|
|
1056
1056
|
const pages = context.pages();
|
|
1057
|
-
|
|
1057
|
+
page = pages[0] ?? await context.newPage();
|
|
1058
1058
|
}
|
|
1059
1059
|
this.browserUseSessionId = session.id;
|
|
1060
1060
|
this.browserUseApiKey = browserUseApiKey;
|
|
1061
|
-
this.browser =
|
|
1061
|
+
this.browser = browser;
|
|
1062
1062
|
context.setDefaultTimeout(6e4);
|
|
1063
1063
|
this.contexts.push(context);
|
|
1064
|
-
this.pages.push(
|
|
1064
|
+
this.pages.push(page);
|
|
1065
1065
|
this.activePageIndex = 0;
|
|
1066
|
-
this.setupPageTracking(
|
|
1066
|
+
this.setupPageTracking(page);
|
|
1067
1067
|
this.setupContextTracking(context);
|
|
1068
1068
|
} catch (error) {
|
|
1069
1069
|
await this.closeBrowserUseSession(session.id, browserUseApiKey).catch((sessionError) => {
|
|
@@ -1185,10 +1185,10 @@ var BrowserManager = class {
|
|
|
1185
1185
|
context.setDefaultTimeout(6e4);
|
|
1186
1186
|
this.contexts.push(context);
|
|
1187
1187
|
this.setupContextTracking(context);
|
|
1188
|
-
const
|
|
1189
|
-
if (!this.pages.includes(
|
|
1190
|
-
this.pages.push(
|
|
1191
|
-
this.setupPageTracking(
|
|
1188
|
+
const page = context.pages()[0] ?? await context.newPage();
|
|
1189
|
+
if (!this.pages.includes(page)) {
|
|
1190
|
+
this.pages.push(page);
|
|
1191
|
+
this.setupPageTracking(page);
|
|
1192
1192
|
}
|
|
1193
1193
|
this.activePageIndex = this.pages.length > 0 ? this.pages.length - 1 : 0;
|
|
1194
1194
|
}
|
|
@@ -1208,34 +1208,34 @@ var BrowserManager = class {
|
|
|
1208
1208
|
} else {
|
|
1209
1209
|
cdpUrl = `http://localhost:${cdpEndpoint}`;
|
|
1210
1210
|
}
|
|
1211
|
-
const
|
|
1211
|
+
const browser = await chromium.connectOverCDP(cdpUrl).catch(() => {
|
|
1212
1212
|
throw new Error(
|
|
1213
1213
|
`Failed to connect via CDP to ${cdpUrl}. ` + (cdpUrl.includes("localhost") ? `Make sure the app is running with --remote-debugging-port=${cdpEndpoint}` : "Make sure the remote browser is accessible and the URL is correct.")
|
|
1214
1214
|
);
|
|
1215
1215
|
});
|
|
1216
1216
|
try {
|
|
1217
|
-
const contexts =
|
|
1217
|
+
const contexts = browser.contexts();
|
|
1218
1218
|
if (contexts.length === 0) {
|
|
1219
1219
|
throw new Error("No browser context found. Make sure the app has an open window.");
|
|
1220
1220
|
}
|
|
1221
|
-
const allPages = contexts.flatMap((context) => context.pages()).filter((
|
|
1221
|
+
const allPages = contexts.flatMap((context) => context.pages()).filter((page) => page.url());
|
|
1222
1222
|
if (allPages.length === 0) {
|
|
1223
1223
|
throw new Error("No page found. Make sure the app has loaded content.");
|
|
1224
1224
|
}
|
|
1225
|
-
this.browser =
|
|
1225
|
+
this.browser = browser;
|
|
1226
1226
|
this.cdpEndpoint = cdpEndpoint;
|
|
1227
1227
|
for (const context of contexts) {
|
|
1228
1228
|
context.setDefaultTimeout(1e4);
|
|
1229
1229
|
this.contexts.push(context);
|
|
1230
1230
|
this.setupContextTracking(context);
|
|
1231
1231
|
}
|
|
1232
|
-
for (const
|
|
1233
|
-
this.pages.push(
|
|
1234
|
-
this.setupPageTracking(
|
|
1232
|
+
for (const page of allPages) {
|
|
1233
|
+
this.pages.push(page);
|
|
1234
|
+
this.setupPageTracking(page);
|
|
1235
1235
|
}
|
|
1236
1236
|
this.activePageIndex = 0;
|
|
1237
1237
|
} catch (error) {
|
|
1238
|
-
await
|
|
1238
|
+
await browser.close().catch(() => {
|
|
1239
1239
|
});
|
|
1240
1240
|
throw error;
|
|
1241
1241
|
}
|
|
@@ -1243,22 +1243,22 @@ var BrowserManager = class {
|
|
|
1243
1243
|
/**
|
|
1244
1244
|
* Set up console, error, and close tracking for a page
|
|
1245
1245
|
*/
|
|
1246
|
-
setupPageTracking(
|
|
1247
|
-
|
|
1246
|
+
setupPageTracking(page) {
|
|
1247
|
+
page.on("console", (msg) => {
|
|
1248
1248
|
this.consoleMessages.push({
|
|
1249
1249
|
type: msg.type(),
|
|
1250
1250
|
text: msg.text(),
|
|
1251
1251
|
timestamp: Date.now()
|
|
1252
1252
|
});
|
|
1253
1253
|
});
|
|
1254
|
-
|
|
1254
|
+
page.on("pageerror", (error) => {
|
|
1255
1255
|
this.pageErrors.push({
|
|
1256
1256
|
message: error.message,
|
|
1257
1257
|
timestamp: Date.now()
|
|
1258
1258
|
});
|
|
1259
1259
|
});
|
|
1260
|
-
|
|
1261
|
-
const index = this.pages.indexOf(
|
|
1260
|
+
page.on("close", () => {
|
|
1261
|
+
const index = this.pages.indexOf(page);
|
|
1262
1262
|
if (index !== -1) {
|
|
1263
1263
|
this.pages.splice(index, 1);
|
|
1264
1264
|
if (this.activePageIndex >= this.pages.length) {
|
|
@@ -1272,12 +1272,12 @@ var BrowserManager = class {
|
|
|
1272
1272
|
* This handles pages created externally (e.g., via target="_blank" links, window.open)
|
|
1273
1273
|
*/
|
|
1274
1274
|
setupContextTracking(context) {
|
|
1275
|
-
context.on("page", (
|
|
1276
|
-
if (!this.pages.includes(
|
|
1277
|
-
this.pages.push(
|
|
1278
|
-
this.setupPageTracking(
|
|
1275
|
+
context.on("page", (page) => {
|
|
1276
|
+
if (!this.pages.includes(page)) {
|
|
1277
|
+
this.pages.push(page);
|
|
1278
|
+
this.setupPageTracking(page);
|
|
1279
1279
|
}
|
|
1280
|
-
const newIndex = this.pages.indexOf(
|
|
1280
|
+
const newIndex = this.pages.indexOf(page);
|
|
1281
1281
|
if (newIndex !== -1 && newIndex !== this.activePageIndex) {
|
|
1282
1282
|
this.activePageIndex = newIndex;
|
|
1283
1283
|
this.invalidateCDPSession().catch(() => {
|
|
@@ -1294,10 +1294,10 @@ var BrowserManager = class {
|
|
|
1294
1294
|
}
|
|
1295
1295
|
await this.invalidateCDPSession();
|
|
1296
1296
|
const context = this.contexts[0];
|
|
1297
|
-
const
|
|
1298
|
-
if (!this.pages.includes(
|
|
1299
|
-
this.pages.push(
|
|
1300
|
-
this.setupPageTracking(
|
|
1297
|
+
const page = await context.newPage();
|
|
1298
|
+
if (!this.pages.includes(page)) {
|
|
1299
|
+
this.pages.push(page);
|
|
1300
|
+
this.setupPageTracking(page);
|
|
1301
1301
|
}
|
|
1302
1302
|
this.activePageIndex = this.pages.length - 1;
|
|
1303
1303
|
return { index: this.activePageIndex, total: this.pages.length };
|
|
@@ -1315,10 +1315,10 @@ var BrowserManager = class {
|
|
|
1315
1315
|
context.setDefaultTimeout(6e4);
|
|
1316
1316
|
this.contexts.push(context);
|
|
1317
1317
|
this.setupContextTracking(context);
|
|
1318
|
-
const
|
|
1319
|
-
if (!this.pages.includes(
|
|
1320
|
-
this.pages.push(
|
|
1321
|
-
this.setupPageTracking(
|
|
1318
|
+
const page = await context.newPage();
|
|
1319
|
+
if (!this.pages.includes(page)) {
|
|
1320
|
+
this.pages.push(page);
|
|
1321
|
+
this.setupPageTracking(page);
|
|
1322
1322
|
}
|
|
1323
1323
|
this.activePageIndex = this.pages.length - 1;
|
|
1324
1324
|
return { index: this.activePageIndex, total: this.pages.length };
|
|
@@ -1348,10 +1348,10 @@ var BrowserManager = class {
|
|
|
1348
1348
|
await this.invalidateCDPSession();
|
|
1349
1349
|
}
|
|
1350
1350
|
this.activePageIndex = index;
|
|
1351
|
-
const
|
|
1351
|
+
const page = this.pages[index];
|
|
1352
1352
|
return {
|
|
1353
1353
|
index: this.activePageIndex,
|
|
1354
|
-
url:
|
|
1354
|
+
url: page.url(),
|
|
1355
1355
|
title: ""
|
|
1356
1356
|
// Title requires async, will be fetched separately
|
|
1357
1357
|
};
|
|
@@ -1370,8 +1370,8 @@ var BrowserManager = class {
|
|
|
1370
1370
|
if (targetIndex === this.activePageIndex) {
|
|
1371
1371
|
await this.invalidateCDPSession();
|
|
1372
1372
|
}
|
|
1373
|
-
const
|
|
1374
|
-
await
|
|
1373
|
+
const page = this.pages[targetIndex];
|
|
1374
|
+
await page.close();
|
|
1375
1375
|
this.pages.splice(targetIndex, 1);
|
|
1376
1376
|
if (this.activePageIndex >= this.pages.length) {
|
|
1377
1377
|
this.activePageIndex = this.pages.length - 1;
|
|
@@ -1385,10 +1385,10 @@ var BrowserManager = class {
|
|
|
1385
1385
|
*/
|
|
1386
1386
|
async listTabs() {
|
|
1387
1387
|
const tabs = await Promise.all(
|
|
1388
|
-
this.pages.map(async (
|
|
1388
|
+
this.pages.map(async (page, index) => ({
|
|
1389
1389
|
index,
|
|
1390
|
-
url:
|
|
1391
|
-
title: await
|
|
1390
|
+
url: page.url(),
|
|
1391
|
+
title: await page.title().catch(() => ""),
|
|
1392
1392
|
active: index === this.activePageIndex
|
|
1393
1393
|
}))
|
|
1394
1394
|
);
|
|
@@ -1402,9 +1402,9 @@ var BrowserManager = class {
|
|
|
1402
1402
|
if (this.cdpSession) {
|
|
1403
1403
|
return this.cdpSession;
|
|
1404
1404
|
}
|
|
1405
|
-
const
|
|
1406
|
-
const context =
|
|
1407
|
-
this.cdpSession = await context.newCDPSession(
|
|
1405
|
+
const page = this.getPage();
|
|
1406
|
+
const context = page.context();
|
|
1407
|
+
this.cdpSession = await context.newCDPSession(page);
|
|
1408
1408
|
return this.cdpSession;
|
|
1409
1409
|
}
|
|
1410
1410
|
/**
|
|
@@ -1692,8 +1692,8 @@ var BrowserManager = class {
|
|
|
1692
1692
|
this.browser = null;
|
|
1693
1693
|
}
|
|
1694
1694
|
} else {
|
|
1695
|
-
for (const
|
|
1696
|
-
await
|
|
1695
|
+
for (const page of this.pages) {
|
|
1696
|
+
await page.close().catch(() => {
|
|
1697
1697
|
});
|
|
1698
1698
|
}
|
|
1699
1699
|
for (const context of this.contexts) {
|
|
@@ -2096,8 +2096,8 @@ var IOSManager = class _IOSManager {
|
|
|
2096
2096
|
if (!this.browser) {
|
|
2097
2097
|
throw new Error("iOS browser not launched");
|
|
2098
2098
|
}
|
|
2099
|
-
const
|
|
2100
|
-
await
|
|
2099
|
+
const element = await this.getElement(selector);
|
|
2100
|
+
await element.click();
|
|
2101
2101
|
}
|
|
2102
2102
|
/**
|
|
2103
2103
|
* Alias for click (semantic clarity for touch)
|
|
@@ -2112,17 +2112,17 @@ var IOSManager = class _IOSManager {
|
|
|
2112
2112
|
if (!this.browser) {
|
|
2113
2113
|
throw new Error("iOS browser not launched");
|
|
2114
2114
|
}
|
|
2115
|
-
const
|
|
2115
|
+
const element = await this.getElement(selector);
|
|
2116
2116
|
if (options?.clear) {
|
|
2117
|
-
await
|
|
2117
|
+
await element.clearValue();
|
|
2118
2118
|
}
|
|
2119
2119
|
if (options?.delay && options.delay > 0) {
|
|
2120
2120
|
for (const char of text) {
|
|
2121
|
-
await
|
|
2121
|
+
await element.addValue(char);
|
|
2122
2122
|
await new Promise((r) => setTimeout(r, options.delay));
|
|
2123
2123
|
}
|
|
2124
2124
|
} else {
|
|
2125
|
-
await
|
|
2125
|
+
await element.addValue(text);
|
|
2126
2126
|
}
|
|
2127
2127
|
}
|
|
2128
2128
|
/**
|
|
@@ -2132,9 +2132,9 @@ var IOSManager = class _IOSManager {
|
|
|
2132
2132
|
if (!this.browser) {
|
|
2133
2133
|
throw new Error("iOS browser not launched");
|
|
2134
2134
|
}
|
|
2135
|
-
const
|
|
2136
|
-
await
|
|
2137
|
-
await
|
|
2135
|
+
const element = await this.getElement(selector);
|
|
2136
|
+
await element.clearValue();
|
|
2137
|
+
await element.setValue(value);
|
|
2138
2138
|
}
|
|
2139
2139
|
/**
|
|
2140
2140
|
* Get element by selector or ref
|
|
@@ -2224,12 +2224,12 @@ var IOSManager = class _IOSManager {
|
|
|
2224
2224
|
"DETAILS",
|
|
2225
2225
|
"SUMMARY"
|
|
2226
2226
|
]);
|
|
2227
|
-
function getXPath(
|
|
2228
|
-
if (
|
|
2229
|
-
return `//*[@id="${
|
|
2227
|
+
function getXPath(element) {
|
|
2228
|
+
if (element.id) {
|
|
2229
|
+
return `//*[@id="${element.id}"]`;
|
|
2230
2230
|
}
|
|
2231
2231
|
const parts = [];
|
|
2232
|
-
let current =
|
|
2232
|
+
let current = element;
|
|
2233
2233
|
while (current && current.nodeType === 1) {
|
|
2234
2234
|
let index = 1;
|
|
2235
2235
|
let sibling = current.previousElementSibling;
|
|
@@ -2245,36 +2245,36 @@ var IOSManager = class _IOSManager {
|
|
|
2245
2245
|
}
|
|
2246
2246
|
return "/" + parts.join("/");
|
|
2247
2247
|
}
|
|
2248
|
-
function getAccessibleName(
|
|
2249
|
-
const ariaLabel =
|
|
2248
|
+
function getAccessibleName(element) {
|
|
2249
|
+
const ariaLabel = element.getAttribute("aria-label");
|
|
2250
2250
|
if (ariaLabel) return ariaLabel;
|
|
2251
|
-
const tagName =
|
|
2251
|
+
const tagName = element.tagName;
|
|
2252
2252
|
if (tagName === "INPUT" || tagName === "TEXTAREA") {
|
|
2253
|
-
const id =
|
|
2253
|
+
const id = element.id;
|
|
2254
2254
|
if (id) {
|
|
2255
2255
|
const label = document.querySelector(`label[for="${id}"]`);
|
|
2256
2256
|
if (label) return label.textContent?.trim() || "";
|
|
2257
2257
|
}
|
|
2258
|
-
if (
|
|
2258
|
+
if (element.placeholder) return element.placeholder;
|
|
2259
2259
|
}
|
|
2260
2260
|
if (tagName === "BUTTON" || tagName === "A") {
|
|
2261
|
-
return
|
|
2261
|
+
return element.textContent?.trim() || "";
|
|
2262
2262
|
}
|
|
2263
|
-
const labelledBy =
|
|
2263
|
+
const labelledBy = element.getAttribute("aria-labelledby");
|
|
2264
2264
|
if (labelledBy) {
|
|
2265
2265
|
const labelElement = document.getElementById(labelledBy);
|
|
2266
2266
|
if (labelElement) return labelElement.textContent?.trim() || "";
|
|
2267
2267
|
}
|
|
2268
|
-
return
|
|
2268
|
+
return element.textContent?.trim().slice(0, 50) || "";
|
|
2269
2269
|
}
|
|
2270
|
-
function getRole(
|
|
2271
|
-
const role =
|
|
2270
|
+
function getRole(element) {
|
|
2271
|
+
const role = element.getAttribute("role");
|
|
2272
2272
|
if (role) return role;
|
|
2273
|
-
const tag =
|
|
2274
|
-
if (tag === "A" &&
|
|
2273
|
+
const tag = element.tagName;
|
|
2274
|
+
if (tag === "A" && element.hasAttribute("href")) return "link";
|
|
2275
2275
|
if (tag === "BUTTON") return "button";
|
|
2276
2276
|
if (tag === "INPUT") {
|
|
2277
|
-
const type =
|
|
2277
|
+
const type = element.type;
|
|
2278
2278
|
if (type === "checkbox") return "checkbox";
|
|
2279
2279
|
if (type === "radio") return "radio";
|
|
2280
2280
|
if (type === "text" || type === "email" || type === "password" || type === "search")
|
|
@@ -2292,18 +2292,18 @@ var IOSManager = class _IOSManager {
|
|
|
2292
2292
|
if (tag === "FOOTER") return "contentinfo";
|
|
2293
2293
|
return null;
|
|
2294
2294
|
}
|
|
2295
|
-
function traverse(
|
|
2295
|
+
function traverse(element, depth) {
|
|
2296
2296
|
if (depth > 10) return null;
|
|
2297
|
-
const tag =
|
|
2298
|
-
const role = getRole(
|
|
2299
|
-
const name = getAccessibleName(
|
|
2297
|
+
const tag = element.tagName;
|
|
2298
|
+
const role = getRole(element);
|
|
2299
|
+
const name = getAccessibleName(element);
|
|
2300
2300
|
const isInteractive = INTERACTIVE_TAGS.has(tag) || role !== null && INTERACTIVE_ROLES2.has(role);
|
|
2301
|
-
const style = window.getComputedStyle(
|
|
2301
|
+
const style = window.getComputedStyle(element);
|
|
2302
2302
|
if (style.display === "none" || style.visibility === "hidden") {
|
|
2303
2303
|
return null;
|
|
2304
2304
|
}
|
|
2305
2305
|
const children = [];
|
|
2306
|
-
for (const child of
|
|
2306
|
+
for (const child of element.children) {
|
|
2307
2307
|
const childInfo = traverse(child, depth + 1);
|
|
2308
2308
|
if (childInfo) {
|
|
2309
2309
|
children.push(childInfo);
|
|
@@ -2316,9 +2316,9 @@ var IOSManager = class _IOSManager {
|
|
|
2316
2316
|
tag,
|
|
2317
2317
|
role,
|
|
2318
2318
|
name,
|
|
2319
|
-
text:
|
|
2319
|
+
text: element.textContent?.trim().slice(0, 100) || "",
|
|
2320
2320
|
isInteractive,
|
|
2321
|
-
xpath: getXPath(
|
|
2321
|
+
xpath: getXPath(element),
|
|
2322
2322
|
children
|
|
2323
2323
|
};
|
|
2324
2324
|
}
|
|
@@ -2372,8 +2372,8 @@ var IOSManager = class _IOSManager {
|
|
|
2372
2372
|
}
|
|
2373
2373
|
const amount = options?.amount ?? 300;
|
|
2374
2374
|
if (options?.selector) {
|
|
2375
|
-
const
|
|
2376
|
-
await
|
|
2375
|
+
const element = await this.getElement(options.selector);
|
|
2376
|
+
await element.scrollIntoView();
|
|
2377
2377
|
return;
|
|
2378
2378
|
}
|
|
2379
2379
|
let deltaX = options?.x ?? 0;
|
|
@@ -2421,16 +2421,16 @@ var IOSManager = class _IOSManager {
|
|
|
2421
2421
|
/**
|
|
2422
2422
|
* Execute JavaScript
|
|
2423
2423
|
*/
|
|
2424
|
-
async evaluate(
|
|
2424
|
+
async evaluate(script, ...args) {
|
|
2425
2425
|
if (!this.browser) {
|
|
2426
2426
|
throw new Error("iOS browser not launched");
|
|
2427
2427
|
}
|
|
2428
2428
|
const result = await this.browser.execute(
|
|
2429
2429
|
function(code, evalArgs) {
|
|
2430
|
-
const
|
|
2431
|
-
return
|
|
2430
|
+
const fn = new Function(...evalArgs.map((_, i) => `arg${i}`), code);
|
|
2431
|
+
return fn(...evalArgs);
|
|
2432
2432
|
},
|
|
2433
|
-
|
|
2433
|
+
script.includes("return") ? script : `return (${script})`,
|
|
2434
2434
|
args
|
|
2435
2435
|
);
|
|
2436
2436
|
return result;
|
|
@@ -2444,20 +2444,20 @@ var IOSManager = class _IOSManager {
|
|
|
2444
2444
|
}
|
|
2445
2445
|
const timeout = options.timeout ?? 3e4;
|
|
2446
2446
|
if (options.selector) {
|
|
2447
|
-
const
|
|
2447
|
+
const element = await this.getElement(options.selector);
|
|
2448
2448
|
switch (options.state) {
|
|
2449
2449
|
case "detached":
|
|
2450
|
-
await
|
|
2450
|
+
await element.waitForExist({ timeout, reverse: true });
|
|
2451
2451
|
break;
|
|
2452
2452
|
case "hidden":
|
|
2453
|
-
await
|
|
2453
|
+
await element.waitForDisplayed({ timeout, reverse: true });
|
|
2454
2454
|
break;
|
|
2455
2455
|
case "visible":
|
|
2456
|
-
await
|
|
2456
|
+
await element.waitForDisplayed({ timeout });
|
|
2457
2457
|
break;
|
|
2458
2458
|
case "attached":
|
|
2459
2459
|
default:
|
|
2460
|
-
await
|
|
2460
|
+
await element.waitForExist({ timeout });
|
|
2461
2461
|
break;
|
|
2462
2462
|
}
|
|
2463
2463
|
} else {
|
|
@@ -2492,8 +2492,8 @@ var IOSManager = class _IOSManager {
|
|
|
2492
2492
|
if (!this.browser) {
|
|
2493
2493
|
throw new Error("iOS browser not launched");
|
|
2494
2494
|
}
|
|
2495
|
-
const
|
|
2496
|
-
await
|
|
2495
|
+
const element = await this.getElement(selector);
|
|
2496
|
+
await element.scrollIntoView();
|
|
2497
2497
|
}
|
|
2498
2498
|
/**
|
|
2499
2499
|
* Get page content (HTML)
|
|
@@ -2503,8 +2503,8 @@ var IOSManager = class _IOSManager {
|
|
|
2503
2503
|
throw new Error("iOS browser not launched");
|
|
2504
2504
|
}
|
|
2505
2505
|
if (selector) {
|
|
2506
|
-
const
|
|
2507
|
-
return
|
|
2506
|
+
const element = await this.getElement(selector);
|
|
2507
|
+
return element.getHTML();
|
|
2508
2508
|
}
|
|
2509
2509
|
return this.browser.getPageSource();
|
|
2510
2510
|
}
|
|
@@ -2515,8 +2515,8 @@ var IOSManager = class _IOSManager {
|
|
|
2515
2515
|
if (!this.browser) {
|
|
2516
2516
|
throw new Error("iOS browser not launched");
|
|
2517
2517
|
}
|
|
2518
|
-
const
|
|
2519
|
-
return
|
|
2518
|
+
const element = await this.getElement(selector);
|
|
2519
|
+
return element.getText();
|
|
2520
2520
|
}
|
|
2521
2521
|
/**
|
|
2522
2522
|
* Get attribute value
|
|
@@ -2525,8 +2525,8 @@ var IOSManager = class _IOSManager {
|
|
|
2525
2525
|
if (!this.browser) {
|
|
2526
2526
|
throw new Error("iOS browser not launched");
|
|
2527
2527
|
}
|
|
2528
|
-
const
|
|
2529
|
-
return
|
|
2528
|
+
const element = await this.getElement(selector);
|
|
2529
|
+
return element.getAttribute(attribute);
|
|
2530
2530
|
}
|
|
2531
2531
|
/**
|
|
2532
2532
|
* Check if element is visible
|
|
@@ -2536,8 +2536,8 @@ var IOSManager = class _IOSManager {
|
|
|
2536
2536
|
throw new Error("iOS browser not launched");
|
|
2537
2537
|
}
|
|
2538
2538
|
try {
|
|
2539
|
-
const
|
|
2540
|
-
return
|
|
2539
|
+
const element = await this.getElement(selector);
|
|
2540
|
+
return element.isDisplayed();
|
|
2541
2541
|
} catch {
|
|
2542
2542
|
return false;
|
|
2543
2543
|
}
|
|
@@ -2549,8 +2549,8 @@ var IOSManager = class _IOSManager {
|
|
|
2549
2549
|
if (!this.browser) {
|
|
2550
2550
|
throw new Error("iOS browser not launched");
|
|
2551
2551
|
}
|
|
2552
|
-
const
|
|
2553
|
-
return
|
|
2552
|
+
const element = await this.getElement(selector);
|
|
2553
|
+
return element.isEnabled();
|
|
2554
2554
|
}
|
|
2555
2555
|
/**
|
|
2556
2556
|
* Navigate back
|
|
@@ -2586,10 +2586,10 @@ var IOSManager = class _IOSManager {
|
|
|
2586
2586
|
if (!this.browser) {
|
|
2587
2587
|
throw new Error("iOS browser not launched");
|
|
2588
2588
|
}
|
|
2589
|
-
const
|
|
2589
|
+
const element = await this.getElement(selector);
|
|
2590
2590
|
const valueArray = Array.isArray(values) ? values : [values];
|
|
2591
2591
|
for (const value of valueArray) {
|
|
2592
|
-
await
|
|
2592
|
+
await element.selectByAttribute("value", value);
|
|
2593
2593
|
}
|
|
2594
2594
|
}
|
|
2595
2595
|
/**
|
|
@@ -2599,10 +2599,10 @@ var IOSManager = class _IOSManager {
|
|
|
2599
2599
|
if (!this.browser) {
|
|
2600
2600
|
throw new Error("iOS browser not launched");
|
|
2601
2601
|
}
|
|
2602
|
-
const
|
|
2603
|
-
const isChecked = await
|
|
2602
|
+
const element = await this.getElement(selector);
|
|
2603
|
+
const isChecked = await element.isSelected();
|
|
2604
2604
|
if (!isChecked) {
|
|
2605
|
-
await
|
|
2605
|
+
await element.click();
|
|
2606
2606
|
}
|
|
2607
2607
|
}
|
|
2608
2608
|
/**
|
|
@@ -2612,10 +2612,10 @@ var IOSManager = class _IOSManager {
|
|
|
2612
2612
|
if (!this.browser) {
|
|
2613
2613
|
throw new Error("iOS browser not launched");
|
|
2614
2614
|
}
|
|
2615
|
-
const
|
|
2616
|
-
const isChecked = await
|
|
2615
|
+
const element = await this.getElement(selector);
|
|
2616
|
+
const isChecked = await element.isSelected();
|
|
2617
2617
|
if (isChecked) {
|
|
2618
|
-
await
|
|
2618
|
+
await element.click();
|
|
2619
2619
|
}
|
|
2620
2620
|
}
|
|
2621
2621
|
/**
|
|
@@ -2625,10 +2625,10 @@ var IOSManager = class _IOSManager {
|
|
|
2625
2625
|
if (!this.browser) {
|
|
2626
2626
|
throw new Error("iOS browser not launched");
|
|
2627
2627
|
}
|
|
2628
|
-
const
|
|
2629
|
-
await this.browser.execute(function(
|
|
2630
|
-
|
|
2631
|
-
},
|
|
2628
|
+
const element = await this.getElement(selector);
|
|
2629
|
+
await this.browser.execute(function(el) {
|
|
2630
|
+
el.focus();
|
|
2631
|
+
}, element);
|
|
2632
2632
|
}
|
|
2633
2633
|
/**
|
|
2634
2634
|
* Clear input field
|
|
@@ -2637,8 +2637,8 @@ var IOSManager = class _IOSManager {
|
|
|
2637
2637
|
if (!this.browser) {
|
|
2638
2638
|
throw new Error("iOS browser not launched");
|
|
2639
2639
|
}
|
|
2640
|
-
const
|
|
2641
|
-
await
|
|
2640
|
+
const element = await this.getElement(selector);
|
|
2641
|
+
await element.clearValue();
|
|
2642
2642
|
}
|
|
2643
2643
|
/**
|
|
2644
2644
|
* Get element count
|
|
@@ -2647,8 +2647,8 @@ var IOSManager = class _IOSManager {
|
|
|
2647
2647
|
if (!this.browser) {
|
|
2648
2648
|
throw new Error("iOS browser not launched");
|
|
2649
2649
|
}
|
|
2650
|
-
const
|
|
2651
|
-
return
|
|
2650
|
+
const elements = await this.browser.$$(selector);
|
|
2651
|
+
return elements.length;
|
|
2652
2652
|
}
|
|
2653
2653
|
/**
|
|
2654
2654
|
* Get bounding box
|
|
@@ -2658,9 +2658,9 @@ var IOSManager = class _IOSManager {
|
|
|
2658
2658
|
throw new Error("iOS browser not launched");
|
|
2659
2659
|
}
|
|
2660
2660
|
try {
|
|
2661
|
-
const
|
|
2662
|
-
const location = await
|
|
2663
|
-
const size = await
|
|
2661
|
+
const element = await this.getElement(selector);
|
|
2662
|
+
const location = await element.getLocation();
|
|
2663
|
+
const size = await element.getSize();
|
|
2664
2664
|
return {
|
|
2665
2665
|
x: location.x,
|
|
2666
2666
|
y: location.y,
|
|
@@ -3548,357 +3548,357 @@ function toAIFriendlyError(error, selector) {
|
|
|
3548
3548
|
}
|
|
3549
3549
|
return error instanceof Error ? error : new Error(message);
|
|
3550
3550
|
}
|
|
3551
|
-
async function executeCommand(
|
|
3551
|
+
async function executeCommand(command, browser) {
|
|
3552
3552
|
try {
|
|
3553
|
-
switch (
|
|
3553
|
+
switch (command.action) {
|
|
3554
3554
|
case "launch":
|
|
3555
|
-
return await handleLaunch(
|
|
3555
|
+
return await handleLaunch(command, browser);
|
|
3556
3556
|
case "navigate":
|
|
3557
|
-
return await handleNavigate(
|
|
3557
|
+
return await handleNavigate(command, browser);
|
|
3558
3558
|
case "click":
|
|
3559
|
-
return await handleClick(
|
|
3559
|
+
return await handleClick(command, browser);
|
|
3560
3560
|
case "type":
|
|
3561
|
-
return await handleType(
|
|
3561
|
+
return await handleType(command, browser);
|
|
3562
3562
|
case "fill":
|
|
3563
|
-
return await handleFill(
|
|
3563
|
+
return await handleFill(command, browser);
|
|
3564
3564
|
case "check":
|
|
3565
|
-
return await handleCheck(
|
|
3565
|
+
return await handleCheck(command, browser);
|
|
3566
3566
|
case "uncheck":
|
|
3567
|
-
return await handleUncheck(
|
|
3567
|
+
return await handleUncheck(command, browser);
|
|
3568
3568
|
case "upload":
|
|
3569
|
-
return await handleUpload(
|
|
3569
|
+
return await handleUpload(command, browser);
|
|
3570
3570
|
case "dblclick":
|
|
3571
|
-
return await handleDoubleClick(
|
|
3571
|
+
return await handleDoubleClick(command, browser);
|
|
3572
3572
|
case "focus":
|
|
3573
|
-
return await handleFocus(
|
|
3573
|
+
return await handleFocus(command, browser);
|
|
3574
3574
|
case "drag":
|
|
3575
|
-
return await handleDrag(
|
|
3575
|
+
return await handleDrag(command, browser);
|
|
3576
3576
|
case "frame":
|
|
3577
|
-
return await handleFrame(
|
|
3577
|
+
return await handleFrame(command, browser);
|
|
3578
3578
|
case "mainframe":
|
|
3579
|
-
return await handleMainFrame(
|
|
3579
|
+
return await handleMainFrame(command, browser);
|
|
3580
3580
|
case "getbyrole":
|
|
3581
|
-
return await handleGetByRole(
|
|
3581
|
+
return await handleGetByRole(command, browser);
|
|
3582
3582
|
case "getbytext":
|
|
3583
|
-
return await handleGetByText(
|
|
3583
|
+
return await handleGetByText(command, browser);
|
|
3584
3584
|
case "getbylabel":
|
|
3585
|
-
return await handleGetByLabel(
|
|
3585
|
+
return await handleGetByLabel(command, browser);
|
|
3586
3586
|
case "getbyplaceholder":
|
|
3587
|
-
return await handleGetByPlaceholder(
|
|
3587
|
+
return await handleGetByPlaceholder(command, browser);
|
|
3588
3588
|
case "press":
|
|
3589
|
-
return await handlePress(
|
|
3589
|
+
return await handlePress(command, browser);
|
|
3590
3590
|
case "screenshot":
|
|
3591
|
-
return await handleScreenshot(
|
|
3591
|
+
return await handleScreenshot(command, browser);
|
|
3592
3592
|
case "snapshot":
|
|
3593
|
-
return await handleSnapshot(
|
|
3593
|
+
return await handleSnapshot(command, browser);
|
|
3594
3594
|
case "evaluate":
|
|
3595
|
-
return await handleEvaluate(
|
|
3595
|
+
return await handleEvaluate(command, browser);
|
|
3596
3596
|
case "wait":
|
|
3597
|
-
return await handleWait(
|
|
3597
|
+
return await handleWait(command, browser);
|
|
3598
3598
|
case "scroll":
|
|
3599
|
-
return await handleScroll(
|
|
3599
|
+
return await handleScroll(command, browser);
|
|
3600
3600
|
case "select":
|
|
3601
|
-
return await handleSelect(
|
|
3601
|
+
return await handleSelect(command, browser);
|
|
3602
3602
|
case "hover":
|
|
3603
|
-
return await handleHover(
|
|
3603
|
+
return await handleHover(command, browser);
|
|
3604
3604
|
case "content":
|
|
3605
|
-
return await handleContent(
|
|
3605
|
+
return await handleContent(command, browser);
|
|
3606
3606
|
case "close":
|
|
3607
|
-
return await handleClose(
|
|
3607
|
+
return await handleClose(command, browser);
|
|
3608
3608
|
case "tab_new":
|
|
3609
|
-
return await handleTabNew(
|
|
3609
|
+
return await handleTabNew(command, browser);
|
|
3610
3610
|
case "tab_list":
|
|
3611
|
-
return await handleTabList(
|
|
3611
|
+
return await handleTabList(command, browser);
|
|
3612
3612
|
case "tab_switch":
|
|
3613
|
-
return await handleTabSwitch(
|
|
3613
|
+
return await handleTabSwitch(command, browser);
|
|
3614
3614
|
case "tab_close":
|
|
3615
|
-
return await handleTabClose(
|
|
3615
|
+
return await handleTabClose(command, browser);
|
|
3616
3616
|
case "window_new":
|
|
3617
|
-
return await handleWindowNew(
|
|
3617
|
+
return await handleWindowNew(command, browser);
|
|
3618
3618
|
case "cookies_get":
|
|
3619
|
-
return await handleCookiesGet(
|
|
3619
|
+
return await handleCookiesGet(command, browser);
|
|
3620
3620
|
case "cookies_set":
|
|
3621
|
-
return await handleCookiesSet(
|
|
3621
|
+
return await handleCookiesSet(command, browser);
|
|
3622
3622
|
case "cookies_clear":
|
|
3623
|
-
return await handleCookiesClear(
|
|
3623
|
+
return await handleCookiesClear(command, browser);
|
|
3624
3624
|
case "storage_get":
|
|
3625
|
-
return await handleStorageGet(
|
|
3625
|
+
return await handleStorageGet(command, browser);
|
|
3626
3626
|
case "storage_set":
|
|
3627
|
-
return await handleStorageSet(
|
|
3627
|
+
return await handleStorageSet(command, browser);
|
|
3628
3628
|
case "storage_clear":
|
|
3629
|
-
return await handleStorageClear(
|
|
3629
|
+
return await handleStorageClear(command, browser);
|
|
3630
3630
|
case "dialog":
|
|
3631
|
-
return await handleDialog(
|
|
3631
|
+
return await handleDialog(command, browser);
|
|
3632
3632
|
case "pdf":
|
|
3633
|
-
return await handlePdf(
|
|
3633
|
+
return await handlePdf(command, browser);
|
|
3634
3634
|
case "route":
|
|
3635
|
-
return await handleRoute(
|
|
3635
|
+
return await handleRoute(command, browser);
|
|
3636
3636
|
case "unroute":
|
|
3637
|
-
return await handleUnroute(
|
|
3637
|
+
return await handleUnroute(command, browser);
|
|
3638
3638
|
case "requests":
|
|
3639
|
-
return await handleRequests(
|
|
3639
|
+
return await handleRequests(command, browser);
|
|
3640
3640
|
case "download":
|
|
3641
|
-
return await handleDownload(
|
|
3641
|
+
return await handleDownload(command, browser);
|
|
3642
3642
|
case "geolocation":
|
|
3643
|
-
return await handleGeolocation(
|
|
3643
|
+
return await handleGeolocation(command, browser);
|
|
3644
3644
|
case "permissions":
|
|
3645
|
-
return await handlePermissions(
|
|
3645
|
+
return await handlePermissions(command, browser);
|
|
3646
3646
|
case "viewport":
|
|
3647
|
-
return await handleViewport(
|
|
3647
|
+
return await handleViewport(command, browser);
|
|
3648
3648
|
case "useragent":
|
|
3649
|
-
return await handleUserAgent(
|
|
3649
|
+
return await handleUserAgent(command, browser);
|
|
3650
3650
|
case "device":
|
|
3651
|
-
return await handleDevice(
|
|
3651
|
+
return await handleDevice(command, browser);
|
|
3652
3652
|
case "back":
|
|
3653
|
-
return await handleBack(
|
|
3653
|
+
return await handleBack(command, browser);
|
|
3654
3654
|
case "forward":
|
|
3655
|
-
return await handleForward(
|
|
3655
|
+
return await handleForward(command, browser);
|
|
3656
3656
|
case "reload":
|
|
3657
|
-
return await handleReload(
|
|
3657
|
+
return await handleReload(command, browser);
|
|
3658
3658
|
case "url":
|
|
3659
|
-
return await handleUrl(
|
|
3659
|
+
return await handleUrl(command, browser);
|
|
3660
3660
|
case "title":
|
|
3661
|
-
return await handleTitle(
|
|
3661
|
+
return await handleTitle(command, browser);
|
|
3662
3662
|
case "getattribute":
|
|
3663
|
-
return await handleGetAttribute(
|
|
3663
|
+
return await handleGetAttribute(command, browser);
|
|
3664
3664
|
case "gettext":
|
|
3665
|
-
return await handleGetText(
|
|
3665
|
+
return await handleGetText(command, browser);
|
|
3666
3666
|
case "isvisible":
|
|
3667
|
-
return await handleIsVisible(
|
|
3667
|
+
return await handleIsVisible(command, browser);
|
|
3668
3668
|
case "isenabled":
|
|
3669
|
-
return await handleIsEnabled(
|
|
3669
|
+
return await handleIsEnabled(command, browser);
|
|
3670
3670
|
case "ischecked":
|
|
3671
|
-
return await handleIsChecked(
|
|
3671
|
+
return await handleIsChecked(command, browser);
|
|
3672
3672
|
case "count":
|
|
3673
|
-
return await handleCount(
|
|
3673
|
+
return await handleCount(command, browser);
|
|
3674
3674
|
case "boundingbox":
|
|
3675
|
-
return await handleBoundingBox(
|
|
3675
|
+
return await handleBoundingBox(command, browser);
|
|
3676
3676
|
case "styles":
|
|
3677
|
-
return await handleStyles(
|
|
3677
|
+
return await handleStyles(command, browser);
|
|
3678
3678
|
case "video_start":
|
|
3679
|
-
return await handleVideoStart(
|
|
3679
|
+
return await handleVideoStart(command, browser);
|
|
3680
3680
|
case "video_stop":
|
|
3681
|
-
return await handleVideoStop(
|
|
3681
|
+
return await handleVideoStop(command, browser);
|
|
3682
3682
|
case "trace_start":
|
|
3683
|
-
return await handleTraceStart(
|
|
3683
|
+
return await handleTraceStart(command, browser);
|
|
3684
3684
|
case "trace_stop":
|
|
3685
|
-
return await handleTraceStop(
|
|
3685
|
+
return await handleTraceStop(command, browser);
|
|
3686
3686
|
case "har_start":
|
|
3687
|
-
return await handleHarStart(
|
|
3687
|
+
return await handleHarStart(command, browser);
|
|
3688
3688
|
case "har_stop":
|
|
3689
|
-
return await handleHarStop(
|
|
3689
|
+
return await handleHarStop(command, browser);
|
|
3690
3690
|
case "state_save":
|
|
3691
|
-
return await handleStateSave(
|
|
3691
|
+
return await handleStateSave(command, browser);
|
|
3692
3692
|
case "state_load":
|
|
3693
|
-
return await handleStateLoad(
|
|
3693
|
+
return await handleStateLoad(command, browser);
|
|
3694
3694
|
case "console":
|
|
3695
|
-
return await handleConsole(
|
|
3695
|
+
return await handleConsole(command, browser);
|
|
3696
3696
|
case "errors":
|
|
3697
|
-
return await handleErrors(
|
|
3697
|
+
return await handleErrors(command, browser);
|
|
3698
3698
|
case "keyboard":
|
|
3699
|
-
return await handleKeyboard(
|
|
3699
|
+
return await handleKeyboard(command, browser);
|
|
3700
3700
|
case "wheel":
|
|
3701
|
-
return await handleWheel(
|
|
3701
|
+
return await handleWheel(command, browser);
|
|
3702
3702
|
case "tap":
|
|
3703
|
-
return await handleTap(
|
|
3703
|
+
return await handleTap(command, browser);
|
|
3704
3704
|
case "clipboard":
|
|
3705
|
-
return await handleClipboard(
|
|
3705
|
+
return await handleClipboard(command, browser);
|
|
3706
3706
|
case "highlight":
|
|
3707
|
-
return await handleHighlight(
|
|
3707
|
+
return await handleHighlight(command, browser);
|
|
3708
3708
|
case "clear":
|
|
3709
|
-
return await handleClear(
|
|
3709
|
+
return await handleClear(command, browser);
|
|
3710
3710
|
case "selectall":
|
|
3711
|
-
return await handleSelectAll(
|
|
3711
|
+
return await handleSelectAll(command, browser);
|
|
3712
3712
|
case "innertext":
|
|
3713
|
-
return await handleInnerText(
|
|
3713
|
+
return await handleInnerText(command, browser);
|
|
3714
3714
|
case "innerhtml":
|
|
3715
|
-
return await handleInnerHtml(
|
|
3715
|
+
return await handleInnerHtml(command, browser);
|
|
3716
3716
|
case "inputvalue":
|
|
3717
|
-
return await handleInputValue(
|
|
3717
|
+
return await handleInputValue(command, browser);
|
|
3718
3718
|
case "setvalue":
|
|
3719
|
-
return await handleSetValue(
|
|
3719
|
+
return await handleSetValue(command, browser);
|
|
3720
3720
|
case "dispatch":
|
|
3721
|
-
return await handleDispatch(
|
|
3721
|
+
return await handleDispatch(command, browser);
|
|
3722
3722
|
case "evalhandle":
|
|
3723
|
-
return await handleEvalHandle(
|
|
3723
|
+
return await handleEvalHandle(command, browser);
|
|
3724
3724
|
case "expose":
|
|
3725
|
-
return await handleExpose(
|
|
3725
|
+
return await handleExpose(command, browser);
|
|
3726
3726
|
case "addscript":
|
|
3727
|
-
return await handleAddScript(
|
|
3727
|
+
return await handleAddScript(command, browser);
|
|
3728
3728
|
case "addstyle":
|
|
3729
|
-
return await handleAddStyle(
|
|
3729
|
+
return await handleAddStyle(command, browser);
|
|
3730
3730
|
case "emulatemedia":
|
|
3731
|
-
return await handleEmulateMedia(
|
|
3731
|
+
return await handleEmulateMedia(command, browser);
|
|
3732
3732
|
case "offline":
|
|
3733
|
-
return await handleOffline(
|
|
3733
|
+
return await handleOffline(command, browser);
|
|
3734
3734
|
case "headers":
|
|
3735
|
-
return await handleHeaders(
|
|
3735
|
+
return await handleHeaders(command, browser);
|
|
3736
3736
|
case "pause":
|
|
3737
|
-
return await handlePause(
|
|
3737
|
+
return await handlePause(command, browser);
|
|
3738
3738
|
case "getbyalttext":
|
|
3739
|
-
return await handleGetByAltText(
|
|
3739
|
+
return await handleGetByAltText(command, browser);
|
|
3740
3740
|
case "getbytitle":
|
|
3741
|
-
return await handleGetByTitle(
|
|
3741
|
+
return await handleGetByTitle(command, browser);
|
|
3742
3742
|
case "getbytestid":
|
|
3743
|
-
return await handleGetByTestId(
|
|
3743
|
+
return await handleGetByTestId(command, browser);
|
|
3744
3744
|
case "nth":
|
|
3745
|
-
return await handleNth(
|
|
3745
|
+
return await handleNth(command, browser);
|
|
3746
3746
|
case "waitforurl":
|
|
3747
|
-
return await handleWaitForUrl(
|
|
3747
|
+
return await handleWaitForUrl(command, browser);
|
|
3748
3748
|
case "waitforloadstate":
|
|
3749
|
-
return await handleWaitForLoadState(
|
|
3749
|
+
return await handleWaitForLoadState(command, browser);
|
|
3750
3750
|
case "setcontent":
|
|
3751
|
-
return await handleSetContent(
|
|
3751
|
+
return await handleSetContent(command, browser);
|
|
3752
3752
|
case "timezone":
|
|
3753
|
-
return await handleTimezone(
|
|
3753
|
+
return await handleTimezone(command, browser);
|
|
3754
3754
|
case "locale":
|
|
3755
|
-
return await handleLocale(
|
|
3755
|
+
return await handleLocale(command, browser);
|
|
3756
3756
|
case "credentials":
|
|
3757
|
-
return await handleCredentials(
|
|
3757
|
+
return await handleCredentials(command, browser);
|
|
3758
3758
|
case "mousemove":
|
|
3759
|
-
return await handleMouseMove(
|
|
3759
|
+
return await handleMouseMove(command, browser);
|
|
3760
3760
|
case "mousedown":
|
|
3761
|
-
return await handleMouseDown(
|
|
3761
|
+
return await handleMouseDown(command, browser);
|
|
3762
3762
|
case "mouseup":
|
|
3763
|
-
return await handleMouseUp(
|
|
3763
|
+
return await handleMouseUp(command, browser);
|
|
3764
3764
|
case "bringtofront":
|
|
3765
|
-
return await handleBringToFront(
|
|
3765
|
+
return await handleBringToFront(command, browser);
|
|
3766
3766
|
case "waitforfunction":
|
|
3767
|
-
return await handleWaitForFunction(
|
|
3767
|
+
return await handleWaitForFunction(command, browser);
|
|
3768
3768
|
case "scrollintoview":
|
|
3769
|
-
return await handleScrollIntoView(
|
|
3769
|
+
return await handleScrollIntoView(command, browser);
|
|
3770
3770
|
case "addinitscript":
|
|
3771
|
-
return await handleAddInitScript(
|
|
3771
|
+
return await handleAddInitScript(command, browser);
|
|
3772
3772
|
case "keydown":
|
|
3773
|
-
return await handleKeyDown(
|
|
3773
|
+
return await handleKeyDown(command, browser);
|
|
3774
3774
|
case "keyup":
|
|
3775
|
-
return await handleKeyUp(
|
|
3775
|
+
return await handleKeyUp(command, browser);
|
|
3776
3776
|
case "inserttext":
|
|
3777
|
-
return await handleInsertText(
|
|
3777
|
+
return await handleInsertText(command, browser);
|
|
3778
3778
|
case "multiselect":
|
|
3779
|
-
return await handleMultiSelect(
|
|
3779
|
+
return await handleMultiSelect(command, browser);
|
|
3780
3780
|
case "waitfordownload":
|
|
3781
|
-
return await handleWaitForDownload(
|
|
3781
|
+
return await handleWaitForDownload(command, browser);
|
|
3782
3782
|
case "responsebody":
|
|
3783
|
-
return await handleResponseBody(
|
|
3783
|
+
return await handleResponseBody(command, browser);
|
|
3784
3784
|
case "screencast_start":
|
|
3785
|
-
return await handleScreencastStart(
|
|
3785
|
+
return await handleScreencastStart(command, browser);
|
|
3786
3786
|
case "screencast_stop":
|
|
3787
|
-
return await handleScreencastStop(
|
|
3787
|
+
return await handleScreencastStop(command, browser);
|
|
3788
3788
|
case "input_mouse":
|
|
3789
|
-
return await handleInputMouse(
|
|
3789
|
+
return await handleInputMouse(command, browser);
|
|
3790
3790
|
case "input_keyboard":
|
|
3791
|
-
return await handleInputKeyboard(
|
|
3791
|
+
return await handleInputKeyboard(command, browser);
|
|
3792
3792
|
case "input_touch":
|
|
3793
|
-
return await handleInputTouch(
|
|
3793
|
+
return await handleInputTouch(command, browser);
|
|
3794
3794
|
case "recording_start":
|
|
3795
|
-
return await handleRecordingStart(
|
|
3795
|
+
return await handleRecordingStart(command, browser);
|
|
3796
3796
|
case "recording_stop":
|
|
3797
|
-
return await handleRecordingStop(
|
|
3797
|
+
return await handleRecordingStop(command, browser);
|
|
3798
3798
|
case "recording_restart":
|
|
3799
|
-
return await handleRecordingRestart(
|
|
3799
|
+
return await handleRecordingRestart(command, browser);
|
|
3800
3800
|
default: {
|
|
3801
|
-
const unknownCommand =
|
|
3801
|
+
const unknownCommand = command;
|
|
3802
3802
|
return errorResponse(unknownCommand.id, `Unknown action: ${unknownCommand.action}`);
|
|
3803
3803
|
}
|
|
3804
3804
|
}
|
|
3805
3805
|
} catch (error) {
|
|
3806
3806
|
const message = error instanceof Error ? error.message : String(error);
|
|
3807
|
-
return errorResponse(
|
|
3807
|
+
return errorResponse(command.id, message);
|
|
3808
3808
|
}
|
|
3809
3809
|
}
|
|
3810
|
-
async function handleLaunch(
|
|
3811
|
-
await
|
|
3812
|
-
return successResponse(
|
|
3810
|
+
async function handleLaunch(command, browser) {
|
|
3811
|
+
await browser.launch(command);
|
|
3812
|
+
return successResponse(command.id, { launched: true });
|
|
3813
3813
|
}
|
|
3814
|
-
async function handleNavigate(
|
|
3815
|
-
const
|
|
3816
|
-
if (
|
|
3817
|
-
await
|
|
3814
|
+
async function handleNavigate(command, browser) {
|
|
3815
|
+
const page = browser.getPage();
|
|
3816
|
+
if (command.headers && Object.keys(command.headers).length > 0) {
|
|
3817
|
+
await browser.setScopedHeaders(command.url, command.headers);
|
|
3818
3818
|
}
|
|
3819
|
-
await
|
|
3820
|
-
waitUntil:
|
|
3819
|
+
await page.goto(command.url, {
|
|
3820
|
+
waitUntil: command.waitUntil ?? "load"
|
|
3821
3821
|
});
|
|
3822
|
-
return successResponse(
|
|
3823
|
-
url:
|
|
3824
|
-
title: await
|
|
3822
|
+
return successResponse(command.id, {
|
|
3823
|
+
url: page.url(),
|
|
3824
|
+
title: await page.title()
|
|
3825
3825
|
});
|
|
3826
3826
|
}
|
|
3827
|
-
async function handleClick(
|
|
3828
|
-
if (
|
|
3829
|
-
const refData =
|
|
3827
|
+
async function handleClick(command, browser) {
|
|
3828
|
+
if (browser.isRef(command.selector)) {
|
|
3829
|
+
const refData = browser.getRefData(command.selector);
|
|
3830
3830
|
if (refData && refData.bounds) {
|
|
3831
3831
|
const b = refData.bounds;
|
|
3832
3832
|
const centerX = b.left + (b.right - b.left) / 2;
|
|
3833
3833
|
const centerY = b.top + (b.bottom - b.top) / 2;
|
|
3834
|
-
await
|
|
3834
|
+
await browser.injectMouseEvent({
|
|
3835
3835
|
type: "mousePressed",
|
|
3836
3836
|
x: centerX,
|
|
3837
3837
|
y: centerY,
|
|
3838
|
-
button:
|
|
3839
|
-
clickCount:
|
|
3838
|
+
button: command.button || "left",
|
|
3839
|
+
clickCount: command.clickCount || 1
|
|
3840
3840
|
});
|
|
3841
|
-
await
|
|
3841
|
+
await browser.injectMouseEvent({
|
|
3842
3842
|
type: "mouseReleased",
|
|
3843
3843
|
x: centerX,
|
|
3844
3844
|
y: centerY,
|
|
3845
|
-
button:
|
|
3845
|
+
button: command.button || "left"
|
|
3846
3846
|
});
|
|
3847
|
-
return successResponse(
|
|
3847
|
+
return successResponse(command.id, { clicked: true, method: "cdp_coordinates" });
|
|
3848
3848
|
}
|
|
3849
3849
|
}
|
|
3850
|
-
const
|
|
3850
|
+
const locator = browser.getLocator(command.selector);
|
|
3851
3851
|
try {
|
|
3852
|
-
await
|
|
3853
|
-
button:
|
|
3854
|
-
clickCount:
|
|
3855
|
-
delay:
|
|
3852
|
+
await locator.click({
|
|
3853
|
+
button: command.button,
|
|
3854
|
+
clickCount: command.clickCount,
|
|
3855
|
+
delay: command.delay
|
|
3856
3856
|
});
|
|
3857
3857
|
} catch (error) {
|
|
3858
|
-
throw toAIFriendlyError(error,
|
|
3858
|
+
throw toAIFriendlyError(error, command.selector);
|
|
3859
3859
|
}
|
|
3860
|
-
return successResponse(
|
|
3860
|
+
return successResponse(command.id, { clicked: true, method: "playwright_locator" });
|
|
3861
3861
|
}
|
|
3862
|
-
async function handleType(
|
|
3863
|
-
const
|
|
3862
|
+
async function handleType(command, browser) {
|
|
3863
|
+
const locator = browser.getLocator(command.selector);
|
|
3864
3864
|
try {
|
|
3865
|
-
if (
|
|
3866
|
-
await
|
|
3865
|
+
if (command.clear) {
|
|
3866
|
+
await locator.fill("");
|
|
3867
3867
|
}
|
|
3868
|
-
await
|
|
3869
|
-
delay:
|
|
3868
|
+
await locator.pressSequentially(command.text, {
|
|
3869
|
+
delay: command.delay
|
|
3870
3870
|
});
|
|
3871
3871
|
} catch (error) {
|
|
3872
|
-
throw toAIFriendlyError(error,
|
|
3872
|
+
throw toAIFriendlyError(error, command.selector);
|
|
3873
3873
|
}
|
|
3874
|
-
return successResponse(
|
|
3874
|
+
return successResponse(command.id, { typed: true });
|
|
3875
3875
|
}
|
|
3876
|
-
async function handlePress(
|
|
3877
|
-
const
|
|
3878
|
-
if (
|
|
3879
|
-
await
|
|
3876
|
+
async function handlePress(command, browser) {
|
|
3877
|
+
const page = browser.getPage();
|
|
3878
|
+
if (command.selector) {
|
|
3879
|
+
await page.press(command.selector, command.key);
|
|
3880
3880
|
} else {
|
|
3881
|
-
await
|
|
3881
|
+
await page.keyboard.press(command.key);
|
|
3882
3882
|
}
|
|
3883
|
-
return successResponse(
|
|
3883
|
+
return successResponse(command.id, { pressed: true });
|
|
3884
3884
|
}
|
|
3885
|
-
async function handleScreenshot(
|
|
3886
|
-
const
|
|
3885
|
+
async function handleScreenshot(command, browser) {
|
|
3886
|
+
const page = browser.getPage();
|
|
3887
3887
|
const options = {
|
|
3888
|
-
fullPage:
|
|
3889
|
-
type:
|
|
3888
|
+
fullPage: command.fullPage,
|
|
3889
|
+
type: command.format ?? "png"
|
|
3890
3890
|
};
|
|
3891
|
-
if (
|
|
3892
|
-
options.quality =
|
|
3891
|
+
if (command.format === "jpeg" && command.quality !== void 0) {
|
|
3892
|
+
options.quality = command.quality;
|
|
3893
3893
|
}
|
|
3894
|
-
let target =
|
|
3895
|
-
if (
|
|
3896
|
-
target =
|
|
3894
|
+
let target = page;
|
|
3895
|
+
if (command.selector) {
|
|
3896
|
+
target = browser.getLocator(command.selector);
|
|
3897
3897
|
}
|
|
3898
3898
|
try {
|
|
3899
|
-
let savePath =
|
|
3899
|
+
let savePath = command.path;
|
|
3900
3900
|
if (!savePath) {
|
|
3901
|
-
const ext =
|
|
3901
|
+
const ext = command.format === "jpeg" ? "jpg" : "png";
|
|
3902
3902
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
3903
3903
|
const random = Math.random().toString(36).substring(2, 8);
|
|
3904
3904
|
const filename = `screenshot-${timestamp}-${random}.${ext}`;
|
|
@@ -3907,69 +3907,69 @@ async function handleScreenshot(command2, browser2) {
|
|
|
3907
3907
|
savePath = path3.join(screenshotDir, filename);
|
|
3908
3908
|
}
|
|
3909
3909
|
await target.screenshot({ ...options, path: savePath });
|
|
3910
|
-
return successResponse(
|
|
3910
|
+
return successResponse(command.id, { path: savePath });
|
|
3911
3911
|
} catch (error) {
|
|
3912
|
-
if (
|
|
3913
|
-
throw toAIFriendlyError(error,
|
|
3912
|
+
if (command.selector) {
|
|
3913
|
+
throw toAIFriendlyError(error, command.selector);
|
|
3914
3914
|
}
|
|
3915
3915
|
throw error;
|
|
3916
3916
|
}
|
|
3917
3917
|
}
|
|
3918
|
-
async function handleSnapshot(
|
|
3919
|
-
const { tree, refs } = await
|
|
3920
|
-
interactive:
|
|
3921
|
-
cursor:
|
|
3922
|
-
maxDepth:
|
|
3923
|
-
compact:
|
|
3924
|
-
selector:
|
|
3918
|
+
async function handleSnapshot(command, browser) {
|
|
3919
|
+
const { tree, refs } = await browser.getSnapshot({
|
|
3920
|
+
interactive: command.interactive,
|
|
3921
|
+
cursor: command.cursor,
|
|
3922
|
+
maxDepth: command.maxDepth,
|
|
3923
|
+
compact: command.compact,
|
|
3924
|
+
selector: command.selector
|
|
3925
3925
|
});
|
|
3926
3926
|
const simpleRefs = {};
|
|
3927
3927
|
for (const [ref, data] of Object.entries(refs)) {
|
|
3928
3928
|
simpleRefs[ref] = { role: data.role, name: data.name };
|
|
3929
3929
|
}
|
|
3930
|
-
return successResponse(
|
|
3930
|
+
return successResponse(command.id, {
|
|
3931
3931
|
snapshot: tree || "Empty page",
|
|
3932
3932
|
refs: Object.keys(simpleRefs).length > 0 ? simpleRefs : void 0
|
|
3933
3933
|
});
|
|
3934
3934
|
}
|
|
3935
|
-
async function handleEvaluate(
|
|
3936
|
-
const
|
|
3937
|
-
const result = await
|
|
3938
|
-
return successResponse(
|
|
3939
|
-
}
|
|
3940
|
-
async function handleWait(
|
|
3941
|
-
const
|
|
3942
|
-
if (
|
|
3943
|
-
await
|
|
3944
|
-
state:
|
|
3945
|
-
timeout:
|
|
3935
|
+
async function handleEvaluate(command, browser) {
|
|
3936
|
+
const page = browser.getPage();
|
|
3937
|
+
const result = await page.evaluate(command.script);
|
|
3938
|
+
return successResponse(command.id, { result });
|
|
3939
|
+
}
|
|
3940
|
+
async function handleWait(command, browser) {
|
|
3941
|
+
const page = browser.getPage();
|
|
3942
|
+
if (command.selector) {
|
|
3943
|
+
await page.waitForSelector(command.selector, {
|
|
3944
|
+
state: command.state ?? "visible",
|
|
3945
|
+
timeout: command.timeout
|
|
3946
3946
|
});
|
|
3947
|
-
} else if (
|
|
3948
|
-
await
|
|
3947
|
+
} else if (command.timeout) {
|
|
3948
|
+
await page.waitForTimeout(command.timeout);
|
|
3949
3949
|
} else {
|
|
3950
|
-
await
|
|
3951
|
-
}
|
|
3952
|
-
return successResponse(
|
|
3953
|
-
}
|
|
3954
|
-
async function handleScroll(
|
|
3955
|
-
const
|
|
3956
|
-
if (
|
|
3957
|
-
const
|
|
3958
|
-
await
|
|
3959
|
-
if (
|
|
3960
|
-
await
|
|
3961
|
-
(
|
|
3962
|
-
|
|
3950
|
+
await page.waitForLoadState("load");
|
|
3951
|
+
}
|
|
3952
|
+
return successResponse(command.id, { waited: true });
|
|
3953
|
+
}
|
|
3954
|
+
async function handleScroll(command, browser) {
|
|
3955
|
+
const page = browser.getPage();
|
|
3956
|
+
if (command.selector) {
|
|
3957
|
+
const element = page.locator(command.selector);
|
|
3958
|
+
await element.scrollIntoViewIfNeeded();
|
|
3959
|
+
if (command.x !== void 0 || command.y !== void 0) {
|
|
3960
|
+
await element.evaluate(
|
|
3961
|
+
(el, { x, y }) => {
|
|
3962
|
+
el.scrollBy(x ?? 0, y ?? 0);
|
|
3963
3963
|
},
|
|
3964
|
-
{ x:
|
|
3964
|
+
{ x: command.x, y: command.y }
|
|
3965
3965
|
);
|
|
3966
3966
|
}
|
|
3967
3967
|
} else {
|
|
3968
|
-
let deltaX =
|
|
3969
|
-
let deltaY =
|
|
3970
|
-
if (
|
|
3971
|
-
const amount =
|
|
3972
|
-
switch (
|
|
3968
|
+
let deltaX = command.x ?? 0;
|
|
3969
|
+
let deltaY = command.y ?? 0;
|
|
3970
|
+
if (command.direction) {
|
|
3971
|
+
const amount = command.amount ?? 100;
|
|
3972
|
+
switch (command.direction) {
|
|
3973
3973
|
case "up":
|
|
3974
3974
|
deltaY = -amount;
|
|
3975
3975
|
break;
|
|
@@ -3984,236 +3984,236 @@ async function handleScroll(command2, browser2) {
|
|
|
3984
3984
|
break;
|
|
3985
3985
|
}
|
|
3986
3986
|
}
|
|
3987
|
-
await
|
|
3987
|
+
await page.evaluate(`window.scrollBy(${deltaX}, ${deltaY})`);
|
|
3988
3988
|
}
|
|
3989
|
-
return successResponse(
|
|
3989
|
+
return successResponse(command.id, { scrolled: true });
|
|
3990
3990
|
}
|
|
3991
|
-
async function handleSelect(
|
|
3992
|
-
const
|
|
3993
|
-
const values = Array.isArray(
|
|
3991
|
+
async function handleSelect(command, browser) {
|
|
3992
|
+
const locator = browser.getLocator(command.selector);
|
|
3993
|
+
const values = Array.isArray(command.values) ? command.values : [command.values];
|
|
3994
3994
|
try {
|
|
3995
|
-
await
|
|
3995
|
+
await locator.selectOption(values);
|
|
3996
3996
|
} catch (error) {
|
|
3997
|
-
throw toAIFriendlyError(error,
|
|
3997
|
+
throw toAIFriendlyError(error, command.selector);
|
|
3998
3998
|
}
|
|
3999
|
-
return successResponse(
|
|
3999
|
+
return successResponse(command.id, { selected: values });
|
|
4000
4000
|
}
|
|
4001
|
-
async function handleHover(
|
|
4002
|
-
const
|
|
4001
|
+
async function handleHover(command, browser) {
|
|
4002
|
+
const locator = browser.getLocator(command.selector);
|
|
4003
4003
|
try {
|
|
4004
|
-
await
|
|
4004
|
+
await locator.hover();
|
|
4005
4005
|
} catch (error) {
|
|
4006
|
-
throw toAIFriendlyError(error,
|
|
4006
|
+
throw toAIFriendlyError(error, command.selector);
|
|
4007
4007
|
}
|
|
4008
|
-
return successResponse(
|
|
4008
|
+
return successResponse(command.id, { hovered: true });
|
|
4009
4009
|
}
|
|
4010
|
-
async function handleContent(
|
|
4011
|
-
const
|
|
4010
|
+
async function handleContent(command, browser) {
|
|
4011
|
+
const page = browser.getPage();
|
|
4012
4012
|
let html;
|
|
4013
|
-
if (
|
|
4014
|
-
html = await
|
|
4013
|
+
if (command.selector) {
|
|
4014
|
+
html = await page.locator(command.selector).innerHTML();
|
|
4015
4015
|
} else {
|
|
4016
|
-
html = await
|
|
4016
|
+
html = await page.content();
|
|
4017
4017
|
}
|
|
4018
|
-
return successResponse(
|
|
4018
|
+
return successResponse(command.id, { html });
|
|
4019
4019
|
}
|
|
4020
|
-
async function handleClose(
|
|
4021
|
-
await
|
|
4022
|
-
return successResponse(
|
|
4020
|
+
async function handleClose(command, browser) {
|
|
4021
|
+
await browser.close();
|
|
4022
|
+
return successResponse(command.id, { closed: true });
|
|
4023
4023
|
}
|
|
4024
|
-
async function handleTabNew(
|
|
4025
|
-
const result = await
|
|
4026
|
-
if (
|
|
4027
|
-
const
|
|
4028
|
-
await
|
|
4024
|
+
async function handleTabNew(command, browser) {
|
|
4025
|
+
const result = await browser.newTab();
|
|
4026
|
+
if (command.url) {
|
|
4027
|
+
const page = browser.getPage();
|
|
4028
|
+
await page.goto(command.url, { waitUntil: "domcontentloaded" });
|
|
4029
4029
|
}
|
|
4030
|
-
return successResponse(
|
|
4030
|
+
return successResponse(command.id, result);
|
|
4031
4031
|
}
|
|
4032
|
-
async function handleTabList(
|
|
4033
|
-
const tabs = await
|
|
4034
|
-
return successResponse(
|
|
4032
|
+
async function handleTabList(command, browser) {
|
|
4033
|
+
const tabs = await browser.listTabs();
|
|
4034
|
+
return successResponse(command.id, {
|
|
4035
4035
|
tabs,
|
|
4036
|
-
active:
|
|
4036
|
+
active: browser.getActiveIndex()
|
|
4037
4037
|
});
|
|
4038
4038
|
}
|
|
4039
|
-
async function handleTabSwitch(
|
|
4040
|
-
const result = await
|
|
4041
|
-
const
|
|
4042
|
-
return successResponse(
|
|
4039
|
+
async function handleTabSwitch(command, browser) {
|
|
4040
|
+
const result = await browser.switchTo(command.index);
|
|
4041
|
+
const page = browser.getPage();
|
|
4042
|
+
return successResponse(command.id, {
|
|
4043
4043
|
...result,
|
|
4044
|
-
title: await
|
|
4044
|
+
title: await page.title()
|
|
4045
4045
|
});
|
|
4046
4046
|
}
|
|
4047
|
-
async function handleTabClose(
|
|
4048
|
-
const result = await
|
|
4049
|
-
return successResponse(
|
|
4047
|
+
async function handleTabClose(command, browser) {
|
|
4048
|
+
const result = await browser.closeTab(command.index);
|
|
4049
|
+
return successResponse(command.id, result);
|
|
4050
4050
|
}
|
|
4051
|
-
async function handleWindowNew(
|
|
4052
|
-
const result = await
|
|
4053
|
-
return successResponse(
|
|
4051
|
+
async function handleWindowNew(command, browser) {
|
|
4052
|
+
const result = await browser.newWindow(command.viewport);
|
|
4053
|
+
return successResponse(command.id, result);
|
|
4054
4054
|
}
|
|
4055
|
-
async function handleFill(
|
|
4056
|
-
const
|
|
4055
|
+
async function handleFill(command, browser) {
|
|
4056
|
+
const locator = browser.getLocator(command.selector);
|
|
4057
4057
|
try {
|
|
4058
|
-
await
|
|
4058
|
+
await locator.fill(command.value);
|
|
4059
4059
|
} catch (error) {
|
|
4060
|
-
throw toAIFriendlyError(error,
|
|
4060
|
+
throw toAIFriendlyError(error, command.selector);
|
|
4061
4061
|
}
|
|
4062
|
-
return successResponse(
|
|
4062
|
+
return successResponse(command.id, { filled: true });
|
|
4063
4063
|
}
|
|
4064
|
-
async function handleCheck(
|
|
4065
|
-
const
|
|
4064
|
+
async function handleCheck(command, browser) {
|
|
4065
|
+
const locator = browser.getLocator(command.selector);
|
|
4066
4066
|
try {
|
|
4067
|
-
await
|
|
4067
|
+
await locator.check();
|
|
4068
4068
|
} catch (error) {
|
|
4069
|
-
throw toAIFriendlyError(error,
|
|
4069
|
+
throw toAIFriendlyError(error, command.selector);
|
|
4070
4070
|
}
|
|
4071
|
-
return successResponse(
|
|
4071
|
+
return successResponse(command.id, { checked: true });
|
|
4072
4072
|
}
|
|
4073
|
-
async function handleUncheck(
|
|
4074
|
-
const
|
|
4073
|
+
async function handleUncheck(command, browser) {
|
|
4074
|
+
const locator = browser.getLocator(command.selector);
|
|
4075
4075
|
try {
|
|
4076
|
-
await
|
|
4076
|
+
await locator.uncheck();
|
|
4077
4077
|
} catch (error) {
|
|
4078
|
-
throw toAIFriendlyError(error,
|
|
4078
|
+
throw toAIFriendlyError(error, command.selector);
|
|
4079
4079
|
}
|
|
4080
|
-
return successResponse(
|
|
4080
|
+
return successResponse(command.id, { unchecked: true });
|
|
4081
4081
|
}
|
|
4082
|
-
async function handleUpload(
|
|
4083
|
-
const
|
|
4084
|
-
const files = Array.isArray(
|
|
4082
|
+
async function handleUpload(command, browser) {
|
|
4083
|
+
const locator = browser.getLocator(command.selector);
|
|
4084
|
+
const files = Array.isArray(command.files) ? command.files : [command.files];
|
|
4085
4085
|
try {
|
|
4086
|
-
await
|
|
4086
|
+
await locator.setInputFiles(files);
|
|
4087
4087
|
} catch (error) {
|
|
4088
|
-
throw toAIFriendlyError(error,
|
|
4088
|
+
throw toAIFriendlyError(error, command.selector);
|
|
4089
4089
|
}
|
|
4090
|
-
return successResponse(
|
|
4090
|
+
return successResponse(command.id, { uploaded: files });
|
|
4091
4091
|
}
|
|
4092
|
-
async function handleDoubleClick(
|
|
4093
|
-
const
|
|
4092
|
+
async function handleDoubleClick(command, browser) {
|
|
4093
|
+
const locator = browser.getLocator(command.selector);
|
|
4094
4094
|
try {
|
|
4095
|
-
await
|
|
4095
|
+
await locator.dblclick();
|
|
4096
4096
|
} catch (error) {
|
|
4097
|
-
throw toAIFriendlyError(error,
|
|
4097
|
+
throw toAIFriendlyError(error, command.selector);
|
|
4098
4098
|
}
|
|
4099
|
-
return successResponse(
|
|
4099
|
+
return successResponse(command.id, { clicked: true });
|
|
4100
4100
|
}
|
|
4101
|
-
async function handleFocus(
|
|
4102
|
-
const
|
|
4101
|
+
async function handleFocus(command, browser) {
|
|
4102
|
+
const locator = browser.getLocator(command.selector);
|
|
4103
4103
|
try {
|
|
4104
|
-
await
|
|
4104
|
+
await locator.focus();
|
|
4105
4105
|
} catch (error) {
|
|
4106
|
-
throw toAIFriendlyError(error,
|
|
4106
|
+
throw toAIFriendlyError(error, command.selector);
|
|
4107
4107
|
}
|
|
4108
|
-
return successResponse(
|
|
4108
|
+
return successResponse(command.id, { focused: true });
|
|
4109
4109
|
}
|
|
4110
|
-
async function handleDrag(
|
|
4111
|
-
const frame =
|
|
4112
|
-
await frame.dragAndDrop(
|
|
4113
|
-
return successResponse(
|
|
4110
|
+
async function handleDrag(command, browser) {
|
|
4111
|
+
const frame = browser.getFrame();
|
|
4112
|
+
await frame.dragAndDrop(command.source, command.target);
|
|
4113
|
+
return successResponse(command.id, { dragged: true });
|
|
4114
4114
|
}
|
|
4115
|
-
async function handleFrame(
|
|
4116
|
-
await
|
|
4117
|
-
selector:
|
|
4118
|
-
name:
|
|
4119
|
-
url:
|
|
4115
|
+
async function handleFrame(command, browser) {
|
|
4116
|
+
await browser.switchToFrame({
|
|
4117
|
+
selector: command.selector,
|
|
4118
|
+
name: command.name,
|
|
4119
|
+
url: command.url
|
|
4120
4120
|
});
|
|
4121
|
-
return successResponse(
|
|
4121
|
+
return successResponse(command.id, { switched: true });
|
|
4122
4122
|
}
|
|
4123
|
-
async function handleMainFrame(
|
|
4124
|
-
|
|
4125
|
-
return successResponse(
|
|
4123
|
+
async function handleMainFrame(command, browser) {
|
|
4124
|
+
browser.switchToMainFrame();
|
|
4125
|
+
return successResponse(command.id, { switched: true });
|
|
4126
4126
|
}
|
|
4127
|
-
async function handleGetByRole(
|
|
4128
|
-
const
|
|
4129
|
-
const
|
|
4130
|
-
switch (
|
|
4127
|
+
async function handleGetByRole(command, browser) {
|
|
4128
|
+
const page = browser.getPage();
|
|
4129
|
+
const locator = page.getByRole(command.role, { name: command.name, exact: command.exact });
|
|
4130
|
+
switch (command.subaction) {
|
|
4131
4131
|
case "click":
|
|
4132
|
-
await
|
|
4133
|
-
return successResponse(
|
|
4132
|
+
await locator.click();
|
|
4133
|
+
return successResponse(command.id, { clicked: true });
|
|
4134
4134
|
case "fill":
|
|
4135
|
-
await
|
|
4136
|
-
return successResponse(
|
|
4135
|
+
await locator.fill(command.value ?? "");
|
|
4136
|
+
return successResponse(command.id, { filled: true });
|
|
4137
4137
|
case "check":
|
|
4138
|
-
await
|
|
4139
|
-
return successResponse(
|
|
4138
|
+
await locator.check();
|
|
4139
|
+
return successResponse(command.id, { checked: true });
|
|
4140
4140
|
case "hover":
|
|
4141
|
-
await
|
|
4142
|
-
return successResponse(
|
|
4141
|
+
await locator.hover();
|
|
4142
|
+
return successResponse(command.id, { hovered: true });
|
|
4143
4143
|
}
|
|
4144
4144
|
}
|
|
4145
|
-
async function handleGetByText(
|
|
4146
|
-
const
|
|
4147
|
-
const
|
|
4148
|
-
switch (
|
|
4145
|
+
async function handleGetByText(command, browser) {
|
|
4146
|
+
const page = browser.getPage();
|
|
4147
|
+
const locator = page.getByText(command.text, { exact: command.exact });
|
|
4148
|
+
switch (command.subaction) {
|
|
4149
4149
|
case "click":
|
|
4150
|
-
await
|
|
4151
|
-
return successResponse(
|
|
4150
|
+
await locator.click();
|
|
4151
|
+
return successResponse(command.id, { clicked: true });
|
|
4152
4152
|
case "hover":
|
|
4153
|
-
await
|
|
4154
|
-
return successResponse(
|
|
4153
|
+
await locator.hover();
|
|
4154
|
+
return successResponse(command.id, { hovered: true });
|
|
4155
4155
|
}
|
|
4156
4156
|
}
|
|
4157
|
-
async function handleGetByLabel(
|
|
4158
|
-
const
|
|
4159
|
-
const
|
|
4160
|
-
switch (
|
|
4157
|
+
async function handleGetByLabel(command, browser) {
|
|
4158
|
+
const page = browser.getPage();
|
|
4159
|
+
const locator = page.getByLabel(command.label, { exact: command.exact });
|
|
4160
|
+
switch (command.subaction) {
|
|
4161
4161
|
case "click":
|
|
4162
|
-
await
|
|
4163
|
-
return successResponse(
|
|
4162
|
+
await locator.click();
|
|
4163
|
+
return successResponse(command.id, { clicked: true });
|
|
4164
4164
|
case "fill":
|
|
4165
|
-
await
|
|
4166
|
-
return successResponse(
|
|
4165
|
+
await locator.fill(command.value ?? "");
|
|
4166
|
+
return successResponse(command.id, { filled: true });
|
|
4167
4167
|
case "check":
|
|
4168
|
-
await
|
|
4169
|
-
return successResponse(
|
|
4168
|
+
await locator.check();
|
|
4169
|
+
return successResponse(command.id, { checked: true });
|
|
4170
4170
|
}
|
|
4171
4171
|
}
|
|
4172
|
-
async function handleGetByPlaceholder(
|
|
4173
|
-
const
|
|
4174
|
-
const
|
|
4175
|
-
switch (
|
|
4172
|
+
async function handleGetByPlaceholder(command, browser) {
|
|
4173
|
+
const page = browser.getPage();
|
|
4174
|
+
const locator = page.getByPlaceholder(command.placeholder, { exact: command.exact });
|
|
4175
|
+
switch (command.subaction) {
|
|
4176
4176
|
case "click":
|
|
4177
|
-
await
|
|
4178
|
-
return successResponse(
|
|
4177
|
+
await locator.click();
|
|
4178
|
+
return successResponse(command.id, { clicked: true });
|
|
4179
4179
|
case "fill":
|
|
4180
|
-
await
|
|
4181
|
-
return successResponse(
|
|
4180
|
+
await locator.fill(command.value ?? "");
|
|
4181
|
+
return successResponse(command.id, { filled: true });
|
|
4182
4182
|
}
|
|
4183
4183
|
}
|
|
4184
|
-
async function handleCookiesGet(
|
|
4185
|
-
const
|
|
4186
|
-
const context =
|
|
4187
|
-
const cookies = await context.cookies(
|
|
4188
|
-
return successResponse(
|
|
4184
|
+
async function handleCookiesGet(command, browser) {
|
|
4185
|
+
const page = browser.getPage();
|
|
4186
|
+
const context = page.context();
|
|
4187
|
+
const cookies = await context.cookies(command.urls);
|
|
4188
|
+
return successResponse(command.id, { cookies });
|
|
4189
4189
|
}
|
|
4190
|
-
async function handleCookiesSet(
|
|
4191
|
-
const
|
|
4192
|
-
const context =
|
|
4193
|
-
const pageUrl =
|
|
4194
|
-
const cookies =
|
|
4190
|
+
async function handleCookiesSet(command, browser) {
|
|
4191
|
+
const page = browser.getPage();
|
|
4192
|
+
const context = page.context();
|
|
4193
|
+
const pageUrl = page.url();
|
|
4194
|
+
const cookies = command.cookies.map((cookie) => {
|
|
4195
4195
|
if (!cookie.url && !cookie.domain && !cookie.path) {
|
|
4196
4196
|
return { ...cookie, url: pageUrl };
|
|
4197
4197
|
}
|
|
4198
4198
|
return cookie;
|
|
4199
4199
|
});
|
|
4200
4200
|
await context.addCookies(cookies);
|
|
4201
|
-
return successResponse(
|
|
4201
|
+
return successResponse(command.id, { set: true });
|
|
4202
4202
|
}
|
|
4203
|
-
async function handleCookiesClear(
|
|
4204
|
-
const
|
|
4205
|
-
const context =
|
|
4203
|
+
async function handleCookiesClear(command, browser) {
|
|
4204
|
+
const page = browser.getPage();
|
|
4205
|
+
const context = page.context();
|
|
4206
4206
|
await context.clearCookies();
|
|
4207
|
-
return successResponse(
|
|
4208
|
-
}
|
|
4209
|
-
async function handleStorageGet(
|
|
4210
|
-
const
|
|
4211
|
-
const storageType =
|
|
4212
|
-
if (
|
|
4213
|
-
const value = await
|
|
4214
|
-
return successResponse(
|
|
4207
|
+
return successResponse(command.id, { cleared: true });
|
|
4208
|
+
}
|
|
4209
|
+
async function handleStorageGet(command, browser) {
|
|
4210
|
+
const page = browser.getPage();
|
|
4211
|
+
const storageType = command.type === "local" ? "localStorage" : "sessionStorage";
|
|
4212
|
+
if (command.key) {
|
|
4213
|
+
const value = await page.evaluate(`${storageType}.getItem(${JSON.stringify(command.key)})`);
|
|
4214
|
+
return successResponse(command.id, { key: command.key, value });
|
|
4215
4215
|
} else {
|
|
4216
|
-
const data = await
|
|
4216
|
+
const data = await page.evaluate(`
|
|
4217
4217
|
(() => {
|
|
4218
4218
|
const storage = ${storageType};
|
|
4219
4219
|
const result = {};
|
|
@@ -4224,102 +4224,102 @@ async function handleStorageGet(command2, browser2) {
|
|
|
4224
4224
|
return result;
|
|
4225
4225
|
})()
|
|
4226
4226
|
`);
|
|
4227
|
-
return successResponse(
|
|
4227
|
+
return successResponse(command.id, { data });
|
|
4228
4228
|
}
|
|
4229
4229
|
}
|
|
4230
|
-
async function handleStorageSet(
|
|
4231
|
-
const
|
|
4232
|
-
const storageType =
|
|
4233
|
-
await
|
|
4234
|
-
`${storageType}.setItem(${JSON.stringify(
|
|
4230
|
+
async function handleStorageSet(command, browser) {
|
|
4231
|
+
const page = browser.getPage();
|
|
4232
|
+
const storageType = command.type === "local" ? "localStorage" : "sessionStorage";
|
|
4233
|
+
await page.evaluate(
|
|
4234
|
+
`${storageType}.setItem(${JSON.stringify(command.key)}, ${JSON.stringify(command.value)})`
|
|
4235
4235
|
);
|
|
4236
|
-
return successResponse(
|
|
4237
|
-
}
|
|
4238
|
-
async function handleStorageClear(
|
|
4239
|
-
const
|
|
4240
|
-
const storageType =
|
|
4241
|
-
await
|
|
4242
|
-
return successResponse(
|
|
4243
|
-
}
|
|
4244
|
-
async function handleDialog(
|
|
4245
|
-
|
|
4246
|
-
return successResponse(
|
|
4247
|
-
}
|
|
4248
|
-
async function handlePdf(
|
|
4249
|
-
const
|
|
4250
|
-
await
|
|
4251
|
-
path:
|
|
4252
|
-
format:
|
|
4236
|
+
return successResponse(command.id, { set: true });
|
|
4237
|
+
}
|
|
4238
|
+
async function handleStorageClear(command, browser) {
|
|
4239
|
+
const page = browser.getPage();
|
|
4240
|
+
const storageType = command.type === "local" ? "localStorage" : "sessionStorage";
|
|
4241
|
+
await page.evaluate(`${storageType}.clear()`);
|
|
4242
|
+
return successResponse(command.id, { cleared: true });
|
|
4243
|
+
}
|
|
4244
|
+
async function handleDialog(command, browser) {
|
|
4245
|
+
browser.setDialogHandler(command.response, command.promptText);
|
|
4246
|
+
return successResponse(command.id, { handler: "set", response: command.response });
|
|
4247
|
+
}
|
|
4248
|
+
async function handlePdf(command, browser) {
|
|
4249
|
+
const page = browser.getPage();
|
|
4250
|
+
await page.pdf({
|
|
4251
|
+
path: command.path,
|
|
4252
|
+
format: command.format ?? "Letter"
|
|
4253
4253
|
});
|
|
4254
|
-
return successResponse(
|
|
4254
|
+
return successResponse(command.id, { path: command.path });
|
|
4255
4255
|
}
|
|
4256
|
-
async function handleRoute(
|
|
4257
|
-
await
|
|
4258
|
-
response:
|
|
4259
|
-
abort:
|
|
4256
|
+
async function handleRoute(command, browser) {
|
|
4257
|
+
await browser.addRoute(command.url, {
|
|
4258
|
+
response: command.response,
|
|
4259
|
+
abort: command.abort
|
|
4260
4260
|
});
|
|
4261
|
-
return successResponse(
|
|
4262
|
-
}
|
|
4263
|
-
async function handleUnroute(
|
|
4264
|
-
await
|
|
4265
|
-
return successResponse(
|
|
4266
|
-
}
|
|
4267
|
-
async function handleRequests(
|
|
4268
|
-
if (
|
|
4269
|
-
|
|
4270
|
-
return successResponse(
|
|
4271
|
-
}
|
|
4272
|
-
|
|
4273
|
-
const requests =
|
|
4274
|
-
return successResponse(
|
|
4275
|
-
}
|
|
4276
|
-
async function handleDownload(
|
|
4277
|
-
const
|
|
4278
|
-
const
|
|
4279
|
-
const [download] = await Promise.all([
|
|
4280
|
-
await download.saveAs(
|
|
4281
|
-
return successResponse(
|
|
4282
|
-
path:
|
|
4261
|
+
return successResponse(command.id, { routed: command.url });
|
|
4262
|
+
}
|
|
4263
|
+
async function handleUnroute(command, browser) {
|
|
4264
|
+
await browser.removeRoute(command.url);
|
|
4265
|
+
return successResponse(command.id, { unrouted: command.url ?? "all" });
|
|
4266
|
+
}
|
|
4267
|
+
async function handleRequests(command, browser) {
|
|
4268
|
+
if (command.clear) {
|
|
4269
|
+
browser.clearRequests();
|
|
4270
|
+
return successResponse(command.id, { cleared: true });
|
|
4271
|
+
}
|
|
4272
|
+
browser.startRequestTracking();
|
|
4273
|
+
const requests = browser.getRequests(command.filter);
|
|
4274
|
+
return successResponse(command.id, { requests });
|
|
4275
|
+
}
|
|
4276
|
+
async function handleDownload(command, browser) {
|
|
4277
|
+
const page = browser.getPage();
|
|
4278
|
+
const locator = browser.getLocator(command.selector);
|
|
4279
|
+
const [download] = await Promise.all([page.waitForEvent("download"), locator.click()]);
|
|
4280
|
+
await download.saveAs(command.path);
|
|
4281
|
+
return successResponse(command.id, {
|
|
4282
|
+
path: command.path,
|
|
4283
4283
|
suggestedFilename: download.suggestedFilename()
|
|
4284
4284
|
});
|
|
4285
4285
|
}
|
|
4286
|
-
async function handleGeolocation(
|
|
4287
|
-
await
|
|
4288
|
-
return successResponse(
|
|
4289
|
-
latitude:
|
|
4290
|
-
longitude:
|
|
4286
|
+
async function handleGeolocation(command, browser) {
|
|
4287
|
+
await browser.setGeolocation(command.latitude, command.longitude, command.accuracy);
|
|
4288
|
+
return successResponse(command.id, {
|
|
4289
|
+
latitude: command.latitude,
|
|
4290
|
+
longitude: command.longitude
|
|
4291
4291
|
});
|
|
4292
4292
|
}
|
|
4293
|
-
async function handlePermissions(
|
|
4294
|
-
await
|
|
4295
|
-
return successResponse(
|
|
4296
|
-
permissions:
|
|
4297
|
-
granted:
|
|
4293
|
+
async function handlePermissions(command, browser) {
|
|
4294
|
+
await browser.setPermissions(command.permissions, command.grant);
|
|
4295
|
+
return successResponse(command.id, {
|
|
4296
|
+
permissions: command.permissions,
|
|
4297
|
+
granted: command.grant
|
|
4298
4298
|
});
|
|
4299
4299
|
}
|
|
4300
|
-
async function handleViewport(
|
|
4301
|
-
await
|
|
4302
|
-
return successResponse(
|
|
4303
|
-
width:
|
|
4304
|
-
height:
|
|
4300
|
+
async function handleViewport(command, browser) {
|
|
4301
|
+
await browser.setViewport(command.width, command.height);
|
|
4302
|
+
return successResponse(command.id, {
|
|
4303
|
+
width: command.width,
|
|
4304
|
+
height: command.height
|
|
4305
4305
|
});
|
|
4306
4306
|
}
|
|
4307
|
-
async function handleUserAgent(
|
|
4308
|
-
const
|
|
4309
|
-
const context =
|
|
4310
|
-
return successResponse(
|
|
4307
|
+
async function handleUserAgent(command, browser) {
|
|
4308
|
+
const page = browser.getPage();
|
|
4309
|
+
const context = page.context();
|
|
4310
|
+
return successResponse(command.id, {
|
|
4311
4311
|
note: "User agent can only be set at launch time. Use device command instead."
|
|
4312
4312
|
});
|
|
4313
4313
|
}
|
|
4314
|
-
async function handleDevice(
|
|
4315
|
-
const device =
|
|
4314
|
+
async function handleDevice(command, browser) {
|
|
4315
|
+
const device = browser.getDevice(command.device);
|
|
4316
4316
|
if (!device) {
|
|
4317
|
-
const available =
|
|
4318
|
-
throw new Error(`Unknown device: ${
|
|
4317
|
+
const available = browser.listDevices().slice(0, 10).join(", ");
|
|
4318
|
+
throw new Error(`Unknown device: ${command.device}. Available: ${available}...`);
|
|
4319
4319
|
}
|
|
4320
|
-
await
|
|
4320
|
+
await browser.setViewport(device.viewport.width, device.viewport.height);
|
|
4321
4321
|
if (device.deviceScaleFactor && device.deviceScaleFactor !== 1) {
|
|
4322
|
-
await
|
|
4322
|
+
await browser.setDeviceScaleFactor(
|
|
4323
4323
|
device.deviceScaleFactor,
|
|
4324
4324
|
device.viewport.width,
|
|
4325
4325
|
device.viewport.height,
|
|
@@ -4327,79 +4327,79 @@ async function handleDevice(command2, browser2) {
|
|
|
4327
4327
|
);
|
|
4328
4328
|
} else {
|
|
4329
4329
|
try {
|
|
4330
|
-
await
|
|
4330
|
+
await browser.clearDeviceMetricsOverride();
|
|
4331
4331
|
} catch {
|
|
4332
4332
|
}
|
|
4333
4333
|
}
|
|
4334
|
-
return successResponse(
|
|
4335
|
-
device:
|
|
4334
|
+
return successResponse(command.id, {
|
|
4335
|
+
device: command.device,
|
|
4336
4336
|
viewport: device.viewport,
|
|
4337
4337
|
userAgent: device.userAgent,
|
|
4338
4338
|
deviceScaleFactor: device.deviceScaleFactor
|
|
4339
4339
|
});
|
|
4340
4340
|
}
|
|
4341
|
-
async function handleBack(
|
|
4342
|
-
const
|
|
4343
|
-
await
|
|
4344
|
-
return successResponse(
|
|
4345
|
-
}
|
|
4346
|
-
async function handleForward(
|
|
4347
|
-
const
|
|
4348
|
-
await
|
|
4349
|
-
return successResponse(
|
|
4350
|
-
}
|
|
4351
|
-
async function handleReload(
|
|
4352
|
-
const
|
|
4353
|
-
await
|
|
4354
|
-
return successResponse(
|
|
4355
|
-
}
|
|
4356
|
-
async function handleUrl(
|
|
4357
|
-
const
|
|
4358
|
-
return successResponse(
|
|
4359
|
-
}
|
|
4360
|
-
async function handleTitle(
|
|
4361
|
-
const
|
|
4362
|
-
const title = await
|
|
4363
|
-
return successResponse(
|
|
4364
|
-
}
|
|
4365
|
-
async function handleGetAttribute(
|
|
4366
|
-
const
|
|
4367
|
-
const value = await
|
|
4368
|
-
return successResponse(
|
|
4369
|
-
}
|
|
4370
|
-
async function handleGetText(
|
|
4371
|
-
const
|
|
4372
|
-
const text = await
|
|
4373
|
-
return successResponse(
|
|
4374
|
-
}
|
|
4375
|
-
async function handleIsVisible(
|
|
4376
|
-
const
|
|
4377
|
-
const visible = await
|
|
4378
|
-
return successResponse(
|
|
4379
|
-
}
|
|
4380
|
-
async function handleIsEnabled(
|
|
4381
|
-
const
|
|
4382
|
-
const enabled = await
|
|
4383
|
-
return successResponse(
|
|
4384
|
-
}
|
|
4385
|
-
async function handleIsChecked(
|
|
4386
|
-
const
|
|
4387
|
-
const checked = await
|
|
4388
|
-
return successResponse(
|
|
4389
|
-
}
|
|
4390
|
-
async function handleCount(
|
|
4391
|
-
const
|
|
4392
|
-
const count = await
|
|
4393
|
-
return successResponse(
|
|
4394
|
-
}
|
|
4395
|
-
async function handleBoundingBox(
|
|
4396
|
-
const
|
|
4397
|
-
const box = await
|
|
4398
|
-
return successResponse(
|
|
4341
|
+
async function handleBack(command, browser) {
|
|
4342
|
+
const page = browser.getPage();
|
|
4343
|
+
await page.goBack();
|
|
4344
|
+
return successResponse(command.id, { url: page.url() });
|
|
4345
|
+
}
|
|
4346
|
+
async function handleForward(command, browser) {
|
|
4347
|
+
const page = browser.getPage();
|
|
4348
|
+
await page.goForward();
|
|
4349
|
+
return successResponse(command.id, { url: page.url() });
|
|
4350
|
+
}
|
|
4351
|
+
async function handleReload(command, browser) {
|
|
4352
|
+
const page = browser.getPage();
|
|
4353
|
+
await page.reload();
|
|
4354
|
+
return successResponse(command.id, { url: page.url() });
|
|
4355
|
+
}
|
|
4356
|
+
async function handleUrl(command, browser) {
|
|
4357
|
+
const page = browser.getPage();
|
|
4358
|
+
return successResponse(command.id, { url: page.url() });
|
|
4359
|
+
}
|
|
4360
|
+
async function handleTitle(command, browser) {
|
|
4361
|
+
const page = browser.getPage();
|
|
4362
|
+
const title = await page.title();
|
|
4363
|
+
return successResponse(command.id, { title });
|
|
4364
|
+
}
|
|
4365
|
+
async function handleGetAttribute(command, browser) {
|
|
4366
|
+
const locator = browser.getLocator(command.selector);
|
|
4367
|
+
const value = await locator.getAttribute(command.attribute);
|
|
4368
|
+
return successResponse(command.id, { attribute: command.attribute, value });
|
|
4369
|
+
}
|
|
4370
|
+
async function handleGetText(command, browser) {
|
|
4371
|
+
const locator = browser.getLocator(command.selector);
|
|
4372
|
+
const text = await locator.textContent();
|
|
4373
|
+
return successResponse(command.id, { text });
|
|
4374
|
+
}
|
|
4375
|
+
async function handleIsVisible(command, browser) {
|
|
4376
|
+
const locator = browser.getLocator(command.selector);
|
|
4377
|
+
const visible = await locator.isVisible();
|
|
4378
|
+
return successResponse(command.id, { visible });
|
|
4379
|
+
}
|
|
4380
|
+
async function handleIsEnabled(command, browser) {
|
|
4381
|
+
const locator = browser.getLocator(command.selector);
|
|
4382
|
+
const enabled = await locator.isEnabled();
|
|
4383
|
+
return successResponse(command.id, { enabled });
|
|
4384
|
+
}
|
|
4385
|
+
async function handleIsChecked(command, browser) {
|
|
4386
|
+
const locator = browser.getLocator(command.selector);
|
|
4387
|
+
const checked = await locator.isChecked();
|
|
4388
|
+
return successResponse(command.id, { checked });
|
|
4389
|
+
}
|
|
4390
|
+
async function handleCount(command, browser) {
|
|
4391
|
+
const page = browser.getPage();
|
|
4392
|
+
const count = await page.locator(command.selector).count();
|
|
4393
|
+
return successResponse(command.id, { count });
|
|
4394
|
+
}
|
|
4395
|
+
async function handleBoundingBox(command, browser) {
|
|
4396
|
+
const page = browser.getPage();
|
|
4397
|
+
const box = await page.locator(command.selector).boundingBox();
|
|
4398
|
+
return successResponse(command.id, { box });
|
|
4399
4399
|
}
|
|
4400
4400
|
async function handleStyles(command, browser) {
|
|
4401
4401
|
const page = browser.getPage();
|
|
4402
|
-
const
|
|
4402
|
+
const extractStyles = (el) => {
|
|
4403
4403
|
const s = getComputedStyle(el);
|
|
4404
4404
|
const r = el.getBoundingClientRect();
|
|
4405
4405
|
return {
|
|
@@ -4409,408 +4409,424 @@ async function handleStyles(command, browser) {
|
|
|
4409
4409
|
x: Math.round(r.x),
|
|
4410
4410
|
y: Math.round(r.y),
|
|
4411
4411
|
width: Math.round(r.width),
|
|
4412
|
-
height: Math.round(r.height)
|
|
4412
|
+
height: Math.round(r.height)
|
|
4413
4413
|
},
|
|
4414
4414
|
styles: {
|
|
4415
4415
|
fontSize: s.fontSize,
|
|
4416
4416
|
fontWeight: s.fontWeight,
|
|
4417
|
-
fontFamily: s.fontFamily.split(
|
|
4417
|
+
fontFamily: s.fontFamily.split(",")[0].trim().replace(/"/g, ""),
|
|
4418
4418
|
color: s.color,
|
|
4419
4419
|
backgroundColor: s.backgroundColor,
|
|
4420
4420
|
borderRadius: s.borderRadius,
|
|
4421
|
-
border: s.border !==
|
|
4422
|
-
boxShadow: s.boxShadow !==
|
|
4423
|
-
padding: s.padding
|
|
4424
|
-
}
|
|
4421
|
+
border: s.border !== "none" && s.borderWidth !== "0px" ? s.border : null,
|
|
4422
|
+
boxShadow: s.boxShadow !== "none" ? s.boxShadow : null,
|
|
4423
|
+
padding: s.padding
|
|
4424
|
+
}
|
|
4425
4425
|
};
|
|
4426
|
-
}
|
|
4426
|
+
};
|
|
4427
4427
|
if (browser.isRef(command.selector)) {
|
|
4428
4428
|
const locator = browser.getLocator(command.selector);
|
|
4429
|
-
const element = await locator.evaluate(
|
|
4430
|
-
const fn = eval(script);
|
|
4431
|
-
return fn(el);
|
|
4432
|
-
}, extractStylesScript);
|
|
4429
|
+
const element = await locator.evaluate(extractStyles);
|
|
4433
4430
|
return successResponse(command.id, { elements: [element] });
|
|
4434
4431
|
}
|
|
4435
|
-
const elements = await page.$$eval(
|
|
4436
|
-
|
|
4437
|
-
|
|
4438
|
-
const
|
|
4439
|
-
return
|
|
4440
|
-
|
|
4441
|
-
|
|
4442
|
-
|
|
4432
|
+
const elements = await page.$$eval(command.selector, (els) => {
|
|
4433
|
+
return els.map((el) => {
|
|
4434
|
+
const s = getComputedStyle(el);
|
|
4435
|
+
const r = el.getBoundingClientRect();
|
|
4436
|
+
return {
|
|
4437
|
+
tag: el.tagName.toLowerCase(),
|
|
4438
|
+
text: el.innerText?.trim().slice(0, 80) || null,
|
|
4439
|
+
box: {
|
|
4440
|
+
x: Math.round(r.x),
|
|
4441
|
+
y: Math.round(r.y),
|
|
4442
|
+
width: Math.round(r.width),
|
|
4443
|
+
height: Math.round(r.height)
|
|
4444
|
+
},
|
|
4445
|
+
styles: {
|
|
4446
|
+
fontSize: s.fontSize,
|
|
4447
|
+
fontWeight: s.fontWeight,
|
|
4448
|
+
fontFamily: s.fontFamily.split(",")[0].trim().replace(/"/g, ""),
|
|
4449
|
+
color: s.color,
|
|
4450
|
+
backgroundColor: s.backgroundColor,
|
|
4451
|
+
borderRadius: s.borderRadius,
|
|
4452
|
+
border: s.border !== "none" && s.borderWidth !== "0px" ? s.border : null,
|
|
4453
|
+
boxShadow: s.boxShadow !== "none" ? s.boxShadow : null,
|
|
4454
|
+
padding: s.padding
|
|
4455
|
+
}
|
|
4456
|
+
};
|
|
4457
|
+
});
|
|
4458
|
+
});
|
|
4443
4459
|
return successResponse(command.id, { elements });
|
|
4444
4460
|
}
|
|
4445
|
-
async function handleVideoStart(
|
|
4446
|
-
return successResponse(
|
|
4461
|
+
async function handleVideoStart(command, browser) {
|
|
4462
|
+
return successResponse(command.id, {
|
|
4447
4463
|
note: "Video recording must be enabled at browser launch. Use --video flag when starting.",
|
|
4448
|
-
path:
|
|
4464
|
+
path: command.path
|
|
4449
4465
|
});
|
|
4450
4466
|
}
|
|
4451
|
-
async function handleVideoStop(
|
|
4452
|
-
const
|
|
4453
|
-
const video =
|
|
4467
|
+
async function handleVideoStop(command, browser) {
|
|
4468
|
+
const page = browser.getPage();
|
|
4469
|
+
const video = page.video();
|
|
4454
4470
|
if (video) {
|
|
4455
4471
|
const path5 = await video.path();
|
|
4456
|
-
return successResponse(
|
|
4472
|
+
return successResponse(command.id, { path: path5 });
|
|
4457
4473
|
}
|
|
4458
|
-
return successResponse(
|
|
4474
|
+
return successResponse(command.id, { note: "No video recording active" });
|
|
4459
4475
|
}
|
|
4460
|
-
async function handleTraceStart(
|
|
4461
|
-
await
|
|
4462
|
-
screenshots:
|
|
4463
|
-
snapshots:
|
|
4476
|
+
async function handleTraceStart(command, browser) {
|
|
4477
|
+
await browser.startTracing({
|
|
4478
|
+
screenshots: command.screenshots,
|
|
4479
|
+
snapshots: command.snapshots
|
|
4464
4480
|
});
|
|
4465
|
-
return successResponse(
|
|
4481
|
+
return successResponse(command.id, { started: true });
|
|
4466
4482
|
}
|
|
4467
|
-
async function handleTraceStop(
|
|
4468
|
-
await
|
|
4469
|
-
return successResponse(
|
|
4483
|
+
async function handleTraceStop(command, browser) {
|
|
4484
|
+
await browser.stopTracing(command.path);
|
|
4485
|
+
return successResponse(command.id, { path: command.path });
|
|
4470
4486
|
}
|
|
4471
|
-
async function handleHarStart(
|
|
4472
|
-
await
|
|
4473
|
-
|
|
4474
|
-
return successResponse(
|
|
4487
|
+
async function handleHarStart(command, browser) {
|
|
4488
|
+
await browser.startHarRecording();
|
|
4489
|
+
browser.startRequestTracking();
|
|
4490
|
+
return successResponse(command.id, { started: true });
|
|
4475
4491
|
}
|
|
4476
|
-
async function handleHarStop(
|
|
4477
|
-
const requests =
|
|
4478
|
-
return successResponse(
|
|
4479
|
-
path:
|
|
4492
|
+
async function handleHarStop(command, browser) {
|
|
4493
|
+
const requests = browser.getRequests();
|
|
4494
|
+
return successResponse(command.id, {
|
|
4495
|
+
path: command.path,
|
|
4480
4496
|
requestCount: requests.length
|
|
4481
4497
|
});
|
|
4482
4498
|
}
|
|
4483
|
-
async function handleStateSave(
|
|
4484
|
-
await
|
|
4485
|
-
return successResponse(
|
|
4499
|
+
async function handleStateSave(command, browser) {
|
|
4500
|
+
await browser.saveStorageState(command.path);
|
|
4501
|
+
return successResponse(command.id, { path: command.path });
|
|
4486
4502
|
}
|
|
4487
|
-
async function handleStateLoad(
|
|
4488
|
-
return successResponse(
|
|
4503
|
+
async function handleStateLoad(command, browser) {
|
|
4504
|
+
return successResponse(command.id, {
|
|
4489
4505
|
note: "Storage state must be loaded at browser launch. Use --state flag.",
|
|
4490
|
-
path:
|
|
4506
|
+
path: command.path
|
|
4491
4507
|
});
|
|
4492
4508
|
}
|
|
4493
|
-
async function handleConsole(
|
|
4494
|
-
if (
|
|
4495
|
-
|
|
4496
|
-
return successResponse(
|
|
4509
|
+
async function handleConsole(command, browser) {
|
|
4510
|
+
if (command.clear) {
|
|
4511
|
+
browser.clearConsoleMessages();
|
|
4512
|
+
return successResponse(command.id, { cleared: true });
|
|
4497
4513
|
}
|
|
4498
|
-
const messages =
|
|
4499
|
-
return successResponse(
|
|
4514
|
+
const messages = browser.getConsoleMessages();
|
|
4515
|
+
return successResponse(command.id, { messages });
|
|
4500
4516
|
}
|
|
4501
|
-
async function handleErrors(
|
|
4502
|
-
if (
|
|
4503
|
-
|
|
4504
|
-
return successResponse(
|
|
4517
|
+
async function handleErrors(command, browser) {
|
|
4518
|
+
if (command.clear) {
|
|
4519
|
+
browser.clearPageErrors();
|
|
4520
|
+
return successResponse(command.id, { cleared: true });
|
|
4505
4521
|
}
|
|
4506
|
-
const errors =
|
|
4507
|
-
return successResponse(
|
|
4522
|
+
const errors = browser.getPageErrors();
|
|
4523
|
+
return successResponse(command.id, { errors });
|
|
4508
4524
|
}
|
|
4509
|
-
async function handleKeyboard(
|
|
4510
|
-
const
|
|
4511
|
-
await
|
|
4512
|
-
return successResponse(
|
|
4525
|
+
async function handleKeyboard(command, browser) {
|
|
4526
|
+
const page = browser.getPage();
|
|
4527
|
+
await page.keyboard.press(command.keys);
|
|
4528
|
+
return successResponse(command.id, { pressed: command.keys });
|
|
4513
4529
|
}
|
|
4514
|
-
async function handleWheel(
|
|
4515
|
-
const
|
|
4516
|
-
if (
|
|
4517
|
-
const
|
|
4518
|
-
await
|
|
4530
|
+
async function handleWheel(command, browser) {
|
|
4531
|
+
const page = browser.getPage();
|
|
4532
|
+
if (command.selector) {
|
|
4533
|
+
const element = page.locator(command.selector);
|
|
4534
|
+
await element.hover();
|
|
4519
4535
|
}
|
|
4520
|
-
await
|
|
4521
|
-
return successResponse(
|
|
4536
|
+
await page.mouse.wheel(command.deltaX ?? 0, command.deltaY ?? 0);
|
|
4537
|
+
return successResponse(command.id, { scrolled: true });
|
|
4522
4538
|
}
|
|
4523
|
-
async function handleTap(
|
|
4524
|
-
const
|
|
4525
|
-
await
|
|
4526
|
-
return successResponse(
|
|
4539
|
+
async function handleTap(command, browser) {
|
|
4540
|
+
const page = browser.getPage();
|
|
4541
|
+
await page.tap(command.selector);
|
|
4542
|
+
return successResponse(command.id, { tapped: true });
|
|
4527
4543
|
}
|
|
4528
|
-
async function handleClipboard(
|
|
4529
|
-
const
|
|
4530
|
-
switch (
|
|
4544
|
+
async function handleClipboard(command, browser) {
|
|
4545
|
+
const page = browser.getPage();
|
|
4546
|
+
switch (command.operation) {
|
|
4531
4547
|
case "copy":
|
|
4532
|
-
await
|
|
4533
|
-
return successResponse(
|
|
4548
|
+
await page.keyboard.press("Control+c");
|
|
4549
|
+
return successResponse(command.id, { copied: true });
|
|
4534
4550
|
case "paste":
|
|
4535
|
-
await
|
|
4536
|
-
return successResponse(
|
|
4551
|
+
await page.keyboard.press("Control+v");
|
|
4552
|
+
return successResponse(command.id, { pasted: true });
|
|
4537
4553
|
case "read":
|
|
4538
|
-
const text = await
|
|
4539
|
-
return successResponse(
|
|
4554
|
+
const text = await page.evaluate("navigator.clipboard.readText()");
|
|
4555
|
+
return successResponse(command.id, { text });
|
|
4540
4556
|
default:
|
|
4541
|
-
return errorResponse(
|
|
4542
|
-
}
|
|
4543
|
-
}
|
|
4544
|
-
async function handleHighlight(
|
|
4545
|
-
const
|
|
4546
|
-
await
|
|
4547
|
-
return successResponse(
|
|
4548
|
-
}
|
|
4549
|
-
async function handleClear(
|
|
4550
|
-
const
|
|
4551
|
-
await
|
|
4552
|
-
return successResponse(
|
|
4553
|
-
}
|
|
4554
|
-
async function handleSelectAll(
|
|
4555
|
-
const
|
|
4556
|
-
await
|
|
4557
|
-
return successResponse(
|
|
4558
|
-
}
|
|
4559
|
-
async function handleInnerText(
|
|
4560
|
-
const
|
|
4561
|
-
const text = await
|
|
4562
|
-
return successResponse(
|
|
4563
|
-
}
|
|
4564
|
-
async function handleInnerHtml(
|
|
4565
|
-
const
|
|
4566
|
-
const html = await
|
|
4567
|
-
return successResponse(
|
|
4568
|
-
}
|
|
4569
|
-
async function handleInputValue(
|
|
4570
|
-
const
|
|
4571
|
-
const value = await
|
|
4572
|
-
return successResponse(
|
|
4573
|
-
}
|
|
4574
|
-
async function handleSetValue(
|
|
4575
|
-
const
|
|
4576
|
-
await
|
|
4577
|
-
return successResponse(
|
|
4578
|
-
}
|
|
4579
|
-
async function handleDispatch(
|
|
4580
|
-
const
|
|
4581
|
-
await
|
|
4582
|
-
return successResponse(
|
|
4583
|
-
}
|
|
4584
|
-
async function handleEvalHandle(
|
|
4585
|
-
const
|
|
4586
|
-
const handle = await
|
|
4557
|
+
return errorResponse(command.id, "Unknown clipboard operation");
|
|
4558
|
+
}
|
|
4559
|
+
}
|
|
4560
|
+
async function handleHighlight(command, browser) {
|
|
4561
|
+
const page = browser.getPage();
|
|
4562
|
+
await page.locator(command.selector).highlight();
|
|
4563
|
+
return successResponse(command.id, { highlighted: true });
|
|
4564
|
+
}
|
|
4565
|
+
async function handleClear(command, browser) {
|
|
4566
|
+
const page = browser.getPage();
|
|
4567
|
+
await page.locator(command.selector).clear();
|
|
4568
|
+
return successResponse(command.id, { cleared: true });
|
|
4569
|
+
}
|
|
4570
|
+
async function handleSelectAll(command, browser) {
|
|
4571
|
+
const page = browser.getPage();
|
|
4572
|
+
await page.locator(command.selector).selectText();
|
|
4573
|
+
return successResponse(command.id, { selected: true });
|
|
4574
|
+
}
|
|
4575
|
+
async function handleInnerText(command, browser) {
|
|
4576
|
+
const page = browser.getPage();
|
|
4577
|
+
const text = await page.locator(command.selector).innerText();
|
|
4578
|
+
return successResponse(command.id, { text });
|
|
4579
|
+
}
|
|
4580
|
+
async function handleInnerHtml(command, browser) {
|
|
4581
|
+
const page = browser.getPage();
|
|
4582
|
+
const html = await page.locator(command.selector).innerHTML();
|
|
4583
|
+
return successResponse(command.id, { html });
|
|
4584
|
+
}
|
|
4585
|
+
async function handleInputValue(command, browser) {
|
|
4586
|
+
const locator = browser.getLocator(command.selector);
|
|
4587
|
+
const value = await locator.inputValue();
|
|
4588
|
+
return successResponse(command.id, { value });
|
|
4589
|
+
}
|
|
4590
|
+
async function handleSetValue(command, browser) {
|
|
4591
|
+
const page = browser.getPage();
|
|
4592
|
+
await page.locator(command.selector).fill(command.value);
|
|
4593
|
+
return successResponse(command.id, { set: true });
|
|
4594
|
+
}
|
|
4595
|
+
async function handleDispatch(command, browser) {
|
|
4596
|
+
const page = browser.getPage();
|
|
4597
|
+
await page.locator(command.selector).dispatchEvent(command.event, command.eventInit);
|
|
4598
|
+
return successResponse(command.id, { dispatched: command.event });
|
|
4599
|
+
}
|
|
4600
|
+
async function handleEvalHandle(command, browser) {
|
|
4601
|
+
const page = browser.getPage();
|
|
4602
|
+
const handle = await page.evaluateHandle(command.script);
|
|
4587
4603
|
const result = await handle.jsonValue().catch(() => "Handle (non-serializable)");
|
|
4588
|
-
return successResponse(
|
|
4604
|
+
return successResponse(command.id, { result });
|
|
4589
4605
|
}
|
|
4590
|
-
async function handleExpose(
|
|
4591
|
-
const
|
|
4592
|
-
await
|
|
4593
|
-
return `Function ${
|
|
4606
|
+
async function handleExpose(command, browser) {
|
|
4607
|
+
const page = browser.getPage();
|
|
4608
|
+
await page.exposeFunction(command.name, () => {
|
|
4609
|
+
return `Function ${command.name} called`;
|
|
4594
4610
|
});
|
|
4595
|
-
return successResponse(
|
|
4596
|
-
}
|
|
4597
|
-
async function handleAddScript(
|
|
4598
|
-
const
|
|
4599
|
-
if (
|
|
4600
|
-
await
|
|
4601
|
-
} else if (
|
|
4602
|
-
await
|
|
4603
|
-
}
|
|
4604
|
-
return successResponse(
|
|
4605
|
-
}
|
|
4606
|
-
async function handleAddStyle(
|
|
4607
|
-
const
|
|
4608
|
-
if (
|
|
4609
|
-
await
|
|
4610
|
-
} else if (
|
|
4611
|
-
await
|
|
4612
|
-
}
|
|
4613
|
-
return successResponse(
|
|
4614
|
-
}
|
|
4615
|
-
async function handleEmulateMedia(
|
|
4616
|
-
const
|
|
4617
|
-
await
|
|
4618
|
-
media:
|
|
4619
|
-
colorScheme:
|
|
4620
|
-
reducedMotion:
|
|
4621
|
-
forcedColors:
|
|
4611
|
+
return successResponse(command.id, { exposed: command.name });
|
|
4612
|
+
}
|
|
4613
|
+
async function handleAddScript(command, browser) {
|
|
4614
|
+
const page = browser.getPage();
|
|
4615
|
+
if (command.content) {
|
|
4616
|
+
await page.addScriptTag({ content: command.content });
|
|
4617
|
+
} else if (command.url) {
|
|
4618
|
+
await page.addScriptTag({ url: command.url });
|
|
4619
|
+
}
|
|
4620
|
+
return successResponse(command.id, { added: true });
|
|
4621
|
+
}
|
|
4622
|
+
async function handleAddStyle(command, browser) {
|
|
4623
|
+
const page = browser.getPage();
|
|
4624
|
+
if (command.content) {
|
|
4625
|
+
await page.addStyleTag({ content: command.content });
|
|
4626
|
+
} else if (command.url) {
|
|
4627
|
+
await page.addStyleTag({ url: command.url });
|
|
4628
|
+
}
|
|
4629
|
+
return successResponse(command.id, { added: true });
|
|
4630
|
+
}
|
|
4631
|
+
async function handleEmulateMedia(command, browser) {
|
|
4632
|
+
const page = browser.getPage();
|
|
4633
|
+
await page.emulateMedia({
|
|
4634
|
+
media: command.media,
|
|
4635
|
+
colorScheme: command.colorScheme,
|
|
4636
|
+
reducedMotion: command.reducedMotion,
|
|
4637
|
+
forcedColors: command.forcedColors
|
|
4622
4638
|
});
|
|
4623
|
-
return successResponse(
|
|
4639
|
+
return successResponse(command.id, { emulated: true });
|
|
4624
4640
|
}
|
|
4625
|
-
async function handleOffline(
|
|
4626
|
-
await
|
|
4627
|
-
return successResponse(
|
|
4641
|
+
async function handleOffline(command, browser) {
|
|
4642
|
+
await browser.setOffline(command.offline);
|
|
4643
|
+
return successResponse(command.id, { offline: command.offline });
|
|
4628
4644
|
}
|
|
4629
|
-
async function handleHeaders(
|
|
4630
|
-
await
|
|
4631
|
-
return successResponse(
|
|
4645
|
+
async function handleHeaders(command, browser) {
|
|
4646
|
+
await browser.setExtraHeaders(command.headers);
|
|
4647
|
+
return successResponse(command.id, { set: true });
|
|
4632
4648
|
}
|
|
4633
|
-
async function handlePause(
|
|
4634
|
-
const
|
|
4635
|
-
await
|
|
4636
|
-
return successResponse(
|
|
4649
|
+
async function handlePause(command, browser) {
|
|
4650
|
+
const page = browser.getPage();
|
|
4651
|
+
await page.pause();
|
|
4652
|
+
return successResponse(command.id, { paused: true });
|
|
4637
4653
|
}
|
|
4638
|
-
async function handleGetByAltText(
|
|
4639
|
-
const
|
|
4640
|
-
const
|
|
4641
|
-
switch (
|
|
4654
|
+
async function handleGetByAltText(command, browser) {
|
|
4655
|
+
const page = browser.getPage();
|
|
4656
|
+
const locator = page.getByAltText(command.text, { exact: command.exact });
|
|
4657
|
+
switch (command.subaction) {
|
|
4642
4658
|
case "click":
|
|
4643
|
-
await
|
|
4644
|
-
return successResponse(
|
|
4659
|
+
await locator.click();
|
|
4660
|
+
return successResponse(command.id, { clicked: true });
|
|
4645
4661
|
case "hover":
|
|
4646
|
-
await
|
|
4647
|
-
return successResponse(
|
|
4662
|
+
await locator.hover();
|
|
4663
|
+
return successResponse(command.id, { hovered: true });
|
|
4648
4664
|
}
|
|
4649
4665
|
}
|
|
4650
|
-
async function handleGetByTitle(
|
|
4651
|
-
const
|
|
4652
|
-
const
|
|
4653
|
-
switch (
|
|
4666
|
+
async function handleGetByTitle(command, browser) {
|
|
4667
|
+
const page = browser.getPage();
|
|
4668
|
+
const locator = page.getByTitle(command.text, { exact: command.exact });
|
|
4669
|
+
switch (command.subaction) {
|
|
4654
4670
|
case "click":
|
|
4655
|
-
await
|
|
4656
|
-
return successResponse(
|
|
4671
|
+
await locator.click();
|
|
4672
|
+
return successResponse(command.id, { clicked: true });
|
|
4657
4673
|
case "hover":
|
|
4658
|
-
await
|
|
4659
|
-
return successResponse(
|
|
4674
|
+
await locator.hover();
|
|
4675
|
+
return successResponse(command.id, { hovered: true });
|
|
4660
4676
|
}
|
|
4661
4677
|
}
|
|
4662
|
-
async function handleGetByTestId(
|
|
4663
|
-
const
|
|
4664
|
-
const
|
|
4665
|
-
switch (
|
|
4678
|
+
async function handleGetByTestId(command, browser) {
|
|
4679
|
+
const page = browser.getPage();
|
|
4680
|
+
const locator = page.getByTestId(command.testId);
|
|
4681
|
+
switch (command.subaction) {
|
|
4666
4682
|
case "click":
|
|
4667
|
-
await
|
|
4668
|
-
return successResponse(
|
|
4683
|
+
await locator.click();
|
|
4684
|
+
return successResponse(command.id, { clicked: true });
|
|
4669
4685
|
case "fill":
|
|
4670
|
-
await
|
|
4671
|
-
return successResponse(
|
|
4686
|
+
await locator.fill(command.value ?? "");
|
|
4687
|
+
return successResponse(command.id, { filled: true });
|
|
4672
4688
|
case "check":
|
|
4673
|
-
await
|
|
4674
|
-
return successResponse(
|
|
4689
|
+
await locator.check();
|
|
4690
|
+
return successResponse(command.id, { checked: true });
|
|
4675
4691
|
case "hover":
|
|
4676
|
-
await
|
|
4677
|
-
return successResponse(
|
|
4692
|
+
await locator.hover();
|
|
4693
|
+
return successResponse(command.id, { hovered: true });
|
|
4678
4694
|
}
|
|
4679
4695
|
}
|
|
4680
|
-
async function handleNth(
|
|
4681
|
-
const
|
|
4682
|
-
const base =
|
|
4683
|
-
const
|
|
4684
|
-
switch (
|
|
4696
|
+
async function handleNth(command, browser) {
|
|
4697
|
+
const page = browser.getPage();
|
|
4698
|
+
const base = page.locator(command.selector);
|
|
4699
|
+
const locator = command.index === -1 ? base.last() : base.nth(command.index);
|
|
4700
|
+
switch (command.subaction) {
|
|
4685
4701
|
case "click":
|
|
4686
|
-
await
|
|
4687
|
-
return successResponse(
|
|
4702
|
+
await locator.click();
|
|
4703
|
+
return successResponse(command.id, { clicked: true });
|
|
4688
4704
|
case "fill":
|
|
4689
|
-
await
|
|
4690
|
-
return successResponse(
|
|
4705
|
+
await locator.fill(command.value ?? "");
|
|
4706
|
+
return successResponse(command.id, { filled: true });
|
|
4691
4707
|
case "check":
|
|
4692
|
-
await
|
|
4693
|
-
return successResponse(
|
|
4708
|
+
await locator.check();
|
|
4709
|
+
return successResponse(command.id, { checked: true });
|
|
4694
4710
|
case "hover":
|
|
4695
|
-
await
|
|
4696
|
-
return successResponse(
|
|
4711
|
+
await locator.hover();
|
|
4712
|
+
return successResponse(command.id, { hovered: true });
|
|
4697
4713
|
case "text":
|
|
4698
|
-
const text = await
|
|
4699
|
-
return successResponse(
|
|
4714
|
+
const text = await locator.textContent();
|
|
4715
|
+
return successResponse(command.id, { text });
|
|
4700
4716
|
}
|
|
4701
4717
|
}
|
|
4702
|
-
async function handleWaitForUrl(
|
|
4703
|
-
const
|
|
4704
|
-
await
|
|
4705
|
-
return successResponse(
|
|
4718
|
+
async function handleWaitForUrl(command, browser) {
|
|
4719
|
+
const page = browser.getPage();
|
|
4720
|
+
await page.waitForURL(command.url, { timeout: command.timeout });
|
|
4721
|
+
return successResponse(command.id, { url: page.url() });
|
|
4706
4722
|
}
|
|
4707
|
-
async function handleWaitForLoadState(
|
|
4708
|
-
const
|
|
4709
|
-
await
|
|
4710
|
-
return successResponse(
|
|
4723
|
+
async function handleWaitForLoadState(command, browser) {
|
|
4724
|
+
const page = browser.getPage();
|
|
4725
|
+
await page.waitForLoadState(command.state, { timeout: command.timeout });
|
|
4726
|
+
return successResponse(command.id, { state: command.state });
|
|
4711
4727
|
}
|
|
4712
|
-
async function handleSetContent(
|
|
4713
|
-
const
|
|
4714
|
-
await
|
|
4715
|
-
return successResponse(
|
|
4728
|
+
async function handleSetContent(command, browser) {
|
|
4729
|
+
const page = browser.getPage();
|
|
4730
|
+
await page.setContent(command.html);
|
|
4731
|
+
return successResponse(command.id, { set: true });
|
|
4716
4732
|
}
|
|
4717
|
-
async function handleTimezone(
|
|
4718
|
-
const
|
|
4719
|
-
await
|
|
4720
|
-
return successResponse(
|
|
4733
|
+
async function handleTimezone(command, browser) {
|
|
4734
|
+
const page = browser.getPage();
|
|
4735
|
+
await page.context().setGeolocation({ latitude: 0, longitude: 0 });
|
|
4736
|
+
return successResponse(command.id, {
|
|
4721
4737
|
note: "Timezone must be set at browser launch. Use --timezone flag.",
|
|
4722
|
-
timezone:
|
|
4738
|
+
timezone: command.timezone
|
|
4723
4739
|
});
|
|
4724
4740
|
}
|
|
4725
|
-
async function handleLocale(
|
|
4726
|
-
return successResponse(
|
|
4741
|
+
async function handleLocale(command, browser) {
|
|
4742
|
+
return successResponse(command.id, {
|
|
4727
4743
|
note: "Locale must be set at browser launch. Use --locale flag.",
|
|
4728
|
-
locale:
|
|
4744
|
+
locale: command.locale
|
|
4729
4745
|
});
|
|
4730
4746
|
}
|
|
4731
|
-
async function handleCredentials(
|
|
4732
|
-
const context =
|
|
4747
|
+
async function handleCredentials(command, browser) {
|
|
4748
|
+
const context = browser.getPage().context();
|
|
4733
4749
|
await context.setHTTPCredentials({
|
|
4734
|
-
username:
|
|
4735
|
-
password:
|
|
4750
|
+
username: command.username,
|
|
4751
|
+
password: command.password
|
|
4736
4752
|
});
|
|
4737
|
-
return successResponse(
|
|
4738
|
-
}
|
|
4739
|
-
async function handleMouseMove(
|
|
4740
|
-
const
|
|
4741
|
-
await
|
|
4742
|
-
return successResponse(
|
|
4743
|
-
}
|
|
4744
|
-
async function handleMouseDown(
|
|
4745
|
-
const
|
|
4746
|
-
await
|
|
4747
|
-
return successResponse(
|
|
4748
|
-
}
|
|
4749
|
-
async function handleMouseUp(
|
|
4750
|
-
const
|
|
4751
|
-
await
|
|
4752
|
-
return successResponse(
|
|
4753
|
-
}
|
|
4754
|
-
async function handleBringToFront(
|
|
4755
|
-
const
|
|
4756
|
-
await
|
|
4757
|
-
return successResponse(
|
|
4758
|
-
}
|
|
4759
|
-
async function handleWaitForFunction(
|
|
4760
|
-
const
|
|
4761
|
-
await
|
|
4762
|
-
return successResponse(
|
|
4763
|
-
}
|
|
4764
|
-
async function handleScrollIntoView(
|
|
4765
|
-
const
|
|
4766
|
-
await
|
|
4767
|
-
return successResponse(
|
|
4768
|
-
}
|
|
4769
|
-
async function handleAddInitScript(
|
|
4770
|
-
const context =
|
|
4771
|
-
await context.addInitScript(
|
|
4772
|
-
return successResponse(
|
|
4773
|
-
}
|
|
4774
|
-
async function handleKeyDown(
|
|
4775
|
-
const
|
|
4776
|
-
await
|
|
4777
|
-
return successResponse(
|
|
4778
|
-
}
|
|
4779
|
-
async function handleKeyUp(
|
|
4780
|
-
const
|
|
4781
|
-
await
|
|
4782
|
-
return successResponse(
|
|
4783
|
-
}
|
|
4784
|
-
async function handleInsertText(
|
|
4785
|
-
const
|
|
4786
|
-
await
|
|
4787
|
-
return successResponse(
|
|
4788
|
-
}
|
|
4789
|
-
async function handleMultiSelect(
|
|
4790
|
-
const
|
|
4791
|
-
const selected = await
|
|
4792
|
-
return successResponse(
|
|
4793
|
-
}
|
|
4794
|
-
async function handleWaitForDownload(
|
|
4795
|
-
const
|
|
4796
|
-
const download = await
|
|
4753
|
+
return successResponse(command.id, { set: true });
|
|
4754
|
+
}
|
|
4755
|
+
async function handleMouseMove(command, browser) {
|
|
4756
|
+
const page = browser.getPage();
|
|
4757
|
+
await page.mouse.move(command.x, command.y);
|
|
4758
|
+
return successResponse(command.id, { moved: true, x: command.x, y: command.y });
|
|
4759
|
+
}
|
|
4760
|
+
async function handleMouseDown(command, browser) {
|
|
4761
|
+
const page = browser.getPage();
|
|
4762
|
+
await page.mouse.down({ button: command.button ?? "left" });
|
|
4763
|
+
return successResponse(command.id, { down: true });
|
|
4764
|
+
}
|
|
4765
|
+
async function handleMouseUp(command, browser) {
|
|
4766
|
+
const page = browser.getPage();
|
|
4767
|
+
await page.mouse.up({ button: command.button ?? "left" });
|
|
4768
|
+
return successResponse(command.id, { up: true });
|
|
4769
|
+
}
|
|
4770
|
+
async function handleBringToFront(command, browser) {
|
|
4771
|
+
const page = browser.getPage();
|
|
4772
|
+
await page.bringToFront();
|
|
4773
|
+
return successResponse(command.id, { focused: true });
|
|
4774
|
+
}
|
|
4775
|
+
async function handleWaitForFunction(command, browser) {
|
|
4776
|
+
const page = browser.getPage();
|
|
4777
|
+
await page.waitForFunction(command.expression, { timeout: command.timeout });
|
|
4778
|
+
return successResponse(command.id, { waited: true });
|
|
4779
|
+
}
|
|
4780
|
+
async function handleScrollIntoView(command, browser) {
|
|
4781
|
+
const page = browser.getPage();
|
|
4782
|
+
await page.locator(command.selector).scrollIntoViewIfNeeded();
|
|
4783
|
+
return successResponse(command.id, { scrolled: true });
|
|
4784
|
+
}
|
|
4785
|
+
async function handleAddInitScript(command, browser) {
|
|
4786
|
+
const context = browser.getPage().context();
|
|
4787
|
+
await context.addInitScript(command.script);
|
|
4788
|
+
return successResponse(command.id, { added: true });
|
|
4789
|
+
}
|
|
4790
|
+
async function handleKeyDown(command, browser) {
|
|
4791
|
+
const page = browser.getPage();
|
|
4792
|
+
await page.keyboard.down(command.key);
|
|
4793
|
+
return successResponse(command.id, { down: true, key: command.key });
|
|
4794
|
+
}
|
|
4795
|
+
async function handleKeyUp(command, browser) {
|
|
4796
|
+
const page = browser.getPage();
|
|
4797
|
+
await page.keyboard.up(command.key);
|
|
4798
|
+
return successResponse(command.id, { up: true, key: command.key });
|
|
4799
|
+
}
|
|
4800
|
+
async function handleInsertText(command, browser) {
|
|
4801
|
+
const page = browser.getPage();
|
|
4802
|
+
await page.keyboard.insertText(command.text);
|
|
4803
|
+
return successResponse(command.id, { inserted: true });
|
|
4804
|
+
}
|
|
4805
|
+
async function handleMultiSelect(command, browser) {
|
|
4806
|
+
const page = browser.getPage();
|
|
4807
|
+
const selected = await page.locator(command.selector).selectOption(command.values);
|
|
4808
|
+
return successResponse(command.id, { selected });
|
|
4809
|
+
}
|
|
4810
|
+
async function handleWaitForDownload(command, browser) {
|
|
4811
|
+
const page = browser.getPage();
|
|
4812
|
+
const download = await page.waitForEvent("download", { timeout: command.timeout });
|
|
4797
4813
|
let filePath;
|
|
4798
|
-
if (
|
|
4799
|
-
filePath =
|
|
4814
|
+
if (command.path) {
|
|
4815
|
+
filePath = command.path;
|
|
4800
4816
|
await download.saveAs(filePath);
|
|
4801
4817
|
} else {
|
|
4802
4818
|
filePath = await download.path() || download.suggestedFilename();
|
|
4803
4819
|
}
|
|
4804
|
-
return successResponse(
|
|
4820
|
+
return successResponse(command.id, {
|
|
4805
4821
|
path: filePath,
|
|
4806
4822
|
filename: download.suggestedFilename(),
|
|
4807
4823
|
url: download.url()
|
|
4808
4824
|
});
|
|
4809
4825
|
}
|
|
4810
|
-
async function handleResponseBody(
|
|
4811
|
-
const
|
|
4812
|
-
const response = await
|
|
4813
|
-
timeout:
|
|
4826
|
+
async function handleResponseBody(command, browser) {
|
|
4827
|
+
const page = browser.getPage();
|
|
4828
|
+
const response = await page.waitForResponse((resp) => resp.url().includes(command.url), {
|
|
4829
|
+
timeout: command.timeout
|
|
4814
4830
|
});
|
|
4815
4831
|
const body = await response.text();
|
|
4816
4832
|
let parsed = body;
|
|
@@ -4818,80 +4834,80 @@ async function handleResponseBody(command2, browser2) {
|
|
|
4818
4834
|
parsed = JSON.parse(body);
|
|
4819
4835
|
} catch {
|
|
4820
4836
|
}
|
|
4821
|
-
return successResponse(
|
|
4837
|
+
return successResponse(command.id, {
|
|
4822
4838
|
url: response.url(),
|
|
4823
4839
|
status: response.status(),
|
|
4824
4840
|
body: parsed
|
|
4825
4841
|
});
|
|
4826
4842
|
}
|
|
4827
|
-
async function handleScreencastStart(
|
|
4843
|
+
async function handleScreencastStart(command, browser) {
|
|
4828
4844
|
if (!screencastFrameCallback) {
|
|
4829
4845
|
throw new Error("Screencast frame callback not set. Start the streaming server first.");
|
|
4830
4846
|
}
|
|
4831
|
-
await
|
|
4832
|
-
format:
|
|
4833
|
-
quality:
|
|
4834
|
-
maxWidth:
|
|
4835
|
-
maxHeight:
|
|
4836
|
-
everyNthFrame:
|
|
4847
|
+
await browser.startScreencast(screencastFrameCallback, {
|
|
4848
|
+
format: command.format,
|
|
4849
|
+
quality: command.quality,
|
|
4850
|
+
maxWidth: command.maxWidth,
|
|
4851
|
+
maxHeight: command.maxHeight,
|
|
4852
|
+
everyNthFrame: command.everyNthFrame
|
|
4837
4853
|
});
|
|
4838
|
-
return successResponse(
|
|
4854
|
+
return successResponse(command.id, {
|
|
4839
4855
|
started: true,
|
|
4840
|
-
format:
|
|
4841
|
-
quality:
|
|
4856
|
+
format: command.format ?? "jpeg",
|
|
4857
|
+
quality: command.quality ?? 80
|
|
4842
4858
|
});
|
|
4843
4859
|
}
|
|
4844
|
-
async function handleScreencastStop(
|
|
4845
|
-
await
|
|
4846
|
-
return successResponse(
|
|
4847
|
-
}
|
|
4848
|
-
async function handleInputMouse(
|
|
4849
|
-
await
|
|
4850
|
-
type:
|
|
4851
|
-
x:
|
|
4852
|
-
y:
|
|
4853
|
-
button:
|
|
4854
|
-
clickCount:
|
|
4855
|
-
deltaX:
|
|
4856
|
-
deltaY:
|
|
4857
|
-
modifiers:
|
|
4860
|
+
async function handleScreencastStop(command, browser) {
|
|
4861
|
+
await browser.stopScreencast();
|
|
4862
|
+
return successResponse(command.id, { stopped: true });
|
|
4863
|
+
}
|
|
4864
|
+
async function handleInputMouse(command, browser) {
|
|
4865
|
+
await browser.injectMouseEvent({
|
|
4866
|
+
type: command.type,
|
|
4867
|
+
x: command.x,
|
|
4868
|
+
y: command.y,
|
|
4869
|
+
button: command.button,
|
|
4870
|
+
clickCount: command.clickCount,
|
|
4871
|
+
deltaX: command.deltaX,
|
|
4872
|
+
deltaY: command.deltaY,
|
|
4873
|
+
modifiers: command.modifiers
|
|
4858
4874
|
});
|
|
4859
|
-
return successResponse(
|
|
4860
|
-
}
|
|
4861
|
-
async function handleInputKeyboard(
|
|
4862
|
-
await
|
|
4863
|
-
type:
|
|
4864
|
-
key:
|
|
4865
|
-
code:
|
|
4866
|
-
text:
|
|
4867
|
-
modifiers:
|
|
4875
|
+
return successResponse(command.id, { injected: true });
|
|
4876
|
+
}
|
|
4877
|
+
async function handleInputKeyboard(command, browser) {
|
|
4878
|
+
await browser.injectKeyboardEvent({
|
|
4879
|
+
type: command.type,
|
|
4880
|
+
key: command.key,
|
|
4881
|
+
code: command.code,
|
|
4882
|
+
text: command.text,
|
|
4883
|
+
modifiers: command.modifiers
|
|
4868
4884
|
});
|
|
4869
|
-
return successResponse(
|
|
4885
|
+
return successResponse(command.id, { injected: true });
|
|
4870
4886
|
}
|
|
4871
|
-
async function handleInputTouch(
|
|
4872
|
-
await
|
|
4873
|
-
type:
|
|
4874
|
-
touchPoints:
|
|
4875
|
-
modifiers:
|
|
4887
|
+
async function handleInputTouch(command, browser) {
|
|
4888
|
+
await browser.injectTouchEvent({
|
|
4889
|
+
type: command.type,
|
|
4890
|
+
touchPoints: command.touchPoints,
|
|
4891
|
+
modifiers: command.modifiers
|
|
4876
4892
|
});
|
|
4877
|
-
return successResponse(
|
|
4893
|
+
return successResponse(command.id, { injected: true });
|
|
4878
4894
|
}
|
|
4879
|
-
async function handleRecordingStart(
|
|
4880
|
-
await
|
|
4881
|
-
return successResponse(
|
|
4895
|
+
async function handleRecordingStart(command, browser) {
|
|
4896
|
+
await browser.startRecording(command.path, command.url);
|
|
4897
|
+
return successResponse(command.id, {
|
|
4882
4898
|
started: true,
|
|
4883
|
-
path:
|
|
4899
|
+
path: command.path
|
|
4884
4900
|
});
|
|
4885
4901
|
}
|
|
4886
|
-
async function handleRecordingStop(
|
|
4887
|
-
const result = await
|
|
4888
|
-
return successResponse(
|
|
4902
|
+
async function handleRecordingStop(command, browser) {
|
|
4903
|
+
const result = await browser.stopRecording();
|
|
4904
|
+
return successResponse(command.id, result);
|
|
4889
4905
|
}
|
|
4890
|
-
async function handleRecordingRestart(
|
|
4891
|
-
const result = await
|
|
4892
|
-
return successResponse(
|
|
4906
|
+
async function handleRecordingRestart(command, browser) {
|
|
4907
|
+
const result = await browser.restartRecording(command.path, command.url);
|
|
4908
|
+
return successResponse(command.id, {
|
|
4893
4909
|
started: true,
|
|
4894
|
-
path:
|
|
4910
|
+
path: command.path,
|
|
4895
4911
|
previousPath: result.previousPath,
|
|
4896
4912
|
stopped: result.stopped
|
|
4897
4913
|
});
|
|
@@ -4904,12 +4920,12 @@ function successResponse2(id, data) {
|
|
|
4904
4920
|
function errorResponse2(id, error) {
|
|
4905
4921
|
return { id, success: false, error };
|
|
4906
4922
|
}
|
|
4907
|
-
async function executeIOSCommand(
|
|
4908
|
-
const { id, action } =
|
|
4923
|
+
async function executeIOSCommand(command, manager) {
|
|
4924
|
+
const { id, action } = command;
|
|
4909
4925
|
try {
|
|
4910
4926
|
switch (action) {
|
|
4911
4927
|
case "launch": {
|
|
4912
|
-
const cmd =
|
|
4928
|
+
const cmd = command;
|
|
4913
4929
|
await manager.launch({
|
|
4914
4930
|
device: cmd.device,
|
|
4915
4931
|
udid: cmd.udid
|
|
@@ -4922,22 +4938,22 @@ async function executeIOSCommand(command2, manager) {
|
|
|
4922
4938
|
});
|
|
4923
4939
|
}
|
|
4924
4940
|
case "navigate": {
|
|
4925
|
-
const cmd =
|
|
4941
|
+
const cmd = command;
|
|
4926
4942
|
const result = await manager.navigate(cmd.url);
|
|
4927
4943
|
return successResponse2(id, result);
|
|
4928
4944
|
}
|
|
4929
4945
|
case "click": {
|
|
4930
|
-
const cmd =
|
|
4946
|
+
const cmd = command;
|
|
4931
4947
|
await manager.click(cmd.selector);
|
|
4932
4948
|
return successResponse2(id, { clicked: true });
|
|
4933
4949
|
}
|
|
4934
4950
|
case "tap": {
|
|
4935
|
-
const cmd =
|
|
4951
|
+
const cmd = command;
|
|
4936
4952
|
await manager.tap(cmd.selector);
|
|
4937
4953
|
return successResponse2(id, { tapped: true });
|
|
4938
4954
|
}
|
|
4939
4955
|
case "type": {
|
|
4940
|
-
const cmd =
|
|
4956
|
+
const cmd = command;
|
|
4941
4957
|
await manager.type(cmd.selector, cmd.text, {
|
|
4942
4958
|
delay: cmd.delay,
|
|
4943
4959
|
clear: cmd.clear
|
|
@@ -4945,12 +4961,12 @@ async function executeIOSCommand(command2, manager) {
|
|
|
4945
4961
|
return successResponse2(id, { typed: true });
|
|
4946
4962
|
}
|
|
4947
4963
|
case "fill": {
|
|
4948
|
-
const cmd =
|
|
4964
|
+
const cmd = command;
|
|
4949
4965
|
await manager.fill(cmd.selector, cmd.value);
|
|
4950
4966
|
return successResponse2(id, { filled: true });
|
|
4951
4967
|
}
|
|
4952
4968
|
case "screenshot": {
|
|
4953
|
-
const cmd =
|
|
4969
|
+
const cmd = command;
|
|
4954
4970
|
const result = await manager.screenshot({
|
|
4955
4971
|
path: cmd.path,
|
|
4956
4972
|
fullPage: cmd.fullPage
|
|
@@ -4958,14 +4974,14 @@ async function executeIOSCommand(command2, manager) {
|
|
|
4958
4974
|
return successResponse2(id, result);
|
|
4959
4975
|
}
|
|
4960
4976
|
case "snapshot": {
|
|
4961
|
-
const cmd =
|
|
4977
|
+
const cmd = command;
|
|
4962
4978
|
const result = await manager.getSnapshot({
|
|
4963
4979
|
interactive: cmd.interactive
|
|
4964
4980
|
});
|
|
4965
4981
|
return successResponse2(id, { snapshot: result.tree, refs: result.refs });
|
|
4966
4982
|
}
|
|
4967
4983
|
case "scroll": {
|
|
4968
|
-
const cmd =
|
|
4984
|
+
const cmd = command;
|
|
4969
4985
|
await manager.scroll({
|
|
4970
4986
|
selector: cmd.selector,
|
|
4971
4987
|
x: cmd.x,
|
|
@@ -4976,17 +4992,17 @@ async function executeIOSCommand(command2, manager) {
|
|
|
4976
4992
|
return successResponse2(id, { scrolled: true });
|
|
4977
4993
|
}
|
|
4978
4994
|
case "swipe": {
|
|
4979
|
-
const cmd =
|
|
4995
|
+
const cmd = command;
|
|
4980
4996
|
await manager.swipe(cmd.direction, { distance: cmd.distance });
|
|
4981
4997
|
return successResponse2(id, { swiped: true });
|
|
4982
4998
|
}
|
|
4983
4999
|
case "evaluate": {
|
|
4984
|
-
const cmd =
|
|
5000
|
+
const cmd = command;
|
|
4985
5001
|
const result = await manager.evaluate(cmd.script, ...cmd.args ?? []);
|
|
4986
5002
|
return successResponse2(id, { result });
|
|
4987
5003
|
}
|
|
4988
5004
|
case "wait": {
|
|
4989
|
-
const cmd =
|
|
5005
|
+
const cmd = command;
|
|
4990
5006
|
await manager.wait({
|
|
4991
5007
|
selector: cmd.selector,
|
|
4992
5008
|
timeout: cmd.timeout,
|
|
@@ -4995,37 +5011,37 @@ async function executeIOSCommand(command2, manager) {
|
|
|
4995
5011
|
return successResponse2(id, { waited: true });
|
|
4996
5012
|
}
|
|
4997
5013
|
case "press": {
|
|
4998
|
-
const cmd =
|
|
5014
|
+
const cmd = command;
|
|
4999
5015
|
await manager.press(cmd.key);
|
|
5000
5016
|
return successResponse2(id, { pressed: true });
|
|
5001
5017
|
}
|
|
5002
5018
|
case "hover": {
|
|
5003
|
-
const cmd =
|
|
5019
|
+
const cmd = command;
|
|
5004
5020
|
await manager.hover(cmd.selector);
|
|
5005
5021
|
return successResponse2(id, { hovered: true });
|
|
5006
5022
|
}
|
|
5007
5023
|
case "content": {
|
|
5008
|
-
const cmd =
|
|
5024
|
+
const cmd = command;
|
|
5009
5025
|
const html = await manager.getContent(cmd.selector);
|
|
5010
5026
|
return successResponse2(id, { html });
|
|
5011
5027
|
}
|
|
5012
5028
|
case "gettext": {
|
|
5013
|
-
const cmd =
|
|
5029
|
+
const cmd = command;
|
|
5014
5030
|
const text = await manager.getText(cmd.selector);
|
|
5015
5031
|
return successResponse2(id, { text });
|
|
5016
5032
|
}
|
|
5017
5033
|
case "getattribute": {
|
|
5018
|
-
const cmd =
|
|
5034
|
+
const cmd = command;
|
|
5019
5035
|
const value = await manager.getAttribute(cmd.selector, cmd.attribute);
|
|
5020
5036
|
return successResponse2(id, { value });
|
|
5021
5037
|
}
|
|
5022
5038
|
case "isvisible": {
|
|
5023
|
-
const cmd =
|
|
5039
|
+
const cmd = command;
|
|
5024
5040
|
const visible = await manager.isVisible(cmd.selector);
|
|
5025
5041
|
return successResponse2(id, { visible });
|
|
5026
5042
|
}
|
|
5027
5043
|
case "isenabled": {
|
|
5028
|
-
const cmd =
|
|
5044
|
+
const cmd = command;
|
|
5029
5045
|
const enabled = await manager.isEnabled(cmd.selector);
|
|
5030
5046
|
return successResponse2(id, { enabled });
|
|
5031
5047
|
}
|
|
@@ -5050,37 +5066,37 @@ async function executeIOSCommand(command2, manager) {
|
|
|
5050
5066
|
return successResponse2(id, { reloaded: true });
|
|
5051
5067
|
}
|
|
5052
5068
|
case "select": {
|
|
5053
|
-
const cmd =
|
|
5069
|
+
const cmd = command;
|
|
5054
5070
|
await manager.select(cmd.selector, cmd.values);
|
|
5055
5071
|
return successResponse2(id, { selected: true });
|
|
5056
5072
|
}
|
|
5057
5073
|
case "check": {
|
|
5058
|
-
const cmd =
|
|
5074
|
+
const cmd = command;
|
|
5059
5075
|
await manager.check(cmd.selector);
|
|
5060
5076
|
return successResponse2(id, { checked: true });
|
|
5061
5077
|
}
|
|
5062
5078
|
case "uncheck": {
|
|
5063
|
-
const cmd =
|
|
5079
|
+
const cmd = command;
|
|
5064
5080
|
await manager.uncheck(cmd.selector);
|
|
5065
5081
|
return successResponse2(id, { unchecked: true });
|
|
5066
5082
|
}
|
|
5067
5083
|
case "focus": {
|
|
5068
|
-
const cmd =
|
|
5084
|
+
const cmd = command;
|
|
5069
5085
|
await manager.focus(cmd.selector);
|
|
5070
5086
|
return successResponse2(id, { focused: true });
|
|
5071
5087
|
}
|
|
5072
5088
|
case "clear": {
|
|
5073
|
-
const cmd =
|
|
5089
|
+
const cmd = command;
|
|
5074
5090
|
await manager.clear(cmd.selector);
|
|
5075
5091
|
return successResponse2(id, { cleared: true });
|
|
5076
5092
|
}
|
|
5077
5093
|
case "count": {
|
|
5078
|
-
const cmd =
|
|
5094
|
+
const cmd = command;
|
|
5079
5095
|
const count = await manager.count(cmd.selector);
|
|
5080
5096
|
return successResponse2(id, { count });
|
|
5081
5097
|
}
|
|
5082
5098
|
case "boundingbox": {
|
|
5083
|
-
const cmd =
|
|
5099
|
+
const cmd = command;
|
|
5084
5100
|
const box = await manager.getBoundingBox(cmd.selector);
|
|
5085
5101
|
return successResponse2(id, { box });
|
|
5086
5102
|
}
|
|
@@ -5146,8 +5162,8 @@ var StreamServer = class {
|
|
|
5146
5162
|
browser;
|
|
5147
5163
|
port;
|
|
5148
5164
|
isScreencasting = false;
|
|
5149
|
-
constructor(
|
|
5150
|
-
this.browser =
|
|
5165
|
+
constructor(browser, port = 9223) {
|
|
5166
|
+
this.browser = browser;
|
|
5151
5167
|
this.port = port;
|
|
5152
5168
|
}
|
|
5153
5169
|
/**
|
|
@@ -5310,8 +5326,8 @@ var StreamServer = class {
|
|
|
5310
5326
|
let viewportWidth;
|
|
5311
5327
|
let viewportHeight;
|
|
5312
5328
|
try {
|
|
5313
|
-
const
|
|
5314
|
-
const viewport =
|
|
5329
|
+
const page = this.browser.getPage();
|
|
5330
|
+
const viewport = page.viewportSize();
|
|
5315
5331
|
viewportWidth = viewport?.width;
|
|
5316
5332
|
viewportHeight = viewport?.height;
|
|
5317
5333
|
} catch {
|