detox 20.0.4-breaking.new-global-lifecycle.0 → 20.0.7-prerelease.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.0.4-breaking.new-global-lifecycle.0/detox-20.0.4-breaking.new-global-lifecycle.0-javadoc.jar → 20.0.7-prerelease.0/detox-20.0.7-prerelease.0-javadoc.jar} +0 -0
- package/Detox-android/com/wix/detox/20.0.7-prerelease.0/detox-20.0.7-prerelease.0-javadoc.jar.md5 +1 -0
- package/Detox-android/com/wix/detox/20.0.7-prerelease.0/detox-20.0.7-prerelease.0-javadoc.jar.sha1 +1 -0
- package/Detox-android/com/wix/detox/20.0.7-prerelease.0/detox-20.0.7-prerelease.0-javadoc.jar.sha256 +1 -0
- package/Detox-android/com/wix/detox/20.0.7-prerelease.0/detox-20.0.7-prerelease.0-javadoc.jar.sha512 +1 -0
- package/Detox-android/com/wix/detox/{20.0.4-breaking.new-global-lifecycle.0/detox-20.0.4-breaking.new-global-lifecycle.0-sources.jar → 20.0.7-prerelease.0/detox-20.0.7-prerelease.0-sources.jar} +0 -0
- package/Detox-android/com/wix/detox/20.0.7-prerelease.0/detox-20.0.7-prerelease.0-sources.jar.md5 +1 -0
- package/Detox-android/com/wix/detox/20.0.7-prerelease.0/detox-20.0.7-prerelease.0-sources.jar.sha1 +1 -0
- package/Detox-android/com/wix/detox/20.0.7-prerelease.0/detox-20.0.7-prerelease.0-sources.jar.sha256 +1 -0
- package/Detox-android/com/wix/detox/20.0.7-prerelease.0/detox-20.0.7-prerelease.0-sources.jar.sha512 +1 -0
- package/Detox-android/com/wix/detox/20.0.7-prerelease.0/detox-20.0.7-prerelease.0.aar +0 -0
- package/Detox-android/com/wix/detox/20.0.7-prerelease.0/detox-20.0.7-prerelease.0.aar.md5 +1 -0
- package/Detox-android/com/wix/detox/20.0.7-prerelease.0/detox-20.0.7-prerelease.0.aar.sha1 +1 -0
- package/Detox-android/com/wix/detox/20.0.7-prerelease.0/detox-20.0.7-prerelease.0.aar.sha256 +1 -0
- package/Detox-android/com/wix/detox/20.0.7-prerelease.0/detox-20.0.7-prerelease.0.aar.sha512 +1 -0
- package/Detox-android/com/wix/detox/{20.0.4-breaking.new-global-lifecycle.0/detox-20.0.4-breaking.new-global-lifecycle.0.pom → 20.0.7-prerelease.0/detox-20.0.7-prerelease.0.pom} +1 -1
- package/Detox-android/com/wix/detox/20.0.7-prerelease.0/detox-20.0.7-prerelease.0.pom.md5 +1 -0
- package/Detox-android/com/wix/detox/20.0.7-prerelease.0/detox-20.0.7-prerelease.0.pom.sha1 +1 -0
- package/Detox-android/com/wix/detox/20.0.7-prerelease.0/detox-20.0.7-prerelease.0.pom.sha256 +1 -0
- package/Detox-android/com/wix/detox/20.0.7-prerelease.0/detox-20.0.7-prerelease.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/proguard-rules-app.pro +4 -0
- package/android/detox/src/full/java/com/wix/detox/DetoxCrashHandler.kt +1 -1
- package/android/detox/src/full/java/com/wix/detox/LaunchArgs.java +9 -0
- package/android/detox/src/full/java/com/wix/detox/TestEngineFacade.kt +1 -1
- package/android/detox/src/full/java/com/wix/detox/reactnative/ReactNativeExtension.kt +15 -2
- package/android/detox/src/full/java/com/wix/detox/reactnative/ReactNativeIdlingResources.kt +43 -38
- package/index.d.ts +58 -40
- package/internals.d.ts +63 -15
- package/local-cli/cli.js +1 -1
- package/local-cli/rebuild-framework-cache.js +1 -1
- package/local-cli/test.js +3 -2
- package/local-cli/test.test.js +1 -1
- package/local-cli/testCommand/TestRunnerCommand.js +10 -7
- package/package.json +5 -4
- package/runners/jest/globalSetup.js +1 -1
- package/runners/jest/globalTeardown.js +1 -1
- package/runners/jest/testEnvironment/index.js +36 -18
- package/runners/jest/testEnvironment/listeners/DetoxCoreListener.js +76 -41
- package/runners/jest/testEnvironment/listeners/SpecReporter.js +1 -1
- package/runners/jest/testEnvironment/listeners/WorkerAssignReporter.js +1 -1
- package/src/DetoxWorker.js +4 -7
- package/src/android/core/NativeElement.js +56 -20
- package/src/android/core/NativeExpect.js +28 -9
- package/src/android/interactions/native.js +24 -18
- package/src/artifacts/ArtifactsManager.js +8 -23
- package/src/artifacts/instruments/ios/SimulatorInstrumentsRecording.js +3 -3
- package/src/artifacts/log/ios/SimulatorLogRecording.js +1 -1
- package/src/artifacts/screenshot/SimulatorScreenshotPlugin.js +1 -1
- package/src/artifacts/templates/artifact/Artifact.js +1 -1
- package/src/artifacts/templates/plugin/ArtifactPlugin.js +1 -1
- package/src/artifacts/timeline/TimelineContextTypes.js +7 -0
- package/src/artifacts/utils/temporaryPath.js +18 -7
- package/src/artifacts/video/SimulatorRecordVideoPlugin.js +1 -1
- package/src/client/AsyncWebSocket.js +8 -17
- package/src/client/Client.js +19 -2
- package/src/configuration/collectCliConfig.js +1 -1
- package/src/configuration/composeDeviceConfig.js +1 -1
- package/src/configuration/composeLoggerConfig.js +17 -8
- package/src/configuration/composeRunnerConfig.js +1 -1
- package/src/configuration/index.js +5 -1
- package/src/configuration/loadExternalConfig.js +1 -1
- package/src/devices/allocation/DeviceAllocator.js +3 -2
- package/src/devices/allocation/drivers/android/emulator/AVDValidator.js +1 -1
- package/src/devices/allocation/drivers/android/emulator/EmulatorAllocDriver.js +3 -2
- package/src/devices/allocation/drivers/android/emulator/EmulatorAllocationHelper.js +1 -1
- package/src/devices/allocation/drivers/android/emulator/EmulatorLauncher.js +3 -2
- package/src/devices/allocation/drivers/android/emulator/EmulatorVersionResolver.js +4 -6
- package/src/devices/allocation/drivers/android/emulator/launchEmulatorProcess.js +1 -1
- package/src/devices/allocation/drivers/android/genycloud/GenyInstanceAllocationHelper.js +1 -1
- package/src/devices/common/drivers/android/genycloud/services/GenyInstanceNaming.js +3 -3
- package/src/devices/common/drivers/android/genycloud/services/GenyRecipesService.js +1 -1
- package/src/devices/common/drivers/android/tools/EmulatorTelnet.js +1 -1
- package/src/devices/common/drivers/android/tools/FreeDeviceFinder.js +1 -1
- package/src/devices/common/drivers/android/tools/MonitoredInstrumentation.js +1 -1
- package/src/devices/common/drivers/ios/tools/AppleSimUtils.js +4 -2
- package/src/devices/lifecycle/GenyGlobalLifecycleHandler.js +9 -13
- package/src/devices/runtime/RuntimeDevice.js +9 -12
- package/src/devices/runtime/drivers/DeviceDriverBase.js +1 -1
- package/src/devices/runtime/drivers/android/AndroidDriver.js +10 -2
- package/src/devices/runtime/drivers/ios/SimulatorDriver.js +1 -1
- package/src/ios/expectTwo.js +152 -67
- package/src/ipc/IPCClient.js +3 -8
- package/src/ipc/IPCServer.js +11 -11
- package/src/ipc/{state.js → SessionState.js} +23 -50
- package/src/logger/DetoxLogger.js +268 -155
- package/src/logger/index.js +4 -0
- package/src/logger/utils/BunyanLogger.js +72 -0
- package/src/logger/utils/CategoryThreadDispatcher.js +58 -0
- package/src/logger/utils/MessageStack.js +24 -0
- package/src/logger/{TraceThreadDispatcher.js → utils/ThreadDispatcher.js} +34 -5
- package/src/logger/{customConsoleLogger.js → utils/customConsoleLogger.js} +4 -4
- package/src/logger/utils/sanitizeBunyanContext.js +28 -0
- package/src/logger/utils/tracerLegacy.js +48 -0
- package/src/realms/DetoxContext.js +65 -57
- package/src/realms/DetoxInternalsFacade.js +7 -5
- package/src/realms/DetoxPrimaryContext.js +125 -40
- package/src/realms/DetoxSecondaryContext.js +24 -29
- package/src/server/DetoxConnection.js +18 -23
- package/src/server/DetoxServer.js +7 -10
- package/src/server/DetoxSession.js +6 -6
- package/src/server/DetoxSessionManager.js +1 -1
- package/src/server/handlers/RegisteredConnectionHandler.js +1 -2
- package/src/symbols.js +12 -8
- package/src/utils/childProcess/exec.js +1 -1
- package/src/utils/childProcess/spawn.js +1 -1
- package/src/utils/errorUtils.js +4 -3
- package/src/utils/invocationTraceDescriptions.js +43 -0
- package/src/utils/streamUtils.js +10 -11
- package/src/utils/trace.js +2 -18
- package/src/utils/traceMethods.js +15 -0
- package/Detox-android/com/wix/detox/20.0.4-breaking.new-global-lifecycle.0/detox-20.0.4-breaking.new-global-lifecycle.0-javadoc.jar.md5 +0 -1
- package/Detox-android/com/wix/detox/20.0.4-breaking.new-global-lifecycle.0/detox-20.0.4-breaking.new-global-lifecycle.0-javadoc.jar.sha1 +0 -1
- package/Detox-android/com/wix/detox/20.0.4-breaking.new-global-lifecycle.0/detox-20.0.4-breaking.new-global-lifecycle.0-javadoc.jar.sha256 +0 -1
- package/Detox-android/com/wix/detox/20.0.4-breaking.new-global-lifecycle.0/detox-20.0.4-breaking.new-global-lifecycle.0-javadoc.jar.sha512 +0 -1
- package/Detox-android/com/wix/detox/20.0.4-breaking.new-global-lifecycle.0/detox-20.0.4-breaking.new-global-lifecycle.0-sources.jar.md5 +0 -1
- package/Detox-android/com/wix/detox/20.0.4-breaking.new-global-lifecycle.0/detox-20.0.4-breaking.new-global-lifecycle.0-sources.jar.sha1 +0 -1
- package/Detox-android/com/wix/detox/20.0.4-breaking.new-global-lifecycle.0/detox-20.0.4-breaking.new-global-lifecycle.0-sources.jar.sha256 +0 -1
- package/Detox-android/com/wix/detox/20.0.4-breaking.new-global-lifecycle.0/detox-20.0.4-breaking.new-global-lifecycle.0-sources.jar.sha512 +0 -1
- package/Detox-android/com/wix/detox/20.0.4-breaking.new-global-lifecycle.0/detox-20.0.4-breaking.new-global-lifecycle.0.aar +0 -0
- package/Detox-android/com/wix/detox/20.0.4-breaking.new-global-lifecycle.0/detox-20.0.4-breaking.new-global-lifecycle.0.aar.md5 +0 -1
- package/Detox-android/com/wix/detox/20.0.4-breaking.new-global-lifecycle.0/detox-20.0.4-breaking.new-global-lifecycle.0.aar.sha1 +0 -1
- package/Detox-android/com/wix/detox/20.0.4-breaking.new-global-lifecycle.0/detox-20.0.4-breaking.new-global-lifecycle.0.aar.sha256 +0 -1
- package/Detox-android/com/wix/detox/20.0.4-breaking.new-global-lifecycle.0/detox-20.0.4-breaking.new-global-lifecycle.0.aar.sha512 +0 -1
- package/Detox-android/com/wix/detox/20.0.4-breaking.new-global-lifecycle.0/detox-20.0.4-breaking.new-global-lifecycle.0.pom.md5 +0 -1
- package/Detox-android/com/wix/detox/20.0.4-breaking.new-global-lifecycle.0/detox-20.0.4-breaking.new-global-lifecycle.0.pom.sha1 +0 -1
- package/Detox-android/com/wix/detox/20.0.4-breaking.new-global-lifecycle.0/detox-20.0.4-breaking.new-global-lifecycle.0.pom.sha256 +0 -1
- package/Detox-android/com/wix/detox/20.0.4-breaking.new-global-lifecycle.0/detox-20.0.4-breaking.new-global-lifecycle.0.pom.sha512 +0 -1
- package/src/logger/DetoxTraceEventBuilder.js +0 -21
- package/src/logger/DetoxTracer.js +0 -133
- package/src/utils/ChromeTracingExporter.js +0 -54
package/internals.d.ts
CHANGED
@@ -3,33 +3,40 @@
|
|
3
3
|
|
4
4
|
declare global {
|
5
5
|
namespace DetoxInternals {
|
6
|
+
type DetoxStatus = 'inactive' | 'init' | 'active' | 'cleanup';
|
7
|
+
|
6
8
|
type Facade = {
|
7
9
|
// region Initialization
|
8
10
|
/**
|
9
|
-
* Use with a caution, when you still have no config, yet need to avoid {@link Facade#
|
11
|
+
* Use with a caution, when you still have no config, yet need to avoid {@link Facade#init}
|
10
12
|
*/
|
11
|
-
resolveConfig(options?: Partial<
|
13
|
+
resolveConfig(options?: Partial<DetoxInitOptions>): Promise<RuntimeConfig>;
|
14
|
+
|
15
|
+
/**
|
16
|
+
*
|
17
|
+
*/
|
18
|
+
getStatus(): DetoxStatus;
|
12
19
|
|
13
20
|
/**
|
14
21
|
* This is the phase where Detox reads its configuration, starts a server.
|
15
22
|
*/
|
16
|
-
|
23
|
+
init(options?: Partial<DetoxInitOptions>): Promise<void>;
|
17
24
|
|
18
25
|
/**
|
19
|
-
* This is the phase where Detox loads its
|
26
|
+
* This is the phase where Detox loads its expectation library and starts a device.
|
20
27
|
*/
|
21
|
-
|
28
|
+
installWorker(options?: Partial<DetoxInstallWorkerOptions>): Promise<void>;
|
22
29
|
|
23
30
|
/**
|
24
|
-
*
|
31
|
+
* Deallocates the device.
|
25
32
|
*/
|
26
|
-
|
33
|
+
uninstallWorker(): Promise<void>;
|
27
34
|
|
28
35
|
/**
|
29
36
|
* The global cleanup phase should happen after all the tests have finished.
|
30
37
|
* This is the phase where the Detox server shuts down.
|
31
38
|
*/
|
32
|
-
|
39
|
+
cleanup(): Promise<void>;
|
33
40
|
// endregion
|
34
41
|
|
35
42
|
// region Lifecycle
|
@@ -59,28 +66,69 @@ declare global {
|
|
59
66
|
|
60
67
|
readonly config: RuntimeConfig;
|
61
68
|
readonly log: Detox.Logger;
|
62
|
-
readonly trace: Detox.Tracer;
|
63
69
|
readonly session: SessionState;
|
64
70
|
|
65
|
-
readonly worker:
|
71
|
+
readonly worker: Worker;
|
72
|
+
}
|
73
|
+
|
74
|
+
interface Worker extends Detox.DetoxExportWrapper {
|
75
|
+
readonly id: string;
|
66
76
|
}
|
67
77
|
|
68
|
-
type
|
78
|
+
type DetoxInitOptions = {
|
69
79
|
cwd: string;
|
70
80
|
argv: Record<string, unknown>;
|
71
81
|
testRunnerArgv: Record<string, unknown>;
|
72
82
|
override: Partial<Detox.DetoxConfig>;
|
83
|
+
/** @inheritDoc */
|
84
|
+
global: NodeJS.Global;
|
85
|
+
/**
|
86
|
+
* Worker ID. Used to distinguish allocated workers in parallel test execution environment.
|
87
|
+
*
|
88
|
+
* If explicitly set to null, tells {@link Facade#init} to skip {@link Facade#installWorker} call.
|
89
|
+
* Useful for complex test runner integrations, where you have to install the worker via a separate call,
|
90
|
+
* when the environment is ready for that.
|
91
|
+
*
|
92
|
+
* @default 'worker'
|
93
|
+
*/
|
94
|
+
workerId: string | null;
|
73
95
|
};
|
74
96
|
|
75
|
-
type
|
97
|
+
type DetoxInstallWorkerOptions = {
|
98
|
+
/**
|
99
|
+
* Used for integration with sandboxed test environments.
|
100
|
+
* {@link DetoxInternals.Facade#setup} might override {@link Console} methods
|
101
|
+
* to integrate it with Detox loggeing subsystem.
|
102
|
+
*/
|
76
103
|
global: NodeJS.Global;
|
77
|
-
|
104
|
+
/**
|
105
|
+
* Worker ID. Used to distinguish allocated workers in parallel test execution environment.
|
106
|
+
*
|
107
|
+
* @default 'worker'
|
108
|
+
*/
|
109
|
+
workerId: string;
|
78
110
|
};
|
79
111
|
|
80
112
|
type SessionState = Readonly<{
|
113
|
+
/**
|
114
|
+
* Randomly generated ID for the entire Detox test session, including retries.
|
115
|
+
*/
|
116
|
+
id: string;
|
117
|
+
/**
|
118
|
+
* Permanently failed test file paths.
|
119
|
+
*/
|
81
120
|
failedTestFiles: string[];
|
121
|
+
/**
|
122
|
+
* Failed test file paths suggested to retry via Detox CLI mechanism.
|
123
|
+
*/
|
82
124
|
testFilesToRetry: string[];
|
125
|
+
/**
|
126
|
+
* Retry index of the test session: 0..retriesCount.
|
127
|
+
*/
|
83
128
|
testSessionIndex: number;
|
129
|
+
/**
|
130
|
+
* TODO
|
131
|
+
*/
|
84
132
|
workersCount: number;
|
85
133
|
}>;
|
86
134
|
|
@@ -95,14 +143,14 @@ declare global {
|
|
95
143
|
apps: Record<string, Readonly<Detox.DetoxAppConfig>>;
|
96
144
|
artifacts: Readonly<Detox.DetoxArtifactsConfig>;
|
97
145
|
behavior: Readonly<Detox.DetoxBehaviorConfig>;
|
98
|
-
cli: Readonly<
|
146
|
+
cli: Readonly<CLIConfig>;
|
99
147
|
device: Readonly<Detox.DetoxDeviceConfig>;
|
100
148
|
logger: Readonly<Detox.DetoxLoggerConfig>;
|
101
149
|
testRunner: Readonly<Detox.DetoxTestRunnerConfig>;
|
102
150
|
session: Readonly<Detox.DetoxSessionConfig>;
|
103
151
|
}>;
|
104
152
|
|
105
|
-
type
|
153
|
+
type CLIConfig = Readonly<Partial<{
|
106
154
|
appLaunchArgs: string;
|
107
155
|
artifactsLocation: string;
|
108
156
|
captureViewHierarchy: string;
|
package/local-cli/cli.js
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
const yargs = require('yargs');
|
3
3
|
|
4
4
|
const DetoxError = require('../src/errors/DetoxError');
|
5
|
-
const logger = require('../src/utils/logger').child({
|
5
|
+
const logger = require('../src/utils/logger').child({ cat: 'cli' });
|
6
6
|
|
7
7
|
yargs
|
8
8
|
.scriptName('detox')
|
@@ -4,7 +4,7 @@ const path = require('path');
|
|
4
4
|
|
5
5
|
const fs = require('fs-extra');
|
6
6
|
|
7
|
-
const log = require('../src/utils/logger').child({
|
7
|
+
const log = require('../src/utils/logger').child({ cat: 'cli' });
|
8
8
|
|
9
9
|
module.exports.command = 'rebuild-framework-cache';
|
10
10
|
module.exports.desc = 'Rebuilds a cached Detox framework for the current environment in ~/Library/Detox. The cached framework is unique for each combination of Xcode and Detox version. (macOS only)';
|
package/local-cli/test.js
CHANGED
@@ -9,9 +9,10 @@ module.exports.middlewares = require('./testCommand/middlewares').default;
|
|
9
9
|
|
10
10
|
module.exports.handler = async function test({ detoxArgs, runnerArgs }) {
|
11
11
|
try {
|
12
|
-
await detox.
|
12
|
+
await detox.init({
|
13
13
|
argv: detoxArgs,
|
14
14
|
testRunnerArgv: runnerArgs,
|
15
|
+
workerId: null,
|
15
16
|
});
|
16
17
|
|
17
18
|
const runnerCommand = new TestRunnerCommand()
|
@@ -21,6 +22,6 @@ module.exports.handler = async function test({ detoxArgs, runnerArgs }) {
|
|
21
22
|
|
22
23
|
await runnerCommand.execute();
|
23
24
|
} finally {
|
24
|
-
await detox.
|
25
|
+
await detox.cleanup();
|
25
26
|
}
|
26
27
|
};
|
package/local-cli/test.test.js
CHANGED
@@ -504,7 +504,7 @@ describe('CLI', () => {
|
|
504
504
|
return {
|
505
505
|
...mockCall,
|
506
506
|
fullCommand: _.chain(logger().log.mock.calls)
|
507
|
-
.filter(([_level, _childMeta, meta]) => meta && meta.
|
507
|
+
.filter(([_level, _childMeta, meta]) => meta && meta.env)
|
508
508
|
.get(index)
|
509
509
|
.get(3)
|
510
510
|
.value(),
|
@@ -5,6 +5,7 @@ const parser = require('yargs-parser');
|
|
5
5
|
const unparse = require('yargs-unparser');
|
6
6
|
|
7
7
|
const detox = require('../../internals');
|
8
|
+
const log = detox.log.child({ cat: ['lifecycle', 'cli'] });
|
8
9
|
const { DetoxRuntimeError } = require('../../src/errors');
|
9
10
|
const { printEnvironmentVariables, prependNodeModulesBinToPATH } = require('../../src/utils/envUtils');
|
10
11
|
const { escapeSpaces } = require('../../src/utils/shellUtils');
|
@@ -45,7 +46,7 @@ class TestRunnerCommand {
|
|
45
46
|
}
|
46
47
|
|
47
48
|
/**
|
48
|
-
* @param {Partial<Readonly<DetoxInternals.
|
49
|
+
* @param {Partial<Readonly<DetoxInternals.CLIConfig>>} cliConfig
|
49
50
|
* @returns {this}
|
50
51
|
*/
|
51
52
|
replicateCLIConfig(cliConfig) {
|
@@ -88,7 +89,7 @@ class TestRunnerCommand {
|
|
88
89
|
try {
|
89
90
|
if (launchError) {
|
90
91
|
const list = this._argv._.map((file, index) => ` ${index + 1}. ${file}`).join('\n');
|
91
|
-
|
92
|
+
log.error(
|
92
93
|
`There were failing tests in the following files:\n${list}\n\n` +
|
93
94
|
'Detox CLI is going to restart the test runner with those files...\n'
|
94
95
|
);
|
@@ -104,11 +105,13 @@ class TestRunnerCommand {
|
|
104
105
|
throw e;
|
105
106
|
}
|
106
107
|
|
107
|
-
|
108
|
-
|
109
|
-
|
108
|
+
if (--runsLeft > 0) {
|
109
|
+
this._argv._ = testFilesToRetry.splice(0, Infinity);
|
110
|
+
// @ts-ignore
|
111
|
+
detox.session.testSessionIndex++; // it is always a primary context, so we can update it
|
112
|
+
}
|
110
113
|
}
|
111
|
-
} while (launchError &&
|
114
|
+
} while (launchError && runsLeft > 0);
|
112
115
|
|
113
116
|
if (launchError) {
|
114
117
|
throw launchError;
|
@@ -119,7 +122,7 @@ class TestRunnerCommand {
|
|
119
122
|
const fullCommand = this._buildSpawnArguments().map(escapeSpaces);
|
120
123
|
const fullCommandWithHint = printEnvironmentVariables(this._envHint) + fullCommand.join(' ');
|
121
124
|
|
122
|
-
|
125
|
+
log.info({ env: this._envHint }, fullCommandWithHint);
|
123
126
|
|
124
127
|
return new Promise((resolve, reject) => {
|
125
128
|
cp.spawn(fullCommand[0], fullCommand.slice(1), {
|
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.0.
|
4
|
+
"version": "20.0.7-prerelease.0",
|
5
5
|
"bin": {
|
6
6
|
"detox": "local-cli/cli.js"
|
7
7
|
},
|
@@ -57,13 +57,14 @@
|
|
57
57
|
"dependencies": {
|
58
58
|
"ajv": "^8.6.3",
|
59
59
|
"bunyan": "^1.8.12",
|
60
|
-
"bunyan-debug-stream": "^3.0
|
60
|
+
"bunyan-debug-stream": "^3.1.0",
|
61
61
|
"chalk": "^2.4.2",
|
62
62
|
"child-process-promise": "^2.2.0",
|
63
63
|
"duplexify": "^4.1.2",
|
64
64
|
"find-up": "^4.1.0",
|
65
65
|
"fs-extra": "^4.0.2",
|
66
66
|
"funpermaproxy": "^1.0.1",
|
67
|
+
"glob": "^8.0.3",
|
67
68
|
"ini": "^1.3.4",
|
68
69
|
"json-cycle": "^1.3.0",
|
69
70
|
"lodash": "^4.17.5",
|
@@ -83,7 +84,7 @@
|
|
83
84
|
"tail": "^2.0.0",
|
84
85
|
"telnet-client": "1.2.8",
|
85
86
|
"tempfile": "^2.0.0",
|
86
|
-
"trace-event-lib": "^1.1
|
87
|
+
"trace-event-lib": "^1.3.1",
|
87
88
|
"which": "^1.3.1",
|
88
89
|
"ws": "^7.0.0",
|
89
90
|
"yargs": "^16.0.3",
|
@@ -183,5 +184,5 @@
|
|
183
184
|
}
|
184
185
|
}
|
185
186
|
},
|
186
|
-
"gitHead": "
|
187
|
+
"gitHead": "4b75f39310b93707f01e2bb38a4fba4d385e8acd"
|
187
188
|
}
|
@@ -1 +1 @@
|
|
1
|
-
module.exports = async () => require('../../internals').
|
1
|
+
module.exports = async () => require('../../internals').init({ workerId: null });
|
@@ -1 +1 @@
|
|
1
|
-
module.exports = async () => require('../../internals').
|
1
|
+
module.exports = async () => require('../../internals').cleanup();
|
@@ -1,9 +1,9 @@
|
|
1
|
-
|
2
|
-
const maybeNodeEnvironment = require('jest-environment-node');
|
1
|
+
const resolveFrom = require('resolve-from');
|
2
|
+
const maybeNodeEnvironment = require(resolveFrom(process.cwd(), 'jest-environment-node'));
|
3
|
+
// @ts-ignore
|
3
4
|
const NodeEnvironment = maybeNodeEnvironment.default || maybeNodeEnvironment;
|
4
5
|
|
5
6
|
const detox = require('../../../internals');
|
6
|
-
const { DetoxError } = require('../../../src/errors');
|
7
7
|
const Timer = require('../../../src/utils/Timer');
|
8
8
|
|
9
9
|
const {
|
@@ -24,6 +24,8 @@ const SYNC_CIRCUS_EVENTS = new Set([
|
|
24
24
|
'error',
|
25
25
|
]);
|
26
26
|
|
27
|
+
const log = detox.log.child({ cat: 'lifecycle,jest-environment' });
|
28
|
+
|
27
29
|
/**
|
28
30
|
* @see https://www.npmjs.com/package/jest-circus#overview
|
29
31
|
*/
|
@@ -41,18 +43,31 @@ class DetoxCircusEnvironment extends NodeEnvironment {
|
|
41
43
|
SpecReporter,
|
42
44
|
WorkerAssignReporter,
|
43
45
|
};
|
44
|
-
/** @
|
46
|
+
/** @private */
|
47
|
+
this._shouldManageDetox = detox.getStatus() === 'inactive';
|
48
|
+
/** @internal */
|
45
49
|
this.testPath = context.testPath;
|
46
50
|
/** @protected */
|
47
51
|
this.testEventListeners = [];
|
48
52
|
/** @protected */
|
49
53
|
this.initTimeout = detox.config.testRunner.jest.initTimeout;
|
54
|
+
/** @internal */
|
55
|
+
log.trace.begin(this.testPath);
|
56
|
+
|
57
|
+
this.setup = log.trace.complete.bind(null, 'set up environment', this.setup.bind(this));
|
58
|
+
const _teardown = this.teardown.bind(this);
|
59
|
+
this.teardown = async () => {
|
60
|
+
try {
|
61
|
+
await log.trace.complete('tear down environment', _teardown);
|
62
|
+
} finally {
|
63
|
+
await log.trace.end();
|
64
|
+
}
|
65
|
+
};
|
50
66
|
}
|
51
67
|
|
52
68
|
/** @override */
|
53
69
|
async setup() {
|
54
70
|
await super.setup();
|
55
|
-
|
56
71
|
await Timer.run({
|
57
72
|
description: `setting up Detox environment`,
|
58
73
|
timeout: this.initTimeout,
|
@@ -85,7 +100,7 @@ class DetoxCircusEnvironment extends NodeEnvironment {
|
|
85
100
|
try {
|
86
101
|
await this._timer.run(() => listener[name](event, state));
|
87
102
|
} catch (listenerError) {
|
88
|
-
|
103
|
+
log.error(listenerError);
|
89
104
|
break;
|
90
105
|
}
|
91
106
|
}
|
@@ -100,9 +115,7 @@ class DetoxCircusEnvironment extends NodeEnvironment {
|
|
100
115
|
await Timer.run({
|
101
116
|
description: `tearing down Detox environment`,
|
102
117
|
timeout: this.initTimeout,
|
103
|
-
fn: async () =>
|
104
|
-
await this.cleanupDetox();
|
105
|
-
},
|
118
|
+
fn: async () => await this.cleanupDetox(),
|
106
119
|
});
|
107
120
|
}
|
108
121
|
|
@@ -115,15 +128,25 @@ class DetoxCircusEnvironment extends NodeEnvironment {
|
|
115
128
|
* @protected
|
116
129
|
*/
|
117
130
|
async initDetox() {
|
118
|
-
|
131
|
+
const opts = {
|
119
132
|
global: this.global,
|
120
|
-
workerId:
|
121
|
-
}
|
133
|
+
workerId: `w${process.env.JEST_WORKER_ID}`,
|
134
|
+
};
|
135
|
+
|
136
|
+
if (this._shouldManageDetox) {
|
137
|
+
await detox.init(opts);
|
138
|
+
} else {
|
139
|
+
await detox.installWorker(opts);
|
140
|
+
}
|
122
141
|
}
|
123
142
|
|
124
143
|
/** @protected */
|
125
144
|
async cleanupDetox() {
|
126
|
-
|
145
|
+
if (this._shouldManageDetox) {
|
146
|
+
await detox.cleanup();
|
147
|
+
} else {
|
148
|
+
await detox.uninstallWorker();
|
149
|
+
}
|
127
150
|
}
|
128
151
|
|
129
152
|
/** @private */
|
@@ -145,11 +168,6 @@ class DetoxCircusEnvironment extends NodeEnvironment {
|
|
145
168
|
}));
|
146
169
|
}
|
147
170
|
}
|
148
|
-
|
149
|
-
/** @private */
|
150
|
-
_logError(e) {
|
151
|
-
detox.log.error(DetoxError.format(e));
|
152
|
-
}
|
153
171
|
}
|
154
172
|
|
155
173
|
module.exports = DetoxCircusEnvironment;
|
@@ -7,6 +7,8 @@ const { getFullTestName, hasTimedOut } = require('../utils');
|
|
7
7
|
|
8
8
|
const RETRY_TIMES = Symbol.for('RETRY_TIMES');
|
9
9
|
|
10
|
+
const log = detoxInternals.log.child({ cat: 'lifecycle,jest-environment' });
|
11
|
+
|
10
12
|
class DetoxCoreListener {
|
11
13
|
constructor({ env }) {
|
12
14
|
this._startedTests = new WeakSet();
|
@@ -15,11 +17,6 @@ class DetoxCoreListener {
|
|
15
17
|
this._testRunTimes = 1;
|
16
18
|
}
|
17
19
|
|
18
|
-
_getTestInvocations(test) {
|
19
|
-
const { testSessionIndex } = detoxInternals.session;
|
20
|
-
return testSessionIndex * this._testRunTimes + test.invocations;
|
21
|
-
}
|
22
|
-
|
23
20
|
async setup() {
|
24
21
|
// Workaround to override Jest's expect
|
25
22
|
if (detoxInternals.config.behavior.init.exposeGlobals) {
|
@@ -27,15 +24,19 @@ class DetoxCoreListener {
|
|
27
24
|
}
|
28
25
|
}
|
29
26
|
|
30
|
-
async run_describe_start({ describeBlock
|
31
|
-
if (children.length) {
|
32
|
-
|
27
|
+
async run_describe_start({ describeBlock }) {
|
28
|
+
if (describeBlock.children.length) {
|
29
|
+
log.trace.begin(describeBlock.parent ? describeBlock.name : 'run the tests');
|
30
|
+
await detoxInternals.onRunDescribeStart({
|
31
|
+
name: describeBlock.name,
|
32
|
+
});
|
33
33
|
}
|
34
34
|
}
|
35
35
|
|
36
|
-
async run_describe_finish({ describeBlock
|
37
|
-
if (children.length) {
|
38
|
-
await detoxInternals.onRunDescribeFinish({ name });
|
36
|
+
async run_describe_finish({ describeBlock }) {
|
37
|
+
if (describeBlock.children.length) {
|
38
|
+
await detoxInternals.onRunDescribeFinish({ name: describeBlock.name });
|
39
|
+
log.trace.end();
|
39
40
|
}
|
40
41
|
}
|
41
42
|
|
@@ -48,61 +49,87 @@ class DetoxCoreListener {
|
|
48
49
|
this._testRunTimes = isNaN(circusRetryTimes) ? 1 : 1 + circusRetryTimes;
|
49
50
|
}
|
50
51
|
|
51
|
-
async hook_start(
|
52
|
+
async hook_start(event, state) {
|
52
53
|
await this._onBeforeActualTestStart(state.currentlyRunningTest);
|
54
|
+
log.trace.begin({ functionCode: event.hook.fn.toString() }, event.hook.type);
|
55
|
+
}
|
56
|
+
|
57
|
+
async hook_success() {
|
58
|
+
log.trace.end({ success: true });
|
53
59
|
}
|
54
60
|
|
55
|
-
async hook_failure({ error
|
56
|
-
|
57
|
-
error,
|
58
|
-
hook: hook.type,
|
59
|
-
});
|
61
|
+
async hook_failure({ error }) {
|
62
|
+
log.trace.end({ success: false, error });
|
60
63
|
}
|
61
64
|
|
62
65
|
async test_fn_start({ test }) {
|
63
66
|
await this._onBeforeActualTestStart(test);
|
67
|
+
log.trace.begin({ functionCode: test.fn.toString() }, 'test_fn');
|
64
68
|
}
|
65
69
|
|
66
|
-
async
|
67
|
-
|
70
|
+
async test_fn_success() {
|
71
|
+
log.trace.end({ success: true });
|
68
72
|
}
|
69
73
|
|
70
|
-
async
|
71
|
-
|
72
|
-
|
73
|
-
}
|
74
|
-
|
75
|
-
this._startedTests.add(test);
|
76
|
-
|
77
|
-
await detoxInternals.onTestStart({
|
78
|
-
title: test.name,
|
79
|
-
fullName: getFullTestName(test),
|
80
|
-
status: 'running',
|
81
|
-
invocations: this._getTestInvocations(test),
|
82
|
-
});
|
74
|
+
async test_fn_failure({ error }) {
|
75
|
+
await detoxInternals.onTestFnFailure({ error });
|
76
|
+
log.trace.end({ success: false, error });
|
83
77
|
}
|
84
78
|
|
85
79
|
async test_done({ test }) {
|
86
80
|
if (this._startedTests.has(test)) {
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
status:
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
81
|
+
const failed = test.errors.length > 0;
|
82
|
+
const metadata = {
|
83
|
+
...this._getTestMetadata(test),
|
84
|
+
status: failed ? 'failed' : 'passed',
|
85
|
+
timedOut: failed ? hasTimedOut(test) : undefined,
|
86
|
+
};
|
87
|
+
|
88
|
+
await detoxInternals.onTestDone(metadata);
|
95
89
|
this._startedTests.delete(test);
|
90
|
+
log.trace.end({
|
91
|
+
status: metadata.status,
|
92
|
+
timedOut: metadata.timedOut,
|
93
|
+
});
|
96
94
|
}
|
97
95
|
}
|
98
96
|
|
99
97
|
async run_finish(_event, state) {
|
100
|
-
|
98
|
+
const hasFailedTests = this._hasFailedTests(state.rootDescribeBlock);
|
99
|
+
if (hasFailedTests) {
|
101
100
|
const handledByJestCircus = this._testRunTimes > 1 && !detoxInternals.config.testRunner.jest.retryAfterCircusRetries;
|
102
101
|
await detoxInternals.reportFailedTests([this._env.testPath], handledByJestCircus);
|
103
102
|
}
|
104
103
|
}
|
105
104
|
|
105
|
+
async _onBeforeActualTestStart(test) {
|
106
|
+
if (!test || test.status === 'skip' || this._startedTests.has(test) || this._testsFailedBeforeStart.has(test)) {
|
107
|
+
return false;
|
108
|
+
}
|
109
|
+
|
110
|
+
const metadata = {
|
111
|
+
...this._getTestMetadata(test),
|
112
|
+
status: 'running',
|
113
|
+
};
|
114
|
+
|
115
|
+
this._startedTests.add(test);
|
116
|
+
|
117
|
+
log.trace.begin({
|
118
|
+
context: 'test',
|
119
|
+
status: metadata.status,
|
120
|
+
fullName: metadata.fullName,
|
121
|
+
invocations: metadata.invocations,
|
122
|
+
}, metadata.title);
|
123
|
+
|
124
|
+
await detoxInternals.onTestStart(metadata);
|
125
|
+
return true;
|
126
|
+
}
|
127
|
+
|
128
|
+
_getTestInvocations(test) {
|
129
|
+
const { testSessionIndex } = detoxInternals.session;
|
130
|
+
return testSessionIndex * this._testRunTimes + test.invocations;
|
131
|
+
}
|
132
|
+
|
106
133
|
_hasFailedTests(block) {
|
107
134
|
if (block.children) {
|
108
135
|
for (const child of block.children) {
|
@@ -114,6 +141,14 @@ class DetoxCoreListener {
|
|
114
141
|
|
115
142
|
return block.errors ? block.errors.length > 0 : false;
|
116
143
|
}
|
144
|
+
|
145
|
+
_getTestMetadata(test) {
|
146
|
+
return {
|
147
|
+
title: test.name,
|
148
|
+
fullName: getFullTestName(test),
|
149
|
+
invocations: this._getTestInvocations(test),
|
150
|
+
};
|
151
|
+
}
|
117
152
|
}
|
118
153
|
|
119
154
|
module.exports = DetoxCoreListener;
|
@@ -118,7 +118,7 @@ class SpecReporter {
|
|
118
118
|
const retriesDescription = (invocations > 1) ? chalk.gray(` [Retry #${invocations - 1}]`) : '';
|
119
119
|
const status = chalk.gray(_status ? ` [${_status}]` : '');
|
120
120
|
const desc = this._suitesDesc + testDescription + retriesDescription + status;
|
121
|
-
log.info({
|
121
|
+
log.info({ cat: 'lifecycle' }, desc);
|
122
122
|
}
|
123
123
|
}
|
124
124
|
|
@@ -13,7 +13,7 @@ class WorkerAssignReporter {
|
|
13
13
|
|
14
14
|
run_start() {
|
15
15
|
if (config.testRunner.jest.reportWorkerAssign) {
|
16
|
-
log.info({
|
16
|
+
log.info({ cat: 'lifecycle' }, `${this._formatTestName()} is assigned to ${this._formatDeviceName()}`);
|
17
17
|
}
|
18
18
|
}
|
19
19
|
|
package/src/DetoxWorker.js
CHANGED
@@ -32,6 +32,8 @@ class DetoxWorker {
|
|
32
32
|
onError: this._onEmitError.bind(this),
|
33
33
|
});
|
34
34
|
|
35
|
+
/** @type {string} */
|
36
|
+
this.id = 'worker';
|
35
37
|
/** @type {Detox.Device} */
|
36
38
|
this.device = null;
|
37
39
|
/** @type {Detox.ElementFacade} */
|
@@ -63,14 +65,15 @@ class DetoxWorker {
|
|
63
65
|
device: deviceConfig,
|
64
66
|
session: sessionConfig
|
65
67
|
} = this._config;
|
68
|
+
|
66
69
|
this._appsConfig = appsConfig;
|
67
70
|
this._artifactsConfig = artifactsConfig;
|
68
71
|
this._behaviorConfig = behaviorConfig;
|
69
72
|
this._deviceConfig = deviceConfig;
|
70
73
|
this._sessionConfig = sessionConfig;
|
74
|
+
this._sessionConfig.sessionId = sessionConfig.sessionId || uuid.UUID();
|
71
75
|
this._runtimeErrorComposer.appsConfig = this._appsConfig;
|
72
76
|
|
73
|
-
sessionConfig.sessionId = sessionConfig.sessionId || uuid.UUID();
|
74
77
|
this._client = new Client(sessionConfig);
|
75
78
|
this._client.terminateApp = async () => {
|
76
79
|
// @ts-ignore
|
@@ -192,7 +195,6 @@ class DetoxWorker {
|
|
192
195
|
onTestStart = async (testSummary) => {
|
193
196
|
if (this._isCleaningUp) return;
|
194
197
|
this._validateTestSummary('beforeEach', testSummary);
|
195
|
-
this._logTestRunCheckpoint('DETOX_BEFORE_EACH', testSummary);
|
196
198
|
|
197
199
|
if (this._isCleaningUp) return;
|
198
200
|
await this._dumpUnhandledErrorsIfAny({
|
@@ -212,7 +214,6 @@ class DetoxWorker {
|
|
212
214
|
onTestDone = async (testSummary) => {
|
213
215
|
if (this._isCleaningUp) return;
|
214
216
|
this._validateTestSummary('afterEach', testSummary);
|
215
|
-
this._logTestRunCheckpoint('DETOX_AFTER_EACH', testSummary);
|
216
217
|
|
217
218
|
if (this._isCleaningUp) return;
|
218
219
|
await this._artifactsManager.onTestDone(testSummary);
|
@@ -248,10 +249,6 @@ class DetoxWorker {
|
|
248
249
|
}
|
249
250
|
}
|
250
251
|
|
251
|
-
_logTestRunCheckpoint(event, { status, fullName }) {
|
252
|
-
this.log.trace({ event, status }, `${status} test: ${JSON.stringify(fullName)}`);
|
253
|
-
}
|
254
|
-
|
255
252
|
_validateTestSummary(methodName, testSummary) {
|
256
253
|
if (!_.isPlainObject(testSummary)) {
|
257
254
|
throw this._runtimeErrorComposer.invalidTestSummary(methodName, testSummary);
|