feat: elHandle:screenshot captures full element (#1787)

feat: make ElementHandle.screenshot work with large elements

This patch increases the viewport size if the element is bigger than
viewport.

Fixes #1779
This commit is contained in:
Frankie Bagnardi
2018-02-23 15:13:08 -07:00
committed by Andrey Lushnikov
parent b07e705dc9
commit 56a475f86b
4 changed files with 146 additions and 12 deletions

View File

@@ -58,9 +58,7 @@ class ElementHandle extends JSHandle {
*/
async _visibleCenter() {
await this._scrollIntoViewIfNeeded();
const box = await this.boundingBox();
if (!box)
throw new Error('Node is not visible');
const box = await this._assertBoundingBox();
return {
x: box.x + box.width / 2,
y: box.y + box.height / 2
@@ -137,24 +135,59 @@ class ElementHandle extends JSHandle {
return {x, y, width, height};
}
/**
* @return {!Promise<?{x: number, y: number, width: number, height: number}>}
*/
async _assertBoundingBox() {
const boundingBox = await this.boundingBox();
if (boundingBox)
return boundingBox;
throw new Error('Node is either not visible or not an HTMLElement');
}
/**
*
* @param {!Object=} options
* @returns {!Promise<Object>}
*/
async screenshot(options = {}) {
await this._scrollIntoViewIfNeeded();
let needsViewportReset = false;
let boundingBox = await this._assertBoundingBox();
const viewport = this._page.viewport();
if (boundingBox.width > viewport.width || boundingBox.height > viewport.height) {
const newViewport = {
width: Math.max(viewport.width, Math.ceil(boundingBox.width)),
height: Math.max(viewport.height, Math.ceil(boundingBox.height)),
};
await this._page.setViewport(Object.assign({}, viewport, newViewport));
needsViewportReset = true;
}
await this.executionContext().evaluate(function(element) {
element.scrollIntoView({block: 'center', inline: 'center', behavior: 'instant'});
}, this);
boundingBox = await this._assertBoundingBox();
const { layoutViewport: { pageX, pageY } } = await this._client.send('Page.getLayoutMetrics');
const boundingBox = await this.boundingBox();
if (!boundingBox)
throw new Error('Node is not visible');
const clip = Object.assign({}, boundingBox);
clip.x += pageX;
clip.y += pageY;
return await this._page.screenshot(Object.assign({}, {
const imageData = await this._page.screenshot(Object.assign({}, {
clip
}, options));
if (needsViewportReset)
await this._page.setViewport(viewport);
return imageData;
}
/**