Repository: wix/Detox
Pull request #1986 (2020-03-31 13:31:45)

Rearrange device drivers directory
- [x] This is a small change 
- [ ] This change has been discussed in issue #<?> and the solution has been agreed upon with maintainers.

---

**Description:**

Rearrange device drivers directory in a way that makes more sense, esp. now that Android/Emulator driver has been split to sub-modules, and thus is implemented across multiple files.

The new schema is:
```
detox
...
   |
   |- devices (device specific things at root)
       |- drivers
           |- android (everything android-related)
              |- tools (AAPT, ADB etc.)
           |- ios (everything ios-related)
              |- tools (AppleSimUtils)
```

>Beforehand, android and ios related things were scattered over 2 main directories.



Patch:
diff --git a/detox/package.json b/detox/package.json
index ed4c7b5ba..55557d909 100644
--- a/detox/package.json
+++ b/detox/package.json
@@ -85,7 +85,7 @@
       "src/artifacts/instruments",
       "src/artifacts/screenshot",
       "src/artifacts/video",
-      "src/devices/ios/AppleSimUtils.js",
+      "src/devices/drivers/ios/tools/AppleSimUtils.js",
       "src/server/DetoxServer.js",
       ".*Driver.js",
       "MissingDetox.js",
diff --git a/detox/src/Detox.js b/detox/src/Detox.js
index 9b0f57a59..c98ef2e41 100644
--- a/detox/src/Detox.js
+++ b/detox/src/Detox.js
@@ -3,10 +3,10 @@ const util = require('util');
 const logger = require('./utils/logger');
 const log = logger.child({ __filename });
 const Device = require('./devices/Device');
-const IosDriver = require('./devices/drivers/IosDriver');
-const SimulatorDriver = require('./devices/drivers/SimulatorDriver');
-const EmulatorDriver = require('./devices/drivers/EmulatorDriver');
-const AttachedAndroidDriver = require('./devices/drivers/AttachedAndroidDriver');
+const IosDriver = require('./devices/drivers/ios/IosDriver');
+const SimulatorDriver = require('./devices/drivers/ios/SimulatorDriver');
+const EmulatorDriver = require('./devices/drivers/android/EmulatorDriver');
+const AttachedAndroidDriver = require('./devices/drivers/android/AttachedAndroidDriver');
 const DetoxRuntimeError = require('./errors/DetoxRuntimeError');
 const argparse = require('./utils/argparse');
 const MissingDetox = require('./utils/MissingDetox');
diff --git a/detox/src/DetoxExportWrapper.js b/detox/src/DetoxExportWrapper.js
index cae11ecf7..f599afe51 100644
--- a/detox/src/DetoxExportWrapper.js
+++ b/detox/src/DetoxExportWrapper.js
@@ -2,7 +2,6 @@ const _ = require('lodash');
 const funpermaproxy = require('funpermaproxy');
 const Detox = require('./Detox');
 const DetoxConstants = require('./DetoxConstants');
-const argparse = require('./utils/argparse');
 const log = require('./utils/logger').child({ __filename });
 const configuration = require('./configuration');
 
diff --git a/detox/src/devices/drivers/AdbDevicesHelper.js b/detox/src/devices/drivers/android/AdbDevicesHelper.js
similarity index 100%
rename from detox/src/devices/drivers/AdbDevicesHelper.js
rename to detox/src/devices/drivers/android/AdbDevicesHelper.js
diff --git a/detox/src/devices/drivers/AdbDevicesHelper.test.js b/detox/src/devices/drivers/android/AdbDevicesHelper.test.js
similarity index 100%
rename from detox/src/devices/drivers/AdbDevicesHelper.test.js
rename to detox/src/devices/drivers/android/AdbDevicesHelper.test.js
diff --git a/detox/src/devices/drivers/AndroidDriver.js b/detox/src/devices/drivers/android/AndroidDriver.js
similarity index 87%
rename from detox/src/devices/drivers/AndroidDriver.js
rename to detox/src/devices/drivers/android/AndroidDriver.js
index ab2843e99..5b7568fe0 100644
--- a/detox/src/devices/drivers/AndroidDriver.js
+++ b/detox/src/devices/drivers/android/AndroidDriver.js
@@ -1,30 +1,30 @@
 const fs = require('fs');
 const URL = require('url').URL;
 const _ = require('lodash');
