How to use adb.startLogcat method in Appium Android Driver

Best JavaScript code snippet using appium-android-driver

Run Appium Android Driver automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

instrumentation_linux_android.js

Source: instrumentation_linux_android.js Github

copy
1
2var spawn = require('child_process').spawn;
3var exec = require('child_process').exec;
4var os = require('os');
5
6var Adb = require('./adb')
7
8var buffer_last=false;
9var rooted = false;
10var started=false
11config.location = '"ws://'+getLocalAddress() + ':' + config.port + '"'
12var address = 'http://' + getLocalAddress() + ':' + config.port
13var client_address = '';
14process.argv.forEach(function(arg) {
15	if (arg.indexOf('targetip=') != -1) {
16		client_address = arg.split('=')[1];
17		console.log("Client: " + client_address);
18	}
19	if (arg.indexOf('rooted') != -1) rooted = true;
20})
21var adb = new Adb({rooted: rooted});
22
23adb.connect(client_address, function(status) {
24	console.log("Connected to " + client_address);
25
26	if (adb.startLogcat()) {
27		console.log("Logcat started");
28	}
29});
30
31function startBrowser(){
32	started=true
33	buffer_last = config.previousTestCasesBuffer[config.previousTestCasesBuffer.length - 1];
34	console.log("Starting browser with address: " + address);
35	adb.open(address,function(err){
36		if (err) {
37			console.error("Start Error: " + err);
38		}
39	});
40}
41
42function restartBrowser(url){
43	var buffer_current = config.previousTestCasesBuffer[config.previousTestCasesBuffer.length - 1]
44	if (!buffer_last) buffer_last = buffer_current;
45	else if (buffer_last == buffer_current) url = address;
46	buffer_last = buffer_current;
47
48	adb.respawn(url, function(err) {
49		if (err) { 
50			console.error("Restart Error: " + err);
51		}
52	});
53}
54
55instrumentationEvents.on('websocketTimeout',restartBrowser)
56instrumentationEvents.on('startClient',startBrowser)
57//instrumentationEvents.on('exiting',clearBrowserEvents)
58instrumentationEvents.on('testCasesWithoutRestartLimit',restartBrowser)
59instrumentationEvents.on('exiting', adb.kill)
60
61
62// Logcat
63var log=''
64var ADBlogging=false
65var SEGVLine=''
66adb.on('logcat out', function(data) {
67	var temp=data.toString()
68	var lines=temp.split('\n')
69	if(started){
70		lines.forEach(function(line,index){
71			if(!line.match(/GC_(CONCURRENT|EXPLICIT)/)){	
72				if(ADBlogging==false && line.indexOf('Chrome build fingerprint:')!=-1){
73					ADBlogging=true;
74					log+=line+'\n'
75				}
76				else if (ADBlogging==true && line.indexOf('Zygote')!=-1){
77					ADBlogging=false
78					if(log.indexOf('(SIGSEGV),')!=-1){
79						write_repro(cloneArray(config.previousTestCasesBuffer),log)
80					}else{
81						console.log('Something weird happened')
82						console.log(log)
83					}
84					log=''
85				}
86				else if(ADBlogging==true && line!='' && line.indexOf("WakeLockMgr")==-1 &&  line.indexOf("DownloadManager")==-1 &&  line.indexOf("AtivityManager")==-1){
87					log+=line+'\n'
88				}
89				
90			}
91		})
92	}
93	//	if(log!='')
94//	console.log(log)
95	//log=''
96	//logging=false
97})
98adb.on('logcat exit', function(data) {
99	console.log("Logcat exited");
100})
101
102
103// Helpers
104function getLocalAddress() {
105	var interfaces = os.networkInterfaces();
106	var wlan0 = interfaces.wlan0;
107	var eth0 = interfaces.eth0;
108
109	if (wlan0) {
110		for (var key in wlan0) {
111			var addr = wlan0[key];
112			if (addr.family == "IPv4") return addr.address;
113		}
114	}
115	return 'localhost';
116}
117
118var path=require('path')
119var fs=require('fs')
120var mkdirsSync = function (dirname, mode) {
121  if (mode === undefined) mode = 0777 ^ process.umask();
122  var pathsCreated = [], pathsFound = [];
123  var fn = dirname;
124  while (true) {
125    try {
126      var stats = fs.statSync(fn);
127      if (stats.isDirectory())
128        break;
129      throw new Error('Unable to create directory at '+fn);
130    }
131    catch (e) {
132      if (e.errno == 34) {
133        pathsFound.push(fn);
134        fn = path.dirname(fn);
135      }
136      else {
137        throw e;
138      }
139    }
140  }
141  for (var i=pathsFound.length-1; i>-1; i--) {
142    var fn = pathsFound[i];
143    fs.mkdirSync(fn, mode);
144    pathsCreated.push(fn);
145  }
146  return pathsCreated;
147};
148
149function cloneArray(obj){
150        var copy = [];
151        for (var i = 0; i < obj.length; ++i) {
152            copy[i] = obj[i];
153        }
154        return copy;
155}
156
157
158
159
160function write_repro(reproFiles,log){
161	if (!fs.existsSync(config.result_dir+'/folders/')) {
162    mkdirsSync(config.result_dir+'/folders/')
163	}
164
165	fs.mkdir(config.result_dir,function(error, stdout, stderr){
166		
167
168		var reproname='adroid-SEGV-'+(new Date().getTime()) 
169		var current_repro=reproFiles[0]
170		console.log('Checking for file '+reproname+'.txt Status ')
171		if(!fs.existsSync(config.result_dir+config.target+'-'+reproname+".txt")){
172
173			var index=0
174			mkdirsSync(config.result_dir+'/folders/'+config.target+'-'+reproname)
175			while(reproFiles.length){
176			
177    			repro=reproFiles.pop();
178    			index++
179				fs.writeFile(config.result_dir+'/folders/'+config.target+'-'+reproname+'/'+config.target+'-'+reproname+index+'.'+config.filetype, repro, function(err) {
180					if(err) {
181						console.log(err);
182					
183					}
184				}); 
185			}
186			console.log(config.result_dir+config.target+'-'+reproname+'.'+config.filetype)
187			fs.writeFile(config.result_dir+config.target+'-'+reproname+'.'+config.filetype, current_repro, function(err) {
188				if(err) {
189					console.log(err);
190					
191				}
192			}); 
193			fs.writeFile(config.result_dir+'/folders/'+config.target+'-'+reproname+'/'+config.target+'-'+reproname+".txt", log, function(err) {
194				fs.writeFile(config.result_dir+config.target+'-'+reproname+".txt", log, function(err) {
195					if(err) {
196					} else {
197						console.log("The file was saved!");
198					}
199				}); 
200			}); 
201		}
202	});
203}
204
205config.addCustomWebSocketHandler= function(wsServer){
206	wsServer.on("request",function(request) {
207	    connection = request.accept('fuzz-protocol', request.origin);
208	    connection.on('message', function(message) {
209	    	setTimeout(function(){
210	    		adb.respawn(address, function(err) {
211					if (err) { 
212						console.error("Restart Error: " + err);
213					}
214				});
215	    	},config.timeout*5)
216		})
217	})
218
219
220}
Full Screen

