detox 20.12.2 → 20.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (124) hide show
  1. package/Detox-android/com/wix/detox/{20.12.2/detox-20.12.2-javadoc.jar → 20.13.0/detox-20.13.0-javadoc.jar} +0 -0
  2. package/Detox-android/com/wix/detox/20.13.0/detox-20.13.0-javadoc.jar.md5 +1 -0
  3. package/Detox-android/com/wix/detox/20.13.0/detox-20.13.0-javadoc.jar.sha1 +1 -0
  4. package/Detox-android/com/wix/detox/20.13.0/detox-20.13.0-javadoc.jar.sha256 +1 -0
  5. package/Detox-android/com/wix/detox/20.13.0/detox-20.13.0-javadoc.jar.sha512 +1 -0
  6. package/Detox-android/com/wix/detox/{20.12.2/detox-20.12.2-sources.jar → 20.13.0/detox-20.13.0-sources.jar} +0 -0
  7. package/Detox-android/com/wix/detox/20.13.0/detox-20.13.0-sources.jar.md5 +1 -0
  8. package/Detox-android/com/wix/detox/20.13.0/detox-20.13.0-sources.jar.sha1 +1 -0
  9. package/Detox-android/com/wix/detox/20.13.0/detox-20.13.0-sources.jar.sha256 +1 -0
  10. package/Detox-android/com/wix/detox/20.13.0/detox-20.13.0-sources.jar.sha512 +1 -0
  11. package/Detox-android/com/wix/detox/{20.12.2/detox-20.12.2.pom → 20.13.0/detox-20.13.0.pom} +1 -1
  12. package/Detox-android/com/wix/detox/20.13.0/detox-20.13.0.pom.md5 +1 -0
  13. package/Detox-android/com/wix/detox/20.13.0/detox-20.13.0.pom.sha1 +1 -0
  14. package/Detox-android/com/wix/detox/20.13.0/detox-20.13.0.pom.sha256 +1 -0
  15. package/Detox-android/com/wix/detox/20.13.0/detox-20.13.0.pom.sha512 +1 -0
  16. package/Detox-android/com/wix/detox/maven-metadata.xml +4 -4
  17. package/Detox-android/com/wix/detox/maven-metadata.xml.md5 +1 -1
  18. package/Detox-android/com/wix/detox/maven-metadata.xml.sha1 +1 -1
  19. package/Detox-android/com/wix/detox/maven-metadata.xml.sha256 +1 -1
  20. package/Detox-android/com/wix/detox/maven-metadata.xml.sha512 +1 -1
  21. package/Detox-ios-src.tbz +0 -0
  22. package/Detox-ios.tbz +0 -0
  23. package/local-cli/reset-lock-file.js +5 -9
  24. package/package.json +5 -6
  25. package/runners/jest/testEnvironment/index.js +1 -1
  26. package/src/DetoxWorker.js +5 -11
  27. package/src/artifacts/providers/index.js +3 -3
  28. package/src/artifacts/screenshot/SimulatorScreenshotPlugin.js +0 -17
  29. package/src/configuration/composeLoggerConfig.js +1 -0
  30. package/src/devices/allocation/DeviceAllocator.js +66 -20
  31. package/src/devices/allocation/DeviceList.js +44 -0
  32. package/src/devices/allocation/DeviceRegistry.js +189 -0
  33. package/src/devices/allocation/drivers/AllocationDriverBase.d.ts +15 -0
  34. package/src/devices/{common/drivers/android/tools → allocation/drivers/android}/FreeDeviceFinder.js +11 -10
  35. package/src/devices/allocation/drivers/android/attached/AttachedAndroidAllocDriver.js +22 -17
  36. package/src/devices/allocation/drivers/android/emulator/EmulatorAllocDriver.js +97 -38
  37. package/src/devices/allocation/drivers/android/emulator/EmulatorLauncher.js +32 -45
  38. package/src/devices/allocation/drivers/android/emulator/FreeEmulatorFinder.js +1 -1
  39. package/src/devices/allocation/drivers/android/emulator/FreePortFinder.js +37 -0
  40. package/src/devices/allocation/drivers/android/emulator/launchEmulatorProcess.js +3 -3
  41. package/src/devices/allocation/drivers/android/genycloud/GenyAllocDriver.js +104 -32
  42. package/src/devices/allocation/drivers/android/genycloud/GenyInstanceLauncher.js +40 -31
  43. package/src/devices/allocation/drivers/android/genycloud/GenyRegistry.js +121 -0
  44. package/src/devices/allocation/drivers/android/genycloud/services/GenyInstanceLifecycleService.js +24 -0
  45. package/src/devices/{common → allocation}/drivers/android/genycloud/services/GenyRecipesService.js +1 -1
  46. package/src/devices/allocation/drivers/android/genycloud/services/dto/GenyInstance.js +83 -0
  47. package/src/devices/allocation/drivers/android/genycloud/services/dto/GenyRecipe.js +25 -0
  48. package/src/devices/allocation/drivers/ios/SimulatorAllocDriver.js +94 -51
  49. package/src/devices/allocation/drivers/ios/SimulatorLauncher.js +11 -7
  50. package/src/devices/allocation/drivers/ios/SimulatorQuery.js +24 -0
  51. package/src/devices/allocation/factories/android.js +29 -35
  52. package/src/devices/allocation/factories/ios.js +7 -5
  53. package/src/devices/common/drivers/DeviceCookie.d.ts +12 -0
  54. package/src/devices/common/drivers/android/cookies.d.ts +11 -0
  55. package/src/devices/common/drivers/android/emulator/exec/EmulatorExec.js +17 -5
  56. package/src/devices/common/drivers/android/exec/ADB.js +1 -0
  57. package/src/devices/common/drivers/ios/cookies.d.ts +9 -0
  58. package/src/devices/cookies/index.js +0 -6
  59. package/src/devices/runtime/drivers/android/genycloud/GenyCloudDriver.js +7 -6
  60. package/src/devices/runtime/factories/android.js +3 -11
  61. package/src/devices/runtime/factories/ios.js +3 -2
  62. package/src/{servicelocator → devices/servicelocator}/android/emulatorServiceLocator.js +1 -1
  63. package/src/devices/servicelocator/android/genycloudServiceLocator.js +17 -0
  64. package/src/devices/servicelocator/android/index.js +23 -0
  65. package/src/{validation → devices/validation}/EnvironmentValidatorBase.js +1 -0
  66. package/src/{validation → devices/validation}/android/GenycloudEnvValidator.js +2 -2
  67. package/src/{validation → devices/validation}/factories/index.js +1 -1
  68. package/src/{validation → devices/validation}/ios/IosSimulatorEnvValidator.js +2 -2
  69. package/src/environmentFactory.js +1 -11
  70. package/src/ipc/IPCClient.js +17 -1
  71. package/src/ipc/IPCServer.js +27 -1
  72. package/src/logger/DetoxLogger.js +2 -2
  73. package/src/realms/DetoxContext.js +6 -0
  74. package/src/realms/DetoxPrimaryContext.js +42 -42
  75. package/src/realms/DetoxSecondaryContext.js +19 -0
  76. package/src/realms/symbols.js +4 -0
  77. package/src/utils/PIDService.js +27 -0
  78. package/src/utils/environment.js +8 -15
  79. package/src/utils/errorUtils.js +2 -2
  80. package/tsconfig.json +5 -3
  81. package/Detox-android/com/wix/detox/20.12.2/detox-20.12.2-javadoc.jar.md5 +0 -1
  82. package/Detox-android/com/wix/detox/20.12.2/detox-20.12.2-javadoc.jar.sha1 +0 -1
  83. package/Detox-android/com/wix/detox/20.12.2/detox-20.12.2-javadoc.jar.sha256 +0 -1
  84. package/Detox-android/com/wix/detox/20.12.2/detox-20.12.2-javadoc.jar.sha512 +0 -1
  85. package/Detox-android/com/wix/detox/20.12.2/detox-20.12.2-sources.jar.md5 +0 -1
  86. package/Detox-android/com/wix/detox/20.12.2/detox-20.12.2-sources.jar.sha1 +0 -1
  87. package/Detox-android/com/wix/detox/20.12.2/detox-20.12.2-sources.jar.sha256 +0 -1
  88. package/Detox-android/com/wix/detox/20.12.2/detox-20.12.2-sources.jar.sha512 +0 -1
  89. package/Detox-android/com/wix/detox/20.12.2/detox-20.12.2.pom.md5 +0 -1
  90. package/Detox-android/com/wix/detox/20.12.2/detox-20.12.2.pom.sha1 +0 -1
  91. package/Detox-android/com/wix/detox/20.12.2/detox-20.12.2.pom.sha256 +0 -1
  92. package/Detox-android/com/wix/detox/20.12.2/detox-20.12.2.pom.sha512 +0 -1
  93. package/src/devices/DeviceRegistry.js +0 -176
  94. package/src/devices/allocation/drivers/AllocationDriverBase.js +0 -30
  95. package/src/devices/allocation/drivers/android/attached/AttachedAndroidLauncher.js +0 -13
  96. package/src/devices/allocation/drivers/android/emulator/EmulatorAllocationHelper.js +0 -72
  97. package/src/devices/allocation/drivers/android/genycloud/GenyDeviceRegistryFactory.js +0 -16
  98. package/src/devices/allocation/drivers/android/genycloud/GenyInstanceAllocationHelper.js +0 -65
  99. package/src/devices/common/drivers/DeviceAllocationHelper.js +0 -20
  100. package/src/devices/common/drivers/DeviceLauncher.js +0 -19
  101. package/src/devices/common/drivers/android/genycloud/services/GenyInstanceLifecycleService.js +0 -25
  102. package/src/devices/common/drivers/android/genycloud/services/GenyInstanceLookupService.js +0 -38
  103. package/src/devices/common/drivers/android/genycloud/services/GenyInstanceNaming.js +0 -14
  104. package/src/devices/common/drivers/android/genycloud/services/dto/GenyInstance.js +0 -66
  105. package/src/devices/common/drivers/android/genycloud/services/dto/GenyRecipe.js +0 -13
  106. package/src/devices/cookies/AndroidDeviceCookie.js +0 -13
  107. package/src/devices/cookies/AndroidEmulatorCookie.js +0 -6
  108. package/src/devices/cookies/AttachedAndroidDeviceCookie.js +0 -12
  109. package/src/devices/cookies/DeviceCookie.js +0 -4
  110. package/src/devices/cookies/GenycloudEmulatorCookie.js +0 -20
  111. package/src/devices/cookies/IosCookie.js +0 -6
  112. package/src/devices/cookies/IosSimulatorCookie.js +0 -10
  113. package/src/devices/lifecycle/GenyGlobalLifecycleHandler.js +0 -71
  114. package/src/devices/lifecycle/factories/GenyGlobalLifecycleHandlerFactory.js +0 -18
  115. package/src/servicelocator/android/genycloudServiceLocator.js +0 -21
  116. package/src/servicelocator/android/index.js +0 -25
  117. package/src/servicelocator/ios.js +0 -7
  118. /package/Detox-android/com/wix/detox/{20.12.2/detox-20.12.2.aar → 20.13.0/detox-20.13.0.aar} +0 -0
  119. /package/Detox-android/com/wix/detox/{20.12.2/detox-20.12.2.aar.md5 → 20.13.0/detox-20.13.0.aar.md5} +0 -0
  120. /package/Detox-android/com/wix/detox/{20.12.2/detox-20.12.2.aar.sha1 → 20.13.0/detox-20.13.0.aar.sha1} +0 -0
  121. /package/Detox-android/com/wix/detox/{20.12.2/detox-20.12.2.aar.sha256 → 20.13.0/detox-20.13.0.aar.sha256} +0 -0
  122. /package/Detox-android/com/wix/detox/{20.12.2/detox-20.12.2.aar.sha512 → 20.13.0/detox-20.13.0.aar.sha512} +0 -0
  123. /package/src/devices/{common → allocation}/drivers/android/genycloud/exec/GenyCloudExec.js +0 -0
  124. /package/src/devices/{common → allocation}/drivers/android/genycloud/services/GenyAuthService.js +0 -0
