From 6c08ad67bca78a5a6f4789e6f509f3fa555b4d25 Mon Sep 17 00:00:00 2001 From: jonchurch Date: Mon, 13 Sep 2021 15:43:41 -0400 Subject: [PATCH 1/2] feat: add webp to screenshot options --- src/common/Page.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/common/Page.ts b/src/common/Page.ts index b2aa354d9eb30..d896d406eccd5 100644 --- a/src/common/Page.ts +++ b/src/common/Page.ts @@ -157,7 +157,7 @@ export interface ScreenshotOptions { /** * @defaultValue 'png' */ - type?: 'png' | 'jpeg'; + type?: 'png' | 'jpeg' | 'webp'; /** * 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 @@ -2552,7 +2552,9 @@ export class Page extends EventEmitter { // (i.e. as a temp file). if (options.type) { assert( - options.type === 'png' || options.type === 'jpeg', + options.type === 'png' || + options.type === 'jpeg' || + options.type === 'webp', 'Unknown options.type value: ' + options.type ); screenshotType = options.type; @@ -2564,6 +2566,7 @@ export class Page extends EventEmitter { if (extension === 'png') screenshotType = 'png'; else if (extension === 'jpg' || extension === 'jpeg') screenshotType = 'jpeg'; + else if (extension === 'webp') screenshotType = 'webp'; assert( screenshotType, `Unsupported screenshot type for extension \`.${extension}\`` @@ -2634,7 +2637,7 @@ export class Page extends EventEmitter { } private async _screenshotTask( - format: 'png' | 'jpeg', + format: 'png' | 'jpeg' | 'webp', options?: ScreenshotOptions ): Promise { await this._client.send('Target.activateTarget', { From b1d19474de4f7dceb1f2b9332c8cd9c85a308614 Mon Sep 17 00:00:00 2001 From: Jan Scheffler Date: Tue, 21 Sep 2021 15:44:06 +0200 Subject: [PATCH 2/2] chore: add tests and types --- docs/api.md | 2 +- src/common/Page.ts | 16 +++++++--------- src/common/assert.ts | 4 ++++ test/screenshot.spec.ts | 11 +++++++++++ 4 files changed, 23 insertions(+), 10 deletions(-) diff --git a/docs/api.md b/docs/api.md index 44f34273d1219..219f41964eed6 100644 --- a/docs/api.md +++ b/docs/api.md @@ -2175,7 +2175,7 @@ Shortcut for [page.mainFrame().executionContext().queryObjects(prototypeHandle)] - `options` <[Object]> Options object which might have the following properties: - `path` <[string]> 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 [current working directory](https://nodejs.org/api/process.html#process_process_cwd). If no path is provided, the image won't be saved to the disk. - - `type` <[string]> Specify screenshot type, can be either `jpeg` or `png`. Defaults to 'png'. + - `type` <[string]> Specify screenshot type, can be either `jpeg`, `png` or `webp`. Defaults to 'png'. - `quality` <[number]> The quality of the image, between 0-100. Not applicable to `png` images. - `fullPage` <[boolean]> When true, takes a screenshot of the full scrollable page. Defaults to `false`. - `clip` <[Object]> An object which specifies clipping region of the page. Should have the following fields: diff --git a/src/common/Page.ts b/src/common/Page.ts index a0562c3b07322..ef5c70d3ffac5 100644 --- a/src/common/Page.ts +++ b/src/common/Page.ts @@ -31,7 +31,7 @@ import { } from './FrameManager.js'; import { Keyboard, Mouse, Touchscreen, MouseButton } from './Input.js'; import { Tracing } from './Tracing.js'; -import { assert } from './assert.js'; +import { assert, assertNever } from './assert.js'; import { helper, debugError } from './helper.js'; import { Coverage } from './Coverage.js'; import { WebWorker } from './WebWorker.js'; @@ -2552,12 +2552,10 @@ export class Page extends EventEmitter { // because it may be a 0-length file with no extension created beforehand // (i.e. as a temp file). if (options.type) { - assert( - options.type === 'png' || - options.type === 'jpeg' || - options.type === 'webp', - 'Unknown options.type value: ' + options.type - ); + const type = options.type; + if (type !== 'png' && type !== 'jpeg' && type !== 'webp') { + assertNever(type, 'Unknown options.type value: ' + type); + } screenshotType = options.type; } else if (options.path) { const filePath = options.path; @@ -2638,7 +2636,7 @@ export class Page extends EventEmitter { } private async _screenshotTask( - format: 'png' | 'jpeg' | 'webp', + format: Protocol.Page.CaptureScreenshotRequestFormat, options?: ScreenshotOptions ): Promise { await this._client.send('Target.activateTarget', { @@ -2677,7 +2675,7 @@ export class Page extends EventEmitter { } } const shouldSetDefaultBackground = - options.omitBackground && format === 'png'; + options.omitBackground && (format === 'png' || format === 'webp'); if (shouldSetDefaultBackground) { await this._setTransparentBackgroundColor(); } diff --git a/src/common/assert.ts b/src/common/assert.ts index 6ba090ce26e85..97dcc4278316b 100644 --- a/src/common/assert.ts +++ b/src/common/assert.ts @@ -22,3 +22,7 @@ export const assert = (value: unknown, message?: string): void => { if (!value) throw new Error(message); }; + +export const assertNever = (value: never, message?: string): void => { + if (value) throw new Error(message); +}; diff --git a/test/screenshot.spec.ts b/test/screenshot.spec.ts index 223d6c4a5687e..f2a6adc6d5fe1 100644 --- a/test/screenshot.spec.ts +++ b/test/screenshot.spec.ts @@ -142,6 +142,17 @@ describe('Screenshots', function () { }); expect(screenshot).toBeGolden('white.jpg'); }); + itFailsFirefox('should work with webp', async () => { + const { page, server } = 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 with odd clip size on Retina displays', async () => { const { page } = getTestState();