Skip to content

Commit 6447403

Browse files
Tsenov/relaxed security (#128)
* refactor: frame-comparer * chore: exit if no device found * refactor: option clean app after tests
1 parent ce780bf commit 6447403

13 files changed

+44
-24
lines changed

index.ts

+5
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { shutdown, findFreePort } from "./lib/utils";
77
import * as frameComparerHelper from "./lib/frame-comparer";
88
import { FrameComparer } from "./lib/frame-comparer";
99
import { DeviceManager } from "./lib/device-manager";
10+
import { DeviceController } from "mobile-devices-controller";
1011

1112
export { AppiumDriver } from "./lib/appium-driver";
1213
export { AppiumServer } from "./lib/appium-server";
@@ -49,6 +50,10 @@ export async function stopServer() {
4950
if (appiumServer && appiumServer.server && !appiumServer.server.killed) {
5051
await appiumServer.stop();
5152
}
53+
54+
if (nsCapabilities.cleanApp) {
55+
await DeviceController.uninstallApp(nsCapabilities.device, nsCapabilities.appPath);
56+
}
5257
};
5358

5459
export async function createDriver() {

lib/appium-driver.ts

+6-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ import {
3131
calculateOffset,
3232
scroll,
3333
findFreePort,
34-
wait
34+
wait,
35+
copy
3536
} from "./utils";
3637

3738
import { INsCapabilities } from "./interfaces/ns-capabilities";
@@ -42,6 +43,7 @@ import { ImageOptions } from "./image-options"
4243
import { unlinkSync, writeFileSync } from "fs";
4344
import * as webdriverio from "webdriverio";
4445
import { DeviceManager } from "../lib/device-manager";
46+
import { extname, basename } from "path";
4547

4648
export class AppiumDriver {
4749
private static pngFileExt = '.png';
@@ -451,6 +453,9 @@ export class AppiumDriver {
451453
await this._imageHelper.clipRectangleImage(rect, pathActualImage);
452454
}
453455

456+
const pathActualImageToReportsFolder = resolve(this._logPath, basename(pathActualImage));
457+
copy(pathActualImage, pathActualImageToReportsFolder, false);
458+
454459
console.log("Remove the 'actual' suffix to continue using the image as expected one ", pathExpectedImage);
455460
return false;
456461
}

lib/device-manager.d.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ export declare class DeviceManager implements IDeviceManager {
1111
static kill(device: IDevice): Promise<void>;
1212
private static getDefaultDevice;
1313
static setDontKeepActivities(args: INsCapabilities, driver: any, value: any): Promise<void>;
14-
static executeShellCommand(driver: IDevice, commandAndargs: {
14+
static executeShellCommand(driver: any, commandAndargs: {
1515
command: string;
1616
"args": Array<any>;
1717
}): Promise<any>;

lib/device-manager.ts

+7-4
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import {
66
shutdown,
77
executeCommand
88
} from "./utils";
9-
import * as child_process from "child_process";
109
import { INsCapabilities } from "./interfaces/ns-capabilities";
1110
import { IDeviceManager } from "./interfaces/device-manager";
1211

@@ -80,8 +79,8 @@ export class DeviceManager implements IDeviceManager {
8079
await DeviceController.startDevice(device);
8180
console.log("Started device: ", device);
8281
} else {
83-
console.log("Device is already started", device);
84-
if (!args.reuseDevice && device.type !== DeviceType.EMULATOR && device.type !== DeviceType.SIMULATOR) {
82+
device.type === DeviceType.DEVICE ? console.log("Device is connected:", device) : console.log("Device is already started", device)
83+
if (!args.reuseDevice && device.type !== DeviceType.DEVICE) {
8584
console.log("Since is it specified without reusing, the device would be shut down and restart!");
8685
DeviceController.kill(device);
8786
await DeviceController.startDevice(device);
@@ -91,6 +90,10 @@ export class DeviceManager implements IDeviceManager {
9190

9291
DeviceManager._emulators.set(args.runType, device);
9392

93+
if (!device || !device.token) {
94+
console.error("Check appium capabilites and provide correct device options!");
95+
process.exit(1);
96+
}
9497
return device;
9598
}
9699

@@ -149,7 +152,7 @@ export class DeviceManager implements IDeviceManager {
149152
}
150153
}
151154

152-
public static async executeShellCommand(driver: IDevice, commandAndargs: { command: string, "args": Array<any> }) {
155+
public static async executeShellCommand(driver, commandAndargs: { command: string, "args": Array<any> }) {
153156
if (driver.platform.toLowerCase() === Platform.ANDROID) {
154157
const output = await driver.execute("mobile: shell", commandAndargs);
155158
return output;

lib/frame-comparer.d.ts

+4-6
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,13 @@
11
import { INsCapabilities } from "./interfaces/ns-capabilities";
2-
import * as frComparer from "frame-comparer";
32
export declare function loadFrameComparer(nsCapabilities: INsCapabilities): FrameComparer;
43
export declare class FrameComparer {
54
private _nsCapabilities;
65
private _storage;
76
private _logPath;
8-
private _frameComparer;
97
private _framesGeneralName;
108
private _cropImageRect;
11-
constructor(_nsCapabilities: INsCapabilities, _storage: string, _logPath: string, _frameComparer: frComparer.FrameComparer);
12-
processVideo(videoFullName: any, framesGeneralName?: string, videoTempStorage?: string): Promise<void>;
13-
compareFrameRanges(imageFrameCount: number, startRange: any, endRange: any, logImageComparisonResults?: boolean, tollerancePixels?: number, verbose?: boolean): Promise<boolean>;
14-
compareFrames(imageFrameCount: number, tolleranceRange?: number, tollerancePixels?: number, logImageComparisonResults?: boolean, verbose?: boolean): Promise<boolean>;
9+
constructor(_nsCapabilities: INsCapabilities, _storage: string, _logPath: string);
10+
processVideo(videoFullName: any, framesGeneralName?: string, videoTempStorage?: string): Promise<any>;
11+
compareFrameRanges(frames: Array<string>, imageFrameCount: number, startRange: any, endRange: any, logImageComparisonResults?: boolean, tollerancePixels?: number, verbose?: boolean): Promise<boolean>;
12+
compareFrames(frames: Array<string>, imageFrameCount: number, tolleranceRange?: number, tollerancePixels?: number, logImageComparisonResults?: boolean, verbose?: boolean): Promise<boolean>;
1513
}

lib/frame-comparer.ts

+7-8
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,9 @@ import { ImageHelper } from "./image-helper";
77

88
export function loadFrameComparer(nsCapabilities: INsCapabilities) {
99
try {
10-
const frameComparer = frComparer.createFrameComparer();
1110
const storage = getStorageByDeviceName(nsCapabilities);
1211
const logPath = getReportPath(nsCapabilities);
13-
return new FrameComparer(nsCapabilities, storage, logPath, frameComparer);
12+
return new FrameComparer(nsCapabilities, storage, logPath);
1413
} catch (error) {
1514
console.error("In order to use frame comaprer, please read carefully https://github.com/SvetoslavTsenov/frame-comparer/blob/master/README.md for dependecies that are required!");
1615
}
@@ -20,25 +19,25 @@ export class FrameComparer {
2019
private _framesGeneralName: string = "frame";
2120
private _cropImageRect: IRectangle;
2221

23-
constructor(private _nsCapabilities: INsCapabilities, private _storage: string, private _logPath: string, private _frameComparer: frComparer.FrameComparer) {
22+
constructor(private _nsCapabilities: INsCapabilities, private _storage: string, private _logPath: string) {
2423
this._cropImageRect = ImageHelper.cropImageDefault(this._nsCapabilities);
2524
}
2625

2726
async processVideo(videoFullName, framesGeneralName?: string, videoTempStorage = "tempFramesFolder") {
2827
this._framesGeneralName = framesGeneralName || this._framesGeneralName;
2928
this._framesGeneralName = this._framesGeneralName.replace(/\s/gi, "");
30-
await this._frameComparer.processVideo(videoFullName, videoTempStorage, this._framesGeneralName);
29+
return await frComparer.FrameComparer.processVideo(videoFullName, videoTempStorage, this._framesGeneralName);
3130
}
3231

33-
async compareFrameRanges(imageFrameCount: number, startRange, endRange, logImageComparisonResults: boolean = false, tollerancePixels = 0.1, verbose = false): Promise<boolean> {
34-
const result = await this._frameComparer.compareImageFromVideo(resolve(this._storage, `${this._framesGeneralName}${imageFrameCount}.png`), this._logPath, startRange, endRange, tollerancePixels, this._cropImageRect, true, logImageComparisonResults, verbose);
32+
async compareFrameRanges(frames: Array<string>, imageFrameCount: number, startRange, endRange, logImageComparisonResults: boolean = false, tollerancePixels = 0.1, verbose = false): Promise<boolean> {
33+
const result = await frComparer.FrameComparer.compareImageFromVideo(frames, resolve(this._storage, `${this._framesGeneralName}${imageFrameCount}.png`), this._logPath, startRange, endRange, tollerancePixels, true, logImageComparisonResults, this._cropImageRect, verbose);
3534
return result;
3635
}
3736

38-
async compareFrames(imageFrameCount: number, tolleranceRange = 3, tollerancePixels = 0.1, logImageComparisonResults: boolean = false, verbose = false): Promise<boolean> {
37+
async compareFrames(frames: Array<string>, imageFrameCount: number, tolleranceRange = 3, tollerancePixels = 0.1, logImageComparisonResults: boolean = false, verbose = false): Promise<boolean> {
3938
const start = imageFrameCount - tolleranceRange > 0 ? imageFrameCount - tolleranceRange : 0;
4039
const end = imageFrameCount + tolleranceRange;
41-
const result = await this.compareFrameRanges(imageFrameCount, start, end, logImageComparisonResults, tollerancePixels)
40+
const result = await this.compareFrameRanges(frames, imageFrameCount, start, end, logImageComparisonResults, tollerancePixels)
4241
return result;
4342
}
4443
}

lib/image-helper.d.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ export declare class ImageHelper {
1010
blockOutAreas: IRectangle[];
1111
imageOutputLimit(): ImageOptions;
1212
thresholdType(): ImageOptions;
13-
threshold(thresholdType: any): 10 | 0.01;
13+
threshold(thresholdType: any): 0.01 | 10;
1414
delta(): number;
1515
static cropImageDefault(_args: INsCapabilities): {
1616
x: number;

lib/interfaces/ns-capabilities.d.ts

+1
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,5 @@ export interface INsCapabilities {
3131
path: string;
3232
automationName: AutomationName;
3333
relaxedSecurity: boolean;
34+
cleanApp: boolean;
3435
}

lib/interfaces/ns-capabilities.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -32,5 +32,6 @@ export interface INsCapabilities {
3232
wdaLocalPort: number;
3333
path: string;
3434
automationName: AutomationName;
35-
relaxedSecurity: boolean
35+
relaxedSecurity: boolean,
36+
cleanApp: boolean,
3637
}

lib/ns-capabilities.d.ts

+2
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ export declare class NsCapabilities implements INsCapabilities {
2727
private _ignoreDeviceController;
2828
private _wdaLocalPort;
2929
private _relaxedSecurity;
30+
private _cleanApp;
3031
private exceptions;
3132
constructor();
3233
readonly path: string;
@@ -55,6 +56,7 @@ export declare class NsCapabilities implements INsCapabilities {
5556
device: IDevice;
5657
readonly emulatorOptions: string;
5758
readonly relaxedSecurity: boolean;
59+
readonly cleanApp: boolean;
5860
private isAndroidPlatform;
5961
private setAutomationName;
6062
tryGetAndroidApiLevel(): number;

lib/ns-capabilities.ts

+3
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ export class NsCapabilities implements INsCapabilities {
3131
private _ignoreDeviceController: boolean;
3232
private _wdaLocalPort: number;
3333
private _relaxedSecurity: boolean;
34+
private _cleanApp: boolean;
3435
private exceptions: Array<string> = new Array();
3536

3637
constructor() {
@@ -56,6 +57,7 @@ export class NsCapabilities implements INsCapabilities {
5657
this._wdaLocalPort = parser.wdaLocalPort;
5758
this._path = parser.path;
5859
this._relaxedSecurity = parser.relaxedSecurity;
60+
this._cleanApp = parser.cleanApp;
5961
this.setAutomationName();
6062
this.resolveApplication();
6163
this.checkMandatoryCapabiliies();
@@ -91,6 +93,7 @@ export class NsCapabilities implements INsCapabilities {
9193
set device(device: IDevice) { this._device = device; }
9294
get emulatorOptions() { return (this._emulatorOptions || "-wipe-data -gpu on") }
9395
get relaxedSecurity() { return this._relaxedSecurity }
96+
get cleanApp() { return this._cleanApp; }
9497

9598
private isAndroidPlatform() { return this._appiumCaps.platformName.toLowerCase().includes("android"); }
9699

lib/parser.d.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
export declare const capabilitiesName = "appium.capabilities.json";
2-
export declare const projectDir: any, projectBinary: any, pluginRoot: any, pluginBinary: any, port: any, verbose: any, appiumCapsLocation: any, testFolder: any, runType: any, isSauceLab: any, appPath: any, storage: any, testReports: any, reuseDevice: any, devMode: any, ignoreDeviceController: any, wdaLocalPort: any, path: any, relaxedSecurity: any;
2+
export declare const projectDir: any, projectBinary: any, pluginRoot: any, pluginBinary: any, port: any, verbose: any, appiumCapsLocation: any, testFolder: any, runType: any, isSauceLab: any, appPath: any, storage: any, testReports: any, reuseDevice: any, devMode: any, ignoreDeviceController: any, wdaLocalPort: any, path: any, relaxedSecurity: any, cleanApp: boolean;

lib/parser.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ const config = (() => {
2121
.option("reuseDevice", { describe: "Reusing device if available.", type: "boolean", default: false })
2222
.option("devMode", { alias: "dev-mode", describe: "Will skipp app instalation and will reuse the one installed on device!", type: "boolean", default: false })
2323
.option("ignoreDeviceController", { alias: "i-ns-device-controller", describe: "Use default appium options for running emulatos/ simulators.", type: "boolean", default: false })
24+
.option("cleanApp", { alias: "c", describe: "Uninstall app after test are finished", type: "boolean", default: false })
2425
.help()
2526
.argv;
2627

@@ -55,6 +56,7 @@ const config = (() => {
5556
testReports: options.testReports || process.env.npm_config_TEST_REPORTS || process.env.TEST_REPORTS,
5657
reuseDevice: options.devMode ? true : options.reuseDevice || process.env.npm_config_REUSE_DEVICE || process.env.REUSE_DEVICE,
5758
devMode: options.devMode || process.env.npm_config_REUSE_APP,
59+
cleanApp: !options.devMode && options.cleanApp && !options.sauceLab && !options.ignoreDeviceController,
5860
ignoreDeviceController: options.ignoreDeviceController,
5961
path: options.path,
6062
relaxedSecurity: options.relaxedSecurity
@@ -82,5 +84,6 @@ export const {
8284
ignoreDeviceController,
8385
wdaLocalPort,
8486
path,
85-
relaxedSecurity
87+
relaxedSecurity,
88+
cleanApp
8689
} = config;

0 commit comments

Comments
 (0)