From b096ffaa0359078bd5748b53b67e87c9453c7196 Mon Sep 17 00:00:00 2001 From: Alex Rudenko Date: Thu, 21 Mar 2024 09:16:24 +0100 Subject: [PATCH] fix: support clip in ElementHandle.screenshot (#12115) --- docs/api/puppeteer.screenshotoptions.md | 2 +- .../puppeteer-core/src/api/ElementHandle.ts | 18 ++++++++---- packages/puppeteer-core/src/api/Page.ts | 2 +- .../golden-chrome/screenshot-element-clip.png | Bin 0 -> 104 bytes .../screenshot-element-clip.png | Bin 0 -> 104 bytes test/src/screenshot.spec.ts | 27 ++++++++++++++++++ 6 files changed, 41 insertions(+), 8 deletions(-) create mode 100644 test/golden-chrome/screenshot-element-clip.png create mode 100644 test/golden-firefox/screenshot-element-clip.png diff --git a/docs/api/puppeteer.screenshotoptions.md b/docs/api/puppeteer.screenshotoptions.md index 465711aa5e1..7f42d79458b 100644 --- a/docs/api/puppeteer.screenshotoptions.md +++ b/docs/api/puppeteer.screenshotoptions.md @@ -68,7 +68,7 @@ clip -Specifies the region of the page to clip. +Specifies the region of the page/element to clip. diff --git a/packages/puppeteer-core/src/api/ElementHandle.ts b/packages/puppeteer-core/src/api/ElementHandle.ts index 9b1326f998e..896cf5fe34d 100644 --- a/packages/puppeteer-core/src/api/ElementHandle.ts +++ b/packages/puppeteer-core/src/api/ElementHandle.ts @@ -1236,9 +1236,9 @@ export abstract class ElementHandle< this: ElementHandle, options: Readonly = {} ): Promise { - const {scrollIntoView = true} = options; + const {scrollIntoView = true, clip} = options; - let clip = await this.#nonEmptyVisibleBoundingBox(); + let elementClip = await this.#nonEmptyVisibleBoundingBox(); const page = this.frame.page(); @@ -1247,7 +1247,7 @@ export abstract class ElementHandle< await this.scrollIntoViewIfNeeded(); // We measure again just in case. - clip = await this.#nonEmptyVisibleBoundingBox(); + elementClip = await this.#nonEmptyVisibleBoundingBox(); } const [pageLeft, pageTop] = await this.evaluate(() => { @@ -1259,10 +1259,16 @@ export abstract class ElementHandle< window.visualViewport.pageTop, ] as const; }); - clip.x += pageLeft; - clip.y += pageTop; + elementClip.x += pageLeft; + elementClip.y += pageTop; + if (clip) { + elementClip.x += clip.x; + elementClip.y += clip.y; + elementClip.height = clip.height; + elementClip.width = clip.width; + } - return await page.screenshot({...options, clip}); + return await page.screenshot({...options, clip: elementClip}); } async #nonEmptyVisibleBoundingBox() { diff --git a/packages/puppeteer-core/src/api/Page.ts b/packages/puppeteer-core/src/api/Page.ts index 234745e47c9..b3d65103720 100644 --- a/packages/puppeteer-core/src/api/Page.ts +++ b/packages/puppeteer-core/src/api/Page.ts @@ -274,7 +274,7 @@ export interface ScreenshotOptions { */ path?: string; /** - * Specifies the region of the page to clip. + * Specifies the region of the page/element to clip. */ clip?: ScreenshotClip; /** diff --git a/test/golden-chrome/screenshot-element-clip.png b/test/golden-chrome/screenshot-element-clip.png new file mode 100644 index 0000000000000000000000000000000000000000..609952cd3d3cab57b94e9b32684b7093b39bd8eb GIT binary patch literal 104 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1|)ksWqE-VV{wqX6T`Z5GB1G~B~KT}5R2aA zl#GNQ=N()RxcDA+%fT|fhUHx3vIVCg!0FrbX AlK=n! literal 0 HcmV?d00001 diff --git a/test/golden-firefox/screenshot-element-clip.png b/test/golden-firefox/screenshot-element-clip.png new file mode 100644 index 0000000000000000000000000000000000000000..609952cd3d3cab57b94e9b32684b7093b39bd8eb GIT binary patch literal 104 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1|)ksWqE-VV{wqX6T`Z5GB1G~B~KT}5R2aA zl#GNQ=N()RxcDA+%fT|fhUHx3vIVCg!0FrbX AlK=n! literal 0 HcmV?d00001 diff --git a/test/src/screenshot.spec.ts b/test/src/screenshot.spec.ts index 9176d0c9204..9880581217b 100644 --- a/test/src/screenshot.spec.ts +++ b/test/src/screenshot.spec.ts @@ -393,6 +393,33 @@ describe('Screenshots', function () { await context.close(); }); + + it('should use element clip', async () => { + const {page} = await getTestState(); + + await page.setViewport({width: 500, height: 500}); + await page.setContent(` + something above + +
+ `); + using elementHandle = (await page.$('div'))!; + const screenshot = await elementHandle.screenshot({ + clip: { + x: 10, + y: 10, + width: 20, + height: 20, + }, + }); + expect(screenshot).toBeGolden('screenshot-element-clip.png'); + }); }); describe('Cdp', () => {