chore: add support for format and quality to BiDi (#11124)

This commit is contained in:
jrandolf 2023-10-11 18:53:50 +02:00 committed by GitHub
parent 4170fefc5c
commit a3fce3118a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 39 additions and 65 deletions

View File

@ -2535,57 +2535,32 @@ export abstract class Page extends EventEmitter<PageEvents> {
break; break;
} }
} }
if (options.quality) { if (options.quality !== undefined) {
assert( if (options.quality < 0 && options.quality > 100) {
options.type === 'jpeg' || options.type === 'webp', throw new Error(
`options.quality is unsupported for the ${options.type} screenshots` `Expected 'quality' (${options.quality}) to be between 0 and 100, inclusive.`
); );
assert( }
typeof options.quality === 'number', if (
`Expected options.quality to be a number but found ${typeof options.quality}` options.type === undefined ||
); !['jpeg', 'webp'].includes(options.type)
assert( ) {
Number.isInteger(options.quality), throw new Error(
'Expected options.quality to be an integer' `${options.type ?? 'png'} screenshots do not support 'quality'.`
); );
assert( }
options.quality >= 0 && options.quality <= 100,
`Expected options.quality to be between 0 and 100 (inclusive), got ${options.quality}`
);
} }
assert( assert(
!options.clip || !options.fullPage, !options.clip || !options.fullPage,
'options.clip and options.fullPage are exclusive' "'clip' and 'fullPage' are exclusive"
); );
if (options.clip) { if (options.clip) {
assert( if (options.clip.width <= 0) {
typeof options.clip.x === 'number', throw new Error("'width' in 'clip' must be positive.");
`Expected options.clip.x to be a number but found ${typeof options.clip }
.x}` if (options.clip.height <= 0) {
); throw new Error("'height' in 'clip' must be positive.");
assert( }
typeof options.clip.y === 'number',
`Expected options.clip.y to be a number but found ${typeof options.clip
.y}`
);
assert(
typeof options.clip.width === 'number',
`Expected options.clip.width to be a number but found ${typeof options
.clip.width}`
);
assert(
typeof options.clip.height === 'number',
`Expected options.clip.height to be a number but found ${typeof options
.clip.height}`
);
assert(
options.clip.width !== 0,
'Expected options.clip.width not to be 0.'
);
assert(
options.clip.height !== 0,
'Expected options.clip.height not to be 0.'
);
} }
setDefaultScreenshotOptions(options); setDefaultScreenshotOptions(options);

View File

@ -650,7 +650,8 @@ export class BidiPage extends Page {
override async _screenshot( override async _screenshot(
options: Readonly<ScreenshotOptions> options: Readonly<ScreenshotOptions>
): Promise<string> { ): Promise<string> {
const {clip, type, captureBeyondViewport, allowViewportExpansion} = options; const {clip, type, captureBeyondViewport, allowViewportExpansion, quality} =
options;
if (captureBeyondViewport && !allowViewportExpansion) { if (captureBeyondViewport && !allowViewportExpansion) {
throw new Error( throw new Error(
`BiDi does not support 'captureBeyondViewport'. Use 'allowViewportExpansion'.` `BiDi does not support 'captureBeyondViewport'. Use 'allowViewportExpansion'.`
@ -665,12 +666,6 @@ export class BidiPage extends Page {
if (options.fromSurface !== undefined && !options.fromSurface) { if (options.fromSurface !== undefined && !options.fromSurface) {
throw new Error(`BiDi does not support 'fromSurface'.`); throw new Error(`BiDi does not support 'fromSurface'.`);
} }
if (options.quality !== undefined) {
throw new Error(`BiDi does not support 'quality'.`);
}
if (type === 'webp' || type === 'jpeg') {
throw new Error(`BiDi only supports 'png' type.`);
}
if (clip !== undefined && clip.scale !== undefined && clip.scale !== 1) { if (clip !== undefined && clip.scale !== undefined && clip.scale !== 1) {
throw new Error(`BiDi does not support 'scale' in 'clip'.`); throw new Error(`BiDi does not support 'scale' in 'clip'.`);
} }
@ -678,6 +673,10 @@ export class BidiPage extends Page {
result: {data}, result: {data},
} = await this.#connection.send('browsingContext.captureScreenshot', { } = await this.#connection.send('browsingContext.captureScreenshot', {
context: this.mainFrame()._id, context: this.mainFrame()._id,
format: {
type: `image/${type}`,
...(quality === undefined ? {} : {quality: quality / 100}),
},
clip: clip && { clip: clip && {
type: 'viewport', type: 'viewport',
...clip, ...clip,

View File

@ -1091,7 +1091,7 @@ export class CdpPage extends Page {
const {data} = await this.#client.send('Page.captureScreenshot', { const {data} = await this.#client.send('Page.captureScreenshot', {
format: type, format: type,
...(optimizeForSpeed ? {optimizeForSpeed} : {}), ...(optimizeForSpeed ? {optimizeForSpeed} : {}),
...(quality !== undefined ? {quality} : {}), ...(quality !== undefined ? {quality: Math.round(quality)} : {}),
clip: clip && { clip: clip && {
...clip, ...clip,
scale: clip.scale ?? 1, scale: clip.scale ?? 1,

View File

@ -357,6 +357,17 @@ describe('Screenshots', function () {
const screenshot = await elementHandle.screenshot(); const screenshot = await elementHandle.screenshot();
expect(screenshot).toBeGolden('screenshot-element-fractional-offset.png'); expect(screenshot).toBeGolden('screenshot-element-fractional-offset.png');
}); });
it('should work with webp', async () => {
const {page, server} = await getTestState();
await page.setViewport({width: 100, height: 100});
await page.goto(server.PREFIX + '/grid.html');
const screenshot = await page.screenshot({
type: 'webp',
});
expect(screenshot).toBeInstanceOf(Buffer);
});
}); });
describe('Cdp', () => { describe('Cdp', () => {
@ -379,17 +390,6 @@ describe('Screenshots', function () {
}); });
expect(screenshot).toBeGolden('white.jpg'); expect(screenshot).toBeGolden('white.jpg');
}); });
it('should work with webp', async () => {
const {page, server} = await getTestState();
await page.setViewport({width: 100, height: 100});
await page.goto(server.PREFIX + '/grid.html');
const screenshot = await page.screenshot({
type: 'webp',
});
expect(screenshot).toBeInstanceOf(Buffer);
});
it('should work in "fromSurface: false" mode', async () => { it('should work in "fromSurface: false" mode', async () => {
const {page, server} = await getTestState(); const {page, server} = await getTestState();