-const { encodeBase64 } = require('../../utils/encoding');
-const logger = require('../../utils/logger');
+const { encodeBase64 } = require('../../../utils/encoding');
+const logger = require('../../../utils/logger');
 const log = logger.child({ __filename });
-const invoke = require('../../invoke');
+const invoke = require('../../../invoke');
 const InvocationManager = invoke.InvocationManager;
-const ADB = require('../android/ADB');
-const AAPT = require('../android/AAPT');
-const APKPath = require('../android/APKPath');
-const DeviceDriverBase = require('./DeviceDriverBase');
-const DetoxApi = require('../../android/espressoapi/Detox');
-const EspressoDetoxApi = require('../../android/espressoapi/EspressoDetox');
-const UiDeviceProxy = require('../../android/espressoapi/UiDeviceProxy');
-const AndroidInstrumentsPlugin = require('../../artifacts/instruments/android/AndroidInstrumentsPlugin');
-const ADBLogcatPlugin = require('../../artifacts/log/android/ADBLogcatPlugin');
-const ADBScreencapPlugin = require('../../artifacts/screenshot/ADBScreencapPlugin');
-const ADBScreenrecorderPlugin = require('../../artifacts/video/ADBScreenrecorderPlugin');
-const AndroidDevicePathBuilder = require('../../artifacts/utils/AndroidDevicePathBuilder');
-const TimelineArtifactPlugin = require('../../artifacts/timeline/TimelineArtifactPlugin');
-const temporaryPath = require('../../artifacts/utils/temporaryPath');
-const DetoxRuntimeError = require('../../errors/DetoxRuntimeError');
-const sleep = require('../../utils/sleep');
-const retry = require('../../utils/retry');
-const { interruptProcess, spawnAndLog } = require('../../utils/exec');
-const AndroidExpect = require('../../android/expect');
+const ADB = require('./tools/ADB');
+const AAPT = require('./tools/AAPT');
+const APKPath = require('./tools/APKPath');
+const DeviceDriverBase = require('../DeviceDriverBase');
+const DetoxApi = require('../../../android/espressoapi/Detox');
+const EspressoDetoxApi = require('../../../android/espressoapi/EspressoDetox');
+const UiDeviceProxy = require('../../../android/espressoapi/UiDeviceProxy');
+const AndroidInstrumentsPlugin = require('../../../artifacts/instruments/android/AndroidInstrumentsPlugin');
+const ADBLogcatPlugin = require('../../../artifacts/log/android/ADBLogcatPlugin');
+const ADBScreencapPlugin = require('../../../artifacts/screenshot/ADBScreencapPlugin');
+const ADBScreenrecorderPlugin = require('../../../artifacts/video/ADBScreenrecorderPlugin');
+const AndroidDevicePathBuilder = require('../../../artifacts/utils/AndroidDevicePathBuilder');
+const TimelineArtifactPlugin = require('../../../artifacts/timeline/TimelineArtifactPlugin');
+const temporaryPath = require('../../../artifacts/utils/temporaryPath');
+const DetoxRuntimeError = require('../../../errors/DetoxRuntimeError');
+const sleep = require('../../../utils/sleep');
+const retry = require('../../../utils/retry');
+const { interruptProcess, spawnAndLog } = require('../../../utils/exec');
+const AndroidExpect = require('../../../android/expect');
 const { InstrumentationLogsParser } = require('./InstrumentationLogsParser');
 
 const reservedInstrumentationArgs = ['class', 'package', 'func', 'unit', 'size', 'perf', 'debug', 'log', 'emma', 'coverageFile'];
diff --git a/detox/src/devices/drivers/AttachedAndroidDriver.js b/detox/src/devices/drivers/android/AttachedAndroidDriver.js
similarity index 93%
rename from detox/src/devices/drivers/AttachedAndroidDriver.js
rename to detox/src/devices/drivers/android/AttachedAndroidDriver.js
index da6a5e5e2..159cc9ba8 100644
--- a/detox/src/devices/drivers/AttachedAndroidDriver.js
+++ b/detox/src/devices/drivers/android/AttachedAndroidDriver.js
@@ -1,6 +1,6 @@
 const _ = require('lodash');
 const AndroidDriver = require('./AndroidDriver');
