Merge remote-tracking branch 'sand4rt/hello-angular-ct' into hello-angular-ct

This commit is contained in:
Younes Jaaidi 2024-02-25 20:00:54 -05:00
commit df2884590b
No known key found for this signature in database
GPG key ID: 3126C5717BDF3241
49 changed files with 4522 additions and 3330 deletions

View file

@ -1,6 +1,6 @@
# 🎭 Playwright
[![npm version](https://img.shields.io/npm/v/playwright.svg)](https://www.npmjs.com/package/playwright) <!-- GEN:chromium-version-badge -->[![Chromium version](https://img.shields.io/badge/chromium-122.0.6261.57-blue.svg?logo=google-chrome)](https://www.chromium.org/Home)<!-- GEN:stop --> <!-- GEN:firefox-version-badge -->[![Firefox version](https://img.shields.io/badge/firefox-122.0-blue.svg?logo=firefoxbrowser)](https://www.mozilla.org/en-US/firefox/new/)<!-- GEN:stop --> <!-- GEN:webkit-version-badge -->[![WebKit version](https://img.shields.io/badge/webkit-17.4-blue.svg?logo=safari)](https://webkit.org/)<!-- GEN:stop -->
[![npm version](https://img.shields.io/npm/v/playwright.svg)](https://www.npmjs.com/package/playwright) <!-- GEN:chromium-version-badge -->[![Chromium version](https://img.shields.io/badge/chromium-123.0.6312.4-blue.svg?logo=google-chrome)](https://www.chromium.org/Home)<!-- GEN:stop --> <!-- GEN:firefox-version-badge -->[![Firefox version](https://img.shields.io/badge/firefox-123.0-blue.svg?logo=firefoxbrowser)](https://www.mozilla.org/en-US/firefox/new/)<!-- GEN:stop --> <!-- GEN:webkit-version-badge -->[![WebKit version](https://img.shields.io/badge/webkit-17.4-blue.svg?logo=safari)](https://webkit.org/)<!-- GEN:stop -->
## [Documentation](https://playwright.dev) | [API reference](https://playwright.dev/docs/api/class-playwright)
@ -8,9 +8,9 @@ Playwright is a framework for Web Testing and Automation. It allows testing [Chr
| | Linux | macOS | Windows |
| :--- | :---: | :---: | :---: |
| Chromium <!-- GEN:chromium-version -->122.0.6261.57<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| Chromium <!-- GEN:chromium-version -->123.0.6312.4<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| WebKit <!-- GEN:webkit-version -->17.4<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| Firefox <!-- GEN:firefox-version -->122.0<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| Firefox <!-- GEN:firefox-version -->123.0<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
Headless execution is supported for all browsers on all platforms. Check out [system requirements](https://playwright.dev/docs/intro#system-requirements) for details.

View file

@ -1,3 +1,3 @@
REMOTE_URL="https://github.com/mozilla/gecko-dev"
BASE_BRANCH="release"
BASE_REVISION="7ab3cc0103090dd7bfa02e072a529b9fc784ab4e"
BASE_REVISION="a32b8662993085139ac91212a297123b632fc1c0"

View file

@ -23,6 +23,16 @@ class Helper {
return allBrowsingContexts;
}
awaitTopic(topic) {
return new Promise(resolve => {
const listener = () => {
Services.obs.removeObserver(listener, topic);
resolve();
}
Services.obs.addObserver(listener, topic);
});
}
toProtocolNavigationId(loadIdentifier) {
return `nav-${loadIdentifier}`;
}

View file

@ -366,13 +366,6 @@ class NetworkRequest {
return;
}
const browserContext = pageNetwork._target.browserContext();
if (browserContext.crossProcessCookie.settings.onlineOverride === 'offline') {
// Implement offline.
this.abort(Cr.NS_ERROR_OFFLINE);
return;
}
// Ok, so now we have intercepted the request, let's issue onRequest.
// If interception has been disabled while we were intercepting, resume and forget.
const interceptionEnabled = this._shouldIntercept();
@ -462,8 +455,6 @@ class NetworkRequest {
const browserContext = pageNetwork._target.browserContext();
if (browserContext.requestInterceptionEnabled)
return true;
if (browserContext.crossProcessCookie.settings.onlineOverride === 'offline')
return true;
return false;
}

View file

@ -458,6 +458,11 @@ class PageTarget {
this.updateColorSchemeOverride(browsingContext);
this.updateReducedMotionOverride(browsingContext);
this.updateForcedColorsOverride(browsingContext);
this.updateForceOffline(browsingContext);
}
updateForceOffline(browsingContext = undefined) {
(browsingContext || this._linkedBrowser.browsingContext).forceOffline = this._browserContext.forceOffline;
}
updateTouchOverride(browsingContext = undefined) {
@ -829,6 +834,7 @@ class BrowserContext {
this.defaultUserAgent = null;
this.defaultPlatform = null;
this.touchOverride = false;
this.forceOffline = false;
this.colorScheme = 'none';
this.forcedColors = 'no-override';
this.reducedMotion = 'none';
@ -924,6 +930,12 @@ class BrowserContext {
page.updateTouchOverride();
}
setForceOffline(forceOffline) {
this.forceOffline = forceOffline;
for (const page of this.pages)
page.updateForceOffline();
}
async setDefaultViewport(viewport) {
this.defaultViewportSize = viewport ? viewport.viewportSize : undefined;
this.deviceScaleFactor = viewport ? viewport.deviceScaleFactor : undefined;

View file

@ -461,16 +461,8 @@ class PageAgent {
}
async _dispatchKeyEvent({type, keyCode, code, key, repeat, location, text}) {
if (code === 'OSLeft')
code = 'MetaLeft';
else if (code === 'OSRight')
code = 'MetaRight';
const frame = this._frameTree.mainFrame();
const tip = frame.textInputProcessor();
if (key === 'Meta' && Services.appinfo.OS !== 'Darwin')
key = 'OS';
else if (key === 'OS' && Services.appinfo.OS === 'Darwin')
key = 'Meta';
let keyEvent = new (frame.domWindow().KeyboardEvent)("", {
key,
code,

View file

@ -47,15 +47,6 @@ function initialize(browsingContext, docShell, actor) {
}
},
onlineOverride: (onlineOverride) => {
if (!onlineOverride) {
docShell.onlineOverride = Ci.nsIDocShell.ONLINE_OVERRIDE_NONE;
return;
}
docShell.onlineOverride = onlineOverride === 'online' ?
Ci.nsIDocShell.ONLINE_OVERRIDE_ONLINE : Ci.nsIDocShell.ONLINE_OVERRIDE_OFFLINE;
},
bypassCSP: (bypassCSP) => {
docShell.bypassCSPEnabled = bypassCSP;
},

View file

@ -199,7 +199,8 @@ class BrowserHandler {
}
async ['Browser.setOnlineOverride']({browserContextId, override}) {
await this._targetRegistry.browserContextForId(browserContextId).applySetting('onlineOverride', nullToUndefined(override));
const forceOffline = override === 'offline';
await this._targetRegistry.browserContextForId(browserContextId).setForceOffline(forceOffline);
}
async ['Browser.setColorScheme']({browserContextId, colorScheme}) {

View file

@ -488,6 +488,9 @@ class PageHandler {
this._pageTarget._linkedBrowser.scrollRectIntoViewIfNeeded(x, y, 0, 0);
// 2. Get element's bounding box in the browser after the scroll is completed.
const boundingBox = this._pageTarget._linkedBrowser.getBoundingClientRect();
// 3. Make sure compositor is flushed after scrolling.
if (win.windowUtils.flushApzRepaints())
await helper.awaitTopic('apz-repaints-flushed');
const watcher = new EventWatcher(this._pageEventSink, types, this._pendingEventWatchers);
const promises = [];
@ -608,7 +611,7 @@ class PageHandler {
const lineOrPageDeltaX = deltaX > 0 ? Math.floor(deltaX) : Math.ceil(deltaX);
const lineOrPageDeltaY = deltaY > 0 ? Math.floor(deltaY) : Math.ceil(deltaY);
await this._pageTarget.activateAndRun(() => {
await this._pageTarget.activateAndRun(async () => {
this._pageTarget.ensureContextMenuClosed();
// 1. Scroll element to the desired location first; the coordinates are relative to the element.
@ -617,6 +620,10 @@ class PageHandler {
const boundingBox = this._pageTarget._linkedBrowser.getBoundingClientRect();
const win = this._pageTarget._window;
// 3. Make sure compositor is flushed after scrolling.
if (win.windowUtils.flushApzRepaints())
await helper.awaitTopic('apz-repaints-flushed');
win.windowUtils.sendWheelEvent(
x + boundingBox.left,
y + boundingBox.top,

File diff suppressed because it is too large Load diff

View file

@ -6,6 +6,8 @@
pref("dom.input_events.security.minNumTicks", 0);
pref("dom.input_events.security.minTimeElapsedInMS", 0);
pref("dom.iframe_lazy_loading.enabled", false);
pref("datareporting.policy.dataSubmissionEnabled", false);
pref("datareporting.policy.dataSubmissionPolicyAccepted", false);
pref("datareporting.policy.dataSubmissionPolicyBypassNotification", true);
@ -97,9 +99,6 @@ pref("security.enterprise_roots.enabled", true);
// See AppShutdown.cpp for more details on shutdown phases.
pref("toolkit.shutdown.fastShutdownStage", 3);
// @see https://github.com/microsoft/playwright/issues/8178
pref("dom.postMessage.sharedArrayBuffer.bypassCOOP_COEP.insecure.enabled", true);
// Use light theme by default.
pref("ui.systemUsesDarkTheme", 0);

View file

@ -1,3 +1,3 @@
REMOTE_URL="https://github.com/WebKit/WebKit.git"
BASE_BRANCH="main"
BASE_REVISION="bc0bc692bc9e368bbd9d530322db73b374cd6268"
BASE_REVISION="3db3a794a844d2c7e4cda8fc6a7588f8e62ee85a"

File diff suppressed because it is too large Load diff

View file

@ -3344,12 +3344,19 @@ await page.GetByRole("button", new() { Name = "Start here" }).ClickAsync();
Locator that triggers the handler.
### param: Page.addLocatorHandler.handler
* langs: js, python, csharp
* langs: js, python
* since: v1.42
- `handler` <[function]>
Function that should be run once [`param: locator`] appears. This function should get rid of the element that blocks actions like click.
### param: Page.addLocatorHandler.handler
* langs: csharp
* since: v1.42
- `handler` <[function](): [Promise<any>]>
Function that should be run once [`param: locator`] appears. This function should get rid of the element that blocks actions like click.
### param: Page.addLocatorHandler.handler
* langs: java
* since: v1.42

4605
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -3,43 +3,43 @@
"browsers": [
{
"name": "chromium",
"revision": "1104",
"revision": "1105",
"installByDefault": true,
"browserVersion": "122.0.6261.57"
"browserVersion": "123.0.6312.4"
},
{
"name": "chromium-with-symbols",
"revision": "1104",
"revision": "1105",
"installByDefault": false,
"browserVersion": "122.0.6261.57"
"browserVersion": "123.0.6312.4"
},
{
"name": "chromium-tip-of-tree",
"revision": "1194",
"revision": "1195",
"installByDefault": false,
"browserVersion": "123.0.6302.0"
"browserVersion": "123.0.6312.0"
},
{
"name": "firefox",
"revision": "1439",
"revision": "1440",
"installByDefault": true,
"browserVersion": "122.0"
"browserVersion": "123.0"
},
{
"name": "firefox-asan",
"revision": "1439",
"revision": "1440",
"installByDefault": false,
"browserVersion": "122.0"
"browserVersion": "123.0"
},
{
"name": "firefox-beta",
"revision": "1439",
"revision": "1440",
"installByDefault": false,
"browserVersion": "123.0b3"
"browserVersion": "124.0b3"
},
{
"name": "webkit",
"revision": "1982",
"revision": "1983",
"installByDefault": true,
"revisionOverrides": {
"mac10.14": "1446",

View file

@ -287,11 +287,8 @@ export class CRNetworkManager {
if (requestPausedEvent) {
// We do not support intercepting redirects.
if (redirectedFrom || (!this._userRequestInterceptionEnabled && this._protocolRequestInterceptionEnabled)) {
let headers = undefined;
const previousHeaderOverrides = redirectedFrom?._originalRequestRoute?._alreadyContinuedParams?.headers;
// Chromium does not preserve header overrides between redirects, so we have to do it ourselves.
if (previousHeaderOverrides)
headers = network.mergeHeaders([headersObjectToArray(requestPausedEvent.request.headers, '\n'), previousHeaderOverrides]);
const headers = redirectedFrom?._originalRequestRoute?._alreadyContinuedParams?.headers;
this._session._sendMayFail('Fetch.continueRequest', { requestId: requestPausedEvent.requestId, headers });
} else {
route = new RouteImpl(this._session, requestPausedEvent.requestId);

View file

@ -245,7 +245,7 @@ If omitted, the full tree is returned.
depth?: number;
/**
* The frame for whose document the AX tree should be retrieved.
If omited, the root frame is used.
If omitted, the root frame is used.
*/
frameId?: Page.FrameId;
}
@ -305,7 +305,7 @@ If omitted, the root frame is used.
/**
* Query a DOM node's accessibility subtree for accessible name and role.
This command computes the name and role for all nodes in the subtree, including those that are
ignored for accessibility, and returns those that mactch the specified name and role. If no DOM
ignored for accessibility, and returns those that match the specified name and role. If no DOM
node is specified, or the DOM node does not exist, the command returns an error. If neither
`accessibleName` or `role` is specified, it returns all the accessibility nodes in the subtree.
*/
@ -367,6 +367,9 @@ including nodes that are ignored for accessibility.
playbackRate: number;
/**
* `Animation`'s start time.
Milliseconds for time based animations and
percentage [0 - 100] for scroll driven animations
(i.e. when viewOrScrollTimeline exists).
*/
startTime: number;
/**
@ -386,6 +389,39 @@ including nodes that are ignored for accessibility.
animation/transition.
*/
cssId?: string;
/**
* View or scroll timeline
*/
viewOrScrollTimeline?: ViewOrScrollTimeline;
}
/**
* Timeline instance
*/
export interface ViewOrScrollTimeline {
/**
* Scroll container node
*/
sourceNodeId?: DOM.BackendNodeId;
/**
* Represents the starting scroll position of the timeline
as a length offset in pixels from scroll origin.
*/
startOffset?: number;
/**
* Represents the ending scroll position of the timeline
as a length offset in pixels from scroll origin.
*/
endOffset?: number;
/**
* The element whose principal box's visibility in the
scrollport defined the progress of the timeline.
Does not exist for animations with ScrollTimeline
*/
subjectNodeId?: DOM.BackendNodeId;
/**
* Orientation of the scroll
*/
axis: DOM.ScrollOrientation;
}
/**
* AnimationEffect instance
@ -409,6 +445,9 @@ animation/transition.
iterations: number;
/**
* `AnimationEffect`'s iteration duration.
Milliseconds for time based animations and
percentage [0 - 100] for scroll driven animations
(i.e. when viewOrScrollTimeline exists).
*/
duration: number;
/**
@ -1132,7 +1171,7 @@ Munich 81456
*/
export interface AddressUI {
/**
* A two dimension array containing the repesentation of values from an address profile.
* A two dimension array containing the representation of values from an address profile.
*/
addressFields: AddressFields[];
}
@ -1165,6 +1204,10 @@ Munich 81456
* The filling strategy
*/
fillingStrategy: FillingStrategy;
/**
* The frame the field belongs to
*/
frameId: Page.FrameId;
/**
* The form field's DOM node
*/
@ -1367,7 +1410,7 @@ events afterwards if enabled and recording.
*/
windowState?: WindowState;
}
export type PermissionType = "accessibilityEvents"|"audioCapture"|"backgroundSync"|"backgroundFetch"|"capturedSurfaceControl"|"clipboardReadWrite"|"clipboardSanitizedWrite"|"displayCapture"|"durableStorage"|"flash"|"geolocation"|"idleDetection"|"localFonts"|"midi"|"midiSysex"|"nfc"|"notifications"|"paymentHandler"|"periodicBackgroundSync"|"protectedMediaIdentifier"|"sensors"|"storageAccess"|"topLevelStorageAccess"|"videoCapture"|"videoCapturePanTiltZoom"|"wakeLockScreen"|"wakeLockSystem"|"windowManagement";
export type PermissionType = "accessibilityEvents"|"audioCapture"|"backgroundSync"|"backgroundFetch"|"capturedSurfaceControl"|"clipboardReadWrite"|"clipboardSanitizedWrite"|"displayCapture"|"durableStorage"|"flash"|"geolocation"|"idleDetection"|"localFonts"|"midi"|"midiSysex"|"nfc"|"notifications"|"paymentHandler"|"periodicBackgroundSync"|"protectedMediaIdentifier"|"sensors"|"storageAccess"|"speakerSelection"|"topLevelStorageAccess"|"videoCapture"|"videoCapturePanTiltZoom"|"wakeLockScreen"|"wakeLockSystem"|"windowManagement";
export type PermissionSetting = "granted"|"denied"|"prompt";
/**
* Definition of PermissionDescriptor defined in the Permissions API:
@ -1540,7 +1583,7 @@ Note that userVisibleOnly = true is the only currently supported type.
/**
* Whether to allow all or deny all download requests, or use default Chrome behavior if
available (otherwise deny). |allowAndName| allows download and names files according to
their dowmload guids.
their download guids.
*/
behavior: "deny"|"allow"|"allowAndName"|"default";
/**
@ -1888,7 +1931,7 @@ pseudo-classes.
frameId: Page.FrameId;
/**
* Stylesheet resource URL. Empty if this is a constructed stylesheet created using
new CSSStyleSheet() (but non-empty if this is a constructed sylesheet imported
new CSSStyleSheet() (but non-empty if this is a constructed stylesheet imported
as a CSS module script).
*/
sourceURL: string;
@ -3378,6 +3421,10 @@ front-end.
* ContainerSelector logical axes
*/
export type LogicalAxes = "Inline"|"Block"|"Both";
/**
* Physical scroll orientation
*/
export type ScrollOrientation = "horizontal"|"vertical";
/**
* DOM interaction is implemented in terms of mirror objects that represent the actual DOM nodes.
DOMNode is a base node mirror type.
@ -3951,7 +3998,7 @@ be called for that search.
*/
export type getAttributesParameters = {
/**
* Id of the node to retrieve attibutes for.
* Id of the node to retrieve attributes for.
*/
nodeId: NodeId;
}
@ -5679,14 +5726,14 @@ resource fetches.
*/
export type VirtualTimePolicy = "advance"|"pause"|"pauseIfNetworkFetchesPending";
/**
* Used to specify User Agent Cient Hints to emulate. See https://wicg.github.io/ua-client-hints
* Used to specify User Agent Client Hints to emulate. See https://wicg.github.io/ua-client-hints
*/
export interface UserAgentBrandVersion {
brand: string;
version: string;
}
/**
* Used to specify User Agent Cient Hints to emulate. See https://wicg.github.io/ua-client-hints
* Used to specify User Agent Client Hints to emulate. See https://wicg.github.io/ua-client-hints
Missing optional values will be filled in by the target with what it would normally use.
*/
export interface UserAgentMetadata {
@ -5990,7 +6037,7 @@ Sensor.start() will attempt to use a real sensor instead.
export type setSensorOverrideEnabledReturnValue = {
}
/**
* Updates the sensor readings reported by a sensor type previously overriden
* Updates the sensor readings reported by a sensor type previously overridden
by setSensorOverrideEnabled.
*/
export type setSensorOverrideReadingsParameters = {
@ -6113,8 +6160,9 @@ restores default host system locale.
*/
export type setTimezoneOverrideParameters = {
/**
* The timezone identifier. If empty, disables the override and
restores default host system timezone.
* The timezone identifier. List of supported timezones:
https://source.chromium.org/chromium/chromium/deps/icu.git/+/faee8bc70570192d82d2978a71e2a615788597d1:source/data/misc/metaZones.txt
If empty, disables the override and restores default host system timezone.
*/
timezoneId: string;
}
@ -6155,6 +6203,7 @@ on Android.
}
/**
* Allows overriding user agent with the given string.
`userAgentMetadata` must be set for Client Hint headers to be sent.
*/
export type setUserAgentOverrideParameters = {
/**
@ -6300,7 +6349,7 @@ display. Reported for diagnostic uses, may be removed in the future.
*/
handle: StreamHandle;
/**
* Seek to the specified offset before reading (if not specificed, proceed with offset
* Seek to the specified offset before reading (if not specified, proceed with offset
following the last read). Some types of streams may only support sequential reads.
*/
offset?: number;
@ -6926,7 +6975,7 @@ for example an emoji keyboard or an IME.
export type insertTextReturnValue = {
}
/**
* This method sets the current candidate text for ime.
* This method sets the current candidate text for IME.
Use imeCommitComposition to commit the final text.
Use imeSetComposition with empty string as text to cancel composition.
*/
@ -7425,7 +7474,7 @@ transform/scrolling purposes only.
}
export type layerTreeDidChangePayload = {
/**
* Layer tree, absent if not in the comspositing mode.
* Layer tree, absent if not in the compositing mode.
*/
layers?: Layer[];
}
@ -8036,7 +8085,7 @@ passed by the developer (e.g. via "fetch") as understood by the backend.
trustTokenParams?: TrustTokenParams;
/**
* True if this resource request is considered to be the 'same site' as the
request correspondinfg to the main frame.
request corresponding to the main frame.
*/
isSameSite?: boolean;
}
@ -8188,8 +8237,13 @@ records.
* The reason why Chrome uses a specific transport protocol for HTTP semantics.
*/
export type AlternateProtocolUsage = "alternativeJobWonWithoutRace"|"alternativeJobWonRace"|"mainJobWonRace"|"mappingMissing"|"broken"|"dnsAlpnH3JobWonWithoutRace"|"dnsAlpnH3JobWonRace"|"unspecifiedReason";
/**
* Source of service worker router.
*/
export type ServiceWorkerRouterSource = "network"|"cache"|"fetch-event"|"race-network-and-fetch-handler";
export interface ServiceWorkerRouterInfo {
ruleIdMatched: number;
matchedSourceType: ServiceWorkerRouterSource;
}
/**
* HTTP response data.
@ -8260,7 +8314,7 @@ records.
*/
fromPrefetchCache?: boolean;
/**
* Infomation about how Service Worker Static Router was used.
* Information about how Service Worker Static Router was used.
*/
serviceWorkerRouterInfo?: ServiceWorkerRouterInfo;
/**
@ -8489,6 +8543,10 @@ of the request to the endpoint that set the cookie.
* Types of reasons why a cookie may not be sent with a request.
*/
export type CookieBlockedReason = "SecureOnly"|"NotOnPath"|"DomainMismatch"|"SameSiteStrict"|"SameSiteLax"|"SameSiteUnspecifiedTreatedAsLax"|"SameSiteNoneInsecure"|"UserPreferences"|"ThirdPartyPhaseout"|"ThirdPartyBlockedInFirstPartySet"|"UnknownError"|"SchemefulSameSiteStrict"|"SchemefulSameSiteLax"|"SchemefulSameSiteUnspecifiedTreatedAsLax"|"SamePartyFromCrossPartyContext"|"NameValuePairExceedsMaxSize";
/**
* Types of reasons why a cookie should have been blocked by 3PCD but is exempted for the request.
*/
export type CookieExemptionReason = "None"|"UserSetting"|"TPCDMetadata"|"TPCDDeprecationTrial"|"TPCDHeuristics"|"EnterprisePolicy"|"StorageAccess"|"TopLevelStorageAccess"|"CorsOptIn";
/**
* A cookie which was not stored from a response with the corresponding reason.
*/
@ -8510,17 +8568,37 @@ errors.
cookie?: Cookie;
}
/**
* A cookie with was not sent with a request with the corresponding reason.
* A cookie should have been blocked by 3PCD but is exempted and stored from a response with the
corresponding reason. A cookie could only have at most one exemption reason.
*/
export interface BlockedCookieWithReason {
export interface ExemptedSetCookieWithReason {
/**
* The reason(s) the cookie was blocked.
* The reason the cookie was exempted.
*/
blockedReasons: CookieBlockedReason[];
exemptionReason: CookieExemptionReason;
/**
* The cookie object representing the cookie.
*/
cookie: Cookie;
}
/**
* A cookie associated with the request which may or may not be sent with it.
Includes the cookies itself and reasons for blocking or exemption.
*/
export interface AssociatedCookie {
/**
* The cookie object representing the cookie which was not sent.
*/
cookie: Cookie;
/**
* The reason(s) the cookie was blocked. If empty means the cookie is included.
*/
blockedReasons: CookieBlockedReason[];
/**
* The reason the cookie should have been blocked by 3PCD but is exempted. A cookie could
only have at most one exemption reason.
*/
exemptionReason?: CookieExemptionReason;
}
/**
* Cookie parameter object
@ -8759,7 +8837,7 @@ https://wicg.github.io/webpackage/draft-yasskin-httpbis-origin-signed-exchanges-
*/
securityDetails?: SecurityDetails;
/**
* Errors occurred while handling the signed exchagne.
* Errors occurred while handling the signed exchange.
*/
errors?: SignedExchangeError[];
}
@ -8950,7 +9028,7 @@ CORB and streaming.
*/
type: ResourceType;
/**
* User friendly error message.
* Error message. List of network errors: https://cs.chromium.org/chromium/src/net/base/net_error_list.h
*/
errorText: string;
/**
@ -9350,9 +9428,9 @@ or requestWillBeSentExtraInfo will be fired first for the same request.
requestId: RequestId;
/**
* A list of cookies potentially associated to the requested URL. This includes both cookies sent with
the request and the ones not sent; the latter are distinguished by having blockedReason field set.
the request and the ones not sent; the latter are distinguished by having blockedReasons field set.
*/
associatedCookies: BlockedCookieWithReason[];
associatedCookies: AssociatedCookie[];
/**
* Raw request headers as they will be sent over the wire.
*/
@ -9412,9 +9490,14 @@ Only sent when partitioned cookies are enabled.
*/
cookiePartitionKey?: string;
/**
* True if partitioned cookies are enabled, but the partition key is not serializeable to string.
* True if partitioned cookies are enabled, but the partition key is not serializable to string.
*/
cookiePartitionKeyOpaque?: boolean;
/**
* A list of cookies which should have been blocked by 3PCD but are exempted and stored from
the response with the corresponding reason.
*/
exemptedCookies?: ExemptedSetCookieWithReason[];
}
/**
* Fired exactly once for each Trust Token operation. Depending on
@ -9645,7 +9728,7 @@ authChallenge.
export type continueInterceptedRequestReturnValue = {
}
/**
* Deletes browser cookies with matching name and url or domain/path pair.
* Deletes browser cookies with matching name and url or domain/path/partitionKey pair.
*/
export type deleteCookiesParameters = {
/**
@ -9665,6 +9748,11 @@ provided URL.
* If specified, deletes only cookies with the exact path.
*/
path?: string;
/**
* If specified, deletes only cookies with the the given name and partitionKey where domain
matches provided URL.
*/
partitionKey?: string;
}
export type deleteCookiesReturnValue = {
}
@ -10115,7 +10203,7 @@ should be omitted for worker targets.
*/
export interface SourceOrderConfig {
/**
* the color to outline the givent element in.
* the color to outline the given element in.
*/
parentOutlineColor: DOM.RGBA;
/**
@ -10448,7 +10536,7 @@ should be omitted for worker targets.
*/
showCSS: boolean;
/**
* Seleted platforms to show the overlay.
* Selected platforms to show the overlay.
*/
selectedPlatform: string;
/**
@ -10616,8 +10704,8 @@ user manually inspects an element.
}
/**
* Highlights owner element of the frame with given id.
Deprecated: Doesn't work reliablity and cannot be fixed due to process
separatation (the owner node might be in a different process). Determine
Deprecated: Doesn't work reliably and cannot be fixed due to process
separation (the owner node might be in a different process). Determine
the owner node in the client and use highlightNode.
*/
export type highlightFrameParameters = {
@ -10977,7 +11065,7 @@ as an ad.
* All Permissions Policy features. This enum should match the one defined
in third_party/blink/renderer/core/permissions_policy/permissions_policy_features.json5.
*/
export type PermissionsPolicyFeature = "accelerometer"|"ambient-light-sensor"|"attribution-reporting"|"autoplay"|"bluetooth"|"browsing-topics"|"camera"|"captured-surface-control"|"ch-dpr"|"ch-device-memory"|"ch-downlink"|"ch-ect"|"ch-prefers-color-scheme"|"ch-prefers-reduced-motion"|"ch-prefers-reduced-transparency"|"ch-rtt"|"ch-save-data"|"ch-ua"|"ch-ua-arch"|"ch-ua-bitness"|"ch-ua-platform"|"ch-ua-model"|"ch-ua-mobile"|"ch-ua-form-factor"|"ch-ua-full-version"|"ch-ua-full-version-list"|"ch-ua-platform-version"|"ch-ua-wow64"|"ch-viewport-height"|"ch-viewport-width"|"ch-width"|"clipboard-read"|"clipboard-write"|"compute-pressure"|"cross-origin-isolated"|"direct-sockets"|"display-capture"|"document-domain"|"encrypted-media"|"execution-while-out-of-viewport"|"execution-while-not-rendered"|"focus-without-user-activation"|"fullscreen"|"frobulate"|"gamepad"|"geolocation"|"gyroscope"|"hid"|"identity-credentials-get"|"idle-detection"|"interest-cohort"|"join-ad-interest-group"|"keyboard-map"|"local-fonts"|"magnetometer"|"microphone"|"midi"|"otp-credentials"|"payment"|"picture-in-picture"|"private-aggregation"|"private-state-token-issuance"|"private-state-token-redemption"|"publickey-credentials-create"|"publickey-credentials-get"|"run-ad-auction"|"screen-wake-lock"|"serial"|"shared-autofill"|"shared-storage"|"shared-storage-select-url"|"smart-card"|"storage-access"|"sub-apps"|"sync-xhr"|"unload"|"usb"|"usb-unrestricted"|"vertical-scroll"|"web-printing"|"web-share"|"window-management"|"window-placement"|"xr-spatial-tracking";
export type PermissionsPolicyFeature = "accelerometer"|"ambient-light-sensor"|"attribution-reporting"|"autoplay"|"bluetooth"|"browsing-topics"|"camera"|"captured-surface-control"|"ch-dpr"|"ch-device-memory"|"ch-downlink"|"ch-ect"|"ch-prefers-color-scheme"|"ch-prefers-reduced-motion"|"ch-prefers-reduced-transparency"|"ch-rtt"|"ch-save-data"|"ch-ua"|"ch-ua-arch"|"ch-ua-bitness"|"ch-ua-platform"|"ch-ua-model"|"ch-ua-mobile"|"ch-ua-form-factor"|"ch-ua-full-version"|"ch-ua-full-version-list"|"ch-ua-platform-version"|"ch-ua-wow64"|"ch-viewport-height"|"ch-viewport-width"|"ch-width"|"clipboard-read"|"clipboard-write"|"compute-pressure"|"cross-origin-isolated"|"direct-sockets"|"display-capture"|"document-domain"|"encrypted-media"|"execution-while-out-of-viewport"|"execution-while-not-rendered"|"focus-without-user-activation"|"fullscreen"|"frobulate"|"gamepad"|"geolocation"|"gyroscope"|"hid"|"identity-credentials-get"|"idle-detection"|"interest-cohort"|"join-ad-interest-group"|"keyboard-map"|"local-fonts"|"magnetometer"|"microphone"|"midi"|"otp-credentials"|"payment"|"picture-in-picture"|"private-aggregation"|"private-state-token-issuance"|"private-state-token-redemption"|"publickey-credentials-create"|"publickey-credentials-get"|"run-ad-auction"|"screen-wake-lock"|"serial"|"shared-autofill"|"shared-storage"|"shared-storage-select-url"|"smart-card"|"speaker-selection"|"storage-access"|"sub-apps"|"sync-xhr"|"unload"|"usb"|"usb-unrestricted"|"vertical-scroll"|"web-printing"|"web-share"|"window-management"|"window-placement"|"xr-spatial-tracking";
/**
* Reason for a permissions policy feature to be disabled.
*/
@ -11229,7 +11317,7 @@ Example URLs: http://www.google.com/file.html -> "google.com"
*/
message: string;
/**
* If criticial, this is a non-recoverable parse error.
* If critical, this is a non-recoverable parse error.
*/
critical: number;
/**
@ -11436,7 +11524,7 @@ Example URLs: http://www.google.com/file.html -> "google.com"
eager?: boolean;
}
/**
* Enum of possible auto-reponse for permisison / prompt dialogs.
* Enum of possible auto-response for permission / prompt dialogs.
*/
export type AutoResponseMode = "none"|"autoAccept"|"autoReject"|"autoOptOut";
/**
@ -11446,7 +11534,7 @@ Example URLs: http://www.google.com/file.html -> "google.com"
/**
* List of not restored reasons for back-forward cache.
*/
export type BackForwardCacheNotRestoredReason = "NotPrimaryMainFrame"|"BackForwardCacheDisabled"|"RelatedActiveContentsExist"|"HTTPStatusNotOK"|"SchemeNotHTTPOrHTTPS"|"Loading"|"WasGrantedMediaAccess"|"DisableForRenderFrameHostCalled"|"DomainNotAllowed"|"HTTPMethodNotGET"|"SubframeIsNavigating"|"Timeout"|"CacheLimit"|"JavaScriptExecution"|"RendererProcessKilled"|"RendererProcessCrashed"|"SchedulerTrackedFeatureUsed"|"ConflictingBrowsingInstance"|"CacheFlushed"|"ServiceWorkerVersionActivation"|"SessionRestored"|"ServiceWorkerPostMessage"|"EnteredBackForwardCacheBeforeServiceWorkerHostAdded"|"RenderFrameHostReused_SameSite"|"RenderFrameHostReused_CrossSite"|"ServiceWorkerClaim"|"IgnoreEventAndEvict"|"HaveInnerContents"|"TimeoutPuttingInCache"|"BackForwardCacheDisabledByLowMemory"|"BackForwardCacheDisabledByCommandLine"|"NetworkRequestDatapipeDrainedAsBytesConsumer"|"NetworkRequestRedirected"|"NetworkRequestTimeout"|"NetworkExceedsBufferLimit"|"NavigationCancelledWhileRestoring"|"NotMostRecentNavigationEntry"|"BackForwardCacheDisabledForPrerender"|"UserAgentOverrideDiffers"|"ForegroundCacheLimit"|"BrowsingInstanceNotSwapped"|"BackForwardCacheDisabledForDelegate"|"UnloadHandlerExistsInMainFrame"|"UnloadHandlerExistsInSubFrame"|"ServiceWorkerUnregistration"|"CacheControlNoStore"|"CacheControlNoStoreCookieModified"|"CacheControlNoStoreHTTPOnlyCookieModified"|"NoResponseHead"|"Unknown"|"ActivationNavigationsDisallowedForBug1234857"|"ErrorDocument"|"FencedFramesEmbedder"|"CookieDisabled"|"HTTPAuthRequired"|"CookieFlushed"|"WebSocket"|"WebTransport"|"WebRTC"|"MainResourceHasCacheControlNoStore"|"MainResourceHasCacheControlNoCache"|"SubresourceHasCacheControlNoStore"|"SubresourceHasCacheControlNoCache"|"ContainsPlugins"|"DocumentLoaded"|"DedicatedWorkerOrWorklet"|"OutstandingNetworkRequestOthers"|"RequestedMIDIPermission"|"RequestedAudioCapturePermission"|"RequestedVideoCapturePermission"|"RequestedBackForwardCacheBlockedSensors"|"RequestedBackgroundWorkPermission"|"BroadcastChannel"|"WebXR"|"SharedWorker"|"WebLocks"|"WebHID"|"WebShare"|"RequestedStorageAccessGrant"|"WebNfc"|"OutstandingNetworkRequestFetch"|"OutstandingNetworkRequestXHR"|"AppBanner"|"Printing"|"WebDatabase"|"PictureInPicture"|"Portal"|"SpeechRecognizer"|"IdleManager"|"PaymentManager"|"SpeechSynthesis"|"KeyboardLock"|"WebOTPService"|"OutstandingNetworkRequestDirectSocket"|"InjectedJavascript"|"InjectedStyleSheet"|"KeepaliveRequest"|"IndexedDBEvent"|"Dummy"|"JsNetworkRequestReceivedCacheControlNoStoreResource"|"WebRTCSticky"|"WebTransportSticky"|"WebSocketSticky"|"SmartCard"|"LiveMediaStreamTrack"|"UnloadHandler"|"ContentSecurityHandler"|"ContentWebAuthenticationAPI"|"ContentFileChooser"|"ContentSerial"|"ContentFileSystemAccess"|"ContentMediaDevicesDispatcherHost"|"ContentWebBluetooth"|"ContentWebUSB"|"ContentMediaSessionService"|"ContentScreenReader"|"EmbedderPopupBlockerTabHelper"|"EmbedderSafeBrowsingTriggeredPopupBlocker"|"EmbedderSafeBrowsingThreatDetails"|"EmbedderAppBannerManager"|"EmbedderDomDistillerViewerSource"|"EmbedderDomDistillerSelfDeletingRequestDelegate"|"EmbedderOomInterventionTabHelper"|"EmbedderOfflinePage"|"EmbedderChromePasswordManagerClientBindCredentialManager"|"EmbedderPermissionRequestManager"|"EmbedderModalDialog"|"EmbedderExtensions"|"EmbedderExtensionMessaging"|"EmbedderExtensionMessagingForOpenPort"|"EmbedderExtensionSentMessageToCachedFrame";
export type BackForwardCacheNotRestoredReason = "NotPrimaryMainFrame"|"BackForwardCacheDisabled"|"RelatedActiveContentsExist"|"HTTPStatusNotOK"|"SchemeNotHTTPOrHTTPS"|"Loading"|"WasGrantedMediaAccess"|"DisableForRenderFrameHostCalled"|"DomainNotAllowed"|"HTTPMethodNotGET"|"SubframeIsNavigating"|"Timeout"|"CacheLimit"|"JavaScriptExecution"|"RendererProcessKilled"|"RendererProcessCrashed"|"SchedulerTrackedFeatureUsed"|"ConflictingBrowsingInstance"|"CacheFlushed"|"ServiceWorkerVersionActivation"|"SessionRestored"|"ServiceWorkerPostMessage"|"EnteredBackForwardCacheBeforeServiceWorkerHostAdded"|"RenderFrameHostReused_SameSite"|"RenderFrameHostReused_CrossSite"|"ServiceWorkerClaim"|"IgnoreEventAndEvict"|"HaveInnerContents"|"TimeoutPuttingInCache"|"BackForwardCacheDisabledByLowMemory"|"BackForwardCacheDisabledByCommandLine"|"NetworkRequestDatapipeDrainedAsBytesConsumer"|"NetworkRequestRedirected"|"NetworkRequestTimeout"|"NetworkExceedsBufferLimit"|"NavigationCancelledWhileRestoring"|"NotMostRecentNavigationEntry"|"BackForwardCacheDisabledForPrerender"|"UserAgentOverrideDiffers"|"ForegroundCacheLimit"|"BrowsingInstanceNotSwapped"|"BackForwardCacheDisabledForDelegate"|"UnloadHandlerExistsInMainFrame"|"UnloadHandlerExistsInSubFrame"|"ServiceWorkerUnregistration"|"CacheControlNoStore"|"CacheControlNoStoreCookieModified"|"CacheControlNoStoreHTTPOnlyCookieModified"|"NoResponseHead"|"Unknown"|"ActivationNavigationsDisallowedForBug1234857"|"ErrorDocument"|"FencedFramesEmbedder"|"CookieDisabled"|"HTTPAuthRequired"|"CookieFlushed"|"WebSocket"|"WebTransport"|"WebRTC"|"MainResourceHasCacheControlNoStore"|"MainResourceHasCacheControlNoCache"|"SubresourceHasCacheControlNoStore"|"SubresourceHasCacheControlNoCache"|"ContainsPlugins"|"DocumentLoaded"|"OutstandingNetworkRequestOthers"|"RequestedMIDIPermission"|"RequestedAudioCapturePermission"|"RequestedVideoCapturePermission"|"RequestedBackForwardCacheBlockedSensors"|"RequestedBackgroundWorkPermission"|"BroadcastChannel"|"WebXR"|"SharedWorker"|"WebLocks"|"WebHID"|"WebShare"|"RequestedStorageAccessGrant"|"WebNfc"|"OutstandingNetworkRequestFetch"|"OutstandingNetworkRequestXHR"|"AppBanner"|"Printing"|"WebDatabase"|"PictureInPicture"|"Portal"|"SpeechRecognizer"|"IdleManager"|"PaymentManager"|"SpeechSynthesis"|"KeyboardLock"|"WebOTPService"|"OutstandingNetworkRequestDirectSocket"|"InjectedJavascript"|"InjectedStyleSheet"|"KeepaliveRequest"|"IndexedDBEvent"|"Dummy"|"JsNetworkRequestReceivedCacheControlNoStoreResource"|"WebRTCSticky"|"WebTransportSticky"|"WebSocketSticky"|"SmartCard"|"LiveMediaStreamTrack"|"UnloadHandler"|"ContentSecurityHandler"|"ContentWebAuthenticationAPI"|"ContentFileChooser"|"ContentSerial"|"ContentFileSystemAccess"|"ContentMediaDevicesDispatcherHost"|"ContentWebBluetooth"|"ContentWebUSB"|"ContentMediaSessionService"|"ContentScreenReader"|"EmbedderPopupBlockerTabHelper"|"EmbedderSafeBrowsingTriggeredPopupBlocker"|"EmbedderSafeBrowsingThreatDetails"|"EmbedderAppBannerManager"|"EmbedderDomDistillerViewerSource"|"EmbedderDomDistillerSelfDeletingRequestDelegate"|"EmbedderOomInterventionTabHelper"|"EmbedderOfflinePage"|"EmbedderChromePasswordManagerClientBindCredentialManager"|"EmbedderPermissionRequestManager"|"EmbedderModalDialog"|"EmbedderExtensions"|"EmbedderExtensionMessaging"|"EmbedderExtensionMessagingForOpenPort"|"EmbedderExtensionSentMessageToCachedFrame";
/**
* Types of not restored reasons for back-forward cache.
*/
@ -11723,7 +11811,7 @@ open.
*/
type: DialogType;
/**
* True iff browser is capable showing or acting on the given dialog. When browser has no
* True if browser is capable showing or acting on the given dialog. When browser has no
dialog handler for given target, calling alert while Page domain is engaged will stall
the page execution. Execution can be resumed via calling Page.handleJavaScriptDialog.
*/
@ -11756,7 +11844,7 @@ when bfcache navigation fails.
*/
export type backForwardCacheNotUsedPayload = {
/**
* The loader id for the associated navgation.
* The loader id for the associated navigation.
*/
loaderId: Network.LoaderId;
/**
@ -12704,7 +12792,7 @@ https://github.com/WICG/web-lifecycle/
}
/**
* Requests backend to produce compilation cache for the specified scripts.
`scripts` are appeneded to the list of scripts for which the cache
`scripts` are appended to the list of scripts for which the cache
would be produced. The list may be reset during page navigation.
When script with a matching URL is encountered, the cache is optionally
produced upon backend discretion, based on internal heuristics.
@ -12923,7 +13011,7 @@ https://w3c.github.io/performance-timeline/#dom-performanceobserver.
frameId: Page.FrameId;
/**
* The event type, as specified in https://w3c.github.io/performance-timeline/#dom-performanceentry-entrytype
This determines which of the optional "details" fiedls is present.
This determines which of the optional "details" fields is present.
*/
type: string;
/**
@ -13033,7 +13121,7 @@ https://www.w3.org/TR/mixed-content/#categories
*/
certificateNetworkError?: string;
/**
* True if the certificate uses a weak signature aglorithm.
* True if the certificate uses a weak signature algorithm.
*/
certificateHasWeakSignature: boolean;
/**
@ -13441,6 +13529,10 @@ Tokens from that issuer.
* Enum of auction events.
*/
export type InterestGroupAuctionEventType = "started"|"configResolved";
/**
* Enum of network fetches auctions can do.
*/
export type InterestGroupAuctionFetchType = "bidderJs"|"bidderWasm"|"sellerJs"|"bidderTrustedSignals"|"sellerTrustedSignals";
/**
* Ad advertising element inside an interest group.
*/
@ -13480,9 +13572,23 @@ Tokens from that issuer.
* Details for an origin's shared storage.
*/
export interface SharedStorageMetadata {
/**
* Time when the origin's shared storage was last created.
*/
creationTime: Network.TimeSinceEpoch;
/**
* Number of key-value pairs stored in origin's shared storage.
*/
length: number;
/**
* Current amount of bits of entropy remaining in the navigation budget.
*/
remainingBudget: number;
/**
* Total number of bytes stored as key-value pairs in origin's shared
storage.
*/
bytesUsed: number;
}
/**
* Pair of reporting metadata details for a candidate URL for `selectURL()`.
@ -13642,7 +13748,7 @@ int
}
export type AttributionReportingSourceRegistrationResult = "success"|"internalError"|"insufficientSourceCapacity"|"insufficientUniqueDestinationCapacity"|"excessiveReportingOrigins"|"prohibitedByBrowserPolicy"|"successNoised"|"destinationReportingLimitReached"|"destinationGlobalLimitReached"|"destinationBothLimitsReached"|"reportingOriginsPerSiteLimitReached"|"exceedsMaxChannelCapacity";
export type AttributionReportingSourceRegistrationTimeConfig = "include"|"exclude";
export interface AttributionReportingAggregatableValueEntry {
export interface AttributionReportingAggregatableValueDictEntry {
key: string;
/**
* number instead of integer because not all uint32 can be represented by
@ -13650,6 +13756,10 @@ int
*/
value: number;
}
export interface AttributionReportingAggregatableValueEntry {
values: AttributionReportingAggregatableValueDictEntry[];
filters: AttributionReportingFilterPair;
}
export interface AttributionReportingEventTriggerData {
data: UnsignedInt64AsBase10;
priority: SignedInt64AsBase10;
@ -13801,6 +13911,22 @@ target-specific.
*/
auctionConfig?: { [key: string]: string };
}
/**
* Specifies which auctions a particular network fetch may be related to, and
in what role. Note that it is not ordered with respect to
Network.requestWillBeSent (but will happen before loadingFinished
loadingFailed).
*/
export type interestGroupAuctionNetworkRequestCreatedPayload = {
type: InterestGroupAuctionFetchType;
requestId: Network.RequestId;
/**
* This is the set of the auctions using the worklet that issued this
request. In the case of trusted signals, it's possible that only some of
them actually care about the keys being queried.
*/
auctions: InterestGroupAuctionId[];
}
/**
* Shared storage was accessed by the associated page.
The following parameters are included in all events.
@ -13823,7 +13949,7 @@ The following parameters are included in all events.
*/
ownerOrigin: string;
/**
* The sub-parameters warapped by `params` are all optional and their
* The sub-parameters wrapped by `params` are all optional and their
presence/absence depends on `type`.
*/
params: SharedStorageAccessParams;
@ -14101,7 +14227,8 @@ Leaves other stored data, including the issuer's Redemption Records, intact.
export type setInterestGroupTrackingReturnValue = {
}
/**
* Enables/Disables issuing of interestGroupAuctionEvent events.
* Enables/Disables issuing of interestGroupAuctionEventOccurred and
interestGroupAuctionNetworkRequestCreated.
*/
export type setInterestGroupAuctionTrackingParameters = {
enable: boolean;
@ -14456,6 +14583,9 @@ supported.
export interface TargetInfo {
targetId: TargetID;
type: string;
/**
* List of types: https://source.chromium.org/chromium/chromium/src/+/main:content/browser/devtools/devtools_agent_host_impl.cc?ss=chromium&q=f:devtools%20-f:out%20%22::kTypeTab%5B%5D%22
*/
title: string;
url: string;
/**
@ -14486,7 +14616,7 @@ the type of "page", this may be set to "portal" or "prerender".
*/
export interface FilterEntry {
/**
* If set, causes exclusion of mathcing targets from the list.
* If set, causes exclusion of matching targets from the list.
*/
exclude?: boolean;
/**
@ -14637,7 +14767,7 @@ channel with browser target.
Injected object will be available as `window[bindingName]`.
The object has the follwing API:
The object has the following API:
- `binding.send(json)` - a method to send messages over the remote debugging protocol
- `binding.onmessage = json => handleMessage(json)` - a callback that will be called for the protocol notifications and command responses.
*/
@ -15850,6 +15980,18 @@ See https://w3c.github.io/webauthn/#signature-counter
See https://w3c.github.io/webauthn/#sctn-large-blob-extension
*/
largeBlob?: binary;
/**
* Assertions returned by this credential will have the backup eligibility
(BE) flag set to this value. Defaults to the authenticator's
defaultBackupEligibility value.
*/
backupEligibility?: boolean;
/**
* Assertions returned by this credential will have the backup state (BS)
flag set to this value. Defaults to the authenticator's
defaultBackupState value.
*/
backupState?: boolean;
}
/**
@ -15996,6 +16138,18 @@ The default is true.
}
export type setAutomaticPresenceSimulationReturnValue = {
}
/**
* Allows setting credential properties.
https://w3c.github.io/webauthn/#sctn-automation-set-credential-properties
*/
export type setCredentialPropertiesParameters = {
authenticatorId: AuthenticatorId;
credentialId: binary;
backupEligibility?: boolean;
backupState?: boolean;
}
export type setCredentialPropertiesReturnValue = {
}
}
/**
@ -16231,7 +16385,7 @@ See also:
requestId?: Network.RequestId;
/**
* Error information
`errorMessage` is null iff `errorType` is null.
`errorMessage` is null if `errorType` is null.
*/
errorType?: RuleSetErrorType;
/**
@ -16270,7 +16424,7 @@ still keyed with the initial URL.
that had a speculation rule that triggered the attempt, and the
BackendNodeIds of <a href> or <area href> elements that triggered the
attempt (in the case of attempts triggered by a document rule). It is
possible for mulitple rule sets and links to trigger a single attempt.
possible for multiple rule sets and links to trigger a single attempt.
*/
export interface PreloadingAttemptSource {
key: PreloadingAttemptKey;
@ -19226,6 +19380,7 @@ Error was thrown.
"Storage.indexedDBListUpdated": Storage.indexedDBListUpdatedPayload;
"Storage.interestGroupAccessed": Storage.interestGroupAccessedPayload;
"Storage.interestGroupAuctionEventOccurred": Storage.interestGroupAuctionEventOccurredPayload;
"Storage.interestGroupAuctionNetworkRequestCreated": Storage.interestGroupAuctionNetworkRequestCreatedPayload;
"Storage.sharedStorageAccessed": Storage.sharedStorageAccessedPayload;
"Storage.storageBucketCreatedOrUpdated": Storage.storageBucketCreatedOrUpdatedPayload;
"Storage.storageBucketDeleted": Storage.storageBucketDeletedPayload;
@ -19781,6 +19936,7 @@ Error was thrown.
"WebAuthn.clearCredentials": WebAuthn.clearCredentialsParameters;
"WebAuthn.setUserVerified": WebAuthn.setUserVerifiedParameters;
"WebAuthn.setAutomaticPresenceSimulation": WebAuthn.setAutomaticPresenceSimulationParameters;
"WebAuthn.setCredentialProperties": WebAuthn.setCredentialPropertiesParameters;
"Media.enable": Media.enableParameters;
"Media.disable": Media.disableParameters;
"DeviceAccess.enable": DeviceAccess.enableParameters;
@ -20362,6 +20518,7 @@ Error was thrown.
"WebAuthn.clearCredentials": WebAuthn.clearCredentialsReturnValue;
"WebAuthn.setUserVerified": WebAuthn.setUserVerifiedReturnValue;
"WebAuthn.setAutomaticPresenceSimulation": WebAuthn.setAutomaticPresenceSimulationReturnValue;
"WebAuthn.setCredentialProperties": WebAuthn.setCredentialPropertiesReturnValue;
"Media.enable": Media.enableReturnValue;
"Media.disable": Media.disableReturnValue;
"DeviceAccess.enable": DeviceAccess.enableReturnValue;

View file

@ -110,7 +110,7 @@
"defaultBrowserType": "webkit"
},
"Galaxy S5": {
"userAgent": "Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.6261.57 Mobile Safari/537.36",
"userAgent": "Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.6312.4 Mobile Safari/537.36",
"viewport": {
"width": 360,
"height": 640
@ -121,7 +121,7 @@
"defaultBrowserType": "chromium"
},
"Galaxy S5 landscape": {
"userAgent": "Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.6261.57 Mobile Safari/537.36",
"userAgent": "Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.6312.4 Mobile Safari/537.36",
"viewport": {
"width": 640,
"height": 360
@ -132,7 +132,7 @@
"defaultBrowserType": "chromium"
},
"Galaxy S8": {
"userAgent": "Mozilla/5.0 (Linux; Android 7.0; SM-G950U Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.6261.57 Mobile Safari/537.36",
"userAgent": "Mozilla/5.0 (Linux; Android 7.0; SM-G950U Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.6312.4 Mobile Safari/537.36",
"viewport": {
"width": 360,
"height": 740
@ -143,7 +143,7 @@
"defaultBrowserType": "chromium"
},
"Galaxy S8 landscape": {
"userAgent": "Mozilla/5.0 (Linux; Android 7.0; SM-G950U Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.6261.57 Mobile Safari/537.36",
"userAgent": "Mozilla/5.0 (Linux; Android 7.0; SM-G950U Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.6312.4 Mobile Safari/537.36",
"viewport": {
"width": 740,
"height": 360
@ -154,7 +154,7 @@
"defaultBrowserType": "chromium"
},
"Galaxy S9+": {
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; SM-G965U Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.6261.57 Mobile Safari/537.36",
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; SM-G965U Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.6312.4 Mobile Safari/537.36",
"viewport": {
"width": 320,
"height": 658
@ -165,7 +165,7 @@
"defaultBrowserType": "chromium"
},
"Galaxy S9+ landscape": {
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; SM-G965U Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.6261.57 Mobile Safari/537.36",
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; SM-G965U Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.6312.4 Mobile Safari/537.36",
"viewport": {
"width": 658,
"height": 320
@ -176,7 +176,7 @@
"defaultBrowserType": "chromium"
},
"Galaxy Tab S4": {
"userAgent": "Mozilla/5.0 (Linux; Android 8.1.0; SM-T837A) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.6261.57 Safari/537.36",
"userAgent": "Mozilla/5.0 (Linux; Android 8.1.0; SM-T837A) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.6312.4 Safari/537.36",
"viewport": {
"width": 712,
"height": 1138
@ -187,7 +187,7 @@
"defaultBrowserType": "chromium"
},
"Galaxy Tab S4 landscape": {
"userAgent": "Mozilla/5.0 (Linux; Android 8.1.0; SM-T837A) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.6261.57 Safari/537.36",
"userAgent": "Mozilla/5.0 (Linux; Android 8.1.0; SM-T837A) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.6312.4 Safari/537.36",
"viewport": {
"width": 1138,
"height": 712
@ -978,7 +978,7 @@
"defaultBrowserType": "webkit"
},
"LG Optimus L70": {
"userAgent": "Mozilla/5.0 (Linux; U; Android 4.4.2; en-us; LGMS323 Build/KOT49I.MS32310c) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/122.0.6261.57 Mobile Safari/537.36",
"userAgent": "Mozilla/5.0 (Linux; U; Android 4.4.2; en-us; LGMS323 Build/KOT49I.MS32310c) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/123.0.6312.4 Mobile Safari/537.36",
"viewport": {
"width": 384,
"height": 640
@ -989,7 +989,7 @@
"defaultBrowserType": "chromium"
},
"LG Optimus L70 landscape": {
"userAgent": "Mozilla/5.0 (Linux; U; Android 4.4.2; en-us; LGMS323 Build/KOT49I.MS32310c) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/122.0.6261.57 Mobile Safari/537.36",
"userAgent": "Mozilla/5.0 (Linux; U; Android 4.4.2; en-us; LGMS323 Build/KOT49I.MS32310c) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/123.0.6312.4 Mobile Safari/537.36",
"viewport": {
"width": 640,
"height": 384
@ -1000,7 +1000,7 @@
"defaultBrowserType": "chromium"
},
"Microsoft Lumia 550": {
"userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 550) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.6261.57 Mobile Safari/537.36 Edge/14.14263",
"userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 550) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.6312.4 Mobile Safari/537.36 Edge/14.14263",
"viewport": {
"width": 640,
"height": 360
@ -1011,7 +1011,7 @@
"defaultBrowserType": "chromium"
},
"Microsoft Lumia 550 landscape": {
"userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 550) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.6261.57 Mobile Safari/537.36 Edge/14.14263",
"userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 550) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.6312.4 Mobile Safari/537.36 Edge/14.14263",
"viewport": {
"width": 360,
"height": 640
@ -1022,7 +1022,7 @@
"defaultBrowserType": "chromium"
},
"Microsoft Lumia 950": {
"userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 950) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.6261.57 Mobile Safari/537.36 Edge/14.14263",
"userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 950) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.6312.4 Mobile Safari/537.36 Edge/14.14263",
"viewport": {
"width": 360,
"height": 640
@ -1033,7 +1033,7 @@
"defaultBrowserType": "chromium"
},
"Microsoft Lumia 950 landscape": {
"userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 950) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.6261.57 Mobile Safari/537.36 Edge/14.14263",
"userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 950) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.6312.4 Mobile Safari/537.36 Edge/14.14263",
"viewport": {
"width": 640,
"height": 360
@ -1044,7 +1044,7 @@
"defaultBrowserType": "chromium"
},
"Nexus 10": {
"userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 10 Build/MOB31T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.6261.57 Safari/537.36",
"userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 10 Build/MOB31T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.6312.4 Safari/537.36",
"viewport": {
"width": 800,
"height": 1280
@ -1055,7 +1055,7 @@
"defaultBrowserType": "chromium"
},
"Nexus 10 landscape": {
"userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 10 Build/MOB31T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.6261.57 Safari/537.36",
"userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 10 Build/MOB31T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.6312.4 Safari/537.36",
"viewport": {
"width": 1280,
"height": 800
@ -1066,7 +1066,7 @@
"defaultBrowserType": "chromium"
},
"Nexus 4": {
"userAgent": "Mozilla/5.0 (Linux; Android 4.4.2; Nexus 4 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.6261.57 Mobile Safari/537.36",
"userAgent": "Mozilla/5.0 (Linux; Android 4.4.2; Nexus 4 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.6312.4 Mobile Safari/537.36",
"viewport": {
"width": 384,
"height": 640
@ -1077,7 +1077,7 @@
"defaultBrowserType": "chromium"
},
"Nexus 4 landscape": {
"userAgent": "Mozilla/5.0 (Linux; Android 4.4.2; Nexus 4 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.6261.57 Mobile Safari/537.36",
"userAgent": "Mozilla/5.0 (Linux; Android 4.4.2; Nexus 4 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.6312.4 Mobile Safari/537.36",
"viewport": {
"width": 640,
"height": 384
@ -1088,7 +1088,7 @@
"defaultBrowserType": "chromium"
},
"Nexus 5": {
"userAgent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.6261.57 Mobile Safari/537.36",
"userAgent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.6312.4 Mobile Safari/537.36",
"viewport": {
"width": 360,
"height": 640
@ -1099,7 +1099,7 @@
"defaultBrowserType": "chromium"
},
"Nexus 5 landscape": {
"userAgent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.6261.57 Mobile Safari/537.36",
"userAgent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.6312.4 Mobile Safari/537.36",
"viewport": {
"width": 640,
"height": 360
@ -1110,7 +1110,7 @@
"defaultBrowserType": "chromium"
},
"Nexus 5X": {
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 5X Build/OPR4.170623.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.6261.57 Mobile Safari/537.36",
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 5X Build/OPR4.170623.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.6312.4 Mobile Safari/537.36",
"viewport": {
"width": 412,
"height": 732
@ -1121,7 +1121,7 @@
"defaultBrowserType": "chromium"
},
"Nexus 5X landscape": {
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 5X Build/OPR4.170623.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.6261.57 Mobile Safari/537.36",
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 5X Build/OPR4.170623.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.6312.4 Mobile Safari/537.36",
"viewport": {
"width": 732,
"height": 412
@ -1132,7 +1132,7 @@
"defaultBrowserType": "chromium"
},
"Nexus 6": {
"userAgent": "Mozilla/5.0 (Linux; Android 7.1.1; Nexus 6 Build/N6F26U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.6261.57 Mobile Safari/537.36",
"userAgent": "Mozilla/5.0 (Linux; Android 7.1.1; Nexus 6 Build/N6F26U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.6312.4 Mobile Safari/537.36",
"viewport": {
"width": 412,
"height": 732
@ -1143,7 +1143,7 @@
"defaultBrowserType": "chromium"
},
"Nexus 6 landscape": {
"userAgent": "Mozilla/5.0 (Linux; Android 7.1.1; Nexus 6 Build/N6F26U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.6261.57 Mobile Safari/537.36",
"userAgent": "Mozilla/5.0 (Linux; Android 7.1.1; Nexus 6 Build/N6F26U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.6312.4 Mobile Safari/537.36",
"viewport": {
"width": 732,
"height": 412
@ -1154,7 +1154,7 @@
"defaultBrowserType": "chromium"
},
"Nexus 6P": {
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 6P Build/OPP3.170518.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.6261.57 Mobile Safari/537.36",
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 6P Build/OPP3.170518.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.6312.4 Mobile Safari/537.36",
"viewport": {
"width": 412,
"height": 732
@ -1165,7 +1165,7 @@
"defaultBrowserType": "chromium"
},
"Nexus 6P landscape": {
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 6P Build/OPP3.170518.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.6261.57 Mobile Safari/537.36",
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 6P Build/OPP3.170518.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.6312.4 Mobile Safari/537.36",
"viewport": {
"width": 732,
"height": 412
@ -1176,7 +1176,7 @@
"defaultBrowserType": "chromium"
},
"Nexus 7": {
"userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 7 Build/MOB30X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.6261.57 Safari/537.36",
"userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 7 Build/MOB30X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.6312.4 Safari/537.36",
"viewport": {
"width": 600,
"height": 960
@ -1187,7 +1187,7 @@
"defaultBrowserType": "chromium"
},
"Nexus 7 landscape": {
"userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 7 Build/MOB30X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.6261.57 Safari/537.36",
"userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 7 Build/MOB30X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.6312.4 Safari/537.36",
"viewport": {
"width": 960,
"height": 600
@ -1242,7 +1242,7 @@
"defaultBrowserType": "webkit"
},
"Pixel 2": {
"userAgent": "Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.6261.57 Mobile Safari/537.36",
"userAgent": "Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.6312.4 Mobile Safari/537.36",
"viewport": {
"width": 411,
"height": 731
@ -1253,7 +1253,7 @@
"defaultBrowserType": "chromium"
},
"Pixel 2 landscape": {
"userAgent": "Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.6261.57 Mobile Safari/537.36",
"userAgent": "Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.6312.4 Mobile Safari/537.36",
"viewport": {
"width": 731,
"height": 411
@ -1264,7 +1264,7 @@
"defaultBrowserType": "chromium"
},
"Pixel 2 XL": {
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Pixel 2 XL Build/OPD1.170816.004) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.6261.57 Mobile Safari/537.36",
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Pixel 2 XL Build/OPD1.170816.004) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.6312.4 Mobile Safari/537.36",
"viewport": {
"width": 411,
"height": 823
@ -1275,7 +1275,7 @@
"defaultBrowserType": "chromium"
},
"Pixel 2 XL landscape": {
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Pixel 2 XL Build/OPD1.170816.004) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.6261.57 Mobile Safari/537.36",
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Pixel 2 XL Build/OPD1.170816.004) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.6312.4 Mobile Safari/537.36",
"viewport": {
"width": 823,
"height": 411
@ -1286,7 +1286,7 @@
"defaultBrowserType": "chromium"
},
"Pixel 3": {
"userAgent": "Mozilla/5.0 (Linux; Android 9; Pixel 3 Build/PQ1A.181105.017.A1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.6261.57 Mobile Safari/537.36",
"userAgent": "Mozilla/5.0 (Linux; Android 9; Pixel 3 Build/PQ1A.181105.017.A1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.6312.4 Mobile Safari/537.36",
"viewport": {
"width": 393,
"height": 786
@ -1297,7 +1297,7 @@
"defaultBrowserType": "chromium"
},
"Pixel 3 landscape": {
"userAgent": "Mozilla/5.0 (Linux; Android 9; Pixel 3 Build/PQ1A.181105.017.A1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.6261.57 Mobile Safari/537.36",
"userAgent": "Mozilla/5.0 (Linux; Android 9; Pixel 3 Build/PQ1A.181105.017.A1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.6312.4 Mobile Safari/537.36",
"viewport": {
"width": 786,
"height": 393
@ -1308,7 +1308,7 @@
"defaultBrowserType": "chromium"
},
"Pixel 4": {
"userAgent": "Mozilla/5.0 (Linux; Android 10; Pixel 4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.6261.57 Mobile Safari/537.36",
"userAgent": "Mozilla/5.0 (Linux; Android 10; Pixel 4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.6312.4 Mobile Safari/537.36",
"viewport": {
"width": 353,
"height": 745
@ -1319,7 +1319,7 @@
"defaultBrowserType": "chromium"
},
"Pixel 4 landscape": {
"userAgent": "Mozilla/5.0 (Linux; Android 10; Pixel 4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.6261.57 Mobile Safari/537.36",
"userAgent": "Mozilla/5.0 (Linux; Android 10; Pixel 4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.6312.4 Mobile Safari/537.36",
"viewport": {
"width": 745,
"height": 353
@ -1330,7 +1330,7 @@
"defaultBrowserType": "chromium"
},
"Pixel 4a (5G)": {
"userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 4a (5G)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.6261.57 Mobile Safari/537.36",
"userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 4a (5G)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.6312.4 Mobile Safari/537.36",
"screen": {
"width": 412,
"height": 892
@ -1345,7 +1345,7 @@
"defaultBrowserType": "chromium"
},
"Pixel 4a (5G) landscape": {
"userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 4a (5G)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.6261.57 Mobile Safari/537.36",
"userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 4a (5G)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.6312.4 Mobile Safari/537.36",
"screen": {
"height": 892,
"width": 412
@ -1360,7 +1360,7 @@
"defaultBrowserType": "chromium"
},
"Pixel 5": {
"userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.6261.57 Mobile Safari/537.36",
"userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.6312.4 Mobile Safari/537.36",
"screen": {
"width": 393,
"height": 851
@ -1375,7 +1375,7 @@
"defaultBrowserType": "chromium"
},
"Pixel 5 landscape": {
"userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.6261.57 Mobile Safari/537.36",
"userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.6312.4 Mobile Safari/537.36",
"screen": {
"width": 851,
"height": 393
@ -1390,7 +1390,7 @@
"defaultBrowserType": "chromium"
},
"Pixel 7": {
"userAgent": "Mozilla/5.0 (Linux; Android 14; Pixel 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.6261.57 Mobile Safari/537.36",
"userAgent": "Mozilla/5.0 (Linux; Android 14; Pixel 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.6312.4 Mobile Safari/537.36",
"screen": {
"width": 412,
"height": 915
@ -1405,7 +1405,7 @@
"defaultBrowserType": "chromium"
},
"Pixel 7 landscape": {
"userAgent": "Mozilla/5.0 (Linux; Android 14; Pixel 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.6261.57 Mobile Safari/537.36",
"userAgent": "Mozilla/5.0 (Linux; Android 14; Pixel 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.6312.4 Mobile Safari/537.36",
"screen": {
"width": 915,
"height": 412
@ -1420,7 +1420,7 @@
"defaultBrowserType": "chromium"
},
"Moto G4": {
"userAgent": "Mozilla/5.0 (Linux; Android 7.0; Moto G (4)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.6261.57 Mobile Safari/537.36",
"userAgent": "Mozilla/5.0 (Linux; Android 7.0; Moto G (4)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.6312.4 Mobile Safari/537.36",
"viewport": {
"width": 360,
"height": 640
@ -1431,7 +1431,7 @@
"defaultBrowserType": "chromium"
},
"Moto G4 landscape": {
"userAgent": "Mozilla/5.0 (Linux; Android 7.0; Moto G (4)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.6261.57 Mobile Safari/537.36",
"userAgent": "Mozilla/5.0 (Linux; Android 7.0; Moto G (4)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.6312.4 Mobile Safari/537.36",
"viewport": {
"width": 640,
"height": 360
@ -1442,7 +1442,7 @@
"defaultBrowserType": "chromium"
},
"Desktop Chrome HiDPI": {
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.6261.57 Safari/537.36",
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.6312.4 Safari/537.36",
"screen": {
"width": 1792,
"height": 1120
@ -1457,7 +1457,7 @@
"defaultBrowserType": "chromium"
},
"Desktop Edge HiDPI": {
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.6261.57 Safari/537.36 Edg/122.0.6261.57",
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.6312.4 Safari/537.36 Edg/123.0.6312.4",
"screen": {
"width": 1792,
"height": 1120
@ -1472,7 +1472,7 @@
"defaultBrowserType": "chromium"
},
"Desktop Firefox HiDPI": {
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:122.0) Gecko/20100101 Firefox/122.0",
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:123.0) Gecko/20100101 Firefox/123.0",
"screen": {
"width": 1792,
"height": 1120
@ -1502,7 +1502,7 @@
"defaultBrowserType": "webkit"
},
"Desktop Chrome": {
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.6261.57 Safari/537.36",
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.6312.4 Safari/537.36",
"screen": {
"width": 1920,
"height": 1080
@ -1517,7 +1517,7 @@
"defaultBrowserType": "chromium"
},
"Desktop Edge": {
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.6261.57 Safari/537.36 Edg/122.0.6261.57",
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.6312.4 Safari/537.36 Edg/123.0.6312.4",
"screen": {
"width": 1920,
"height": 1080
@ -1532,7 +1532,7 @@
"defaultBrowserType": "chromium"
},
"Desktop Firefox": {
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:122.0) Gecko/20100101 Firefox/122.0",
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:123.0) Gecko/20100101 Firefox/123.0",
"screen": {
"width": 1920,
"height": 1080

View file

@ -245,7 +245,7 @@ If omitted, the full tree is returned.
depth?: number;
/**
* The frame for whose document the AX tree should be retrieved.
If omited, the root frame is used.
If omitted, the root frame is used.
*/
frameId?: Page.FrameId;
}
@ -305,7 +305,7 @@ If omitted, the root frame is used.
/**
* Query a DOM node's accessibility subtree for accessible name and role.
This command computes the name and role for all nodes in the subtree, including those that are
ignored for accessibility, and returns those that mactch the specified name and role. If no DOM
ignored for accessibility, and returns those that match the specified name and role. If no DOM
node is specified, or the DOM node does not exist, the command returns an error. If neither
`accessibleName` or `role` is specified, it returns all the accessibility nodes in the subtree.
*/
@ -367,6 +367,9 @@ including nodes that are ignored for accessibility.
playbackRate: number;
/**
* `Animation`'s start time.
Milliseconds for time based animations and
percentage [0 - 100] for scroll driven animations
(i.e. when viewOrScrollTimeline exists).
*/
startTime: number;
/**
@ -386,6 +389,39 @@ including nodes that are ignored for accessibility.
animation/transition.
*/
cssId?: string;
/**
* View or scroll timeline
*/
viewOrScrollTimeline?: ViewOrScrollTimeline;
}
/**
* Timeline instance
*/
export interface ViewOrScrollTimeline {
/**
* Scroll container node
*/
sourceNodeId?: DOM.BackendNodeId;
/**
* Represents the starting scroll position of the timeline
as a length offset in pixels from scroll origin.
*/
startOffset?: number;
/**
* Represents the ending scroll position of the timeline
as a length offset in pixels from scroll origin.
*/
endOffset?: number;
/**
* The element whose principal box's visibility in the
scrollport defined the progress of the timeline.
Does not exist for animations with ScrollTimeline
*/
subjectNodeId?: DOM.BackendNodeId;
/**
* Orientation of the scroll
*/
axis: DOM.ScrollOrientation;
}
/**
* AnimationEffect instance
@ -409,6 +445,9 @@ animation/transition.
iterations: number;
/**
* `AnimationEffect`'s iteration duration.
Milliseconds for time based animations and
percentage [0 - 100] for scroll driven animations
(i.e. when viewOrScrollTimeline exists).
*/
duration: number;
/**
@ -1132,7 +1171,7 @@ Munich 81456
*/
export interface AddressUI {
/**
* A two dimension array containing the repesentation of values from an address profile.
* A two dimension array containing the representation of values from an address profile.
*/
addressFields: AddressFields[];
}
@ -1165,6 +1204,10 @@ Munich 81456
* The filling strategy
*/
fillingStrategy: FillingStrategy;
/**
* The frame the field belongs to
*/
frameId: Page.FrameId;
/**
* The form field's DOM node
*/
@ -1367,7 +1410,7 @@ events afterwards if enabled and recording.
*/
windowState?: WindowState;
}
export type PermissionType = "accessibilityEvents"|"audioCapture"|"backgroundSync"|"backgroundFetch"|"capturedSurfaceControl"|"clipboardReadWrite"|"clipboardSanitizedWrite"|"displayCapture"|"durableStorage"|"flash"|"geolocation"|"idleDetection"|"localFonts"|"midi"|"midiSysex"|"nfc"|"notifications"|"paymentHandler"|"periodicBackgroundSync"|"protectedMediaIdentifier"|"sensors"|"storageAccess"|"topLevelStorageAccess"|"videoCapture"|"videoCapturePanTiltZoom"|"wakeLockScreen"|"wakeLockSystem"|"windowManagement";
export type PermissionType = "accessibilityEvents"|"audioCapture"|"backgroundSync"|"backgroundFetch"|"capturedSurfaceControl"|"clipboardReadWrite"|"clipboardSanitizedWrite"|"displayCapture"|"durableStorage"|"flash"|"geolocation"|"idleDetection"|"localFonts"|"midi"|"midiSysex"|"nfc"|"notifications"|"paymentHandler"|"periodicBackgroundSync"|"protectedMediaIdentifier"|"sensors"|"storageAccess"|"speakerSelection"|"topLevelStorageAccess"|"videoCapture"|"videoCapturePanTiltZoom"|"wakeLockScreen"|"wakeLockSystem"|"windowManagement";
export type PermissionSetting = "granted"|"denied"|"prompt";
/**
* Definition of PermissionDescriptor defined in the Permissions API:
@ -1540,7 +1583,7 @@ Note that userVisibleOnly = true is the only currently supported type.
/**
* Whether to allow all or deny all download requests, or use default Chrome behavior if
available (otherwise deny). |allowAndName| allows download and names files according to
their dowmload guids.
their download guids.
*/
behavior: "deny"|"allow"|"allowAndName"|"default";
/**
@ -1888,7 +1931,7 @@ pseudo-classes.
frameId: Page.FrameId;
/**
* Stylesheet resource URL. Empty if this is a constructed stylesheet created using
new CSSStyleSheet() (but non-empty if this is a constructed sylesheet imported
new CSSStyleSheet() (but non-empty if this is a constructed stylesheet imported
as a CSS module script).
*/
sourceURL: string;
@ -3378,6 +3421,10 @@ front-end.
* ContainerSelector logical axes
*/
export type LogicalAxes = "Inline"|"Block"|"Both";
/**
* Physical scroll orientation
*/
export type ScrollOrientation = "horizontal"|"vertical";
/**
* DOM interaction is implemented in terms of mirror objects that represent the actual DOM nodes.
DOMNode is a base node mirror type.
@ -3951,7 +3998,7 @@ be called for that search.
*/
export type getAttributesParameters = {
/**
* Id of the node to retrieve attibutes for.
* Id of the node to retrieve attributes for.
*/
nodeId: NodeId;
}
@ -5679,14 +5726,14 @@ resource fetches.
*/
export type VirtualTimePolicy = "advance"|"pause"|"pauseIfNetworkFetchesPending";
/**
* Used to specify User Agent Cient Hints to emulate. See https://wicg.github.io/ua-client-hints
* Used to specify User Agent Client Hints to emulate. See https://wicg.github.io/ua-client-hints
*/
export interface UserAgentBrandVersion {
brand: string;
version: string;
}
/**
* Used to specify User Agent Cient Hints to emulate. See https://wicg.github.io/ua-client-hints
* Used to specify User Agent Client Hints to emulate. See https://wicg.github.io/ua-client-hints
Missing optional values will be filled in by the target with what it would normally use.
*/
export interface UserAgentMetadata {
@ -5990,7 +6037,7 @@ Sensor.start() will attempt to use a real sensor instead.
export type setSensorOverrideEnabledReturnValue = {
}
/**
* Updates the sensor readings reported by a sensor type previously overriden
* Updates the sensor readings reported by a sensor type previously overridden
by setSensorOverrideEnabled.
*/
export type setSensorOverrideReadingsParameters = {
@ -6113,8 +6160,9 @@ restores default host system locale.
*/
export type setTimezoneOverrideParameters = {
/**
* The timezone identifier. If empty, disables the override and
restores default host system timezone.
* The timezone identifier. List of supported timezones:
https://source.chromium.org/chromium/chromium/deps/icu.git/+/faee8bc70570192d82d2978a71e2a615788597d1:source/data/misc/metaZones.txt
If empty, disables the override and restores default host system timezone.
*/
timezoneId: string;
}
@ -6155,6 +6203,7 @@ on Android.
}
/**
* Allows overriding user agent with the given string.
`userAgentMetadata` must be set for Client Hint headers to be sent.
*/
export type setUserAgentOverrideParameters = {
/**
@ -6300,7 +6349,7 @@ display. Reported for diagnostic uses, may be removed in the future.
*/
handle: StreamHandle;
/**
* Seek to the specified offset before reading (if not specificed, proceed with offset
* Seek to the specified offset before reading (if not specified, proceed with offset
following the last read). Some types of streams may only support sequential reads.
*/
offset?: number;
@ -6926,7 +6975,7 @@ for example an emoji keyboard or an IME.
export type insertTextReturnValue = {
}
/**
* This method sets the current candidate text for ime.
* This method sets the current candidate text for IME.
Use imeCommitComposition to commit the final text.
Use imeSetComposition with empty string as text to cancel composition.
*/
@ -7425,7 +7474,7 @@ transform/scrolling purposes only.
}
export type layerTreeDidChangePayload = {
/**
* Layer tree, absent if not in the comspositing mode.
* Layer tree, absent if not in the compositing mode.
*/
layers?: Layer[];
}
@ -8036,7 +8085,7 @@ passed by the developer (e.g. via "fetch") as understood by the backend.
trustTokenParams?: TrustTokenParams;
/**
* True if this resource request is considered to be the 'same site' as the
request correspondinfg to the main frame.
request corresponding to the main frame.
*/
isSameSite?: boolean;
}
@ -8188,8 +8237,13 @@ records.
* The reason why Chrome uses a specific transport protocol for HTTP semantics.
*/
export type AlternateProtocolUsage = "alternativeJobWonWithoutRace"|"alternativeJobWonRace"|"mainJobWonRace"|"mappingMissing"|"broken"|"dnsAlpnH3JobWonWithoutRace"|"dnsAlpnH3JobWonRace"|"unspecifiedReason";
/**
* Source of service worker router.
*/
export type ServiceWorkerRouterSource = "network"|"cache"|"fetch-event"|"race-network-and-fetch-handler";
export interface ServiceWorkerRouterInfo {
ruleIdMatched: number;
matchedSourceType: ServiceWorkerRouterSource;
}
/**
* HTTP response data.
@ -8260,7 +8314,7 @@ records.
*/
fromPrefetchCache?: boolean;
/**
* Infomation about how Service Worker Static Router was used.
* Information about how Service Worker Static Router was used.
*/
serviceWorkerRouterInfo?: ServiceWorkerRouterInfo;
/**
@ -8489,6 +8543,10 @@ of the request to the endpoint that set the cookie.
* Types of reasons why a cookie may not be sent with a request.
*/
export type CookieBlockedReason = "SecureOnly"|"NotOnPath"|"DomainMismatch"|"SameSiteStrict"|"SameSiteLax"|"SameSiteUnspecifiedTreatedAsLax"|"SameSiteNoneInsecure"|"UserPreferences"|"ThirdPartyPhaseout"|"ThirdPartyBlockedInFirstPartySet"|"UnknownError"|"SchemefulSameSiteStrict"|"SchemefulSameSiteLax"|"SchemefulSameSiteUnspecifiedTreatedAsLax"|"SamePartyFromCrossPartyContext"|"NameValuePairExceedsMaxSize";
/**
* Types of reasons why a cookie should have been blocked by 3PCD but is exempted for the request.
*/
export type CookieExemptionReason = "None"|"UserSetting"|"TPCDMetadata"|"TPCDDeprecationTrial"|"TPCDHeuristics"|"EnterprisePolicy"|"StorageAccess"|"TopLevelStorageAccess"|"CorsOptIn";
/**
* A cookie which was not stored from a response with the corresponding reason.
*/
@ -8510,17 +8568,37 @@ errors.
cookie?: Cookie;
}
/**
* A cookie with was not sent with a request with the corresponding reason.
* A cookie should have been blocked by 3PCD but is exempted and stored from a response with the
corresponding reason. A cookie could only have at most one exemption reason.
*/
export interface BlockedCookieWithReason {
export interface ExemptedSetCookieWithReason {
/**
* The reason(s) the cookie was blocked.
* The reason the cookie was exempted.
*/
blockedReasons: CookieBlockedReason[];
exemptionReason: CookieExemptionReason;
/**
* The cookie object representing the cookie.
*/
cookie: Cookie;
}
/**
* A cookie associated with the request which may or may not be sent with it.
Includes the cookies itself and reasons for blocking or exemption.
*/
export interface AssociatedCookie {
/**
* The cookie object representing the cookie which was not sent.
*/
cookie: Cookie;
/**
* The reason(s) the cookie was blocked. If empty means the cookie is included.
*/
blockedReasons: CookieBlockedReason[];
/**
* The reason the cookie should have been blocked by 3PCD but is exempted. A cookie could
only have at most one exemption reason.
*/
exemptionReason?: CookieExemptionReason;
}
/**
* Cookie parameter object
@ -8759,7 +8837,7 @@ https://wicg.github.io/webpackage/draft-yasskin-httpbis-origin-signed-exchanges-
*/
securityDetails?: SecurityDetails;
/**
* Errors occurred while handling the signed exchagne.
* Errors occurred while handling the signed exchange.
*/
errors?: SignedExchangeError[];
}
@ -8950,7 +9028,7 @@ CORB and streaming.
*/
type: ResourceType;
/**
* User friendly error message.
* Error message. List of network errors: https://cs.chromium.org/chromium/src/net/base/net_error_list.h
*/
errorText: string;
/**
@ -9350,9 +9428,9 @@ or requestWillBeSentExtraInfo will be fired first for the same request.
requestId: RequestId;
/**
* A list of cookies potentially associated to the requested URL. This includes both cookies sent with
the request and the ones not sent; the latter are distinguished by having blockedReason field set.
the request and the ones not sent; the latter are distinguished by having blockedReasons field set.
*/
associatedCookies: BlockedCookieWithReason[];
associatedCookies: AssociatedCookie[];
/**
* Raw request headers as they will be sent over the wire.
*/
@ -9412,9 +9490,14 @@ Only sent when partitioned cookies are enabled.
*/
cookiePartitionKey?: string;
/**
* True if partitioned cookies are enabled, but the partition key is not serializeable to string.
* True if partitioned cookies are enabled, but the partition key is not serializable to string.
*/
cookiePartitionKeyOpaque?: boolean;
/**
* A list of cookies which should have been blocked by 3PCD but are exempted and stored from
the response with the corresponding reason.
*/
exemptedCookies?: ExemptedSetCookieWithReason[];
}
/**
* Fired exactly once for each Trust Token operation. Depending on
@ -9645,7 +9728,7 @@ authChallenge.
export type continueInterceptedRequestReturnValue = {
}
/**
* Deletes browser cookies with matching name and url or domain/path pair.
* Deletes browser cookies with matching name and url or domain/path/partitionKey pair.
*/
export type deleteCookiesParameters = {
/**
@ -9665,6 +9748,11 @@ provided URL.
* If specified, deletes only cookies with the exact path.
*/
path?: string;
/**
* If specified, deletes only cookies with the the given name and partitionKey where domain
matches provided URL.
*/
partitionKey?: string;
}
export type deleteCookiesReturnValue = {
}
@ -10115,7 +10203,7 @@ should be omitted for worker targets.
*/
export interface SourceOrderConfig {
/**
* the color to outline the givent element in.
* the color to outline the given element in.
*/
parentOutlineColor: DOM.RGBA;
/**
@ -10448,7 +10536,7 @@ should be omitted for worker targets.
*/
showCSS: boolean;
/**
* Seleted platforms to show the overlay.
* Selected platforms to show the overlay.
*/
selectedPlatform: string;
/**
@ -10616,8 +10704,8 @@ user manually inspects an element.
}
/**
* Highlights owner element of the frame with given id.
Deprecated: Doesn't work reliablity and cannot be fixed due to process
separatation (the owner node might be in a different process). Determine
Deprecated: Doesn't work reliably and cannot be fixed due to process
separation (the owner node might be in a different process). Determine
the owner node in the client and use highlightNode.
*/
export type highlightFrameParameters = {
@ -10977,7 +11065,7 @@ as an ad.
* All Permissions Policy features. This enum should match the one defined
in third_party/blink/renderer/core/permissions_policy/permissions_policy_features.json5.
*/
export type PermissionsPolicyFeature = "accelerometer"|"ambient-light-sensor"|"attribution-reporting"|"autoplay"|"bluetooth"|"browsing-topics"|"camera"|"captured-surface-control"|"ch-dpr"|"ch-device-memory"|"ch-downlink"|"ch-ect"|"ch-prefers-color-scheme"|"ch-prefers-reduced-motion"|"ch-prefers-reduced-transparency"|"ch-rtt"|"ch-save-data"|"ch-ua"|"ch-ua-arch"|"ch-ua-bitness"|"ch-ua-platform"|"ch-ua-model"|"ch-ua-mobile"|"ch-ua-form-factor"|"ch-ua-full-version"|"ch-ua-full-version-list"|"ch-ua-platform-version"|"ch-ua-wow64"|"ch-viewport-height"|"ch-viewport-width"|"ch-width"|"clipboard-read"|"clipboard-write"|"compute-pressure"|"cross-origin-isolated"|"direct-sockets"|"display-capture"|"document-domain"|"encrypted-media"|"execution-while-out-of-viewport"|"execution-while-not-rendered"|"focus-without-user-activation"|"fullscreen"|"frobulate"|"gamepad"|"geolocation"|"gyroscope"|"hid"|"identity-credentials-get"|"idle-detection"|"interest-cohort"|"join-ad-interest-group"|"keyboard-map"|"local-fonts"|"magnetometer"|"microphone"|"midi"|"otp-credentials"|"payment"|"picture-in-picture"|"private-aggregation"|"private-state-token-issuance"|"private-state-token-redemption"|"publickey-credentials-create"|"publickey-credentials-get"|"run-ad-auction"|"screen-wake-lock"|"serial"|"shared-autofill"|"shared-storage"|"shared-storage-select-url"|"smart-card"|"storage-access"|"sub-apps"|"sync-xhr"|"unload"|"usb"|"usb-unrestricted"|"vertical-scroll"|"web-printing"|"web-share"|"window-management"|"window-placement"|"xr-spatial-tracking";
export type PermissionsPolicyFeature = "accelerometer"|"ambient-light-sensor"|"attribution-reporting"|"autoplay"|"bluetooth"|"browsing-topics"|"camera"|"captured-surface-control"|"ch-dpr"|"ch-device-memory"|"ch-downlink"|"ch-ect"|"ch-prefers-color-scheme"|"ch-prefers-reduced-motion"|"ch-prefers-reduced-transparency"|"ch-rtt"|"ch-save-data"|"ch-ua"|"ch-ua-arch"|"ch-ua-bitness"|"ch-ua-platform"|"ch-ua-model"|"ch-ua-mobile"|"ch-ua-form-factor"|"ch-ua-full-version"|"ch-ua-full-version-list"|"ch-ua-platform-version"|"ch-ua-wow64"|"ch-viewport-height"|"ch-viewport-width"|"ch-width"|"clipboard-read"|"clipboard-write"|"compute-pressure"|"cross-origin-isolated"|"direct-sockets"|"display-capture"|"document-domain"|"encrypted-media"|"execution-while-out-of-viewport"|"execution-while-not-rendered"|"focus-without-user-activation"|"fullscreen"|"frobulate"|"gamepad"|"geolocation"|"gyroscope"|"hid"|"identity-credentials-get"|"idle-detection"|"interest-cohort"|"join-ad-interest-group"|"keyboard-map"|"local-fonts"|"magnetometer"|"microphone"|"midi"|"otp-credentials"|"payment"|"picture-in-picture"|"private-aggregation"|"private-state-token-issuance"|"private-state-token-redemption"|"publickey-credentials-create"|"publickey-credentials-get"|"run-ad-auction"|"screen-wake-lock"|"serial"|"shared-autofill"|"shared-storage"|"shared-storage-select-url"|"smart-card"|"speaker-selection"|"storage-access"|"sub-apps"|"sync-xhr"|"unload"|"usb"|"usb-unrestricted"|"vertical-scroll"|"web-printing"|"web-share"|"window-management"|"window-placement"|"xr-spatial-tracking";
/**
* Reason for a permissions policy feature to be disabled.
*/
@ -11229,7 +11317,7 @@ Example URLs: http://www.google.com/file.html -> "google.com"
*/
message: string;
/**
* If criticial, this is a non-recoverable parse error.
* If critical, this is a non-recoverable parse error.
*/
critical: number;
/**
@ -11436,7 +11524,7 @@ Example URLs: http://www.google.com/file.html -> "google.com"
eager?: boolean;
}
/**
* Enum of possible auto-reponse for permisison / prompt dialogs.
* Enum of possible auto-response for permission / prompt dialogs.
*/
export type AutoResponseMode = "none"|"autoAccept"|"autoReject"|"autoOptOut";
/**
@ -11446,7 +11534,7 @@ Example URLs: http://www.google.com/file.html -> "google.com"
/**
* List of not restored reasons for back-forward cache.
*/
export type BackForwardCacheNotRestoredReason = "NotPrimaryMainFrame"|"BackForwardCacheDisabled"|"RelatedActiveContentsExist"|"HTTPStatusNotOK"|"SchemeNotHTTPOrHTTPS"|"Loading"|"WasGrantedMediaAccess"|"DisableForRenderFrameHostCalled"|"DomainNotAllowed"|"HTTPMethodNotGET"|"SubframeIsNavigating"|"Timeout"|"CacheLimit"|"JavaScriptExecution"|"RendererProcessKilled"|"RendererProcessCrashed"|"SchedulerTrackedFeatureUsed"|"ConflictingBrowsingInstance"|"CacheFlushed"|"ServiceWorkerVersionActivation"|"SessionRestored"|"ServiceWorkerPostMessage"|"EnteredBackForwardCacheBeforeServiceWorkerHostAdded"|"RenderFrameHostReused_SameSite"|"RenderFrameHostReused_CrossSite"|"ServiceWorkerClaim"|"IgnoreEventAndEvict"|"HaveInnerContents"|"TimeoutPuttingInCache"|"BackForwardCacheDisabledByLowMemory"|"BackForwardCacheDisabledByCommandLine"|"NetworkRequestDatapipeDrainedAsBytesConsumer"|"NetworkRequestRedirected"|"NetworkRequestTimeout"|"NetworkExceedsBufferLimit"|"NavigationCancelledWhileRestoring"|"NotMostRecentNavigationEntry"|"BackForwardCacheDisabledForPrerender"|"UserAgentOverrideDiffers"|"ForegroundCacheLimit"|"BrowsingInstanceNotSwapped"|"BackForwardCacheDisabledForDelegate"|"UnloadHandlerExistsInMainFrame"|"UnloadHandlerExistsInSubFrame"|"ServiceWorkerUnregistration"|"CacheControlNoStore"|"CacheControlNoStoreCookieModified"|"CacheControlNoStoreHTTPOnlyCookieModified"|"NoResponseHead"|"Unknown"|"ActivationNavigationsDisallowedForBug1234857"|"ErrorDocument"|"FencedFramesEmbedder"|"CookieDisabled"|"HTTPAuthRequired"|"CookieFlushed"|"WebSocket"|"WebTransport"|"WebRTC"|"MainResourceHasCacheControlNoStore"|"MainResourceHasCacheControlNoCache"|"SubresourceHasCacheControlNoStore"|"SubresourceHasCacheControlNoCache"|"ContainsPlugins"|"DocumentLoaded"|"DedicatedWorkerOrWorklet"|"OutstandingNetworkRequestOthers"|"RequestedMIDIPermission"|"RequestedAudioCapturePermission"|"RequestedVideoCapturePermission"|"RequestedBackForwardCacheBlockedSensors"|"RequestedBackgroundWorkPermission"|"BroadcastChannel"|"WebXR"|"SharedWorker"|"WebLocks"|"WebHID"|"WebShare"|"RequestedStorageAccessGrant"|"WebNfc"|"OutstandingNetworkRequestFetch"|"OutstandingNetworkRequestXHR"|"AppBanner"|"Printing"|"WebDatabase"|"PictureInPicture"|"Portal"|"SpeechRecognizer"|"IdleManager"|"PaymentManager"|"SpeechSynthesis"|"KeyboardLock"|"WebOTPService"|"OutstandingNetworkRequestDirectSocket"|"InjectedJavascript"|"InjectedStyleSheet"|"KeepaliveRequest"|"IndexedDBEvent"|"Dummy"|"JsNetworkRequestReceivedCacheControlNoStoreResource"|"WebRTCSticky"|"WebTransportSticky"|"WebSocketSticky"|"SmartCard"|"LiveMediaStreamTrack"|"UnloadHandler"|"ContentSecurityHandler"|"ContentWebAuthenticationAPI"|"ContentFileChooser"|"ContentSerial"|"ContentFileSystemAccess"|"ContentMediaDevicesDispatcherHost"|"ContentWebBluetooth"|"ContentWebUSB"|"ContentMediaSessionService"|"ContentScreenReader"|"EmbedderPopupBlockerTabHelper"|"EmbedderSafeBrowsingTriggeredPopupBlocker"|"EmbedderSafeBrowsingThreatDetails"|"EmbedderAppBannerManager"|"EmbedderDomDistillerViewerSource"|"EmbedderDomDistillerSelfDeletingRequestDelegate"|"EmbedderOomInterventionTabHelper"|"EmbedderOfflinePage"|"EmbedderChromePasswordManagerClientBindCredentialManager"|"EmbedderPermissionRequestManager"|"EmbedderModalDialog"|"EmbedderExtensions"|"EmbedderExtensionMessaging"|"EmbedderExtensionMessagingForOpenPort"|"EmbedderExtensionSentMessageToCachedFrame";
export type BackForwardCacheNotRestoredReason = "NotPrimaryMainFrame"|"BackForwardCacheDisabled"|"RelatedActiveContentsExist"|"HTTPStatusNotOK"|"SchemeNotHTTPOrHTTPS"|"Loading"|"WasGrantedMediaAccess"|"DisableForRenderFrameHostCalled"|"DomainNotAllowed"|"HTTPMethodNotGET"|"SubframeIsNavigating"|"Timeout"|"CacheLimit"|"JavaScriptExecution"|"RendererProcessKilled"|"RendererProcessCrashed"|"SchedulerTrackedFeatureUsed"|"ConflictingBrowsingInstance"|"CacheFlushed"|"ServiceWorkerVersionActivation"|"SessionRestored"|"ServiceWorkerPostMessage"|"EnteredBackForwardCacheBeforeServiceWorkerHostAdded"|"RenderFrameHostReused_SameSite"|"RenderFrameHostReused_CrossSite"|"ServiceWorkerClaim"|"IgnoreEventAndEvict"|"HaveInnerContents"|"TimeoutPuttingInCache"|"BackForwardCacheDisabledByLowMemory"|"BackForwardCacheDisabledByCommandLine"|"NetworkRequestDatapipeDrainedAsBytesConsumer"|"NetworkRequestRedirected"|"NetworkRequestTimeout"|"NetworkExceedsBufferLimit"|"NavigationCancelledWhileRestoring"|"NotMostRecentNavigationEntry"|"BackForwardCacheDisabledForPrerender"|"UserAgentOverrideDiffers"|"ForegroundCacheLimit"|"BrowsingInstanceNotSwapped"|"BackForwardCacheDisabledForDelegate"|"UnloadHandlerExistsInMainFrame"|"UnloadHandlerExistsInSubFrame"|"ServiceWorkerUnregistration"|"CacheControlNoStore"|"CacheControlNoStoreCookieModified"|"CacheControlNoStoreHTTPOnlyCookieModified"|"NoResponseHead"|"Unknown"|"ActivationNavigationsDisallowedForBug1234857"|"ErrorDocument"|"FencedFramesEmbedder"|"CookieDisabled"|"HTTPAuthRequired"|"CookieFlushed"|"WebSocket"|"WebTransport"|"WebRTC"|"MainResourceHasCacheControlNoStore"|"MainResourceHasCacheControlNoCache"|"SubresourceHasCacheControlNoStore"|"SubresourceHasCacheControlNoCache"|"ContainsPlugins"|"DocumentLoaded"|"OutstandingNetworkRequestOthers"|"RequestedMIDIPermission"|"RequestedAudioCapturePermission"|"RequestedVideoCapturePermission"|"RequestedBackForwardCacheBlockedSensors"|"RequestedBackgroundWorkPermission"|"BroadcastChannel"|"WebXR"|"SharedWorker"|"WebLocks"|"WebHID"|"WebShare"|"RequestedStorageAccessGrant"|"WebNfc"|"OutstandingNetworkRequestFetch"|"OutstandingNetworkRequestXHR"|"AppBanner"|"Printing"|"WebDatabase"|"PictureInPicture"|"Portal"|"SpeechRecognizer"|"IdleManager"|"PaymentManager"|"SpeechSynthesis"|"KeyboardLock"|"WebOTPService"|"OutstandingNetworkRequestDirectSocket"|"InjectedJavascript"|"InjectedStyleSheet"|"KeepaliveRequest"|"IndexedDBEvent"|"Dummy"|"JsNetworkRequestReceivedCacheControlNoStoreResource"|"WebRTCSticky"|"WebTransportSticky"|"WebSocketSticky"|"SmartCard"|"LiveMediaStreamTrack"|"UnloadHandler"|"ContentSecurityHandler"|"ContentWebAuthenticationAPI"|"ContentFileChooser"|"ContentSerial"|"ContentFileSystemAccess"|"ContentMediaDevicesDispatcherHost"|"ContentWebBluetooth"|"ContentWebUSB"|"ContentMediaSessionService"|"ContentScreenReader"|"EmbedderPopupBlockerTabHelper"|"EmbedderSafeBrowsingTriggeredPopupBlocker"|"EmbedderSafeBrowsingThreatDetails"|"EmbedderAppBannerManager"|"EmbedderDomDistillerViewerSource"|"EmbedderDomDistillerSelfDeletingRequestDelegate"|"EmbedderOomInterventionTabHelper"|"EmbedderOfflinePage"|"EmbedderChromePasswordManagerClientBindCredentialManager"|"EmbedderPermissionRequestManager"|"EmbedderModalDialog"|"EmbedderExtensions"|"EmbedderExtensionMessaging"|"EmbedderExtensionMessagingForOpenPort"|"EmbedderExtensionSentMessageToCachedFrame";
/**
* Types of not restored reasons for back-forward cache.
*/
@ -11723,7 +11811,7 @@ open.
*/
type: DialogType;
/**
* True iff browser is capable showing or acting on the given dialog. When browser has no
* True if browser is capable showing or acting on the given dialog. When browser has no
dialog handler for given target, calling alert while Page domain is engaged will stall
the page execution. Execution can be resumed via calling Page.handleJavaScriptDialog.
*/
@ -11756,7 +11844,7 @@ when bfcache navigation fails.
*/
export type backForwardCacheNotUsedPayload = {
/**
* The loader id for the associated navgation.
* The loader id for the associated navigation.
*/
loaderId: Network.LoaderId;
/**
@ -12704,7 +12792,7 @@ https://github.com/WICG/web-lifecycle/
}
/**
* Requests backend to produce compilation cache for the specified scripts.
`scripts` are appeneded to the list of scripts for which the cache
`scripts` are appended to the list of scripts for which the cache
would be produced. The list may be reset during page navigation.
When script with a matching URL is encountered, the cache is optionally
produced upon backend discretion, based on internal heuristics.
@ -12923,7 +13011,7 @@ https://w3c.github.io/performance-timeline/#dom-performanceobserver.
frameId: Page.FrameId;
/**
* The event type, as specified in https://w3c.github.io/performance-timeline/#dom-performanceentry-entrytype
This determines which of the optional "details" fiedls is present.
This determines which of the optional "details" fields is present.
*/
type: string;
/**
@ -13033,7 +13121,7 @@ https://www.w3.org/TR/mixed-content/#categories
*/
certificateNetworkError?: string;
/**
* True if the certificate uses a weak signature aglorithm.
* True if the certificate uses a weak signature algorithm.
*/
certificateHasWeakSignature: boolean;
/**
@ -13441,6 +13529,10 @@ Tokens from that issuer.
* Enum of auction events.
*/
export type InterestGroupAuctionEventType = "started"|"configResolved";
/**
* Enum of network fetches auctions can do.
*/
export type InterestGroupAuctionFetchType = "bidderJs"|"bidderWasm"|"sellerJs"|"bidderTrustedSignals"|"sellerTrustedSignals";
/**
* Ad advertising element inside an interest group.
*/
@ -13480,9 +13572,23 @@ Tokens from that issuer.
* Details for an origin's shared storage.
*/
export interface SharedStorageMetadata {
/**
* Time when the origin's shared storage was last created.
*/
creationTime: Network.TimeSinceEpoch;
/**
* Number of key-value pairs stored in origin's shared storage.
*/
length: number;
/**
* Current amount of bits of entropy remaining in the navigation budget.
*/
remainingBudget: number;
/**
* Total number of bytes stored as key-value pairs in origin's shared
storage.
*/
bytesUsed: number;
}
/**
* Pair of reporting metadata details for a candidate URL for `selectURL()`.
@ -13642,7 +13748,7 @@ int
}
export type AttributionReportingSourceRegistrationResult = "success"|"internalError"|"insufficientSourceCapacity"|"insufficientUniqueDestinationCapacity"|"excessiveReportingOrigins"|"prohibitedByBrowserPolicy"|"successNoised"|"destinationReportingLimitReached"|"destinationGlobalLimitReached"|"destinationBothLimitsReached"|"reportingOriginsPerSiteLimitReached"|"exceedsMaxChannelCapacity";
export type AttributionReportingSourceRegistrationTimeConfig = "include"|"exclude";
export interface AttributionReportingAggregatableValueEntry {
export interface AttributionReportingAggregatableValueDictEntry {
key: string;
/**
* number instead of integer because not all uint32 can be represented by
@ -13650,6 +13756,10 @@ int
*/
value: number;
}
export interface AttributionReportingAggregatableValueEntry {
values: AttributionReportingAggregatableValueDictEntry[];
filters: AttributionReportingFilterPair;
}
export interface AttributionReportingEventTriggerData {
data: UnsignedInt64AsBase10;
priority: SignedInt64AsBase10;
@ -13801,6 +13911,22 @@ target-specific.
*/
auctionConfig?: { [key: string]: string };
}
/**
* Specifies which auctions a particular network fetch may be related to, and
in what role. Note that it is not ordered with respect to
Network.requestWillBeSent (but will happen before loadingFinished
loadingFailed).
*/
export type interestGroupAuctionNetworkRequestCreatedPayload = {
type: InterestGroupAuctionFetchType;
requestId: Network.RequestId;
/**
* This is the set of the auctions using the worklet that issued this
request. In the case of trusted signals, it's possible that only some of
them actually care about the keys being queried.
*/
auctions: InterestGroupAuctionId[];
}
/**
* Shared storage was accessed by the associated page.
The following parameters are included in all events.
@ -13823,7 +13949,7 @@ The following parameters are included in all events.
*/
ownerOrigin: string;
/**
* The sub-parameters warapped by `params` are all optional and their
* The sub-parameters wrapped by `params` are all optional and their
presence/absence depends on `type`.
*/
params: SharedStorageAccessParams;
@ -14101,7 +14227,8 @@ Leaves other stored data, including the issuer's Redemption Records, intact.
export type setInterestGroupTrackingReturnValue = {
}
/**
* Enables/Disables issuing of interestGroupAuctionEvent events.
* Enables/Disables issuing of interestGroupAuctionEventOccurred and
interestGroupAuctionNetworkRequestCreated.
*/
export type setInterestGroupAuctionTrackingParameters = {
enable: boolean;
@ -14456,6 +14583,9 @@ supported.
export interface TargetInfo {
targetId: TargetID;
type: string;
/**
* List of types: https://source.chromium.org/chromium/chromium/src/+/main:content/browser/devtools/devtools_agent_host_impl.cc?ss=chromium&q=f:devtools%20-f:out%20%22::kTypeTab%5B%5D%22
*/
title: string;
url: string;
/**
@ -14486,7 +14616,7 @@ the type of "page", this may be set to "portal" or "prerender".
*/
export interface FilterEntry {
/**
* If set, causes exclusion of mathcing targets from the list.
* If set, causes exclusion of matching targets from the list.
*/
exclude?: boolean;
/**
@ -14637,7 +14767,7 @@ channel with browser target.
Injected object will be available as `window[bindingName]`.
The object has the follwing API:
The object has the following API:
- `binding.send(json)` - a method to send messages over the remote debugging protocol
- `binding.onmessage = json => handleMessage(json)` - a callback that will be called for the protocol notifications and command responses.
*/
@ -15850,6 +15980,18 @@ See https://w3c.github.io/webauthn/#signature-counter
See https://w3c.github.io/webauthn/#sctn-large-blob-extension
*/
largeBlob?: binary;
/**
* Assertions returned by this credential will have the backup eligibility
(BE) flag set to this value. Defaults to the authenticator's
defaultBackupEligibility value.
*/
backupEligibility?: boolean;
/**
* Assertions returned by this credential will have the backup state (BS)
flag set to this value. Defaults to the authenticator's
defaultBackupState value.
*/
backupState?: boolean;
}
/**
@ -15996,6 +16138,18 @@ The default is true.
}
export type setAutomaticPresenceSimulationReturnValue = {
}
/**
* Allows setting credential properties.
https://w3c.github.io/webauthn/#sctn-automation-set-credential-properties
*/
export type setCredentialPropertiesParameters = {
authenticatorId: AuthenticatorId;
credentialId: binary;
backupEligibility?: boolean;
backupState?: boolean;
}
export type setCredentialPropertiesReturnValue = {
}
}
/**
@ -16231,7 +16385,7 @@ See also:
requestId?: Network.RequestId;
/**
* Error information
`errorMessage` is null iff `errorType` is null.
`errorMessage` is null if `errorType` is null.
*/
errorType?: RuleSetErrorType;
/**
@ -16270,7 +16424,7 @@ still keyed with the initial URL.
that had a speculation rule that triggered the attempt, and the
BackendNodeIds of <a href> or <area href> elements that triggered the
attempt (in the case of attempts triggered by a document rule). It is
possible for mulitple rule sets and links to trigger a single attempt.
possible for multiple rule sets and links to trigger a single attempt.
*/
export interface PreloadingAttemptSource {
key: PreloadingAttemptKey;
@ -19226,6 +19380,7 @@ Error was thrown.
"Storage.indexedDBListUpdated": Storage.indexedDBListUpdatedPayload;
"Storage.interestGroupAccessed": Storage.interestGroupAccessedPayload;
"Storage.interestGroupAuctionEventOccurred": Storage.interestGroupAuctionEventOccurredPayload;
"Storage.interestGroupAuctionNetworkRequestCreated": Storage.interestGroupAuctionNetworkRequestCreatedPayload;
"Storage.sharedStorageAccessed": Storage.sharedStorageAccessedPayload;
"Storage.storageBucketCreatedOrUpdated": Storage.storageBucketCreatedOrUpdatedPayload;
"Storage.storageBucketDeleted": Storage.storageBucketDeletedPayload;
@ -19781,6 +19936,7 @@ Error was thrown.
"WebAuthn.clearCredentials": WebAuthn.clearCredentialsParameters;
"WebAuthn.setUserVerified": WebAuthn.setUserVerifiedParameters;
"WebAuthn.setAutomaticPresenceSimulation": WebAuthn.setAutomaticPresenceSimulationParameters;
"WebAuthn.setCredentialProperties": WebAuthn.setCredentialPropertiesParameters;
"Media.enable": Media.enableParameters;
"Media.disable": Media.disableParameters;
"DeviceAccess.enable": DeviceAccess.enableParameters;
@ -20362,6 +20518,7 @@ Error was thrown.
"WebAuthn.clearCredentials": WebAuthn.clearCredentialsReturnValue;
"WebAuthn.setUserVerified": WebAuthn.setUserVerifiedReturnValue;
"WebAuthn.setAutomaticPresenceSimulation": WebAuthn.setAutomaticPresenceSimulationReturnValue;
"WebAuthn.setCredentialProperties": WebAuthn.setCredentialPropertiesReturnValue;
"Media.enable": Media.enableReturnValue;
"Media.disable": Media.disableReturnValue;
"DeviceAccess.enable": DeviceAccess.enableReturnValue;

View file

@ -14,9 +14,8 @@
* limitations under the License.
*/
const path = require('path');
const { test, expect, devices, defineConfig: originalDefineConfig } = require('@playwright/experimental-ct-core');
const path = require('path');
process.env['NODE_ENV'] = 'test';

View file

@ -17,7 +17,7 @@
import fs from 'fs';
import path from 'path';
import { Watcher } from 'playwright/lib/fsWatcher';
import { loadConfigFromFile } from 'playwright/lib/common/configLoader';
import { loadConfigFromFileRestartIfNeeded } from 'playwright/lib/common/configLoader';
import { Runner } from 'playwright/lib/runner/runner';
import type { PluginContext } from 'rollup';
import { source as injectedSource } from './generated/indexSource';
@ -25,7 +25,7 @@ import { createConfig, populateComponentsFromTests, resolveDirs, transformIndexF
import type { ComponentRegistry } from './viteUtils';
export async function runDevServer(configFile: string) {
const config = await loadConfigFromFile(configFile);
const config = await loadConfigFromFileRestartIfNeeded(configFile);
if (!config)
return;

View file

@ -40,7 +40,13 @@ function __pwRender(value) {
if (isJsxComponent(v)) {
const component = v;
const props = component.props ? __pwRender(component.props) : {};
return { result: __pwReact.createElement(/** @type { any } */ (component.type), { ...props, children: undefined }, props.children) };
const {children, ...propsWithoutChildren} = props;
/** @type {[any, any, any?]} */
const createElementArguments = [component.type, propsWithoutChildren];
if(children){
createElementArguments.push(children);
}
return { result: __pwReact.createElement(...createElementArguments) };
}
});
}

View file

@ -40,7 +40,14 @@ function __pwRender(value) {
if (isJsxComponent(v)) {
const component = v;
const props = component.props ? __pwRender(component.props) : {};
return { result: __pwReact.createElement(/** @type { any } */ (component.type), { ...props, children: undefined }, props.children) };
const {children, ...propsWithoutChildren} = props;
/** @type {[any, any, any?]} */
const createElementArguments = [component.type, propsWithoutChildren];
if(children){
createElementArguments.push(children);
}
return { result: __pwReact.createElement(...createElementArguments) };
}
});
}

View file

@ -26,6 +26,11 @@ import type { ConfigCLIOverrides } from './ipc';
import type { FullConfig, FullProject } from '../../types/test';
import { setTransformConfig } from '../transform/transform';
export type ConfigLocation = {
resolvedConfigFile?: string;
configDir: string;
};
export type FixturesWithLocation = {
fixtures: Fixtures;
location: Location;
@ -58,53 +63,54 @@ export class FullConfigInternal {
return (config as any)[configInternalSymbol];
}
constructor(configDir: string, configFile: string | undefined, config: Config, configCLIOverrides: ConfigCLIOverrides) {
if (configCLIOverrides.projects && config.projects)
constructor(location: ConfigLocation, userConfig: Config, configCLIOverrides: ConfigCLIOverrides) {
if (configCLIOverrides.projects && userConfig.projects)
throw new Error(`Cannot use --browser option when configuration file defines projects. Specify browserName in the projects instead.`);
const { resolvedConfigFile, configDir } = location;
const packageJsonPath = getPackageJsonPath(configDir);
const packageJsonDir = packageJsonPath ? path.dirname(packageJsonPath) : undefined;
const throwawayArtifactsPath = packageJsonDir || process.cwd();
this.configDir = configDir;
this.configCLIOverrides = configCLIOverrides;
this.globalOutputDir = takeFirst(configCLIOverrides.outputDir, pathResolve(configDir, config.outputDir), throwawayArtifactsPath, path.resolve(process.cwd()));
this.globalOutputDir = takeFirst(configCLIOverrides.outputDir, pathResolve(configDir, userConfig.outputDir), throwawayArtifactsPath, path.resolve(process.cwd()));
this.preserveOutputDir = configCLIOverrides.preserveOutputDir || false;
this.ignoreSnapshots = takeFirst(configCLIOverrides.ignoreSnapshots, config.ignoreSnapshots, false);
const privateConfiguration = (config as any)['@playwright/test'];
this.ignoreSnapshots = takeFirst(configCLIOverrides.ignoreSnapshots, userConfig.ignoreSnapshots, false);
const privateConfiguration = (userConfig as any)['@playwright/test'];
this.plugins = (privateConfiguration?.plugins || []).map((p: any) => ({ factory: p }));
this.config = {
configFile,
rootDir: pathResolve(configDir, config.testDir) || configDir,
forbidOnly: takeFirst(configCLIOverrides.forbidOnly, config.forbidOnly, false),
fullyParallel: takeFirst(configCLIOverrides.fullyParallel, config.fullyParallel, false),
globalSetup: takeFirst(resolveScript(config.globalSetup, configDir), null),
globalTeardown: takeFirst(resolveScript(config.globalTeardown, configDir), null),
globalTimeout: takeFirst(configCLIOverrides.globalTimeout, config.globalTimeout, 0),
grep: takeFirst(config.grep, defaultGrep),
grepInvert: takeFirst(config.grepInvert, null),
maxFailures: takeFirst(configCLIOverrides.maxFailures, config.maxFailures, 0),
metadata: takeFirst(config.metadata, {}),
preserveOutput: takeFirst(config.preserveOutput, 'always'),
reporter: takeFirst(configCLIOverrides.reporter, resolveReporters(config.reporter, configDir), [[defaultReporter]]),
reportSlowTests: takeFirst(config.reportSlowTests, { max: 5, threshold: 15000 }),
quiet: takeFirst(configCLIOverrides.quiet, config.quiet, false),
configFile: resolvedConfigFile,
rootDir: pathResolve(configDir, userConfig.testDir) || configDir,
forbidOnly: takeFirst(configCLIOverrides.forbidOnly, userConfig.forbidOnly, false),
fullyParallel: takeFirst(configCLIOverrides.fullyParallel, userConfig.fullyParallel, false),
globalSetup: takeFirst(resolveScript(userConfig.globalSetup, configDir), null),
globalTeardown: takeFirst(resolveScript(userConfig.globalTeardown, configDir), null),
globalTimeout: takeFirst(configCLIOverrides.globalTimeout, userConfig.globalTimeout, 0),
grep: takeFirst(userConfig.grep, defaultGrep),
grepInvert: takeFirst(userConfig.grepInvert, null),
maxFailures: takeFirst(configCLIOverrides.maxFailures, userConfig.maxFailures, 0),
metadata: takeFirst(userConfig.metadata, {}),
preserveOutput: takeFirst(userConfig.preserveOutput, 'always'),
reporter: takeFirst(configCLIOverrides.reporter, resolveReporters(userConfig.reporter, configDir), [[defaultReporter]]),
reportSlowTests: takeFirst(userConfig.reportSlowTests, { max: 5, threshold: 15000 }),
quiet: takeFirst(configCLIOverrides.quiet, userConfig.quiet, false),
projects: [],
shard: takeFirst(configCLIOverrides.shard, config.shard, null),
updateSnapshots: takeFirst(configCLIOverrides.updateSnapshots, config.updateSnapshots, 'missing'),
shard: takeFirst(configCLIOverrides.shard, userConfig.shard, null),
updateSnapshots: takeFirst(configCLIOverrides.updateSnapshots, userConfig.updateSnapshots, 'missing'),
version: require('../../package.json').version,
workers: 0,
webServer: null,
};
for (const key in config) {
for (const key in userConfig) {
if (key.startsWith('@'))
(this.config as any)[key] = (config as any)[key];
(this.config as any)[key] = (userConfig as any)[key];
}
(this.config as any)[configInternalSymbol] = this;
const workers = takeFirst(configCLIOverrides.workers, config.workers, '50%');
const workers = takeFirst(configCLIOverrides.workers, userConfig.workers, '50%');
if (typeof workers === 'string') {
if (workers.endsWith('%')) {
const cpus = os.cpus().length;
@ -116,7 +122,7 @@ export class FullConfigInternal {
this.config.workers = workers;
}
const webServers = takeFirst(config.webServer, null);
const webServers = takeFirst(userConfig.webServer, null);
if (Array.isArray(webServers)) { // multiple web server mode
// Due to previous choices, this value shows up to the user in globalSetup as part of FullConfig. Arrays are not supported by the old type.
this.config.webServer = null;
@ -128,13 +134,13 @@ export class FullConfigInternal {
this.webServers = [];
}
const projectConfigs = configCLIOverrides.projects || config.projects || [config];
this.projects = projectConfigs.map(p => new FullProjectInternal(configDir, config, this, p, this.configCLIOverrides, throwawayArtifactsPath));
const projectConfigs = configCLIOverrides.projects || userConfig.projects || [userConfig];
this.projects = projectConfigs.map(p => new FullProjectInternal(configDir, userConfig, this, p, this.configCLIOverrides, throwawayArtifactsPath));
resolveProjectDependencies(this.projects);
this._assignUniqueProjectIds(this.projects);
setTransformConfig({
babelPlugins: privateConfiguration?.babelPlugins || [],
external: config.build?.external || [],
external: userConfig.build?.external || [],
});
this.config.projects = this.projects.map(p => p.project);
}

View file

@ -21,7 +21,7 @@ import type { ConfigCLIOverrides, SerializedConfig } from './ipc';
import { requireOrImport } from '../transform/transform';
import type { Config, Project } from '../../types/test';
import { errorWithFile, fileIsModule } from '../util';
import { setCurrentConfig } from './globals';
import type { ConfigLocation } from './config';
import { FullConfigInternal } from './config';
import { addToCompilationCache } from '../transform/compilationCache';
import { initializeEsmLoader, registerESMLoader } from './esmLoaderHost';
@ -84,60 +84,34 @@ export const defineConfig = (...configs: any[]) => {
return result;
};
export class ConfigLoader {
private _configCLIOverrides: ConfigCLIOverrides;
private _fullConfig: FullConfigInternal | undefined;
export async function deserializeConfig(data: SerializedConfig): Promise<FullConfigInternal> {
if (data.compilationCache)
addToCompilationCache(data.compilationCache);
constructor(configCLIOverrides?: ConfigCLIOverrides) {
this._configCLIOverrides = configCLIOverrides || {};
}
static async deserialize(data: SerializedConfig): Promise<FullConfigInternal> {
if (data.compilationCache)
addToCompilationCache(data.compilationCache);
const loader = new ConfigLoader(data.configCLIOverrides);
const config = data.configFile ? await loader.loadConfigFile(data.configFile) : await loader.loadEmptyConfig(data.configDir);
await initializeEsmLoader();
return config;
}
async loadConfigFile(file: string, ignoreProjectDependencies = false): Promise<FullConfigInternal> {
if (this._fullConfig)
throw new Error('Cannot load two config files');
const config = await requireOrImportDefaultObject(file) as Config;
const fullConfig = await this._loadConfig(config, path.dirname(file), file);
setCurrentConfig(fullConfig);
if (ignoreProjectDependencies) {
for (const project of fullConfig.projects) {
project.deps = [];
project.teardown = undefined;
}
}
this._fullConfig = fullConfig;
return fullConfig;
}
async loadEmptyConfig(configDir: string): Promise<FullConfigInternal> {
const fullConfig = await this._loadConfig({}, configDir);
setCurrentConfig(fullConfig);
return fullConfig;
}
private async _loadConfig(config: Config, configDir: string, configFile?: string): Promise<FullConfigInternal> {
// 1. Validate data provided in the config file.
validateConfig(configFile || '<default config>', config);
const fullConfig = new FullConfigInternal(configDir, configFile, config, this._configCLIOverrides);
fullConfig.defineConfigWasUsed = !!(config as any)[kDefineConfigWasUsed];
return fullConfig;
}
const config = await loadConfig(data.location, data.configCLIOverrides);
await initializeEsmLoader();
return config;
}
async function requireOrImportDefaultObject(file: string) {
let object = await requireOrImport(file);
async function loadUserConfig(location: ConfigLocation): Promise<Config> {
let object = location.resolvedConfigFile ? await requireOrImport(location.resolvedConfigFile) : {};
if (object && typeof object === 'object' && ('default' in object))
object = object['default'];
return object;
return object as Config;
}
export async function loadConfig(location: ConfigLocation, overrides?: ConfigCLIOverrides, ignoreProjectDependencies = false): Promise<FullConfigInternal> {
const userConfig = await loadUserConfig(location);
validateConfig(location.resolvedConfigFile || '<default config>', userConfig);
const fullConfig = new FullConfigInternal(location, userConfig, overrides || {});
fullConfig.defineConfigWasUsed = !!(userConfig as any)[kDefineConfigWasUsed];
if (ignoreProjectDependencies) {
for (const project of fullConfig.projects) {
project.deps = [];
project.teardown = undefined;
}
}
return fullConfig;
}
function validateConfig(file: string, config: Config) {
@ -312,7 +286,7 @@ function validateProject(file: string, project: Project, title: string) {
}
}
export function resolveConfigFile(configFileOrDirectory: string): string | null {
export function resolveConfigFile(configFileOrDirectory: string): string | undefined {
const resolveConfig = (configFile: string) => {
if (fs.existsSync(configFile))
return configFile;
@ -334,7 +308,7 @@ export function resolveConfigFile(configFileOrDirectory: string): string | null
if (configFile)
return configFile;
// If there is no config, assume this as a root testing directory.
return null;
return undefined;
} else {
// When passed a file, it must be a config file.
const configFile = resolveConfig(configFileOrDirectory);
@ -342,26 +316,29 @@ export function resolveConfigFile(configFileOrDirectory: string): string | null
}
}
export async function loadConfigFromFile(configFile: string | undefined, overrides?: ConfigCLIOverrides, ignoreDeps?: boolean): Promise<FullConfigInternal | null> {
export async function loadConfigFromFileRestartIfNeeded(configFile: string | undefined, overrides?: ConfigCLIOverrides, ignoreDeps?: boolean): Promise<FullConfigInternal | null> {
const configFileOrDirectory = configFile ? path.resolve(process.cwd(), configFile) : process.cwd();
const resolvedConfigFile = resolveConfigFile(configFileOrDirectory);
if (restartWithExperimentalTsEsm(resolvedConfigFile))
return null;
const configLoader = new ConfigLoader(overrides);
let config: FullConfigInternal;
if (resolvedConfigFile)
config = await configLoader.loadConfigFile(resolvedConfigFile, ignoreDeps);
else
config = await configLoader.loadEmptyConfig(configFileOrDirectory);
return config;
const location: ConfigLocation = {
configDir: resolvedConfigFile ? path.dirname(resolvedConfigFile) : configFileOrDirectory,
resolvedConfigFile,
};
return await loadConfig(location, overrides, ignoreDeps);
}
export function restartWithExperimentalTsEsm(configFile: string | null): boolean {
export async function loadEmptyConfigForMergeReports() {
// Merge reports is "different" for no good reason. It should not pick up local config from the cwd.
return await loadConfig({ configDir: process.cwd() });
}
export function restartWithExperimentalTsEsm(configFile: string | undefined, force: boolean = false): boolean {
const nodeVersion = +process.versions.node.split('.')[0];
// New experimental loader is only supported on Node 16+.
if (nodeVersion < 16)
return false;
if (!configFile)
if (!configFile && !force)
return false;
if (process.env.PW_DISABLE_TS_ESM)
return false;
@ -371,9 +348,10 @@ export function restartWithExperimentalTsEsm(configFile: string | null): boolean
process.execArgv = execArgvWithoutExperimentalLoaderOptions();
return false;
}
if (!fileIsModule(configFile))
if (!force && !fileIsModule(configFile!))
return false;
// Node.js < 20
// Node.js < 20
if (!require('node:module').register) {
const innerProcess = (require('child_process') as typeof import('child_process')).fork(require.resolve('../../cli'), process.argv.slice(2), {
env: {

View file

@ -16,7 +16,6 @@
import type { TestInfoImpl } from '../worker/testInfo';
import type { Suite } from './test';
import type { FullConfigInternal } from './config';
let currentTestInfoValue: TestInfoImpl | null = null;
export function setCurrentTestInfo(testInfo: TestInfoImpl | null) {
@ -61,11 +60,3 @@ export function setIsWorkerProcess() {
export function isWorkerProcess() {
return _isWorkerProcess;
}
let currentConfigValue: FullConfigInternal | null = null;
export function setCurrentConfig(config: FullConfigInternal | null) {
currentConfigValue = config;
}
export function currentConfig(): FullConfigInternal | null {
return currentConfigValue;
}

View file

@ -16,7 +16,7 @@
import util from 'util';
import { serializeCompilationCache } from '../transform/compilationCache';
import type { FullConfigInternal } from './config';
import type { ConfigLocation, FullConfigInternal } from './config';
import type { ReporterDescription, TestInfoError, TestStatus } from '../../types/test';
export type ConfigCLIOverrides = {
@ -41,8 +41,7 @@ export type ConfigCLIOverrides = {
};
export type SerializedConfig = {
configFile: string | undefined;
configDir: string;
location: ConfigLocation;
configCLIOverrides: ConfigCLIOverrides;
compilationCache: any;
};
@ -138,8 +137,7 @@ export type EnvProducedPayload = [string, string | null][];
export function serializeConfig(config: FullConfigInternal, passCompilationCache: boolean): SerializedConfig {
const result: SerializedConfig = {
configFile: config.config.configFile,
configDir: config.configDir,
location: { configDir: config.configDir, resolvedConfigFile: config.config.configFile },
configCLIOverrides: config.configCLIOverrides,
compilationCache: passCompilationCache ? serializeCompilationCache() : undefined,
};

View file

@ -15,7 +15,7 @@
*/
import type { SerializedConfig } from '../common/ipc';
import { ConfigLoader } from '../common/configLoader';
import { deserializeConfig } from '../common/configLoader';
import { ProcessRunner } from '../common/process';
import type { FullConfigInternal } from '../common/config';
import { loadTestFile } from '../common/testLoader';
@ -36,7 +36,7 @@ export class LoaderMain extends ProcessRunner {
private _config(): Promise<FullConfigInternal> {
if (!this._configPromise)
this._configPromise = ConfigLoader.deserialize(this._serializedConfig);
this._configPromise = deserializeConfig(this._serializedConfig);
return this._configPromise;
}

View file

@ -24,17 +24,16 @@ import { stopProfiling, startProfiling, gracefullyProcessExitDoNotHang } from 'p
import { serializeError } from './util';
import { showHTMLReport } from './reporters/html';
import { createMergedReport } from './reporters/merge';
import { ConfigLoader, loadConfigFromFile } from './common/configLoader';
import { loadConfigFromFileRestartIfNeeded, loadEmptyConfigForMergeReports } from './common/configLoader';
import type { ConfigCLIOverrides } from './common/ipc';
import type { FullResult, TestError } from '../types/testReporter';
import type { FullConfig, TraceMode } from '../types/test';
import type { TraceMode } from '../types/test';
import { builtInReporters, defaultReporter, defaultTimeout } from './common/config';
import type { FullConfigInternal } from './common/config';
import { program } from 'playwright-core/lib/cli/program';
export { program } from 'playwright-core/lib/cli/program';
import type { ReporterDescription } from '../types/test';
import { prepareErrorStack } from './reporters/base';
import { affectedTestFiles, cacheDir } from './transform/compilationCache';
import { cacheDir } from './transform/compilationCache';
import { runTestServer } from './runner/testServer';
function addTestCommand(program: Command) {
@ -74,7 +73,7 @@ function addClearCacheCommand(program: Command) {
command.description('clears build and test caches');
command.option('-c, --config <file>', `Configuration file, or a test directory with optional "playwright.config.{m,c}?{js,ts}"`);
command.action(async opts => {
const configInternal = await loadConfigFromFile(opts.config);
const configInternal = await loadConfigFromFileRestartIfNeeded(opts.config);
if (!configInternal)
return;
const { config, configDir } = configInternal;
@ -102,26 +101,15 @@ function addFindRelatedTestFilesCommand(program: Command) {
command.description('Returns the list of related tests to the given files');
command.option('-c, --config <file>', `Configuration file, or a test directory with optional "playwright.config.{m,c}?{js,ts}"`);
command.action(async (files, options) => {
await withRunnerAndMutedWrite(options.config, async (runner, config, configDir) => {
const result = await runner.loadAllTests();
if (result.status !== 'passed' || !result.suite)
return { errors: result.errors };
const resolvedFiles = (files as string[]).map(file => path.resolve(process.cwd(), file));
const override = (config as any)['@playwright/test']?.['cli']?.['find-related-test-files'];
if (override)
return await override(resolvedFiles, config, configDir, result.suite);
return { testFiles: affectedTestFiles(resolvedFiles) };
});
await withRunnerAndMutedWrite(options.config, runner => runner.findRelatedTestFiles('in-process', files));
});
}
function addTestServerCommand(program: Command) {
const command = program.command('test-server', { hidden: true });
command.description('start test server');
command.option('-c, --config <file>', `Configuration file, or a test directory with optional "playwright.config.{m,c}?{js,ts}"`);
command.action(options => {
void runTestServer(options.config);
command.action(() => {
void runTestServer();
});
}
@ -164,7 +152,7 @@ Examples:
async function runTests(args: string[], opts: { [key: string]: any }) {
await startProfiling();
const config = await loadConfigFromFile(opts.config, overridesFromOptions(opts), opts.deps === false);
const config = await loadConfigFromFileRestartIfNeeded(opts.config, overridesFromOptions(opts), opts.deps === false);
if (!config)
return;
@ -188,16 +176,16 @@ async function runTests(args: string[], opts: { [key: string]: any }) {
gracefullyProcessExitDoNotHang(exitCode);
}
export async function withRunnerAndMutedWrite(configFile: string | undefined, callback: (runner: Runner, config: FullConfig, configDir: string) => Promise<any>) {
export async function withRunnerAndMutedWrite(configFile: string | undefined, callback: (runner: Runner) => Promise<any>) {
// Redefine process.stdout.write in case config decides to pollute stdio.
const stdoutWrite = process.stdout.write.bind(process.stdout);
process.stdout.write = ((a: any, b: any, c: any) => process.stderr.write(a, b, c)) as any;
try {
const config = await loadConfigFromFile(configFile);
const config = await loadConfigFromFileRestartIfNeeded(configFile);
if (!config)
return;
const runner = new Runner(config);
const result = await callback(runner, config.config, config.configDir);
const result = await callback(runner);
stdoutWrite(JSON.stringify(result, undefined, 2), () => {
gracefullyProcessExitDoNotHang(0);
});
@ -211,21 +199,14 @@ export async function withRunnerAndMutedWrite(configFile: string | undefined, ca
}
async function listTestFiles(opts: { [key: string]: any }) {
await withRunnerAndMutedWrite(opts.config, async (runner, config) => {
const frameworkPackage = (config as any)['@playwright/test']?.['packageJSON'];
return await runner.listTestFiles(frameworkPackage, opts.project);
await withRunnerAndMutedWrite(opts.config, async runner => {
return await runner.listTestFiles();
});
}
async function mergeReports(reportDir: string | undefined, opts: { [key: string]: any }) {
const configFile = opts.config;
let config: FullConfigInternal | null;
if (configFile) {
config = await loadConfigFromFile(configFile);
} else {
const configLoader = new ConfigLoader();
config = await configLoader.loadEmptyConfig(process.cwd());
}
const config = configFile ? await loadConfigFromFileRestartIfNeeded(configFile) : await loadEmptyConfigForMergeReports();
if (!config)
return;

View file

@ -316,8 +316,8 @@ export function loadGlobalHook(config: FullConfigInternal, file: string): Promis
return requireOrImportDefaultFunction(path.resolve(config.config.rootDir, file), false);
}
export function loadReporter(config: FullConfigInternal, file: string): Promise<new (arg?: any) => Reporter> {
return requireOrImportDefaultFunction(path.resolve(config.config.rootDir, file), true);
export function loadReporter(config: FullConfigInternal | undefined, file: string): Promise<new (arg?: any) => Reporter> {
return requireOrImportDefaultFunction(config ? path.resolve(config.config.rootDir, file) : file, true);
}
function sourceMapSources(file: string, cache: Map<string, string[]>): string[] {

View file

@ -30,6 +30,7 @@ import { InternalReporter } from '../reporters/internalReporter';
import { Multiplexer } from '../reporters/multiplexer';
import type { Suite } from '../common/test';
import { wrapReporterAsV2 } from '../reporters/reporterV2';
import { affectedTestFiles } from '../transform/compilationCache';
type ProjectConfigWithFiles = {
name: string;
@ -44,6 +45,11 @@ type ConfigListFilesReport = {
error?: TestError;
};
export type FindRelatedTestFilesReport = {
testFiles: string[];
errors?: TestError[];
};
export class Runner {
private _config: FullConfigInternal;
@ -51,8 +57,9 @@ export class Runner {
this._config = config;
}
async listTestFiles(frameworkPackage: string | undefined, projectNames: string[] | undefined): Promise<ConfigListFilesReport> {
const projects = filterProjects(this._config.projects, projectNames);
async listTestFiles(): Promise<ConfigListFilesReport> {
const frameworkPackage = (this._config.config as any)['@playwright/test']?.['packageJSON'];
const projects = filterProjects(this._config.projects);
const report: ConfigListFilesReport = {
projects: [],
cliEntryPoint: frameworkPackage ? path.join(path.dirname(frameworkPackage), 'cli.js') : undefined,
@ -144,4 +151,16 @@ export class Runner {
webServerPluginsForConfig(config).forEach(p => config.plugins.push({ factory: p }));
return await runUIMode(config, options);
}
async findRelatedTestFiles(mode: 'in-process' | 'out-of-process', files: string[]): Promise<FindRelatedTestFilesReport> {
const result = await this.loadAllTests(mode);
if (result.status !== 'passed' || !result.suite)
return { errors: result.errors, testFiles: [] };
const resolvedFiles = (files as string[]).map(file => path.resolve(process.cwd(), file));
const override = (this._config.config as any)['@playwright/test']?.['cli']?.['find-related-test-files'];
if (override)
return await override(resolvedFiles, this._config.config, this._config.configDir, result.suite);
return { testFiles: affectedTestFiles(resolvedFiles) };
}
}

View file

@ -16,48 +16,32 @@
import type http from 'http';
import path from 'path';
import { ManualPromise, createGuid } from 'playwright-core/lib/utils';
import { ManualPromise, createGuid, gracefullyProcessExitDoNotHang } from 'playwright-core/lib/utils';
import { WSServer } from 'playwright-core/lib/utils';
import type { WebSocket } from 'playwright-core/lib/utilsBundle';
import type { FullResult } from 'playwright/types/testReporter';
import type { FullConfigInternal } from '../common/config';
import { ConfigLoader, resolveConfigFile, restartWithExperimentalTsEsm } from '../common/configLoader';
import type { FullResult, TestError } from 'playwright/types/testReporter';
import { loadConfig, restartWithExperimentalTsEsm } from '../common/configLoader';
import { InternalReporter } from '../reporters/internalReporter';
import { Multiplexer } from '../reporters/multiplexer';
import { createReporters } from './reporters';
import { TestRun, createTaskRunnerForList, createTaskRunnerForTestServer } from './tasks';
import type { ConfigCLIOverrides } from '../common/ipc';
import { Runner } from './runner';
import type { FindRelatedTestFilesReport } from './runner';
import type { FullConfigInternal } from '../common/config';
import type { TestServerInterface } from './testServerInterface';
import { serializeError } from '../util';
import { prepareErrorStack } from '../reporters/base';
import { loadReporter } from './loadUtils';
import { wrapReporterAsV2 } from '../reporters/reporterV2';
type PlaywrightTestOptions = {
headed?: boolean,
oneWorker?: boolean,
trace?: 'on' | 'off',
projects?: string[];
grep?: string;
reuseContext?: boolean,
connectWsEndpoint?: string;
};
type ConfigPaths = {
configFile: string | null;
configDir: string;
};
export async function runTestServer(configFile: string | undefined) {
process.env.PW_TEST_HTML_REPORT_OPEN = 'never';
const configFileOrDirectory = configFile ? path.resolve(process.cwd(), configFile) : process.cwd();
const resolvedConfigFile = resolveConfigFile(configFileOrDirectory);
if (restartWithExperimentalTsEsm(resolvedConfigFile))
export async function runTestServer() {
if (restartWithExperimentalTsEsm(undefined, true))
return null;
const configPaths: ConfigPaths = {
configFile: resolvedConfigFile,
configDir: resolvedConfigFile ? path.dirname(resolvedConfigFile) : configFileOrDirectory
};
process.env.PW_TEST_HTML_REPORT_OPEN = 'never';
const wss = new WSServer({
onConnection(request: http.IncomingMessage, url: URL, ws: WebSocket, id: string) {
const dispatcher = new Dispatcher(configPaths, ws);
const dispatcher = new Dispatcher(ws);
ws.on('message', async message => {
const { id, method, params } = JSON.parse(message.toString());
try {
@ -75,16 +59,17 @@ export async function runTestServer(configFile: string | undefined) {
});
const url = await wss.listen(0, 'localhost', '/' + createGuid());
// eslint-disable-next-line no-console
process.on('exit', () => wss.close().catch(console.error));
// eslint-disable-next-line no-console
console.log(`Listening on ${url}`);
process.stdin.on('close', () => gracefullyProcessExitDoNotHang(0));
}
class Dispatcher {
class Dispatcher implements TestServerInterface {
private _testRun: { run: Promise<FullResult['status']>, stop: ManualPromise<void> } | undefined;
private _ws: WebSocket;
private _configPaths: ConfigPaths;
constructor(configPaths: ConfigPaths, ws: WebSocket) {
this._configPaths = configPaths;
constructor(ws: WebSocket) {
this._ws = ws;
process.stdout.write = ((chunk: string | Buffer, cb?: Buffer | Function, cb2?: Function) => {
@ -105,26 +90,39 @@ class Dispatcher {
}) as any;
}
async list(params: { locations: string[], reporter: string, env: NodeJS.ProcessEnv }) {
for (const name in params.env)
process.env[name] = params.env[name];
await this._listTests(params.reporter, params.locations);
async listFiles(params: {
configFile: string;
}): Promise<{
projects: {
name: string;
testDir: string;
use: { testIdAttribute?: string };
files: string[];
}[];
cliEntryPoint?: string;
error?: TestError;
}> {
try {
const config = await this._loadConfig(params.configFile);
const runner = new Runner(config);
return runner.listTestFiles();
} catch (e) {
const error: TestError = serializeError(e);
error.location = prepareErrorStack(e.stack).location;
return { projects: [], error };
}
}
async test(params: { locations: string[], options: PlaywrightTestOptions, reporter: string, env: NodeJS.ProcessEnv }) {
for (const name in params.env)
process.env[name] = params.env[name];
await this._runTests(params.reporter, params.locations, params.options);
}
async stop() {
await this._stopTests();
}
private async _listTests(reporterPath: string, locations: string[] | undefined) {
const config = await this._loadConfig({});
config.cliArgs = [...(locations || []), '--reporter=null'];
const reporter = new InternalReporter(new Multiplexer(await createReporters(config, 'list', [[reporterPath]])));
async listTests(params: {
configFile: string;
locations: string[];
reporter: string;
env: NodeJS.ProcessEnv;
}) {
const config = await this._loadConfig(params.configFile);
config.cliArgs = params.locations || [];
const wireReporter = await this._createReporter(params.reporter);
const reporter = new InternalReporter(new Multiplexer([wireReporter]));
const taskRunner = createTaskRunnerForList(config, reporter, 'out-of-process', { failOnLoadErrors: true });
const testRun = new TestRun(config, reporter);
reporter.onConfigure(config.config);
@ -139,29 +137,43 @@ class Dispatcher {
await reporter.onExit();
}
private async _runTests(reporterPath: string, locations: string[] | undefined, options: PlaywrightTestOptions) {
async test(params: {
configFile: string;
locations: string[];
reporter: string;
env: NodeJS.ProcessEnv;
headed?: boolean;
oneWorker?: boolean;
trace?: 'on' | 'off';
projects?: string[];
grep?: string;
reuseContext?: boolean;
connectWsEndpoint?: string;
}) {
await this._stopTests();
const overrides: ConfigCLIOverrides = {
additionalReporters: [[reporterPath]],
repeatEach: 1,
retries: 0,
preserveOutputDir: true,
use: {
trace: options.trace,
headless: options.headed ? false : undefined,
_optionContextReuseMode: options.reuseContext ? 'when-possible' : undefined,
_optionConnectOptions: options.connectWsEndpoint ? { wsEndpoint: options.connectWsEndpoint } : undefined,
trace: params.trace,
headless: params.headed ? false : undefined,
_optionContextReuseMode: params.reuseContext ? 'when-possible' : undefined,
_optionConnectOptions: params.connectWsEndpoint ? { wsEndpoint: params.connectWsEndpoint } : undefined,
},
workers: options.oneWorker ? 1 : undefined,
workers: params.oneWorker ? 1 : undefined,
};
const config = await this._loadConfig(overrides);
const config = await this._loadConfig(params.configFile, overrides);
config.cliListOnly = false;
config.cliArgs = locations || [];
config.cliGrep = options.grep;
config.cliProjectFilter = options.projects?.length ? options.projects : undefined;
config.cliArgs = params.locations || [];
config.cliGrep = params.grep;
config.cliProjectFilter = params.projects?.length ? params.projects : undefined;
const reporter = new InternalReporter(new Multiplexer(await createReporters(config, 'run')));
const wireReporter = await this._createReporter(params.reporter);
const configReporters = await createReporters(config, 'run');
const reporter = new InternalReporter(new Multiplexer([...configReporters, wireReporter]));
const taskRunner = createTaskRunnerForTestServer(config, reporter);
const testRun = new TestRun(config, reporter);
reporter.onConfigure(config.config);
@ -176,24 +188,43 @@ class Dispatcher {
await run;
}
async findRelatedTestFiles(params: {
configFile: string;
files: string[];
}): Promise<FindRelatedTestFilesReport> {
const config = await this._loadConfig(params.configFile);
const runner = new Runner(config);
return runner.findRelatedTestFiles('out-of-process', params.files);
}
async stop(params: {
configFile: string;
}) {
await this._stopTests();
}
async closeGracefully() {
gracefullyProcessExitDoNotHang(0);
}
private async _stopTests() {
this._testRun?.stop?.resolve();
await this._testRun?.run;
}
private async _loadConfig(overrides: ConfigCLIOverrides) {
const configLoader = new ConfigLoader(overrides);
let config: FullConfigInternal;
if (this._configPaths.configFile)
config = await configLoader.loadConfigFile(this._configPaths.configFile, false);
else
config = await configLoader.loadEmptyConfig(this._configPaths.configDir);
return config;
}
private _dispatchEvent(method: string, params: any) {
this._ws.send(JSON.stringify({ method, params }));
}
private async _loadConfig(configFile: string, overrides?: ConfigCLIOverrides): Promise<FullConfigInternal> {
return loadConfig({ resolvedConfigFile: configFile, configDir: path.dirname(configFile) }, overrides);
}
private async _createReporter(file: string) {
const reporterConstructor = await loadReporter(undefined, file);
const instance = new reporterConstructor((message: any) => this._dispatchEvent('report', message));
return wrapReporterAsV2(instance);
}
}
function chunkToPayload(type: 'stdout' | 'stderr', chunk: Buffer | string) {

View file

@ -0,0 +1,67 @@
/**
* Copyright (c) Microsoft Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import type { TestError } from '../../types/testReporter';
export interface TestServerInterface {
listFiles(params: {
configFile: string;
}): Promise<{
projects: {
name: string;
testDir: string;
use: { testIdAttribute?: string };
files: string[];
}[];
cliEntryPoint?: string;
error?: TestError;
}>;
listTests(params: {
configFile: string;
locations: string[];
reporter: string;
}): Promise<void>;
test(params: {
configFile: string;
locations: string[];
reporter: string;
headed?: boolean;
oneWorker?: boolean;
trace?: 'on' | 'off';
projects?: string[];
grep?: string;
reuseContext?: boolean;
connectWsEndpoint?: string;
}): Promise<void>;
findRelatedTestFiles(params: {
configFile: string;
files: string[];
}): Promise<{ testFiles: string[]; errors?: TestError[]; }>;
stop(params: {
configFile: string;
}): Promise<void>;
closeGracefully(): Promise<void>;
}
export interface TestServerEvents {
on(event: 'report', listener: (params: any) => void): void;
on(event: 'stdio', listener: (params: { type: 'stdout' | 'stderr', text?: string, buffer?: string }) => void): void;
}

View file

@ -58,15 +58,40 @@ class Fixture {
}
async setup(testInfo: TestInfoImpl) {
this.runner.instanceForId.set(this.registration.id, this);
if (typeof this.registration.fn !== 'function') {
this.value = this.registration.fn;
return;
}
testInfo._timeoutManager.setCurrentFixture(this._setupDescription);
const beforeStep = this._shouldGenerateStep ? testInfo._addStep({
title: `fixture: ${this.registration.name}`,
category: 'fixture',
location: this._isInternalFixture ? this.registration.location : undefined,
wallTime: Date.now(),
}) : undefined;
try {
await this._setupInternal(testInfo);
beforeStep?.complete({});
} catch (error) {
beforeStep?.complete({ error });
throw error;
} finally {
testInfo._timeoutManager.setCurrentFixture(undefined);
}
}
private async _setupInternal(testInfo: TestInfoImpl) {
const params: { [key: string]: any } = {};
for (const name of this.registration.deps) {
const registration = this.runner.pool!.resolve(name, this.registration)!;
const dep = await this.runner.setupFixtureForRegistration(registration, testInfo);
const dep = this.runner.instanceForId.get(registration.id);
if (!dep) {
this.failed = true;
return;
}
// Fixture teardown is root => leafs, when we need to teardown a fixture,
// it recursively tears down its usages first.
dep._usages.add(this);
@ -80,25 +105,6 @@ class Fixture {
}
}
testInfo._timeoutManager.setCurrentFixture(this._setupDescription);
const beforeStep = this._shouldGenerateStep ? testInfo._addStep({
title: `fixture: ${this.registration.name}`,
category: 'fixture',
location: this._isInternalFixture ? this.registration.location : undefined,
wallTime: Date.now(),
}) : undefined;
try {
await this._setupInternal(testInfo, params);
beforeStep?.complete({});
} catch (error) {
beforeStep?.complete({ error });
throw error;
} finally {
testInfo._timeoutManager.setCurrentFixture(undefined);
}
}
private async _setupInternal(testInfo: TestInfoImpl, params: object) {
let called = false;
const useFuncStarted = new ManualPromise<void>();
debugTest(`setup ${this.registration.name}`);
@ -198,6 +204,16 @@ export class FixtureRunner {
this.pool = pool;
}
private _collectFixturesInSetupOrder(registration: FixtureRegistration, collector: Set<FixtureRegistration>) {
if (collector.has(registration))
return;
for (const name of registration.deps) {
const dep = this.pool!.resolve(name, registration)!;
this._collectFixturesInSetupOrder(dep, collector);
}
collector.add(registration);
}
async teardownScope(scope: FixtureScope, testInfo: TestInfoImpl, onFixtureError: (error: Error) => void) {
// Teardown fixtures in the reverse order.
const fixtures = Array.from(this.instanceForId.values()).reverse();
@ -211,7 +227,9 @@ export class FixtureRunner {
}
async resolveParametersForFunction(fn: Function, testInfo: TestInfoImpl, autoFixtures: 'worker' | 'test' | 'all-hooks-only'): Promise<object | null> {
// Install automatic fixtures.
const collector = new Set<FixtureRegistration>();
// Collect automatic fixtures.
const auto: FixtureRegistration[] = [];
for (const registration of this.pool!.autoFixtures()) {
let shouldRun = true;
@ -223,19 +241,27 @@ export class FixtureRunner {
auto.push(registration);
}
auto.sort((r1, r2) => (r1.scope === 'worker' ? 0 : 1) - (r2.scope === 'worker' ? 0 : 1));
for (const registration of auto) {
const fixture = await this.setupFixtureForRegistration(registration, testInfo);
for (const registration of auto)
this._collectFixturesInSetupOrder(registration, collector);
// Collect used fixtures.
const names = getRequiredFixtureNames(fn);
for (const name of names)
this._collectFixturesInSetupOrder(this.pool!.resolve(name)!, collector);
// Setup fixtures.
for (const registration of collector) {
const fixture = await this._setupFixtureForRegistration(registration, testInfo);
if (fixture.failed)
return null;
}
// Install used fixtures.
const names = getRequiredFixtureNames(fn);
// Create params object.
const params: { [key: string]: any } = {};
for (const name of names) {
const registration = this.pool!.resolve(name)!;
const fixture = await this.setupFixtureForRegistration(registration, testInfo);
if (fixture.failed)
const fixture = this.instanceForId.get(registration.id)!;
if (!fixture || fixture.failed)
return null;
params[name] = fixture.value;
}
@ -251,7 +277,7 @@ export class FixtureRunner {
return fn(params, testInfo);
}
async setupFixtureForRegistration(registration: FixtureRegistration, testInfo: TestInfoImpl): Promise<Fixture> {
private async _setupFixtureForRegistration(registration: FixtureRegistration, testInfo: TestInfoImpl): Promise<Fixture> {
if (registration.scope === 'test')
this.testScopeClean = false;
@ -260,7 +286,6 @@ export class FixtureRunner {
return fixture;
fixture = new Fixture(this, registration);
this.instanceForId.set(registration.id, fixture);
await fixture.setup(testInfo);
return fixture;
}

View file

@ -18,7 +18,7 @@ import { colors } from 'playwright-core/lib/utilsBundle';
import { debugTest, formatLocation, relativeFilePath, serializeError } from '../util';
import { type TestBeginPayload, type TestEndPayload, type RunPayload, type DonePayload, type WorkerInitParams, type TeardownErrorsPayload, stdioChunkToParams } from '../common/ipc';
import { setCurrentTestInfo, setIsWorkerProcess } from '../common/globals';
import { ConfigLoader } from '../common/configLoader';
import { deserializeConfig } from '../common/configLoader';
import type { Suite, TestCase } from '../common/test';
import type { Annotation, FullConfigInternal, FullProjectInternal } from '../common/config';
import { FixtureRunner } from './fixtureRunner';
@ -205,7 +205,7 @@ export class WorkerMain extends ProcessRunner {
if (this._config)
return;
this._config = await ConfigLoader.deserialize(this._params.config);
this._config = await deserializeConfig(this._params.config);
this._project = this._config.projects.find(p => p.id === this._params.projectId)!;
this._poolBuilder = PoolBuilder.createForWorker(this._project);
}

View file

@ -1,10 +1,9 @@
import { beforeMount, afterMount } from '@playwright/experimental-ct-angular/hooks';
import { Router, provideRouter } from '@angular/router';
import { ButtonComponent } from '@/components/button.component';
import '@/assets/styles.css';
import { TOKEN } from '@/components/inject.component';
import { routes } from '@/router';
import '@/assets/styles.css';
import { APP_INITIALIZER, inject } from '@angular/core';
import { Router, provideRouter } from '@angular/router';
import { afterMount, beforeMount } from '@playwright/experimental-ct-angular/hooks';
export type HooksConfig = {
routing?: boolean;

View file

@ -0,0 +1 @@
<button (click)="submit.emit('hello')">{{title}}</button>

View file

@ -0,0 +1,12 @@
import { test, expect } from '@playwright/experimental-ct-angular';
import type { HooksConfig } from 'playwright';
import { AppComponent } from '@/app.component';
test('navigate to a page by clicking a link', async ({ page, mount }) => {
const component = await mount<HooksConfig>(AppComponent, {
hooksConfig: { routing: true },
});
await expect(component.getByRole('main')).toHaveText('Login');
await component.getByRole('link', { name: 'Dashboard' }).click();
await expect(component.getByRole('main')).toHaveText('Dashboard');
});

View file

@ -7,3 +7,4 @@ test('inject a token', async ({ mount }) => {
});
await expect(component).toHaveText('has been overwritten');
});

View file

@ -0,0 +1,16 @@
type DefaultChildrenProps = {
children?: any;
}
export default function CheckChildrenProp(props: DefaultChildrenProps) {
const content = 'children' in props ? props.children : 'No Children';
return <div>
<h1>Welcome!</h1>
<main>
{content}
</main>
<footer>
Thanks for visiting.
</footer>
</div>
}

View file

@ -1,5 +1,6 @@
import { test, expect } from '@playwright/experimental-ct-react';
import Button from '@/components/Button';
import CheckChildrenProp from '@/components/CheckChildrenProp';
import DefaultChildren from '@/components/DefaultChildren';
import MultipleChildren from '@/components/MultipleChildren';
@ -58,3 +59,8 @@ test('render number as child', async ({ mount }) => {
const component = await mount(<DefaultChildren>{1337}</DefaultChildren>);
await expect(component).toContainText('1337');
});
test('render without children', async ({ mount }) => {
const component = await mount(<CheckChildrenProp />);
await expect(component).toContainText('No Children');
});

View file

@ -0,0 +1,16 @@
type DefaultChildrenProps = {
children?: any;
}
export default function CheckChildrenProp(props: DefaultChildrenProps) {
const content = 'children' in props ? props.children : 'No Children';
return <div>
<h1>Welcome!</h1>
<main>
{content}
</main>
<footer>
Thanks for visiting.
</footer>
</div>
}

View file

@ -1,5 +1,6 @@
import { test, expect } from '@playwright/experimental-ct-react17';
import Button from '@/components/Button';
import CheckChildrenProp from '@/components/CheckChildrenProp';
import DefaultChildren from '@/components/DefaultChildren';
import MultipleChildren from '@/components/MultipleChildren';
@ -58,3 +59,8 @@ test('render number as child', async ({ mount }) => {
const component = await mount(<DefaultChildren>{1337}</DefaultChildren>);
await expect(component).toContainText('1337');
});
test('render without children', async ({ mount }) => {
const component = await mount(<CheckChildrenProp />);
await expect(component).toContainText('No Children');
});

View file

@ -132,14 +132,14 @@ it.describe('should proxy local network requests', () => {
}
]) {
it(`${params.description}`, async ({ platform, browserName, contextFactory, server, proxyServer }) => {
it.skip(browserName === 'webkit' && platform === 'darwin' && ['localhost', '127.0.0.1'].includes(params.target), 'Mac webkit does not proxy localhost');
it.skip(browserName === 'webkit' && platform === 'darwin' && ['localhost', '127.0.0.1'].includes(params.target) && additionalBypass, 'Mac webkit does not proxy localhost when bypass rules are set');
const path = `/target-${additionalBypass}-${params.target}.html`;
server.setRoute(path, async (req, res) => {
res.end('<html><title>Served by the proxy</title></html>');
});
const url = `http://${params.target}:${server.PORT}${path}`;
const url = `http://${params.target}:55555${path}`;
proxyServer.forwardTo(server.PORT);
const context = await contextFactory({
proxy: { server: `localhost:${proxyServer.PORT}`, bypass: additionalBypass ? '1.non.existent.domain.for.the.test' : undefined }

View file

@ -91,14 +91,14 @@ it.describe('should proxy local network requests', () => {
}
]) {
it(`${params.description}`, async ({ platform, browserName, browserType, server, proxyServer }) => {
it.skip(browserName === 'webkit' && platform === 'darwin' && ['localhost', '127.0.0.1'].includes(params.target), 'Mac webkit does not proxy localhost.');
it.skip(browserName === 'webkit' && platform === 'darwin' && ['localhost', '127.0.0.1'].includes(params.target) && additionalBypass, 'Mac webkit does not proxy localhost when bypass rules are set.');
const path = `/target-${additionalBypass}-${params.target}.html`;
server.setRoute(path, async (req, res) => {
res.end('<html><title>Served by the proxy</title></html>');
});
const url = `http://${params.target}:${server.PORT}${path}`;
const url = `http://${params.target}:55555${path}`;
proxyServer.forwardTo(server.PORT);
const browser = await browserType.launch({
proxy: { server: `localhost:${proxyServer.PORT}`, bypass: additionalBypass ? '1.non.existent.domain.for.the.test' : undefined }

View file

@ -48,30 +48,6 @@ test('should list files', async ({ runCLICommand }) => {
});
});
test('should support wildcard list files', async ({ runCLICommand }) => {
const result = await runCLICommand({
'playwright.config.ts': `
module.exports = { projects: [{ name: 'foo' }, { name: 'bar' }] };
`,
'a.test.js': ``
}, 'list-files', ['--project', 'f*o']);
expect(result.exitCode).toBe(0);
const data = JSON.parse(result.stdout);
expect(data).toEqual({
projects: [
{
name: 'foo',
testDir: expect.stringContaining('list-files-should-support-wildcard-list-files-playwright-test'),
use: {},
files: [
expect.stringContaining('a.test.js')
]
}
]
});
});
test('should include testIdAttribute', async ({ runCLICommand }) => {
const result = await runCLICommand({
'playwright.config.ts': `

View file

@ -709,6 +709,9 @@ function translateType(type, parent, generateNameCallback = t => t.name, optiona
if (type.expression === '[null]|[Error]')
return 'void';
if (type.name == 'Promise' && type.templates?.[0].name === 'any')
return 'Task';
if (type.union) {
if (type.union[0].name === 'null' && type.union.length === 2)
return translateType(type.union[1], parent, generateNameCallback, true, isReturnType);
@ -799,6 +802,8 @@ function translateType(type, parent, generateNameCallback = t => t.name, optiona
if (returnType === null)
throw new Error('Unexpected null as return type.');
if (!argsList)
return `Func<${returnType}>`;
return `Func<${argsList}, ${returnType}>`;
}
}

View file

@ -154,6 +154,12 @@ playwright.chromium.launch().then(async browser => {
return 'something random for no reason';
});
await page.addLocatorHandler(page.locator(''), () => {});
await page.addLocatorHandler(page.locator(''), () => 42);
await page.addLocatorHandler(page.locator(''), async () => { });
await page.addLocatorHandler(page.locator(''), async () => 42);
await page.addLocatorHandler(page.locator(''), () => Promise.resolve(42));
await page.keyboard.type('Hello'); // Types instantly
await page.keyboard.type('World', { delay: 100 }); // Types slower, like a user