Repository: wix/Detox
Pull request #1474 (2019-06-24 19:16:08)

(Android) Improve reporting of 'adb devices' for #1427
Improve reporting of 'adb devices' for #1427, so that users could report important stuff back when (if) this happens.


Patch:
diff --git a/detox/src/devices/android/ADB.js b/detox/src/devices/android/ADB.js
index 1f0b6cd17..6ccb7e701 100644
--- a/detox/src/devices/android/ADB.js
+++ b/detox/src/devices/android/ADB.js
@@ -66,6 +66,10 @@ class ADB {
       let device;
       if (this.isEmulator(deviceAdbName)) {
         const port = _.split(deviceAdbName, '-')[1];
+        if (!port) {
+          _reportTelnetPortResolutionError(input, devicesList, deviceAdbName, port);
+        }
+
         const telnet = new EmulatorTelnet();
         await telnet.connect(port);
         const name = await telnet.avdName();
@@ -103,7 +107,7 @@ class ADB {
 
   async install(deviceId, apkPath) {
     apkPath = `"${escape.inQuotedString(apkPath)}"`;
-    
+
     const apiLvl = await this.apiLevel(deviceId);
 
     let childProcess;
@@ -283,4 +287,20 @@ class ADB {
   }
 }
 
+function _reportTelnetPortResolutionError(input, devicesList, deviceAdbName, port) {
+  const {encodeBase64} = require('../../utils/encoding');
+  const errorMessage = [
+    `Failed to determine telnet port for emulator device '${deviceAdbName}'!`,
+    `Please help us out by reporting dump below in: https://github.com/wix/Detox/issues/1427`,
+    `------ BEGIN DUMP ------`,
+    `adb devices base64: ${encodeBase64(input)}`,
+    `adb devices: ${input}`,
+    `devicesList: ${devicesList}`,
+    `port: ${port}`,
+    `------  END DUMP  ------`,
+  ].join('\n');
+
+  throw new Error(errorMessage);
+}
+
 module.exports = ADB;


Test patch:
diff --git a/detox/src/devices/android/ADB.test.js b/detox/src/devices/android/ADB.test.js
index 4759e7987..42e3846c3 100644
--- a/detox/src/devices/android/ADB.test.js
+++ b/detox/src/devices/android/ADB.test.js
@@ -1,9 +1,11 @@
+
 describe('ADB', () => {
   const mockAndroidSDKPath = '/Android/sdk-mock';
+  const adbBinPath = `${mockAndroidSDKPath}/platform-tools/adb`;
 
+  let mockEmulatorTelnet;
   let ADB;
   let adb;
-  let EmulatorTelnet;
   let exec;
 
   beforeEach(() => {
@@ -12,9 +14,23 @@ describe('ADB', () => {
       getAndroidSDKPath: () => mockAndroidSDKPath,
     }));
 
-    jest.mock('./EmulatorTelnet');
-    EmulatorTelnet = require('./EmulatorTelnet');
+    jest.mock('../../utils/encoding', () => ({
+      encodeBase64: (text) => `base64(${text})`,
+    }));
 
+    mockEmulatorTelnet = {
+      connect: jest.fn(),
+      quit: jest.fn(),
+      avdName: jest.fn(),
+    };
+    class MockEmulatorTelnet {
+      constructor() {
+        this.connect = mockEmulatorTelnet.connect;
+        this.quit = mockEmulatorTelnet.quit;
+        this.avdName = mockEmulatorTelnet.avdName;
+      }
+    }
+    jest.mock('./EmulatorTelnet', () => MockEmulatorTelnet);
 
     jest.mock('../../utils/exec', () => {
       const exec = jest.fn();
@@ -27,10 +43,46 @@ describe('ADB', () => {
     adb = new ADB();
   });
 
-  it(`devices`, async () => {
-    await adb.devices();
-    expect(exec).toHaveBeenCalledWith(`${mockAndroidSDKPath}/platform-tools/adb  devices`, { verbosity: 'high' }, undefined, 1);
-    expect(exec).toHaveBeenCalledTimes(1);
+  describe('devices', () => {
+    it(`should invoke ADB`, async () => {
+      await adb.devices();
+      expect(exec).toHaveBeenCalledWith(`${adbBinPath}  devices`, { verbosity: 'high' }, undefined, 1);
+      expect(exec).toHaveBeenCalledTimes(1);
+    });
+
+    it(`should parse emulator devices`, async () => {
+      exec.mockReturnValue({
+        stdout: 'List of devices attached\nemulator-5554\tdevice\nemulator-5555\tdevice\n'
+      });
+
+      await adb.devices();
+      expect(mockEmulatorTelnet.connect).toHaveBeenCalledWith("5554");
+    });
+
+    it(`should abort if port can't be parsed`, async () => {
+      const adbDevicesResult = 'List of devices attached\nemulator-\tdevice\n';
+      exec.mockReturnValue({
+        stdout: adbDevicesResult
+      });
+
+      try {
+        await adb.devices();
+        fail('Expected an error');
+      } catch (error) {
+        expect(mockEmulatorTelnet.connect).not.toHaveBeenCalled();
+        expect(error.message).toContain(`Failed to determine telnet port for emulator device 'emulator-'!`);
+        expect(error.message).toContain(`base64(${adbDevicesResult})`);
+      }
+    });
+
+    it(`should skip if no devices are available`, async () => {
+      exec.mockReturnValue({
+        stdout: 'List of devices attached\n'
+      });
+
+      await adb.devices();
+      expect(mockEmulatorTelnet.connect).not.toHaveBeenCalled();
+    });
   });
 
   it(`install`, async () => {