controller.js

Source: controller.js Github

copy
1import {
2    adb, devices, apps, deviceDetail, dumpsysyActivityTop,
3    dumsysPackage, dumpsysActivityProcesses, measureActivityLaunch,
4    getLaunchActivityList, clearLog, screencap, startApp
5} from "../module/adb";
6import { openTerminalWith } from "../module/terminal";
7import { writeFile } from "../module/utils";
8import path from 'path';
9import { cachedir, file, serverPort } from "../module/context";
10import EmptyWorker from "./EmptyWorker";
11
12class Controller {
13
14    // 更新设备列表,并连接指定设备/默认设备
15    refreshPageContent = async (deviceUDID) => {
16        const devicesList = await devices();
17        if (devicesList && devicesList.length > 1) {
18            const matchedDevice = devicesList.filter(item => item.udid === deviceUDID);
19            try {
20                const _adb = await adb();
21                if (matchedDevice && matchedDevice.length > 0) {
22                    _adb.setDeviceId(deviceUDID);
23                } else {
24                    console.log('invalid udid, set to the first device');
25                    _adb.setDeviceId(devicesList[0].udid);
26                }
27            } catch (err) {
28                console.error(err);
29                adb(true).then(() => {
30                    console.log('new adb instance created')
31                });
32            }
33        }
34        const appList = await apps();
35        return { devices: devicesList, apps: appList };
36    }
37
38    resetAdb = () => {
39        adb(true).then(() => {
40            console.log('new adb instance created')
41        });
42    }
43    // 获取设备信息
44    getDeviceDetail = async () => {
45        return await deviceDetail();
46    }
47
48    // 获取当前活动Activity信息
49    getActivityTop = async () => {
50        return await dumpsysyActivityTop();
51    }
52
53    // 连接设备,并返回设备信息和当前活动Activity信息
54    selectDevice = async (udid) => {
55        const _adb = await adb();
56        _adb.setDeviceId(udid)
57        console.log('set deviceid success', udid)
58        const detail = await this.getDeviceDetail();
59        const activityTop = await this.getActivityTop();
60        return { detail, activityTop };
61    }
62
63    // 获取指定app信息
64    getAppDetail = async (pkgName) => {
65        const packageInfo = await dumsysPackage(pkgName);
66        const processes = await dumpsysActivityProcesses(pkgName);
67        return { packageInfo, processes }
68    }
69
70    openData = (selected_app_package) => {
71        const script = file(cachedir(), "open-data.command");
72        const scriptContent = "#!/bin/bash\n" +
73            '# Set terminal title\n' +
74            'echo -en "\\033]0;Android Debug Bridge\\a"\n' +
75            'clear\n' +
76            'THIS_DIR=$(cd -P "$(dirname "$(readlink "${BASH_SOURCE[0]}" || echo "${BASH_SOURCE[0]}")")" && pwd)\n' +
77            'echo $THIS_DIR\n' +
78            `if [ ! -d ${selected_app_package} ]; then\n` +
79            `  mkdir ${selected_app_package}\n` +
80            'fi\n' +
81            `adb exec-out run-as ${selected_app_package} tar c ./ > ${selected_app_package}/data.tar\n` +
82            `cd ${selected_app_package} && tar -xvf data.tar\n` +
83            'rm -rf data.tar\n' +
84            'open ./\n' +
85            'if [ $? -ne 0 ]; then\n' +
86            '  echo "数据同步失败"\n' +
87            'else\n' +
88            '  echo "data数据已同步至本地"\n' +
89            'fi\n';
90        console.log(script);
91        writeFile(script, scriptContent).then(() => {
92            openTerminalWith(script, { cwd: cachedir() });
93        })
94    }
95
96    openDumpTermial = () => {
97        // don't support win
98        const scriptFile = /^win/.test(process.platform) ?
99            'launch.bat' :
100            'launch.command';
101        const scriptsDir = path.resolve(__dirname);
102        const launchPackagerScript = path.resolve(scriptsDir, scriptFile);
103        const procConfig = { cwd: scriptsDir };
104        openTerminalWith(launchPackagerScript, procConfig);
105    }
106
107    measureStateTime = async (activity, count = 10) => {
108        return measureActivityLaunch(activity, count).then(result => {
109            const average_this_time = result.reduce((pre, current) => pre + current.this_time, 0) / result.length;
110            const average_total_time = result.reduce((pre, current) => pre + current.total_time, 0) / result.length;
111            const average_wait_time = result.reduce((pre, current) => pre + current.wait_time, 0) / result.length;
112            const data = result.map((it, i) => {
113                return { name: `测量#${i + 1}`, ...it }
114            })
115            return { activity, average_this_time, average_total_time, average_wait_time, data: data }
116        })
117    }
118
119    launchActivityCache = {}
120
121    // 获取Launcher Activity,存在多个则取第一个
122    getLauncherActivity = async (packageName, cache = true) => {
123        const cacheActivity = this.launchActivityCache[packageName];
124        if (cache && cacheActivity && cacheActivity !== '') {
125            console.log('return cached Launch Activity')
126            return cacheActivity;
127        }
128        return getLaunchActivityList(packageName).then(list => {
129            const activity = list.length > 0 ? list[0] : '';
130            this.launchActivityCache[packageName] = activity;
131            return activity;
132        });
133    }
134
135    watchLogcat = async (handler) => {
136        const clearResult = await clearLog();
137        console.log(`logcat clear ${clearResult}`);
138        const _adb = await adb();
139        await _adb.stopLogcat();
140        const callback = handler;
141        _adb.startLogcat().then(() => {
142            console.log('logcat connected...')
143            _adb.setLogcatListener(line => {
144                callback && callback(line)
145            })
146        });
147    }
148
149    takeScreenshot = async (fileName = 'next-screenshot.png') => {
150        const path = file(cachedir(), fileName);
151        const success = await screencap(path);
152        return { success, file: path };
153    }
154
155    measureDataContainer = {};
156
157    newContainer(onMessage) {
158        return {
159            result: [],
160            mesauredCount: 0,
161            screenshot: false,
162            retry: 0,
163            measuring: false,
164            callback: onMessage,
165            notifyComplete: function () {
166                this.callback && this.callback(this.result);
167            },
168        }
169    }
170
171    measureAverageAppLaunchTime = async (packageName, onMessage, count = 5, needScreenshot = false, timeout = 10) => {
172        this.measureDataContainer = this.newContainer(onMessage);
173        this.measureDataContainer.screenshot = needScreenshot;
174        this.measureDataContainer.timeout = timeout;
175        // 定时检测是否需要开始下一轮测量,避免出现递归调用后卡死的情况(实际上并为彻底解决)
176        this.measureDataContainer.interval = setInterval(() => {
177            if (this.measureDataContainer.measuring) {
178                console.log('skip as measuring');
179                return;
180            }
181            if (this.measureDataContainer.mesauredCount < count) {
182                console.log(`===>trigger next measure #${this.measureDataContainer.mesauredCount}`)
183                this.nextMeasureRound(packageName);
184            } else {
185                console.log('finished');
186                clearInterval(this.measureDataContainer.interval);
187                this.measureDataContainer.notifyComplete();
188            }
189        }, 500);
190    }
191
192    nextMeasureRound = (packageName) => {
193        console.log('execute nextMeasureRound');
194        const _callback = data => {
195            if (data.failed) {
196                if (this.measureDataContainer.retry < 3) {
197                    this.measureDataContainer.mesauredCount--;
198                    this.measureDataContainer.retry++;
199                    console.log('retry measure:', this.measureDataContainer.retry);
200                } else {
201                    console.log('retry measure skip');
202                    this.measureDataContainer.retry = 0;
203                }
204                this.measureDataContainer.measuring = false;
205                return;
206            }
207            this.measureDataContainer.result.push(data);
208            console.log('handle message #', this.measureDataContainer.mesauredCount)
209            this.measureDataContainer.measuring = false;
210            this.measureDataContainer.retry = 0;
211        }
212        this.measureDataContainer.measuring = true;
213        this.measureDataContainer.mesauredCount++;
214        this.meaureAppLaunch(packageName, _callback, this.measureDataContainer.timeout).then(() => {
215            console.log('app measuring...')
216        }).catch(err => {
217            console.error(`failed to measure #${this.measureDataContainer.mesauredCount}`, err);
218            this.measureDataContainer.measuring = false;
219        });
220    }
221
222    /**
223     * App启动后,设置超时检测,避免长时间测量
224     */
225    meaureAppLaunch = async (packageName, onMessage, screenTimeout) => {
226        const callback = onMessage;
227        console.log('execute meaureAppLaunch')
228        let worker;
229
230        if (this.measureDataContainer.screenshot) {
231            const scriptsDir = path.resolve(__dirname);
232            const workerScript = path.resolve(scriptsDir, 'screenshotlooper.js');
233            worker = new Worker(workerScript);
234        } else {
235            worker = new EmptyWorker();
236        }
237
238        const logs = [];
239
240        const launchActivity = await this.getLauncherActivity(packageName);
241        console.log(`launch Activity ${launchActivity}`);
242        worker.onmessage = e => {
243            console.log('receive work result')
244            const activityRegex = RegExp(`ActivityManager: Displayed ${packageName}/`)
245            const filterLog = logs.filter(line => {
246                return activityRegex.test(line.message);
247            });
248            const launchData = {};
249            var launchitem = filterLog.filter(line => (line.message.indexOf(launchActivity) > 0))[0];
250            // if launcher not displayed, "Displayed" can not be found
251            var unDisplayedLauncher = false;
252            if (launchitem == undefined) {
253                unDisplayedLauncher = true;
254                launchitem = {
255                    "timestamp": "",
256                    "message": `ActivityManager: Displayed ${launchActivity}: +0ms `
257                };
258            }
259            const launchMessage = launchitem.message;
260            if (filterLog.length > 0) {
261                launchData.launcher = {
262                    timestamp: launchitem.timestamp,
263                    activity: launchMessage.substring(launchMessage.indexOf('Displayed ') + 10, launchMessage.lastIndexOf(':')),
264                    consumed: this.convertLogTime2Mills(launchMessage.substring(launchMessage.lastIndexOf('+') + 1)),// TODO 格式化
265                }
266
267                const findTargetScreen = (sourceData, baseTimestammp) => {
268                    let minDiff = Number.MAX_VALUE;
269                    let targetImg = undefined;
270                    for (let i = 0; i < sourceData.image.length; i++) {
271                        const img = sourceData.image[i];
272                        const diff = img.timestamp - baseTimestammp
273                        if (diff < 0) {
274                            continue;
275                        }
276                        if (diff <= minDiff) {
277                            minDiff = diff;
278                            targetImg = { ...img };
279                        }
280                    }
281                    return { ...targetImg };
282                }
283
284                const data = e.data;
285                // 截屏处理
286                if (this.measureDataContainer.screenshot) {
287                    const launchImg = findTargetScreen(data, launchData.launcher.timestamp);
288                    launchData.launcher.screen = launchImg;
289                } else {
290                    launchData.launcher.screen = '';
291                }
292
293
294                //启动页与主页二合一?
295                if (unDisplayedLauncher) {
296                    launchData.singleActivity = false;
297                } else {
298                    launchData.singleActivy = filterLog.length === 1;
299                }
300                if (!launchData.singleActivity) {
301                    const message = filterLog[filterLog.length - 1].message;
302                    launchData.home = {
303                        timestamp: filterLog[filterLog.length - 1].timestamp,
304                        activity: message.substring(message.indexOf('Displayed ') + 10, message.lastIndexOf(':')),
305                        consumed: this.convertLogTime2Mills(message.substring(message.lastIndexOf('+') + 1)),// TODO 格式化
306                    }
307                    // 截屏处理
308                    if (this.measureDataContainer.screenshot) {
309                        const homeImg = findTargetScreen(data, launchData.home.timestamp);
310                        launchData.home.screen = homeImg;
311                    } else {
312                        launchData.home.screen = '';
313                    }
314                }
315                if (unDisplayedLauncher) {
316                    launchData.totalTime = launchData.home.consumed;
317                } else {
318                    launchData.totalTime = launchData.singleActivity ? launchData.launcher.consumed : (launchData.home.timestamp - launchData.launcher.timestamp);
319                }
320                // 截屏处理
321                if (this.measureDataContainer.screenshot) {
322                    launchData.finnalScreen = data.image[data.image.length - 1];
323                } else {
324                    launchData.finnalScreen = '';
325                }
326            }
327
328
329            console.log('shutdown worker');
330            worker && worker.terminate();
331            console.log('notify message callback');
332            callback && callback({ /*screenshots: data, */log: logs, launchData: launchData });
333        }
334
335        worker.onerror = err => {
336            console.error('load worker failed', err);
337            callback && callback({ failed: true });
338        }
339        // start logcat
340        let timeoutTrigger;
341        const regex = /ActivityManager:/;
342        const regexDisplay = /ActivityManager: Displayed /;
343        console.log('start watch logcat');
344
345        await this.watchLogcat(line => {
346            if (regex.test(line.message)) {
347                console.log(line);
348                logs.push(line);
349                // new activity displayed
350                if (regexDisplay.test(line.message)) {
351                    // 设定界面间隔超时
352                    if (timeoutTrigger) {
353                        clearTimeout(timeoutTrigger);
354                    }
355                    console.log('reset timeout as new Activity dispalyed')
356                    timeoutTrigger = setTimeout(() => {
357                        console.log('hit screen timeout')
358                        worker.postMessage({ terminate: true })
359                    }, screenTimeout * 1000);
360                } else {
361                    // 设定启动超
362                    if (timeoutTrigger) {
363                        return;
364                    }
365                    timeoutTrigger = setTimeout(() => {
366                        console.log('hit launch timeout')
367                        worker.postMessage({ terminate: true, timeout: true })
368                    }, screenTimeout * 1000);
369                }
370            }
371        })
372        // start app
373        const output = await startApp(packageName);
374        console.log(output);
375        // start worker
376        const dir = file(cachedir(), '/');
377        worker.postMessage({ desDir: dir, port: serverPort() });
378    }
379
380    //'1m2s100ms' or 2s100ms or 100ms
381    convertLogTime2Mills = text => {
382        const result = text.match(/([0-9]*)/g);
383        console.log(result);
384        const filter = result.filter(it => (it !== '')).map(it => (parseInt(it))).reverse();
385        console.log(filter)
386        const ms = filter[0];
387        const s = filter.length > 1 ? filter[1] : 0;
388        const m = filter.length > 2 ? filter[2] : 0
389        return ms + s * 1000 + m * 60 * 1000;
390    }
391
392    test = () => {
393        //image();
394    }
395}
396
397export default Controller;
Full Screen

