diff --git a/docs/api.md b/docs/api.md index 6888f2201c0..700371a871b 100644 --- a/docs/api.md +++ b/docs/api.md @@ -22,7 +22,6 @@ - [page.evaluate(fun, args)](#pageevaluatefun-args) - [page.evaluateOnInitialized(fun, args)](#pageevaluateoninitializedfun-args) - [page.screenshot(type[, clipRect])](#pagescreenshottype-cliprect) - - [page.saveScreenshot(filePath[, clipRect])](#pagesavescreenshotfilepath-cliprect) - [page.printToPDF(filePath[, options])](#pageprinttopdffilepath-options) - [page.plainText()](#pageplaintext) - [page.title()](#pagetitle) @@ -157,11 +156,6 @@ Pages could be closed by `page.close()` method. - `height` [<number>](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Number_type) height of clipping area - returns: [<Promise<Buffer>>](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise) Promise which resolves to buffer with captured screenshot -#### page.saveScreenshot(filePath[, clipRect]) - -- `filePath` [<string>](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#String_type) The file path to save image to. The screenshot type will be inferred from file extension -- `clipRect` [<Object>](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object) Clip rect object which will be passed over to `page.screenshot` method. - #### page.printToPDF(filePath[, options]) - `filePath` [<string>](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#String_type) The file path to save image to. The screenshot type will be inferred from file extension diff --git a/lib/Page.js b/lib/Page.js index 51f37b49645..8adff1c8c9e 100644 --- a/lib/Page.js +++ b/lib/Page.js @@ -387,20 +387,52 @@ class Page extends EventEmitter { } /** - * @param {!Page.ScreenshotType} screenshotType - * @param {?{x: number, y: number, width: number, height: number}} clipRect + * @param {!Object=} options * @return {!Promise} */ - async screenshot(screenshotType, clipRect) { - if (clipRect) { + async screenshot(options) { + var screenshotType = null; + if (options.path) { + var mimeType = mime.lookup(options.path); + if (mimeType === 'image/png') + screenshotType = 'png'; + else if (mimeType === 'image/jpeg') + screenshotType = 'jpeg'; + else + throw new Error('Unsupported screenshot mime type: ' + mimeType); + } + if (options.type) { + if (screenshotType && options.type !== screenshotType) + throw new Error(`Passed screenshot type '${options.type}' does not match to the type inferred from the file path: '${screenshotType}'`); + if (options.type !== 'png' && options.type !== 'jpeg') + throw new Error('Unknown screenshot type: ' + options.type); + screenshotType = options.type; + } + if (!screenshotType) + screenshotType = 'png'; + + if (options.quality) { + console.assert(screenshotType === 'jpeg', 'options.quality is unsupported for the ' + screenshotType + ' screenshots'); + console.assert(typeof options.quality === 'number', 'Expected options.quality to be a number but found ' + (typeof options.quality)); + console.assert(Number.isInteger(options.quality), 'Expected options.quality to be an integer'); + console.assert(options.quality >= 0 && options.quality <= 100, 'Expected options.quality to be between 0 and 100 (inclusive), got ' + options.quality); + } + if (options.clip) { + console.assert(typeof options.clip.x === 'number', 'Expected options.clip.x to be a number but found ' + (typeof options.clip.x)); + console.assert(typeof options.clip.y === 'number', 'Expected options.clip.y to be a number but found ' + (typeof options.clip.y)); + console.assert(typeof options.clip.width === 'number', 'Expected options.clip.width to be a number but found ' + (typeof options.clip.width)); + console.assert(typeof options.clip.height === 'number', 'Expected options.clip.height to be a number but found ' + (typeof options.clip.height)); + } + + if (options.clip) { await Promise.all([ this._client.send('Emulation.setVisibleSize', { - width: Math.ceil(clipRect.width / this._screenDPI), - height: Math.ceil(clipRect.height / this._screenDPI), + width: Math.ceil(options.clip.width / this._screenDPI), + height: Math.ceil(options.clip.height / this._screenDPI), }), this._client.send('Emulation.forceViewport', { - x: clipRect.x / this._screenDPI, - y: clipRect.y / this._screenDPI, + x: options.clip.x / this._screenDPI, + y: options.clip.y / this._screenDPI, scale: 1, }) ]); @@ -408,32 +440,18 @@ class Page extends EventEmitter { var result = await this._client.send('Page.captureScreenshot', { fromSurface: true, format: screenshotType, + quality: options.quality }); - if (clipRect) { + if (options.clip) { await Promise.all([ this.setViewportSize(this.viewportSize()), this._client.send('Emulation.resetViewport') ]); } - return new Buffer(result.data, 'base64'); - } - - /** - * @param {string} filePath - * @param {?{x: number, y: number, width: number, height: number}} clipRect - * @return {!Promise} - */ - async saveScreenshot(filePath, clipRect) { - var mimeType = mime.lookup(filePath); - var screenshotType = null; - if (mimeType === 'image/png') - screenshotType = Page.ScreenshotTypes.PNG; - else if (mimeType === 'image/jpeg') - screenshotType = Page.ScreenshotTypes.JPG; - if (!screenshotType) - throw new Error(`Cannot render to file ${filePath} - unsupported mimeType ${mimeType}`); - var buffer = await this.screenshot(screenshotType, clipRect); - fs.writeFileSync(filePath, buffer); + var buffer = new Buffer(result.data, 'base64'); + if (options.path) + fs.writeFileSync(options.path, buffer); + return buffer; } /** @@ -522,12 +540,6 @@ class InPageCallback { } } -/** @enum {string} */ -Page.ScreenshotTypes = { - PNG: 'png', - JPG: 'jpeg', -}; - /** @enum {string} */ Page.PaperFormats = { Letter: {width: 8.5, height: 11}, diff --git a/phantom_shim/WebPage.js b/phantom_shim/WebPage.js index cebe70d2bf8..b4c081d4df2 100644 --- a/phantom_shim/WebPage.js +++ b/phantom_shim/WebPage.js @@ -285,15 +285,6 @@ class WebPage { * {string} fileName */ render(fileName) { - var clipRect = null; - if (this.clipRect && (this.clipRect.left || this.clipRect.top || this.clipRect.width || this.clipRect.height)) { - clipRect = { - x: this.clipRect.left, - y: this.clipRect.top, - width: this.clipRect.width, - height: this.clipRect.height - }; - } if (fileName.endsWith('pdf')) { var options = {}; var paperSize = this.paperSize || {}; @@ -304,6 +295,16 @@ class WebPage { options.height = paperSize.height; await(this._page.printToPDF(fileName, options)); } else { + var options = {}; + if (this.clipRect && (this.clipRect.left || this.clipRect.top || this.clipRect.width || this.clipRect.height)) { + options.clipRect = { + x: this.clipRect.left, + y: this.clipRect.top, + width: this.clipRect.width, + height: this.clipRect.height + }; + } + options.path = fileName; await(this._page.saveScreenshot(fileName, clipRect)); } } diff --git a/test/goldentest.js b/test/goldentest.js index 34f65c760b5..d5f417edc67 100644 --- a/test/goldentest.js +++ b/test/goldentest.js @@ -55,17 +55,19 @@ describe('GoldenTests', function() { imageTest('screenshot-sanity.png', async function() { await page.setViewportSize({width: 500, height: 500}); await page.navigate(STATIC_PREFIX + '/grid.html'); - return page.screenshot('png'); + return await page.screenshot(); }); imageTest('screenshot-clip-rect.png', async function() { await page.setViewportSize({width: 500, height: 500}); await page.navigate(STATIC_PREFIX + '/grid.html'); - return page.screenshot('png', { - x: 50, - y: 100, - width: 150, - height: 100 + return await page.screenshot({ + clip: { + x: 50, + y: 100, + width: 150, + height: 100 + } }); }); });