@@ -0,0 +1 @@
1
+ 0709a8a30b2cc4c27244a2257ac28ed7
@@ -0,0 +1 @@
1
+ 08f017a03aa160bead65af9b208ea95857ac9697
@@ -0,0 +1 @@
1
+ 5cc49445c8f5440e5e5ed8d2d95e4827fb1ab4796d20e32ab30d7151da661ce7
@@ -0,0 +1 @@
1
+ 7360ab285d19450619f38c7da9985fda6514d382f903e87a2af9d4e0204a0250851c412a045da6ce04cc932e9addf7c131fd5147889975be20910e2fdc64e88f
@@ -0,0 +1 @@
1
+ 972fa81d6c5d9f0eb6edc63765bf01af
@@ -0,0 +1 @@
1
+ 1ea26448826d4701a7dce9d2c0c24355853ad9d7
@@ -0,0 +1 @@
1
+ 6b2f9a8186f2eef1075910eae28c189ac2030561520277e503e3a696f3c977e2
@@ -0,0 +1 @@
1
+ eae9264b4d57f78a80ecffae3c85e157a2cd1df1b2259c0edc93f5c22d305a004216c5e9e6b35a1415fab6ba14a4f6667acd2eac4d5c6ae5a7a410ee85ca2c7c
@@ -3,7 +3,7 @@
3
3
  <modelVersion>4.0.0</modelVersion>
