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
1 change: 1 addition & 0 deletions docs/src/api/class-screencast.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ await screencast.stop();

## async method: Screencast.start
* since: v1.59
- returns: <[Disposable]>

Starts capturing screencast frames. Frames are emitted as [`event: Screencast.screencastFrame`] events.

Expand Down
53 changes: 27 additions & 26 deletions docs/src/api/class-video.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,33 +26,33 @@ Console.WriteLine(await page.Video.GetPathAsync());
Alternatively, you can use [`method: Video.start`] and [`method: Video.stop`] to record video manually. This approach is mutually exclusive with the `recordVideo` option.

```js
await page.video().start();
await page.video().start({ path: 'video.webm' });
// ... perform actions ...
await page.video().stop({ path: 'video.webm' });
await page.video().stop();
```

```java
page.video().start();
page.video().start(new Video.StartOptions().setPath(Paths.get("video.webm")));
// ... perform actions ...
page.video().stop(new Video.StopOptions().setPath(Paths.get("video.webm")));
page.video().stop();
```

```python async
await page.video.start()
await page.video.start(path="video.webm")
# ... perform actions ...
await page.video.stop(path="video.webm")
await page.video.stop()
```

```python sync
page.video.start()
page.video.start(path="video.webm")
# ... perform actions ...
page.video.stop(path="video.webm")
page.video.stop()
```

```csharp
await page.Video.StartAsync();
await page.Video.StartAsync(new() { Path = "video.webm" });
// ... perform actions ...
await page.Video.StopAsync(new() { Path = "video.webm" });
await page.Video.StopAsync();
```

## async method: Video.delete
Expand Down Expand Up @@ -94,41 +94,48 @@ Path where the video should be saved.

## async method: Video.start
* since: v1.59
- returns: <[Disposable]>

Starts video recording. This method is mutually exclusive with the `recordVideo` context option.

**Usage**

```js
await page.video().start();
await page.video().start({ path: 'video.webm' });
// ... perform actions ...
await page.video().stop({ path: 'video.webm' });
await page.video().stop();
```

```java
page.video().start();
page.video().start(new Video.StartOptions().setPath(Paths.get("video.webm")));
// ... perform actions ...
page.video().stop(new Video.StopOptions().setPath(Paths.get("video.webm")));
page.video().stop();
```

```python async
await page.video.start()
await page.video.start(path="video.webm")
# ... perform actions ...
await page.video.stop(path="video.webm")
await page.video.stop()
```

```python sync
page.video.start()
page.video.start(path="video.webm")
# ... perform actions ...
page.video.stop(path="video.webm")
page.video.stop()
```

```csharp
await page.Video.StartAsync();
await page.Video.StartAsync(new() { Path = "video.webm" });
// ... perform actions ...
await page.Video.StopAsync(new() { Path = "video.webm" });
await page.Video.StopAsync();
```

### option: Video.start.path
* since: v1.59
- `path` <[path]>

Path where the video should be saved when the recording is stopped.

### option: Video.start.size
* since: v1.59
- `size` ?<[Object]>
Expand All @@ -141,9 +148,3 @@ Optional dimensions of the recorded video. If not specified the size will be equ
* since: v1.59

Stops video recording started with [`method: Video.start`].

### option: Video.stop.path
* since: v1.59
- `path` <[path]>

Path where the video should be saved.
33 changes: 16 additions & 17 deletions packages/playwright-client/types/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4823,8 +4823,8 @@ export interface Page {
/**
* Video object associated with this page. Can be used to control video recording with
* [video.start([options])](https://playwright.dev/docs/api/class-video#video-start) and
* [video.stop([options])](https://playwright.dev/docs/api/class-video#video-stop), or to access the video file when
* using the `recordVideo` context option.
* [video.stop()](https://playwright.dev/docs/api/class-video#video-stop), or to access the video file when using the
* `recordVideo` context option.
*/
video(): Video;

Expand Down Expand Up @@ -21779,7 +21779,7 @@ export interface Screencast {
*/
height: number;
};
}): Promise<void>;
}): Promise<Disposable>;

