detox 20.12.0-smoke.0 → 20.12.0
Sign up to get free protection for your applications and to get access to all the features.
- package/Detox-android/com/wix/detox/{20.12.0-smoke.0/detox-20.12.0-smoke.0-javadoc.jar → 20.12.0/detox-20.12.0-javadoc.jar} +0 -0
- package/Detox-android/com/wix/detox/20.12.0/detox-20.12.0-javadoc.jar.md5 +1 -0
- package/Detox-android/com/wix/detox/20.12.0/detox-20.12.0-javadoc.jar.sha1 +1 -0
- package/Detox-android/com/wix/detox/20.12.0/detox-20.12.0-javadoc.jar.sha256 +1 -0
- package/Detox-android/com/wix/detox/20.12.0/detox-20.12.0-javadoc.jar.sha512 +1 -0
- package/Detox-android/com/wix/detox/{20.12.0-smoke.0/detox-20.12.0-smoke.0-sources.jar → 20.12.0/detox-20.12.0-sources.jar} +0 -0
- package/Detox-android/com/wix/detox/20.12.0/detox-20.12.0-sources.jar.md5 +1 -0
- package/Detox-android/com/wix/detox/20.12.0/detox-20.12.0-sources.jar.sha1 +1 -0
- package/Detox-android/com/wix/detox/20.12.0/detox-20.12.0-sources.jar.sha256 +1 -0
- package/Detox-android/com/wix/detox/20.12.0/detox-20.12.0-sources.jar.sha512 +1 -0
- package/Detox-android/com/wix/detox/20.12.0/detox-20.12.0.aar +0 -0
- package/Detox-android/com/wix/detox/20.12.0/detox-20.12.0.aar.md5 +1 -0
- package/Detox-android/com/wix/detox/20.12.0/detox-20.12.0.aar.sha1 +1 -0
- package/Detox-android/com/wix/detox/20.12.0/detox-20.12.0.aar.sha256 +1 -0
- package/Detox-android/com/wix/detox/20.12.0/detox-20.12.0.aar.sha512 +1 -0
- package/Detox-android/com/wix/detox/{20.12.0-smoke.0/detox-20.12.0-smoke.0.pom → 20.12.0/detox-20.12.0.pom} +1 -1
- package/Detox-android/com/wix/detox/20.12.0/detox-20.12.0.pom.md5 +1 -0
- package/Detox-android/com/wix/detox/20.12.0/detox-20.12.0.pom.sha1 +1 -0
- package/Detox-android/com/wix/detox/20.12.0/detox-20.12.0.pom.sha256 +1 -0
- package/Detox-android/com/wix/detox/20.12.0/detox-20.12.0.pom.sha512 +1 -0
- package/Detox-android/com/wix/detox/maven-metadata.xml +4 -4
- package/Detox-android/com/wix/detox/maven-metadata.xml.md5 +1 -1
- package/Detox-android/com/wix/detox/maven-metadata.xml.sha1 +1 -1
- package/Detox-android/com/wix/detox/maven-metadata.xml.sha256 +1 -1
- package/Detox-android/com/wix/detox/maven-metadata.xml.sha512 +1 -1
- package/Detox-ios-src.tbz +0 -0
- package/Detox-ios.tbz +0 -0
- package/android/detox/build.gradle +1 -1
- package/android/detox/src/full/java/com/wix/detox/espresso/DetoxAssertion.java +44 -25
- package/android/detox/src/full/java/com/wix/detox/espresso/EspressoDetox.java +6 -7
- package/android/detox/src/full/java/com/wix/detox/espresso/action/GetAttributesAction.kt +4 -4
- package/android/detox/src/full/java/com/wix/detox/espresso/performer/MultipleViewsActionPerformer.kt +43 -0
- package/android/detox/src/full/java/com/wix/detox/espresso/performer/SingleViewActionPerformer.kt +19 -0
- package/android/detox/src/full/java/com/wix/detox/espresso/performer/ViewActionPerformer.kt +24 -0
- package/android/detox/src/full/java/com/wix/invoke/types/Invocation.java +5 -4
- package/android/detox/src/main/java/com/wix/detox/espresso/MultipleViewsAction.kt +4 -0
- package/android/detox/src/main/java/com/wix/detox/espresso/UiControllerSpy.kt +0 -1
- package/android/detox/src/main/java/com/wix/detox/espresso/ViewActionWithResult.kt +2 -1
- package/android/detox/src/testFull/java/com/wix/detox/espresso/action/GetAttributesActionTest.kt +6 -5
- package/android/detox/src/testFull/java/com/wix/detox/espresso/performer/ViewActionPerformerSpec.kt +37 -0
- package/index.d.ts +4 -3
- package/local-cli/reset-lock-file.js +9 -5
- package/package.json +6 -6
- package/src/DetoxWorker.js +9 -5
- package/src/android/core/NativeElement.js +26 -29
- package/src/android/espressoapi/DetoxAssertion.js +16 -14
- package/src/android/espressoapi/EspressoDetox.js +9 -2
- package/src/android/interactions/native.js +2 -3
- package/src/artifacts/providers/index.js +3 -3
- package/src/artifacts/screenshot/SimulatorScreenshotPlugin.js +17 -0
- package/src/devices/DeviceRegistry.js +176 -0
- package/src/devices/allocation/DeviceAllocator.js +15 -50
- package/src/devices/allocation/drivers/AllocationDriverBase.js +4 -10
- package/src/devices/allocation/drivers/android/attached/AttachedAndroidAllocDriver.js +6 -7
- package/src/devices/allocation/drivers/android/attached/AttachedAndroidLauncher.js +13 -0
- package/src/devices/allocation/drivers/android/emulator/EmulatorAllocDriver.js +26 -108
- package/src/devices/allocation/drivers/android/emulator/EmulatorAllocationHelper.js +72 -0
- package/src/devices/allocation/drivers/android/emulator/EmulatorLauncher.js +43 -33
- package/src/devices/allocation/drivers/android/emulator/FreeEmulatorFinder.js +1 -1
- package/src/devices/allocation/drivers/android/emulator/launchEmulatorProcess.js +3 -3
- package/src/devices/allocation/drivers/android/genycloud/GenyAllocDriver.js +27 -87
- package/src/devices/allocation/drivers/android/genycloud/GenyDeviceRegistryFactory.js +16 -0
- package/src/devices/allocation/drivers/android/genycloud/GenyInstanceAllocationHelper.js +65 -0
- package/src/devices/allocation/drivers/android/genycloud/GenyInstanceLauncher.js +28 -39
- package/src/devices/allocation/drivers/ios/SimulatorAllocDriver.js +40 -70
- package/src/devices/allocation/drivers/ios/SimulatorLauncher.js +7 -11
- package/src/devices/allocation/factories/android.js +35 -29
- package/src/devices/allocation/factories/ios.js +5 -7
- package/src/devices/common/drivers/DeviceAllocationHelper.js +20 -0
- package/src/devices/common/drivers/DeviceLauncher.js +19 -0
- package/src/devices/common/drivers/android/emulator/exec/EmulatorExec.js +5 -17
- package/src/devices/common/drivers/android/exec/ADB.js +0 -1
- package/src/devices/common/drivers/android/genycloud/services/GenyInstanceLifecycleService.js +25 -0
- package/src/devices/common/drivers/android/genycloud/services/GenyInstanceLookupService.js +38 -0
- package/src/devices/common/drivers/android/genycloud/services/GenyInstanceNaming.js +14 -0
- package/src/devices/{allocation → common}/drivers/android/genycloud/services/GenyRecipesService.js +1 -1
- package/src/devices/{allocation → common}/drivers/android/genycloud/services/dto/GenyInstance.js +1 -6
- package/src/devices/{allocation/drivers/android → common/drivers/android/tools}/FreeDeviceFinder.js +10 -11
- package/src/devices/common/drivers/ios/tools/AppleSimUtils.js +1 -1
- package/src/devices/cookies/AndroidDeviceCookie.js +0 -4
- package/src/devices/cookies/GenycloudEmulatorCookie.js +5 -3
- package/src/devices/cookies/IosSimulatorCookie.js +0 -4
- package/src/devices/lifecycle/GenyGlobalLifecycleHandler.js +71 -0
- package/src/devices/lifecycle/factories/GenyGlobalLifecycleHandlerFactory.js +18 -0
- package/src/devices/runtime/drivers/android/genycloud/GenyCloudDriver.js +2 -2
- package/src/devices/runtime/factories/android.js +1 -1
- package/src/devices/runtime/factories/ios.js +2 -3
- package/src/environmentFactory.js +11 -1
- package/src/ipc/IPCClient.js +1 -17
- package/src/ipc/IPCServer.js +1 -25
- package/src/realms/DetoxContext.js +0 -6
- package/src/realms/DetoxPrimaryContext.js +42 -42
- package/src/realms/DetoxSecondaryContext.js +0 -19
- package/src/realms/symbols.js +0 -4
- package/src/{devices/servicelocator → servicelocator}/android/emulatorServiceLocator.js +1 -1
- package/src/servicelocator/android/genycloudServiceLocator.js +21 -0
- package/src/servicelocator/android/index.js +25 -0
- package/src/servicelocator/ios.js +7 -0
- package/src/utils/environment.js +15 -8
- package/src/utils/errorUtils.js +2 -2
- package/src/{devices/validation → validation}/android/GenycloudEnvValidator.js +2 -2
- package/src/{devices/validation → validation}/factories/index.js +1 -1
- package/src/{devices/validation → validation}/ios/IosSimulatorEnvValidator.js +2 -2
- package/Detox-android/com/wix/detox/20.12.0-smoke.0/detox-20.12.0-smoke.0-javadoc.jar.md5 +0 -1
- package/Detox-android/com/wix/detox/20.12.0-smoke.0/detox-20.12.0-smoke.0-javadoc.jar.sha1 +0 -1
- package/Detox-android/com/wix/detox/20.12.0-smoke.0/detox-20.12.0-smoke.0-javadoc.jar.sha256 +0 -1
- package/Detox-android/com/wix/detox/20.12.0-smoke.0/detox-20.12.0-smoke.0-javadoc.jar.sha512 +0 -1
- package/Detox-android/com/wix/detox/20.12.0-smoke.0/detox-20.12.0-smoke.0-sources.jar.md5 +0 -1
- package/Detox-android/com/wix/detox/20.12.0-smoke.0/detox-20.12.0-smoke.0-sources.jar.sha1 +0 -1
- package/Detox-android/com/wix/detox/20.12.0-smoke.0/detox-20.12.0-smoke.0-sources.jar.sha256 +0 -1
- package/Detox-android/com/wix/detox/20.12.0-smoke.0/detox-20.12.0-smoke.0-sources.jar.sha512 +0 -1
- package/Detox-android/com/wix/detox/20.12.0-smoke.0/detox-20.12.0-smoke.0.aar +0 -0
- package/Detox-android/com/wix/detox/20.12.0-smoke.0/detox-20.12.0-smoke.0.aar.md5 +0 -1
- package/Detox-android/com/wix/detox/20.12.0-smoke.0/detox-20.12.0-smoke.0.aar.sha1 +0 -1
- package/Detox-android/com/wix/detox/20.12.0-smoke.0/detox-20.12.0-smoke.0.aar.sha256 +0 -1
- package/Detox-android/com/wix/detox/20.12.0-smoke.0/detox-20.12.0-smoke.0.aar.sha512 +0 -1
- package/Detox-android/com/wix/detox/20.12.0-smoke.0/detox-20.12.0-smoke.0.pom.md5 +0 -1
- package/Detox-android/com/wix/detox/20.12.0-smoke.0/detox-20.12.0-smoke.0.pom.sha1 +0 -1
- package/Detox-android/com/wix/detox/20.12.0-smoke.0/detox-20.12.0-smoke.0.pom.sha256 +0 -1
- package/Detox-android/com/wix/detox/20.12.0-smoke.0/detox-20.12.0-smoke.0.pom.sha512 +0 -1
- package/src/devices/allocation/DeviceList.js +0 -44
- package/src/devices/allocation/DeviceRegistry.js +0 -186
- package/src/devices/allocation/drivers/android/emulator/FreePortFinder.js +0 -16
- package/src/devices/allocation/drivers/android/genycloud/GenyRegistry.js +0 -93
- package/src/devices/allocation/drivers/android/genycloud/services/GenyInstanceLifecycleService.js +0 -24
- package/src/devices/allocation/drivers/ios/SimulatorQuery.js +0 -24
- package/src/devices/servicelocator/android/genycloudServiceLocator.js +0 -17
- package/src/devices/servicelocator/android/index.js +0 -23
- package/src/utils/PIDService.js +0 -27
- /package/src/devices/{allocation → common}/drivers/android/genycloud/exec/GenyCloudExec.js +0 -0
- /package/src/devices/{allocation → common}/drivers/android/genycloud/services/GenyAuthService.js +0 -0
- /package/src/devices/{allocation → common}/drivers/android/genycloud/services/dto/GenyRecipe.js +0 -0
- /package/src/{devices/validation → validation}/EnvironmentValidatorBase.js +0 -0
@@ -1,39 +1,25 @@
|
|
1
1
|
const { DetoxRuntimeError } = require('../../../../../errors');
|
2
2
|
const Timer = require('../../../../../utils/Timer');
|
3
|
-
const log = require('../../../../../utils/logger').child({ cat: 'device' });
|
4
3
|
const GenycloudEmulatorCookie = require('../../../../cookies/GenycloudEmulatorCookie');
|
5
4
|
const AllocationDriverBase = require('../../AllocationDriverBase');
|
6
5
|
|
7
|
-
const GenyRegistry = require('./GenyRegistry');
|
8
|
-
|
9
|
-
const events = {
|
10
|
-
GENYCLOUD_TEARDOWN: { event: 'GENYCLOUD_TEARDOWN' },
|
11
|
-
};
|
12
|
-
|
13
6
|
class GenyAllocDriver extends AllocationDriverBase {
|
7
|
+
|
14
8
|
/**
|
15
9
|
* @param {object} options
|
16
10
|
* @param {import('../../../../common/drivers/android/exec/ADB')} options.adb
|
17
|
-
* @param {DetoxInternals.SessionState} options.detoxSession
|
18
|
-
* @param {import('./GenyRegistry')} options.genyRegistry
|
19
|
-
* @param {import('./GenyInstanceLauncher')} options.instanceLauncher
|
20
11
|
* @param {import('./GenyRecipeQuerying')} options.recipeQuerying
|
12
|
+
* @param {import('./GenyInstanceAllocationHelper')} options.allocationHelper
|
13
|
+
* @param {import('./GenyInstanceLauncher')} options.instanceLauncher
|
21
14
|
*/
|
22
|
-
constructor({
|
23
|
-
adb,
|
24
|
-
detoxSession,
|
25
|
-
genyRegistry = new GenyRegistry(),
|
26
|
-
instanceLauncher,
|
27
|
-
recipeQuerying,
|
28
|
-
}) {
|
15
|
+
constructor({ adb, recipeQuerying, allocationHelper, instanceLauncher }) {
|
29
16
|
super();
|
30
17
|
|
31
18
|
this._adb = adb;
|
32
|
-
this._detoxSessionId = detoxSession.id;
|
33
|
-
this._genyRegistry = genyRegistry;
|
34
|
-
this._instanceLauncher = instanceLauncher;
|
35
19
|
this._recipeQuerying = recipeQuerying;
|
36
|
-
this.
|
20
|
+
this._instanceLauncher = instanceLauncher;
|
21
|
+
this._instanceAllocationHelper = allocationHelper;
|
22
|
+
this._launchInfo = {};
|
37
23
|
}
|
38
24
|
|
39
25
|
/**
|
@@ -41,72 +27,45 @@ class GenyAllocDriver extends AllocationDriverBase {
|
|
41
27
|
* @return {Promise<GenycloudEmulatorCookie>}
|
42
28
|
*/
|
43
29
|
async allocate(deviceConfig) {
|
44
|
-
await new Promise((resolve) => setTimeout(resolve, 10000));
|
45
30
|
const deviceQuery = deviceConfig.device;
|
46
31
|
const recipe = await this._recipeQuerying.getRecipeFromQuery(deviceQuery);
|
47
32
|
this._assertRecipe(deviceQuery, recipe);
|
48
33
|
|
49
|
-
|
50
|
-
|
51
|
-
const instanceName = `Detox.${this._detoxSessionId}.${this._instanceCounter++}`;
|
52
|
-
instance = await this._instanceLauncher.launch(recipe, instanceName);
|
53
|
-
this._genyRegistry.addInstance(instance, recipe);
|
54
|
-
}
|
55
|
-
|
34
|
+
const { instance, isNew } = await this._instanceAllocationHelper.allocateDevice(recipe);
|
35
|
+
this._launchInfo[instance.uuid] = { isNew };
|
56
36
|
return new GenycloudEmulatorCookie(instance);
|
57
37
|
}
|
58
38
|
|
59
39
|
/**
|
60
40
|
* @param {GenycloudEmulatorCookie} cookie
|
41
|
+
* @returns {Promise<void>}
|
61
42
|
*/
|
62
43
|
async postAllocate(cookie) {
|
63
|
-
const instance =
|
64
|
-
this.
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
await
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
});
|
74
|
-
}
|
75
|
-
|
76
|
-
return new GenycloudEmulatorCookie(instance);
|
44
|
+
const { instance } = cookie;
|
45
|
+
const { isNew } = this._launchInfo[instance.uuid];
|
46
|
+
const readyInstance = cookie.instance = await this._instanceLauncher.launch(instance, isNew);
|
47
|
+
|
48
|
+
const { adbName } = readyInstance;
|
49
|
+
await Timer.run(20000, 'waiting for device to respond', async () => {
|
50
|
+
await this._adb.disableAndroidAnimations(adbName);
|
51
|
+
await this._adb.setWiFiToggle(adbName, true);
|
52
|
+
await this._adb.apiLevel(adbName);
|
53
|
+
});
|
77
54
|
}
|
78
55
|
|
79
56
|
/**
|
80
|
-
* @param cookie {GenycloudEmulatorCookie}
|
81
|
-
* @param options {
|
57
|
+
* @param cookie { GenycloudEmulatorCookie }
|
58
|
+
* @param options { DeallocOptions }
|
82
59
|
* @return {Promise<void>}
|
83
60
|
*/
|
84
61
|
async free(cookie, options = {}) {
|
85
|
-
|
86
|
-
this._genyRegistry.removeInstance(cookie.instance);
|
87
|
-
await this._instanceLauncher.shutdown(cookie.instance);
|
88
|
-
} else {
|
89
|
-
this._genyRegistry.markAsFree(cookie.instance);
|
90
|
-
}
|
91
|
-
}
|
92
|
-
|
93
|
-
async cleanup() {
|
94
|
-
log.info(events.GENYCLOUD_TEARDOWN, 'Initiating Genymotion SaaS instances teardown...');
|
62
|
+
const { instance } = cookie;
|
95
63
|
|
96
|
-
|
97
|
-
this._genyRegistry.markAsBusy(instance);
|
98
|
-
const onSuccess = () => this._genyRegistry.removeInstance(instance);
|
99
|
-
const onError = (error) => ({ ...instance, error });
|
100
|
-
return this._instanceLauncher.shutdown(instance).then(onSuccess, onError);
|
101
|
-
});
|
102
|
-
|
103
|
-
const deletionLeaks = (await Promise.all(killPromises)).filter(Boolean);
|
104
|
-
this._reportGlobalCleanupSummary(deletionLeaks);
|
105
|
-
}
|
64
|
+
await this._instanceAllocationHelper.deallocateDevice(instance.uuid);
|
106
65
|
|
107
|
-
|
108
|
-
|
109
|
-
|
66
|
+
if (options.shutdown) {
|
67
|
+
await this._instanceLauncher.shutdown(instance);
|
68
|
+
}
|
110
69
|
}
|
111
70
|
|
112
71
|
_assertRecipe(deviceQuery, recipe) {
|
@@ -117,25 +76,6 @@ class GenyAllocDriver extends AllocationDriverBase {
|
|
117
76
|
});
|
118
77
|
}
|
119
78
|
}
|
120
|
-
|
121
|
-
_reportGlobalCleanupSummary(deletionLeaks) {
|
122
|
-
if (deletionLeaks.length) {
|
123
|
-
log.warn(events.GENYCLOUD_TEARDOWN, 'WARNING! Detected a Genymotion SaaS instance leakage, for the following instances:');
|
124
|
-
|
125
|
-
deletionLeaks.forEach(({ uuid, name, error }) => {
|
126
|
-
log.warn(events.GENYCLOUD_TEARDOWN, [
|
127
|
-
`Instance ${name} (${uuid})${error ? `: ${error}` : ''}`,
|
128
|
-
` Kill it by visiting https://cloud.geny.io/instance/${uuid}, or by running:`,
|
129
|
-
` gmsaas instances stop ${uuid}`,
|
130
|
-
].join('\n'));
|
131
|
-
});
|
132
|
-
|
133
|
-
log.info(events.GENYCLOUD_TEARDOWN, 'Instances teardown completed with warnings');
|
134
|
-
} else {
|
135
|
-
log.info(events.GENYCLOUD_TEARDOWN, 'Instances teardown completed successfully');
|
136
|
-
}
|
137
|
-
}
|
138
79
|
}
|
139
80
|
|
140
|
-
|
141
81
|
module.exports = GenyAllocDriver;
|
@@ -0,0 +1,16 @@
|
|
1
|
+
const environment = require('../../../../../utils/environment');
|
2
|
+
const DeviceRegistry = require('../../../../DeviceRegistry');
|
3
|
+
|
4
|
+
class GenyDeviceRegistryFactory {
|
5
|
+
forRuntime() {
|
6
|
+
return DeviceRegistry.forAndroid();
|
7
|
+
}
|
8
|
+
|
9
|
+
forGlobalShutdown() {
|
10
|
+
return new DeviceRegistry({
|
11
|
+
lockfilePath: environment.getGenyCloudGlobalCleanupFilePath(),
|
12
|
+
});
|
13
|
+
}
|
14
|
+
}
|
15
|
+
|
16
|
+
module.exports = new GenyDeviceRegistryFactory();
|
@@ -0,0 +1,65 @@
|
|
1
|
+
// @ts-nocheck
|
2
|
+
const logger = require('../../../../../utils/logger').child({ cat: 'device' });
|
3
|
+
const DeviceAllocationHelper = require('../../../../common/drivers/DeviceAllocationHelper');
|
4
|
+
|
5
|
+
const { ALLOCATE_DEVICE_LOG_EVT } = DeviceAllocationHelper;
|
6
|
+
|
7
|
+
class AllocationResult {
|
8
|
+
constructor(instance, isNew) {
|
9
|
+
this.instance = instance;
|
10
|
+
this.isNew = isNew;
|
11
|
+
}
|
12
|
+
}
|
13
|
+
|
14
|
+
class GenyInstanceAllocationHelper extends DeviceAllocationHelper {
|
15
|
+
constructor({ deviceRegistry, instanceLookupService, instanceLifecycleService }) {
|
16
|
+
super(deviceRegistry, logger);
|
17
|
+
|
18
|
+
this._instanceLookupService = instanceLookupService;
|
19
|
+
this._instanceLifecycleService = instanceLifecycleService;
|
20
|
+
}
|
21
|
+
|
22
|
+
/**
|
23
|
+
* @param recipe { GenyRecipe }
|
24
|
+
* @return { Promise<AllocationResult> }
|
25
|
+
*/
|
26
|
+
async allocateDevice(recipe) {
|
27
|
+
this._logAllocationAttempt(recipe);
|
28
|
+
|
29
|
+
const allocationResult = await this._doSynchronizedAllocation(recipe);
|
30
|
+
this._logAllocationResult(recipe, allocationResult.instance);
|
31
|
+
|
32
|
+
return allocationResult;
|
33
|
+
}
|
34
|
+
|
35
|
+
async deallocateDevice(instanceUUID) {
|
36
|
+
await this._deviceRegistry.disposeDevice(instanceUUID);
|
37
|
+
}
|
38
|
+
|
39
|
+
/**
|
40
|
+
* @param recipe { GenyRecipe }
|
41
|
+
* @return {Promise<{AllocationResult}>}
|
42
|
+
* @private
|
43
|
+
*/
|
44
|
+
async _doSynchronizedAllocation(recipe) {
|
45
|
+
let instance = null;
|
46
|
+
let isNew = false;
|
47
|
+
|
48
|
+
await this._deviceRegistry.allocateDevice(async () => {
|
49
|
+
instance = await this._instanceLookupService.findFreeInstance();
|
50
|
+
if (!instance) {
|
51
|
+
instance = await this._instanceLifecycleService.createInstance(recipe.uuid);
|
52
|
+
isNew = true;
|
53
|
+
}
|
54
|
+
return instance.uuid;
|
55
|
+
});
|
56
|
+
|
57
|
+
return new AllocationResult(instance, isNew);
|
58
|
+
}
|
59
|
+
|
60
|
+
_logAllocationResult(deviceQuery, deviceHandle) {
|
61
|
+
logger.info({ event: ALLOCATE_DEVICE_LOG_EVT }, `Allocating Genymotion-Cloud instance ${deviceHandle.name} for testing. To access it via a browser, go to: https://cloud.geny.io/instance/${deviceHandle.uuid}`);
|
62
|
+
}
|
63
|
+
}
|
64
|
+
|
65
|
+
module.exports = GenyInstanceAllocationHelper;
|
@@ -1,51 +1,44 @@
|
|
1
|
+
// @ts-nocheck
|
1
2
|
const DetoxRuntimeError = require('../../../../../errors/DetoxRuntimeError');
|
2
|
-
const logger = require('../../../../../utils/logger').child({ cat: 'device' });
|
3
3
|
const retry = require('../../../../../utils/retry');
|
4
|
+
const DeviceLauncher = require('../../../../common/drivers/DeviceLauncher');
|
4
5
|
|
5
|
-
|
6
|
+
class GenyInstanceLauncher extends DeviceLauncher {
|
7
|
+
constructor({ instanceLifecycleService, instanceLookupService, deviceCleanupRegistry, eventEmitter }) {
|
8
|
+
super(eventEmitter);
|
6
9
|
|
7
|
-
const events = {
|
8
|
-
CREATE_DEVICE: { event: 'CREATE_DEVICE' },
|
9
|
-
};
|
10
|
-
|
11
|
-
class GenyInstanceLauncher {
|
12
|
-
constructor({ genyCloudExec, instanceLifecycleService }) {
|
13
|
-
this._genyCloudExec = genyCloudExec;
|
14
10
|
this._instanceLifecycleService = instanceLifecycleService;
|
11
|
+
this._instanceLookupService = instanceLookupService;
|
12
|
+
this._deviceCleanupRegistry = deviceCleanupRegistry;
|
15
13
|
}
|
16
14
|
|
17
15
|
/**
|
18
|
-
*
|
19
|
-
*
|
16
|
+
* Note:
|
17
|
+
* In the context of Genymotion-cloud (as opposed to local emulators), emulators are
|
18
|
+
* not launched per-se, as with local emulators. Rather, we just need to sync-up with
|
19
|
+
* them and connect, if needed.
|
20
|
+
*
|
21
|
+
* @param instance {GenyInstance} The freshly allocated cloud-instance.
|
22
|
+
* @param isNew { boolean }
|
20
23
|
* @returns {Promise<GenyInstance>}
|
21
24
|
*/
|
22
|
-
async launch(
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
25
|
+
async launch(instance, isNew = true) {
|
26
|
+
if (isNew) {
|
27
|
+
await this._deviceCleanupRegistry.allocateDevice(instance.uuid, { name: instance.name });
|
28
|
+
}
|
29
|
+
instance = await this._waitForInstanceBoot(instance);
|
30
|
+
instance = await this._adbConnectIfNeeded(instance);
|
31
|
+
await this._notifyBootEvent(instance.adbName, instance.recipeName, isNew);
|
28
32
|
return instance;
|
29
33
|
}
|
30
34
|
|
31
|
-
/**
|
32
|
-
* @param {GenyInstance} instance The freshly allocated cloud-instance.
|
33
|
-
* @returns {Promise<GenyInstance>}
|
34
|
-
*/
|
35
|
-
async connect(instance) {
|
36
|
-
const bootedInstance = await this._waitForInstanceBoot(instance);
|
37
|
-
const connectedInstance = await this._adbConnectIfNeeded(bootedInstance);
|
38
|
-
|
39
|
-
return connectedInstance;
|
40
|
-
}
|
41
|
-
|
42
|
-
/**
|
43
|
-
* @param {import('./services/dto/GenyInstance')} instance The freshly allocated cloud-instance.
|
44
|
-
*/
|
45
35
|
async shutdown(instance) {
|
46
36
|
const { uuid } = instance;
|
47
37
|
|
38
|
+
await this._notifyPreShutdown(uuid);
|
48
39
|
await this._instanceLifecycleService.deleteInstance(uuid);
|
40
|
+
await this._deviceCleanupRegistry.disposeDevice(uuid);
|
41
|
+
await this._notifyShutdownCompleted(uuid);
|
49
42
|
}
|
50
43
|
|
51
44
|
async _waitForInstanceBoot(instance) {
|
@@ -55,21 +48,17 @@ class GenyInstanceLauncher {
|
|
55
48
|
|
56
49
|
const options = {
|
57
50
|
backoff: 'none',
|
58
|
-
retries:
|
51
|
+
retries: 25,
|
59
52
|
interval: 5000,
|
60
53
|
initialSleep: 45000,
|
61
|
-
shouldUnref: true,
|
62
54
|
};
|
63
55
|
|
64
56
|
return await retry(options, async () => {
|
65
|
-
const
|
66
|
-
|
67
|
-
|
68
|
-
if (!anInstance.isOnline()) {
|
57
|
+
const _instance = await this._instanceLookupService.getInstance(instance.uuid);
|
58
|
+
if (!_instance.isOnline()) {
|
69
59
|
throw new DetoxRuntimeError(`Timeout waiting for instance ${instance.uuid} to be ready`);
|
70
60
|
}
|
71
|
-
|
72
|
-
return anInstance;
|
61
|
+
return _instance;
|
73
62
|
});
|
74
63
|
}
|
75
64
|
|
@@ -2,31 +2,21 @@
|
|
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' });
|
6
5
|
const IosSimulatorCookie = require('../../../cookies/IosSimulatorCookie');
|
7
6
|
const AllocationDriverBase = require('../AllocationDriverBase');
|
8
7
|
|
9
|
-
const SimulatorQuery = require('./SimulatorQuery');
|
10
|
-
|
11
8
|
class SimulatorAllocDriver extends AllocationDriverBase {
|
12
9
|
/**
|
13
|
-
* @param deviceRegistry { DeviceRegistry }
|
14
|
-
* @param detoxConfig { DetoxInternals.RuntimeConfig }
|
15
10
|
* @param deviceRegistry { DeviceRegistry }
|
16
11
|
* @param applesimutils { AppleSimUtils }
|
17
12
|
* @param simulatorLauncher { SimulatorLauncher }
|
18
13
|
*/
|
19
|
-
constructor({
|
14
|
+
constructor({ deviceRegistry, applesimutils, simulatorLauncher }) {
|
20
15
|
super();
|
21
16
|
this._deviceRegistry = deviceRegistry;
|
22
17
|
this._applesimutils = applesimutils;
|
23
18
|
this._simulatorLauncher = simulatorLauncher;
|
24
19
|
this._launchInfo = {};
|
25
|
-
this._shouldShutdown = detoxConfig.behavior.cleanup.shutdownDevice;
|
26
|
-
}
|
27
|
-
|
28
|
-
async init() {
|
29
|
-
await this._deviceRegistry.unregisterZombieDevices();
|
30
20
|
}
|
31
21
|
|
32
22
|
/**
|
@@ -34,15 +24,16 @@ class SimulatorAllocDriver extends AllocationDriverBase {
|
|
34
24
|
* @return {Promise<IosSimulatorCookie>}
|
35
25
|
*/
|
36
26
|
async allocate(deviceConfig) {
|
37
|
-
const deviceQuery =
|
27
|
+
const deviceQuery = this._adaptQuery(deviceConfig.device);
|
38
28
|
|
39
29
|
// TODO Delegate this onto a well tested allocator class
|
40
|
-
const udid = await this._deviceRegistry.
|
30
|
+
const udid = await this._deviceRegistry.allocateDevice(async () => {
|
41
31
|
return await this._findOrCreateDevice(deviceQuery);
|
42
32
|
});
|
43
33
|
|
34
|
+
const deviceComment = this._commentDevice(deviceQuery);
|
44
35
|
if (!udid) {
|
45
|
-
throw new DetoxRuntimeError(`Failed to find device matching ${
|
36
|
+
throw new DetoxRuntimeError(`Failed to find device matching ${deviceComment}`);
|
46
37
|
}
|
47
38
|
|
48
39
|
this._launchInfo[udid] = { deviceConfig };
|
@@ -67,40 +58,21 @@ class SimulatorAllocDriver extends AllocationDriverBase {
|
|
67
58
|
async free(cookie, options = {}) {
|
68
59
|
const { udid } = cookie;
|
69
60
|
|
70
|
-
|
71
|
-
await this._doShutdown(udid);
|
72
|
-
await this._deviceRegistry.unregisterDevice(udid);
|
73
|
-
} else {
|
74
|
-
await this._deviceRegistry.releaseDevice(udid);
|
75
|
-
}
|
76
|
-
}
|
61
|
+
await this._deviceRegistry.disposeDevice(udid);
|
77
62
|
|
78
|
-
|
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 {
|
63
|
+
if (options.shutdown) {
|
95
64
|
await this._simulatorLauncher.shutdown(udid);
|
96
|
-
} catch (err) {
|
97
|
-
log.warn({ err }, `Failed to shutdown simulator ${udid}`);
|
98
65
|
}
|
99
66
|
}
|
100
67
|
|
101
68
|
/***
|
102
69
|
* @private
|
103
|
-
* @param {
|
70
|
+
* @param deviceQuery {{
|
71
|
+
* byId?: string;
|
72
|
+
* byName?: string;
|
73
|
+
* byType?: string;
|
74
|
+
* byOS?: string;
|
75
|
+
* }}
|
104
76
|
* @returns {Promise<String>}
|
105
77
|
*/
|
106
78
|
async _findOrCreateDevice(deviceQuery) {
|
@@ -111,7 +83,6 @@ class SimulatorAllocDriver extends AllocationDriverBase {
|
|
111
83
|
if (_.isEmpty(free)) {
|
112
84
|
const prototypeDevice = taken[0];
|
113
85
|
udid = this._applesimutils.create(prototypeDevice);
|
114
|
-
await this._runScreenshotWorkaround(udid);
|
115
86
|
} else {
|
116
87
|
udid = free[0].udid;
|
117
88
|
}
|
@@ -119,30 +90,11 @@ class SimulatorAllocDriver extends AllocationDriverBase {
|
|
119
90
|
return udid;
|
120
91
|
}
|
121
92
|
|
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
|
-
*/
|
139
93
|
async _groupDevicesByStatus(deviceQuery) {
|
140
94
|
const searchResults = await this._queryDevices(deviceQuery);
|
141
|
-
const takenDevices = this._deviceRegistry.
|
142
|
-
|
143
|
-
const { taken, free } = _.groupBy(searchResults, ({ udid }) =>
|
144
|
-
return takenDevices.includes(udid) ? 'taken' : 'free';
|
145
|
-
});
|
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');
|
146
98
|
|
147
99
|
const targetOS = _.get(taken, '0.os.identifier');
|
148
100
|
const isMatching = targetOS && { os: { identifier: targetOS } };
|
@@ -153,25 +105,43 @@ class SimulatorAllocDriver extends AllocationDriverBase {
|
|
153
105
|
};
|
154
106
|
}
|
155
107
|
|
156
|
-
/**
|
157
|
-
* @private
|
158
|
-
* @param {SimulatorQuery} deviceQuery
|
159
|
-
*/
|
160
108
|
async _queryDevices(deviceQuery) {
|
161
109
|
const result = await this._applesimutils.list(
|
162
110
|
deviceQuery,
|
163
|
-
`Searching for device ${deviceQuery} ...`
|
111
|
+
`Searching for device ${this._commentQuery(deviceQuery)} ...`
|
164
112
|
);
|
165
113
|
|
166
114
|
if (_.isEmpty(result)) {
|
167
115
|
throw new DetoxRuntimeError({
|
168
|
-
message: `Failed to find a device ${deviceQuery}`,
|
116
|
+
message: `Failed to find a device ${this._commentQuery(deviceQuery)}`,
|
169
117
|
hint: `Run 'applesimutils --list' to list your supported devices. ` +
|
170
118
|
`It is advised only to specify a device type, e.g., "iPhone Xʀ" and avoid explicit search by OS version.`
|
171
119
|
});
|
172
120
|
}
|
173
121
|
return result;
|
174
122
|
}
|
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
|
+
}
|
175
145
|
}
|
176
146
|
|
177
147
|
module.exports = SimulatorAllocDriver;
|
@@ -1,24 +1,20 @@
|
|
1
|
-
|
1
|
+
const DeviceLauncher = require('../../../common/drivers/DeviceLauncher');
|
2
|
+
|
3
|
+
class SimulatorLauncher extends DeviceLauncher {
|
2
4
|
constructor({ applesimutils, eventEmitter }) {
|
5
|
+
super(eventEmitter);
|
3
6
|
this._applesimutils = applesimutils;
|
4
|
-
this._eventEmitter = eventEmitter;
|
5
7
|
}
|
6
8
|
|
7
9
|
async launch(udid, type, bootArgs, headless) {
|
8
10
|
const coldBoot = await this._applesimutils.boot(udid, bootArgs, headless);
|
9
|
-
|
11
|
+
await this._notifyBootEvent(udid, type, coldBoot, headless);
|
10
12
|
}
|
11
13
|
|
12
14
|
async shutdown(udid) {
|
13
|
-
|
14
|
-
await this._eventEmitter.emit('beforeShutdownDevice', { deviceId: udid });
|
15
|
-
}
|
16
|
-
|
15
|
+
await this._notifyPreShutdown(udid);
|
17
16
|
await this._applesimutils.shutdown(udid);
|
18
|
-
|
19
|
-
if (this._eventEmitter) {
|
20
|
-
await this._eventEmitter.emit('shutdownDevice', { deviceId: udid });
|
21
|
-
}
|
17
|
+
await this._notifyShutdownCompleted(udid);
|
22
18
|
}
|
23
19
|
}
|
24
20
|
|