Skip to content

Commit 1279323

Browse files
feature: deviceLog
1 parent 3f5318c commit 1279323

9 files changed

+150
-80
lines changed

Diff for: CHANGELOG.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@
1313
* attach to session option "--attachToDebug"
1414
* create session "--createSession"
1515
* option "--sessionId" to provide specific session
16-
* get device log
16+
* exposed driver.getDeviceLog() which will return device log
17+
* exposed driver.logDeviceLog(fileName, logtype) which will create such file with postfix `${fileName}_${logtype}.log` in reports folder under appName/deviceName
1718
* **android:** provide option "--relaxedSecurity" to enable relaxed security and execute shell commands using appium android driver (#126) ([ce780bf](https://github.com/NativeScript/nativescript-dev-appium/commit/ce780bf)), closes [#126](https://github.com/NativeScript/nativescript-dev-appium/issues/126)
1819

1920
+### BREAKING CHANGES

Diff for: README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,7 @@ $ npm run e2e -- --runType android25
293293

294294
Starting new session will console log appium server port and session id
295295
```
296-
$ node ./node_modules/.bin/ns-appium -- --runType android23 --startSession
296+
$ node ./node_modules/.bin/ns-appium --runType android23 --startSession
297297
```
298298

299299
Run tests with already started session. Specify session id and server port. Default value for server port is 8300

Diff for: lib/appium-driver.d.ts

+7-1
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,6 @@ export declare class AppiumDriver {
5555
* Get the storage where images are captured. It will be resources/app nam/device name
5656
*/
5757
readonly storageByDeviceName: string;
58-
getlog(logType: LogType): Promise<any>;
5958
static createAppiumDriver(port: number, args: INsCapabilities): Promise<AppiumDriver>;
6059
/**
6160
*
@@ -163,7 +162,14 @@ export declare class AppiumDriver {
163162
prepareImageToCompare(filePath: string, rect: IRectangle): Promise<void>;
164163
takeScreenshot(fileName: string): Promise<string>;
165164
logScreenshot(fileName: string): Promise<string>;
165+
getlog(logType: LogType): Promise<any>;
166166
logPageSource(fileName: string): Promise<void>;
167+
logDeviceLog(fileName: any, logType: LogType, filter?: string): Promise<void>;
168+
/**
169+
* This method will snapshot the screen of device, get page source and log from device
170+
* @param logName
171+
*/
172+
logTestArtifacts(logName: string): Promise<void>;
167173
/**
168174
* Send the currently active app to the background
169175
* @param time

Diff for: lib/appium-driver.ts

+61-9
Original file line numberDiff line numberDiff line change
@@ -158,11 +158,6 @@ export class AppiumDriver {
158158
return this._storageByDeviceName;
159159
}
160160

161-
public async getlog(logType: LogType) {
162-
const logs = await this._driver.log(logType);
163-
return logs;
164-
}
165-
166161
// Still not supported in wd
167162
// public async getPerformanceDataTypes() {
168163
// return await this._driver.getSupportedPerformanceDataTypes;
@@ -216,7 +211,7 @@ export class AppiumDriver {
216211
args.sessionId = info.value[0].id;
217212
}
218213
if (!args.sessionId || args.sessionId.includes("undefined")) {
219-
logError("Please provide session id!");
214+
logError("Please provide session id!");
220215
process.exit(1);
221216
}
222217
}
@@ -243,7 +238,7 @@ export class AppiumDriver {
243238
}
244239
if (hasStarted) {
245240
console.log("Appium driver has started successfully!");
246-
}else{
241+
} else {
247242
logError("Appium driver is NOT started!")
248243
}
249244

@@ -564,7 +559,7 @@ export class AppiumDriver {
564559
}
565560

566561
public async logScreenshot(fileName: string) {
567-
if (!this._logPath && !fileExists(fileName)) {
562+
if (!this._logPath) {
568563
this._logPath = getReportPath(this._args);
569564
}
570565
if (!fileName.endsWith(AppiumDriver.pngFileExt)) {
@@ -575,8 +570,13 @@ export class AppiumDriver {
575570
return imgPath;
576571
}
577572

573+
public async getlog(logType: LogType) {
574+
const logs = await this._driver.log(logType);
575+
return logs;
576+
}
577+
578578
public async logPageSource(fileName: string) {
579-
if (!this._logPath && !fileExists(fileName)) {
579+
if (!this._logPath) {
580580
this._logPath = getReportPath(this._args);
581581
}
582582
if (!fileName.endsWith(".xml")) {
@@ -588,6 +588,58 @@ export class AppiumDriver {
588588
writeFileSync(path, xml.value, 'utf8');
589589
}
590590

591+
public async logDeviceLog(fileName, logType: LogType, filter: string = undefined) {
592+
let logs;
593+
try {
594+
logs = await this.getlog(logType);
595+
} catch (error) {
596+
logError(`Failed to get log type: ${logType}`);
597+
}
598+
let deviceLog = ""
599+
logs.forEach(log => {
600+
const curruntLog = `\n${JSON.stringify(log)}`;
601+
if (filter) {
602+
if (curruntLog.includes(filter)) {
603+
deviceLog += `\n${JSON.stringify(log)}`;
604+
}
605+
} else {
606+
deviceLog += `\n${JSON.stringify(log)}`;
607+
}
608+
});
609+
610+
if (logs.length > 0 && deviceLog) {
611+
const ext = extname(fileName);
612+
fileName = fileName.replace(ext, "");
613+
fileName = fileName.concat('_').concat(logType);
614+
fileName = fileName.concat(".log");
615+
616+
if (!this._logPath) {
617+
this._logPath = getReportPath(this._args);
618+
}
619+
620+
const path = resolve(this._logPath, fileName);
621+
writeFileSync(path, deviceLog, 'utf8');
622+
} else {
623+
console.log(`Log type: ${logType} is empty!`);
624+
}
625+
}
626+
627+
/**
628+
* This method will snapshot the screen of device, get page source and log from device
629+
* @param logName
630+
*/
631+
public async logTestArtifacts(logName: string) {
632+
await this.logScreenshot(logName);
633+
await this.logPageSource(logName);
634+
635+
if (this.isAndroid) {
636+
await this.logDeviceLog(logName, LogType.logcat);
637+
} else {
638+
await this.logDeviceLog(logName, LogType.crashlog);
639+
await this.logDeviceLog(logName, LogType.syslog, this._args.device.token);
640+
}
641+
}
642+
591643
/**
592644
* Send the currently active app to the background
593645
* @param time

Diff for: lib/device-manager.ts

+4
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,10 @@ export class DeviceManager implements IDeviceManager {
9898
}
9999
}
100100

101+
if (device.platform === Platform.ANDROID) {
102+
AndroidController.clearLog(device);
103+
}
104+
101105
DeviceManager._emulators.set(args.runType, device);
102106

103107
if (!device || !device.token) {

Diff for: lib/log-types.d.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
export declare enum LogType {
22
logcat = "logcat",
33
bugreport = "bugreport",
4-
server = "server"
4+
server = "server",
5+
driver = "driver",
6+
syslog = "syslog",
7+
crashlog = "crashlog",
8+
performance = "performance"
59
}

Diff for: lib/log-types.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
export enum LogType {
22
logcat = "logcat",
33
bugreport = "bugreport",
4-
server = "server"
4+
server = "server",
5+
driver = "driver",
6+
syslog = "syslog",
7+
crashlog = "crashlog",
8+
performance = "performance"
59
}

Diff for: lib/ns-capabilities.ts

+62-63
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import * as parser from "./parser"
22
import { INsCapabilities, AutomationName } from "./interfaces/ns-capabilities";
33
import { resolveCapabilities } from "./capabilities-helper";
4-
import { getAppPath, fileExists, logErr } from "./utils";
4+
import { getAppPath, fileExists, logErr, logInfo, logError } from "./utils";
55
import { IDevice } from "mobile-devices-controller";
66

77
export class NsCapabilities implements INsCapabilities {
@@ -108,7 +108,7 @@ export class NsCapabilities implements INsCapabilities {
108108

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

111-
private shouldSetFullResetOption(){
111+
private shouldSetFullResetOption() {
112112
if (this._ignoreDeviceController) {
113113
this.appiumCaps["fullReset"] = true;
114114
this.appiumCaps["noReset"] = false;
@@ -123,84 +123,83 @@ export class NsCapabilities implements INsCapabilities {
123123
}
124124

125125
private setAutomationName() {
126-
if (this.appiumCaps["automationName"]) {
127-
switch (this.appiumCaps["automationName"].toLowerCase()) {
128-
case AutomationName.UiAutomator2.toString().toLowerCase():
129-
this._automationName = AutomationName.UiAutomator2; break;
130-
case AutomationName.Appium.toString().toLowerCase():
131-
this._automationName = AutomationName.Appium; break;
132-
case AutomationName.XCUITest.toString().toLowerCase():
133-
this._automationName = AutomationName.XCUITest; break;
134-
}
135-
} else {
136-
if (this._isAndroid) {
137-
if (this.tryGetAndroidApiLevel() > 6 || (this.appiumCaps["apiLevel"] && this.appiumCaps["apiLevel"].toLowerCase().includes("p"))) {
138-
this._automationName = AutomationName.UiAutomator2;
126+
if (this.appiumCaps["automationName"]) {
127+
switch (this.appiumCaps["automationName"].toLowerCase()) {
128+
case AutomationName.UiAutomator2.toString().toLowerCase():
129+
this._automationName = AutomationName.UiAutomator2; break;
130+
case AutomationName.Appium.toString().toLowerCase():
131+
this._automationName = AutomationName.Appium; break;
132+
case AutomationName.XCUITest.toString().toLowerCase():
133+
this._automationName = AutomationName.XCUITest; break;
134+
}
135+
} else {
136+
if (this._isAndroid) {
137+
if (this.tryGetAndroidApiLevel() > 6 || (this.appiumCaps["apiLevel"] && this.appiumCaps["apiLevel"].toLowerCase().includes("p"))) {
138+
this._automationName = AutomationName.UiAutomator2;
139+
}
139140
}
140141
}
141-
}
142142

143-
if (this._automationName) {
144-
this.appiumCaps["automationName"] = this._automationName.toString();
145-
console.log(`Automation name set to: ${this.appiumCaps["automationName"]}`);
146-
console.log(`To change automation name, you need to set it in appium capabilities!`);
147-
} else {
148-
console.log(`Appium will use default automation name`);
143+
if (this._automationName) {
144+
this.appiumCaps["automationName"] = this._automationName.toString();
145+
logInfo(`Automation name set to: ${this.appiumCaps["automationName"]}`);
146+
console.log(`To change automation name, you need to set it in appium capabilities!`);
147+
} else {
148+
console.log(`Appium will use default automation name`);
149+
}
149150
}
150-
}
151151

152-
tryGetAndroidApiLevel() {
153-
try {
154-
if (this.appiumCaps["platformVersion"]) {
155-
const apiLevel = this.appiumCaps["platformVersion"].split(".").splice(0, 2).join('.');
156-
return parseFloat(apiLevel);
157-
}
158-
} catch (error) { }
159-
return undefined;
160-
}
152+
tryGetAndroidApiLevel() {
153+
try {
154+
if (this.appiumCaps["platformVersion"]) {
155+
const apiLevel = this.appiumCaps["platformVersion"].split(".").splice(0, 2).join('.');
156+
return parseFloat(apiLevel);
157+
}
158+
} catch (error) { }
159+
return undefined;
160+
}
161161

162162
private resolveApplication() {
163-
if (this.isSauceLab) {
164-
this._appiumCaps.app = `sauce-storage:${this.appPath}`
165-
this._ignoreDeviceController = true;
166-
console.log("Using Sauce Labs. The application path is changed to: " + this.appPath);
167-
} else {
168-
this.appiumCaps.app = getAppPath(this);
169-
this._appPath = this._appiumCaps.app;
170-
console.log("Application full path: " + this._appiumCaps.app);
163+
if (this.isSauceLab) {
164+
this._appiumCaps.app = `sauce-storage:${this.appPath}`
165+
this._ignoreDeviceController = true;
166+
console.log("Using Sauce Labs. The application path is changed to: " + this.appPath);
167+
} else {
168+
this.appiumCaps.app = getAppPath(this);
169+
this._appPath = this._appiumCaps.app;
170+
console.log("Application full path: " + this._appiumCaps.app);
171+
}
171172
}
172-
}
173173

174174
private checkMandatoryCapabiliies() {
175-
if (!this.isSauceLab && !fileExists(this._appiumCaps.app)) {
176-
this.exceptions.push("The application folder doesn't exist!");
177-
}
175+
if (!this.isSauceLab && !fileExists(this._appiumCaps.app)) {
176+
this.exceptions.push("The application folder doesn't exist!");
177+
}
178178

179-
if (!this._runType) {
180-
this.exceptions.push("Missing runType! Please select one from appium capabilities file!");
181-
}
179+
if (!this._runType) {
180+
this.exceptions.push("Missing runType! Please select one from appium capabilities file!");
181+
}
182182

183-
if (!this._appiumCaps.platformName) {
184-
this.exceptions.push("Platform name is missing! Please, check appium capabilities file!");
185-
}
183+
if (!this._appiumCaps.platformName) {
184+
this.exceptions.push("Platform name is missing! Please, check appium capabilities file!");
185+
}
186186

187-
if (!this._appiumCaps.platformVersion) {
188-
console.warn("Platform version is missing! You'd better to set it in order to use the correct device");
189-
}
187+
if (!this._appiumCaps.platformVersion) {
188+
console.warn("Platform version is missing! You'd better to set it in order to use the correct device");
189+
}
190190

191-
if (!this._appiumCaps.deviceName && !this._appiumCaps.udid) {
192-
this.exceptions.push("The device name or udid are missing! Please, check appium capabilities file!");
191+
if (!this._appiumCaps.deviceName && !this._appiumCaps.udid) {
192+
this.exceptions.push("The device name or udid are missing! Please, check appium capabilities file!");
193+
}
193194
}
194-
}
195195

196196
private throwExceptions() {
197-
this.exceptions.forEach(msg => {
198-
logErr(msg, true);
199-
});
197+
this.exceptions.forEach(msg => {
198+
logError(msg);
199+
});
200200

201-
if (this.exceptions.length > 0) {
202-
const messagesString = this.exceptions.length > 1 ? "messages" : "message";
203-
throw new Error(`See the ${messagesString} above and fullfill the conditions!!!`);
201+
if (this.exceptions.length > 0) {
202+
process.exit(1);
203+
}
204204
}
205-
}
206205
}

Diff for: lib/parser.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import * as yargs from "yargs";
22
import { join, dirname } from "path";
3-
import { resolve } from "./utils";
3+
import { resolve, logError } from "./utils";
44

55
export const capabilitiesName = "appium.capabilities.json";
66

@@ -45,7 +45,7 @@ const config = (() => {
4545
options.devMode = true;
4646
console.log(`Option attachToDebug is set to true. Option --devMode is set true as well !`)
4747
if (!options.port) {
48-
console.error("Provide appium server port started from desktop application!")
48+
logError("Provide appium server port started from desktop application!")
4949
process.exit(1);
5050
}
5151
}
@@ -54,7 +54,7 @@ const config = (() => {
5454
options.attachToDebug = true;
5555
options.devMode = true;
5656
if (!options.port) {
57-
console.error("Provide appium server port started from desktop application!")
57+
logError("Provide appium server port started from desktop application!")
5858
process.exit(1);
5959
}
6060
}

0 commit comments

Comments
 (0)