Skip to content

Commit b0637a3

Browse files
committed
Refactor uninstall onto a helper, as well
1 parent 486696b commit b0637a3

File tree

6 files changed

+122
-35
lines changed

6 files changed

+122
-35
lines changed

detox/src/devices/drivers/android/AndroidDriver.js

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ const InvocationManager = invoke.InvocationManager;
99
const ADB = require('./tools/ADB');
1010
const AAPT = require('./tools/AAPT');
1111
const APKPath = require('./tools/APKPath');
12+
const AppUninstallHelper = require('./tools/AppUninstallHelper');
1213
const DeviceDriverBase = require('../DeviceDriverBase');
1314
const DetoxApi = require('../../../android/espressoapi/Detox');
1415
const EspressoDetoxApi = require('../../../android/espressoapi/EspressoDetox');
@@ -79,15 +80,8 @@ class AndroidDriver extends DeviceDriverBase {
7980

8081
async uninstallApp(deviceId, bundleId) {
8182
await this.emitter.emit('beforeUninstallApp', { deviceId, bundleId });
82-
83-
if (await this.adb.isPackageInstalled(deviceId, bundleId)) {
84-
await this.adb.uninstall(deviceId, bundleId);
85-
}
86-
87-
const testBundle = `${bundleId}.test`;
88-
if (await this.adb.isPackageInstalled(deviceId, testBundle)) {
89-
await this.adb.uninstall(deviceId, testBundle);
90-
}
83+
const uninstallHelper = new AppUninstallHelper(this.adb);
84+
await uninstallHelper.uninstall(deviceId, bundleId);
9185
}
9286

9387
async uninstallAppByApk(deviceId, apkPath) {

detox/src/devices/drivers/android/EmulatorDriver.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,10 +68,10 @@ class EmulatorDriver extends AndroidDriver {
6868
testBinaryPath,
6969
} = this._getInstallPaths(_binaryPath, _testBinaryPath);
7070

71-
await this.uninstallAppByApk(deviceId, binaryPath); // TODO extract this (and all related logic) to a designated helper?
71+
await this.uninstallAppByApk(deviceId, binaryPath);
7272

73-
const installHelper = new AppInstallHelper(this.adb, deviceId);
74-
await installHelper.install(binaryPath, testBinaryPath);
73+
const installHelper = new AppInstallHelper(this.adb);
74+
await installHelper.install(deviceId, binaryPath, testBinaryPath);
7575
}
7676

7777
async cleanup(adbName, bundleId) {

detox/src/devices/drivers/android/tools/AppInstallHelper.js

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,30 +2,29 @@ const EMU_TEMP_PATH = '/data/local/tmp';
22
const EMU_TEMP_INSTALL_PATH = `${EMU_TEMP_PATH}/detox`;
33

44
class AppInstallHelper {
5-
constructor(adb, deviceId, tempDir = EMU_TEMP_INSTALL_PATH) {
5+
constructor(adb, tempDir = EMU_TEMP_INSTALL_PATH) {
66
this._adb = adb;
7-
this._deviceId = deviceId;
87
this._tempDir = tempDir;
98
}
109

11-
async install(appBinaryPath, testBinaryPath) {
12-
await this._prepareTempDirOnDevice();
10+
async install(deviceId, appBinaryPath, testBinaryPath) {
11+
await this._prepareTempDirOnDevice(deviceId);
1312

1413
const appBinaryPathOnTarget = this._getTargetBinaryPath(false);
15-
await this._pushAndInstallBinary(appBinaryPath, appBinaryPathOnTarget);
14+
await this._pushAndInstallBinary(deviceId, appBinaryPath, appBinaryPathOnTarget);
1615

1716
const testBinaryPathOnTarget = this._getTargetBinaryPath(true);
18-
await this._pushAndInstallBinary(testBinaryPath, testBinaryPathOnTarget);
17+
await this._pushAndInstallBinary(deviceId, testBinaryPath, testBinaryPathOnTarget);
1918
}
2019

21-
async _prepareTempDirOnDevice() {
22-
await this._adb.shell(this._deviceId, `rm -fr ${this._tempDir}`);
23-
await this._adb.shell(this._deviceId, `mkdir -p ${this._tempDir}`);
20+
async _prepareTempDirOnDevice(deviceId) {
21+
await this._adb.shell(deviceId, `rm -fr ${this._tempDir}`);
22+
await this._adb.shell(deviceId, `mkdir -p ${this._tempDir}`);
2423
}
2524

26-
async _pushAndInstallBinary(binaryPath, binaryPathOnTarget) {
27-
await this._adb.push(this._deviceId, binaryPath, binaryPathOnTarget);
28-
await this._adb.remoteInstall(this._deviceId, binaryPathOnTarget);
25+
async _pushAndInstallBinary(deviceId, binaryPath, binaryPathOnTarget) {
26+
await this._adb.push(deviceId, binaryPath, binaryPathOnTarget);
27+
await this._adb.remoteInstall(deviceId, binaryPathOnTarget);
2928
}
3029

3130
_getTargetBinaryPath(isTestBinary) {

detox/src/devices/drivers/android/tools/AppInstallHelper.test.js

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
const deviceTempDir = '/mock-tmp-dir';
21
const deviceId = 'mock-device-id';
2+
const deviceTempDir = '/mock-tmp-dir';
33
const appBinaryPath = '/mock-app-binary-path/binary.apk';
44
const testBinaryPath = '/mock-test-binary-path/test/binary.apk';
55

@@ -22,11 +22,11 @@ describe('Android app installation helper', () => {
2222
let uut;
2323
beforeEach(() => {
2424
const AppInstallHelper = require('./AppInstallHelper');
25-
uut = new AppInstallHelper(adb, deviceId, deviceTempDir);
25+
uut = new AppInstallHelper(adb, deviceTempDir);
2626
});
2727

2828
it('should recreate a temp dir on the device', async () => {
29-
await uut.install(appBinaryPath, testBinaryPath);
29+
await uut.install(deviceId, appBinaryPath, testBinaryPath);
3030

3131
expect(adb.shell).toHaveBeenCalledWith(deviceId, `rm -fr ${deviceTempDir}`);
3232
expect(adb.shell).toHaveBeenCalledWith(deviceId, `mkdir -p ${deviceTempDir}`);
@@ -36,32 +36,32 @@ describe('Android app installation helper', () => {
3636
adb.shell.mockRejectedValue(new Error('mocked error in adb-shell'));
3737

3838
try {
39-
await uut.install(appBinaryPath, testBinaryPath);
39+
await uut.install(deviceId, appBinaryPath, testBinaryPath);
4040
fail('expected to throw');
4141
} catch (err) {}
4242
});
4343

4444
it('should push app-binary file to temp dir on device', async () => {
45-
await uut.install(appBinaryPath, testBinaryPath);
45+
await uut.install(deviceId, appBinaryPath, testBinaryPath);
4646
expect(adb.push).toHaveBeenCalledWith(deviceId, appBinaryPath, '/mock-tmp-dir/Application.apk');
4747
});
4848

4949
it('should push test-binary file to temp dir on device', async () => {
50-
await uut.install(appBinaryPath, testBinaryPath);
50+
await uut.install(deviceId, appBinaryPath, testBinaryPath);
5151
expect(adb.push).toHaveBeenCalledWith(deviceId, testBinaryPath, '/mock-tmp-dir/Test.apk');
5252
});
5353

5454
it('should fail if adb-push fails', async () => {
5555
adb.push.mockRejectedValue(new Error('mocked error in adb-push'));
5656

5757
try {
58-
await uut.install(appBinaryPath, testBinaryPath);
58+
await uut.install(deviceId, appBinaryPath, testBinaryPath);
5959
fail('expected to throw');
6060
} catch(err) {}
6161
});
6262

6363
it('should remote-install both binaries via shell', async () => {
64-
await uut.install(appBinaryPath, testBinaryPath);
64+
await uut.install(deviceId, appBinaryPath, testBinaryPath);
6565
expect(adb.remoteInstall).toHaveBeenCalledWith(deviceId, '/mock-tmp-dir/Application.apk');
6666
expect(adb.remoteInstall).toHaveBeenCalledWith(deviceId, '/mock-tmp-dir/Test.apk');
6767
});
@@ -70,16 +70,16 @@ describe('Android app installation helper', () => {
7070
adb.remoteInstall.mockRejectedValue(new Error('mocked error in remote-install'));
7171

7272
try {
73-
await uut.install(appBinaryPath, testBinaryPath);
73+
await uut.install(deviceId, appBinaryPath, testBinaryPath);
7474
fail('expected to throw');
7575
} catch(err) {}
7676
});
7777

7878
it('should use a default temp-dir', async () => {
7979
const AppInstallHelper = require('./AppInstallHelper');
80-
uut = new AppInstallHelper(adb, deviceId, undefined);
80+
uut = new AppInstallHelper(adb, undefined);
8181

82-
await uut.install(appBinaryPath, testBinaryPath);
82+
await uut.install(deviceId, appBinaryPath, testBinaryPath);
8383

8484
expect(adb.push).toHaveBeenCalledWith(deviceId, appBinaryPath, '/data/local/tmp/detox/Application.apk');
8585
});
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
class AppUninstallHelper {
2+
constructor(adb) {
3+
this._adb = adb;
4+
}
5+
6+
async uninstall(deviceId, bundleId) {
7+
if (await this._adb.isPackageInstalled(deviceId, bundleId)) {
8+
await this._adb.uninstall(deviceId, bundleId);
9+
}
10+
11+
const testBundleId = `${bundleId}.test`;
12+
if (await this._adb.isPackageInstalled(deviceId, testBundleId)) {
13+
await this._adb.uninstall(deviceId, testBundleId);
14+
}
15+
}
16+
}
17+
18+
module.exports = AppUninstallHelper;
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
const deviceId = 'mock-device-id';
2+
const bundleId = 'mock-bundle-id';
3+
const testBundleId = 'mock-bundle-id.test';
4+
5+
describe('Android app uninstall helper', () => {
6+
let adb;
7+
class MockAdbClass {
8+
constructor() {
9+
this.uninstall = (...args) => adb.uninstall(...args);
10+
this.isPackageInstalled = (...args) => adb.isPackageInstalled(...args);
11+
}
12+
}
13+
14+
beforeEach(() => {
15+
const ADBMock = jest.genMockFromModule('./ADB');
16+
adb = new ADBMock();
17+
adb.isPackageInstalled.mockResolvedValue(true);
18+
19+
jest.mock('./ADB', () => MockAdbClass);
20+
});
21+
22+
let uut;
23+
beforeEach(() => {
24+
const AppUninstallHelper = require('./AppUninstallHelper');
25+
uut = new AppUninstallHelper(adb);
26+
});
27+
28+
it('should uninstall the app\'s binary using adb', async () => {
29+
await uut.uninstall(deviceId, bundleId);
30+
expect(adb.uninstall).toHaveBeenCalledWith(deviceId, bundleId);
31+
});
32+
33+
it('should fail if app uninstall fails', async () => {
34+
adb.uninstall.mockRejectedValue(new Error('mocked error in adb.uninstall'));
35+
try {
36+
await uut.uninstall(deviceId, bundleId);
37+
fail('expected an error');
38+
} catch (err) {}
39+
});
40+
41+
it('should avoid uninstalling app if not already installed', async () => {
42+
adb.isPackageInstalled.mockResolvedValue(false);
43+
44+
await uut.uninstall(deviceId, bundleId);
45+
46+
expect(adb.isPackageInstalled).toHaveBeenCalledWith(deviceId, bundleId);
47+
expect(adb.uninstall).not.toHaveBeenCalledWith(deviceId, bundleId);
48+
});
49+
50+
it('should uninstall the test binary using adb', async () => {
51+
await uut.uninstall(deviceId, bundleId);
52+
expect(adb.uninstall).toHaveBeenCalledWith(deviceId, testBundleId);
53+
});
54+
55+
it('should fail if test binary uninstall fails', async () => {
56+
adb.uninstall
57+
.mockResolvedValueOnce(true)
58+
.mockRejectedValueOnce(new Error('mocked error in adb.uninstall'));
59+
60+
try {
61+
await uut.uninstall(deviceId, bundleId);
62+
fail('expected an error');
63+
} catch (err) {}
64+
});
65+
66+
it('should avoid uninstalling test binary if not already installed', async () => {
67+
adb.isPackageInstalled
68+
.mockResolvedValueOnce(true)
69+
.mockResolvedValueOnce(false);
70+
71+
await uut.uninstall(deviceId, bundleId);
72+
73+
expect(adb.isPackageInstalled).toHaveBeenCalledWith(deviceId, testBundleId);
74+
expect(adb.uninstall).not.toHaveBeenCalledWith(deviceId, testBundleId);
75+
});
76+
});

0 commit comments

Comments
 (0)