patchright-core 1.51.3 → 1.52.1
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 +15 -13
- package/lib/androidServerImpl.js +42 -48
- package/lib/browserServerImpl.js +54 -67
- package/lib/cli/driver.js +71 -69
- package/lib/cli/program.js +312 -328
- package/lib/cli/programWithTestStub.js +51 -45
- package/lib/client/accessibility.js +31 -32
- package/lib/client/android.js +141 -228
- package/lib/client/api.js +135 -283
- package/lib/client/artifact.js +39 -36
- package/lib/client/browser.js +57 -61
- package/lib/client/browserContext.js +297 -326
- package/lib/client/browserType.js +92 -106
- package/lib/client/cdpSession.js +29 -31
- package/lib/client/channelOwner.js +82 -95
- package/lib/client/clientHelper.js +46 -38
- package/lib/client/clientInstrumentation.js +40 -37
- package/lib/client/clientStackTrace.js +41 -37
- package/lib/client/clock.js +36 -36
- package/lib/client/connection.js +190 -212
- package/lib/client/consoleMessage.js +31 -28
- package/lib/client/coverage.js +25 -22
- package/lib/client/dialog.js +30 -31
- package/lib/client/download.js +25 -25
- package/lib/client/electron.js +73 -75
- package/lib/client/elementHandle.js +111 -147
- package/lib/client/errors.js +53 -53
- package/lib/client/eventEmitter.js +124 -121
- package/lib/client/events.js +72 -68
- package/lib/client/fetch.js +135 -158
- package/lib/client/fileChooser.js +25 -24
- package/lib/client/fileUtils.js +31 -28
- package/lib/client/frame.js +187 -306
- package/lib/client/harRouter.js +42 -52
- package/lib/client/input.js +40 -69
- package/lib/client/jsHandle.js +56 -71
- package/lib/client/jsonPipe.js +27 -23
- package/lib/client/localUtils.js +29 -28
- package/lib/client/locator.js +161 -245
- package/lib/client/network.js +277 -295
- package/lib/client/page.js +270 -318
- package/lib/client/platform.js +46 -43
- package/lib/client/playwright.js +51 -66
- package/lib/client/selectors.js +48 -46
- package/lib/client/stream.js +29 -25
- package/lib/client/timeoutSettings.js +49 -39
- package/lib/client/tracing.js +48 -84
- package/lib/client/types.js +26 -22
- package/lib/client/video.js +35 -27
- package/lib/client/waiter.js +69 -88
- package/lib/client/webError.js +25 -23
- package/lib/client/webSocket.js +61 -56
- package/lib/client/worker.js +48 -58
- package/lib/client/writableStream.js +27 -23
- package/lib/generated/clockSource.js +26 -5
- package/lib/generated/consoleApiSource.js +26 -5
- package/lib/generated/injectedScriptSource.js +26 -5
- package/lib/generated/pollingRecorderSource.js +26 -5
- package/lib/generated/utilityScriptSource.js +26 -5
- package/lib/generated/webSocketMockSource.js +371 -4
- package/lib/inProcessFactory.js +53 -53
- package/lib/inprocess.js +2 -19
- package/lib/outofprocess.js +53 -46
- package/lib/protocol/debug.js +209 -25
- package/lib/protocol/serializers.js +153 -134
- package/lib/protocol/validator.js +2714 -2714
- package/lib/protocol/validatorPrimitives.js +114 -73
- package/lib/remote/playwrightConnection.js +140 -157
- package/lib/remote/playwrightServer.js +99 -84
- package/lib/server/accessibility.js +44 -37
- package/lib/server/android/android.js +216 -209
- package/lib/server/android/backendAdb.js +89 -82
- package/lib/server/artifact.js +78 -55
- package/lib/server/bidi/bidiBrowser.js +221 -155
- package/lib/server/bidi/bidiChromium.js +106 -79
- package/lib/server/bidi/bidiConnection.js +66 -83
- package/lib/server/bidi/bidiExecutionContext.js +128 -113
- package/lib/server/bidi/bidiFirefox.js +76 -69
- package/lib/server/bidi/bidiInput.js +86 -97
- package/lib/server/bidi/bidiNetworkManager.js +137 -154
- package/lib/server/bidi/bidiOverCdp.js +57 -58
- package/lib/server/bidi/bidiPage.js +247 -219
- package/lib/server/bidi/bidiPdf.js +52 -86
- package/lib/server/bidi/third_party/bidiCommands.d.js +22 -0
- package/lib/server/bidi/third_party/bidiDeserializer.js +55 -50
- package/lib/server/bidi/third_party/bidiKeyboard.js +236 -220
- package/lib/server/bidi/third_party/bidiProtocol.js +144 -131
- package/lib/server/bidi/third_party/bidiSerializer.js +67 -63
- package/lib/server/bidi/third_party/firefoxPrefs.js +141 -119
- package/lib/server/browser.js +76 -84
- package/lib/server/browserContext.js +321 -346
- package/lib/server/browserType.js +169 -182
- package/lib/server/callLog.js +47 -44
- package/lib/server/chromium/chromium.js +212 -190
- package/lib/server/chromium/chromiumSwitches.js +86 -64
- package/lib/server/chromium/crAccessibility.js +157 -131
- package/lib/server/chromium/crBrowser.js +253 -273
- package/lib/server/chromium/crConnection.js +91 -116
- package/lib/server/chromium/crCoverage.js +113 -127
- package/lib/server/chromium/crDevTools.js +59 -51
- package/lib/server/chromium/crDragDrop.js +62 -79
- package/lib/server/chromium/crExecutionContext.js +88 -83
- package/lib/server/chromium/crInput.js +97 -95
- package/lib/server/chromium/crNetworkManager.js +284 -404
- package/lib/server/chromium/crPage.js +522 -608
- package/lib/server/chromium/crPdf.js +54 -86
- package/lib/server/chromium/crProtocolHelper.js +92 -80
- package/lib/server/chromium/crServiceWorker.js +82 -67
- package/lib/server/chromium/defaultFontFamilies.js +152 -135
- package/lib/server/chromium/protocol.d.js +16 -0
- package/lib/server/chromium/videoRecorder.js +65 -99
- package/lib/server/clock.js +62 -50
- package/lib/server/codegen/csharp.js +185 -160
- package/lib/server/codegen/java.js +155 -128
- package/lib/server/codegen/javascript.js +163 -148
- package/lib/server/codegen/jsonl.js +32 -28
- package/lib/server/codegen/language.js +75 -52
- package/lib/server/codegen/languages.js +65 -27
- package/lib/server/codegen/python.js +140 -125
- package/lib/server/codegen/types.js +15 -4
- package/lib/server/console.js +28 -32
- package/lib/server/cookieStore.js +105 -86
- package/lib/server/debugController.js +97 -124
- package/lib/server/debugger.js +82 -78
- package/lib/server/deviceDescriptors.js +37 -24
- package/lib/server/deviceDescriptorsSource.json +50 -50
- package/lib/server/dialog.js +36 -35
- package/lib/server/dispatchers/androidDispatcher.js +196 -107
- package/lib/server/dispatchers/artifactDispatcher.js +62 -62
- package/lib/server/dispatchers/browserContextDispatcher.js +176 -205
- package/lib/server/dispatchers/browserDispatcher.js +78 -97
- package/lib/server/dispatchers/browserTypeDispatcher.js +35 -35
- package/lib/server/dispatchers/cdpSessionDispatcher.js +32 -36
- package/lib/server/dispatchers/debugControllerDispatcher.js +48 -66
- package/lib/server/dispatchers/dialogDispatcher.js +30 -27
- package/lib/server/dispatchers/dispatcher.js +169 -220
- package/lib/server/dispatchers/electronDispatcher.js +54 -57
- package/lib/server/dispatchers/elementHandlerDispatcher.js +77 -119
- package/lib/server/dispatchers/frameDispatcher.js +99 -163
- package/lib/server/dispatchers/jsHandleDispatcher.js +49 -66
- package/lib/server/dispatchers/jsonPipeDispatcher.js +35 -36
- package/lib/server/dispatchers/localUtilsDispatcher.js +95 -80
- package/lib/server/dispatchers/networkDispatchers.js +90 -107
- package/lib/server/dispatchers/pageDispatcher.js +128 -169
- package/lib/server/dispatchers/playwrightDispatcher.js +69 -76
- package/lib/server/dispatchers/selectorsDispatcher.js +28 -24
- package/lib/server/dispatchers/streamDispatcher.js +42 -45
- package/lib/server/dispatchers/tracingDispatcher.js +36 -41
- package/lib/server/dispatchers/webSocketRouteDispatcher.js +96 -131
- package/lib/server/dispatchers/writableStreamDispatcher.js +54 -38
- package/lib/server/dom.js +413 -443
- package/lib/server/download.js +45 -35
- package/lib/server/electron/electron.js +156 -176
- package/lib/server/electron/loader.js +8 -36
- package/lib/server/errors.js +47 -46
- package/lib/server/fetch.js +289 -323
- package/lib/server/fileChooser.js +25 -24
- package/lib/server/fileUploadUtils.js +65 -59
- package/lib/server/firefox/ffAccessibility.js +153 -131
- package/lib/server/firefox/ffBrowser.js +213 -277
- package/lib/server/firefox/ffConnection.js +63 -84
- package/lib/server/firefox/ffExecutionContext.js +91 -73
- package/lib/server/firefox/ffInput.js +67 -69
- package/lib/server/firefox/ffNetworkManager.js +131 -110
- package/lib/server/firefox/ffPage.js +236 -273
- package/lib/server/firefox/firefox.js +76 -67
- package/lib/server/firefox/protocol.d.js +16 -0
- package/lib/server/formData.js +107 -35
- package/lib/server/frameSelectors.js +221 -112
- package/lib/server/frames.js +731 -894
- package/lib/server/har/harRecorder.js +85 -77
- package/lib/server/har/harTracer.js +287 -222
- package/lib/server/harBackend.js +80 -80
- package/lib/server/helper.js +56 -59
- package/lib/server/index.js +59 -99
- package/lib/server/input.js +134 -163
- package/lib/server/instrumentation.js +49 -44
- package/lib/server/javascript.js +143 -134
- package/lib/server/launchApp.js +92 -73
- package/lib/server/localUtils.js +130 -122
- package/lib/server/macEditingCommands.js +141 -137
- package/lib/server/network.js +262 -296
- package/lib/server/page.js +326 -423
- package/lib/server/pageBinding.js +88 -0
- package/lib/server/pipeTransport.js +49 -45
- package/lib/server/playwright.js +60 -67
- package/lib/server/progress.js +56 -51
- package/lib/server/protocolError.js +34 -31
- package/lib/server/recorder/chat.js +70 -86
- package/lib/server/recorder/contextRecorder.js +134 -138
- package/lib/server/recorder/recorderApp.js +127 -136
- package/lib/server/recorder/recorderCollection.js +56 -44
- package/lib/server/recorder/recorderFrontend.js +15 -4
- package/lib/server/recorder/recorderRunner.js +79 -103
- package/lib/server/recorder/recorderUtils.js +56 -45
- package/lib/server/recorder/throttledFile.js +42 -30
- package/lib/server/recorder.js +177 -186
- package/lib/server/registry/browserFetcher.js +106 -101
- package/lib/server/registry/dependencies.js +245 -196
- package/lib/server/registry/index.js +904 -792
- package/lib/server/registry/nativeDeps.js +1073 -464
- package/lib/server/registry/oopDownloadBrowserMain.js +57 -75
- package/lib/server/screenshotter.js +166 -182
- package/lib/server/selectors.js +85 -46
- package/lib/server/socksClientCertificatesInterceptor.js +166 -185
- package/lib/server/socksInterceptor.js +62 -70
- package/lib/server/storageScript.js +94 -100
- package/lib/server/timeoutSettings.js +58 -43
- package/lib/server/trace/recorder/snapshotter.js +70 -89
- package/lib/server/trace/recorder/snapshotterInjected.js +238 -217
- package/lib/server/trace/recorder/tracing.js +321 -333
- package/lib/server/trace/test/inMemorySnapshotter.js +46 -52
- package/lib/server/trace/viewer/traceViewer.js +168 -146
- package/lib/server/transport.js +124 -133
- package/lib/server/types.js +26 -22
- package/lib/server/usKeyboardLayout.js +135 -545
- package/lib/server/utils/ascii.js +39 -26
- package/lib/server/utils/comparators.js +105 -103
- package/lib/server/utils/crypto.js +157 -112
- package/lib/server/utils/debug.js +37 -28
- package/lib/server/utils/debugLogger.js +69 -48
- package/lib/server/utils/env.js +52 -37
- package/lib/server/utils/eventsHelper.js +29 -28
- package/lib/server/utils/expectUtils.js +31 -26
- package/lib/server/utils/fileUtils.js +123 -136
- package/lib/server/utils/happyEyeballs.js +138 -123
- package/lib/server/utils/hostPlatform.js +84 -120
- package/lib/server/utils/httpServer.js +106 -121
- package/lib/server/utils/image_tools/colorUtils.js +42 -51
- package/lib/server/utils/image_tools/compare.js +44 -43
- package/lib/server/utils/image_tools/imageChannel.js +38 -30
- package/lib/server/utils/image_tools/stats.js +40 -40
- package/lib/server/utils/linuxUtils.js +50 -37
- package/lib/server/utils/network.js +143 -86
- package/lib/server/utils/nodePlatform.js +87 -79
- package/lib/server/utils/pipeTransport.js +44 -42
- package/lib/server/utils/processLauncher.js +111 -121
- package/lib/server/utils/profiler.js +52 -39
- package/lib/server/utils/socksProxy.js +280 -339
- package/lib/server/utils/spawnAsync.js +37 -41
- package/lib/server/utils/task.js +31 -38
- package/lib/server/utils/userAgent.js +73 -66
- package/lib/server/utils/wsServer.js +73 -69
- package/lib/server/utils/zipFile.js +36 -37
- package/lib/server/utils/zones.js +37 -34
- package/lib/server/webkit/protocol.d.js +16 -0
- package/lib/server/webkit/webkit.js +76 -63
- package/lib/server/webkit/wkAccessibility.js +161 -118
- package/lib/server/webkit/wkBrowser.js +159 -176
- package/lib/server/webkit/wkConnection.js +59 -83
- package/lib/server/webkit/wkExecutionContext.js +84 -70
- package/lib/server/webkit/wkInput.js +82 -80
- package/lib/server/webkit/wkInterceptableRequest.js +102 -95
- package/lib/server/webkit/wkPage.js +525 -619
- package/lib/server/webkit/wkProvisionalPage.js +45 -56
- package/lib/server/webkit/wkWorkers.js +77 -77
- package/lib/utils/isomorphic/ariaSnapshot.js +144 -152
- package/lib/utils/isomorphic/assert.js +28 -22
- package/lib/utils/isomorphic/builtins.js +86 -0
- package/lib/utils/isomorphic/colors.js +66 -59
- package/lib/utils/isomorphic/cssParser.js +121 -125
- package/lib/utils/isomorphic/cssTokenizer.js +436 -364
- package/lib/utils/isomorphic/headers.js +38 -37
- package/lib/utils/isomorphic/locatorGenerators.js +340 -357
- package/lib/utils/isomorphic/locatorParser.js +96 -105
- package/lib/utils/isomorphic/locatorUtils.js +63 -44
- package/lib/utils/isomorphic/manualPromise.js +47 -39
- package/lib/utils/isomorphic/mimeType.js +448 -25
- package/lib/utils/isomorphic/multimap.js +35 -27
- package/lib/utils/isomorphic/rtti.js +35 -33
- package/lib/utils/isomorphic/selectorParser.js +183 -193
- package/lib/utils/isomorphic/semaphore.js +27 -24
- package/lib/utils/isomorphic/stackTrace.js +87 -98
- package/lib/utils/isomorphic/stringUtils.js +113 -106
- package/lib/utils/isomorphic/time.js +41 -22
- package/lib/utils/isomorphic/timeoutRunner.js +55 -54
- package/lib/utils/isomorphic/traceUtils.js +38 -41
- package/lib/utils/isomorphic/types.js +15 -4
- package/lib/utils/isomorphic/urlMatch.js +112 -67
- package/lib/utils/isomorphic/utilityScriptSerializers.js +248 -0
- package/lib/utils.js +97 -443
- package/lib/utilsBundle.js +101 -52
- package/lib/vite/htmlReport/index.html +21 -15
- package/lib/vite/recorder/assets/{codeMirrorModule-B9YMkrwa.js → codeMirrorModule-CXVeovup.js} +1 -1
- package/lib/vite/recorder/assets/index-BsWQsSGl.js +184 -0
- package/lib/vite/recorder/index.html +1 -1
- package/lib/vite/traceViewer/assets/{codeMirrorModule-1DiydmYA.js → codeMirrorModule-_GLjJL-7.js} +1 -1
- package/lib/vite/traceViewer/assets/defaultSettingsView-DtCQiGHe.js +265 -0
- package/lib/vite/traceViewer/{defaultSettingsView.5fN5lw10.css → defaultSettingsView.QdHITyLI.css} +1 -1
- package/lib/vite/traceViewer/index.cFZzK9RN.js +2 -0
- package/lib/vite/traceViewer/index.html +3 -3
- package/lib/vite/traceViewer/sw.bundle.js +3 -3
- package/lib/vite/traceViewer/uiMode.XVPIqBeS.js +5 -0
- package/lib/vite/traceViewer/uiMode.html +3 -3
- package/lib/zipBundle.js +32 -23
- package/package.json +1 -1
- package/types/protocol.d.ts +436 -17
- package/types/types.d.ts +35 -16
- package/lib/server/isomorphic/utilityScriptSerializers.js +0 -229
- package/lib/vite/recorder/assets/index-ELPgmkwA.js +0 -184
- package/lib/vite/traceViewer/assets/defaultSettingsView-l0TyP_G8.js +0 -259
- package/lib/vite/traceViewer/index.BqUZLSro.js +0 -2
- package/lib/vite/traceViewer/uiMode.C1d2m5sF.js +0 -5
package/lib/server/dom.js
CHANGED
|
@@ -1,83 +1,84 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty
|
|
4
|
-
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
var dom_exports = {};
|
|
30
|
+
__export(dom_exports, {
|
|
31
|
+
ElementHandle: () => ElementHandle,
|
|
32
|
+
FrameExecutionContext: () => FrameExecutionContext,
|
|
33
|
+
NonRecoverableDOMError: () => NonRecoverableDOMError,
|
|
34
|
+
assertDone: () => assertDone,
|
|
35
|
+
isNonRecoverableDOMError: () => isNonRecoverableDOMError,
|
|
36
|
+
kUnableToAdoptErrorMessage: () => kUnableToAdoptErrorMessage,
|
|
37
|
+
throwElementIsNotAttached: () => throwElementIsNotAttached,
|
|
38
|
+
throwRetargetableDOMError: () => throwRetargetableDOMError
|
|
5
39
|
});
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
var
|
|
13
|
-
var
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
var _fileUploadUtils = require("./fileUploadUtils");
|
|
17
|
-
var _protocolError = require("./protocolError");
|
|
18
|
-
var injectedScriptSource = _interopRequireWildcard(require("../generated/injectedScriptSource"));
|
|
19
|
-
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
|
20
|
-
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
|
21
|
-
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
22
|
-
/**
|
|
23
|
-
* Copyright (c) Microsoft Corporation.
|
|
24
|
-
*
|
|
25
|
-
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
26
|
-
* you may not use this file except in compliance with the License.
|
|
27
|
-
* You may obtain a copy of the License at
|
|
28
|
-
*
|
|
29
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
|
30
|
-
*
|
|
31
|
-
* Unless required by applicable law or agreed to in writing, software
|
|
32
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
33
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
34
|
-
* See the License for the specific language governing permissions and
|
|
35
|
-
* limitations under the License.
|
|
36
|
-
*/
|
|
37
|
-
|
|
38
|
-
class NonRecoverableDOMError extends Error {}
|
|
39
|
-
exports.NonRecoverableDOMError = NonRecoverableDOMError;
|
|
40
|
+
module.exports = __toCommonJS(dom_exports);
|
|
41
|
+
var import_fs = __toESM(require("fs"));
|
|
42
|
+
var js = __toESM(require("./javascript"));
|
|
43
|
+
var import_progress = require("./progress");
|
|
44
|
+
var import_utils = require("../utils");
|
|
45
|
+
var import_fileUploadUtils = require("./fileUploadUtils");
|
|
46
|
+
var import_protocolError = require("./protocolError");
|
|
47
|
+
var injectedScriptSource = __toESM(require("../generated/injectedScriptSource"));
|
|
48
|
+
class NonRecoverableDOMError extends Error {
|
|
49
|
+
}
|
|
40
50
|
function isNonRecoverableDOMError(error) {
|
|
41
51
|
return error instanceof NonRecoverableDOMError;
|
|
42
52
|
}
|
|
43
53
|
class FrameExecutionContext extends js.ExecutionContext {
|
|
44
54
|
constructor(delegate, frame, world) {
|
|
45
|
-
super(frame, delegate, world ||
|
|
46
|
-
this.frame = void 0;
|
|
47
|
-
this._injectedScriptPromise = void 0;
|
|
48
|
-
this.world = void 0;
|
|
55
|
+
super(frame, delegate, world || "content-script");
|
|
49
56
|
this.frame = frame;
|
|
50
57
|
this.world = world;
|
|
51
58
|
}
|
|
52
59
|
adoptIfNeeded(handle) {
|
|
53
|
-
if (handle instanceof ElementHandle && handle._context !== this)
|
|
60
|
+
if (handle instanceof ElementHandle && handle._context !== this)
|
|
61
|
+
return this.frame._page._delegate.adoptElementHandle(handle, this);
|
|
54
62
|
return null;
|
|
55
63
|
}
|
|
56
64
|
async evaluate(pageFunction, arg) {
|
|
57
|
-
return js.evaluate(this, true
|
|
65
|
+
return js.evaluate(this, true, pageFunction, arg);
|
|
58
66
|
}
|
|
59
67
|
async evaluateHandle(pageFunction, arg) {
|
|
60
|
-
return js.evaluate(this, false
|
|
68
|
+
return js.evaluate(this, false, pageFunction, arg);
|
|
61
69
|
}
|
|
62
70
|
async evaluateExpression(expression, options, arg) {
|
|
63
|
-
return js.evaluateExpression(this, expression, {
|
|
64
|
-
...options,
|
|
65
|
-
returnByValue: true
|
|
66
|
-
}, arg);
|
|
71
|
+
return js.evaluateExpression(this, expression, { ...options, returnByValue: true }, arg);
|
|
67
72
|
}
|
|
68
73
|
async evaluateExpressionHandle(expression, options, arg) {
|
|
69
|
-
return js.evaluateExpression(this, expression, {
|
|
70
|
-
...options,
|
|
71
|
-
returnByValue: false
|
|
72
|
-
}, arg);
|
|
74
|
+
return js.evaluateExpression(this, expression, { ...options, returnByValue: false }, arg);
|
|
73
75
|
}
|
|
74
76
|
injectedScript() {
|
|
75
77
|
if (!this._injectedScriptPromise) {
|
|
76
78
|
const custom = [];
|
|
77
79
|
const selectorsRegistry = this.frame._page.context().selectors();
|
|
78
|
-
for (const [name, {
|
|
79
|
-
|
|
80
|
-
}] of selectorsRegistry._engines) custom.push(`{ name: '${name}', engine: (${source}) }`);
|
|
80
|
+
for (const [name, { source: source2 }] of selectorsRegistry._engines)
|
|
81
|
+
custom.push(`{ name: '${name}', engine: (${source2}) }`);
|
|
81
82
|
const sdkLanguage = this.frame.attribution.playwright.options.sdkLanguage;
|
|
82
83
|
const source = `
|
|
83
84
|
(() => {
|
|
@@ -85,37 +86,36 @@ class FrameExecutionContext extends js.ExecutionContext {
|
|
|
85
86
|
${injectedScriptSource.source}
|
|
86
87
|
return new (module.exports.InjectedScript())(
|
|
87
88
|
globalThis,
|
|
88
|
-
${(0,
|
|
89
|
+
${(0, import_utils.isUnderTest)()},
|
|
89
90
|
"${sdkLanguage}",
|
|
90
91
|
${JSON.stringify(selectorsRegistry.testIdAttributeName())},
|
|
91
92
|
${this.frame._page._delegate.rafCountForStablePosition()},
|
|
92
93
|
"${this.frame._page._browserContext._browser.options.name}",
|
|
93
|
-
|
|
94
|
+
${process.env.PLAYWRIGHT_INPUT_FILE_TEXTBOX ? "true" : "false"},
|
|
95
|
+
[${custom.join(",\n")}]
|
|
94
96
|
);
|
|
95
97
|
})();
|
|
96
98
|
`;
|
|
97
|
-
this._injectedScriptPromise = this.rawEvaluateHandle(source).then(handle => {
|
|
98
|
-
handle._setPreview(
|
|
99
|
+
this._injectedScriptPromise = this.rawEvaluateHandle(source).then((handle) => {
|
|
100
|
+
handle._setPreview("InjectedScript");
|
|
99
101
|
return handle;
|
|
100
102
|
});
|
|
101
103
|
}
|
|
102
104
|
return this._injectedScriptPromise;
|
|
103
105
|
}
|
|
104
106
|
}
|
|
105
|
-
exports.FrameExecutionContext = FrameExecutionContext;
|
|
106
107
|
class ElementHandle extends js.JSHandle {
|
|
107
108
|
constructor(context, objectId) {
|
|
108
|
-
super(context,
|
|
109
|
+
super(context, "node", void 0, objectId);
|
|
109
110
|
this.__elementhandle = true;
|
|
110
|
-
this._page = void 0;
|
|
111
|
-
this._frame = void 0;
|
|
112
111
|
this._page = context.frame._page;
|
|
113
112
|
this._frame = context.frame;
|
|
114
|
-
this._initializePreview().catch(e => {
|
|
113
|
+
this._initializePreview().catch((e) => {
|
|
114
|
+
});
|
|
115
115
|
}
|
|
116
116
|
async _initializePreview() {
|
|
117
117
|
const utility = await this._context.injectedScript();
|
|
118
|
-
this._setPreview(await utility.evaluate((injected, e) =>
|
|
118
|
+
this._setPreview(await utility.evaluate((injected, e) => "JSHandle@" + injected.previewNode(e), this));
|
|
119
119
|
}
|
|
120
120
|
asElement() {
|
|
121
121
|
return this;
|
|
@@ -125,8 +125,9 @@ class ElementHandle extends js.JSHandle {
|
|
|
125
125
|
const utility = await this._frame._utilityContext();
|
|
126
126
|
return await utility.evaluate(pageFunction, [await utility.injectedScript(), this, arg]);
|
|
127
127
|
} catch (e) {
|
|
128
|
-
if (js.isJavaScriptErrorInEvaluate(e) || (0,
|
|
129
|
-
|
|
128
|
+
if (js.isJavaScriptErrorInEvaluate(e) || (0, import_protocolError.isSessionClosedError)(e))
|
|
129
|
+
throw e;
|
|
130
|
+
return "error:notconnected";
|
|
130
131
|
}
|
|
131
132
|
}
|
|
132
133
|
async evaluateHandleInUtility(pageFunction, arg) {
|
|
@@ -134,86 +135,94 @@ class ElementHandle extends js.JSHandle {
|
|
|
134
135
|
const utility = await this._frame._utilityContext();
|
|
135
136
|
return await utility.evaluateHandle(pageFunction, [await utility.injectedScript(), this, arg]);
|
|
136
137
|
} catch (e) {
|
|
137
|
-
if (js.isJavaScriptErrorInEvaluate(e) || (0,
|
|
138
|
-
|
|
138
|
+
if (js.isJavaScriptErrorInEvaluate(e) || (0, import_protocolError.isSessionClosedError)(e))
|
|
139
|
+
throw e;
|
|
140
|
+
return "error:notconnected";
|
|
139
141
|
}
|
|
140
142
|
}
|
|
141
143
|
async ownerFrame() {
|
|
142
144
|
const frameId = await this._page._delegate.getOwnerFrame(this);
|
|
143
|
-
if (!frameId)
|
|
145
|
+
if (!frameId)
|
|
146
|
+
return null;
|
|
144
147
|
const frame = this._page._frameManager.frame(frameId);
|
|
145
|
-
if (frame)
|
|
148
|
+
if (frame)
|
|
149
|
+
return frame;
|
|
146
150
|
for (const page of this._page._browserContext.pages()) {
|
|
147
|
-
const
|
|
148
|
-
if (
|
|
151
|
+
const frame2 = page._frameManager.frame(frameId);
|
|
152
|
+
if (frame2)
|
|
153
|
+
return frame2;
|
|
149
154
|
}
|
|
150
155
|
return null;
|
|
151
156
|
}
|
|
152
157
|
async isIframeElement() {
|
|
153
|
-
return this.evaluateInUtility(([injected, node]) => node && (node.nodeName ===
|
|
158
|
+
return this.evaluateInUtility(([injected, node]) => node && (node.nodeName === "IFRAME" || node.nodeName === "FRAME"), {});
|
|
154
159
|
}
|
|
155
160
|
async contentFrame() {
|
|
156
161
|
const isFrameElement = throwRetargetableDOMError(await this.isIframeElement());
|
|
157
|
-
if (!isFrameElement)
|
|
162
|
+
if (!isFrameElement)
|
|
163
|
+
return null;
|
|
158
164
|
return this._page._delegate.getContentFrame(this);
|
|
159
165
|
}
|
|
160
166
|
async generateLocatorString() {
|
|
161
167
|
const selector = await this.evaluateInUtility(async ([injected, node]) => {
|
|
162
168
|
return injected.generateSelectorSimple(node);
|
|
163
169
|
}, {});
|
|
164
|
-
if (selector ===
|
|
165
|
-
|
|
170
|
+
if (selector === "error:notconnected")
|
|
171
|
+
return;
|
|
172
|
+
return (0, import_utils.asLocator)("javascript", selector);
|
|
166
173
|
}
|
|
167
174
|
async getAttribute(metadata, name) {
|
|
168
|
-
return this._frame.getAttribute(metadata,
|
|
175
|
+
return this._frame.getAttribute(metadata, ":scope", name, {}, this);
|
|
169
176
|
}
|
|
170
177
|
async inputValue(metadata) {
|
|
171
|
-
return this._frame.inputValue(metadata,
|
|
178
|
+
return this._frame.inputValue(metadata, ":scope", {}, this);
|
|
172
179
|
}
|
|
173
180
|
async textContent(metadata) {
|
|
174
|
-
return this._frame.textContent(metadata,
|
|
181
|
+
return this._frame.textContent(metadata, ":scope", {}, this);
|
|
175
182
|
}
|
|
176
183
|
async innerText(metadata) {
|
|
177
|
-
return this._frame.innerText(metadata,
|
|
184
|
+
return this._frame.innerText(metadata, ":scope", {}, this);
|
|
178
185
|
}
|
|
179
186
|
async innerHTML(metadata) {
|
|
180
|
-
return this._frame.innerHTML(metadata,
|
|
187
|
+
return this._frame.innerHTML(metadata, ":scope", {}, this);
|
|
181
188
|
}
|
|
182
189
|
async dispatchEvent(metadata, type, eventInit = {}) {
|
|
183
|
-
return this._frame.dispatchEvent(metadata,
|
|
190
|
+
return this._frame.dispatchEvent(metadata, ":scope", type, eventInit, {}, this);
|
|
184
191
|
}
|
|
185
192
|
async _scrollRectIntoViewIfNeeded(rect) {
|
|
186
193
|
return await this._page._delegate.scrollRectIntoViewIfNeeded(this, rect);
|
|
187
194
|
}
|
|
188
195
|
async _waitAndScrollIntoViewIfNeeded(progress, waitForVisible) {
|
|
189
|
-
const result = await this._retryAction(progress,
|
|
196
|
+
const result = await this._retryAction(progress, "scroll into view", async () => {
|
|
190
197
|
progress.log(` waiting for element to be stable`);
|
|
191
|
-
const waitResult = await this.evaluateInUtility(async ([injected, node, {
|
|
192
|
-
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
waitForVisible
|
|
197
|
-
});
|
|
198
|
-
if (waitResult) return waitResult;
|
|
198
|
+
const waitResult = await this.evaluateInUtility(async ([injected, node, { waitForVisible: waitForVisible2 }]) => {
|
|
199
|
+
return await injected.checkElementStates(node, waitForVisible2 ? ["visible", "stable"] : ["stable"]);
|
|
200
|
+
}, { waitForVisible });
|
|
201
|
+
if (waitResult)
|
|
202
|
+
return waitResult;
|
|
199
203
|
return await this._scrollRectIntoViewIfNeeded();
|
|
200
204
|
}, {});
|
|
201
205
|
assertDone(throwRetargetableDOMError(result));
|
|
202
206
|
}
|
|
203
207
|
async scrollIntoViewIfNeeded(metadata, options = {}) {
|
|
204
|
-
const controller = new
|
|
205
|
-
return controller.run(
|
|
208
|
+
const controller = new import_progress.ProgressController(metadata, this);
|
|
209
|
+
return controller.run(
|
|
210
|
+
(progress) => this._waitAndScrollIntoViewIfNeeded(
|
|
211
|
+
progress,
|
|
212
|
+
false
|
|
213
|
+
/* waitForVisible */
|
|
214
|
+
),
|
|
215
|
+
this._page._timeoutSettings.timeout(options)
|
|
216
|
+
);
|
|
206
217
|
}
|
|
207
218
|
async _clickablePoint() {
|
|
208
|
-
const intersectQuadWithViewport = quad => {
|
|
209
|
-
return quad.map(point => ({
|
|
219
|
+
const intersectQuadWithViewport = (quad) => {
|
|
220
|
+
return quad.map((point) => ({
|
|
210
221
|
x: Math.min(Math.max(point.x, 0), metrics.width),
|
|
211
222
|
y: Math.min(Math.max(point.y, 0), metrics.height)
|
|
212
223
|
}));
|
|
213
224
|
};
|
|
214
|
-
const computeQuadArea = quad => {
|
|
215
|
-
// Compute sum of all directed areas of adjacent triangles
|
|
216
|
-
// https://en.wikipedia.org/wiki/Polygon#Simple_polygons
|
|
225
|
+
const computeQuadArea = (quad) => {
|
|
217
226
|
let area = 0;
|
|
218
227
|
for (let i = 0; i < quad.length; ++i) {
|
|
219
228
|
const p1 = quad[i];
|
|
@@ -222,37 +231,36 @@ class ElementHandle extends js.JSHandle {
|
|
|
222
231
|
}
|
|
223
232
|
return Math.abs(area);
|
|
224
233
|
};
|
|
225
|
-
const [quads, metrics] = await Promise.all([
|
|
226
|
-
|
|
227
|
-
height: innerHeight
|
|
228
|
-
|
|
229
|
-
if (quads ===
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
const filtered = quads.map(quad => intersectQuadWithViewport(quad)).filter(quad => computeQuadArea(quad) > 0.99);
|
|
234
|
-
if (!filtered.length)
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
//
|
|
238
|
-
// This does not work nicely for small elements. For example, 1x1 square with corners
|
|
239
|
-
// (8;8) and (9;9) is targeted when clicking at (8;8) but not when clicking at (9;9).
|
|
240
|
-
// So, clicking at (8.x;8.y) will sometimes click at (9;9) and miss the target.
|
|
241
|
-
//
|
|
242
|
-
// Therefore, we try to find an integer point within a quad to make sure we click inside the element.
|
|
234
|
+
const [quads, metrics] = await Promise.all([
|
|
235
|
+
this._page._delegate.getContentQuads(this),
|
|
236
|
+
this._page.mainFrame()._utilityContext().then((utility) => utility.evaluate(() => ({ width: innerWidth, height: innerHeight })))
|
|
237
|
+
]);
|
|
238
|
+
if (quads === "error:notconnected")
|
|
239
|
+
return quads;
|
|
240
|
+
if (!quads || !quads.length)
|
|
241
|
+
return "error:notvisible";
|
|
242
|
+
const filtered = quads.map((quad) => intersectQuadWithViewport(quad)).filter((quad) => computeQuadArea(quad) > 0.99);
|
|
243
|
+
if (!filtered.length)
|
|
244
|
+
return "error:notinviewport";
|
|
245
|
+
if (this._page._browserContext._browser.options.name === "firefox") {
|
|
243
246
|
for (const quad of filtered) {
|
|
244
247
|
const integerPoint = findIntegerPointInsideQuad(quad);
|
|
245
|
-
if (integerPoint)
|
|
248
|
+
if (integerPoint)
|
|
249
|
+
return integerPoint;
|
|
246
250
|
}
|
|
247
251
|
}
|
|
248
|
-
// Return the middle point of the first quad.
|
|
249
252
|
return quadMiddlePoint(filtered[0]);
|
|
250
253
|
}
|
|
251
254
|
async _offsetPoint(offset) {
|
|
252
|
-
const [box, border] = await Promise.all([
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
255
|
+
const [box, border] = await Promise.all([
|
|
256
|
+
this.boundingBox(),
|
|
257
|
+
this.evaluateInUtility(([injected, node]) => injected.getElementBorderWidth(node), {}).catch((e) => {
|
|
258
|
+
})
|
|
259
|
+
]);
|
|
260
|
+
if (!box || !border)
|
|
261
|
+
return "error:notvisible";
|
|
262
|
+
if (border === "error:notconnected")
|
|
263
|
+
return border;
|
|
256
264
|
return {
|
|
257
265
|
x: box.x + border.left + offset.x,
|
|
258
266
|
y: box.y + border.top + offset.y
|
|
@@ -260,122 +268,105 @@ class ElementHandle extends js.JSHandle {
|
|
|
260
268
|
}
|
|
261
269
|
async _retryAction(progress, actionName, action, options) {
|
|
262
270
|
let retry = 0;
|
|
263
|
-
// We progressively wait longer between retries, up to 500ms.
|
|
264
271
|
const waitTime = [0, 20, 100, 100, 500];
|
|
265
272
|
while (progress.isRunning()) {
|
|
266
273
|
if (retry) {
|
|
267
|
-
progress.log(`retrying ${actionName} action${options.trial ?
|
|
274
|
+
progress.log(`retrying ${actionName} action${options.trial ? " (trial run)" : ""}`);
|
|
268
275
|
const timeout = waitTime[Math.min(retry - 1, waitTime.length - 1)];
|
|
269
276
|
if (timeout) {
|
|
270
277
|
progress.log(` waiting ${timeout}ms`);
|
|
271
|
-
const
|
|
272
|
-
if (
|
|
278
|
+
const result2 = await this.evaluateInUtility(([injected, node, timeout2]) => new Promise((f) => setTimeout(f, timeout2)), timeout);
|
|
279
|
+
if (result2 === "error:notconnected")
|
|
280
|
+
return result2;
|
|
273
281
|
}
|
|
274
282
|
} else {
|
|
275
|
-
progress.log(`attempting ${actionName} action${options.trial ?
|
|
283
|
+
progress.log(`attempting ${actionName} action${options.trial ? " (trial run)" : ""}`);
|
|
276
284
|
}
|
|
277
|
-
if (!options.skipActionPreChecks && !options.force)
|
|
285
|
+
if (!options.skipActionPreChecks && !options.force)
|
|
286
|
+
await this._frame._page.performActionPreChecks(progress);
|
|
278
287
|
const result = await action(retry);
|
|
279
288
|
++retry;
|
|
280
|
-
if (result ===
|
|
281
|
-
if (options.force)
|
|
282
|
-
|
|
289
|
+
if (result === "error:notvisible") {
|
|
290
|
+
if (options.force)
|
|
291
|
+
throw new NonRecoverableDOMError("Element is not visible");
|
|
292
|
+
progress.log(" element is not visible");
|
|
283
293
|
continue;
|
|
284
294
|
}
|
|
285
|
-
if (result ===
|
|
286
|
-
if (options.force)
|
|
287
|
-
|
|
295
|
+
if (result === "error:notinviewport") {
|
|
296
|
+
if (options.force)
|
|
297
|
+
throw new NonRecoverableDOMError("Element is outside of the viewport");
|
|
298
|
+
progress.log(" element is outside of the viewport");
|
|
288
299
|
continue;
|
|
289
300
|
}
|
|
290
|
-
if (result ===
|
|
291
|
-
progress.log(
|
|
301
|
+
if (result === "error:optionsnotfound") {
|
|
302
|
+
progress.log(" did not find some options");
|
|
292
303
|
continue;
|
|
293
304
|
}
|
|
294
|
-
if (typeof result ===
|
|
305
|
+
if (typeof result === "object" && "hitTargetDescription" in result) {
|
|
295
306
|
progress.log(` ${result.hitTargetDescription} intercepts pointer events`);
|
|
296
307
|
continue;
|
|
297
308
|
}
|
|
298
|
-
if (typeof result ===
|
|
309
|
+
if (typeof result === "object" && "missingState" in result) {
|
|
299
310
|
progress.log(` element is not ${result.missingState}`);
|
|
300
311
|
continue;
|
|
301
312
|
}
|
|
302
313
|
return result;
|
|
303
314
|
}
|
|
304
|
-
return
|
|
315
|
+
return "done";
|
|
305
316
|
}
|
|
306
317
|
async _retryPointerAction(progress, actionName, waitForEnabled, action, options) {
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
block: 'end',
|
|
316
|
-
inline: 'end'
|
|
317
|
-
}, {
|
|
318
|
-
block: 'center',
|
|
319
|
-
inline: 'center'
|
|
320
|
-
}, {
|
|
321
|
-
block: 'start',
|
|
322
|
-
inline: 'start'
|
|
323
|
-
}];
|
|
318
|
+
const skipActionPreChecks = actionName === "move and up";
|
|
319
|
+
return await this._retryAction(progress, actionName, async (retry) => {
|
|
320
|
+
const scrollOptions = [
|
|
321
|
+
void 0,
|
|
322
|
+
{ block: "end", inline: "end" },
|
|
323
|
+
{ block: "center", inline: "center" },
|
|
324
|
+
{ block: "start", inline: "start" }
|
|
325
|
+
];
|
|
324
326
|
const forceScrollOptions = scrollOptions[retry % scrollOptions.length];
|
|
325
327
|
return await this._performPointerAction(progress, actionName, waitForEnabled, action, forceScrollOptions, options);
|
|
326
|
-
}, {
|
|
327
|
-
...options,
|
|
328
|
-
skipActionPreChecks
|
|
329
|
-
});
|
|
328
|
+
}, { ...options, skipActionPreChecks });
|
|
330
329
|
}
|
|
331
330
|
async _performPointerAction(progress, actionName, waitForEnabled, action, forceScrollOptions, options) {
|
|
332
|
-
const {
|
|
333
|
-
force = false,
|
|
334
|
-
position
|
|
335
|
-
} = options;
|
|
331
|
+
const { force = false, position } = options;
|
|
336
332
|
const doScrollIntoView = async () => {
|
|
337
333
|
if (forceScrollOptions) {
|
|
338
|
-
return await this.evaluateInUtility(([injected, node,
|
|
339
|
-
if (node.nodeType === 1
|
|
340
|
-
|
|
334
|
+
return await this.evaluateInUtility(([injected, node, options2]) => {
|
|
335
|
+
if (node.nodeType === 1)
|
|
336
|
+
node.scrollIntoView(options2);
|
|
337
|
+
return "done";
|
|
341
338
|
}, forceScrollOptions);
|
|
342
339
|
}
|
|
343
|
-
return await this._scrollRectIntoViewIfNeeded(position ? {
|
|
344
|
-
x: position.x,
|
|
345
|
-
y: position.y,
|
|
346
|
-
width: 0,
|
|
347
|
-
height: 0
|
|
348
|
-
} : undefined);
|
|
340
|
+
return await this._scrollRectIntoViewIfNeeded(position ? { x: position.x, y: position.y, width: 0, height: 0 } : void 0);
|
|
349
341
|
};
|
|
350
342
|
if (this._frame.parentFrame()) {
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
progress.throwIfAborted(); // Avoid action that has side-effects.
|
|
355
|
-
await doScrollIntoView().catch(() => {});
|
|
343
|
+
progress.throwIfAborted();
|
|
344
|
+
await doScrollIntoView().catch(() => {
|
|
345
|
+
});
|
|
356
346
|
}
|
|
357
|
-
if (options.__testHookBeforeStable)
|
|
347
|
+
if (options.__testHookBeforeStable)
|
|
348
|
+
await options.__testHookBeforeStable();
|
|
358
349
|
if (!force) {
|
|
359
|
-
const elementStates = waitForEnabled ? [
|
|
360
|
-
progress.log(` waiting for element to be ${waitForEnabled ?
|
|
361
|
-
const result = await this.evaluateInUtility(async ([injected, node, {
|
|
362
|
-
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
});
|
|
368
|
-
if (result) return result;
|
|
369
|
-
progress.log(` element is ${waitForEnabled ? 'visible, enabled and stable' : 'visible and stable'}`);
|
|
350
|
+
const elementStates = waitForEnabled ? ["visible", "enabled", "stable"] : ["visible", "stable"];
|
|
351
|
+
progress.log(` waiting for element to be ${waitForEnabled ? "visible, enabled and stable" : "visible and stable"}`);
|
|
352
|
+
const result = await this.evaluateInUtility(async ([injected, node, { elementStates: elementStates2 }]) => {
|
|
353
|
+
return await injected.checkElementStates(node, elementStates2);
|
|
354
|
+
}, { elementStates });
|
|
355
|
+
if (result)
|
|
356
|
+
return result;
|
|
357
|
+
progress.log(` element is ${waitForEnabled ? "visible, enabled and stable" : "visible and stable"}`);
|
|
370
358
|
}
|
|
371
|
-
if (options.__testHookAfterStable)
|
|
372
|
-
|
|
373
|
-
progress.
|
|
359
|
+
if (options.__testHookAfterStable)
|
|
360
|
+
await options.__testHookAfterStable();
|
|
361
|
+
progress.log(" scrolling into view if needed");
|
|
362
|
+
progress.throwIfAborted();
|
|
374
363
|
const scrolled = await doScrollIntoView();
|
|
375
|
-
if (scrolled !==
|
|
376
|
-
|
|
364
|
+
if (scrolled !== "done")
|
|
365
|
+
return scrolled;
|
|
366
|
+
progress.log(" done scrolling");
|
|
377
367
|
const maybePoint = position ? await this._offsetPoint(position) : await this._clickablePoint();
|
|
378
|
-
if (typeof maybePoint ===
|
|
368
|
+
if (typeof maybePoint === "string")
|
|
369
|
+
return maybePoint;
|
|
379
370
|
const point = roundPoint(maybePoint);
|
|
380
371
|
progress.metadata.point = point;
|
|
381
372
|
await this.instrumentation.onBeforeInputAction(this, progress.metadata);
|
|
@@ -383,132 +374,118 @@ class ElementHandle extends js.JSHandle {
|
|
|
383
374
|
if (force) {
|
|
384
375
|
progress.log(` forcing action`);
|
|
385
376
|
} else {
|
|
386
|
-
if (options.__testHookBeforeHitTarget)
|
|
377
|
+
if (options.__testHookBeforeHitTarget)
|
|
378
|
+
await options.__testHookBeforeHitTarget();
|
|
387
379
|
const frameCheckResult = await this._checkFrameIsHitTarget(point);
|
|
388
|
-
if (frameCheckResult ===
|
|
380
|
+
if (frameCheckResult === "error:notconnected" || "hitTargetDescription" in frameCheckResult)
|
|
381
|
+
return frameCheckResult;
|
|
389
382
|
const hitPoint = frameCheckResult.framePoint;
|
|
390
|
-
const actionType = actionName ===
|
|
391
|
-
const handle = await this.evaluateHandleInUtility(([injected, node, {
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
trial
|
|
395
|
-
}]) => injected.setupHitTargetInterceptor(node, actionType, hitPoint, trial), {
|
|
396
|
-
actionType,
|
|
397
|
-
hitPoint,
|
|
398
|
-
trial: !!options.trial
|
|
399
|
-
});
|
|
400
|
-
if (handle === 'error:notconnected') return handle;
|
|
383
|
+
const actionType = actionName === "move and up" ? "drag" : actionName === "hover" || actionName === "tap" ? actionName : "mouse";
|
|
384
|
+
const handle = await this.evaluateHandleInUtility(([injected, node, { actionType: actionType2, hitPoint: hitPoint2, trial }]) => injected.setupHitTargetInterceptor(node, actionType2, hitPoint2, trial), { actionType, hitPoint, trial: !!options.trial });
|
|
385
|
+
if (handle === "error:notconnected")
|
|
386
|
+
return handle;
|
|
401
387
|
if (!handle._objectId) {
|
|
402
388
|
const error = handle.rawValue();
|
|
403
|
-
if (error ===
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
};
|
|
389
|
+
if (error === "error:notconnected")
|
|
390
|
+
return error;
|
|
391
|
+
return { hitTargetDescription: error };
|
|
407
392
|
}
|
|
408
393
|
hitTargetInterceptionHandle = handle;
|
|
409
394
|
progress.cleanupWhenAborted(() => {
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
hitTargetInterceptionHandle.evaluate(h => h.stop()).catch(e => {});
|
|
395
|
+
hitTargetInterceptionHandle.evaluate((h) => h.stop()).catch((e) => {
|
|
396
|
+
});
|
|
413
397
|
hitTargetInterceptionHandle.dispose();
|
|
414
398
|
});
|
|
415
399
|
}
|
|
416
400
|
const actionResult = await this._page._frameManager.waitForSignalsCreatedBy(progress, options.waitAfter === true, async () => {
|
|
417
|
-
if (options.__testHookBeforePointerAction)
|
|
418
|
-
|
|
401
|
+
if (options.__testHookBeforePointerAction)
|
|
402
|
+
await options.__testHookBeforePointerAction();
|
|
403
|
+
progress.throwIfAborted();
|
|
419
404
|
let restoreModifiers;
|
|
420
|
-
if (options && options.modifiers)
|
|
405
|
+
if (options && options.modifiers)
|
|
406
|
+
restoreModifiers = await this._page.keyboard.ensureModifiers(options.modifiers);
|
|
421
407
|
progress.log(` performing ${actionName} action`);
|
|
422
408
|
await action(point);
|
|
423
|
-
if (restoreModifiers)
|
|
409
|
+
if (restoreModifiers)
|
|
410
|
+
await this._page.keyboard.ensureModifiers(restoreModifiers);
|
|
424
411
|
if (hitTargetInterceptionHandle) {
|
|
425
412
|
const stopHitTargetInterception = this._frame.raceAgainstEvaluationStallingEvents(() => {
|
|
426
|
-
return hitTargetInterceptionHandle.evaluate(h => h.stop());
|
|
427
|
-
}).catch(e =>
|
|
428
|
-
|
|
429
|
-
(_hitTargetInterceptio = hitTargetInterceptionHandle) === null || _hitTargetInterceptio === void 0 || _hitTargetInterceptio.dispose();
|
|
413
|
+
return hitTargetInterceptionHandle.evaluate((h) => h.stop());
|
|
414
|
+
}).catch((e) => "done").finally(() => {
|
|
415
|
+
hitTargetInterceptionHandle?.dispose();
|
|
430
416
|
});
|
|
431
417
|
if (options.waitAfter !== false) {
|
|
432
|
-
// When noWaitAfter is passed, we do not want to accidentally stall on
|
|
433
|
-
// non-committed navigation blocking the evaluate.
|
|
434
418
|
const hitTargetResult = await stopHitTargetInterception;
|
|
435
|
-
if (hitTargetResult !==
|
|
419
|
+
if (hitTargetResult !== "done")
|
|
420
|
+
return hitTargetResult;
|
|
436
421
|
}
|
|
437
422
|
}
|
|
438
|
-
progress.log(` ${options.trial ?
|
|
439
|
-
progress.log(
|
|
440
|
-
if (options.__testHookAfterPointerAction)
|
|
441
|
-
|
|
423
|
+
progress.log(` ${options.trial ? "trial " : ""}${actionName} action done`);
|
|
424
|
+
progress.log(" waiting for scheduled navigations to finish");
|
|
425
|
+
if (options.__testHookAfterPointerAction)
|
|
426
|
+
await options.__testHookAfterPointerAction();
|
|
427
|
+
return "done";
|
|
442
428
|
});
|
|
443
|
-
if (actionResult !==
|
|
444
|
-
|
|
445
|
-
|
|
429
|
+
if (actionResult !== "done")
|
|
430
|
+
return actionResult;
|
|
431
|
+
progress.log(" navigations have finished");
|
|
432
|
+
return "done";
|
|
446
433
|
}
|
|
447
434
|
async _markAsTargetElement(metadata) {
|
|
448
|
-
if (!metadata.id)
|
|
435
|
+
if (!metadata.id)
|
|
436
|
+
return;
|
|
449
437
|
await this.evaluateInUtility(([injected, node, callId]) => {
|
|
450
|
-
if (node.nodeType === 1
|
|
438
|
+
if (node.nodeType === 1)
|
|
439
|
+
injected.markTargetElements(/* @__PURE__ */ new Set([node]), callId);
|
|
451
440
|
}, metadata.id);
|
|
452
441
|
}
|
|
453
442
|
async hover(metadata, options) {
|
|
454
|
-
const controller = new
|
|
455
|
-
return controller.run(async progress => {
|
|
443
|
+
const controller = new import_progress.ProgressController(metadata, this);
|
|
444
|
+
return controller.run(async (progress) => {
|
|
456
445
|
await this._markAsTargetElement(metadata);
|
|
457
446
|
const result = await this._hover(progress, options);
|
|
458
447
|
return assertDone(throwRetargetableDOMError(result));
|
|
459
448
|
}, this._page._timeoutSettings.timeout(options));
|
|
460
449
|
}
|
|
461
450
|
_hover(progress, options) {
|
|
462
|
-
return this._retryPointerAction(progress,
|
|
463
|
-
...options,
|
|
464
|
-
waitAfter: 'disabled'
|
|
465
|
-
});
|
|
451
|
+
return this._retryPointerAction(progress, "hover", false, (point) => this._page.mouse.move(point.x, point.y), { ...options, waitAfter: "disabled" });
|
|
466
452
|
}
|
|
467
453
|
async click(metadata, options = {}) {
|
|
468
|
-
const controller = new
|
|
469
|
-
return controller.run(async progress => {
|
|
454
|
+
const controller = new import_progress.ProgressController(metadata, this);
|
|
455
|
+
return controller.run(async (progress) => {
|
|
470
456
|
await this._markAsTargetElement(metadata);
|
|
471
|
-
const result = await this._click(progress, {
|
|
472
|
-
...options,
|
|
473
|
-
waitAfter: !options.noWaitAfter
|
|
474
|
-
});
|
|
457
|
+
const result = await this._click(progress, { ...options, waitAfter: !options.noWaitAfter });
|
|
475
458
|
return assertDone(throwRetargetableDOMError(result));
|
|
476
459
|
}, this._page._timeoutSettings.timeout(options));
|
|
477
460
|
}
|
|
478
461
|
_click(progress, options) {
|
|
479
|
-
return this._retryPointerAction(progress,
|
|
462
|
+
return this._retryPointerAction(progress, "click", true, (point) => this._page.mouse.click(point.x, point.y, options), options);
|
|
480
463
|
}
|
|
481
464
|
async dblclick(metadata, options) {
|
|
482
|
-
const controller = new
|
|
483
|
-
return controller.run(async progress => {
|
|
465
|
+
const controller = new import_progress.ProgressController(metadata, this);
|
|
466
|
+
return controller.run(async (progress) => {
|
|
484
467
|
await this._markAsTargetElement(metadata);
|
|
485
468
|
const result = await this._dblclick(progress, options);
|
|
486
469
|
return assertDone(throwRetargetableDOMError(result));
|
|
487
470
|
}, this._page._timeoutSettings.timeout(options));
|
|
488
471
|
}
|
|
489
472
|
_dblclick(progress, options) {
|
|
490
|
-
return this._retryPointerAction(progress,
|
|
491
|
-
...options,
|
|
492
|
-
waitAfter: 'disabled'
|
|
493
|
-
});
|
|
473
|
+
return this._retryPointerAction(progress, "dblclick", true, (point) => this._page.mouse.dblclick(point.x, point.y, options), { ...options, waitAfter: "disabled" });
|
|
494
474
|
}
|
|
495
475
|
async tap(metadata, options = {}) {
|
|
496
|
-
const controller = new
|
|
497
|
-
return controller.run(async progress => {
|
|
476
|
+
const controller = new import_progress.ProgressController(metadata, this);
|
|
477
|
+
return controller.run(async (progress) => {
|
|
498
478
|
await this._markAsTargetElement(metadata);
|
|
499
479
|
const result = await this._tap(progress, options);
|
|
500
480
|
return assertDone(throwRetargetableDOMError(result));
|
|
501
481
|
}, this._page._timeoutSettings.timeout(options));
|
|
502
482
|
}
|
|
503
483
|
_tap(progress, options) {
|
|
504
|
-
return this._retryPointerAction(progress,
|
|
505
|
-
...options,
|
|
506
|
-
waitAfter: 'disabled'
|
|
507
|
-
});
|
|
484
|
+
return this._retryPointerAction(progress, "tap", true, (point) => this._page.touchscreen.tap(point.x, point.y), { ...options, waitAfter: "disabled" });
|
|
508
485
|
}
|
|
509
486
|
async selectOption(metadata, elements, values, options) {
|
|
510
|
-
const controller = new
|
|
511
|
-
return controller.run(async progress => {
|
|
487
|
+
const controller = new import_progress.ProgressController(metadata, this);
|
|
488
|
+
return controller.run(async (progress) => {
|
|
512
489
|
await this._markAsTargetElement(metadata);
|
|
513
490
|
const result = await this._selectOption(progress, elements, values, options);
|
|
514
491
|
return throwRetargetableDOMError(result);
|
|
@@ -516,35 +493,33 @@ class ElementHandle extends js.JSHandle {
|
|
|
516
493
|
}
|
|
517
494
|
async _selectOption(progress, elements, values, options) {
|
|
518
495
|
let resultingOptions = [];
|
|
519
|
-
await this._retryAction(progress,
|
|
496
|
+
const result = await this._retryAction(progress, "select option", async () => {
|
|
520
497
|
await this.instrumentation.onBeforeInputAction(this, progress.metadata);
|
|
521
|
-
if (!options.force)
|
|
498
|
+
if (!options.force)
|
|
499
|
+
progress.log(` waiting for element to be visible and enabled`);
|
|
522
500
|
const optionsToSelect = [...elements, ...values];
|
|
523
|
-
const
|
|
524
|
-
optionsToSelect,
|
|
525
|
-
force
|
|
526
|
-
}]) => {
|
|
501
|
+
const result2 = await this.evaluateInUtility(async ([injected, node, { optionsToSelect: optionsToSelect2, force }]) => {
|
|
527
502
|
if (!force) {
|
|
528
|
-
const checkResult = await injected.checkElementStates(node, [
|
|
529
|
-
if (checkResult)
|
|
503
|
+
const checkResult = await injected.checkElementStates(node, ["visible", "enabled"]);
|
|
504
|
+
if (checkResult)
|
|
505
|
+
return checkResult;
|
|
530
506
|
}
|
|
531
|
-
return injected.selectOptions(node,
|
|
532
|
-
}, {
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
progress.log(' selected specified option(s)');
|
|
538
|
-
resultingOptions = result;
|
|
539
|
-
return 'done';
|
|
507
|
+
return injected.selectOptions(node, optionsToSelect2);
|
|
508
|
+
}, { optionsToSelect, force: options.force });
|
|
509
|
+
if (Array.isArray(result2)) {
|
|
510
|
+
progress.log(" selected specified option(s)");
|
|
511
|
+
resultingOptions = result2;
|
|
512
|
+
return "done";
|
|
540
513
|
}
|
|
541
|
-
return
|
|
514
|
+
return result2;
|
|
542
515
|
}, options);
|
|
516
|
+
if (result === "error:notconnected")
|
|
517
|
+
return result;
|
|
543
518
|
return resultingOptions;
|
|
544
519
|
}
|
|
545
520
|
async fill(metadata, value, options = {}) {
|
|
546
|
-
const controller = new
|
|
547
|
-
return controller.run(async progress => {
|
|
521
|
+
const controller = new import_progress.ProgressController(metadata, this);
|
|
522
|
+
return controller.run(async (progress) => {
|
|
548
523
|
await this._markAsTargetElement(metadata);
|
|
549
524
|
const result = await this._fill(progress, value, options);
|
|
550
525
|
assertDone(throwRetargetableDOMError(result));
|
|
@@ -552,122 +527,113 @@ class ElementHandle extends js.JSHandle {
|
|
|
552
527
|
}
|
|
553
528
|
async _fill(progress, value, options) {
|
|
554
529
|
progress.log(` fill("${value}")`);
|
|
555
|
-
return await this._retryAction(progress,
|
|
530
|
+
return await this._retryAction(progress, "fill", async () => {
|
|
556
531
|
await this.instrumentation.onBeforeInputAction(this, progress.metadata);
|
|
557
|
-
if (!options.force)
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
force
|
|
561
|
-
}]) => {
|
|
532
|
+
if (!options.force)
|
|
533
|
+
progress.log(" waiting for element to be visible, enabled and editable");
|
|
534
|
+
const result = await this.evaluateInUtility(async ([injected, node, { value: value2, force }]) => {
|
|
562
535
|
if (!force) {
|
|
563
|
-
const checkResult = await injected.checkElementStates(node, [
|
|
564
|
-
if (checkResult)
|
|
536
|
+
const checkResult = await injected.checkElementStates(node, ["visible", "enabled", "editable"]);
|
|
537
|
+
if (checkResult)
|
|
538
|
+
return checkResult;
|
|
565
539
|
}
|
|
566
|
-
return injected.fill(node,
|
|
567
|
-
}, {
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
return
|
|
540
|
+
return injected.fill(node, value2);
|
|
541
|
+
}, { value, force: options.force });
|
|
542
|
+
progress.throwIfAborted();
|
|
543
|
+
if (result === "needsinput") {
|
|
544
|
+
if (value)
|
|
545
|
+
await this._page.keyboard.insertText(value);
|
|
546
|
+
else
|
|
547
|
+
await this._page.keyboard.press("Delete");
|
|
548
|
+
return "done";
|
|
575
549
|
} else {
|
|
576
550
|
return result;
|
|
577
551
|
}
|
|
578
552
|
}, options);
|
|
579
553
|
}
|
|
580
554
|
async selectText(metadata, options = {}) {
|
|
581
|
-
const controller = new
|
|
582
|
-
return controller.run(async progress => {
|
|
583
|
-
const result = await this._retryAction(progress,
|
|
584
|
-
if (!options.force)
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
}]) => {
|
|
555
|
+
const controller = new import_progress.ProgressController(metadata, this);
|
|
556
|
+
return controller.run(async (progress) => {
|
|
557
|
+
const result = await this._retryAction(progress, "selectText", async () => {
|
|
558
|
+
if (!options.force)
|
|
559
|
+
progress.log(" waiting for element to be visible");
|
|
560
|
+
return await this.evaluateInUtility(async ([injected, node, { force }]) => {
|
|
588
561
|
if (!force) {
|
|
589
|
-
const checkResult = await injected.checkElementStates(node, [
|
|
590
|
-
if (checkResult)
|
|
562
|
+
const checkResult = await injected.checkElementStates(node, ["visible"]);
|
|
563
|
+
if (checkResult)
|
|
564
|
+
return checkResult;
|
|
591
565
|
}
|
|
592
566
|
return injected.selectText(node);
|
|
593
|
-
}, {
|
|
594
|
-
force: options.force
|
|
595
|
-
});
|
|
567
|
+
}, { force: options.force });
|
|
596
568
|
}, options);
|
|
597
569
|
assertDone(throwRetargetableDOMError(result));
|
|
598
570
|
}, this._page._timeoutSettings.timeout(options));
|
|
599
571
|
}
|
|
600
572
|
async setInputFiles(metadata, params) {
|
|
601
|
-
const inputFileItems = await (0,
|
|
602
|
-
const controller = new
|
|
603
|
-
return controller.run(async progress => {
|
|
573
|
+
const inputFileItems = await (0, import_fileUploadUtils.prepareFilesForUpload)(this._frame, params);
|
|
574
|
+
const controller = new import_progress.ProgressController(metadata, this);
|
|
575
|
+
return controller.run(async (progress) => {
|
|
604
576
|
await this._markAsTargetElement(metadata);
|
|
605
577
|
const result = await this._setInputFiles(progress, inputFileItems);
|
|
606
578
|
return assertDone(throwRetargetableDOMError(result));
|
|
607
579
|
}, this._page._timeoutSettings.timeout(params));
|
|
608
580
|
}
|
|
609
581
|
async _setInputFiles(progress, items) {
|
|
610
|
-
const {
|
|
611
|
-
filePayloads,
|
|
612
|
-
localPaths,
|
|
613
|
-
localDirectory
|
|
614
|
-
} = items;
|
|
582
|
+
const { filePayloads, localPaths, localDirectory } = items;
|
|
615
583
|
const multiple = filePayloads && filePayloads.length > 1 || localPaths && localPaths.length > 1;
|
|
616
|
-
const result = await this.evaluateHandleInUtility(([injected, node, {
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
if (element.tagName !== 'INPUT') throw injected.createStacklessError('Node is not an HTMLInputElement');
|
|
584
|
+
const result = await this.evaluateHandleInUtility(([injected, node, { multiple: multiple2, directoryUpload }]) => {
|
|
585
|
+
const element = injected.retarget(node, "follow-label");
|
|
586
|
+
if (!element)
|
|
587
|
+
return;
|
|
588
|
+
if (element.tagName !== "INPUT")
|
|
589
|
+
throw injected.createStacklessError("Node is not an HTMLInputElement");
|
|
623
590
|
const inputElement = element;
|
|
624
|
-
if (
|
|
625
|
-
|
|
626
|
-
if (
|
|
591
|
+
if (multiple2 && !inputElement.multiple && !inputElement.webkitdirectory)
|
|
592
|
+
throw injected.createStacklessError("Non-multiple file input can only accept single file");
|
|
593
|
+
if (directoryUpload && !inputElement.webkitdirectory)
|
|
594
|
+
throw injected.createStacklessError("File input does not support directories, pass individual files instead");
|
|
595
|
+
if (!directoryUpload && inputElement.webkitdirectory)
|
|
596
|
+
throw injected.createStacklessError("[webkitdirectory] input requires passing a path to a directory");
|
|
627
597
|
return inputElement;
|
|
628
|
-
}, {
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
});
|
|
632
|
-
if (result === 'error:notconnected' || !result.asElement()) return 'error:notconnected';
|
|
598
|
+
}, { multiple, directoryUpload: !!localDirectory });
|
|
599
|
+
if (result === "error:notconnected" || !result.asElement())
|
|
600
|
+
return "error:notconnected";
|
|
633
601
|
const retargeted = result.asElement();
|
|
634
602
|
await this.instrumentation.onBeforeInputAction(this, progress.metadata);
|
|
635
|
-
progress.throwIfAborted();
|
|
603
|
+
progress.throwIfAborted();
|
|
636
604
|
if (localPaths || localDirectory) {
|
|
637
605
|
const localPathsOrDirectory = localDirectory ? [localDirectory] : localPaths;
|
|
638
|
-
await Promise.all(localPathsOrDirectory.map(localPath =>
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
});
|
|
644
|
-
})).catch(() => {}) : Promise.resolve();
|
|
606
|
+
await Promise.all(localPathsOrDirectory.map((localPath) => import_fs.default.promises.access(localPath, import_fs.default.constants.F_OK)));
|
|
607
|
+
const waitForInputEvent = localDirectory ? this.evaluate((node) => new Promise((fulfill) => {
|
|
608
|
+
node.addEventListener("input", fulfill, { once: true });
|
|
609
|
+
})).catch(() => {
|
|
610
|
+
}) : Promise.resolve();
|
|
645
611
|
await this._page._delegate.setInputFilePaths(retargeted, localPathsOrDirectory);
|
|
646
612
|
await waitForInputEvent;
|
|
647
613
|
} else {
|
|
648
614
|
await retargeted.evaluateInUtility(([injected, node, files]) => injected.setInputFiles(node, files), filePayloads);
|
|
649
615
|
}
|
|
650
|
-
return
|
|
616
|
+
return "done";
|
|
651
617
|
}
|
|
652
618
|
async focus(metadata) {
|
|
653
|
-
const controller = new
|
|
654
|
-
await controller.run(async progress => {
|
|
619
|
+
const controller = new import_progress.ProgressController(metadata, this);
|
|
620
|
+
await controller.run(async (progress) => {
|
|
655
621
|
await this._markAsTargetElement(metadata);
|
|
656
622
|
const result = await this._focus(progress);
|
|
657
623
|
return assertDone(throwRetargetableDOMError(result));
|
|
658
624
|
}, 0);
|
|
659
625
|
}
|
|
660
626
|
async _focus(progress, resetSelectionIfNotFocused) {
|
|
661
|
-
progress.throwIfAborted();
|
|
662
|
-
return await this.evaluateInUtility(([injected, node,
|
|
627
|
+
progress.throwIfAborted();
|
|
628
|
+
return await this.evaluateInUtility(([injected, node, resetSelectionIfNotFocused2]) => injected.focusNode(node, resetSelectionIfNotFocused2), resetSelectionIfNotFocused);
|
|
663
629
|
}
|
|
664
630
|
async _blur(progress) {
|
|
665
|
-
progress.throwIfAborted();
|
|
631
|
+
progress.throwIfAborted();
|
|
666
632
|
return await this.evaluateInUtility(([injected, node]) => injected.blurNode(node), {});
|
|
667
633
|
}
|
|
668
634
|
async type(metadata, text, options) {
|
|
669
|
-
const controller = new
|
|
670
|
-
return controller.run(async progress => {
|
|
635
|
+
const controller = new import_progress.ProgressController(metadata, this);
|
|
636
|
+
return controller.run(async (progress) => {
|
|
671
637
|
await this._markAsTargetElement(metadata);
|
|
672
638
|
const result = await this._type(progress, text, options);
|
|
673
639
|
return assertDone(throwRetargetableDOMError(result));
|
|
@@ -676,15 +642,20 @@ class ElementHandle extends js.JSHandle {
|
|
|
676
642
|
async _type(progress, text, options) {
|
|
677
643
|
progress.log(`elementHandle.type("${text}")`);
|
|
678
644
|
await this.instrumentation.onBeforeInputAction(this, progress.metadata);
|
|
679
|
-
const result = await this._focus(
|
|
680
|
-
|
|
681
|
-
|
|
645
|
+
const result = await this._focus(
|
|
646
|
+
progress,
|
|
647
|
+
true
|
|
648
|
+
/* resetSelectionIfNotFocused */
|
|
649
|
+
);
|
|
650
|
+
if (result !== "done")
|
|
651
|
+
return result;
|
|
652
|
+
progress.throwIfAborted();
|
|
682
653
|
await this._page.keyboard.type(text, options);
|
|
683
|
-
return
|
|
654
|
+
return "done";
|
|
684
655
|
}
|
|
685
656
|
async press(metadata, key, options) {
|
|
686
|
-
const controller = new
|
|
687
|
-
return controller.run(async progress => {
|
|
657
|
+
const controller = new import_progress.ProgressController(metadata, this);
|
|
658
|
+
return controller.run(async (progress) => {
|
|
688
659
|
await this._markAsTargetElement(metadata);
|
|
689
660
|
const result = await this._press(progress, key, options);
|
|
690
661
|
return assertDone(throwRetargetableDOMError(result));
|
|
@@ -694,53 +665,63 @@ class ElementHandle extends js.JSHandle {
|
|
|
694
665
|
progress.log(`elementHandle.press("${key}")`);
|
|
695
666
|
await this.instrumentation.onBeforeInputAction(this, progress.metadata);
|
|
696
667
|
return this._page._frameManager.waitForSignalsCreatedBy(progress, !options.noWaitAfter, async () => {
|
|
697
|
-
const result = await this._focus(
|
|
698
|
-
|
|
699
|
-
|
|
668
|
+
const result = await this._focus(
|
|
669
|
+
progress,
|
|
670
|
+
true
|
|
671
|
+
/* resetSelectionIfNotFocused */
|
|
672
|
+
);
|
|
673
|
+
if (result !== "done")
|
|
674
|
+
return result;
|
|
675
|
+
progress.throwIfAborted();
|
|
700
676
|
await this._page.keyboard.press(key, options);
|
|
701
|
-
return
|
|
677
|
+
return "done";
|
|
702
678
|
});
|
|
703
679
|
}
|
|
704
680
|
async check(metadata, options) {
|
|
705
|
-
const controller = new
|
|
706
|
-
return controller.run(async progress => {
|
|
681
|
+
const controller = new import_progress.ProgressController(metadata, this);
|
|
682
|
+
return controller.run(async (progress) => {
|
|
707
683
|
const result = await this._setChecked(progress, true, options);
|
|
708
684
|
return assertDone(throwRetargetableDOMError(result));
|
|
709
685
|
}, this._page._timeoutSettings.timeout(options));
|
|
710
686
|
}
|
|
711
687
|
async uncheck(metadata, options) {
|
|
712
|
-
const controller = new
|
|
713
|
-
return controller.run(async progress => {
|
|
688
|
+
const controller = new import_progress.ProgressController(metadata, this);
|
|
689
|
+
return controller.run(async (progress) => {
|
|
714
690
|
const result = await this._setChecked(progress, false, options);
|
|
715
691
|
return assertDone(throwRetargetableDOMError(result));
|
|
716
692
|
}, this._page._timeoutSettings.timeout(options));
|
|
717
693
|
}
|
|
718
694
|
async _setChecked(progress, state, options) {
|
|
719
695
|
const isChecked = async () => {
|
|
720
|
-
const
|
|
721
|
-
if (
|
|
722
|
-
|
|
696
|
+
const result2 = await this.evaluateInUtility(([injected, node]) => injected.elementState(node, "checked"), {});
|
|
697
|
+
if (result2 === "error:notconnected" || result2.received === "error:notconnected")
|
|
698
|
+
throwElementIsNotAttached();
|
|
699
|
+
return result2.matches;
|
|
723
700
|
};
|
|
724
701
|
await this._markAsTargetElement(progress.metadata);
|
|
725
|
-
if (
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
if (
|
|
731
|
-
|
|
732
|
-
if (
|
|
733
|
-
|
|
702
|
+
if (await isChecked() === state)
|
|
703
|
+
return "done";
|
|
704
|
+
const result = await this._click(progress, { ...options, waitAfter: "disabled" });
|
|
705
|
+
if (result !== "done")
|
|
706
|
+
return result;
|
|
707
|
+
if (options.trial)
|
|
708
|
+
return "done";
|
|
709
|
+
if (await isChecked() !== state)
|
|
710
|
+
throw new NonRecoverableDOMError("Clicking the checkbox did not change its state");
|
|
711
|
+
return "done";
|
|
734
712
|
}
|
|
735
713
|
async boundingBox() {
|
|
736
714
|
return this._page._delegate.getBoundingBox(this);
|
|
737
715
|
}
|
|
738
716
|
async ariaSnapshot(options) {
|
|
739
|
-
return await this.evaluateInUtility(([injected, element,
|
|
717
|
+
return await this.evaluateInUtility(([injected, element, options2]) => injected.ariaSnapshot(element, options2), options);
|
|
740
718
|
}
|
|
741
719
|
async screenshot(metadata, options = {}) {
|
|
742
|
-
const controller = new
|
|
743
|
-
return controller.run(
|
|
720
|
+
const controller = new import_progress.ProgressController(metadata, this);
|
|
721
|
+
return controller.run(
|
|
722
|
+
(progress) => this._page._screenshotter.screenshotElement(progress, this, options),
|
|
723
|
+
this._page._timeoutSettings.timeout(options)
|
|
724
|
+
);
|
|
744
725
|
}
|
|
745
726
|
async querySelector(selector, options) {
|
|
746
727
|
return this._frame.selectors.query(selector, options, this);
|
|
@@ -755,30 +736,30 @@ class ElementHandle extends js.JSHandle {
|
|
|
755
736
|
return this._frame.evalOnSelectorAll(selector, expression, isFunction, arg, this);
|
|
756
737
|
}
|
|
757
738
|
async isVisible(metadata) {
|
|
758
|
-
return this._frame.isVisible(metadata,
|
|
739
|
+
return this._frame.isVisible(metadata, ":scope", {}, this);
|
|
759
740
|
}
|
|
760
741
|
async isHidden(metadata) {
|
|
761
|
-
return this._frame.isHidden(metadata,
|
|
742
|
+
return this._frame.isHidden(metadata, ":scope", {}, this);
|
|
762
743
|
}
|
|
763
744
|
async isEnabled(metadata) {
|
|
764
|
-
return this._frame.isEnabled(metadata,
|
|
745
|
+
return this._frame.isEnabled(metadata, ":scope", {}, this);
|
|
765
746
|
}
|
|
766
747
|
async isDisabled(metadata) {
|
|
767
|
-
return this._frame.isDisabled(metadata,
|
|
748
|
+
return this._frame.isDisabled(metadata, ":scope", {}, this);
|
|
768
749
|
}
|
|
769
750
|
async isEditable(metadata) {
|
|
770
|
-
return this._frame.isEditable(metadata,
|
|
751
|
+
return this._frame.isEditable(metadata, ":scope", {}, this);
|
|
771
752
|
}
|
|
772
753
|
async isChecked(metadata) {
|
|
773
|
-
return this._frame.isChecked(metadata,
|
|
754
|
+
return this._frame.isChecked(metadata, ":scope", {}, this);
|
|
774
755
|
}
|
|
775
756
|
async waitForElementState(metadata, state, options = {}) {
|
|
776
|
-
const controller = new
|
|
777
|
-
return controller.run(async progress => {
|
|
757
|
+
const controller = new import_progress.ProgressController(metadata, this);
|
|
758
|
+
return controller.run(async (progress) => {
|
|
778
759
|
const actionName = `wait for ${state}`;
|
|
779
760
|
const result = await this._retryAction(progress, actionName, async () => {
|
|
780
|
-
return await this.evaluateInUtility(async ([injected, node,
|
|
781
|
-
return
|
|
761
|
+
return await this.evaluateInUtility(async ([injected, node, state2]) => {
|
|
762
|
+
return await injected.checkElementStates(node, [state2]) || "done";
|
|
782
763
|
}, state);
|
|
783
764
|
}, {});
|
|
784
765
|
assertDone(throwRetargetableDOMError(result));
|
|
@@ -801,58 +782,38 @@ class ElementHandle extends js.JSHandle {
|
|
|
801
782
|
while (frame.parentFrame()) {
|
|
802
783
|
const frameElement = await frame.frameElement();
|
|
803
784
|
const box = await frameElement.boundingBox();
|
|
804
|
-
const style = await frameElement.evaluateInUtility(([injected, iframe]) => injected.describeIFrameStyle(iframe), {}).catch(e =>
|
|
805
|
-
if (!box || style ===
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
// and solely rely on the event interceptor.
|
|
810
|
-
return {
|
|
811
|
-
framePoint: undefined
|
|
812
|
-
};
|
|
785
|
+
const style = await frameElement.evaluateInUtility(([injected, iframe]) => injected.describeIFrameStyle(iframe), {}).catch((e) => "error:notconnected");
|
|
786
|
+
if (!box || style === "error:notconnected")
|
|
787
|
+
return "error:notconnected";
|
|
788
|
+
if (style === "transformed") {
|
|
789
|
+
return { framePoint: void 0 };
|
|
813
790
|
}
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
x: point.x - box.x - style.left,
|
|
817
|
-
y: point.y - box.y - style.top
|
|
818
|
-
};
|
|
819
|
-
data.push({
|
|
820
|
-
frame,
|
|
821
|
-
frameElement,
|
|
822
|
-
pointInFrame
|
|
823
|
-
});
|
|
791
|
+
const pointInFrame = { x: point.x - box.x - style.left, y: point.y - box.y - style.top };
|
|
792
|
+
data.push({ frame, frameElement, pointInFrame });
|
|
824
793
|
frame = frame.parentFrame();
|
|
825
794
|
}
|
|
826
|
-
|
|
827
|
-
data.push({
|
|
828
|
-
frame,
|
|
829
|
-
frameElement: null,
|
|
830
|
-
pointInFrame: point
|
|
831
|
-
});
|
|
795
|
+
data.push({ frame, frameElement: null, pointInFrame: point });
|
|
832
796
|
for (let i = data.length - 1; i > 0; i--) {
|
|
833
797
|
const element = data[i - 1].frameElement;
|
|
834
|
-
const
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
798
|
+
const point2 = data[i].pointInFrame;
|
|
799
|
+
const hitTargetResult = await element.evaluateInUtility(([injected, element2, hitPoint]) => {
|
|
800
|
+
return injected.expectHitTarget(hitPoint, element2);
|
|
801
|
+
}, point2);
|
|
802
|
+
if (hitTargetResult !== "done")
|
|
803
|
+
return hitTargetResult;
|
|
840
804
|
}
|
|
841
|
-
return {
|
|
842
|
-
framePoint: data[0].pointInFrame
|
|
843
|
-
};
|
|
805
|
+
return { framePoint: data[0].pointInFrame };
|
|
844
806
|
}
|
|
845
807
|
}
|
|
846
|
-
exports.ElementHandle = ElementHandle;
|
|
847
808
|
function throwRetargetableDOMError(result) {
|
|
848
|
-
if (result ===
|
|
809
|
+
if (result === "error:notconnected")
|
|
810
|
+
throwElementIsNotAttached();
|
|
849
811
|
return result;
|
|
850
812
|
}
|
|
851
813
|
function throwElementIsNotAttached() {
|
|
852
|
-
throw new Error(
|
|
814
|
+
throw new Error("Element is not attached to the DOM");
|
|
853
815
|
}
|
|
854
816
|
function assertDone(result) {
|
|
855
|
-
// This function converts 'done' to void and ensures typescript catches unhandled errors.
|
|
856
817
|
}
|
|
857
818
|
function roundPoint(point) {
|
|
858
819
|
return {
|
|
@@ -861,10 +822,7 @@ function roundPoint(point) {
|
|
|
861
822
|
};
|
|
862
823
|
}
|
|
863
824
|
function quadMiddlePoint(quad) {
|
|
864
|
-
const result = {
|
|
865
|
-
x: 0,
|
|
866
|
-
y: 0
|
|
867
|
-
};
|
|
825
|
+
const result = { x: 0, y: 0 };
|
|
868
826
|
for (const point of quad) {
|
|
869
827
|
result.x += point.x / 4;
|
|
870
828
|
result.y += point.y / 4;
|
|
@@ -877,23 +835,35 @@ function triangleArea(p1, p2, p3) {
|
|
|
877
835
|
function isPointInsideQuad(point, quad) {
|
|
878
836
|
const area1 = triangleArea(point, quad[0], quad[1]) + triangleArea(point, quad[1], quad[2]) + triangleArea(point, quad[2], quad[3]) + triangleArea(point, quad[3], quad[0]);
|
|
879
837
|
const area2 = triangleArea(quad[0], quad[1], quad[2]) + triangleArea(quad[1], quad[2], quad[3]);
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
// Check that point is not on the right/bottom edge, because clicking
|
|
883
|
-
// there does not actually click the element.
|
|
838
|
+
if (Math.abs(area1 - area2) > 0.1)
|
|
839
|
+
return false;
|
|
884
840
|
return point.x < Math.max(quad[0].x, quad[1].x, quad[2].x, quad[3].x) && point.y < Math.max(quad[0].y, quad[1].y, quad[2].y, quad[3].y);
|
|
885
841
|
}
|
|
886
842
|
function findIntegerPointInsideQuad(quad) {
|
|
887
|
-
// Try all four rounding directions of the middle point.
|
|
888
843
|
const point = quadMiddlePoint(quad);
|
|
889
844
|
point.x = Math.floor(point.x);
|
|
890
845
|
point.y = Math.floor(point.y);
|
|
891
|
-
if (isPointInsideQuad(point, quad))
|
|
846
|
+
if (isPointInsideQuad(point, quad))
|
|
847
|
+
return point;
|
|
892
848
|
point.x += 1;
|
|
893
|
-
if (isPointInsideQuad(point, quad))
|
|
849
|
+
if (isPointInsideQuad(point, quad))
|
|
850
|
+
return point;
|
|
894
851
|
point.y += 1;
|
|
895
|
-
if (isPointInsideQuad(point, quad))
|
|
852
|
+
if (isPointInsideQuad(point, quad))
|
|
853
|
+
return point;
|
|
896
854
|
point.x -= 1;
|
|
897
|
-
if (isPointInsideQuad(point, quad))
|
|
855
|
+
if (isPointInsideQuad(point, quad))
|
|
856
|
+
return point;
|
|
898
857
|
}
|
|
899
|
-
const kUnableToAdoptErrorMessage =
|
|
858
|
+
const kUnableToAdoptErrorMessage = "Unable to adopt element handle from a different document";
|
|
859
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
860
|
+
0 && (module.exports = {
|
|
861
|
+
ElementHandle,
|
|
862
|
+
FrameExecutionContext,
|
|
863
|
+
NonRecoverableDOMError,
|
|
864
|
+
assertDone,
|
|
865
|
+
isNonRecoverableDOMError,
|
|
866
|
+
kUnableToAdoptErrorMessage,
|
|
867
|
+
throwElementIsNotAttached,
|
|
868
|
+
throwRetargetableDOMError
|
|
869
|
+
});
|