detox 20.11.4 → 20.12.0-smoke.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (110) hide show
  1. package/Detox-android/com/wix/detox/{20.11.4/detox-20.11.4-javadoc.jar → 20.12.0-smoke.0/detox-20.12.0-smoke.0-javadoc.jar} +0 -0
  2. package/Detox-android/com/wix/detox/20.12.0-smoke.0/detox-20.12.0-smoke.0-javadoc.jar.md5 +1 -0
  3. package/Detox-android/com/wix/detox/20.12.0-smoke.0/detox-20.12.0-smoke.0-javadoc.jar.sha1 +1 -0
  4. package/Detox-android/com/wix/detox/20.12.0-smoke.0/detox-20.12.0-smoke.0-javadoc.jar.sha256 +1 -0
  5. package/Detox-android/com/wix/detox/20.12.0-smoke.0/detox-20.12.0-smoke.0-javadoc.jar.sha512 +1 -0
  6. package/Detox-android/com/wix/detox/{20.11.4/detox-20.11.4-sources.jar → 20.12.0-smoke.0/detox-20.12.0-smoke.0-sources.jar} +0 -0
  7. package/Detox-android/com/wix/detox/20.12.0-smoke.0/detox-20.12.0-smoke.0-sources.jar.md5 +1 -0
  8. package/Detox-android/com/wix/detox/20.12.0-smoke.0/detox-20.12.0-smoke.0-sources.jar.sha1 +1 -0
  9. package/Detox-android/com/wix/detox/20.12.0-smoke.0/detox-20.12.0-smoke.0-sources.jar.sha256 +1 -0
  10. package/Detox-android/com/wix/detox/20.12.0-smoke.0/detox-20.12.0-smoke.0-sources.jar.sha512 +1 -0
  11. package/Detox-android/com/wix/detox/{20.11.4/detox-20.11.4.pom → 20.12.0-smoke.0/detox-20.12.0-smoke.0.pom} +1 -1
  12. package/Detox-android/com/wix/detox/20.12.0-smoke.0/detox-20.12.0-smoke.0.pom.md5 +1 -0
  13. package/Detox-android/com/wix/detox/20.12.0-smoke.0/detox-20.12.0-smoke.0.pom.sha1 +1 -0
  14. package/Detox-android/com/wix/detox/20.12.0-smoke.0/detox-20.12.0-smoke.0.pom.sha256 +1 -0
  15. package/Detox-android/com/wix/detox/20.12.0-smoke.0/detox-20.12.0-smoke.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 +6 -6
  25. package/src/DetoxWorker.js +5 -9
  26. package/src/artifacts/providers/index.js +3 -3
  27. package/src/artifacts/screenshot/SimulatorScreenshotPlugin.js +0 -17
  28. package/src/devices/allocation/DeviceAllocator.js +50 -15
  29. package/src/devices/allocation/DeviceList.js +44 -0
  30. package/src/devices/allocation/DeviceRegistry.js +186 -0
  31. package/src/devices/allocation/drivers/AllocationDriverBase.js +10 -4
  32. package/src/devices/{common/drivers/android/tools → allocation/drivers/android}/FreeDeviceFinder.js +11 -10
  33. package/src/devices/allocation/drivers/android/attached/AttachedAndroidAllocDriver.js +7 -6
  34. package/src/devices/allocation/drivers/android/emulator/EmulatorAllocDriver.js +108 -26
  35. package/src/devices/allocation/drivers/android/emulator/EmulatorLauncher.js +33 -43
  36. package/src/devices/allocation/drivers/android/emulator/FreeEmulatorFinder.js +1 -1
  37. package/src/devices/allocation/drivers/android/emulator/FreePortFinder.js +16 -0
  38. package/src/devices/allocation/drivers/android/emulator/launchEmulatorProcess.js +3 -3
  39. package/src/devices/allocation/drivers/android/genycloud/GenyAllocDriver.js +87 -27
  40. package/src/devices/allocation/drivers/android/genycloud/GenyInstanceLauncher.js +39 -28
  41. package/src/devices/allocation/drivers/android/genycloud/GenyRegistry.js +93 -0
  42. package/src/devices/allocation/drivers/android/genycloud/services/GenyInstanceLifecycleService.js +24 -0
  43. package/src/devices/{common → allocation}/drivers/android/genycloud/services/GenyRecipesService.js +1 -1
  44. package/src/devices/{common → allocation}/drivers/android/genycloud/services/dto/GenyInstance.js +6 -1
  45. package/src/devices/allocation/drivers/ios/SimulatorAllocDriver.js +70 -40
  46. package/src/devices/allocation/drivers/ios/SimulatorLauncher.js +11 -7
  47. package/src/devices/allocation/drivers/ios/SimulatorQuery.js +24 -0
  48. package/src/devices/allocation/factories/android.js +29 -35
  49. package/src/devices/allocation/factories/ios.js +7 -5
  50. package/src/devices/common/drivers/android/emulator/exec/EmulatorExec.js +17 -5
  51. package/src/devices/common/drivers/android/exec/ADB.js +1 -0
  52. package/src/devices/common/drivers/ios/tools/AppleSimUtils.js +1 -1
  53. package/src/devices/cookies/AndroidDeviceCookie.js +4 -0
  54. package/src/devices/cookies/GenycloudEmulatorCookie.js +3 -5
  55. package/src/devices/cookies/IosSimulatorCookie.js +4 -0
  56. package/src/devices/runtime/drivers/android/genycloud/GenyCloudDriver.js +2 -2
  57. package/src/devices/runtime/factories/android.js +1 -1
  58. package/src/devices/runtime/factories/ios.js +3 -2
  59. package/src/{servicelocator → devices/servicelocator}/android/emulatorServiceLocator.js +1 -1
  60. package/src/devices/servicelocator/android/genycloudServiceLocator.js +17 -0
  61. package/src/devices/servicelocator/android/index.js +23 -0
  62. package/src/{validation → devices/validation}/android/GenycloudEnvValidator.js +2 -2
  63. package/src/{validation → devices/validation}/factories/index.js +1 -1
  64. package/src/{validation → devices/validation}/ios/IosSimulatorEnvValidator.js +2 -2
  65. package/src/environmentFactory.js +1 -11
  66. package/src/ipc/IPCClient.js +17 -1
  67. package/src/ipc/IPCServer.js +25 -1
  68. package/src/realms/DetoxContext.js +6 -0
  69. package/src/realms/DetoxPrimaryContext.js +42 -42
  70. package/src/realms/DetoxSecondaryContext.js +19 -0
  71. package/src/realms/symbols.js +4 -0
  72. package/src/utils/PIDService.js +27 -0
  73. package/src/utils/environment.js +8 -15
  74. package/src/utils/errorUtils.js +2 -2
  75. package/Detox-android/com/wix/detox/20.11.4/detox-20.11.4-javadoc.jar.md5 +0 -1
  76. package/Detox-android/com/wix/detox/20.11.4/detox-20.11.4-javadoc.jar.sha1 +0 -1
  77. package/Detox-android/com/wix/detox/20.11.4/detox-20.11.4-javadoc.jar.sha256 +0 -1
  78. package/Detox-android/com/wix/detox/20.11.4/detox-20.11.4-javadoc.jar.sha512 +0 -1
  79. package/Detox-android/com/wix/detox/20.11.4/detox-20.11.4-sources.jar.md5 +0 -1
  80. package/Detox-android/com/wix/detox/20.11.4/detox-20.11.4-sources.jar.sha1 +0 -1
  81. package/Detox-android/com/wix/detox/20.11.4/detox-20.11.4-sources.jar.sha256 +0 -1
  82. package/Detox-android/com/wix/detox/20.11.4/detox-20.11.4-sources.jar.sha512 +0 -1
  83. package/Detox-android/com/wix/detox/20.11.4/detox-20.11.4.pom.md5 +0 -1
  84. package/Detox-android/com/wix/detox/20.11.4/detox-20.11.4.pom.sha1 +0 -1
  85. package/Detox-android/com/wix/detox/20.11.4/detox-20.11.4.pom.sha256 +0 -1
  86. package/Detox-android/com/wix/detox/20.11.4/detox-20.11.4.pom.sha512 +0 -1
  87. package/src/devices/DeviceRegistry.js +0 -176
  88. package/src/devices/allocation/drivers/android/attached/AttachedAndroidLauncher.js +0 -13
  89. package/src/devices/allocation/drivers/android/emulator/EmulatorAllocationHelper.js +0 -72
  90. package/src/devices/allocation/drivers/android/genycloud/GenyDeviceRegistryFactory.js +0 -16
  91. package/src/devices/allocation/drivers/android/genycloud/GenyInstanceAllocationHelper.js +0 -65
  92. package/src/devices/common/drivers/DeviceAllocationHelper.js +0 -20
  93. package/src/devices/common/drivers/DeviceLauncher.js +0 -19
  94. package/src/devices/common/drivers/android/genycloud/services/GenyInstanceLifecycleService.js +0 -25
  95. package/src/devices/common/drivers/android/genycloud/services/GenyInstanceLookupService.js +0 -38
  96. package/src/devices/common/drivers/android/genycloud/services/GenyInstanceNaming.js +0 -14
  97. package/src/devices/lifecycle/GenyGlobalLifecycleHandler.js +0 -71
  98. package/src/devices/lifecycle/factories/GenyGlobalLifecycleHandlerFactory.js +0 -18
  99. package/src/servicelocator/android/genycloudServiceLocator.js +0 -21
  100. package/src/servicelocator/android/index.js +0 -25
  101. package/src/servicelocator/ios.js +0 -7
  102. /package/Detox-android/com/wix/detox/{20.11.4/detox-20.11.4.aar → 20.12.0-smoke.0/detox-20.12.0-smoke.0.aar} +0 -0
  103. /package/Detox-android/com/wix/detox/{20.11.4/detox-20.11.4.aar.md5 → 20.12.0-smoke.0/detox-20.12.0-smoke.0.aar.md5} +0 -0
  104. /package/Detox-android/com/wix/detox/{20.11.4/detox-20.11.4.aar.sha1 → 20.12.0-smoke.0/detox-20.12.0-smoke.0.aar.sha1} +0 -0
  105. /package/Detox-android/com/wix/detox/{20.11.4/detox-20.11.4.aar.sha256 → 20.12.0-smoke.0/detox-20.12.0-smoke.0.aar.sha256} +0 -0
  106. /package/Detox-android/com/wix/detox/{20.11.4/detox-20.11.4.aar.sha512 → 20.12.0-smoke.0/detox-20.12.0-smoke.0.aar.sha512} +0 -0
  107. /package/src/devices/{common → allocation}/drivers/android/genycloud/exec/GenyCloudExec.js +0 -0
  108. /package/src/devices/{common → allocation}/drivers/android/genycloud/services/GenyAuthService.js +0 -0
  109. /package/src/devices/{common → allocation}/drivers/android/genycloud/services/dto/GenyRecipe.js +0 -0
  110. /package/src/{validation → devices/validation}/EnvironmentValidatorBase.js +0 -0
