@smoothdeploy/playwright-core 1.57.1 → 1.58.1-beta-1770452953000
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.
Potentially problematic release.
This version of @smoothdeploy/playwright-core might be problematic. Click here for more details.
- package/ThirdPartyNotices.txt +3223 -308
- package/browsers.json +21 -22
- package/lib/cli/program.js +4 -5
- package/lib/client/api.js +3 -0
- package/lib/client/browser.js +3 -5
- package/lib/client/browserContext.js +35 -0
- package/lib/client/browserType.js +4 -3
- package/lib/client/channelOwner.js +4 -3
- package/lib/client/clientInstrumentation.js +10 -0
- package/lib/client/connection.js +4 -0
- package/lib/client/elementHandle.js +3 -0
- package/lib/client/events.js +3 -0
- package/lib/client/fetch.js +3 -4
- package/lib/client/frame.js +1 -0
- package/lib/client/page.js +28 -1
- package/lib/client/pageAgent.js +64 -0
- package/lib/client/platform.js +3 -0
- package/lib/generated/injectedScriptSource.js +1 -1
- package/lib/generated/pollingRecorderSource.js +1 -1
- package/lib/mcpBundle.js +84 -0
- package/lib/mcpBundleImpl/index.js +147 -0
- package/lib/protocol/serializers.js +5 -0
- package/lib/protocol/validator.js +92 -3
- package/lib/remote/playwrightServer.js +1 -2
- package/lib/server/agent/actionRunner.js +335 -0
- package/lib/server/agent/actions.js +128 -0
- package/lib/server/agent/codegen.js +111 -0
- package/lib/server/agent/context.js +150 -0
- package/lib/server/agent/expectTools.js +156 -0
- package/lib/server/agent/pageAgent.js +204 -0
- package/lib/server/agent/performTools.js +262 -0
- package/lib/server/agent/tool.js +109 -0
- package/lib/server/artifact.js +1 -1
- package/lib/server/bidi/bidiBrowser.js +56 -12
- package/lib/server/bidi/bidiChromium.js +6 -11
- package/lib/server/bidi/bidiConnection.js +1 -0
- package/lib/server/bidi/bidiDeserializer.js +116 -0
- package/lib/server/bidi/bidiExecutionContext.js +75 -29
- package/lib/server/bidi/bidiFirefox.js +6 -8
- package/lib/server/bidi/bidiNetworkManager.js +1 -1
- package/lib/server/bidi/bidiPage.js +39 -28
- package/lib/server/bidi/third_party/bidiProtocolCore.js +1 -0
- package/lib/server/browserContext.js +32 -25
- package/lib/server/browserType.js +12 -4
- package/lib/server/chromium/chromium.js +14 -21
- package/lib/server/chromium/chromiumSwitches.js +2 -2
- package/lib/server/chromium/crBrowser.js +22 -12
- package/lib/server/chromium/crConnection.js +0 -5
- package/lib/server/chromium/crDevTools.js +0 -2
- package/lib/server/chromium/crNetworkManager.js +43 -2
- package/lib/server/chromium/crPage.js +19 -87
- package/lib/server/codegen/javascript.js +6 -29
- package/lib/server/deviceDescriptorsSource.json +56 -56
- package/lib/server/dispatchers/browserContextDispatcher.js +3 -0
- package/lib/server/dispatchers/dispatcher.js +6 -13
- package/lib/server/dispatchers/frameDispatcher.js +1 -1
- package/lib/server/dispatchers/pageAgentDispatcher.js +96 -0
- package/lib/server/dispatchers/pageDispatcher.js +4 -0
- package/lib/server/dom.js +12 -3
- package/lib/server/electron/electron.js +5 -2
- package/lib/server/firefox/ffBrowser.js +10 -20
- package/lib/server/firefox/ffConnection.js +0 -5
- package/lib/server/firefox/ffNetworkManager.js +2 -2
- package/lib/server/firefox/ffPage.js +15 -18
- package/lib/server/firefox/firefox.js +6 -8
- package/lib/server/frameSelectors.js +9 -3
- package/lib/server/frames.js +49 -33
- package/lib/server/instrumentation.js +3 -0
- package/lib/server/network.js +50 -12
- package/lib/server/page.js +33 -89
- package/lib/server/progress.js +26 -6
- package/lib/server/recorder/recorderApp.js +79 -100
- package/lib/server/recorder.js +55 -0
- package/lib/server/registry/browserFetcher.js +6 -4
- package/lib/server/registry/index.js +172 -149
- package/lib/server/registry/oopDownloadBrowserMain.js +3 -0
- package/lib/server/screencast.js +190 -0
- package/lib/server/screenshotCompositor.js +153 -0
- package/lib/server/trace/recorder/snapshotterInjected.js +21 -1
- package/lib/server/trace/recorder/tracing.js +21 -21
- package/lib/server/trace/viewer/traceParser.js +72 -0
- package/lib/server/trace/viewer/traceViewer.js +17 -13
- package/lib/server/utils/expectUtils.js +87 -2
- package/lib/server/utils/httpServer.js +4 -19
- package/lib/server/utils/network.js +37 -28
- package/lib/server/utils/nodePlatform.js +6 -0
- package/lib/server/videoRecorder.js +124 -0
- package/lib/server/webkit/webkit.js +4 -6
- package/lib/server/webkit/wkBrowser.js +2 -6
- package/lib/server/webkit/wkConnection.js +1 -6
- package/lib/server/webkit/wkInterceptableRequest.js +29 -1
- package/lib/server/webkit/wkPage.js +75 -46
- package/lib/utils/isomorphic/ariaSnapshot.js +60 -2
- package/lib/utils/isomorphic/lruCache.js +51 -0
- package/lib/utils/isomorphic/protocolMetainfo.js +9 -1
- package/lib/utils/isomorphic/stringUtils.js +49 -0
- package/lib/utils/isomorphic/trace/entries.js +16 -0
- package/lib/utils/isomorphic/trace/snapshotRenderer.js +499 -0
- package/lib/utils/isomorphic/trace/snapshotServer.js +120 -0
- package/lib/utils/isomorphic/trace/snapshotStorage.js +89 -0
- package/lib/utils/isomorphic/trace/traceLoader.js +131 -0
- package/lib/utils/isomorphic/trace/traceModel.js +365 -0
- package/lib/utils/isomorphic/trace/traceModernizer.js +400 -0
- package/lib/utils/isomorphic/trace/versions/traceV3.js +16 -0
- package/lib/utils/isomorphic/trace/versions/traceV4.js +16 -0
- package/lib/utils/isomorphic/trace/versions/traceV5.js +16 -0
- package/lib/utils/isomorphic/trace/versions/traceV6.js +16 -0
- package/lib/utils/isomorphic/trace/versions/traceV7.js +16 -0
- package/lib/utils/isomorphic/trace/versions/traceV8.js +16 -0
- package/lib/utils/isomorphic/yaml.js +84 -0
- package/lib/utils.js +2 -0
- package/lib/utilsBundle.js +2 -5
- package/lib/utilsBundleImpl/index.js +165 -165
- package/lib/vite/htmlReport/index.html +21 -21
- package/lib/vite/recorder/assets/{codeMirrorModule-C3UTv-Ge.css → codeMirrorModule-DYBRYzYX.css} +1 -1
- package/lib/vite/recorder/assets/codeMirrorModule-DadYNm1I.js +32 -0
- package/lib/vite/recorder/assets/{index-Ri0uHF7I.css → index-BSjZa4pk.css} +1 -1
- package/lib/vite/recorder/assets/index-BhTWtUlo.js +193 -0
- package/lib/vite/recorder/index.html +2 -2
- package/lib/vite/traceViewer/assets/codeMirrorModule-8UJPCtp4.js +16884 -0
- package/lib/vite/{recorder/assets/codeMirrorModule-BoWUGj0J.js → traceViewer/assets/codeMirrorModule-BNr6yhVP.js} +1 -1
- package/lib/vite/traceViewer/assets/codeMirrorModule-Dimjuz94.js +32 -0
- package/lib/vite/traceViewer/assets/codeMirrorModule-DkmsYcws.js +32 -0
- package/lib/vite/traceViewer/assets/codeMirrorModule-DySgctgr.js +16884 -0
- package/lib/vite/traceViewer/assets/defaultSettingsView-B1vuWQsF.js +266 -0
- package/lib/vite/traceViewer/assets/defaultSettingsView-CtEsdeVH.js +266 -0
- package/lib/vite/traceViewer/assets/defaultSettingsView-D4fm31R-.js +34087 -0
- package/lib/vite/traceViewer/assets/defaultSettingsView-JtyB0yzL.js +34087 -0
- package/lib/vite/traceViewer/assets/defaultSettingsView-tEZf-LNj.js +266 -0
- package/lib/vite/traceViewer/assets/xtermModule-DDw6eROI.js +6168 -0
- package/lib/vite/traceViewer/codeMirrorModule.DYBRYzYX.css +1 -0
- package/lib/vite/traceViewer/codeMirrorModule.DuST8d_k.css +344 -0
- package/lib/vite/traceViewer/defaultSettingsView.5FCqBwKs.css +3986 -0
- package/lib/vite/traceViewer/defaultSettingsView.7ch9cixO.css +1 -0
- package/lib/vite/traceViewer/index.BQs8gGhY.js +249 -0
- package/lib/vite/traceViewer/index.BVu7tZDe.css +1 -0
- package/lib/vite/traceViewer/index.BoLn624r.js +2 -0
- package/lib/vite/traceViewer/index.Bq_EaK8x.js +249 -0
- package/lib/vite/traceViewer/index.C8YVh4B5.js +2 -0
- package/lib/vite/traceViewer/index.Cr7-GRf8.js +2 -0
- package/lib/vite/traceViewer/index.G-7UhDxt.css +164 -0
- package/lib/vite/traceViewer/index.html +4 -4
- package/lib/vite/traceViewer/sw.bundle.js +5 -3
- package/lib/vite/traceViewer/uiMode.-Kflt2XM.css +1440 -0
- package/lib/vite/traceViewer/uiMode.BTRKnokb.js +5 -0
- package/lib/vite/traceViewer/uiMode.CEZ5RVHh.js +5 -0
- package/lib/vite/traceViewer/uiMode.CIWF23si.js +1829 -0
- package/lib/vite/traceViewer/uiMode.Wi-DvIEY.js +1829 -0
- package/lib/vite/traceViewer/uiMode.html +3 -3
- package/lib/vite/traceViewer/uiMode.zEH1ejvz.js +5 -0
- package/lib/vite/traceViewer/xtermModule.BKlWQB97.css +218 -0
- package/package.json +3 -1
- package/types/protocol.d.ts +738 -159
- package/types/types.d.ts +25 -38
- package/lib/vite/recorder/assets/index-DJqDAOZp.js +0 -193
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var pageAgentDispatcher_exports = {};
|
|
20
|
+
__export(pageAgentDispatcher_exports, {
|
|
21
|
+
PageAgentDispatcher: () => PageAgentDispatcher
|
|
22
|
+
});
|
|
23
|
+
module.exports = __toCommonJS(pageAgentDispatcher_exports);
|
|
24
|
+
var import_dispatcher = require("./dispatcher");
|
|
25
|
+
var import_pageAgent = require("../agent/pageAgent");
|
|
26
|
+
var import_instrumentation = require("../instrumentation");
|
|
27
|
+
var import_context = require("../agent/context");
|
|
28
|
+
class PageAgentDispatcher extends import_dispatcher.Dispatcher {
|
|
29
|
+
constructor(scope, options) {
|
|
30
|
+
super(scope, new import_instrumentation.SdkObject(scope._object, "pageAgent"), "PageAgent", { page: scope });
|
|
31
|
+
this._type_PageAgent = true;
|
|
32
|
+
this._type_EventTarget = true;
|
|
33
|
+
this._usage = { turns: 0, inputTokens: 0, outputTokens: 0 };
|
|
34
|
+
this._page = scope._object;
|
|
35
|
+
this._context = new import_context.Context(this._page, options, this._eventSupport());
|
|
36
|
+
}
|
|
37
|
+
async perform(params, progress) {
|
|
38
|
+
try {
|
|
39
|
+
await (0, import_pageAgent.pageAgentPerform)(progress, this._context, params.task, params);
|
|
40
|
+
} finally {
|
|
41
|
+
this._context.pushHistory({ type: "perform", description: params.task });
|
|
42
|
+
}
|
|
43
|
+
return { usage: this._usage };
|
|
44
|
+
}
|
|
45
|
+
async expect(params, progress) {
|
|
46
|
+
try {
|
|
47
|
+
await (0, import_pageAgent.pageAgentExpect)(progress, this._context, params.expectation, params);
|
|
48
|
+
} finally {
|
|
49
|
+
this._context.pushHistory({ type: "expect", description: params.expectation });
|
|
50
|
+
}
|
|
51
|
+
return { usage: this._usage };
|
|
52
|
+
}
|
|
53
|
+
async extract(params, progress) {
|
|
54
|
+
const result = await (0, import_pageAgent.pageAgentExtract)(progress, this._context, params.query, params.schema, params);
|
|
55
|
+
return { result, usage: this._usage };
|
|
56
|
+
}
|
|
57
|
+
async usage(params, progress) {
|
|
58
|
+
return { usage: this._usage };
|
|
59
|
+
}
|
|
60
|
+
async dispose(params, progress) {
|
|
61
|
+
progress.metadata.potentiallyClosesScope = true;
|
|
62
|
+
void this.stopPendingOperations(new Error("The agent is disposed"));
|
|
63
|
+
this._dispose();
|
|
64
|
+
}
|
|
65
|
+
_eventSupport() {
|
|
66
|
+
const self = this;
|
|
67
|
+
return {
|
|
68
|
+
onBeforeTurn(params) {
|
|
69
|
+
const userMessage = params.conversation.messages.find((m) => m.role === "user");
|
|
70
|
+
self._dispatchEvent("turn", { role: "user", message: userMessage?.content ?? "" });
|
|
71
|
+
},
|
|
72
|
+
onAfterTurn(params) {
|
|
73
|
+
const usage = { inputTokens: params.totalUsage.input, outputTokens: params.totalUsage.output };
|
|
74
|
+
const intent = params.assistantMessage.content.filter((c) => c.type === "text").map((c) => c.text).join("\n");
|
|
75
|
+
self._dispatchEvent("turn", { role: "assistant", message: intent, usage });
|
|
76
|
+
if (!params.assistantMessage.content.filter((c) => c.type === "tool_call").length)
|
|
77
|
+
self._dispatchEvent("turn", { role: "assistant", message: `no tool calls`, usage });
|
|
78
|
+
self._usage = { turns: self._usage.turns + 1, inputTokens: self._usage.inputTokens + usage.inputTokens, outputTokens: self._usage.outputTokens + usage.outputTokens };
|
|
79
|
+
},
|
|
80
|
+
onBeforeToolCall(params) {
|
|
81
|
+
self._dispatchEvent("turn", { role: "assistant", message: `call tool "${params.toolCall.name}"` });
|
|
82
|
+
},
|
|
83
|
+
onAfterToolCall(params) {
|
|
84
|
+
const suffix = params.toolCall.result?.isError ? "failed" : "succeeded";
|
|
85
|
+
self._dispatchEvent("turn", { role: "user", message: `tool "${params.toolCall.name}" ${suffix}` });
|
|
86
|
+
},
|
|
87
|
+
onToolCallError(params) {
|
|
88
|
+
self._dispatchEvent("turn", { role: "user", message: `tool "${params.toolCall.name}" failed: ${params.error.message}` });
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
94
|
+
0 && (module.exports = {
|
|
95
|
+
PageAgentDispatcher
|
|
96
|
+
});
|
|
@@ -36,6 +36,7 @@ var import_networkDispatchers3 = require("./networkDispatchers");
|
|
|
36
36
|
var import_webSocketRouteDispatcher = require("./webSocketRouteDispatcher");
|
|
37
37
|
var import_instrumentation = require("../instrumentation");
|
|
38
38
|
var import_urlMatch = require("../../utils/isomorphic/urlMatch");
|
|
39
|
+
var import_pageAgentDispatcher = require("./pageAgentDispatcher");
|
|
39
40
|
class PageDispatcher extends import_dispatcher.Dispatcher {
|
|
40
41
|
constructor(parentScope, page) {
|
|
41
42
|
const mainFrame = import_frameDispatcher.FrameDispatcher.from(parentScope, page.mainFrame());
|
|
@@ -288,6 +289,9 @@ class PageDispatcher extends import_dispatcher.Dispatcher {
|
|
|
288
289
|
const coverage = this._page.coverage;
|
|
289
290
|
return await coverage.stopCSSCoverage();
|
|
290
291
|
}
|
|
292
|
+
async agent(params, progress) {
|
|
293
|
+
return { agent: new import_pageAgentDispatcher.PageAgentDispatcher(this, params) };
|
|
294
|
+
}
|
|
291
295
|
_onFrameAttached(frame) {
|
|
292
296
|
this._dispatchEvent("frameAttached", { frame: import_frameDispatcher.FrameDispatcher.from(this.parentScope(), frame) });
|
|
293
297
|
}
|
package/lib/server/dom.js
CHANGED
|
@@ -255,6 +255,7 @@ class ElementHandle extends js.JSHandle {
|
|
|
255
255
|
async _retryAction(progress, actionName, action, options) {
|
|
256
256
|
let retry = 0;
|
|
257
257
|
const waitTime = [0, 20, 100, 100, 500];
|
|
258
|
+
const noAutoWaiting = options.__testHookNoAutoWaiting ?? options.noAutoWaiting;
|
|
258
259
|
while (true) {
|
|
259
260
|
if (retry) {
|
|
260
261
|
progress.log(`retrying ${actionName} action${options.trial ? " (trial run)" : ""}`);
|
|
@@ -268,35 +269,43 @@ class ElementHandle extends js.JSHandle {
|
|
|
268
269
|
} else {
|
|
269
270
|
progress.log(`attempting ${actionName} action${options.trial ? " (trial run)" : ""}`);
|
|
270
271
|
}
|
|
271
|
-
if (!options.skipActionPreChecks && !options.force)
|
|
272
|
+
if (!options.skipActionPreChecks && !options.force && !noAutoWaiting)
|
|
272
273
|
await this._frame._page.performActionPreChecks(progress);
|
|
273
274
|
const result = await action(retry);
|
|
274
275
|
++retry;
|
|
275
276
|
if (result === "error:notvisible") {
|
|
276
|
-
if (options.force)
|
|
277
|
+
if (options.force || noAutoWaiting)
|
|
277
278
|
throw new NonRecoverableDOMError("Element is not visible");
|
|
278
279
|
progress.log(" element is not visible");
|
|
279
280
|
continue;
|
|
280
281
|
}
|
|
281
282
|
if (result === "error:notinviewport") {
|
|
282
|
-
if (options.force)
|
|
283
|
+
if (options.force || noAutoWaiting)
|
|
283
284
|
throw new NonRecoverableDOMError("Element is outside of the viewport");
|
|
284
285
|
progress.log(" element is outside of the viewport");
|
|
285
286
|
continue;
|
|
286
287
|
}
|
|
287
288
|
if (result === "error:optionsnotfound") {
|
|
289
|
+
if (noAutoWaiting)
|
|
290
|
+
throw new NonRecoverableDOMError("Did not find some options");
|
|
288
291
|
progress.log(" did not find some options");
|
|
289
292
|
continue;
|
|
290
293
|
}
|
|
291
294
|
if (result === "error:optionnotenabled") {
|
|
295
|
+
if (noAutoWaiting)
|
|
296
|
+
throw new NonRecoverableDOMError("Option being selected is not enabled");
|
|
292
297
|
progress.log(" option being selected is not enabled");
|
|
293
298
|
continue;
|
|
294
299
|
}
|
|
295
300
|
if (typeof result === "object" && "hitTargetDescription" in result) {
|
|
301
|
+
if (noAutoWaiting)
|
|
302
|
+
throw new NonRecoverableDOMError(`${result.hitTargetDescription} intercepts pointer events`);
|
|
296
303
|
progress.log(` ${result.hitTargetDescription} intercepts pointer events`);
|
|
297
304
|
continue;
|
|
298
305
|
}
|
|
299
306
|
if (typeof result === "object" && "missingState" in result) {
|
|
307
|
+
if (noAutoWaiting)
|
|
308
|
+
throw new NonRecoverableDOMError(`Element is not ${result.missingState}`);
|
|
300
309
|
progress.log(` element is not ${result.missingState}`);
|
|
301
310
|
continue;
|
|
302
311
|
}
|
|
@@ -158,8 +158,8 @@ class Electron extends import_instrumentation.SdkObject {
|
|
|
158
158
|
let shell = false;
|
|
159
159
|
if (process.platform === "win32") {
|
|
160
160
|
shell = true;
|
|
161
|
-
command = `"${
|
|
162
|
-
electronArguments =
|
|
161
|
+
command = [command, ...electronArguments].map((arg) => `"${escapeDoubleQuotes(arg)}"`).join(" ");
|
|
162
|
+
electronArguments = [];
|
|
163
163
|
}
|
|
164
164
|
delete env.NODE_OPTIONS;
|
|
165
165
|
const { launchedProcess, gracefullyClose, kill } = await (0, import_processLauncher.launchProcess)({
|
|
@@ -263,6 +263,9 @@ async function waitForLine(progress, process2, regex) {
|
|
|
263
263
|
import_eventsHelper.eventsHelper.removeEventListeners(listeners);
|
|
264
264
|
}
|
|
265
265
|
}
|
|
266
|
+
function escapeDoubleQuotes(str) {
|
|
267
|
+
return str.replace(/"/g, '\\"');
|
|
268
|
+
}
|
|
266
269
|
// Annotate the CommonJS export names for ESM import in node:
|
|
267
270
|
0 && (module.exports = {
|
|
268
271
|
Electron,
|
|
@@ -54,7 +54,6 @@ class FFBrowser extends import_browser.Browser {
|
|
|
54
54
|
this.session.on("Browser.detachedFromTarget", this._onDetachedFromTarget.bind(this));
|
|
55
55
|
this.session.on("Browser.downloadCreated", this._onDownloadCreated.bind(this));
|
|
56
56
|
this.session.on("Browser.downloadFinished", this._onDownloadFinished.bind(this));
|
|
57
|
-
this.session.on("Browser.videoRecordingFinished", this._onVideoRecordingFinished.bind(this));
|
|
58
57
|
}
|
|
59
58
|
static async connect(parent, transport, options) {
|
|
60
59
|
const connection = new import_ffConnection.FFConnection(transport, options.protocolLogger, options.browserLogsCollector);
|
|
@@ -141,12 +140,9 @@ class FFBrowser extends import_browser.Browser {
|
|
|
141
140
|
const error = payload.canceled ? "canceled" : payload.error;
|
|
142
141
|
this._downloadFinished(payload.uuid, error);
|
|
143
142
|
}
|
|
144
|
-
_onVideoRecordingFinished(payload) {
|
|
145
|
-
this._takeVideo(payload.screencastId)?.reportFinished();
|
|
146
|
-
}
|
|
147
143
|
_onDisconnect() {
|
|
148
144
|
for (const video of this._idToVideo.values())
|
|
149
|
-
video.artifact.reportFinished(new import_errors.TargetClosedError());
|
|
145
|
+
video.artifact.reportFinished(new import_errors.TargetClosedError(this.closeReason()));
|
|
150
146
|
this._idToVideo.clear();
|
|
151
147
|
for (const ffPage of this._ffPages.values())
|
|
152
148
|
ffPage.didClose();
|
|
@@ -199,15 +195,13 @@ class FFBrowserContext extends import_browserContext.BrowserContext {
|
|
|
199
195
|
promises.push(this.doUpdateOffline());
|
|
200
196
|
promises.push(this.doUpdateDefaultEmulatedMedia());
|
|
201
197
|
if (this._options.recordVideo) {
|
|
202
|
-
promises.push(this.
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
browserContextId: this._browserContextId
|
|
210
|
-
});
|
|
198
|
+
promises.push(this._browser.session.send("Browser.setScreencastOptions", {
|
|
199
|
+
// validateBrowserContextOptions ensures correct video size.
|
|
200
|
+
options: {
|
|
201
|
+
...this._options.recordVideo.size,
|
|
202
|
+
quality: 90
|
|
203
|
+
},
|
|
204
|
+
browserContextId: this._browserContextId
|
|
211
205
|
}));
|
|
212
206
|
}
|
|
213
207
|
const proxy = this._options.proxyOverride || this._options.proxy;
|
|
@@ -379,12 +373,8 @@ class FFBrowserContext extends import_browserContext.BrowserContext {
|
|
|
379
373
|
}
|
|
380
374
|
async doClose(reason) {
|
|
381
375
|
if (!this._browserContextId) {
|
|
382
|
-
if (this._options.recordVideo)
|
|
383
|
-
await this.
|
|
384
|
-
options: void 0,
|
|
385
|
-
browserContextId: this._browserContextId
|
|
386
|
-
});
|
|
387
|
-
}
|
|
376
|
+
if (this._options.recordVideo)
|
|
377
|
+
await Promise.all(this._ffPages().map((ffPage) => ffPage._page.screencast.stopVideoRecording()));
|
|
388
378
|
await this._browser.close({ reason });
|
|
389
379
|
} else {
|
|
390
380
|
await this._browser.session.send("Browser.removeBrowserContext", { browserContextId: this._browserContextId });
|
|
@@ -90,11 +90,6 @@ class FFSession extends import_events.EventEmitter {
|
|
|
90
90
|
this._connection = connection;
|
|
91
91
|
this._sessionId = sessionId;
|
|
92
92
|
this._rawSend = rawSend;
|
|
93
|
-
this.on = super.on;
|
|
94
|
-
this.addListener = super.addListener;
|
|
95
|
-
this.off = super.removeListener;
|
|
96
|
-
this.removeListener = super.removeListener;
|
|
97
|
-
this.once = super.once;
|
|
98
93
|
}
|
|
99
94
|
markAsCrashed() {
|
|
100
95
|
this._crashed = true;
|
|
@@ -170,9 +170,9 @@ const causeToResourceType = {
|
|
|
170
170
|
TYPE_FONT: "font",
|
|
171
171
|
TYPE_MEDIA: "media",
|
|
172
172
|
TYPE_WEBSOCKET: "websocket",
|
|
173
|
-
TYPE_CSP_REPORT: "
|
|
173
|
+
TYPE_CSP_REPORT: "cspreport",
|
|
174
174
|
TYPE_XSLT: "other",
|
|
175
|
-
TYPE_BEACON: "
|
|
175
|
+
TYPE_BEACON: "beacon",
|
|
176
176
|
TYPE_FETCH: "fetch",
|
|
177
177
|
TYPE_IMAGESET: "image",
|
|
178
178
|
TYPE_WEB_MANIFEST: "manifest"
|
|
@@ -41,9 +41,9 @@ var import_ffConnection = require("./ffConnection");
|
|
|
41
41
|
var import_ffExecutionContext = require("./ffExecutionContext");
|
|
42
42
|
var import_ffInput = require("./ffInput");
|
|
43
43
|
var import_ffNetworkManager = require("./ffNetworkManager");
|
|
44
|
-
var import_debugLogger = require("../utils/debugLogger");
|
|
45
44
|
var import_stackTrace = require("../../utils/isomorphic/stackTrace");
|
|
46
45
|
var import_errors = require("../errors");
|
|
46
|
+
var import_debugLogger = require("../utils/debugLogger");
|
|
47
47
|
const UTILITY_WORLD_NAME = "__playwright_utility_world__";
|
|
48
48
|
class FFPage {
|
|
49
49
|
constructor(session, browserContext, opener) {
|
|
@@ -83,13 +83,16 @@ class FFPage {
|
|
|
83
83
|
import_eventsHelper.eventsHelper.addEventListener(this._session, "Page.workerDestroyed", this._onWorkerDestroyed.bind(this)),
|
|
84
84
|
import_eventsHelper.eventsHelper.addEventListener(this._session, "Page.dispatchMessageFromWorker", this._onDispatchMessageFromWorker.bind(this)),
|
|
85
85
|
import_eventsHelper.eventsHelper.addEventListener(this._session, "Page.crashed", this._onCrashed.bind(this)),
|
|
86
|
-
import_eventsHelper.eventsHelper.addEventListener(this._session, "Page.videoRecordingStarted", this._onVideoRecordingStarted.bind(this)),
|
|
87
86
|
import_eventsHelper.eventsHelper.addEventListener(this._session, "Page.webSocketCreated", this._onWebSocketCreated.bind(this)),
|
|
88
87
|
import_eventsHelper.eventsHelper.addEventListener(this._session, "Page.webSocketClosed", this._onWebSocketClosed.bind(this)),
|
|
89
88
|
import_eventsHelper.eventsHelper.addEventListener(this._session, "Page.webSocketFrameReceived", this._onWebSocketFrameReceived.bind(this)),
|
|
90
89
|
import_eventsHelper.eventsHelper.addEventListener(this._session, "Page.webSocketFrameSent", this._onWebSocketFrameSent.bind(this)),
|
|
91
90
|
import_eventsHelper.eventsHelper.addEventListener(this._session, "Page.screencastFrame", this._onScreencastFrame.bind(this))
|
|
92
91
|
];
|
|
92
|
+
const screencast = this._page.screencast;
|
|
93
|
+
const videoOptions = screencast.launchVideoRecorder();
|
|
94
|
+
if (videoOptions)
|
|
95
|
+
screencast.startVideoRecording(videoOptions).catch((e) => import_debugLogger.debugLogger.log("error", e));
|
|
93
96
|
this._session.once("Page.ready", () => {
|
|
94
97
|
if (this._reportedAsNew)
|
|
95
98
|
return;
|
|
@@ -272,11 +275,8 @@ class FFPage {
|
|
|
272
275
|
this._session.markAsCrashed();
|
|
273
276
|
this._page._didCrash();
|
|
274
277
|
}
|
|
275
|
-
_onVideoRecordingStarted(event) {
|
|
276
|
-
this._browserContext._browser._videoStarted(this._browserContext, event.screencastId, event.file, this._page.waitForInitializedOrError());
|
|
277
|
-
}
|
|
278
278
|
didClose() {
|
|
279
|
-
this._markAsError(new import_errors.TargetClosedError());
|
|
279
|
+
this._markAsError(new import_errors.TargetClosedError(this._page.closeReason()));
|
|
280
280
|
this._session.dispose();
|
|
281
281
|
import_eventsHelper.eventsHelper.removeEventListeners(this._eventListeners);
|
|
282
282
|
this._networkManager.dispose();
|
|
@@ -417,24 +417,21 @@ class FFPage {
|
|
|
417
417
|
throw e;
|
|
418
418
|
});
|
|
419
419
|
}
|
|
420
|
-
async
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
await this._session.send("Page.stopScreencast");
|
|
426
|
-
}
|
|
420
|
+
async startScreencast(options) {
|
|
421
|
+
await this._session.send("Page.startScreencast", options);
|
|
422
|
+
}
|
|
423
|
+
async stopScreencast() {
|
|
424
|
+
await this._session.sendMayFail("Page.stopScreencast");
|
|
427
425
|
}
|
|
428
426
|
_onScreencastFrame(event) {
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
const screencastId = this._screencastId;
|
|
432
|
-
this._page.throttleScreencastFrameAck(() => {
|
|
433
|
-
this._session.send("Page.screencastFrameAck", { screencastId }).catch((e) => import_debugLogger.debugLogger.log("error", e));
|
|
427
|
+
this._page.screencast.throttleFrameAck(() => {
|
|
428
|
+
this._session.sendMayFail("Page.screencastFrameAck");
|
|
434
429
|
});
|
|
435
430
|
const buffer = Buffer.from(event.data, "base64");
|
|
436
431
|
this._page.emit(import_page2.Page.Events.ScreencastFrame, {
|
|
437
432
|
buffer,
|
|
433
|
+
frameSwapWallTime: event.timestamp * 1e3,
|
|
434
|
+
// timestamp is in seconds, we need to convert to milliseconds.
|
|
438
435
|
width: event.deviceWidth,
|
|
439
436
|
height: event.deviceHeight
|
|
440
437
|
});
|
|
@@ -56,15 +56,13 @@ class Firefox extends import_browserType.BrowserType {
|
|
|
56
56
|
connectToTransport(transport, options) {
|
|
57
57
|
return import_ffBrowser.FFBrowser.connect(this.attribution.playwright, transport, options);
|
|
58
58
|
}
|
|
59
|
-
doRewriteStartupLog(
|
|
60
|
-
if (
|
|
61
|
-
|
|
62
|
-
if (error.logs.includes(`as root in a regular user's session is not supported.`))
|
|
63
|
-
error.logs = "\n" + (0, import_ascii.wrapInASCIIBox)(`Firefox is unable to launch if the $HOME folder isn't owned by the current user.
|
|
59
|
+
doRewriteStartupLog(logs) {
|
|
60
|
+
if (logs.includes(`as root in a regular user's session is not supported.`))
|
|
61
|
+
logs = "\n" + (0, import_ascii.wrapInASCIIBox)(`Firefox is unable to launch if the $HOME folder isn't owned by the current user.
|
|
64
62
|
Workaround: Set the HOME=/root environment variable${process.env.GITHUB_ACTION ? " in your GitHub Actions workflow file" : ""} when running Playwright.`, 1);
|
|
65
|
-
if (
|
|
66
|
-
|
|
67
|
-
return
|
|
63
|
+
if (logs.includes("no DISPLAY environment variable specified"))
|
|
64
|
+
logs = "\n" + (0, import_ascii.wrapInASCIIBox)(import_browserType.kNoXServerRunningError, 1);
|
|
65
|
+
return logs;
|
|
68
66
|
}
|
|
69
67
|
amendEnvironment(env) {
|
|
70
68
|
if (!import_path.default.isAbsolute(import_os.default.homedir()))
|
|
@@ -50,7 +50,9 @@ class FrameSelectors {
|
|
|
50
50
|
if (!resolved)
|
|
51
51
|
throw new Error(`Failed to find frame for selector "${selector}"`);
|
|
52
52
|
return await resolved.injected.evaluateHandle((injected, { info, scope: scope2 }) => {
|
|
53
|
-
|
|
53
|
+
const elements = injected.querySelectorAll(info.parsed, scope2 || document);
|
|
54
|
+
injected.checkDeprecatedSelectorUsage(info.parsed, elements);
|
|
55
|
+
return elements;
|
|
54
56
|
}, { info: resolved.info, scope: resolved.scope });
|
|
55
57
|
}
|
|
56
58
|
async queryCount(selector, options) {
|
|
@@ -59,7 +61,9 @@ class FrameSelectors {
|
|
|
59
61
|
throw new Error(`Failed to find frame for selector "${selector}"`);
|
|
60
62
|
await options.__testHookBeforeQuery?.();
|
|
61
63
|
return await resolved.injected.evaluate((injected, { info }) => {
|
|
62
|
-
|
|
64
|
+
const elements = injected.querySelectorAll(info.parsed, document);
|
|
65
|
+
injected.checkDeprecatedSelectorUsage(info.parsed, elements);
|
|
66
|
+
return elements.length;
|
|
63
67
|
}, { info: resolved.info });
|
|
64
68
|
}
|
|
65
69
|
async queryAll(selector, scope) {
|
|
@@ -67,7 +71,9 @@ class FrameSelectors {
|
|
|
67
71
|
if (!resolved)
|
|
68
72
|
return [];
|
|
69
73
|
const arrayHandle = await resolved.injected.evaluateHandle((injected, { info, scope: scope2 }) => {
|
|
70
|
-
|
|
74
|
+
const elements = injected.querySelectorAll(info.parsed, scope2 || document);
|
|
75
|
+
injected.checkDeprecatedSelectorUsage(info.parsed, elements);
|
|
76
|
+
return elements;
|
|
71
77
|
}, { info: resolved.info, scope: resolved.scope });
|
|
72
78
|
const properties = await arrayHandle.getProperties();
|
|
73
79
|
arrayHandle.dispose();
|
package/lib/server/frames.js
CHANGED
|
@@ -350,6 +350,11 @@ class FrameManager {
|
|
|
350
350
|
frame.emit(Frame.Events.InternalNavigation, event);
|
|
351
351
|
}
|
|
352
352
|
}
|
|
353
|
+
const FrameEvent = {
|
|
354
|
+
InternalNavigation: "internalnavigation",
|
|
355
|
+
AddLifecycle: "addlifecycle",
|
|
356
|
+
RemoveLifecycle: "removelifecycle"
|
|
357
|
+
};
|
|
353
358
|
class Frame extends import_instrumentation.SdkObject {
|
|
354
359
|
constructor(page, id, parentFrame) {
|
|
355
360
|
super(page, "frame");
|
|
@@ -382,11 +387,7 @@ class Frame extends import_instrumentation.SdkObject {
|
|
|
382
387
|
this._startNetworkIdleTimer();
|
|
383
388
|
}
|
|
384
389
|
static {
|
|
385
|
-
this.Events =
|
|
386
|
-
InternalNavigation: "internalnavigation",
|
|
387
|
-
AddLifecycle: "addlifecycle",
|
|
388
|
-
RemoveLifecycle: "removelifecycle"
|
|
389
|
-
};
|
|
390
|
+
this.Events = FrameEvent;
|
|
390
391
|
}
|
|
391
392
|
isDetached() {
|
|
392
393
|
return this._detachedScope.isClosed();
|
|
@@ -569,7 +570,7 @@ class Frame extends import_instrumentation.SdkObject {
|
|
|
569
570
|
const request = navigationEvent.newDocument ? navigationEvent.newDocument.request : void 0;
|
|
570
571
|
return request ? progress.race(request._finalRequest().response()) : null;
|
|
571
572
|
}
|
|
572
|
-
async
|
|
573
|
+
async waitForLoadState(progress, state) {
|
|
573
574
|
const waitUntil = verifyLifecycle("state", state);
|
|
574
575
|
if (!this._firedLifecycleEvents.has(waitUntil))
|
|
575
576
|
await import_helper.helper.waitForEvent(progress, this, Frame.Events.AddLifecycle, (e) => e === waitUntil).promise;
|
|
@@ -640,6 +641,7 @@ class Frame extends import_instrumentation.SdkObject {
|
|
|
640
641
|
} else if (element2) {
|
|
641
642
|
log2 = ` locator resolved to ${visible2 ? "visible" : "hidden"} ${injected.previewNode(element2)}`;
|
|
642
643
|
}
|
|
644
|
+
injected.checkDeprecatedSelectorUsage(info.parsed, elements);
|
|
643
645
|
return { log: log2, element: element2, visible: visible2, attached: !!element2 };
|
|
644
646
|
}, { info: resolved.info, root: resolved.frame === this ? scope : void 0 }));
|
|
645
647
|
const { log, visible, attached } = await progress.race(result.evaluate((r) => ({ log: r.log, visible: r.visible, attached: r.attached })));
|
|
@@ -735,7 +737,7 @@ class Frame extends import_instrumentation.SdkObject {
|
|
|
735
737
|
this._onClearLifecycle();
|
|
736
738
|
tagPromise.resolve();
|
|
737
739
|
});
|
|
738
|
-
const lifecyclePromise = progress.race(tagPromise).then(() => this.
|
|
740
|
+
const lifecyclePromise = progress.race(tagPromise).then(() => this.waitForLoadState(progress, waitUntil));
|
|
739
741
|
const contentPromise = progress.race(context.evaluate(({ html: html2, tag: tag2 }) => {
|
|
740
742
|
document.open();
|
|
741
743
|
console.debug(tag2);
|
|
@@ -905,14 +907,19 @@ class Frame extends import_instrumentation.SdkObject {
|
|
|
905
907
|
return true;
|
|
906
908
|
return false;
|
|
907
909
|
}
|
|
908
|
-
async _retryWithProgressIfNotConnected(progress, selector,
|
|
910
|
+
async _retryWithProgressIfNotConnected(progress, selector, options, action) {
|
|
909
911
|
progress.log(`waiting for ${this._asLocator(selector)}`);
|
|
912
|
+
const noAutoWaiting = options.__testHookNoAutoWaiting ?? options.noAutoWaiting;
|
|
913
|
+
const performActionPreChecks = (options.performActionPreChecks ?? !options.force) && !noAutoWaiting;
|
|
910
914
|
return this.retryWithProgressAndTimeouts(progress, [0, 20, 50, 100, 100, 500], async (continuePolling) => {
|
|
911
915
|
if (performActionPreChecks)
|
|
912
916
|
await this._page.performActionPreChecks(progress);
|
|
913
|
-
const resolved = await progress.race(this.selectors.resolveInjectedForSelector(selector, { strict }));
|
|
914
|
-
if (!resolved)
|
|
917
|
+
const resolved = await progress.race(this.selectors.resolveInjectedForSelector(selector, { strict: options.strict }));
|
|
918
|
+
if (!resolved) {
|
|
919
|
+
if (noAutoWaiting)
|
|
920
|
+
throw new dom.NonRecoverableDOMError("Element(s) not found");
|
|
915
921
|
return continuePolling;
|
|
922
|
+
}
|
|
916
923
|
const result = await progress.race(resolved.injected.evaluateHandle((injected, { info, callId }) => {
|
|
917
924
|
const elements = injected.querySelectorAll(info.parsed, document);
|
|
918
925
|
if (callId)
|
|
@@ -926,12 +933,15 @@ class Frame extends import_instrumentation.SdkObject {
|
|
|
926
933
|
} else if (element2) {
|
|
927
934
|
log2 = ` locator resolved to ${injected.previewNode(element2)}`;
|
|
928
935
|
}
|
|
936
|
+
injected.checkDeprecatedSelectorUsage(info.parsed, elements);
|
|
929
937
|
return { log: log2, success: !!element2, element: element2 };
|
|
930
938
|
}, { info: resolved.info, callId: progress.metadata.id }));
|
|
931
939
|
const { log, success } = await progress.race(result.evaluate((r) => ({ log: r.log, success: r.success })));
|
|
932
940
|
if (log)
|
|
933
941
|
progress.log(log);
|
|
934
942
|
if (!success) {
|
|
943
|
+
if (noAutoWaiting)
|
|
944
|
+
throw new dom.NonRecoverableDOMError("Element(s) not found");
|
|
935
945
|
result.dispose();
|
|
936
946
|
return continuePolling;
|
|
937
947
|
}
|
|
@@ -940,6 +950,8 @@ class Frame extends import_instrumentation.SdkObject {
|
|
|
940
950
|
try {
|
|
941
951
|
const result2 = await action(element);
|
|
942
952
|
if (result2 === "error:notconnected") {
|
|
953
|
+
if (noAutoWaiting)
|
|
954
|
+
throw new dom.NonRecoverableDOMError("Element is not attached to the DOM");
|
|
943
955
|
progress.log("element was detached from the DOM, retrying");
|
|
944
956
|
return continuePolling;
|
|
945
957
|
}
|
|
@@ -950,19 +962,19 @@ class Frame extends import_instrumentation.SdkObject {
|
|
|
950
962
|
});
|
|
951
963
|
}
|
|
952
964
|
async rafrafTimeoutScreenshotElementWithProgress(progress, selector, timeout, options) {
|
|
953
|
-
return await this._retryWithProgressIfNotConnected(progress, selector, true, true, async (handle) => {
|
|
965
|
+
return await this._retryWithProgressIfNotConnected(progress, selector, { strict: true, performActionPreChecks: true }, async (handle) => {
|
|
954
966
|
await handle._frame.rafrafTimeout(progress, timeout);
|
|
955
967
|
return await this._page.screenshotter.screenshotElement(progress, handle, options);
|
|
956
968
|
});
|
|
957
969
|
}
|
|
958
970
|
async click(progress, selector, options) {
|
|
959
|
-
return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options
|
|
971
|
+
return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options, (handle) => handle._click(progress, { ...options, waitAfter: !options.noWaitAfter })));
|
|
960
972
|
}
|
|
961
973
|
async dblclick(progress, selector, options) {
|
|
962
|
-
return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options
|
|
974
|
+
return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options, (handle) => handle._dblclick(progress, options)));
|
|
963
975
|
}
|
|
964
976
|
async dragAndDrop(progress, source, target, options) {
|
|
965
|
-
dom.assertDone(await this._retryWithProgressIfNotConnected(progress, source, options
|
|
977
|
+
dom.assertDone(await this._retryWithProgressIfNotConnected(progress, source, options, async (handle) => {
|
|
966
978
|
return handle._retryPointerAction(progress, "move and down", false, async (point) => {
|
|
967
979
|
await this._page.mouse.move(progress, point.x, point.y);
|
|
968
980
|
await this._page.mouse.down(progress);
|
|
@@ -972,7 +984,7 @@ class Frame extends import_instrumentation.SdkObject {
|
|
|
972
984
|
position: options.sourcePosition
|
|
973
985
|
});
|
|
974
986
|
}));
|
|
975
|
-
dom.assertDone(await this._retryWithProgressIfNotConnected(progress, target, options
|
|
987
|
+
dom.assertDone(await this._retryWithProgressIfNotConnected(progress, target, { ...options, performActionPreChecks: false }, async (handle) => {
|
|
976
988
|
return handle._retryPointerAction(progress, "move and up", false, async (point) => {
|
|
977
989
|
await this._page.mouse.move(progress, point.x, point.y, { steps: options.steps });
|
|
978
990
|
await this._page.mouse.up(progress);
|
|
@@ -986,16 +998,16 @@ class Frame extends import_instrumentation.SdkObject {
|
|
|
986
998
|
async tap(progress, selector, options) {
|
|
987
999
|
if (!this._page.browserContext._options.hasTouch)
|
|
988
1000
|
throw new Error("The page does not support tap. Use hasTouch context option to enable touch support.");
|
|
989
|
-
return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options
|
|
1001
|
+
return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options, (handle) => handle._tap(progress, options)));
|
|
990
1002
|
}
|
|
991
1003
|
async fill(progress, selector, value, options) {
|
|
992
|
-
return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options
|
|
1004
|
+
return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options, (handle) => handle._fill(progress, value, options)));
|
|
993
1005
|
}
|
|
994
1006
|
async focus(progress, selector, options) {
|
|
995
|
-
dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options
|
|
1007
|
+
dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options, (handle) => handle._focus(progress)));
|
|
996
1008
|
}
|
|
997
1009
|
async blur(progress, selector, options) {
|
|
998
|
-
dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options
|
|
1010
|
+
dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options, (handle) => handle._blur(progress)));
|
|
999
1011
|
}
|
|
1000
1012
|
async resolveSelector(progress, selector, options = {}) {
|
|
1001
1013
|
const element = await progress.race(this.selectors.query(selector, options));
|
|
@@ -1109,35 +1121,35 @@ class Frame extends import_instrumentation.SdkObject {
|
|
|
1109
1121
|
return this._elementState(progress, selector, "checked", options, scope);
|
|
1110
1122
|
}
|
|
1111
1123
|
async hover(progress, selector, options) {
|
|
1112
|
-
return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options
|
|
1124
|
+
return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options, (handle) => handle._hover(progress, options)));
|
|
1113
1125
|
}
|
|
1114
1126
|
async selectOption(progress, selector, elements, values, options) {
|
|
1115
|
-
return await this._retryWithProgressIfNotConnected(progress, selector, options
|
|
1127
|
+
return await this._retryWithProgressIfNotConnected(progress, selector, options, (handle) => handle._selectOption(progress, elements, values, options));
|
|
1116
1128
|
}
|
|
1117
1129
|
async setInputFiles(progress, selector, params) {
|
|
1118
1130
|
const inputFileItems = await (0, import_fileUploadUtils.prepareFilesForUpload)(this, params);
|
|
1119
|
-
return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, params
|
|
1131
|
+
return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, params, (handle) => handle._setInputFiles(progress, inputFileItems)));
|
|
1120
1132
|
}
|
|
1121
1133
|
async type(progress, selector, text, options) {
|
|
1122
|
-
return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options
|
|
1134
|
+
return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options, (handle) => handle._type(progress, text, options)));
|
|
1123
1135
|
}
|
|
1124
1136
|
async press(progress, selector, key, options) {
|
|
1125
|
-
return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options
|
|
1137
|
+
return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options, (handle) => handle._press(progress, key, options)));
|
|
1126
1138
|
}
|
|
1127
1139
|
async check(progress, selector, options) {
|
|
1128
|
-
return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options
|
|
1140
|
+
return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options, (handle) => handle._setChecked(progress, true, options)));
|
|
1129
1141
|
}
|
|
1130
1142
|
async uncheck(progress, selector, options) {
|
|
1131
|
-
return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options
|
|
1143
|
+
return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options, (handle) => handle._setChecked(progress, false, options)));
|
|
1132
1144
|
}
|
|
1133
1145
|
async waitForTimeout(progress, timeout) {
|
|
1134
1146
|
return progress.wait(timeout);
|
|
1135
1147
|
}
|
|
1136
1148
|
async ariaSnapshot(progress, selector) {
|
|
1137
|
-
return await this._retryWithProgressIfNotConnected(progress, selector, true, true, (handle) => progress.race(handle.ariaSnapshot()));
|
|
1149
|
+
return await this._retryWithProgressIfNotConnected(progress, selector, { strict: true, performActionPreChecks: true }, (handle) => progress.race(handle.ariaSnapshot()));
|
|
1138
1150
|
}
|
|
1139
|
-
async expect(progress, selector, options
|
|
1140
|
-
progress.log(`${(0, import_utils.renderTitleForCall)(progress.metadata)}${
|
|
1151
|
+
async expect(progress, selector, options) {
|
|
1152
|
+
progress.log(`${(0, import_utils.renderTitleForCall)(progress.metadata)}${options.timeoutForLogs ? ` with timeout ${options.timeoutForLogs}ms` : ""}`);
|
|
1141
1153
|
const lastIntermediateResult = { isSet: false };
|
|
1142
1154
|
const fixupMetadataError = (result) => {
|
|
1143
1155
|
if (result.matches === options.isNot)
|
|
@@ -1146,17 +1158,19 @@ class Frame extends import_instrumentation.SdkObject {
|
|
|
1146
1158
|
try {
|
|
1147
1159
|
if (selector)
|
|
1148
1160
|
progress.log(`waiting for ${this._asLocator(selector)}`);
|
|
1149
|
-
|
|
1161
|
+
if (!options.noAutoWaiting)
|
|
1162
|
+
await this._page.performActionPreChecks(progress);
|
|
1150
1163
|
try {
|
|
1151
1164
|
const resultOneShot = await this._expectInternal(progress, selector, options, lastIntermediateResult, true);
|
|
1152
|
-
if (resultOneShot.matches !== options.isNot)
|
|
1165
|
+
if (options.noAutoWaiting || resultOneShot.matches !== options.isNot)
|
|
1153
1166
|
return resultOneShot;
|
|
1154
1167
|
} catch (e) {
|
|
1155
|
-
if (this.isNonRetriableError(e))
|
|
1168
|
+
if (options.noAutoWaiting || this.isNonRetriableError(e))
|
|
1156
1169
|
throw e;
|
|
1157
1170
|
}
|
|
1158
1171
|
const result = await this.retryWithProgressAndTimeouts(progress, [100, 250, 500, 1e3], async (continuePolling) => {
|
|
1159
|
-
|
|
1172
|
+
if (!options.noAutoWaiting)
|
|
1173
|
+
await this._page.performActionPreChecks(progress);
|
|
1160
1174
|
const { matches, received } = await this._expectInternal(progress, selector, options, lastIntermediateResult, false);
|
|
1161
1175
|
if (matches === options.isNot) {
|
|
1162
1176
|
return continuePolling;
|
|
@@ -1200,6 +1214,8 @@ class Frame extends import_instrumentation.SdkObject {
|
|
|
1200
1214
|
throw injected2.strictModeViolationError(info2.parsed, elements);
|
|
1201
1215
|
else if (elements.length)
|
|
1202
1216
|
log2 = ` locator resolved to ${injected2.previewNode(elements[0])}`;
|
|
1217
|
+
if (info2)
|
|
1218
|
+
injected2.checkDeprecatedSelectorUsage(info2.parsed, elements);
|
|
1203
1219
|
return { log: log2, ...await injected2.expect(elements[0], options2, elements) };
|
|
1204
1220
|
}, { info, options, callId: progress.metadata.id }));
|
|
1205
1221
|
if (log)
|
|
@@ -33,6 +33,9 @@ class SdkObject extends import_events.EventEmitter {
|
|
|
33
33
|
this.attribution = { ...parent.attribution };
|
|
34
34
|
this.instrumentation = parent.instrumentation;
|
|
35
35
|
}
|
|
36
|
+
closeReason() {
|
|
37
|
+
return this.attribution.page?._closeReason || this.attribution.context?._closeReason || this.attribution.browser?._closeReason;
|
|
38
|
+
}
|
|
36
39
|
}
|
|
37
40
|
function createRootSdkObject() {
|
|
38
41
|
const fakeParent = { attribution: {}, instrumentation: createInstrumentation() };
|