From d507dfbdea16400ee6c59b5f7ef1f9ab7e8762ad Mon Sep 17 00:00:00 2001 From: artem-babich Date: Thu, 26 May 2022 23:22:42 +0400 Subject: [PATCH] Fix: Incorrect page size on screenshot in full-page mode in Chrome headless(closes #5961) --- package.json | 2 +- .../dedicated/chrome/cdp-client/index.ts | 55 ++++++------------- src/services/compiler/host.ts | 12 ++-- .../gh-5961/testcafe-fixtures/index.js | 7 ++- 4 files changed, 29 insertions(+), 47 deletions(-) diff --git a/package.json b/package.json index a22009b2716..205ae5adf3e 100644 --- a/package.json +++ b/package.json @@ -180,7 +180,7 @@ "chai-string": "^1.5.0", "chrome-launcher": "^0.15.0", "connect": "^3.4.0", - "devtools-protocol": "0.0.678506", + "devtools-protocol": "0.0.1007616", "dom-walk": "^0.1.1", "escape-string-regexp": "^4.0.0", "eslint-plugin-hammerhead": "0.4.0", diff --git a/src/browser/provider/built-in/dedicated/chrome/cdp-client/index.ts b/src/browser/provider/built-in/dedicated/chrome/cdp-client/index.ts index 3dc10a8368e..fa2aa94d64b 100644 --- a/src/browser/provider/built-in/dedicated/chrome/cdp-client/index.ts +++ b/src/browser/provider/built-in/dedicated/chrome/cdp-client/index.ts @@ -29,7 +29,7 @@ import ExecutionContext from './execution-context'; import * as clientsManager from './clients-manager'; import delay from '../../../../../../utils/delay'; -const DEBUG_SCOPE = (id: string): string => `testcafe:browser:provider:built-in:chrome:browser-client:${id}`; +const DEBUG_SCOPE = (id: string): string => `testcafe:browser:provider:built-in:chrome:browser-client:${ id }`; const DOWNLOADS_DIR = path.join(os.homedir(), 'Downloads'); const debugLog = debug('testcafe:browser:provider:built-in:dedicated:chrome'); @@ -86,7 +86,7 @@ export class BrowserClient { } private _checkDropOfPerformance (method: CheckedCDPMethod, elapsedTime: [number, number]): void { - this.debugLogger(`CDP method '${method}' took ${prettyTime(elapsedTime)}`); + this.debugLogger(`CDP method '${ method }' took ${ prettyTime(elapsedTime) }`); const [ elapsedSeconds ] = elapsedTime; @@ -206,15 +206,15 @@ export class BrowserClient { public async resizeWindow (newDimensions: Size): Promise { 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(); @@ -292,10 +292,7 @@ export class BrowserClient { } public async getScreenshotData (fullPage?: boolean): Promise { - let viewportWidth = 0; - let viewportHeight = 0; - - const { config, emulatedDevicePixelRatio } = this._runtimeInfo; + let clip: Protocol.Page.Viewport | undefined = void 0; const client = await this.getActiveClient(); @@ -307,37 +304,21 @@ 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: true, + }); - return Buffer.from(screenshotData.data, 'base64'); + return Buffer.from(result.data, 'base64'); } + public async closeTab (): Promise { if (this._parentTarget) await remoteChrome.Close({ id: this._parentTarget.id, port: this._runtimeInfo.cdpPort }); @@ -349,11 +330,11 @@ export class BrowserClient { if (!client) return; - const windowDimensionsQueryResult = await this._evaluateRuntime(client, `(${GET_WINDOW_DIMENSIONS_INFO_SCRIPT})()`, true); + const windowDimensionsQueryResult = await this._evaluateRuntime(client, `(${ GET_WINDOW_DIMENSIONS_INFO_SCRIPT })()`, true); const windowDimensions = windowDimensionsQueryResult.result.value; - this._runtimeInfo.viewportSize.width = windowDimensions.outerWidth; + this._runtimeInfo.viewportSize.width = windowDimensions.outerWidth; this._runtimeInfo.viewportSize.height = windowDimensions.outerHeight; } diff --git a/src/services/compiler/host.ts b/src/services/compiler/host.ts index 8b318e42aa3..3e8bbe959da 100644 --- a/src/services/compiler/host.ts +++ b/src/services/compiler/host.ts @@ -108,7 +108,7 @@ interface CompilerHostInitOptions { } export default class CompilerHost extends AsyncEventEmitter implements CompilerProtocol { - private runtime: Promise; + private runtime: Promise; private cdp: cdp.ProtocolApi & EventEmitter | undefined; private readonly developmentMode: boolean; private readonly v8Flags: string[]; @@ -174,7 +174,7 @@ export default class CompilerHost extends AsyncEventEmitter implements CompilerP includeCommandLineAPI: true, }); - await this.cdp.Debugger.resume(); + await this.cdp.Debugger.resume({ terminateOnResume: false }); }); testRunTracker.on(DEBUG_ACTION.step, async () => { @@ -191,7 +191,7 @@ export default class CompilerHost extends AsyncEventEmitter implements CompilerP includeCommandLineAPI: true, }); - await this.cdp.Debugger.resume(); + await this.cdp.Debugger.resume({ terminateOnResume: false }); }); // NOTE: need to step out from the source code until breakpoint is set in the code of test @@ -202,7 +202,7 @@ export default class CompilerHost extends AsyncEventEmitter implements CompilerP if (this.cdp) { if (args.reason === INITIAL_DEBUGGER_BREAK_ON_START) - return this.cdp.Debugger.resume(); + return this.cdp.Debugger.resume({ terminateOnResume: false }); if (callFrames[0].url.includes(INTERNAL_FILES_URL)) return this.cdp.Debugger.stepOut(); @@ -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): Promise { + private async _init (runtime: Promise): Promise { const resolvedRuntime = await runtime; if (resolvedRuntime) diff --git a/test/functional/fixtures/regression/gh-5961/testcafe-fixtures/index.js b/test/functional/fixtures/regression/gh-5961/testcafe-fixtures/index.js index 8564fd20ddc..fd9f82ca5b9 100644 --- a/test/functional/fixtures/regression/gh-5961/testcafe-fixtures/index.js +++ b/test/functional/fixtures/regression/gh-5961/testcafe-fixtures/index.js @@ -1,4 +1,4 @@ -import {Selector} from "testcafe"; +import { Selector } from 'testcafe'; fixture`Getting Started` .page`../pages/index.html`; @@ -8,15 +8,16 @@ const getBrowserName = (alias) => alias.split(':').join('_'); test('Take a full page screenshot', async t => { const path = `gh-5961/${ getBrowserName(t.browser.alias) }_full-page.png`; - await t.resizeWindow(2024, 768); + await t.resizeWindow(1024, 768); await t.takeScreenshot({ path, - fullPage: true + fullPage: true, }); }); test.page('https://advancedinstaller.com/blog/page-1.html')('Take a full page screenshot2', async t => { const path = `gh-5961/${ getBrowserName(t.browser.alias) }1_full-page.png`; + await t .resizeWindow(768, 800) .click(Selector('#cookies button'))