mirror of
https://github.com/microsoft/playwright.git
synced 2024-11-30 23:45:33 +03:00
feat: add support for browserContext.on('pageerror') (#24452)
+ fix #24466 + Adds support for exposing the `pageerror` events via `browserContext` API. + Helps with capturing the overall exceptions that are thrown outside of the the current page and also captures the exceptions happens on other windows/popups. + Keeps the API in sync with `context.on('request)', context.on('console'), etc..`
This commit is contained in:
parent
2c4897094b
commit
adc9b2d390
@ -239,6 +239,13 @@ Use [`method: Page.waitForLoadState`] to wait until the page gets to a particula
|
||||
cases).
|
||||
:::
|
||||
|
||||
## event: BrowserContext.pageError
|
||||
* since: v1.38
|
||||
- argument: <[PageError]>
|
||||
|
||||
Emitted when unhandled exceptions occur on any pages created through this
|
||||
context. To only listen for `pageError` events from a particular page, use [`event: Page.pageError`].
|
||||
|
||||
## event: BrowserContext.request
|
||||
* since: v1.12
|
||||
- argument: <[Request]>
|
||||
|
62
docs/src/api/class-pageerror.md
Normal file
62
docs/src/api/class-pageerror.md
Normal file
@ -0,0 +1,62 @@
|
||||
# class: PageError
|
||||
* since: v1.38
|
||||
|
||||
[PageError] class represents objects created by context when there are unhandled
|
||||
execeptions thrown on the pages and dispatched via the [`event: BrowserContext.pageError`] event.
|
||||
|
||||
```js
|
||||
// Log all uncaught errors to the terminal
|
||||
context.on('pageerror', pageerror => {
|
||||
console.log(`Uncaught exception: "${pageerror.error()}"`);
|
||||
});
|
||||
|
||||
// Navigate to a page with an exception.
|
||||
await page.goto('data:text/html,<script>throw new Error("Test")</script>');
|
||||
```
|
||||
|
||||
```java
|
||||
// Log all uncaught errors to the terminal
|
||||
context.onPageError(pagerror -> {
|
||||
System.out.println("Uncaught exception: " + pagerror.error());
|
||||
});
|
||||
|
||||
// Navigate to a page with an exception.
|
||||
page.navigate("data:text/html,<script>throw new Error('Test')</script>");
|
||||
```
|
||||
|
||||
```python async
|
||||
# Log all uncaught errors to the terminal
|
||||
context.on("pageerror", lambda pageerror: print(f"uncaught exception: {pageerror.error}"))
|
||||
|
||||
# Navigate to a page with an exception.
|
||||
await page.goto("data:text/html,<script>throw new Error('test')</script>")
|
||||
```
|
||||
|
||||
```python sync
|
||||
# Log all uncaught errors to the terminal
|
||||
context.on("pageerror", lambda pageerror: print(f"uncaught exception: {pageerror.error}"))
|
||||
|
||||
# Navigate to a page with an exception.
|
||||
page.goto("data:text/html,<script>throw new Error('test')</script>")
|
||||
```
|
||||
|
||||
```csharp
|
||||
// Log all uncaught errors to the terminal
|
||||
context.PageError += (_, pageerror) =>
|
||||
{
|
||||
Console.WriteLine("Uncaught exception: " + pageerror.Error);
|
||||
};
|
||||
```
|
||||
|
||||
## method: PageError.page
|
||||
* since: v1.38
|
||||
- returns: <[null]|[Page]>
|
||||
|
||||
The page that produced this unhandled exception, if any.
|
||||
|
||||
## method: PageError.error
|
||||
* since: v1.38
|
||||
- returns: <[Error]>
|
||||
|
||||
Unhandled error that was thrown.
|
||||
|
@ -42,3 +42,4 @@ export { Video } from './video';
|
||||
export { Worker } from './worker';
|
||||
export { CDPSession } from './cdpSession';
|
||||
export { Playwright } from './playwright';
|
||||
export { PageError } from './pageError';
|
||||
|
@ -41,6 +41,8 @@ import { rewriteErrorMessage } from '../utils/stackTrace';
|
||||
import { HarRouter } from './harRouter';
|
||||
import { ConsoleMessage } from './consoleMessage';
|
||||
import { Dialog } from './dialog';
|
||||
import { PageError } from './pageError';
|
||||
import { parseError } from '../protocol/serializers';
|
||||
|
||||
export class BrowserContext extends ChannelOwner<channels.BrowserContextChannel> implements api.BrowserContext {
|
||||
_pages = new Set<Page>();
|
||||
@ -100,6 +102,13 @@ export class BrowserContext extends ChannelOwner<channels.BrowserContextChannel>
|
||||
if (page)
|
||||
page.emit(Events.Page.Console, consoleMessage);
|
||||
});
|
||||
this._channel.on('pageError', ({ error, page }) => {
|
||||
const pageObject = Page.from(page);
|
||||
const parsedError = parseError(error);
|
||||
this.emit(Events.BrowserContext.PageError, new PageError(pageObject, parsedError));
|
||||
if (pageObject)
|
||||
pageObject.emit(Events.Page.PageError, parsedError);
|
||||
});
|
||||
this._channel.on('dialog', ({ dialog }) => {
|
||||
const dialogObject = Dialog.from(dialog);
|
||||
let hasListeners = this.emit(Events.BrowserContext.Dialog, dialogObject);
|
||||
|
@ -39,6 +39,9 @@ export const Events = {
|
||||
Close: 'close',
|
||||
Dialog: 'dialog',
|
||||
Page: 'page',
|
||||
// Can't use just 'error' due to node.js special treatment of error events.
|
||||
// @see https://nodejs.org/api/events.html#events_error_events
|
||||
PageError: 'pageerror',
|
||||
BackgroundPage: 'backgroundpage',
|
||||
ServiceWorker: 'serviceworker',
|
||||
Request: 'request',
|
||||
|
@ -23,7 +23,7 @@ import { isSafeCloseError, kBrowserOrContextClosedError } from '../common/errors
|
||||
import { urlMatches } from '../utils/network';
|
||||
import { TimeoutSettings } from '../common/timeoutSettings';
|
||||
import type * as channels from '@protocol/channels';
|
||||
import { parseError, serializeError } from '../protocol/serializers';
|
||||
import { serializeError } from '../protocol/serializers';
|
||||
import { assert, headersObjectToArray, isObject, isRegExp, isString, LongStandingScope, urlMatchesEqual } from '../utils';
|
||||
import { mkdirIfNeeded } from '../utils/fileUtils';
|
||||
import { Accessibility } from './accessibility';
|
||||
@ -130,7 +130,6 @@ export class Page extends ChannelOwner<channels.PageChannel> implements api.Page
|
||||
this._channel.on('fileChooser', ({ element, isMultiple }) => this.emit(Events.Page.FileChooser, new FileChooser(this, ElementHandle.from(element), isMultiple)));
|
||||
this._channel.on('frameAttached', ({ frame }) => this._onFrameAttached(Frame.from(frame)));
|
||||
this._channel.on('frameDetached', ({ frame }) => this._onFrameDetached(Frame.from(frame)));
|
||||
this._channel.on('pageError', ({ error }) => this.emit(Events.Page.PageError, parseError(error)));
|
||||
this._channel.on('route', ({ route }) => this._onRoute(Route.from(route)));
|
||||
this._channel.on('video', ({ artifact }) => {
|
||||
const artifactObject = Artifact.from(artifact);
|
||||
|
36
packages/playwright-core/src/client/pageError.ts
Normal file
36
packages/playwright-core/src/client/pageError.ts
Normal file
@ -0,0 +1,36 @@
|
||||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import type * as api from '../../types/types';
|
||||
import type { Page } from './page';
|
||||
|
||||
export class PageError implements api.PageError {
|
||||
private _page: Page | null;
|
||||
private _error: Error;
|
||||
|
||||
constructor(page: Page | null, error: Error) {
|
||||
this._page = page;
|
||||
this._error = error;
|
||||
}
|
||||
|
||||
page() {
|
||||
return this._page;
|
||||
}
|
||||
|
||||
error() {
|
||||
return this._error;
|
||||
}
|
||||
}
|
@ -770,6 +770,10 @@ scheme.BrowserContextDialogEvent = tObject({
|
||||
scheme.BrowserContextPageEvent = tObject({
|
||||
page: tChannel(['Page']),
|
||||
});
|
||||
scheme.BrowserContextPageErrorEvent = tObject({
|
||||
error: tType('SerializedError'),
|
||||
page: tChannel(['Page']),
|
||||
});
|
||||
scheme.BrowserContextRouteEvent = tObject({
|
||||
route: tChannel(['Route']),
|
||||
});
|
||||
@ -957,9 +961,6 @@ scheme.PageFrameAttachedEvent = tObject({
|
||||
scheme.PageFrameDetachedEvent = tObject({
|
||||
frame: tChannel(['Frame']),
|
||||
});
|
||||
scheme.PagePageErrorEvent = tObject({
|
||||
error: tType('SerializedError'),
|
||||
});
|
||||
scheme.PageRouteEvent = tObject({
|
||||
route: tChannel(['Route']),
|
||||
});
|
||||
|
@ -48,6 +48,9 @@ export abstract class BrowserContext extends SdkObject {
|
||||
Close: 'close',
|
||||
Dialog: 'dialog',
|
||||
Page: 'page',
|
||||
// Can't use just 'error' due to node.js special treatment of error events.
|
||||
// @see https://nodejs.org/api/events.html#events_error_events
|
||||
PageError: 'pageerror',
|
||||
Request: 'request',
|
||||
Response: 'response',
|
||||
RequestFailed: 'requestfailed',
|
||||
|
@ -756,7 +756,7 @@ class FrameSession {
|
||||
const args = event.args.map(o => worker._existingExecutionContext!.createHandle(o));
|
||||
this._page._addConsoleMessage(event.type, args, toConsoleMessageLocation(event.stackTrace));
|
||||
});
|
||||
session.on('Runtime.exceptionThrown', exception => this._page.emit(Page.Events.PageError, exceptionToError(exception.exceptionDetails)));
|
||||
session.on('Runtime.exceptionThrown', exception => this._page.emitOnContextOnceInitialized(BrowserContext.Events.PageError, exceptionToError(exception.exceptionDetails), this._page));
|
||||
// TODO: attribute workers to the right frame.
|
||||
this._networkManager.instrumentNetworkEvents({ session, workerFrame: this._page._frameManager.frame(this._targetId) ?? undefined });
|
||||
}
|
||||
@ -859,7 +859,7 @@ class FrameSession {
|
||||
}
|
||||
|
||||
_handleException(exceptionDetails: Protocol.Runtime.ExceptionDetails) {
|
||||
this._page.firePageError(exceptionToError(exceptionDetails));
|
||||
this._page.emitOnContextOnceInitialized(BrowserContext.Events.PageError, exceptionToError(exceptionDetails), this._page);
|
||||
}
|
||||
|
||||
async _onTargetCrashed() {
|
||||
|
@ -38,6 +38,7 @@ import { DialogDispatcher } from './dialogDispatcher';
|
||||
import type { Page } from '../page';
|
||||
import type { Dialog } from '../dialog';
|
||||
import type { ConsoleMessage } from '../console';
|
||||
import { serializeError } from '../../protocol/serializers';
|
||||
|
||||
export class BrowserContextDispatcher extends Dispatcher<BrowserContext, channels.BrowserContextChannel, DispatcherScope> implements channels.BrowserContextChannel {
|
||||
_type_EventTarget = true;
|
||||
@ -84,6 +85,9 @@ export class BrowserContextDispatcher extends Dispatcher<BrowserContext, channel
|
||||
this._dispatchEvent('close');
|
||||
this._dispose();
|
||||
});
|
||||
this.addObjectListener(BrowserContext.Events.PageError, (error: Error, page: Page) => {
|
||||
this._dispatchEvent('pageError', { error: serializeError(error), page: PageDispatcher.from(this, page) });
|
||||
});
|
||||
this.addObjectListener(BrowserContext.Events.Console, (message: ConsoleMessage) => {
|
||||
if (this._shouldDispatchEvent(message.page(), 'console'))
|
||||
this._dispatchEvent('console', { message: new ConsoleMessageDispatcher(PageDispatcher.from(this, message.page()), message) });
|
||||
|
@ -19,7 +19,7 @@ import type { Frame } from '../frames';
|
||||
import { Page, Worker } from '../page';
|
||||
import type * as channels from '@protocol/channels';
|
||||
import { Dispatcher, existingDispatcher } from './dispatcher';
|
||||
import { parseError, serializeError } from '../../protocol/serializers';
|
||||
import { parseError } from '../../protocol/serializers';
|
||||
import { FrameDispatcher } from './frameDispatcher';
|
||||
import { RequestDispatcher } from './networkDispatchers';
|
||||
import { ResponseDispatcher } from './networkDispatchers';
|
||||
@ -85,7 +85,6 @@ export class PageDispatcher extends Dispatcher<Page, channels.PageChannel, Brows
|
||||
}));
|
||||
this.addObjectListener(Page.Events.FrameAttached, frame => this._onFrameAttached(frame));
|
||||
this.addObjectListener(Page.Events.FrameDetached, frame => this._onFrameDetached(frame));
|
||||
this.addObjectListener(Page.Events.PageError, error => this._dispatchEvent('pageError', { error: serializeError(error) }));
|
||||
this.addObjectListener(Page.Events.WebSocket, webSocket => this._dispatchEvent('webSocket', { webSocket: new WebSocketDispatcher(this, webSocket) }));
|
||||
this.addObjectListener(Page.Events.Worker, worker => this._dispatchEvent('worker', { worker: new WorkerDispatcher(this, worker) }));
|
||||
this.addObjectListener(Page.Events.Video, (artifact: Artifact) => this._dispatchEvent('video', { artifact: ArtifactDispatcher.from(parentScope, artifact) }));
|
||||
|
@ -246,7 +246,7 @@ export class FFPage implements PageDelegate {
|
||||
const error = new Error(message);
|
||||
error.stack = params.message + '\n' + params.stack.split('\n').filter(Boolean).map(a => a.replace(/([^@]*)@(.*)/, ' at $1 ($2)')).join('\n');
|
||||
error.name = name;
|
||||
this._page.firePageError(error);
|
||||
this._page.emitOnContextOnceInitialized(BrowserContext.Events.PageError, error, this._page);
|
||||
}
|
||||
|
||||
_onConsole(payload: Protocol.Runtime.consolePayload) {
|
||||
|
@ -125,9 +125,6 @@ export class Page extends SdkObject {
|
||||
Crash: 'crash',
|
||||
Download: 'download',
|
||||
FileChooser: 'filechooser',
|
||||
// Can't use just 'error' due to node.js special treatment of error events.
|
||||
// @see https://nodejs.org/api/events.html#events_error_events
|
||||
PageError: 'pageerror',
|
||||
FrameAttached: 'frameattached',
|
||||
FrameDetached: 'framedetached',
|
||||
InternalFrameNavigatedToNewDocument: 'internalframenavigatedtonewdocument',
|
||||
@ -696,10 +693,6 @@ export class Page extends SdkObject {
|
||||
this._frameThrottler.recharge();
|
||||
}
|
||||
|
||||
firePageError(error: Error) {
|
||||
this.emit(Page.Events.PageError, error);
|
||||
}
|
||||
|
||||
async hideHighlight() {
|
||||
await Promise.all(this.frames().map(frame => frame.hideHighlight().catch(() => {})));
|
||||
}
|
||||
|
@ -555,7 +555,7 @@ export class WKPage implements PageDelegate {
|
||||
error.stack = stack;
|
||||
error.name = name;
|
||||
|
||||
this._page.firePageError(error);
|
||||
this._page.emitOnContextOnceInitialized(BrowserContext.Events.PageError, error, this._page);
|
||||
return;
|
||||
}
|
||||
|
||||
|
72
packages/playwright-core/types/types.d.ts
vendored
72
packages/playwright-core/types/types.d.ts
vendored
@ -7636,6 +7636,13 @@ export interface BrowserContext {
|
||||
*/
|
||||
on(event: 'page', listener: (page: Page) => void): this;
|
||||
|
||||
/**
|
||||
* Emitted when unhandled exceptions occur on any pages created through this context. To only listen for `pageError`
|
||||
* events from a particular page, use
|
||||
* [page.on('pageerror')](https://playwright.dev/docs/api/class-page#page-event-page-error).
|
||||
*/
|
||||
on(event: 'pageerror', listener: (pageError: PageError) => void): this;
|
||||
|
||||
/**
|
||||
* Emitted when a request is issued from any pages created through this context. The [request] object is read-only. To
|
||||
* only listen for requests from a particular page, use
|
||||
@ -7706,6 +7713,11 @@ export interface BrowserContext {
|
||||
*/
|
||||
once(event: 'page', listener: (page: Page) => void): 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: 'pageerror', listener: (pageError: PageError) => void): this;
|
||||
|
||||
/**
|
||||
* Adds an event listener that will be automatically removed after it is triggered once. See `addListener` for more information about this event.
|
||||
*/
|
||||
@ -7817,6 +7829,13 @@ export interface BrowserContext {
|
||||
*/
|
||||
addListener(event: 'page', listener: (page: Page) => void): this;
|
||||
|
||||
/**
|
||||
* Emitted when unhandled exceptions occur on any pages created through this context. To only listen for `pageError`
|
||||
* events from a particular page, use
|
||||
* [page.on('pageerror')](https://playwright.dev/docs/api/class-page#page-event-page-error).
|
||||
*/
|
||||
addListener(event: 'pageerror', listener: (pageError: PageError) => void): this;
|
||||
|
||||
/**
|
||||
* Emitted when a request is issued from any pages created through this context. The [request] object is read-only. To
|
||||
* only listen for requests from a particular page, use
|
||||
@ -7887,6 +7906,11 @@ export interface BrowserContext {
|
||||
*/
|
||||
removeListener(event: 'page', listener: (page: Page) => void): this;
|
||||
|
||||
/**
|
||||
* Removes an event listener added by `on` or `addListener`.
|
||||
*/
|
||||
removeListener(event: 'pageerror', listener: (pageError: PageError) => void): this;
|
||||
|
||||
/**
|
||||
* Removes an event listener added by `on` or `addListener`.
|
||||
*/
|
||||
@ -7937,6 +7961,11 @@ export interface BrowserContext {
|
||||
*/
|
||||
off(event: 'page', listener: (page: Page) => void): this;
|
||||
|
||||
/**
|
||||
* Removes an event listener added by `on` or `addListener`.
|
||||
*/
|
||||
off(event: 'pageerror', listener: (pageError: PageError) => void): this;
|
||||
|
||||
/**
|
||||
* Removes an event listener added by `on` or `addListener`.
|
||||
*/
|
||||
@ -8048,6 +8077,13 @@ export interface BrowserContext {
|
||||
*/
|
||||
prependListener(event: 'page', listener: (page: Page) => void): this;
|
||||
|
||||
/**
|
||||
* Emitted when unhandled exceptions occur on any pages created through this context. To only listen for `pageError`
|
||||
* events from a particular page, use
|
||||
* [page.on('pageerror')](https://playwright.dev/docs/api/class-page#page-event-page-error).
|
||||
*/
|
||||
prependListener(event: 'pageerror', listener: (pageError: PageError) => void): this;
|
||||
|
||||
/**
|
||||
* Emitted when a request is issued from any pages created through this context. The [request] object is read-only. To
|
||||
* only listen for requests from a particular page, use
|
||||
@ -8634,6 +8670,13 @@ export interface BrowserContext {
|
||||
*/
|
||||
waitForEvent(event: 'page', optionsOrPredicate?: { predicate?: (page: Page) => boolean | Promise<boolean>, timeout?: number } | ((page: Page) => boolean | Promise<boolean>)): Promise<Page>;
|
||||
|
||||
/**
|
||||
* Emitted when unhandled exceptions occur on any pages created through this context. To only listen for `pageError`
|
||||
* events from a particular page, use
|
||||
* [page.on('pageerror')](https://playwright.dev/docs/api/class-page#page-event-page-error).
|
||||
*/
|
||||
waitForEvent(event: 'pageerror', optionsOrPredicate?: { predicate?: (pageError: PageError) => boolean | Promise<boolean>, timeout?: number } | ((pageError: PageError) => boolean | Promise<boolean>)): Promise<PageError>;
|
||||
|
||||
/**
|
||||
* Emitted when a request is issued from any pages created through this context. The [request] object is read-only. To
|
||||
* only listen for requests from a particular page, use
|
||||
@ -17900,6 +17943,35 @@ export interface Mouse {
|
||||
wheel(deltaX: number, deltaY: number): Promise<void>;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link PageError} class represents objects created by context when there are unhandled execeptions thrown on the
|
||||
* pages and dispatched via the
|
||||
* [browserContext.on('pageerror')](https://playwright.dev/docs/api/class-browsercontext#browser-context-event-page-error)
|
||||
* event.
|
||||
*
|
||||
* ```js
|
||||
* // Log all uncaught errors to the terminal
|
||||
* context.on('pageerror', pageerror => {
|
||||
* console.log(`Uncaught exception: "${pageerror.error()}"`);
|
||||
* });
|
||||
*
|
||||
* // Navigate to a page with an exception.
|
||||
* await page.goto('data:text/html,<script>throw new Error("Test")</script>');
|
||||
* ```
|
||||
*
|
||||
*/
|
||||
export interface PageError {
|
||||
/**
|
||||
* Unhandled error that was thrown.
|
||||
*/
|
||||
error(): Error;
|
||||
|
||||
/**
|
||||
* The page that produced this unhandled exception, if any.
|
||||
*/
|
||||
page(): null|Page;
|
||||
}
|
||||
|
||||
/**
|
||||
* This object can be used to launch or connect to Chromium, returning instances of {@link Browser}.
|
||||
*/
|
||||
|
@ -1404,6 +1404,7 @@ export interface BrowserContextEventTarget {
|
||||
on(event: 'close', callback: (params: BrowserContextCloseEvent) => void): this;
|
||||
on(event: 'dialog', callback: (params: BrowserContextDialogEvent) => void): this;
|
||||
on(event: 'page', callback: (params: BrowserContextPageEvent) => void): this;
|
||||
on(event: 'pageError', callback: (params: BrowserContextPageErrorEvent) => void): this;
|
||||
on(event: 'route', callback: (params: BrowserContextRouteEvent) => void): this;
|
||||
on(event: 'video', callback: (params: BrowserContextVideoEvent) => void): this;
|
||||
on(event: 'backgroundPage', callback: (params: BrowserContextBackgroundPageEvent) => void): this;
|
||||
@ -1453,6 +1454,10 @@ export type BrowserContextDialogEvent = {
|
||||
export type BrowserContextPageEvent = {
|
||||
page: PageChannel,
|
||||
};
|
||||
export type BrowserContextPageErrorEvent = {
|
||||
error: SerializedError,
|
||||
page: PageChannel,
|
||||
};
|
||||
export type BrowserContextRouteEvent = {
|
||||
route: RouteChannel,
|
||||
};
|
||||
@ -1697,6 +1702,7 @@ export interface BrowserContextEvents {
|
||||
'close': BrowserContextCloseEvent;
|
||||
'dialog': BrowserContextDialogEvent;
|
||||
'page': BrowserContextPageEvent;
|
||||
'pageError': BrowserContextPageErrorEvent;
|
||||
'route': BrowserContextRouteEvent;
|
||||
'video': BrowserContextVideoEvent;
|
||||
'backgroundPage': BrowserContextBackgroundPageEvent;
|
||||
@ -1725,7 +1731,6 @@ export interface PageEventTarget {
|
||||
on(event: 'fileChooser', callback: (params: PageFileChooserEvent) => void): this;
|
||||
on(event: 'frameAttached', callback: (params: PageFrameAttachedEvent) => void): this;
|
||||
on(event: 'frameDetached', callback: (params: PageFrameDetachedEvent) => void): this;
|
||||
on(event: 'pageError', callback: (params: PagePageErrorEvent) => void): this;
|
||||
on(event: 'route', callback: (params: PageRouteEvent) => void): this;
|
||||
on(event: 'video', callback: (params: PageVideoEvent) => void): this;
|
||||
on(event: 'webSocket', callback: (params: PageWebSocketEvent) => void): this;
|
||||
@ -1787,9 +1792,6 @@ export type PageFrameAttachedEvent = {
|
||||
export type PageFrameDetachedEvent = {
|
||||
frame: FrameChannel,
|
||||
};
|
||||
export type PagePageErrorEvent = {
|
||||
error: SerializedError,
|
||||
};
|
||||
export type PageRouteEvent = {
|
||||
route: RouteChannel,
|
||||
};
|
||||
@ -2220,7 +2222,6 @@ export interface PageEvents {
|
||||
'fileChooser': PageFileChooserEvent;
|
||||
'frameAttached': PageFrameAttachedEvent;
|
||||
'frameDetached': PageFrameDetachedEvent;
|
||||
'pageError': PagePageErrorEvent;
|
||||
'route': PageRouteEvent;
|
||||
'video': PageVideoEvent;
|
||||
'webSocket': PageWebSocketEvent;
|
||||
|
@ -1188,6 +1188,11 @@ BrowserContext:
|
||||
parameters:
|
||||
page: Page
|
||||
|
||||
pageError:
|
||||
parameters:
|
||||
error: SerializedError
|
||||
page: Page
|
||||
|
||||
route:
|
||||
parameters:
|
||||
route: Route
|
||||
@ -1635,10 +1640,6 @@ Page:
|
||||
parameters:
|
||||
frame: Frame
|
||||
|
||||
pageError:
|
||||
parameters:
|
||||
error: SerializedError
|
||||
|
||||
route:
|
||||
parameters:
|
||||
route: Route
|
||||
|
@ -160,3 +160,12 @@ test('dialog event should work with inline script tag', async ({ page, server })
|
||||
await promise;
|
||||
await expect.poll(() => popup.evaluate('window.result')).toBe('hello');
|
||||
});
|
||||
|
||||
test('pageError event should work', async ({ page }) => {
|
||||
const [pageerror] = await Promise.all([
|
||||
page.context().waitForEvent('pageerror'),
|
||||
page.setContent('<script>throw new Error("boom")</script>'),
|
||||
]);
|
||||
expect(pageerror.page()).toBe(page);
|
||||
expect(pageerror.error().stack).toContain('boom');
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user