adb-commands-e2e-specs.js

Source: adb-commands-e2e-specs.js Github

copy
1import chai from 'chai';
2import chaiAsPromised from 'chai-as-promised';
3import ADB from '../..';
4import path from 'path';
5import { rootDir } from '../../lib/helpers.js';
6import { apiLevel, platformVersion, MOCHA_TIMEOUT } from './setup';
7import { fs, mkdirp } from 'appium-support';
8import temp from 'temp';
9
10
11chai.should();
12chai.use(chaiAsPromised);
13let expect = chai.expect;
14
15// change according to CI
16const IME = 'com.example.android.softkeyboard/.SoftKeyboard',
17      defaultIMEs = ['com.android.inputmethod.latin/.LatinIME',
18                     'io.appium.android.ime/.UnicodeIME'],
19      contactManagerPath = path.resolve(rootDir, 'test',
20                                        'fixtures', 'ContactManager.apk'),
21      pkg = 'com.example.android.contactmanager',
22      activity = 'ContactManager';
23
24describe('adb commands', function () {
25  this.timeout(MOCHA_TIMEOUT);
26
27  let adb;
28  before(async () => {
29    adb = await ADB.createADB();
30  });
31  it('getApiLevel should get correct api level', async () => {
32    (await adb.getApiLevel()).should.equal(apiLevel);
33  });
34  it('getPlatformVersion should get correct platform version', async () => {
35    (await adb.getPlatformVersion()).should.include(platformVersion);
36  });
37  it('availableIMEs should get list of available IMEs', async () => {
38    (await adb.availableIMEs()).should.have.length.above(0);
39  });
40  it('enabledIMEs should get list of enabled IMEs', async () => {
41    (await adb.enabledIMEs()).should.have.length.above(0);
42  });
43  it('defaultIME should get default IME', async () => {
44    defaultIMEs.should.include(await adb.defaultIME());
45  });
46  it('enableIME and disableIME should enable and disble IME', async () => {
47    await adb.disableIME(IME);
48    (await adb.enabledIMEs()).should.not.include(IME);
49    await adb.enableIME(IME);
50    (await adb.enabledIMEs()).should.include(IME);
51    await adb.enabledIMEs();
52  });
53  it('processExists should be able to find ui process', async () => {
54    (await adb.processExists('com.android.systemui')).should.be.true;
55  });
56  it('ping should return true', async () => {
57    (await adb.ping()).should.be.true;
58  });
59  it('getPIDsByName should return pids', async () => {
60    (await adb.getPIDsByName('m.android.phone')).should.have.length.above(0);
61  });
62  it('killProcessesByName should kill process', async () => {
63    await adb.install(contactManagerPath);
64    await adb.startApp({pkg, activity});
65    await adb.killProcessesByName(pkg);
66    (await adb.getPIDsByName(pkg)).should.have.length(0);
67  });
68  it('killProcessByPID should kill process', async () => {
69    await adb.install(contactManagerPath);
70    await adb.startApp({pkg, activity});
71    let pids = await adb.getPIDsByName(pkg);
72    pids.should.have.length.above(0);
73    await adb.killProcessByPID(pids[0]);
74    (await adb.getPIDsByName(pkg)).length.should.equal(0);
75  });
76  it('should get device language and country', async function () {
77    if (parseInt(apiLevel, 10) >= 23) return this.skip(); // eslint-disable-line curly
78    if (process.env.TRAVIS) return this.skip(); // eslint-disable-line curly
79
80    ['en', 'fr'].should.contain(await adb.getDeviceSysLanguage());
81    ['US', 'EN_US', 'EN', 'FR'].should.contain(await adb.getDeviceSysCountry());
82  });
83  it('should set device language and country', async function () {
84    if (parseInt(apiLevel, 10) >= 23) return this.skip(); // eslint-disable-line curly
85    if (process.env.TRAVIS) return this.skip(); // eslint-disable-line curly
86
87    await adb.setDeviceSysLanguage('fr');
88    await adb.setDeviceSysCountry('fr');
89    await adb.reboot();
90    await adb.getDeviceSysLanguage().should.eventually.equal('fr');
91    await adb.getDeviceSysCountry().should.eventually.equal('FR');
92    // cleanup
93    await adb.setDeviceSysLanguage('en');
94    await adb.setDeviceSysCountry('us');
95  });
96  it('should get device locale', async function () {
97    if (parseInt(apiLevel, 10) < 23) return this.skip(); // eslint-disable-line curly
98
99    ['us', 'en', 'ca_en'].should.contain(await adb.getDeviceLocale());
100  });
101  it('should forward the port', async () => {
102    await adb.forwardPort(4724, 4724);
103  });
104  it('should remove forwarded port', async () => {
105    await adb.forwardPort(8200, 6790);
106    (await adb.adbExec([`forward`, `--list`])).should.contain('tcp:8200');
107    await adb.removePortForward(8200);
108    (await adb.adbExec([`forward`, `--list`])).should.not.contain('tcp:8200');
109
110  });
111  it('should start logcat from adb', async () => {
112    await adb.startLogcat();
113    let logs = adb.logcat.getLogs();
114    logs.should.have.length.above(0);
115    await adb.stopLogcat();
116  });
117  it('should get model', async () => {
118    (await adb.getModel()).should.not.be.null;
119  });
120  it('should get manufacturer', async () => {
121    (await adb.getManufacturer()).should.not.be.null;
122  });
123  it('should get screen size', async () => {
124    (await adb.getScreenSize()).should.not.be.null;
125  });
126  it('should be able to toggle gps location provider', async () => {
127    await adb.toggleGPSLocationProvider(true);
128    (await adb.getLocationProviders()).should.include('gps');
129    await adb.toggleGPSLocationProvider(false);
130    (await adb.getLocationProviders()).should.not.include('gps');
131  });
132  it('should be able to toogle airplane mode', async () => {
133    await adb.setAirplaneMode(true);
134    (await adb.isAirplaneModeOn()).should.be.true;
135    await adb.setAirplaneMode(false);
136    (await adb.isAirplaneModeOn()).should.be.false;
137  });
138  it('should be able to toogle wifi @skip-ci', async function () {
139    this.retries(3);
140
141    await adb.setWifiState(true);
142    (await adb.isWifiOn()).should.be.true;
143    await adb.setWifiState(false);
144    (await adb.isWifiOn()).should.be.false;
145  });
146  it('should be able to turn off animation @skip-ci', async () => {
147    await adb.setAnimationState(false);
148    (await adb.isAnimationOn()).should.be.false;
149  });
150  it('should be able to turn on animation @skip-ci', async () => {
151    await adb.setAnimationState(true);
152    (await adb.isAnimationOn()).should.be.true;
153  });
154  describe('app permissions', async () => {
155    before(async function () {
156      let deviceApiLevel = await adb.getApiLevel();
157      if (deviceApiLevel < 23) {
158        //test should skip if the device API < 23
159        this.skip();
160      }
161      let isInstalled = await adb.isAppInstalled('io.appium.android.apis');
162      if (isInstalled) {
163        await adb.uninstallApk('io.appium.android.apis');
164      }
165    });
166    it('should install and grant all permission', async () => {
167      let apiDemos = path.resolve(rootDir, 'test',
168          'fixtures', 'ApiDemos-debug.apk');
169      await adb.install(apiDemos);
170      (await adb.isAppInstalled('io.appium.android.apis')).should.be.true;
171      await adb.grantAllPermissions('io.appium.android.apis');
172      let requestedPermissions = await adb.getReqPermissions('io.appium.android.apis');
173      expect(await adb.getGrantedPermissions('io.appium.android.apis')).to.have.members(requestedPermissions);
174    });
175    it('should revoke permission', async () => {
176      await adb.revokePermission('io.appium.android.apis', 'android.permission.RECEIVE_SMS');
177      expect(await adb.getGrantedPermissions('io.appium.android.apis')).to.not.have.members(['android.permission.RECEIVE_SMS']);
178    });
179    it('should grant permission', async () => {
180      await adb.grantPermission('io.appium.android.apis', 'android.permission.RECEIVE_SMS');
181      expect(await adb.getGrantedPermissions('io.appium.android.apis')).to.include.members(['android.permission.RECEIVE_SMS']);
182    });
183  });
184
185  describe('push file', function () {
186    function getRandomDir () {
187      return `/data/local/tmp/test${Math.random()}`;
188    }
189
190    let localFile = temp.path({prefix: 'appium', suffix: '.tmp'});
191    let tempFile = temp.path({prefix: 'appium', suffix: '.tmp'});
192    const stringData = `random string data ${Math.random()}`;
193    before(async function () {
194      await mkdirp(path.dirname(localFile));
195      await mkdirp(path.dirname(tempFile));
196
197      await fs.writeFile(localFile, stringData);
198    });
199    after(async function () {
200      if (await fs.exists(localFile)) {
201        await fs.unlink(localFile);
202      }
203    });
204    afterEach(async function () {
205      if (await fs.exists(tempFile)) {
206        await fs.unlink(tempFile);
207      }
208    });
209    it('should push file to a valid location', async function () {
210      let remoteFile = `${getRandomDir()}/remote.txt`;
211
212      await adb.push(localFile, remoteFile);
213
214      // get the file and its contents, to check
215      await adb.pull(remoteFile, tempFile);
216      let remoteData = await fs.readFile(tempFile);
217      remoteData.toString().should.equal(stringData);
218    });
219    it('should throw error if it cannot write to the remote file', async function () {
220      let remoteFile = '/foo/bar/remote.txt';
221
222      await adb.push(localFile, remoteFile).should.be.rejectedWith(/\/foo\/bar\/remote.txt/);
223    });
224  });
225});
226
Full Screen

Accelerate Your Automation Test Cycles With LambdaTest

Leverage LambdaTest’s cloud-based platform to execute your automation tests in parallel and trim down your test execution time significantly. Your first 100 automation testing minutes are on us.

Try LambdaTest

Run JavaScript Tests on LambdaTest Cloud Grid

Execute automation tests with Appium Android Driver on a cloud-based Grid of 3000+ real browsers and operating systems for both web and mobile applications.

Test now for Free
LambdaTestX

We use cookies to give you the best experience. Cookies help to provide a more personalized experience and relevant advertising for you, and web analytics for us. Learn More in our Cookies policy, Privacy & Terms of service

Allow Cookie
Sarah

I hope you find the best code examples for your project.

If you want to accelerate automated browser testing, try LambdaTest. Your first 100 automation testing minutes are FREE.

Sarah Elson (Product & Growth Lead)