Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions docs/src/api/class-browsercontext.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,13 @@ This event is not emitted.

Playwright has ability to mock clock and passage of time.

## property: BrowserContext.debugger
* since: v1.59
* langs: js
- type: <[Debugger]>

Debugger allows to pause and resume the execution.

## event: BrowserContext.close
* since: v1.8
- argument: <[BrowserContext]>
Expand Down
50 changes: 50 additions & 0 deletions docs/src/api/class-debugger.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# class: Debugger
* since: v1.59
* langs: js

API for controlling the Playwright debugger. The debugger allows pausing script execution and inspecting the page.
Obtain the debugger instance via [`property: BrowserContext.debugger`].

See also [`method: Page.pause`] for a simple way to pause script execution.

## event: Debugger.pausedStateChanged
* since: v1.59

Emitted when the debugger pauses or resumes.

## method: Debugger.pausedDetails
* since: v1.59
- returns: <[Array]<[Object]>>
- `location` <[Object]>
- `file` <[string]>
- `line` ?<[int]>
- `column` ?<[int]>
- `title` <[string]>

Returns details about the currently paused calls. Returns an empty array if the debugger is not paused.

## async method: Debugger.resume
* since: v1.59

Resumes script execution if the debugger is paused.

## async method: Debugger.setPauseAt
* since: v1.59

Configures the debugger to pause at the next action or at a specific source location.
Call without arguments to reset the pausing behavior.

### option: Debugger.setPauseAt.next
* since: v1.59
- `next` <[boolean]>

When `true`, the debugger will pause before the next action.

### option: Debugger.setPauseAt.location
* since: v1.59
- `location` <[Object]>
- `file` <[string]>
- `line` ?<[int]>
- `column` ?<[int]>

When specified, the debugger will pause when the action originates from the given source location.
88 changes: 88 additions & 0 deletions packages/playwright-client/types/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9695,6 +9695,11 @@ export interface BrowserContext {
*/
clock: Clock;

/**
* Debugger allows to pause and resume the execution.
*/
debugger: Debugger;

/**
* API testing helper associated with this context. Requests made with this API will use context cookies.
*/
Expand Down Expand Up @@ -19404,6 +19409,89 @@ export interface Coverage {
}>>;
}

/**
* API for controlling the Playwright debugger. The debugger allows pausing script execution and inspecting the page.
* Obtain the debugger instance via
* [browserContext.debugger](https://playwright.dev/docs/api/class-browsercontext#browser-context-debugger).
*
* See also [page.pause()](https://playwright.dev/docs/api/class-page#page-pause) for a simple way to pause script
* execution.
*/
export interface Debugger {
/**
* Emitted when the debugger pauses or resumes.
*/
on(event: 'pausedstatechanged', listener: () => 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: 'pausedstatechanged', listener: () => any): this;

/**
* Emitted when the debugger pauses or resumes.
*/
addListener(event: 'pausedstatechanged', listener: () => any): this;

/**
* Removes an event listener added by `on` or `addListener`.
*/
removeListener(event: 'pausedstatechanged', listener: () => any): this;

/**
* Removes an event listener added by `on` or `addListener`.
*/
off(event: 'pausedstatechanged', listener: () => any): this;

/**
* Emitted when the debugger pauses or resumes.
*/
prependListener(event: 'pausedstatechanged', listener: () => any): this;

/**
* Returns details about the currently paused calls. Returns an empty array if the debugger is not paused.
*/
pausedDetails(): Array<{
location: {
file: string;

line?: number;

column?: number;
};

title: string;
}>;

/**
* Resumes script execution if the debugger is paused.
*/
resume(): Promise<void>;

/**
* Configures the debugger to pause at the next action or at a specific source location. Call without arguments to
* reset the pausing behavior.
* @param options
*/
setPauseAt(options?: {
/**
* When specified, the debugger will pause when the action originates from the given source location.
*/
location?: {
file: string;

line?: number;

column?: number;
};

/**
* When `true`, the debugger will pause before the next action.
*/
next?: boolean;
}): Promise<void>;
}

