detox 20.34.4 → 20.35.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Detox-android/com/wix/detox/{20.34.4/detox-20.34.4-sources.jar → 20.35.0/detox-20.35.0-sources.jar} +0 -0
- package/Detox-android/com/wix/detox/20.35.0/detox-20.35.0-sources.jar.md5 +1 -0
- package/Detox-android/com/wix/detox/20.35.0/detox-20.35.0-sources.jar.sha1 +1 -0
- package/Detox-android/com/wix/detox/20.35.0/detox-20.35.0-sources.jar.sha256 +1 -0
- package/Detox-android/com/wix/detox/20.35.0/detox-20.35.0-sources.jar.sha512 +1 -0
- package/Detox-android/com/wix/detox/{20.34.4/detox-20.34.4.pom → 20.35.0/detox-20.35.0.pom} +1 -1
- package/Detox-android/com/wix/detox/20.35.0/detox-20.35.0.pom.md5 +1 -0
- package/Detox-android/com/wix/detox/20.35.0/detox-20.35.0.pom.sha1 +1 -0
- package/Detox-android/com/wix/detox/20.35.0/detox-20.35.0.pom.sha256 +1 -0
- package/Detox-android/com/wix/detox/20.35.0/detox-20.35.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-framework.tbz +0 -0
- package/Detox-ios-src.tbz +0 -0
- package/Detox-ios-xcuitest.tbz +0 -0
- package/detox.d.ts +14 -8
- package/globals.d.ts +2 -0
- package/jest.config.js +1 -1
- package/local-cli/utils/frameworkUtils.js +2 -3
- package/package.json +6 -5
- package/src/DetoxWorker.js +16 -10
- package/src/devices/allocation/drivers/android/emulator/launchEmulatorProcess.js +28 -14
- package/src/devices/common/drivers/android/exec/ADB.js +14 -4
- package/src/devices/common/drivers/android/exec/BinaryExec.js +8 -7
- package/src/devices/runtime/drivers/android/genycloud/GenyCloudDriver.js +6 -0
- package/src/devices/runtime/drivers/ios/SimulatorDriver.js +6 -7
- package/src/ios/XCUITestRunner.js +2 -3
- package/src/pilot/DetoxPilot.js +49 -0
- package/src/realms/DetoxContext.js +2 -0
- package/src/utils/assertArgument.js +3 -1
- package/src/utils/childProcess/exec.js +9 -2
- package/src/utils/childProcess/spawn.js +33 -15
- package/src/utils/environment.js +10 -11
- package/Detox-android/com/wix/detox/20.34.4/detox-20.34.4-sources.jar.md5 +0 -1
- package/Detox-android/com/wix/detox/20.34.4/detox-20.34.4-sources.jar.sha1 +0 -1
- package/Detox-android/com/wix/detox/20.34.4/detox-20.34.4-sources.jar.sha256 +0 -1
- package/Detox-android/com/wix/detox/20.34.4/detox-20.34.4-sources.jar.sha512 +0 -1
- package/Detox-android/com/wix/detox/20.34.4/detox-20.34.4.pom.md5 +0 -1
- package/Detox-android/com/wix/detox/20.34.4/detox-20.34.4.pom.sha1 +0 -1
- package/Detox-android/com/wix/detox/20.34.4/detox-20.34.4.pom.sha256 +0 -1
- package/Detox-android/com/wix/detox/20.34.4/detox-20.34.4.pom.sha512 +0 -1
- package/src/copilot/DetoxCopilot.js +0 -21
- package/src/copilot/detoxCopilotFrameworkDriver.js +0 -703
- /package/Detox-android/com/wix/detox/{20.34.4/detox-20.34.4.aar → 20.35.0/detox-20.35.0.aar} +0 -0
- /package/Detox-android/com/wix/detox/{20.34.4/detox-20.34.4.aar.md5 → 20.35.0/detox-20.35.0.aar.md5} +0 -0
- /package/Detox-android/com/wix/detox/{20.34.4/detox-20.34.4.aar.sha1 → 20.35.0/detox-20.35.0.aar.sha1} +0 -0
- /package/Detox-android/com/wix/detox/{20.34.4/detox-20.34.4.aar.sha256 → 20.35.0/detox-20.35.0.aar.sha256} +0 -0
- /package/Detox-android/com/wix/detox/{20.34.4/detox-20.34.4.aar.sha512 → 20.35.0/detox-20.35.0.aar.sha512} +0 -0
Binary file
|
@@ -0,0 +1 @@
|
|
1
|
+
e10fbe02ae741953ba7fcaf4e49c46b2
|
@@ -0,0 +1 @@
|
|
1
|
+
54cd5b84590cf69c3fbe857a45195d431fcc0d03
|
@@ -0,0 +1 @@
|
|
1
|
+
9ebc41643bf86a13cc5360a51de676d69cee5d050ba69ff860e0fa3f67f36329
|
@@ -0,0 +1 @@
|
|
1
|
+
c498fd81f0f898366a6c8916fbe40a60838abd79055b198613ae44b31bd902db16ae32b955924d2b2fe380002589d1830214565409ec4c5e12aae27efad3b38c
|
@@ -3,7 +3,7 @@
|
|
3
3
|
<modelVersion>4.0.0</modelVersion>
|
4
4
|
<groupId>com.wix</groupId>
|
5
5
|
<artifactId>detox</artifactId>
|
6
|
-
<version>20.
|
6
|
+
<version>20.35.0</version>
|
7
7
|
<packaging>aar</packaging>
|
8
8
|
<name>Detox</name>
|
9
9
|
<description>Gray box end-to-end testing and automation library for mobile apps</description>
|
@@ -0,0 +1 @@
|
|
1
|
+
143eb7c5c6f86392b48530a0e3797140
|
@@ -0,0 +1 @@
|
|
1
|
+
c30db2dbe5e3d3378ad63879153f4c4c56a6a3c3
|
@@ -0,0 +1 @@
|
|
1
|
+
07e8ba7093940f31c77fc95027d7125a8888fb4c2973843d1abef8318e1135e2
|
@@ -0,0 +1 @@
|
|
1
|
+
c831c274c24a3d1d22682108e90ae976880d96abf02a03cc18e70fdd89a13d487d5e4df6fe725fb7b7bd61d0dada06dda2dd0155fcf25106812efaacf6acbe4d
|
@@ -3,11 +3,11 @@
|
|
3
3
|
<groupId>com.wix</groupId>
|
4
4
|
<artifactId>detox</artifactId>
|
5
5
|
<versioning>
|
6
|
-
<latest>20.
|
7
|
-
<release>20.
|
6
|
+
<latest>20.35.0</latest>
|
7
|
+
<release>20.35.0</release>
|
8
8
|
<versions>
|
9
|
-
<version>20.
|
9
|
+
<version>20.35.0</version>
|
10
10
|
</versions>
|
11
|
-
<lastUpdated>
|
11
|
+
<lastUpdated>20250315183637</lastUpdated>
|
12
12
|
</versioning>
|
13
13
|
</metadata>
|
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
2b2da1caee0ef6508eb79eba3c6ea2b1
|
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
b34995356a8d0d1334d7f0eaf6dbe077a68cbded
|
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
fe9f9de98f86637d4ba74fd60601adf63a52c994b022d94f9d6d7406e6477462
|
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
9f5fe00e8e14a49bc02a5f0d643b8ac49c2182acf22739f27e2b9cacb42aff2f014ce7c1e32768154ce030376da6337502bf2b5402464e9f7c76f18ef90e79bf
|
package/Detox-ios-framework.tbz
CHANGED
Binary file
|
package/Detox-ios-src.tbz
CHANGED
Binary file
|
package/Detox-ios-xcuitest.tbz
CHANGED
Binary file
|
package/detox.d.ts
CHANGED
@@ -9,7 +9,7 @@
|
|
9
9
|
// * Dor Ben Baruch <https://github.com/Dor256>
|
10
10
|
|
11
11
|
import { BunyanDebugStreamOptions } from 'bunyan-debug-stream';
|
12
|
-
import {
|
12
|
+
import type { Pilot, PromptHandler as _PromptHandler } from '@wix-pilot/core'
|
13
13
|
|
14
14
|
declare global {
|
15
15
|
namespace Detox {
|
@@ -446,7 +446,13 @@ declare global {
|
|
446
446
|
|
447
447
|
readonly system: SystemFacade;
|
448
448
|
|
449
|
-
readonly
|
449
|
+
readonly pilot: PilotFacade;
|
450
|
+
|
451
|
+
/**
|
452
|
+
* @deprecated This API is deprecated and will be removed in the next major version.
|
453
|
+
* Please use `pilot` instead of `pilot`.
|
454
|
+
*/
|
455
|
+
readonly copilot: PilotFacade;
|
450
456
|
|
451
457
|
readonly DetoxConstants: {
|
452
458
|
userNotificationTriggers: {
|
@@ -1329,17 +1335,17 @@ declare global {
|
|
1329
1335
|
element(systemMatcher: SystemMatcher): IndexableSystemElement;
|
1330
1336
|
}
|
1331
1337
|
|
1332
|
-
interface
|
1338
|
+
interface PilotFacade extends Pick<Pilot, "perform" | "autopilot" | "extendAPICatalog"> {
|
1333
1339
|
/**
|
1334
|
-
* Initializes the
|
1335
|
-
* Must be called before any other
|
1336
|
-
* @note
|
1340
|
+
* Initializes the Pilot with the given prompt handler.
|
1341
|
+
* Must be called before any other Pilot methods.
|
1342
|
+
* @note Wix-Pilot APIs are still in experimental phase and are subject to changes in the near future.
|
1337
1343
|
* @param promptHandler The prompt handler to use.
|
1338
1344
|
*/
|
1339
|
-
init: (promptHandler:
|
1345
|
+
init: (promptHandler: PromptHandler) => void;
|
1340
1346
|
}
|
1341
1347
|
|
1342
|
-
|
1348
|
+
type PromptHandler = _PromptHandler;
|
1343
1349
|
|
1344
1350
|
interface IndexableSystemElement extends SystemElement {
|
1345
1351
|
/**
|
package/globals.d.ts
CHANGED
@@ -10,6 +10,7 @@ declare global {
|
|
10
10
|
const web: Detox.DetoxExportWrapper['web'];
|
11
11
|
const system: Detox.DetoxExportWrapper['system'];
|
12
12
|
const copilot: Detox.DetoxExportWrapper['copilot'];
|
13
|
+
const pilot: Detox.DetoxExportWrapper['pilot'];
|
13
14
|
|
14
15
|
namespace NodeJS {
|
15
16
|
interface Global {
|
@@ -22,6 +23,7 @@ declare global {
|
|
22
23
|
web: Detox.DetoxExportWrapper['web'];
|
23
24
|
system: Detox.DetoxExportWrapper['system'];
|
24
25
|
copilot: Detox.DetoxExportWrapper['copilot'];
|
26
|
+
pilot: Detox.DetoxExportWrapper['pilot'];
|
25
27
|
}
|
26
28
|
}
|
27
29
|
}
|
package/jest.config.js
CHANGED
@@ -1,13 +1,12 @@
|
|
1
1
|
const os = require('os');
|
2
2
|
const path = require('path');
|
3
3
|
|
4
|
-
const { spawn } = require('child-process-promise');
|
5
4
|
const fs = require('fs-extra');
|
6
5
|
|
7
6
|
const detox = require('../../internals');
|
7
|
+
const { spawnAndLog } = require('../../src/utils/childProcess');
|
8
8
|
const { getFrameworkDirPath, getXCUITestRunnerDirPath } = require('../../src/utils/environment');
|
9
9
|
|
10
|
-
|
11
10
|
const frameworkBuildScript = '../../scripts/build_local_framework.ios.sh';
|
12
11
|
const xcuitestBuildScript = '../../scripts/build_local_xcuitest.ios.sh';
|
13
12
|
|
@@ -26,7 +25,7 @@ async function execBuildScript(targetPath, scriptPath, descriptor) {
|
|
26
25
|
const scriptFullPath = path.join(__dirname, scriptPath);
|
27
26
|
|
28
27
|
try {
|
29
|
-
await
|
28
|
+
await spawnAndLog(scriptFullPath, [], { stdio: 'inherit' });
|
30
29
|
} catch (error) {
|
31
30
|
detox.log.error(`Error while building ${descriptor}:\n${error}`);
|
32
31
|
throw error;
|
package/package.json
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
{
|
2
2
|
"name": "detox",
|
3
3
|
"description": "E2E tests and automation for mobile",
|
4
|
-
"version": "20.
|
4
|
+
"version": "20.35.0",
|
5
5
|
"bin": {
|
6
6
|
"detox": "local-cli/cli.js"
|
7
7
|
},
|
@@ -64,17 +64,17 @@
|
|
64
64
|
"prettier": "^3.1.1",
|
65
65
|
"react-native": "0.76.3",
|
66
66
|
"react-native-codegen": "^0.0.8",
|
67
|
-
"typescript": "
|
67
|
+
"typescript": "~5.3.3",
|
68
68
|
"wtfnode": "^0.9.1"
|
69
69
|
},
|
70
70
|
"dependencies": {
|
71
|
+
"@wix-pilot/core": "^3.1.4",
|
72
|
+
"@wix-pilot/detox": "^1.0.8",
|
71
73
|
"ajv": "^8.6.3",
|
72
74
|
"bunyan": "^1.8.12",
|
73
75
|
"bunyan-debug-stream": "^3.1.0",
|
74
76
|
"caf": "^15.0.1",
|
75
77
|
"chalk": "^4.0.0",
|
76
|
-
"child-process-promise": "^2.2.0",
|
77
|
-
"detox-copilot": "^0.0.27",
|
78
78
|
"execa": "^5.1.1",
|
79
79
|
"find-up": "^5.0.0",
|
80
80
|
"fs-extra": "^11.0.0",
|
@@ -87,6 +87,7 @@
|
|
87
87
|
"multi-sort-stream": "^1.0.3",
|
88
88
|
"multipipe": "^4.0.0",
|
89
89
|
"node-ipc": "9.2.1",
|
90
|
+
"promisify-child-process": "^4.1.2",
|
90
91
|
"proper-lockfile": "^3.0.2",
|
91
92
|
"resolve-from": "^5.0.0",
|
92
93
|
"sanitize-filename": "^1.6.1",
|
@@ -119,5 +120,5 @@
|
|
119
120
|
"browserslist": [
|
120
121
|
"node 14"
|
121
122
|
],
|
122
|
-
"gitHead": "
|
123
|
+
"gitHead": "76d581f3f67875f245eca865e6f3a449332c63bd"
|
123
124
|
}
|
package/src/DetoxWorker.js
CHANGED
@@ -1,12 +1,11 @@
|
|
1
1
|
const CAF = require('caf');
|
2
|
-
const copilot = require('detox-copilot').default;
|
3
2
|
const _ = require('lodash');
|
4
3
|
|
5
4
|
const Client = require('./client/Client');
|
6
|
-
const DetoxCopilot = require('./copilot/DetoxCopilot');
|
7
5
|
const environmentFactory = require('./environmentFactory');
|
8
6
|
const { DetoxRuntimeErrorComposer } = require('./errors');
|
9
7
|
const { InvocationManager } = require('./invoke');
|
8
|
+
const DetoxPilot = require('./pilot/DetoxPilot');
|
10
9
|
const symbols = require('./realms/symbols');
|
11
10
|
const AsyncEmitter = require('./utils/AsyncEmitter');
|
12
11
|
const uuid = require('./utils/uuid');
|
@@ -62,8 +61,8 @@ class DetoxWorker {
|
|
62
61
|
this.web = null;
|
63
62
|
/** @type {Detox.SystemFacade} */
|
64
63
|
this.system = null;
|
65
|
-
/** @type {Detox.
|
66
|
-
this.
|
64
|
+
/** @type {Detox.PilotFacade} */
|
65
|
+
this.pilot = null;
|
67
66
|
|
68
67
|
this._deviceCookie = null;
|
69
68
|
|
@@ -103,7 +102,6 @@ class DetoxWorker {
|
|
103
102
|
// @ts-ignore
|
104
103
|
this._sessionConfig.sessionId = sessionConfig.sessionId || uuid.UUID();
|
105
104
|
this._runtimeErrorComposer.appsConfig = this._appsConfig;
|
106
|
-
|
107
105
|
this._client = new Client(sessionConfig);
|
108
106
|
this._client.terminateApp = async () => {
|
109
107
|
// @ts-ignore
|
@@ -111,6 +109,7 @@ class DetoxWorker {
|
|
111
109
|
await this.device.terminateApp();
|
112
110
|
}
|
113
111
|
};
|
112
|
+
this.pilot = new DetoxPilot();
|
114
113
|
|
115
114
|
yield this._client.connect();
|
116
115
|
|
@@ -163,12 +162,19 @@ class DetoxWorker {
|
|
163
162
|
const injectedGlobals = {
|
164
163
|
...matchers,
|
165
164
|
device: this.device,
|
166
|
-
|
165
|
+
pilot: this.pilot,
|
167
166
|
detox: this,
|
168
167
|
};
|
169
168
|
|
170
169
|
this._injectedGlobalProperties = Object.keys(injectedGlobals);
|
171
170
|
Object.assign(DetoxWorker.global, injectedGlobals);
|
171
|
+
Object.defineProperty(DetoxWorker.global, 'copilot', {
|
172
|
+
get: () => {
|
173
|
+
console.warn('Warning: "copilot" is deprecated. Please use "pilot" instead.');
|
174
|
+
return this.pilot;
|
175
|
+
},
|
176
|
+
configurable: true,
|
177
|
+
});
|
172
178
|
}
|
173
179
|
|
174
180
|
// @ts-ignore
|
@@ -226,8 +232,8 @@ class DetoxWorker {
|
|
226
232
|
};
|
227
233
|
|
228
234
|
onTestStart = function* (_signal, testSummary){
|
229
|
-
if (
|
230
|
-
|
235
|
+
if (this.pilot.isInitialized()) {
|
236
|
+
this.pilot.start();
|
231
237
|
}
|
232
238
|
|
233
239
|
this._validateTestSummary('beforeEach', testSummary);
|
@@ -258,8 +264,8 @@ class DetoxWorker {
|
|
258
264
|
testName: testSummary.fullName,
|
259
265
|
});
|
260
266
|
|
261
|
-
if (
|
262
|
-
|
267
|
+
if (this.pilot.isInitialized()) {
|
268
|
+
this.pilot.end(testSummary.status === 'passed');
|
263
269
|
}
|
264
270
|
};
|
265
271
|
|
@@ -31,23 +31,37 @@ function launchEmulatorProcess(emulatorExec, adb, emulatorLaunchCommand) {
|
|
31
31
|
|
32
32
|
log = log.child({ child_pid: childProcessPromise.childProcess.pid });
|
33
33
|
|
34
|
-
|
34
|
+
// Create a deferred promise that resolves when the device is ready
|
35
|
+
let resolveEmulatorReady;
|
36
|
+
const emulatorReadyPromise = new Promise(resolve => {
|
37
|
+
resolveEmulatorReady = resolve;
|
38
|
+
});
|
35
39
|
|
36
|
-
|
37
|
-
|
40
|
+
// Wait for the device to be ready
|
41
|
+
adb.waitForDevice(emulatorLaunchCommand.adbName).then(() => {
|
42
|
+
resolveEmulatorReady();
|
43
|
+
});
|
38
44
|
|
39
|
-
|
40
|
-
|
41
|
-
|
45
|
+
// Use Promise.race to resolve with the first one to complete - either the emulator process exits
|
46
|
+
// or the emulator device is ready
|
47
|
+
return Promise.race([childProcessPromise, emulatorReadyPromise])
|
48
|
+
.then(() => true)
|
49
|
+
.catch((err) => {
|
50
|
+
detach();
|
42
51
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
52
|
+
if (childProcessOutput && childProcessOutput.includes(`There's another emulator instance running with the current AVD`)) {
|
53
|
+
return false;
|
54
|
+
}
|
55
|
+
|
56
|
+
log.error({ event: 'SPAWN_FAIL', error: true, err }, err.message);
|
57
|
+
log.error({ event: 'SPAWN_FAIL', stderr: true }, childProcessOutput);
|
58
|
+
throw err;
|
59
|
+
})
|
60
|
+
.then((coldBoot) => {
|
61
|
+
detach();
|
62
|
+
log.debug({ event: 'SPAWN_SUCCESS', stdout: true }, childProcessOutput);
|
63
|
+
return coldBoot;
|
64
|
+
});
|
51
65
|
}
|
52
66
|
|
53
67
|
module.exports = { launchEmulatorProcess };
|
@@ -8,11 +8,19 @@ const { escape } = require('../../../../../utils/pipeCommands');
|
|
8
8
|
const DeviceHandle = require('../tools/DeviceHandle');
|
9
9
|
const EmulatorHandle = require('../tools/EmulatorHandle');
|
10
10
|
|
11
|
-
const
|
11
|
+
const DEFAULT_EXEC_OPTIONS = {
|
12
|
+
retries: 1,
|
13
|
+
};
|
14
|
+
const DEFAULT_INSTALL_OPTIONS = {
|
15
|
+
timeout: 60000,
|
16
|
+
retries: 3,
|
17
|
+
};
|
12
18
|
|
13
19
|
class ADB {
|
14
20
|
constructor() {
|
15
21
|
this._cachedApiLevels = new Map();
|
22
|
+
this.defaultExecOptions = DEFAULT_EXEC_OPTIONS;
|
23
|
+
this.installOptions = DEFAULT_INSTALL_OPTIONS;
|
16
24
|
this.adbBin = getAdbPath();
|
17
25
|
}
|
18
26
|
|
@@ -113,7 +121,7 @@ class ADB {
|
|
113
121
|
const command = (apiLvl >= 23)
|
114
122
|
? `install -r -g -t ${apkPath}`
|
115
123
|
: `install -rg ${apkPath}`;
|
116
|
-
const result = await this.adbCmdSpawned(deviceId, command,
|
124
|
+
const result = await this.adbCmdSpawned(deviceId, command, this.installOptions);
|
117
125
|
|
118
126
|
const [failure] = (result.stdout || '').match(/^Failure \[.*\]$/m) || [];
|
119
127
|
if (failure) {
|
@@ -129,7 +137,7 @@ class ADB {
|
|
129
137
|
const command = (apiLvl >= 23)
|
130
138
|
? `pm install -r -g -t ${path}`
|
131
139
|
: `pm install -rg ${path}`;
|
132
|
-
return this.shellSpawned(deviceId, command,
|
140
|
+
return this.shellSpawned(deviceId, command, this.installOptions);
|
133
141
|
}
|
134
142
|
|
135
143
|
async uninstall(deviceId, appId) {
|
@@ -353,7 +361,7 @@ class ADB {
|
|
353
361
|
const serial = `${deviceId ? `-s ${deviceId}` : ''}`;
|
354
362
|
const cmd = `"${this.adbBin}" ${serial} ${params}`;
|
355
363
|
const _options = {
|
356
|
-
|
364
|
+
...this.defaultExecOptions,
|
357
365
|
...options,
|
358
366
|
};
|
359
367
|
return execWithRetriesAndLogs(cmd, _options);
|
@@ -364,8 +372,10 @@ class ADB {
|
|
364
372
|
const serial = deviceId ? ['-s', deviceId] : [];
|
365
373
|
const _flags = [...serial, ...flags];
|
366
374
|
const _spawnOptions = {
|
375
|
+
...this.defaultExecOptions,
|
367
376
|
...spawnOptions,
|
368
377
|
capture: ['stdout'],
|
378
|
+
encoding: 'utf8',
|
369
379
|
};
|
370
380
|
return spawnWithRetriesAndLogs(this.adbBin, _flags, _spawnOptions);
|
371
381
|
}
|
@@ -1,7 +1,4 @@
|
|
1
|
-
|
2
|
-
const spawn = require('child-process-promise').spawn;
|
3
|
-
|
4
|
-
const exec = require('../../../../../utils/childProcess').execWithRetriesAndLogs;
|
1
|
+
const { execAsync, spawnAndLog } = require('../../../../../utils/childProcess');
|
5
2
|
|
6
3
|
class ExecCommand {
|
7
4
|
toString() {
|
@@ -27,15 +24,19 @@ class BinaryExec {
|
|
27
24
|
}
|
28
25
|
|
29
26
|
async exec(command) {
|
30
|
-
return
|
27
|
+
return await execAsync(`"${this.binary}" ${command._getArgsString()}`);
|
31
28
|
}
|
32
29
|
|
33
30
|
spawn(command, stdout, stderr) {
|
34
|
-
return
|
31
|
+
return spawnAndLog(this.binary, command._getArgs(), {
|
32
|
+
detached: true,
|
33
|
+
encoding: 'utf8',
|
34
|
+
stdio: ['ignore', stdout, stderr]
|
35
|
+
});
|
35
36
|
}
|
36
37
|
}
|
37
38
|
|
38
39
|
module.exports = {
|
39
40
|
ExecCommand,
|
40
|
-
BinaryExec
|
41
|
+
BinaryExec
|
41
42
|
};
|
@@ -19,6 +19,12 @@ class GenyCloudDriver extends AndroidDriver {
|
|
19
19
|
constructor(deps, { adbName, name }) {
|
20
20
|
super(deps, { adbName });
|
21
21
|
|
22
|
+
// Make ADB more resilient to network latency and connection hiccups
|
23
|
+
this.adb.defaultExecOptions = {
|
24
|
+
retries: 5,
|
25
|
+
interval: 3000,
|
26
|
+
backoff: 'linear',
|
27
|
+
};
|
22
28
|
this._instanceName = name;
|
23
29
|
}
|
24
30
|
|
@@ -1,13 +1,14 @@
|
|
1
1
|
// @ts-nocheck
|
2
2
|
const path = require('path');
|
3
3
|
|
4
|
-
const exec = require('child-process-promise').exec;
|
5
4
|
const _ = require('lodash');
|
6
5
|
|
6
|
+
|
7
7
|
const temporaryPath = require('../../../../artifacts/utils/temporaryPath');
|
8
8
|
const DetoxRuntimeError = require('../../../../errors/DetoxRuntimeError');
|
9
9
|
const XCUITestRunner = require('../../../../ios/XCUITestRunner');
|
10
10
|
const { assertTraceDescription } = require('../../../../utils/assertArgument');
|
11
|
+
const { execAsync } = require('../../../../utils/childProcess');
|
11
12
|
const getAbsoluteBinaryPath = require('../../../../utils/getAbsoluteBinaryPath');
|
12
13
|
const { actionDescription } = require('../../../../utils/invocationTraceDescriptions');
|
13
14
|
const log = require('../../../../utils/logger').child({ cat: 'device' });
|
@@ -16,7 +17,6 @@ const traceInvocationCall = require('../../../../utils/traceInvocationCall').bin
|
|
16
17
|
|
17
18
|
const IosDriver = require('./IosDriver');
|
18
19
|
|
19
|
-
|
20
20
|
/**
|
21
21
|
* @typedef SimulatorDriverDeps { DeviceDriverDeps }
|
22
22
|
* @property applesimutils { AppleSimUtils }
|
@@ -69,8 +69,7 @@ class SimulatorDriver extends IosDriver {
|
|
69
69
|
async getBundleIdFromBinary(appPath) {
|
70
70
|
appPath = getAbsoluteBinaryPath(appPath);
|
71
71
|
try {
|
72
|
-
const
|
73
|
-
const bundleId = _.trim(result.stdout);
|
72
|
+
const bundleId = await execAsync(`/usr/libexec/PlistBuddy -c "Print CFBundleIdentifier" "${path.join(appPath, 'Info.plist')}"`);
|
74
73
|
if (_.isEmpty(bundleId)) {
|
75
74
|
throw new Error();
|
76
75
|
}
|
@@ -141,7 +140,7 @@ class SimulatorDriver extends IosDriver {
|
|
141
140
|
const xcuitestRunner = new XCUITestRunner({ runtimeDevice: { id: this.getExternalId(), _bundleId } });
|
142
141
|
let x = point?.x ?? 100;
|
143
142
|
let y = point?.y ?? 100;
|
144
|
-
let _pressDuration = pressDuration ?
|
143
|
+
let _pressDuration = pressDuration ? pressDuration / 1000 : 1;
|
145
144
|
const traceDescription = actionDescription.longPress({ x, y }, _pressDuration);
|
146
145
|
return this.withAction(xcuitestRunner, 'coordinateLongPress', traceDescription, x.toString(), y.toString(), _pressDuration.toString());
|
147
146
|
}
|
@@ -210,7 +209,7 @@ class SimulatorDriver extends IosDriver {
|
|
210
209
|
await this.emitter.emit('createExternalArtifact', {
|
211
210
|
pluginId: 'screenshot',
|
212
211
|
artifactName: screenshotName || path.basename(tempPath, '.png'),
|
213
|
-
artifactPath: tempPath
|
212
|
+
artifactPath: tempPath
|
214
213
|
});
|
215
214
|
|
216
215
|
return tempPath;
|
@@ -223,7 +222,7 @@ class SimulatorDriver extends IosDriver {
|
|
223
222
|
await this.emitter.emit('createExternalArtifact', {
|
224
223
|
pluginId: 'uiHierarchy',
|
225
224
|
artifactName: artifactName,
|
226
|
-
artifactPath: viewHierarchyURL
|
225
|
+
artifactPath: viewHierarchyURL
|
227
226
|
});
|
228
227
|
|
229
228
|
return viewHierarchyURL;
|
@@ -1,6 +1,5 @@
|
|
1
|
-
const { exec } = require('child-process-promise');
|
2
|
-
|
3
1
|
const DetoxRuntimeError = require('../errors/DetoxRuntimeError');
|
2
|
+
const { execAsync } = require('../utils/childProcess');
|
4
3
|
const environment = require('../utils/environment');
|
5
4
|
const log = require('../utils/logger').child({ cat: 'xcuitest-runner' });
|
6
5
|
|
@@ -37,7 +36,7 @@ class XCUITestRunner {
|
|
37
36
|
`--predicate 'process == "DetoxXCUITestRunner-Runner" && subsystem == "com.wix.DetoxXCUITestRunner.xctrunner"'`);
|
38
37
|
|
39
38
|
try {
|
40
|
-
return await
|
39
|
+
return await execAsync(`TEST_RUNNER_PARAMS="${base64InvocationParams}" TEST_RUNNER_BUNDLE_ID="${this.runtimeDevice._bundleId}" xcodebuild ${flags.join(' ')}`);
|
41
40
|
} catch (e) {
|
42
41
|
const stdout = e.stdout.toString();
|
43
42
|
const innerError = this.findInnerError(stdout);
|
@@ -0,0 +1,49 @@
|
|
1
|
+
const { Pilot } = require('@wix-pilot/core');
|
2
|
+
const { DetoxFrameworkDriver } = require('@wix-pilot/detox');
|
3
|
+
|
4
|
+
const detox = require('../..');
|
5
|
+
|
6
|
+
/** @type {Detox.PilotFacade} */
|
7
|
+
class DetoxPilot {
|
8
|
+
init(promptHandler) {
|
9
|
+
this.pilot = new Pilot({
|
10
|
+
frameworkDriver: new DetoxFrameworkDriver(detox),
|
11
|
+
promptHandler: promptHandler
|
12
|
+
});
|
13
|
+
}
|
14
|
+
|
15
|
+
start(){
|
16
|
+
if (!this.isInitialized()) {
|
17
|
+
throw new Error('DetoxPilot is not initialized');
|
18
|
+
}
|
19
|
+
return this.pilot.start();
|
20
|
+
}
|
21
|
+
|
22
|
+
perform(...steps){
|
23
|
+
if (!this.isInitialized()) {
|
24
|
+
throw new Error('DetoxPilot is not initialized');
|
25
|
+
}
|
26
|
+
return this.pilot.perform(...steps);
|
27
|
+
}
|
28
|
+
|
29
|
+
autopilot(goal) {
|
30
|
+
return this.pilot.autopilot(goal);
|
31
|
+
}
|
32
|
+
|
33
|
+
extendAPICatalog(categories, context) {
|
34
|
+
return this.pilot.extendAPICatalog(categories, context);
|
35
|
+
}
|
36
|
+
|
37
|
+
end(shouldSaveInCache){
|
38
|
+
if(!this.isInitialized()){
|
39
|
+
throw new Error('DetoxPilot is not initialized');
|
40
|
+
}
|
41
|
+
return this.pilot.end(shouldSaveInCache);
|
42
|
+
}
|
43
|
+
|
44
|
+
isInitialized(){
|
45
|
+
return !!this.pilot;
|
46
|
+
}
|
47
|
+
}
|
48
|
+
|
49
|
+
module.exports = DetoxPilot;
|
@@ -83,6 +83,8 @@ class DetoxContext {
|
|
83
83
|
|
84
84
|
system = funpermaproxy.callable(() => this[symbols.worker].system);
|
85
85
|
|
86
|
+
pilot = funpermaproxy.callable(() => this[symbols.worker].pilot);
|
87
|
+
|
86
88
|
copilot = funpermaproxy.callable(() => this[symbols.worker].copilot);
|
87
89
|
|
88
90
|
get DetoxConstants() {
|
@@ -1,6 +1,6 @@
|
|
1
1
|
// @ts-nocheck
|
2
|
-
const { exec } = require('child-process-promise');
|
3
2
|
const _ = require('lodash');
|
3
|
+
const { exec } = require('promisify-child-process');
|
4
4
|
|
5
5
|
const DetoxRuntimeError = require('../../errors/DetoxRuntimeError');
|
6
6
|
const rootLogger = require('../logger').child({ cat: ['child-process', 'child-process-exec'] });
|
@@ -8,10 +8,17 @@ const retry = require('../retry');
|
|
8
8
|
|
9
9
|
const execsCounter = require('./opsCounter');
|
10
10
|
|
11
|
+
/**
|
12
|
+
* Executes a command with retries and logs
|
13
|
+
* @param {*} bin - command to execute
|
14
|
+
* @param {*} options - options
|
15
|
+
* @returns {Promise<import('promisify-child-process').Output>}
|
16
|
+
*/
|
11
17
|
async function execWithRetriesAndLogs(bin, options = {}) {
|
12
18
|
const {
|
13
19
|
retries = 9,
|
14
20
|
interval = 1000,
|
21
|
+
backoff,
|
15
22
|
prefix = null,
|
16
23
|
args = null,
|
17
24
|
timeout,
|
@@ -30,7 +37,7 @@ async function execWithRetriesAndLogs(bin, options = {}) {
|
|
30
37
|
try {
|
31
38
|
logger.debug({ event: 'EXEC_CMD' }, `${cmd}`);
|
32
39
|
|
33
|
-
await retry({ retries, interval }, async (tryNumber, lastError) => {
|
40
|
+
await retry({ retries, interval, backoff }, async (tryNumber, lastError) => {
|
34
41
|
if (statusLogs.trying) {
|
35
42
|
_logExecTrying(logger, statusLogs.trying, tryNumber, lastError);
|
36
43
|
} else if (statusLogs.retrying) {
|