From 3e8d84009f7a6b7d3c52e1440e1345e8da551f72 Mon Sep 17 00:00:00 2001 From: vchimev Date: Thu, 23 Nov 2017 20:06:31 +0200 Subject: [PATCH 1/3] feat(image-comparison): implement for elements and rectangles --- lib/appium-driver.d.ts | 3 ++ lib/appium-driver.ts | 80 +++++++++++++++++++++++++++++++++++++++--- lib/image-helper.d.ts | 1 + lib/image-helper.ts | 19 ++++++++++ lib/ui-element.d.ts | 18 +++++++++- lib/ui-element.ts | 27 +++++++++++--- 6 files changed, 138 insertions(+), 10 deletions(-) diff --git a/lib/appium-driver.d.ts b/lib/appium-driver.d.ts index 8f3d318..1859215 100644 --- a/lib/appium-driver.d.ts +++ b/lib/appium-driver.d.ts @@ -5,6 +5,7 @@ import { UIElement } from "./ui-element"; import { Direction } from "./direction"; import { Locator } from "./locators"; import { INsCapabilities } from "./interfaces/ns-capabilities"; +import { IRectangle } from "./interfaces/rectangle"; import { Point } from "./point"; import { ImageHelper } from "./image-helper"; export declare class AppiumDriver { @@ -121,6 +122,8 @@ export declare class AppiumDriver { swipe(y: number, x: number, yOffset: number, inertia?: number, xOffset?: number): Promise; source(): Promise; sessionId(): Promise; + compareElement(element: UIElement, imageName: string): Promise; + compareRectangle(rect: IRectangle, imageName: string, timeOutSeconds?: number, tollerance?: number): Promise; compareScreen(imageName: string, timeOutSeconds?: number, tollerance?: number): Promise; takeScreenshot(fileName: string): Promise; logScreenshot(fileName: string): Promise; diff --git a/lib/appium-driver.ts b/lib/appium-driver.ts index 26d95a9..b3c41c4 100644 --- a/lib/appium-driver.ts +++ b/lib/appium-driver.ts @@ -22,6 +22,7 @@ import { scroll } from "./utils"; import { INsCapabilities } from "./interfaces/ns-capabilities"; +import { IRectangle } from "./interfaces/rectangle"; import { Point } from "./point"; import { ImageHelper } from "./image-helper"; import { ImageOptions } from "./image-options" @@ -268,6 +269,77 @@ export class AppiumDriver { return await this.driver.getSessionId(); } + public async compareElement(element: UIElement, imageName: string, ) { + return this.compareRectangle(await element.getRectangle(), imageName); + } + + public async compareRectangle(rect: IRectangle, imageName: string, timeOutSeconds: number = 3, tollerance: number = 0.01) { + if (!imageName.endsWith(AppiumDriver.pngFileExt)) { + imageName = imageName.concat(AppiumDriver.pngFileExt); + } + + if (!this._storageByDeviceName) { + this._storageByDeviceName = getStorageByDeviceName(this._args); + } + + let expectedImage = resolve(this._storageByDeviceName, imageName); + if (!fileExists(expectedImage)) { + if (!this._storageByPlatform) { + this._storageByPlatform = getStorageByPlatform(this._args); + } + expectedImage = resolve(this._storageByPlatform, imageName); + } + + if (!fileExists(expectedImage)) { + expectedImage = resolve(this._storageByDeviceName, imageName); + } + + if (!this._logPath) { + this._logPath = getReportPath(this._args); + } + + expectedImage = resolve(this._storageByDeviceName, imageName); + + // Firts capture of screen when the expected image is not available + if (!fileExists(expectedImage)) { + await this.takeScreenshot(resolve(this._storageByDeviceName, imageName.replace(".", "_actual."))); + console.log("Remove the 'actual' suffix to continue using the image as expected one ", expectedImage); + let eventStartTime = Date.now().valueOf(); + let counter = 1; + timeOutSeconds *= 1000; + + while ((Date.now().valueOf() - eventStartTime) <= timeOutSeconds) { + let actualImage = await this.takeScreenshot(resolve(this._logPath, imageName.replace(".", "_actual" + "_" + counter + "."))); + counter++; + } + + // return false; + } + + let actualImage = await this.takeScreenshot(resolve(this._logPath, imageName.replace(".", "_actual."))); + let diffImage = actualImage.replace("actual", "diff"); + let result = await this._imageHelper.compareRectangle(rect, actualImage, expectedImage, diffImage, tollerance); + if (!result) { + let eventStartTime = Date.now().valueOf(); + let counter = 1; + timeOutSeconds *= 1000; + while ((Date.now().valueOf() - eventStartTime) <= timeOutSeconds && !result) { + let actualImage = await this.takeScreenshot(resolve(this._logPath, imageName.replace(".", "_actual" + "_" + counter + "."))); + result = await this._imageHelper.compareRectangle(rect, actualImage, expectedImage, diffImage, tollerance); + counter++; + } + } else { + if (fileExists(diffImage)) { + unlinkSync(diffImage); + } + if (fileExists(actualImage)) { + unlinkSync(actualImage); + } + } + + return result; + } + public async compareScreen(imageName: string, timeOutSeconds: number = 3, tollerance: number = 0.01) { if (!imageName.endsWith(AppiumDriver.pngFileExt)) { imageName = imageName.concat(AppiumDriver.pngFileExt); @@ -281,14 +353,14 @@ export class AppiumDriver { if (!fileExists(expectedImage)) { if (!this._storageByPlatform) { this._storageByPlatform = getStorageByPlatform(this._args); - } - expectedImage = resolve(this._storageByPlatform, imageName); + } + expectedImage = resolve(this._storageByPlatform, imageName); } - + if (!fileExists(expectedImage)) { expectedImage = resolve(this._storageByDeviceName, imageName); } - + if (!this._logPath) { this._logPath = getReportPath(this._args); } diff --git a/lib/image-helper.d.ts b/lib/image-helper.d.ts index c426f8b..51c7d2f 100644 --- a/lib/image-helper.d.ts +++ b/lib/image-helper.d.ts @@ -19,5 +19,6 @@ export declare class ImageHelper { y: any; }; private runDiff(diffOptions, diffImage); + compareRectangle(rect: IRectangle, actual: string, expected: string, output: string, valueThreshold?: number, typeThreshold?: any): Promise; compareImages(actual: string, expected: string, output: string, valueThreshold?: number, typeThreshold?: any): Promise; } diff --git a/lib/image-helper.ts b/lib/image-helper.ts index eda6f38..6761d2e 100644 --- a/lib/image-helper.ts +++ b/lib/image-helper.ts @@ -76,6 +76,25 @@ export class ImageHelper { }); } + public compareRectangle(rect: IRectangle, actual: string, expected: string, output: string, valueThreshold: number = this.threshold(), typeThreshold: any = ImageOptions.pixel) { + let diff = new blinkDiff({ + + imageAPath: actual, + imageBPath: expected, + imageOutputPath: output, + imageOutputLimit: this.imageOutputLimit(), + thresholdType: typeThreshold, + threshold: valueThreshold, + delta: this.delta(), + + cropImageA: rect, + verbose: this._args.verbose, + }); + + const result = this.runDiff(diff, output); + return result; + } + public compareImages(actual: string, expected: string, output: string, valueThreshold: number = this.threshold(), typeThreshold: any = ImageOptions.pixel) { const rectToCrop = this._cropImageRect || ImageHelper.cropImageDefaultParams(this._args); let diff = new blinkDiff({ diff --git a/lib/ui-element.d.ts b/lib/ui-element.d.ts index a9b5be3..12248d5 100644 --- a/lib/ui-element.d.ts +++ b/lib/ui-element.d.ts @@ -18,7 +18,7 @@ export declare class UIElement { */ tap(): Promise; /** - * double tap + * Double tap on element */ doubleTap(): Promise; /** @@ -29,6 +29,9 @@ export declare class UIElement { * Get size of element */ size(): Promise; + /** + * Get text of element + */ text(): Promise; /** * Get web driver element @@ -52,7 +55,20 @@ export declare class UIElement { * @param wait */ waitForExist(wait?: number): Promise; + /** + * Get attribute of element + * @param attr + */ getAttribute(attr: any): Promise; + /** + * Get rectangle of element + */ + getRectangle(): Promise<{ + x: number; + y: number; + width: number; + height: number; + }>; /** * Scroll with offset from elemnt with minimum inertia * @param direction diff --git a/lib/ui-element.ts b/lib/ui-element.ts index 1ac89ac..3fb7e31 100644 --- a/lib/ui-element.ts +++ b/lib/ui-element.ts @@ -1,10 +1,10 @@ import { Point } from "./point"; import { Direction } from "./direction"; +import { IRectangle } from "./interfaces/rectangle"; import { calculateOffset } from "./utils"; export class UIElement { - constructor(private _element: any, private _driver: any, private _wd: any, private _webio: any, private _searchMethod: string, private _searchParams: string, private _index?: number) { - } + constructor(private _element: any, private _driver: any, private _wd: any, private _webio: any, private _searchMethod: string, private _searchParams: string, private _index?: number) { } /** * Click on element @@ -21,7 +21,7 @@ export class UIElement { } /** - * double tap + * Double tap on element */ public async doubleTap() { return await this._driver.execute('mobile: doubleTap', { element: (await this.element()).value.ELEMENT }); @@ -46,6 +46,9 @@ export class UIElement { return point; } + /** + * Get text of element + */ public async text() { return await (await this.element()).text(); } @@ -89,10 +92,24 @@ export class UIElement { return this._webio.waitForExist(this._searchParams, wait, false); } + /** + * Get attribute of element + * @param attr + */ public async getAttribute(attr) { return await (await this.element()).getAttribute(attr); } + /** + * Get rectangle of element + */ + public async getRectangle() { + const location = await this.location(); + const size = await this.size(); + const rect = { x: location.x, y: location.y, width: size.y, height: size.x }; + return rect; + } + /** * Scroll with offset from elemnt with minimum inertia * @param direction @@ -112,7 +129,7 @@ export class UIElement { if (direction === Direction.down) { y = (location.y + size.y) - 15; - + if (!this._webio.isIOS) { if (yOffset === 0) { yOffset = location.y + size.y - 15; @@ -197,7 +214,7 @@ export class UIElement { public async hold() { let action = new this._wd.TouchAction(this._driver); action - .longPress({el: await this.element()}) + .longPress({ el: await this.element() }) .release(); await action.perform(); await this._driver.sleep(150); From d11765545289ce0e06cd5e41a685c13663da85db Mon Sep 17 00:00:00 2001 From: vchimev Date: Tue, 28 Nov 2017 21:13:06 +0200 Subject: [PATCH 2/3] feat(image-comparison): first time capture of element/rectangle --- lib/appium-driver.d.ts | 5 +- lib/appium-driver.ts | 173 ++++++++++++++++------------------------- lib/image-helper.d.ts | 12 +-- lib/image-helper.ts | 68 +++++++++------- lib/utils.d.ts | 1 + lib/utils.ts | 2 + 6 files changed, 120 insertions(+), 141 deletions(-) diff --git a/lib/appium-driver.d.ts b/lib/appium-driver.d.ts index 1859215..53dbfc6 100644 --- a/lib/appium-driver.d.ts +++ b/lib/appium-driver.d.ts @@ -123,8 +123,10 @@ export declare class AppiumDriver { source(): Promise; sessionId(): Promise; compareElement(element: UIElement, imageName: string): Promise; - compareRectangle(rect: IRectangle, imageName: string, timeOutSeconds?: number, tollerance?: number): Promise; + compareRectangles(rect: IRectangle, imageName: string, timeOutSeconds?: number, tollerance?: number): Promise; compareScreen(imageName: string, timeOutSeconds?: number, tollerance?: number): Promise; + compare(imageName: string, timeOutSeconds?: number, tollerance?: number, rect?: IRectangle): Promise; + prepareImageToCompare(filePath: string, rect: IRectangle): Promise; takeScreenshot(fileName: string): Promise; logScreenshot(fileName: string): Promise; logPageSource(fileName: string): Promise; @@ -134,4 +136,5 @@ export declare class AppiumDriver { quit(): Promise; private convertArrayToUIElements(array, searchM, args); private static configureLogging(driver, verbose); + private getExpectedImagePath(imageName); } diff --git a/lib/appium-driver.ts b/lib/appium-driver.ts index b3c41c4..19d8a51 100644 --- a/lib/appium-driver.ts +++ b/lib/appium-driver.ts @@ -11,6 +11,7 @@ import { UIElement } from "./ui-element"; import { Direction } from "./direction"; import { Locator } from "./locators"; import { + addExt, log, getStorageByPlatform, getStorageByDeviceName, @@ -19,7 +20,7 @@ import { getAppPath, getReportPath, calculateOffset, - scroll + scroll, } from "./utils"; import { INsCapabilities } from "./interfaces/ns-capabilities"; import { IRectangle } from "./interfaces/rectangle"; @@ -270,141 +271,81 @@ export class AppiumDriver { } public async compareElement(element: UIElement, imageName: string, ) { - return this.compareRectangle(await element.getRectangle(), imageName); + return this.compareRectangles(await element.getRectangle(), imageName); } - public async compareRectangle(rect: IRectangle, imageName: string, timeOutSeconds: number = 3, tollerance: number = 0.01) { - if (!imageName.endsWith(AppiumDriver.pngFileExt)) { - imageName = imageName.concat(AppiumDriver.pngFileExt); - } - - if (!this._storageByDeviceName) { - this._storageByDeviceName = getStorageByDeviceName(this._args); - } + public async compareRectangles(rect: IRectangle, imageName: string, timeOutSeconds: number = 3, tollerance: number = 0.01) { + return this.compare(imageName, timeOutSeconds, tollerance, rect); + } - let expectedImage = resolve(this._storageByDeviceName, imageName); - if (!fileExists(expectedImage)) { - if (!this._storageByPlatform) { - this._storageByPlatform = getStorageByPlatform(this._args); - } - expectedImage = resolve(this._storageByPlatform, imageName); - } + public async compareScreen(imageName: string, timeOutSeconds: number = 3, tollerance: number = 0.01) { + return this.compare(imageName, timeOutSeconds, tollerance); + } - if (!fileExists(expectedImage)) { - expectedImage = resolve(this._storageByDeviceName, imageName); - } + public async compare(imageName: string, timeOutSeconds: number = 3, tollerance: number = 0.01, rect?: IRectangle) { if (!this._logPath) { this._logPath = getReportPath(this._args); } - expectedImage = resolve(this._storageByDeviceName, imageName); + imageName = addExt(imageName, AppiumDriver.pngFileExt); - // Firts capture of screen when the expected image is not available - if (!fileExists(expectedImage)) { - await this.takeScreenshot(resolve(this._storageByDeviceName, imageName.replace(".", "_actual."))); - console.log("Remove the 'actual' suffix to continue using the image as expected one ", expectedImage); - let eventStartTime = Date.now().valueOf(); - let counter = 1; - timeOutSeconds *= 1000; + const pathExpectedImage = this.getExpectedImagePath(imageName); - while ((Date.now().valueOf() - eventStartTime) <= timeOutSeconds) { - let actualImage = await this.takeScreenshot(resolve(this._logPath, imageName.replace(".", "_actual" + "_" + counter + "."))); - counter++; + // First time capture + if (!fileExists(pathExpectedImage)) { + const pathActualImage = resolve(this._storageByDeviceName, imageName.replace(".", "_actual.")); + await this.takeScreenshot(pathActualImage); + + if (rect) { + await this._imageHelper.clipRectangleImage(rect, pathActualImage); } - // return false; + console.log("Remove the 'actual' suffix to continue using the image as expected one ", pathExpectedImage); + return false; } - let actualImage = await this.takeScreenshot(resolve(this._logPath, imageName.replace(".", "_actual."))); - let diffImage = actualImage.replace("actual", "diff"); - let result = await this._imageHelper.compareRectangle(rect, actualImage, expectedImage, diffImage, tollerance); + // Compare + let pathActualImage = await this.takeScreenshot(resolve(this._logPath, imageName.replace(".", "_actual."))); + const pathDiffImage = pathActualImage.replace("actual", "diff"); + + await this.prepareImageToCompare(pathActualImage, rect); + let result = await this._imageHelper.compareImages(pathActualImage, pathExpectedImage, pathDiffImage, tollerance); + + // Iterate if (!result) { - let eventStartTime = Date.now().valueOf(); + const eventStartTime = Date.now().valueOf(); let counter = 1; timeOutSeconds *= 1000; while ((Date.now().valueOf() - eventStartTime) <= timeOutSeconds && !result) { - let actualImage = await this.takeScreenshot(resolve(this._logPath, imageName.replace(".", "_actual" + "_" + counter + "."))); - result = await this._imageHelper.compareRectangle(rect, actualImage, expectedImage, diffImage, tollerance); + const pathActualImageConter = resolve(this._logPath, imageName.replace(".", "_actual_" + counter + ".")); + pathActualImage = await this.takeScreenshot(pathActualImageConter); + + await this.prepareImageToCompare(pathActualImage, rect); + result = await this._imageHelper.compareImages(pathActualImage, pathExpectedImage, pathDiffImage, tollerance); counter++; } } else { - if (fileExists(diffImage)) { - unlinkSync(diffImage); + if (fileExists(pathDiffImage)) { + unlinkSync(pathDiffImage); } - if (fileExists(actualImage)) { - unlinkSync(actualImage); + if (fileExists(pathActualImage)) { + unlinkSync(pathActualImage); } } + this._imageHelper.imageCropRect = undefined; return result; } - public async compareScreen(imageName: string, timeOutSeconds: number = 3, tollerance: number = 0.01) { - if (!imageName.endsWith(AppiumDriver.pngFileExt)) { - imageName = imageName.concat(AppiumDriver.pngFileExt); - } - - if (!this._storageByDeviceName) { - this._storageByDeviceName = getStorageByDeviceName(this._args); - } - - let expectedImage = resolve(this._storageByDeviceName, imageName); - if (!fileExists(expectedImage)) { - if (!this._storageByPlatform) { - this._storageByPlatform = getStorageByPlatform(this._args); - } - expectedImage = resolve(this._storageByPlatform, imageName); - } - - if (!fileExists(expectedImage)) { - expectedImage = resolve(this._storageByDeviceName, imageName); - } - - if (!this._logPath) { - this._logPath = getReportPath(this._args); - } - - expectedImage = resolve(this._storageByDeviceName, imageName); - - // Firts capture of screen when the expected image is not available - if (!fileExists(expectedImage)) { - await this.takeScreenshot(resolve(this._storageByDeviceName, imageName.replace(".", "_actual."))); - console.log("Remove the 'actual' suffix to continue using the image as expected one ", expectedImage); - let eventStartTime = Date.now().valueOf(); - let counter = 1; - timeOutSeconds *= 1000; - - while ((Date.now().valueOf() - eventStartTime) <= timeOutSeconds) { - let actualImage = await this.takeScreenshot(resolve(this._logPath, imageName.replace(".", "_actual" + "_" + counter + "."))); - counter++; - } - - return false; - } - - let actualImage = await this.takeScreenshot(resolve(this._logPath, imageName.replace(".", "_actual."))); - let diffImage = actualImage.replace("actual", "diff"); - let result = await this._imageHelper.compareImages(actualImage, expectedImage, diffImage, tollerance); - if (!result) { - let eventStartTime = Date.now().valueOf(); - let counter = 1; - timeOutSeconds *= 1000; - while ((Date.now().valueOf() - eventStartTime) <= timeOutSeconds && !result) { - let actualImage = await this.takeScreenshot(resolve(this._logPath, imageName.replace(".", "_actual" + "_" + counter + "."))); - result = await this._imageHelper.compareImages(actualImage, expectedImage, diffImage, tollerance); - counter++; - } + public async prepareImageToCompare(filePath: string, rect: IRectangle) { + if (rect) { + await this._imageHelper.clipRectangleImage(rect, filePath); + const rectToCrop = { x: 0, y: 0, width: undefined, height: undefined }; + this._imageHelper.imageCropRect = rectToCrop; } else { - if (fileExists(diffImage)) { - unlinkSync(diffImage); - } - if (fileExists(actualImage)) { - unlinkSync(actualImage); - } + this._imageHelper.imageCropRect = ImageHelper.cropImageDefault(this._args); } - - return result; } public takeScreenshot(fileName: string) { @@ -529,4 +470,26 @@ export class AppiumDriver { log(" > " + meth.magenta + path + " " + (data || "").grey, verbose); }); }; + + private getExpectedImagePath(imageName: string) { + + if (!this._storageByDeviceName) { + this._storageByDeviceName = getStorageByDeviceName(this._args); + } + + let pathExpectedImage = resolve(this._storageByDeviceName, imageName); + + if (!fileExists(pathExpectedImage)) { + if (!this._storageByPlatform) { + this._storageByPlatform = getStorageByPlatform(this._args); + } + pathExpectedImage = resolve(this._storageByPlatform, imageName); + } + + if (!fileExists(pathExpectedImage)) { + pathExpectedImage = resolve(this._storageByDeviceName, imageName); + } + + return pathExpectedImage; + } } \ No newline at end of file diff --git a/lib/image-helper.d.ts b/lib/image-helper.d.ts index 51c7d2f..0766810 100644 --- a/lib/image-helper.d.ts +++ b/lib/image-helper.d.ts @@ -6,19 +6,21 @@ export declare class ImageHelper { private _cropImageRect; private _blockOutAreas; constructor(_args: INsCapabilities); - readonly cropImageRect: IRectangle; - cropImageRec: IRectangle; + imageCropRect: IRectangle; blockOutAreas: IRectangle[]; imageOutputLimit(): ImageOptions; thresholdType(): ImageOptions; threshold(): number; delta(): number; - private static getOffsetPixels(args); - static cropImageDefaultParams(_args: INsCapabilities): { + static cropImageDefault(_args: INsCapabilities): { x: number; y: any; + width: any; + height: any; }; + private static getOffsetPixels(args); private runDiff(diffOptions, diffImage); - compareRectangle(rect: IRectangle, actual: string, expected: string, output: string, valueThreshold?: number, typeThreshold?: any): Promise; compareImages(actual: string, expected: string, output: string, valueThreshold?: number, typeThreshold?: any): Promise; + clipRectangleImage(rect: IRectangle, path: string): Promise<{}>; + readImage(path: string): Promise; } diff --git a/lib/image-helper.ts b/lib/image-helper.ts index 6761d2e..257e5d6 100644 --- a/lib/image-helper.ts +++ b/lib/image-helper.ts @@ -1,7 +1,9 @@ -import * as blinkDiff from "blink-diff"; +import * as BlinkDiff from "blink-diff"; +import * as PngJsImage from "pngjs-image"; import { ImageOptions } from "./image-options"; import { INsCapabilities } from "./interfaces/ns-capabilities"; import { IRectangle } from "./interfaces/rectangle"; +import { Point } from "./point"; export class ImageHelper { @@ -11,11 +13,11 @@ export class ImageHelper { constructor(private _args: INsCapabilities) { } - get cropImageRect() { + get imageCropRect(): IRectangle { return this._cropImageRect; } - set cropImageRec(rect: IRectangle) { + set imageCropRect(rect: IRectangle) { this._cropImageRect = rect; } @@ -43,15 +45,15 @@ export class ImageHelper { return 20; } - private static getOffsetPixels(args: INsCapabilities) { - return args.device.config ? args.device.config.offsetPixels : 0 + public static cropImageDefault(_args: INsCapabilities) { + return { x: 0, y: ImageHelper.getOffsetPixels(_args), width: undefined, height: undefined }; } - public static cropImageDefaultParams(_args: INsCapabilities) { - return { x: 0, y: ImageHelper.getOffsetPixels(_args) }; + private static getOffsetPixels(args: INsCapabilities) { + return args.device.config ? args.device.config.offsetPixels : 0 } - private runDiff(diffOptions: blinkDiff, diffImage: string) { + private runDiff(diffOptions: BlinkDiff, diffImage: string) { return new Promise((resolve, reject) => { diffOptions.run(function (error, result) { if (error) { @@ -76,8 +78,8 @@ export class ImageHelper { }); } - public compareRectangle(rect: IRectangle, actual: string, expected: string, output: string, valueThreshold: number = this.threshold(), typeThreshold: any = ImageOptions.pixel) { - let diff = new blinkDiff({ + public compareImages(actual: string, expected: string, output: string, valueThreshold: number = this.threshold(), typeThreshold: any = ImageOptions.pixel) { + const diff = new BlinkDiff({ imageAPath: actual, imageBPath: expected, @@ -87,34 +89,40 @@ export class ImageHelper { threshold: valueThreshold, delta: this.delta(), - cropImageA: rect, + cropImageA: this._cropImageRect, + cropImageB: this._cropImageRect, + blockOut: this._blockOutAreas, verbose: this._args.verbose, }); const result = this.runDiff(diff, output); + this._blockOutAreas = undefined; return result; } - public compareImages(actual: string, expected: string, output: string, valueThreshold: number = this.threshold(), typeThreshold: any = ImageOptions.pixel) { - const rectToCrop = this._cropImageRect || ImageHelper.cropImageDefaultParams(this._args); - let diff = new blinkDiff({ - - imageAPath: actual, - imageBPath: expected, - imageOutputPath: output, - imageOutputLimit: this.imageOutputLimit(), - thresholdType: typeThreshold, - threshold: valueThreshold, - delta: this.delta(), + public async clipRectangleImage(rect: IRectangle, path: string) { + let imageToClip: PngJsImage; + imageToClip = await this.readImage(path); + imageToClip.clip(rect.x, rect.y, rect.width, rect.height); + return new Promise((resolve, reject) => { + imageToClip.writeImage(path, (err) => { + if (err) { + return reject(err); + } + return resolve(); + }); - cropImageA: rectToCrop, - cropImageB: rectToCrop, - blockOut: this._blockOutAreas, - verbose: this._args.verbose, - }); + }) + } - const result = this.runDiff(diff, output); - this._blockOutAreas = undefined; - return result; + public readImage(path: string): Promise { + return new Promise((resolve, reject) => { + PngJsImage.readImage(path, (err, image) => { + if (err) { + return reject(err); + } + return resolve(image); + }); + }) } } diff --git a/lib/utils.d.ts b/lib/utils.d.ts index 7ed8dad..d6a8f71 100644 --- a/lib/utils.d.ts +++ b/lib/utils.d.ts @@ -33,3 +33,4 @@ export declare function calculateOffset(direction: any, y: number, yOffset: numb * @param xOffset */ export declare function scroll(wd: any, driver: any, direction: Direction, isIOS: boolean, y: number, x: number, yOffset: number, xOffset: number, verbose: any): Promise; +export declare const addExt: (fileName: string, ext: string) => string; diff --git a/lib/utils.ts b/lib/utils.ts index a70087f..9c723ea 100644 --- a/lib/utils.ts +++ b/lib/utils.ts @@ -386,3 +386,5 @@ function createStorageFolder(storage, direcotry) { return storage; } + +export const addExt = (fileName: string, ext: string) => { return fileName.endsWith(ext) ? fileName : fileName.concat(ext); } \ No newline at end of file From 80e8a01a9c60a37245a9a708b8d1831f8c3915c9 Mon Sep 17 00:00:00 2001 From: vchimev Date: Wed, 29 Nov 2017 14:53:06 +0200 Subject: [PATCH 3/3] refactor: image-compaarison for elements and rectangles --- lib/appium-driver.d.ts | 2 +- lib/appium-driver.ts | 8 ++++---- lib/ui-element.ts | 1 - 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/lib/appium-driver.d.ts b/lib/appium-driver.d.ts index 53dbfc6..48d5c0c 100644 --- a/lib/appium-driver.d.ts +++ b/lib/appium-driver.d.ts @@ -125,7 +125,7 @@ export declare class AppiumDriver { compareElement(element: UIElement, imageName: string): Promise; compareRectangles(rect: IRectangle, imageName: string, timeOutSeconds?: number, tollerance?: number): Promise; compareScreen(imageName: string, timeOutSeconds?: number, tollerance?: number): Promise; - compare(imageName: string, timeOutSeconds?: number, tollerance?: number, rect?: IRectangle): Promise; + private compare(imageName, timeOutSeconds?, tollerance?, rect?); prepareImageToCompare(filePath: string, rect: IRectangle): Promise; takeScreenshot(fileName: string): Promise; logScreenshot(fileName: string): Promise; diff --git a/lib/appium-driver.ts b/lib/appium-driver.ts index 19d8a51..02a46c8 100644 --- a/lib/appium-driver.ts +++ b/lib/appium-driver.ts @@ -271,18 +271,18 @@ export class AppiumDriver { } public async compareElement(element: UIElement, imageName: string, ) { - return this.compareRectangles(await element.getRectangle(), imageName); + return await this.compareRectangles(await element.getRectangle(), imageName); } public async compareRectangles(rect: IRectangle, imageName: string, timeOutSeconds: number = 3, tollerance: number = 0.01) { - return this.compare(imageName, timeOutSeconds, tollerance, rect); + return await this.compare(imageName, timeOutSeconds, tollerance, rect); } public async compareScreen(imageName: string, timeOutSeconds: number = 3, tollerance: number = 0.01) { - return this.compare(imageName, timeOutSeconds, tollerance); + return await this.compare(imageName, timeOutSeconds, tollerance); } - public async compare(imageName: string, timeOutSeconds: number = 3, tollerance: number = 0.01, rect?: IRectangle) { + private async compare(imageName: string, timeOutSeconds: number = 3, tollerance: number = 0.01, rect?: IRectangle) { if (!this._logPath) { this._logPath = getReportPath(this._args); diff --git a/lib/ui-element.ts b/lib/ui-element.ts index 3fb7e31..a7e20cd 100644 --- a/lib/ui-element.ts +++ b/lib/ui-element.ts @@ -42,7 +42,6 @@ export class UIElement { public async size() { const size = await (await this.element()).getSize(); const point = new Point(size.height, size.width); - return point; }