4
4
  <groupId>com.wix</groupId>
5
5
  <artifactId>detox</artifactId>
6
- <version>20.12.2</version>
6
+ <version>20.13.0</version>
7
7
  <packaging>aar</packaging>
8
8
  <name>Detox</name>
9
9
  <description>Gray box end-to-end testing and automation library for mobile apps</description>
@@ -0,0 +1 @@
1
+ 293aa59dd07a84b7a1bd7c4dc2bffe16
@@ -0,0 +1 @@
1
+ 144cef7278f92d8e7798cae134d8f93136492080
@@ -0,0 +1 @@
1
+ a1062bb5feb8cb7210de7f0e2c36d8a219f8d4065377c9ced13ae55d7eb13220
@@ -0,0 +1 @@
1
+ 216ecb00454a1e03ef9ab2a197b616c4d326ec6ef47fd08b83b22d57c2c9d4dc37725a3c4d19600874074b40918387cebd1be11d558270af4ab7e797af40607f
@@ -3,11 +3,11 @@
3
3
  <groupId>com.wix</groupId>
4
4
  <artifactId>detox</artifactId>
5
5
  <versioning>
6
- <latest>20.12.2</latest>
7
- <release>20.12.2</release>
6
+ <latest>20.13.0</latest>
7
+ <release>20.13.0</release>
8
8
  <versions>
