browser-debugger-cli 0.8.0 → 0.10.0
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/README.md +7 -1
- package/dist/cdp/schema.d.ts +4 -1
- package/dist/cdp/schema.js +48 -7
- package/dist/commands/cdp.js +3 -2
- package/dist/commands/cleanup.d.ts +11 -0
- package/dist/commands/cleanup.js +161 -57
- package/dist/commands/console.d.ts +20 -1
- package/dist/commands/console.js +57 -17
- package/dist/commands/details.js +3 -2
- package/dist/commands/dom/DomElementResolver.d.ts +10 -3
- package/dist/commands/dom/DomElementResolver.js +35 -17
- package/dist/commands/dom/a11y.d.ts +10 -0
- package/dist/commands/dom/a11y.js +29 -6
- package/dist/commands/dom/eval.d.ts +3 -1
- package/dist/commands/dom/eval.js +29 -4
- package/dist/commands/dom/form.js +16 -62
- package/dist/commands/dom/formInteraction.js +189 -119
- package/dist/commands/dom/formSummary.d.ts +49 -0
- package/dist/commands/dom/formSummary.js +180 -0
- package/dist/commands/dom/frames.d.ts +2 -1
- package/dist/commands/dom/frames.js +17 -2
- package/dist/commands/dom/get.d.ts +6 -5
- package/dist/commands/dom/get.js +92 -82
- package/dist/commands/dom/helpers/index.d.ts +1 -1
- package/dist/commands/dom/helpers/index.js +1 -1
- package/dist/commands/dom/helpers/keyAttributes.d.ts +20 -0
- package/dist/commands/dom/helpers/keyAttributes.js +54 -0
- package/dist/commands/dom/helpers/query.d.ts +44 -17
- package/dist/commands/dom/helpers/query.js +300 -106
- package/dist/commands/dom/helpers/runElementCommand.d.ts +10 -2
- package/dist/commands/dom/helpers/runElementCommand.js +98 -30
- package/dist/commands/dom/helpers/screenshot.d.ts +4 -1
- package/dist/commands/dom/helpers/screenshot.js +239 -51
- package/dist/commands/dom/index.d.ts +4 -1
- package/dist/commands/dom/index.js +22 -7
- package/dist/commands/dom/inspect.d.ts +15 -0
- package/dist/commands/dom/inspect.js +82 -0
- package/dist/commands/dom/layout.d.ts +14 -0
- package/dist/commands/dom/layout.js +54 -0
- package/dist/commands/dom/listeners.d.ts +5 -1
- package/dist/commands/dom/listeners.js +15 -5
- package/dist/commands/dom/query.js +2 -3
- package/dist/commands/dom/screenshot.d.ts +12 -2
- package/dist/commands/dom/screenshot.js +27 -3
- package/dist/commands/dom/semanticUtils.d.ts +16 -10
- package/dist/commands/dom/semanticUtils.js +53 -16
- package/dist/commands/dom/wait.d.ts +13 -0
- package/dist/commands/dom/wait.js +83 -0
- package/dist/commands/helpJson.js +2 -2
- package/dist/commands/network/list.js +17 -13
- package/dist/commands/optionBehaviors.js +154 -21
- package/dist/commands/page.d.ts +3 -2
- package/dist/commands/page.js +100 -5
- package/dist/commands/peek.js +4 -11
- package/dist/commands/sessions.d.ts +8 -0
- package/dist/commands/sessions.js +19 -0
- package/dist/commands/shared/CommandRunner.js +4 -4
- package/dist/commands/shared/commonOptions.d.ts +4 -0
- package/dist/commands/shared/commonOptions.js +9 -0
- package/dist/commands/shared/dataFetcher.js +2 -2
- package/dist/commands/shared/followMode.d.ts +21 -1
- package/dist/commands/shared/followMode.js +29 -2
- package/dist/commands/shared/handleValidationError.d.ts +2 -2
- package/dist/commands/shared/handleValidationError.js +12 -3
- package/dist/commands/shared/optionTypes.d.ts +61 -5
- package/dist/commands/shared/startHelpers.d.ts +66 -0
- package/dist/commands/shared/startHelpers.js +103 -13
- package/dist/commands/shared/validation.d.ts +14 -2
- package/dist/commands/shared/validation.js +20 -3
- package/dist/commands/start.d.ts +63 -0
- package/dist/commands/start.js +115 -15
- package/dist/commands/status.js +29 -7
- package/dist/commands/stop.js +7 -6
- package/dist/commands/tail.js +4 -11
- package/dist/commands/types.d.ts +2 -0
- package/dist/commands.js +2 -0
- package/dist/connection/chromeIdentity.d.ts +65 -0
- package/dist/connection/chromeIdentity.js +143 -0
- package/dist/connection/launcher/profilePreferences.d.ts +47 -0
- package/dist/connection/launcher/profilePreferences.js +151 -0
- package/dist/connection/launcher.d.ts +21 -2
- package/dist/connection/launcher.js +42 -16
- package/dist/connection/portReservation.d.ts +14 -4
- package/dist/connection/portReservation.js +21 -6
- package/dist/connection/startupExit.d.ts +8 -0
- package/dist/connection/startupExit.js +15 -6
- package/dist/constants.d.ts +6 -2
- package/dist/constants.js +9 -2
- package/dist/daemon/SessionController.js +23 -7
- package/dist/daemon/errors.d.ts +1 -1
- package/dist/daemon/errors.js +1 -1
- package/dist/daemon/launcher.d.ts +10 -2
- package/dist/daemon/launcher.js +8 -7
- package/dist/daemon/server/SocketServer.js +1 -2
- package/dist/daemon/session/Session.d.ts +20 -0
- package/dist/daemon/session/Session.js +80 -9
- package/dist/daemon/session/chromeConnection.d.ts +9 -0
- package/dist/daemon/session/chromeConnection.js +45 -8
- package/dist/daemon/session/commandRegistry.d.ts +14 -1
- package/dist/daemon/session/commandRegistry.js +113 -67
- package/dist/daemon/session/interactions.d.ts +48 -9
- package/dist/daemon/session/interactions.js +46 -9
- package/dist/daemon/session/triggeredRequests.d.ts +67 -0
- package/dist/daemon/session/triggeredRequests.js +157 -0
- package/dist/daemon/session/types.d.ts +5 -1
- package/dist/daemon.js +10630 -3601
- package/dist/errors/messages.d.ts +456 -24
- package/dist/errors/messages.js +862 -67
- package/dist/index.js +6915 -3401
- package/dist/ipc/client.d.ts +21 -1
- package/dist/ipc/client.js +35 -3
- package/dist/ipc/protocol/commands.d.ts +145 -5
- package/dist/ipc/protocol/commands.js +4 -0
- package/dist/ipc/protocol/domTypes.d.ts +291 -7
- package/dist/ipc/protocol/inspectTypes.d.ts +388 -0
- package/dist/ipc/protocol/inspectTypes.js +10 -0
- package/dist/ipc/session/lifecycle.d.ts +8 -1
- package/dist/ipc/session/queries.d.ts +5 -1
- package/dist/ipc/session/types.d.ts +5 -0
- package/dist/ipc/transport/index.d.ts +2 -1
- package/dist/ipc/transport/index.js +2 -2
- package/dist/runtime/dom/actionEffects.d.ts +185 -0
- package/dist/runtime/dom/actionEffects.js +402 -0
- package/dist/runtime/dom/actionEffectsScripts.d.ts +90 -0
- package/dist/runtime/dom/actionEffectsScripts.js +426 -0
- package/dist/runtime/dom/elementGeometry.d.ts +170 -0
- package/dist/runtime/dom/elementGeometry.js +553 -0
- package/dist/runtime/dom/elementInfo.d.ts +103 -0
- package/dist/runtime/dom/elementInfo.js +256 -0
- package/dist/runtime/dom/evalHelpers.d.ts +51 -6
- package/dist/runtime/dom/evalHelpers.js +136 -26
- package/dist/runtime/dom/eventListeners.d.ts +2 -1
- package/dist/runtime/dom/eventListeners.js +184 -47
- package/dist/runtime/dom/formDiscovery.d.ts +1 -1
- package/dist/runtime/dom/formDiscovery.js +116 -16
- package/dist/runtime/dom/formFillHelpers/fill.d.ts +9 -0
- package/dist/runtime/dom/formFillHelpers/fill.js +178 -14
- package/dist/runtime/dom/formFillHelpers/index.d.ts +2 -2
- package/dist/runtime/dom/formFillHelpers/index.js +2 -2
- package/dist/runtime/dom/formFillHelpers/pressKey.js +14 -3
- package/dist/runtime/dom/formFillHelpers/scroll.d.ts +3 -0
- package/dist/runtime/dom/formFillHelpers/scroll.js +60 -18
- package/dist/runtime/dom/formFillHelpers/shared.d.ts +17 -0
- package/dist/runtime/dom/formFillHelpers/shared.js +25 -1
- package/dist/runtime/dom/formFillHelpers/stability.d.ts +20 -6
- package/dist/runtime/dom/formFillHelpers/stability.js +50 -19
- package/dist/runtime/dom/formSubmitHelpers.d.ts +3 -0
- package/dist/runtime/dom/formSubmitHelpers.js +89 -15
- package/dist/runtime/dom/frameLayout.d.ts +60 -0
- package/dist/runtime/dom/frameLayout.js +140 -0
- package/dist/runtime/dom/frameOrigin.d.ts +50 -0
- package/dist/runtime/dom/frameOrigin.js +62 -0
- package/dist/runtime/dom/frameScopedConnection.d.ts +92 -0
- package/dist/runtime/dom/frameScopedConnection.js +252 -0
- package/dist/runtime/dom/frameSelection.d.ts +12 -1
- package/dist/runtime/dom/frameSelection.js +22 -3
- package/dist/runtime/dom/frames.d.ts +61 -5
- package/dist/runtime/dom/frames.js +329 -75
- package/dist/runtime/dom/inspect.d.ts +28 -0
- package/dist/runtime/dom/inspect.js +557 -0
- package/dist/runtime/dom/inspectAllStyles.d.ts +62 -0
- package/dist/runtime/dom/inspectAllStyles.js +385 -0
- package/dist/runtime/dom/inspectCascade.d.ts +94 -0
- package/dist/runtime/dom/inspectCascade.js +371 -0
- package/dist/runtime/dom/inspectCascadeModel.d.ts +39 -0
- package/dist/runtime/dom/inspectCascadeModel.js +232 -0
- package/dist/runtime/dom/inspectHints.d.ts +62 -0
- package/dist/runtime/dom/inspectHints.js +305 -0
- package/dist/runtime/dom/inspectLayoutModel.d.ts +87 -0
- package/dist/runtime/dom/inspectLayoutModel.js +346 -0
- package/dist/runtime/dom/inspectModel.d.ts +74 -0
- package/dist/runtime/dom/inspectModel.js +184 -0
- package/dist/runtime/dom/inspectPaintModel.d.ts +157 -0
- package/dist/runtime/dom/inspectPaintModel.js +461 -0
- package/dist/runtime/dom/inspectRules.d.ts +37 -0
- package/dist/runtime/dom/inspectRules.js +101 -0
- package/dist/runtime/dom/inspectScripts.d.ts +132 -0
- package/dist/runtime/dom/inspectScripts.js +263 -0
- package/dist/runtime/dom/inspectTree.d.ts +40 -0
- package/dist/runtime/dom/inspectTree.js +134 -0
- package/dist/runtime/dom/inspectVariables.d.ts +33 -0
- package/dist/runtime/dom/inspectVariables.js +94 -0
- package/dist/runtime/dom/inspectWhyModel.d.ts +20 -0
- package/dist/runtime/dom/inspectWhyModel.js +134 -0
- package/dist/runtime/dom/layout.d.ts +71 -0
- package/dist/runtime/dom/layout.js +340 -0
- package/dist/runtime/dom/listenerPageScripts.d.ts +72 -0
- package/dist/runtime/dom/listenerPageScripts.js +365 -0
- package/dist/runtime/dom/listenerSummary.d.ts +136 -11
- package/dist/runtime/dom/listenerSummary.js +361 -22
- package/dist/runtime/dom/pageActivity.d.ts +41 -0
- package/dist/runtime/dom/pageActivity.js +123 -0
- package/dist/runtime/dom/reactEventHelpers.d.ts +63 -2
- package/dist/runtime/dom/reactEventHelpers.js +220 -41
- package/dist/runtime/dom/targetNode.d.ts +80 -27
- package/dist/runtime/dom/targetNode.js +249 -33
- package/dist/runtime/dom/wait.d.ts +25 -0
- package/dist/runtime/dom/wait.js +199 -0
- package/dist/runtime/dom/waitCondition.d.ts +71 -0
- package/dist/runtime/dom/waitCondition.js +75 -0
- package/dist/runtime/page/emulation.d.ts +71 -0
- package/dist/runtime/page/emulation.js +117 -0
- package/dist/runtime/page/loadingState.d.ts +36 -0
- package/dist/runtime/page/loadingState.js +86 -0
- package/dist/runtime/page/navigation.d.ts +46 -2
- package/dist/runtime/page/navigation.js +69 -33
- package/dist/session/QueryCacheManager.d.ts +11 -1
- package/dist/session/QueryCacheManager.js +25 -3
- package/dist/session/chromeOwners.d.ts +34 -0
- package/dist/session/chromeOwners.js +51 -0
- package/dist/session/cleanup/staleSession.d.ts +11 -1
- package/dist/session/cleanup/staleSession.js +17 -6
- package/dist/session/cleanup/userCommands.js +2 -4
- package/dist/session/metadata.d.ts +5 -1
- package/dist/session/metadata.js +2 -1
- package/dist/session/paths.d.ts +77 -3
- package/dist/session/paths.js +111 -5
- package/dist/session/port.d.ts +31 -7
- package/dist/session/port.js +50 -43
- package/dist/session/portClaims.d.ts +66 -0
- package/dist/session/portClaims.js +284 -0
- package/dist/session/sessionList.d.ts +58 -0
- package/dist/session/sessionList.js +199 -0
- package/dist/session/sessionName.d.ts +46 -0
- package/dist/session/sessionName.js +97 -0
- package/dist/telemetry/a11y.d.ts +18 -3
- package/dist/telemetry/a11y.js +170 -29
- package/dist/telemetry/console.d.ts +1 -0
- package/dist/telemetry/console.js +100 -5
- package/dist/telemetry/network.js +3 -1
- package/dist/telemetry/requestKinds.d.ts +32 -0
- package/dist/telemetry/requestKinds.js +61 -0
- package/dist/telemetry/requestState.d.ts +31 -0
- package/dist/telemetry/requestState.js +38 -0
- package/dist/types.d.ts +112 -3
- package/dist/ui/formatters/a11y.js +3 -0
- package/dist/ui/formatters/console/chronological.d.ts +8 -0
- package/dist/ui/formatters/console/chronological.js +17 -4
- package/dist/ui/formatters/console/json.js +3 -4
- package/dist/ui/formatters/console/shared.d.ts +12 -0
- package/dist/ui/formatters/console.d.ts +2 -2
- package/dist/ui/formatters/console.js +1 -1
- package/dist/ui/formatters/details.d.ts +8 -0
- package/dist/ui/formatters/details.js +61 -4
- package/dist/ui/formatters/dom.d.ts +27 -14
- package/dist/ui/formatters/dom.js +88 -59
- package/dist/ui/formatters/form.js +29 -18
- package/dist/ui/formatters/inspect.d.ts +39 -0
- package/dist/ui/formatters/inspect.js +596 -0
- package/dist/ui/formatters/keyAttributes.d.ts +19 -0
- package/dist/ui/formatters/keyAttributes.js +84 -0
- package/dist/ui/formatters/layout.d.ts +31 -0
- package/dist/ui/formatters/layout.js +53 -0
- package/dist/ui/formatters/listeners.d.ts +3 -2
- package/dist/ui/formatters/listeners.js +73 -9
- package/dist/ui/formatters/networkHeaders.d.ts +13 -0
- package/dist/ui/formatters/networkHeaders.js +36 -3
- package/dist/ui/formatters/networkList.d.ts +29 -1
- package/dist/ui/formatters/networkList.js +86 -20
- package/dist/ui/formatters/preview.js +2 -1
- package/dist/ui/formatters/requestStatus.d.ts +1 -17
- package/dist/ui/formatters/requestStatus.js +2 -30
- package/dist/ui/formatters/sessions.d.ts +12 -0
- package/dist/ui/formatters/sessions.js +40 -0
- package/dist/ui/formatters/status.d.ts +21 -2
- package/dist/ui/formatters/status.js +47 -10
- package/dist/ui/formatters/triggeredRequests.d.ts +36 -0
- package/dist/ui/formatters/triggeredRequests.js +65 -0
- package/dist/ui/formatting.d.ts +19 -0
- package/dist/ui/formatting.js +31 -36
- package/dist/ui/messages/chrome.d.ts +9 -0
- package/dist/ui/messages/chrome.js +17 -5
- package/dist/ui/messages/commands.d.ts +504 -14
- package/dist/ui/messages/commands.js +835 -21
- package/dist/ui/messages/consoleMessages.d.ts +10 -0
- package/dist/ui/messages/consoleMessages.js +17 -0
- package/dist/ui/messages/hints.js +2 -1
- package/dist/ui/messages/networkMessages.d.ts +14 -0
- package/dist/ui/messages/networkMessages.js +18 -0
- package/dist/ui/messages/preview.js +5 -4
- package/dist/ui/messages/session.d.ts +30 -21
- package/dist/ui/messages/session.js +48 -26
- package/dist/ui/messages/sessionCommand.d.ts +43 -0
- package/dist/ui/messages/sessionCommand.js +52 -0
- package/dist/utils/async.d.ts +17 -0
- package/dist/utils/async.js +36 -0
- package/dist/utils/color.d.ts +84 -0
- package/dist/utils/color.js +376 -0
- package/dist/utils/cssValues.d.ts +109 -0
- package/dist/utils/cssValues.js +236 -0
- package/dist/utils/http.d.ts +22 -1
- package/dist/utils/http.js +28 -9
- package/dist/utils/selectorFilters.d.ts +48 -8
- package/dist/utils/selectorFilters.js +296 -53
- package/dist/utils/shellDetection.d.ts +8 -2
- package/dist/utils/shellDetection.js +120 -33
- package/dist/utils/suggestions.d.ts +26 -0
- package/dist/utils/suggestions.js +73 -0
- package/dist/utils/taskMappings.js +10 -0
- package/dist/utils/url.d.ts +12 -2
- package/dist/utils/url.js +69 -7
- package/package.json +1 -1
- package/dist/ui/formatters/sessionFormatters.d.ts +0 -58
- package/dist/ui/formatters/sessionFormatters.js +0 -121
|
@@ -3,6 +3,9 @@
|
|
|
3
3
|
* page boundaries.
|
|
4
4
|
*/
|
|
5
5
|
import { CommandError } from '../../../errors/index.js';
|
|
6
|
+
import { scrollNoEffectWarning } from '../../../errors/messages.js';
|
|
7
|
+
import { SCROLL_RANGE_JS, VIEWPORT_SIZE_JS, } from '../elementGeometry.js';
|
|
8
|
+
import { ELEMENT_IDENTITY_JS } from '../elementInfo.js';
|
|
6
9
|
import { throwIfInvalidSelector, withMultipleMatchesWarning, } from './shared.js';
|
|
7
10
|
import { FIND_ELEMENTS_JS, selectorArgsJS } from '../targetNode.js';
|
|
8
11
|
import { EXIT_CODES } from '../../../utils/exitCodes.js';
|
|
@@ -29,26 +32,20 @@ const SCROLL_TO_ELEMENT_SCRIPT = `
|
|
|
29
32
|
|
|
30
33
|
el.scrollIntoView({ behavior: 'instant', block: 'center' });
|
|
31
34
|
|
|
32
|
-
const rect = el.getBoundingClientRect();
|
|
33
|
-
const scrollX = window.scrollX + rect.left + rect.width / 2 - window.innerWidth / 2;
|
|
34
|
-
const scrollY = window.scrollY + rect.top + rect.height / 2 - window.innerHeight / 2;
|
|
35
|
-
|
|
36
35
|
return {
|
|
37
36
|
success: true,
|
|
38
37
|
scrollType: 'element',
|
|
39
38
|
selector: selector,
|
|
39
|
+
element: (${ELEMENT_IDENTITY_JS})(el),
|
|
40
40
|
matchCount: allMatches.length,
|
|
41
41
|
scrolledTo: {
|
|
42
42
|
x: Math.round(window.scrollX),
|
|
43
43
|
y: Math.round(window.scrollY)
|
|
44
44
|
},
|
|
45
|
-
viewportSize: {
|
|
46
|
-
width: window.innerWidth,
|
|
47
|
-
height: window.innerHeight
|
|
48
|
-
},
|
|
45
|
+
viewportSize: (${VIEWPORT_SIZE_JS})(window),
|
|
49
46
|
pageSize: {
|
|
50
|
-
width: document.documentElement.scrollWidth,
|
|
51
|
-
height: document.documentElement.scrollHeight
|
|
47
|
+
width: (document.scrollingElement || document.documentElement).scrollWidth,
|
|
48
|
+
height: (document.scrollingElement || document.documentElement).scrollHeight
|
|
52
49
|
}
|
|
53
50
|
};
|
|
54
51
|
})`;
|
|
@@ -56,6 +53,7 @@ const SCROLL_BY_SCRIPT = `
|
|
|
56
53
|
(function(options) {
|
|
57
54
|
const beforeX = window.scrollX;
|
|
58
55
|
const beforeY = window.scrollY;
|
|
56
|
+
const range = (${SCROLL_RANGE_JS})(window);
|
|
59
57
|
|
|
60
58
|
if (options.top) {
|
|
61
59
|
window.scrollTo({ top: 0, behavior: 'instant' });
|
|
@@ -81,16 +79,60 @@ const SCROLL_BY_SCRIPT = `
|
|
|
81
79
|
scrollType: options.top || options.bottom ? 'position' : 'offset',
|
|
82
80
|
scrolledTo: { x: Math.round(afterX), y: Math.round(afterY) },
|
|
83
81
|
scrolledBy: { x: Math.round(afterX - beforeX), y: Math.round(afterY - beforeY) },
|
|
84
|
-
viewportSize: {
|
|
85
|
-
width: window.innerWidth,
|
|
86
|
-
height: window.innerHeight
|
|
87
|
-
},
|
|
82
|
+
viewportSize: (${VIEWPORT_SIZE_JS})(window),
|
|
88
83
|
pageSize: {
|
|
89
|
-
width: document.documentElement.scrollWidth,
|
|
90
|
-
height: document.documentElement.scrollHeight
|
|
91
|
-
}
|
|
84
|
+
width: (document.scrollingElement || document.documentElement).scrollWidth,
|
|
85
|
+
height: (document.scrollingElement || document.documentElement).scrollHeight
|
|
86
|
+
},
|
|
87
|
+
rangeBefore: range,
|
|
88
|
+
readyState: document.readyState
|
|
92
89
|
};
|
|
93
90
|
})`;
|
|
91
|
+
/**
|
|
92
|
+
* The direction a page scroll asked for (the options allow one per axis;
|
|
93
|
+
* only one axis is checked, vertical first).
|
|
94
|
+
*
|
|
95
|
+
* @param options - Scroll options
|
|
96
|
+
* @returns Direction, or undefined when no distance was asked for
|
|
97
|
+
*/
|
|
98
|
+
function requestedDirection(options) {
|
|
99
|
+
if (options.bottom || (options.down ?? 0) > 0)
|
|
100
|
+
return 'down';
|
|
101
|
+
if (options.top || (options.up ?? 0) > 0)
|
|
102
|
+
return 'up';
|
|
103
|
+
if ((options.right ?? 0) > 0)
|
|
104
|
+
return 'right';
|
|
105
|
+
if ((options.left ?? 0) > 0)
|
|
106
|
+
return 'left';
|
|
107
|
+
return undefined;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Warn when a page scroll moved nothing: the document does not scroll in
|
|
111
|
+
* that direction, the page was already at its edge, or scrolling is locked;
|
|
112
|
+
* while the page is still loading, also that it may grow.
|
|
113
|
+
*
|
|
114
|
+
* @param result - Page script result
|
|
115
|
+
* @param options - Scroll options
|
|
116
|
+
* @returns The scroll result, with `warning` when nothing scrolled
|
|
117
|
+
*/
|
|
118
|
+
function withNoEffectWarning(result, options) {
|
|
119
|
+
const { rangeBefore, readyState, ...scroll } = result;
|
|
120
|
+
const direction = requestedDirection(options);
|
|
121
|
+
const moved = scroll.scrolledBy && (scroll.scrolledBy.x !== 0 || scroll.scrolledBy.y !== 0);
|
|
122
|
+
if (!direction || moved || !scroll.viewportSize)
|
|
123
|
+
return scroll;
|
|
124
|
+
const vertical = direction === 'up' || direction === 'down';
|
|
125
|
+
const scrollable = vertical
|
|
126
|
+
? rangeBefore.up + rangeBefore.down > 0
|
|
127
|
+
: rangeBefore.left + rangeBefore.right > 0;
|
|
128
|
+
const warning = scrollNoEffectWarning({
|
|
129
|
+
direction,
|
|
130
|
+
reason: !scrollable ? 'too-small' : rangeBefore[direction] <= 0 ? 'at-edge' : 'locked',
|
|
131
|
+
viewport: vertical ? scroll.viewportSize.height : scroll.viewportSize.width,
|
|
132
|
+
readyState,
|
|
133
|
+
});
|
|
134
|
+
return { ...scroll, warning };
|
|
135
|
+
}
|
|
94
136
|
function isScrollResult(value) {
|
|
95
137
|
if (typeof value !== 'object' || value === null)
|
|
96
138
|
return false;
|
|
@@ -164,7 +206,7 @@ export async function scrollPage(cdp, selector, options = {}) {
|
|
|
164
206
|
};
|
|
165
207
|
}
|
|
166
208
|
if (cdpResponse.result?.value && isScrollResult(cdpResponse.result.value)) {
|
|
167
|
-
return cdpResponse.result.value;
|
|
209
|
+
return withNoEffectWarning(cdpResponse.result.value, options);
|
|
168
210
|
}
|
|
169
211
|
return {
|
|
170
212
|
success: false,
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* and JS string escaping.
|
|
4
4
|
*/
|
|
5
5
|
import type { Protocol } from '../../../connection/typed-cdp.js';
|
|
6
|
+
import type { FillResult } from '../../../ipc/protocol/domTypes.js';
|
|
6
7
|
/**
|
|
7
8
|
* Escape a CSS selector for embedding in a single-quoted JS string.
|
|
8
9
|
*/
|
|
@@ -20,6 +21,14 @@ export declare function withMultipleMatchesWarning<T extends {
|
|
|
20
21
|
matchCount?: number | undefined;
|
|
21
22
|
warning?: string | undefined;
|
|
22
23
|
}>(result: T, index: number | undefined, action: string): T;
|
|
24
|
+
/**
|
|
25
|
+
* Put a warning first when the filled field's value is not the one given
|
|
26
|
+
* (see `valueMismatch`). Keeps an existing warning after it.
|
|
27
|
+
*
|
|
28
|
+
* @param result - Fill result
|
|
29
|
+
* @returns The result, with the warning when the value differs
|
|
30
|
+
*/
|
|
31
|
+
export declare function withValueMismatchWarning(result: FillResult): FillResult;
|
|
23
32
|
/**
|
|
24
33
|
* Escape a value for embedding in a single-quoted JS string.
|
|
25
34
|
*/
|
|
@@ -30,6 +39,14 @@ export declare function escapeValueForJS(value: string): string;
|
|
|
30
39
|
* query-then-act pattern.
|
|
31
40
|
*/
|
|
32
41
|
export declare function formatScriptExecutionError(exceptionDetails: Protocol.Runtime.ExceptionDetails, selector: string, operationType?: 'fill' | 'click', expression?: string): string;
|
|
42
|
+
/**
|
|
43
|
+
* What a page script threw, in one line (`TypeError: Cannot read …` rather
|
|
44
|
+
* than CDP's bare "Uncaught").
|
|
45
|
+
*
|
|
46
|
+
* @param details - Exception details from Runtime.evaluate
|
|
47
|
+
* @returns First line of the exception's description
|
|
48
|
+
*/
|
|
49
|
+
export declare function exceptionSummary(details: Protocol.Runtime.ExceptionDetails): string;
|
|
33
50
|
/**
|
|
34
51
|
* Throw a user error when a page script failed because the CSS selector is
|
|
35
52
|
* invalid (the browser's `querySelectorAll` rejected it), instead of reporting
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import { CommandError } from '../../../errors/index.js';
|
|
6
6
|
import { invalidSelectorError } from '../../../errors/messages.js';
|
|
7
|
-
import { multipleMatchesWarning } from '../../../ui/messages/commands.js';
|
|
7
|
+
import { multipleMatchesWarning, valueMismatchWarning } from '../../../ui/messages/commands.js';
|
|
8
8
|
import { EXIT_CODES } from '../../../utils/exitCodes.js';
|
|
9
9
|
import { detectSelectorQuoteDamage } from '../../../utils/shellDetection.js';
|
|
10
10
|
/**
|
|
@@ -29,6 +29,19 @@ export function withMultipleMatchesWarning(result, index, action) {
|
|
|
29
29
|
const warning = multipleMatchesWarning(count, action);
|
|
30
30
|
return { ...result, warning: result.warning ? `${result.warning}; ${warning}` : warning };
|
|
31
31
|
}
|
|
32
|
+
/**
|
|
33
|
+
* Put a warning first when the filled field's value is not the one given
|
|
34
|
+
* (see `valueMismatch`). Keeps an existing warning after it.
|
|
35
|
+
*
|
|
36
|
+
* @param result - Fill result
|
|
37
|
+
* @returns The result, with the warning when the value differs
|
|
38
|
+
*/
|
|
39
|
+
export function withValueMismatchWarning(result) {
|
|
40
|
+
if (!result.valueMismatch)
|
|
41
|
+
return result;
|
|
42
|
+
const warning = valueMismatchWarning(result.valueMismatch);
|
|
43
|
+
return { ...result, warning: result.warning ? `${warning}; ${result.warning}` : warning };
|
|
44
|
+
}
|
|
32
45
|
/**
|
|
33
46
|
* Escape a value for embedding in a single-quoted JS string.
|
|
34
47
|
*/
|
|
@@ -81,6 +94,17 @@ export function formatScriptExecutionError(exceptionDetails, selector, operation
|
|
|
81
94
|
lines.push(` ${troubleshootingSteps.join('\n ')}`);
|
|
82
95
|
return lines.join('\n');
|
|
83
96
|
}
|
|
97
|
+
/**
|
|
98
|
+
* What a page script threw, in one line (`TypeError: Cannot read …` rather
|
|
99
|
+
* than CDP's bare "Uncaught").
|
|
100
|
+
*
|
|
101
|
+
* @param details - Exception details from Runtime.evaluate
|
|
102
|
+
* @returns First line of the exception's description
|
|
103
|
+
*/
|
|
104
|
+
export function exceptionSummary(details) {
|
|
105
|
+
const description = details.exception?.description ?? details.text;
|
|
106
|
+
return description.split('\n')[0] ?? description;
|
|
107
|
+
}
|
|
84
108
|
/**
|
|
85
109
|
* Throw a user error when a page script failed because the CSS selector is
|
|
86
110
|
* invalid (the browser's `querySelectorAll` rejected it), instead of reporting
|
|
@@ -1,14 +1,28 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Post-action network-stability wait.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* Used around fill/click/hover/pressKey/scroll: tracks in-flight requests
|
|
5
|
+
* from before the action runs (so a request its handler sends synchronously
|
|
6
|
+
* is seen), then waits until no request has been pending for
|
|
7
|
+
* ACTION_NETWORK_IDLE_MS, giving up after ACTION_STABILITY_TIMEOUT_MS.
|
|
7
8
|
*/
|
|
8
9
|
import type { CDPConnection } from '../../../connection/cdp.js';
|
|
9
10
|
/**
|
|
10
|
-
*
|
|
11
|
-
*
|
|
11
|
+
* Run an action and, when it succeeds, wait for the network to settle.
|
|
12
|
+
*
|
|
13
|
+
* Requests are tracked from before the action, so one an event handler
|
|
14
|
+
* starts while the action runs (`onclick = () => fetch(...)`) is waited for.
|
|
15
|
+
* `Network.enable` is sent without waiting for it: the session's network
|
|
16
|
+
* collector has already enabled the domain, and Chrome holds the call until
|
|
17
|
+
* a pending navigation commits, which would otherwise block for as long as
|
|
18
|
+
* the new page's server takes to answer.
|
|
19
|
+
*
|
|
20
|
+
* @param cdp - CDP connection
|
|
21
|
+
* @param action - Action to run (its result's `success` decides whether to wait)
|
|
22
|
+
* @param wait - Wait for the network after the action (false for `--no-wait`)
|
|
23
|
+
* @returns The action's result, once the network is idle or the wait timed out
|
|
12
24
|
*/
|
|
13
|
-
export declare function
|
|
25
|
+
export declare function withActionStability<T extends {
|
|
26
|
+
success: boolean;
|
|
27
|
+
}>(cdp: CDPConnection, action: () => Promise<T>, wait?: boolean): Promise<T>;
|
|
14
28
|
//# sourceMappingURL=stability.d.ts.map
|
|
@@ -1,40 +1,71 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Post-action network-stability wait.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* Used around fill/click/hover/pressKey/scroll: tracks in-flight requests
|
|
5
|
+
* from before the action runs (so a request its handler sends synchronously
|
|
6
|
+
* is seen), then waits until no request has been pending for
|
|
7
|
+
* ACTION_NETWORK_IDLE_MS, giving up after ACTION_STABILITY_TIMEOUT_MS.
|
|
7
8
|
*/
|
|
8
9
|
import { trackInFlightRequests } from '../../../connection/inFlightRequests.js';
|
|
9
10
|
import { createLogger } from '../../../ui/logging/index.js';
|
|
10
11
|
import { delay } from '../../../utils/async.js';
|
|
12
|
+
import { getErrorMessage } from '../../../utils/errors.js';
|
|
11
13
|
const log = createLogger('dom');
|
|
12
14
|
const ACTION_NETWORK_IDLE_MS = 150;
|
|
13
15
|
const ACTION_STABILITY_TIMEOUT_MS = 2000;
|
|
14
16
|
const STABILITY_CHECK_INTERVAL_MS = 50;
|
|
15
17
|
/**
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
+
* Run an action and, when it succeeds, wait for the network to settle.
|
|
19
|
+
*
|
|
20
|
+
* Requests are tracked from before the action, so one an event handler
|
|
21
|
+
* starts while the action runs (`onclick = () => fetch(...)`) is waited for.
|
|
22
|
+
* `Network.enable` is sent without waiting for it: the session's network
|
|
23
|
+
* collector has already enabled the domain, and Chrome holds the call until
|
|
24
|
+
* a pending navigation commits, which would otherwise block for as long as
|
|
25
|
+
* the new page's server takes to answer.
|
|
26
|
+
*
|
|
27
|
+
* @param cdp - CDP connection
|
|
28
|
+
* @param action - Action to run (its result's `success` decides whether to wait)
|
|
29
|
+
* @param wait - Wait for the network after the action (false for `--no-wait`)
|
|
30
|
+
* @returns The action's result, once the network is idle or the wait timed out
|
|
18
31
|
*/
|
|
19
|
-
export async function
|
|
20
|
-
|
|
21
|
-
|
|
32
|
+
export async function withActionStability(cdp, action, wait = true) {
|
|
33
|
+
if (!wait)
|
|
34
|
+
return action();
|
|
35
|
+
void cdp
|
|
36
|
+
.send('Network.enable')
|
|
37
|
+
.catch((error) => log.debug(`Network.enable failed: ${getErrorMessage(error)}`));
|
|
22
38
|
const requests = trackInFlightRequests(cdp);
|
|
23
39
|
try {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
log.debug(`Network stable after ${idleTime}ms idle`);
|
|
29
|
-
return;
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
await delay(STABILITY_CHECK_INTERVAL_MS);
|
|
33
|
-
}
|
|
34
|
-
log.debug('Stability timeout reached, proceeding');
|
|
40
|
+
const result = await action();
|
|
41
|
+
if (result.success)
|
|
42
|
+
await waitForNetworkIdle(requests);
|
|
43
|
+
return result;
|
|
35
44
|
}
|
|
36
45
|
finally {
|
|
37
46
|
requests.dispose();
|
|
38
47
|
}
|
|
39
48
|
}
|
|
49
|
+
/**
|
|
50
|
+
* Wait until no request has been in flight for ACTION_NETWORK_IDLE_MS since
|
|
51
|
+
* the wait began (a request the action started counts until it ends), or
|
|
52
|
+
* until ACTION_STABILITY_TIMEOUT_MS passed.
|
|
53
|
+
*
|
|
54
|
+
* @param requests - Tracker started before the action
|
|
55
|
+
*/
|
|
56
|
+
async function waitForNetworkIdle(requests) {
|
|
57
|
+
const waitStart = Date.now();
|
|
58
|
+
const deadline = waitStart + ACTION_STABILITY_TIMEOUT_MS;
|
|
59
|
+
while (Date.now() < deadline) {
|
|
60
|
+
if (requests.count === 0) {
|
|
61
|
+
const idleTime = Date.now() - Math.max(requests.lastActivity, waitStart);
|
|
62
|
+
if (idleTime >= ACTION_NETWORK_IDLE_MS) {
|
|
63
|
+
log.debug(`Network stable after ${idleTime}ms idle`);
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
await delay(STABILITY_CHECK_INTERVAL_MS);
|
|
68
|
+
}
|
|
69
|
+
log.debug(`Stability timeout reached with ${requests.count} request(s) in flight, proceeding`);
|
|
70
|
+
}
|
|
40
71
|
//# sourceMappingURL=stability.js.map
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import type { CDPConnection } from '../../connection/cdp.js';
|
|
5
5
|
import type { SubmitResult } from '../../ipc/protocol/domTypes.js';
|
|
6
|
+
import type { PendingRequest } from '../../telemetry/network.js';
|
|
6
7
|
/**
|
|
7
8
|
* Options for submitting a form.
|
|
8
9
|
*/
|
|
@@ -15,6 +16,8 @@ export interface SubmitOptions {
|
|
|
15
16
|
waitNetwork?: number;
|
|
16
17
|
/** Maximum time to wait in milliseconds (default: 10000) */
|
|
17
18
|
timeout?: number;
|
|
19
|
+
/** Requests still running in the session (named when the wait times out) */
|
|
20
|
+
pendingRequests?: () => Iterable<PendingRequest>;
|
|
18
21
|
}
|
|
19
22
|
export type { SubmitResult } from '../../ipc/protocol/domTypes.js';
|
|
20
23
|
/**
|
|
@@ -3,9 +3,11 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import { CDPTimeoutError } from '../../connection/errors.js';
|
|
5
5
|
import { trackInFlightRequests } from '../../connection/inFlightRequests.js';
|
|
6
|
-
import { submitTimeoutError } from '../../errors/messages.js';
|
|
6
|
+
import { submitNetworkBusyWarning, submitTimeoutError } from '../../errors/messages.js';
|
|
7
|
+
import { ELEMENT_IDENTITY_JS } from './elementInfo.js';
|
|
7
8
|
import { throwIfInvalidSelector } from './formFillHelpers/shared.js';
|
|
8
9
|
import { FIND_ELEMENTS_JS, selectorArgsJS } from './targetNode.js';
|
|
10
|
+
import { summarizePendingRequests } from '../page/loadingState.js';
|
|
9
11
|
import { EXIT_CODES } from '../../utils/exitCodes.js';
|
|
10
12
|
import { clickElement } from './formFillHelpers/index.js';
|
|
11
13
|
/**
|
|
@@ -61,9 +63,10 @@ const PREPARE_SUBMIT_SCRIPT = `
|
|
|
61
63
|
// Like pressing Enter: the form's default button is the submitter, so its
|
|
62
64
|
// name=value is sent too
|
|
63
65
|
const submitter = submitters.find((f) => !f.matches(':disabled'));
|
|
66
|
+
const element = (${ELEMENT_IDENTITY_JS})(submitter || el);
|
|
64
67
|
if (submitter) el.requestSubmit(submitter);
|
|
65
68
|
else el.requestSubmit();
|
|
66
|
-
return { action: 'submitted', clicked: Boolean(submitter) };
|
|
69
|
+
return { action: 'submitted', clicked: Boolean(submitter), element: element };
|
|
67
70
|
}
|
|
68
71
|
return { action: 'click' };
|
|
69
72
|
})`;
|
|
@@ -84,9 +87,14 @@ const FAILURE_SUGGESTIONS = {
|
|
|
84
87
|
/**
|
|
85
88
|
* Watches navigation and network activity from before a submission is
|
|
86
89
|
* triggered, so fast navigations are not missed.
|
|
90
|
+
*
|
|
91
|
+
* A navigation is a new document committed in the main frame
|
|
92
|
+
* (`Page.frameNavigated`), whatever its URL: a POST that redirects back to
|
|
93
|
+
* the form's own URL (a login error) navigates too.
|
|
87
94
|
*/
|
|
88
95
|
class SubmissionWatcher {
|
|
89
96
|
navigated = false;
|
|
97
|
+
documentRequest;
|
|
90
98
|
onChange = null;
|
|
91
99
|
requests;
|
|
92
100
|
disposers = [];
|
|
@@ -96,27 +104,66 @@ class SubmissionWatcher {
|
|
|
96
104
|
constructor(cdp) {
|
|
97
105
|
this.requests = trackInFlightRequests(cdp, () => this.onChange?.());
|
|
98
106
|
this.disposers.push(this.requests.dispose);
|
|
99
|
-
this.disposers.push(cdp.on('Page.frameNavigated', (params) => {
|
|
100
|
-
if (params.frame.parentId !== undefined)
|
|
107
|
+
this.disposers.push(cdp.on('Page.frameNavigated', (params, sessionId) => {
|
|
108
|
+
if (sessionId !== undefined || params.frame.parentId !== undefined)
|
|
101
109
|
return;
|
|
102
110
|
this.navigated = true;
|
|
103
111
|
this.onChange?.();
|
|
112
|
+
}), cdp.on('Network.requestWillBeSent', (params, sessionId) => {
|
|
113
|
+
if (sessionId !== undefined || params.type !== 'Document')
|
|
114
|
+
return;
|
|
115
|
+
this.documentRequest ??= {
|
|
116
|
+
requestId: params.requestId,
|
|
117
|
+
method: params.request.method,
|
|
118
|
+
url: params.request.url,
|
|
119
|
+
startedAt: Date.now(),
|
|
120
|
+
};
|
|
121
|
+
}), cdp.on('Network.responseReceived', (params) => {
|
|
122
|
+
if (params.requestId !== this.documentRequest?.requestId)
|
|
123
|
+
return;
|
|
124
|
+
this.documentRequest.status = params.response.status;
|
|
125
|
+
this.documentRequest.statusText = params.response.statusText;
|
|
126
|
+
}), cdp.on('Network.loadingFailed', (params) => {
|
|
127
|
+
if (params.requestId !== this.documentRequest?.requestId)
|
|
128
|
+
return;
|
|
129
|
+
this.documentRequest.errorText = params.errorText;
|
|
104
130
|
}));
|
|
105
131
|
}
|
|
106
132
|
/** Whether the main frame navigated since watching began. */
|
|
107
133
|
get navigationOccurred() {
|
|
108
134
|
return this.navigated;
|
|
109
135
|
}
|
|
136
|
+
/** How far the first page request sent since watching began got, if one was sent */
|
|
137
|
+
get firstDocumentRequest() {
|
|
138
|
+
const request = this.documentRequest;
|
|
139
|
+
if (!request)
|
|
140
|
+
return undefined;
|
|
141
|
+
const answered = request.status !== undefined || request.errorText !== undefined;
|
|
142
|
+
return {
|
|
143
|
+
method: request.method,
|
|
144
|
+
url: request.url,
|
|
145
|
+
...(!answered && { pendingMs: Date.now() - request.startedAt }),
|
|
146
|
+
...(request.status !== undefined && { status: request.status }),
|
|
147
|
+
...(request.statusText && { statusText: request.statusText }),
|
|
148
|
+
...(request.errorText !== undefined && { errorText: request.errorText }),
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
/** Requests still in flight */
|
|
152
|
+
get pendingRequests() {
|
|
153
|
+
return this.requests.count;
|
|
154
|
+
}
|
|
110
155
|
/** Requests started since watching began. */
|
|
111
156
|
get networkRequests() {
|
|
112
157
|
return this.requests.started;
|
|
113
158
|
}
|
|
114
159
|
/**
|
|
115
160
|
* Wait until the network is idle for `waitNetwork` ms and, if requested,
|
|
116
|
-
* the main frame navigated.
|
|
161
|
+
* the main frame navigated. When a requested navigation happened but the
|
|
162
|
+
* network was still busy at the timeout (a slow script or tracker on the
|
|
163
|
+
* new page), the wait ends without an error: resolves to `'busy'`.
|
|
117
164
|
*
|
|
118
165
|
* @param options - Wait conditions
|
|
119
|
-
* @returns
|
|
166
|
+
* @returns `'idle'`, or `'busy'` when only the network wait timed out
|
|
120
167
|
* @throws CDPTimeoutError after `timeout` ms
|
|
121
168
|
*/
|
|
122
169
|
wait(options) {
|
|
@@ -131,13 +178,16 @@ class SubmissionWatcher {
|
|
|
131
178
|
};
|
|
132
179
|
const deadline = setTimeout(() => {
|
|
133
180
|
finish();
|
|
134
|
-
|
|
181
|
+
if (waitNavigation && this.navigated)
|
|
182
|
+
resolve('busy');
|
|
183
|
+
else
|
|
184
|
+
reject(new CDPTimeoutError('Wait for completion timed out', new Error(`${timeout}ms`)));
|
|
135
185
|
}, timeout);
|
|
136
186
|
const check = () => {
|
|
137
187
|
const networkIdle = waitNetwork === 0 || this.requests.count === 0;
|
|
138
188
|
if (networkIdle && (!waitNavigation || this.navigated)) {
|
|
139
189
|
finish();
|
|
140
|
-
resolve();
|
|
190
|
+
resolve('idle');
|
|
141
191
|
}
|
|
142
192
|
};
|
|
143
193
|
const schedule = () => {
|
|
@@ -184,14 +234,16 @@ async function triggerSubmit(cdp, selector, index) {
|
|
|
184
234
|
clicked: false,
|
|
185
235
|
exitCode: FAILURE_EXIT_CODES[reason],
|
|
186
236
|
suggestion: FAILURE_SUGGESTIONS[reason],
|
|
237
|
+
...(reason === 'not-submittable' && { unsuitableElement: true }),
|
|
187
238
|
};
|
|
188
239
|
return { failure };
|
|
189
240
|
}
|
|
190
|
-
if (prepared.action === 'submitted')
|
|
191
|
-
return { clicked: prepared.clicked === true };
|
|
241
|
+
if (prepared.action === 'submitted') {
|
|
242
|
+
return { clicked: prepared.clicked === true, element: prepared.element };
|
|
243
|
+
}
|
|
192
244
|
const click = await clickElement(cdp, selector, index !== undefined ? { index } : {});
|
|
193
245
|
if (click.success)
|
|
194
|
-
return { clicked: true };
|
|
246
|
+
return { clicked: true, element: click.element };
|
|
195
247
|
const failure = {
|
|
196
248
|
success: false,
|
|
197
249
|
error: click.error ?? 'Click failed',
|
|
@@ -202,6 +254,21 @@ async function triggerSubmit(cdp, selector, index) {
|
|
|
202
254
|
};
|
|
203
255
|
return { failure };
|
|
204
256
|
}
|
|
257
|
+
/**
|
|
258
|
+
* The requests still running in the session, the longest-running first.
|
|
259
|
+
*
|
|
260
|
+
* @param pendingRequests - Source of the session's pending requests
|
|
261
|
+
* @returns The ones to name and the count, none without a source
|
|
262
|
+
*/
|
|
263
|
+
function pendingSummary(pendingRequests) {
|
|
264
|
+
if (!pendingRequests)
|
|
265
|
+
return {};
|
|
266
|
+
const requests = [...pendingRequests()];
|
|
267
|
+
return {
|
|
268
|
+
pending: summarizePendingRequests(requests, Date.now()),
|
|
269
|
+
pendingCount: requests.length,
|
|
270
|
+
};
|
|
271
|
+
}
|
|
205
272
|
/**
|
|
206
273
|
* Submit a form and wait for the result.
|
|
207
274
|
*
|
|
@@ -218,22 +285,29 @@ export async function submitForm(cdp, selector, options = {}) {
|
|
|
218
285
|
const triggered = await triggerSubmit(cdp, selector, index);
|
|
219
286
|
if ('failure' in triggered)
|
|
220
287
|
return triggered.failure;
|
|
221
|
-
|
|
222
|
-
await watcher.wait({ waitNavigation, waitNetwork, timeout })
|
|
223
|
-
|
|
288
|
+
const outcome = waitNetwork > 0 || waitNavigation
|
|
289
|
+
? await watcher.wait({ waitNavigation, waitNetwork, timeout })
|
|
290
|
+
: 'idle';
|
|
224
291
|
return {
|
|
225
292
|
success: true,
|
|
226
293
|
selector,
|
|
294
|
+
...(triggered.element !== undefined && { element: triggered.element }),
|
|
227
295
|
clicked: triggered.clicked,
|
|
228
296
|
networkRequests: watcher.networkRequests,
|
|
229
297
|
navigationOccurred: watcher.navigationOccurred,
|
|
230
298
|
waitTimeMs: Date.now() - startTime,
|
|
299
|
+
...(outcome === 'busy' && {
|
|
300
|
+
warning: submitNetworkBusyWarning(timeout, watcher.pendingRequests),
|
|
301
|
+
}),
|
|
231
302
|
};
|
|
232
303
|
}
|
|
233
304
|
catch (error) {
|
|
234
305
|
if (!(error instanceof CDPTimeoutError))
|
|
235
306
|
throw error;
|
|
236
|
-
const err = submitTimeoutError(timeout, waitNavigation
|
|
307
|
+
const err = submitTimeoutError(timeout, waitNavigation, {
|
|
308
|
+
document: watcher.firstDocumentRequest,
|
|
309
|
+
...pendingSummary(options.pendingRequests),
|
|
310
|
+
});
|
|
237
311
|
return {
|
|
238
312
|
success: false,
|
|
239
313
|
error: err.message,
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Layout of an element inside a cross-origin iframe that shares the page's
|
|
3
|
+
* process (an a11y query can return those).
|
|
4
|
+
*
|
|
5
|
+
* The element is measured in its own frame, whose scripts cannot see the top
|
|
6
|
+
* page, so its measurements are relative to the frame's viewport. The
|
|
7
|
+
* iframe element holding the frame is measured in its own document, and the
|
|
8
|
+
* element is placed in the top-level viewport through it: mapped by the
|
|
9
|
+
* frame's position and scale, clipped to the frame's viewport and to what clips the
|
|
10
|
+
* iframe, and fixed, scrolled or hidden as the iframe is.
|
|
11
|
+
*/
|
|
12
|
+
import type { CDPConnection } from '../../connection/cdp.js';
|
|
13
|
+
import type { Protocol } from '../../connection/typed-cdp.js';
|
|
14
|
+
import type { LayoutBox } from '../../ipc/protocol/domTypes.js';
|
|
15
|
+
import { type FrameMapping } from './frameScopedConnection.js';
|
|
16
|
+
import type { RawLayout } from './layout.js';
|
|
17
|
+
/**
|
|
18
|
+
* Ids of all frames below a frame tree's root.
|
|
19
|
+
*
|
|
20
|
+
* @param tree - Frame tree
|
|
21
|
+
* @returns Frame ids, depth-first
|
|
22
|
+
*/
|
|
23
|
+
export declare function childFrameIds(tree: Protocol.Page.FrameTree | undefined): string[];
|
|
24
|
+
/**
|
|
25
|
+
* The iframe element whose document holds an element.
|
|
26
|
+
*
|
|
27
|
+
* @param cdp - CDP connection
|
|
28
|
+
* @param objectId - Remote object of the element
|
|
29
|
+
* @returns Backend node id of the iframe element, undefined when not found
|
|
30
|
+
*/
|
|
31
|
+
export declare function findFrameOwner(cdp: CDPConnection, objectId: string): Promise<number | undefined>;
|
|
32
|
+
/**
|
|
33
|
+
* Overlap of boxes.
|
|
34
|
+
*
|
|
35
|
+
* @param boxes - Boxes (null ones are left out)
|
|
36
|
+
* @returns Overlap (zero size when they do not overlap)
|
|
37
|
+
*/
|
|
38
|
+
export declare function intersection(...boxes: Array<LayoutBox | null>): LayoutBox;
|
|
39
|
+
/**
|
|
40
|
+
* Whether a box lies inside another.
|
|
41
|
+
*
|
|
42
|
+
* @param inner - Inner box
|
|
43
|
+
* @param outer - Outer box
|
|
44
|
+
* @returns True when it does
|
|
45
|
+
*/
|
|
46
|
+
export declare function inside(inner: LayoutBox, outer: LayoutBox): boolean;
|
|
47
|
+
/**
|
|
48
|
+
* Place an element measured inside a cross-origin frame in the top-level
|
|
49
|
+
* viewport, through the measurements of the frame's iframe element: mapped by
|
|
50
|
+
* the frame's position and scale (border, padding, `transform`, `zoom`),
|
|
51
|
+
* clipped to the frame's viewport and to what clips the iframe.
|
|
52
|
+
*
|
|
53
|
+
* @param raw - The element, measured in its frame
|
|
54
|
+
* @param owner - The iframe element, measured in its document
|
|
55
|
+
* @param mapping - How the frame's viewport maps into the top-level viewport
|
|
56
|
+
* @returns The element's layout in the top-level page (unchanged when the
|
|
57
|
+
* iframe could not be measured)
|
|
58
|
+
*/
|
|
59
|
+
export declare function placeInOwnerFrame(raw: RawLayout, owner: RawLayout, mapping: FrameMapping): RawLayout;
|
|
60
|
+
//# sourceMappingURL=frameLayout.d.ts.map
|