@@ -0,0 +1,93 @@
1
+ const { DetoxInternalError } = require('../../../../../errors');
2
+
3
+ class GenyRegistry {
4
+ constructor() {
5
+ /** @type {Map<string, import('./services/dto/GenyRecipe')>} */
6
+ this._recipes = new Map();
7
+ /** @type {Map<string, import('./services/dto/GenyInstance')>} */
8
+ this._freeInstances = new Map();
9
+ /** @type {Map<string, import('./services/dto/GenyInstance')>} */
10
+ this._busyInstances = new Map();
11
+ /** @type {Set<string>} */
12
+ this._newInstances = new Set();
13
+ }
14
+
15
+ getInstances() {
16
+ return [...this._freeInstances.values(), ...this._busyInstances.values()];
17
+ }
18
+
19
+ /**
20
+ * @param {import('./services/dto/GenyInstance')} instance
21
+ * @param {import('./services/dto/GenyRecipe')} recipe
22
+ */
23
+ addInstance(instance, recipe) {
24
+ this._recipes.set(instance.uuid, recipe);
25
+ this._busyInstances.set(instance.uuid, instance);
26
+ this._newInstances.add(instance.uuid);
27
+ }
28
+
29
+ /** @param {import('./services/dto/GenyInstance')} instance */
30
+ pollNewInstance(instance) {
31
+ const result = this._newInstances.has(instance.uuid);
32
+ this._newInstances.delete(instance.uuid);
33
+ return result;
34
+ }
35
+
36
+ /** @param {import('./services/dto/GenyInstance')} instance */
37
+ updateInstance(instance) {
38
+ if (this._freeInstances.has(instance.uuid)) {
39
+ this._freeInstances.set(instance.uuid, instance);
40
+ }
41
+
42
+ if (this._busyInstances.has(instance.uuid)) {
43
+ this._busyInstances.set(instance.uuid, instance);
44
+ }
45
+ }
46
+
47
+ /** @param {import('./services/dto/GenyInstance')} instance */
48
+ removeInstance(instance) {
49
+ this._freeInstances.delete(instance.uuid);
50
+ this._busyInstances.delete(instance.uuid);
51
+ this._newInstances.delete(instance.uuid);
52
+ this._recipes.delete(instance.uuid);
53
+ }
54
+
55
+ /** @param {import('./services/dto/GenyInstance')} instance */
56
+ markAsBusy({ uuid }) {
57
+ if (this._busyInstances.has(uuid)) {
58
+ return;
59
+ }
60
+
61
+ const instance = this._freeInstances.get(uuid);
62
+ if (!instance) {
63
+ throw new DetoxInternalError(`Cannot mark an unknown instance ${uuid} as busy`);
64
+ }
65
+
66
+ this._busyInstances.set(uuid, instance);
67
+ this._freeInstances.delete(uuid);
68
+ return instance;
69
+ }
70
+
71
+ /** @param {import('./services/dto/GenyInstance')} instance */
72
+ markAsFree({ uuid }) {
73
+ const instance = this._busyInstances.get(uuid);
74
+ if (!instance) {
75
+ throw new DetoxInternalError(`Cannot mark an unknown instance ${uuid} as free`);
76
+ }
77
+
78
+ this._busyInstances.delete(uuid);
79
+ this._freeInstances.set(uuid, instance);
80
+ return instance;
81
+ }
82
+
83
+ findFreeInstance(recipe) {
84
+ for (const instance of this._freeInstances.values()) {
85
+ const aRecipe = this._recipes.get(instance.uuid);
86
+ if (recipe.uuid === aRecipe.uuid) {
87
+ return this.markAsBusy(instance);
88
+ }
89
+ }
90
+ }
91
+ }
92
+
93
+ module.exports = GenyRegistry;
@@ -0,0 +1,24 @@
1
+ const Instance = require('./dto/GenyInstance');
2
+
3
+ class GenyInstanceLifecycleService {
4
+ constructor(genyCloudExec) {
5
+ this._genyCloudExec = genyCloudExec;
6
+ }
7
+
8
+ async createInstance(recipeUUID, instanceName) {
9
+ const result = await this._genyCloudExec.startInstance(recipeUUID, instanceName);
10
+ return new Instance(result.instance);
11
+ }
12
+
13
+ async adbConnectInstance(instanceUUID) {
14
+ const result = (await this._genyCloudExec.adbConnect(instanceUUID));
15
+ return new Instance(result.instance);
16
+ }
17
+
18
+ async deleteInstance(instanceUUID) {
19
+ const result = await this._genyCloudExec.stopInstance(instanceUUID);
20
+ return new Instance(result.instance);
21
+ }
22
+ }
23
+
24
+ module.exports = GenyInstanceLifecycleService;
@@ -1,6 +1,6 @@
1
1
  const logger = require('../../../../../../utils/logger').child({ cat: 'device' });