9
- <version>20.12.2</version>
9
+ <version>20.13.0</version>
10
10
  </versions>
11
- <lastUpdated>20230927202100</lastUpdated>
11
+ <lastUpdated>20231002075250</lastUpdated>
12
12
  </versioning>
13
13
  </metadata>
@@ -1 +1 @@
1
- c4e29695a8333254dfdb58e83b723a94
1
+ 253d464cc30a2d00e586eadca31d5952
@@ -1 +1 @@
1
- 8c90e83ee27dd4d9370742524f141054555c926b
1
+ 1a402a8246b4532c9be982b61c2b4d3b3e6ab741
@@ -1 +1 @@
1
- 5fb1606470374345397232c3529c053c5aa26fd8650b3f7d9706f251a7f2e3b8
1
+ 09104c2799b83cedb2f68628779529f7efb1e96b3e33c0ed8c814da6a5e19ef8
@@ -1 +1 @@
1
- 541d2924f1ccdd6c901ba584a978d8d26ba3027c6abca381dcb6b2553b4b730ca428d6743bc9d1fe0836e2662a4e81f5d53049fa164376173e76960fcdc33ccc
1
+ b1547a601cae891dc3f1a58b66c63e70670d9f3e512c50cb6d26d40568972b94cb2f28887c13ea8d04e2b75b57bba73f8ba4ad780b471009fed3cd4e42b469ae
package/Detox-ios-src.tbz CHANGED
Binary file
package/Detox-ios.tbz CHANGED
Binary file
@@ -1,16 +1,12 @@
1
1
  const { log } = require('../internals');
2
- const DeviceRegistry = require('../src/devices/DeviceRegistry');
3
- const { getDetoxLibraryRootPath } = require('../src/utils/environment');
4
-
2
+ const DeviceRegistry = require('../src/devices/allocation/DeviceRegistry');
5
3
 
6
4
  module.exports.command = 'reset-lock-file';
7
- module.exports.desc = 'Resets all Detox lock files. Useful when you need to run multiple `detox test` commands in parallel with --keepLockFile.';
5
+ module.exports.desc = 'Resets Detox lock file completely - all devices are marked as available after that.';
8
6
 
9
7
  module.exports.handler = async function resetLockFile() {
10
- await Promise.all([
11
- DeviceRegistry.forIOS().reset(),
12
- DeviceRegistry.forAndroid().reset(),
13
- ]);
8
+ const registry = new DeviceRegistry();
9
+ await registry.reset();
14
10
 
15
- log.info(`Cleaned lock files from: ${getDetoxLibraryRootPath()}`);
11
+ log.info(`Cleaned lock file at: ${registry.lockFilePath}`);
16
12
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "detox",
3
3
  "description": "E2E tests and automation for mobile",
4
- "version": "20.12.2",
4
+ "version": "20.13.0",
5
5
  "bin": {
6
6
  "detox": "local-cli/cli.js"
7
7
  },
@@ -137,9 +137,9 @@
137
137
  "src/artifacts/log",
138
138
  "src/artifacts/screenshot",
139
139
  "src/artifacts/video",
140
- "src/devices/allocation/drivers/AllocationDriverBase.js",
141
140
  "src/devices/allocation/drivers/android/emulator/launchEmulatorProcess.js",
142
141
  "src/devices/allocation/drivers/android/emulator/patchAvdSkinConfig.js",
142
+ "src/devices/allocation/.*AllocDriver.js",
143
143
  "src/devices/allocation/drivers/ios",
144
144
  "src/devices/allocation/factories",
145
145
  "src/devices/allocation/factories/drivers",
@@ -154,10 +154,9 @@
154
154
  "src/devices/runtime/drivers/ios",
155
155
  "src/devices/runtime/factories",
156
156
  "src/devices/runtime/factories/drivers",
157
+ "src/devices/validation/EnvironmentValidatorBase.js",
158
+ "src/devices/validation/factories",
157
159
  "src/matchers/factories",
158
- "src/validation/EnvironmentValidatorBase.js",
159
- "src/validation/factories",
160
- "src/validation/ios/IosSimulatorEnvValidator",
161
160
  "src/utils/appdatapath.js",
162
161
  "src/utils/debug.js",
163
162
  "src/utils/environment.js",
@@ -206,5 +205,5 @@
206
205
  "browserslist": [
207
206
  "node 14"
208
207
  ],
209
- "gitHead": "3ed86bf3628cda4673412a4e2c38e32077473851"
208
+ "gitHead": "72e85a2fe078a2a721628255249410423fc5c1ac"
210
209
  }