/**
* Stops the screencast started with
Expand Down Expand Up @@ -22111,13 +22111,13 @@ export interface Tracing {
* ```
*
* Alternatively, you can use [video.start([options])](https://playwright.dev/docs/api/class-video#video-start) and
* [video.stop([options])](https://playwright.dev/docs/api/class-video#video-stop) to record video manually. This
* approach is mutually exclusive with the `recordVideo` option.
* [video.stop()](https://playwright.dev/docs/api/class-video#video-stop) to record video manually. This approach is
* mutually exclusive with the `recordVideo` option.
*
* ```js
* await page.video().start();
* await page.video().start({ path: 'video.webm' });
* // ... perform actions ...
* await page.video().stop({ path: 'video.webm' });
* await page.video().stop();
* ```
*
*/
Expand Down Expand Up @@ -22146,14 +22146,19 @@ export interface Video {
* **Usage**
*
* ```js
* await page.video().start();
* await page.video().start({ path: 'video.webm' });
* // ... perform actions ...
* await page.video().stop({ path: 'video.webm' });
* await page.video().stop();
* ```
*
* @param options
*/
start(options?: {
/**
* Path where the video should be saved when the recording is stopped.
*/
path?: string;

/**
* Optional dimensions of the recorded video. If not specified the size will be equal to page viewport scaled down to
* fit into 800x800. Actual picture of the page will be scaled down if necessary to fit the specified size.
Expand All @@ -22169,19 +22174,13 @@ export interface Video {
*/
height: number;
};
}): Promise<void>;
}): Promise<Disposable>;

/**
* Stops video recording started with
* [video.start([options])](https://playwright.dev/docs/api/class-video#video-start).
* @param options
*/
stop(options?: {
/**
* Path where the video should be saved.
*/
path?: string;
}): Promise<void>;
stop(): Promise<void>;
}

/**
Expand Down
4 changes: 3 additions & 1 deletion packages/playwright-core/src/client/screencast.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
* limitations under the License.
*/

import { DisposableStub } from './disposable';
import { EventEmitter } from './eventEmitter';

import type * as api from '../../types/types';
Expand All @@ -28,8 +29,9 @@ export class Screencast extends EventEmitter implements api.Screencast {
this._page._channel.on('screencastFrame', ({ data }) => this.emit('screencastframe', { data }));
}

