123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688 |
- /**
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
- */
-
- const fs = require('fs');
- const path = require('path');
- const rewire = require('rewire');
- const shelljs = require('shelljs');
-
- const CordovaError = require('cordova-common').CordovaError;
- const check_reqs = require('../../bin/templates/cordova/lib/check_reqs');
- const superspawn = require('cordova-common').superspawn;
-
- describe('emulator', () => {
- const EMULATOR_LIST = ['emulator-5555', 'emulator-5556', 'emulator-5557'];
- let emu;
-
- beforeEach(() => {
- emu = rewire('../../bin/templates/cordova/lib/emulator');
- });
-
- describe('list_images_using_avdmanager', () => {
- it('should properly parse details of SDK Tools 25.3.1 `avdmanager` output', () => {
- const avdList = fs.readFileSync(path.join('spec', 'fixtures', 'sdk25.3-avdmanager_list_avd.txt'), 'utf-8');
- spyOn(superspawn, 'spawn').and.returnValue(Promise.resolve(avdList));
-
- return emu.list_images_using_avdmanager().then(list => {
- expect(list).toBeDefined();
- expect(list[0].name).toEqual('nexus5-5.1');
- expect(list[0].target).toEqual('Android 5.1 (API level 22)');
- expect(list[1].device).toEqual('pixel (Google)');
- expect(list[2].abi).toEqual('default/x86_64');
- });
- });
- });
-
- describe('list_images_using_android', () => {
- it('should invoke `android` with the `list avd` command and _not_ the `list avds` command, as the plural form is not supported in some Android SDK Tools versions', () => {
- spyOn(superspawn, 'spawn').and.returnValue(new Promise(() => {}, () => {}));
- emu.list_images_using_android();
- expect(superspawn.spawn).toHaveBeenCalledWith('android', ['list', 'avd']);
- });
-
- it('should properly parse details of SDK Tools pre-25.3.1 `android list avd` output', () => {
- const avdList = fs.readFileSync(path.join('spec', 'fixtures', 'sdk25.2-android_list_avd.txt'), 'utf-8');
- spyOn(superspawn, 'spawn').and.returnValue(Promise.resolve(avdList));
-
- return emu.list_images_using_android().then(list => {
- expect(list).toBeDefined();
- expect(list[0].name).toEqual('QWR');
- expect(list[0].device).toEqual('Nexus 5 (Google)');
- expect(list[0].path).toEqual('/Users/shazron/.android/avd/QWR.avd');
- expect(list[0].target).toEqual('Android 7.1.1 (API level 25)');
- expect(list[0].abi).toEqual('google_apis/x86_64');
- expect(list[0].skin).toEqual('1080x1920');
- });
- });
- });
-
- describe('list_images', () => {
- beforeEach(() => {
- spyOn(fs, 'realpathSync').and.callFake(cmd => cmd);
- });
-
- it('should try to parse AVD information using `avdmanager` first', () => {
- spyOn(shelljs, 'which').and.callFake(cmd => cmd === 'avdmanager');
-
- const avdmanager_spy = spyOn(emu, 'list_images_using_avdmanager').and.returnValue(Promise.resolve([]));
-
- return emu.list_images().then(() => {
- expect(avdmanager_spy).toHaveBeenCalled();
- });
- });
-
- it('should delegate to `android` if `avdmanager` cant be found and `android` can', () => {
- spyOn(shelljs, 'which').and.callFake(cmd => cmd !== 'avdmanager');
-
- const android_spy = spyOn(emu, 'list_images_using_android').and.returnValue(Promise.resolve([]));
-
- return emu.list_images().then(() => {
- expect(android_spy).toHaveBeenCalled();
- });
- });
-
- it('should correct api level information and fill in the blanks about api level if exists', () => {
- spyOn(shelljs, 'which').and.callFake(cmd => cmd === 'avdmanager');
- spyOn(emu, 'list_images_using_avdmanager').and.returnValue(Promise.resolve([
- {
- name: 'Pixel_7.0',
- device: 'pixel (Google)',
- path: '/Users/maj/.android/avd/Pixel_7.0.avd',
- abi: 'google_apis/x86_64',
- target: 'Android 7.0 (API level 24)'
- }, {
- name: 'Pixel_8.0',
- device: 'pixel (Google)',
- path: '/Users/maj/.android/avd/Pixel_8.0.avd',
- abi: 'google_apis/x86',
- target: 'Android API 26'
- }
- ]));
-
- return emu.list_images().then(avds => {
- expect(avds[1].target).toContain('Android 8');
- expect(avds[1].target).toContain('API level 26');
- });
- });
-
- it('should throw an error if neither `avdmanager` nor `android` are able to be found', () => {
- spyOn(shelljs, 'which').and.returnValue(false);
-
- return emu.list_images().then(
- () => fail('Unexpectedly resolved'),
- err => {
- expect(err).toBeDefined();
- expect(err.message).toContain('Could not find either `android` or `avdmanager`');
- }
- );
- });
- });
-
- describe('best_image', () => {
- let target_mock;
-
- beforeEach(() => {
- spyOn(emu, 'list_images');
- target_mock = spyOn(check_reqs, 'get_target').and.returnValue('android-26');
- });
-
- it('should return undefined if there are no defined AVDs', () => {
- emu.list_images.and.returnValue(Promise.resolve([]));
-
- return emu.best_image().then(best_avd => {
- expect(best_avd).toBeUndefined();
- });
- });
-
- it('should return the first available image if there is no available target information for existing AVDs', () => {
- const fake_avd = { name: 'MyFakeAVD' };
- const second_fake_avd = { name: 'AnotherAVD' };
- emu.list_images.and.returnValue(Promise.resolve([fake_avd, second_fake_avd]));
-
- return emu.best_image().then(best_avd => {
- expect(best_avd).toBe(fake_avd);
- });
- });
-
- it('should return the first AVD for the API level that matches the project target', () => {
- target_mock.and.returnValue('android-25');
- const fake_avd = { name: 'MyFakeAVD', target: 'Android 7.0 (API level 24)' };
- const second_fake_avd = { name: 'AnotherAVD', target: 'Android 7.1 (API level 25)' };
- const third_fake_avd = { name: 'AVDThree', target: 'Android 8.0 (API level 26)' };
- emu.list_images.and.returnValue(Promise.resolve([fake_avd, second_fake_avd, third_fake_avd]));
-
- return emu.best_image().then(best_avd => {
- expect(best_avd).toBe(second_fake_avd);
- });
- });
-
- it('should return the AVD with API level that is closest to the project target API level, without going over', () => {
- target_mock.and.returnValue('android-26');
- const fake_avd = { name: 'MyFakeAVD', target: 'Android 7.0 (API level 24)' };
- const second_fake_avd = { name: 'AnotherAVD', target: 'Android 7.1 (API level 25)' };
- const third_fake_avd = { name: 'AVDThree', target: 'Android 99.0 (API level 134)' };
- emu.list_images.and.returnValue(Promise.resolve([fake_avd, second_fake_avd, third_fake_avd]));
-
- return emu.best_image().then(best_avd => {
- expect(best_avd).toBe(second_fake_avd);
- });
- });
-
- it('should not try to compare API levels when an AVD definition is missing API level info', () => {
- emu.list_images.and.returnValue(Promise.resolve([{
- name: 'Samsung_S8_API_26',
- device: 'Samsung S8+ (User)',
- path: '/Users/daviesd/.android/avd/Samsung_S8_API_26.avd',
- abi: 'google_apis/x86',
- target: 'Android 8.0'
- }]));
-
- return emu.best_image().then(best_avd => {
- expect(best_avd).toBeDefined();
- });
- });
- });
-
- describe('list_started', () => {
- it('should call adb devices with the emulators flag', () => {
- const AdbSpy = jasmine.createSpyObj('Adb', ['devices']);
- AdbSpy.devices.and.returnValue(Promise.resolve());
- emu.__set__('Adb', AdbSpy);
-
- return emu.list_started().then(() => {
- expect(AdbSpy.devices).toHaveBeenCalledWith({ emulators: true });
- });
- });
- });
-
- describe('get_available_port', () => {
- let emus;
-
- beforeEach(() => {
- emus = [];
- spyOn(emu, 'list_started').and.returnValue(Promise.resolve(emus));
- });
-
- it('should find the closest available port below 5584 for the emulator', () => {
- const lowestUsedPort = 5565;
- for (let i = 5584; i >= lowestUsedPort; i--) {
- emus.push(`emulator-${i}`);
- }
-
- return emu.get_available_port().then(port => {
- expect(port).toBe(lowestUsedPort - 1);
- });
- });
-
- it('should throw an error if no port is available between 5554 and 5584', () => {
- for (let i = 5584; i >= 5554; i--) {
- emus.push(`emulator-${i}`);
- }
-
- return emu.get_available_port().then(
- () => fail('Unexpectedly resolved'),
- err => {
- expect(err).toEqual(jasmine.any(CordovaError));
- }
- );
- });
- });
-
- describe('start', () => {
- const port = 5555;
- let emulator;
- let AdbSpy;
- let checkReqsSpy;
- let childProcessSpy;
- let shellJsSpy;
-
- beforeEach(() => {
- emulator = {
- name: 'Samsung_S8_API_26',
- device: 'Samsung S8+ (User)',
- path: '/Users/daviesd/.android/avd/Samsung_S8_API_26.avd',
- abi: 'google_apis/x86',
- target: 'Android 8.0'
- };
-
- AdbSpy = jasmine.createSpyObj('Adb', ['shell']);
- AdbSpy.shell.and.returnValue(Promise.resolve());
- emu.__set__('Adb', AdbSpy);
-
- checkReqsSpy = jasmine.createSpyObj('create_reqs', ['getAbsoluteAndroidCmd']);
- emu.__set__('check_reqs', checkReqsSpy);
-
- childProcessSpy = jasmine.createSpyObj('child_process', ['spawn']);
- childProcessSpy.spawn.and.returnValue(jasmine.createSpyObj('spawnFns', ['unref']));
- emu.__set__('child_process', childProcessSpy);
-
- spyOn(emu, 'get_available_port').and.returnValue(Promise.resolve(port));
- spyOn(emu, 'wait_for_emulator').and.returnValue(Promise.resolve('randomname'));
- spyOn(emu, 'wait_for_boot').and.returnValue(Promise.resolve());
-
- // Prevent pollution of the test logs
- const proc = emu.__get__('process');
- spyOn(proc.stdout, 'write').and.stub();
-
- shellJsSpy = jasmine.createSpyObj('shelljs', ['which']);
- shellJsSpy.which.and.returnValue('/dev/android-sdk/tools');
- emu.__set__('shelljs', shellJsSpy);
- });
-
- it('should find an emulator if an id is not specified', () => {
- spyOn(emu, 'best_image').and.returnValue(Promise.resolve(emulator));
-
- return emu.start().then(() => {
- // This is the earliest part in the code where we can hook in and check
- // the emulator that has been selected.
- const spawnArgs = childProcessSpy.spawn.calls.argsFor(0);
- expect(spawnArgs[1]).toContain(emulator.name);
- });
- });
-
- it('should use the specified emulator', () => {
- spyOn(emu, 'best_image');
-
- return emu.start(emulator.name).then(() => {
- expect(emu.best_image).not.toHaveBeenCalled();
-
- const spawnArgs = childProcessSpy.spawn.calls.argsFor(0);
- expect(spawnArgs[1]).toContain(emulator.name);
- });
- });
-
- it('should throw an error if no emulator is specified and no default is found', () => {
- spyOn(emu, 'best_image').and.returnValue(Promise.resolve());
-
- return emu.start().then(
- () => fail('Unexpectedly resolved'),
- err => {
- expect(err).toEqual(jasmine.any(CordovaError));
- }
- );
- });
-
- it('should unlock the screen after the emulator has booted', () => {
- emu.wait_for_emulator.and.returnValue(Promise.resolve(emulator.name));
- emu.wait_for_boot.and.returnValue(Promise.resolve(true));
-
- return emu.start(emulator.name).then(() => {
- expect(emu.wait_for_emulator).toHaveBeenCalledBefore(AdbSpy.shell);
- expect(emu.wait_for_boot).toHaveBeenCalledBefore(AdbSpy.shell);
- expect(AdbSpy.shell).toHaveBeenCalledWith(emulator.name, 'input keyevent 82');
- });
- });
-
- it('should resolve with the emulator id after the emulator has started', () => {
- emu.wait_for_emulator.and.returnValue(Promise.resolve(emulator.name));
- emu.wait_for_boot.and.returnValue(Promise.resolve(true));
-
- return emu.start(emulator.name).then(emulatorId => {
- expect(emulatorId).toBe(emulator.name);
- });
- });
-
- it('should resolve with null if starting the emulator times out', () => {
- emu.wait_for_emulator.and.returnValue(Promise.resolve(emulator.name));
- emu.wait_for_boot.and.returnValue(Promise.resolve(false));
-
- return emu.start(emulator.name).then(emulatorId => {
- expect(emulatorId).toBe(null);
- });
- });
- });
-
- describe('wait_for_emulator', () => {
- const port = 5656;
- const expectedEmulatorId = `emulator-${port}`;
- let AdbSpy;
-
- beforeEach(() => {
- AdbSpy = jasmine.createSpyObj('Adb', ['shell']);
- AdbSpy.shell.and.returnValue(Promise.resolve());
- emu.__set__('Adb', AdbSpy);
-
- spyOn(emu, 'wait_for_emulator').and.callThrough();
- });
-
- it('should resolve with the emulator id if the emulator has completed boot', () => {
- AdbSpy.shell.and.callFake((emulatorId, shellArgs) => {
- expect(emulatorId).toBe(expectedEmulatorId);
- expect(shellArgs).toContain('getprop dev.bootcomplete');
-
- return Promise.resolve('1'); // 1 means boot is complete
- });
-
- return emu.wait_for_emulator(port).then(emulatorId => {
- expect(emulatorId).toBe(expectedEmulatorId);
- });
- });
-
- it('should call itself again if the emulator is not ready', () => {
- AdbSpy.shell.and.returnValues(
- Promise.resolve('0'),
- Promise.resolve('0'),
- Promise.resolve('1')
- );
-
- return emu.wait_for_emulator(port).then(() => {
- expect(emu.wait_for_emulator).toHaveBeenCalledTimes(3);
- });
- });
-
- it('should call itself again if shell fails for a known reason', () => {
- AdbSpy.shell.and.returnValues(
- Promise.reject({ message: 'device not found' }),
- Promise.reject({ message: 'device offline' }),
- Promise.reject({ message: 'device still connecting' }),
- Promise.resolve('1')
- );
-
- return emu.wait_for_emulator(port).then(() => {
- expect(emu.wait_for_emulator).toHaveBeenCalledTimes(4);
- });
- });
-
- it('should throw an error if shell fails for an unknown reason', () => {
- const errorMessage = { message: 'Some unknown error' };
- AdbSpy.shell.and.returnValue(Promise.reject(errorMessage));
-
- return emu.wait_for_emulator(port).then(
- () => fail('Unexpectedly resolved'),
- err => {
- expect(err).toBe(errorMessage);
- }
- );
- });
- });
-
- describe('wait_for_boot', () => {
- const port = 5656;
- const emulatorId = `emulator-${port}`;
- const psOutput = `
- root 1 0 8504 1512 SyS_epoll_ 00000000 S /init
- u0_a1 2044 1350 1423452 47256 SyS_epoll_ 00000000 S android.process.acore
- u0_a51 2963 1350 1417724 37492 SyS_epoll_ 00000000 S com.google.process.gapps
- `;
-
- let AdbSpy;
-
- beforeEach(() => {
- // If we use Jasmine's fake clock, we need to re-require the target module,
- // or else it will not work.
- jasmine.clock().install();
- emu = rewire('../../bin/templates/cordova/lib/emulator');
-
- AdbSpy = jasmine.createSpyObj('Adb', ['shell']);
- emu.__set__('Adb', AdbSpy);
-
- spyOn(emu, 'wait_for_boot').and.callThrough();
-
- // Stop the logs from being polluted
- const proc = emu.__get__('process');
- spyOn(proc.stdout, 'write').and.stub();
- });
-
- afterEach(() => {
- jasmine.clock().uninstall();
- });
-
- it('should resolve with true if the system has booted', () => {
- AdbSpy.shell.and.callFake((emuId, shellArgs) => {
- expect(emuId).toBe(emulatorId);
- expect(shellArgs).toContain('ps');
-
- return Promise.resolve(psOutput);
- });
-
- return emu.wait_for_boot(emulatorId).then(isReady => {
- expect(isReady).toBe(true);
- });
- });
-
- it('should should check boot status at regular intervals until ready', () => {
- const retryInterval = emu.__get__('CHECK_BOOTED_INTERVAL');
- const RETRIES = 10;
-
- let shellPromise = Promise.resolve('');
- AdbSpy.shell.and.returnValue(shellPromise);
-
- const waitPromise = emu.wait_for_boot(emulatorId);
-
- let attempts = 0;
- function tickTimer () {
- shellPromise.then(() => {
- if (attempts + 1 === RETRIES) {
- AdbSpy.shell.and.returnValue(Promise.resolve(psOutput));
- jasmine.clock().tick(retryInterval);
- } else {
- attempts++;
- shellPromise = Promise.resolve('');
- AdbSpy.shell.and.returnValue(shellPromise);
- jasmine.clock().tick(retryInterval);
- tickTimer();
- }
- });
- }
-
- tickTimer();
-
- // After all the retries and eventual success, this is called
- return waitPromise.then(isReady => {
- expect(isReady).toBe(true);
- expect(emu.wait_for_boot).toHaveBeenCalledTimes(RETRIES + 1);
- });
- });
-
- it('should should check boot status at regular intervals until timeout', () => {
- const retryInterval = emu.__get__('CHECK_BOOTED_INTERVAL');
- const TIMEOUT = 9000;
- const expectedRetries = Math.floor(TIMEOUT / retryInterval);
-
- let shellPromise = Promise.resolve('');
- AdbSpy.shell.and.returnValue(shellPromise);
-
- const waitPromise = emu.wait_for_boot(emulatorId, TIMEOUT);
-
- let attempts = 0;
- function tickTimer () {
- shellPromise.then(() => {
- attempts++;
- shellPromise = Promise.resolve('');
- AdbSpy.shell.and.returnValue(shellPromise);
- jasmine.clock().tick(retryInterval);
-
- if (attempts < expectedRetries) {
- tickTimer();
- }
- });
- }
-
- tickTimer();
-
- // After all the retries and eventual success, this is called
- return waitPromise.then(isReady => {
- expect(isReady).toBe(false);
- expect(emu.wait_for_boot).toHaveBeenCalledTimes(expectedRetries + 1);
- });
- });
- });
-
- describe('resolveTarget', () => {
- const arch = 'arm7-test';
-
- beforeEach(() => {
- const buildSpy = jasmine.createSpyObj('build', ['detectArchitecture']);
- buildSpy.detectArchitecture.and.returnValue(Promise.resolve(arch));
- emu.__set__('build', buildSpy);
-
- spyOn(emu, 'list_started').and.returnValue(Promise.resolve(EMULATOR_LIST));
- });
-
- it('should throw an error if there are no running emulators', () => {
- emu.list_started.and.returnValue(Promise.resolve([]));
-
- return emu.resolveTarget().then(
- () => fail('Unexpectedly resolved'),
- err => {
- expect(err).toEqual(jasmine.any(CordovaError));
- }
- );
- });
-
- it('should throw an error if the requested emulator is not running', () => {
- const targetEmulator = 'unstarted-emu';
-
- return emu.resolveTarget(targetEmulator).then(
- () => fail('Unexpectedly resolved'),
- err => {
- expect(err.message).toContain(targetEmulator);
- }
- );
- });
-
- it('should return info on the first running emulator if none is specified', () => {
- return emu.resolveTarget().then(emulatorInfo => {
- expect(emulatorInfo.target).toBe(EMULATOR_LIST[0]);
- });
- });
-
- it('should return the emulator info', () => {
- return emu.resolveTarget(EMULATOR_LIST[1]).then(emulatorInfo => {
- expect(emulatorInfo).toEqual({ target: EMULATOR_LIST[1], arch, isEmulator: true });
- });
- });
- });
-
- describe('install', () => {
- let AndroidManifestSpy;
- let AndroidManifestFns;
- let AndroidManifestGetActivitySpy;
- let AdbSpy;
- let buildSpy;
- let childProcessSpy;
- let target;
-
- beforeEach(() => {
- target = { target: EMULATOR_LIST[1], arch: 'arm7', isEmulator: true };
-
- buildSpy = jasmine.createSpyObj('build', ['findBestApkForArchitecture']);
- emu.__set__('build', buildSpy);
-
- AndroidManifestFns = jasmine.createSpyObj('AndroidManifestFns', ['getPackageId', 'getActivity']);
- AndroidManifestGetActivitySpy = jasmine.createSpyObj('getActivity', ['getName']);
- AndroidManifestFns.getActivity.and.returnValue(AndroidManifestGetActivitySpy);
- AndroidManifestSpy = jasmine.createSpy('AndroidManifest').and.returnValue(AndroidManifestFns);
- emu.__set__('AndroidManifest', AndroidManifestSpy);
-
- AdbSpy = jasmine.createSpyObj('Adb', ['shell', 'start', 'uninstall']);
- AdbSpy.shell.and.returnValue(Promise.resolve());
- AdbSpy.start.and.returnValue(Promise.resolve());
- AdbSpy.uninstall.and.returnValue(Promise.resolve());
- emu.__set__('Adb', AdbSpy);
-
- childProcessSpy = jasmine.createSpyObj('child_process', ['exec']);
- childProcessSpy.exec.and.callFake((cmd, opts, callback) => callback());
- emu.__set__('child_process', childProcessSpy);
- });
-
- it('should get the full target object if only id is specified', () => {
- const targetId = target.target;
- spyOn(emu, 'resolveTarget').and.returnValue(Promise.resolve(target));
-
- return emu.install(targetId, {}).then(() => {
- expect(emu.resolveTarget).toHaveBeenCalledWith(targetId);
- });
- });
-
- it('should install to the passed target', () => {
- return emu.install(target, {}).then(() => {
- const execCmd = childProcessSpy.exec.calls.argsFor(0)[0];
- expect(execCmd).toContain(`-s ${target.target} install`);
- });
- });
-
- it('should install the correct apk based on the architecture and build results', () => {
- const buildResults = {
- apkPaths: 'path/to/apks',
- buildType: 'debug',
- buildMethod: 'foo'
- };
-
- const apkPath = 'my/apk/path/app.apk';
- buildSpy.findBestApkForArchitecture.and.returnValue(apkPath);
-
- return emu.install(target, buildResults).then(() => {
- expect(buildSpy.findBestApkForArchitecture).toHaveBeenCalledWith(buildResults, target.arch);
-
- const execCmd = childProcessSpy.exec.calls.argsFor(0)[0];
- expect(execCmd).toMatch(new RegExp(`install.*${apkPath}`));
- });
- });
-
- it('should uninstall and reinstall app if failure is due to different certificates', () => {
- let execAlreadyCalled;
- childProcessSpy.exec.and.callFake((cmd, opts, callback) => {
- if (!execAlreadyCalled) {
- execAlreadyCalled = true;
- callback(null, 'Failure: INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES');
- } else {
- callback();
- }
- });
-
- return emu.install(target, {}).then(() => {
- expect(childProcessSpy.exec).toHaveBeenCalledTimes(2);
- expect(AdbSpy.uninstall).toHaveBeenCalled();
- });
- });
-
- it('should throw any error not caused by different certificates', () => {
- const errorMsg = 'Failure: Failed to install';
- childProcessSpy.exec.and.callFake((cmd, opts, callback) => {
- callback(null, errorMsg);
- });
-
- return emu.install(target, {}).then(
- () => fail('Unexpectedly resolved'),
- err => {
- expect(err).toEqual(jasmine.any(CordovaError));
- expect(err.message).toContain(errorMsg);
- }
- );
- });
-
- it('should unlock the screen on device', () => {
- return emu.install(target, {}).then(() => {
- expect(AdbSpy.shell).toHaveBeenCalledWith(target.target, 'input keyevent 82');
- });
- });
-
- it('should start the newly installed app on the device', () => {
- const packageId = 'unittestapp';
- const activityName = 'TestActivity';
- AndroidManifestFns.getPackageId.and.returnValue(packageId);
- AndroidManifestGetActivitySpy.getName.and.returnValue(activityName);
-
- return emu.install(target, {}).then(() => {
- expect(AdbSpy.start).toHaveBeenCalledWith(target.target, `${packageId}/.${activityName}`);
- });
- });
- });
- });
|