fix(webkit): fullPage screenshot w/o viewport (#210)

This commit is contained in:
Pavel Feldman 2019-12-11 11:26:34 -08:00 committed by Dmitry Gozman
parent 26e96bf591
commit 357e175964
6 changed files with 36 additions and 6 deletions

View file

@ -37,4 +37,8 @@ export class CRScreenshotDelegate implements ScreenshotterDelegate {
const result = await this._session.send('Page.captureScreenshot', { format, quality: options.quality, clip });
return Buffer.from(result.data, 'base64');
}
async resetViewport(): Promise<void> {
await this._session.send('Emulation.setDeviceMetricsOverride', { mobile: false, width: 0, height: 0, deviceScaleFactor: 0 });
}
}

View file

@ -39,4 +39,8 @@ export class FFScreenshotDelegate implements ScreenshotterDelegate {
});
return Buffer.from(data, 'base64');
}
async resetViewport(): Promise<void> {
await this._session.send('Page.setViewport', { viewport: null });
}
}

View file

@ -34,6 +34,7 @@ export interface ScreenshotterDelegate {
canCaptureOutsideViewport(): boolean;
setBackgroundColor(color?: { r: number; g: number; b: number; a: number; }): Promise<void>;
screenshot(format: string, options: types.ScreenshotOptions, viewport: types.Viewport): Promise<Buffer>;
resetViewport(oldSize: types.Size): Promise<void>;
}
export class Screenshotter {
@ -57,8 +58,15 @@ export class Screenshotter {
return this._queue.postTask(async () => {
let overridenViewport: types.Viewport | undefined;
const viewport = this._page.viewport();
if (viewport && options.fullPage && !this._delegate.canCaptureOutsideViewport()) {
const fullPage = await this._page.evaluate(() => ({
let viewportSize: types.Size | undefined;
if (!viewport) {
viewportSize = await this._page.evaluate(() => ({
width: Math.max(document.body.offsetWidth, document.documentElement.offsetWidth),
height: Math.max(document.body.offsetHeight, document.documentElement.offsetHeight)
}));
}
if (options.fullPage && !this._delegate.canCaptureOutsideViewport()) {
const fullPageRect = await this._page.evaluate(() => ({
width: Math.max(
document.body.scrollWidth, document.documentElement.scrollWidth,
document.body.offsetWidth, document.documentElement.offsetWidth,
@ -70,7 +78,7 @@ export class Screenshotter {
document.body.clientHeight, document.documentElement.clientHeight
)
}));
overridenViewport = { ...viewport, ...fullPage };
overridenViewport = viewport ? { ...viewport, ...fullPageRect } : fullPageRect;
await this._page.setViewport(overridenViewport);
} else if (options.clip) {
options.clip = trimClipToViewport(viewport, options.clip);
@ -78,8 +86,12 @@ export class Screenshotter {
const result = await this._screenshot(format, options, overridenViewport || viewport);
if (overridenViewport)
await this._page.setViewport(viewport);
if (overridenViewport) {
if (viewport)
await this._page.setViewport(viewport);
else
await this._delegate.resetViewport(viewportSize);
}
return result;
});
}

View file

@ -19,8 +19,9 @@ export type $$Eval<O = string | Selector> = <Args extends any[], R, S extends O>
export type EvaluateOn<T> = <Args extends any[], R>(pageFunction: PageFunctionOn<T, Args, R>, ...args: Boxed<Args>) => Promise<R>;
export type EvaluateHandleOn<T> = <Args extends any[], R>(pageFunction: PageFunctionOn<T, Args, R>, ...args: Boxed<Args>) => Promise<Handle<R>>;
export type Rect = { x: number, y: number, width: number, height: number };
export type Size = { width: number, height: number };
export type Point = { x: number, y: number };
export type Rect = Size & Point;
export type Quad = [ Point, Point, Point, Point ];
export type TimeoutOptions = { timeout?: number };

View file

@ -37,4 +37,8 @@ export class WKScreenshotDelegate implements ScreenshotterDelegate {
buffer = jpeg.encode(PNG.sync.read(buffer)).data;
return buffer;
}
async resetViewport(oldSize: types.Size): Promise<void> {
await this._session.send('Emulation.setDeviceMetricsOverride', { ...oldSize, deviceScaleFactor: 0 });
}
}

View file

@ -74,10 +74,15 @@ module.exports.addTests = function({testRunner, expect, defaultBrowserOptions, p
const browser = await playwright.launch(options);
const page = await browser.newPage();
await page.goto(server.PREFIX + '/grid.html');
const sizeBefore = await page.evaluate(() => ({ width: document.body.offsetWidth, height: document.body.offsetHeight }));
const screenshot = await page.screenshot({
fullPage: true
});
expect(screenshot).toBeInstanceOf(Buffer);
const sizeAfter = await page.evaluate(() => ({ width: document.body.offsetWidth, height: document.body.offsetHeight }));
expect(sizeBefore.width).toBe(sizeAfter.width);
expect(sizeBefore.height).toBe(sizeAfter.height);
await browser.close();
});
it('should have default URL when launching browser', async function() {