async start(options: { maxSize?: { width: number, height: number } } = {}): Promise<void> {
async start(options: { maxSize?: { width: number, height: number } } = {}) {
await this._page._channel.startScreencast(options);
return new DisposableStub(() => this.stop());
}

async stop(): Promise<void> {
Expand Down
14 changes: 9 additions & 5 deletions packages/playwright-core/src/client/video.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/

import { Artifact } from './artifact';
import { DisposableStub } from './disposable';
import { EventEmitter } from './eventEmitter';

import type { Connection } from './connection';
Expand All @@ -25,6 +26,7 @@ export class Video extends EventEmitter implements api.Video {
private _artifact: Artifact | undefined;
private _isRemote = false;
private _page: Page;
private _savePath: string | undefined;

constructor(page: Page, connection: Connection, artifact: Artifact | undefined) {
super(page._platform);
Expand All @@ -33,16 +35,18 @@ export class Video extends EventEmitter implements api.Video {
this._artifact = artifact;
}

async start(options: { size?: { width: number, height: number } } = {}): Promise<void> {
const result = await this._page._channel.videoStart(options);
async start(options: { path?: string, size?: { width: number, height: number } } = {}) {
const result = await this._page._channel.videoStart({ size: options.size });
this._artifact = Artifact.from(result.artifact);
this._savePath = options.path;
return new DisposableStub(() => this.stop());
}

async stop(options: { path?: string } = {}): Promise<void> {
async stop(): Promise<void> {
await this._page._wrapApiCall(async () => {
await this._page._channel.videoStop();
if (options.path)
await this.saveAs(options.path);
if (this._savePath)
await this.saveAs(this._savePath);
});
}

Expand Down
33 changes: 16 additions & 17 deletions packages/playwright-core/types/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4823,8 +4823,8 @@ export interface Page {
/**
* Video object associated with this page. Can be used to control video recording with
* [video.start([options])](https://playwright.dev/docs/api/class-video#video-start) and
* [video.stop([options])](https://playwright.dev/docs/api/class-video#video-stop), or to access the video file when
* using the `recordVideo` context option.
* [video.stop()](https://playwright.dev/docs/api/class-video#video-stop), or to access the video file when using the
* `recordVideo` context option.
*/
video(): Video;

Expand Down Expand Up @@ -21779,7 +21779,7 @@ export interface Screencast {
*/
height: number;
};
}): Promise<void>;
}): Promise<Disposable>;

/**
* Stops the screencast started with
Expand Down Expand Up @@ -22111,13 +22111,13 @@ export interface Tracing {
* ```
*
* Alternatively, you can use [video.start([options])](https://playwright.dev/docs/api/class-video#video-start) and
* [video.stop([options])](https://playwright.dev/docs/api/class-video#video-stop) to record video manually. This
* approach is mutually exclusive with the `recordVideo` option.
* [video.stop()](https://playwright.dev/docs/api/class-video#video-stop) to record video manually. This approach is
* mutually exclusive with the `recordVideo` option.
*
* ```js
* await page.video().start();
* await page.video().start({ path: 'video.webm' });
* // ... perform actions ...
* await page.video().stop({ path: 'video.webm' });
* await page.video().stop();
* ```
*
*/
Expand Down Expand Up @@ -22146,14 +22146,19 @@ export interface Video {
* **Usage**
*
* ```js
* await page.video().start();
* await page.video().start({ path: 'video.webm' });
* // ... perform actions ...
* await page.video().stop({ path: 'video.webm' });
* await page.video().stop();
* ```
*
* @param options
*/
start(options?: {
/**
* Path where the video should be saved when the recording is stopped.
*/
path?: string;

/**
* Optional dimensions of the recorded video. If not specified the size will be equal to page viewport scaled down to
* fit into 800x800. Actual picture of the page will be scaled down if necessary to fit the specified size.
Expand All @@ -22169,19 +22174,13 @@ export interface Video {
*/
height: number;
};
}): Promise<void>;
}): Promise<Disposable>;

/**
* Stops video recording started with
* [video.start([options])](https://playwright.dev/docs/api/class-video#video-start).
* @param options
*/
stop(options?: {
/**
* Path where the video should be saved.
*/
path?: string;
}): Promise<void>;
stop(): Promise<void>;
}

/**
Expand Down
18 changes: 18 additions & 0 deletions tests/library/screencast.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,24 @@ test('start throws when video recording is running with different params', async
await context.close();
});

test('screencast.start dispose stops screencast', async ({ browser, server, trace }) => {
test.skip(trace === 'on', 'trace=on has different screencast image configuration');
const context = await browser.newContext({ viewport: { width: 1000, height: 400 } });
const page = await context.newPage();

const frames: { data: Buffer }[] = [];
page.screencast().on('screencastframe', frame => frames.push(frame));

const disposable = await page.screencast().start({ maxSize: { width: 500, height: 400 } });
await page.goto(server.EMPTY_PAGE);
await page.evaluate(() => document.body.style.backgroundColor = 'red');
await rafraf(page, 100);
await disposable.dispose();

expect(frames.length).toBeGreaterThan(0);
await context.close();
});

test('video.start does not emit screencastframe events', async ({ page, server, trace }) => {
test.skip(trace === 'on', 'trace=on enables screencast frame events');

Expand Down
Loading
Loading