fix(ElementHandle.boundingBox): account for margin, padding, and border in element.boxModel (#1017)

This patch starts relying on border quad to compute element's bounding box.

Fixes #1010
This commit is contained in:
JoelEinbinder 2017-10-12 17:53:59 -07:00 committed by Andrey Lushnikov
parent 1c528308a8
commit 8f430fb23d
4 changed files with 39 additions and 10 deletions

View File

@ -116,20 +116,22 @@ class ElementHandle extends JSHandle {
} }
/** /**
* @return {!Promise<Object>} * @return {!Promise<{x: number, y: number, width: number, height: number}>}
*/ */
async boundingBox() { async boundingBox() {
const boxModel = await this._client.send('DOM.getBoxModel', { const {model} = await this._client.send('DOM.getBoxModel', {
objectId: this._remoteObject.objectId objectId: this._remoteObject.objectId
}); });
if (!boxModel || !boxModel.model) if (!model)
return null; throw new Error('Node is detached from document');
return {
x: boxModel.model.margin[0], const quad = model.border;
y: boxModel.model.margin[1], const x = Math.min(quad[0], quad[2], quad[4], quad[6]);
width: boxModel.model.width, const y = Math.min(quad[1], quad[3], quad[5], quad[7]);
height: boxModel.model.height const width = Math.max(quad[0], quad[2], quad[4], quad[6]) - x;
}; const height = Math.max(quad[1], quad[3], quad[5], quad[7]) - y;
return {x, y, width, height};
} }
/** /**

Binary file not shown.

After

Width:  |  Height:  |  Size: 272 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@ -1503,6 +1503,33 @@ describe('Page', function() {
const screenshot = await elementHandle.screenshot(); const screenshot = await elementHandle.screenshot();
expect(screenshot).toBeGolden('screenshot-element-bounding-box.png'); expect(screenshot).toBeGolden('screenshot-element-bounding-box.png');
})); }));
it('should take into account padding and border', SX(async function() {
await page.setViewport({width: 500, height: 500});
await page.setContent('something above<h1 style="border:2px solid blue; background: green;">&nbsp;</h1>');
const elementHandle = await page.$('h1');
const screenshot = await elementHandle.screenshot();
expect(screenshot).toBeGolden('screenshot-element-padding-border.png');
}));
it('should work with a rotated element', SX(async function() {
await page.setViewport({width: 500, height: 500});
await page.setContent(`<div style="position:absolute;
top: 100px;
left: 100px;
width: 100px;
height: 100px;
background: green;
transform: rotateZ(200deg);">&nbsp;</div>`);
const elementHandle = await page.$('div');
const screenshot = await elementHandle.screenshot();
expect(screenshot).toBeGolden('screenshot-element-rotate.png');
}));
it('should fail to screenshot a detached element', SX(async function() {
await page.setContent('<h1>remove this</h1>');
const elementHandle = await page.$('h1');
await page.evaluate(element => element.remove(), elementHandle);
const screenshotError = await elementHandle.screenshot().catch(error => error);
expect(screenshotError.message).toBe('Node is detached from document');
}));
}); });
describe('input', function() { describe('input', function() {