-const DetoxRuntimeError = require('../../errors/DetoxRuntimeError');
+const DetoxRuntimeError = require('../../../errors/DetoxRuntimeError');
 
 class AttachedAndroidDriver extends AndroidDriver {
 
diff --git a/detox/src/devices/drivers/EmulatorDriver.js b/detox/src/devices/drivers/android/EmulatorDriver.js
similarity index 93%
rename from detox/src/devices/drivers/EmulatorDriver.js
rename to detox/src/devices/drivers/android/EmulatorDriver.js
index 40141252d..eed09d9e3 100644
--- a/detox/src/devices/drivers/EmulatorDriver.js
+++ b/detox/src/devices/drivers/android/EmulatorDriver.js
@@ -4,13 +4,13 @@ const path = require('path');
 const ini = require('ini');
 const AndroidDriver = require('./AndroidDriver');
 const EmulatorLookupHelper = require('./EmulatorLookupHelper');
-const DetoxRuntimeError = require('../../errors/DetoxRuntimeError');
-const DeviceRegistry = require('../DeviceRegistry');
-const Emulator = require('../android/Emulator');
-const EmulatorTelnet = require('../android/EmulatorTelnet');
-const environment = require('../../utils/environment');
-const retry = require('../../utils/retry');
-const log = require('../../utils/logger').child({ __filename });
+const DetoxRuntimeError = require('../../../errors/DetoxRuntimeError');
+const DeviceRegistry = require('../../DeviceRegistry');
+const Emulator = require('./tools/Emulator');
+const EmulatorTelnet = require('./tools/EmulatorTelnet');
+const environment = require('../../../utils/environment');
+const retry = require('../../../utils/retry');
+const log = require('../../../utils/logger').child({ __filename });
 
 const DetoxEmulatorsPortRange = {
   min: 10000,
@@ -159,9 +159,7 @@ class EmulatorDriver extends AndroidDriver {
 
   async _allocateDevice(avdName) {
     log.debug({ event: ACQUIRE_DEVICE_EV }, `Looking up a device based on ${avdName}`);
-
     const adbName = await this.deviceRegistry.allocateDevice(() => this._doAllocateDevice(avdName));
-
     log.debug({ event: ACQUIRE_DEVICE_EV }, `Settled on ${adbName}`);
     return adbName;
   }
diff --git a/detox/src/devices/drivers/EmulatorLookupHelper.js b/detox/src/devices/drivers/android/EmulatorLookupHelper.js
similarity index 94%
rename from detox/src/devices/drivers/EmulatorLookupHelper.js
rename to detox/src/devices/drivers/android/EmulatorLookupHelper.js
index 1dcd2517d..89305e51d 100644
--- a/detox/src/devices/drivers/EmulatorLookupHelper.js
+++ b/detox/src/devices/drivers/android/EmulatorLookupHelper.js
@@ -1,4 +1,4 @@
-const log = require('../../utils/logger').child({ __filename });
+const log = require('../../../utils/logger').child({ __filename });
 const AdbDevicesHelper = require('./AdbDevicesHelper');
 
 const ACQUIRE_DEVICE_EV = 'ACQUIRE_DEVICE';
diff --git a/detox/src/devices/drivers/InstrumentationLogsParser.js b/detox/src/devices/drivers/android/InstrumentationLogsParser.js
similarity index 100%
rename from detox/src/devices/drivers/InstrumentationLogsParser.js
rename to detox/src/devices/drivers/android/InstrumentationLogsParser.js
diff --git a/detox/src/devices/drivers/InstrumentationLogsParser.test.js b/detox/src/devices/drivers/android/InstrumentationLogsParser.test.js
similarity index 100%
rename from detox/src/devices/drivers/InstrumentationLogsParser.test.js
rename to detox/src/devices/drivers/android/InstrumentationLogsParser.test.js
diff --git a/detox/src/devices/android/AAPT.js b/detox/src/devices/drivers/android/tools/AAPT.js
similarity index 63%
rename from detox/src/devices/android/AAPT.js
rename to detox/src/devices/drivers/android/tools/AAPT.js
index 814765e06..39b973139 100644
--- a/detox/src/devices/android/AAPT.js
+++ b/detox/src/devices/drivers/android/tools/AAPT.js
@@ -1,10 +1,10 @@
 const _ = require('lodash');
-const {getAaptPath} = require('../../utils/environment');
+const {getAaptPath} = require('../../../../utils/environment');
 const path = require('path');
-const exec = require('../../utils/exec').execWithRetriesAndLogs;
-const escape = require('../../utils/pipeCommands').escape.inQuotedString;
-const egrep = require('../../utils/pipeCommands').search.fragment;
-const fsext = require('../../utils/fsext');
+const exec = require('../../../../utils/exec').execWithRetriesAndLogs;
+const escape = require('../../../../utils/pipeCommands').escape.inQuotedString;
+const egrep = require('../../../../utils/pipeCommands').search.fragment;
+const fsext = require('../../../../utils/fsext');
 
 class AAPT {
   constructor() {
diff --git a/detox/src/devices/android/ADB.js b/detox/src/devices/drivers/android/tools/ADB.js
similarity index 96%
rename from detox/src/devices/android/ADB.js
rename to detox/src/devices/drivers/android/tools/ADB.js
index fc686c9a4..0b38d6081 100644
--- a/detox/src/devices/android/ADB.js
+++ b/detox/src/devices/drivers/android/tools/ADB.js
@@ -1,10 +1,10 @@
 const _ = require('lodash');
-const {execWithRetriesAndLogs, spawnAndLog} = require('../../utils/exec');
-const {escape} = require('../../utils/pipeCommands');
-const DetoxRuntimeError = require('../../errors/DetoxRuntimeError');
+const {execWithRetriesAndLogs, spawnAndLog} = require('../../../../utils/exec');
+const {escape} = require('../../../../utils/pipeCommands');
+const DetoxRuntimeError = require('../../../../errors/DetoxRuntimeError');
 const EmulatorTelnet = require('./EmulatorTelnet');
-const {getAdbPath} = require('../../utils/environment');
-const {encodeBase64} = require('../../utils/encoding');
+const {getAdbPath} = require('../../../../utils/environment');
+const {encodeBase64} = require('../../../../utils/encoding');
 
 class ADB {
   constructor() {
diff --git a/detox/src/devices/android/APKPath.js b/detox/src/devices/drivers/android/tools/APKPath.js
similarity index 94%
rename from detox/src/devices/android/APKPath.js
rename to detox/src/devices/drivers/android/tools/APKPath.js
index b8708feab..41c4bebae 100644
--- a/detox/src/devices/android/APKPath.js
+++ b/detox/src/devices/drivers/android/tools/APKPath.js
@@ -1,6 +1,6 @@
 const path = require('path');
 const _ = require('lodash');
-const string = require('../../utils/string');
+const string = require('../../../../utils/string');
 
 class APKPath {
 
diff --git a/detox/src/devices/android/APKPath.test.js b/detox/src/devices/drivers/android/tools/APKPath.test.js
similarity index 100%
rename from detox/src/devices/android/APKPath.test.js
rename to detox/src/devices/drivers/android/tools/APKPath.test.js
diff --git a/detox/src/devices/android/Emulator.js b/detox/src/devices/drivers/android/tools/Emulator.js
similarity index 92%
rename from detox/src/devices/android/Emulator.js
rename to detox/src/devices/drivers/android/tools/Emulator.js
index 6696af089..7a33ec12d 100644
--- a/detox/src/devices/android/Emulator.js
+++ b/detox/src/devices/drivers/android/tools/Emulator.js
@@ -3,11 +3,11 @@ const fs = require('fs');
 const os = require('os');
 const spawn = require('child-process-promise').spawn;
 const Tail = require('tail').Tail;
-const exec = require('../../utils/exec').execWithRetriesAndLogs;
-const unitLogger = require('../../utils/logger').child({ __filename });
-const {getAndroidEmulatorPath} = require('../../utils/environment');
-const argparse = require('../../utils/argparse');
-const retry = require('../../utils/retry');
+const exec = require('../../../../utils/exec').execWithRetriesAndLogs;
+const unitLogger = require('../../../../utils/logger').child({ __filename });
+const {getAndroidEmulatorPath} = require('../../../../utils/environment');
+const argparse = require('../../../../utils/argparse');
+const retry = require('../../../../utils/retry');
 
 const isUnknownEmulatorError = (err) => (err.message || '').includes('failed with code null');
 
diff --git a/detox/src/devices/android/EmulatorTelnet.js b/detox/src/devices/drivers/android/tools/EmulatorTelnet.js
similarity index 96%
rename from detox/src/devices/android/EmulatorTelnet.js
rename to detox/src/devices/drivers/android/tools/EmulatorTelnet.js
index b5af8c876..d1207c9f4 100644
--- a/detox/src/devices/android/EmulatorTelnet.js
+++ b/detox/src/devices/drivers/android/tools/EmulatorTelnet.js
@@ -2,7 +2,7 @@ const Telnet = require('telnet-client');
 const path = require('path');
 const os = require('os');
 const fs = require('fs-extra');
-const log = require('../../utils/logger').child({ __filename });
+const log = require('../../../../utils/logger').child({ __filename });
 
 class EmulatorTelnet {
   constructor() {
diff --git a/detox/src/devices/drivers/IosDriver.js b/detox/src/devices/drivers/ios/IosDriver.js
similarity index 65%
rename from detox/src/devices/drivers/IosDriver.js
rename to detox/src/devices/drivers/ios/IosDriver.js
index 5746beb91..d23572005 100644
--- a/detox/src/devices/drivers/IosDriver.js
+++ b/detox/src/devices/drivers/ios/IosDriver.js
@@ -1,20 +1,20 @@
 const path = require('path');
 const fs = require('fs');
-const log = require('../../utils/logger').child({ __filename });
-const DeviceDriverBase = require('./DeviceDriverBase');
-const InvocationManager = require('../../invoke').InvocationManager;
-const invoke = require('../../invoke');
-const GREYConfigurationApi = require('../../ios/earlgreyapi/GREYConfiguration');
-const GREYConfigurationDetox = require('../../ios/earlgreyapi/GREYConfigurationDetox');
-const EarlyGreyImpl = require('../../ios/earlgreyapi/EarlGreyImpl');
-const AppleSimUtils = require('../ios/AppleSimUtils');
+const log = require('../../../utils/logger').child({ __filename });
+const DeviceDriverBase = require('../DeviceDriverBase');
+const InvocationManager = require('../../../invoke').InvocationManager;
+const invoke = require('../../../invoke');
+const GREYConfigurationApi = require('../../../ios/earlgreyapi/GREYConfiguration');
+const GREYConfigurationDetox = require('../../../ios/earlgreyapi/GREYConfigurationDetox');
+const EarlyGreyImpl = require('../../../ios/earlgreyapi/EarlGreyImpl');
+const AppleSimUtils = require('./tools/AppleSimUtils');
 
-const SimulatorLogPlugin = require('../../artifacts/log/ios/SimulatorLogPlugin');
-const SimulatorScreenshotPlugin = require('../../artifacts/screenshot/SimulatorScreenshotPlugin');
-const SimulatorRecordVideoPlugin = require('../../artifacts/video/SimulatorRecordVideoPlugin');
-const SimulatorInstrumentsPlugin = require('../../artifacts/instruments/ios/SimulatorInstrumentsPlugin');
-const TimelineArtifactPlugin = require('../../artifacts/timeline/TimelineArtifactPlugin');
-const IosExpect = require('../../ios/expect');
+const SimulatorLogPlugin = require('../../../artifacts/log/ios/SimulatorLogPlugin');
+const SimulatorScreenshotPlugin = require('../../../artifacts/screenshot/SimulatorScreenshotPlugin');
+const SimulatorRecordVideoPlugin = require('../../../artifacts/video/SimulatorRecordVideoPlugin');
+const SimulatorInstrumentsPlugin = require('../../../artifacts/instruments/ios/SimulatorInstrumentsPlugin');
+const TimelineArtifactPlugin = require('../../../artifacts/timeline/TimelineArtifactPlugin');
+const IosExpect = require('../../../ios/expect');
 
 class IosDriver extends DeviceDriverBase {
   constructor(config) {
diff --git a/detox/src/devices/drivers/SimulatorDriver.js b/detox/src/devices/drivers/ios/SimulatorDriver.js
similarity index 95%
rename from detox/src/devices/drivers/SimulatorDriver.js
rename to detox/src/devices/drivers/ios/SimulatorDriver.js
index d64156dec..36e135d56 100644
--- a/detox/src/devices/drivers/SimulatorDriver.js
+++ b/detox/src/devices/drivers/ios/SimulatorDriver.js
@@ -2,13 +2,13 @@ const _ = require('lodash');
 const fs = require('fs');
 const path = require('path');
 const exec = require('child-process-promise').exec;
-const DeviceRegistry = require('../DeviceRegistry');
+const DeviceRegistry = require('../../DeviceRegistry');
 const IosDriver = require('./IosDriver');
-const temporaryPath = require('../../artifacts/utils/temporaryPath');
-const configuration = require('../../configuration');
-const DetoxRuntimeError = require('../../errors/DetoxRuntimeError');
-const environment = require('../../utils/environment');
-const argparse = require('../../utils/argparse');
+const temporaryPath = require('../../../artifacts/utils/temporaryPath');
+const configuration = require('../../../configuration');
+const DetoxRuntimeError = require('../../../errors/DetoxRuntimeError');
+const environment = require('../../../utils/environment');
+const argparse = require('../../../utils/argparse');
 
 class SimulatorDriver extends IosDriver {
 
diff --git a/detox/src/devices/ios/AppleSimUtils.js b/detox/src/devices/drivers/ios/tools/AppleSimUtils.js
similarity index 97%
rename from detox/src/devices/ios/AppleSimUtils.js
rename to detox/src/devices/drivers/ios/tools/AppleSimUtils.js
index 8e9daac13..0dce5c864 100644
--- a/detox/src/devices/ios/AppleSimUtils.js
+++ b/detox/src/devices/drivers/ios/tools/AppleSimUtils.js
@@ -1,9 +1,9 @@
 const _ = require('lodash');
 const path = require('path');
-const {joinArgs} = require('../../utils/argparse');
-const exec = require('../../utils/exec');
-const log = require('../../utils/logger').child({ __filename });
-const environment = require('../../utils/environment');
+const {joinArgs} = require('../../../../utils/argparse');
+const exec = require('../../../../utils/exec');
+const log = require('../../../../utils/logger').child({ __filename });
+const environment = require('../../../../utils/environment');
 
 class AppleSimUtils {
   async setPermissions(udid, bundleId, permissionsObj) {


Test patch:
diff --git a/detox/src/Detox.test.js b/detox/src/Detox.test.js
index cacfb95d9..e1631dd21 100644
--- a/detox/src/Detox.test.js
+++ b/detox/src/Detox.test.js
@@ -72,8 +72,8 @@ describe('Detox', () => {
 
     global.device = undefined;
 
-    jest.mock('./devices/drivers/IosDriver');
-    jest.mock('./devices/drivers/SimulatorDriver');
+    jest.mock('./devices/drivers/ios/IosDriver');
+    jest.mock('./devices/drivers/ios/SimulatorDriver');
     jest.mock('./devices/Device');
     jest.mock('./server/DetoxServer');
   });
diff --git a/detox/src/devices/Device.test.js b/detox/src/devices/Device.test.js
index ce06976d4..49d9db697 100644
--- a/detox/src/devices/Device.test.js
+++ b/detox/src/devices/Device.test.js
@@ -28,7 +28,7 @@ describe('Device', () => {
     jest.mock('./drivers/DeviceDriverBase');
     DeviceDriverBase = require('./drivers/DeviceDriverBase');
 
-    SimulatorDriver = require('./drivers/SimulatorDriver');
+    SimulatorDriver = require('./drivers/ios/SimulatorDriver');
 
     jest.mock('../client/Client');
     Client = require('../client/Client');
diff --git a/detox/src/devices/drivers/AndroidDriver.test.js b/detox/src/devices/drivers/android/AndroidDriver.test.js
similarity index 93%
rename from detox/src/devices/drivers/AndroidDriver.test.js
rename to detox/src/devices/drivers/android/AndroidDriver.test.js
index f9d2ae620..b6b709279 100644
--- a/detox/src/devices/drivers/AndroidDriver.test.js
+++ b/detox/src/devices/drivers/android/AndroidDriver.test.js
@@ -7,14 +7,14 @@ describe('Android driver', () => {
   let client;
   let exec;
   beforeEach(() => {
-    jest.mock('../../utils/encoding', () => ({
+    jest.mock('../../../utils/encoding', () => ({
       encodeBase64: (x) => `base64(${x})`,
     }));
 
-    jest.mock('../android/ADB', () => mockADBClass);
-    jest.mock('../../utils/AsyncEmitter', () => mockAsyncEmitter);
-    jest.mock('../../utils/sleep', () => jest.fn().mockResolvedValue(''));
-    jest.mock('../../utils/retry', () => jest.fn().mockResolvedValue(''));
+    jest.mock('./tools/ADB', () => mockADBClass);
+    jest.mock('../../../utils/AsyncEmitter', () => mockAsyncEmitter);
+    jest.mock('../../../utils/sleep', () => jest.fn().mockResolvedValue(''));
+    jest.mock('../../../utils/retry', () => jest.fn().mockResolvedValue(''));
 
     jest.mock('./InstrumentationLogsParser', () => ({
       InstrumentationLogsParser: mockInstrumentationLogsParserClass,
@@ -23,13 +23,13 @@ describe('Android driver', () => {
     const mockLogger = {
       warn: jest.fn(),
     };
-    jest.mock('../../utils/logger', () => ({
+    jest.mock('../../../utils/logger', () => ({
       child: () => mockLogger,
       ...mockLogger,
     }));
-    logger = require('../../utils/logger');
+    logger = require('../../../utils/logger');
 
-    jest.mock('../../utils/exec', () => ({
+    jest.mock('../../../utils/exec', () => ({
       spawnAndLog: jest.fn().mockReturnValue({
         childProcess: {
           on: jest.fn(),
@@ -41,7 +41,7 @@ describe('Android driver', () => {
       }),
       interruptProcess: jest.fn(),
     }));
-    exec = require('../../utils/exec');
+    exec = require('../../../utils/exec');
 
     client = {
       configuration: {
diff --git a/detox/src/devices/drivers/EmulatorLookupHelper.test.js b/detox/src/devices/drivers/android/EmulatorLookupHelper.test.js
similarity index 98%
rename from detox/src/devices/drivers/EmulatorLookupHelper.test.js
rename to detox/src/devices/drivers/android/EmulatorLookupHelper.test.js
index 63a690a09..3da54cad0 100644
--- a/detox/src/devices/drivers/EmulatorLookupHelper.test.js
+++ b/detox/src/devices/drivers/android/EmulatorLookupHelper.test.js
@@ -24,7 +24,7 @@ describe('emulators lookup helper', () => {
   let mockDeviceRegistry;
   let helper;
   beforeEach(() => {
-    jest.mock('../../utils/logger', () => ({
+    jest.mock('../../../utils/logger', () => ({
       child: jest.fn().mockReturnValue({
         debug: jest.fn(),
       }),
diff --git a/detox/src/devices/android/AAPT.test.js b/detox/src/devices/drivers/android/tools/AAPT.test.js
similarity index 97%
rename from detox/src/devices/android/AAPT.test.js
rename to detox/src/devices/drivers/android/tools/AAPT.test.js
index 4fc2c5bb4..245c08e17 100644
--- a/detox/src/devices/android/AAPT.test.js
+++ b/detox/src/devices/drivers/android/tools/AAPT.test.js
@@ -5,7 +5,7 @@ xdescribe('AAPT', () => {
   let exec;
 
   beforeEach(() => {
-    jest.mock('../../utils/logger');
+    jest.mock('../../../utils/logger');
     jest.mock('child-process-promise');
     exec = require('child-process-promise').exec;
 
@@ -67,4 +67,4 @@ supports-screens: 'small' 'normal' 'large' 'xlarge'
 supports-any-density: 'true'
 locales: '--_--' 'ca' 'da' 'fa' 'ja' 'nb' 'de' 'af' 'bg' 'th' 'fi' 'hi' 'vi' 'sk' 'uk' 'el' 'nl' 'pl' 'sl' 'tl' 'am' 'in' 'ko' 'ro' 'ar' 'fr' 'hr' 'sr' 'sr-Latn' 'tr' 'cs' 'es' 'it' 'lt' 'pt' 'hu' 'ru' 'zu' 'lv' 'sv' 'iw' 'sw' 'bs-BA' 'fr-CA' 'lo-LA' 'en-GB' 'bn-BD' 'et-EE' 'ka-GE' 'ky-KG' 'km-KH' 'zh-HK' 'si-LK' 'mk-MK' 'ur-PK' 'sq-AL' 'hy-AM' 'my-MM' 'zh-CN' 'pa-IN' 'ta-IN' 'te-IN' 'ml-IN' 'en-IN' 'kn-IN' 'mr-IN' 'gu-IN' 'mn-MN' 'ne-NP' 'pt-BR' 'gl-ES' 'eu-ES' 'is-IS' 'es-US' 'pt-PT' 'en-AU' 'zh-TW' 'be-BY' 'ms-MY' 'az-AZ' 'kk-KZ' 'uz-UZ'
 densities: '160' '240' '320' '480' '640'
-native-code: 'armeabi-v7a' 'x86'`;
\ No newline at end of file
+native-code: 'armeabi-v7a' 'x86'`;
diff --git a/detox/src/devices/android/ADB.test.js b/detox/src/devices/drivers/android/tools/ADB.test.js
similarity index 96%
rename from detox/src/devices/android/ADB.test.js
rename to detox/src/devices/drivers/android/tools/ADB.test.js
index fd6e1878a..bcfac0f21 100644
--- a/detox/src/devices/android/ADB.test.js
+++ b/detox/src/devices/drivers/android/tools/ADB.test.js
@@ -8,11 +8,11 @@ describe('ADB', () => {
   let exec;
 
   beforeEach(() => {
-    jest.mock('../../utils/logger');
-    jest.mock('../../utils/environment');
-    require('../../utils/environment').getAdbPath.mockReturnValue(adbBinPath);
+    jest.mock('../../../../utils/logger');
+    jest.mock('../../../../utils/environment');
+    require('../../../../utils/environment').getAdbPath.mockReturnValue(adbBinPath);
 
-    jest.mock('../../utils/encoding', () => ({
+    jest.mock('../../../../utils/encoding', () => ({
       encodeBase64: (text) => `base64(${text})`,
     }));
 
@@ -30,12 +30,12 @@ describe('ADB', () => {
     }
     jest.mock('./EmulatorTelnet', () => MockEmulatorTelnet);
 
-    jest.mock('../../utils/exec', () => {
+    jest.mock('../../../../utils/exec', () => {
       const exec = jest.fn();
       exec.mockReturnValue({ stdout: '' });
       return { execWithRetriesAndLogs: exec };
     });
-    exec = require('../../utils/exec').execWithRetriesAndLogs;
+    exec = require('../../../../utils/exec').execWithRetriesAndLogs;
 
     ADB = require('./ADB');
     adb = new ADB();
diff --git a/detox/src/devices/drivers/SimulatorDriver.test.js b/detox/src/devices/drivers/ios/SimulatorDriver.test.js
similarity index 98%
rename from detox/src/devices/drivers/SimulatorDriver.test.js
rename to detox/src/devices/drivers/ios/SimulatorDriver.test.js
index 57c0071ec..1b597b95f 100644
--- a/detox/src/devices/drivers/SimulatorDriver.test.js
+++ b/detox/src/devices/drivers/ios/SimulatorDriver.test.js
@@ -5,7 +5,7 @@ describe('IOS simulator driver', () => {
   const bundleId = 'bundle-id-mock';
 
   beforeEach(() => {
-    jest.mock('../ios/AppleSimUtils', () => mockAppleSimUtils);
+    jest.mock('./tools/AppleSimUtils', () => mockAppleSimUtils);
   });
 
   describe('launch args', () => {
@@ -88,7 +88,7 @@ describe('IOS simulator driver', () => {
       uut = new SimulatorDriver({ client: {} });
       jest.spyOn(uut.deviceRegistry, 'isDeviceBusy').mockReturnValue(false);
       applesimutils = uut.applesimutils;
-      applesimutils.list.mockImplementation(async () => require('../ios/applesimutils.mock')['--list']);
+      applesimutils.list.mockImplementation(async () => require('./tools/applesimutils.mock')['--list']);
     });
 
     it('should accept string as device type', async () => {