diff --git a/docs/src/api/class-browser.md b/docs/src/api/class-browser.md index 9ae59571fc..8d1d2d99c1 100644 --- a/docs/src/api/class-browser.md +++ b/docs/src/api/class-browser.md @@ -296,6 +296,18 @@ testing frameworks should explicitly create [`method: Browser.newContext`] follo ### option: Browser.newPage.storageStatePath = %%-csharp-java-context-option-storage-state-path-%% * since: v1.9 +## async method: Browser.removeAllListeners +* since: v1.47 + +Removes all the listeners of the given type if the type is given. Otherwise removes all the listeners. + +### param: Browser.removeAllListeners.type +* since: v1.47 +- `type` ?<[string]> + +### option: Browser.removeAllListeners.behavior = %%-remove-all-listeners-options-behavior-%% +* since: v1.47 + ## async method: Browser.startTracing * since: v1.11 * langs: java, js, python diff --git a/docs/src/api/class-browsercontext.md b/docs/src/api/class-browsercontext.md index 48542a2603..cf7efd7af1 100644 --- a/docs/src/api/class-browsercontext.md +++ b/docs/src/api/class-browsercontext.md @@ -1016,6 +1016,18 @@ Creates a new page in the browser context. Returns all open pages in the context. +## async method: BrowserContext.removeAllListeners +* since: v1.47 + +Removes all the listeners of the given type if the type is given. Otherwise removes all the listeners. + +### param: BrowserContext.removeAllListeners.type +* since: v1.47 +- `type` ?<[string]> + +### option: BrowserContext.removeAllListeners.behavior = %%-remove-all-listeners-options-behavior-%% +* since: v1.47 + ## property: BrowserContext.request * since: v1.16 * langs: diff --git a/docs/src/api/class-page.md b/docs/src/api/class-page.md index 7953952e30..47303634b0 100644 --- a/docs/src/api/class-page.md +++ b/docs/src/api/class-page.md @@ -3340,6 +3340,17 @@ Specifies the maximum number of times this handler should be called. Unlimited b By default, after calling the handler Playwright will wait until the overlay becomes hidden, and only then Playwright will continue with the action/assertion that triggered the handler. This option allows to opt-out of this behavior, so that overlay can stay visible after the handler has run. +## async method: Page.removeAllListeners +* since: v1.47 + +Removes all the listeners of the given type if the type is given. Otherwise removes all the listeners. + +### param: Page.removeAllListeners.type +* since: v1.47 +- `type` ?<[string]> + +### option: Page.removeAllListeners.behavior = %%-remove-all-listeners-options-behavior-%% +* since: v1.47 ## async method: Page.removeLocatorHandler * since: v1.44 diff --git a/docs/src/api/params.md b/docs/src/api/params.md index 5a3a17d97e..1743066647 100644 --- a/docs/src/api/params.md +++ b/docs/src/api/params.md @@ -781,6 +781,16 @@ Whether to allow sites to register Service workers. Defaults to `'allow'`. * `'allow'`: [Service Workers](https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API) can be registered. * `'block'`: Playwright will block all registration of Service Workers. +## remove-all-listeners-options-behavior +* langs: js +* since: v1.47 +- `behavior` <[RemoveAllListenersBehavior]<"wait"|"ignoreErrors"|"default">> + +Specifies whether to wait for already running listeners and what to do if they throw errors: +* `'default'` - do not wait for current listener calls (if any) to finish, if the listener throws, it may result in unhandled error +* `'wait'` - wait for current listener calls (if any) to finish +* `'ignoreErrors'` - do not wait for current listener calls (if any) to finish, all errors thrown by the listeners after removal are silently caught + ## unroute-all-options-behavior * langs: js, csharp, python * since: v1.41 @@ -791,6 +801,7 @@ Specifies whether to wait for already running handlers and what to do if they th * `'wait'` - wait for current handler calls (if any) to finish * `'ignoreErrors'` - do not wait for current handler calls (if any) to finish, all errors thrown by the handlers after unrouting are silently caught + ## select-options-values * langs: java, js, csharp - `values` <[null]|[string]|[ElementHandle]|[Array]<[string]>|[Object]|[Array]<[ElementHandle]>|[Array]<[Object]>> diff --git a/packages/playwright-core/src/client/eventEmitter.ts b/packages/playwright-core/src/client/eventEmitter.ts index 6de8ca3a31..c0375a70dc 100644 --- a/packages/playwright-core/src/client/eventEmitter.ts +++ b/packages/playwright-core/src/client/eventEmitter.ts @@ -23,7 +23,7 @@ */ type EventType = string | symbol; -type Listener = (...args: any[]) => void; +type Listener = (...args: any[]) => any; type EventMap = Record; import { EventEmitter as OriginalEventEmitter } from 'events'; import type { EventEmitter as EventEmitterType } from 'events'; @@ -34,6 +34,8 @@ export class EventEmitter implements EventEmitterType { private _events: EventMap | undefined = undefined; private _eventsCount = 0; private _maxListeners: number | undefined = undefined; + readonly _pendingHandlers = new Map>>(); + private _rejectionHandler: ((error: Error) => void) | undefined; constructor() { if (this._events === undefined || this._events === Object.getPrototypeOf(this)._events) { @@ -66,17 +68,34 @@ export class EventEmitter implements EventEmitterType { return false; if (typeof handler === 'function') { - Reflect.apply(handler, this, args); + this._callHandler(type, handler, args); } else { const len = handler.length; const listeners = handler.slice(); for (let i = 0; i < len; ++i) - Reflect.apply(listeners[i], this, args); + this._callHandler(type, listeners[i], args); } - return true; } + private _callHandler(type: EventType, handler: Listener, args: any[]): void { + const promise = Reflect.apply(handler, this, args); + if (!(promise instanceof Promise)) + return; + let set = this._pendingHandlers.get(type); + if (!set) { + set = new Set(); + this._pendingHandlers.set(type, set); + } + set.add(promise); + promise.catch(e => { + if (this._rejectionHandler) + this._rejectionHandler(e); + else + throw e; + }).finally(() => set.delete(promise)); + } + addListener(type: EventType, listener: Listener): this { return this._addListener(type, listener, false); } @@ -214,10 +233,34 @@ export class EventEmitter implements EventEmitterType { return this.removeListener(type, listener); } - removeAllListeners(type?: string): this { + removeAllListeners(type?: EventType): this; + removeAllListeners(type: EventType | undefined, options: { behavior?: 'wait'|'ignoreErrors'|'default' }): Promise; + removeAllListeners(type?: string, options?: { behavior?: 'wait'|'ignoreErrors'|'default' }): this | Promise { + this._removeAllListeners(type); + if (!options) + return this; + + if (options.behavior === 'wait') { + const errors: Error[] = []; + this._rejectionHandler = error => errors.push(error); + // eslint-disable-next-line internal-playwright/await-promise-in-class-returns + return this._waitFor(type).then(() => { + if (errors.length) + throw errors[0]; + }); + } + + if (options.behavior === 'ignoreErrors') + this._rejectionHandler = () => {}; + + // eslint-disable-next-line internal-playwright/await-promise-in-class-returns + return Promise.resolve(); + } + + private _removeAllListeners(type?: string) { const events = this._events; if (!events) - return this; + return; // not listening for removeListener, no need to emit if (!events.removeListener) { @@ -230,7 +273,7 @@ export class EventEmitter implements EventEmitterType { else delete events[type]; } - return this; + return; } // emit removeListener for all listeners on all events @@ -241,12 +284,12 @@ export class EventEmitter implements EventEmitterType { key = keys[i]; if (key === 'removeListener') continue; - this.removeAllListeners(key); + this._removeAllListeners(key); } - this.removeAllListeners('removeListener'); + this._removeAllListeners('removeListener'); this._events = Object.create(null); this._eventsCount = 0; - return this; + return; } const listeners = events[type]; @@ -258,8 +301,6 @@ export class EventEmitter implements EventEmitterType { for (let i = listeners.length - 1; i >= 0; i--) this.removeListener(type, listeners[i]); } - - return this; } listeners(type: EventType): Listener[] { @@ -286,6 +327,18 @@ export class EventEmitter implements EventEmitterType { return this._eventsCount > 0 && this._events ? Reflect.ownKeys(this._events) : []; } + private async _waitFor(type?: EventType) { + let promises: Promise[] = []; + if (type) { + promises = [...(this._pendingHandlers.get(type) || [])]; + } else { + promises = []; + for (const [, pending] of this._pendingHandlers) + promises.push(...pending); + } + await Promise.all(promises); + } + private _listeners(target: EventEmitter, type: EventType, unwrap: boolean): Listener[] { const events = target._events; @@ -310,7 +363,7 @@ function checkListener(listener: any) { class OnceWrapper { private _fired = false; - readonly wrapperFunction: (...args: any[]) => void; + readonly wrapperFunction: (...args: any[]) => Promise | void; readonly _listener: Listener; private _eventEmitter: EventEmitter; private _eventType: EventType; diff --git a/packages/playwright-core/types/types.d.ts b/packages/playwright-core/types/types.d.ts index 94ebd513da..8e818983c9 100644 --- a/packages/playwright-core/types/types.d.ts +++ b/packages/playwright-core/types/types.d.ts @@ -865,6 +865,19 @@ export interface Page { * @param options */ exposeBinding(name: string, playwrightBinding: (source: BindingSource, ...args: any[]) => any, options?: { handle?: boolean }): Promise; + + /** + * Removes all the listeners of the given type if the type is given. Otherwise removes all the listeners. + * @param type + * @param options + */ + removeAllListeners(type?: string): this; + /** + * Removes all the listeners of the given type if the type is given. Otherwise removes all the listeners. + * @param type + * @param options + */ + removeAllListeners(type: string | undefined, options: { behavior?: 'wait'|'ignoreErrors'|'default' }): Promise; /** * Emitted when the page closes. */ @@ -7661,6 +7674,19 @@ export interface BrowserContext { * @param arg Optional argument to pass to `script` (only supported when passing a function). */ addInitScript(script: PageFunction | { path?: string, content?: string }, arg?: Arg): Promise; + + /** + * Removes all the listeners of the given type if the type is given. Otherwise removes all the listeners. + * @param type + * @param options + */ + removeAllListeners(type?: string): this; + /** + * Removes all the listeners of the given type if the type is given. Otherwise removes all the listeners. + * @param type + * @param options + */ + removeAllListeners(type: string | undefined, options: { behavior?: 'wait'|'ignoreErrors'|'default' }): Promise; /** * **NOTE** Only works with Chromium browser's persistent context. * @@ -8915,6 +8941,665 @@ export interface BrowserContext { [Symbol.asyncDispose](): Promise; } +/** + * - extends: [EventEmitter] + * + * A Browser is created via + * [browserType.launch([options])](https://playwright.dev/docs/api/class-browsertype#browser-type-launch). An example + * of using a {@link Browser} to create a {@link Page}: + * + * ```js + * const { firefox } = require('playwright'); // Or 'chromium' or 'webkit'. + * + * (async () => { + * const browser = await firefox.launch(); + * const page = await browser.newPage(); + * await page.goto('https://example.com'); + * await browser.close(); + * })(); + * ``` + * + */ +export interface Browser { + /** + * Removes all the listeners of the given type if the type is given. Otherwise removes all the listeners. + * @param type + * @param options + */ + removeAllListeners(type?: string): this; + /** + * Removes all the listeners of the given type if the type is given. Otherwise removes all the listeners. + * @param type + * @param options + */ + removeAllListeners(type: string | undefined, options: { behavior?: 'wait'|'ignoreErrors'|'default' }): Promise; + /** + * Emitted when Browser gets disconnected from the browser application. This might happen because of one of the + * following: + * - Browser application is closed or crashed. + * - The [browser.close([options])](https://playwright.dev/docs/api/class-browser#browser-close) method was called. + */ + on(event: 'disconnected', listener: (browser: Browser) => any): this; + + /** + * Adds an event listener that will be automatically removed after it is triggered once. See `addListener` for more information about this event. + */ + once(event: 'disconnected', listener: (browser: Browser) => any): this; + + /** + * Emitted when Browser gets disconnected from the browser application. This might happen because of one of the + * following: + * - Browser application is closed or crashed. + * - The [browser.close([options])](https://playwright.dev/docs/api/class-browser#browser-close) method was called. + */ + addListener(event: 'disconnected', listener: (browser: Browser) => any): this; + + /** + * Removes an event listener added by `on` or `addListener`. + */ + removeListener(event: 'disconnected', listener: (browser: Browser) => any): this; + + /** + * Removes an event listener added by `on` or `addListener`. + */ + off(event: 'disconnected', listener: (browser: Browser) => any): this; + + /** + * Emitted when Browser gets disconnected from the browser application. This might happen because of one of the + * following: + * - Browser application is closed or crashed. + * - The [browser.close([options])](https://playwright.dev/docs/api/class-browser#browser-close) method was called. + */ + prependListener(event: 'disconnected', listener: (browser: Browser) => any): this; + + /** + * Get the browser type (chromium, firefox or webkit) that the browser belongs to. + */ + browserType(): BrowserType; + + /** + * In case this browser is obtained using + * [browserType.launch([options])](https://playwright.dev/docs/api/class-browsertype#browser-type-launch), closes the + * browser and all of its pages (if any were opened). + * + * In case this browser is connected to, clears all created contexts belonging to this browser and disconnects from + * the browser server. + * + * **NOTE** This is similar to force quitting the browser. Therefore, you should call + * [browserContext.close([options])](https://playwright.dev/docs/api/class-browsercontext#browser-context-close) on + * any {@link BrowserContext}'s you explicitly created earlier with + * [browser.newContext([options])](https://playwright.dev/docs/api/class-browser#browser-new-context) **before** + * calling [browser.close([options])](https://playwright.dev/docs/api/class-browser#browser-close). + * + * The {@link Browser} object itself is considered to be disposed and cannot be used anymore. + * @param options + */ + close(options?: { + /** + * The reason to be reported to the operations interrupted by the browser closure. + */ + reason?: string; + }): Promise; + + /** + * Returns an array of all open browser contexts. In a newly created browser, this will return zero browser contexts. + * + * **Usage** + * + * ```js + * const browser = await pw.webkit.launch(); + * console.log(browser.contexts().length); // prints `0` + * + * const context = await browser.newContext(); + * console.log(browser.contexts().length); // prints `1` + * ``` + * + */ + contexts(): Array; + + /** + * Indicates that the browser is connected. + */ + isConnected(): boolean; + + /** + * **NOTE** CDP Sessions are only supported on Chromium-based browsers. + * + * Returns the newly created browser session. + */ + newBrowserCDPSession(): Promise; + + /** + * Creates a new browser context. It won't share cookies/cache with other browser contexts. + * + * **NOTE** If directly using this method to create {@link BrowserContext}s, it is best practice to explicitly close + * the returned context via + * [browserContext.close([options])](https://playwright.dev/docs/api/class-browsercontext#browser-context-close) when + * your code is done with the {@link BrowserContext}, and before calling + * [browser.close([options])](https://playwright.dev/docs/api/class-browser#browser-close). This will ensure the + * `context` is closed gracefully and any artifacts—like HARs and videos—are fully flushed and saved. + * + * **Usage** + * + * ```js + * (async () => { + * const browser = await playwright.firefox.launch(); // Or 'chromium' or 'webkit'. + * // Create a new incognito browser context. + * const context = await browser.newContext(); + * // Create a new page in a pristine context. + * const page = await context.newPage(); + * await page.goto('https://example.com'); + * + * // Gracefully close up everything + * await context.close(); + * await browser.close(); + * })(); + * ``` + * + * @param options + */ + newContext(options?: BrowserContextOptions): Promise; + + /** + * Creates a new page in a new browser context. Closing this page will close the context as well. + * + * This is a convenience API that should only be used for the single-page scenarios and short snippets. Production + * code and testing frameworks should explicitly create + * [browser.newContext([options])](https://playwright.dev/docs/api/class-browser#browser-new-context) followed by the + * [browserContext.newPage()](https://playwright.dev/docs/api/class-browsercontext#browser-context-new-page) to + * control their exact life times. + * @param options + */ + newPage(options?: { + /** + * Whether to automatically download all the attachments. Defaults to `true` where all the downloads are accepted. + */ + acceptDownloads?: boolean; + + /** + * When using [page.goto(url[, options])](https://playwright.dev/docs/api/class-page#page-goto), + * [page.route(url, handler[, options])](https://playwright.dev/docs/api/class-page#page-route), + * [page.waitForURL(url[, options])](https://playwright.dev/docs/api/class-page#page-wait-for-url), + * [page.waitForRequest(urlOrPredicate[, options])](https://playwright.dev/docs/api/class-page#page-wait-for-request), + * or + * [page.waitForResponse(urlOrPredicate[, options])](https://playwright.dev/docs/api/class-page#page-wait-for-response) + * it takes the base URL in consideration by using the + * [`URL()`](https://developer.mozilla.org/en-US/docs/Web/API/URL/URL) constructor for building the corresponding URL. + * Unset by default. Examples: + * - baseURL: `http://localhost:3000` and navigating to `/bar.html` results in `http://localhost:3000/bar.html` + * - baseURL: `http://localhost:3000/foo/` and navigating to `./bar.html` results in + * `http://localhost:3000/foo/bar.html` + * - baseURL: `http://localhost:3000/foo` (without trailing slash) and navigating to `./bar.html` results in + * `http://localhost:3000/bar.html` + */ + baseURL?: string; + + /** + * Toggles bypassing page's Content-Security-Policy. Defaults to `false`. + */ + bypassCSP?: boolean; + + /** + * TLS Client Authentication allows the server to request a client certificate and verify it. + * + * **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. 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. + * + * **NOTE** When using WebKit on macOS, accessing `localhost` will not pick up client certificates. You can make it + * work by replacing `localhost` with `local.playwright`. + */ + clientCertificates?: Array<{ + /** + * Exact origin that the certificate is valid for. Origin includes `https` protocol, a hostname and optionally a port. + */ + origin: string; + + /** + * Path to the file with the certificate in PEM format. + */ + certPath?: string; + + /** + * Path to the file with the private key in PEM format. + */ + keyPath?: string; + + /** + * Path to the PFX or PKCS12 encoded private key and certificate chain. + */ + pfxPath?: string; + + /** + * Passphrase for the private key (PEM or PFX). + */ + passphrase?: string; + }>; + + /** + * Emulates `'prefers-colors-scheme'` media feature, supported values are `'light'`, `'dark'`, `'no-preference'`. See + * [page.emulateMedia([options])](https://playwright.dev/docs/api/class-page#page-emulate-media) for more details. + * Passing `null` resets emulation to system defaults. Defaults to `'light'`. + */ + colorScheme?: null|"light"|"dark"|"no-preference"; + + /** + * Specify device scale factor (can be thought of as dpr). Defaults to `1`. Learn more about + * [emulating devices with device scale factor](https://playwright.dev/docs/emulation#devices). + */ + deviceScaleFactor?: number; + + /** + * An object containing additional HTTP headers to be sent with every request. Defaults to none. + */ + extraHTTPHeaders?: { [key: string]: string; }; + + /** + * Emulates `'forced-colors'` media feature, supported values are `'active'`, `'none'`. See + * [page.emulateMedia([options])](https://playwright.dev/docs/api/class-page#page-emulate-media) for more details. + * Passing `null` resets emulation to system defaults. Defaults to `'none'`. + */ + forcedColors?: null|"active"|"none"; + + geolocation?: { + /** + * Latitude between -90 and 90. + */ + latitude: number; + + /** + * Longitude between -180 and 180. + */ + longitude: number; + + /** + * Non-negative accuracy value. Defaults to `0`. + */ + accuracy?: number; + }; + + /** + * Specifies if viewport supports touch events. Defaults to false. Learn more about + * [mobile emulation](https://playwright.dev/docs/emulation#devices). + */ + hasTouch?: boolean; + + /** + * Credentials for [HTTP authentication](https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication). If no + * origin is specified, the username and password are sent to any servers upon unauthorized responses. + */ + httpCredentials?: { + username: string; + + password: string; + + /** + * Restrain sending http credentials on specific origin (scheme://host:port). + */ + origin?: string; + + /** + * This option only applies to the requests sent from corresponding {@link APIRequestContext} and does not affect + * requests sent from the browser. `'always'` - `Authorization` header with basic authentication credentials will be + * sent with the each API request. `'unauthorized` - the credentials are only sent when 401 (Unauthorized) response + * with `WWW-Authenticate` header is received. Defaults to `'unauthorized'`. + */ + send?: "unauthorized"|"always"; + }; + + /** + * Whether to ignore HTTPS errors when sending network requests. Defaults to `false`. + */ + ignoreHTTPSErrors?: boolean; + + /** + * Whether the `meta viewport` tag is taken into account and touch events are enabled. isMobile is a part of device, + * so you don't actually need to set it manually. Defaults to `false` and is not supported in Firefox. Learn more + * about [mobile emulation](https://playwright.dev/docs/emulation#ismobile). + */ + isMobile?: boolean; + + /** + * Whether or not to enable JavaScript in the context. Defaults to `true`. Learn more about + * [disabling JavaScript](https://playwright.dev/docs/emulation#javascript-enabled). + */ + javaScriptEnabled?: boolean; + + /** + * Specify user locale, for example `en-GB`, `de-DE`, etc. Locale will affect `navigator.language` value, + * `Accept-Language` request header value as well as number and date formatting rules. Defaults to the system default + * locale. Learn more about emulation in our [emulation guide](https://playwright.dev/docs/emulation#locale--timezone). + */ + locale?: string; + + /** + * Logger sink for Playwright logging. + */ + logger?: Logger; + + /** + * Whether to emulate network being offline. Defaults to `false`. Learn more about + * [network emulation](https://playwright.dev/docs/emulation#offline). + */ + offline?: boolean; + + /** + * A list of permissions to grant to all pages in this context. See + * [browserContext.grantPermissions(permissions[, options])](https://playwright.dev/docs/api/class-browsercontext#browser-context-grant-permissions) + * for more details. Defaults to none. + */ + permissions?: Array; + + /** + * Network proxy settings to use with this context. Defaults to none. + * + * **NOTE** For Chromium on Windows the browser needs to be launched with the global proxy for this option to work. If + * all contexts override the proxy, global proxy will be never used and can be any string, for example `launch({ + * proxy: { server: 'http://per-context' } })`. + */ + proxy?: { + /** + * Proxy to be used for all requests. HTTP and SOCKS proxies are supported, for example `http://myproxy.com:3128` or + * `socks5://myproxy.com:3128`. Short form `myproxy.com:3128` is considered an HTTP proxy. + */ + server: string; + + /** + * Optional comma-separated domains to bypass proxy, for example `".com, chromium.org, .domain.com"`. + */ + bypass?: string; + + /** + * Optional username to use if HTTP proxy requires authentication. + */ + username?: string; + + /** + * Optional password to use if HTTP proxy requires authentication. + */ + password?: string; + }; + + /** + * Enables [HAR](http://www.softwareishard.com/blog/har-12-spec) recording for all pages into `recordHar.path` file. + * If not specified, the HAR is not recorded. Make sure to await + * [browserContext.close([options])](https://playwright.dev/docs/api/class-browsercontext#browser-context-close) for + * the HAR to be saved. + */ + recordHar?: { + /** + * Optional setting to control whether to omit request content from the HAR. Defaults to `false`. Deprecated, use + * `content` policy instead. + */ + omitContent?: boolean; + + /** + * Optional setting to control resource content management. If `omit` is specified, content is not persisted. If + * `attach` is specified, resources are persisted as separate files or entries in the ZIP archive. If `embed` is + * specified, content is stored inline the HAR file as per HAR specification. Defaults to `attach` for `.zip` output + * files and to `embed` for all other file extensions. + */ + content?: "omit"|"embed"|"attach"; + + /** + * Path on the filesystem to write the HAR file to. If the file name ends with `.zip`, `content: 'attach'` is used by + * default. + */ + path: string; + + /** + * When set to `minimal`, only record information necessary for routing from HAR. This omits sizes, timing, page, + * cookies, security and other types of HAR information that are not used when replaying from HAR. Defaults to `full`. + */ + mode?: "full"|"minimal"; + + /** + * A glob or regex pattern to filter requests that are stored in the HAR. When a `baseURL` via the context options was + * provided and the passed URL is a path, it gets merged via the + * [`new URL()`](https://developer.mozilla.org/en-US/docs/Web/API/URL/URL) constructor. Defaults to none. + */ + urlFilter?: string|RegExp; + }; + + /** + * Enables video recording for all pages into `recordVideo.dir` directory. If not specified videos are not recorded. + * Make sure to await + * [browserContext.close([options])](https://playwright.dev/docs/api/class-browsercontext#browser-context-close) for + * videos to be saved. + */ + recordVideo?: { + /** + * Path to the directory to put videos into. + */ + dir: string; + + /** + * Optional dimensions of the recorded videos. If not specified the size will be equal to `viewport` scaled down to + * fit into 800x800. If `viewport` is not configured explicitly the video size defaults to 800x450. Actual picture of + * each page will be scaled down if necessary to fit the specified size. + */ + size?: { + /** + * Video frame width. + */ + width: number; + + /** + * Video frame height. + */ + height: number; + }; + }; + + /** + * Emulates `'prefers-reduced-motion'` media feature, supported values are `'reduce'`, `'no-preference'`. See + * [page.emulateMedia([options])](https://playwright.dev/docs/api/class-page#page-emulate-media) for more details. + * Passing `null` resets emulation to system defaults. Defaults to `'no-preference'`. + */ + reducedMotion?: null|"reduce"|"no-preference"; + + /** + * Emulates consistent window screen size available inside web page via `window.screen`. Is only used when the + * `viewport` is set. + */ + screen?: { + /** + * page width in pixels. + */ + width: number; + + /** + * page height in pixels. + */ + height: number; + }; + + /** + * Whether to allow sites to register Service workers. Defaults to `'allow'`. + * - `'allow'`: [Service Workers](https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API) can be + * registered. + * - `'block'`: Playwright will block all registration of Service Workers. + */ + serviceWorkers?: "allow"|"block"; + + /** + * Learn more about [storage state and auth](https://playwright.dev/docs/auth). + * + * Populates context with given storage state. This option can be used to initialize context with logged-in + * information obtained via + * [browserContext.storageState([options])](https://playwright.dev/docs/api/class-browsercontext#browser-context-storage-state). + */ + storageState?: string|{ + /** + * Cookies to set for context + */ + cookies: Array<{ + name: string; + + value: string; + + /** + * Domain and path are required. For the cookie to apply to all subdomains as well, prefix domain with a dot, like + * this: ".example.com" + */ + domain: string; + + /** + * Domain and path are required + */ + path: string; + + /** + * Unix time in seconds. + */ + expires: number; + + httpOnly: boolean; + + secure: boolean; + + /** + * sameSite flag + */ + sameSite: "Strict"|"Lax"|"None"; + }>; + + /** + * localStorage to set for context + */ + origins: Array<{ + origin: string; + + localStorage: Array<{ + name: string; + + value: string; + }>; + }>; + }; + + /** + * If set to true, enables strict selectors mode for this context. In the strict selectors mode all operations on + * selectors that imply single target DOM element will throw when more than one element matches the selector. This + * option does not affect any Locator APIs (Locators are always strict). Defaults to `false`. See {@link Locator} to + * learn more about the strict mode. + */ + strictSelectors?: boolean; + + /** + * Changes the timezone of the context. See + * [ICU's metaZones.txt](https://cs.chromium.org/chromium/src/third_party/icu/source/data/misc/metaZones.txt?rcl=faee8bc70570192d82d2978a71e2a615788597d1) + * for a list of supported timezone IDs. Defaults to the system timezone. + */ + timezoneId?: string; + + /** + * Specific user agent to use in this context. + */ + userAgent?: string; + + /** + * @deprecated Use `recordVideo` instead. + */ + videoSize?: { + /** + * Video frame width. + */ + width: number; + + /** + * Video frame height. + */ + height: number; + }; + + /** + * @deprecated Use `recordVideo` instead. + */ + videosPath?: string; + + /** + * Emulates consistent viewport for each page. Defaults to an 1280x720 viewport. Use `null` to disable the consistent + * viewport emulation. Learn more about [viewport emulation](https://playwright.dev/docs/emulation#viewport). + * + * **NOTE** The `null` value opts out from the default presets, makes viewport depend on the host window size defined + * by the operating system. It makes the execution of the tests non-deterministic. + */ + viewport?: null|{ + /** + * page width in pixels. + */ + width: number; + + /** + * page height in pixels. + */ + height: number; + }; + }): Promise; + + /** + * **NOTE** This API controls + * [Chromium Tracing](https://www.chromium.org/developers/how-tos/trace-event-profiling-tool) which is a low-level + * chromium-specific debugging tool. API to control [Playwright Tracing](https://playwright.dev/docs/trace-viewer) could be found + * [here](https://playwright.dev/docs/api/class-tracing). + * + * You can use + * [browser.startTracing([page, options])](https://playwright.dev/docs/api/class-browser#browser-start-tracing) and + * [browser.stopTracing()](https://playwright.dev/docs/api/class-browser#browser-stop-tracing) to create a trace file + * that can be opened in Chrome DevTools performance panel. + * + * **Usage** + * + * ```js + * await browser.startTracing(page, { path: 'trace.json' }); + * await page.goto('https://www.google.com'); + * await browser.stopTracing(); + * ``` + * + * @param page Optional, if specified, tracing includes screenshots of the given page. + * @param options + */ + startTracing(page?: Page, options?: { + /** + * specify custom categories to use instead of default. + */ + categories?: Array; + + /** + * A path to write the trace file to. + */ + path?: string; + + /** + * captures screenshots in the trace. + */ + screenshots?: boolean; + }): Promise; + + /** + * **NOTE** This API controls + * [Chromium Tracing](https://www.chromium.org/developers/how-tos/trace-event-profiling-tool) which is a low-level + * chromium-specific debugging tool. API to control [Playwright Tracing](https://playwright.dev/docs/trace-viewer) could be found + * [here](https://playwright.dev/docs/api/class-tracing). + * + * Returns the buffer with trace data. + */ + stopTracing(): Promise; + + /** + * Returns the browser version. + */ + version(): string; + + [Symbol.asyncDispose](): Promise; +} + /** * The Worker class represents a [WebWorker](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API). * `worker` event is emitted on the page object to signal a worker creation. `close` event is emitted on the worker @@ -16590,653 +17275,6 @@ export interface APIResponse { [Symbol.asyncDispose](): Promise; } -/** - * - extends: [EventEmitter] - * - * A Browser is created via - * [browserType.launch([options])](https://playwright.dev/docs/api/class-browsertype#browser-type-launch). An example - * of using a {@link Browser} to create a {@link Page}: - * - * ```js - * const { firefox } = require('playwright'); // Or 'chromium' or 'webkit'. - * - * (async () => { - * const browser = await firefox.launch(); - * const page = await browser.newPage(); - * await page.goto('https://example.com'); - * await browser.close(); - * })(); - * ``` - * - */ -export interface Browser extends EventEmitter { - /** - * Emitted when Browser gets disconnected from the browser application. This might happen because of one of the - * following: - * - Browser application is closed or crashed. - * - The [browser.close([options])](https://playwright.dev/docs/api/class-browser#browser-close) method was called. - */ - on(event: 'disconnected', listener: (browser: Browser) => any): this; - - /** - * Adds an event listener that will be automatically removed after it is triggered once. See `addListener` for more information about this event. - */ - once(event: 'disconnected', listener: (browser: Browser) => any): this; - - /** - * Emitted when Browser gets disconnected from the browser application. This might happen because of one of the - * following: - * - Browser application is closed or crashed. - * - The [browser.close([options])](https://playwright.dev/docs/api/class-browser#browser-close) method was called. - */ - addListener(event: 'disconnected', listener: (browser: Browser) => any): this; - - /** - * Removes an event listener added by `on` or `addListener`. - */ - removeListener(event: 'disconnected', listener: (browser: Browser) => any): this; - - /** - * Removes an event listener added by `on` or `addListener`. - */ - off(event: 'disconnected', listener: (browser: Browser) => any): this; - - /** - * Emitted when Browser gets disconnected from the browser application. This might happen because of one of the - * following: - * - Browser application is closed or crashed. - * - The [browser.close([options])](https://playwright.dev/docs/api/class-browser#browser-close) method was called. - */ - prependListener(event: 'disconnected', listener: (browser: Browser) => any): this; - - /** - * Get the browser type (chromium, firefox or webkit) that the browser belongs to. - */ - browserType(): BrowserType; - - /** - * In case this browser is obtained using - * [browserType.launch([options])](https://playwright.dev/docs/api/class-browsertype#browser-type-launch), closes the - * browser and all of its pages (if any were opened). - * - * In case this browser is connected to, clears all created contexts belonging to this browser and disconnects from - * the browser server. - * - * **NOTE** This is similar to force quitting the browser. Therefore, you should call - * [browserContext.close([options])](https://playwright.dev/docs/api/class-browsercontext#browser-context-close) on - * any {@link BrowserContext}'s you explicitly created earlier with - * [browser.newContext([options])](https://playwright.dev/docs/api/class-browser#browser-new-context) **before** - * calling [browser.close([options])](https://playwright.dev/docs/api/class-browser#browser-close). - * - * The {@link Browser} object itself is considered to be disposed and cannot be used anymore. - * @param options - */ - close(options?: { - /** - * The reason to be reported to the operations interrupted by the browser closure. - */ - reason?: string; - }): Promise; - - /** - * Returns an array of all open browser contexts. In a newly created browser, this will return zero browser contexts. - * - * **Usage** - * - * ```js - * const browser = await pw.webkit.launch(); - * console.log(browser.contexts().length); // prints `0` - * - * const context = await browser.newContext(); - * console.log(browser.contexts().length); // prints `1` - * ``` - * - */ - contexts(): Array; - - /** - * Indicates that the browser is connected. - */ - isConnected(): boolean; - - /** - * **NOTE** CDP Sessions are only supported on Chromium-based browsers. - * - * Returns the newly created browser session. - */ - newBrowserCDPSession(): Promise; - - /** - * Creates a new browser context. It won't share cookies/cache with other browser contexts. - * - * **NOTE** If directly using this method to create {@link BrowserContext}s, it is best practice to explicitly close - * the returned context via - * [browserContext.close([options])](https://playwright.dev/docs/api/class-browsercontext#browser-context-close) when - * your code is done with the {@link BrowserContext}, and before calling - * [browser.close([options])](https://playwright.dev/docs/api/class-browser#browser-close). This will ensure the - * `context` is closed gracefully and any artifacts—like HARs and videos—are fully flushed and saved. - * - * **Usage** - * - * ```js - * (async () => { - * const browser = await playwright.firefox.launch(); // Or 'chromium' or 'webkit'. - * // Create a new incognito browser context. - * const context = await browser.newContext(); - * // Create a new page in a pristine context. - * const page = await context.newPage(); - * await page.goto('https://example.com'); - * - * // Gracefully close up everything - * await context.close(); - * await browser.close(); - * })(); - * ``` - * - * @param options - */ - newContext(options?: BrowserContextOptions): Promise; - - /** - * Creates a new page in a new browser context. Closing this page will close the context as well. - * - * This is a convenience API that should only be used for the single-page scenarios and short snippets. Production - * code and testing frameworks should explicitly create - * [browser.newContext([options])](https://playwright.dev/docs/api/class-browser#browser-new-context) followed by the - * [browserContext.newPage()](https://playwright.dev/docs/api/class-browsercontext#browser-context-new-page) to - * control their exact life times. - * @param options - */ - newPage(options?: { - /** - * Whether to automatically download all the attachments. Defaults to `true` where all the downloads are accepted. - */ - acceptDownloads?: boolean; - - /** - * When using [page.goto(url[, options])](https://playwright.dev/docs/api/class-page#page-goto), - * [page.route(url, handler[, options])](https://playwright.dev/docs/api/class-page#page-route), - * [page.waitForURL(url[, options])](https://playwright.dev/docs/api/class-page#page-wait-for-url), - * [page.waitForRequest(urlOrPredicate[, options])](https://playwright.dev/docs/api/class-page#page-wait-for-request), - * or - * [page.waitForResponse(urlOrPredicate[, options])](https://playwright.dev/docs/api/class-page#page-wait-for-response) - * it takes the base URL in consideration by using the - * [`URL()`](https://developer.mozilla.org/en-US/docs/Web/API/URL/URL) constructor for building the corresponding URL. - * Unset by default. Examples: - * - baseURL: `http://localhost:3000` and navigating to `/bar.html` results in `http://localhost:3000/bar.html` - * - baseURL: `http://localhost:3000/foo/` and navigating to `./bar.html` results in - * `http://localhost:3000/foo/bar.html` - * - baseURL: `http://localhost:3000/foo` (without trailing slash) and navigating to `./bar.html` results in - * `http://localhost:3000/bar.html` - */ - baseURL?: string; - - /** - * Toggles bypassing page's Content-Security-Policy. Defaults to `false`. - */ - bypassCSP?: boolean; - - /** - * TLS Client Authentication allows the server to request a client certificate and verify it. - * - * **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. 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. - * - * **NOTE** When using WebKit on macOS, accessing `localhost` will not pick up client certificates. You can make it - * work by replacing `localhost` with `local.playwright`. - */ - clientCertificates?: Array<{ - /** - * Exact origin that the certificate is valid for. Origin includes `https` protocol, a hostname and optionally a port. - */ - origin: string; - - /** - * Path to the file with the certificate in PEM format. - */ - certPath?: string; - - /** - * Path to the file with the private key in PEM format. - */ - keyPath?: string; - - /** - * Path to the PFX or PKCS12 encoded private key and certificate chain. - */ - pfxPath?: string; - - /** - * Passphrase for the private key (PEM or PFX). - */ - passphrase?: string; - }>; - - /** - * Emulates `'prefers-colors-scheme'` media feature, supported values are `'light'`, `'dark'`, `'no-preference'`. See - * [page.emulateMedia([options])](https://playwright.dev/docs/api/class-page#page-emulate-media) for more details. - * Passing `null` resets emulation to system defaults. Defaults to `'light'`. - */ - colorScheme?: null|"light"|"dark"|"no-preference"; - - /** - * Specify device scale factor (can be thought of as dpr). Defaults to `1`. Learn more about - * [emulating devices with device scale factor](https://playwright.dev/docs/emulation#devices). - */ - deviceScaleFactor?: number; - - /** - * An object containing additional HTTP headers to be sent with every request. Defaults to none. - */ - extraHTTPHeaders?: { [key: string]: string; }; - - /** - * Emulates `'forced-colors'` media feature, supported values are `'active'`, `'none'`. See - * [page.emulateMedia([options])](https://playwright.dev/docs/api/class-page#page-emulate-media) for more details. - * Passing `null` resets emulation to system defaults. Defaults to `'none'`. - */ - forcedColors?: null|"active"|"none"; - - geolocation?: { - /** - * Latitude between -90 and 90. - */ - latitude: number; - - /** - * Longitude between -180 and 180. - */ - longitude: number; - - /** - * Non-negative accuracy value. Defaults to `0`. - */ - accuracy?: number; - }; - - /** - * Specifies if viewport supports touch events. Defaults to false. Learn more about - * [mobile emulation](https://playwright.dev/docs/emulation#devices). - */ - hasTouch?: boolean; - - /** - * Credentials for [HTTP authentication](https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication). If no - * origin is specified, the username and password are sent to any servers upon unauthorized responses. - */ - httpCredentials?: { - username: string; - - password: string; - - /** - * Restrain sending http credentials on specific origin (scheme://host:port). - */ - origin?: string; - - /** - * This option only applies to the requests sent from corresponding {@link APIRequestContext} and does not affect - * requests sent from the browser. `'always'` - `Authorization` header with basic authentication credentials will be - * sent with the each API request. `'unauthorized` - the credentials are only sent when 401 (Unauthorized) response - * with `WWW-Authenticate` header is received. Defaults to `'unauthorized'`. - */ - send?: "unauthorized"|"always"; - }; - - /** - * Whether to ignore HTTPS errors when sending network requests. Defaults to `false`. - */ - ignoreHTTPSErrors?: boolean; - - /** - * Whether the `meta viewport` tag is taken into account and touch events are enabled. isMobile is a part of device, - * so you don't actually need to set it manually. Defaults to `false` and is not supported in Firefox. Learn more - * about [mobile emulation](https://playwright.dev/docs/emulation#ismobile). - */ - isMobile?: boolean; - - /** - * Whether or not to enable JavaScript in the context. Defaults to `true`. Learn more about - * [disabling JavaScript](https://playwright.dev/docs/emulation#javascript-enabled). - */ - javaScriptEnabled?: boolean; - - /** - * Specify user locale, for example `en-GB`, `de-DE`, etc. Locale will affect `navigator.language` value, - * `Accept-Language` request header value as well as number and date formatting rules. Defaults to the system default - * locale. Learn more about emulation in our [emulation guide](https://playwright.dev/docs/emulation#locale--timezone). - */ - locale?: string; - - /** - * Logger sink for Playwright logging. - */ - logger?: Logger; - - /** - * Whether to emulate network being offline. Defaults to `false`. Learn more about - * [network emulation](https://playwright.dev/docs/emulation#offline). - */ - offline?: boolean; - - /** - * A list of permissions to grant to all pages in this context. See - * [browserContext.grantPermissions(permissions[, options])](https://playwright.dev/docs/api/class-browsercontext#browser-context-grant-permissions) - * for more details. Defaults to none. - */ - permissions?: Array; - - /** - * Network proxy settings to use with this context. Defaults to none. - * - * **NOTE** For Chromium on Windows the browser needs to be launched with the global proxy for this option to work. If - * all contexts override the proxy, global proxy will be never used and can be any string, for example `launch({ - * proxy: { server: 'http://per-context' } })`. - */ - proxy?: { - /** - * Proxy to be used for all requests. HTTP and SOCKS proxies are supported, for example `http://myproxy.com:3128` or - * `socks5://myproxy.com:3128`. Short form `myproxy.com:3128` is considered an HTTP proxy. - */ - server: string; - - /** - * Optional comma-separated domains to bypass proxy, for example `".com, chromium.org, .domain.com"`. - */ - bypass?: string; - - /** - * Optional username to use if HTTP proxy requires authentication. - */ - username?: string; - - /** - * Optional password to use if HTTP proxy requires authentication. - */ - password?: string; - }; - - /** - * Enables [HAR](http://www.softwareishard.com/blog/har-12-spec) recording for all pages into `recordHar.path` file. - * If not specified, the HAR is not recorded. Make sure to await - * [browserContext.close([options])](https://playwright.dev/docs/api/class-browsercontext#browser-context-close) for - * the HAR to be saved. - */ - recordHar?: { - /** - * Optional setting to control whether to omit request content from the HAR. Defaults to `false`. Deprecated, use - * `content` policy instead. - */ - omitContent?: boolean; - - /** - * Optional setting to control resource content management. If `omit` is specified, content is not persisted. If - * `attach` is specified, resources are persisted as separate files or entries in the ZIP archive. If `embed` is - * specified, content is stored inline the HAR file as per HAR specification. Defaults to `attach` for `.zip` output - * files and to `embed` for all other file extensions. - */ - content?: "omit"|"embed"|"attach"; - - /** - * Path on the filesystem to write the HAR file to. If the file name ends with `.zip`, `content: 'attach'` is used by - * default. - */ - path: string; - - /** - * When set to `minimal`, only record information necessary for routing from HAR. This omits sizes, timing, page, - * cookies, security and other types of HAR information that are not used when replaying from HAR. Defaults to `full`. - */ - mode?: "full"|"minimal"; - - /** - * A glob or regex pattern to filter requests that are stored in the HAR. When a `baseURL` via the context options was - * provided and the passed URL is a path, it gets merged via the - * [`new URL()`](https://developer.mozilla.org/en-US/docs/Web/API/URL/URL) constructor. Defaults to none. - */ - urlFilter?: string|RegExp; - }; - - /** - * Enables video recording for all pages into `recordVideo.dir` directory. If not specified videos are not recorded. - * Make sure to await - * [browserContext.close([options])](https://playwright.dev/docs/api/class-browsercontext#browser-context-close) for - * videos to be saved. - */ - recordVideo?: { - /** - * Path to the directory to put videos into. - */ - dir: string; - - /** - * Optional dimensions of the recorded videos. If not specified the size will be equal to `viewport` scaled down to - * fit into 800x800. If `viewport` is not configured explicitly the video size defaults to 800x450. Actual picture of - * each page will be scaled down if necessary to fit the specified size. - */ - size?: { - /** - * Video frame width. - */ - width: number; - - /** - * Video frame height. - */ - height: number; - }; - }; - - /** - * Emulates `'prefers-reduced-motion'` media feature, supported values are `'reduce'`, `'no-preference'`. See - * [page.emulateMedia([options])](https://playwright.dev/docs/api/class-page#page-emulate-media) for more details. - * Passing `null` resets emulation to system defaults. Defaults to `'no-preference'`. - */ - reducedMotion?: null|"reduce"|"no-preference"; - - /** - * Emulates consistent window screen size available inside web page via `window.screen`. Is only used when the - * `viewport` is set. - */ - screen?: { - /** - * page width in pixels. - */ - width: number; - - /** - * page height in pixels. - */ - height: number; - }; - - /** - * Whether to allow sites to register Service workers. Defaults to `'allow'`. - * - `'allow'`: [Service Workers](https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API) can be - * registered. - * - `'block'`: Playwright will block all registration of Service Workers. - */ - serviceWorkers?: "allow"|"block"; - - /** - * Learn more about [storage state and auth](https://playwright.dev/docs/auth). - * - * Populates context with given storage state. This option can be used to initialize context with logged-in - * information obtained via - * [browserContext.storageState([options])](https://playwright.dev/docs/api/class-browsercontext#browser-context-storage-state). - */ - storageState?: string|{ - /** - * Cookies to set for context - */ - cookies: Array<{ - name: string; - - value: string; - - /** - * Domain and path are required. For the cookie to apply to all subdomains as well, prefix domain with a dot, like - * this: ".example.com" - */ - domain: string; - - /** - * Domain and path are required - */ - path: string; - - /** - * Unix time in seconds. - */ - expires: number; - - httpOnly: boolean; - - secure: boolean; - - /** - * sameSite flag - */ - sameSite: "Strict"|"Lax"|"None"; - }>; - - /** - * localStorage to set for context - */ - origins: Array<{ - origin: string; - - localStorage: Array<{ - name: string; - - value: string; - }>; - }>; - }; - - /** - * If set to true, enables strict selectors mode for this context. In the strict selectors mode all operations on - * selectors that imply single target DOM element will throw when more than one element matches the selector. This - * option does not affect any Locator APIs (Locators are always strict). Defaults to `false`. See {@link Locator} to - * learn more about the strict mode. - */ - strictSelectors?: boolean; - - /** - * Changes the timezone of the context. See - * [ICU's metaZones.txt](https://cs.chromium.org/chromium/src/third_party/icu/source/data/misc/metaZones.txt?rcl=faee8bc70570192d82d2978a71e2a615788597d1) - * for a list of supported timezone IDs. Defaults to the system timezone. - */ - timezoneId?: string; - - /** - * Specific user agent to use in this context. - */ - userAgent?: string; - - /** - * @deprecated Use `recordVideo` instead. - */ - videoSize?: { - /** - * Video frame width. - */ - width: number; - - /** - * Video frame height. - */ - height: number; - }; - - /** - * @deprecated Use `recordVideo` instead. - */ - videosPath?: string; - - /** - * Emulates consistent viewport for each page. Defaults to an 1280x720 viewport. Use `null` to disable the consistent - * viewport emulation. Learn more about [viewport emulation](https://playwright.dev/docs/emulation#viewport). - * - * **NOTE** The `null` value opts out from the default presets, makes viewport depend on the host window size defined - * by the operating system. It makes the execution of the tests non-deterministic. - */ - viewport?: null|{ - /** - * page width in pixels. - */ - width: number; - - /** - * page height in pixels. - */ - height: number; - }; - }): Promise; - - /** - * **NOTE** This API controls - * [Chromium Tracing](https://www.chromium.org/developers/how-tos/trace-event-profiling-tool) which is a low-level - * chromium-specific debugging tool. API to control [Playwright Tracing](https://playwright.dev/docs/trace-viewer) could be found - * [here](https://playwright.dev/docs/api/class-tracing). - * - * You can use - * [browser.startTracing([page, options])](https://playwright.dev/docs/api/class-browser#browser-start-tracing) and - * [browser.stopTracing()](https://playwright.dev/docs/api/class-browser#browser-stop-tracing) to create a trace file - * that can be opened in Chrome DevTools performance panel. - * - * **Usage** - * - * ```js - * await browser.startTracing(page, { path: 'trace.json' }); - * await page.goto('https://www.google.com'); - * await browser.stopTracing(); - * ``` - * - * @param page Optional, if specified, tracing includes screenshots of the given page. - * @param options - */ - startTracing(page?: Page, options?: { - /** - * specify custom categories to use instead of default. - */ - categories?: Array; - - /** - * A path to write the trace file to. - */ - path?: string; - - /** - * captures screenshots in the trace. - */ - screenshots?: boolean; - }): Promise; - - /** - * **NOTE** This API controls - * [Chromium Tracing](https://www.chromium.org/developers/how-tos/trace-event-profiling-tool) which is a low-level - * chromium-specific debugging tool. API to control [Playwright Tracing](https://playwright.dev/docs/trace-viewer) could be found - * [here](https://playwright.dev/docs/api/class-tracing). - * - * Returns the buffer with trace data. - */ - stopTracing(): Promise; - - /** - * Returns the browser version. - */ - version(): string; - - [Symbol.asyncDispose](): Promise; -} - export interface BrowserServer { /** * Emitted when the browser server closes. @@ -20203,6 +20241,322 @@ export interface WebSocket { } +interface AccessibilitySnapshotOptions { + /** + * Prune uninteresting nodes from the tree. Defaults to `true`. + */ + interestingOnly?: boolean; + + /** + * The root DOM element for the snapshot. Defaults to the whole page. + */ + root?: ElementHandle; +} + +export interface LaunchOptions { + /** + * **NOTE** Use custom browser args at your own risk, as some of them may break Playwright functionality. + * + * Additional arguments to pass to the browser instance. The list of Chromium flags can be found + * [here](https://peter.sh/experiments/chromium-command-line-switches/). + */ + args?: Array; + + /** + * Browser distribution channel. Supported values are "chrome", "chrome-beta", "chrome-dev", "chrome-canary", + * "msedge", "msedge-beta", "msedge-dev", "msedge-canary". Read more about using + * [Google Chrome and Microsoft Edge](https://playwright.dev/docs/browsers#google-chrome--microsoft-edge). + */ + channel?: string; + + /** + * Enable Chromium sandboxing. Defaults to `false`. + */ + chromiumSandbox?: boolean; + + /** + * **Chromium-only** Whether to auto-open a Developer Tools panel for each tab. If this option is `true`, the + * `headless` option will be set `false`. + * @deprecated Use [debugging tools](https://playwright.dev/docs/debug) instead. + */ + devtools?: boolean; + + /** + * If specified, accepted downloads are downloaded into this directory. Otherwise, temporary directory is created and + * is deleted when browser is closed. In either case, the downloads are deleted when the browser context they were + * created in is closed. + */ + downloadsPath?: string; + + /** + * Specify environment variables that will be visible to the browser. Defaults to `process.env`. + */ + env?: { [key: string]: string|number|boolean; }; + + /** + * Path to a browser executable to run instead of the bundled one. If `executablePath` is a relative path, then it is + * resolved relative to the current working directory. Note that Playwright only works with the bundled Chromium, + * Firefox or WebKit, use at your own risk. + */ + executablePath?: string; + + /** + * Firefox user preferences. Learn more about the Firefox user preferences at + * [`about:config`](https://support.mozilla.org/en-US/kb/about-config-editor-firefox). + */ + firefoxUserPrefs?: { [key: string]: string|number|boolean; }; + + /** + * Close the browser process on SIGHUP. Defaults to `true`. + */ + handleSIGHUP?: boolean; + + /** + * Close the browser process on Ctrl-C. Defaults to `true`. + */ + handleSIGINT?: boolean; + + /** + * Close the browser process on SIGTERM. Defaults to `true`. + */ + handleSIGTERM?: boolean; + + /** + * Whether to run browser in headless mode. More details for + * [Chromium](https://developers.google.com/web/updates/2017/04/headless-chrome) and + * [Firefox](https://developer.mozilla.org/en-US/docs/Mozilla/Firefox/Headless_mode). Defaults to `true` unless the + * `devtools` option is `true`. + */ + headless?: boolean; + + /** + * If `true`, Playwright does not pass its own configurations args and only uses the ones from `args`. If an array is + * given, then filters out the given default arguments. Dangerous option; use with care. Defaults to `false`. + */ + ignoreDefaultArgs?: boolean|Array; + + /** + * Logger sink for Playwright logging. + */ + logger?: Logger; + + /** + * Network proxy settings. + */ + proxy?: { + /** + * Proxy to be used for all requests. HTTP and SOCKS proxies are supported, for example `http://myproxy.com:3128` or + * `socks5://myproxy.com:3128`. Short form `myproxy.com:3128` is considered an HTTP proxy. + */ + server: string; + + /** + * Optional comma-separated domains to bypass proxy, for example `".com, chromium.org, .domain.com"`. + */ + bypass?: string; + + /** + * Optional username to use if HTTP proxy requires authentication. + */ + username?: string; + + /** + * Optional password to use if HTTP proxy requires authentication. + */ + password?: string; + }; + + /** + * Slows down Playwright operations by the specified amount of milliseconds. Useful so that you can see what is going + * on. + */ + slowMo?: number; + + /** + * Maximum time in milliseconds to wait for the browser instance to start. Defaults to `30000` (30 seconds). Pass `0` + * to disable timeout. + */ + timeout?: number; + + /** + * If specified, traces are saved into this directory. + */ + tracesDir?: string; +} + +export interface ConnectOverCDPOptions { + /** + * Deprecated, use the first argument instead. Optional. + */ + endpointURL?: string; + + /** + * Additional HTTP headers to be sent with connect request. Optional. + */ + headers?: { [key: string]: string; }; + + /** + * Logger sink for Playwright logging. Optional. + */ + logger?: Logger; + + /** + * Slows down Playwright operations by the specified amount of milliseconds. Useful so that you can see what is going + * on. Defaults to 0. + */ + slowMo?: number; + + /** + * Maximum time in milliseconds to wait for the connection to be established. Defaults to `30000` (30 seconds). Pass + * `0` to disable timeout. + */ + timeout?: number; +} + +export interface ConnectOptions { + /** + * This option exposes network available on the connecting client to the browser being connected to. Consists of a + * list of rules separated by comma. + * + * Available rules: + * 1. Hostname pattern, for example: `example.com`, `*.org:99`, `x.*.y.com`, `*foo.org`. + * 1. IP literal, for example: `127.0.0.1`, `0.0.0.0:99`, `[::1]`, `[0:0::1]:99`. + * 1. `` that matches local loopback interfaces: `localhost`, `*.localhost`, `127.0.0.1`, `[::1]`. + * + * Some common examples: + * 1. `"*"` to expose all network. + * 1. `""` to expose localhost network. + * 1. `"*.test.internal-domain,*.staging.internal-domain,"` to expose test/staging deployments and + * localhost. + */ + exposeNetwork?: string; + + /** + * Additional HTTP headers to be sent with web socket connect request. Optional. + */ + headers?: { [key: string]: string; }; + + /** + * Logger sink for Playwright logging. Optional. + */ + logger?: Logger; + + /** + * Slows down Playwright operations by the specified amount of milliseconds. Useful so that you can see what is going + * on. Defaults to 0. + */ + slowMo?: number; + + /** + * Maximum time in milliseconds to wait for the connection to be established. Defaults to `0` (no timeout). + */ + timeout?: number; +} + +export interface LocatorScreenshotOptions { + /** + * When set to `"disabled"`, stops CSS animations, CSS transitions and Web Animations. Animations get different + * treatment depending on their duration: + * - finite animations are fast-forwarded to completion, so they'll fire `transitionend` event. + * - infinite animations are canceled to initial state, and then played over after the screenshot. + * + * Defaults to `"allow"` that leaves animations untouched. + */ + animations?: "disabled"|"allow"; + + /** + * When set to `"hide"`, screenshot will hide text caret. When set to `"initial"`, text caret behavior will not be + * changed. Defaults to `"hide"`. + */ + caret?: "hide"|"initial"; + + /** + * Specify locators that should be masked when the screenshot is taken. Masked elements will be overlaid with a pink + * box `#FF00FF` (customized by `maskColor`) that completely covers its bounding box. + */ + mask?: Array; + + /** + * Specify the color of the overlay box for masked elements, in + * [CSS color format](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value). Default color is pink `#FF00FF`. + */ + maskColor?: string; + + /** + * Hides default white background and allows capturing screenshots with transparency. Not applicable to `jpeg` images. + * Defaults to `false`. + */ + omitBackground?: boolean; + + /** + * The file path to save the image to. The screenshot type will be inferred from file extension. If `path` is a + * relative path, then it is resolved relative to the current working directory. If no path is provided, the image + * won't be saved to the disk. + */ + path?: string; + + /** + * The quality of the image, between 0-100. Not applicable to `png` images. + */ + quality?: number; + + /** + * When set to `"css"`, screenshot will have a single pixel per each css pixel on the page. For high-dpi devices, this + * will keep screenshots small. Using `"device"` option will produce a single pixel per each device pixel, so + * screenshots of high-dpi devices will be twice as large or even larger. + * + * Defaults to `"device"`. + */ + scale?: "css"|"device"; + + /** + * Text of the stylesheet to apply while making the screenshot. This is where you can hide dynamic elements, make + * elements invisible or change their properties to help you creating repeatable screenshots. This stylesheet pierces + * the Shadow DOM and applies to the inner frames. + */ + style?: string; + + /** + * Maximum time in milliseconds. Defaults to `0` - no timeout. The default value can be changed via `actionTimeout` + * option in the config, or by using the + * [browserContext.setDefaultTimeout(timeout)](https://playwright.dev/docs/api/class-browsercontext#browser-context-set-default-timeout) + * or [page.setDefaultTimeout(timeout)](https://playwright.dev/docs/api/class-page#page-set-default-timeout) methods. + */ + timeout?: number; + + /** + * Specify screenshot type, defaults to `png`. + */ + type?: "png"|"jpeg"; +} + +interface ElementHandleWaitForSelectorOptions { + /** + * Defaults to `'visible'`. Can be either: + * - `'attached'` - wait for element to be present in DOM. + * - `'detached'` - wait for element to not be present in DOM. + * - `'visible'` - wait for element to have non-empty bounding box and no `visibility:hidden`. Note that element + * without any content or with `display:none` has an empty bounding box and is not considered visible. + * - `'hidden'` - wait for element to be either detached from DOM, or have an empty bounding box or + * `visibility:hidden`. This is opposite to the `'visible'` option. + */ + state?: "attached"|"detached"|"visible"|"hidden"; + + /** + * When true, the call requires selector to resolve to a single element. If given selector resolves to more than one + * element, the call throws an exception. + */ + strict?: boolean; + + /** + * Maximum time in milliseconds. Defaults to `0` - no timeout. The default value can be changed via `actionTimeout` + * option in the config, or by using the + * [browserContext.setDefaultTimeout(timeout)](https://playwright.dev/docs/api/class-browsercontext#browser-context-set-default-timeout) + * or [page.setDefaultTimeout(timeout)](https://playwright.dev/docs/api/class-page#page-set-default-timeout) methods. + */ + timeout?: number; +} + export interface BrowserContextOptions { /** * Whether to automatically download all the attachments. Defaults to `true` where all the downloads are accepted. @@ -20642,322 +20996,6 @@ export interface Geolocation { accuracy?: number; } -interface AccessibilitySnapshotOptions { - /** - * Prune uninteresting nodes from the tree. Defaults to `true`. - */ - interestingOnly?: boolean; - - /** - * The root DOM element for the snapshot. Defaults to the whole page. - */ - root?: ElementHandle; -} - -export interface LaunchOptions { - /** - * **NOTE** Use custom browser args at your own risk, as some of them may break Playwright functionality. - * - * Additional arguments to pass to the browser instance. The list of Chromium flags can be found - * [here](https://peter.sh/experiments/chromium-command-line-switches/). - */ - args?: Array; - - /** - * Browser distribution channel. Supported values are "chrome", "chrome-beta", "chrome-dev", "chrome-canary", - * "msedge", "msedge-beta", "msedge-dev", "msedge-canary". Read more about using - * [Google Chrome and Microsoft Edge](https://playwright.dev/docs/browsers#google-chrome--microsoft-edge). - */ - channel?: string; - - /** - * Enable Chromium sandboxing. Defaults to `false`. - */ - chromiumSandbox?: boolean; - - /** - * **Chromium-only** Whether to auto-open a Developer Tools panel for each tab. If this option is `true`, the - * `headless` option will be set `false`. - * @deprecated Use [debugging tools](https://playwright.dev/docs/debug) instead. - */ - devtools?: boolean; - - /** - * If specified, accepted downloads are downloaded into this directory. Otherwise, temporary directory is created and - * is deleted when browser is closed. In either case, the downloads are deleted when the browser context they were - * created in is closed. - */ - downloadsPath?: string; - - /** - * Specify environment variables that will be visible to the browser. Defaults to `process.env`. - */ - env?: { [key: string]: string|number|boolean; }; - - /** - * Path to a browser executable to run instead of the bundled one. If `executablePath` is a relative path, then it is - * resolved relative to the current working directory. Note that Playwright only works with the bundled Chromium, - * Firefox or WebKit, use at your own risk. - */ - executablePath?: string; - - /** - * Firefox user preferences. Learn more about the Firefox user preferences at - * [`about:config`](https://support.mozilla.org/en-US/kb/about-config-editor-firefox). - */ - firefoxUserPrefs?: { [key: string]: string|number|boolean; }; - - /** - * Close the browser process on SIGHUP. Defaults to `true`. - */ - handleSIGHUP?: boolean; - - /** - * Close the browser process on Ctrl-C. Defaults to `true`. - */ - handleSIGINT?: boolean; - - /** - * Close the browser process on SIGTERM. Defaults to `true`. - */ - handleSIGTERM?: boolean; - - /** - * Whether to run browser in headless mode. More details for - * [Chromium](https://developers.google.com/web/updates/2017/04/headless-chrome) and - * [Firefox](https://developer.mozilla.org/en-US/docs/Mozilla/Firefox/Headless_mode). Defaults to `true` unless the - * `devtools` option is `true`. - */ - headless?: boolean; - - /** - * If `true`, Playwright does not pass its own configurations args and only uses the ones from `args`. If an array is - * given, then filters out the given default arguments. Dangerous option; use with care. Defaults to `false`. - */ - ignoreDefaultArgs?: boolean|Array; - - /** - * Logger sink for Playwright logging. - */ - logger?: Logger; - - /** - * Network proxy settings. - */ - proxy?: { - /** - * Proxy to be used for all requests. HTTP and SOCKS proxies are supported, for example `http://myproxy.com:3128` or - * `socks5://myproxy.com:3128`. Short form `myproxy.com:3128` is considered an HTTP proxy. - */ - server: string; - - /** - * Optional comma-separated domains to bypass proxy, for example `".com, chromium.org, .domain.com"`. - */ - bypass?: string; - - /** - * Optional username to use if HTTP proxy requires authentication. - */ - username?: string; - - /** - * Optional password to use if HTTP proxy requires authentication. - */ - password?: string; - }; - - /** - * Slows down Playwright operations by the specified amount of milliseconds. Useful so that you can see what is going - * on. - */ - slowMo?: number; - - /** - * Maximum time in milliseconds to wait for the browser instance to start. Defaults to `30000` (30 seconds). Pass `0` - * to disable timeout. - */ - timeout?: number; - - /** - * If specified, traces are saved into this directory. - */ - tracesDir?: string; -} - -export interface ConnectOverCDPOptions { - /** - * Deprecated, use the first argument instead. Optional. - */ - endpointURL?: string; - - /** - * Additional HTTP headers to be sent with connect request. Optional. - */ - headers?: { [key: string]: string; }; - - /** - * Logger sink for Playwright logging. Optional. - */ - logger?: Logger; - - /** - * Slows down Playwright operations by the specified amount of milliseconds. Useful so that you can see what is going - * on. Defaults to 0. - */ - slowMo?: number; - - /** - * Maximum time in milliseconds to wait for the connection to be established. Defaults to `30000` (30 seconds). Pass - * `0` to disable timeout. - */ - timeout?: number; -} - -export interface ConnectOptions { - /** - * This option exposes network available on the connecting client to the browser being connected to. Consists of a - * list of rules separated by comma. - * - * Available rules: - * 1. Hostname pattern, for example: `example.com`, `*.org:99`, `x.*.y.com`, `*foo.org`. - * 1. IP literal, for example: `127.0.0.1`, `0.0.0.0:99`, `[::1]`, `[0:0::1]:99`. - * 1. `` that matches local loopback interfaces: `localhost`, `*.localhost`, `127.0.0.1`, `[::1]`. - * - * Some common examples: - * 1. `"*"` to expose all network. - * 1. `""` to expose localhost network. - * 1. `"*.test.internal-domain,*.staging.internal-domain,"` to expose test/staging deployments and - * localhost. - */ - exposeNetwork?: string; - - /** - * Additional HTTP headers to be sent with web socket connect request. Optional. - */ - headers?: { [key: string]: string; }; - - /** - * Logger sink for Playwright logging. Optional. - */ - logger?: Logger; - - /** - * Slows down Playwright operations by the specified amount of milliseconds. Useful so that you can see what is going - * on. Defaults to 0. - */ - slowMo?: number; - - /** - * Maximum time in milliseconds to wait for the connection to be established. Defaults to `0` (no timeout). - */ - timeout?: number; -} - -export interface LocatorScreenshotOptions { - /** - * When set to `"disabled"`, stops CSS animations, CSS transitions and Web Animations. Animations get different - * treatment depending on their duration: - * - finite animations are fast-forwarded to completion, so they'll fire `transitionend` event. - * - infinite animations are canceled to initial state, and then played over after the screenshot. - * - * Defaults to `"allow"` that leaves animations untouched. - */ - animations?: "disabled"|"allow"; - - /** - * When set to `"hide"`, screenshot will hide text caret. When set to `"initial"`, text caret behavior will not be - * changed. Defaults to `"hide"`. - */ - caret?: "hide"|"initial"; - - /** - * Specify locators that should be masked when the screenshot is taken. Masked elements will be overlaid with a pink - * box `#FF00FF` (customized by `maskColor`) that completely covers its bounding box. - */ - mask?: Array; - - /** - * Specify the color of the overlay box for masked elements, in - * [CSS color format](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value). Default color is pink `#FF00FF`. - */ - maskColor?: string; - - /** - * Hides default white background and allows capturing screenshots with transparency. Not applicable to `jpeg` images. - * Defaults to `false`. - */ - omitBackground?: boolean; - - /** - * The file path to save the image to. The screenshot type will be inferred from file extension. If `path` is a - * relative path, then it is resolved relative to the current working directory. If no path is provided, the image - * won't be saved to the disk. - */ - path?: string; - - /** - * The quality of the image, between 0-100. Not applicable to `png` images. - */ - quality?: number; - - /** - * When set to `"css"`, screenshot will have a single pixel per each css pixel on the page. For high-dpi devices, this - * will keep screenshots small. Using `"device"` option will produce a single pixel per each device pixel, so - * screenshots of high-dpi devices will be twice as large or even larger. - * - * Defaults to `"device"`. - */ - scale?: "css"|"device"; - - /** - * Text of the stylesheet to apply while making the screenshot. This is where you can hide dynamic elements, make - * elements invisible or change their properties to help you creating repeatable screenshots. This stylesheet pierces - * the Shadow DOM and applies to the inner frames. - */ - style?: string; - - /** - * Maximum time in milliseconds. Defaults to `0` - no timeout. The default value can be changed via `actionTimeout` - * option in the config, or by using the - * [browserContext.setDefaultTimeout(timeout)](https://playwright.dev/docs/api/class-browsercontext#browser-context-set-default-timeout) - * or [page.setDefaultTimeout(timeout)](https://playwright.dev/docs/api/class-page#page-set-default-timeout) methods. - */ - timeout?: number; - - /** - * Specify screenshot type, defaults to `png`. - */ - type?: "png"|"jpeg"; -} - -interface ElementHandleWaitForSelectorOptions { - /** - * Defaults to `'visible'`. Can be either: - * - `'attached'` - wait for element to be present in DOM. - * - `'detached'` - wait for element to not be present in DOM. - * - `'visible'` - wait for element to have non-empty bounding box and no `visibility:hidden`. Note that element - * without any content or with `display:none` has an empty bounding box and is not considered visible. - * - `'hidden'` - wait for element to be either detached from DOM, or have an empty bounding box or - * `visibility:hidden`. This is opposite to the `'visible'` option. - */ - state?: "attached"|"detached"|"visible"|"hidden"; - - /** - * When true, the call requires selector to resolve to a single element. If given selector resolves to more than one - * element, the call throws an exception. - */ - strict?: boolean; - - /** - * Maximum time in milliseconds. Defaults to `0` - no timeout. The default value can be changed via `actionTimeout` - * option in the config, or by using the - * [browserContext.setDefaultTimeout(timeout)](https://playwright.dev/docs/api/class-browsercontext#browser-context-set-default-timeout) - * or [page.setDefaultTimeout(timeout)](https://playwright.dev/docs/api/class-page#page-set-default-timeout) methods. - */ - timeout?: number; -} - export interface Cookie { name: string; diff --git a/tests/library/events/listener-count.spec.ts b/tests/library/events/listener-count.spec.ts index 8fae8cdfad..d8aaf867a3 100644 --- a/tests/library/events/listener-count.spec.ts +++ b/tests/library/events/listener-count.spec.ts @@ -20,7 +20,6 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE // USE OR OTHER DEALINGS IN THE SOFTWARE. -import events from 'events'; import { EventEmitter } from '../../../packages/playwright-core/lib/client/eventEmitter'; import { test, expect } from '@playwright/test'; @@ -32,7 +31,6 @@ test('Listener count test', () => { // Allow any type emitter.on(123, () => {}); - expect(events.listenerCount(emitter, 'foo')).toEqual(2); expect(emitter.listenerCount('foo')).toEqual(2); expect(emitter.listenerCount('bar')).toEqual(0); expect(emitter.listenerCount('baz')).toEqual(1); diff --git a/tests/library/events/listeners.spec.ts b/tests/library/events/listeners.spec.ts index 4553ed92aa..86803af178 100644 --- a/tests/library/events/listeners.spec.ts +++ b/tests/library/events/listeners.spec.ts @@ -40,7 +40,7 @@ test('EventEmitter listeners with one listener', () => { expect(listeners).toHaveLength(1); expect(listeners[0]).toEqual(listener); - ee.removeAllListeners('foo'); + void ee.removeAllListeners('foo'); expect>(ee.listeners('foo')).toHaveLength(0); expect(Array.isArray(fooListeners)).toBeTruthy(); diff --git a/tests/library/events/modify-in-emit.spec.ts b/tests/library/events/modify-in-emit.spec.ts index 1d832aa650..25937977f4 100644 --- a/tests/library/events/modify-in-emit.spec.ts +++ b/tests/library/events/modify-in-emit.spec.ts @@ -72,7 +72,7 @@ test('add and remove listeners', () => { e.on('foo', callback1); e.on('foo', callback2); expect(e.listeners('foo')).toHaveLength(2); - e.removeAllListeners('foo'); + void e.removeAllListeners('foo'); expect(e.listeners('foo')).toHaveLength(0); }); diff --git a/tests/library/events/remove-all-listeners-wait.spec.ts b/tests/library/events/remove-all-listeners-wait.spec.ts new file mode 100644 index 0000000000..1f8dcc8dd0 --- /dev/null +++ b/tests/library/events/remove-all-listeners-wait.spec.ts @@ -0,0 +1,80 @@ +/** + * Copyright 2018 Google Inc. All rights reserved. + * Modifications copyright (c) Microsoft Corporation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ManualPromise } from '../../../packages/playwright-core/lib/utils/manualPromise'; +import { EventEmitter } from '../../../packages/playwright-core/lib/client/eventEmitter'; +import { test, expect } from '@playwright/test'; + +test('should not throw with ignoreErrors', async () => { + const ee = new EventEmitter(); + const releaseHandler = new ManualPromise(); + ee.on('console', async () => { + await releaseHandler; + throw new Error('Error in console handler'); + }); + ee.emit('console'); + await ee.removeAllListeners('console', { behavior: 'ignoreErrors' }); + releaseHandler.resolve(); +}); + +test('should wait', async () => { + const ee = new EventEmitter(); + const releaseHandler = new ManualPromise(); + let value = 0; + ee.on('console', async () => { + await releaseHandler; + value = 42; + }); + ee.emit('console'); + const removePromise = ee.removeAllListeners('console', { behavior: 'wait' }); + releaseHandler.resolve(); + await removePromise; + expect(value).toBe(42); +}); + +test('should wait all', async () => { + const ee = new EventEmitter(); + const releaseHandler = new ManualPromise(); + const values = []; + ee.on('a', async () => { + await releaseHandler; + values.push(42); + }); + ee.on('b', async () => { + await releaseHandler; + values.push(43); + }); + ee.emit('a'); + ee.emit('b'); + const removePromise = ee.removeAllListeners(undefined, { behavior: 'wait' }); + releaseHandler.resolve(); + await removePromise; + expect(values).toEqual([42, 43]); +}); + +test('wait should throw', async () => { + const ee = new EventEmitter(); + const releaseHandler = new ManualPromise(); + ee.on('console', async () => { + await releaseHandler; + throw new Error('Error in handler'); + }); + ee.emit('console'); + const removePromise = ee.removeAllListeners('console', { behavior: 'wait' }); + releaseHandler.resolve(); + await expect(removePromise).rejects.toThrow('Error in handler'); +}); diff --git a/tests/library/events/remove-all-listeners.spec.ts b/tests/library/events/remove-all-listeners.spec.ts index 116b9e768c..275c0700ff 100644 --- a/tests/library/events/remove-all-listeners.spec.ts +++ b/tests/library/events/remove-all-listeners.spec.ts @@ -58,8 +58,8 @@ test('listeners', () => { const barListeners = ee.listeners('bar'); const bazListeners = ee.listeners('baz'); ee.on('removeListener', expectWrapper(['bar', 'baz', 'baz'])); - ee.removeAllListeners('bar'); - ee.removeAllListeners('baz'); + void ee.removeAllListeners('bar'); + void ee.removeAllListeners('baz'); let listeners = ee.listeners('foo'); expect(Array.isArray(listeners)).toBeTruthy(); @@ -91,7 +91,7 @@ test('removeAllListeners removes all listeners', () => { ee.on('bar', () => { }); ee.on('removeListener', expectWrapper(['foo', 'bar', 'removeListener'])); ee.on('removeListener', expectWrapper(['foo', 'bar'])); - ee.removeAllListeners(); + void ee.removeAllListeners(); let listeners = ee.listeners('foo'); expect(Array.isArray(listeners)).toBeTruthy(); @@ -120,7 +120,7 @@ test('listener count after removeAllListeners', () => { ee.on('baz', () => { }); ee.on('baz', () => { }); expect(ee.listeners('baz').length).toEqual(expectLength + 1); - ee.removeAllListeners('baz'); + void ee.removeAllListeners('baz'); expect(ee.listeners('baz').length).toEqual(0); }); diff --git a/tests/library/events/subclass.spec.ts b/tests/library/events/subclass.spec.ts index 37b548a92a..3852657b8d 100644 --- a/tests/library/events/subclass.spec.ts +++ b/tests/library/events/subclass.spec.ts @@ -28,7 +28,7 @@ class MyEE extends EventEmitter { super(); this.once(1, cb); this.emit(1); - this.removeAllListeners(); + void this.removeAllListeners(); } } diff --git a/tests/library/events/symbols.spec.ts b/tests/library/events/symbols.spec.ts index 7efb00f189..1c143def37 100644 --- a/tests/library/events/symbols.spec.ts +++ b/tests/library/events/symbols.spec.ts @@ -34,7 +34,7 @@ test('should support symbols', () => { ee.emit(foo); - ee.removeAllListeners(); + void ee.removeAllListeners(); expect(ee.listeners(foo).length).toEqual(0); ee.on(foo, listener); diff --git a/tests/page/page-listeners.spec.ts b/tests/page/page-listeners.spec.ts new file mode 100644 index 0000000000..c22be64553 --- /dev/null +++ b/tests/page/page-listeners.spec.ts @@ -0,0 +1,67 @@ +/** + * Copyright 2018 Google Inc. All rights reserved. + * Modifications copyright (c) Microsoft Corporation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ManualPromise } from '../../packages/playwright-core/lib/utils/manualPromise'; +import { test as it, expect } from './pageTest'; + +// This test is mostly for type checking, the actual tests are in the library/events. + +it('should not throw with ignoreErrors', async ({ page }) => { + const reachedHandler = new ManualPromise(); + const releaseHandler = new ManualPromise(); + page.on('console', async () => { + reachedHandler.resolve(); + await releaseHandler; + throw new Error('Error in console handler'); + }); + await page.evaluate('console.log(1)'); + await reachedHandler; + await page.removeAllListeners('console', { behavior: 'ignoreErrors' }); + releaseHandler.resolve(); + await page.waitForTimeout(1000); +}); + +it('should wait', async ({ page }) => { + const reachedHandler = new ManualPromise(); + const releaseHandler = new ManualPromise(); + let value = 0; + page.on('console', async () => { + reachedHandler.resolve(); + value = 42; + }); + await page.evaluate('console.log(1)'); + await reachedHandler; + const removePromise = page.removeAllListeners('console', { behavior: 'wait' }); + releaseHandler.resolve(); + await removePromise; + expect(value).toBe(42); +}); + +it('wait should throw', async ({ page }) => { + const reachedHandler = new ManualPromise(); + const releaseHandler = new ManualPromise(); + page.on('console', async () => { + reachedHandler.resolve(); + await releaseHandler; + throw new Error('Error in handler'); + }); + await page.evaluate('console.log(1)'); + await reachedHandler; + const removePromise = page.removeAllListeners('console', { behavior: 'wait' }); + releaseHandler.resolve(); + await expect(removePromise).rejects.toThrow('Error in handler'); +}); diff --git a/utils/doclint/missingDocs.js b/utils/doclint/missingDocs.js index 8042bc4222..7fffc156dc 100644 --- a/utils/doclint/missingDocs.js +++ b/utils/doclint/missingDocs.js @@ -56,7 +56,7 @@ module.exports = function lint(documentation, jsSources, apiFileName) { continue; } for (const member of cls.membersArray) { - if (member.kind === 'event') + if (member.kind === 'event' || member.alias === 'removeAllListeners') continue; const params = methods.get(member.alias); if (!params) { diff --git a/utils/generate_types/overrides.d.ts b/utils/generate_types/overrides.d.ts index 1f90713e92..578602959a 100644 --- a/utils/generate_types/overrides.d.ts +++ b/utils/generate_types/overrides.d.ts @@ -62,6 +62,9 @@ export interface Page { exposeBinding(name: string, playwrightBinding: (source: BindingSource, arg: JSHandle) => any, options: { handle: true }): Promise; exposeBinding(name: string, playwrightBinding: (source: BindingSource, ...args: any[]) => any, options?: { handle?: boolean }): Promise; + + removeAllListeners(type?: string): this; + removeAllListeners(type: string | undefined, options: { behavior?: 'wait'|'ignoreErrors'|'default' }): Promise; } export interface Frame { @@ -101,6 +104,14 @@ export interface BrowserContext { exposeBinding(name: string, playwrightBinding: (source: BindingSource, ...args: any[]) => any, options?: { handle?: boolean }): Promise; addInitScript(script: PageFunction | { path?: string, content?: string }, arg?: Arg): Promise; + + removeAllListeners(type?: string): this; + removeAllListeners(type: string | undefined, options: { behavior?: 'wait'|'ignoreErrors'|'default' }): Promise; +} + +export interface Browser { + removeAllListeners(type?: string): this; + removeAllListeners(type: string | undefined, options: { behavior?: 'wait'|'ignoreErrors'|'default' }): Promise; } export interface Worker {