2
2
 
3
- const Recipe = require('./dto/GenyRecipe');
3
+ const Recipe = require('./dto/GenyRecipe');
4
4
 
5
5
  class GenyRecipesService {
6
6
  constructor(genyCloudExec) {
@@ -59,7 +59,12 @@ class GenyInstance {
59
59
  }
60
60
 
61
61
  toString() {
62
- return `GenyCloud:${this.name} (${this.uuid} ${this.adbName})`;
62
+ const description = [
63
+ this.uuid,
64
+ this.adbName
65
+ ].filter(Boolean).join('/');
66
+
67
+ return `${this.name} (${description})`;
63
68
  }
64
69
  }
65
70
 
@@ -2,21 +2,31 @@
2
2
  const _ = require('lodash');
3
3
 
4
4
  const DetoxRuntimeError = require('../../../../errors/DetoxRuntimeError');
5
+ const log = require('../../../../utils/logger').child({ cat: 'device,device-allocation' });
5
6
  const IosSimulatorCookie = require('../../../cookies/IosSimulatorCookie');
6
7
  const AllocationDriverBase = require('../AllocationDriverBase');
7
8
 
9
+ const SimulatorQuery = require('./SimulatorQuery');
10
+
8
11
  class SimulatorAllocDriver extends AllocationDriverBase {
9
12
  /**
13
+ * @param deviceRegistry { DeviceRegistry }
14
+ * @param detoxConfig { DetoxInternals.RuntimeConfig }
10
15
  * @param deviceRegistry { DeviceRegistry }
11
16
  * @param applesimutils { AppleSimUtils }
12
17
  * @param simulatorLauncher { SimulatorLauncher }
13
18
  */
14
- constructor({ deviceRegistry, applesimutils, simulatorLauncher }) {
19
+ constructor({ detoxConfig, deviceRegistry, applesimutils, simulatorLauncher }) {
15
20
  super();
16
21
  this._deviceRegistry = deviceRegistry;
17
22
  this._applesimutils = applesimutils;
18
23
  this._simulatorLauncher = simulatorLauncher;
19
24
  this._launchInfo = {};
25
+ this._shouldShutdown = detoxConfig.behavior.cleanup.shutdownDevice;
26
+ }
27
+
28
+ async init() {
29
+ await this._deviceRegistry.unregisterZombieDevices();
20
30
  }
21
31
 
22
32
  /**
@@ -24,16 +34,15 @@ class SimulatorAllocDriver extends AllocationDriverBase {
24
34
  * @return {Promise<IosSimulatorCookie>}
25
35
  */
26
36
  async allocate(deviceConfig) {
27
- const deviceQuery = this._adaptQuery(deviceConfig.device);
37
+ const deviceQuery = new SimulatorQuery(deviceConfig.device);
28
38
 
29
39
  // TODO Delegate this onto a well tested allocator class
30
- const udid = await this._deviceRegistry.allocateDevice(async () => {
40
+ const udid = await this._deviceRegistry.registerDevice(async () => {
31
41
  return await this._findOrCreateDevice(deviceQuery);
32
42
  });
33
43
 
34
- const deviceComment = this._commentDevice(deviceQuery);
35
44
  if (!udid) {
36
- throw new DetoxRuntimeError(`Failed to find device matching ${deviceComment}`);
45
+ throw new DetoxRuntimeError(`Failed to find device matching ${deviceQuery.getDeviceComment()}`);
37
46
  }
38
47
 
39
48
  this._launchInfo[udid] = { deviceConfig };
@@ -58,21 +67,40 @@ class SimulatorAllocDriver extends AllocationDriverBase {
58
67
  async free(cookie, options = {}) {
59
68
  const { udid } = cookie;
60
69
 
61
- await this._deviceRegistry.disposeDevice(udid);
62
-
63
70
  if (options.shutdown) {
71
+ await this._doShutdown(udid);
72
+ await this._deviceRegistry.unregisterDevice(udid);
73
+ } else {
74
+ await this._deviceRegistry.releaseDevice(udid);
75
+ }
76
+ }
77
+
78
+ async cleanup() {
79
+ if (this._shouldShutdown) {
80
+ const sessionDevices = await this._deviceRegistry.readSessionDevices();
81
+ const shutdownPromises = sessionDevices.getIds().map((udid) => this._doShutdown(udid));
82
+ await Promise.all(shutdownPromises);
83
+ }
84
+
85
+ await this._deviceRegistry.unregisterSessionDevices();
86
+ }
87
+
88
+ /**
89
+ * @param {string} udid
90
+ * @returns {Promise<void>}
91
+ * @private
92
+ */
93
+ async _doShutdown(udid) {
94
+ try {
64
95
  await this._simulatorLauncher.shutdown(udid);
96
+ } catch (err) {
97
+ log.warn({ err }, `Failed to shutdown simulator ${udid}`);
65
98
  }
66
99
  }
67
100
 
68
101
  /***
69
102
  * @private
70
- * @param deviceQuery {{
71
- * byId?: string;
72
- * byName?: string;
73
- * byType?: string;
74
- * byOS?: string;
75
- * }}
103
+ * @param {SimulatorQuery} deviceQuery
76
104
  * @returns {Promise<String>}
77
105
  */
78
106
  async _findOrCreateDevice(deviceQuery) {
@@ -83,6 +111,7 @@ class SimulatorAllocDriver extends AllocationDriverBase {
83
111
  if (_.isEmpty(free)) {
84
112
  const prototypeDevice = taken[0];
85
113
  udid = this._applesimutils.create(prototypeDevice);
114
+ await this._runScreenshotWorkaround(udid);
86
115
  } else {
87
116
  udid = free[0].udid;
88
117
  }
@@ -90,11 +119,30 @@ class SimulatorAllocDriver extends AllocationDriverBase {
90
119
  return udid;
91
120
  }
92
121
 
122
+ async _runScreenshotWorkaround(udid) {
123
+ await this._applesimutils.takeScreenshot(udid, '/dev/null').catch(() => {
124
+ log.debug({}, `
125
+ NOTE: For an unknown yet reason, taking the first screenshot is apt
126
+ to fail when booting iOS Simulator in a hidden window mode (or on CI).
127
+ Detox applies a workaround by taking a dummy screenshot to ensure
128
+ that the future ones are going to work fine. This screenshot is not
129
+ saved anywhere, and the error above is suppressed for all log levels
130
+ except for "debug" and "trace."
131
+ `.trim());
132
+ });
133
+ }
134
+
135
+ /**
136
+ * @private
137
+ * @param {SimulatorQuery} deviceQuery
138
+ */
93
139
  async _groupDevicesByStatus(deviceQuery) {
94
140
  const searchResults = await this._queryDevices(deviceQuery);
95
- const { rawDevices: takenDevices } = this._deviceRegistry.getRegisteredDevices();
96
- const takenUDIDs = new Set(_.map(takenDevices, 'id'));
97
- const { taken, free } = _.groupBy(searchResults, ({ udid }) => takenUDIDs.has(udid) ? 'taken' : 'free');
141
+ const takenDevices = this._deviceRegistry.getTakenDevicesSync();
142
+
143
+ const { taken, free } = _.groupBy(searchResults, ({ udid }) => {
144
+ return takenDevices.includes(udid) ? 'taken' : 'free';
145
+ });
98
146
 
99
147
  const targetOS = _.get(taken, '0.os.identifier');
100
148
  const isMatching = targetOS && { os: { identifier: targetOS } };
@@ -105,43 +153,25 @@ class SimulatorAllocDriver extends AllocationDriverBase {
105
153
  };
106
154
  }
107
155
 
156
+ /**
157
+ * @private
158
+ * @param {SimulatorQuery} deviceQuery
159
+ */
108
160
  async _queryDevices(deviceQuery) {
109
161
  const result = await this._applesimutils.list(
110
162
  deviceQuery,
111
- `Searching for device ${this._commentQuery(deviceQuery)} ...`
163
+ `Searching for device ${deviceQuery} ...`
112
164
  );
113
165
 
114
166
  if (_.isEmpty(result)) {
115
167
  throw new DetoxRuntimeError({
116
- message: `Failed to find a device ${this._commentQuery(deviceQuery)}`,
168
+ message: `Failed to find a device ${deviceQuery}`,
117
169
  hint: `Run 'applesimutils --list' to list your supported devices. ` +
118
170
  `It is advised only to specify a device type, e.g., "iPhone Xʀ" and avoid explicit search by OS version.`
119
171
  });
120
172
  }
121
173
  return result;
122
174
  }
123
-
124
- _adaptQuery({ id, name, os, type }) {
125
- return _.omitBy({
126
- byId: id,
127
- byName: name,
128
- byOS: os,
129
- byType: type,
130
- }, _.isUndefined);
131
- }
132
-
133
- _commentQuery({ byId, byName, byOS, byType }) {
134
- return _.compact([
135
- byId && `by UDID = ${JSON.stringify(byId)}`,
136
- byName && `by name = ${JSON.stringify(byName)}`,
137
- byType && `by type = ${JSON.stringify(byType)}`,
138
- byOS && `by OS = ${JSON.stringify(byOS)}`,
139
- ]).join(' and ');
140
- }
141
-
142
- _commentDevice({ byId, byName, byOS, byType }) {
143
- return byId || _.compact([byName, byType, byOS]).join(', ');
144
- }
145
175
  }
146
176
 
147
177
  module.exports = SimulatorAllocDriver;
@@ -1,20 +1,24 @@
1
- const DeviceLauncher = require('../../../common/drivers/DeviceLauncher');
2
-
3
- class SimulatorLauncher extends DeviceLauncher {
1
+ class SimulatorLauncher {
4
2
  constructor({ applesimutils, eventEmitter }) {
5
- super(eventEmitter);
6
3
  this._applesimutils = applesimutils;
4
+ this._eventEmitter = eventEmitter;
7
5
  }
8
6
 
9
7
  async launch(udid, type, bootArgs, headless) {
10
8
  const coldBoot = await this._applesimutils.boot(udid, bootArgs, headless);
11
- await this._notifyBootEvent(udid, type, coldBoot, headless);
9
+ return coldBoot;
12
10
  }
13
11
 
14
12
  async shutdown(udid) {
15
- await this._notifyPreShutdown(udid);
13
+ if (this._eventEmitter) {
14
+ await this._eventEmitter.emit('beforeShutdownDevice', { deviceId: udid });
15
+ }
16
+
16
17
  await this._applesimutils.shutdown(udid);
17
- await this._notifyShutdownCompleted(udid);
18
+
19
+ if (this._eventEmitter) {
20
+ await this._eventEmitter.emit('shutdownDevice', { deviceId: udid });
21
+ }
18
22
  }
19
23
  }
20
24
 
@@ -0,0 +1,24 @@
1
+ class SimulatorQuery {
2
+ /** @param {Partial<Detox.IosSimulatorQuery>} query */
3
+ constructor({ id, name, os, type }) {
4
+ if (id != null) this.byId = id;
5
+ if (name != null) this.byName = name;
6
+ if (os != null) this.byOS = os;
7
+ if (type != null) this.byType = type;
8
+ }
9
+
10
+ getDeviceComment() {
11
+ return this.byId || [this.byName, this.byType, this.byOS].filter(Boolean).join(', ');
12
+ }
13
+
14
+ toString() {
15
+ return [
16
+ this.byId && `by UDID = ${JSON.stringify(this.byId)}`,
17
+ this.byName && `by name = ${JSON.stringify(this.byName)}`,
18
+ this.byType && `by type = ${JSON.stringify(this.byType)}`,
19
+ this.byOS && `by OS = ${JSON.stringify(this.byOS)}`,
20
+ ].filter(Boolean).join(' and ');
21
+ }
22
+ }
23
+
24
+ module.exports = SimulatorQuery;
@@ -2,11 +2,12 @@
2
2
  const DeviceAllocatorFactory = require('./base');
3
3
 
4
4
  class AndroidEmulator extends DeviceAllocatorFactory {
5
- _createDriver({ eventEmitter }) {
6
- const serviceLocator = require('../../../servicelocator/android');
5
+ _createDriver({ detoxSession, detoxConfig }) {
6
+ const serviceLocator = require('../../servicelocator/android');
7
7
  const adb = serviceLocator.adb;
8
8
  const emulatorExec = serviceLocator.emulator.exec;
9
- const deviceRegistry = serviceLocator.deviceRegistry;
9
+ const DeviceRegistry = require('../../allocation/DeviceRegistry');
10
+ const deviceRegistry = new DeviceRegistry({ sessionId: detoxSession.id });
10
11
 
11
12
  const AVDsResolver = require('../drivers/android/emulator/AVDsResolver');
12
13
  const avdsResolver = new AVDsResolver(emulatorExec);
@@ -20,74 +21,67 @@ class AndroidEmulator extends DeviceAllocatorFactory {
20
21
  const FreeEmulatorFinder = require('../drivers/android/emulator/FreeEmulatorFinder');
21
22
  const freeEmulatorFinder = new FreeEmulatorFinder(adb, deviceRegistry);
22
23
 
23
- const EmulatorLauncher = require('../drivers/android/emulator/EmulatorLauncher');
24
- const emulatorLauncher = new EmulatorLauncher({ adb, emulatorExec, eventEmitter });
24
+ const FreePortFinder = require('../drivers/android/emulator/FreePortFinder');
25
+ const freePortFinder = new FreePortFinder();
25
26
 
26
- const EmulatorAllocationHelper = require('../drivers/android/emulator/EmulatorAllocationHelper');
27
- const allocationHelper = new EmulatorAllocationHelper(deviceRegistry, freeEmulatorFinder);
27
+ const EmulatorLauncher = require('../drivers/android/emulator/EmulatorLauncher');
28
+ const emulatorLauncher = new EmulatorLauncher({ adb, emulatorExec });
28
29
 
29
30
  const EmulatorAllocDriver = require('../drivers/android/emulator/EmulatorAllocDriver');
30
31
  return new EmulatorAllocDriver({
31
32
  adb,
32
33
  avdValidator,
34
+ detoxConfig,
35
+ deviceRegistry,
33
36
  emulatorVersionResolver,
34
37
  emulatorLauncher,
35
- allocationHelper,
38
+ freeDeviceFinder: freeEmulatorFinder,
39
+ freePortFinder,
36
40
  });
37
41
  }
38
42
  }
39
43
 
40
44
  class AndroidAttached extends DeviceAllocatorFactory {
41
- _createDriver({ eventEmitter }) {
42
- const serviceLocator = require('../../../servicelocator/android');
45
+ _createDriver({ detoxSession, detoxConfig }) {
46
+ const serviceLocator = require('../../servicelocator/android');
43
47
  const adb = serviceLocator.adb;
44
- const deviceRegistry = serviceLocator.deviceRegistry;
48
+ const DeviceRegistry = require('../../allocation/DeviceRegistry');
49
+ const deviceRegistry = new DeviceRegistry({ sessionId: detoxSession.id });
45
50
 
46
- const FreeDeviceFinder = require('../../common/drivers/android/tools/FreeDeviceFinder');
51
+ const FreeDeviceFinder = require('../drivers/android/FreeDeviceFinder');
47
52
  const freeDeviceFinder = new FreeDeviceFinder(adb, deviceRegistry);
48
53
 
49
- const AttachedAndroidLauncher = require('../drivers/android/attached/AttachedAndroidLauncher');
50
- const attachedAndroidLauncher = new AttachedAndroidLauncher(eventEmitter);
51
-
52
54
  const AttachedAndroidAllocDriver = require('../drivers/android/attached/AttachedAndroidAllocDriver');
53
- return new AttachedAndroidAllocDriver({ adb, deviceRegistry, freeDeviceFinder, attachedAndroidLauncher });
55
+ return new AttachedAndroidAllocDriver({ adb, deviceRegistry, freeDeviceFinder });
54
56
  }
55
57
  }
56
58
 
57
59
  class Genycloud extends DeviceAllocatorFactory {
58
- _createDriver({ eventEmitter }) {
59
- const serviceLocator = require('../../../servicelocator/android');
60
+ _createDriver(deps) {
61
+ const serviceLocator = require('../../servicelocator/android');
60
62
  const adb = serviceLocator.adb;
61
63
  const exec = serviceLocator.genycloud.exec;
62
- const deviceRegistry = serviceLocator.genycloud.runtimeDeviceRegistry;
63
- const deviceCleanupRegistry = serviceLocator.genycloud.cleanupDeviceRegistry;
64
64
 
65
- const InstanceNaming = require('../../common/drivers/android/genycloud/services/GenyInstanceNaming');
66
- const instanceNaming = new InstanceNaming(); // TODO should consider a permissive impl for debug/dev mode. Maybe even a custom arg in package.json (Detox > ... > genycloud > sharedAccount: false)
67
-
68
- const RecipesService = require('../../common/drivers/android/genycloud/services/GenyRecipesService');
65
+ const RecipesService = require('../drivers/android/genycloud/services/GenyRecipesService');
69
66
  const recipeService = new RecipesService(exec);
70
67
 
71
- const InstanceLookupService = require('../../common/drivers/android/genycloud/services/GenyInstanceLookupService');
72
- const instanceLookupService = new InstanceLookupService(exec, instanceNaming, deviceRegistry);
73
-
74
- const InstanceLifecycleService = require('../../common/drivers/android/genycloud/services/GenyInstanceLifecycleService');
75
- const instanceLifecycleService = new InstanceLifecycleService(exec, instanceNaming);
68
+ const InstanceLifecycleService = require('../drivers/android/genycloud/services/GenyInstanceLifecycleService');
69
+ const instanceLifecycleService = new InstanceLifecycleService(exec);
76
70
 
77
71
  const RecipeQuerying = require('../drivers/android/genycloud/GenyRecipeQuerying');
78
72
  const recipeQuerying = new RecipeQuerying(recipeService);
79
73
 
80
- const InstanceAllocationHelper = require('../drivers/android/genycloud/GenyInstanceAllocationHelper');
81
- const allocationHelper = new InstanceAllocationHelper({ deviceRegistry, instanceLookupService, instanceLifecycleService });
82
-
83
74
  const InstanceLauncher = require('../drivers/android/genycloud/GenyInstanceLauncher');
75
+ const instanceLauncher = new InstanceLauncher({ genyCloudExec: exec, instanceLifecycleService });
76
+
84
77
  const GenyAllocDriver = require('../drivers/android/genycloud/GenyAllocDriver');
85
- const instanceLauncher = new InstanceLauncher({ instanceLifecycleService, instanceLookupService, deviceCleanupRegistry, eventEmitter });
78
+
86
79
  return new GenyAllocDriver({
87
80
  adb,
88
- recipeQuerying,
89
- allocationHelper,
90
81
  instanceLauncher,
82
+ instanceLifecycleService,
83
+ recipeQuerying,
84
+ ...deps,
91
85
  });
92
86
  }
93
87
  }
@@ -2,16 +2,18 @@
2
2
  const DeviceAllocatorFactory = require('./base');
3
3
 
4
4
  class IosSimulator extends DeviceAllocatorFactory {
5
- _createDriver({ eventEmitter }) {
6
- const serviceLocator = require('../../../servicelocator/ios');
7
- const applesimutils = serviceLocator.appleSimUtils;
8
- const deviceRegistry = serviceLocator.deviceRegistry;
5
+ _createDriver({ detoxConfig, detoxSession, eventEmitter }) {
6
+ const AppleSimUtils = require('../../../devices/common/drivers/ios/tools/AppleSimUtils');
7
+ const applesimutils = new AppleSimUtils();
8
+
9
+ const DeviceRegistry = require('../../../devices/allocation/DeviceRegistry');
10
+ const deviceRegistry = new DeviceRegistry({ sessionId: detoxSession.id });
9
11
 
10
12
  const SimulatorLauncher = require('../drivers/ios/SimulatorLauncher');
11
13
  const simulatorLauncher = new SimulatorLauncher({ applesimutils, eventEmitter });
12
14
 
13
15
  const SimulatorAllocDriver = require('../drivers/ios/SimulatorAllocDriver');
14
- return new SimulatorAllocDriver({ deviceRegistry, applesimutils, simulatorLauncher });
16
+ return new SimulatorAllocDriver({ detoxConfig, deviceRegistry, applesimutils, simulatorLauncher });
15
17
  }
16
18
  }
17
19
 
@@ -32,19 +32,31 @@ class QueryVersionCommand extends ExecCommand {
32
32
  }
33
33
 
34
34
  class LaunchCommand extends ExecCommand {
35
- constructor(emulatorName, options) {
35
+ constructor(options) {
36
36
  super();
37
37
  this._options = options;
38
- this._args = this._getEmulatorArgs(emulatorName);
39
- this.port = options.port;
38
+ this._args = this._getEmulatorArgs();
39
+ }
40
+
41
+ get adbName() {
42
+ return this._options.adbName;
43
+ }
44
+
45
+ get avdName() {
46
+ return this._options.avdName;
47
+ }
48
+
49
+ get port() {
50
+ return this._options.port;
40
51
  }
41
52
 
42
53
  _getArgs() {
43
54
  return this._args;
44
55
  }
45
56
 
46
- _getEmulatorArgs(emulatorName) {
57
+ _getEmulatorArgs() {
47
58
  const {
59
+ avdName,
48
60
  bootArgs,
49
61
  gpuMode = this._getDefaultGPUMode(),
50
62
  headless,
@@ -64,7 +76,7 @@ class LaunchCommand extends ExecCommand {
64
76
  port ? '-port' : '',
65
77
  port ? `${port}` : '',
66
78
  ...deviceBootArgs,
67
- `@${emulatorName}`
79
+ `@${avdName}`
68
80
  ]);
69
81
 
70
82
  return emulatorArgs;
@@ -18,6 +18,7 @@ class ADB {
18
18
 
19
19
  async devices() {
20
20
  const { stdout } = await this.adbCmd('', 'devices', { verbosity: 'high' });
21
+ /** @type {DeviceHandle[]} */
21
22
  const devices = _.chain(stdout)
22
23
  .trim()
23
24
  .split('\n')
@@ -297,7 +297,7 @@ class AppleSimUtils {
297
297
  // want to make sure it isn't now.
298
298
  if (err.code === 3 &&
299
299
  (err.stderr.includes(`the app is not currently running`) ||
300
- err.stderr.includes(`found nothing to terminate`))) {
300
+ err.stderr.includes(`The operation couldn’t be completed. found nothing to terminate`))) {
301
301
  return;
302
302
  }
303
303
 
@@ -8,6 +8,10 @@ class AndroidDeviceCookie extends DeviceCookie {
8
8
  super();
9
9
  this.adbName = adbName;
10
10
  }
11
+
12
+ toString() {
13
+ return this.adbName;
14
+ }
11
15
  }
12
16
 
13
17
  module.exports = AndroidDeviceCookie;
@@ -6,15 +6,13 @@ class GenycloudEmulatorCookie extends AndroidDeviceCookie {
6
6
  * @param instance { GenyInstance }
7
7
  */
8
8
  constructor(instance) {
9
- super();
9
+ super(instance.adb.name);
10
10
  this.instance = instance;
11
11
  }
12
12
 
13
- get adbName() {
14
- return this.instance.adbName;
13
+ toString() {
14
+ return `${this.instance}`;
15
15
  }
16
-
17
- set adbName(value) {}
18
16
  }
19
17
 
20
18
  module.exports = GenycloudEmulatorCookie;
@@ -5,6 +5,10 @@ class IosSimulatorCookie extends IosCookie {
5
5
  super();
6
6
  this.udid = udid;
7
7
  }
8
+
9
+ toString() {
10
+ return this.udid;
11
+ }
8
12
  }
9
13
 
10
14
  module.exports = IosSimulatorCookie;
@@ -17,12 +17,12 @@ class GenyCloudDriver extends AndroidDriver {
17
17
  * @param props { GenycloudDriverProps }
18
18
  */
19
19
  constructor(deps, { instance }) {
20
- super(deps, { adbName: instance.adbName });
20
+ super(deps, { adbName: instance.adb.name });
21
21
  this.instance = instance;
22
22
  }
23
23
 
24
24
  getDeviceName() {
25
- return this.instance.toString();
25
+ return this.instance.name;
26
26
  }
27
27
 
28
28
  async setLocation(lat, lon) {
@@ -3,7 +3,7 @@ const RuntimeDeviceFactory = require('./base');
3
3
 
4
4
  class RuntimeDriverFactoryAndroid extends RuntimeDeviceFactory {
5
5
  _createDriverDependencies(commonDeps) {
6
- const serviceLocator = require('../../../servicelocator/android');
6
+ const serviceLocator = require('../../servicelocator/android');
7
7
  const adb = serviceLocator.adb;
8
8
  const aapt = serviceLocator.aapt;
9
9
  const apkValidator = serviceLocator.apkValidator;