@@ -70,7 +70,7 @@ class DetoxCircusEnvironment extends NodeEnvironment {
70
70
  await this.initDetox();
71
71
  }
72
72
 
73
- // @ts-ignore
73
+ // @ts-expect-error TS2425
74
74
  async handleTestEvent(event, state) {
75
75
  if (detox.session.unsafe_earlyTeardown) {
76
76
  throw new Error('Detox halted test execution due to an early teardown request');
@@ -33,7 +33,6 @@ class DetoxWorker {
33
33
  onError: this._onEmitError.bind(this),
34
34
  });
35
35
 
36
-
37
36
  /** @type {DetoxInternals.RuntimeConfig['apps']} */
38
37
  this._appsConfig = null;
39
38
  /** @type {DetoxInternals.RuntimeConfig['artifacts']} */
@@ -60,7 +59,6 @@ class DetoxWorker {
60
59
  /** @type {Detox.WebFacade} */
61
60
  this.web = null;
62
61
 
63
- this._deviceAllocator = null;
64
62
  this._deviceCookie = null;
65
63
 
66
64
  this.trace = this._context.trace;
@@ -115,14 +113,13 @@ class DetoxWorker {
115
113
  const {
116
114
  // @ts-ignore
117
115
  envValidatorFactory,
118
- deviceAllocatorFactory,
119
116
  // @ts-ignore
120
117
  artifactsManagerFactory,
121
118
  // @ts-ignore
122
119
  matchersFactory,
123
120
  // @ts-ignore
124
121
  runtimeDeviceFactory,
125
- } = environmentFactory.createFactories(this._deviceConfig);
122
+ } = environmentFactory.createFactories(deviceConfig);
126
123
 
127
124
  const envValidator = envValidatorFactory.createValidator();
128
125
  yield envValidator.validate();
@@ -135,10 +132,7 @@ class DetoxWorker {
135
132
  };
136
133
 
137
134
  this._artifactsManager = artifactsManagerFactory.createArtifactsManager(this._artifactsConfig, commonDeps);
138
- this._deviceAllocator = deviceAllocatorFactory.createDeviceAllocator(commonDeps);
139
- this._deviceCookie = yield this._deviceAllocator.allocate(this._deviceConfig);
140
-
141
- yield this._deviceAllocator.postAllocate(this._deviceCookie);
135
+ this._deviceCookie = yield this._context[symbols.allocateDevice]();
142
136
 
143
137
  this.device = runtimeDeviceFactory.createRuntimeDevice(
144
138
  this._deviceCookie,
@@ -157,6 +151,8 @@ class DetoxWorker {
157
151
  });
158
152
  Object.assign(this, matchers);
159
153
 
154
+ yield this._eventEmitter.emit('bootDevice', { deviceId: this.device.id });
155
+
160
156
  if (behaviorConfig.init.exposeGlobals) {
161
157
  const injectedGlobals = {
162
158
  ...matchers,
@@ -207,11 +203,9 @@ class DetoxWorker {
207
203
  }
208
204
 
209
205
  if (this._deviceCookie) {
210
- const shutdown = this._behaviorConfig ? this._behaviorConfig.cleanup.shutdownDevice : false;
211
- await this._deviceAllocator.free(this._deviceCookie, { shutdown });
206
+ await this._context[symbols.deallocateDevice](this._deviceCookie);
212
207
  }
213
208
 
214
- this._deviceAllocator = null;
215
209
  this._deviceCookie = null;
216
210
  this.device = null;
217
211
  }
@@ -4,7 +4,7 @@ class ArtifactPluginsProvider {
4
4
 
5
5
  class AndroidArtifactPluginsProvider extends ArtifactPluginsProvider {
6
6
  declareArtifactPlugins({ client }) {
7
- const serviceLocator = require('../../servicelocator/android');
7
+ const serviceLocator = require('../../devices/servicelocator/android');
8
8
  const adb = serviceLocator.adb;
9
9
  const devicePathBuilder = serviceLocator.devicePathBuilder;
10
10
 
@@ -34,8 +34,8 @@ class IosArtifactPluginsProvider extends ArtifactPluginsProvider {
34
34
 
35
35
  class IosSimulatorArtifactPluginsProvider extends IosArtifactPluginsProvider {
36
36
  declareArtifactPlugins({ client }) {
37
- const serviceLocator = require('../../servicelocator/ios');
38
- const appleSimUtils = serviceLocator.appleSimUtils;
37
+ const AppleSimUtils = require('../../devices/common/drivers/ios/tools/AppleSimUtils');
38
+ const appleSimUtils = new AppleSimUtils();
39
39
 
40
40
  const SimulatorInstrumentsPlugin = require('../instruments/ios/SimulatorInstrumentsPlugin');
41
41
  const SimulatorLogPlugin = require('../log/ios/SimulatorLogPlugin');
@@ -22,23 +22,6 @@ class SimulatorScreenshotPlugin extends ScreenshotArtifactPlugin {
22
22
  }
23
23
  }
24
24
 
25
- async onBootDevice(event) {
26
- await super.onBootDevice(event);
27
-
28
- if (this.enabled && event.coldBoot) {
29
- await this.appleSimUtils.takeScreenshot(event.deviceId, '/dev/null').catch(() => {
30
- log.debug({}, `
31
- NOTE: For an unknown yet reason, taking the first screenshot is apt
32
- to fail when booting iOS Simulator in a hidden window mode (or on CI).
33
- Detox applies a workaround by taking a dummy screenshot to ensure
34
- that the future ones are going to work fine. This screenshot is not
35
- saved anywhere, and the error above is suppressed for all log levels
36
- except for "debug" and "trace."
37
- `.trim());
38
- });
39
- }
40
- }
41
-
42
25
  async onBeforeUninstallApp(event) {
43
26
  await this.api.requestIdleCallback(async () => {
44
27
  const snapshots = [
@@ -32,6 +32,7 @@ function composeLoggerConfig(opts) {
32
32
  if (!config) return acc;
33
33
  const { options } = config;
34
34
  return _.merge(acc, {
35
+ // @ts-ignore-line
35
36
  options: typeof options === 'function' ? options(acc) : options
36
37
  });
37
38
  },
@@ -1,43 +1,89 @@
1
- // @ts-nocheck
2
- const log = require('../../utils/logger').child({ cat: 'device' });
1
+ /**
2
+ * @typedef {import('./drivers/AllocationDriverBase').AllocationDriverBase} AllocationDriverBase
3
+ * @typedef {import('./drivers/AllocationDriverBase').DeallocOptions} DeallocOptions
4
+ * @typedef {import('../common/drivers/DeviceCookie').DeviceCookie} DeviceCookie
5
+ */
6
+
7
+ const log = require('../../utils/logger').child({ cat: 'device,device-allocation' });
3
8
  const traceMethods = require('../../utils/traceMethods');
4
9
 
5
10
  class DeviceAllocator {
6
11
  /**
7
- * @param allocationDriver { AllocationDriverBase }
12
+ * @param {AllocationDriverBase} allocationDriver
8
13
  */
9
14
  constructor(allocationDriver) {
10
15
  this._driver = allocationDriver;
11
- traceMethods(log, this, ['allocate', 'postAllocate', 'free']);
16
+ this._counter = 0;
17
+ this._ids = new Map();
18
+ traceMethods(log, this, ['init', 'cleanup', 'emergencyCleanup']);
12
19
  }
13
20
 
14
21
  /**
15
- * @param deviceConfig { Object }
16
- * @return {Promise<DeviceCookie>}
22
+ * @returns {Promise<void>}
17
23
  */
18
- allocate(deviceConfig) {
19
- return this._driver.allocate(deviceConfig);
24
+ async init() {
25
+ if (typeof this._driver.init === 'function') {
26
+ await this._driver.init();
27
+ }
20
28
  }
21
29
 
22
30
  /**
23
- * @param {DeviceCookie} deviceCookie
24
- * @return {Promise<unknown>}
31
+ * @param {Detox.DetoxDeviceConfig} deviceConfig
32
+ * @returns {Promise<DeviceCookie>}
25
33
  */
26
- postAllocate(deviceCookie) {
27
- if (typeof this._driver.postAllocate !== 'function') {
28
- return Promise.resolve();
29
- }
34
+ async allocate(deviceConfig) {
35
+ const tid = this._counter++;
36
+ return await log.trace.complete({ data: deviceConfig, id: tid }, 'allocate', async () => {
37
+ const cookie = await this._driver.allocate(deviceConfig);
38
+ log.debug({ data: cookie }, `settled on ${cookie.name || cookie.id}`);
39
+ this._ids.set(cookie.id, tid);
40
+ return cookie;
41
+ });
42
+ }
30
43
 
31
- return this._driver.postAllocate(deviceCookie);
44
+ /**
45
+ * @param {DeviceCookie} cookie
46
+ * @returns {Promise<DeviceCookie>}
47
+ */
48
+ async postAllocate(cookie) {
49
+ const tid = this._ids.get(cookie.id);
50
+ return await log.trace.complete({ data: cookie, id: tid }, `post-allocate: ${cookie.id}`, async () => {
51
+ const updatedCookie = typeof this._driver.postAllocate === 'function'
52
+ ? await this._driver.postAllocate(cookie)
53
+ : undefined;
54
+
55
+ return updatedCookie || cookie;
56
+ });
32
57
  }
33
58
 
34
59
  /**
35
- * @param cookie { DeviceCookie }
36
- * @param options { DeallocOptions }
37
- * @return {Promise<void>}
60
+ * @param {DeviceCookie} cookie
61
+ * @param {DeallocOptions} options
62
+ * @returns {Promise<void>}
38
63
  */
39
- free(cookie, options) {
40
- return this._driver.free(cookie, options);
64
+ async free(cookie, options = {}) {
65
+ const tid = this._ids.get(cookie.id);
66
+ await log.trace.complete({ data: options, id: tid }, `free: ${cookie.id}`, async () => {
67
+ await this._driver.free(cookie, options);
68
+ });
69
+ }
70
+
71
+ /**
72
+ * @returns {Promise<void>}
73
+ */
74
+ async cleanup() {
75
+ if (typeof this._driver.cleanup === 'function') {
76
+ await this._driver.cleanup();
77
+ }
78
+ }
79
+
80
+ /**
81
+ * @returns {void}
82
+ */
83
+ emergencyCleanup() {
84
+ if (typeof this._driver.emergencyCleanup === 'function') {
85
+ this._driver.emergencyCleanup();
86
+ }
41
87
  }
42
88
  }
43
89
 
@@ -0,0 +1,44 @@
1
+ class DeviceListReadonly {
2
+ constructor(devices = []) {
3
+ this._devices = new Map(devices.map(device => [device.id, device]));
4
+ }
5
+
6
+ concat(other) {
7
+ return new DeviceListReadonly([...this, ...other]);
8
+ }
9
+
10
+ getIds() {
11
+ return [...this._devices.keys()];
12
+ }
13
+
14
+ [Symbol.iterator]() {
15
+ return this._devices.values();
16
+ }
17
+
18
+ /**
19
+ * @param {string} deviceId
20
+ * @returns {boolean}
21
+ */
22
+ includes(deviceId) {
23
+ return this._devices.has(deviceId);
24
+ }
25
+ }
26
+
27
+ class DeviceList extends DeviceListReadonly {
28
+ filter(predicate) {
29
+ return new DeviceListReadonly([...this].filter(predicate));
30
+ }
31
+
32
+ add(deviceId, data) {
33
+ this._devices.set(deviceId, {
34
+ id: deviceId,
35
+ ...data,
36
+ });
37
+ }
38
+
39
+ delete(deviceId) {
40
+ this._devices.delete(deviceId);
41
+ }
42
+ }
43
+
44
+ module.exports = DeviceList;
@@ -0,0 +1,189 @@
1
+ const ExclusiveLockfile = require('../../utils/ExclusiveLockfile');
2
+ const PIDService = require('../../utils/PIDService');
3
+ const { getDeviceRegistryPath } = require('../../utils/environment');
4
+ const safeAsync = require('../../utils/safeAsync');
5
+
6
+ const DeviceList = require('./DeviceList');
7
+
8
+ const readOptions = {
9
+ encoding: 'utf8',
10
+ };
11
+
12
+ class DeviceRegistry {
13
+ constructor({
14
+ lockfilePath = getDeviceRegistryPath(),
15
+ sessionId = '',
16
+ pidService = new PIDService(),
17
+ } = {}) {
18
+ /***
19
+ * @private
20
+ * @type {string}
21
+ */
22
+ this._lockfilePath = lockfilePath;
23
+ /***
24
+ * @private
25
+ * @type {string}
26
+ */
27
+ this._sessionId = sessionId;
28
+ /***
29
+ * @private
30
+ */
31
+ this._pidService = pidService;
32
+ /***
33
+ * @protected
34
+ * @type {ExclusiveLockfile}
35
+ */
36
+ this._lockfile = new ExclusiveLockfile(this._lockfilePath, {
37
+ getInitialState: this._getInitialLockFileState.bind(this),
38
+ readOptions,
39
+ });
40
+ }
41
+
42
+ get lockFilePath() {
43
+ return this._lockfilePath;
44
+ }
45
+
46
+ /**
47
+ * Safety method to ensure that there are no remains of previously crashed Detox sessions.
48
+ */
49
+ async reset() {
50
+ await this._lockfile.exclusively(() => {
51
+ const empty = this._getInitialLockFileState();
52
+ this._lockfile.write(empty);
53
+ });
54
+ }
55
+
56
+ /***
57
+ * @param {string|Function} getDeviceId
58
+ * @returns {Promise<string>}
59
+ */
60
+ async registerDevice(getDeviceId) {
61
+ return this._lockfile.exclusively(async () => {
62
+ const deviceId = await safeAsync(getDeviceId);
63
+ if (deviceId) {
64
+ this._upsertDevice(deviceId, {
65
+ busy: true,
66
+ sessionId: this._sessionId,
67
+ pid: this._pidService.getPid(),
68
+ });
69
+ }
70
+ return deviceId;
71
+ });
72
+ }
73
+
74
+ /***
75
+ * @param {string|Function} getDeviceId
76
+ * @returns {Promise<string>}
77
+ */
78
+ async releaseDevice(getDeviceId) {
79
+ return this._lockfile.exclusively(async () => {
80
+ const deviceId = await safeAsync(getDeviceId);
81
+ if (deviceId) {
82
+ this._upsertDevice(deviceId, {
83
+ busy: false,
84
+ sessionId: this._sessionId,
85
+ pid: this._pidService.getPid(),
86
+ });
87
+ }
88
+ return deviceId;
89
+ });
90
+ }
91
+
92
+ /***
93
+ * @param {string|Function} getDeviceId
94
+ * @returns {Promise<void>}
95
+ */
96
+ async unregisterDevice(getDeviceId) {
97
+ await this._lockfile.exclusively(async () => {
98
+ const deviceId = await safeAsync(getDeviceId);
99
+ if (deviceId) {
100
+ this._deleteDevice(deviceId);
101
+ }
102
+ });
103
+ }
104
+
105
+ async unregisterSessionDevices() {
106
+ await this._lockfile.exclusively(async () => {
107
+ const allDevices = this._getRegisteredDevices();
108
+ const sessionDevices = allDevices.filter(device => device.sessionId === this._sessionId);
109
+ for (const id of sessionDevices.getIds()) {
110
+ allDevices.delete(id);
111
+ }
112
+ this._lockfile.write([...allDevices]);
113
+ });
114
+ }
115
+
116
+ async unregisterZombieDevices() {
117
+ await this._lockfile.exclusively(async () => {
118
+ const allDevices = this._getRegisteredDevices();
119
+ const zombieDevices = allDevices.filter(device => {
120
+ return device.sessionId !== this._sessionId && !this._pidService.isAlive(device.pid);
121
+ });
122
+
123
+ for (const id of zombieDevices.getIds()) {
124
+ allDevices.delete(id);
125
+ }
126
+ this._lockfile.write([...allDevices]);
127
+ });
128
+ }
129
+
130
+ /**
131
+ * @returns {Promise<DeviceList>}
132
+ */
133
+ async readSessionDevices() {
134
+ let devices;
135
+ await this._lockfile.exclusively(() => {
136
+ devices = this._getSessionDevicesSync();
137
+ });
138
+ return devices;
139
+ }
140
+
141
+ getTakenDevicesSync() {
142
+ const allDevices = this._getRegisteredDevices();
143
+ const busyDevices = allDevices.filter(device => device.busy);
144
+ const externalDevices = allDevices.filter(device => device.sessionId !== this._sessionId);
145
+ return busyDevices.concat(externalDevices);
146
+ }
147
+
148
+ /***
149
+ * @private
150
+ */
151
+ _getInitialLockFileState() {
152
+ return [];
153
+ }
154
+
155
+ /**
156
+ * @private
157
+ */
158
+ _upsertDevice(deviceId, data) {
159
+ const devices = this._getRegisteredDevices();
160
+ devices.add(deviceId, data);
161
+ this._lockfile.write([...devices]);
162
+ }
163
+
164
+ /**
165
+ * @private
166
+ */
167
+ _deleteDevice(deviceId) {
168
+ const devices = this._getRegisteredDevices();
169
+ devices.delete(deviceId);
170
+ this._lockfile.write([...devices]);
171
+ }
172
+
173
+ /***
174
+ * @private
175
+ * @returns {DeviceList}
176
+ */
177
+ _getRegisteredDevices() {
178
+ const devices = this._lockfile.read();
179
+ return new DeviceList(devices);
180
+ }
181
+
182
+ _getSessionDevicesSync() {
183
+ const devices = this._getRegisteredDevices();
184
+ const sessionDevices = devices.filter(device => device.sessionId === this._sessionId);
185
+ return sessionDevices;
186
+ }
187
+ }
188
+
189
+ module.exports = DeviceRegistry;
@@ -0,0 +1,15 @@
1
+ /* eslint-disable import/no-unresolved,node/no-missing-import,node/no-unsupported-features/es-syntax */
2
+ import { DeviceCookie } from '../../common/drivers/DeviceCookie';
3
+
4
+ export interface DeallocOptions {
5
+ shutdown?: boolean;
6
+ }
7
+
8
+ export interface AllocationDriverBase {
9
+ init?(): Promise<void>;
10
+ allocate(deviceConfig: any): Promise<DeviceCookie>;
11
+ postAllocate?(deviceCookie: DeviceCookie): Promise<DeviceCookie | void>;
12
+ free(cookie: DeviceCookie, options: DeallocOptions): Promise<void>;
13
+ cleanup?(): Promise<void>;
14
+ emergencyCleanup?(): void;
15
+ }