From 81127eb7e54a3e1cbe881cb75b6826b7722b39d6 Mon Sep 17 00:00:00 2001 From: Maksym Moshniaha Date: Mon, 17 Nov 2025 17:47:46 +0200 Subject: [PATCH] WAT-5355: Add possibility to take screenshots of elements --- core/types/src/browser-proxy/index.ts | 2 +- .../static-fixtures/screenshot.html | 5 ++--- .../selenium/test/element-screenshot.spec.js | 20 +++++++++++++++++++ .../src/plugin/index.ts | 4 ++-- .../web-application/src/web-application.ts | 14 +++++++++++-- packages/web-application/src/web-client.ts | 4 ++-- 6 files changed, 39 insertions(+), 10 deletions(-) create mode 100644 packages/e2e-test-app/test/selenium/test/element-screenshot.spec.js diff --git a/core/types/src/browser-proxy/index.ts b/core/types/src/browser-proxy/index.ts index dfe35be2b..4d9262076 100644 --- a/core/types/src/browser-proxy/index.ts +++ b/core/types/src/browser-proxy/index.ts @@ -175,7 +175,7 @@ export interface IBrowserProxyPlugin { makeScreenshot(applicant: string): Promise; - makeElementScreenshot(applicant: string, selector: Selector, scroll?: boolean): Promise; + makeElementScreenshot(applicant: string, selector: Selector): Promise; uploadFile(applicant: string, filePath: string): Promise; diff --git a/packages/e2e-test-app/static-fixtures/screenshot.html b/packages/e2e-test-app/static-fixtures/screenshot.html index 14bc26d50..d150be32f 100644 --- a/packages/e2e-test-app/static-fixtures/screenshot.html +++ b/packages/e2e-test-app/static-fixtures/screenshot.html @@ -9,9 +9,8 @@ -
- +
- \ No newline at end of file + diff --git a/packages/e2e-test-app/test/selenium/test/element-screenshot.spec.js b/packages/e2e-test-app/test/selenium/test/element-screenshot.spec.js new file mode 100644 index 000000000..e87d02aed --- /dev/null +++ b/packages/e2e-test-app/test/selenium/test/element-screenshot.spec.js @@ -0,0 +1,20 @@ +import {run} from 'testring'; +import {assert} from 'chai'; +import {getTargetUrl} from './utils'; + +run(async (api) => { + const app = api.application; + await app.url(getTargetUrl(api, 'screenshot.html')); + + const base64String = await app.makeElementScreenshot(app.root.testElement); + + assert.ok( + typeof base64String === 'string' && base64String.length > 0, + 'makeElementScreenshot should return a non-empty string', + ); + + assert.doesNotThrow( + () => Buffer.from(base64String, 'base64'), + 'returned string should be valid base64 encoded', + ); +}); diff --git a/packages/plugin-selenium-driver/src/plugin/index.ts b/packages/plugin-selenium-driver/src/plugin/index.ts index ae9bee63b..d1008867e 100644 --- a/packages/plugin-selenium-driver/src/plugin/index.ts +++ b/packages/plugin-selenium-driver/src/plugin/index.ts @@ -1247,12 +1247,12 @@ export class SeleniumPlugin implements IBrowserProxyPlugin { return client.takeScreenshot(); } - public async makeElementScreenshot(applicant: string, selector: Selector, scroll: boolean = true): Promise { + public async makeElementScreenshot(applicant: string, selector: Selector): Promise { await this.createClient(applicant); const client = this.getBrowserClient(applicant); const element = await this.getElement(applicant, selector); - return client.takeElementScreenshot(await element.elementId, scroll); + return client.takeElementScreenshot(await element.elementId); } public async uploadFile( diff --git a/packages/web-application/src/web-application.ts b/packages/web-application/src/web-application.ts index 5c5e12dab..c5e03b9f1 100644 --- a/packages/web-application/src/web-application.ts +++ b/packages/web-application/src/web-application.ts @@ -199,7 +199,7 @@ export class WebApplication extends PluggableModule { if (typeof selector === 'string') { return { type: 'xpath', xpath: selector } as XpathSelector; } - + if (this.isShadowElementPathProxy(selector)) { return { type: 'shadow-css', css: selector.toShadowCSSSelector(), parentSelectors: selector.getParentSelectors(), isShadowElement: true } as ShadowCssSelector; } @@ -458,7 +458,7 @@ export class WebApplication extends PluggableModule { return result; } - + @stepLog(function (this: WebApplication, xpath: ElementPath, timeout: number = this.WAIT_TIMEOUT) { return `Checking if ${this.formatXpath(xpath)} is visible for ${timeout}`; }) @@ -1714,6 +1714,16 @@ export class WebApplication extends PluggableModule { return null; } + @stepLog(function (this: WebApplication, xpath: ElementPath) { + return `Making screenshot of ${this.formatXpath(xpath)}`; + }) + public async makeElementScreenshot(xpath: ElementPath, timeout: number = this.WAIT_TIMEOUT): Promise { + await this.waitForExist(xpath, timeout); + + const normalizedXPath = this.normalizeSelector(xpath); + return await this.client.makeElementScreenshot(normalizedXPath); + } + @stepLog(function (this: WebApplication, fullPath: string) { return `Uploading file ${fullPath}`; }) diff --git a/packages/web-application/src/web-client.ts b/packages/web-application/src/web-client.ts index 6fa1a8798..f0ddb73dd 100644 --- a/packages/web-application/src/web-client.ts +++ b/packages/web-application/src/web-client.ts @@ -307,8 +307,8 @@ export class WebClient implements IWebApplicationClient { return this.makeRequest(BrowserProxyActions.makeScreenshot, []); } - public makeElementScreenshot(selector: Selector, scroll?: boolean) { - return this.makeRequest(BrowserProxyActions.makeElementScreenshot, [selector, scroll]); + public makeElementScreenshot(selector: Selector) { + return this.makeRequest(BrowserProxyActions.makeElementScreenshot, [selector]); } public uploadFile(path: string) {