detox 20.15.1-prerelease.0 → 20.17.0
Sign up to get free protection for your applications and to get access to all the features.
- package/.eslintrc.js +1 -5
- package/Detox-android/com/wix/detox/20.17.0/detox-20.17.0-javadoc.jar +0 -0
- package/Detox-android/com/wix/detox/20.17.0/detox-20.17.0-javadoc.jar.md5 +1 -0
- package/Detox-android/com/wix/detox/20.17.0/detox-20.17.0-javadoc.jar.sha1 +1 -0
- package/Detox-android/com/wix/detox/20.17.0/detox-20.17.0-javadoc.jar.sha256 +1 -0
- package/Detox-android/com/wix/detox/20.17.0/detox-20.17.0-javadoc.jar.sha512 +1 -0
- package/Detox-android/com/wix/detox/{20.15.0-prerelease.0/detox-20.15.0-prerelease.0-sources.jar → 20.17.0/detox-20.17.0-sources.jar} +0 -0
- package/Detox-android/com/wix/detox/20.17.0/detox-20.17.0-sources.jar.md5 +1 -0
- package/Detox-android/com/wix/detox/20.17.0/detox-20.17.0-sources.jar.sha1 +1 -0
- package/Detox-android/com/wix/detox/20.17.0/detox-20.17.0-sources.jar.sha256 +1 -0
- package/Detox-android/com/wix/detox/20.17.0/detox-20.17.0-sources.jar.sha512 +1 -0
- package/Detox-android/com/wix/detox/20.17.0/detox-20.17.0.aar +0 -0
- package/Detox-android/com/wix/detox/20.17.0/detox-20.17.0.aar.md5 +1 -0
- package/Detox-android/com/wix/detox/20.17.0/detox-20.17.0.aar.sha1 +1 -0
- package/Detox-android/com/wix/detox/20.17.0/detox-20.17.0.aar.sha256 +1 -0
- package/Detox-android/com/wix/detox/20.17.0/detox-20.17.0.aar.sha512 +1 -0
- package/Detox-android/com/wix/detox/{20.15.0-prerelease.0/detox-20.15.0-prerelease.0.pom → 20.17.0/detox-20.17.0.pom} +1 -1
- package/Detox-android/com/wix/detox/20.17.0/detox-20.17.0.pom.md5 +1 -0
- package/Detox-android/com/wix/detox/20.17.0/detox-20.17.0.pom.sha1 +1 -0
- package/Detox-android/com/wix/detox/20.17.0/detox-20.17.0.pom.sha256 +1 -0
- package/Detox-android/com/wix/detox/20.17.0/detox-20.17.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/build.gradle +2 -10
- package/android/detox/build.gradle +2 -0
- package/android/detox/proguard-rules-app.pro +1 -2
- package/android/detox/publishing.gradle +2 -2
- package/android/detox/src/full/java/com/wix/detox/espresso/DetoxAction.java +11 -6
- package/android/detox/src/full/java/com/wix/detox/espresso/common/ReactSliderHelper.kt +5 -5
- package/android/detox/src/main/java/com/wix/detox/espresso/DeviceDisplay.kt +1 -1
- package/android/detox/src/main/java/com/wix/detox/espresso/scroll/ScrollHelper.java +113 -16
- package/android/detox/src/testFull/java/com/wix/detox/espresso/action/GetAttributesActionTest.kt +3 -3
- package/android/detox/src/testFull/java/com/wix/detox/espresso/common/ReactSliderHelperTest.kt +25 -23
- package/android/detox/src/testFull/java/com/wix/detox/espresso/scroll/ScrollHelperTest.kt +188 -0
- package/android/rninfo.gradle +27 -15
- package/android/settings.gradle +13 -1
- package/detox.d.ts +26 -20
- package/jest.config.js +1 -1
- package/local-cli/init.js +1 -1
- package/package.json +22 -18
- package/runners/jest/testEnvironment/index.js +24 -9
- package/src/DetoxWorker.js +1 -1
- package/src/android/actions/native.js +2 -2
- package/src/android/core/NativeElement.js +3 -4
- package/src/android/espressoapi/DetoxAction.js +9 -1
- package/src/android/interactions/native.js +2 -2
- package/src/android/matchers/native.js +1 -1
- package/src/artifacts/providers/index.js +1 -1
- package/src/artifacts/screenshot/SimulatorScreenshotPlugin.js +0 -1
- package/src/artifacts/templates/artifact/Artifact.js +1 -1
- package/src/client/AsyncWebSocket.js +2 -2
- package/src/client/Client.js +2 -2
- package/src/devices/allocation/drivers/android/attached/AttachedAndroidAllocDriver.js +0 -1
- package/src/devices/allocation/drivers/android/emulator/EmulatorAllocDriver.js +0 -1
- package/src/devices/allocation/drivers/android/emulator/EmulatorVersionResolver.js +1 -1
- package/src/devices/allocation/drivers/ios/SimulatorAllocDriver.js +0 -1
- package/src/devices/allocation/factories/android.js +1 -1
- package/src/devices/allocation/factories/ios.js +1 -1
- package/src/devices/common/drivers/android/exec/ADB.js +1 -2
- package/src/devices/common/drivers/android/tools/ApkValidator.js +1 -1
- package/src/devices/common/drivers/android/tools/AppInstallHelper.js +0 -2
- package/src/devices/common/drivers/ios/tools/AppleSimUtils.js +111 -15
- package/src/devices/runtime/drivers/android/AndroidDriver.js +1 -1
- package/src/devices/runtime/drivers/android/emulator/EmulatorDriver.js +0 -1
- package/src/devices/runtime/factories/ios.js +0 -2
- package/src/ios/expectTwo.js +6 -3
- package/src/ipc/IPCClient.js +2 -2
- package/src/ipc/IPCServer.js +4 -4
- package/src/realms/DetoxContext.js +3 -3
- package/src/realms/DetoxPrimaryContext.js +74 -29
- package/src/realms/DetoxSecondaryContext.js +2 -2
- package/src/utils/childProcess/exec.js +3 -2
- package/src/utils/invocationTraceDescriptions.js +3 -2
- package/tsconfig.json +1 -1
- package/Detox-android/com/wix/detox/20.15.0-prerelease.0/detox-20.15.0-prerelease.0-javadoc.jar +0 -0
- package/Detox-android/com/wix/detox/20.15.0-prerelease.0/detox-20.15.0-prerelease.0-javadoc.jar.md5 +0 -1
- package/Detox-android/com/wix/detox/20.15.0-prerelease.0/detox-20.15.0-prerelease.0-javadoc.jar.sha1 +0 -1
- package/Detox-android/com/wix/detox/20.15.0-prerelease.0/detox-20.15.0-prerelease.0-javadoc.jar.sha256 +0 -1
- package/Detox-android/com/wix/detox/20.15.0-prerelease.0/detox-20.15.0-prerelease.0-javadoc.jar.sha512 +0 -1
- package/Detox-android/com/wix/detox/20.15.0-prerelease.0/detox-20.15.0-prerelease.0-sources.jar.md5 +0 -1
- package/Detox-android/com/wix/detox/20.15.0-prerelease.0/detox-20.15.0-prerelease.0-sources.jar.sha1 +0 -1
- package/Detox-android/com/wix/detox/20.15.0-prerelease.0/detox-20.15.0-prerelease.0-sources.jar.sha256 +0 -1
- package/Detox-android/com/wix/detox/20.15.0-prerelease.0/detox-20.15.0-prerelease.0-sources.jar.sha512 +0 -1
- package/Detox-android/com/wix/detox/20.15.0-prerelease.0/detox-20.15.0-prerelease.0.aar +0 -0
- package/Detox-android/com/wix/detox/20.15.0-prerelease.0/detox-20.15.0-prerelease.0.aar.md5 +0 -1
- package/Detox-android/com/wix/detox/20.15.0-prerelease.0/detox-20.15.0-prerelease.0.aar.sha1 +0 -1
- package/Detox-android/com/wix/detox/20.15.0-prerelease.0/detox-20.15.0-prerelease.0.aar.sha256 +0 -1
- package/Detox-android/com/wix/detox/20.15.0-prerelease.0/detox-20.15.0-prerelease.0.aar.sha512 +0 -1
- package/Detox-android/com/wix/detox/20.15.0-prerelease.0/detox-20.15.0-prerelease.0.pom.md5 +0 -1
- package/Detox-android/com/wix/detox/20.15.0-prerelease.0/detox-20.15.0-prerelease.0.pom.sha1 +0 -1
- package/Detox-android/com/wix/detox/20.15.0-prerelease.0/detox-20.15.0-prerelease.0.pom.sha256 +0 -1
- package/Detox-android/com/wix/detox/20.15.0-prerelease.0/detox-20.15.0-prerelease.0.pom.sha512 +0 -1
package/src/client/Client.js
CHANGED
@@ -187,14 +187,14 @@ class Client {
|
|
187
187
|
this._whenAppIsReady = new Deferred();
|
188
188
|
|
189
189
|
await this._whenAppIsConnected.promise;
|
190
|
-
// TODO: optimize traffic (!) - we can just listen for 'ready' event
|
190
|
+
// TODO [2024-12-01]: optimize traffic (!) - we can just listen for 'ready' event
|
191
191
|
// if app always sends it upon load completion. On iOS it works,
|
192
192
|
// but not on Android. Afterwards, this will suffice:
|
193
193
|
//
|
194
194
|
// await this._whenAppIsReady.promise;
|
195
195
|
}
|
196
196
|
|
197
|
-
// TODO: move to else branch after the optimization
|
197
|
+
// TODO [2024-12-01]: move to else branch after the optimization ↑↑
|
198
198
|
if (!this._whenAppIsReady.isResolved()) {
|
199
199
|
this._whenAppIsReady = new Deferred();
|
200
200
|
await this.sendAction(new actions.Ready());
|
@@ -7,7 +7,7 @@ class EmulatorVersionResolver {
|
|
7
7
|
this.version = undefined;
|
8
8
|
}
|
9
9
|
|
10
|
-
async resolve(isHeadless = false) {
|
10
|
+
async resolve(isHeadless = false) {
|
11
11
|
if (!this.version) {
|
12
12
|
this.version = await this._resolve(isHeadless);
|
13
13
|
}
|
@@ -39,7 +39,6 @@ class SimulatorAllocDriver {
|
|
39
39
|
async allocate(deviceConfig) {
|
40
40
|
const deviceQuery = new SimulatorQuery(deviceConfig.device);
|
41
41
|
|
42
|
-
// TODO Delegate this onto a well tested allocator class
|
43
42
|
const udid = await this._deviceRegistry.registerDevice(async () => {
|
44
43
|
return await this._findOrCreateDevice(deviceQuery);
|
45
44
|
});
|
@@ -42,7 +42,7 @@ class AndroidEmulator extends DeviceAllocatorFactory {
|
|
42
42
|
}
|
43
43
|
|
44
44
|
class AndroidAttached extends DeviceAllocatorFactory {
|
45
|
-
_createDriver({ detoxSession
|
45
|
+
_createDriver({ detoxSession }) {
|
46
46
|
const serviceLocator = require('../../servicelocator/android');
|
47
47
|
const adb = serviceLocator.adb;
|
48
48
|
const DeviceRegistry = require('../../allocation/DeviceRegistry');
|
@@ -2,7 +2,7 @@
|
|
2
2
|
const DeviceAllocatorFactory = require('./base');
|
3
3
|
|
4
4
|
class IosSimulator extends DeviceAllocatorFactory {
|
5
|
-
_createDriver({ detoxConfig, detoxSession
|
5
|
+
_createDriver({ detoxConfig, detoxSession }) {
|
6
6
|
const AppleSimUtils = require('../../../devices/common/drivers/ios/tools/AppleSimUtils');
|
7
7
|
const applesimutils = new AppleSimUtils();
|
8
8
|
|
@@ -8,7 +8,7 @@ const { escape } = require('../../../../../utils/pipeCommands');
|
|
8
8
|
const DeviceHandle = require('../tools/DeviceHandle');
|
9
9
|
const EmulatorHandle = require('../tools/EmulatorHandle');
|
10
10
|
|
11
|
-
const INSTALL_TIMEOUT = 45000;
|
11
|
+
const INSTALL_TIMEOUT = 45000;
|
12
12
|
|
13
13
|
class ADB {
|
14
14
|
constructor() {
|
@@ -345,7 +345,6 @@ class ADB {
|
|
345
345
|
return this.adbCmd(deviceId, `emu kill`);
|
346
346
|
}
|
347
347
|
|
348
|
-
// TODO refactor the whole thing so as to make usage of BinaryExec -- similar to EmulatorExec
|
349
348
|
async adbCmd(deviceId, params, options = {}) {
|
350
349
|
const serial = `${deviceId ? `-s ${deviceId}` : ''}`;
|
351
350
|
const cmd = `"${this.adbBin}" ${serial} ${params}`;
|
@@ -1,6 +1,6 @@
|
|
1
1
|
const DetoxRuntimeError = require('../../../../../errors/DetoxRuntimeError');
|
2
2
|
|
3
|
-
const setupGuideHint = 'For further assistance, visit the
|
3
|
+
const setupGuideHint = 'For further assistance, visit the project setup guide (select the Android tabs): https://wix.github.io/Detox/docs/introduction/project-setup';
|
4
4
|
|
5
5
|
class ApkValidator {
|
6
6
|
constructor(aapt) {
|
@@ -10,21 +10,123 @@ const environment = require('../../../../../utils/environment');
|
|
10
10
|
const log = require('../../../../../utils/logger').child({ cat: 'device' });
|
11
11
|
const { quote } = require('../../../../../utils/shellQuote');
|
12
12
|
|
13
|
+
const PERMISSIONS_VALUES = {
|
14
|
+
YES: 'YES',
|
15
|
+
NO: 'NO',
|
16
|
+
UNSET: 'unset',
|
17
|
+
LIMITED: 'limited',
|
18
|
+
};
|
19
|
+
|
20
|
+
const SIMCTL_SET_PERMISSION_ACTIONS ={
|
21
|
+
GRANT: 'grant',
|
22
|
+
REVOKE: 'revoke',
|
23
|
+
RESET: 'reset',
|
24
|
+
};
|
25
|
+
|
13
26
|
class AppleSimUtils {
|
14
27
|
async setPermissions(udid, bundleId, permissionsObj) {
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
28
|
+
for (const [service, value] of Object.entries(permissionsObj)) {
|
29
|
+
switch (service) {
|
30
|
+
case 'location':
|
31
|
+
switch (value) {
|
32
|
+
case 'always':
|
33
|
+
await this.setPermissionWithSimctl(udid, bundleId, SIMCTL_SET_PERMISSION_ACTIONS.GRANT, 'location-always');
|
34
|
+
break;
|
35
|
+
|
36
|
+
case 'inuse':
|
37
|
+
await this.setPermissionWithSimctl(udid, bundleId, SIMCTL_SET_PERMISSION_ACTIONS.GRANT, 'location');
|
38
|
+
break;
|
39
|
+
|
40
|
+
case 'never':
|
41
|
+
await this.setPermissionWithSimctl(udid, bundleId, SIMCTL_SET_PERMISSION_ACTIONS.REVOKE, 'location');
|
42
|
+
break;
|
43
|
+
|
44
|
+
case 'unset':
|
45
|
+
await this.setPermissionWithSimctl(udid, bundleId, SIMCTL_SET_PERMISSION_ACTIONS.RESET, 'location');
|
46
|
+
break;
|
47
|
+
}
|
48
|
+
|
49
|
+
break;
|
50
|
+
|
51
|
+
case 'contacts':
|
52
|
+
if (value === PERMISSIONS_VALUES.LIMITED) {
|
53
|
+
await this.setPermissionWithSimctl(udid, bundleId, SIMCTL_SET_PERMISSION_ACTIONS.GRANT, 'contacts-limited');
|
54
|
+
} else {
|
55
|
+
await this.setPermissionWithAppleSimUtils(udid, bundleId, service, value);
|
56
|
+
}
|
57
|
+
break;
|
58
|
+
|
59
|
+
case 'photos':
|
60
|
+
if (value === PERMISSIONS_VALUES.LIMITED) {
|
61
|
+
await this.setPermissionWithSimctl(udid, bundleId, SIMCTL_SET_PERMISSION_ACTIONS.GRANT, 'photos-add');
|
62
|
+
} else {
|
63
|
+
await this.setPermissionWithAppleSimUtils(udid, bundleId, service, value);
|
64
|
+
}
|
65
|
+
break;
|
66
|
+
|
67
|
+
// eslint-disable-next-line no-fallthrough
|
68
|
+
case 'calendar':
|
69
|
+
case 'camera':
|
70
|
+
case 'medialibrary':
|
71
|
+
case 'microphone':
|
72
|
+
case 'motion':
|
73
|
+
case 'reminders':
|
74
|
+
case 'siri':
|
75
|
+
// Simctl uses kebab-case for service names.
|
76
|
+
const simctlService = service.replace('medialibrary', 'media-library');
|
77
|
+
await this.setPermissionWithSimctl(udid, bundleId, this.basicPermissionValueToSimctlAction(value), simctlService);
|
78
|
+
break;
|
79
|
+
|
80
|
+
// Requires AppleSimUtils: unsupported by latest Simctl at the moment of writing this code.
|
81
|
+
// eslint-disable-next-line no-fallthrough
|
82
|
+
case 'notifications':
|
83
|
+
case 'health':
|
84
|
+
case 'homekit':
|
85
|
+
case 'speech':
|
86
|
+
case 'faceid':
|
87
|
+
case 'userTracking':
|
88
|
+
await this.setPermissionWithAppleSimUtils(udid, bundleId, service, value);
|
89
|
+
break;
|
90
|
+
}
|
91
|
+
}
|
92
|
+
}
|
93
|
+
|
94
|
+
basicPermissionValueToSimctlAction(value) {
|
95
|
+
switch (value) {
|
96
|
+
case PERMISSIONS_VALUES.YES:
|
97
|
+
return SIMCTL_SET_PERMISSION_ACTIONS.GRANT;
|
98
|
+
|
99
|
+
case PERMISSIONS_VALUES.NO:
|
100
|
+
return SIMCTL_SET_PERMISSION_ACTIONS.REVOKE;
|
101
|
+
|
102
|
+
case PERMISSIONS_VALUES.UNSET:
|
103
|
+
return SIMCTL_SET_PERMISSION_ACTIONS.RESET;
|
104
|
+
}
|
105
|
+
}
|
19
106
|
|
107
|
+
async setPermissionWithSimctl(udid, bundleId, action, service) {
|
20
108
|
const options = {
|
21
|
-
|
109
|
+
cmd: `privacy ${udid} ${action} ${service} ${bundleId}`,
|
22
110
|
statusLogs: {
|
23
|
-
trying: `Trying to set permissions...`,
|
24
|
-
successful:
|
111
|
+
trying: `Trying to set permissions with Simctl: ${action} ${service}...`,
|
112
|
+
successful: `${service} permissions are set`
|
25
113
|
},
|
26
114
|
retries: 1,
|
27
115
|
};
|
116
|
+
|
117
|
+
await this._execSimctl(options);
|
118
|
+
}
|
119
|
+
|
120
|
+
async setPermissionWithAppleSimUtils(udid, bundleId, service, value) {
|
121
|
+
const options = {
|
122
|
+
args: `--byId ${udid} --bundle ${bundleId} --restartSB --setPermissions ${service}=${value}`,
|
123
|
+
statusLogs: {
|
124
|
+
trying: `Trying to set permissions with AppleSimUtils: ${service}=${value}...`,
|
125
|
+
successful: `${service} permissions are set`
|
126
|
+
},
|
127
|
+
retries: 1,
|
128
|
+
};
|
129
|
+
|
28
130
|
await this._execAppleSimUtils(options);
|
29
131
|
}
|
30
132
|
|
@@ -33,6 +135,7 @@ class AppleSimUtils {
|
|
33
135
|
args: `--list ${joinArgs(query)}`,
|
34
136
|
retries: 1,
|
35
137
|
statusLogs: listOptions.trying ? { trying: listOptions.trying } : undefined,
|
138
|
+
maxBuffer: 4 * 1024 * 1024,
|
36
139
|
};
|
37
140
|
const response = await this._execAppleSimUtils(options);
|
38
141
|
const parsed = this._parseResponseFromAppleSimUtils(response);
|
@@ -318,14 +421,7 @@ class AppleSimUtils {
|
|
318
421
|
}
|
319
422
|
|
320
423
|
async setLocation(udid, lat, lon) {
|
321
|
-
|
322
|
-
if (_.get(result, 'stdout')) {
|
323
|
-
await childProcess.execWithRetriesAndLogs(`fbsimctl ${udid} set_location ${lat} ${lon}`, { retries: 1 });
|
324
|
-
} else {
|
325
|
-
throw new DetoxRuntimeError(`setLocation currently supported only through fbsimctl.
|
326
|
-
Install fbsimctl using:
|
327
|
-
"brew tap facebook/fb && export CODE_SIGNING_REQUIRED=NO && brew install fbsimctl"`);
|
328
|
-
}
|
424
|
+
await this._execSimctl({ cmd: `location ${udid} set ${lat},${lon}` });
|
329
425
|
}
|
330
426
|
|
331
427
|
async resetContentAndSettings(udid) {
|
@@ -280,7 +280,7 @@ class AndroidDriver extends DeviceDriverBase {
|
|
280
280
|
throw new DetoxRuntimeError({
|
281
281
|
message: `The test APK could not be found at path: '${testApkPath}'`,
|
282
282
|
hint: 'Try running the detox build command, and make sure it was configured to execute a build command (e.g. \'./gradlew assembleAndroidTest\')' +
|
283
|
-
'\nFor further assistance, visit the
|
283
|
+
'\nFor further assistance, visit the project setup guide (select the Android tabs): https://wix.github.io/Detox/docs/introduction/project-setup',
|
284
284
|
});
|
285
285
|
}
|
286
286
|
return testApkPath;
|
@@ -2,8 +2,6 @@ const RuntimeDeviceFactory = require('./base');
|
|
2
2
|
|
3
3
|
class RuntimeDriverFactoryIos extends RuntimeDeviceFactory {
|
4
4
|
_createDriverDependencies(commonDeps) {
|
5
|
-
const { eventEmitter } = commonDeps;
|
6
|
-
|
7
5
|
const AppleSimUtils = require('../../../devices/common/drivers/ios/tools/AppleSimUtils');
|
8
6
|
const applesimutils = new AppleSimUtils();
|
9
7
|
|
package/src/ios/expectTwo.js
CHANGED
@@ -247,10 +247,13 @@ class Element {
|
|
247
247
|
return this.withAction('scroll', traceDescription, pixels, direction, startPositionX, startPositionY);
|
248
248
|
}
|
249
249
|
|
250
|
-
scrollTo(edge) {
|
250
|
+
scrollTo(edge, startPositionX = NaN, startPositionY = NaN) {
|
251
251
|
if (!['left', 'right', 'top', 'bottom'].some(option => option === edge)) throw new Error('edge should be one of [left, right, top, bottom], but got ' + edge);
|
252
|
-
|
253
|
-
|
252
|
+
if (typeof startPositionX !== 'number') throw new Error('startPositionX should be a number, but got ' + (startPositionX + (' (' + (typeof startPositionX + ')'))));
|
253
|
+
if (typeof startPositionY !== 'number') throw new Error('startPositionY should be a number, but got ' + (startPositionY + (' (' + (typeof startPositionY + ')'))));
|
254
|
+
|
255
|
+
const traceDescription = actionDescription.scrollTo(edge, startPositionX, startPositionY);
|
256
|
+
return this.withAction('scrollTo', traceDescription, edge, startPositionX, startPositionY);
|
254
257
|
}
|
255
258
|
|
256
259
|
swipe(direction, speed = 'fast', normalizedSwipeOffset = NaN, normalizedStartingPointX = NaN, normalizedStartingPointY = NaN) {
|
package/src/ipc/IPCClient.js
CHANGED
@@ -60,8 +60,8 @@ class IPCClient {
|
|
60
60
|
this._sessionState.patch(sessionState);
|
61
61
|
}
|
62
62
|
|
63
|
-
async allocateDevice() {
|
64
|
-
const { deviceCookie, error } = deserializeObjectWithError(await this._emit('allocateDevice', {}));
|
63
|
+
async allocateDevice(deviceConfig) {
|
64
|
+
const { deviceCookie, error } = deserializeObjectWithError(await this._emit('allocateDevice', { deviceConfig }));
|
65
65
|
if (error) {
|
66
66
|
throw error;
|
67
67
|
}
|
package/src/ipc/IPCServer.js
CHANGED
@@ -9,7 +9,7 @@ class IPCServer {
|
|
9
9
|
* @param {import('./SessionState')} options.sessionState
|
10
10
|
* @param {Detox.Logger} options.logger
|
11
11
|
* @param {object} options.callbacks
|
12
|
-
* @param {() => Promise<any>} options.callbacks.onAllocateDevice
|
12
|
+
* @param {(deviceConfig: DetoxInternals.RuntimeConfig['device']) => Promise<any>} options.callbacks.onAllocateDevice
|
13
13
|
* @param {(cookie: any) => Promise<void>} options.callbacks.onDeallocateDevice
|
14
14
|
*/
|
15
15
|
constructor({ sessionState, logger, callbacks }) {
|
@@ -40,7 +40,7 @@ class IPCServer {
|
|
40
40
|
this._ipc.config.logger = (msg) => this._logger.trace(msg);
|
41
41
|
|
42
42
|
await new Promise((resolve) => {
|
43
|
-
//
|
43
|
+
// It is worth to handle rejection here some day
|
44
44
|
this._ipc.serve(() => resolve());
|
45
45
|
this._ipc.server.on('conductEarlyTeardown', this.onConductEarlyTeardown.bind(this));
|
46
46
|
this._ipc.server.on('registerContext', this.onRegisterContext.bind(this));
|
@@ -104,11 +104,11 @@ class IPCServer {
|
|
104
104
|
this._ipc.server.broadcast('sessionStateUpdate', newState);
|
105
105
|
}
|
106
106
|
|
107
|
-
async onAllocateDevice(
|
107
|
+
async onAllocateDevice({ deviceConfig }, socket) {
|
108
108
|
let deviceCookie;
|
109
109
|
|
110
110
|
try {
|
111
|
-
deviceCookie = await this._callbacks.onAllocateDevice();
|
111
|
+
deviceCookie = await this._callbacks.onAllocateDevice(deviceConfig);
|
112
112
|
this._ipc.server.emit(socket, 'allocateDeviceDone', { deviceCookie });
|
113
113
|
} catch (error) {
|
114
114
|
this._ipc.server.emit(socket, 'allocateDeviceDone', serializeObjectWithError({ error }));
|
@@ -47,7 +47,7 @@ class DetoxContext {
|
|
47
47
|
this[$sessionState] = this[$restoreSessionState]();
|
48
48
|
|
49
49
|
/**
|
50
|
-
* @type {DetoxLogger & Detox.Logger}
|
50
|
+
* @type {import('../logger/').DetoxLogger & Detox.Logger}
|
51
51
|
*/
|
52
52
|
this[symbols.logger] = new DetoxLogger({
|
53
53
|
file: temporary.for.jsonl(`${this[$sessionState].id}.${process.pid}`),
|
@@ -152,10 +152,10 @@ class DetoxContext {
|
|
152
152
|
}
|
153
153
|
|
154
154
|
/** @abstract */
|
155
|
-
async [symbols.allocateDevice]() {}
|
155
|
+
async [symbols.allocateDevice](_deviceConfig) {}
|
156
156
|
|
157
157
|
/** @abstract */
|
158
|
-
async [symbols.deallocateDevice]() {}
|
158
|
+
async [symbols.deallocateDevice](_deviceCookie) {}
|
159
159
|
|
160
160
|
async [symbols.uninstallWorker]() {
|
161
161
|
try {
|
@@ -23,7 +23,9 @@ const _emergencyTeardown = Symbol('emergencyTeardown');
|
|
23
23
|
const _lifecycleLogger = Symbol('lifecycleLogger');
|
24
24
|
const _sessionFile = Symbol('sessionFile');
|
25
25
|
const _logFinalError = Symbol('logFinalError');
|
26
|
-
const
|
26
|
+
const _cookieAllocators = Symbol('cookieAllocators');
|
27
|
+
const _deviceAllocators = Symbol('deviceAllocators');
|
28
|
+
const _createDeviceAllocator = Symbol('createDeviceAllocator');
|
27
29
|
//#endregion
|
28
30
|
|
29
31
|
class DetoxPrimaryContext extends DetoxContext {
|
@@ -32,7 +34,8 @@ class DetoxPrimaryContext extends DetoxContext {
|
|
32
34
|
|
33
35
|
this[_dirty] = false;
|
34
36
|
this[_wss] = null;
|
35
|
-
this[
|
37
|
+
this[_cookieAllocators] = {};
|
38
|
+
this[_deviceAllocators] = {};
|
36
39
|
|
37
40
|
/** Path to file where the initial session object is serialized */
|
38
41
|
this[_sessionFile] = '';
|
@@ -85,7 +88,6 @@ class DetoxPrimaryContext extends DetoxContext {
|
|
85
88
|
const detoxConfig = await this[symbols.resolveConfig](opts);
|
86
89
|
|
87
90
|
const {
|
88
|
-
device: deviceConfig,
|
89
91
|
logger: loggerConfig,
|
90
92
|
session: sessionConfig
|
91
93
|
} = detoxConfig;
|
@@ -96,7 +98,6 @@ class DetoxPrimaryContext extends DetoxContext {
|
|
96
98
|
data: this[$sessionState],
|
97
99
|
}, getCurrentCommand());
|
98
100
|
|
99
|
-
// TODO: IPC Server creation ought to be delegated to a generator/factory.
|
100
101
|
const IPCServer = require('../ipc/IPCServer');
|
101
102
|
this[_ipcServer] = new IPCServer({
|
102
103
|
sessionState: this[$sessionState],
|
@@ -109,17 +110,6 @@ class DetoxPrimaryContext extends DetoxContext {
|
|
109
110
|
|
110
111
|
await this[_ipcServer].init();
|
111
112
|
|
112
|
-
const environmentFactory = require('../environmentFactory');
|
113
|
-
|
114
|
-
const { deviceAllocatorFactory } = environmentFactory.createFactories(deviceConfig);
|
115
|
-
this[_deviceAllocator] = deviceAllocatorFactory.createDeviceAllocator({
|
116
|
-
detoxConfig,
|
117
|
-
detoxSession: this[$sessionState],
|
118
|
-
});
|
119
|
-
|
120
|
-
await this[_deviceAllocator].init();
|
121
|
-
|
122
|
-
// TODO: Detox-server creation ought to be delegated to a generator/factory.
|
123
113
|
const DetoxServer = require('../server/DetoxServer');
|
124
114
|
if (sessionConfig.autoStart) {
|
125
115
|
this[_wss] = new DetoxServer({
|
@@ -132,7 +122,6 @@ class DetoxPrimaryContext extends DetoxContext {
|
|
132
122
|
await this[_wss].open();
|
133
123
|
}
|
134
124
|
|
135
|
-
// TODO: double check that this config is indeed propogated onto the client create at the detox-worker side
|
136
125
|
if (!sessionConfig.server && this[_wss]) {
|
137
126
|
// @ts-ignore
|
138
127
|
sessionConfig.server = `ws://localhost:${this[_wss].port}`;
|
@@ -162,17 +151,20 @@ class DetoxPrimaryContext extends DetoxContext {
|
|
162
151
|
}
|
163
152
|
|
164
153
|
/** @override */
|
165
|
-
async [symbols.allocateDevice]() {
|
166
|
-
const
|
167
|
-
const deviceCookie = await
|
154
|
+
async [symbols.allocateDevice](deviceConfig) {
|
155
|
+
const deviceAllocator = await this[_createDeviceAllocator](deviceConfig);
|
156
|
+
const deviceCookie = await deviceAllocator.allocate(deviceConfig);
|
157
|
+
this[_cookieAllocators][deviceCookie.id] = deviceAllocator;
|
168
158
|
|
169
159
|
try {
|
170
|
-
return await
|
160
|
+
return await deviceAllocator.postAllocate(deviceCookie);
|
171
161
|
} catch (e) {
|
172
162
|
try {
|
173
|
-
await
|
163
|
+
await deviceAllocator.free(deviceCookie, { shutdown: true });
|
174
164
|
} catch (e2) {
|
175
|
-
this[symbols.logger].error({ cat: 'device', err: e2 }, `Failed to free ${deviceCookie.name || deviceCookie.id} after a failed allocation`);
|
165
|
+
this[symbols.logger].error({ cat: 'device', err: e2 }, `Failed to free ${deviceCookie.name || deviceCookie.id} after a failed allocation attempt`);
|
166
|
+
} finally {
|
167
|
+
delete this[_cookieAllocators][deviceCookie.id];
|
176
168
|
}
|
177
169
|
|
178
170
|
throw e;
|
@@ -181,7 +173,17 @@ class DetoxPrimaryContext extends DetoxContext {
|
|
181
173
|
|
182
174
|
/** @override */
|
183
175
|
async [symbols.deallocateDevice](cookie) {
|
184
|
-
|
176
|
+
const deviceAllocator = this[_cookieAllocators][cookie.id];
|
177
|
+
if (!deviceAllocator) {
|
178
|
+
throw new DetoxRuntimeError({
|
179
|
+
message: `Cannot deallocate device ${cookie.id} because it was not allocated by this context.`,
|
180
|
+
hint: `See the actually known allocated devices below:`,
|
181
|
+
debugInfo: Object.keys(this[_cookieAllocators]).map(id => `- ${id}`).join('\n'),
|
182
|
+
});
|
183
|
+
}
|
184
|
+
|
185
|
+
await deviceAllocator.free(cookie);
|
186
|
+
delete this[_cookieAllocators][cookie.id];
|
185
187
|
}
|
186
188
|
|
187
189
|
/** @override */
|
@@ -191,11 +193,18 @@ class DetoxPrimaryContext extends DetoxContext {
|
|
191
193
|
await this[symbols.uninstallWorker]();
|
192
194
|
}
|
193
195
|
} finally {
|
194
|
-
|
195
|
-
|
196
|
-
this[
|
196
|
+
for (const key of Object.keys(this[_deviceAllocators])) {
|
197
|
+
const deviceAllocator = this[_deviceAllocators][key];
|
198
|
+
delete this[_deviceAllocators][key];
|
199
|
+
try {
|
200
|
+
await deviceAllocator.cleanup();
|
201
|
+
} catch (err) {
|
202
|
+
this[symbols.logger].error({ cat: 'device', err }, `Failed to cleanup the device allocation driver for ${key}`);
|
203
|
+
}
|
197
204
|
}
|
198
205
|
|
206
|
+
this[_cookieAllocators] = {};
|
207
|
+
|
199
208
|
if (this[_wss]) {
|
200
209
|
await this[_wss].close();
|
201
210
|
this[_wss] = null;
|
@@ -227,11 +236,18 @@ class DetoxPrimaryContext extends DetoxContext {
|
|
227
236
|
return;
|
228
237
|
}
|
229
238
|
|
230
|
-
|
231
|
-
this[
|
232
|
-
this[
|
239
|
+
for (const key of Object.keys(this[_deviceAllocators])) {
|
240
|
+
const deviceAllocator = this[_deviceAllocators][key];
|
241
|
+
delete this[_deviceAllocators][key];
|
242
|
+
try {
|
243
|
+
deviceAllocator.emergencyCleanup();
|
244
|
+
} catch (err) {
|
245
|
+
this[symbols.logger].error({ cat: 'device', err }, `Failed to clean up the device allocation driver for ${key} in emergency mode`);
|
246
|
+
}
|
233
247
|
}
|
234
248
|
|
249
|
+
this[_cookieAllocators] = {};
|
250
|
+
|
235
251
|
if (this[_wss]) {
|
236
252
|
this[_wss].close();
|
237
253
|
}
|
@@ -253,6 +269,35 @@ class DetoxPrimaryContext extends DetoxContext {
|
|
253
269
|
}
|
254
270
|
};
|
255
271
|
|
272
|
+
/** @param {Detox.DetoxDeviceConfig} deviceConfig */
|
273
|
+
[_createDeviceAllocator] = async (deviceConfig) => {
|
274
|
+
const deviceType = deviceConfig.type;
|
275
|
+
if (!this[_deviceAllocators][deviceType]) {
|
276
|
+
const environmentFactory = require('../environmentFactory');
|
277
|
+
const { deviceAllocatorFactory } = environmentFactory.createFactories(deviceConfig);
|
278
|
+
const { detoxConfig } = this[$sessionState];
|
279
|
+
const deviceAllocator = deviceAllocatorFactory.createDeviceAllocator({
|
280
|
+
detoxConfig,
|
281
|
+
detoxSession: this[$sessionState],
|
282
|
+
});
|
283
|
+
|
284
|
+
try {
|
285
|
+
await deviceAllocator.init();
|
286
|
+
this[_deviceAllocators][deviceType] = deviceAllocator;
|
287
|
+
} catch (e) {
|
288
|
+
try {
|
289
|
+
await deviceAllocator.cleanup();
|
290
|
+
} catch (e2) {
|
291
|
+
this[symbols.logger].error({ cat: 'device', err: e2 }, `Failed to cleanup the device allocation driver for ${deviceType} after a failed initialization`);
|
292
|
+
}
|
293
|
+
|
294
|
+
throw e;
|
295
|
+
}
|
296
|
+
}
|
297
|
+
|
298
|
+
return this[_deviceAllocators][deviceType];
|
299
|
+
};
|
300
|
+
|
256
301
|
[_logFinalError] = (err) => {
|
257
302
|
this[_lifecycleLogger].error(err, 'Encountered an error while merging the process logs:');
|
258
303
|
};
|
@@ -63,9 +63,9 @@ class DetoxSecondaryContext extends DetoxContext {
|
|
63
63
|
}
|
64
64
|
|
65
65
|
/** @override */
|
66
|
-
async [symbols.allocateDevice]() {
|
66
|
+
async [symbols.allocateDevice](deviceConfig) {
|
67
67
|
if (this[_ipcClient]) {
|
68
|
-
const deviceCookie = await this[_ipcClient].allocateDevice();
|
68
|
+
const deviceCookie = await this[_ipcClient].allocateDevice(deviceConfig);
|
69
69
|
return deviceCookie;
|
70
70
|
} else {
|
71
71
|
throw new DetoxInternalError('Detected an attempt to allocate a device using a non-initialized context.');
|
@@ -14,9 +14,10 @@ async function execWithRetriesAndLogs(bin, options = {}) {
|
|
14
14
|
interval = 1000,
|
15
15
|
prefix = null,
|
16
16
|
args = null,
|
17
|
-
timeout
|
17
|
+
timeout,
|
18
18
|
statusLogs = {},
|
19
19
|
verbosity = 'normal',
|
20
|
+
maxBuffer,
|
20
21
|
} = options;
|
21
22
|
|
22
23
|
const trackingId = execsCounter.inc();
|
@@ -35,7 +36,7 @@ async function execWithRetriesAndLogs(bin, options = {}) {
|
|
35
36
|
} else if (statusLogs.retrying) {
|
36
37
|
_logExecRetrying(logger, cmd, tryNumber, lastError);
|
37
38
|
}
|
38
|
-
result = await exec(cmd, { timeout });
|
39
|
+
result = await exec(cmd, _.omitBy({ timeout, maxBuffer }, _.isUndefined));
|
39
40
|
});
|
40
41
|
} catch (err) {
|
41
42
|
const failReason = err.code == null && timeout > 0
|
@@ -12,8 +12,9 @@ module.exports = {
|
|
12
12
|
pinchWithAngle: (direction, speed, angle) => `pinch with direction ${direction}, speed ${speed}, and angle ${angle}`,
|
13
13
|
replaceText: (value) => `replace input text: "${value}"`,
|
14
14
|
scroll: (amount, direction, startPositionX, startPositionY) =>
|
15
|
-
`scroll ${amount} pixels ${direction}${startPositionX !== undefined
|
16
|
-
scrollTo: (edge) =>
|
15
|
+
`scroll ${amount} pixels ${direction}${startPositionX !== undefined || startPositionY !== undefined ? ` from normalized position (${startPositionX}, ${startPositionY})` : ''}`,
|
16
|
+
scrollTo: (edge, startPositionX, startPositionY) =>
|
17
|
+
`scroll to ${edge} ${startPositionX !== undefined || startPositionY !== undefined ? ` from normalized position (${startPositionX}, ${startPositionY})` : ''}`,
|
17
18
|
scrollToIndex: (index) => `scroll to index #${index}`,
|
18
19
|
setColumnToValue: (column, value) => `set column ${column} to value ${value}`,
|
19
20
|
setDatePickerDate: (dateString, dateFormat) => `set date picker date to ${dateString} using format ${dateFormat}`,
|
package/tsconfig.json
CHANGED
package/Detox-android/com/wix/detox/20.15.0-prerelease.0/detox-20.15.0-prerelease.0-javadoc.jar
DELETED
Binary file
|
package/Detox-android/com/wix/detox/20.15.0-prerelease.0/detox-20.15.0-prerelease.0-javadoc.jar.md5
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
d186084aecacd72fb090ddb8b6e95039
|
package/Detox-android/com/wix/detox/20.15.0-prerelease.0/detox-20.15.0-prerelease.0-javadoc.jar.sha1
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
862c5158e6d2f299fb84d31bb91701cd2a957a84
|
@@ -1 +0,0 @@
|
|
1
|
-
aac472f3c6a5695b08ce2a6f7f83927cbf4adb494316a64282e44c8dc6b91bf7
|
@@ -1 +0,0 @@
|
|
1
|
-
7d23fb7769a5f64a1232d9d6466fc08cdafb5f7e7b33027c6296c2ceb9d050daa4dd0c52e0da56da6d3bb87509a27d5789082bab919b0428fa94dc4e6d1601de
|
package/Detox-android/com/wix/detox/20.15.0-prerelease.0/detox-20.15.0-prerelease.0-sources.jar.md5
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
3f11c334abdbac1f62db3258cd97ccbd
|
package/Detox-android/com/wix/detox/20.15.0-prerelease.0/detox-20.15.0-prerelease.0-sources.jar.sha1
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
a66bc0bc574842d176d1da4a0c148aea8ef3507f
|
@@ -1 +0,0 @@
|
|
1
|
-
5b57ac262feb204c4284d6c7e3c07ba3e49a4d3fb7eca4e902f0532dc8c47704
|
@@ -1 +0,0 @@
|
|
1
|
-
c9f2fb00f54efb71ef213625fff971b4c87c1df802c7b6006f6224f286c00e40cb31c672a99fbbb7e08c77cf9ab0793e8a0fc81bc56488c056492c8452a382d8
|