Skip to content

Commit

Permalink
fix: preserve correct page size on screenshot in full-page mode in Ch…
Browse files Browse the repository at this point in the history
…rome headless(closes #5961) (#7054)

## Purpose
For some reason in chrome:headless page body size is set incorrectly.

## Approach
Update devtools-protocol package and use the native screenshot approach.

## References
Closes #5961
Closes #7224

## Pre-Merge TODO
- [ ] Write tests for your proposed changes
- [ ] Make sure that existing tests do not fail

Co-authored-by: Andrey Belym <belym.a.2105@gmail.com>
Co-authored-by: Aleksey Popov <alekseypopow1995@yandex.ru>
  • Loading branch information
3 people committed Nov 2, 2022
1 parent f79980f commit 89eecab
Show file tree
Hide file tree
Showing 5 changed files with 125 additions and 37 deletions.
48 changes: 14 additions & 34 deletions src/browser/provider/built-in/dedicated/chrome/cdp-client/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -201,15 +201,15 @@ export class BrowserClient {
public async resizeWindow (newDimensions: Size): Promise<void> {
const { browserId, config, viewportSize, providerMethods, emulatedDevicePixelRatio } = this._runtimeInfo;

const currentWidth = viewportSize.width;
const currentWidth = viewportSize.width;
const currentHeight = viewportSize.height;
const newWidth = newDimensions.width || currentWidth;
const newHeight = newDimensions.height || currentHeight;
const newWidth = newDimensions.width || currentWidth;
const newHeight = newDimensions.height || currentHeight;

if (!config.headless)
await providerMethods.resizeLocalBrowserWindow(browserId, newWidth, newHeight, currentWidth, currentHeight);

viewportSize.width = newWidth;
viewportSize.width = newWidth;
viewportSize.height = newHeight;

const client = await this.getActiveClient();
Expand Down Expand Up @@ -281,10 +281,7 @@ export class BrowserClient {
}

public async getScreenshotData (fullPage?: boolean): Promise<Buffer> {
let viewportWidth = 0;
let viewportHeight = 0;

const { config, emulatedDevicePixelRatio } = this._runtimeInfo;
let clip: Protocol.Page.Viewport | undefined = void 0;

const client = await this.getActiveClient();

Expand All @@ -296,35 +293,18 @@ export class BrowserClient {
}

if (fullPage) {
const { contentSize, visualViewport } = await client.Page.getLayoutMetrics();

await this._setDeviceMetricsOverride(
client,
Math.ceil(contentSize.width),
Math.ceil(contentSize.height),
emulatedDevicePixelRatio,
config.mobile);
const metrics = await client.Page.getLayoutMetrics();
const { width, height } = metrics.cssContentSize || metrics.contentSize;

viewportWidth = visualViewport.clientWidth;
viewportHeight = visualViewport.clientHeight;
clip = { x: 0, y: 0, width, height, scale: 1 };
}

const screenshotData = await client.Page.captureScreenshot({});

if (fullPage) {
if (config.emulation) {
await this._setDeviceMetricsOverride(
client,
config.width || viewportWidth,
config.height || viewportHeight,
emulatedDevicePixelRatio,
config.mobile);
}
else
await client.Emulation.clearDeviceMetricsOverride();
}
const result = await client.Page.captureScreenshot({
clip,
captureBeyondViewport: fullPage,
});

return Buffer.from(screenshotData.data, 'base64');
return Buffer.from(result.data, 'base64');
}

public async closeTab (): Promise<void> {
Expand All @@ -342,7 +322,7 @@ export class BrowserClient {

const windowDimensions = windowDimensionsQueryResult.result.value;

this._runtimeInfo.viewportSize.width = windowDimensions.outerWidth;
this._runtimeInfo.viewportSize.width = windowDimensions.outerWidth;
this._runtimeInfo.viewportSize.height = windowDimensions.outerHeight;
}

Expand Down
6 changes: 3 additions & 3 deletions src/services/compiler/host.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ interface CompilerHostInitOptions {
}

export default class CompilerHost extends AsyncEventEmitter implements CompilerProtocol {
private runtime: Promise<RuntimeResources|undefined>;
private runtime: Promise<RuntimeResources | undefined>;
private cdp: cdp.ProtocolApi & EventEmitter | undefined;
private readonly developmentMode: boolean;
private readonly v8Flags: string[];
Expand Down Expand Up @@ -246,14 +246,14 @@ export default class CompilerHost extends AsyncEventEmitter implements CompilerP
args = this.v8Flags.filter(flag => !INSPECT_RE.test(flag));

// TODO: debugging: refactor to a separate debug info parsing unit
const inspectBrkFlag = `--inspect-brk=127.0.0.1:${port}`;
const inspectBrkFlag = `--inspect-brk=127.0.0.1:${ port }`;

args.push(inspectBrkFlag, SERVICE_PATH);

return args;
}

private async _init (runtime: Promise<RuntimeResources|undefined>): Promise<RuntimeResources|undefined> {
private async _init (runtime: Promise<RuntimeResources | undefined>): Promise<RuntimeResources | undefined> {
const resolvedRuntime = await runtime;

if (resolvedRuntime)
Expand Down
73 changes: 73 additions & 0 deletions test/functional/fixtures/regression/gh-5961/pages/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<title>Testcafe screenshot sizing issue</title>
<style>
* {
margin: 0;
padding: 0;
}

body {
background-color: black;
}

div.wrapper {
position: relative;
height: 5000px;
}

div.d {
width: 50px;
height: 50px;
position: absolute;
}

.left {
left: 0;
}

.right {
right: 0;
}

.top {
top: 0;
}

.bottom {
bottom: 0;
}

.red {
background-color: rgb(255, 0, 0);
}

.green {
background-color: rgb(0, 255, 0);
}

@media screen and (max-width: 1023px) {
.red {
background-color: rgb(0, 255, 0);
}

.green {
background-color: rgb(255, 0, 0);
}
}
</style>
</head>

<body>
<div class="wrapper">
<div class="d left top red"></div>
<div class="d right top green"></div>
<div class="d left bottom green"></div>
<div class="d right bottom red"></div>
</div>
</body>

</html>
20 changes: 20 additions & 0 deletions test/functional/fixtures/regression/gh-5961/test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
const assertionHelper = require('../../../assertion-helper.js');
const { expect } = require('chai');
const config = require('../../../config.js');
const { skipInExperimentalDebug } = require('../../../utils/skip-in.js');

if (config.useLocalBrowsers && config.useHeadlessBrowsers) {
describe('[Regression](GH-5961)', () => {
afterEach(assertionHelper.removeScreenshotDir);

skipInExperimentalDebug('Screenshot', () => {
return runTests('./testcafe-fixtures/index.js', 'Take a resized full page screenshot', { setScreenshotPath: true })
.then(function () {
return assertionHelper.checkScreenshotFileFullPage(false, 'custom');
})
.then(function (result) {
expect(result).eql(true);
});
});
});
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { ClientFunction } from 'testcafe';
import { parseUserAgent } from '../../../../../../lib/utils/parse-user-agent';

fixture`Getting Started`
.page`http://localhost:3000/fixtures/regression/gh-5961/pages/index.html`;

test('Take a resized full page screenshot', async t => {
const ua = await ClientFunction(() => navigator.userAgent.toString())();

await t.resizeWindow(1024, 768);
await t.takeScreenshot({
path: 'custom/' + parseUserAgent(ua).name + '.png',
fullPage: true,
});
});

0 comments on commit 89eecab

Please sign in to comment.