/**
* [Dialog](https://playwright.dev/docs/api/class-dialog) objects are dispatched by page via the
* [page.on('dialog')](https://playwright.dev/docs/api/class-page#page-event-dialog) event.
Expand Down
1 change: 1 addition & 0 deletions packages/playwright-core/src/client/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export { BrowserType } from './browserType';
export { Clock } from './clock';
export { ConsoleMessage } from './consoleMessage';
export { Coverage } from './coverage';
export { Debugger } from './debugger';
export { Dialog } from './dialog';
export type { Disposable } from './disposable';
export { Download } from './download';
Expand Down
3 changes: 3 additions & 0 deletions packages/playwright-core/src/client/browserContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { ChannelOwner } from './channelOwner';
import { evaluationScript } from './clientHelper';
import { Clock } from './clock';
import { ConsoleMessage } from './consoleMessage';
import { Debugger } from './debugger';
import { Dialog } from './dialog';
import { DisposableObject, DisposableStub } from './disposable';
import { TargetClosedError, parseError } from './errors';
Expand Down Expand Up @@ -69,6 +70,7 @@ export class BrowserContext extends ChannelOwner<channels.BrowserContextChannel>
private _closedPromise: Promise<void>;
readonly _options: channels.BrowserNewContextParams;

readonly debugger: Debugger;
readonly request: APIRequestContext;
readonly tracing: Tracing;
readonly clock: Clock;
Expand All @@ -93,6 +95,7 @@ export class BrowserContext extends ChannelOwner<channels.BrowserContextChannel>
super(parent, type, guid, initializer);
this._options = initializer.options;
this._timeoutSettings = new TimeoutSettings(this._platform);
this.debugger = Debugger.from(initializer.debugger);
this.tracing = Tracing.from(initializer.tracing);
this.request = APIRequestContext.from(initializer.requestContext);
this.request._timeoutSettings = this._timeoutSettings;
Expand Down
4 changes: 4 additions & 0 deletions packages/playwright-core/src/client/connection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import { BrowserType } from './browserType';
import { CDPSession } from './cdpSession';
import { ChannelOwner } from './channelOwner';
import { createInstrumentation } from './clientInstrumentation';
import { Debugger } from './debugger';
import { Dialog } from './dialog';
import { DisposableObject } from './disposable';
import { Electron, ElectronApplication } from './electron';
Expand Down Expand Up @@ -266,6 +267,9 @@ export class Connection extends EventEmitter {
case 'CDPSession':
result = new CDPSession(parent, type, guid, initializer);
break;
case 'Debugger':
result = new Debugger(parent, type, guid, initializer);
break;
case 'Dialog':
result = new Dialog(parent, type, guid, initializer);
break;
Expand Down
51 changes: 51 additions & 0 deletions packages/playwright-core/src/client/debugger.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/**
* 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 { ChannelOwner } from './channelOwner';
import { Events } from './events';

import type * as api from '../../types/types';
import type * as channels from '@protocol/channels';

type PausedDetail = { location: { file: string, line?: number, column?: number }, title: string };

export class Debugger extends ChannelOwner<channels.DebuggerChannel> implements api.Debugger {
private _pausedDetails: PausedDetail[] = [];

static from(channel: channels.DebuggerChannel): Debugger {
return (channel as any)._object;
}

constructor(parent: ChannelOwner, type: string, guid: string, initializer: channels.DebuggerInitializer) {
super(parent, type, guid, initializer);
this._channel.on('pausedStateChanged', ({ pausedDetails }) => {
this._pausedDetails = pausedDetails;
this.emit(Events.Debugger.PausedStateChanged);
});
}

async setPauseAt(options: { next?: boolean, location?: { file: string, line?: number, column?: number } } = {}) {
await this._channel.setPauseAt(options);
}

async resume(): Promise<void> {
await this._channel.resume();
}

pausedDetails(): PausedDetail[] {
return this._pausedDetails;
}
}
4 changes: 4 additions & 0 deletions packages/playwright-core/src/client/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ export const Events = {
Disconnected: 'disconnected'
},

Debugger: {
PausedStateChanged: 'pausedstatechanged'
},

BrowserContext: {
Console: 'console',
Close: 'close',
Expand Down
25 changes: 25 additions & 0 deletions packages/playwright-core/src/protocol/validator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -844,16 +844,19 @@ scheme.BrowserContextWaitForEventInfoParams = tType('EventTargetWaitForEventInfo
scheme.PageWaitForEventInfoParams = tType('EventTargetWaitForEventInfoParams');
scheme.WorkerWaitForEventInfoParams = tType('EventTargetWaitForEventInfoParams');
scheme.WebSocketWaitForEventInfoParams = tType('EventTargetWaitForEventInfoParams');
scheme.DebuggerWaitForEventInfoParams = tType('EventTargetWaitForEventInfoParams');
scheme.ElectronApplicationWaitForEventInfoParams = tType('EventTargetWaitForEventInfoParams');
scheme.AndroidDeviceWaitForEventInfoParams = tType('EventTargetWaitForEventInfoParams');
scheme.EventTargetWaitForEventInfoResult = tOptional(tObject({}));
scheme.BrowserContextWaitForEventInfoResult = tType('EventTargetWaitForEventInfoResult');
scheme.PageWaitForEventInfoResult = tType('EventTargetWaitForEventInfoResult');
scheme.WorkerWaitForEventInfoResult = tType('EventTargetWaitForEventInfoResult');
scheme.WebSocketWaitForEventInfoResult = tType('EventTargetWaitForEventInfoResult');
scheme.DebuggerWaitForEventInfoResult = tType('EventTargetWaitForEventInfoResult');
scheme.ElectronApplicationWaitForEventInfoResult = tType('EventTargetWaitForEventInfoResult');
scheme.AndroidDeviceWaitForEventInfoResult = tType('EventTargetWaitForEventInfoResult');
scheme.BrowserContextInitializer = tObject({
debugger: tChannel(['Debugger']),
requestContext: tChannel(['APIRequestContext']),
tracing: tChannel(['Tracing']),
options: tObject({
Expand Down Expand Up @@ -2494,6 +2497,28 @@ scheme.BindingCallResolveParams = tObject({
result: tType('SerializedArgument'),
});
scheme.BindingCallResolveResult = tOptional(tObject({}));
scheme.DebuggerInitializer = tOptional(tObject({}));
scheme.DebuggerPausedStateChangedEvent = tObject({
pausedDetails: tArray(tObject({
location: tObject({
file: tString,
line: tOptional(tInt),
column: tOptional(tInt),
}),
title: tString,
})),
});
scheme.DebuggerSetPauseAtParams = tObject({
next: tOptional(tBoolean),
location: tOptional(tObject({
file: tString,
line: tOptional(tInt),
column: tOptional(tInt),
})),
});
scheme.DebuggerSetPauseAtResult = tOptional(tObject({}));
scheme.DebuggerResumeParams = tOptional(tObject({}));
scheme.DebuggerResumeResult = tOptional(tObject({}));
scheme.DialogInitializer = tObject({
page: tOptional(tChannel(['Page'])),
type: tString,
Expand Down
Loading
Loading