From ca149be154fef847e137b01a39c88e61d23e8a8f Mon Sep 17 00:00:00 2001 From: Max Schmitt Date: Wed, 24 Jul 2024 18:45:03 +0200 Subject: [PATCH 01/20] test: skip SharedArrayBuffer on macOS 12 (#31845) --- tests/library/browsercontext-viewport.spec.ts | 2 +- tests/library/capabilities.spec.ts | 3 ++- tests/page/page-set-input-files.spec.ts | 18 +++++++++--------- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/tests/library/browsercontext-viewport.spec.ts b/tests/library/browsercontext-viewport.spec.ts index 3ffaee0ba2..360cc5815d 100644 --- a/tests/library/browsercontext-viewport.spec.ts +++ b/tests/library/browsercontext-viewport.spec.ts @@ -181,7 +181,7 @@ browserTest('should be able to get correct orientation angle on non-mobile devic it('should set window.screen.orientation.type for mobile devices', async ({ contextFactory, browserName, server, isMac }) => { it.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/31151' }); it.skip(browserName === 'firefox', 'Firefox does not support mobile emulation'); - it.skip(isMac && parseInt(os.release().split('.')[0], 10) <= 21, 'WebKit on macOS 12 is frozen and does not support orientation.type override'); + it.skip(browserName === 'webkit' && isMac && parseInt(os.release().split('.')[0], 10) <= 21, 'WebKit on macOS 12 is frozen and does not support orientation.type override'); const context = await contextFactory(devices['iPhone 14']); const page = await context.newPage(); await page.goto(server.PREFIX + '/index.html'); diff --git a/tests/library/capabilities.spec.ts b/tests/library/capabilities.spec.ts index bc5fc10cf3..60f09d49e9 100644 --- a/tests/library/capabilities.spec.ts +++ b/tests/library/capabilities.spec.ts @@ -19,7 +19,8 @@ import url from 'url'; import { contextTest as it, expect } from '../config/browserTest'; import { hostPlatform } from '../../packages/playwright-core/src/utils/hostPlatform'; -it('SharedArrayBuffer should work @smoke', async function({ contextFactory, httpsServer }) { +it('SharedArrayBuffer should work @smoke', async function({ contextFactory, httpsServer, isMac, browserName }) { + it.skip(browserName === 'webkit' && isMac && parseInt(os.release().split('.')[0], 10) <= 21, 'WebKit on macOS 12 is frozen and does not support SharedArrayBuffer'); const context = await contextFactory({ ignoreHTTPSErrors: true }); const page = await context.newPage(); httpsServer.setRoute('/sharedarraybuffer', (req, res) => { diff --git a/tests/page/page-set-input-files.spec.ts b/tests/page/page-set-input-files.spec.ts index a32db203bd..8e654f06dd 100644 --- a/tests/page/page-set-input-files.spec.ts +++ b/tests/page/page-set-input-files.spec.ts @@ -39,7 +39,7 @@ it('should upload the file', async ({ page, server, asset }) => { it('should upload a folder', async ({ page, server, browserName, headless, browserMajorVersion, isAndroid }) => { it.skip(isAndroid); - it.skip(os.platform() === 'darwin' && parseInt(os.release().split('.')[0], 10) <= 21, 'WebKit on macOS-12 is frozen'); + it.skip(browserName === 'webkit' && os.platform() === 'darwin' && parseInt(os.release().split('.')[0], 10) <= 21, 'WebKit on macOS-12 is frozen'); await page.goto(server.PREFIX + '/input/folderupload.html'); const input = await page.$('input'); @@ -70,9 +70,9 @@ it('should upload a folder', async ({ page, server, browserName, headless, brows } }); -it('should upload a folder and throw for multiple directories', async ({ page, server, isAndroid }) => { +it('should upload a folder and throw for multiple directories', async ({ page, server, isAndroid, browserName }) => { it.skip(isAndroid); - it.skip(os.platform() === 'darwin' && parseInt(os.release().split('.')[0], 10) <= 21, 'WebKit on macOS-12 is frozen'); + it.skip(browserName === 'webkit' && os.platform() === 'darwin' && parseInt(os.release().split('.')[0], 10) <= 21, 'WebKit on macOS-12 is frozen'); await page.goto(server.PREFIX + '/input/folderupload.html'); const input = await page.$('input'); @@ -89,9 +89,9 @@ it('should upload a folder and throw for multiple directories', async ({ page, s ])).rejects.toThrow('Multiple directories are not supported'); }); -it('should throw if a directory and files are passed', async ({ page, server, isAndroid }) => { +it('should throw if a directory and files are passed', async ({ page, server, isAndroid, browserName }) => { it.skip(isAndroid); - it.skip(os.platform() === 'darwin' && parseInt(os.release().split('.')[0], 10) <= 21, 'WebKit on macOS-12 is frozen'); + it.skip(browserName === 'webkit' && os.platform() === 'darwin' && parseInt(os.release().split('.')[0], 10) <= 21, 'WebKit on macOS-12 is frozen'); await page.goto(server.PREFIX + '/input/folderupload.html'); const input = await page.$('input'); @@ -106,9 +106,9 @@ it('should throw if a directory and files are passed', async ({ page, server, is ])).rejects.toThrow('File paths must be all files or a single directory'); }); -it('should throw when uploading a folder in a normal file upload input', async ({ page, server, isAndroid }) => { +it('should throw when uploading a folder in a normal file upload input', async ({ page, server, isAndroid, browserName }) => { it.skip(isAndroid); - it.skip(os.platform() === 'darwin' && parseInt(os.release().split('.')[0], 10) <= 21, 'WebKit on macOS-12 is frozen'); + it.skip(browserName === 'webkit' && os.platform() === 'darwin' && parseInt(os.release().split('.')[0], 10) <= 21, 'WebKit on macOS-12 is frozen'); await page.goto(server.PREFIX + '/input/fileupload.html'); const input = await page.$('input'); @@ -120,9 +120,9 @@ it('should throw when uploading a folder in a normal file upload input', async ( await expect(input.setInputFiles(dir)).rejects.toThrow('File input does not support directories, pass individual files instead'); }); -it('should throw when uploading a file in a directory upload input', async ({ page, server, isAndroid, asset }) => { +it('should throw when uploading a file in a directory upload input', async ({ page, server, isAndroid, asset, browserName }) => { it.skip(isAndroid); - it.skip(os.platform() === 'darwin' && parseInt(os.release().split('.')[0], 10) <= 21, 'WebKit on macOS-12 is frozen'); + it.skip(browserName === 'webkit' && os.platform() === 'darwin' && parseInt(os.release().split('.')[0], 10) <= 21, 'WebKit on macOS-12 is frozen'); await page.goto(server.PREFIX + '/input/folderupload.html'); const input = await page.$('input'); From 7570c25b3da02b94e8d72ba5843a6f116e8197c4 Mon Sep 17 00:00:00 2001 From: Max Schmitt Date: Wed, 24 Jul 2024 19:13:03 +0200 Subject: [PATCH 02/20] chore: remove glob from client-certificate matching (#31846) Signed-off-by: Max Schmitt Co-authored-by: Dmitry Gozman --- docs/src/api/params.md | 4 ++-- .../socksClientCertificatesInterceptor.ts | 14 ++++------- packages/playwright-core/types/types.d.ts | 24 +++++++++---------- packages/playwright/types/test.d.ts | 4 ++-- tests/library/client-certificates.spec.ts | 14 +++++++++++ 5 files changed, 35 insertions(+), 25 deletions(-) diff --git a/docs/src/api/params.md b/docs/src/api/params.md index 487270d79e..78d62060cc 100644 --- a/docs/src/api/params.md +++ b/docs/src/api/params.md @@ -523,7 +523,7 @@ Does not enforce fixed viewport, allows resizing window in the headed mode. ## context-option-clientCertificates - `clientCertificates` <[Array]<[Object]>> - - `origin` <[string]> Glob pattern to match against the request origin that the certificate is valid for. + - `origin` <[string]> Exact origin that the certificate is valid for. Origin includes `https` protocol, a hostname and optionally a port. - `certPath` ?<[string]> Path to the file with the certificate in PEM format. - `keyPath` ?<[string]> Path to the file with the private key in PEM format. - `pfxPath` ?<[string]> Path to the PFX or PKCS12 encoded private key and certificate chain. @@ -533,7 +533,7 @@ TLS Client Authentication allows the server to request a client certificate and **Details** -An array of client certificates to be used. Each certificate object must have both `certPath` and `keyPath` or a single `pfxPath` to load the client certificate. Optionally, `passphrase` property should be provided if the certficiate is encrypted. If the certificate is valid only for specific origins, the `origin` property should be provided with a glob pattern to match the origins that the certificate is valid for. +An array of client certificates to be used. Each certificate object must have both `certPath` and `keyPath` or a single `pfxPath` to load the client certificate. Optionally, `passphrase` property should be provided if the certficiate is encrypted. The `origin` property should be provided with an exact match to the request origin that the certificate is valid for. :::note Using Client Certificates in combination with Proxy Servers is not supported. diff --git a/packages/playwright-core/src/server/socksClientCertificatesInterceptor.ts b/packages/playwright-core/src/server/socksClientCertificatesInterceptor.ts index 87b0f11c16..ce8086c821 100644 --- a/packages/playwright-core/src/server/socksClientCertificatesInterceptor.ts +++ b/packages/playwright-core/src/server/socksClientCertificatesInterceptor.ts @@ -21,7 +21,7 @@ import fs from 'fs'; import tls from 'tls'; import stream from 'stream'; import { createSocket } from '../utils/happy-eyeballs'; -import { globToRegex, isUnderTest, ManualPromise } from '../utils'; +import { isUnderTest, ManualPromise } from '../utils'; import type { SocksSocketClosedPayload, SocksSocketDataPayload, SocksSocketRequestedPayload } from '../common/socksProxy'; import { SocksProxy } from '../common/socksProxy'; import type * as channels from '@protocol/channels'; @@ -224,20 +224,16 @@ export class ClientCertificatesProxy { } } -const kClientCertificatesGlobRegex = Symbol('kClientCertificatesGlobRegex'); - export function clientCertificatesToTLSOptions( clientCertificates: channels.BrowserNewContextOptions['clientCertificates'], origin: string ): Pick | undefined { const matchingCerts = clientCertificates?.filter(c => { - let regex: RegExp | undefined = (c as any)[kClientCertificatesGlobRegex]; - if (!regex) { - regex = globToRegex(c.origin); - (c as any)[kClientCertificatesGlobRegex] = regex; + try { + return new URL(c.origin).origin === origin; + } catch (error) { + return c.origin === origin; } - regex.lastIndex = 0; - return regex.test(origin); }); if (!matchingCerts || !matchingCerts.length) return; diff --git a/packages/playwright-core/types/types.d.ts b/packages/playwright-core/types/types.d.ts index d207756459..47e263cdb6 100644 --- a/packages/playwright-core/types/types.d.ts +++ b/packages/playwright-core/types/types.d.ts @@ -13172,8 +13172,8 @@ export interface BrowserType { * * An array of client certificates to be used. Each certificate object must have both `certPath` and `keyPath` or a * single `pfxPath` to load the client certificate. Optionally, `passphrase` property should be provided if the - * certficiate is encrypted. If the certificate is valid only for specific origins, the `origin` property should be - * provided with a glob pattern to match the origins that the certificate is valid for. + * certficiate is encrypted. The `origin` property should be provided with an exact match to the request origin that + * the certificate is valid for. * * **NOTE** Using Client Certificates in combination with Proxy Servers is not supported. * @@ -13182,7 +13182,7 @@ export interface BrowserType { */ clientCertificates?: Array<{ /** - * Glob pattern to match against the request origin that the certificate is valid for. + * Exact origin that the certificate is valid for. Origin includes `https` protocol, a hostname and optionally a port. */ origin: string; @@ -15583,8 +15583,8 @@ export interface APIRequest { * * An array of client certificates to be used. Each certificate object must have both `certPath` and `keyPath` or a * single `pfxPath` to load the client certificate. Optionally, `passphrase` property should be provided if the - * certficiate is encrypted. If the certificate is valid only for specific origins, the `origin` property should be - * provided with a glob pattern to match the origins that the certificate is valid for. + * certficiate is encrypted. The `origin` property should be provided with an exact match to the request origin that + * the certificate is valid for. * * **NOTE** Using Client Certificates in combination with Proxy Servers is not supported. * @@ -15593,7 +15593,7 @@ export interface APIRequest { */ clientCertificates?: Array<{ /** - * Glob pattern to match against the request origin that the certificate is valid for. + * Exact origin that the certificate is valid for. Origin includes `https` protocol, a hostname and optionally a port. */ origin: string; @@ -16776,8 +16776,8 @@ export interface Browser extends EventEmitter { * * An array of client certificates to be used. Each certificate object must have both `certPath` and `keyPath` or a * single `pfxPath` to load the client certificate. Optionally, `passphrase` property should be provided if the - * certficiate is encrypted. If the certificate is valid only for specific origins, the `origin` property should be - * provided with a glob pattern to match the origins that the certificate is valid for. + * certficiate is encrypted. The `origin` property should be provided with an exact match to the request origin that + * the certificate is valid for. * * **NOTE** Using Client Certificates in combination with Proxy Servers is not supported. * @@ -16786,7 +16786,7 @@ export interface Browser extends EventEmitter { */ clientCertificates?: Array<{ /** - * Glob pattern to match against the request origin that the certificate is valid for. + * Exact origin that the certificate is valid for. Origin includes `https` protocol, a hostname and optionally a port. */ origin: string; @@ -20226,8 +20226,8 @@ export interface BrowserContextOptions { * * An array of client certificates to be used. Each certificate object must have both `certPath` and `keyPath` or a * single `pfxPath` to load the client certificate. Optionally, `passphrase` property should be provided if the - * certficiate is encrypted. If the certificate is valid only for specific origins, the `origin` property should be - * provided with a glob pattern to match the origins that the certificate is valid for. + * certficiate is encrypted. The `origin` property should be provided with an exact match to the request origin that + * the certificate is valid for. * * **NOTE** Using Client Certificates in combination with Proxy Servers is not supported. * @@ -20236,7 +20236,7 @@ export interface BrowserContextOptions { */ clientCertificates?: Array<{ /** - * Glob pattern to match against the request origin that the certificate is valid for. + * Exact origin that the certificate is valid for. Origin includes `https` protocol, a hostname and optionally a port. */ origin: string; diff --git a/packages/playwright/types/test.d.ts b/packages/playwright/types/test.d.ts index f1f9ee32dd..c5a3f5d9dd 100644 --- a/packages/playwright/types/test.d.ts +++ b/packages/playwright/types/test.d.ts @@ -5208,8 +5208,8 @@ export interface PlaywrightTestOptions { * * An array of client certificates to be used. Each certificate object must have both `certPath` and `keyPath` or a * single `pfxPath` to load the client certificate. Optionally, `passphrase` property should be provided if the - * certficiate is encrypted. If the certificate is valid only for specific origins, the `origin` property should be - * provided with a glob pattern to match the origins that the certificate is valid for. + * certficiate is encrypted. The `origin` property should be provided with an exact match to the request origin that + * the certificate is valid for. * * **NOTE** Using Client Certificates in combination with Proxy Servers is not supported. * diff --git a/tests/library/client-certificates.spec.ts b/tests/library/client-certificates.spec.ts index d1b15e4658..c5fc523925 100644 --- a/tests/library/client-certificates.spec.ts +++ b/tests/library/client-certificates.spec.ts @@ -248,6 +248,20 @@ test.describe('browser', () => { await page.close(); }); + test('should pass with matching certificates and trailing slash', async ({ browser, startCCServer, asset, browserName }) => { + const serverURL = await startCCServer({ useFakeLocalhost: browserName === 'webkit' && process.platform === 'darwin' }); + const page = await browser.newPage({ + clientCertificates: [{ + origin: serverURL, + certPath: asset('client-certificates/client/trusted/cert.pem'), + keyPath: asset('client-certificates/client/trusted/key.pem'), + }], + }); + await page.goto(serverURL); + await expect(page.getByText('Hello Alice, your certificate was issued by localhost!')).toBeVisible(); + await page.close(); + }); + test('should have ignoreHTTPSErrors=false by default', async ({ browser, httpsServer, asset, browserName, platform }) => { const page = await browser.newPage({ clientCertificates: [{ From bdbe4795f137d08c91da6e4363e13743fb3c385f Mon Sep 17 00:00:00 2001 From: Playwright Service <89237858+playwrightmachine@users.noreply.github.com> Date: Thu, 25 Jul 2024 00:42:53 -0700 Subject: [PATCH 03/20] feat(chromium): roll to r1128 (#31848) Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com> --- README.md | 4 +- packages/playwright-core/browsers.json | 4 +- .../src/server/chromium/protocol.d.ts | 185 ++++++++++++++++-- .../src/server/deviceDescriptorsSource.json | 96 ++++----- packages/playwright-core/types/protocol.d.ts | 185 ++++++++++++++++-- 5 files changed, 396 insertions(+), 78 deletions(-) diff --git a/README.md b/README.md index 4b558f7b7f..9dcb0ae885 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # 🎭 Playwright -[![npm version](https://img.shields.io/npm/v/playwright.svg)](https://www.npmjs.com/package/playwright) [![Chromium version](https://img.shields.io/badge/chromium-127.0.6533.57-blue.svg?logo=google-chrome)](https://www.chromium.org/Home) [![Firefox version](https://img.shields.io/badge/firefox-128.0-blue.svg?logo=firefoxbrowser)](https://www.mozilla.org/en-US/firefox/new/) [![WebKit version](https://img.shields.io/badge/webkit-17.4-blue.svg?logo=safari)](https://webkit.org/) +[![npm version](https://img.shields.io/npm/v/playwright.svg)](https://www.npmjs.com/package/playwright) [![Chromium version](https://img.shields.io/badge/chromium-128.0.6613.7-blue.svg?logo=google-chrome)](https://www.chromium.org/Home) [![Firefox version](https://img.shields.io/badge/firefox-128.0-blue.svg?logo=firefoxbrowser)](https://www.mozilla.org/en-US/firefox/new/) [![WebKit version](https://img.shields.io/badge/webkit-17.4-blue.svg?logo=safari)](https://webkit.org/) ## [Documentation](https://playwright.dev) | [API reference](https://playwright.dev/docs/api/class-playwright) @@ -8,7 +8,7 @@ Playwright is a framework for Web Testing and Automation. It allows testing [Chr | | Linux | macOS | Windows | | :--- | :---: | :---: | :---: | -| Chromium 127.0.6533.57 | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| Chromium 128.0.6613.7 | :white_check_mark: | :white_check_mark: | :white_check_mark: | | WebKit 17.4 | :white_check_mark: | :white_check_mark: | :white_check_mark: | | Firefox 128.0 | :white_check_mark: | :white_check_mark: | :white_check_mark: | diff --git a/packages/playwright-core/browsers.json b/packages/playwright-core/browsers.json index f92f4c4bce..cf8a374751 100644 --- a/packages/playwright-core/browsers.json +++ b/packages/playwright-core/browsers.json @@ -3,9 +3,9 @@ "browsers": [ { "name": "chromium", - "revision": "1127", + "revision": "1128", "installByDefault": true, - "browserVersion": "127.0.6533.57" + "browserVersion": "128.0.6613.7" }, { "name": "chromium-tip-of-tree", diff --git a/packages/playwright-core/src/server/chromium/protocol.d.ts b/packages/playwright-core/src/server/chromium/protocol.d.ts index 671230d86c..99ce1d3a6a 100644 --- a/packages/playwright-core/src/server/chromium/protocol.d.ts +++ b/packages/playwright-core/src/server/chromium/protocol.d.ts @@ -112,7 +112,7 @@ export module Protocol { - from 'checked' to 'selected': states which apply to widgets - from 'activedescendant' to 'owns' - relationships between elements other than parent/child/sibling. */ - export type AXPropertyName = "busy"|"disabled"|"editable"|"focusable"|"focused"|"hidden"|"hiddenRoot"|"invalid"|"keyshortcuts"|"settable"|"roledescription"|"live"|"atomic"|"relevant"|"root"|"autocomplete"|"hasPopup"|"level"|"multiselectable"|"orientation"|"multiline"|"readonly"|"required"|"valuemin"|"valuemax"|"valuetext"|"checked"|"expanded"|"modal"|"pressed"|"selected"|"activedescendant"|"controls"|"describedby"|"details"|"errormessage"|"flowto"|"labelledby"|"owns"; + export type AXPropertyName = "busy"|"disabled"|"editable"|"focusable"|"focused"|"hidden"|"hiddenRoot"|"invalid"|"keyshortcuts"|"settable"|"roledescription"|"live"|"atomic"|"relevant"|"root"|"autocomplete"|"hasPopup"|"level"|"multiselectable"|"orientation"|"multiline"|"readonly"|"required"|"valuemin"|"valuemax"|"valuetext"|"checked"|"expanded"|"modal"|"pressed"|"selected"|"activedescendant"|"controls"|"describedby"|"details"|"errormessage"|"flowto"|"labelledby"|"owns"|"url"; /** * A node in the accessibility tree. */ @@ -875,7 +875,7 @@ instead of "limited-quirks". sharedDictionaryError: SharedDictionaryError; request: AffectedRequest; } - export type GenericIssueErrorType = "CrossOriginPortalPostMessageError"|"FormLabelForNameError"|"FormDuplicateIdForInputError"|"FormInputWithNoLabelError"|"FormAutocompleteAttributeEmptyError"|"FormEmptyIdAndNameAttributesForInputError"|"FormAriaLabelledByToNonExistingId"|"FormInputAssignedAutocompleteValueToIdOrNameAttributeError"|"FormLabelHasNeitherForNorNestedInput"|"FormLabelForMatchesNonExistingIdError"|"FormInputHasWrongButWellIntendedAutocompleteValueError"|"ResponseWasBlockedByORB"; + export type GenericIssueErrorType = "FormLabelForNameError"|"FormDuplicateIdForInputError"|"FormInputWithNoLabelError"|"FormAutocompleteAttributeEmptyError"|"FormEmptyIdAndNameAttributesForInputError"|"FormAriaLabelledByToNonExistingId"|"FormInputAssignedAutocompleteValueToIdOrNameAttributeError"|"FormLabelHasNeitherForNorNestedInput"|"FormLabelForMatchesNonExistingIdError"|"FormInputHasWrongButWellIntendedAutocompleteValueError"|"ResponseWasBlockedByORB"; /** * Depending on the concrete errorType, different properties are set. */ @@ -934,7 +934,7 @@ Should be updated alongside RequestIdTokenStatus in third_party/blink/public/mojom/devtools/inspector_issue.mojom to include all cases except for success. */ - export type FederatedAuthRequestIssueReason = "ShouldEmbargo"|"TooManyRequests"|"WellKnownHttpNotFound"|"WellKnownNoResponse"|"WellKnownInvalidResponse"|"WellKnownListEmpty"|"WellKnownInvalidContentType"|"ConfigNotInWellKnown"|"WellKnownTooBig"|"ConfigHttpNotFound"|"ConfigNoResponse"|"ConfigInvalidResponse"|"ConfigInvalidContentType"|"ClientMetadataHttpNotFound"|"ClientMetadataNoResponse"|"ClientMetadataInvalidResponse"|"ClientMetadataInvalidContentType"|"DisabledInSettings"|"ErrorFetchingSignin"|"InvalidSigninResponse"|"AccountsHttpNotFound"|"AccountsNoResponse"|"AccountsInvalidResponse"|"AccountsListEmpty"|"AccountsInvalidContentType"|"IdTokenHttpNotFound"|"IdTokenNoResponse"|"IdTokenInvalidResponse"|"IdTokenIdpErrorResponse"|"IdTokenCrossSiteIdpErrorResponse"|"IdTokenInvalidRequest"|"IdTokenInvalidContentType"|"ErrorIdToken"|"Canceled"|"RpPageNotVisible"|"SilentMediationFailure"|"ThirdPartyCookiesBlocked"|"NotSignedInWithIdp"|"MissingTransientUserActivation"|"ReplacedByButtonMode"|"RelyingPartyOriginIsOpaque"|"TypeNotMatching"; + export type FederatedAuthRequestIssueReason = "ShouldEmbargo"|"TooManyRequests"|"WellKnownHttpNotFound"|"WellKnownNoResponse"|"WellKnownInvalidResponse"|"WellKnownListEmpty"|"WellKnownInvalidContentType"|"ConfigNotInWellKnown"|"WellKnownTooBig"|"ConfigHttpNotFound"|"ConfigNoResponse"|"ConfigInvalidResponse"|"ConfigInvalidContentType"|"ClientMetadataHttpNotFound"|"ClientMetadataNoResponse"|"ClientMetadataInvalidResponse"|"ClientMetadataInvalidContentType"|"IdpNotPotentiallyTrustworthy"|"DisabledInSettings"|"DisabledInFlags"|"ErrorFetchingSignin"|"InvalidSigninResponse"|"AccountsHttpNotFound"|"AccountsNoResponse"|"AccountsInvalidResponse"|"AccountsListEmpty"|"AccountsInvalidContentType"|"IdTokenHttpNotFound"|"IdTokenNoResponse"|"IdTokenInvalidResponse"|"IdTokenIdpErrorResponse"|"IdTokenCrossSiteIdpErrorResponse"|"IdTokenInvalidRequest"|"IdTokenInvalidContentType"|"ErrorIdToken"|"Canceled"|"RpPageNotVisible"|"SilentMediationFailure"|"ThirdPartyCookiesBlocked"|"NotSignedInWithIdp"|"MissingTransientUserActivation"|"ReplacedByButtonMode"|"InvalidFieldsSpecified"|"RelyingPartyOriginIsOpaque"|"TypeNotMatching"; export interface FederatedAuthUserInfoRequestIssueDetails { federatedAuthUserInfoRequestIssueReason: FederatedAuthUserInfoRequestIssueReason; } @@ -1480,6 +1480,10 @@ Note that userVisibleOnly = true is the only currently supported type. * For "clipboard" permission, may specify allowWithoutSanitization. */ allowWithoutSanitization?: boolean; + /** + * For "fullscreen" permission, must specify allowWithoutGesture:true. + */ + allowWithoutGesture?: boolean; /** * For "camera" permission, may specify panTiltZoom. */ @@ -2559,6 +2563,7 @@ stylesheet rules) this rule came from. * Associated style declaration. */ style: CSSStyle; + active: boolean; } /** * CSS keyframes rule representation. @@ -2888,9 +2893,14 @@ attributes) for a DOM node identified by `nodeId`. */ cssPositionFallbackRules?: CSSPositionFallbackRule[]; /** - * A list of CSS @position-try rules matching this node, based on the position-try-options property. + * A list of CSS @position-try rules matching this node, based on the position-try-fallbacks property. */ cssPositionTryRules?: CSSPositionTryRule[]; + /** + * Index of the active fallback in the applied position-try-fallback property, +will not be set if there is no active position-try fallback. + */ + activePositionFallbackIndex?: number; /** * A list of CSS at-property rules matching this node. */ @@ -5907,6 +5917,11 @@ See https://w3c.github.io/sensors/#automation for more information. xyz?: SensorReadingXYZ; quaternion?: SensorReadingQuaternion; } + export type PressureSource = "cpu"; + export type PressureState = "nominal"|"fair"|"serious"|"critical"; + export interface PressureMetadata { + available?: boolean; + } /** * Enum of image types that can be disabled. */ @@ -6190,6 +6205,30 @@ by setSensorOverrideEnabled. } export type setSensorOverrideReadingsReturnValue = { } + /** + * Overrides a pressure source of a given type, as used by the Compute +Pressure API, so that updates to PressureObserver.observe() are provided +via setPressureStateOverride instead of being retrieved from +platform-provided telemetry data. + */ + export type setPressureSourceOverrideEnabledParameters = { + enabled: boolean; + source: PressureSource; + metadata?: PressureMetadata; + } + export type setPressureSourceOverrideEnabledReturnValue = { + } + /** + * Provides a given pressure state that will be processed and eventually be +delivered to PressureObserver users. |source| must have been previously +overridden by setPressureSourceOverrideEnabled. + */ + export type setPressureStateOverrideParameters = { + source: PressureSource; + state: PressureState; + } + export type setPressureStateOverrideReturnValue = { + } /** * Overrides the Idle state. */ @@ -6533,6 +6572,54 @@ following the last read). Some types of streams may only support sequential read } } + export module FileSystem { + export interface File { + name: string; + /** + * Timestamp + */ + lastModified: Network.TimeSinceEpoch; + /** + * Size in bytes + */ + size: number; + type: string; + } + export interface Directory { + name: string; + nestedDirectories: string[]; + /** + * Files that are directly nested under this directory. + */ + nestedFiles: File[]; + } + export interface BucketFileSystemLocator { + /** + * Storage key + */ + storageKey: Storage.SerializedStorageKey; + /** + * Bucket name. Not passing a `bucketName` will retrieve the default Bucket. (https://developer.mozilla.org/en-US/docs/Web/API/Storage_API#storage_buckets) + */ + bucketName?: string; + /** + * Path to the directory using each path component as an array item. + */ + pathComponents: string[]; + } + + + export type getDirectoryParameters = { + bucketFileSystemLocator: BucketFileSystemLocator; + } + export type getDirectoryReturnValue = { + /** + * Returns the directory object at the path. + */ + directory: Directory; + } + } + export module IndexedDB { /** * Database with an array of object stores. @@ -9048,7 +9135,7 @@ the same request (but not for redirected requests). initiatorIPAddressSpace: IPAddressSpace; privateNetworkRequestPolicy: PrivateNetworkRequestPolicy; } - export type CrossOriginOpenerPolicyValue = "SameOrigin"|"SameOriginAllowPopups"|"RestrictProperties"|"UnsafeNone"|"SameOriginPlusCoep"|"RestrictPropertiesPlusCoep"; + export type CrossOriginOpenerPolicyValue = "SameOrigin"|"SameOriginAllowPopups"|"RestrictProperties"|"UnsafeNone"|"SameOriginPlusCoep"|"RestrictPropertiesPlusCoep"|"NoopenerAllowPopups"; export interface CrossOriginOpenerPolicyStatus { value: CrossOriginOpenerPolicyValue; reportOnlyValue: CrossOriginOpenerPolicyValue; @@ -9731,6 +9818,10 @@ preemptively (e.g. a cache hit). */ issuedTokenCount?: number; } + /** + * Fired once security policy has been updated. + */ + export type policyUpdatedPayload = void; /** * Fired once when parsing the .wbn file has succeeded. The event contains the information about the web bundle contents. @@ -11278,7 +11369,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-factors"|"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"|"deferred-fetch"|"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"|"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-factors"|"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"|"deferred-fetch"|"digital-credentials-get"|"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"|"xr-spatial-tracking"; /** * Reason for a permissions policy feature to be disabled. */ @@ -11866,7 +11957,7 @@ https://github.com/WICG/manifest-incubations/blob/gh-pages/scope_extensions-expl /** * 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"|"BroadcastChannelOnMessage"|"WebViewSettingsChanged"|"WebViewJavaScriptObjectChanged"|"WebViewMessageListenerInjected"|"WebViewSafeBrowsingAllowlistChanged"|"WebViewDocumentStartJavascriptChanged"|"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"|"ParserAborted"|"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"|"RequestedByWebViewClient"; + 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"|"BroadcastChannelOnMessage"|"WebViewSettingsChanged"|"WebViewJavaScriptObjectChanged"|"WebViewMessageListenerInjected"|"WebViewSafeBrowsingAllowlistChanged"|"WebViewDocumentStartJavascriptChanged"|"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"|"SpeechRecognizer"|"IdleManager"|"PaymentManager"|"SpeechSynthesis"|"KeyboardLock"|"WebOTPService"|"OutstandingNetworkRequestDirectSocket"|"InjectedJavascript"|"InjectedStyleSheet"|"KeepaliveRequest"|"IndexedDBEvent"|"Dummy"|"JsNetworkRequestReceivedCacheControlNoStoreResource"|"WebRTCSticky"|"WebTransportSticky"|"WebSocketSticky"|"SmartCard"|"LiveMediaStreamTrack"|"UnloadHandler"|"ParserAborted"|"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"|"RequestedByWebViewClient"; /** * Types of not restored reasons for back-forward cache. */ @@ -14053,6 +14144,25 @@ int eventReportWindows: AttributionReportingEventReportWindows; } export type AttributionReportingTriggerDataMatching = "exact"|"modulus"; + export interface AttributionReportingAggregatableDebugReportingData { + keyPiece: UnsignedInt128AsBase16; + /** + * number instead of integer because not all uint32 can be represented by +int + */ + value: number; + types: string[]; + } + export interface AttributionReportingAggregatableDebugReportingConfig { + /** + * number instead of integer because not all uint32 can be represented by +int, only present for source registrations + */ + budget?: number; + keyPiece: UnsignedInt128AsBase16; + debugData: AttributionReportingAggregatableDebugReportingData[]; + aggregationCoordinatorOrigin?: string; + } export interface AttributionReportingSourceRegistration { time: Network.TimeSinceEpoch; /** @@ -14074,8 +14184,10 @@ int aggregationKeys: AttributionReportingAggregationKeysEntry[]; debugKey?: UnsignedInt64AsBase10; triggerDataMatching: AttributionReportingTriggerDataMatching; + destinationLimitPriority: SignedInt64AsBase10; + aggregatableDebugReportingConfig: AttributionReportingAggregatableDebugReportingConfig; } - export type AttributionReportingSourceRegistrationResult = "success"|"internalError"|"insufficientSourceCapacity"|"insufficientUniqueDestinationCapacity"|"excessiveReportingOrigins"|"prohibitedByBrowserPolicy"|"successNoised"|"destinationReportingLimitReached"|"destinationGlobalLimitReached"|"destinationBothLimitsReached"|"reportingOriginsPerSiteLimitReached"|"exceedsMaxChannelCapacity"|"exceedsMaxTriggerStateCardinality"; + export type AttributionReportingSourceRegistrationResult = "success"|"internalError"|"insufficientSourceCapacity"|"insufficientUniqueDestinationCapacity"|"excessiveReportingOrigins"|"prohibitedByBrowserPolicy"|"successNoised"|"destinationReportingLimitReached"|"destinationGlobalLimitReached"|"destinationBothLimitsReached"|"reportingOriginsPerSiteLimitReached"|"exceedsMaxChannelCapacity"|"exceedsMaxTriggerStateCardinality"|"destinationPerDayReportingLimitReached"; export type AttributionReportingSourceRegistrationTimeConfig = "include"|"exclude"; export interface AttributionReportingAggregatableValueDictEntry { key: string; @@ -14084,6 +14196,7 @@ int int */ value: number; + filteringId: UnsignedInt64AsBase10; } export interface AttributionReportingAggregatableValueEntry { values: AttributionReportingAggregatableValueDictEntry[]; @@ -14111,10 +14224,12 @@ int eventTriggerData: AttributionReportingEventTriggerData[]; aggregatableTriggerData: AttributionReportingAggregatableTriggerData[]; aggregatableValues: AttributionReportingAggregatableValueEntry[]; + aggregatableFilteringIdMaxBytes: number; debugReporting: boolean; aggregationCoordinatorOrigin?: string; sourceRegistrationTimeConfig: AttributionReportingSourceRegistrationTimeConfig; triggerContextId?: string; + aggregatableDebugReportingConfig: AttributionReportingAggregatableDebugReportingConfig; } export type AttributionReportingEventLevelResult = "success"|"successDroppedLowerPriority"|"internalError"|"noCapacityForAttributionDestination"|"noMatchingSources"|"deduplicated"|"excessiveAttributions"|"priorityTooLow"|"neverAttributedSource"|"excessiveReportingOrigins"|"noMatchingSourceFilterData"|"prohibitedByBrowserPolicy"|"noMatchingConfigurations"|"excessiveReports"|"falselyAttributedSource"|"reportWindowPassed"|"notRegistered"|"reportWindowNotStarted"|"noMatchingTriggerData"; export type AttributionReportingAggregatableResult = "success"|"internalError"|"noCapacityForAttributionDestination"|"noMatchingSources"|"excessiveAttributions"|"excessiveReportingOrigins"|"noHistograms"|"insufficientBudget"|"noMatchingSourceFilterData"|"notRegistered"|"prohibitedByBrowserPolicy"|"deduplicated"|"reportWindowPassed"|"excessiveReports"; @@ -14980,7 +15095,7 @@ supported. browserContextId?: Browser.BrowserContextID; /** * Provides additional details for specific target types. For example, for -the type of "page", this may be set to "portal" or "prerender". +the type of "page", this may be set to "prerender". */ subtype?: string; } @@ -16807,7 +16922,7 @@ possible for multiple rule sets and links to trigger a single attempt. /** * List of FinalStatus reasons for Prerender2. */ - export type PrerenderFinalStatus = "Activated"|"Destroyed"|"LowEndDevice"|"InvalidSchemeRedirect"|"InvalidSchemeNavigation"|"NavigationRequestBlockedByCsp"|"MainFrameNavigation"|"MojoBinderPolicy"|"RendererProcessCrashed"|"RendererProcessKilled"|"Download"|"TriggerDestroyed"|"NavigationNotCommitted"|"NavigationBadHttpStatus"|"ClientCertRequested"|"NavigationRequestNetworkError"|"CancelAllHostsForTesting"|"DidFailLoad"|"Stop"|"SslCertificateError"|"LoginAuthRequested"|"UaChangeRequiresReload"|"BlockedByClient"|"AudioOutputDeviceRequested"|"MixedContent"|"TriggerBackgrounded"|"MemoryLimitExceeded"|"DataSaverEnabled"|"TriggerUrlHasEffectiveUrl"|"ActivatedBeforeStarted"|"InactivePageRestriction"|"StartFailed"|"TimeoutBackgrounded"|"CrossSiteRedirectInInitialNavigation"|"CrossSiteNavigationInInitialNavigation"|"SameSiteCrossOriginRedirectNotOptInInInitialNavigation"|"SameSiteCrossOriginNavigationNotOptInInInitialNavigation"|"ActivationNavigationParameterMismatch"|"ActivatedInBackground"|"EmbedderHostDisallowed"|"ActivationNavigationDestroyedBeforeSuccess"|"TabClosedByUserGesture"|"TabClosedWithoutUserGesture"|"PrimaryMainFrameRendererProcessCrashed"|"PrimaryMainFrameRendererProcessKilled"|"ActivationFramePolicyNotCompatible"|"PreloadingDisabled"|"BatterySaverEnabled"|"ActivatedDuringMainFrameNavigation"|"PreloadingUnsupportedByWebContents"|"CrossSiteRedirectInMainFrameNavigation"|"CrossSiteNavigationInMainFrameNavigation"|"SameSiteCrossOriginRedirectNotOptInInMainFrameNavigation"|"SameSiteCrossOriginNavigationNotOptInInMainFrameNavigation"|"MemoryPressureOnTrigger"|"MemoryPressureAfterTriggered"|"PrerenderingDisabledByDevTools"|"SpeculationRuleRemoved"|"ActivatedWithAuxiliaryBrowsingContexts"|"MaxNumOfRunningEagerPrerendersExceeded"|"MaxNumOfRunningNonEagerPrerendersExceeded"|"MaxNumOfRunningEmbedderPrerendersExceeded"|"PrerenderingUrlHasEffectiveUrl"|"RedirectedPrerenderingUrlHasEffectiveUrl"|"ActivationUrlHasEffectiveUrl"|"JavaScriptInterfaceAdded"|"JavaScriptInterfaceRemoved"|"AllPrerenderingCanceled"; + export type PrerenderFinalStatus = "Activated"|"Destroyed"|"LowEndDevice"|"InvalidSchemeRedirect"|"InvalidSchemeNavigation"|"NavigationRequestBlockedByCsp"|"MainFrameNavigation"|"MojoBinderPolicy"|"RendererProcessCrashed"|"RendererProcessKilled"|"Download"|"TriggerDestroyed"|"NavigationNotCommitted"|"NavigationBadHttpStatus"|"ClientCertRequested"|"NavigationRequestNetworkError"|"CancelAllHostsForTesting"|"DidFailLoad"|"Stop"|"SslCertificateError"|"LoginAuthRequested"|"UaChangeRequiresReload"|"BlockedByClient"|"AudioOutputDeviceRequested"|"MixedContent"|"TriggerBackgrounded"|"MemoryLimitExceeded"|"DataSaverEnabled"|"TriggerUrlHasEffectiveUrl"|"ActivatedBeforeStarted"|"InactivePageRestriction"|"StartFailed"|"TimeoutBackgrounded"|"CrossSiteRedirectInInitialNavigation"|"CrossSiteNavigationInInitialNavigation"|"SameSiteCrossOriginRedirectNotOptInInInitialNavigation"|"SameSiteCrossOriginNavigationNotOptInInInitialNavigation"|"ActivationNavigationParameterMismatch"|"ActivatedInBackground"|"EmbedderHostDisallowed"|"ActivationNavigationDestroyedBeforeSuccess"|"TabClosedByUserGesture"|"TabClosedWithoutUserGesture"|"PrimaryMainFrameRendererProcessCrashed"|"PrimaryMainFrameRendererProcessKilled"|"ActivationFramePolicyNotCompatible"|"PreloadingDisabled"|"BatterySaverEnabled"|"ActivatedDuringMainFrameNavigation"|"PreloadingUnsupportedByWebContents"|"CrossSiteRedirectInMainFrameNavigation"|"CrossSiteNavigationInMainFrameNavigation"|"SameSiteCrossOriginRedirectNotOptInInMainFrameNavigation"|"SameSiteCrossOriginNavigationNotOptInInMainFrameNavigation"|"MemoryPressureOnTrigger"|"MemoryPressureAfterTriggered"|"PrerenderingDisabledByDevTools"|"SpeculationRuleRemoved"|"ActivatedWithAuxiliaryBrowsingContexts"|"MaxNumOfRunningEagerPrerendersExceeded"|"MaxNumOfRunningNonEagerPrerendersExceeded"|"MaxNumOfRunningEmbedderPrerendersExceeded"|"PrerenderingUrlHasEffectiveUrl"|"RedirectedPrerenderingUrlHasEffectiveUrl"|"ActivationUrlHasEffectiveUrl"|"JavaScriptInterfaceAdded"|"JavaScriptInterfaceRemoved"|"AllPrerenderingCanceled"|"WindowClosed"; /** * Preloading status values, see also PreloadingTriggeringOutcome. This status is shared by prefetchStatusUpdated and prerenderStatusUpdated. @@ -17021,6 +17136,10 @@ https://www.iana.org/assignments/media-types/media-types.xhtml accepts: FileHandlerAccept[]; displayName: string; } + /** + * If user prefers opening the app in browser or an app window. + */ + export type DisplayMode = "standalone"|"browser"; /** @@ -17061,7 +17180,7 @@ manifestId. export type installReturnValue = { } /** - * Uninstals the given manifest_id and closes any opened app windows. + * Uninstalls the given manifest_id and closes any opened app windows. */ export type uninstallParameters = { manifestId: string; @@ -17090,7 +17209,7 @@ the files. The API returns one or more page Target.TargetIDs which can be used to attach to via Target.attachToTarget or similar APIs. If some files in the parameters cannot be handled by the web app, they will be ignored. If none of the files can be handled, this API returns an error. -If no files provided as the parameter, this API also returns an error. +If no files are provided as the parameter, this API also returns an error. According to the definition of the file handlers in the manifest file, one Target.TargetID may represent a page handling one or more files. The order @@ -17111,13 +17230,44 @@ TODO(crbug.com/339454034): Check the existences of the input files. /** * Opens the current page in its web app identified by the manifest id, needs to be called on a page target. This function returns immediately without -waiting for the app finishing loading. +waiting for the app to finish loading. */ export type openCurrentPageInAppParameters = { manifestId: string; } export type openCurrentPageInAppReturnValue = { } + /** + * Changes user settings of the web app identified by its manifestId. If the +app was not installed, this command returns an error. Unset parameters will +be ignored; unrecognized values will cause an error. + +Unlike the ones defined in the manifest files of the web apps, these +settings are provided by the browser and controlled by the users, they +impact the way the browser handling the web apps. + +See the comment of each parameter. + */ + export type changeAppUserSettingsParameters = { + manifestId: string; + /** + * If user allows the links clicked on by the user in the app's scope, or +extended scope if the manifest has scope extensions and the flags +`DesktopPWAsLinkCapturingWithScopeExtensions` and +`WebAppEnableScopeExtensions` are enabled. + +Note, the API does not support resetting the linkCapturing to the +initial value, uninstalling and installing the web app again will reset +it. + +TODO(crbug.com/339453269): Setting this value on ChromeOS is not +supported yet. + */ + linkCapturing?: boolean; + displayMode?: DisplayMode; + } + export type changeAppUserSettingsReturnValue = { + } } /** @@ -19824,6 +19974,7 @@ Error was thrown. "Network.responseReceivedExtraInfo": Network.responseReceivedExtraInfoPayload; "Network.responseReceivedEarlyHints": Network.responseReceivedEarlyHintsPayload; "Network.trustTokenOperationDone": Network.trustTokenOperationDonePayload; + "Network.policyUpdated": Network.policyUpdatedPayload; "Network.subresourceWebBundleMetadataReceived": Network.subresourceWebBundleMetadataReceivedPayload; "Network.subresourceWebBundleMetadataError": Network.subresourceWebBundleMetadataErrorPayload; "Network.subresourceWebBundleInnerResponseParsed": Network.subresourceWebBundleInnerResponseParsedPayload; @@ -20139,6 +20290,8 @@ Error was thrown. "Emulation.getOverriddenSensorInformation": Emulation.getOverriddenSensorInformationParameters; "Emulation.setSensorOverrideEnabled": Emulation.setSensorOverrideEnabledParameters; "Emulation.setSensorOverrideReadings": Emulation.setSensorOverrideReadingsParameters; + "Emulation.setPressureSourceOverrideEnabled": Emulation.setPressureSourceOverrideEnabledParameters; + "Emulation.setPressureStateOverride": Emulation.setPressureStateOverrideParameters; "Emulation.setIdleOverride": Emulation.setIdleOverrideParameters; "Emulation.clearIdleOverride": Emulation.clearIdleOverrideParameters; "Emulation.setNavigatorOverrides": Emulation.setNavigatorOverridesParameters; @@ -20159,6 +20312,7 @@ Error was thrown. "IO.close": IO.closeParameters; "IO.read": IO.readParameters; "IO.resolveBlob": IO.resolveBlobParameters; + "FileSystem.getDirectory": FileSystem.getDirectoryParameters; "IndexedDB.clearObjectStore": IndexedDB.clearObjectStoreParameters; "IndexedDB.deleteDatabase": IndexedDB.deleteDatabaseParameters; "IndexedDB.deleteObjectStoreEntries": IndexedDB.deleteObjectStoreEntriesParameters; @@ -20461,6 +20615,7 @@ Error was thrown. "PWA.launch": PWA.launchParameters; "PWA.launchFilesInApp": PWA.launchFilesInAppParameters; "PWA.openCurrentPageInApp": PWA.openCurrentPageInAppParameters; + "PWA.changeAppUserSettings": PWA.changeAppUserSettingsParameters; "Console.clearMessages": Console.clearMessagesParameters; "Console.disable": Console.disableParameters; "Console.enable": Console.enableParameters; @@ -20735,6 +20890,8 @@ Error was thrown. "Emulation.getOverriddenSensorInformation": Emulation.getOverriddenSensorInformationReturnValue; "Emulation.setSensorOverrideEnabled": Emulation.setSensorOverrideEnabledReturnValue; "Emulation.setSensorOverrideReadings": Emulation.setSensorOverrideReadingsReturnValue; + "Emulation.setPressureSourceOverrideEnabled": Emulation.setPressureSourceOverrideEnabledReturnValue; + "Emulation.setPressureStateOverride": Emulation.setPressureStateOverrideReturnValue; "Emulation.setIdleOverride": Emulation.setIdleOverrideReturnValue; "Emulation.clearIdleOverride": Emulation.clearIdleOverrideReturnValue; "Emulation.setNavigatorOverrides": Emulation.setNavigatorOverridesReturnValue; @@ -20755,6 +20912,7 @@ Error was thrown. "IO.close": IO.closeReturnValue; "IO.read": IO.readReturnValue; "IO.resolveBlob": IO.resolveBlobReturnValue; + "FileSystem.getDirectory": FileSystem.getDirectoryReturnValue; "IndexedDB.clearObjectStore": IndexedDB.clearObjectStoreReturnValue; "IndexedDB.deleteDatabase": IndexedDB.deleteDatabaseReturnValue; "IndexedDB.deleteObjectStoreEntries": IndexedDB.deleteObjectStoreEntriesReturnValue; @@ -21057,6 +21215,7 @@ Error was thrown. "PWA.launch": PWA.launchReturnValue; "PWA.launchFilesInApp": PWA.launchFilesInAppReturnValue; "PWA.openCurrentPageInApp": PWA.openCurrentPageInAppReturnValue; + "PWA.changeAppUserSettings": PWA.changeAppUserSettingsReturnValue; "Console.clearMessages": Console.clearMessagesReturnValue; "Console.disable": Console.disableReturnValue; "Console.enable": Console.enableReturnValue; diff --git a/packages/playwright-core/src/server/deviceDescriptorsSource.json b/packages/playwright-core/src/server/deviceDescriptorsSource.json index e3f13006f7..abcc0ba5ad 100644 --- a/packages/playwright-core/src/server/deviceDescriptorsSource.json +++ b/packages/playwright-core/src/server/deviceDescriptorsSource.json @@ -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/127.0.6533.57 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.6613.7 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/127.0.6533.57 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.6613.7 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/127.0.6533.57 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 7.0; SM-G950U Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.6613.7 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/127.0.6533.57 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 7.0; SM-G950U Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.6613.7 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/127.0.6533.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/128.0.6613.7 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/127.0.6533.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/128.0.6613.7 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/127.0.6533.57 Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 8.1.0; SM-T837A) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.6613.7 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/127.0.6533.57 Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 8.1.0; SM-T837A) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.6613.7 Safari/537.36", "viewport": { "width": 1138, "height": 712 @@ -1098,7 +1098,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/127.0.6533.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/128.0.6613.7 Mobile Safari/537.36", "viewport": { "width": 384, "height": 640 @@ -1109,7 +1109,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/127.0.6533.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/128.0.6613.7 Mobile Safari/537.36", "viewport": { "width": 640, "height": 384 @@ -1120,7 +1120,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/127.0.6533.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/128.0.6613.7 Mobile Safari/537.36 Edge/14.14263", "viewport": { "width": 640, "height": 360 @@ -1131,7 +1131,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/127.0.6533.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/128.0.6613.7 Mobile Safari/537.36 Edge/14.14263", "viewport": { "width": 360, "height": 640 @@ -1142,7 +1142,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/127.0.6533.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/128.0.6613.7 Mobile Safari/537.36 Edge/14.14263", "viewport": { "width": 360, "height": 640 @@ -1153,7 +1153,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/127.0.6533.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/128.0.6613.7 Mobile Safari/537.36 Edge/14.14263", "viewport": { "width": 640, "height": 360 @@ -1164,7 +1164,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/127.0.6533.57 Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 10 Build/MOB31T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.6613.7 Safari/537.36", "viewport": { "width": 800, "height": 1280 @@ -1175,7 +1175,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/127.0.6533.57 Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 10 Build/MOB31T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.6613.7 Safari/537.36", "viewport": { "width": 1280, "height": 800 @@ -1186,7 +1186,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/127.0.6533.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/128.0.6613.7 Mobile Safari/537.36", "viewport": { "width": 384, "height": 640 @@ -1197,7 +1197,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/127.0.6533.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/128.0.6613.7 Mobile Safari/537.36", "viewport": { "width": 640, "height": 384 @@ -1208,7 +1208,7 @@ "defaultBrowserType": "chromium" }, "Nexus 5": { - "userAgent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.6533.57 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.6613.7 Mobile Safari/537.36", "viewport": { "width": 360, "height": 640 @@ -1219,7 +1219,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/127.0.6533.57 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.6613.7 Mobile Safari/537.36", "viewport": { "width": 640, "height": 360 @@ -1230,7 +1230,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/127.0.6533.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/128.0.6613.7 Mobile Safari/537.36", "viewport": { "width": 412, "height": 732 @@ -1241,7 +1241,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/127.0.6533.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/128.0.6613.7 Mobile Safari/537.36", "viewport": { "width": 732, "height": 412 @@ -1252,7 +1252,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/127.0.6533.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/128.0.6613.7 Mobile Safari/537.36", "viewport": { "width": 412, "height": 732 @@ -1263,7 +1263,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/127.0.6533.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/128.0.6613.7 Mobile Safari/537.36", "viewport": { "width": 732, "height": 412 @@ -1274,7 +1274,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/127.0.6533.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/128.0.6613.7 Mobile Safari/537.36", "viewport": { "width": 412, "height": 732 @@ -1285,7 +1285,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/127.0.6533.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/128.0.6613.7 Mobile Safari/537.36", "viewport": { "width": 732, "height": 412 @@ -1296,7 +1296,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/127.0.6533.57 Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 7 Build/MOB30X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.6613.7 Safari/537.36", "viewport": { "width": 600, "height": 960 @@ -1307,7 +1307,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/127.0.6533.57 Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 7 Build/MOB30X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.6613.7 Safari/537.36", "viewport": { "width": 960, "height": 600 @@ -1362,7 +1362,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/127.0.6533.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/128.0.6613.7 Mobile Safari/537.36", "viewport": { "width": 411, "height": 731 @@ -1373,7 +1373,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/127.0.6533.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/128.0.6613.7 Mobile Safari/537.36", "viewport": { "width": 731, "height": 411 @@ -1384,7 +1384,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/127.0.6533.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/128.0.6613.7 Mobile Safari/537.36", "viewport": { "width": 411, "height": 823 @@ -1395,7 +1395,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/127.0.6533.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/128.0.6613.7 Mobile Safari/537.36", "viewport": { "width": 823, "height": 411 @@ -1406,7 +1406,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/127.0.6533.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/128.0.6613.7 Mobile Safari/537.36", "viewport": { "width": 393, "height": 786 @@ -1417,7 +1417,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/127.0.6533.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/128.0.6613.7 Mobile Safari/537.36", "viewport": { "width": 786, "height": 393 @@ -1428,7 +1428,7 @@ "defaultBrowserType": "chromium" }, "Pixel 4": { - "userAgent": "Mozilla/5.0 (Linux; Android 10; Pixel 4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.6533.57 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 10; Pixel 4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.6613.7 Mobile Safari/537.36", "viewport": { "width": 353, "height": 745 @@ -1439,7 +1439,7 @@ "defaultBrowserType": "chromium" }, "Pixel 4 landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 10; Pixel 4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.6533.57 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 10; Pixel 4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.6613.7 Mobile Safari/537.36", "viewport": { "width": 745, "height": 353 @@ -1450,7 +1450,7 @@ "defaultBrowserType": "chromium" }, "Pixel 4a (5G)": { - "userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 4a (5G)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.6533.57 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 4a (5G)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.6613.7 Mobile Safari/537.36", "screen": { "width": 412, "height": 892 @@ -1465,7 +1465,7 @@ "defaultBrowserType": "chromium" }, "Pixel 4a (5G) landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 4a (5G)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.6533.57 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 4a (5G)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.6613.7 Mobile Safari/537.36", "screen": { "height": 892, "width": 412 @@ -1480,7 +1480,7 @@ "defaultBrowserType": "chromium" }, "Pixel 5": { - "userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.6533.57 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.6613.7 Mobile Safari/537.36", "screen": { "width": 393, "height": 851 @@ -1495,7 +1495,7 @@ "defaultBrowserType": "chromium" }, "Pixel 5 landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.6533.57 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.6613.7 Mobile Safari/537.36", "screen": { "width": 851, "height": 393 @@ -1510,7 +1510,7 @@ "defaultBrowserType": "chromium" }, "Pixel 7": { - "userAgent": "Mozilla/5.0 (Linux; Android 14; Pixel 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.6533.57 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 14; Pixel 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.6613.7 Mobile Safari/537.36", "screen": { "width": 412, "height": 915 @@ -1525,7 +1525,7 @@ "defaultBrowserType": "chromium" }, "Pixel 7 landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 14; Pixel 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.6533.57 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 14; Pixel 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.6613.7 Mobile Safari/537.36", "screen": { "width": 915, "height": 412 @@ -1540,7 +1540,7 @@ "defaultBrowserType": "chromium" }, "Moto G4": { - "userAgent": "Mozilla/5.0 (Linux; Android 7.0; Moto G (4)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.6533.57 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 7.0; Moto G (4)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.6613.7 Mobile Safari/537.36", "viewport": { "width": 360, "height": 640 @@ -1551,7 +1551,7 @@ "defaultBrowserType": "chromium" }, "Moto G4 landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 7.0; Moto G (4)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.6533.57 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 7.0; Moto G (4)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.6613.7 Mobile Safari/537.36", "viewport": { "width": 640, "height": 360 @@ -1562,7 +1562,7 @@ "defaultBrowserType": "chromium" }, "Desktop Chrome HiDPI": { - "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.6533.57 Safari/537.36", + "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.6613.7 Safari/537.36", "screen": { "width": 1792, "height": 1120 @@ -1577,7 +1577,7 @@ "defaultBrowserType": "chromium" }, "Desktop Edge HiDPI": { - "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.6533.57 Safari/537.36 Edg/127.0.6533.57", + "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.6613.7 Safari/537.36 Edg/128.0.6613.7", "screen": { "width": 1792, "height": 1120 @@ -1622,7 +1622,7 @@ "defaultBrowserType": "webkit" }, "Desktop Chrome": { - "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.6533.57 Safari/537.36", + "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.6613.7 Safari/537.36", "screen": { "width": 1920, "height": 1080 @@ -1637,7 +1637,7 @@ "defaultBrowserType": "chromium" }, "Desktop Edge": { - "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.6533.57 Safari/537.36 Edg/127.0.6533.57", + "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.6613.7 Safari/537.36 Edg/128.0.6613.7", "screen": { "width": 1920, "height": 1080 diff --git a/packages/playwright-core/types/protocol.d.ts b/packages/playwright-core/types/protocol.d.ts index 671230d86c..99ce1d3a6a 100644 --- a/packages/playwright-core/types/protocol.d.ts +++ b/packages/playwright-core/types/protocol.d.ts @@ -112,7 +112,7 @@ export module Protocol { - from 'checked' to 'selected': states which apply to widgets - from 'activedescendant' to 'owns' - relationships between elements other than parent/child/sibling. */ - export type AXPropertyName = "busy"|"disabled"|"editable"|"focusable"|"focused"|"hidden"|"hiddenRoot"|"invalid"|"keyshortcuts"|"settable"|"roledescription"|"live"|"atomic"|"relevant"|"root"|"autocomplete"|"hasPopup"|"level"|"multiselectable"|"orientation"|"multiline"|"readonly"|"required"|"valuemin"|"valuemax"|"valuetext"|"checked"|"expanded"|"modal"|"pressed"|"selected"|"activedescendant"|"controls"|"describedby"|"details"|"errormessage"|"flowto"|"labelledby"|"owns"; + export type AXPropertyName = "busy"|"disabled"|"editable"|"focusable"|"focused"|"hidden"|"hiddenRoot"|"invalid"|"keyshortcuts"|"settable"|"roledescription"|"live"|"atomic"|"relevant"|"root"|"autocomplete"|"hasPopup"|"level"|"multiselectable"|"orientation"|"multiline"|"readonly"|"required"|"valuemin"|"valuemax"|"valuetext"|"checked"|"expanded"|"modal"|"pressed"|"selected"|"activedescendant"|"controls"|"describedby"|"details"|"errormessage"|"flowto"|"labelledby"|"owns"|"url"; /** * A node in the accessibility tree. */ @@ -875,7 +875,7 @@ instead of "limited-quirks". sharedDictionaryError: SharedDictionaryError; request: AffectedRequest; } - export type GenericIssueErrorType = "CrossOriginPortalPostMessageError"|"FormLabelForNameError"|"FormDuplicateIdForInputError"|"FormInputWithNoLabelError"|"FormAutocompleteAttributeEmptyError"|"FormEmptyIdAndNameAttributesForInputError"|"FormAriaLabelledByToNonExistingId"|"FormInputAssignedAutocompleteValueToIdOrNameAttributeError"|"FormLabelHasNeitherForNorNestedInput"|"FormLabelForMatchesNonExistingIdError"|"FormInputHasWrongButWellIntendedAutocompleteValueError"|"ResponseWasBlockedByORB"; + export type GenericIssueErrorType = "FormLabelForNameError"|"FormDuplicateIdForInputError"|"FormInputWithNoLabelError"|"FormAutocompleteAttributeEmptyError"|"FormEmptyIdAndNameAttributesForInputError"|"FormAriaLabelledByToNonExistingId"|"FormInputAssignedAutocompleteValueToIdOrNameAttributeError"|"FormLabelHasNeitherForNorNestedInput"|"FormLabelForMatchesNonExistingIdError"|"FormInputHasWrongButWellIntendedAutocompleteValueError"|"ResponseWasBlockedByORB"; /** * Depending on the concrete errorType, different properties are set. */ @@ -934,7 +934,7 @@ Should be updated alongside RequestIdTokenStatus in third_party/blink/public/mojom/devtools/inspector_issue.mojom to include all cases except for success. */ - export type FederatedAuthRequestIssueReason = "ShouldEmbargo"|"TooManyRequests"|"WellKnownHttpNotFound"|"WellKnownNoResponse"|"WellKnownInvalidResponse"|"WellKnownListEmpty"|"WellKnownInvalidContentType"|"ConfigNotInWellKnown"|"WellKnownTooBig"|"ConfigHttpNotFound"|"ConfigNoResponse"|"ConfigInvalidResponse"|"ConfigInvalidContentType"|"ClientMetadataHttpNotFound"|"ClientMetadataNoResponse"|"ClientMetadataInvalidResponse"|"ClientMetadataInvalidContentType"|"DisabledInSettings"|"ErrorFetchingSignin"|"InvalidSigninResponse"|"AccountsHttpNotFound"|"AccountsNoResponse"|"AccountsInvalidResponse"|"AccountsListEmpty"|"AccountsInvalidContentType"|"IdTokenHttpNotFound"|"IdTokenNoResponse"|"IdTokenInvalidResponse"|"IdTokenIdpErrorResponse"|"IdTokenCrossSiteIdpErrorResponse"|"IdTokenInvalidRequest"|"IdTokenInvalidContentType"|"ErrorIdToken"|"Canceled"|"RpPageNotVisible"|"SilentMediationFailure"|"ThirdPartyCookiesBlocked"|"NotSignedInWithIdp"|"MissingTransientUserActivation"|"ReplacedByButtonMode"|"RelyingPartyOriginIsOpaque"|"TypeNotMatching"; + export type FederatedAuthRequestIssueReason = "ShouldEmbargo"|"TooManyRequests"|"WellKnownHttpNotFound"|"WellKnownNoResponse"|"WellKnownInvalidResponse"|"WellKnownListEmpty"|"WellKnownInvalidContentType"|"ConfigNotInWellKnown"|"WellKnownTooBig"|"ConfigHttpNotFound"|"ConfigNoResponse"|"ConfigInvalidResponse"|"ConfigInvalidContentType"|"ClientMetadataHttpNotFound"|"ClientMetadataNoResponse"|"ClientMetadataInvalidResponse"|"ClientMetadataInvalidContentType"|"IdpNotPotentiallyTrustworthy"|"DisabledInSettings"|"DisabledInFlags"|"ErrorFetchingSignin"|"InvalidSigninResponse"|"AccountsHttpNotFound"|"AccountsNoResponse"|"AccountsInvalidResponse"|"AccountsListEmpty"|"AccountsInvalidContentType"|"IdTokenHttpNotFound"|"IdTokenNoResponse"|"IdTokenInvalidResponse"|"IdTokenIdpErrorResponse"|"IdTokenCrossSiteIdpErrorResponse"|"IdTokenInvalidRequest"|"IdTokenInvalidContentType"|"ErrorIdToken"|"Canceled"|"RpPageNotVisible"|"SilentMediationFailure"|"ThirdPartyCookiesBlocked"|"NotSignedInWithIdp"|"MissingTransientUserActivation"|"ReplacedByButtonMode"|"InvalidFieldsSpecified"|"RelyingPartyOriginIsOpaque"|"TypeNotMatching"; export interface FederatedAuthUserInfoRequestIssueDetails { federatedAuthUserInfoRequestIssueReason: FederatedAuthUserInfoRequestIssueReason; } @@ -1480,6 +1480,10 @@ Note that userVisibleOnly = true is the only currently supported type. * For "clipboard" permission, may specify allowWithoutSanitization. */ allowWithoutSanitization?: boolean; + /** + * For "fullscreen" permission, must specify allowWithoutGesture:true. + */ + allowWithoutGesture?: boolean; /** * For "camera" permission, may specify panTiltZoom. */ @@ -2559,6 +2563,7 @@ stylesheet rules) this rule came from. * Associated style declaration. */ style: CSSStyle; + active: boolean; } /** * CSS keyframes rule representation. @@ -2888,9 +2893,14 @@ attributes) for a DOM node identified by `nodeId`. */ cssPositionFallbackRules?: CSSPositionFallbackRule[]; /** - * A list of CSS @position-try rules matching this node, based on the position-try-options property. + * A list of CSS @position-try rules matching this node, based on the position-try-fallbacks property. */ cssPositionTryRules?: CSSPositionTryRule[]; + /** + * Index of the active fallback in the applied position-try-fallback property, +will not be set if there is no active position-try fallback. + */ + activePositionFallbackIndex?: number; /** * A list of CSS at-property rules matching this node. */ @@ -5907,6 +5917,11 @@ See https://w3c.github.io/sensors/#automation for more information. xyz?: SensorReadingXYZ; quaternion?: SensorReadingQuaternion; } + export type PressureSource = "cpu"; + export type PressureState = "nominal"|"fair"|"serious"|"critical"; + export interface PressureMetadata { + available?: boolean; + } /** * Enum of image types that can be disabled. */ @@ -6190,6 +6205,30 @@ by setSensorOverrideEnabled. } export type setSensorOverrideReadingsReturnValue = { } + /** + * Overrides a pressure source of a given type, as used by the Compute +Pressure API, so that updates to PressureObserver.observe() are provided +via setPressureStateOverride instead of being retrieved from +platform-provided telemetry data. + */ + export type setPressureSourceOverrideEnabledParameters = { + enabled: boolean; + source: PressureSource; + metadata?: PressureMetadata; + } + export type setPressureSourceOverrideEnabledReturnValue = { + } + /** + * Provides a given pressure state that will be processed and eventually be +delivered to PressureObserver users. |source| must have been previously +overridden by setPressureSourceOverrideEnabled. + */ + export type setPressureStateOverrideParameters = { + source: PressureSource; + state: PressureState; + } + export type setPressureStateOverrideReturnValue = { + } /** * Overrides the Idle state. */ @@ -6533,6 +6572,54 @@ following the last read). Some types of streams may only support sequential read } } + export module FileSystem { + export interface File { + name: string; + /** + * Timestamp + */ + lastModified: Network.TimeSinceEpoch; + /** + * Size in bytes + */ + size: number; + type: string; + } + export interface Directory { + name: string; + nestedDirectories: string[]; + /** + * Files that are directly nested under this directory. + */ + nestedFiles: File[]; + } + export interface BucketFileSystemLocator { + /** + * Storage key + */ + storageKey: Storage.SerializedStorageKey; + /** + * Bucket name. Not passing a `bucketName` will retrieve the default Bucket. (https://developer.mozilla.org/en-US/docs/Web/API/Storage_API#storage_buckets) + */ + bucketName?: string; + /** + * Path to the directory using each path component as an array item. + */ + pathComponents: string[]; + } + + + export type getDirectoryParameters = { + bucketFileSystemLocator: BucketFileSystemLocator; + } + export type getDirectoryReturnValue = { + /** + * Returns the directory object at the path. + */ + directory: Directory; + } + } + export module IndexedDB { /** * Database with an array of object stores. @@ -9048,7 +9135,7 @@ the same request (but not for redirected requests). initiatorIPAddressSpace: IPAddressSpace; privateNetworkRequestPolicy: PrivateNetworkRequestPolicy; } - export type CrossOriginOpenerPolicyValue = "SameOrigin"|"SameOriginAllowPopups"|"RestrictProperties"|"UnsafeNone"|"SameOriginPlusCoep"|"RestrictPropertiesPlusCoep"; + export type CrossOriginOpenerPolicyValue = "SameOrigin"|"SameOriginAllowPopups"|"RestrictProperties"|"UnsafeNone"|"SameOriginPlusCoep"|"RestrictPropertiesPlusCoep"|"NoopenerAllowPopups"; export interface CrossOriginOpenerPolicyStatus { value: CrossOriginOpenerPolicyValue; reportOnlyValue: CrossOriginOpenerPolicyValue; @@ -9731,6 +9818,10 @@ preemptively (e.g. a cache hit). */ issuedTokenCount?: number; } + /** + * Fired once security policy has been updated. + */ + export type policyUpdatedPayload = void; /** * Fired once when parsing the .wbn file has succeeded. The event contains the information about the web bundle contents. @@ -11278,7 +11369,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-factors"|"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"|"deferred-fetch"|"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"|"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-factors"|"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"|"deferred-fetch"|"digital-credentials-get"|"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"|"xr-spatial-tracking"; /** * Reason for a permissions policy feature to be disabled. */ @@ -11866,7 +11957,7 @@ https://github.com/WICG/manifest-incubations/blob/gh-pages/scope_extensions-expl /** * 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"|"BroadcastChannelOnMessage"|"WebViewSettingsChanged"|"WebViewJavaScriptObjectChanged"|"WebViewMessageListenerInjected"|"WebViewSafeBrowsingAllowlistChanged"|"WebViewDocumentStartJavascriptChanged"|"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"|"ParserAborted"|"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"|"RequestedByWebViewClient"; + 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"|"BroadcastChannelOnMessage"|"WebViewSettingsChanged"|"WebViewJavaScriptObjectChanged"|"WebViewMessageListenerInjected"|"WebViewSafeBrowsingAllowlistChanged"|"WebViewDocumentStartJavascriptChanged"|"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"|"SpeechRecognizer"|"IdleManager"|"PaymentManager"|"SpeechSynthesis"|"KeyboardLock"|"WebOTPService"|"OutstandingNetworkRequestDirectSocket"|"InjectedJavascript"|"InjectedStyleSheet"|"KeepaliveRequest"|"IndexedDBEvent"|"Dummy"|"JsNetworkRequestReceivedCacheControlNoStoreResource"|"WebRTCSticky"|"WebTransportSticky"|"WebSocketSticky"|"SmartCard"|"LiveMediaStreamTrack"|"UnloadHandler"|"ParserAborted"|"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"|"RequestedByWebViewClient"; /** * Types of not restored reasons for back-forward cache. */ @@ -14053,6 +14144,25 @@ int eventReportWindows: AttributionReportingEventReportWindows; } export type AttributionReportingTriggerDataMatching = "exact"|"modulus"; + export interface AttributionReportingAggregatableDebugReportingData { + keyPiece: UnsignedInt128AsBase16; + /** + * number instead of integer because not all uint32 can be represented by +int + */ + value: number; + types: string[]; + } + export interface AttributionReportingAggregatableDebugReportingConfig { + /** + * number instead of integer because not all uint32 can be represented by +int, only present for source registrations + */ + budget?: number; + keyPiece: UnsignedInt128AsBase16; + debugData: AttributionReportingAggregatableDebugReportingData[]; + aggregationCoordinatorOrigin?: string; + } export interface AttributionReportingSourceRegistration { time: Network.TimeSinceEpoch; /** @@ -14074,8 +14184,10 @@ int aggregationKeys: AttributionReportingAggregationKeysEntry[]; debugKey?: UnsignedInt64AsBase10; triggerDataMatching: AttributionReportingTriggerDataMatching; + destinationLimitPriority: SignedInt64AsBase10; + aggregatableDebugReportingConfig: AttributionReportingAggregatableDebugReportingConfig; } - export type AttributionReportingSourceRegistrationResult = "success"|"internalError"|"insufficientSourceCapacity"|"insufficientUniqueDestinationCapacity"|"excessiveReportingOrigins"|"prohibitedByBrowserPolicy"|"successNoised"|"destinationReportingLimitReached"|"destinationGlobalLimitReached"|"destinationBothLimitsReached"|"reportingOriginsPerSiteLimitReached"|"exceedsMaxChannelCapacity"|"exceedsMaxTriggerStateCardinality"; + export type AttributionReportingSourceRegistrationResult = "success"|"internalError"|"insufficientSourceCapacity"|"insufficientUniqueDestinationCapacity"|"excessiveReportingOrigins"|"prohibitedByBrowserPolicy"|"successNoised"|"destinationReportingLimitReached"|"destinationGlobalLimitReached"|"destinationBothLimitsReached"|"reportingOriginsPerSiteLimitReached"|"exceedsMaxChannelCapacity"|"exceedsMaxTriggerStateCardinality"|"destinationPerDayReportingLimitReached"; export type AttributionReportingSourceRegistrationTimeConfig = "include"|"exclude"; export interface AttributionReportingAggregatableValueDictEntry { key: string; @@ -14084,6 +14196,7 @@ int int */ value: number; + filteringId: UnsignedInt64AsBase10; } export interface AttributionReportingAggregatableValueEntry { values: AttributionReportingAggregatableValueDictEntry[]; @@ -14111,10 +14224,12 @@ int eventTriggerData: AttributionReportingEventTriggerData[]; aggregatableTriggerData: AttributionReportingAggregatableTriggerData[]; aggregatableValues: AttributionReportingAggregatableValueEntry[]; + aggregatableFilteringIdMaxBytes: number; debugReporting: boolean; aggregationCoordinatorOrigin?: string; sourceRegistrationTimeConfig: AttributionReportingSourceRegistrationTimeConfig; triggerContextId?: string; + aggregatableDebugReportingConfig: AttributionReportingAggregatableDebugReportingConfig; } export type AttributionReportingEventLevelResult = "success"|"successDroppedLowerPriority"|"internalError"|"noCapacityForAttributionDestination"|"noMatchingSources"|"deduplicated"|"excessiveAttributions"|"priorityTooLow"|"neverAttributedSource"|"excessiveReportingOrigins"|"noMatchingSourceFilterData"|"prohibitedByBrowserPolicy"|"noMatchingConfigurations"|"excessiveReports"|"falselyAttributedSource"|"reportWindowPassed"|"notRegistered"|"reportWindowNotStarted"|"noMatchingTriggerData"; export type AttributionReportingAggregatableResult = "success"|"internalError"|"noCapacityForAttributionDestination"|"noMatchingSources"|"excessiveAttributions"|"excessiveReportingOrigins"|"noHistograms"|"insufficientBudget"|"noMatchingSourceFilterData"|"notRegistered"|"prohibitedByBrowserPolicy"|"deduplicated"|"reportWindowPassed"|"excessiveReports"; @@ -14980,7 +15095,7 @@ supported. browserContextId?: Browser.BrowserContextID; /** * Provides additional details for specific target types. For example, for -the type of "page", this may be set to "portal" or "prerender". +the type of "page", this may be set to "prerender". */ subtype?: string; } @@ -16807,7 +16922,7 @@ possible for multiple rule sets and links to trigger a single attempt. /** * List of FinalStatus reasons for Prerender2. */ - export type PrerenderFinalStatus = "Activated"|"Destroyed"|"LowEndDevice"|"InvalidSchemeRedirect"|"InvalidSchemeNavigation"|"NavigationRequestBlockedByCsp"|"MainFrameNavigation"|"MojoBinderPolicy"|"RendererProcessCrashed"|"RendererProcessKilled"|"Download"|"TriggerDestroyed"|"NavigationNotCommitted"|"NavigationBadHttpStatus"|"ClientCertRequested"|"NavigationRequestNetworkError"|"CancelAllHostsForTesting"|"DidFailLoad"|"Stop"|"SslCertificateError"|"LoginAuthRequested"|"UaChangeRequiresReload"|"BlockedByClient"|"AudioOutputDeviceRequested"|"MixedContent"|"TriggerBackgrounded"|"MemoryLimitExceeded"|"DataSaverEnabled"|"TriggerUrlHasEffectiveUrl"|"ActivatedBeforeStarted"|"InactivePageRestriction"|"StartFailed"|"TimeoutBackgrounded"|"CrossSiteRedirectInInitialNavigation"|"CrossSiteNavigationInInitialNavigation"|"SameSiteCrossOriginRedirectNotOptInInInitialNavigation"|"SameSiteCrossOriginNavigationNotOptInInInitialNavigation"|"ActivationNavigationParameterMismatch"|"ActivatedInBackground"|"EmbedderHostDisallowed"|"ActivationNavigationDestroyedBeforeSuccess"|"TabClosedByUserGesture"|"TabClosedWithoutUserGesture"|"PrimaryMainFrameRendererProcessCrashed"|"PrimaryMainFrameRendererProcessKilled"|"ActivationFramePolicyNotCompatible"|"PreloadingDisabled"|"BatterySaverEnabled"|"ActivatedDuringMainFrameNavigation"|"PreloadingUnsupportedByWebContents"|"CrossSiteRedirectInMainFrameNavigation"|"CrossSiteNavigationInMainFrameNavigation"|"SameSiteCrossOriginRedirectNotOptInInMainFrameNavigation"|"SameSiteCrossOriginNavigationNotOptInInMainFrameNavigation"|"MemoryPressureOnTrigger"|"MemoryPressureAfterTriggered"|"PrerenderingDisabledByDevTools"|"SpeculationRuleRemoved"|"ActivatedWithAuxiliaryBrowsingContexts"|"MaxNumOfRunningEagerPrerendersExceeded"|"MaxNumOfRunningNonEagerPrerendersExceeded"|"MaxNumOfRunningEmbedderPrerendersExceeded"|"PrerenderingUrlHasEffectiveUrl"|"RedirectedPrerenderingUrlHasEffectiveUrl"|"ActivationUrlHasEffectiveUrl"|"JavaScriptInterfaceAdded"|"JavaScriptInterfaceRemoved"|"AllPrerenderingCanceled"; + export type PrerenderFinalStatus = "Activated"|"Destroyed"|"LowEndDevice"|"InvalidSchemeRedirect"|"InvalidSchemeNavigation"|"NavigationRequestBlockedByCsp"|"MainFrameNavigation"|"MojoBinderPolicy"|"RendererProcessCrashed"|"RendererProcessKilled"|"Download"|"TriggerDestroyed"|"NavigationNotCommitted"|"NavigationBadHttpStatus"|"ClientCertRequested"|"NavigationRequestNetworkError"|"CancelAllHostsForTesting"|"DidFailLoad"|"Stop"|"SslCertificateError"|"LoginAuthRequested"|"UaChangeRequiresReload"|"BlockedByClient"|"AudioOutputDeviceRequested"|"MixedContent"|"TriggerBackgrounded"|"MemoryLimitExceeded"|"DataSaverEnabled"|"TriggerUrlHasEffectiveUrl"|"ActivatedBeforeStarted"|"InactivePageRestriction"|"StartFailed"|"TimeoutBackgrounded"|"CrossSiteRedirectInInitialNavigation"|"CrossSiteNavigationInInitialNavigation"|"SameSiteCrossOriginRedirectNotOptInInInitialNavigation"|"SameSiteCrossOriginNavigationNotOptInInInitialNavigation"|"ActivationNavigationParameterMismatch"|"ActivatedInBackground"|"EmbedderHostDisallowed"|"ActivationNavigationDestroyedBeforeSuccess"|"TabClosedByUserGesture"|"TabClosedWithoutUserGesture"|"PrimaryMainFrameRendererProcessCrashed"|"PrimaryMainFrameRendererProcessKilled"|"ActivationFramePolicyNotCompatible"|"PreloadingDisabled"|"BatterySaverEnabled"|"ActivatedDuringMainFrameNavigation"|"PreloadingUnsupportedByWebContents"|"CrossSiteRedirectInMainFrameNavigation"|"CrossSiteNavigationInMainFrameNavigation"|"SameSiteCrossOriginRedirectNotOptInInMainFrameNavigation"|"SameSiteCrossOriginNavigationNotOptInInMainFrameNavigation"|"MemoryPressureOnTrigger"|"MemoryPressureAfterTriggered"|"PrerenderingDisabledByDevTools"|"SpeculationRuleRemoved"|"ActivatedWithAuxiliaryBrowsingContexts"|"MaxNumOfRunningEagerPrerendersExceeded"|"MaxNumOfRunningNonEagerPrerendersExceeded"|"MaxNumOfRunningEmbedderPrerendersExceeded"|"PrerenderingUrlHasEffectiveUrl"|"RedirectedPrerenderingUrlHasEffectiveUrl"|"ActivationUrlHasEffectiveUrl"|"JavaScriptInterfaceAdded"|"JavaScriptInterfaceRemoved"|"AllPrerenderingCanceled"|"WindowClosed"; /** * Preloading status values, see also PreloadingTriggeringOutcome. This status is shared by prefetchStatusUpdated and prerenderStatusUpdated. @@ -17021,6 +17136,10 @@ https://www.iana.org/assignments/media-types/media-types.xhtml accepts: FileHandlerAccept[]; displayName: string; } + /** + * If user prefers opening the app in browser or an app window. + */ + export type DisplayMode = "standalone"|"browser"; /** @@ -17061,7 +17180,7 @@ manifestId. export type installReturnValue = { } /** - * Uninstals the given manifest_id and closes any opened app windows. + * Uninstalls the given manifest_id and closes any opened app windows. */ export type uninstallParameters = { manifestId: string; @@ -17090,7 +17209,7 @@ the files. The API returns one or more page Target.TargetIDs which can be used to attach to via Target.attachToTarget or similar APIs. If some files in the parameters cannot be handled by the web app, they will be ignored. If none of the files can be handled, this API returns an error. -If no files provided as the parameter, this API also returns an error. +If no files are provided as the parameter, this API also returns an error. According to the definition of the file handlers in the manifest file, one Target.TargetID may represent a page handling one or more files. The order @@ -17111,13 +17230,44 @@ TODO(crbug.com/339454034): Check the existences of the input files. /** * Opens the current page in its web app identified by the manifest id, needs to be called on a page target. This function returns immediately without -waiting for the app finishing loading. +waiting for the app to finish loading. */ export type openCurrentPageInAppParameters = { manifestId: string; } export type openCurrentPageInAppReturnValue = { } + /** + * Changes user settings of the web app identified by its manifestId. If the +app was not installed, this command returns an error. Unset parameters will +be ignored; unrecognized values will cause an error. + +Unlike the ones defined in the manifest files of the web apps, these +settings are provided by the browser and controlled by the users, they +impact the way the browser handling the web apps. + +See the comment of each parameter. + */ + export type changeAppUserSettingsParameters = { + manifestId: string; + /** + * If user allows the links clicked on by the user in the app's scope, or +extended scope if the manifest has scope extensions and the flags +`DesktopPWAsLinkCapturingWithScopeExtensions` and +`WebAppEnableScopeExtensions` are enabled. + +Note, the API does not support resetting the linkCapturing to the +initial value, uninstalling and installing the web app again will reset +it. + +TODO(crbug.com/339453269): Setting this value on ChromeOS is not +supported yet. + */ + linkCapturing?: boolean; + displayMode?: DisplayMode; + } + export type changeAppUserSettingsReturnValue = { + } } /** @@ -19824,6 +19974,7 @@ Error was thrown. "Network.responseReceivedExtraInfo": Network.responseReceivedExtraInfoPayload; "Network.responseReceivedEarlyHints": Network.responseReceivedEarlyHintsPayload; "Network.trustTokenOperationDone": Network.trustTokenOperationDonePayload; + "Network.policyUpdated": Network.policyUpdatedPayload; "Network.subresourceWebBundleMetadataReceived": Network.subresourceWebBundleMetadataReceivedPayload; "Network.subresourceWebBundleMetadataError": Network.subresourceWebBundleMetadataErrorPayload; "Network.subresourceWebBundleInnerResponseParsed": Network.subresourceWebBundleInnerResponseParsedPayload; @@ -20139,6 +20290,8 @@ Error was thrown. "Emulation.getOverriddenSensorInformation": Emulation.getOverriddenSensorInformationParameters; "Emulation.setSensorOverrideEnabled": Emulation.setSensorOverrideEnabledParameters; "Emulation.setSensorOverrideReadings": Emulation.setSensorOverrideReadingsParameters; + "Emulation.setPressureSourceOverrideEnabled": Emulation.setPressureSourceOverrideEnabledParameters; + "Emulation.setPressureStateOverride": Emulation.setPressureStateOverrideParameters; "Emulation.setIdleOverride": Emulation.setIdleOverrideParameters; "Emulation.clearIdleOverride": Emulation.clearIdleOverrideParameters; "Emulation.setNavigatorOverrides": Emulation.setNavigatorOverridesParameters; @@ -20159,6 +20312,7 @@ Error was thrown. "IO.close": IO.closeParameters; "IO.read": IO.readParameters; "IO.resolveBlob": IO.resolveBlobParameters; + "FileSystem.getDirectory": FileSystem.getDirectoryParameters; "IndexedDB.clearObjectStore": IndexedDB.clearObjectStoreParameters; "IndexedDB.deleteDatabase": IndexedDB.deleteDatabaseParameters; "IndexedDB.deleteObjectStoreEntries": IndexedDB.deleteObjectStoreEntriesParameters; @@ -20461,6 +20615,7 @@ Error was thrown. "PWA.launch": PWA.launchParameters; "PWA.launchFilesInApp": PWA.launchFilesInAppParameters; "PWA.openCurrentPageInApp": PWA.openCurrentPageInAppParameters; + "PWA.changeAppUserSettings": PWA.changeAppUserSettingsParameters; "Console.clearMessages": Console.clearMessagesParameters; "Console.disable": Console.disableParameters; "Console.enable": Console.enableParameters; @@ -20735,6 +20890,8 @@ Error was thrown. "Emulation.getOverriddenSensorInformation": Emulation.getOverriddenSensorInformationReturnValue; "Emulation.setSensorOverrideEnabled": Emulation.setSensorOverrideEnabledReturnValue; "Emulation.setSensorOverrideReadings": Emulation.setSensorOverrideReadingsReturnValue; + "Emulation.setPressureSourceOverrideEnabled": Emulation.setPressureSourceOverrideEnabledReturnValue; + "Emulation.setPressureStateOverride": Emulation.setPressureStateOverrideReturnValue; "Emulation.setIdleOverride": Emulation.setIdleOverrideReturnValue; "Emulation.clearIdleOverride": Emulation.clearIdleOverrideReturnValue; "Emulation.setNavigatorOverrides": Emulation.setNavigatorOverridesReturnValue; @@ -20755,6 +20912,7 @@ Error was thrown. "IO.close": IO.closeReturnValue; "IO.read": IO.readReturnValue; "IO.resolveBlob": IO.resolveBlobReturnValue; + "FileSystem.getDirectory": FileSystem.getDirectoryReturnValue; "IndexedDB.clearObjectStore": IndexedDB.clearObjectStoreReturnValue; "IndexedDB.deleteDatabase": IndexedDB.deleteDatabaseReturnValue; "IndexedDB.deleteObjectStoreEntries": IndexedDB.deleteObjectStoreEntriesReturnValue; @@ -21057,6 +21215,7 @@ Error was thrown. "PWA.launch": PWA.launchReturnValue; "PWA.launchFilesInApp": PWA.launchFilesInAppReturnValue; "PWA.openCurrentPageInApp": PWA.openCurrentPageInAppReturnValue; + "PWA.changeAppUserSettings": PWA.changeAppUserSettingsReturnValue; "Console.clearMessages": Console.clearMessagesReturnValue; "Console.disable": Console.disableReturnValue; "Console.enable": Console.enableReturnValue; From a1a4216b88f25f3f4b28ac11075e9ac9cadca380 Mon Sep 17 00:00:00 2001 From: Simon Knott Date: Thu, 25 Jul 2024 12:21:24 +0200 Subject: [PATCH 04/20] chore(ui): add test expectation that doesn't immediately pass on blank tree (#31850) Followup to #31815 --- tests/playwright-test/ui-mode-test-filters.spec.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/playwright-test/ui-mode-test-filters.spec.ts b/tests/playwright-test/ui-mode-test-filters.spec.ts index 3f65c65a0e..5d70048473 100644 --- a/tests/playwright-test/ui-mode-test-filters.spec.ts +++ b/tests/playwright-test/ui-mode-test-filters.spec.ts @@ -234,6 +234,7 @@ test('should only show tests selected with --grep', async ({ runUITest }) => { const { page } = await runUITest(basicTestTree, undefined, { additionalArgs: ['--grep', 'fails'], }); + await expect.poll(dumpTestTree(page)).toContain('fails'); await expect.poll(dumpTestTree(page)).not.toContain('passes'); }); From 3ce948e972b594a59fbb0a06f6cf146c21ed79f8 Mon Sep 17 00:00:00 2001 From: Playwright Service <89237858+playwrightmachine@users.noreply.github.com> Date: Thu, 25 Jul 2024 03:52:50 -0700 Subject: [PATCH 05/20] chore(driver): roll driver to recent Node.js LTS version (#31854) --- utils/build/build-playwright-driver.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/build/build-playwright-driver.sh b/utils/build/build-playwright-driver.sh index a59688cd7e..7aaee25b62 100755 --- a/utils/build/build-playwright-driver.sh +++ b/utils/build/build-playwright-driver.sh @@ -4,7 +4,7 @@ set -x trap "cd $(pwd -P)" EXIT SCRIPT_PATH="$(cd "$(dirname "$0")" ; pwd -P)" -NODE_VERSION="20.15.1" # autogenerated via ./update-playwright-driver-version.mjs +NODE_VERSION="20.16.0" # autogenerated via ./update-playwright-driver-version.mjs cd "$(dirname "$0")" PACKAGE_VERSION=$(node -p "require('../../package.json').version") From 4d4ed2a5c4da7467ae0d1d721018ba0766e8fc35 Mon Sep 17 00:00:00 2001 From: Simon Knott Date: Thu, 25 Jul 2024 13:06:26 +0200 Subject: [PATCH 06/20] chore: enforce single quotes in JSX (#31855) Discovered in https://github.com/microsoft/playwright/pull/31852#discussion_r1691133106: We're not enforcing single quotes for JSX, and it shows! We need to start enforcing it to prevent even greater damage from being done ;D --- .eslintrc.js | 1 + packages/html-reporter/src/icons.tsx | 14 +++++++------- packages/html-reporter/src/testFileView.tsx | 4 ++-- packages/html-reporter/src/testFilesView.tsx | 8 ++++---- packages/trace-viewer/src/ui/actionList.tsx | 4 ++-- 5 files changed, 16 insertions(+), 15 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index bff9ffeeb4..bb351a8c56 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -30,6 +30,7 @@ module.exports = { "avoidEscape": true, "allowTemplateLiterals": true }], + "jsx-quotes": [2, "prefer-single"], "no-extra-semi": 2, "@typescript-eslint/semi": [2], "comma-style": [2, "last"], diff --git a/packages/html-reporter/src/icons.tsx b/packages/html-reporter/src/icons.tsx index c3eb471b4d..6111fac7c1 100644 --- a/packages/html-reporter/src/icons.tsx +++ b/packages/html-reporter/src/icons.tsx @@ -70,36 +70,36 @@ export const blank = () => { }; export const externalLink = () => { - return ; + return ; }; export const calendar = () => { - return ; + return ; }; export const person = () => { - return ; + return ; }; export const commit = () => { - return ; + return ; }; export const image = () => { return ; }; export const video = () => { return ; }; export const trace = () => { return ; }; diff --git a/packages/html-reporter/src/testFileView.tsx b/packages/html-reporter/src/testFileView.tsx index a5f9a7a358..184b2b63ba 100644 --- a/packages/html-reporter/src/testFileView.tsx +++ b/packages/html-reporter/src/testFileView.tsx @@ -41,8 +41,8 @@ export const TestFileView: React.FC filter.matches(t)).map(test =>
-
- +
+ {statusIcon(test.outcome)} diff --git a/packages/html-reporter/src/testFilesView.tsx b/packages/html-reporter/src/testFilesView.tsx index 2a783b5ebe..30c80c075b 100644 --- a/packages/html-reporter/src/testFilesView.tsx +++ b/packages/html-reporter/src/testFilesView.tsx @@ -44,11 +44,11 @@ export const TestFilesView: React.FC<{ }, [report, filter]); return <>
- {projectNames.length === 1 && !!projectNames[0] &&
Project: {projectNames[0]}
} - {!filter.empty() &&
Filtered: {filteredStats.total} {!!filteredStats.total && ('(' + msToString(filteredStats.duration) + ')')}
} + {projectNames.length === 1 && !!projectNames[0] &&
Project: {projectNames[0]}
} + {!filter.empty() &&
Filtered: {filteredStats.total} {!!filteredStats.total && ('(' + msToString(filteredStats.duration) + ')')}
}
-
{report ? new Date(report.startTime).toLocaleString() : ''}
-
Total time: {msToString(report?.duration ?? 0)}
+
{report ? new Date(report.startTime).toLocaleString() : ''}
+
Total time: {msToString(report?.duration ?? 0)}
{report && !!report.errors.length && {report.errors.map((error, index) => )} diff --git a/packages/trace-viewer/src/ui/actionList.tsx b/packages/trace-viewer/src/ui/actionList.tsx index e5866ba310..3935447e7d 100644 --- a/packages/trace-viewer/src/ui/actionList.tsx +++ b/packages/trace-viewer/src/ui/actionList.tsx @@ -107,8 +107,8 @@ export const renderAction = ( {(showDuration || showBadges) &&
} {showDuration &&
{time || }
} {showBadges &&
revealConsole?.()}> - {!!errors &&
{errors}
} - {!!warnings &&
{warnings}
} + {!!errors &&
{errors}
} + {!!warnings &&
{warnings}
}
} ; }; From b06a95dd7500a27dd8b8e71089ab3c55586c12b8 Mon Sep 17 00:00:00 2001 From: Simon Knott Date: Thu, 25 Jul 2024 17:14:46 +0200 Subject: [PATCH 07/20] feat(trace viewer): show `baseURL` in Metadata pane (#31852) Resolves https://github.com/microsoft/playwright/issues/31847 by adding playwright config's `baseURL` value to the `context-options` trace event, and showing that in the Trace Viewer. Because the added property is optional, I didn't increment the trace format version. I've also considered pulling the `baseURL` from the existing `browser.newContext` step to get around modifying the trace format, but that felt pretty hacky. https://github.com/user-attachments/assets/ecaef747-727d-4937-9ca3-1605ca9907b9 --------- Signed-off-by: Simon Knott Co-authored-by: Dmitry Gozman --- packages/trace-viewer/src/ui/callTab.css | 8 ++++++++ packages/trace-viewer/src/ui/metadataView.tsx | 6 ++++++ packages/trace/src/trace.ts | 1 + tests/config/traceViewerFixtures.ts | 6 ++++++ tests/library/trace-viewer.spec.ts | 13 ++++++++++++- 5 files changed, 33 insertions(+), 1 deletion(-) diff --git a/packages/trace-viewer/src/ui/callTab.css b/packages/trace-viewer/src/ui/callTab.css index 3334b2e2ef..3bca9f7141 100644 --- a/packages/trace-viewer/src/ui/callTab.css +++ b/packages/trace-viewer/src/ui/callTab.css @@ -73,6 +73,14 @@ overflow: hidden; } +a.call-value { + text-decoration: none; +} + +a.call-value:hover { + text-decoration: underline; +} + .call-value::before { content: '\00a0'; } diff --git a/packages/trace-viewer/src/ui/metadataView.tsx b/packages/trace-viewer/src/ui/metadataView.tsx index 6cb315686a..5b50a7f081 100644 --- a/packages/trace-viewer/src/ui/metadataView.tsx +++ b/packages/trace-viewer/src/ui/metadataView.tsx @@ -33,6 +33,12 @@ export const MetadataView: React.FunctionComponent<{ {model.channel &&
channel:{model.channel}
} {model.platform &&
platform:{model.platform}
} {model.options.userAgent &&
user agent:{model.options.userAgent}
} + {model.options.baseURL && ( + <> +
Config
+ + + )}
Viewport
{model.options.viewport &&
width:{model.options.viewport.width}
} {model.options.viewport &&
height:{model.options.viewport.height}
} diff --git a/packages/trace/src/trace.ts b/packages/trace/src/trace.ts index ebd3466fd8..0e1c5327a1 100644 --- a/packages/trace/src/trace.ts +++ b/packages/trace/src/trace.ts @@ -24,6 +24,7 @@ export type Size = { width: number, height: number }; export type VERSION = 7; export type BrowserContextEventOptions = { + baseURL?: string, viewport?: Size, deviceScaleFactor?: number, isMobile?: boolean, diff --git a/tests/config/traceViewerFixtures.ts b/tests/config/traceViewerFixtures.ts index 2e6fab2f18..b389f0c07c 100644 --- a/tests/config/traceViewerFixtures.ts +++ b/tests/config/traceViewerFixtures.ts @@ -44,6 +44,7 @@ class TraceViewerPage { consoleStacks: Locator; stackFrames: Locator; networkRequests: Locator; + metadataTab: Locator; snapshotContainer: Locator; constructor(public page: Page) { @@ -57,6 +58,7 @@ class TraceViewerPage { this.stackFrames = page.getByTestId('stack-trace-list').locator('.list-view-entry'); this.networkRequests = page.getByTestId('network-list').locator('.list-view-entry'); this.snapshotContainer = page.locator('.snapshot-container iframe.snapshot-visible[name=snapshot]'); + this.metadataTab = page.locator('.metadata-view'); } async actionIconsText(action: string) { @@ -93,6 +95,10 @@ class TraceViewerPage { await this.page.click('text="Network"'); } + async showMetadataTab() { + await this.page.click('text="Metadata"'); + } + @step async snapshotFrame(actionName: string, ordinal: number = 0, hasSubframe: boolean = false): Promise { await this.selectAction(actionName, ordinal); diff --git a/tests/library/trace-viewer.spec.ts b/tests/library/trace-viewer.spec.ts index 822c50cc09..539c153df6 100644 --- a/tests/library/trace-viewer.spec.ts +++ b/tests/library/trace-viewer.spec.ts @@ -31,7 +31,9 @@ test.slow(); let traceFile: string; test.beforeAll(async function recordTrace({ browser, browserName, browserType, server }, workerInfo) { - const context = await browser.newContext(); + const context = await browser.newContext({ + baseURL: 'https://example.com', + }); await context.tracing.start({ name: 'test', screenshots: true, snapshots: true, sources: true }); const page = await context.newPage(); await page.goto(`data:text/html,Hello world`); @@ -1368,3 +1370,12 @@ test('should allow hiding route actions', { /route.fulfill/, ]); }); + +test('should show baseURL in metadata pane', { + annotation: { type: 'issue', description: 'https://github.com/microsoft/playwright/issues/31847' }, +}, async ({ showTraceViewer }) => { + const traceViewer = await showTraceViewer([traceFile]); + await traceViewer.selectAction('page.evaluate'); + await traceViewer.showMetadataTab(); + await expect(traceViewer.metadataTab).toContainText('baseURL:https://example.com'); +}); From 90af289ba21dcfbd7b0e4e7f6718ebcd3ded83ea Mon Sep 17 00:00:00 2001 From: Max Schmitt Date: Thu, 25 Jul 2024 18:53:38 +0200 Subject: [PATCH 08/20] test: use managed http2 server for client-certificates (#31844) --- packages/playwright-core/src/utils/network.ts | 11 ++++- tests/library/client-certificates.spec.ts | 49 ++++++++++--------- tests/library/har.spec.ts | 4 +- 3 files changed, 38 insertions(+), 26 deletions(-) diff --git a/packages/playwright-core/src/utils/network.ts b/packages/playwright-core/src/utils/network.ts index 8cacb8aeb6..b9bc2c0f06 100644 --- a/packages/playwright-core/src/utils/network.ts +++ b/packages/playwright-core/src/utils/network.ts @@ -17,6 +17,7 @@ import http from 'http'; import https from 'https'; +import http2 from 'http2'; import type net from 'net'; import { getProxyForUrl } from '../utilsBundle'; import { HttpsProxyAgent } from '../utilsBundle'; @@ -169,6 +170,14 @@ export function createHttpsServer(...args: any[]): https.Server { return server; } +export function createHttp2Server( onRequestHandler?: (request: http2.Http2ServerRequest, response: http2.Http2ServerResponse) => void,): http2.Http2SecureServer; +export function createHttp2Server(options: http2.SecureServerOptions, onRequestHandler?: (request: http2.Http2ServerRequest, response: http2.Http2ServerResponse) => void,): http2.Http2SecureServer; +export function createHttp2Server(...args: any[]): http2.Http2SecureServer { + const server = http2.createSecureServer(...args); + decorateServer(server); + return server; +} + export async function isURLAvailable(url: URL, ignoreHTTPSErrors: boolean, onLog?: (data: string) => void, onStdErr?: (data: string) => void) { let statusCode = await httpStatusCode(url, ignoreHTTPSErrors, onLog, onStdErr); if (statusCode === 404 && url.pathname === '/') { @@ -200,7 +209,7 @@ async function httpStatusCode(url: URL, ignoreHTTPSErrors: boolean, onLog?: (dat }); } -function decorateServer(server: http.Server | http.Server) { +function decorateServer(server: net.Server) { const sockets = new Set(); server.on('connection', socket => { sockets.add(socket); diff --git a/tests/library/client-certificates.spec.ts b/tests/library/client-certificates.spec.ts index c5fc523925..ff60010d5b 100644 --- a/tests/library/client-certificates.spec.ts +++ b/tests/library/client-certificates.spec.ts @@ -15,12 +15,12 @@ */ import fs from 'fs'; -import http2 from 'http2'; +import type http2 from 'http2'; import type http from 'http'; import { expect, playwrightTest as base } from '../config/browserTest'; import type net from 'net'; import type { BrowserContextOptions } from 'packages/playwright-test'; -const { createHttpsServer } = require('../../packages/playwright-core/lib/utils'); +const { createHttpsServer, createHttp2Server } = require('../../packages/playwright-core/lib/utils'); type TestOptions = { startCCServer(options?: { @@ -30,11 +30,11 @@ type TestOptions = { }; const test = base.extend({ - startCCServer: async ({ asset, browserName }, use) => { + startCCServer: async ({ asset }, use) => { process.env.PWTEST_UNSUPPORTED_CUSTOM_CA = asset('client-certificates/server/server_cert.pem'); - let server: http.Server | http2.Http2Server | undefined; + let server: http.Server | http2.Http2SecureServer | undefined; await use(async options => { - server = (options?.http2 ? http2.createSecureServer : createHttpsServer)({ + server = (options?.http2 ? createHttp2Server : createHttpsServer)({ key: fs.readFileSync(asset('client-certificates/server/server_key.pem')), cert: fs.readFileSync(asset('client-certificates/server/server_cert.pem')), ca: [ @@ -45,20 +45,22 @@ const test = base.extend({ allowHTTP1: true, }, (req: (http2.Http2ServerRequest | http.IncomingMessage), res: http2.Http2ServerResponse | http.ServerResponse) => { const tlsSocket = req.socket as import('tls').TLSSocket; + const parts: { key: string, value: any }[] = []; + parts.push({ key: 'alpn-protocol', value: tlsSocket.alpnProtocol }); // @ts-expect-error https://github.com/DefinitelyTyped/DefinitelyTyped/discussions/62336 - expect(['localhost', 'local.playwright'].includes((tlsSocket).servername)).toBe(true); - const prefix = `ALPN protocol: ${tlsSocket.alpnProtocol}\n`; + parts.push({ key: 'servername', value: tlsSocket.servername }); const cert = tlsSocket.getPeerCertificate(); if (tlsSocket.authorized) { res.writeHead(200, { 'Content-Type': 'text/html' }); - res.end(prefix + `Hello ${cert.subject.CN}, your certificate was issued by ${cert.issuer.CN}!`); + parts.push({ key: 'message', value: `Hello ${cert.subject.CN}, your certificate was issued by ${cert.issuer.CN}!` }); } else if (cert.subject) { res.writeHead(403, { 'Content-Type': 'text/html' }); - res.end(prefix + `Sorry ${cert.subject.CN}, certificates from ${cert.issuer.CN} are not welcome here.`); + parts.push({ key: 'message', value: `Sorry ${cert.subject.CN}, certificates from ${cert.issuer.CN} are not welcome here.` }); } else { res.writeHead(401, { 'Content-Type': 'text/html' }); - res.end(prefix + `Sorry, but you need to provide a client certificate to continue.`); + parts.push({ key: 'message', value: `Sorry, but you need to provide a client certificate to continue.` }); } + res.end(parts.map(({ key, value }) => `
${value}
`).join('')); }); await new Promise(f => server.listen(0, 'localhost', () => f())); const host = options?.useFakeLocalhost ? 'local.playwright' : 'localhost'; @@ -179,7 +181,7 @@ test.describe('fetch', () => { await route.fulfill({ response }); }); await page.goto(serverURL); - await expect(page.getByText('Hello Alice, your certificate was issued by localhost!')).toBeVisible(); + await expect(page.getByTestId('message')).toHaveText('Hello Alice, your certificate was issued by localhost!'); await page.close(); await request.dispose(); }); @@ -216,7 +218,7 @@ test.describe('browser', () => { }], }); await page.goto(serverURL); - await expect(page.getByText('Sorry, but you need to provide a client certificate to continue.')).toBeVisible(); + await expect(page.getByTestId('message')).toHaveText('Sorry, but you need to provide a client certificate to continue.'); await page.close(); }); @@ -230,7 +232,7 @@ test.describe('browser', () => { }], }); await page.goto(serverURL); - await expect(page.getByText('Sorry Bob, certificates from Bob are not welcome here')).toBeVisible(); + await expect(page.getByTestId('message')).toHaveText('Sorry Bob, certificates from Bob are not welcome here.'); await page.close(); }); @@ -244,7 +246,7 @@ test.describe('browser', () => { }], }); await page.goto(serverURL); - await expect(page.getByText('Hello Alice, your certificate was issued by localhost!')).toBeVisible(); + await expect(page.getByTestId('message')).toHaveText('Hello Alice, your certificate was issued by localhost!'); await page.close(); }); @@ -290,13 +292,14 @@ test.describe('browser', () => { const expectedProtocol = browserName === 'webkit' && process.platform === 'linux' ? 'http/1.1' : 'h2'; { await page.goto(serverURL.replace('localhost', 'local.playwright')); - await expect(page.getByText('Sorry, but you need to provide a client certificate to continue.')).toBeVisible(); - await expect(page.getByText(`ALPN protocol: ${expectedProtocol}`)).toBeVisible(); + await expect(page.getByTestId('message')).toHaveText('Sorry, but you need to provide a client certificate to continue.'); + await expect(page.getByTestId('alpn-protocol')).toHaveText(expectedProtocol); + await expect(page.getByTestId('servername')).toHaveText('local.playwright'); } { await page.goto(serverURL); - await expect(page.getByText('Hello Alice, your certificate was issued by localhost!')).toBeVisible(); - await expect(page.getByText(`ALPN protocol: ${expectedProtocol}`)).toBeVisible(); + await expect(page.getByTestId('message')).toHaveText('Hello Alice, your certificate was issued by localhost!'); + await expect(page.getByTestId('alpn-protocol')).toHaveText(expectedProtocol); } await page.close(); }); @@ -314,13 +317,13 @@ test.describe('browser', () => { }); { await page.goto(serverURL.replace('localhost', 'local.playwright')); - await expect(page.getByText('Sorry, but you need to provide a client certificate to continue.')).toBeVisible(); - await expect(page.getByText('ALPN protocol: http/1.1')).toBeVisible(); + await expect(page.getByTestId('message')).toHaveText('Sorry, but you need to provide a client certificate to continue.'); + await expect(page.getByTestId('alpn-protocol')).toHaveText('http/1.1'); } { await page.goto(serverURL); - await expect(page.getByText('Hello Alice, your certificate was issued by localhost!')).toBeVisible(); - await expect(page.getByText('ALPN protocol: http/1.1')).toBeVisible(); + await expect(page.getByTestId('message')).toHaveText('Hello Alice, your certificate was issued by localhost!'); + await expect(page.getByTestId('alpn-protocol')).toHaveText('http/1.1'); } await browser.close(); }); @@ -342,7 +345,7 @@ test.describe('browser', () => { }], }); await page.goto(serverURL); - await expect(page.getByText('Hello Alice, your certificate was issued by localhost!')).toBeVisible(); + await expect(page.getByTestId('message')).toHaveText('Hello Alice, your certificate was issued by localhost!'); }); }); }); diff --git a/tests/library/har.spec.ts b/tests/library/har.spec.ts index 41723dd7af..29ee7df2d1 100644 --- a/tests/library/har.spec.ts +++ b/tests/library/har.spec.ts @@ -18,11 +18,11 @@ import { browserTest as it, expect } from '../config/browserTest'; import * as path from 'path'; import fs from 'fs'; -import http2 from 'http2'; import type { BrowserContext, BrowserContextOptions } from 'playwright-core'; import type { AddressInfo } from 'net'; import type { Log } from '../../packages/trace/src/har'; import { parseHar } from '../config/utils'; +const { createHttp2Server } = require('../../packages/playwright-core/lib/utils'); async function pageWithHar(contextFactory: (options?: BrowserContextOptions) => Promise, testInfo: any, options: { outputPath?: string, content?: 'embed' | 'attach' | 'omit', omitContent?: boolean } = {}) { const harPath = testInfo.outputPath(options.outputPath || 'test.har'); @@ -686,7 +686,7 @@ it('should return security details directly from response', async ({ contextFact }); it('should contain http2 for http2 requests', async ({ contextFactory }, testInfo) => { - const server = http2.createSecureServer({ + const server = createHttp2Server({ key: await fs.promises.readFile(path.join(__dirname, '..', 'config', 'testserver', 'key.pem')), cert: await fs.promises.readFile(path.join(__dirname, '..', 'config', 'testserver', 'cert.pem')), }); From d3e2c6cbb2d25f15c067fdcaf6da50fb1b57e05d Mon Sep 17 00:00:00 2001 From: Playwright Service <89237858+playwrightmachine@users.noreply.github.com> Date: Thu, 25 Jul 2024 09:54:24 -0700 Subject: [PATCH 09/20] feat(chromium-tip-of-tree): roll to r1244 (#31856) Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com> --- packages/playwright-core/browsers.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/playwright-core/browsers.json b/packages/playwright-core/browsers.json index cf8a374751..1b0a4d3ae7 100644 --- a/packages/playwright-core/browsers.json +++ b/packages/playwright-core/browsers.json @@ -9,9 +9,9 @@ }, { "name": "chromium-tip-of-tree", - "revision": "1243", + "revision": "1244", "installByDefault": false, - "browserVersion": "128.0.6613.0" + "browserVersion": "129.0.6616.0" }, { "name": "firefox", From 0c6ecf8df4e4c913db9873dd4b1e2b5a86e76d9f Mon Sep 17 00:00:00 2001 From: Max Schmitt Date: Thu, 25 Jul 2024 18:55:47 +0200 Subject: [PATCH 10/20] chore: use happy eyeballs for client-certificates (#31859) --- .../socksClientCertificatesInterceptor.ts | 19 +++++----- .../src/utils/happy-eyeballs.ts | 37 ++++++++++++++++++- 2 files changed, 45 insertions(+), 11 deletions(-) diff --git a/packages/playwright-core/src/server/socksClientCertificatesInterceptor.ts b/packages/playwright-core/src/server/socksClientCertificatesInterceptor.ts index ce8086c821..d5a71c73e6 100644 --- a/packages/playwright-core/src/server/socksClientCertificatesInterceptor.ts +++ b/packages/playwright-core/src/server/socksClientCertificatesInterceptor.ts @@ -20,7 +20,7 @@ import type https from 'https'; import fs from 'fs'; import tls from 'tls'; import stream from 'stream'; -import { createSocket } from '../utils/happy-eyeballs'; +import { createSocket, createTLSSocket } from '../utils/happy-eyeballs'; import { isUnderTest, ManualPromise } from '../utils'; import type { SocksSocketClosedPayload, SocksSocketDataPayload, SocksSocketRequestedPayload } from '../common/socksProxy'; import { SocksProxy } from '../common/socksProxy'; @@ -42,22 +42,21 @@ class ALPNCache { const result = new ManualPromise(); this._cache.set(cacheKey, result); result.then(success); - const socket = tls.connect({ + createTLSSocket({ host, port, servername: net.isIP(host) ? undefined : host, ALPNProtocols: ['h2', 'http/1.1'], rejectUnauthorized: false, - }); - socket.on('secureConnect', () => { - // The server may not respond with ALPN, in which case we default to http/1.1. - result.resolve(socket.alpnProtocol || 'http/1.1'); - socket.end(); - }); - socket.on('error', error => { + }).then(socket => { + socket.on('secureConnect', () => { + // The server may not respond with ALPN, in which case we default to http/1.1. + result.resolve(socket.alpnProtocol || 'http/1.1'); + socket.end(); + }); + }).catch(error => { debugLogger.log('client-certificates', `ALPN error: ${error.message}`); result.resolve('http/1.1'); - socket.end(); }); } } diff --git a/packages/playwright-core/src/utils/happy-eyeballs.ts b/packages/playwright-core/src/utils/happy-eyeballs.ts index 37d5c1b271..80663b8192 100644 --- a/packages/playwright-core/src/utils/happy-eyeballs.ts +++ b/packages/playwright-core/src/utils/happy-eyeballs.ts @@ -20,6 +20,7 @@ import * as https from 'https'; import * as net from 'net'; import * as tls from 'tls'; import { ManualPromise } from './manualPromise'; +import { assert } from './debug'; // Implementation(partial) of Happy Eyeballs 2 algorithm described in // https://www.rfc-editor.org/rfc/rfc8305 @@ -66,7 +67,41 @@ export async function createSocket(host: string, port: number): Promise void) | undefined, useTLS: boolean) { +export async function createTLSSocket(options: tls.ConnectionOptions): Promise { + return new Promise((resolve, reject) => { + assert(options.host, 'host is required'); + if (net.isIP(options.host)) { + const socket = tls.connect(options) + socket.on('connect', () => resolve(socket)); + socket.on('error', error => reject(error)); + } else { + createConnectionAsync(options, (err, socket) => { + if (err) + reject(err); + if (socket) + resolve(socket); + }, true).catch(err => reject(err)); + } + }); +} + +export async function createConnectionAsync( + options: http.ClientRequestArgs, + oncreate: ((err: Error | null, socket?: tls.TLSSocket) => void) | undefined, + useTLS: true +): Promise; + +export async function createConnectionAsync( + options: http.ClientRequestArgs, + oncreate: ((err: Error | null, socket?: net.Socket) => void) | undefined, + useTLS: false +): Promise; + +export async function createConnectionAsync( + options: http.ClientRequestArgs, + oncreate: ((err: Error | null, socket?: any) => void) | undefined, + useTLS: boolean +): Promise { const lookup = (options as any).__testHookLookup || lookupAddresses; const hostname = clientRequestArgsToHostName(options); const addresses = await lookup(hostname); From d8d5289e8692c9b1265d23ee66988d1ac5122f33 Mon Sep 17 00:00:00 2001 From: Dmitry Gozman Date: Thu, 25 Jul 2024 09:57:34 -0700 Subject: [PATCH 11/20] fix(remote): make sure api calls reject before browser is closed (#31858) Upon calling `browser.close()` or dropping remote connection, make sure to reject api calls before resolving `browser.close()` and firing a `disconnected` event. This change aligns the order guarantee with non-remote case. --- .../playwright-core/src/client/browserType.ts | 8 ++++++- tests/library/browsertype-connect.spec.ts | 23 +++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/packages/playwright-core/src/client/browserType.ts b/packages/playwright-core/src/client/browserType.ts index 9df049a641..06672cc64e 100644 --- a/packages/playwright-core/src/client/browserType.ts +++ b/packages/playwright-core/src/client/browserType.ts @@ -151,8 +151,14 @@ export class BrowserType extends ChannelOwner imple page._onClose(); context._onClose(); } - browser?._didClose(); connection.close(reason || closeError); + // Give a chance to any API call promises to reject upon page/context closure. + // This happens naturally when we receive page.onClose and browser.onClose from the server + // in separate tasks. However, upon pipe closure we used to dispatch them all synchronously + // here and promises did not have a chance to reject. + // The order of rejects vs closure is a part of the API contract and our test runner + // relies on it to attribute rejections to the right test. + setTimeout(() => browser?._didClose(), 0); }; pipe.on('closed', params => onPipeClosed(params.reason)); connection.onmessage = message => this._wrapApiCall(() => pipe.send({ message }).catch(() => onPipeClosed()), /* isInternal */ true); diff --git a/tests/library/browsertype-connect.spec.ts b/tests/library/browsertype-connect.spec.ts index a78814d326..4a3cdb1efa 100644 --- a/tests/library/browsertype-connect.spec.ts +++ b/tests/library/browsertype-connect.spec.ts @@ -408,6 +408,29 @@ for (const kind of ['launchServer', 'run-server'] as const) { } }); + test('should reject waitForEvent before browser.close finishes', async ({ connect, startRemoteServer, server }) => { + const remoteServer = await startRemoteServer(kind); + const browser = await connect(remoteServer.wsEndpoint()); + const newPage = await browser.newPage(); + let rejected = false; + const promise = newPage.waitForEvent('download').catch(() => rejected = true); + await browser.close(); + expect(rejected).toBe(true); + await promise; + }); + + test('should reject waitForEvent before browser.onDisconnect fires', async ({ connect, startRemoteServer, server }) => { + const remoteServer = await startRemoteServer(kind); + const browser = await connect(remoteServer.wsEndpoint()); + const newPage = await browser.newPage(); + const log: string[] = []; + const promise = newPage.waitForEvent('download').catch(() => log.push('rejected')); + browser.on('disconnected', () => log.push('disconnected')); + await remoteServer.close(); + await promise; + await expect.poll(() => log).toEqual(['rejected', 'disconnected']); + }); + test('should respect selectors', async ({ playwright, connect, startRemoteServer }) => { const remoteServer = await startRemoteServer(kind); From a966abfd31c22a1f34157ffb335952e8dbbe6615 Mon Sep 17 00:00:00 2001 From: Max Schmitt Date: Thu, 25 Jul 2024 20:22:51 +0200 Subject: [PATCH 12/20] test: unflake happy-eyeballs tests (#31861) --- tests/library/browsercontext-fetch-happy-eyeballs.spec.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/library/browsercontext-fetch-happy-eyeballs.spec.ts b/tests/library/browsercontext-fetch-happy-eyeballs.spec.ts index c37859b146..e9de33bcfb 100644 --- a/tests/library/browsercontext-fetch-happy-eyeballs.spec.ts +++ b/tests/library/browsercontext-fetch-happy-eyeballs.spec.ts @@ -35,8 +35,12 @@ const __testHookLookup = (hostname: string): LookupAddress[] => { let interceptedHostnameLookup: string | undefined; -it.beforeEach(() => { +it.beforeEach(({ server }) => { interceptedHostnameLookup = undefined; + // Force a new connection every time, so that we can intercept the hostname lookup. + server.setExtraHeaders('/simple.json', { + 'Connection': 'close', + }); }); it('get should work', async ({ context, server }) => { From a41cebc1c9d362ac352d81e8d210a1ff85a2a6e3 Mon Sep 17 00:00:00 2001 From: Dmitry Gozman Date: Thu, 25 Jul 2024 11:23:43 -0700 Subject: [PATCH 13/20] feat(ui mode): introduce Testing Options and Settings (#31841) Testing Options control tests, while Settings are UI mode settings. Screenshot 2024-07-25 at 10 54 22 AM These sections are separately expandable, collapsed by default. Screenshot 2024-07-24 at 2 06 25 PM References #31520. --------- Signed-off-by: Simon Knott Co-authored-by: Simon Knott --- packages/trace-viewer/src/ui/settingsView.css | 11 ++- packages/trace-viewer/src/ui/settingsView.tsx | 10 +-- .../trace-viewer/src/ui/uiModeTraceView.tsx | 5 +- packages/trace-viewer/src/ui/uiModeView.css | 9 +++ packages/trace-viewer/src/ui/uiModeView.tsx | 70 ++++++++++++++-- packages/trace-viewer/src/ui/workbench.tsx | 81 ++++++++++--------- packages/web/src/components/toolbar.tsx | 8 +- packages/web/src/theme.ts | 13 ++- packages/web/src/uiUtils.ts | 14 +--- .../ui-mode-test-output.spec.ts | 3 +- 10 files changed, 155 insertions(+), 69 deletions(-) diff --git a/packages/trace-viewer/src/ui/settingsView.css b/packages/trace-viewer/src/ui/settingsView.css index cc41911066..3ac8597e35 100644 --- a/packages/trace-viewer/src/ui/settingsView.css +++ b/packages/trace-viewer/src/ui/settingsView.css @@ -16,13 +16,22 @@ .settings-view { flex: none; + margin-top: 4px; } .settings-view .setting label { display: flex; flex-direction: row; align-items: center; - margin: 6px 2px; + margin: 4px 2px; +} + +.settings-view .setting:first-of-type label { + margin-top: 2px; +} + +.settings-view .setting:last-of-type label { + margin-bottom: 2px; } .settings-view .setting input { diff --git a/packages/trace-viewer/src/ui/settingsView.tsx b/packages/trace-viewer/src/ui/settingsView.tsx index 5f803d229f..57c058c248 100644 --- a/packages/trace-viewer/src/ui/settingsView.tsx +++ b/packages/trace-viewer/src/ui/settingsView.tsx @@ -22,13 +22,11 @@ export const SettingsView: React.FunctionComponent<{ settings: Setting[], }> = ({ settings }) => { return
- {settings.map(setting => { - return
+ {settings.map(([value, set, title]) => { + return
; })} diff --git a/packages/trace-viewer/src/ui/uiModeTraceView.tsx b/packages/trace-viewer/src/ui/uiModeTraceView.tsx index 86fd3fbd8c..d26f0c3473 100644 --- a/packages/trace-viewer/src/ui/uiModeTraceView.tsx +++ b/packages/trace-viewer/src/ui/uiModeTraceView.tsx @@ -25,11 +25,13 @@ import type { ContextEntry } from '../entries'; import type { SourceLocation } from './modelUtil'; import { idForAction, MultiTraceModel } from './modelUtil'; import { Workbench } from './workbench'; +import { type Setting } from '@web/uiUtils'; export const TraceView: React.FC<{ + showRouteActionsSetting: Setting, item: { treeItem?: TreeItem, testFile?: SourceLocation, testCase?: reporterTypes.TestCase }, rootDir?: string, -}> = ({ item, rootDir }) => { +}> = ({ showRouteActionsSetting, item, rootDir }) => { const [model, setModel] = React.useState<{ model: MultiTraceModel, isLive: boolean } | undefined>(); const [counter, setCounter] = React.useState(0); const pollTimer = React.useRef(null); @@ -87,6 +89,7 @@ export const TraceView: React.FC<{ return .settings-toolbar { + border-top: 1px solid var(--vscode-panel-border); + cursor: pointer; +} + +.ui-mode-sidebar > .settings-view { + margin: 0 0 3px 23px; +} + .ui-mode-sidebar input[type=search] { flex: auto; } diff --git a/packages/trace-viewer/src/ui/uiModeView.tsx b/packages/trace-viewer/src/ui/uiModeView.tsx index 3e0ad5c65b..5bff9543aa 100644 --- a/packages/trace-viewer/src/ui/uiModeView.tsx +++ b/packages/trace-viewer/src/ui/uiModeView.tsx @@ -29,7 +29,7 @@ import { ToolbarButton } from '@web/components/toolbarButton'; import { Toolbar } from '@web/components/toolbar'; import type { XtermDataSource } from '@web/components/xtermWrapper'; import { XtermWrapper } from '@web/components/xtermWrapper'; -import { toggleTheme } from '@web/theme'; +import { useDarkModeSetting } from '@web/theme'; import { settings, useSetting } from '@web/uiUtils'; import { statusEx, TestTree } from '@testIsomorphic/testTree'; import type { TreeItem } from '@testIsomorphic/testTree'; @@ -39,6 +39,7 @@ import type { TestModel } from './uiModeModel'; import { FiltersView } from './uiModeFiltersView'; import { TestListView } from './uiModeTestListView'; import { TraceView } from './uiModeTraceView'; +import { SettingsView } from './settingsView'; let xtermSize = { cols: 80, rows: 24 }; const xtermDataSource: XtermDataSource = { @@ -93,6 +94,37 @@ export const UIModeView: React.FC<{}> = ({ const [isDisconnected, setIsDisconnected] = React.useState(false); const [hasBrowsers, setHasBrowsers] = React.useState(true); const [testServerConnection, setTestServerConnection] = React.useState(); + const [settingsVisible, setSettingsVisible] = React.useState(false); + const [testingOptionsVisible, setTestingOptionsVisible] = React.useState(false); + + const [runWorkers, setRunWorkers] = React.useState(queryParams.workers); + const singleWorkerSetting = React.useMemo(() => { + return [ + runWorkers === '1', + (value: boolean) => { + // When started with `--workers=1`, the setting allows to undo that. + // Otherwise, fallback to the cli `--workers=X` argument. + setRunWorkers(value ? '1' : (queryParams.workers === '1' ? undefined : queryParams.workers)); + }, + 'Single worker', + ] as const; + }, [runWorkers, setRunWorkers]); + + const [runHeaded, setRunHeaded] = React.useState(queryParams.headed); + const showBrowserSetting = React.useMemo(() => [runHeaded, setRunHeaded, 'Show browser'] as const, [runHeaded, setRunHeaded]); + + const [runUpdateSnapshots, setRunUpdateSnapshots] = React.useState(queryParams.updateSnapshots); + const updateSnapshotsSetting = React.useMemo(() => { + return [ + runUpdateSnapshots === 'all', + (value: boolean) => setRunUpdateSnapshots(value ? 'all' : 'missing'), + 'Update snapshots', + ] as const; + }, [runUpdateSnapshots, setRunUpdateSnapshots]); + + const [, , showRouteActionsSetting] = useSetting('show-route-actions', true, 'Show route actions'); + + const darkModeSetting = useDarkModeSetting(); const inputRef = React.useRef(null); @@ -284,11 +316,11 @@ export const UIModeView: React.FC<{}> = ({ grepInvert: queryParams.grepInvert, testIds: [...testIds], projects: [...projectFilters].filter(([_, v]) => v).map(([p]) => p), - workers: queryParams.workers, + workers: runWorkers, timeout: queryParams.timeout, - headed: queryParams.headed, + headed: runHeaded, outputDir: queryParams.outputDir, - updateSnapshots: queryParams.updateSnapshots, + updateSnapshots: runUpdateSnapshots, reporters: queryParams.reporters, trace: 'on', }); @@ -300,7 +332,7 @@ export const UIModeView: React.FC<{}> = ({ setTestModel({ ...testModel }); setRunningState(undefined); }); - }, [projectFilters, runningState, testModel, testServerConnection]); + }, [projectFilters, runningState, testModel, testServerConnection, runWorkers, runHeaded, runUpdateSnapshots]); // Watch implementation. React.useEffect(() => { @@ -403,14 +435,13 @@ export const UIModeView: React.FC<{}> = ({
- +
Playwright logo
Playwright
- toggleTheme()} /> reloadTests()} disabled={isRunningTest || isLoading}> { setIsShowingOutput(!isShowingOutput); }} /> {!hasBrowsers && } @@ -457,6 +488,31 @@ export const UIModeView: React.FC<{}> = ({ requestedCollapseAllCount={collapseAllCount} setFilterText={setFilterText} /> + setTestingOptionsVisible(!testingOptionsVisible)}> + +
Testing Options
+
+ {testingOptionsVisible && } + setSettingsVisible(!settingsVisible)}> + +
Settings
+
+ {settingsVisible && }
; diff --git a/packages/trace-viewer/src/ui/workbench.tsx b/packages/trace-viewer/src/ui/workbench.tsx index 0a5775bfbc..2755262045 100644 --- a/packages/trace-viewer/src/ui/workbench.tsx +++ b/packages/trace-viewer/src/ui/workbench.tsx @@ -36,7 +36,7 @@ import { AttachmentsTab } from './attachmentsTab'; import type { Boundaries } from '../geometry'; import { InspectorTab } from './inspectorTab'; import { ToolbarButton } from '@web/components/toolbarButton'; -import { useSetting, msToString } from '@web/uiUtils'; +import { useSetting, msToString, type Setting } from '@web/uiUtils'; import type { Entry } from '@trace/har'; import './workbench.css'; import { testStatusIcon, testStatusText } from './testUtils'; @@ -53,8 +53,9 @@ export const Workbench: React.FunctionComponent<{ isLive?: boolean, status?: UITestStatus, inert?: boolean, + showRouteActionsSetting?: Setting, openPage?: (url: string, target?: string) => Window | any, -}> = ({ model, showSourcesFirst, rootDir, fallbackLocation, initialSelection, onSelectionChanged, isLive, status, inert, openPage }) => { +}> = ({ showRouteActionsSetting, model, showSourcesFirst, rootDir, fallbackLocation, initialSelection, onSelectionChanged, isLive, status, inert, openPage }) => { const [selectedAction, setSelectedActionImpl] = React.useState(undefined); const [revealedStack, setRevealedStack] = React.useState(undefined); const [highlightedAction, setHighlightedAction] = React.useState(); @@ -67,7 +68,11 @@ export const Workbench: React.FunctionComponent<{ const activeAction = model ? highlightedAction || selectedAction : undefined; const [selectedTime, setSelectedTime] = React.useState(); const [sidebarLocation, setSidebarLocation] = useSetting<'bottom' | 'right'>('propertiesSidebarLocation', 'bottom'); - const [showRouteActions, , showRouteActionsSetting] = useSetting('show-route-actions', true, 'Show route actions'); + const [, , showRouteActionsSettingInternal] = useSetting(showRouteActionsSetting ? undefined : 'show-route-actions', true, 'Show route actions'); + + const showSettings = !showRouteActionsSetting; + showRouteActionsSetting ||= showRouteActionsSettingInternal; + const showRouteActions = showRouteActionsSetting[0]; const filteredActions = React.useMemo(() => { return (model?.actions || []).filter(action => showRouteActions || action.class !== 'Route'); @@ -229,6 +234,40 @@ export const Workbench: React.FunctionComponent<{ else if (model && model.wallTime) time = Date.now() - model.wallTime; + const actionsTab: TabbedPaneTabModel = { + id: 'actions', + title: 'Actions', + component:
+ {status &&
+ +
{testStatusText(status)}
+
+
{time ? msToString(time) : ''}
+
} + selectPropertiesTab('console')} + isLive={isLive} + /> +
+ }; + const metadataTab: TabbedPaneTabModel = { + id: 'metadata', + title: 'Metadata', + component: + }; + const settingsTab: TabbedPaneTabModel = { + id: 'settings', + title: 'Settings', + component: , + }; + return
- {status &&
- -
{testStatusText(status)}
-
-
{time ? msToString(time) : ''}
-
} - selectPropertiesTab('console')} - isLive={isLive} - /> -
- }, - { - id: 'metadata', - title: 'Metadata', - component: - }, - { - id: 'settings', - title: 'Settings', - component: , - } - ]} + tabs={showSettings ? [actionsTab, metadataTab, settingsTab] : [actionsTab, metadataTab]} selectedTab={selectedNavigatorTab} setSelectedTab={setSelectedNavigatorTab} /> diff --git a/packages/web/src/components/toolbar.tsx b/packages/web/src/components/toolbar.tsx index 5e11de75f7..023fad0232 100644 --- a/packages/web/src/components/toolbar.tsx +++ b/packages/web/src/components/toolbar.tsx @@ -20,12 +20,16 @@ import * as React from 'react'; type ToolbarProps = { noShadow?: boolean; noMinHeight?: boolean; + className?: string; + onClick?: (e: React.MouseEvent) => void; }; export const Toolbar: React.FC> = ({ noShadow, children, - noMinHeight + noMinHeight, + className, + onClick, }) => { - return
{children}
; + return
{children}
; }; diff --git a/packages/web/src/theme.ts b/packages/web/src/theme.ts index 44f663f9e6..5ea2f65566 100644 --- a/packages/web/src/theme.ts +++ b/packages/web/src/theme.ts @@ -14,7 +14,8 @@ * limitations under the License. */ -import { settings } from './uiUtils'; +import React from 'react'; +import { type Setting, settings } from './uiUtils'; export function applyTheme() { if ((document as any).playwrightThemeInitialized) @@ -64,3 +65,13 @@ export function removeThemeListener(listener: (theme: Theme) => void) { export function currentTheme(): Theme { return document.body.classList.contains('dark-mode') ? 'dark-mode' : 'light-mode'; } + +export function useDarkModeSetting() { + const [theme, setTheme] = React.useState(currentTheme() === 'dark-mode'); + return [theme, (value: boolean) => { + const current = currentTheme() === 'dark-mode'; + if (current !== value) + toggleTheme(); + setTheme(value); + }, 'Dark mode'] as Setting; +} diff --git a/packages/web/src/uiUtils.ts b/packages/web/src/uiUtils.ts index de28a807c1..9901a24bde 100644 --- a/packages/web/src/uiUtils.ts +++ b/packages/web/src/uiUtils.ts @@ -139,12 +139,7 @@ export function copy(text: string) { textArea.remove(); } -export type Setting = { - value: T; - set: (value: T) => void; - name: string; - title: string; -}; +export type Setting = readonly [T, (value: T) => void, string]; export function useSetting(name: string | undefined, defaultValue: S, title?: string): [S, React.Dispatch>, Setting] { if (name) @@ -155,12 +150,7 @@ export function useSetting(name: string | undefined, defaultValue: S, title?: settings.setObject(name, value); setValue(value); }, [name, setValue]); - const setting = { - value, - set: setValueWrapper, - name: name || '', - title: title || name || '', - }; + const setting = [value, setValueWrapper, title || name || ''] as Setting; return [value, setValueWrapper, setting]; } diff --git a/tests/playwright-test/ui-mode-test-output.spec.ts b/tests/playwright-test/ui-mode-test-output.spec.ts index b8a6cfddd1..b10c02d08a 100644 --- a/tests/playwright-test/ui-mode-test-output.spec.ts +++ b/tests/playwright-test/ui-mode-test-output.spec.ts @@ -45,7 +45,8 @@ test('should work after theme switch', async ({ runUITest, writeFiles }) => { await page.getByTitle('Run all').click(); await expect(page.getByTestId('output')).toContainText(`Hello world 1`); - await page.getByTitle('Toggle color mode').click(); + await page.getByText('Settings', { exact: true }).click(); + await page.getByLabel('Dark mode').click(); await writeFiles({ 'a.test.ts': ` import { test, expect } from '@playwright/test'; From a02ed38e604d6c8517dda148fcf63ee44f5c9ce4 Mon Sep 17 00:00:00 2001 From: Max Schmitt Date: Thu, 25 Jul 2024 22:36:25 +0200 Subject: [PATCH 14/20] chore: reduce file reads in client-certificates internal TLS server (#31865) --- .../server/socksClientCertificatesInterceptor.ts | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/packages/playwright-core/src/server/socksClientCertificatesInterceptor.ts b/packages/playwright-core/src/server/socksClientCertificatesInterceptor.ts index d5a71c73e6..2c4268524b 100644 --- a/packages/playwright-core/src/server/socksClientCertificatesInterceptor.ts +++ b/packages/playwright-core/src/server/socksClientCertificatesInterceptor.ts @@ -27,6 +27,16 @@ import { SocksProxy } from '../common/socksProxy'; import type * as channels from '@protocol/channels'; import { debugLogger } from '../utils/debugLogger'; +let dummyServerTlsOptions: tls.TlsOptions | undefined = undefined; +function loadDummyServerCertsIfNeeded() { + if (dummyServerTlsOptions) + return; + dummyServerTlsOptions = { + key: fs.readFileSync(path.join(__dirname, '../../bin/socks-certs/key.pem')), + cert: fs.readFileSync(path.join(__dirname, '../../bin/socks-certs/cert.pem')), + }; +} + class ALPNCache { private _cache = new Map>(); @@ -122,8 +132,7 @@ class SocksProxyConnection { this.socksProxy.alpnCache.get(rewriteToLocalhostIfNeeded(this.host), this.port, alpnProtocolChosenByServer => { debugLogger.log('client-certificates', `Proxy->Target ${this.host}:${this.port} chooses ALPN ${alpnProtocolChosenByServer}`); const dummyServer = tls.createServer({ - key: fs.readFileSync(path.join(__dirname, '../../bin/socks-certs/key.pem')), - cert: fs.readFileSync(path.join(__dirname, '../../bin/socks-certs/cert.pem')), + ...dummyServerTlsOptions, ALPNProtocols: alpnProtocolChosenByServer === 'h2' ? ['h2', 'http/1.1'] : ['http/1.1'], }); this.internal?.on('close', () => dummyServer.close()); @@ -211,6 +220,7 @@ export class ClientCertificatesProxy { this._connections.get(payload.uid)?.onClose(); this._connections.delete(payload.uid); }); + loadDummyServerCertsIfNeeded(); } public async listen(): Promise { From 81b3c0c4020ef1766c4b39932a1b8df215742c9e Mon Sep 17 00:00:00 2001 From: Max Schmitt Date: Fri, 26 Jul 2024 11:04:38 +0200 Subject: [PATCH 15/20] fix(client-certificates): include socks-certs in npm package (#31872) --- packages/playwright-core/.npmignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/playwright-core/.npmignore b/packages/playwright-core/.npmignore index bebc52f703..c8c43feeb1 100644 --- a/packages/playwright-core/.npmignore +++ b/packages/playwright-core/.npmignore @@ -15,7 +15,7 @@ # See src/server/injected/README.md. lib/**/injected/ # Include all binaries that we ship with the package. -!bin/* +!bin/**/* # Include FFMPEG !third_party/ffmpeg/* # Include generated types and entrypoint. From 335d31bf6596a511959557ed2d8299141d4523d0 Mon Sep 17 00:00:00 2001 From: Max Schmitt Date: Fri, 26 Jul 2024 11:04:51 +0200 Subject: [PATCH 16/20] devops: remove GHA todo in primary workflow for itest (#31871) This TODO got added during our GHA refactoring a while ago, where I thought it might make sense to run our itests in `bash`. We didn't do it before the refactoring either. It seems good to keep them running in `pwsh` instead, so lets just remove the TODO. Investigation notes: Running in `bash` on Windows via `Git Bash` seems like doing a lot of magic, especially with path handling. Things [like](https://github.com/microsoft/playwright/blob/a02ed38e604d6c8517dda148fcf63ee44f5c9ce4/tests/installation/registry.ts#L143) this break then, since `tar` even when using `Git Bash` [doesn't accept a Windows path](https://sourceforge.net/p/mingw/mailman/mingw-users/thread/54CE104A.7060108@hccnet.nl/). Signed-off-by: Max Schmitt --- .github/workflows/tests_primary.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/tests_primary.yml b/.github/workflows/tests_primary.yml index 0316908da9..02847957c4 100644 --- a/.github/workflows/tests_primary.yml +++ b/.github/workflows/tests_primary.yml @@ -219,7 +219,6 @@ jobs: with: command: npm run itest bot-name: "package-installations-${{ matrix.os }}" - # TODO: figure out why itest fails with 'bash' on Windows. shell: ${{ matrix.os == 'windows-latest' && 'pwsh' || 'bash' }} flakiness-client-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_CLIENT_ID }} flakiness-tenant-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_TENANT_ID }} From 09581b615dc66185059338d6c7432170dad4a27a Mon Sep 17 00:00:00 2001 From: Max Schmitt Date: Fri, 26 Jul 2024 11:28:45 +0200 Subject: [PATCH 17/20] fix(client-certificates): return target errors on response when using http2 (#31867) --- .../socksClientCertificatesInterceptor.ts | 39 +++++++++++++++---- tests/library/client-certificates.spec.ts | 29 ++++++++++++-- 2 files changed, 56 insertions(+), 12 deletions(-) diff --git a/packages/playwright-core/src/server/socksClientCertificatesInterceptor.ts b/packages/playwright-core/src/server/socksClientCertificatesInterceptor.ts index 2c4268524b..f16a60fe00 100644 --- a/packages/playwright-core/src/server/socksClientCertificatesInterceptor.ts +++ b/packages/playwright-core/src/server/socksClientCertificatesInterceptor.ts @@ -16,6 +16,7 @@ import net from 'net'; import path from 'path'; +import http2 from 'http2'; import type https from 'https'; import fs from 'fs'; import tls from 'tls'; @@ -80,17 +81,19 @@ class SocksProxyConnection { target!: net.Socket; // In case of http, we just pipe data to the target socket and they are |undefined|. internal: stream.Duplex | undefined; + private _targetCloseEventListener: () => void; constructor(socksProxy: ClientCertificatesProxy, uid: string, host: string, port: number) { this.socksProxy = socksProxy; this.uid = uid; this.host = host; this.port = port; + this._targetCloseEventListener = () => this.socksProxy._socksProxy.sendSocketEnd({ uid: this.uid }); } async connect() { this.target = await createSocket(rewriteToLocalhostIfNeeded(this.host), this.port); - this.target.on('close', () => this.socksProxy._socksProxy.sendSocketEnd({ uid: this.uid })); + this.target.on('close', this._targetCloseEventListener); this.target.on('error', error => this.socksProxy._socksProxy.sendSocketError({ uid: this.uid, error: error.message })); this.socksProxy._socksProxy.socketConnected({ uid: this.uid, @@ -139,7 +142,6 @@ class SocksProxyConnection { dummyServer.emit('connection', this.internal); dummyServer.on('secureConnection', internalTLS => { debugLogger.log('client-certificates', `Browser->Proxy ${this.host}:${this.port} chooses ALPN ${internalTLS.alpnProtocol}`); - internalTLS.on('close', () => this.socksProxy._socksProxy.sendSocketEnd({ uid: this.uid })); const tlsOptions: tls.ConnectionOptions = { socket: this.target, host: this.host, @@ -154,8 +156,10 @@ class SocksProxyConnection { tlsOptions.ca = [fs.readFileSync(process.env.PWTEST_UNSUPPORTED_CUSTOM_CA)]; const targetTLS = tls.connect(tlsOptions); - internalTLS.pipe(targetTLS); - targetTLS.pipe(internalTLS); + targetTLS.on('secureConnect', () => { + internalTLS.pipe(targetTLS); + targetTLS.pipe(internalTLS); + }); // Handle close and errors const closeBothSockets = () => { @@ -169,11 +173,30 @@ class SocksProxyConnection { internalTLS.on('error', () => closeBothSockets()); targetTLS.on('error', error => { debugLogger.log('client-certificates', `error when connecting to target: ${error.message}`); + const responseBody = 'Playwright client-certificate error: ' + error.message; if (internalTLS?.alpnProtocol === 'h2') { - // https://github.com/nodejs/node/issues/46152 - // TODO: http2.performServerHandshake does not work here for some reason. + // This method is available only in Node.js 20+ + if ('performServerHandshake' in http2) { + // In case of an 'error' event on the target connection, we still need to perform the http2 handshake on the browser side. + // This is an async operation, so we need to intercept the close event to prevent the socket from being closed too early. + this.target.removeListener('close', this._targetCloseEventListener); + // @ts-expect-error + const session: http2.ServerHttp2Session = http2.performServerHandshake(internalTLS); + session.on('stream', (stream: http2.ServerHttp2Stream) => { + stream.respond({ + 'content-type': 'text/html', + [http2.constants.HTTP2_HEADER_STATUS]: 503, + }); + stream.end(responseBody, () => { + session.close(); + closeBothSockets(); + }); + stream.on('error', () => closeBothSockets()); + }); + } else { + closeBothSockets(); + } } else { - const responseBody = 'Playwright client-certificate error: ' + error.message; internalTLS.end([ 'HTTP/1.1 503 Internal Server Error', 'Content-Type: text/html; charset=utf-8', @@ -181,8 +204,8 @@ class SocksProxyConnection { '\r\n', responseBody, ].join('\r\n')); + closeBothSockets(); } - closeBothSockets(); }); }); }); diff --git a/tests/library/client-certificates.spec.ts b/tests/library/client-certificates.spec.ts index ff60010d5b..9f055a678b 100644 --- a/tests/library/client-certificates.spec.ts +++ b/tests/library/client-certificates.spec.ts @@ -25,6 +25,7 @@ const { createHttpsServer, createHttp2Server } = require('../../packages/playwri type TestOptions = { startCCServer(options?: { http2?: boolean; + enableHTTP1FallbackWhenUsingHttp2?: boolean; useFakeLocalhost?: boolean; }): Promise, }; @@ -42,7 +43,7 @@ const test = base.extend({ ], requestCert: true, rejectUnauthorized: false, - allowHTTP1: true, + allowHTTP1: options?.enableHTTP1FallbackWhenUsingHttp2, }, (req: (http2.Http2ServerRequest | http.IncomingMessage), res: http2.Http2ServerResponse | http.ServerResponse) => { const tlsSocket = req.socket as import('tls').TLSSocket; const parts: { key: string, value: any }[] = []; @@ -279,7 +280,8 @@ test.describe('browser', () => { test('support http2', async ({ browser, startCCServer, asset, browserName }) => { test.skip(browserName === 'webkit' && process.platform === 'darwin', 'WebKit on macOS doesn\n proxy localhost'); - const serverURL = await startCCServer({ http2: true }); + const enableHTTP1FallbackWhenUsingHttp2 = browserName === 'webkit' && process.platform === 'linux'; + const serverURL = await startCCServer({ http2: true, enableHTTP1FallbackWhenUsingHttp2 }); const page = await browser.newPage({ clientCertificates: [{ origin: new URL(serverURL).origin, @@ -289,7 +291,7 @@ test.describe('browser', () => { }); // TODO: We should investigate why http2 is not supported in WebKit on Linux. // https://bugs.webkit.org/show_bug.cgi?id=276990 - const expectedProtocol = browserName === 'webkit' && process.platform === 'linux' ? 'http/1.1' : 'h2'; + const expectedProtocol = enableHTTP1FallbackWhenUsingHttp2 ? 'http/1.1' : 'h2'; { await page.goto(serverURL.replace('localhost', 'local.playwright')); await expect(page.getByTestId('message')).toHaveText('Sorry, but you need to provide a client certificate to continue.'); @@ -306,7 +308,7 @@ test.describe('browser', () => { test('support http2 if the browser only supports http1.1', async ({ browserType, browserName, startCCServer, asset }) => { test.skip(browserName !== 'chromium'); - const serverURL = await startCCServer({ http2: true }); + const serverURL = await startCCServer({ http2: true, enableHTTP1FallbackWhenUsingHttp2: true }); const browser = await browserType.launch({ args: ['--disable-http2'] }); const page = await browser.newPage({ clientCertificates: [{ @@ -328,6 +330,25 @@ test.describe('browser', () => { await browser.close(); }); + test('should return target connection errors when using http2', async ({ browser, startCCServer, asset, browserName }) => { + test.skip(browserName === 'webkit' && process.platform === 'darwin', 'WebKit on macOS doesn\n proxy localhost'); + test.fixme(browserName === 'webkit' && process.platform === 'linux', 'WebKit on Linux does not support http2 https://bugs.webkit.org/show_bug.cgi?id=276990'); + test.skip(+process.versions.node.split('.')[0] < 20, 'http2.performServerHandshake is not supported in older Node.js versions'); + + process.env.PWTEST_UNSUPPORTED_CUSTOM_CA = asset('empty.html'); + const serverURL = await startCCServer({ http2: true }); + const page = await browser.newPage({ + clientCertificates: [{ + origin: 'https://just-there-that-the-client-certificates-proxy-server-is-getting-launched.com', + certPath: asset('client-certificates/client/trusted/cert.pem'), + keyPath: asset('client-certificates/client/trusted/key.pem'), + }], + }); + await page.goto(serverURL); + await expect(page.getByText('Playwright client-certificate error: self-signed certificate')).toBeVisible(); + await page.close(); + }); + test.describe('persistentContext', () => { test('validate input', async ({ launchPersistent }) => { test.slow(); From 47e4e45bc2880f8d5e002565f6861da1d907e65e Mon Sep 17 00:00:00 2001 From: Max Schmitt Date: Fri, 26 Jul 2024 11:32:51 +0200 Subject: [PATCH 18/20] chore: update WebKit version to 18.0 (#31873) --- README.md | 4 +- packages/playwright-core/browsers.json | 2 +- .../src/server/deviceDescriptorsSource.json | 154 +++++++++--------- .../src/server/webkit/wkBrowser.ts | 4 +- 4 files changed, 82 insertions(+), 82 deletions(-) diff --git a/README.md b/README.md index 9dcb0ae885..3e2add10dc 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # 🎭 Playwright -[![npm version](https://img.shields.io/npm/v/playwright.svg)](https://www.npmjs.com/package/playwright) [![Chromium version](https://img.shields.io/badge/chromium-128.0.6613.7-blue.svg?logo=google-chrome)](https://www.chromium.org/Home) [![Firefox version](https://img.shields.io/badge/firefox-128.0-blue.svg?logo=firefoxbrowser)](https://www.mozilla.org/en-US/firefox/new/) [![WebKit version](https://img.shields.io/badge/webkit-17.4-blue.svg?logo=safari)](https://webkit.org/) +[![npm version](https://img.shields.io/npm/v/playwright.svg)](https://www.npmjs.com/package/playwright) [![Chromium version](https://img.shields.io/badge/chromium-128.0.6613.7-blue.svg?logo=google-chrome)](https://www.chromium.org/Home) [![Firefox version](https://img.shields.io/badge/firefox-128.0-blue.svg?logo=firefoxbrowser)](https://www.mozilla.org/en-US/firefox/new/) [![WebKit version](https://img.shields.io/badge/webkit-18.0-blue.svg?logo=safari)](https://webkit.org/) ## [Documentation](https://playwright.dev) | [API reference](https://playwright.dev/docs/api/class-playwright) @@ -9,7 +9,7 @@ Playwright is a framework for Web Testing and Automation. It allows testing [Chr | | Linux | macOS | Windows | | :--- | :---: | :---: | :---: | | Chromium 128.0.6613.7 | :white_check_mark: | :white_check_mark: | :white_check_mark: | -| WebKit 17.4 | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| WebKit 18.0 | :white_check_mark: | :white_check_mark: | :white_check_mark: | | Firefox 128.0 | :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. diff --git a/packages/playwright-core/browsers.json b/packages/playwright-core/browsers.json index 1b0a4d3ae7..b372eecd71 100644 --- a/packages/playwright-core/browsers.json +++ b/packages/playwright-core/browsers.json @@ -37,7 +37,7 @@ "mac12": "2009", "mac12-arm64": "2009" }, - "browserVersion": "17.4" + "browserVersion": "18.0" }, { "name": "ffmpeg", diff --git a/packages/playwright-core/src/server/deviceDescriptorsSource.json b/packages/playwright-core/src/server/deviceDescriptorsSource.json index abcc0ba5ad..2209498e32 100644 --- a/packages/playwright-core/src/server/deviceDescriptorsSource.json +++ b/packages/playwright-core/src/server/deviceDescriptorsSource.json @@ -1,6 +1,6 @@ { "Blackberry PlayBook": { - "userAgent": "Mozilla/5.0 (PlayBook; U; RIM Tablet OS 2.1.0; en-US) AppleWebKit/536.2+ (KHTML like Gecko) Version/17.4 Safari/536.2+", + "userAgent": "Mozilla/5.0 (PlayBook; U; RIM Tablet OS 2.1.0; en-US) AppleWebKit/536.2+ (KHTML like Gecko) Version/18.0 Safari/536.2+", "viewport": { "width": 600, "height": 1024 @@ -11,7 +11,7 @@ "defaultBrowserType": "webkit" }, "Blackberry PlayBook landscape": { - "userAgent": "Mozilla/5.0 (PlayBook; U; RIM Tablet OS 2.1.0; en-US) AppleWebKit/536.2+ (KHTML like Gecko) Version/17.4 Safari/536.2+", + "userAgent": "Mozilla/5.0 (PlayBook; U; RIM Tablet OS 2.1.0; en-US) AppleWebKit/536.2+ (KHTML like Gecko) Version/18.0 Safari/536.2+", "viewport": { "width": 1024, "height": 600 @@ -22,7 +22,7 @@ "defaultBrowserType": "webkit" }, "BlackBerry Z30": { - "userAgent": "Mozilla/5.0 (BB10; Touch) AppleWebKit/537.10+ (KHTML, like Gecko) Version/17.4 Mobile Safari/537.10+", + "userAgent": "Mozilla/5.0 (BB10; Touch) AppleWebKit/537.10+ (KHTML, like Gecko) Version/18.0 Mobile Safari/537.10+", "viewport": { "width": 360, "height": 640 @@ -33,7 +33,7 @@ "defaultBrowserType": "webkit" }, "BlackBerry Z30 landscape": { - "userAgent": "Mozilla/5.0 (BB10; Touch) AppleWebKit/537.10+ (KHTML, like Gecko) Version/17.4 Mobile Safari/537.10+", + "userAgent": "Mozilla/5.0 (BB10; Touch) AppleWebKit/537.10+ (KHTML, like Gecko) Version/18.0 Mobile Safari/537.10+", "viewport": { "width": 640, "height": 360 @@ -44,7 +44,7 @@ "defaultBrowserType": "webkit" }, "Galaxy Note 3": { - "userAgent": "Mozilla/5.0 (Linux; U; Android 4.3; en-us; SM-N900T Build/JSS15J) AppleWebKit/534.30 (KHTML, like Gecko) Version/17.4 Mobile Safari/534.30", + "userAgent": "Mozilla/5.0 (Linux; U; Android 4.3; en-us; SM-N900T Build/JSS15J) AppleWebKit/534.30 (KHTML, like Gecko) Version/18.0 Mobile Safari/534.30", "viewport": { "width": 360, "height": 640 @@ -55,7 +55,7 @@ "defaultBrowserType": "webkit" }, "Galaxy Note 3 landscape": { - "userAgent": "Mozilla/5.0 (Linux; U; Android 4.3; en-us; SM-N900T Build/JSS15J) AppleWebKit/534.30 (KHTML, like Gecko) Version/17.4 Mobile Safari/534.30", + "userAgent": "Mozilla/5.0 (Linux; U; Android 4.3; en-us; SM-N900T Build/JSS15J) AppleWebKit/534.30 (KHTML, like Gecko) Version/18.0 Mobile Safari/534.30", "viewport": { "width": 640, "height": 360 @@ -66,7 +66,7 @@ "defaultBrowserType": "webkit" }, "Galaxy Note II": { - "userAgent": "Mozilla/5.0 (Linux; U; Android 4.1; en-us; GT-N7100 Build/JRO03C) AppleWebKit/534.30 (KHTML, like Gecko) Version/17.4 Mobile Safari/534.30", + "userAgent": "Mozilla/5.0 (Linux; U; Android 4.1; en-us; GT-N7100 Build/JRO03C) AppleWebKit/534.30 (KHTML, like Gecko) Version/18.0 Mobile Safari/534.30", "viewport": { "width": 360, "height": 640 @@ -77,7 +77,7 @@ "defaultBrowserType": "webkit" }, "Galaxy Note II landscape": { - "userAgent": "Mozilla/5.0 (Linux; U; Android 4.1; en-us; GT-N7100 Build/JRO03C) AppleWebKit/534.30 (KHTML, like Gecko) Version/17.4 Mobile Safari/534.30", + "userAgent": "Mozilla/5.0 (Linux; U; Android 4.1; en-us; GT-N7100 Build/JRO03C) AppleWebKit/534.30 (KHTML, like Gecko) Version/18.0 Mobile Safari/534.30", "viewport": { "width": 640, "height": 360 @@ -88,7 +88,7 @@ "defaultBrowserType": "webkit" }, "Galaxy S III": { - "userAgent": "Mozilla/5.0 (Linux; U; Android 4.0; en-us; GT-I9300 Build/IMM76D) AppleWebKit/534.30 (KHTML, like Gecko) Version/17.4 Mobile Safari/534.30", + "userAgent": "Mozilla/5.0 (Linux; U; Android 4.0; en-us; GT-I9300 Build/IMM76D) AppleWebKit/534.30 (KHTML, like Gecko) Version/18.0 Mobile Safari/534.30", "viewport": { "width": 360, "height": 640 @@ -99,7 +99,7 @@ "defaultBrowserType": "webkit" }, "Galaxy S III landscape": { - "userAgent": "Mozilla/5.0 (Linux; U; Android 4.0; en-us; GT-I9300 Build/IMM76D) AppleWebKit/534.30 (KHTML, like Gecko) Version/17.4 Mobile Safari/534.30", + "userAgent": "Mozilla/5.0 (Linux; U; Android 4.0; en-us; GT-I9300 Build/IMM76D) AppleWebKit/534.30 (KHTML, like Gecko) Version/18.0 Mobile Safari/534.30", "viewport": { "width": 640, "height": 360 @@ -198,7 +198,7 @@ "defaultBrowserType": "chromium" }, "iPad (gen 5)": { - "userAgent": "Mozilla/5.0 (iPad; CPU OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPad; CPU OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", "viewport": { "width": 768, "height": 1024 @@ -209,7 +209,7 @@ "defaultBrowserType": "webkit" }, "iPad (gen 5) landscape": { - "userAgent": "Mozilla/5.0 (iPad; CPU OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPad; CPU OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", "viewport": { "width": 1024, "height": 768 @@ -220,7 +220,7 @@ "defaultBrowserType": "webkit" }, "iPad (gen 6)": { - "userAgent": "Mozilla/5.0 (iPad; CPU OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPad; CPU OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", "viewport": { "width": 768, "height": 1024 @@ -231,7 +231,7 @@ "defaultBrowserType": "webkit" }, "iPad (gen 6) landscape": { - "userAgent": "Mozilla/5.0 (iPad; CPU OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPad; CPU OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", "viewport": { "width": 1024, "height": 768 @@ -242,7 +242,7 @@ "defaultBrowserType": "webkit" }, "iPad (gen 7)": { - "userAgent": "Mozilla/5.0 (iPad; CPU OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPad; CPU OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", "viewport": { "width": 810, "height": 1080 @@ -253,7 +253,7 @@ "defaultBrowserType": "webkit" }, "iPad (gen 7) landscape": { - "userAgent": "Mozilla/5.0 (iPad; CPU OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPad; CPU OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", "viewport": { "width": 1080, "height": 810 @@ -264,7 +264,7 @@ "defaultBrowserType": "webkit" }, "iPad Mini": { - "userAgent": "Mozilla/5.0 (iPad; CPU OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPad; CPU OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", "viewport": { "width": 768, "height": 1024 @@ -275,7 +275,7 @@ "defaultBrowserType": "webkit" }, "iPad Mini landscape": { - "userAgent": "Mozilla/5.0 (iPad; CPU OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPad; CPU OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", "viewport": { "width": 1024, "height": 768 @@ -286,7 +286,7 @@ "defaultBrowserType": "webkit" }, "iPad Pro 11": { - "userAgent": "Mozilla/5.0 (iPad; CPU OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPad; CPU OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", "viewport": { "width": 834, "height": 1194 @@ -297,7 +297,7 @@ "defaultBrowserType": "webkit" }, "iPad Pro 11 landscape": { - "userAgent": "Mozilla/5.0 (iPad; CPU OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPad; CPU OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", "viewport": { "width": 1194, "height": 834 @@ -308,7 +308,7 @@ "defaultBrowserType": "webkit" }, "iPhone 6": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/17.4 Mobile/15A372 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/18.0 Mobile/15A372 Safari/604.1", "viewport": { "width": 375, "height": 667 @@ -319,7 +319,7 @@ "defaultBrowserType": "webkit" }, "iPhone 6 landscape": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/17.4 Mobile/15A372 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/18.0 Mobile/15A372 Safari/604.1", "viewport": { "width": 667, "height": 375 @@ -330,7 +330,7 @@ "defaultBrowserType": "webkit" }, "iPhone 6 Plus": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/17.4 Mobile/15A372 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/18.0 Mobile/15A372 Safari/604.1", "viewport": { "width": 414, "height": 736 @@ -341,7 +341,7 @@ "defaultBrowserType": "webkit" }, "iPhone 6 Plus landscape": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/17.4 Mobile/15A372 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/18.0 Mobile/15A372 Safari/604.1", "viewport": { "width": 736, "height": 414 @@ -352,7 +352,7 @@ "defaultBrowserType": "webkit" }, "iPhone 7": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/17.4 Mobile/15A372 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/18.0 Mobile/15A372 Safari/604.1", "viewport": { "width": 375, "height": 667 @@ -363,7 +363,7 @@ "defaultBrowserType": "webkit" }, "iPhone 7 landscape": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/17.4 Mobile/15A372 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/18.0 Mobile/15A372 Safari/604.1", "viewport": { "width": 667, "height": 375 @@ -374,7 +374,7 @@ "defaultBrowserType": "webkit" }, "iPhone 7 Plus": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/17.4 Mobile/15A372 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/18.0 Mobile/15A372 Safari/604.1", "viewport": { "width": 414, "height": 736 @@ -385,7 +385,7 @@ "defaultBrowserType": "webkit" }, "iPhone 7 Plus landscape": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/17.4 Mobile/15A372 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/18.0 Mobile/15A372 Safari/604.1", "viewport": { "width": 736, "height": 414 @@ -396,7 +396,7 @@ "defaultBrowserType": "webkit" }, "iPhone 8": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/17.4 Mobile/15A372 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/18.0 Mobile/15A372 Safari/604.1", "viewport": { "width": 375, "height": 667 @@ -407,7 +407,7 @@ "defaultBrowserType": "webkit" }, "iPhone 8 landscape": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/17.4 Mobile/15A372 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/18.0 Mobile/15A372 Safari/604.1", "viewport": { "width": 667, "height": 375 @@ -418,7 +418,7 @@ "defaultBrowserType": "webkit" }, "iPhone 8 Plus": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/17.4 Mobile/15A372 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/18.0 Mobile/15A372 Safari/604.1", "viewport": { "width": 414, "height": 736 @@ -429,7 +429,7 @@ "defaultBrowserType": "webkit" }, "iPhone 8 Plus landscape": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/17.4 Mobile/15A372 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/18.0 Mobile/15A372 Safari/604.1", "viewport": { "width": 736, "height": 414 @@ -440,7 +440,7 @@ "defaultBrowserType": "webkit" }, "iPhone SE": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_1 like Mac OS X) AppleWebKit/603.1.30 (KHTML, like Gecko) Version/17.4 Mobile/14E304 Safari/602.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_1 like Mac OS X) AppleWebKit/603.1.30 (KHTML, like Gecko) Version/18.0 Mobile/14E304 Safari/602.1", "viewport": { "width": 320, "height": 568 @@ -451,7 +451,7 @@ "defaultBrowserType": "webkit" }, "iPhone SE landscape": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_1 like Mac OS X) AppleWebKit/603.1.30 (KHTML, like Gecko) Version/17.4 Mobile/14E304 Safari/602.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_1 like Mac OS X) AppleWebKit/603.1.30 (KHTML, like Gecko) Version/18.0 Mobile/14E304 Safari/602.1", "viewport": { "width": 568, "height": 320 @@ -462,7 +462,7 @@ "defaultBrowserType": "webkit" }, "iPhone X": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/17.4 Mobile/15A372 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/18.0 Mobile/15A372 Safari/604.1", "viewport": { "width": 375, "height": 812 @@ -473,7 +473,7 @@ "defaultBrowserType": "webkit" }, "iPhone X landscape": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/17.4 Mobile/15A372 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/18.0 Mobile/15A372 Safari/604.1", "viewport": { "width": 812, "height": 375 @@ -484,7 +484,7 @@ "defaultBrowserType": "webkit" }, "iPhone XR": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 12_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 12_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", "viewport": { "width": 414, "height": 896 @@ -495,7 +495,7 @@ "defaultBrowserType": "webkit" }, "iPhone XR landscape": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 12_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 12_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", "viewport": { "width": 896, "height": 414 @@ -506,7 +506,7 @@ "defaultBrowserType": "webkit" }, "iPhone 11": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", "screen": { "width": 414, "height": 896 @@ -521,7 +521,7 @@ "defaultBrowserType": "webkit" }, "iPhone 11 landscape": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", "screen": { "width": 414, "height": 896 @@ -536,7 +536,7 @@ "defaultBrowserType": "webkit" }, "iPhone 11 Pro": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", "screen": { "width": 375, "height": 812 @@ -551,7 +551,7 @@ "defaultBrowserType": "webkit" }, "iPhone 11 Pro landscape": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", "screen": { "width": 375, "height": 812 @@ -566,7 +566,7 @@ "defaultBrowserType": "webkit" }, "iPhone 11 Pro Max": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", "screen": { "width": 414, "height": 896 @@ -581,7 +581,7 @@ "defaultBrowserType": "webkit" }, "iPhone 11 Pro Max landscape": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", "screen": { "width": 414, "height": 896 @@ -596,7 +596,7 @@ "defaultBrowserType": "webkit" }, "iPhone 12": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", "screen": { "width": 390, "height": 844 @@ -611,7 +611,7 @@ "defaultBrowserType": "webkit" }, "iPhone 12 landscape": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", "screen": { "width": 390, "height": 844 @@ -626,7 +626,7 @@ "defaultBrowserType": "webkit" }, "iPhone 12 Pro": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", "screen": { "width": 390, "height": 844 @@ -641,7 +641,7 @@ "defaultBrowserType": "webkit" }, "iPhone 12 Pro landscape": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", "screen": { "width": 390, "height": 844 @@ -656,7 +656,7 @@ "defaultBrowserType": "webkit" }, "iPhone 12 Pro Max": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", "screen": { "width": 428, "height": 926 @@ -671,7 +671,7 @@ "defaultBrowserType": "webkit" }, "iPhone 12 Pro Max landscape": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", "screen": { "width": 428, "height": 926 @@ -686,7 +686,7 @@ "defaultBrowserType": "webkit" }, "iPhone 12 Mini": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", "screen": { "width": 375, "height": 812 @@ -701,7 +701,7 @@ "defaultBrowserType": "webkit" }, "iPhone 12 Mini landscape": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", "screen": { "width": 375, "height": 812 @@ -716,7 +716,7 @@ "defaultBrowserType": "webkit" }, "iPhone 13": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", "screen": { "width": 390, "height": 844 @@ -731,7 +731,7 @@ "defaultBrowserType": "webkit" }, "iPhone 13 landscape": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", "screen": { "width": 390, "height": 844 @@ -746,7 +746,7 @@ "defaultBrowserType": "webkit" }, "iPhone 13 Pro": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", "screen": { "width": 390, "height": 844 @@ -761,7 +761,7 @@ "defaultBrowserType": "webkit" }, "iPhone 13 Pro landscape": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", "screen": { "width": 390, "height": 844 @@ -776,7 +776,7 @@ "defaultBrowserType": "webkit" }, "iPhone 13 Pro Max": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", "screen": { "width": 428, "height": 926 @@ -791,7 +791,7 @@ "defaultBrowserType": "webkit" }, "iPhone 13 Pro Max landscape": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", "screen": { "width": 428, "height": 926 @@ -806,7 +806,7 @@ "defaultBrowserType": "webkit" }, "iPhone 13 Mini": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", "screen": { "width": 375, "height": 812 @@ -821,7 +821,7 @@ "defaultBrowserType": "webkit" }, "iPhone 13 Mini landscape": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", "screen": { "width": 375, "height": 812 @@ -836,7 +836,7 @@ "defaultBrowserType": "webkit" }, "iPhone 14": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", "screen": { "width": 390, "height": 844 @@ -851,7 +851,7 @@ "defaultBrowserType": "webkit" }, "iPhone 14 landscape": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", "screen": { "width": 390, "height": 844 @@ -866,7 +866,7 @@ "defaultBrowserType": "webkit" }, "iPhone 14 Plus": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", "screen": { "width": 428, "height": 926 @@ -881,7 +881,7 @@ "defaultBrowserType": "webkit" }, "iPhone 14 Plus landscape": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", "screen": { "width": 428, "height": 926 @@ -896,7 +896,7 @@ "defaultBrowserType": "webkit" }, "iPhone 14 Pro": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", "screen": { "width": 393, "height": 852 @@ -911,7 +911,7 @@ "defaultBrowserType": "webkit" }, "iPhone 14 Pro landscape": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", "screen": { "width": 393, "height": 852 @@ -926,7 +926,7 @@ "defaultBrowserType": "webkit" }, "iPhone 14 Pro Max": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", "screen": { "width": 430, "height": 932 @@ -941,7 +941,7 @@ "defaultBrowserType": "webkit" }, "iPhone 14 Pro Max landscape": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", "screen": { "width": 430, "height": 932 @@ -956,7 +956,7 @@ "defaultBrowserType": "webkit" }, "iPhone 15": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", "screen": { "width": 393, "height": 852 @@ -971,7 +971,7 @@ "defaultBrowserType": "webkit" }, "iPhone 15 landscape": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", "screen": { "width": 393, "height": 852 @@ -986,7 +986,7 @@ "defaultBrowserType": "webkit" }, "iPhone 15 Plus": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", "screen": { "width": 430, "height": 932 @@ -1001,7 +1001,7 @@ "defaultBrowserType": "webkit" }, "iPhone 15 Plus landscape": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", "screen": { "width": 430, "height": 932 @@ -1016,7 +1016,7 @@ "defaultBrowserType": "webkit" }, "iPhone 15 Pro": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", "screen": { "width": 393, "height": 852 @@ -1031,7 +1031,7 @@ "defaultBrowserType": "webkit" }, "iPhone 15 Pro landscape": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", "screen": { "width": 393, "height": 852 @@ -1046,7 +1046,7 @@ "defaultBrowserType": "webkit" }, "iPhone 15 Pro Max": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", "screen": { "width": 430, "height": 932 @@ -1061,7 +1061,7 @@ "defaultBrowserType": "webkit" }, "iPhone 15 Pro Max landscape": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", "screen": { "width": 430, "height": 932 @@ -1607,7 +1607,7 @@ "defaultBrowserType": "firefox" }, "Desktop Safari": { - "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Safari/605.1.15", + "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Safari/605.1.15", "screen": { "width": 1792, "height": 1120 diff --git a/packages/playwright-core/src/server/webkit/wkBrowser.ts b/packages/playwright-core/src/server/webkit/wkBrowser.ts index 9eedec410b..c94486a5c1 100644 --- a/packages/playwright-core/src/server/webkit/wkBrowser.ts +++ b/packages/playwright-core/src/server/webkit/wkBrowser.ts @@ -33,8 +33,8 @@ import { WKPage } from './wkPage'; import { TargetClosedError } from '../errors'; import type { SdkObject } from '../instrumentation'; -const DEFAULT_USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Safari/605.1.15'; -const BROWSER_VERSION = '17.4'; +const DEFAULT_USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Safari/605.1.15'; +const BROWSER_VERSION = '18.0'; export class WKBrowser extends Browser { private readonly _connection: WKConnection; From b214941a01d553385e6d7212525a4da26ca19eb5 Mon Sep 17 00:00:00 2001 From: Max Schmitt Date: Fri, 26 Jul 2024 12:41:33 +0200 Subject: [PATCH 19/20] chore: make it more clear that --only-changed is per file (#31874) --- docs/src/ci-intro.md | 2 +- docs/src/test-cli-js.md | 2 +- packages/playwright/src/program.ts | 2 +- packages/playwright/src/runner/tasks.ts | 4 ++-- packages/playwright/src/runner/vcs.ts | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/src/ci-intro.md b/docs/src/ci-intro.md index 4e4b2bb19c..bad1e358c2 100644 --- a/docs/src/ci-intro.md +++ b/docs/src/ci-intro.md @@ -386,7 +386,7 @@ jobs: ### Fail-Fast * langs: js -Even with sharding enabled, large test suites can take very long to execute. Running changed tests first on PRs will give you a faster feedback loop and use less CI resources. +Even with sharding enabled, large test suites can take very long to execute. Running changed test files first on PRs will give you a faster feedback loop and use less CI resources. ```yml js title=".github/workflows/playwright.yml" name: Playwright Tests diff --git a/docs/src/test-cli-js.md b/docs/src/test-cli-js.md index 052c0abf1f..346d0bc8b5 100644 --- a/docs/src/test-cli-js.md +++ b/docs/src/test-cli-js.md @@ -93,7 +93,7 @@ Complete set of Playwright Test options is available in the [configuration file] | `--max-failures ` or `-x`| Stop after the first `N` test failures. Passing `-x` stops after the first failure.| | `--no-deps` | Ignore the dependencies between projects and behave as if they were not specified. | | `--output ` | Directory for artifacts produced by tests, defaults to `test-results`. | -| `--only-changed [ref]` | Only run tests that have been changed between working tree and "ref". Defaults to running all uncommitted changes with ref=HEAD. Only supports Git. | +| `--only-changed [ref]` | Only run test files that have been changed between working tree and "ref". Defaults to running all uncommitted changes with ref=HEAD. Only supports Git. | | `--pass-with-no-tests` | Allows the test suite to pass when no files are found. | | `--project ` | Only run tests from the specified [projects](./test-projects.md), supports '*' wildcard. Defaults to running all projects defined in the configuration file.| | `--quiet` | Whether to suppress stdout and stderr from the tests. | diff --git a/packages/playwright/src/program.ts b/packages/playwright/src/program.ts index 7cbe7e5461..a6c2c5fead 100644 --- a/packages/playwright/src/program.ts +++ b/packages/playwright/src/program.ts @@ -355,7 +355,7 @@ const testOptions: [string, string][] = [ ['--max-failures ', `Stop after the first N failures`], ['--no-deps', 'Do not run project dependencies'], ['--output ', `Folder for output artifacts (default: "test-results")`], - ['--only-changed [ref]', `Only run tests that have been changed between 'HEAD' and 'ref'. Defaults to running all uncommitted changes. Only supports Git.`], + ['--only-changed [ref]', `Only run test files that have been changed between 'HEAD' and 'ref'. Defaults to running all uncommitted changes. Only supports Git.`], ['--pass-with-no-tests', `Makes test run succeed even if no tests were found`], ['--project ', `Only run tests from the specified list of projects, supports '*' wildcard (default: run all projects)`], ['--quiet', `Suppress stdio`], diff --git a/packages/playwright/src/runner/tasks.ts b/packages/playwright/src/runner/tasks.ts index 7abd1f4749..4220291a08 100644 --- a/packages/playwright/src/runner/tasks.ts +++ b/packages/playwright/src/runner/tasks.ts @@ -31,7 +31,7 @@ import type { Matcher } from '../util'; import { Suite } from '../common/test'; import { buildDependentProjects, buildTeardownToSetupsMap, filterProjects } from './projectUtils'; import { FailureTracker } from './failureTracker'; -import { detectChangedTests } from './vcs'; +import { detectChangedTestFiles } from './vcs'; const readDirAsync = promisify(fs.readdir); @@ -232,7 +232,7 @@ function createLoadTask(mode: 'out-of-process' | 'in-process', options: { filter if (testRun.config.cliOnlyChanged && options.filterOnlyChanged) { for (const plugin of testRun.config.plugins) await plugin.instance?.populateDependencies?.(); - const changedFiles = await detectChangedTests(testRun.config.cliOnlyChanged, testRun.config.configDir); + const changedFiles = await detectChangedTestFiles(testRun.config.cliOnlyChanged, testRun.config.configDir); cliOnlyChangedMatcher = file => changedFiles.has(file); } diff --git a/packages/playwright/src/runner/vcs.ts b/packages/playwright/src/runner/vcs.ts index 160ca60840..3e5fcfc4e3 100644 --- a/packages/playwright/src/runner/vcs.ts +++ b/packages/playwright/src/runner/vcs.ts @@ -18,7 +18,7 @@ import childProcess from 'child_process'; import { affectedTestFiles } from '../transform/compilationCache'; import path from 'path'; -export async function detectChangedTests(baseCommit: string, configDir: string): Promise> { +export async function detectChangedTestFiles(baseCommit: string, configDir: string): Promise> { function gitFileList(command: string) { try { return childProcess.execSync( From 6988194c97d6effe211ea9c2fd0811c634db6fb9 Mon Sep 17 00:00:00 2001 From: Max Schmitt Date: Fri, 26 Jul 2024 12:43:05 +0200 Subject: [PATCH 20/20] test: unflake contextmenu recorder test (#31749) --- .../src/server/injected/recorder/recorder.ts | 3 ++ tests/library/inspector/cli-codegen-3.spec.ts | 46 +++++++++++++------ 2 files changed, 34 insertions(+), 15 deletions(-) diff --git a/packages/playwright-core/src/server/injected/recorder/recorder.ts b/packages/playwright-core/src/server/injected/recorder/recorder.ts index 116fca63bc..c9413e0a72 100644 --- a/packages/playwright-core/src/server/injected/recorder/recorder.ts +++ b/packages/playwright-core/src/server/injected/recorder/recorder.ts @@ -230,6 +230,9 @@ class RecordActionTool implements RecorderTool { // So we check the hovered element instead, and if it is a range input, we skip click handling if (isRangeInput(this._hoveredElement)) return; + // Right clicks are handled by 'contextmenu' event if its auxclick + if (event.button === 2 && event.type === 'auxclick') + return; if (this._shouldIgnoreMouseEvent(event)) return; if (this._actionInProgress(event)) diff --git a/tests/library/inspector/cli-codegen-3.spec.ts b/tests/library/inspector/cli-codegen-3.spec.ts index 8ad14c87b9..424b2bacfe 100644 --- a/tests/library/inspector/cli-codegen-3.spec.ts +++ b/tests/library/inspector/cli-codegen-3.spec.ts @@ -559,7 +559,7 @@ await page.GetByLabel("Coun\\"try").ClickAsync();`); ]); }); - test('should consume contextmenu events, despite a custom context menu', async ({ page, openRecorder }) => { + test('should consume contextmenu events, despite a custom context menu', async ({ page, openRecorder, browserName, platform }) => { const recorder = await openRecorder(); await recorder.setContentAndWait(` @@ -597,20 +597,36 @@ await page.GetByLabel("Coun\\"try").ClickAsync();`); recorder.trustedClick({ button: 'right' }), ]); expect(message.text()).toBe('right-clicked'); - expect(await page.evaluate('log')).toEqual([ - // hover - 'button: pointermove', - 'button: mousemove', - // trusted right click - 'button: pointerup', - 'button: pointermove', - 'button: mousemove', - 'button: pointerdown', - 'button: mousedown', - 'button: contextmenu', - 'menu: pointerup', - 'menu: mouseup' - ]); + if (browserName === 'chromium' && platform === 'win32') { + expect(await page.evaluate('log')).toEqual([ + // hover + 'button: pointermove', + 'button: mousemove', + // trusted right click + 'button: pointermove', + 'button: mousemove', + 'button: pointerdown', + 'button: mousedown', + 'button: pointerup', + 'button: mouseup', + 'button: contextmenu', + ]); + } else { + expect(await page.evaluate('log')).toEqual([ + // hover + 'button: pointermove', + 'button: mousemove', + // trusted right click + 'button: pointerup', + 'button: pointermove', + 'button: mousemove', + 'button: pointerdown', + 'button: mousedown', + 'button: contextmenu', + 'menu: pointerup', + 'menu: mouseup', + ]); + } }); test('should assert value', async ({ openRecorder }) => {