playwright-core 1.58.0-alpha-2025-12-08 → 1.58.0-alpha-2025-12-10
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/browsers.json +8 -8
- package/lib/client/browserContext.js +7 -0
- package/lib/protocol/validator.js +10 -5
- package/lib/server/agent/actionRunner.js +16 -6
- package/lib/server/agent/agent.js +12 -10
- package/lib/server/agent/context.js +34 -10
- package/lib/server/agent/tools.js +51 -9
- package/lib/server/bidi/bidiBrowser.js +13 -4
- package/lib/server/bidi/bidiNetworkManager.js +1 -1
- package/lib/server/bidi/bidiPage.js +12 -2
- package/lib/server/bidi/third_party/bidiProtocolCore.js +1 -0
- package/lib/server/browserContext.js +1 -1
- package/lib/server/chromium/chromiumSwitches.js +0 -2
- package/lib/server/chromium/crBrowser.js +1 -1
- package/lib/server/chromium/crNetworkManager.js +39 -2
- package/lib/server/chromium/crPage.js +14 -81
- package/lib/server/deviceDescriptorsSource.json +2 -2
- package/lib/server/firefox/ffNetworkManager.js +2 -2
- package/lib/server/firefox/ffPage.js +9 -8
- package/lib/server/frames.js +2 -2
- package/lib/server/network.js +3 -0
- package/lib/server/page.js +4 -64
- package/lib/server/progress.js +3 -2
- package/lib/server/registry/index.js +1 -1
- package/lib/server/screencast.js +191 -0
- package/lib/server/trace/recorder/tracing.js +5 -5
- package/lib/server/utils/network.js +18 -26
- package/lib/server/{chromium/videoRecorder.js → videoRecorder.js} +3 -3
- package/lib/server/webkit/wkBrowser.js +1 -1
- package/lib/server/webkit/wkInterceptableRequest.js +29 -1
- package/lib/server/webkit/wkPage.js +20 -40
- package/lib/vite/traceViewer/uiMode.DiEbKRwa.js +5 -0
- package/lib/vite/traceViewer/uiMode.html +1 -1
- package/package.json +1 -1
- package/types/types.d.ts +8 -3
- package/lib/vite/traceViewer/uiMode.CmFFBCQb.js +0 -5
package/browsers.json
CHANGED
|
@@ -17,35 +17,35 @@
|
|
|
17
17
|
},
|
|
18
18
|
{
|
|
19
19
|
"name": "chromium-tip-of-tree",
|
|
20
|
-
"revision": "
|
|
20
|
+
"revision": "1389",
|
|
21
21
|
"installByDefault": false,
|
|
22
|
-
"browserVersion": "
|
|
22
|
+
"browserVersion": "144.0.7559.3",
|
|
23
23
|
"title": "Chrome Canary for Testing"
|
|
24
24
|
},
|
|
25
25
|
{
|
|
26
26
|
"name": "chromium-tip-of-tree-headless-shell",
|
|
27
|
-
"revision": "
|
|
27
|
+
"revision": "1389",
|
|
28
28
|
"installByDefault": false,
|
|
29
|
-
"browserVersion": "
|
|
29
|
+
"browserVersion": "144.0.7559.3",
|
|
30
30
|
"title": "Chrome Canary Headless Shell"
|
|
31
31
|
},
|
|
32
32
|
{
|
|
33
33
|
"name": "firefox",
|
|
34
|
-
"revision": "
|
|
34
|
+
"revision": "1504",
|
|
35
35
|
"installByDefault": true,
|
|
36
|
-
"browserVersion": "145.0.
|
|
36
|
+
"browserVersion": "145.0.2",
|
|
37
37
|
"title": "Firefox"
|
|
38
38
|
},
|
|
39
39
|
{
|
|
40
40
|
"name": "firefox-beta",
|
|
41
|
-
"revision": "
|
|
41
|
+
"revision": "1499",
|
|
42
42
|
"installByDefault": false,
|
|
43
43
|
"browserVersion": "146.0b8",
|
|
44
44
|
"title": "Firefox Beta"
|
|
45
45
|
},
|
|
46
46
|
{
|
|
47
47
|
"name": "webkit",
|
|
48
|
-
"revision": "
|
|
48
|
+
"revision": "2238",
|
|
49
49
|
"installByDefault": true,
|
|
50
50
|
"revisionOverrides": {
|
|
51
51
|
"debian11-x64": "2105",
|
|
@@ -493,6 +493,7 @@ async function prepareBrowserContextParams(platform, options) {
|
|
|
493
493
|
network.validateHeaders(options.extraHTTPHeaders);
|
|
494
494
|
const contextParams = {
|
|
495
495
|
...options,
|
|
496
|
+
agent: toAgentProtocol(options.agent),
|
|
496
497
|
viewport: options.viewport === null ? void 0 : options.viewport,
|
|
497
498
|
noDefaultViewport: options.viewport === null,
|
|
498
499
|
extraHTTPHeaders: options.extraHTTPHeaders ? (0, import_headers.headersObjectToArray)(options.extraHTTPHeaders) : void 0,
|
|
@@ -515,6 +516,12 @@ async function prepareBrowserContextParams(platform, options) {
|
|
|
515
516
|
contextParams.recordVideo.dir = platform.path().resolve(contextParams.recordVideo.dir);
|
|
516
517
|
return contextParams;
|
|
517
518
|
}
|
|
519
|
+
function toAgentProtocol(agent) {
|
|
520
|
+
if (!agent)
|
|
521
|
+
return void 0;
|
|
522
|
+
const secrets = agent.secrets ? Object.entries(agent.secrets).map(([name, value]) => ({ name, value })) : void 0;
|
|
523
|
+
return { ...agent, secrets };
|
|
524
|
+
}
|
|
518
525
|
function toAcceptDownloadsProtocol(acceptDownloads) {
|
|
519
526
|
if (acceptDownloads === void 0)
|
|
520
527
|
return void 0;
|
|
@@ -612,7 +612,8 @@ import_validatorPrimitives.scheme.BrowserTypeLaunchPersistentContextParams = (0,
|
|
|
612
612
|
provider: import_validatorPrimitives.tString,
|
|
613
613
|
model: import_validatorPrimitives.tString,
|
|
614
614
|
cacheFile: (0, import_validatorPrimitives.tOptional)(import_validatorPrimitives.tString),
|
|
615
|
-
cacheMode: (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tEnum)(["ignore", "force", "auto"]))
|
|
615
|
+
cacheMode: (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tEnum)(["ignore", "force", "auto"])),
|
|
616
|
+
secrets: (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tArray)((0, import_validatorPrimitives.tType)("NameValue")))
|
|
616
617
|
})),
|
|
617
618
|
userDataDir: import_validatorPrimitives.tString,
|
|
618
619
|
slowMo: (0, import_validatorPrimitives.tOptional)(import_validatorPrimitives.tFloat)
|
|
@@ -710,7 +711,8 @@ import_validatorPrimitives.scheme.BrowserNewContextParams = (0, import_validator
|
|
|
710
711
|
provider: import_validatorPrimitives.tString,
|
|
711
712
|
model: import_validatorPrimitives.tString,
|
|
712
713
|
cacheFile: (0, import_validatorPrimitives.tOptional)(import_validatorPrimitives.tString),
|
|
713
|
-
cacheMode: (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tEnum)(["ignore", "force", "auto"]))
|
|
714
|
+
cacheMode: (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tEnum)(["ignore", "force", "auto"])),
|
|
715
|
+
secrets: (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tArray)((0, import_validatorPrimitives.tType)("NameValue")))
|
|
714
716
|
})),
|
|
715
717
|
proxy: (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tObject)({
|
|
716
718
|
server: import_validatorPrimitives.tString,
|
|
@@ -787,7 +789,8 @@ import_validatorPrimitives.scheme.BrowserNewContextForReuseParams = (0, import_v
|
|
|
787
789
|
provider: import_validatorPrimitives.tString,
|
|
788
790
|
model: import_validatorPrimitives.tString,
|
|
789
791
|
cacheFile: (0, import_validatorPrimitives.tOptional)(import_validatorPrimitives.tString),
|
|
790
|
-
cacheMode: (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tEnum)(["ignore", "force", "auto"]))
|
|
792
|
+
cacheMode: (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tEnum)(["ignore", "force", "auto"])),
|
|
793
|
+
secrets: (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tArray)((0, import_validatorPrimitives.tType)("NameValue")))
|
|
791
794
|
})),
|
|
792
795
|
proxy: (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tObject)({
|
|
793
796
|
server: import_validatorPrimitives.tString,
|
|
@@ -909,7 +912,8 @@ import_validatorPrimitives.scheme.BrowserContextInitializer = (0, import_validat
|
|
|
909
912
|
provider: import_validatorPrimitives.tString,
|
|
910
913
|
model: import_validatorPrimitives.tString,
|
|
911
914
|
cacheFile: (0, import_validatorPrimitives.tOptional)(import_validatorPrimitives.tString),
|
|
912
|
-
cacheMode: (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tEnum)(["ignore", "force", "auto"]))
|
|
915
|
+
cacheMode: (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tEnum)(["ignore", "force", "auto"])),
|
|
916
|
+
secrets: (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tArray)((0, import_validatorPrimitives.tType)("NameValue")))
|
|
913
917
|
}))
|
|
914
918
|
})
|
|
915
919
|
});
|
|
@@ -2818,7 +2822,8 @@ import_validatorPrimitives.scheme.AndroidDeviceLaunchBrowserParams = (0, import_
|
|
|
2818
2822
|
provider: import_validatorPrimitives.tString,
|
|
2819
2823
|
model: import_validatorPrimitives.tString,
|
|
2820
2824
|
cacheFile: (0, import_validatorPrimitives.tOptional)(import_validatorPrimitives.tString),
|
|
2821
|
-
cacheMode: (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tEnum)(["ignore", "force", "auto"]))
|
|
2825
|
+
cacheMode: (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tEnum)(["ignore", "force", "auto"])),
|
|
2826
|
+
secrets: (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tArray)((0, import_validatorPrimitives.tType)("NameValue")))
|
|
2822
2827
|
})),
|
|
2823
2828
|
pkg: (0, import_validatorPrimitives.tOptional)(import_validatorPrimitives.tString),
|
|
2824
2829
|
args: (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tArray)(import_validatorPrimitives.tString)),
|
|
@@ -21,7 +21,7 @@ __export(actionRunner_exports, {
|
|
|
21
21
|
runAction: () => runAction
|
|
22
22
|
});
|
|
23
23
|
module.exports = __toCommonJS(actionRunner_exports);
|
|
24
|
-
async function runAction(progress, page, action) {
|
|
24
|
+
async function runAction(progress, page, action, secrets) {
|
|
25
25
|
const frame = page.mainFrame();
|
|
26
26
|
switch (action.method) {
|
|
27
27
|
case "click":
|
|
@@ -34,21 +34,31 @@ async function runAction(progress, page, action) {
|
|
|
34
34
|
await frame.hover(progress, action.selector, { ...action.options, ...strictTrue });
|
|
35
35
|
break;
|
|
36
36
|
case "selectOption":
|
|
37
|
-
await frame.selectOption(progress, action.selector, [], action.
|
|
37
|
+
await frame.selectOption(progress, action.selector, [], action.labels.map((a) => ({ label: a })), { ...strictTrue });
|
|
38
38
|
break;
|
|
39
39
|
case "pressKey":
|
|
40
40
|
await page.keyboard.press(progress, action.key);
|
|
41
41
|
break;
|
|
42
|
-
case "pressSequentially":
|
|
43
|
-
|
|
42
|
+
case "pressSequentially": {
|
|
43
|
+
const secret = secrets?.find((s) => s.name === action.text)?.value ?? action.text;
|
|
44
|
+
await frame.type(progress, action.selector, secret, { ...strictTrue });
|
|
44
45
|
if (action.submit)
|
|
45
46
|
await page.keyboard.press(progress, "Enter");
|
|
46
47
|
break;
|
|
47
|
-
|
|
48
|
-
|
|
48
|
+
}
|
|
49
|
+
case "fill": {
|
|
50
|
+
const secret = secrets?.find((s) => s.name === action.text)?.value ?? action.text;
|
|
51
|
+
await frame.fill(progress, action.selector, secret, { ...strictTrue });
|
|
49
52
|
if (action.submit)
|
|
50
53
|
await page.keyboard.press(progress, "Enter");
|
|
51
54
|
break;
|
|
55
|
+
}
|
|
56
|
+
case "setChecked":
|
|
57
|
+
if (action.checked)
|
|
58
|
+
await frame.check(progress, action.selector, { ...strictTrue });
|
|
59
|
+
else
|
|
60
|
+
await frame.uncheck(progress, action.selector, { ...strictTrue });
|
|
61
|
+
break;
|
|
52
62
|
}
|
|
53
63
|
}
|
|
54
64
|
const strictTrue = { strict: true };
|
|
@@ -83,28 +83,30 @@ ${full}
|
|
|
83
83
|
}
|
|
84
84
|
const allCaches = /* @__PURE__ */ new Map();
|
|
85
85
|
async function cachedPerform(context, options) {
|
|
86
|
-
|
|
87
|
-
if (!agentSettings?.cacheFile || agentSettings.cacheMode === "ignore")
|
|
86
|
+
if (!context.options?.cacheFile || context.options.cacheMode === "ignore")
|
|
88
87
|
return false;
|
|
89
|
-
const cache = await cachedActions(
|
|
88
|
+
const cache = await cachedActions(context.options.cacheFile);
|
|
90
89
|
const cacheKey = options.key ?? options.task;
|
|
91
|
-
const
|
|
92
|
-
if (!
|
|
93
|
-
if (
|
|
90
|
+
const entry = cache[cacheKey];
|
|
91
|
+
if (!entry) {
|
|
92
|
+
if (context.options.cacheMode === "force")
|
|
94
93
|
throw new Error(`No cached actions for key "${cacheKey}", but cache mode is set to "force"`);
|
|
95
94
|
return false;
|
|
96
95
|
}
|
|
97
|
-
for (const action of actions)
|
|
98
|
-
await (0, import_actionRunner.runAction)(context.progress, context.page, action);
|
|
96
|
+
for (const action of entry.actions)
|
|
97
|
+
await (0, import_actionRunner.runAction)(context.progress, context.page, action, context.options.secrets ?? []);
|
|
99
98
|
return true;
|
|
100
99
|
}
|
|
101
100
|
async function updateCache(context, options) {
|
|
102
|
-
const cacheFile = context.
|
|
101
|
+
const cacheFile = context.options?.cacheFile;
|
|
103
102
|
if (!cacheFile)
|
|
104
103
|
return;
|
|
105
104
|
const cache = await cachedActions(cacheFile);
|
|
106
105
|
const cacheKey = options.key ?? options.task;
|
|
107
|
-
cache[cacheKey] =
|
|
106
|
+
cache[cacheKey] = {
|
|
107
|
+
timestamp: Date.now(),
|
|
108
|
+
actions: context.actions
|
|
109
|
+
};
|
|
108
110
|
await import_fs.default.promises.writeFile(cacheFile, JSON.stringify(cache, void 0, 2));
|
|
109
111
|
}
|
|
110
112
|
async function cachedActions(cacheFile) {
|
|
@@ -28,10 +28,18 @@ class Context {
|
|
|
28
28
|
this.actions = [];
|
|
29
29
|
this.progress = progress;
|
|
30
30
|
this.page = page;
|
|
31
|
+
this.options = page.browserContext._options.agent;
|
|
31
32
|
}
|
|
32
|
-
async
|
|
33
|
-
await this.
|
|
34
|
-
|
|
33
|
+
async runActionAndWait(action) {
|
|
34
|
+
return await this.runActionsAndWait([action]);
|
|
35
|
+
}
|
|
36
|
+
async runActionsAndWait(action) {
|
|
37
|
+
await this.waitForCompletion(async () => {
|
|
38
|
+
for (const a of action) {
|
|
39
|
+
await (0, import_actionRunner.runAction)(this.progress, this.page, a, this.options?.secrets ?? []);
|
|
40
|
+
this.actions.push(a);
|
|
41
|
+
}
|
|
42
|
+
});
|
|
35
43
|
return await this.snapshotResult();
|
|
36
44
|
}
|
|
37
45
|
async waitForCompletion(callback) {
|
|
@@ -40,6 +48,7 @@ class Context {
|
|
|
40
48
|
const disposeListeners = () => {
|
|
41
49
|
this.page.browserContext.off(import_browserContext.BrowserContext.Events.Request, requestListener);
|
|
42
50
|
};
|
|
51
|
+
this.page.browserContext.on(import_browserContext.BrowserContext.Events.Request, requestListener);
|
|
43
52
|
let result;
|
|
44
53
|
try {
|
|
45
54
|
result = await callback();
|
|
@@ -49,20 +58,24 @@ class Context {
|
|
|
49
58
|
}
|
|
50
59
|
const requestedNavigation = requests.some((request) => request.isNavigationRequest());
|
|
51
60
|
if (requestedNavigation) {
|
|
52
|
-
await this.page.
|
|
61
|
+
await this.page.mainFrame().waitForLoadState(this.progress, "load");
|
|
53
62
|
return result;
|
|
54
63
|
}
|
|
55
|
-
const
|
|
64
|
+
const promises = [];
|
|
56
65
|
for (const request of requests) {
|
|
57
|
-
if (request.
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
66
|
+
if (["document", "stylesheet", "script", "xhr", "fetch"].includes(request.resourceType()))
|
|
67
|
+
promises.push(request.response().then((r) => r?.finished()));
|
|
68
|
+
else
|
|
69
|
+
promises.push(request.response());
|
|
61
70
|
}
|
|
71
|
+
await this.progress.race(promises, { timeout: 5e3 });
|
|
72
|
+
if (requests.length)
|
|
73
|
+
await this.progress.wait(500);
|
|
62
74
|
return result;
|
|
63
75
|
}
|
|
64
76
|
async snapshotResult() {
|
|
65
|
-
|
|
77
|
+
let { full } = await this.page.snapshotForAI(this.progress);
|
|
78
|
+
full = this._redactText(full);
|
|
66
79
|
const text = [`# Page snapshot
|
|
67
80
|
${full}`];
|
|
68
81
|
return {
|
|
@@ -84,6 +97,17 @@ ${full}`];
|
|
|
84
97
|
}
|
|
85
98
|
}));
|
|
86
99
|
}
|
|
100
|
+
_redactText(text) {
|
|
101
|
+
const secrets = this.options?.secrets;
|
|
102
|
+
if (!secrets)
|
|
103
|
+
return text;
|
|
104
|
+
const redactText = (text2) => {
|
|
105
|
+
for (const { name, value } of secrets)
|
|
106
|
+
text2 = text2.replaceAll(value, `<secret>${name}</secret>`);
|
|
107
|
+
return text2;
|
|
108
|
+
};
|
|
109
|
+
return redactText(text);
|
|
110
|
+
}
|
|
87
111
|
}
|
|
88
112
|
// Annotate the CommonJS export names for ESM import in node:
|
|
89
113
|
0 && (module.exports = {
|
|
@@ -54,7 +54,7 @@ const click = defineTool({
|
|
|
54
54
|
},
|
|
55
55
|
handle: async (context, params) => {
|
|
56
56
|
const [selector] = await context.refSelectors([params]);
|
|
57
|
-
return await context.
|
|
57
|
+
return await context.runActionAndWait({
|
|
58
58
|
method: "click",
|
|
59
59
|
selector,
|
|
60
60
|
options: {
|
|
@@ -82,7 +82,7 @@ const drag = defineTool({
|
|
|
82
82
|
{ ref: params.startRef, element: params.startElement },
|
|
83
83
|
{ ref: params.endRef, element: params.endElement }
|
|
84
84
|
]);
|
|
85
|
-
return await context.
|
|
85
|
+
return await context.runActionAndWait({
|
|
86
86
|
method: "drag",
|
|
87
87
|
sourceSelector,
|
|
88
88
|
targetSelector
|
|
@@ -101,7 +101,7 @@ const hover = defineTool({
|
|
|
101
101
|
},
|
|
102
102
|
handle: async (context, params) => {
|
|
103
103
|
const [selector] = await context.refSelectors([params]);
|
|
104
|
-
return await context.
|
|
104
|
+
return await context.runActionAndWait({
|
|
105
105
|
method: "hover",
|
|
106
106
|
selector,
|
|
107
107
|
options: {
|
|
@@ -122,10 +122,10 @@ const selectOption = defineTool({
|
|
|
122
122
|
},
|
|
123
123
|
handle: async (context, params) => {
|
|
124
124
|
const [selector] = await context.refSelectors([params]);
|
|
125
|
-
return await context.
|
|
125
|
+
return await context.runActionAndWait({
|
|
126
126
|
method: "selectOption",
|
|
127
127
|
selector,
|
|
128
|
-
|
|
128
|
+
labels: params.values
|
|
129
129
|
});
|
|
130
130
|
}
|
|
131
131
|
});
|
|
@@ -139,7 +139,7 @@ const pressKey = defineTool({
|
|
|
139
139
|
})
|
|
140
140
|
},
|
|
141
141
|
handle: async (context, params) => {
|
|
142
|
-
return await context.
|
|
142
|
+
return await context.runActionAndWait({
|
|
143
143
|
method: "pressKey",
|
|
144
144
|
key: params.key
|
|
145
145
|
});
|
|
@@ -160,14 +160,14 @@ const type = defineTool({
|
|
|
160
160
|
handle: async (context, params) => {
|
|
161
161
|
const [selector] = await context.refSelectors([params]);
|
|
162
162
|
if (params.slowly) {
|
|
163
|
-
return await context.
|
|
163
|
+
return await context.runActionAndWait({
|
|
164
164
|
method: "pressSequentially",
|
|
165
165
|
selector,
|
|
166
166
|
text: params.text,
|
|
167
167
|
submit: params.submit
|
|
168
168
|
});
|
|
169
169
|
} else {
|
|
170
|
-
return await context.
|
|
170
|
+
return await context.runActionAndWait({
|
|
171
171
|
method: "fill",
|
|
172
172
|
selector,
|
|
173
173
|
text: params.text,
|
|
@@ -176,6 +176,47 @@ const type = defineTool({
|
|
|
176
176
|
}
|
|
177
177
|
}
|
|
178
178
|
});
|
|
179
|
+
const fillForm = defineTool({
|
|
180
|
+
schema: {
|
|
181
|
+
name: "browser_fill_form",
|
|
182
|
+
title: "Fill form",
|
|
183
|
+
description: "Fill multiple form fields",
|
|
184
|
+
inputSchema: import_mcpBundle.z.object({
|
|
185
|
+
fields: import_mcpBundle.z.array(import_mcpBundle.z.object({
|
|
186
|
+
name: import_mcpBundle.z.string().describe("Human-readable field name"),
|
|
187
|
+
type: import_mcpBundle.z.enum(["textbox", "checkbox", "radio", "combobox", "slider"]).describe("Type of the field"),
|
|
188
|
+
ref: import_mcpBundle.z.string().describe("Exact target field reference from the page snapshot"),
|
|
189
|
+
value: import_mcpBundle.z.string().describe("Value to fill in the field. If the field is a checkbox, the value should be `true` or `false`. If the field is a combobox, the value should be the text of the option.")
|
|
190
|
+
})).describe("Fields to fill in")
|
|
191
|
+
})
|
|
192
|
+
},
|
|
193
|
+
handle: async (context, params) => {
|
|
194
|
+
const actions = [];
|
|
195
|
+
for (const field of params.fields) {
|
|
196
|
+
const [selector] = await context.refSelectors([{ ref: field.ref, element: field.name }]);
|
|
197
|
+
if (field.type === "textbox" || field.type === "slider") {
|
|
198
|
+
actions.push({
|
|
199
|
+
method: "fill",
|
|
200
|
+
selector,
|
|
201
|
+
text: field.value
|
|
202
|
+
});
|
|
203
|
+
} else if (field.type === "checkbox" || field.type === "radio") {
|
|
204
|
+
actions.push({
|
|
205
|
+
method: "setChecked",
|
|
206
|
+
selector,
|
|
207
|
+
checked: field.value === "true"
|
|
208
|
+
});
|
|
209
|
+
} else if (field.type === "combobox") {
|
|
210
|
+
actions.push({
|
|
211
|
+
method: "selectOption",
|
|
212
|
+
selector,
|
|
213
|
+
labels: [field.value]
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
return await context.runActionsAndWait(actions);
|
|
218
|
+
}
|
|
219
|
+
});
|
|
179
220
|
var tools_default = [
|
|
180
221
|
snapshot,
|
|
181
222
|
click,
|
|
@@ -183,5 +224,6 @@ var tools_default = [
|
|
|
183
224
|
hover,
|
|
184
225
|
selectOption,
|
|
185
226
|
pressKey,
|
|
186
|
-
type
|
|
227
|
+
type,
|
|
228
|
+
fillForm
|
|
187
229
|
];
|
|
@@ -366,19 +366,28 @@ class BidiBrowserContext extends import_browserContext.BrowserContext {
|
|
|
366
366
|
}
|
|
367
367
|
}
|
|
368
368
|
async doUpdateDefaultViewport() {
|
|
369
|
-
if (!this._options.viewport)
|
|
369
|
+
if (!this._options.viewport && !this._options.screen)
|
|
370
370
|
return;
|
|
371
|
+
const screenSize = this._options.screen || this._options.viewport;
|
|
372
|
+
const viewportSize = this._options.viewport || this._options.screen;
|
|
371
373
|
await Promise.all([
|
|
372
374
|
this._browser._browserSession.send("browsingContext.setViewport", {
|
|
373
375
|
viewport: {
|
|
374
|
-
width:
|
|
375
|
-
height:
|
|
376
|
+
width: viewportSize.width,
|
|
377
|
+
height: viewportSize.height
|
|
376
378
|
},
|
|
377
379
|
devicePixelRatio: this._options.deviceScaleFactor || 1,
|
|
378
380
|
userContexts: [this._userContextId()]
|
|
379
381
|
}),
|
|
380
382
|
this._browser._browserSession.send("emulation.setScreenOrientationOverride", {
|
|
381
|
-
screenOrientation: getScreenOrientation(!!this._options.isMobile,
|
|
383
|
+
screenOrientation: getScreenOrientation(!!this._options.isMobile, screenSize),
|
|
384
|
+
userContexts: [this._userContextId()]
|
|
385
|
+
}),
|
|
386
|
+
this._browser._browserSession.send("emulation.setScreenSettingsOverride", {
|
|
387
|
+
screenArea: {
|
|
388
|
+
width: screenSize.width,
|
|
389
|
+
height: screenSize.height
|
|
390
|
+
},
|
|
382
391
|
userContexts: [this._userContextId()]
|
|
383
392
|
})
|
|
384
393
|
]);
|
|
@@ -306,6 +306,7 @@ ${params.stackTrace?.callFrames.map((f) => {
|
|
|
306
306
|
const emulatedSize = this._page.emulatedSize();
|
|
307
307
|
if (!emulatedSize)
|
|
308
308
|
return;
|
|
309
|
+
const screenSize = emulatedSize.screen;
|
|
309
310
|
const viewportSize = emulatedSize.viewport;
|
|
310
311
|
await Promise.all([
|
|
311
312
|
this._session.send("browsingContext.setViewport", {
|
|
@@ -318,7 +319,14 @@ ${params.stackTrace?.callFrames.map((f) => {
|
|
|
318
319
|
}),
|
|
319
320
|
this._session.send("emulation.setScreenOrientationOverride", {
|
|
320
321
|
contexts: [this._session.sessionId],
|
|
321
|
-
screenOrientation: (0, import_bidiBrowser.getScreenOrientation)(!!options.isMobile,
|
|
322
|
+
screenOrientation: (0, import_bidiBrowser.getScreenOrientation)(!!options.isMobile, screenSize)
|
|
323
|
+
}),
|
|
324
|
+
this._session.send("emulation.setScreenSettingsOverride", {
|
|
325
|
+
contexts: [this._session.sessionId],
|
|
326
|
+
screenArea: {
|
|
327
|
+
width: screenSize.width,
|
|
328
|
+
height: screenSize.height
|
|
329
|
+
}
|
|
322
330
|
})
|
|
323
331
|
]);
|
|
324
332
|
}
|
|
@@ -482,7 +490,9 @@ ${params.stackTrace?.callFrames.map((f) => {
|
|
|
482
490
|
throw e;
|
|
483
491
|
});
|
|
484
492
|
}
|
|
485
|
-
async
|
|
493
|
+
async startScreencast(options) {
|
|
494
|
+
}
|
|
495
|
+
async stopScreencast() {
|
|
486
496
|
}
|
|
487
497
|
rafCountForStablePosition() {
|
|
488
498
|
return 1;
|
|
@@ -322,7 +322,7 @@ if (navigator.serviceWorker) navigator.serviceWorker.register = async () => { co
|
|
|
322
322
|
const pageOrError = await progress.race(page.waitForInitializedOrError());
|
|
323
323
|
if (pageOrError instanceof Error)
|
|
324
324
|
throw pageOrError;
|
|
325
|
-
await page.mainFrame().
|
|
325
|
+
await page.mainFrame().waitForLoadState(progress, "load");
|
|
326
326
|
return page;
|
|
327
327
|
}
|
|
328
328
|
async _loadDefaultContext(progress) {
|
|
@@ -22,8 +22,6 @@ __export(chromiumSwitches_exports, {
|
|
|
22
22
|
});
|
|
23
23
|
module.exports = __toCommonJS(chromiumSwitches_exports);
|
|
24
24
|
const disabledFeatures = (assistantMode) => [
|
|
25
|
-
// See https://github.com/microsoft/playwright/pull/10380
|
|
26
|
-
"AcceptCHFrame",
|
|
27
25
|
// See https://github.com/microsoft/playwright/issues/14047
|
|
28
26
|
"AvoidUnnecessaryBeforeUnloadCheckSync",
|
|
29
27
|
"DestroyProfileOnBrowserClose",
|
|
@@ -470,7 +470,7 @@ class CRBrowserContext extends import_browserContext.BrowserContext {
|
|
|
470
470
|
}
|
|
471
471
|
}
|
|
472
472
|
async stopVideoRecording() {
|
|
473
|
-
await Promise.all(this._crPages().map((crPage) => crPage.
|
|
473
|
+
await Promise.all(this._crPages().map((crPage) => crPage._page.screencast.stopVideoRecording()));
|
|
474
474
|
}
|
|
475
475
|
onClosePersistent() {
|
|
476
476
|
}
|
|
@@ -482,12 +482,11 @@ class InterceptableRequest {
|
|
|
482
482
|
url,
|
|
483
483
|
postDataEntries = null
|
|
484
484
|
} = requestPausedEvent ? requestPausedEvent.request : requestWillBeSentEvent.request;
|
|
485
|
-
const type = (requestWillBeSentEvent.type || "").toLowerCase();
|
|
486
485
|
let postDataBuffer = null;
|
|
487
486
|
const entries = postDataEntries?.filter((entry) => entry.bytes);
|
|
488
487
|
if (entries && entries.length)
|
|
489
488
|
postDataBuffer = Buffer.concat(entries.map((entry) => Buffer.from(entry.bytes, "base64")));
|
|
490
|
-
this.request = new network.Request(context, frame, serviceWorker, redirectedFrom?.request || null, documentId, url, type, method, postDataBuffer, headersOverride || (0, import_utils.headersObjectToArray)(headers));
|
|
489
|
+
this.request = new network.Request(context, frame, serviceWorker, redirectedFrom?.request || null, documentId, url, toResourceType(requestWillBeSentEvent.type || "Other"), method, postDataBuffer, headersOverride || (0, import_utils.headersObjectToArray)(headers));
|
|
491
490
|
}
|
|
492
491
|
}
|
|
493
492
|
class RouteImpl {
|
|
@@ -660,6 +659,44 @@ class ResponseExtraInfoTracker {
|
|
|
660
659
|
this._requests.delete(requestId);
|
|
661
660
|
}
|
|
662
661
|
}
|
|
662
|
+
function toResourceType(type) {
|
|
663
|
+
switch (type) {
|
|
664
|
+
case "Document":
|
|
665
|
+
return "document";
|
|
666
|
+
case "Stylesheet":
|
|
667
|
+
return "stylesheet";
|
|
668
|
+
case "Image":
|
|
669
|
+
return "image";
|
|
670
|
+
case "Media":
|
|
671
|
+
return "media";
|
|
672
|
+
case "Font":
|
|
673
|
+
return "font";
|
|
674
|
+
case "Script":
|
|
675
|
+
return "script";
|
|
676
|
+
case "TextTrack":
|
|
677
|
+
return "texttrack";
|
|
678
|
+
case "XHR":
|
|
679
|
+
return "xhr";
|
|
680
|
+
case "Fetch":
|
|
681
|
+
return "fetch";
|
|
682
|
+
case "EventSource":
|
|
683
|
+
return "eventsource";
|
|
684
|
+
case "WebSocket":
|
|
685
|
+
return "websocket";
|
|
686
|
+
case "Manifest":
|
|
687
|
+
return "manifest";
|
|
688
|
+
case "Ping":
|
|
689
|
+
return "ping";
|
|
690
|
+
case "CSPViolationReport":
|
|
691
|
+
return "cspreport";
|
|
692
|
+
case "Prefetch":
|
|
693
|
+
case "SignedExchange":
|
|
694
|
+
case "Preflight":
|
|
695
|
+
case "FedCM":
|
|
696
|
+
default:
|
|
697
|
+
return "other";
|
|
698
|
+
}
|
|
699
|
+
}
|
|
663
700
|
// Annotate the CommonJS export names for ESM import in node:
|
|
664
701
|
0 && (module.exports = {
|
|
665
702
|
CRNetworkManager
|