@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.cjs
CHANGED
|
@@ -70,15 +70,15 @@ function parseRef(arg) {
|
|
|
70
70
|
}
|
|
71
71
|
|
|
72
72
|
// src/taxtree.ts
|
|
73
|
-
async function getDualModeSnapshot(
|
|
74
|
-
const session = await
|
|
73
|
+
async function getDualModeSnapshot(page, options = {}) {
|
|
74
|
+
const session = await page.context().newCDPSession(page);
|
|
75
75
|
let nodes = [];
|
|
76
76
|
let isDualMode = false;
|
|
77
77
|
try {
|
|
78
78
|
const result = await session.send("Accessibility.getDualModeAXTree");
|
|
79
79
|
nodes = result.nodes;
|
|
80
80
|
isDualMode = true;
|
|
81
|
-
} catch
|
|
81
|
+
} catch {
|
|
82
82
|
try {
|
|
83
83
|
const result = await session.send("Accessibility.getFullAXTree");
|
|
84
84
|
nodes = result.nodes;
|
|
@@ -355,8 +355,8 @@ var BrowserManager = class {
|
|
|
355
355
|
* Get enhanced snapshot with refs and cache the ref map
|
|
356
356
|
*/
|
|
357
357
|
async getSnapshot(options) {
|
|
358
|
-
const
|
|
359
|
-
const snapshot = await getDualModeSnapshot(
|
|
358
|
+
const page = this.getPage();
|
|
359
|
+
const snapshot = await getDualModeSnapshot(page, options);
|
|
360
360
|
this.refMap = snapshot.refs;
|
|
361
361
|
this.lastSnapshot = snapshot.tree;
|
|
362
362
|
return snapshot;
|
|
@@ -376,20 +376,20 @@ var BrowserManager = class {
|
|
|
376
376
|
if (!ref) return null;
|
|
377
377
|
const refData = this.refMap[ref];
|
|
378
378
|
if (!refData) return null;
|
|
379
|
-
const
|
|
379
|
+
const page = this.getPage();
|
|
380
380
|
if (refData.role === "clickable" || refData.role === "focusable") {
|
|
381
|
-
return
|
|
381
|
+
return page.locator(refData.selector);
|
|
382
382
|
}
|
|
383
|
-
let
|
|
383
|
+
let locator;
|
|
384
384
|
if (refData.name) {
|
|
385
|
-
|
|
385
|
+
locator = page.getByRole(refData.role, { name: refData.name, exact: true });
|
|
386
386
|
} else {
|
|
387
|
-
|
|
387
|
+
locator = page.getByRole(refData.role);
|
|
388
388
|
}
|
|
389
389
|
if (refData.nth !== void 0) {
|
|
390
|
-
|
|
390
|
+
locator = locator.nth(refData.nth);
|
|
391
391
|
}
|
|
392
|
-
return
|
|
392
|
+
return locator;
|
|
393
393
|
}
|
|
394
394
|
/**
|
|
395
395
|
* Check if a selector looks like a ref
|
|
@@ -409,10 +409,10 @@ var BrowserManager = class {
|
|
|
409
409
|
* Get locator - supports both refs and regular selectors
|
|
410
410
|
*/
|
|
411
411
|
getLocator(selectorOrRef) {
|
|
412
|
-
const
|
|
413
|
-
if (
|
|
414
|
-
const
|
|
415
|
-
return
|
|
412
|
+
const locator = this.getLocatorFromRef(selectorOrRef);
|
|
413
|
+
if (locator) return locator;
|
|
414
|
+
const page = this.getPage();
|
|
415
|
+
return page.locator(selectorOrRef);
|
|
416
416
|
}
|
|
417
417
|
/**
|
|
418
418
|
* Get the current active page, throws if not launched
|
|
@@ -436,9 +436,9 @@ var BrowserManager = class {
|
|
|
436
436
|
* Switch to a frame by selector, name, or URL
|
|
437
437
|
*/
|
|
438
438
|
async switchToFrame(options) {
|
|
439
|
-
const
|
|
439
|
+
const page = this.getPage();
|
|
440
440
|
if (options.selector) {
|
|
441
|
-
const frameElement = await
|
|
441
|
+
const frameElement = await page.$(options.selector);
|
|
442
442
|
if (!frameElement) {
|
|
443
443
|
throw new Error(`Frame not found: ${options.selector}`);
|
|
444
444
|
}
|
|
@@ -448,13 +448,13 @@ var BrowserManager = class {
|
|
|
448
448
|
}
|
|
449
449
|
this.activeFrame = frame;
|
|
450
450
|
} else if (options.name) {
|
|
451
|
-
const frame =
|
|
451
|
+
const frame = page.frame({ name: options.name });
|
|
452
452
|
if (!frame) {
|
|
453
453
|
throw new Error(`Frame not found with name: ${options.name}`);
|
|
454
454
|
}
|
|
455
455
|
this.activeFrame = frame;
|
|
456
456
|
} else if (options.url) {
|
|
457
|
-
const frame =
|
|
457
|
+
const frame = page.frame({ url: options.url });
|
|
458
458
|
if (!frame) {
|
|
459
459
|
throw new Error(`Frame not found with URL: ${options.url}`);
|
|
460
460
|
}
|
|
@@ -471,9 +471,9 @@ var BrowserManager = class {
|
|
|
471
471
|
* Set up dialog handler
|
|
472
472
|
*/
|
|
473
473
|
setDialogHandler(response, promptText) {
|
|
474
|
-
const
|
|
474
|
+
const page = this.getPage();
|
|
475
475
|
if (this.dialogHandler) {
|
|
476
|
-
|
|
476
|
+
page.removeListener("dialog", this.dialogHandler);
|
|
477
477
|
}
|
|
478
478
|
this.dialogHandler = async (dialog) => {
|
|
479
479
|
if (response === "accept") {
|
|
@@ -482,15 +482,15 @@ var BrowserManager = class {
|
|
|
482
482
|
await dialog.dismiss();
|
|
483
483
|
}
|
|
484
484
|
};
|
|
485
|
-
|
|
485
|
+
page.on("dialog", this.dialogHandler);
|
|
486
486
|
}
|
|
487
487
|
/**
|
|
488
488
|
* Clear dialog handler
|
|
489
489
|
*/
|
|
490
490
|
clearDialogHandler() {
|
|
491
491
|
if (this.dialogHandler) {
|
|
492
|
-
const
|
|
493
|
-
|
|
492
|
+
const page = this.getPage();
|
|
493
|
+
page.removeListener("dialog", this.dialogHandler);
|
|
494
494
|
this.dialogHandler = null;
|
|
495
495
|
}
|
|
496
496
|
}
|
|
@@ -498,8 +498,8 @@ var BrowserManager = class {
|
|
|
498
498
|
* Start tracking requests
|
|
499
499
|
*/
|
|
500
500
|
startRequestTracking() {
|
|
501
|
-
const
|
|
502
|
-
|
|
501
|
+
const page = this.getPage();
|
|
502
|
+
page.on("request", (request) => {
|
|
503
503
|
this.trackedRequests.push({
|
|
504
504
|
url: request.url(),
|
|
505
505
|
method: request.method(),
|
|
@@ -528,7 +528,7 @@ var BrowserManager = class {
|
|
|
528
528
|
* Add a route to intercept requests
|
|
529
529
|
*/
|
|
530
530
|
async addRoute(url, options) {
|
|
531
|
-
const
|
|
531
|
+
const page = this.getPage();
|
|
532
532
|
const handler = async (route) => {
|
|
533
533
|
if (options.abort) {
|
|
534
534
|
await route.abort();
|
|
@@ -544,22 +544,22 @@ var BrowserManager = class {
|
|
|
544
544
|
}
|
|
545
545
|
};
|
|
546
546
|
this.routes.set(url, handler);
|
|
547
|
-
await
|
|
547
|
+
await page.route(url, handler);
|
|
548
548
|
}
|
|
549
549
|
/**
|
|
550
550
|
* Remove a route
|
|
551
551
|
*/
|
|
552
552
|
async removeRoute(url) {
|
|
553
|
-
const
|
|
553
|
+
const page = this.getPage();
|
|
554
554
|
if (url) {
|
|
555
555
|
const handler = this.routes.get(url);
|
|
556
556
|
if (handler) {
|
|
557
|
-
await
|
|
557
|
+
await page.unroute(url, handler);
|
|
558
558
|
this.routes.delete(url);
|
|
559
559
|
}
|
|
560
560
|
} else {
|
|
561
561
|
for (const [routeUrl, handler] of this.routes) {
|
|
562
|
-
await
|
|
562
|
+
await page.unroute(routeUrl, handler);
|
|
563
563
|
}
|
|
564
564
|
this.routes.clear();
|
|
565
565
|
}
|
|
@@ -590,8 +590,8 @@ var BrowserManager = class {
|
|
|
590
590
|
* Set viewport
|
|
591
591
|
*/
|
|
592
592
|
async setViewport(width, height) {
|
|
593
|
-
const
|
|
594
|
-
await
|
|
593
|
+
const page = this.getPage();
|
|
594
|
+
await page.setViewportSize({ width, height });
|
|
595
595
|
}
|
|
596
596
|
/**
|
|
597
597
|
* Set device scale factor (devicePixelRatio) via CDP
|
|
@@ -636,8 +636,8 @@ var BrowserManager = class {
|
|
|
636
636
|
* Start console message tracking
|
|
637
637
|
*/
|
|
638
638
|
startConsoleTracking() {
|
|
639
|
-
const
|
|
640
|
-
|
|
639
|
+
const page = this.getPage();
|
|
640
|
+
page.on("console", (msg) => {
|
|
641
641
|
this.consoleMessages.push({
|
|
642
642
|
type: msg.type(),
|
|
643
643
|
text: msg.text(),
|
|
@@ -661,8 +661,8 @@ var BrowserManager = class {
|
|
|
661
661
|
* Start error tracking
|
|
662
662
|
*/
|
|
663
663
|
startErrorTracking() {
|
|
664
|
-
const
|
|
665
|
-
|
|
664
|
+
const page = this.getPage();
|
|
665
|
+
page.on("pageerror", (error) => {
|
|
666
666
|
this.pageErrors.push({
|
|
667
667
|
message: error.message,
|
|
668
668
|
timestamp: Date.now()
|
|
@@ -716,7 +716,7 @@ var BrowserManager = class {
|
|
|
716
716
|
* Uses route interception to add headers only to matching requests
|
|
717
717
|
*/
|
|
718
718
|
async setScopedHeaders(origin, headers) {
|
|
719
|
-
const
|
|
719
|
+
const page = this.getPage();
|
|
720
720
|
let urlPattern;
|
|
721
721
|
try {
|
|
722
722
|
const url = new URL(origin.startsWith("http") ? origin : `https://${origin}`);
|
|
@@ -726,7 +726,7 @@ var BrowserManager = class {
|
|
|
726
726
|
}
|
|
727
727
|
const existingHandler = this.scopedHeaderRoutes.get(urlPattern);
|
|
728
728
|
if (existingHandler) {
|
|
729
|
-
await
|
|
729
|
+
await page.unroute(urlPattern, existingHandler);
|
|
730
730
|
}
|
|
731
731
|
const handler = async (route) => {
|
|
732
732
|
const requestHeaders = route.request().headers();
|
|
@@ -738,13 +738,13 @@ var BrowserManager = class {
|
|
|
738
738
|
});
|
|
739
739
|
};
|
|
740
740
|
this.scopedHeaderRoutes.set(urlPattern, handler);
|
|
741
|
-
await
|
|
741
|
+
await page.route(urlPattern, handler);
|
|
742
742
|
}
|
|
743
743
|
/**
|
|
744
744
|
* Clear scoped headers for an origin (or all if no origin specified)
|
|
745
745
|
*/
|
|
746
746
|
async clearScopedHeaders(origin) {
|
|
747
|
-
const
|
|
747
|
+
const page = this.getPage();
|
|
748
748
|
if (origin) {
|
|
749
749
|
let urlPattern;
|
|
750
750
|
try {
|
|
@@ -755,12 +755,12 @@ var BrowserManager = class {
|
|
|
755
755
|
}
|
|
756
756
|
const handler = this.scopedHeaderRoutes.get(urlPattern);
|
|
757
757
|
if (handler) {
|
|
758
|
-
await
|
|
758
|
+
await page.unroute(urlPattern, handler);
|
|
759
759
|
this.scopedHeaderRoutes.delete(urlPattern);
|
|
760
760
|
}
|
|
761
761
|
} else {
|
|
762
762
|
for (const [pattern, handler] of this.scopedHeaderRoutes) {
|
|
763
|
-
await
|
|
763
|
+
await page.unroute(pattern, handler);
|
|
764
764
|
}
|
|
765
765
|
this.scopedHeaderRoutes.clear();
|
|
766
766
|
}
|
|
@@ -903,26 +903,26 @@ var BrowserManager = class {
|
|
|
903
903
|
throw new Error(`Failed to create Browserbase session: ${response.statusText}`);
|
|
904
904
|
}
|
|
905
905
|
const session = await response.json();
|
|
906
|
-
const
|
|
906
|
+
const browser = await import_playwright_core.chromium.connectOverCDP(session.connectUrl).catch(() => {
|
|
907
907
|
throw new Error("Failed to connect to Browserbase session via CDP");
|
|
908
908
|
});
|
|
909
909
|
try {
|
|
910
|
-
const contexts =
|
|
910
|
+
const contexts = browser.contexts();
|
|
911
911
|
if (contexts.length === 0) {
|
|
912
912
|
throw new Error("No browser context found in Browserbase session");
|
|
913
913
|
}
|
|
914
914
|
const context = contexts[0];
|
|
915
915
|
const pages = context.pages();
|
|
916
|
-
const
|
|
916
|
+
const page = pages[0] ?? await context.newPage();
|
|
917
917
|
this.browserbaseSessionId = session.id;
|
|
918
918
|
this.browserbaseApiKey = browserbaseApiKey;
|
|
919
|
-
this.browser =
|
|
919
|
+
this.browser = browser;
|
|
920
920
|
context.setDefaultTimeout(1e4);
|
|
921
921
|
this.contexts.push(context);
|
|
922
922
|
this.setupContextTracking(context);
|
|
923
|
-
this.pages.push(
|
|
923
|
+
this.pages.push(page);
|
|
924
924
|
this.activePageIndex = 0;
|
|
925
|
-
this.setupPageTracking(
|
|
925
|
+
this.setupPageTracking(page);
|
|
926
926
|
} catch (error) {
|
|
927
927
|
await this.closeBrowserbaseSession(session.id, browserbaseApiKey).catch((sessionError) => {
|
|
928
928
|
console.error("Failed to close Browserbase session during cleanup:", sessionError);
|
|
@@ -1017,29 +1017,29 @@ var BrowserManager = class {
|
|
|
1017
1017
|
`Invalid Kernel session response: missing ${!session.session_id ? "session_id" : "cdp_ws_url"}`
|
|
1018
1018
|
);
|
|
1019
1019
|
}
|
|
1020
|
-
const
|
|
1020
|
+
const browser = await import_playwright_core.chromium.connectOverCDP(session.cdp_ws_url).catch(() => {
|
|
1021
1021
|
throw new Error("Failed to connect to Kernel session via CDP");
|
|
1022
1022
|
});
|
|
1023
1023
|
try {
|
|
1024
|
-
const contexts =
|
|
1024
|
+
const contexts = browser.contexts();
|
|
1025
1025
|
let context;
|
|
1026
|
-
let
|
|
1026
|
+
let page;
|
|
1027
1027
|
if (contexts.length === 0) {
|
|
1028
|
-
context = await
|
|
1029
|
-
|
|
1028
|
+
context = await browser.newContext();
|
|
1029
|
+
page = await context.newPage();
|
|
1030
1030
|
} else {
|
|
1031
1031
|
context = contexts[0];
|
|
1032
1032
|
const pages = context.pages();
|
|
1033
|
-
|
|
1033
|
+
page = pages[0] ?? await context.newPage();
|
|
1034
1034
|
}
|
|
1035
1035
|
this.kernelSessionId = session.session_id;
|
|
1036
1036
|
this.kernelApiKey = kernelApiKey;
|
|
1037
|
-
this.browser =
|
|
1037
|
+
this.browser = browser;
|
|
1038
1038
|
context.setDefaultTimeout(6e4);
|
|
1039
1039
|
this.contexts.push(context);
|
|
1040
|
-
this.pages.push(
|
|
1040
|
+
this.pages.push(page);
|
|
1041
1041
|
this.activePageIndex = 0;
|
|
1042
|
-
this.setupPageTracking(
|
|
1042
|
+
this.setupPageTracking(page);
|
|
1043
1043
|
this.setupContextTracking(context);
|
|
1044
1044
|
} catch (error) {
|
|
1045
1045
|
await this.closeKernelSession(session.session_id, kernelApiKey).catch((sessionError) => {
|
|
@@ -1081,29 +1081,29 @@ var BrowserManager = class {
|
|
|
1081
1081
|
`Invalid Browser Use session response: missing ${!session.id ? "id" : "cdpUrl"}`
|
|
1082
1082
|
);
|
|
1083
1083
|
}
|
|
1084
|
-
const
|
|
1084
|
+
const browser = await import_playwright_core.chromium.connectOverCDP(session.cdpUrl).catch(() => {
|
|
1085
1085
|
throw new Error("Failed to connect to Browser Use session via CDP");
|
|
1086
1086
|
});
|
|
1087
1087
|
try {
|
|
1088
|
-
const contexts =
|
|
1088
|
+
const contexts = browser.contexts();
|
|
1089
1089
|
let context;
|
|
1090
|
-
let
|
|
1090
|
+
let page;
|
|
1091
1091
|
if (contexts.length === 0) {
|
|
1092
|
-
context = await
|
|
1093
|
-
|
|
1092
|
+
context = await browser.newContext();
|
|
1093
|
+
page = await context.newPage();
|
|
1094
1094
|
} else {
|
|
1095
1095
|
context = contexts[0];
|
|
1096
1096
|
const pages = context.pages();
|
|
1097
|
-
|
|
1097
|
+
page = pages[0] ?? await context.newPage();
|
|
1098
1098
|
}
|
|
1099
1099
|
this.browserUseSessionId = session.id;
|
|
1100
1100
|
this.browserUseApiKey = browserUseApiKey;
|
|
1101
|
-
this.browser =
|
|
1101
|
+
this.browser = browser;
|
|
1102
1102
|
context.setDefaultTimeout(6e4);
|
|
1103
1103
|
this.contexts.push(context);
|
|
1104
|
-
this.pages.push(
|
|
1104
|
+
this.pages.push(page);
|
|
1105
1105
|
this.activePageIndex = 0;
|
|
1106
|
-
this.setupPageTracking(
|
|
1106
|
+
this.setupPageTracking(page);
|
|
1107
1107
|
this.setupContextTracking(context);
|
|
1108
1108
|
} catch (error) {
|
|
1109
1109
|
await this.closeBrowserUseSession(session.id, browserUseApiKey).catch((sessionError) => {
|
|
@@ -1225,10 +1225,10 @@ var BrowserManager = class {
|
|
|
1225
1225
|
context.setDefaultTimeout(6e4);
|
|
1226
1226
|
this.contexts.push(context);
|
|
1227
1227
|
this.setupContextTracking(context);
|
|
1228
|
-
const
|
|
1229
|
-
if (!this.pages.includes(
|
|
1230
|
-
this.pages.push(
|
|
1231
|
-
this.setupPageTracking(
|
|
1228
|
+
const page = context.pages()[0] ?? await context.newPage();
|
|
1229
|
+
if (!this.pages.includes(page)) {
|
|
1230
|
+
this.pages.push(page);
|
|
1231
|
+
this.setupPageTracking(page);
|
|
1232
1232
|
}
|
|
1233
1233
|
this.activePageIndex = this.pages.length > 0 ? this.pages.length - 1 : 0;
|
|
1234
1234
|
}
|
|
@@ -1248,34 +1248,34 @@ var BrowserManager = class {
|
|
|
1248
1248
|
} else {
|
|
1249
1249
|
cdpUrl = `http://localhost:${cdpEndpoint}`;
|
|
1250
1250
|
}
|
|
1251
|
-
const
|
|
1251
|
+
const browser = await import_playwright_core.chromium.connectOverCDP(cdpUrl).catch(() => {
|
|
1252
1252
|
throw new Error(
|
|
1253
1253
|
`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.")
|
|
1254
1254
|
);
|
|
1255
1255
|
});
|
|
1256
1256
|
try {
|
|
1257
|
-
const contexts =
|
|
1257
|
+
const contexts = browser.contexts();
|
|
1258
1258
|
if (contexts.length === 0) {
|
|
1259
1259
|
throw new Error("No browser context found. Make sure the app has an open window.");
|
|
1260
1260
|
}
|
|
1261
|
-
const allPages = contexts.flatMap((context) => context.pages()).filter((
|
|
1261
|
+
const allPages = contexts.flatMap((context) => context.pages()).filter((page) => page.url());
|
|
1262
1262
|
if (allPages.length === 0) {
|
|
1263
1263
|
throw new Error("No page found. Make sure the app has loaded content.");
|
|
1264
1264
|
}
|
|
1265
|
-
this.browser =
|
|
1265
|
+
this.browser = browser;
|
|
1266
1266
|
this.cdpEndpoint = cdpEndpoint;
|
|
1267
1267
|
for (const context of contexts) {
|
|
1268
1268
|
context.setDefaultTimeout(1e4);
|
|
1269
1269
|
this.contexts.push(context);
|
|
1270
1270
|
this.setupContextTracking(context);
|
|
1271
1271
|
}
|
|
1272
|
-
for (const
|
|
1273
|
-
this.pages.push(
|
|
1274
|
-
this.setupPageTracking(
|
|
1272
|
+
for (const page of allPages) {
|
|
1273
|
+
this.pages.push(page);
|
|
1274
|
+
this.setupPageTracking(page);
|
|
1275
1275
|
}
|
|
1276
1276
|
this.activePageIndex = 0;
|
|
1277
1277
|
} catch (error) {
|
|
1278
|
-
await
|
|
1278
|
+
await browser.close().catch(() => {
|
|
1279
1279
|
});
|
|
1280
1280
|
throw error;
|
|
1281
1281
|
}
|
|
@@ -1283,22 +1283,22 @@ var BrowserManager = class {
|
|
|
1283
1283
|
/**
|
|
1284
1284
|
* Set up console, error, and close tracking for a page
|
|
1285
1285
|
*/
|
|
1286
|
-
setupPageTracking(
|
|
1287
|
-
|
|
1286
|
+
setupPageTracking(page) {
|
|
1287
|
+
page.on("console", (msg) => {
|
|
1288
1288
|
this.consoleMessages.push({
|
|
1289
1289
|
type: msg.type(),
|
|
1290
1290
|
text: msg.text(),
|
|
1291
1291
|
timestamp: Date.now()
|
|
1292
1292
|
});
|
|
1293
1293
|
});
|
|
1294
|
-
|
|
1294
|
+
page.on("pageerror", (error) => {
|
|
1295
1295
|
this.pageErrors.push({
|
|
1296
1296
|
message: error.message,
|
|
1297
1297
|
timestamp: Date.now()
|
|
1298
1298
|
});
|
|
1299
1299
|
});
|
|
1300
|
-
|
|
1301
|
-
const index = this.pages.indexOf(
|
|
1300
|
+
page.on("close", () => {
|
|
1301
|
+
const index = this.pages.indexOf(page);
|
|
1302
1302
|
if (index !== -1) {
|
|
1303
1303
|
this.pages.splice(index, 1);
|
|
1304
1304
|
if (this.activePageIndex >= this.pages.length) {
|
|
@@ -1312,12 +1312,12 @@ var BrowserManager = class {
|
|
|
1312
1312
|
* This handles pages created externally (e.g., via target="_blank" links, window.open)
|
|
1313
1313
|
*/
|
|
1314
1314
|
setupContextTracking(context) {
|
|
1315
|
-
context.on("page", (
|
|
1316
|
-
if (!this.pages.includes(
|
|
1317
|
-
this.pages.push(
|
|
1318
|
-
this.setupPageTracking(
|
|
1315
|
+
context.on("page", (page) => {
|
|
1316
|
+
if (!this.pages.includes(page)) {
|
|
1317
|
+
this.pages.push(page);
|
|
1318
|
+
this.setupPageTracking(page);
|
|
1319
1319
|
}
|
|
1320
|
-
const newIndex = this.pages.indexOf(
|
|
1320
|
+
const newIndex = this.pages.indexOf(page);
|
|
1321
1321
|
if (newIndex !== -1 && newIndex !== this.activePageIndex) {
|
|
1322
1322
|
this.activePageIndex = newIndex;
|
|
1323
1323
|
this.invalidateCDPSession().catch(() => {
|
|
@@ -1334,10 +1334,10 @@ var BrowserManager = class {
|
|
|
1334
1334
|
}
|
|
1335
1335
|
await this.invalidateCDPSession();
|
|
1336
1336
|
const context = this.contexts[0];
|
|
1337
|
-
const
|
|
1338
|
-
if (!this.pages.includes(
|
|
1339
|
-
this.pages.push(
|
|
1340
|
-
this.setupPageTracking(
|
|
1337
|
+
const page = await context.newPage();
|
|
1338
|
+
if (!this.pages.includes(page)) {
|
|
1339
|
+
this.pages.push(page);
|
|
1340
|
+
this.setupPageTracking(page);
|
|
1341
1341
|
}
|
|
1342
1342
|
this.activePageIndex = this.pages.length - 1;
|
|
1343
1343
|
return { index: this.activePageIndex, total: this.pages.length };
|
|
@@ -1355,10 +1355,10 @@ var BrowserManager = class {
|
|
|
1355
1355
|
context.setDefaultTimeout(6e4);
|
|
1356
1356
|
this.contexts.push(context);
|
|
1357
1357
|
this.setupContextTracking(context);
|
|
1358
|
-
const
|
|
1359
|
-
if (!this.pages.includes(
|
|
1360
|
-
this.pages.push(
|
|
1361
|
-
this.setupPageTracking(
|
|
1358
|
+
const page = await context.newPage();
|
|
1359
|
+
if (!this.pages.includes(page)) {
|
|
1360
|
+
this.pages.push(page);
|
|
1361
|
+
this.setupPageTracking(page);
|
|
1362
1362
|
}
|
|
1363
1363
|
this.activePageIndex = this.pages.length - 1;
|
|
1364
1364
|
return { index: this.activePageIndex, total: this.pages.length };
|
|
@@ -1388,10 +1388,10 @@ var BrowserManager = class {
|
|
|
1388
1388
|
await this.invalidateCDPSession();
|
|
1389
1389
|
}
|
|
1390
1390
|
this.activePageIndex = index;
|
|
1391
|
-
const
|
|
1391
|
+
const page = this.pages[index];
|
|
1392
1392
|
return {
|
|
1393
1393
|
index: this.activePageIndex,
|
|
1394
|
-
url:
|
|
1394
|
+
url: page.url(),
|
|
1395
1395
|
title: ""
|
|
1396
1396
|
// Title requires async, will be fetched separately
|
|
1397
1397
|
};
|
|
@@ -1410,8 +1410,8 @@ var BrowserManager = class {
|
|
|
1410
1410
|
if (targetIndex === this.activePageIndex) {
|
|
1411
1411
|
await this.invalidateCDPSession();
|
|
1412
1412
|
}
|
|
1413
|
-
const
|
|
1414
|
-
await
|
|
1413
|
+
const page = this.pages[targetIndex];
|
|
1414
|
+
await page.close();
|
|
1415
1415
|
this.pages.splice(targetIndex, 1);
|
|
1416
1416
|
if (this.activePageIndex >= this.pages.length) {
|
|
1417
1417
|
this.activePageIndex = this.pages.length - 1;
|
|
@@ -1425,10 +1425,10 @@ var BrowserManager = class {
|
|
|
1425
1425
|
*/
|
|
1426
1426
|
async listTabs() {
|
|
1427
1427
|
const tabs = await Promise.all(
|
|
1428
|
-
this.pages.map(async (
|
|
1428
|
+
this.pages.map(async (page, index) => ({
|
|
1429
1429
|
index,
|
|
1430
|
-
url:
|
|
1431
|
-
title: await
|
|
1430
|
+
url: page.url(),
|
|
1431
|
+
title: await page.title().catch(() => ""),
|
|
1432
1432
|
active: index === this.activePageIndex
|
|
1433
1433
|
}))
|
|
1434
1434
|
);
|
|
@@ -1442,9 +1442,9 @@ var BrowserManager = class {
|
|
|
1442
1442
|
if (this.cdpSession) {
|
|
1443
1443
|
return this.cdpSession;
|
|
1444
1444
|
}
|
|
1445
|
-
const
|
|
1446
|
-
const context =
|
|
1447
|
-
this.cdpSession = await context.newCDPSession(
|
|
1445
|
+
const page = this.getPage();
|
|
1446
|
+
const context = page.context();
|
|
1447
|
+
this.cdpSession = await context.newCDPSession(page);
|
|
1448
1448
|
return this.cdpSession;
|
|
1449
1449
|
}
|
|
1450
1450
|
/**
|
|
@@ -1732,8 +1732,8 @@ var BrowserManager = class {
|
|
|
1732
1732
|
this.browser = null;
|
|
1733
1733
|
}
|
|
1734
1734
|
} else {
|
|
1735
|
-
for (const
|
|
1736
|
-
await
|
|
1735
|
+
for (const page of this.pages) {
|
|
1736
|
+
await page.close().catch(() => {
|
|
1737
1737
|
});
|
|
1738
1738
|
}
|
|
1739
1739
|
for (const context of this.contexts) {
|
|
@@ -2136,8 +2136,8 @@ var IOSManager = class _IOSManager {
|
|
|
2136
2136
|
if (!this.browser) {
|
|
2137
2137
|
throw new Error("iOS browser not launched");
|
|
2138
2138
|
}
|
|
2139
|
-
const
|
|
2140
|
-
await
|
|
2139
|
+
const element = await this.getElement(selector);
|
|
2140
|
+
await element.click();
|
|
2141
2141
|
}
|
|
2142
2142
|
/**
|
|
2143
2143
|
* Alias for click (semantic clarity for touch)
|
|
@@ -2152,17 +2152,17 @@ var IOSManager = class _IOSManager {
|
|
|
2152
2152
|
if (!this.browser) {
|
|
2153
2153
|
throw new Error("iOS browser not launched");
|
|
2154
2154
|
}
|
|
2155
|
-
const
|
|
2155
|
+
const element = await this.getElement(selector);
|
|
2156
2156
|
if (options?.clear) {
|
|
2157
|
-
await
|
|
2157
|
+
await element.clearValue();
|
|
2158
2158
|
}
|
|
2159
2159
|
if (options?.delay && options.delay > 0) {
|
|
2160
2160
|
for (const char of text) {
|
|
2161
|
-
await
|
|
2161
|
+
await element.addValue(char);
|
|
2162
2162
|
await new Promise((r) => setTimeout(r, options.delay));
|
|
2163
2163
|
}
|
|
2164
2164
|
} else {
|
|
2165
|
-
await
|
|
2165
|
+
await element.addValue(text);
|
|
2166
2166
|
}
|
|
2167
2167
|
}
|
|
2168
2168
|
/**
|
|
@@ -2172,9 +2172,9 @@ var IOSManager = class _IOSManager {
|
|
|
2172
2172
|
if (!this.browser) {
|
|
2173
2173
|
throw new Error("iOS browser not launched");
|
|
2174
2174
|
}
|
|
2175
|
-
const
|
|
2176
|
-
await
|
|
2177
|
-
await
|
|
2175
|
+
const element = await this.getElement(selector);
|
|
2176
|
+
await element.clearValue();
|
|
2177
|
+
await element.setValue(value);
|
|
2178
2178
|
}
|
|
2179
2179
|
/**
|
|
2180
2180
|
* Get element by selector or ref
|
|
@@ -2264,12 +2264,12 @@ var IOSManager = class _IOSManager {
|
|
|
2264
2264
|
"DETAILS",
|
|
2265
2265
|
"SUMMARY"
|
|
2266
2266
|
]);
|
|
2267
|
-
function getXPath(
|
|
2268
|
-
if (
|
|
2269
|
-
return `//*[@id="${
|
|
2267
|
+
function getXPath(element) {
|
|
2268
|
+
if (element.id) {
|
|
2269
|
+
return `//*[@id="${element.id}"]`;
|
|
2270
2270
|
}
|
|
2271
2271
|
const parts = [];
|
|
2272
|
-
let current =
|
|
2272
|
+
let current = element;
|
|
2273
2273
|
while (current && current.nodeType === 1) {
|
|
2274
2274
|
let index = 1;
|
|
2275
2275
|
let sibling = current.previousElementSibling;
|
|
@@ -2285,36 +2285,36 @@ var IOSManager = class _IOSManager {
|
|
|
2285
2285
|
}
|
|
2286
2286
|
return "/" + parts.join("/");
|
|
2287
2287
|
}
|
|
2288
|
-
function getAccessibleName(
|
|
2289
|
-
const ariaLabel =
|
|
2288
|
+
function getAccessibleName(element) {
|
|
2289
|
+
const ariaLabel = element.getAttribute("aria-label");
|
|
2290
2290
|
if (ariaLabel) return ariaLabel;
|
|
2291
|
-
const tagName =
|
|
2291
|
+
const tagName = element.tagName;
|
|
2292
2292
|
if (tagName === "INPUT" || tagName === "TEXTAREA") {
|
|
2293
|
-
const id =
|
|
2293
|
+
const id = element.id;
|
|
2294
2294
|
if (id) {
|
|
2295
2295
|
const label = document.querySelector(`label[for="${id}"]`);
|
|
2296
2296
|
if (label) return label.textContent?.trim() || "";
|
|
2297
2297
|
}
|
|
2298
|
-
if (
|
|
2298
|
+
if (element.placeholder) return element.placeholder;
|
|
2299
2299
|
}
|
|
2300
2300
|
if (tagName === "BUTTON" || tagName === "A") {
|
|
2301
|
-
return
|
|
2301
|
+
return element.textContent?.trim() || "";
|
|
2302
2302
|
}
|
|
2303
|
-
const labelledBy =
|
|
2303
|
+
const labelledBy = element.getAttribute("aria-labelledby");
|
|
2304
2304
|
if (labelledBy) {
|
|
2305
2305
|
const labelElement = document.getElementById(labelledBy);
|
|
2306
2306
|
if (labelElement) return labelElement.textContent?.trim() || "";
|
|
2307
2307
|
}
|
|
2308
|
-
return
|
|
2308
|
+
return element.textContent?.trim().slice(0, 50) || "";
|
|
2309
2309
|
}
|
|
2310
|
-
function getRole(
|
|
2311
|
-
const role =
|
|
2310
|
+
function getRole(element) {
|
|
2311
|
+
const role = element.getAttribute("role");
|
|
2312
2312
|
if (role) return role;
|
|
2313
|
-
const tag =
|
|
2314
|
-
if (tag === "A" &&
|
|
2313
|
+
const tag = element.tagName;
|
|
2314
|
+
if (tag === "A" && element.hasAttribute("href")) return "link";
|
|
2315
2315
|
if (tag === "BUTTON") return "button";
|
|
2316
2316
|
if (tag === "INPUT") {
|
|
2317
|
-
const type =
|
|
2317
|
+
const type = element.type;
|
|
2318
2318
|
if (type === "checkbox") return "checkbox";
|
|
2319
2319
|
if (type === "radio") return "radio";
|
|
2320
2320
|
if (type === "text" || type === "email" || type === "password" || type === "search")
|
|
@@ -2332,18 +2332,18 @@ var IOSManager = class _IOSManager {
|
|
|
2332
2332
|
if (tag === "FOOTER") return "contentinfo";
|
|
2333
2333
|
return null;
|
|
2334
2334
|
}
|
|
2335
|
-
function traverse(
|
|
2335
|
+
function traverse(element, depth) {
|
|
2336
2336
|
if (depth > 10) return null;
|
|
2337
|
-
const tag =
|
|
2338
|
-
const role = getRole(
|
|
2339
|
-
const name = getAccessibleName(
|
|
2337
|
+
const tag = element.tagName;
|
|
2338
|
+
const role = getRole(element);
|
|
2339
|
+
const name = getAccessibleName(element);
|
|
2340
2340
|
const isInteractive = INTERACTIVE_TAGS.has(tag) || role !== null && INTERACTIVE_ROLES2.has(role);
|
|
2341
|
-
const style = window.getComputedStyle(
|
|
2341
|
+
const style = window.getComputedStyle(element);
|
|
2342
2342
|
if (style.display === "none" || style.visibility === "hidden") {
|
|
2343
2343
|
return null;
|
|
2344
2344
|
}
|
|
2345
2345
|
const children = [];
|
|
2346
|
-
for (const child of
|
|
2346
|
+
for (const child of element.children) {
|
|
2347
2347
|
const childInfo = traverse(child, depth + 1);
|
|
2348
2348
|
if (childInfo) {
|
|
2349
2349
|
children.push(childInfo);
|
|
@@ -2356,9 +2356,9 @@ var IOSManager = class _IOSManager {
|
|
|
2356
2356
|
tag,
|
|
2357
2357
|
role,
|
|
2358
2358
|
name,
|
|
2359
|
-
text:
|
|
2359
|
+
text: element.textContent?.trim().slice(0, 100) || "",
|
|
2360
2360
|
isInteractive,
|
|
2361
|
-
xpath: getXPath(
|
|
2361
|
+
xpath: getXPath(element),
|
|
2362
2362
|
children
|
|
2363
2363
|
};
|
|
2364
2364
|
}
|
|
@@ -2412,8 +2412,8 @@ var IOSManager = class _IOSManager {
|
|
|
2412
2412
|
}
|
|
2413
2413
|
const amount = options?.amount ?? 300;
|
|
2414
2414
|
if (options?.selector) {
|
|
2415
|
-
const
|
|
2416
|
-
await
|
|
2415
|
+
const element = await this.getElement(options.selector);
|
|
2416
|
+
await element.scrollIntoView();
|
|
2417
2417
|
return;
|
|
2418
2418
|
}
|
|
2419
2419
|
let deltaX = options?.x ?? 0;
|
|
@@ -2461,16 +2461,16 @@ var IOSManager = class _IOSManager {
|
|
|
2461
2461
|
/**
|
|
2462
2462
|
* Execute JavaScript
|
|
2463
2463
|
*/
|
|
2464
|
-
async evaluate(
|
|
2464
|
+
async evaluate(script, ...args) {
|
|
2465
2465
|
if (!this.browser) {
|
|
2466
2466
|
throw new Error("iOS browser not launched");
|
|
2467
2467
|
}
|
|
2468
2468
|
const result = await this.browser.execute(
|
|
2469
2469
|
function(code, evalArgs) {
|
|
2470
|
-
const
|
|
2471
|
-
return
|
|
2470
|
+
const fn = new Function(...evalArgs.map((_, i) => `arg${i}`), code);
|
|
2471
|
+
return fn(...evalArgs);
|
|
2472
2472
|
},
|
|
2473
|
-
|
|
2473
|
+
script.includes("return") ? script : `return (${script})`,
|
|
2474
2474
|
args
|
|
2475
2475
|
);
|
|
2476
2476
|
return result;
|
|
@@ -2484,20 +2484,20 @@ var IOSManager = class _IOSManager {
|
|
|
2484
2484
|
}
|
|
2485
2485
|
const timeout = options.timeout ?? 3e4;
|
|
2486
2486
|
if (options.selector) {
|
|
2487
|
-
const
|
|
2487
|
+
const element = await this.getElement(options.selector);
|
|
2488
2488
|
switch (options.state) {
|
|
2489
2489
|
case "detached":
|
|
2490
|
-
await
|
|
2490
|
+
await element.waitForExist({ timeout, reverse: true });
|
|
2491
2491
|
break;
|
|
2492
2492
|
case "hidden":
|
|
2493
|
-
await
|
|
2493
|
+
await element.waitForDisplayed({ timeout, reverse: true });
|
|
2494
2494
|
break;
|
|
2495
2495
|
case "visible":
|
|
2496
|
-
await
|
|
2496
|
+
await element.waitForDisplayed({ timeout });
|
|
2497
2497
|
break;
|
|
2498
2498
|
case "attached":
|
|
2499
2499
|
default:
|
|
2500
|
-
await
|
|
2500
|
+
await element.waitForExist({ timeout });
|
|
2501
2501
|
break;
|
|
2502
2502
|
}
|
|
2503
2503
|
} else {
|
|
@@ -2532,8 +2532,8 @@ var IOSManager = class _IOSManager {
|
|
|
2532
2532
|
if (!this.browser) {
|
|
2533
2533
|
throw new Error("iOS browser not launched");
|
|
2534
2534
|
}
|
|
2535
|
-
const
|
|
2536
|
-
await
|
|
2535
|
+
const element = await this.getElement(selector);
|
|
2536
|
+
await element.scrollIntoView();
|
|
2537
2537
|
}
|
|
2538
2538
|
/**
|
|
2539
2539
|
* Get page content (HTML)
|
|
@@ -2543,8 +2543,8 @@ var IOSManager = class _IOSManager {
|
|
|
2543
2543
|
throw new Error("iOS browser not launched");
|
|
2544
2544
|
}
|
|
2545
2545
|
if (selector) {
|
|
2546
|
-
const
|
|
2547
|
-
return
|
|
2546
|
+
const element = await this.getElement(selector);
|
|
2547
|
+
return element.getHTML();
|
|
2548
2548
|
}
|
|
2549
2549
|
return this.browser.getPageSource();
|
|
2550
2550
|
}
|
|
@@ -2555,8 +2555,8 @@ var IOSManager = class _IOSManager {
|
|
|
2555
2555
|
if (!this.browser) {
|
|
2556
2556
|
throw new Error("iOS browser not launched");
|
|
2557
2557
|
}
|
|
2558
|
-
const
|
|
2559
|
-
return
|
|
2558
|
+
const element = await this.getElement(selector);
|
|
2559
|
+
return element.getText();
|
|
2560
2560
|
}
|
|
2561
2561
|
/**
|
|
2562
2562
|
* Get attribute value
|
|
@@ -2565,8 +2565,8 @@ var IOSManager = class _IOSManager {
|
|
|
2565
2565
|
if (!this.browser) {
|
|
2566
2566
|
throw new Error("iOS browser not launched");
|
|
2567
2567
|
}
|
|
2568
|
-
const
|
|
2569
|
-
return
|
|
2568
|
+
const element = await this.getElement(selector);
|
|
2569
|
+
return element.getAttribute(attribute);
|
|
2570
2570
|
}
|
|
2571
2571
|
/**
|
|
2572
2572
|
* Check if element is visible
|
|
@@ -2576,8 +2576,8 @@ var IOSManager = class _IOSManager {
|
|
|
2576
2576
|
throw new Error("iOS browser not launched");
|
|
2577
2577
|
}
|
|
2578
2578
|
try {
|
|
2579
|
-
const
|
|
2580
|
-
return
|
|
2579
|
+
const element = await this.getElement(selector);
|
|
2580
|
+
return element.isDisplayed();
|
|
2581
2581
|
} catch {
|
|
2582
2582
|
return false;
|
|
2583
2583
|
}
|
|
@@ -2589,8 +2589,8 @@ var IOSManager = class _IOSManager {
|
|
|
2589
2589
|
if (!this.browser) {
|
|
2590
2590
|
throw new Error("iOS browser not launched");
|
|
2591
2591
|
}
|
|
2592
|
-
const
|
|
2593
|
-
return
|
|
2592
|
+
const element = await this.getElement(selector);
|
|
2593
|
+
return element.isEnabled();
|
|
2594
2594
|
}
|
|
2595
2595
|
/**
|
|
2596
2596
|
* Navigate back
|
|
@@ -2626,10 +2626,10 @@ var IOSManager = class _IOSManager {
|
|
|
2626
2626
|
if (!this.browser) {
|
|
2627
2627
|
throw new Error("iOS browser not launched");
|
|
2628
2628
|
}
|
|
2629
|
-
const
|
|
2629
|
+
const element = await this.getElement(selector);
|
|
2630
2630
|
const valueArray = Array.isArray(values) ? values : [values];
|
|
2631
2631
|
for (const value of valueArray) {
|
|
2632
|
-
await
|
|
2632
|
+
await element.selectByAttribute("value", value);
|
|
2633
2633
|
}
|
|
2634
2634
|
}
|
|
2635
2635
|
/**
|
|
@@ -2639,10 +2639,10 @@ var IOSManager = class _IOSManager {
|
|
|
2639
2639
|
if (!this.browser) {
|
|
2640
2640
|
throw new Error("iOS browser not launched");
|
|
2641
2641
|
}
|
|
2642
|
-
const
|
|
2643
|
-
const isChecked = await
|
|
2642
|
+
const element = await this.getElement(selector);
|
|
2643
|
+
const isChecked = await element.isSelected();
|
|
2644
2644
|
if (!isChecked) {
|
|
2645
|
-
await
|
|
2645
|
+
await element.click();
|
|
2646
2646
|
}
|
|
2647
2647
|
}
|
|
2648
2648
|
/**
|
|
@@ -2652,10 +2652,10 @@ var IOSManager = class _IOSManager {
|
|
|
2652
2652
|
if (!this.browser) {
|
|
2653
2653
|
throw new Error("iOS browser not launched");
|
|
2654
2654
|
}
|
|
2655
|
-
const
|
|
2656
|
-
const isChecked = await
|
|
2655
|
+
const element = await this.getElement(selector);
|
|
2656
|
+
const isChecked = await element.isSelected();
|
|
2657
2657
|
if (isChecked) {
|
|
2658
|
-
await
|
|
2658
|
+
await element.click();
|
|
2659
2659
|
}
|
|
2660
2660
|
}
|
|
2661
2661
|
/**
|
|
@@ -2665,10 +2665,10 @@ var IOSManager = class _IOSManager {
|
|
|
2665
2665
|
if (!this.browser) {
|
|
2666
2666
|
throw new Error("iOS browser not launched");
|
|
2667
2667
|
}
|
|
2668
|
-
const
|
|
2669
|
-
await this.browser.execute(function(
|
|
2670
|
-
|
|
2671
|
-
},
|
|
2668
|
+
const element = await this.getElement(selector);
|
|
2669
|
+
await this.browser.execute(function(el) {
|
|
2670
|
+
el.focus();
|
|
2671
|
+
}, element);
|
|
2672
2672
|
}
|
|
2673
2673
|
/**
|
|
2674
2674
|
* Clear input field
|
|
@@ -2677,8 +2677,8 @@ var IOSManager = class _IOSManager {
|
|
|
2677
2677
|
if (!this.browser) {
|
|
2678
2678
|
throw new Error("iOS browser not launched");
|
|
2679
2679
|
}
|
|
2680
|
-
const
|
|
2681
|
-
await
|
|
2680
|
+
const element = await this.getElement(selector);
|
|
2681
|
+
await element.clearValue();
|
|
2682
2682
|
}
|
|
2683
2683
|
/**
|
|
2684
2684
|
* Get element count
|
|
@@ -2687,8 +2687,8 @@ var IOSManager = class _IOSManager {
|
|
|
2687
2687
|
if (!this.browser) {
|
|
2688
2688
|
throw new Error("iOS browser not launched");
|
|
2689
2689
|
}
|
|
2690
|
-
const
|
|
2691
|
-
return
|
|
2690
|
+
const elements = await this.browser.$$(selector);
|
|
2691
|
+
return elements.length;
|
|
2692
2692
|
}
|
|
2693
2693
|
/**
|
|
2694
2694
|
* Get bounding box
|
|
@@ -2698,9 +2698,9 @@ var IOSManager = class _IOSManager {
|
|
|
2698
2698
|
throw new Error("iOS browser not launched");
|
|
2699
2699
|
}
|
|
2700
2700
|
try {
|
|
2701
|
-
const
|
|
2702
|
-
const location = await
|
|
2703
|
-
const size = await
|
|
2701
|
+
const element = await this.getElement(selector);
|
|
2702
|
+
const location = await element.getLocation();
|
|
2703
|
+
const size = await element.getSize();
|
|
2704
2704
|
return {
|
|
2705
2705
|
x: location.x,
|
|
2706
2706
|
y: location.y,
|
|
@@ -3588,357 +3588,357 @@ function toAIFriendlyError(error, selector) {
|
|
|
3588
3588
|
}
|
|
3589
3589
|
return error instanceof Error ? error : new Error(message);
|
|
3590
3590
|
}
|
|
3591
|
-
async function executeCommand(
|
|
3591
|
+
async function executeCommand(command, browser) {
|
|
3592
3592
|
try {
|
|
3593
|
-
switch (
|
|
3593
|
+
switch (command.action) {
|
|
3594
3594
|
case "launch":
|
|
3595
|
-
return await handleLaunch(
|
|
3595
|
+
return await handleLaunch(command, browser);
|
|
3596
3596
|
case "navigate":
|
|
3597
|
-
return await handleNavigate(
|
|
3597
|
+
return await handleNavigate(command, browser);
|
|
3598
3598
|
case "click":
|
|
3599
|
-
return await handleClick(
|
|
3599
|
+
return await handleClick(command, browser);
|
|
3600
3600
|
case "type":
|
|
3601
|
-
return await handleType(
|
|
3601
|
+
return await handleType(command, browser);
|
|
3602
3602
|
case "fill":
|
|
3603
|
-
return await handleFill(
|
|
3603
|
+
return await handleFill(command, browser);
|
|
3604
3604
|
case "check":
|
|
3605
|
-
return await handleCheck(
|
|
3605
|
+
return await handleCheck(command, browser);
|
|
3606
3606
|
case "uncheck":
|
|
3607
|
-
return await handleUncheck(
|
|
3607
|
+
return await handleUncheck(command, browser);
|
|
3608
3608
|
case "upload":
|
|
3609
|
-
return await handleUpload(
|
|
3609
|
+
return await handleUpload(command, browser);
|
|
3610
3610
|
case "dblclick":
|
|
3611
|
-
return await handleDoubleClick(
|
|
3611
|
+
return await handleDoubleClick(command, browser);
|
|
3612
3612
|
case "focus":
|
|
3613
|
-
return await handleFocus(
|
|
3613
|
+
return await handleFocus(command, browser);
|
|
3614
3614
|
case "drag":
|
|
3615
|
-
return await handleDrag(
|
|
3615
|
+
return await handleDrag(command, browser);
|
|
3616
3616
|
case "frame":
|
|
3617
|
-
return await handleFrame(
|
|
3617
|
+
return await handleFrame(command, browser);
|
|
3618
3618
|
case "mainframe":
|
|
3619
|
-
return await handleMainFrame(
|
|
3619
|
+
return await handleMainFrame(command, browser);
|
|
3620
3620
|
case "getbyrole":
|
|
3621
|
-
return await handleGetByRole(
|
|
3621
|
+
return await handleGetByRole(command, browser);
|
|
3622
3622
|
case "getbytext":
|
|
3623
|
-
return await handleGetByText(
|
|
3623
|
+
return await handleGetByText(command, browser);
|
|
3624
3624
|
case "getbylabel":
|
|
3625
|
-
return await handleGetByLabel(
|
|
3625
|
+
return await handleGetByLabel(command, browser);
|
|
3626
3626
|
case "getbyplaceholder":
|
|
3627
|
-
return await handleGetByPlaceholder(
|
|
3627
|
+
return await handleGetByPlaceholder(command, browser);
|
|
3628
3628
|
case "press":
|
|
3629
|
-
return await handlePress(
|
|
3629
|
+
return await handlePress(command, browser);
|
|
3630
3630
|
case "screenshot":
|
|
3631
|
-
return await handleScreenshot(
|
|
3631
|
+
return await handleScreenshot(command, browser);
|
|
3632
3632
|
case "snapshot":
|
|
3633
|
-
return await handleSnapshot(
|
|
3633
|
+
return await handleSnapshot(command, browser);
|
|
3634
3634
|
case "evaluate":
|
|
3635
|
-
return await handleEvaluate(
|
|
3635
|
+
return await handleEvaluate(command, browser);
|
|
3636
3636
|
case "wait":
|
|
3637
|
-
return await handleWait(
|
|
3637
|
+
return await handleWait(command, browser);
|
|
3638
3638
|
case "scroll":
|
|
3639
|
-
return await handleScroll(
|
|
3639
|
+
return await handleScroll(command, browser);
|
|
3640
3640
|
case "select":
|
|
3641
|
-
return await handleSelect(
|
|
3641
|
+
return await handleSelect(command, browser);
|
|
3642
3642
|
case "hover":
|
|
3643
|
-
return await handleHover(
|
|
3643
|
+
return await handleHover(command, browser);
|
|
3644
3644
|
case "content":
|
|
3645
|
-
return await handleContent(
|
|
3645
|
+
return await handleContent(command, browser);
|
|
3646
3646
|
case "close":
|
|
3647
|
-
return await handleClose(
|
|
3647
|
+
return await handleClose(command, browser);
|
|
3648
3648
|
case "tab_new":
|
|
3649
|
-
return await handleTabNew(
|
|
3649
|
+
return await handleTabNew(command, browser);
|
|
3650
3650
|
case "tab_list":
|
|
3651
|
-
return await handleTabList(
|
|
3651
|
+
return await handleTabList(command, browser);
|
|
3652
3652
|
case "tab_switch":
|
|
3653
|
-
return await handleTabSwitch(
|
|
3653
|
+
return await handleTabSwitch(command, browser);
|
|
3654
3654
|
case "tab_close":
|
|
3655
|
-
return await handleTabClose(
|
|
3655
|
+
return await handleTabClose(command, browser);
|
|
3656
3656
|
case "window_new":
|
|
3657
|
-
return await handleWindowNew(
|
|
3657
|
+
return await handleWindowNew(command, browser);
|
|
3658
3658
|
case "cookies_get":
|
|
3659
|
-
return await handleCookiesGet(
|
|
3659
|
+
return await handleCookiesGet(command, browser);
|
|
3660
3660
|
case "cookies_set":
|
|
3661
|
-
return await handleCookiesSet(
|
|
3661
|
+
return await handleCookiesSet(command, browser);
|
|
3662
3662
|
case "cookies_clear":
|
|
3663
|
-
return await handleCookiesClear(
|
|
3663
|
+
return await handleCookiesClear(command, browser);
|
|
3664
3664
|
case "storage_get":
|
|
3665
|
-
return await handleStorageGet(
|
|
3665
|
+
return await handleStorageGet(command, browser);
|
|
3666
3666
|
case "storage_set":
|
|
3667
|
-
return await handleStorageSet(
|
|
3667
|
+
return await handleStorageSet(command, browser);
|
|
3668
3668
|
case "storage_clear":
|
|
3669
|
-
return await handleStorageClear(
|
|
3669
|
+
return await handleStorageClear(command, browser);
|
|
3670
3670
|
case "dialog":
|
|
3671
|
-
return await handleDialog(
|
|
3671
|
+
return await handleDialog(command, browser);
|
|
3672
3672
|
case "pdf":
|
|
3673
|
-
return await handlePdf(
|
|
3673
|
+
return await handlePdf(command, browser);
|
|
3674
3674
|
case "route":
|
|
3675
|
-
return await handleRoute(
|
|
3675
|
+
return await handleRoute(command, browser);
|
|
3676
3676
|
case "unroute":
|
|
3677
|
-
return await handleUnroute(
|
|
3677
|
+
return await handleUnroute(command, browser);
|
|
3678
3678
|
case "requests":
|
|
3679
|
-
return await handleRequests(
|
|
3679
|
+
return await handleRequests(command, browser);
|
|
3680
3680
|
case "download":
|
|
3681
|
-
return await handleDownload(
|
|
3681
|
+
return await handleDownload(command, browser);
|
|
3682
3682
|
case "geolocation":
|
|
3683
|
-
return await handleGeolocation(
|
|
3683
|
+
return await handleGeolocation(command, browser);
|
|
3684
3684
|
case "permissions":
|
|
3685
|
-
return await handlePermissions(
|
|
3685
|
+
return await handlePermissions(command, browser);
|
|
3686
3686
|
case "viewport":
|
|
3687
|
-
return await handleViewport(
|
|
3687
|
+
return await handleViewport(command, browser);
|
|
3688
3688
|
case "useragent":
|
|
3689
|
-
return await handleUserAgent(
|
|
3689
|
+
return await handleUserAgent(command, browser);
|
|
3690
3690
|
case "device":
|
|
3691
|
-
return await handleDevice(
|
|
3691
|
+
return await handleDevice(command, browser);
|
|
3692
3692
|
case "back":
|
|
3693
|
-
return await handleBack(
|
|
3693
|
+
return await handleBack(command, browser);
|
|
3694
3694
|
case "forward":
|
|
3695
|
-
return await handleForward(
|
|
3695
|
+
return await handleForward(command, browser);
|
|
3696
3696
|
case "reload":
|
|
3697
|
-
return await handleReload(
|
|
3697
|
+
return await handleReload(command, browser);
|
|
3698
3698
|
case "url":
|
|
3699
|
-
return await handleUrl(
|
|
3699
|
+
return await handleUrl(command, browser);
|
|
3700
3700
|
case "title":
|
|
3701
|
-
return await handleTitle(
|
|
3701
|
+
return await handleTitle(command, browser);
|
|
3702
3702
|
case "getattribute":
|
|
3703
|
-
return await handleGetAttribute(
|
|
3703
|
+
return await handleGetAttribute(command, browser);
|
|
3704
3704
|
case "gettext":
|
|
3705
|
-
return await handleGetText(
|
|
3705
|
+
return await handleGetText(command, browser);
|
|
3706
3706
|
case "isvisible":
|
|
3707
|
-
return await handleIsVisible(
|
|
3707
|
+
return await handleIsVisible(command, browser);
|
|
3708
3708
|
case "isenabled":
|
|
3709
|
-
return await handleIsEnabled(
|
|
3709
|
+
return await handleIsEnabled(command, browser);
|
|
3710
3710
|
case "ischecked":
|
|
3711
|
-
return await handleIsChecked(
|
|
3711
|
+
return await handleIsChecked(command, browser);
|
|
3712
3712
|
case "count":
|
|
3713
|
-
return await handleCount(
|
|
3713
|
+
return await handleCount(command, browser);
|
|
3714
3714
|
case "boundingbox":
|
|
3715
|
-
return await handleBoundingBox(
|
|
3715
|
+
return await handleBoundingBox(command, browser);
|
|
3716
3716
|
case "styles":
|
|
3717
|
-
return await handleStyles(
|
|
3717
|
+
return await handleStyles(command, browser);
|
|
3718
3718
|
case "video_start":
|
|
3719
|
-
return await handleVideoStart(
|
|
3719
|
+
return await handleVideoStart(command, browser);
|
|
3720
3720
|
case "video_stop":
|
|
3721
|
-
return await handleVideoStop(
|
|
3721
|
+
return await handleVideoStop(command, browser);
|
|
3722
3722
|
case "trace_start":
|
|
3723
|
-
return await handleTraceStart(
|
|
3723
|
+
return await handleTraceStart(command, browser);
|
|
3724
3724
|
case "trace_stop":
|
|
3725
|
-
return await handleTraceStop(
|
|
3725
|
+
return await handleTraceStop(command, browser);
|
|
3726
3726
|
case "har_start":
|
|
3727
|
-
return await handleHarStart(
|
|
3727
|
+
return await handleHarStart(command, browser);
|
|
3728
3728
|
case "har_stop":
|
|
3729
|
-
return await handleHarStop(
|
|
3729
|
+
return await handleHarStop(command, browser);
|
|
3730
3730
|
case "state_save":
|
|
3731
|
-
return await handleStateSave(
|
|
3731
|
+
return await handleStateSave(command, browser);
|
|
3732
3732
|
case "state_load":
|
|
3733
|
-
return await handleStateLoad(
|
|
3733
|
+
return await handleStateLoad(command, browser);
|
|
3734
3734
|
case "console":
|
|
3735
|
-
return await handleConsole(
|
|
3735
|
+
return await handleConsole(command, browser);
|
|
3736
3736
|
case "errors":
|
|
3737
|
-
return await handleErrors(
|
|
3737
|
+
return await handleErrors(command, browser);
|
|
3738
3738
|
case "keyboard":
|
|
3739
|
-
return await handleKeyboard(
|
|
3739
|
+
return await handleKeyboard(command, browser);
|
|
3740
3740
|
case "wheel":
|
|
3741
|
-
return await handleWheel(
|
|
3741
|
+
return await handleWheel(command, browser);
|
|
3742
3742
|
case "tap":
|
|
3743
|
-
return await handleTap(
|
|
3743
|
+
return await handleTap(command, browser);
|
|
3744
3744
|
case "clipboard":
|
|
3745
|
-
return await handleClipboard(
|
|
3745
|
+
return await handleClipboard(command, browser);
|
|
3746
3746
|
case "highlight":
|
|
3747
|
-
return await handleHighlight(
|
|
3747
|
+
return await handleHighlight(command, browser);
|
|
3748
3748
|
case "clear":
|
|
3749
|
-
return await handleClear(
|
|
3749
|
+
return await handleClear(command, browser);
|
|
3750
3750
|
case "selectall":
|
|
3751
|
-
return await handleSelectAll(
|
|
3751
|
+
return await handleSelectAll(command, browser);
|
|
3752
3752
|
case "innertext":
|
|
3753
|
-
return await handleInnerText(
|
|
3753
|
+
return await handleInnerText(command, browser);
|
|
3754
3754
|
case "innerhtml":
|
|
3755
|
-
return await handleInnerHtml(
|
|
3755
|
+
return await handleInnerHtml(command, browser);
|
|
3756
3756
|
case "inputvalue":
|
|
3757
|
-
return await handleInputValue(
|
|
3757
|
+
return await handleInputValue(command, browser);
|
|
3758
3758
|
case "setvalue":
|
|
3759
|
-
return await handleSetValue(
|
|
3759
|
+
return await handleSetValue(command, browser);
|
|
3760
3760
|
case "dispatch":
|
|
3761
|
-
return await handleDispatch(
|
|
3761
|
+
return await handleDispatch(command, browser);
|
|
3762
3762
|
case "evalhandle":
|
|
3763
|
-
return await handleEvalHandle(
|
|
3763
|
+
return await handleEvalHandle(command, browser);
|
|
3764
3764
|
case "expose":
|
|
3765
|
-
return await handleExpose(
|
|
3765
|
+
return await handleExpose(command, browser);
|
|
3766
3766
|
case "addscript":
|
|
3767
|
-
return await handleAddScript(
|
|
3767
|
+
return await handleAddScript(command, browser);
|
|
3768
3768
|
case "addstyle":
|
|
3769
|
-
return await handleAddStyle(
|
|
3769
|
+
return await handleAddStyle(command, browser);
|
|
3770
3770
|
case "emulatemedia":
|
|
3771
|
-
return await handleEmulateMedia(
|
|
3771
|
+
return await handleEmulateMedia(command, browser);
|
|
3772
3772
|
case "offline":
|
|
3773
|
-
return await handleOffline(
|
|
3773
|
+
return await handleOffline(command, browser);
|
|
3774
3774
|
case "headers":
|
|
3775
|
-
return await handleHeaders(
|
|
3775
|
+
return await handleHeaders(command, browser);
|
|
3776
3776
|
case "pause":
|
|
3777
|
-
return await handlePause(
|
|
3777
|
+
return await handlePause(command, browser);
|
|
3778
3778
|
case "getbyalttext":
|
|
3779
|
-
return await handleGetByAltText(
|
|
3779
|
+
return await handleGetByAltText(command, browser);
|
|
3780
3780
|
case "getbytitle":
|
|
3781
|
-
return await handleGetByTitle(
|
|
3781
|
+
return await handleGetByTitle(command, browser);
|
|
3782
3782
|
case "getbytestid":
|
|
3783
|
-
return await handleGetByTestId(
|
|
3783
|
+
return await handleGetByTestId(command, browser);
|
|
3784
3784
|
case "nth":
|
|
3785
|
-
return await handleNth(
|
|
3785
|
+
return await handleNth(command, browser);
|
|
3786
3786
|
case "waitforurl":
|
|
3787
|
-
return await handleWaitForUrl(
|
|
3787
|
+
return await handleWaitForUrl(command, browser);
|
|
3788
3788
|
case "waitforloadstate":
|
|
3789
|
-
return await handleWaitForLoadState(
|
|
3789
|
+
return await handleWaitForLoadState(command, browser);
|
|
3790
3790
|
case "setcontent":
|
|
3791
|
-
return await handleSetContent(
|
|
3791
|
+
return await handleSetContent(command, browser);
|
|
3792
3792
|
case "timezone":
|
|
3793
|
-
return await handleTimezone(
|
|
3793
|
+
return await handleTimezone(command, browser);
|
|
3794
3794
|
case "locale":
|
|
3795
|
-
return await handleLocale(
|
|
3795
|
+
return await handleLocale(command, browser);
|
|
3796
3796
|
case "credentials":
|
|
3797
|
-
return await handleCredentials(
|
|
3797
|
+
return await handleCredentials(command, browser);
|
|
3798
3798
|
case "mousemove":
|
|
3799
|
-
return await handleMouseMove(
|
|
3799
|
+
return await handleMouseMove(command, browser);
|
|
3800
3800
|
case "mousedown":
|
|
3801
|
-
return await handleMouseDown(
|
|
3801
|
+
return await handleMouseDown(command, browser);
|
|
3802
3802
|
case "mouseup":
|
|
3803
|
-
return await handleMouseUp(
|
|
3803
|
+
return await handleMouseUp(command, browser);
|
|
3804
3804
|
case "bringtofront":
|
|
3805
|
-
return await handleBringToFront(
|
|
3805
|
+
return await handleBringToFront(command, browser);
|
|
3806
3806
|
case "waitforfunction":
|
|
3807
|
-
return await handleWaitForFunction(
|
|
3807
|
+
return await handleWaitForFunction(command, browser);
|
|
3808
3808
|
case "scrollintoview":
|
|
3809
|
-
return await handleScrollIntoView(
|
|
3809
|
+
return await handleScrollIntoView(command, browser);
|
|
3810
3810
|
case "addinitscript":
|
|
3811
|
-
return await handleAddInitScript(
|
|
3811
|
+
return await handleAddInitScript(command, browser);
|
|
3812
3812
|
case "keydown":
|
|
3813
|
-
return await handleKeyDown(
|
|
3813
|
+
return await handleKeyDown(command, browser);
|
|
3814
3814
|
case "keyup":
|
|
3815
|
-
return await handleKeyUp(
|
|
3815
|
+
return await handleKeyUp(command, browser);
|
|
3816
3816
|
case "inserttext":
|
|
3817
|
-
return await handleInsertText(
|
|
3817
|
+
return await handleInsertText(command, browser);
|
|
3818
3818
|
case "multiselect":
|
|
3819
|
-
return await handleMultiSelect(
|
|
3819
|
+
return await handleMultiSelect(command, browser);
|
|
3820
3820
|
case "waitfordownload":
|
|
3821
|
-
return await handleWaitForDownload(
|
|
3821
|
+
return await handleWaitForDownload(command, browser);
|
|
3822
3822
|
case "responsebody":
|
|
3823
|
-
return await handleResponseBody(
|
|
3823
|
+
return await handleResponseBody(command, browser);
|
|
3824
3824
|
case "screencast_start":
|
|
3825
|
-
return await handleScreencastStart(
|
|
3825
|
+
return await handleScreencastStart(command, browser);
|
|
3826
3826
|
case "screencast_stop":
|
|
3827
|
-
return await handleScreencastStop(
|
|
3827
|
+
return await handleScreencastStop(command, browser);
|
|
3828
3828
|
case "input_mouse":
|
|
3829
|
-
return await handleInputMouse(
|
|
3829
|
+
return await handleInputMouse(command, browser);
|
|
3830
3830
|
case "input_keyboard":
|
|
3831
|
-
return await handleInputKeyboard(
|
|
3831
|
+
return await handleInputKeyboard(command, browser);
|
|
3832
3832
|
case "input_touch":
|
|
3833
|
-
return await handleInputTouch(
|
|
3833
|
+
return await handleInputTouch(command, browser);
|
|
3834
3834
|
case "recording_start":
|
|
3835
|
-
return await handleRecordingStart(
|
|
3835
|
+
return await handleRecordingStart(command, browser);
|
|
3836
3836
|
case "recording_stop":
|
|
3837
|
-
return await handleRecordingStop(
|
|
3837
|
+
return await handleRecordingStop(command, browser);
|
|
3838
3838
|
case "recording_restart":
|
|
3839
|
-
return await handleRecordingRestart(
|
|
3839
|
+
return await handleRecordingRestart(command, browser);
|
|
3840
3840
|
default: {
|
|
3841
|
-
const unknownCommand =
|
|
3841
|
+
const unknownCommand = command;
|
|
3842
3842
|
return errorResponse(unknownCommand.id, `Unknown action: ${unknownCommand.action}`);
|
|
3843
3843
|
}
|
|
3844
3844
|
}
|
|
3845
3845
|
} catch (error) {
|
|
3846
3846
|
const message = error instanceof Error ? error.message : String(error);
|
|
3847
|
-
return errorResponse(
|
|
3847
|
+
return errorResponse(command.id, message);
|
|
3848
3848
|
}
|
|
3849
3849
|
}
|
|
3850
|
-
async function handleLaunch(
|
|
3851
|
-
await
|
|
3852
|
-
return successResponse(
|
|
3850
|
+
async function handleLaunch(command, browser) {
|
|
3851
|
+
await browser.launch(command);
|
|
3852
|
+
return successResponse(command.id, { launched: true });
|
|
3853
3853
|
}
|
|
3854
|
-
async function handleNavigate(
|
|
3855
|
-
const
|
|
3856
|
-
if (
|
|
3857
|
-
await
|
|
3854
|
+
async function handleNavigate(command, browser) {
|
|
3855
|
+
const page = browser.getPage();
|
|
3856
|
+
if (command.headers && Object.keys(command.headers).length > 0) {
|
|
3857
|
+
await browser.setScopedHeaders(command.url, command.headers);
|
|
3858
3858
|
}
|
|
3859
|
-
await
|
|
3860
|
-
waitUntil:
|
|
3859
|
+
await page.goto(command.url, {
|
|
3860
|
+
waitUntil: command.waitUntil ?? "load"
|
|
3861
3861
|
});
|
|
3862
|
-
return successResponse(
|
|
3863
|
-
url:
|
|
3864
|
-
title: await
|
|
3862
|
+
return successResponse(command.id, {
|
|
3863
|
+
url: page.url(),
|
|
3864
|
+
title: await page.title()
|
|
3865
3865
|
});
|
|
3866
3866
|
}
|
|
3867
|
-
async function handleClick(
|
|
3868
|
-
if (
|
|
3869
|
-
const refData =
|
|
3867
|
+
async function handleClick(command, browser) {
|
|
3868
|
+
if (browser.isRef(command.selector)) {
|
|
3869
|
+
const refData = browser.getRefData(command.selector);
|
|
3870
3870
|
if (refData && refData.bounds) {
|
|
3871
3871
|
const b = refData.bounds;
|
|
3872
3872
|
const centerX = b.left + (b.right - b.left) / 2;
|
|
3873
3873
|
const centerY = b.top + (b.bottom - b.top) / 2;
|
|
3874
|
-
await
|
|
3874
|
+
await browser.injectMouseEvent({
|
|
3875
3875
|
type: "mousePressed",
|
|
3876
3876
|
x: centerX,
|
|
3877
3877
|
y: centerY,
|
|
3878
|
-
button:
|
|
3879
|
-
clickCount:
|
|
3878
|
+
button: command.button || "left",
|
|
3879
|
+
clickCount: command.clickCount || 1
|
|
3880
3880
|
});
|
|
3881
|
-
await
|
|
3881
|
+
await browser.injectMouseEvent({
|
|
3882
3882
|
type: "mouseReleased",
|
|
3883
3883
|
x: centerX,
|
|
3884
3884
|
y: centerY,
|
|
3885
|
-
button:
|
|
3885
|
+
button: command.button || "left"
|
|
3886
3886
|
});
|
|
3887
|
-
return successResponse(
|
|
3887
|
+
return successResponse(command.id, { clicked: true, method: "cdp_coordinates" });
|
|
3888
3888
|
}
|
|
3889
3889
|
}
|
|
3890
|
-
const
|
|
3890
|
+
const locator = browser.getLocator(command.selector);
|
|
3891
3891
|
try {
|
|
3892
|
-
await
|
|
3893
|
-
button:
|
|
3894
|
-
clickCount:
|
|
3895
|
-
delay:
|
|
3892
|
+
await locator.click({
|
|
3893
|
+
button: command.button,
|
|
3894
|
+
clickCount: command.clickCount,
|
|
3895
|
+
delay: command.delay
|
|
3896
3896
|
});
|
|
3897
3897
|
} catch (error) {
|
|
3898
|
-
throw toAIFriendlyError(error,
|
|
3898
|
+
throw toAIFriendlyError(error, command.selector);
|
|
3899
3899
|
}
|
|
3900
|
-
return successResponse(
|
|
3900
|
+
return successResponse(command.id, { clicked: true, method: "playwright_locator" });
|
|
3901
3901
|
}
|
|
3902
|
-
async function handleType(
|
|
3903
|
-
const
|
|
3902
|
+
async function handleType(command, browser) {
|
|
3903
|
+
const locator = browser.getLocator(command.selector);
|
|
3904
3904
|
try {
|
|
3905
|
-
if (
|
|
3906
|
-
await
|
|
3905
|
+
if (command.clear) {
|
|
3906
|
+
await locator.fill("");
|
|
3907
3907
|
}
|
|
3908
|
-
await
|
|
3909
|
-
delay:
|
|
3908
|
+
await locator.pressSequentially(command.text, {
|
|
3909
|
+
delay: command.delay
|
|
3910
3910
|
});
|
|
3911
3911
|
} catch (error) {
|
|
3912
|
-
throw toAIFriendlyError(error,
|
|
3912
|
+
throw toAIFriendlyError(error, command.selector);
|
|
3913
3913
|
}
|
|
3914
|
-
return successResponse(
|
|
3914
|
+
return successResponse(command.id, { typed: true });
|
|
3915
3915
|
}
|
|
3916
|
-
async function handlePress(
|
|
3917
|
-
const
|
|
3918
|
-
if (
|
|
3919
|
-
await
|
|
3916
|
+
async function handlePress(command, browser) {
|
|
3917
|
+
const page = browser.getPage();
|
|
3918
|
+
if (command.selector) {
|
|
3919
|
+
await page.press(command.selector, command.key);
|
|
3920
3920
|
} else {
|
|
3921
|
-
await
|
|
3921
|
+
await page.keyboard.press(command.key);
|
|
3922
3922
|
}
|
|
3923
|
-
return successResponse(
|
|
3923
|
+
return successResponse(command.id, { pressed: true });
|
|
3924
3924
|
}
|
|
3925
|
-
async function handleScreenshot(
|
|
3926
|
-
const
|
|
3925
|
+
async function handleScreenshot(command, browser) {
|
|
3926
|
+
const page = browser.getPage();
|
|
3927
3927
|
const options = {
|
|
3928
|
-
fullPage:
|
|
3929
|
-
type:
|
|
3928
|
+
fullPage: command.fullPage,
|
|
3929
|
+
type: command.format ?? "png"
|
|
3930
3930
|
};
|
|
3931
|
-
if (
|
|
3932
|
-
options.quality =
|
|
3931
|
+
if (command.format === "jpeg" && command.quality !== void 0) {
|
|
3932
|
+
options.quality = command.quality;
|
|
3933
3933
|
}
|
|
3934
|
-
let target =
|
|
3935
|
-
if (
|
|
3936
|
-
target =
|
|
3934
|
+
let target = page;
|
|
3935
|
+
if (command.selector) {
|
|
3936
|
+
target = browser.getLocator(command.selector);
|
|
3937
3937
|
}
|
|
3938
3938
|
try {
|
|
3939
|
-
let savePath =
|
|
3939
|
+
let savePath = command.path;
|
|
3940
3940
|
if (!savePath) {
|
|
3941
|
-
const ext =
|
|
3941
|
+
const ext = command.format === "jpeg" ? "jpg" : "png";
|
|
3942
3942
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
3943
3943
|
const random = Math.random().toString(36).substring(2, 8);
|
|
3944
3944
|
const filename = `screenshot-${timestamp}-${random}.${ext}`;
|
|
@@ -3947,69 +3947,69 @@ async function handleScreenshot(command2, browser2) {
|
|
|
3947
3947
|
savePath = import_node_path3.default.join(screenshotDir, filename);
|
|
3948
3948
|
}
|
|
3949
3949
|
await target.screenshot({ ...options, path: savePath });
|
|
3950
|
-
return successResponse(
|
|
3950
|
+
return successResponse(command.id, { path: savePath });
|
|
3951
3951
|
} catch (error) {
|
|
3952
|
-
if (
|
|
3953
|
-
throw toAIFriendlyError(error,
|
|
3952
|
+
if (command.selector) {
|
|
3953
|
+
throw toAIFriendlyError(error, command.selector);
|
|
3954
3954
|
}
|
|
3955
3955
|
throw error;
|
|
3956
3956
|
}
|
|
3957
3957
|
}
|
|
3958
|
-
async function handleSnapshot(
|
|
3959
|
-
const { tree, refs } = await
|
|
3960
|
-
interactive:
|
|
3961
|
-
cursor:
|
|
3962
|
-
maxDepth:
|
|
3963
|
-
compact:
|
|
3964
|
-
selector:
|
|
3958
|
+
async function handleSnapshot(command, browser) {
|
|
3959
|
+
const { tree, refs } = await browser.getSnapshot({
|
|
3960
|
+
interactive: command.interactive,
|
|
3961
|
+
cursor: command.cursor,
|
|
3962
|
+
maxDepth: command.maxDepth,
|
|
3963
|
+
compact: command.compact,
|
|
3964
|
+
selector: command.selector
|
|
3965
3965
|
});
|
|
3966
3966
|
const simpleRefs = {};
|
|
3967
3967
|
for (const [ref, data] of Object.entries(refs)) {
|
|
3968
3968
|
simpleRefs[ref] = { role: data.role, name: data.name };
|
|
3969
3969
|
}
|
|
3970
|
-
return successResponse(
|
|
3970
|
+
return successResponse(command.id, {
|
|
3971
3971
|
snapshot: tree || "Empty page",
|
|
3972
3972
|
refs: Object.keys(simpleRefs).length > 0 ? simpleRefs : void 0
|
|
3973
3973
|
});
|
|
3974
3974
|
}
|
|
3975
|
-
async function handleEvaluate(
|
|
3976
|
-
const
|
|
3977
|
-
const result = await
|
|
3978
|
-
return successResponse(
|
|
3979
|
-
}
|
|
3980
|
-
async function handleWait(
|
|
3981
|
-
const
|
|
3982
|
-
if (
|
|
3983
|
-
await
|
|
3984
|
-
state:
|
|
3985
|
-
timeout:
|
|
3975
|
+
async function handleEvaluate(command, browser) {
|
|
3976
|
+
const page = browser.getPage();
|
|
3977
|
+
const result = await page.evaluate(command.script);
|
|
3978
|
+
return successResponse(command.id, { result });
|
|
3979
|
+
}
|
|
3980
|
+
async function handleWait(command, browser) {
|
|
3981
|
+
const page = browser.getPage();
|
|
3982
|
+
if (command.selector) {
|
|
3983
|
+
await page.waitForSelector(command.selector, {
|
|
3984
|
+
state: command.state ?? "visible",
|
|
3985
|
+
timeout: command.timeout
|
|
3986
3986
|
});
|
|
3987
|
-
} else if (
|
|
3988
|
-
await
|
|
3987
|
+
} else if (command.timeout) {
|
|
3988
|
+
await page.waitForTimeout(command.timeout);
|
|
3989
3989
|
} else {
|
|
3990
|
-
await
|
|
3991
|
-
}
|
|
3992
|
-
return successResponse(
|
|
3993
|
-
}
|
|
3994
|
-
async function handleScroll(
|
|
3995
|
-
const
|
|
3996
|
-
if (
|
|
3997
|
-
const
|
|
3998
|
-
await
|
|
3999
|
-
if (
|
|
4000
|
-
await
|
|
4001
|
-
(
|
|
4002
|
-
|
|
3990
|
+
await page.waitForLoadState("load");
|
|
3991
|
+
}
|
|
3992
|
+
return successResponse(command.id, { waited: true });
|
|
3993
|
+
}
|
|
3994
|
+
async function handleScroll(command, browser) {
|
|
3995
|
+
const page = browser.getPage();
|
|
3996
|
+
if (command.selector) {
|
|
3997
|
+
const element = page.locator(command.selector);
|
|
3998
|
+
await element.scrollIntoViewIfNeeded();
|
|
3999
|
+
if (command.x !== void 0 || command.y !== void 0) {
|
|
4000
|
+
await element.evaluate(
|
|
4001
|
+
(el, { x, y }) => {
|
|
4002
|
+
el.scrollBy(x ?? 0, y ?? 0);
|
|
4003
4003
|
},
|
|
4004
|
-
{ x:
|
|
4004
|
+
{ x: command.x, y: command.y }
|
|
4005
4005
|
);
|
|
4006
4006
|
}
|
|
4007
4007
|
} else {
|
|
4008
|
-
let deltaX =
|
|
4009
|
-
let deltaY =
|
|
4010
|
-
if (
|
|
4011
|
-
const amount =
|
|
4012
|
-
switch (
|
|
4008
|
+
let deltaX = command.x ?? 0;
|
|
4009
|
+
let deltaY = command.y ?? 0;
|
|
4010
|
+
if (command.direction) {
|
|
4011
|
+
const amount = command.amount ?? 100;
|
|
4012
|
+
switch (command.direction) {
|
|
4013
4013
|
case "up":
|
|
4014
4014
|
deltaY = -amount;
|
|
4015
4015
|
break;
|
|
@@ -4024,236 +4024,236 @@ async function handleScroll(command2, browser2) {
|
|
|
4024
4024
|
break;
|
|
4025
4025
|
}
|
|
4026
4026
|
}
|
|
4027
|
-
await
|
|
4027
|
+
await page.evaluate(`window.scrollBy(${deltaX}, ${deltaY})`);
|
|
4028
4028
|
}
|
|
4029
|
-
return successResponse(
|
|
4029
|
+
return successResponse(command.id, { scrolled: true });
|
|
4030
4030
|
}
|
|
4031
|
-
async function handleSelect(
|
|
4032
|
-
const
|
|
4033
|
-
const values = Array.isArray(
|
|
4031
|
+
async function handleSelect(command, browser) {
|
|
4032
|
+
const locator = browser.getLocator(command.selector);
|
|
4033
|
+
const values = Array.isArray(command.values) ? command.values : [command.values];
|
|
4034
4034
|
try {
|
|
4035
|
-
await
|
|
4035
|
+
await locator.selectOption(values);
|
|
4036
4036
|
} catch (error) {
|
|
4037
|
-
throw toAIFriendlyError(error,
|
|
4037
|
+
throw toAIFriendlyError(error, command.selector);
|
|
4038
4038
|
}
|
|
4039
|
-
return successResponse(
|
|
4039
|
+
return successResponse(command.id, { selected: values });
|
|
4040
4040
|
}
|
|
4041
|
-
async function handleHover(
|
|
4042
|
-
const
|
|
4041
|
+
async function handleHover(command, browser) {
|
|
4042
|
+
const locator = browser.getLocator(command.selector);
|
|
4043
4043
|
try {
|
|
4044
|
-
await
|
|
4044
|
+
await locator.hover();
|
|
4045
4045
|
} catch (error) {
|
|
4046
|
-
throw toAIFriendlyError(error,
|
|
4046
|
+
throw toAIFriendlyError(error, command.selector);
|
|
4047
4047
|
}
|
|
4048
|
-
return successResponse(
|
|
4048
|
+
return successResponse(command.id, { hovered: true });
|
|
4049
4049
|
}
|
|
4050
|
-
async function handleContent(
|
|
4051
|
-
const
|
|
4050
|
+
async function handleContent(command, browser) {
|
|
4051
|
+
const page = browser.getPage();
|
|
4052
4052
|
let html;
|
|
4053
|
-
if (
|
|
4054
|
-
html = await
|
|
4053
|
+
if (command.selector) {
|
|
4054
|
+
html = await page.locator(command.selector).innerHTML();
|
|
4055
4055
|
} else {
|
|
4056
|
-
html = await
|
|
4056
|
+
html = await page.content();
|
|
4057
4057
|
}
|
|
4058
|
-
return successResponse(
|
|
4058
|
+
return successResponse(command.id, { html });
|
|
4059
4059
|
}
|
|
4060
|
-
async function handleClose(
|
|
4061
|
-
await
|
|
4062
|
-
return successResponse(
|
|
4060
|
+
async function handleClose(command, browser) {
|
|
4061
|
+
await browser.close();
|
|
4062
|
+
return successResponse(command.id, { closed: true });
|
|
4063
4063
|
}
|
|
4064
|
-
async function handleTabNew(
|
|
4065
|
-
const result = await
|
|
4066
|
-
if (
|
|
4067
|
-
const
|
|
4068
|
-
await
|
|
4064
|
+
async function handleTabNew(command, browser) {
|
|
4065
|
+
const result = await browser.newTab();
|
|
4066
|
+
if (command.url) {
|
|
4067
|
+
const page = browser.getPage();
|
|
4068
|
+
await page.goto(command.url, { waitUntil: "domcontentloaded" });
|
|
4069
4069
|
}
|
|
4070
|
-
return successResponse(
|
|
4070
|
+
return successResponse(command.id, result);
|
|
4071
4071
|
}
|
|
4072
|
-
async function handleTabList(
|
|
4073
|
-
const tabs = await
|
|
4074
|
-
return successResponse(
|
|
4072
|
+
async function handleTabList(command, browser) {
|
|
4073
|
+
const tabs = await browser.listTabs();
|
|
4074
|
+
return successResponse(command.id, {
|
|
4075
4075
|
tabs,
|
|
4076
|
-
active:
|
|
4076
|
+
active: browser.getActiveIndex()
|
|
4077
4077
|
});
|
|
4078
4078
|
}
|
|
4079
|
-
async function handleTabSwitch(
|
|
4080
|
-
const result = await
|
|
4081
|
-
const
|
|
4082
|
-
return successResponse(
|
|
4079
|
+
async function handleTabSwitch(command, browser) {
|
|
4080
|
+
const result = await browser.switchTo(command.index);
|
|
4081
|
+
const page = browser.getPage();
|
|
4082
|
+
return successResponse(command.id, {
|
|
4083
4083
|
...result,
|
|
4084
|
-
title: await
|
|
4084
|
+
title: await page.title()
|
|
4085
4085
|
});
|
|
4086
4086
|
}
|
|
4087
|
-
async function handleTabClose(
|
|
4088
|
-
const result = await
|
|
4089
|
-
return successResponse(
|
|
4087
|
+
async function handleTabClose(command, browser) {
|
|
4088
|
+
const result = await browser.closeTab(command.index);
|
|
4089
|
+
return successResponse(command.id, result);
|
|
4090
4090
|
}
|
|
4091
|
-
async function handleWindowNew(
|
|
4092
|
-
const result = await
|
|
4093
|
-
return successResponse(
|
|
4091
|
+
async function handleWindowNew(command, browser) {
|
|
4092
|
+
const result = await browser.newWindow(command.viewport);
|
|
4093
|
+
return successResponse(command.id, result);
|
|
4094
4094
|
}
|
|
4095
|
-
async function handleFill(
|
|
4096
|
-
const
|
|
4095
|
+
async function handleFill(command, browser) {
|
|
4096
|
+
const locator = browser.getLocator(command.selector);
|
|
4097
4097
|
try {
|
|
4098
|
-
await
|
|
4098
|
+
await locator.fill(command.value);
|
|
4099
4099
|
} catch (error) {
|
|
4100
|
-
throw toAIFriendlyError(error,
|
|
4100
|
+
throw toAIFriendlyError(error, command.selector);
|
|
4101
4101
|
}
|
|
4102
|
-
return successResponse(
|
|
4102
|
+
return successResponse(command.id, { filled: true });
|
|
4103
4103
|
}
|
|
4104
|
-
async function handleCheck(
|
|
4105
|
-
const
|
|
4104
|
+
async function handleCheck(command, browser) {
|
|
4105
|
+
const locator = browser.getLocator(command.selector);
|
|
4106
4106
|
try {
|
|
4107
|
-
await
|
|
4107
|
+
await locator.check();
|
|
4108
4108
|
} catch (error) {
|
|
4109
|
-
throw toAIFriendlyError(error,
|
|
4109
|
+
throw toAIFriendlyError(error, command.selector);
|
|
4110
4110
|
}
|
|
4111
|
-
return successResponse(
|
|
4111
|
+
return successResponse(command.id, { checked: true });
|
|
4112
4112
|
}
|
|
4113
|
-
async function handleUncheck(
|
|
4114
|
-
const
|
|
4113
|
+
async function handleUncheck(command, browser) {
|
|
4114
|
+
const locator = browser.getLocator(command.selector);
|
|
4115
4115
|
try {
|
|
4116
|
-
await
|
|
4116
|
+
await locator.uncheck();
|
|
4117
4117
|
} catch (error) {
|
|
4118
|
-
throw toAIFriendlyError(error,
|
|
4118
|
+
throw toAIFriendlyError(error, command.selector);
|
|
4119
4119
|
}
|
|
4120
|
-
return successResponse(
|
|
4120
|
+
return successResponse(command.id, { unchecked: true });
|
|
4121
4121
|
}
|
|
4122
|
-
async function handleUpload(
|
|
4123
|
-
const
|
|
4124
|
-
const files = Array.isArray(
|
|
4122
|
+
async function handleUpload(command, browser) {
|
|
4123
|
+
const locator = browser.getLocator(command.selector);
|
|
4124
|
+
const files = Array.isArray(command.files) ? command.files : [command.files];
|
|
4125
4125
|
try {
|
|
4126
|
-
await
|
|
4126
|
+
await locator.setInputFiles(files);
|
|
4127
4127
|
} catch (error) {
|
|
4128
|
-
throw toAIFriendlyError(error,
|
|
4128
|
+
throw toAIFriendlyError(error, command.selector);
|
|
4129
4129
|
}
|
|
4130
|
-
return successResponse(
|
|
4130
|
+
return successResponse(command.id, { uploaded: files });
|
|
4131
4131
|
}
|
|
4132
|
-
async function handleDoubleClick(
|
|
4133
|
-
const
|
|
4132
|
+
async function handleDoubleClick(command, browser) {
|
|
4133
|
+
const locator = browser.getLocator(command.selector);
|
|
4134
4134
|
try {
|
|
4135
|
-
await
|
|
4135
|
+
await locator.dblclick();
|
|
4136
4136
|
} catch (error) {
|
|
4137
|
-
throw toAIFriendlyError(error,
|
|
4137
|
+
throw toAIFriendlyError(error, command.selector);
|
|
4138
4138
|
}
|
|
4139
|
-
return successResponse(
|
|
4139
|
+
return successResponse(command.id, { clicked: true });
|
|
4140
4140
|
}
|
|
4141
|
-
async function handleFocus(
|
|
4142
|
-
const
|
|
4141
|
+
async function handleFocus(command, browser) {
|
|
4142
|
+
const locator = browser.getLocator(command.selector);
|
|
4143
4143
|
try {
|
|
4144
|
-
await
|
|
4144
|
+
await locator.focus();
|
|
4145
4145
|
} catch (error) {
|
|
4146
|
-
throw toAIFriendlyError(error,
|
|
4146
|
+
throw toAIFriendlyError(error, command.selector);
|
|
4147
4147
|
}
|
|
4148
|
-
return successResponse(
|
|
4148
|
+
return successResponse(command.id, { focused: true });
|
|
4149
4149
|
}
|
|
4150
|
-
async function handleDrag(
|
|
4151
|
-
const frame =
|
|
4152
|
-
await frame.dragAndDrop(
|
|
4153
|
-
return successResponse(
|
|
4150
|
+
async function handleDrag(command, browser) {
|
|
4151
|
+
const frame = browser.getFrame();
|
|
4152
|
+
await frame.dragAndDrop(command.source, command.target);
|
|
4153
|
+
return successResponse(command.id, { dragged: true });
|
|
4154
4154
|
}
|
|
4155
|
-
async function handleFrame(
|
|
4156
|
-
await
|
|
4157
|
-
selector:
|
|
4158
|
-
name:
|
|
4159
|
-
url:
|
|
4155
|
+
async function handleFrame(command, browser) {
|
|
4156
|
+
await browser.switchToFrame({
|
|
4157
|
+
selector: command.selector,
|
|
4158
|
+
name: command.name,
|
|
4159
|
+
url: command.url
|
|
4160
4160
|
});
|
|
4161
|
-
return successResponse(
|
|
4161
|
+
return successResponse(command.id, { switched: true });
|
|
4162
4162
|
}
|
|
4163
|
-
async function handleMainFrame(
|
|
4164
|
-
|
|
4165
|
-
return successResponse(
|
|
4163
|
+
async function handleMainFrame(command, browser) {
|
|
4164
|
+
browser.switchToMainFrame();
|
|
4165
|
+
return successResponse(command.id, { switched: true });
|
|
4166
4166
|
}
|
|
4167
|
-
async function handleGetByRole(
|
|
4168
|
-
const
|
|
4169
|
-
const
|
|
4170
|
-
switch (
|
|
4167
|
+
async function handleGetByRole(command, browser) {
|
|
4168
|
+
const page = browser.getPage();
|
|
4169
|
+
const locator = page.getByRole(command.role, { name: command.name, exact: command.exact });
|
|
4170
|
+
switch (command.subaction) {
|
|
4171
4171
|
case "click":
|
|
4172
|
-
await
|
|
4173
|
-
return successResponse(
|
|
4172
|
+
await locator.click();
|
|
4173
|
+
return successResponse(command.id, { clicked: true });
|
|
4174
4174
|
case "fill":
|
|
4175
|
-
await
|
|
4176
|
-
return successResponse(
|
|
4175
|
+
await locator.fill(command.value ?? "");
|
|
4176
|
+
return successResponse(command.id, { filled: true });
|
|
4177
4177
|
case "check":
|
|
4178
|
-
await
|
|
4179
|
-
return successResponse(
|
|
4178
|
+
await locator.check();
|
|
4179
|
+
return successResponse(command.id, { checked: true });
|
|
4180
4180
|
case "hover":
|
|
4181
|
-
await
|
|
4182
|
-
return successResponse(
|
|
4181
|
+
await locator.hover();
|
|
4182
|
+
return successResponse(command.id, { hovered: true });
|
|
4183
4183
|
}
|
|
4184
4184
|
}
|
|
4185
|
-
async function handleGetByText(
|
|
4186
|
-
const
|
|
4187
|
-
const
|
|
4188
|
-
switch (
|
|
4185
|
+
async function handleGetByText(command, browser) {
|
|
4186
|
+
const page = browser.getPage();
|
|
4187
|
+
const locator = page.getByText(command.text, { exact: command.exact });
|
|
4188
|
+
switch (command.subaction) {
|
|
4189
4189
|
case "click":
|
|
4190
|
-
await
|
|
4191
|
-
return successResponse(
|
|
4190
|
+
await locator.click();
|
|
4191
|
+
return successResponse(command.id, { clicked: true });
|
|
4192
4192
|
case "hover":
|
|
4193
|
-
await
|
|
4194
|
-
return successResponse(
|
|
4193
|
+
await locator.hover();
|
|
4194
|
+
return successResponse(command.id, { hovered: true });
|
|
4195
4195
|
}
|
|
4196
4196
|
}
|
|
4197
|
-
async function handleGetByLabel(
|
|
4198
|
-
const
|
|
4199
|
-
const
|
|
4200
|
-
switch (
|
|
4197
|
+
async function handleGetByLabel(command, browser) {
|
|
4198
|
+
const page = browser.getPage();
|
|
4199
|
+
const locator = page.getByLabel(command.label, { exact: command.exact });
|
|
4200
|
+
switch (command.subaction) {
|
|
4201
4201
|
case "click":
|
|
4202
|
-
await
|
|
4203
|
-
return successResponse(
|
|
4202
|
+
await locator.click();
|
|
4203
|
+
return successResponse(command.id, { clicked: true });
|
|
4204
4204
|
case "fill":
|
|
4205
|
-
await
|
|
4206
|
-
return successResponse(
|
|
4205
|
+
await locator.fill(command.value ?? "");
|
|
4206
|
+
return successResponse(command.id, { filled: true });
|
|
4207
4207
|
case "check":
|
|
4208
|
-
await
|
|
4209
|
-
return successResponse(
|
|
4208
|
+
await locator.check();
|
|
4209
|
+
return successResponse(command.id, { checked: true });
|
|
4210
4210
|
}
|
|
4211
4211
|
}
|
|
4212
|
-
async function handleGetByPlaceholder(
|
|
4213
|
-
const
|
|
4214
|
-
const
|
|
4215
|
-
switch (
|
|
4212
|
+
async function handleGetByPlaceholder(command, browser) {
|
|
4213
|
+
const page = browser.getPage();
|
|
4214
|
+
const locator = page.getByPlaceholder(command.placeholder, { exact: command.exact });
|
|
4215
|
+
switch (command.subaction) {
|
|
4216
4216
|
case "click":
|
|
4217
|
-
await
|
|
4218
|
-
return successResponse(
|
|
4217
|
+
await locator.click();
|
|
4218
|
+
return successResponse(command.id, { clicked: true });
|
|
4219
4219
|
case "fill":
|
|
4220
|
-
await
|
|
4221
|
-
return successResponse(
|
|
4220
|
+
await locator.fill(command.value ?? "");
|
|
4221
|
+
return successResponse(command.id, { filled: true });
|
|
4222
4222
|
}
|
|
4223
4223
|
}
|
|
4224
|
-
async function handleCookiesGet(
|
|
4225
|
-
const
|
|
4226
|
-
const context =
|
|
4227
|
-
const cookies = await context.cookies(
|
|
4228
|
-
return successResponse(
|
|
4224
|
+
async function handleCookiesGet(command, browser) {
|
|
4225
|
+
const page = browser.getPage();
|
|
4226
|
+
const context = page.context();
|
|
4227
|
+
const cookies = await context.cookies(command.urls);
|
|
4228
|
+
return successResponse(command.id, { cookies });
|
|
4229
4229
|
}
|
|
4230
|
-
async function handleCookiesSet(
|
|
4231
|
-
const
|
|
4232
|
-
const context =
|
|
4233
|
-
const pageUrl =
|
|
4234
|
-
const cookies =
|
|
4230
|
+
async function handleCookiesSet(command, browser) {
|
|
4231
|
+
const page = browser.getPage();
|
|
4232
|
+
const context = page.context();
|
|
4233
|
+
const pageUrl = page.url();
|
|
4234
|
+
const cookies = command.cookies.map((cookie) => {
|
|
4235
4235
|
if (!cookie.url && !cookie.domain && !cookie.path) {
|
|
4236
4236
|
return { ...cookie, url: pageUrl };
|
|
4237
4237
|
}
|
|
4238
4238
|
return cookie;
|
|
4239
4239
|
});
|
|
4240
4240
|
await context.addCookies(cookies);
|
|
4241
|
-
return successResponse(
|
|
4241
|
+
return successResponse(command.id, { set: true });
|
|
4242
4242
|
}
|
|
4243
|
-
async function handleCookiesClear(
|
|
4244
|
-
const
|
|
4245
|
-
const context =
|
|
4243
|
+
async function handleCookiesClear(command, browser) {
|
|
4244
|
+
const page = browser.getPage();
|
|
4245
|
+
const context = page.context();
|
|
4246
4246
|
await context.clearCookies();
|
|
4247
|
-
return successResponse(
|
|
4248
|
-
}
|
|
4249
|
-
async function handleStorageGet(
|
|
4250
|
-
const
|
|
4251
|
-
const storageType =
|
|
4252
|
-
if (
|
|
4253
|
-
const value = await
|
|
4254
|
-
return successResponse(
|
|
4247
|
+
return successResponse(command.id, { cleared: true });
|
|
4248
|
+
}
|
|
4249
|
+
async function handleStorageGet(command, browser) {
|
|
4250
|
+
const page = browser.getPage();
|
|
4251
|
+
const storageType = command.type === "local" ? "localStorage" : "sessionStorage";
|
|
4252
|
+
if (command.key) {
|
|
4253
|
+
const value = await page.evaluate(`${storageType}.getItem(${JSON.stringify(command.key)})`);
|
|
4254
|
+
return successResponse(command.id, { key: command.key, value });
|
|
4255
4255
|
} else {
|
|
4256
|
-
const data = await
|
|
4256
|
+
const data = await page.evaluate(`
|
|
4257
4257
|
(() => {
|
|
4258
4258
|
const storage = ${storageType};
|
|
4259
4259
|
const result = {};
|
|
@@ -4264,102 +4264,102 @@ async function handleStorageGet(command2, browser2) {
|
|
|
4264
4264
|
return result;
|
|
4265
4265
|
})()
|
|
4266
4266
|
`);
|
|
4267
|
-
return successResponse(
|
|
4267
|
+
return successResponse(command.id, { data });
|
|
4268
4268
|
}
|
|
4269
4269
|
}
|
|
4270
|
-
async function handleStorageSet(
|
|
4271
|
-
const
|
|
4272
|
-
const storageType =
|
|
4273
|
-
await
|
|
4274
|
-
`${storageType}.setItem(${JSON.stringify(
|
|
4270
|
+
async function handleStorageSet(command, browser) {
|
|
4271
|
+
const page = browser.getPage();
|
|
4272
|
+
const storageType = command.type === "local" ? "localStorage" : "sessionStorage";
|
|
4273
|
+
await page.evaluate(
|
|
4274
|
+
`${storageType}.setItem(${JSON.stringify(command.key)}, ${JSON.stringify(command.value)})`
|
|
4275
4275
|
);
|
|
4276
|
-
return successResponse(
|
|
4277
|
-
}
|
|
4278
|
-
async function handleStorageClear(
|
|
4279
|
-
const
|
|
4280
|
-
const storageType =
|
|
4281
|
-
await
|
|
4282
|
-
return successResponse(
|
|
4283
|
-
}
|
|
4284
|
-
async function handleDialog(
|
|
4285
|
-
|
|
4286
|
-
return successResponse(
|
|
4287
|
-
}
|
|
4288
|
-
async function handlePdf(
|
|
4289
|
-
const
|
|
4290
|
-
await
|
|
4291
|
-
path:
|
|
4292
|
-
format:
|
|
4276
|
+
return successResponse(command.id, { set: true });
|
|
4277
|
+
}
|
|
4278
|
+
async function handleStorageClear(command, browser) {
|
|
4279
|
+
const page = browser.getPage();
|
|
4280
|
+
const storageType = command.type === "local" ? "localStorage" : "sessionStorage";
|
|
4281
|
+
await page.evaluate(`${storageType}.clear()`);
|
|
4282
|
+
return successResponse(command.id, { cleared: true });
|
|
4283
|
+
}
|
|
4284
|
+
async function handleDialog(command, browser) {
|
|
4285
|
+
browser.setDialogHandler(command.response, command.promptText);
|
|
4286
|
+
return successResponse(command.id, { handler: "set", response: command.response });
|
|
4287
|
+
}
|
|
4288
|
+
async function handlePdf(command, browser) {
|
|
4289
|
+
const page = browser.getPage();
|
|
4290
|
+
await page.pdf({
|
|
4291
|
+
path: command.path,
|
|
4292
|
+
format: command.format ?? "Letter"
|
|
4293
4293
|
});
|
|
4294
|
-
return successResponse(
|
|
4294
|
+
return successResponse(command.id, { path: command.path });
|
|
4295
4295
|
}
|
|
4296
|
-
async function handleRoute(
|
|
4297
|
-
await
|
|
4298
|
-
response:
|
|
4299
|
-
abort:
|
|
4296
|
+
async function handleRoute(command, browser) {
|
|
4297
|
+
await browser.addRoute(command.url, {
|
|
4298
|
+
response: command.response,
|
|
4299
|
+
abort: command.abort
|
|
4300
4300
|
});
|
|
4301
|
-
return successResponse(
|
|
4302
|
-
}
|
|
4303
|
-
async function handleUnroute(
|
|
4304
|
-
await
|
|
4305
|
-
return successResponse(
|
|
4306
|
-
}
|
|
4307
|
-
async function handleRequests(
|
|
4308
|
-
if (
|
|
4309
|
-
|
|
4310
|
-
return successResponse(
|
|
4311
|
-
}
|
|
4312
|
-
|
|
4313
|
-
const requests =
|
|
4314
|
-
return successResponse(
|
|
4315
|
-
}
|
|
4316
|
-
async function handleDownload(
|
|
4317
|
-
const
|
|
4318
|
-
const
|
|
4319
|
-
const [download] = await Promise.all([
|
|
4320
|
-
await download.saveAs(
|
|
4321
|
-
return successResponse(
|
|
4322
|
-
path:
|
|
4301
|
+
return successResponse(command.id, { routed: command.url });
|
|
4302
|
+
}
|
|
4303
|
+
async function handleUnroute(command, browser) {
|
|
4304
|
+
await browser.removeRoute(command.url);
|
|
4305
|
+
return successResponse(command.id, { unrouted: command.url ?? "all" });
|
|
4306
|
+
}
|
|
4307
|
+
async function handleRequests(command, browser) {
|
|
4308
|
+
if (command.clear) {
|
|
4309
|
+
browser.clearRequests();
|
|
4310
|
+
return successResponse(command.id, { cleared: true });
|
|
4311
|
+
}
|
|
4312
|
+
browser.startRequestTracking();
|
|
4313
|
+
const requests = browser.getRequests(command.filter);
|
|
4314
|
+
return successResponse(command.id, { requests });
|
|
4315
|
+
}
|
|
4316
|
+
async function handleDownload(command, browser) {
|
|
4317
|
+
const page = browser.getPage();
|
|
4318
|
+
const locator = browser.getLocator(command.selector);
|
|
4319
|
+
const [download] = await Promise.all([page.waitForEvent("download"), locator.click()]);
|
|
4320
|
+
await download.saveAs(command.path);
|
|
4321
|
+
return successResponse(command.id, {
|
|
4322
|
+
path: command.path,
|
|
4323
4323
|
suggestedFilename: download.suggestedFilename()
|
|
4324
4324
|
});
|
|
4325
4325
|
}
|
|
4326
|
-
async function handleGeolocation(
|
|
4327
|
-
await
|
|
4328
|
-
return successResponse(
|
|
4329
|
-
latitude:
|
|
4330
|
-
longitude:
|
|
4326
|
+
async function handleGeolocation(command, browser) {
|
|
4327
|
+
await browser.setGeolocation(command.latitude, command.longitude, command.accuracy);
|
|
4328
|
+
return successResponse(command.id, {
|
|
4329
|
+
latitude: command.latitude,
|
|
4330
|
+
longitude: command.longitude
|
|
4331
4331
|
});
|
|
4332
4332
|
}
|
|
4333
|
-
async function handlePermissions(
|
|
4334
|
-
await
|
|
4335
|
-
return successResponse(
|
|
4336
|
-
permissions:
|
|
4337
|
-
granted:
|
|
4333
|
+
async function handlePermissions(command, browser) {
|
|
4334
|
+
await browser.setPermissions(command.permissions, command.grant);
|
|
4335
|
+
return successResponse(command.id, {
|
|
4336
|
+
permissions: command.permissions,
|
|
4337
|
+
granted: command.grant
|
|
4338
4338
|
});
|
|
4339
4339
|
}
|
|
4340
|
-
async function handleViewport(
|
|
4341
|
-
await
|
|
4342
|
-
return successResponse(
|
|
4343
|
-
width:
|
|
4344
|
-
height:
|
|
4340
|
+
async function handleViewport(command, browser) {
|
|
4341
|
+
await browser.setViewport(command.width, command.height);
|
|
4342
|
+
return successResponse(command.id, {
|
|
4343
|
+
width: command.width,
|
|
4344
|
+
height: command.height
|
|
4345
4345
|
});
|
|
4346
4346
|
}
|
|
4347
|
-
async function handleUserAgent(
|
|
4348
|
-
const
|
|
4349
|
-
const context =
|
|
4350
|
-
return successResponse(
|
|
4347
|
+
async function handleUserAgent(command, browser) {
|
|
4348
|
+
const page = browser.getPage();
|
|
4349
|
+
const context = page.context();
|
|
4350
|
+
return successResponse(command.id, {
|
|
4351
4351
|
note: "User agent can only be set at launch time. Use device command instead."
|
|
4352
4352
|
});
|
|
4353
4353
|
}
|
|
4354
|
-
async function handleDevice(
|
|
4355
|
-
const device =
|
|
4354
|
+
async function handleDevice(command, browser) {
|
|
4355
|
+
const device = browser.getDevice(command.device);
|
|
4356
4356
|
if (!device) {
|
|
4357
|
-
const available =
|
|
4358
|
-
throw new Error(`Unknown device: ${
|
|
4357
|
+
const available = browser.listDevices().slice(0, 10).join(", ");
|
|
4358
|
+
throw new Error(`Unknown device: ${command.device}. Available: ${available}...`);
|
|
4359
4359
|
}
|
|
4360
|
-
await
|
|
4360
|
+
await browser.setViewport(device.viewport.width, device.viewport.height);
|
|
4361
4361
|
if (device.deviceScaleFactor && device.deviceScaleFactor !== 1) {
|
|
4362
|
-
await
|
|
4362
|
+
await browser.setDeviceScaleFactor(
|
|
4363
4363
|
device.deviceScaleFactor,
|
|
4364
4364
|
device.viewport.width,
|
|
4365
4365
|
device.viewport.height,
|
|
@@ -4367,79 +4367,79 @@ async function handleDevice(command2, browser2) {
|
|
|
4367
4367
|
);
|
|
4368
4368
|
} else {
|
|
4369
4369
|
try {
|
|
4370
|
-
await
|
|
4370
|
+
await browser.clearDeviceMetricsOverride();
|
|
4371
4371
|
} catch {
|
|
4372
4372
|
}
|
|
4373
4373
|
}
|
|
4374
|
-
return successResponse(
|
|
4375
|
-
device:
|
|
4374
|
+
return successResponse(command.id, {
|
|
4375
|
+
device: command.device,
|
|
4376
4376
|
viewport: device.viewport,
|
|
4377
4377
|
userAgent: device.userAgent,
|
|
4378
4378
|
deviceScaleFactor: device.deviceScaleFactor
|
|
4379
4379
|
});
|
|
4380
4380
|
}
|
|
4381
|
-
async function handleBack(
|
|
4382
|
-
const
|
|
4383
|
-
await
|
|
4384
|
-
return successResponse(
|
|
4385
|
-
}
|
|
4386
|
-
async function handleForward(
|
|
4387
|
-
const
|
|
4388
|
-
await
|
|
4389
|
-
return successResponse(
|
|
4390
|
-
}
|
|
4391
|
-
async function handleReload(
|
|
4392
|
-
const
|
|
4393
|
-
await
|
|
4394
|
-
return successResponse(
|
|
4395
|
-
}
|
|
4396
|
-
async function handleUrl(
|
|
4397
|
-
const
|
|
4398
|
-
return successResponse(
|
|
4399
|
-
}
|
|
4400
|
-
async function handleTitle(
|
|
4401
|
-
const
|
|
4402
|
-
const title = await
|
|
4403
|
-
return successResponse(
|
|
4404
|
-
}
|
|
4405
|
-
async function handleGetAttribute(
|
|
4406
|
-
const
|
|
4407
|
-
const value = await
|
|
4408
|
-
return successResponse(
|
|
4409
|
-
}
|
|
4410
|
-
async function handleGetText(
|
|
4411
|
-
const
|
|
4412
|
-
const text = await
|
|
4413
|
-
return successResponse(
|
|
4414
|
-
}
|
|
4415
|
-
async function handleIsVisible(
|
|
4416
|
-
const
|
|
4417
|
-
const visible = await
|
|
4418
|
-
return successResponse(
|
|
4419
|
-
}
|
|
4420
|
-
async function handleIsEnabled(
|
|
4421
|
-
const
|
|
4422
|
-
const enabled = await
|
|
4423
|
-
return successResponse(
|
|
4424
|
-
}
|
|
4425
|
-
async function handleIsChecked(
|
|
4426
|
-
const
|
|
4427
|
-
const checked = await
|
|
4428
|
-
return successResponse(
|
|
4429
|
-
}
|
|
4430
|
-
async function handleCount(
|
|
4431
|
-
const
|
|
4432
|
-
const count = await
|
|
4433
|
-
return successResponse(
|
|
4434
|
-
}
|
|
4435
|
-
async function handleBoundingBox(
|
|
4436
|
-
const
|
|
4437
|
-
const box = await
|
|
4438
|
-
return successResponse(
|
|
4381
|
+
async function handleBack(command, browser) {
|
|
4382
|
+
const page = browser.getPage();
|
|
4383
|
+
await page.goBack();
|
|
4384
|
+
return successResponse(command.id, { url: page.url() });
|
|
4385
|
+
}
|
|
4386
|
+
async function handleForward(command, browser) {
|
|
4387
|
+
const page = browser.getPage();
|
|
4388
|
+
await page.goForward();
|
|
4389
|
+
return successResponse(command.id, { url: page.url() });
|
|
4390
|
+
}
|
|
4391
|
+
async function handleReload(command, browser) {
|
|
4392
|
+
const page = browser.getPage();
|
|
4393
|
+
await page.reload();
|
|
4394
|
+
return successResponse(command.id, { url: page.url() });
|
|
4395
|
+
}
|
|
4396
|
+
async function handleUrl(command, browser) {
|
|
4397
|
+
const page = browser.getPage();
|
|
4398
|
+
return successResponse(command.id, { url: page.url() });
|
|
4399
|
+
}
|
|
4400
|
+
async function handleTitle(command, browser) {
|
|
4401
|
+
const page = browser.getPage();
|
|
4402
|
+
const title = await page.title();
|
|
4403
|
+
return successResponse(command.id, { title });
|
|
4404
|
+
}
|
|
4405
|
+
async function handleGetAttribute(command, browser) {
|
|
4406
|
+
const locator = browser.getLocator(command.selector);
|
|
4407
|
+
const value = await locator.getAttribute(command.attribute);
|
|
4408
|
+
return successResponse(command.id, { attribute: command.attribute, value });
|
|
4409
|
+
}
|
|
4410
|
+
async function handleGetText(command, browser) {
|
|
4411
|
+
const locator = browser.getLocator(command.selector);
|
|
4412
|
+
const text = await locator.textContent();
|
|
4413
|
+
return successResponse(command.id, { text });
|
|
4414
|
+
}
|
|
4415
|
+
async function handleIsVisible(command, browser) {
|
|
4416
|
+
const locator = browser.getLocator(command.selector);
|
|
4417
|
+
const visible = await locator.isVisible();
|
|
4418
|
+
return successResponse(command.id, { visible });
|
|
4419
|
+
}
|
|
4420
|
+
async function handleIsEnabled(command, browser) {
|
|
4421
|
+
const locator = browser.getLocator(command.selector);
|
|
4422
|
+
const enabled = await locator.isEnabled();
|
|
4423
|
+
return successResponse(command.id, { enabled });
|
|
4424
|
+
}
|
|
4425
|
+
async function handleIsChecked(command, browser) {
|
|
4426
|
+
const locator = browser.getLocator(command.selector);
|
|
4427
|
+
const checked = await locator.isChecked();
|
|
4428
|
+
return successResponse(command.id, { checked });
|
|
4429
|
+
}
|
|
4430
|
+
async function handleCount(command, browser) {
|
|
4431
|
+
const page = browser.getPage();
|
|
4432
|
+
const count = await page.locator(command.selector).count();
|
|
4433
|
+
return successResponse(command.id, { count });
|
|
4434
|
+
}
|
|
4435
|
+
async function handleBoundingBox(command, browser) {
|
|
4436
|
+
const page = browser.getPage();
|
|
4437
|
+
const box = await page.locator(command.selector).boundingBox();
|
|
4438
|
+
return successResponse(command.id, { box });
|
|
4439
4439
|
}
|
|
4440
4440
|
async function handleStyles(command, browser) {
|
|
4441
4441
|
const page = browser.getPage();
|
|
4442
|
-
const
|
|
4442
|
+
const extractStyles = (el) => {
|
|
4443
4443
|
const s = getComputedStyle(el);
|
|
4444
4444
|
const r = el.getBoundingClientRect();
|
|
4445
4445
|
return {
|
|
@@ -4449,408 +4449,424 @@ async function handleStyles(command, browser) {
|
|
|
4449
4449
|
x: Math.round(r.x),
|
|
4450
4450
|
y: Math.round(r.y),
|
|
4451
4451
|
width: Math.round(r.width),
|
|
4452
|
-
height: Math.round(r.height)
|
|
4452
|
+
height: Math.round(r.height)
|
|
4453
4453
|
},
|
|
4454
4454
|
styles: {
|
|
4455
4455
|
fontSize: s.fontSize,
|
|
4456
4456
|
fontWeight: s.fontWeight,
|
|
4457
|
-
fontFamily: s.fontFamily.split(
|
|
4457
|
+
fontFamily: s.fontFamily.split(",")[0].trim().replace(/"/g, ""),
|
|
4458
4458
|
color: s.color,
|
|
4459
4459
|
backgroundColor: s.backgroundColor,
|
|
4460
4460
|
borderRadius: s.borderRadius,
|
|
4461
|
-
border: s.border !==
|
|
4462
|
-
boxShadow: s.boxShadow !==
|
|
4463
|
-
padding: s.padding
|
|
4464
|
-
}
|
|
4461
|
+
border: s.border !== "none" && s.borderWidth !== "0px" ? s.border : null,
|
|
4462
|
+
boxShadow: s.boxShadow !== "none" ? s.boxShadow : null,
|
|
4463
|
+
padding: s.padding
|
|
4464
|
+
}
|
|
4465
4465
|
};
|
|
4466
|
-
}
|
|
4466
|
+
};
|
|
4467
4467
|
if (browser.isRef(command.selector)) {
|
|
4468
4468
|
const locator = browser.getLocator(command.selector);
|
|
4469
|
-
const element = await locator.evaluate(
|
|
4470
|
-
const fn = eval(script);
|
|
4471
|
-
return fn(el);
|
|
4472
|
-
}, extractStylesScript);
|
|
4469
|
+
const element = await locator.evaluate(extractStyles);
|
|
4473
4470
|
return successResponse(command.id, { elements: [element] });
|
|
4474
4471
|
}
|
|
4475
|
-
const elements = await page.$$eval(
|
|
4476
|
-
|
|
4477
|
-
|
|
4478
|
-
const
|
|
4479
|
-
return
|
|
4480
|
-
|
|
4481
|
-
|
|
4482
|
-
|
|
4472
|
+
const elements = await page.$$eval(command.selector, (els) => {
|
|
4473
|
+
return els.map((el) => {
|
|
4474
|
+
const s = getComputedStyle(el);
|
|
4475
|
+
const r = el.getBoundingClientRect();
|
|
4476
|
+
return {
|
|
4477
|
+
tag: el.tagName.toLowerCase(),
|
|
4478
|
+
text: el.innerText?.trim().slice(0, 80) || null,
|
|
4479
|
+
box: {
|
|
4480
|
+
x: Math.round(r.x),
|
|
4481
|
+
y: Math.round(r.y),
|
|
4482
|
+
width: Math.round(r.width),
|
|
4483
|
+
height: Math.round(r.height)
|
|
4484
|
+
},
|
|
4485
|
+
styles: {
|
|
4486
|
+
fontSize: s.fontSize,
|
|
4487
|
+
fontWeight: s.fontWeight,
|
|
4488
|
+
fontFamily: s.fontFamily.split(",")[0].trim().replace(/"/g, ""),
|
|
4489
|
+
color: s.color,
|
|
4490
|
+
backgroundColor: s.backgroundColor,
|
|
4491
|
+
borderRadius: s.borderRadius,
|
|
4492
|
+
border: s.border !== "none" && s.borderWidth !== "0px" ? s.border : null,
|
|
4493
|
+
boxShadow: s.boxShadow !== "none" ? s.boxShadow : null,
|
|
4494
|
+
padding: s.padding
|
|
4495
|
+
}
|
|
4496
|
+
};
|
|
4497
|
+
});
|
|
4498
|
+
});
|
|
4483
4499
|
return successResponse(command.id, { elements });
|
|
4484
4500
|
}
|
|
4485
|
-
async function handleVideoStart(
|
|
4486
|
-
return successResponse(
|
|
4501
|
+
async function handleVideoStart(command, browser) {
|
|
4502
|
+
return successResponse(command.id, {
|
|
4487
4503
|
note: "Video recording must be enabled at browser launch. Use --video flag when starting.",
|
|
4488
|
-
path:
|
|
4504
|
+
path: command.path
|
|
4489
4505
|
});
|
|
4490
4506
|
}
|
|
4491
|
-
async function handleVideoStop(
|
|
4492
|
-
const
|
|
4493
|
-
const video =
|
|
4507
|
+
async function handleVideoStop(command, browser) {
|
|
4508
|
+
const page = browser.getPage();
|
|
4509
|
+
const video = page.video();
|
|
4494
4510
|
if (video) {
|
|
4495
4511
|
const path5 = await video.path();
|
|
4496
|
-
return successResponse(
|
|
4512
|
+
return successResponse(command.id, { path: path5 });
|
|
4497
4513
|
}
|
|
4498
|
-
return successResponse(
|
|
4514
|
+
return successResponse(command.id, { note: "No video recording active" });
|
|
4499
4515
|
}
|
|
4500
|
-
async function handleTraceStart(
|
|
4501
|
-
await
|
|
4502
|
-
screenshots:
|
|
4503
|
-
snapshots:
|
|
4516
|
+
async function handleTraceStart(command, browser) {
|
|
4517
|
+
await browser.startTracing({
|
|
4518
|
+
screenshots: command.screenshots,
|
|
4519
|
+
snapshots: command.snapshots
|
|
4504
4520
|
});
|
|
4505
|
-
return successResponse(
|
|
4521
|
+
return successResponse(command.id, { started: true });
|
|
4506
4522
|
}
|
|
4507
|
-
async function handleTraceStop(
|
|
4508
|
-
await
|
|
4509
|
-
return successResponse(
|
|
4523
|
+
async function handleTraceStop(command, browser) {
|
|
4524
|
+
await browser.stopTracing(command.path);
|
|
4525
|
+
return successResponse(command.id, { path: command.path });
|
|
4510
4526
|
}
|
|
4511
|
-
async function handleHarStart(
|
|
4512
|
-
await
|
|
4513
|
-
|
|
4514
|
-
return successResponse(
|
|
4527
|
+
async function handleHarStart(command, browser) {
|
|
4528
|
+
await browser.startHarRecording();
|
|
4529
|
+
browser.startRequestTracking();
|
|
4530
|
+
return successResponse(command.id, { started: true });
|
|
4515
4531
|
}
|
|
4516
|
-
async function handleHarStop(
|
|
4517
|
-
const requests =
|
|
4518
|
-
return successResponse(
|
|
4519
|
-
path:
|
|
4532
|
+
async function handleHarStop(command, browser) {
|
|
4533
|
+
const requests = browser.getRequests();
|
|
4534
|
+
return successResponse(command.id, {
|
|
4535
|
+
path: command.path,
|
|
4520
4536
|
requestCount: requests.length
|
|
4521
4537
|
});
|
|
4522
4538
|
}
|
|
4523
|
-
async function handleStateSave(
|
|
4524
|
-
await
|
|
4525
|
-
return successResponse(
|
|
4539
|
+
async function handleStateSave(command, browser) {
|
|
4540
|
+
await browser.saveStorageState(command.path);
|
|
4541
|
+
return successResponse(command.id, { path: command.path });
|
|
4526
4542
|
}
|
|
4527
|
-
async function handleStateLoad(
|
|
4528
|
-
return successResponse(
|
|
4543
|
+
async function handleStateLoad(command, browser) {
|
|
4544
|
+
return successResponse(command.id, {
|
|
4529
4545
|
note: "Storage state must be loaded at browser launch. Use --state flag.",
|
|
4530
|
-
path:
|
|
4546
|
+
path: command.path
|
|
4531
4547
|
});
|
|
4532
4548
|
}
|
|
4533
|
-
async function handleConsole(
|
|
4534
|
-
if (
|
|
4535
|
-
|
|
4536
|
-
return successResponse(
|
|
4549
|
+
async function handleConsole(command, browser) {
|
|
4550
|
+
if (command.clear) {
|
|
4551
|
+
browser.clearConsoleMessages();
|
|
4552
|
+
return successResponse(command.id, { cleared: true });
|
|
4537
4553
|
}
|
|
4538
|
-
const messages =
|
|
4539
|
-
return successResponse(
|
|
4554
|
+
const messages = browser.getConsoleMessages();
|
|
4555
|
+
return successResponse(command.id, { messages });
|
|
4540
4556
|
}
|
|
4541
|
-
async function handleErrors(
|
|
4542
|
-
if (
|
|
4543
|
-
|
|
4544
|
-
return successResponse(
|
|
4557
|
+
async function handleErrors(command, browser) {
|
|
4558
|
+
if (command.clear) {
|
|
4559
|
+
browser.clearPageErrors();
|
|
4560
|
+
return successResponse(command.id, { cleared: true });
|
|
4545
4561
|
}
|
|
4546
|
-
const errors =
|
|
4547
|
-
return successResponse(
|
|
4562
|
+
const errors = browser.getPageErrors();
|
|
4563
|
+
return successResponse(command.id, { errors });
|
|
4548
4564
|
}
|
|
4549
|
-
async function handleKeyboard(
|
|
4550
|
-
const
|
|
4551
|
-
await
|
|
4552
|
-
return successResponse(
|
|
4565
|
+
async function handleKeyboard(command, browser) {
|
|
4566
|
+
const page = browser.getPage();
|
|
4567
|
+
await page.keyboard.press(command.keys);
|
|
4568
|
+
return successResponse(command.id, { pressed: command.keys });
|
|
4553
4569
|
}
|
|
4554
|
-
async function handleWheel(
|
|
4555
|
-
const
|
|
4556
|
-
if (
|
|
4557
|
-
const
|
|
4558
|
-
await
|
|
4570
|
+
async function handleWheel(command, browser) {
|
|
4571
|
+
const page = browser.getPage();
|
|
4572
|
+
if (command.selector) {
|
|
4573
|
+
const element = page.locator(command.selector);
|
|
4574
|
+
await element.hover();
|
|
4559
4575
|
}
|
|
4560
|
-
await
|
|
4561
|
-
return successResponse(
|
|
4576
|
+
await page.mouse.wheel(command.deltaX ?? 0, command.deltaY ?? 0);
|
|
4577
|
+
return successResponse(command.id, { scrolled: true });
|
|
4562
4578
|
}
|
|
4563
|
-
async function handleTap(
|
|
4564
|
-
const
|
|
4565
|
-
await
|
|
4566
|
-
return successResponse(
|
|
4579
|
+
async function handleTap(command, browser) {
|
|
4580
|
+
const page = browser.getPage();
|
|
4581
|
+
await page.tap(command.selector);
|
|
4582
|
+
return successResponse(command.id, { tapped: true });
|
|
4567
4583
|
}
|
|
4568
|
-
async function handleClipboard(
|
|
4569
|
-
const
|
|
4570
|
-
switch (
|
|
4584
|
+
async function handleClipboard(command, browser) {
|
|
4585
|
+
const page = browser.getPage();
|
|
4586
|
+
switch (command.operation) {
|
|
4571
4587
|
case "copy":
|
|
4572
|
-
await
|
|
4573
|
-
return successResponse(
|
|
4588
|
+
await page.keyboard.press("Control+c");
|
|
4589
|
+
return successResponse(command.id, { copied: true });
|
|
4574
4590
|
case "paste":
|
|
4575
|
-
await
|
|
4576
|
-
return successResponse(
|
|
4591
|
+
await page.keyboard.press("Control+v");
|
|
4592
|
+
return successResponse(command.id, { pasted: true });
|
|
4577
4593
|
case "read":
|
|
4578
|
-
const text = await
|
|
4579
|
-
return successResponse(
|
|
4594
|
+
const text = await page.evaluate("navigator.clipboard.readText()");
|
|
4595
|
+
return successResponse(command.id, { text });
|
|
4580
4596
|
default:
|
|
4581
|
-
return errorResponse(
|
|
4582
|
-
}
|
|
4583
|
-
}
|
|
4584
|
-
async function handleHighlight(
|
|
4585
|
-
const
|
|
4586
|
-
await
|
|
4587
|
-
return successResponse(
|
|
4588
|
-
}
|
|
4589
|
-
async function handleClear(
|
|
4590
|
-
const
|
|
4591
|
-
await
|
|
4592
|
-
return successResponse(
|
|
4593
|
-
}
|
|
4594
|
-
async function handleSelectAll(
|
|
4595
|
-
const
|
|
4596
|
-
await
|
|
4597
|
-
return successResponse(
|
|
4598
|
-
}
|
|
4599
|
-
async function handleInnerText(
|
|
4600
|
-
const
|
|
4601
|
-
const text = await
|
|
4602
|
-
return successResponse(
|
|
4603
|
-
}
|
|
4604
|
-
async function handleInnerHtml(
|
|
4605
|
-
const
|
|
4606
|
-
const html = await
|
|
4607
|
-
return successResponse(
|
|
4608
|
-
}
|
|
4609
|
-
async function handleInputValue(
|
|
4610
|
-
const
|
|
4611
|
-
const value = await
|
|
4612
|
-
return successResponse(
|
|
4613
|
-
}
|
|
4614
|
-
async function handleSetValue(
|
|
4615
|
-
const
|
|
4616
|
-
await
|
|
4617
|
-
return successResponse(
|
|
4618
|
-
}
|
|
4619
|
-
async function handleDispatch(
|
|
4620
|
-
const
|
|
4621
|
-
await
|
|
4622
|
-
return successResponse(
|
|
4623
|
-
}
|
|
4624
|
-
async function handleEvalHandle(
|
|
4625
|
-
const
|
|
4626
|
-
const handle = await
|
|
4597
|
+
return errorResponse(command.id, "Unknown clipboard operation");
|
|
4598
|
+
}
|
|
4599
|
+
}
|
|
4600
|
+
async function handleHighlight(command, browser) {
|
|
4601
|
+
const page = browser.getPage();
|
|
4602
|
+
await page.locator(command.selector).highlight();
|
|
4603
|
+
return successResponse(command.id, { highlighted: true });
|
|
4604
|
+
}
|
|
4605
|
+
async function handleClear(command, browser) {
|
|
4606
|
+
const page = browser.getPage();
|
|
4607
|
+
await page.locator(command.selector).clear();
|
|
4608
|
+
return successResponse(command.id, { cleared: true });
|
|
4609
|
+
}
|
|
4610
|
+
async function handleSelectAll(command, browser) {
|
|
4611
|
+
const page = browser.getPage();
|
|
4612
|
+
await page.locator(command.selector).selectText();
|
|
4613
|
+
return successResponse(command.id, { selected: true });
|
|
4614
|
+
}
|
|
4615
|
+
async function handleInnerText(command, browser) {
|
|
4616
|
+
const page = browser.getPage();
|
|
4617
|
+
const text = await page.locator(command.selector).innerText();
|
|
4618
|
+
return successResponse(command.id, { text });
|
|
4619
|
+
}
|
|
4620
|
+
async function handleInnerHtml(command, browser) {
|
|
4621
|
+
const page = browser.getPage();
|
|
4622
|
+
const html = await page.locator(command.selector).innerHTML();
|
|
4623
|
+
return successResponse(command.id, { html });
|
|
4624
|
+
}
|
|
4625
|
+
async function handleInputValue(command, browser) {
|
|
4626
|
+
const locator = browser.getLocator(command.selector);
|
|
4627
|
+
const value = await locator.inputValue();
|
|
4628
|
+
return successResponse(command.id, { value });
|
|
4629
|
+
}
|
|
4630
|
+
async function handleSetValue(command, browser) {
|
|
4631
|
+
const page = browser.getPage();
|
|
4632
|
+
await page.locator(command.selector).fill(command.value);
|
|
4633
|
+
return successResponse(command.id, { set: true });
|
|
4634
|
+
}
|
|
4635
|
+
async function handleDispatch(command, browser) {
|
|
4636
|
+
const page = browser.getPage();
|
|
4637
|
+
await page.locator(command.selector).dispatchEvent(command.event, command.eventInit);
|
|
4638
|
+
return successResponse(command.id, { dispatched: command.event });
|
|
4639
|
+
}
|
|
4640
|
+
async function handleEvalHandle(command, browser) {
|
|
4641
|
+
const page = browser.getPage();
|
|
4642
|
+
const handle = await page.evaluateHandle(command.script);
|
|
4627
4643
|
const result = await handle.jsonValue().catch(() => "Handle (non-serializable)");
|
|
4628
|
-
return successResponse(
|
|
4644
|
+
return successResponse(command.id, { result });
|
|
4629
4645
|
}
|
|
4630
|
-
async function handleExpose(
|
|
4631
|
-
const
|
|
4632
|
-
await
|
|
4633
|
-
return `Function ${
|
|
4646
|
+
async function handleExpose(command, browser) {
|
|
4647
|
+
const page = browser.getPage();
|
|
4648
|
+
await page.exposeFunction(command.name, () => {
|
|
4649
|
+
return `Function ${command.name} called`;
|
|
4634
4650
|
});
|
|
4635
|
-
return successResponse(
|
|
4636
|
-
}
|
|
4637
|
-
async function handleAddScript(
|
|
4638
|
-
const
|
|
4639
|
-
if (
|
|
4640
|
-
await
|
|
4641
|
-
} else if (
|
|
4642
|
-
await
|
|
4643
|
-
}
|
|
4644
|
-
return successResponse(
|
|
4645
|
-
}
|
|
4646
|
-
async function handleAddStyle(
|
|
4647
|
-
const
|
|
4648
|
-
if (
|
|
4649
|
-
await
|
|
4650
|
-
} else if (
|
|
4651
|
-
await
|
|
4652
|
-
}
|
|
4653
|
-
return successResponse(
|
|
4654
|
-
}
|
|
4655
|
-
async function handleEmulateMedia(
|
|
4656
|
-
const
|
|
4657
|
-
await
|
|
4658
|
-
media:
|
|
4659
|
-
colorScheme:
|
|
4660
|
-
reducedMotion:
|
|
4661
|
-
forcedColors:
|
|
4651
|
+
return successResponse(command.id, { exposed: command.name });
|
|
4652
|
+
}
|
|
4653
|
+
async function handleAddScript(command, browser) {
|
|
4654
|
+
const page = browser.getPage();
|
|
4655
|
+
if (command.content) {
|
|
4656
|
+
await page.addScriptTag({ content: command.content });
|
|
4657
|
+
} else if (command.url) {
|
|
4658
|
+
await page.addScriptTag({ url: command.url });
|
|
4659
|
+
}
|
|
4660
|
+
return successResponse(command.id, { added: true });
|
|
4661
|
+
}
|
|
4662
|
+
async function handleAddStyle(command, browser) {
|
|
4663
|
+
const page = browser.getPage();
|
|
4664
|
+
if (command.content) {
|
|
4665
|
+
await page.addStyleTag({ content: command.content });
|
|
4666
|
+
} else if (command.url) {
|
|
4667
|
+
await page.addStyleTag({ url: command.url });
|
|
4668
|
+
}
|
|
4669
|
+
return successResponse(command.id, { added: true });
|
|
4670
|
+
}
|
|
4671
|
+
async function handleEmulateMedia(command, browser) {
|
|
4672
|
+
const page = browser.getPage();
|
|
4673
|
+
await page.emulateMedia({
|
|
4674
|
+
media: command.media,
|
|
4675
|
+
colorScheme: command.colorScheme,
|
|
4676
|
+
reducedMotion: command.reducedMotion,
|
|
4677
|
+
forcedColors: command.forcedColors
|
|
4662
4678
|
});
|
|
4663
|
-
return successResponse(
|
|
4679
|
+
return successResponse(command.id, { emulated: true });
|
|
4664
4680
|
}
|
|
4665
|
-
async function handleOffline(
|
|
4666
|
-
await
|
|
4667
|
-
return successResponse(
|
|
4681
|
+
async function handleOffline(command, browser) {
|
|
4682
|
+
await browser.setOffline(command.offline);
|
|
4683
|
+
return successResponse(command.id, { offline: command.offline });
|
|
4668
4684
|
}
|
|
4669
|
-
async function handleHeaders(
|
|
4670
|
-
await
|
|
4671
|
-
return successResponse(
|
|
4685
|
+
async function handleHeaders(command, browser) {
|
|
4686
|
+
await browser.setExtraHeaders(command.headers);
|
|
4687
|
+
return successResponse(command.id, { set: true });
|
|
4672
4688
|
}
|
|
4673
|
-
async function handlePause(
|
|
4674
|
-
const
|
|
4675
|
-
await
|
|
4676
|
-
return successResponse(
|
|
4689
|
+
async function handlePause(command, browser) {
|
|
4690
|
+
const page = browser.getPage();
|
|
4691
|
+
await page.pause();
|
|
4692
|
+
return successResponse(command.id, { paused: true });
|
|
4677
4693
|
}
|
|
4678
|
-
async function handleGetByAltText(
|
|
4679
|
-
const
|
|
4680
|
-
const
|
|
4681
|
-
switch (
|
|
4694
|
+
async function handleGetByAltText(command, browser) {
|
|
4695
|
+
const page = browser.getPage();
|
|
4696
|
+
const locator = page.getByAltText(command.text, { exact: command.exact });
|
|
4697
|
+
switch (command.subaction) {
|
|
4682
4698
|
case "click":
|
|
4683
|
-
await
|
|
4684
|
-
return successResponse(
|
|
4699
|
+
await locator.click();
|
|
4700
|
+
return successResponse(command.id, { clicked: true });
|
|
4685
4701
|
case "hover":
|
|
4686
|
-
await
|
|
4687
|
-
return successResponse(
|
|
4702
|
+
await locator.hover();
|
|
4703
|
+
return successResponse(command.id, { hovered: true });
|
|
4688
4704
|
}
|
|
4689
4705
|
}
|
|
4690
|
-
async function handleGetByTitle(
|
|
4691
|
-
const
|
|
4692
|
-
const
|
|
4693
|
-
switch (
|
|
4706
|
+
async function handleGetByTitle(command, browser) {
|
|
4707
|
+
const page = browser.getPage();
|
|
4708
|
+
const locator = page.getByTitle(command.text, { exact: command.exact });
|
|
4709
|
+
switch (command.subaction) {
|
|
4694
4710
|
case "click":
|
|
4695
|
-
await
|
|
4696
|
-
return successResponse(
|
|
4711
|
+
await locator.click();
|
|
4712
|
+
return successResponse(command.id, { clicked: true });
|
|
4697
4713
|
case "hover":
|
|
4698
|
-
await
|
|
4699
|
-
return successResponse(
|
|
4714
|
+
await locator.hover();
|
|
4715
|
+
return successResponse(command.id, { hovered: true });
|
|
4700
4716
|
}
|
|
4701
4717
|
}
|
|
4702
|
-
async function handleGetByTestId(
|
|
4703
|
-
const
|
|
4704
|
-
const
|
|
4705
|
-
switch (
|
|
4718
|
+
async function handleGetByTestId(command, browser) {
|
|
4719
|
+
const page = browser.getPage();
|
|
4720
|
+
const locator = page.getByTestId(command.testId);
|
|
4721
|
+
switch (command.subaction) {
|
|
4706
4722
|
case "click":
|
|
4707
|
-
await
|
|
4708
|
-
return successResponse(
|
|
4723
|
+
await locator.click();
|
|
4724
|
+
return successResponse(command.id, { clicked: true });
|
|
4709
4725
|
case "fill":
|
|
4710
|
-
await
|
|
4711
|
-
return successResponse(
|
|
4726
|
+
await locator.fill(command.value ?? "");
|
|
4727
|
+
return successResponse(command.id, { filled: true });
|
|
4712
4728
|
case "check":
|
|
4713
|
-
await
|
|
4714
|
-
return successResponse(
|
|
4729
|
+
await locator.check();
|
|
4730
|
+
return successResponse(command.id, { checked: true });
|
|
4715
4731
|
case "hover":
|
|
4716
|
-
await
|
|
4717
|
-
return successResponse(
|
|
4732
|
+
await locator.hover();
|
|
4733
|
+
return successResponse(command.id, { hovered: true });
|
|
4718
4734
|
}
|
|
4719
4735
|
}
|
|
4720
|
-
async function handleNth(
|
|
4721
|
-
const
|
|
4722
|
-
const base =
|
|
4723
|
-
const
|
|
4724
|
-
switch (
|
|
4736
|
+
async function handleNth(command, browser) {
|
|
4737
|
+
const page = browser.getPage();
|
|
4738
|
+
const base = page.locator(command.selector);
|
|
4739
|
+
const locator = command.index === -1 ? base.last() : base.nth(command.index);
|
|
4740
|
+
switch (command.subaction) {
|
|
4725
4741
|
case "click":
|
|
4726
|
-
await
|
|
4727
|
-
return successResponse(
|
|
4742
|
+
await locator.click();
|
|
4743
|
+
return successResponse(command.id, { clicked: true });
|
|
4728
4744
|
case "fill":
|
|
4729
|
-
await
|
|
4730
|
-
return successResponse(
|
|
4745
|
+
await locator.fill(command.value ?? "");
|
|
4746
|
+
return successResponse(command.id, { filled: true });
|
|
4731
4747
|
case "check":
|
|
4732
|
-
await
|
|
4733
|
-
return successResponse(
|
|
4748
|
+
await locator.check();
|
|
4749
|
+
return successResponse(command.id, { checked: true });
|
|
4734
4750
|
case "hover":
|
|
4735
|
-
await
|
|
4736
|
-
return successResponse(
|
|
4751
|
+
await locator.hover();
|
|
4752
|
+
return successResponse(command.id, { hovered: true });
|
|
4737
4753
|
case "text":
|
|
4738
|
-
const text = await
|
|
4739
|
-
return successResponse(
|
|
4754
|
+
const text = await locator.textContent();
|
|
4755
|
+
return successResponse(command.id, { text });
|
|
4740
4756
|
}
|
|
4741
4757
|
}
|
|
4742
|
-
async function handleWaitForUrl(
|
|
4743
|
-
const
|
|
4744
|
-
await
|
|
4745
|
-
return successResponse(
|
|
4758
|
+
async function handleWaitForUrl(command, browser) {
|
|
4759
|
+
const page = browser.getPage();
|
|
4760
|
+
await page.waitForURL(command.url, { timeout: command.timeout });
|
|
4761
|
+
return successResponse(command.id, { url: page.url() });
|
|
4746
4762
|
}
|
|
4747
|
-
async function handleWaitForLoadState(
|
|
4748
|
-
const
|
|
4749
|
-
await
|
|
4750
|
-
return successResponse(
|
|
4763
|
+
async function handleWaitForLoadState(command, browser) {
|
|
4764
|
+
const page = browser.getPage();
|
|
4765
|
+
await page.waitForLoadState(command.state, { timeout: command.timeout });
|
|
4766
|
+
return successResponse(command.id, { state: command.state });
|
|
4751
4767
|
}
|
|
4752
|
-
async function handleSetContent(
|
|
4753
|
-
const
|
|
4754
|
-
await
|
|
4755
|
-
return successResponse(
|
|
4768
|
+
async function handleSetContent(command, browser) {
|
|
4769
|
+
const page = browser.getPage();
|
|
4770
|
+
await page.setContent(command.html);
|
|
4771
|
+
return successResponse(command.id, { set: true });
|
|
4756
4772
|
}
|
|
4757
|
-
async function handleTimezone(
|
|
4758
|
-
const
|
|
4759
|
-
await
|
|
4760
|
-
return successResponse(
|
|
4773
|
+
async function handleTimezone(command, browser) {
|
|
4774
|
+
const page = browser.getPage();
|
|
4775
|
+
await page.context().setGeolocation({ latitude: 0, longitude: 0 });
|
|
4776
|
+
return successResponse(command.id, {
|
|
4761
4777
|
note: "Timezone must be set at browser launch. Use --timezone flag.",
|
|
4762
|
-
timezone:
|
|
4778
|
+
timezone: command.timezone
|
|
4763
4779
|
});
|
|
4764
4780
|
}
|
|
4765
|
-
async function handleLocale(
|
|
4766
|
-
return successResponse(
|
|
4781
|
+
async function handleLocale(command, browser) {
|
|
4782
|
+
return successResponse(command.id, {
|
|
4767
4783
|
note: "Locale must be set at browser launch. Use --locale flag.",
|
|
4768
|
-
locale:
|
|
4784
|
+
locale: command.locale
|
|
4769
4785
|
});
|
|
4770
4786
|
}
|
|
4771
|
-
async function handleCredentials(
|
|
4772
|
-
const context =
|
|
4787
|
+
async function handleCredentials(command, browser) {
|
|
4788
|
+
const context = browser.getPage().context();
|
|
4773
4789
|
await context.setHTTPCredentials({
|
|
4774
|
-
username:
|
|
4775
|
-
password:
|
|
4790
|
+
username: command.username,
|
|
4791
|
+
password: command.password
|
|
4776
4792
|
});
|
|
4777
|
-
return successResponse(
|
|
4778
|
-
}
|
|
4779
|
-
async function handleMouseMove(
|
|
4780
|
-
const
|
|
4781
|
-
await
|
|
4782
|
-
return successResponse(
|
|
4783
|
-
}
|
|
4784
|
-
async function handleMouseDown(
|
|
4785
|
-
const
|
|
4786
|
-
await
|
|
4787
|
-
return successResponse(
|
|
4788
|
-
}
|
|
4789
|
-
async function handleMouseUp(
|
|
4790
|
-
const
|
|
4791
|
-
await
|
|
4792
|
-
return successResponse(
|
|
4793
|
-
}
|
|
4794
|
-
async function handleBringToFront(
|
|
4795
|
-
const
|
|
4796
|
-
await
|
|
4797
|
-
return successResponse(
|
|
4798
|
-
}
|
|
4799
|
-
async function handleWaitForFunction(
|
|
4800
|
-
const
|
|
4801
|
-
await
|
|
4802
|
-
return successResponse(
|
|
4803
|
-
}
|
|
4804
|
-
async function handleScrollIntoView(
|
|
4805
|
-
const
|
|
4806
|
-
await
|
|
4807
|
-
return successResponse(
|
|
4808
|
-
}
|
|
4809
|
-
async function handleAddInitScript(
|
|
4810
|
-
const context =
|
|
4811
|
-
await context.addInitScript(
|
|
4812
|
-
return successResponse(
|
|
4813
|
-
}
|
|
4814
|
-
async function handleKeyDown(
|
|
4815
|
-
const
|
|
4816
|
-
await
|
|
4817
|
-
return successResponse(
|
|
4818
|
-
}
|
|
4819
|
-
async function handleKeyUp(
|
|
4820
|
-
const
|
|
4821
|
-
await
|
|
4822
|
-
return successResponse(
|
|
4823
|
-
}
|
|
4824
|
-
async function handleInsertText(
|
|
4825
|
-
const
|
|
4826
|
-
await
|
|
4827
|
-
return successResponse(
|
|
4828
|
-
}
|
|
4829
|
-
async function handleMultiSelect(
|
|
4830
|
-
const
|
|
4831
|
-
const selected = await
|
|
4832
|
-
return successResponse(
|
|
4833
|
-
}
|
|
4834
|
-
async function handleWaitForDownload(
|
|
4835
|
-
const
|
|
4836
|
-
const download = await
|
|
4793
|
+
return successResponse(command.id, { set: true });
|
|
4794
|
+
}
|
|
4795
|
+
async function handleMouseMove(command, browser) {
|
|
4796
|
+
const page = browser.getPage();
|
|
4797
|
+
await page.mouse.move(command.x, command.y);
|
|
4798
|
+
return successResponse(command.id, { moved: true, x: command.x, y: command.y });
|
|
4799
|
+
}
|
|
4800
|
+
async function handleMouseDown(command, browser) {
|
|
4801
|
+
const page = browser.getPage();
|
|
4802
|
+
await page.mouse.down({ button: command.button ?? "left" });
|
|
4803
|
+
return successResponse(command.id, { down: true });
|
|
4804
|
+
}
|
|
4805
|
+
async function handleMouseUp(command, browser) {
|
|
4806
|
+
const page = browser.getPage();
|
|
4807
|
+
await page.mouse.up({ button: command.button ?? "left" });
|
|
4808
|
+
return successResponse(command.id, { up: true });
|
|
4809
|
+
}
|
|
4810
|
+
async function handleBringToFront(command, browser) {
|
|
4811
|
+
const page = browser.getPage();
|
|
4812
|
+
await page.bringToFront();
|
|
4813
|
+
return successResponse(command.id, { focused: true });
|
|
4814
|
+
}
|
|
4815
|
+
async function handleWaitForFunction(command, browser) {
|
|
4816
|
+
const page = browser.getPage();
|
|
4817
|
+
await page.waitForFunction(command.expression, { timeout: command.timeout });
|
|
4818
|
+
return successResponse(command.id, { waited: true });
|
|
4819
|
+
}
|
|
4820
|
+
async function handleScrollIntoView(command, browser) {
|
|
4821
|
+
const page = browser.getPage();
|
|
4822
|
+
await page.locator(command.selector).scrollIntoViewIfNeeded();
|
|
4823
|
+
return successResponse(command.id, { scrolled: true });
|
|
4824
|
+
}
|
|
4825
|
+
async function handleAddInitScript(command, browser) {
|
|
4826
|
+
const context = browser.getPage().context();
|
|
4827
|
+
await context.addInitScript(command.script);
|
|
4828
|
+
return successResponse(command.id, { added: true });
|
|
4829
|
+
}
|
|
4830
|
+
async function handleKeyDown(command, browser) {
|
|
4831
|
+
const page = browser.getPage();
|
|
4832
|
+
await page.keyboard.down(command.key);
|
|
4833
|
+
return successResponse(command.id, { down: true, key: command.key });
|
|
4834
|
+
}
|
|
4835
|
+
async function handleKeyUp(command, browser) {
|
|
4836
|
+
const page = browser.getPage();
|
|
4837
|
+
await page.keyboard.up(command.key);
|
|
4838
|
+
return successResponse(command.id, { up: true, key: command.key });
|
|
4839
|
+
}
|
|
4840
|
+
async function handleInsertText(command, browser) {
|
|
4841
|
+
const page = browser.getPage();
|
|
4842
|
+
await page.keyboard.insertText(command.text);
|
|
4843
|
+
return successResponse(command.id, { inserted: true });
|
|
4844
|
+
}
|
|
4845
|
+
async function handleMultiSelect(command, browser) {
|
|
4846
|
+
const page = browser.getPage();
|
|
4847
|
+
const selected = await page.locator(command.selector).selectOption(command.values);
|
|
4848
|
+
return successResponse(command.id, { selected });
|
|
4849
|
+
}
|
|
4850
|
+
async function handleWaitForDownload(command, browser) {
|
|
4851
|
+
const page = browser.getPage();
|
|
4852
|
+
const download = await page.waitForEvent("download", { timeout: command.timeout });
|
|
4837
4853
|
let filePath;
|
|
4838
|
-
if (
|
|
4839
|
-
filePath =
|
|
4854
|
+
if (command.path) {
|
|
4855
|
+
filePath = command.path;
|
|
4840
4856
|
await download.saveAs(filePath);
|
|
4841
4857
|
} else {
|
|
4842
4858
|
filePath = await download.path() || download.suggestedFilename();
|
|
4843
4859
|
}
|
|
4844
|
-
return successResponse(
|
|
4860
|
+
return successResponse(command.id, {
|
|
4845
4861
|
path: filePath,
|
|
4846
4862
|
filename: download.suggestedFilename(),
|
|
4847
4863
|
url: download.url()
|
|
4848
4864
|
});
|
|
4849
4865
|
}
|
|
4850
|
-
async function handleResponseBody(
|
|
4851
|
-
const
|
|
4852
|
-
const response = await
|
|
4853
|
-
timeout:
|
|
4866
|
+
async function handleResponseBody(command, browser) {
|
|
4867
|
+
const page = browser.getPage();
|
|
4868
|
+
const response = await page.waitForResponse((resp) => resp.url().includes(command.url), {
|
|
4869
|
+
timeout: command.timeout
|
|
4854
4870
|
});
|
|
4855
4871
|
const body = await response.text();
|
|
4856
4872
|
let parsed = body;
|
|
@@ -4858,80 +4874,80 @@ async function handleResponseBody(command2, browser2) {
|
|
|
4858
4874
|
parsed = JSON.parse(body);
|
|
4859
4875
|
} catch {
|
|
4860
4876
|
}
|
|
4861
|
-
return successResponse(
|
|
4877
|
+
return successResponse(command.id, {
|
|
4862
4878
|
url: response.url(),
|
|
4863
4879
|
status: response.status(),
|
|
4864
4880
|
body: parsed
|
|
4865
4881
|
});
|
|
4866
4882
|
}
|
|
4867
|
-
async function handleScreencastStart(
|
|
4883
|
+
async function handleScreencastStart(command, browser) {
|
|
4868
4884
|
if (!screencastFrameCallback) {
|
|
4869
4885
|
throw new Error("Screencast frame callback not set. Start the streaming server first.");
|
|
4870
4886
|
}
|
|
4871
|
-
await
|
|
4872
|
-
format:
|
|
4873
|
-
quality:
|
|
4874
|
-
maxWidth:
|
|
4875
|
-
maxHeight:
|
|
4876
|
-
everyNthFrame:
|
|
4887
|
+
await browser.startScreencast(screencastFrameCallback, {
|
|
4888
|
+
format: command.format,
|
|
4889
|
+
quality: command.quality,
|
|
4890
|
+
maxWidth: command.maxWidth,
|
|
4891
|
+
maxHeight: command.maxHeight,
|
|
4892
|
+
everyNthFrame: command.everyNthFrame
|
|
4877
4893
|
});
|
|
4878
|
-
return successResponse(
|
|
4894
|
+
return successResponse(command.id, {
|
|
4879
4895
|
started: true,
|
|
4880
|
-
format:
|
|
4881
|
-
quality:
|
|
4896
|
+
format: command.format ?? "jpeg",
|
|
4897
|
+
quality: command.quality ?? 80
|
|
4882
4898
|
});
|
|
4883
4899
|
}
|
|
4884
|
-
async function handleScreencastStop(
|
|
4885
|
-
await
|
|
4886
|
-
return successResponse(
|
|
4887
|
-
}
|
|
4888
|
-
async function handleInputMouse(
|
|
4889
|
-
await
|
|
4890
|
-
type:
|
|
4891
|
-
x:
|
|
4892
|
-
y:
|
|
4893
|
-
button:
|
|
4894
|
-
clickCount:
|
|
4895
|
-
deltaX:
|
|
4896
|
-
deltaY:
|
|
4897
|
-
modifiers:
|
|
4900
|
+
async function handleScreencastStop(command, browser) {
|
|
4901
|
+
await browser.stopScreencast();
|
|
4902
|
+
return successResponse(command.id, { stopped: true });
|
|
4903
|
+
}
|
|
4904
|
+
async function handleInputMouse(command, browser) {
|
|
4905
|
+
await browser.injectMouseEvent({
|
|
4906
|
+
type: command.type,
|
|
4907
|
+
x: command.x,
|
|
4908
|
+
y: command.y,
|
|
4909
|
+
button: command.button,
|
|
4910
|
+
clickCount: command.clickCount,
|
|
4911
|
+
deltaX: command.deltaX,
|
|
4912
|
+
deltaY: command.deltaY,
|
|
4913
|
+
modifiers: command.modifiers
|
|
4898
4914
|
});
|
|
4899
|
-
return successResponse(
|
|
4900
|
-
}
|
|
4901
|
-
async function handleInputKeyboard(
|
|
4902
|
-
await
|
|
4903
|
-
type:
|
|
4904
|
-
key:
|
|
4905
|
-
code:
|
|
4906
|
-
text:
|
|
4907
|
-
modifiers:
|
|
4915
|
+
return successResponse(command.id, { injected: true });
|
|
4916
|
+
}
|
|
4917
|
+
async function handleInputKeyboard(command, browser) {
|
|
4918
|
+
await browser.injectKeyboardEvent({
|
|
4919
|
+
type: command.type,
|
|
4920
|
+
key: command.key,
|
|
4921
|
+
code: command.code,
|
|
4922
|
+
text: command.text,
|
|
4923
|
+
modifiers: command.modifiers
|
|
4908
4924
|
});
|
|
4909
|
-
return successResponse(
|
|
4925
|
+
return successResponse(command.id, { injected: true });
|
|
4910
4926
|
}
|
|
4911
|
-
async function handleInputTouch(
|
|
4912
|
-
await
|
|
4913
|
-
type:
|
|
4914
|
-
touchPoints:
|
|
4915
|
-
modifiers:
|
|
4927
|
+
async function handleInputTouch(command, browser) {
|
|
4928
|
+
await browser.injectTouchEvent({
|
|
4929
|
+
type: command.type,
|
|
4930
|
+
touchPoints: command.touchPoints,
|
|
4931
|
+
modifiers: command.modifiers
|
|
4916
4932
|
});
|
|
4917
|
-
return successResponse(
|
|
4933
|
+
return successResponse(command.id, { injected: true });
|
|
4918
4934
|
}
|
|
4919
|
-
async function handleRecordingStart(
|
|
4920
|
-
await
|
|
4921
|
-
return successResponse(
|
|
4935
|
+
async function handleRecordingStart(command, browser) {
|
|
4936
|
+
await browser.startRecording(command.path, command.url);
|
|
4937
|
+
return successResponse(command.id, {
|
|
4922
4938
|
started: true,
|
|
4923
|
-
path:
|
|
4939
|
+
path: command.path
|
|
4924
4940
|
});
|
|
4925
4941
|
}
|
|
4926
|
-
async function handleRecordingStop(
|
|
4927
|
-
const result = await
|
|
4928
|
-
return successResponse(
|
|
4942
|
+
async function handleRecordingStop(command, browser) {
|
|
4943
|
+
const result = await browser.stopRecording();
|
|
4944
|
+
return successResponse(command.id, result);
|
|
4929
4945
|
}
|
|
4930
|
-
async function handleRecordingRestart(
|
|
4931
|
-
const result = await
|
|
4932
|
-
return successResponse(
|
|
4946
|
+
async function handleRecordingRestart(command, browser) {
|
|
4947
|
+
const result = await browser.restartRecording(command.path, command.url);
|
|
4948
|
+
return successResponse(command.id, {
|
|
4933
4949
|
started: true,
|
|
4934
|
-
path:
|
|
4950
|
+
path: command.path,
|
|
4935
4951
|
previousPath: result.previousPath,
|
|
4936
4952
|
stopped: result.stopped
|
|
4937
4953
|
});
|
|
@@ -4944,12 +4960,12 @@ function successResponse2(id, data) {
|
|
|
4944
4960
|
function errorResponse2(id, error) {
|
|
4945
4961
|
return { id, success: false, error };
|
|
4946
4962
|
}
|
|
4947
|
-
async function executeIOSCommand(
|
|
4948
|
-
const { id, action } =
|
|
4963
|
+
async function executeIOSCommand(command, manager) {
|
|
4964
|
+
const { id, action } = command;
|
|
4949
4965
|
try {
|
|
4950
4966
|
switch (action) {
|
|
4951
4967
|
case "launch": {
|
|
4952
|
-
const cmd =
|
|
4968
|
+
const cmd = command;
|
|
4953
4969
|
await manager.launch({
|
|
4954
4970
|
device: cmd.device,
|
|
4955
4971
|
udid: cmd.udid
|
|
@@ -4962,22 +4978,22 @@ async function executeIOSCommand(command2, manager) {
|
|
|
4962
4978
|
});
|
|
4963
4979
|
}
|
|
4964
4980
|
case "navigate": {
|
|
4965
|
-
const cmd =
|
|
4981
|
+
const cmd = command;
|
|
4966
4982
|
const result = await manager.navigate(cmd.url);
|
|
4967
4983
|
return successResponse2(id, result);
|
|
4968
4984
|
}
|
|
4969
4985
|
case "click": {
|
|
4970
|
-
const cmd =
|
|
4986
|
+
const cmd = command;
|
|
4971
4987
|
await manager.click(cmd.selector);
|
|
4972
4988
|
return successResponse2(id, { clicked: true });
|
|
4973
4989
|
}
|
|
4974
4990
|
case "tap": {
|
|
4975
|
-
const cmd =
|
|
4991
|
+
const cmd = command;
|
|
4976
4992
|
await manager.tap(cmd.selector);
|
|
4977
4993
|
return successResponse2(id, { tapped: true });
|
|
4978
4994
|
}
|
|
4979
4995
|
case "type": {
|
|
4980
|
-
const cmd =
|
|
4996
|
+
const cmd = command;
|
|
4981
4997
|
await manager.type(cmd.selector, cmd.text, {
|
|
4982
4998
|
delay: cmd.delay,
|
|
4983
4999
|
clear: cmd.clear
|
|
@@ -4985,12 +5001,12 @@ async function executeIOSCommand(command2, manager) {
|
|
|
4985
5001
|
return successResponse2(id, { typed: true });
|
|
4986
5002
|
}
|
|
4987
5003
|
case "fill": {
|
|
4988
|
-
const cmd =
|
|
5004
|
+
const cmd = command;
|
|
4989
5005
|
await manager.fill(cmd.selector, cmd.value);
|
|
4990
5006
|
return successResponse2(id, { filled: true });
|
|
4991
5007
|
}
|
|
4992
5008
|
case "screenshot": {
|
|
4993
|
-
const cmd =
|
|
5009
|
+
const cmd = command;
|
|
4994
5010
|
const result = await manager.screenshot({
|
|
4995
5011
|
path: cmd.path,
|
|
4996
5012
|
fullPage: cmd.fullPage
|
|
@@ -4998,14 +5014,14 @@ async function executeIOSCommand(command2, manager) {
|
|
|
4998
5014
|
return successResponse2(id, result);
|
|
4999
5015
|
}
|
|
5000
5016
|
case "snapshot": {
|
|
5001
|
-
const cmd =
|
|
5017
|
+
const cmd = command;
|
|
5002
5018
|
const result = await manager.getSnapshot({
|
|
5003
5019
|
interactive: cmd.interactive
|
|
5004
5020
|
});
|
|
5005
5021
|
return successResponse2(id, { snapshot: result.tree, refs: result.refs });
|
|
5006
5022
|
}
|
|
5007
5023
|
case "scroll": {
|
|
5008
|
-
const cmd =
|
|
5024
|
+
const cmd = command;
|
|
5009
5025
|
await manager.scroll({
|
|
5010
5026
|
selector: cmd.selector,
|
|
5011
5027
|
x: cmd.x,
|
|
@@ -5016,17 +5032,17 @@ async function executeIOSCommand(command2, manager) {
|
|
|
5016
5032
|
return successResponse2(id, { scrolled: true });
|
|
5017
5033
|
}
|
|
5018
5034
|
case "swipe": {
|
|
5019
|
-
const cmd =
|
|
5035
|
+
const cmd = command;
|
|
5020
5036
|
await manager.swipe(cmd.direction, { distance: cmd.distance });
|
|
5021
5037
|
return successResponse2(id, { swiped: true });
|
|
5022
5038
|
}
|
|
5023
5039
|
case "evaluate": {
|
|
5024
|
-
const cmd =
|
|
5040
|
+
const cmd = command;
|
|
5025
5041
|
const result = await manager.evaluate(cmd.script, ...cmd.args ?? []);
|
|
5026
5042
|
return successResponse2(id, { result });
|
|
5027
5043
|
}
|
|
5028
5044
|
case "wait": {
|
|
5029
|
-
const cmd =
|
|
5045
|
+
const cmd = command;
|
|
5030
5046
|
await manager.wait({
|
|
5031
5047
|
selector: cmd.selector,
|
|
5032
5048
|
timeout: cmd.timeout,
|
|
@@ -5035,37 +5051,37 @@ async function executeIOSCommand(command2, manager) {
|
|
|
5035
5051
|
return successResponse2(id, { waited: true });
|
|
5036
5052
|
}
|
|
5037
5053
|
case "press": {
|
|
5038
|
-
const cmd =
|
|
5054
|
+
const cmd = command;
|
|
5039
5055
|
await manager.press(cmd.key);
|
|
5040
5056
|
return successResponse2(id, { pressed: true });
|
|
5041
5057
|
}
|
|
5042
5058
|
case "hover": {
|
|
5043
|
-
const cmd =
|
|
5059
|
+
const cmd = command;
|
|
5044
5060
|
await manager.hover(cmd.selector);
|
|
5045
5061
|
return successResponse2(id, { hovered: true });
|
|
5046
5062
|
}
|
|
5047
5063
|
case "content": {
|
|
5048
|
-
const cmd =
|
|
5064
|
+
const cmd = command;
|
|
5049
5065
|
const html = await manager.getContent(cmd.selector);
|
|
5050
5066
|
return successResponse2(id, { html });
|
|
5051
5067
|
}
|
|
5052
5068
|
case "gettext": {
|
|
5053
|
-
const cmd =
|
|
5069
|
+
const cmd = command;
|
|
5054
5070
|
const text = await manager.getText(cmd.selector);
|
|
5055
5071
|
return successResponse2(id, { text });
|
|
5056
5072
|
}
|
|
5057
5073
|
case "getattribute": {
|
|
5058
|
-
const cmd =
|
|
5074
|
+
const cmd = command;
|
|
5059
5075
|
const value = await manager.getAttribute(cmd.selector, cmd.attribute);
|
|
5060
5076
|
return successResponse2(id, { value });
|
|
5061
5077
|
}
|
|
5062
5078
|
case "isvisible": {
|
|
5063
|
-
const cmd =
|
|
5079
|
+
const cmd = command;
|
|
5064
5080
|
const visible = await manager.isVisible(cmd.selector);
|
|
5065
5081
|
return successResponse2(id, { visible });
|
|
5066
5082
|
}
|
|
5067
5083
|
case "isenabled": {
|
|
5068
|
-
const cmd =
|
|
5084
|
+
const cmd = command;
|
|
5069
5085
|
const enabled = await manager.isEnabled(cmd.selector);
|
|
5070
5086
|
return successResponse2(id, { enabled });
|
|
5071
5087
|
}
|
|
@@ -5090,37 +5106,37 @@ async function executeIOSCommand(command2, manager) {
|
|
|
5090
5106
|
return successResponse2(id, { reloaded: true });
|
|
5091
5107
|
}
|
|
5092
5108
|
case "select": {
|
|
5093
|
-
const cmd =
|
|
5109
|
+
const cmd = command;
|
|
5094
5110
|
await manager.select(cmd.selector, cmd.values);
|
|
5095
5111
|
return successResponse2(id, { selected: true });
|
|
5096
5112
|
}
|
|
5097
5113
|
case "check": {
|
|
5098
|
-
const cmd =
|
|
5114
|
+
const cmd = command;
|
|
5099
5115
|
await manager.check(cmd.selector);
|
|
5100
5116
|
return successResponse2(id, { checked: true });
|
|
5101
5117
|
}
|
|
5102
5118
|
case "uncheck": {
|
|
5103
|
-
const cmd =
|
|
5119
|
+
const cmd = command;
|
|
5104
5120
|
await manager.uncheck(cmd.selector);
|
|
5105
5121
|
return successResponse2(id, { unchecked: true });
|
|
5106
5122
|
}
|
|
5107
5123
|
case "focus": {
|
|
5108
|
-
const cmd =
|
|
5124
|
+
const cmd = command;
|
|
5109
5125
|
await manager.focus(cmd.selector);
|
|
5110
5126
|
return successResponse2(id, { focused: true });
|
|
5111
5127
|
}
|
|
5112
5128
|
case "clear": {
|
|
5113
|
-
const cmd =
|
|
5129
|
+
const cmd = command;
|
|
5114
5130
|
await manager.clear(cmd.selector);
|
|
5115
5131
|
return successResponse2(id, { cleared: true });
|
|
5116
5132
|
}
|
|
5117
5133
|
case "count": {
|
|
5118
|
-
const cmd =
|
|
5134
|
+
const cmd = command;
|
|
5119
5135
|
const count = await manager.count(cmd.selector);
|
|
5120
5136
|
return successResponse2(id, { count });
|
|
5121
5137
|
}
|
|
5122
5138
|
case "boundingbox": {
|
|
5123
|
-
const cmd =
|
|
5139
|
+
const cmd = command;
|
|
5124
5140
|
const box = await manager.getBoundingBox(cmd.selector);
|
|
5125
5141
|
return successResponse2(id, { box });
|
|
5126
5142
|
}
|
|
@@ -5186,8 +5202,8 @@ var StreamServer = class {
|
|
|
5186
5202
|
browser;
|
|
5187
5203
|
port;
|
|
5188
5204
|
isScreencasting = false;
|
|
5189
|
-
constructor(
|
|
5190
|
-
this.browser =
|
|
5205
|
+
constructor(browser, port = 9223) {
|
|
5206
|
+
this.browser = browser;
|
|
5191
5207
|
this.port = port;
|
|
5192
5208
|
}
|
|
5193
5209
|
/**
|
|
@@ -5350,8 +5366,8 @@ var StreamServer = class {
|
|
|
5350
5366
|
let viewportWidth;
|
|
5351
5367
|
let viewportHeight;
|
|
5352
5368
|
try {
|
|
5353
|
-
const
|
|
5354
|
-
const viewport =
|
|
5369
|
+
const page = this.browser.getPage();
|
|
5370
|
+
const viewport = page.viewportSize();
|
|
5355
5371
|
viewportWidth = viewport?.width;
|
|
5356
5372
|
viewportHeight = viewport?.height;
|
|
5357
5373
|
} catch {
|