chore: set allowViewportExpansion to captureBeyondViewport (#10992)

This commit is contained in:
jrandolf 2023-09-22 04:48:01 -07:00 committed by GitHub
parent 9676da3b51
commit 4ca36454c3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 75 additions and 7 deletions

View File

@ -1338,7 +1338,7 @@ export abstract class ElementHandle<
const { const {
scrollIntoView = true, scrollIntoView = true,
captureBeyondViewport = true, captureBeyondViewport = true,
allowViewportExpansion = true, allowViewportExpansion = captureBeyondViewport,
} = options; } = options;
let clip = await this.#nonEmptyVisibleBoundingBox(); let clip = await this.#nonEmptyVisibleBoundingBox();
@ -1347,7 +1347,7 @@ export abstract class ElementHandle<
// eslint-disable-next-line @typescript-eslint/no-unused-vars // eslint-disable-next-line @typescript-eslint/no-unused-vars
await using _ = await using _ =
(captureBeyondViewport || allowViewportExpansion) && clip allowViewportExpansion && clip
? await page._createTemporaryViewportContainingBox(clip) ? await page._createTemporaryViewportContainingBox(clip)
: null; : null;
@ -1373,7 +1373,6 @@ export abstract class ElementHandle<
return await page.screenshot({ return await page.screenshot({
...options, ...options,
captureBeyondViewport: false, captureBeyondViewport: false,
allowViewportExpansion: false,
clip, clip,
}); });
} }

View File

@ -2351,7 +2351,7 @@ export abstract class Page extends EventEmitter<PageEvents> {
} }
options.captureBeyondViewport ??= true; options.captureBeyondViewport ??= true;
options.allowViewportExpansion ??= true; options.allowViewportExpansion ??= options.captureBeyondViewport;
options.clip = options.clip && roundClip(normalizeClip(options.clip)); options.clip = options.clip && roundClip(normalizeClip(options.clip));
await using stack = new AsyncDisposableStack(); await using stack = new AsyncDisposableStack();

View File

@ -627,7 +627,12 @@ export class BidiPage extends Page {
override async screenshot( override async screenshot(
options: Readonly<ScreenshotOptions> = {} options: Readonly<ScreenshotOptions> = {}
): Promise<Buffer | string> { ): Promise<Buffer | string> {
const {clip, type, captureBeyondViewport} = options; const {
clip,
type,
captureBeyondViewport,
allowViewportExpansion = true,
} = options;
if (captureBeyondViewport) { if (captureBeyondViewport) {
throw new Error(`BiDi does not support 'captureBeyondViewport'.`); throw new Error(`BiDi does not support 'captureBeyondViewport'.`);
} }
@ -648,7 +653,11 @@ export class BidiPage extends Page {
if (clip?.scale !== undefined) { if (clip?.scale !== undefined) {
throw new Error(`BiDi does not support 'scale' in 'clip'.`); throw new Error(`BiDi does not support 'scale' in 'clip'.`);
} }
return await super.screenshot({...options, captureBeyondViewport: false}); return await super.screenshot({
...options,
captureBeyondViewport,
allowViewportExpansion: captureBeyondViewport ?? allowViewportExpansion,
});
} }
override async _screenshot( override async _screenshot(

View File

@ -35,6 +35,7 @@ import {
type NewDocumentScriptEvaluation, type NewDocumentScriptEvaluation,
type ScreenshotOptions, type ScreenshotOptions,
type WaitTimeoutOptions, type WaitTimeoutOptions,
type ScreenshotClip,
} from '../api/Page.js'; } from '../api/Page.js';
import { import {
ConsoleMessage, ConsoleMessage,
@ -1044,7 +1045,7 @@ export class CdpPage extends Page {
omitBackground, omitBackground,
optimizeForSpeed, optimizeForSpeed,
quality, quality,
clip, clip: userClip,
type, type,
captureBeyondViewport, captureBeyondViewport,
} = options; } = options;
@ -1057,6 +1058,22 @@ export class CdpPage extends Page {
}); });
} }
let clip = userClip;
if (clip && !captureBeyondViewport) {
const viewport = await this.mainFrame()
.isolatedRealm()
.evaluate(() => {
const {
height,
pageLeft: x,
pageTop: y,
width,
} = window.visualViewport!;
return {x, y, height, width};
});
clip = getIntersectionRect(clip, viewport);
}
const {data} = await this.#client.send('Page.captureScreenshot', { const {data} = await this.#client.send('Page.captureScreenshot', {
format: type, format: type,
optimizeForSpeed, optimizeForSpeed,
@ -1204,3 +1221,25 @@ const supportedMetrics = new Set<string>([
'JSHeapUsedSize', 'JSHeapUsedSize',
'JSHeapTotalSize', 'JSHeapTotalSize',
]); ]);
/** @see https://w3c.github.io/webdriver-bidi/#rectangle-intersection */
function getIntersectionRect(
clip: Readonly<ScreenshotClip>,
viewport: Readonly<Protocol.DOM.Rect>
): ScreenshotClip {
// Note these will already be normalized.
const x = Math.max(clip.x, viewport.x);
const y = Math.max(clip.y, viewport.y);
return {
x,
y,
width: Math.max(
Math.min(clip.x + clip.width, viewport.x + viewport.width) - x,
0
),
height: Math.max(
Math.min(clip.y + clip.height, viewport.y + viewport.height) - y,
0
),
};
}

View File

@ -1265,6 +1265,12 @@
"parameters": ["cdp", "firefox"], "parameters": ["cdp", "firefox"],
"expectations": ["FAIL", "SKIP"] "expectations": ["FAIL", "SKIP"]
}, },
{
"testIdPattern": "[screenshot.spec] Screenshots Page.screenshot should clip clip bigger than the viewport without \"captureBeyondViewport\"",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["firefox"],
"expectations": ["FAIL", "PASS"]
},
{ {
"testIdPattern": "[screenshot.spec] Screenshots Page.screenshot should get screenshot bigger than the viewport", "testIdPattern": "[screenshot.spec] Screenshots Page.screenshot should get screenshot bigger than the viewport",
"platforms": ["darwin", "linux", "win32"], "platforms": ["darwin", "linux", "win32"],

Binary file not shown.

After

Width:  |  Height:  |  Size: 188 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 204 B

View File

@ -77,6 +77,21 @@ describe('Screenshots', function () {
}); });
expect(screenshot).toBeGolden('screenshot-offscreen-clip.png'); expect(screenshot).toBeGolden('screenshot-offscreen-clip.png');
}); });
it('should clip clip bigger than the viewport without "captureBeyondViewport"', async () => {
const {page, server} = await getTestState();
await page.setViewport({width: 50, height: 50});
await page.goto(server.PREFIX + '/grid.html');
const screenshot = await page.screenshot({
captureBeyondViewport: false,
clip: {
x: 25,
y: 25,
width: 100,
height: 100,
},
});
expect(screenshot).toBeGolden('screenshot-offscreen-clip-2.png');
});
it('should run in parallel', async () => { it('should run in parallel', async () => {
const {page, server} = await getTestState(); const {page, server} = await getTestState();