detox 20.0.3-breaking.new-global-lifecycle.0 → 20.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (192) hide show
  1. package/Detox-android/com/wix/detox/{20.0.3-breaking.new-global-lifecycle.0/detox-20.0.3-breaking.new-global-lifecycle.0-javadoc.jar → 20.0.3/detox-20.0.3-javadoc.jar} +0 -0
  2. package/Detox-android/com/wix/detox/20.0.3/detox-20.0.3-javadoc.jar.md5 +1 -0
  3. package/Detox-android/com/wix/detox/20.0.3/detox-20.0.3-javadoc.jar.sha1 +1 -0
  4. package/Detox-android/com/wix/detox/20.0.3/detox-20.0.3-javadoc.jar.sha256 +1 -0
  5. package/Detox-android/com/wix/detox/20.0.3/detox-20.0.3-javadoc.jar.sha512 +1 -0
  6. package/Detox-android/com/wix/detox/{20.0.3-breaking.new-global-lifecycle.0/detox-20.0.3-breaking.new-global-lifecycle.0-sources.jar → 20.0.3/detox-20.0.3-sources.jar} +0 -0
  7. package/Detox-android/com/wix/detox/20.0.3/detox-20.0.3-sources.jar.md5 +1 -0
  8. package/Detox-android/com/wix/detox/20.0.3/detox-20.0.3-sources.jar.sha1 +1 -0
  9. package/Detox-android/com/wix/detox/20.0.3/detox-20.0.3-sources.jar.sha256 +1 -0
  10. package/Detox-android/com/wix/detox/20.0.3/detox-20.0.3-sources.jar.sha512 +1 -0
  11. package/Detox-android/com/wix/detox/20.0.3/detox-20.0.3.aar +0 -0
  12. package/Detox-android/com/wix/detox/20.0.3/detox-20.0.3.aar.md5 +1 -0
  13. package/Detox-android/com/wix/detox/20.0.3/detox-20.0.3.aar.sha1 +1 -0
  14. package/Detox-android/com/wix/detox/20.0.3/detox-20.0.3.aar.sha256 +1 -0
  15. package/Detox-android/com/wix/detox/20.0.3/detox-20.0.3.aar.sha512 +1 -0
  16. package/Detox-android/com/wix/detox/{20.0.3-breaking.new-global-lifecycle.0/detox-20.0.3-breaking.new-global-lifecycle.0.pom → 20.0.3/detox-20.0.3.pom} +1 -7
  17. package/Detox-android/com/wix/detox/20.0.3/detox-20.0.3.pom.md5 +1 -0
  18. package/Detox-android/com/wix/detox/20.0.3/detox-20.0.3.pom.sha1 +1 -0
  19. package/Detox-android/com/wix/detox/20.0.3/detox-20.0.3.pom.sha256 +1 -0
  20. package/Detox-android/com/wix/detox/20.0.3/detox-20.0.3.pom.sha512 +1 -0
  21. package/Detox-android/com/wix/detox/maven-metadata.xml +4 -4
  22. package/Detox-android/com/wix/detox/maven-metadata.xml.md5 +1 -1
  23. package/Detox-android/com/wix/detox/maven-metadata.xml.sha1 +1 -1
  24. package/Detox-android/com/wix/detox/maven-metadata.xml.sha256 +1 -1
  25. package/Detox-android/com/wix/detox/maven-metadata.xml.sha512 +1 -1
  26. package/Detox-ios-src.tbz +0 -0
  27. package/Detox-ios.tbz +0 -0
  28. package/README.md +1 -1
  29. package/android/build.gradle +12 -7
  30. package/android/detox/build.gradle +13 -9
  31. package/android/detox/proguard-rules-app.pro +6 -0
  32. package/android/detox/proguard-rules.pro +3 -0
  33. package/android/detox/publishing.gradle +27 -27
  34. package/android/detox/src/full/java/com/wix/detox/DetoxCrashHandler.kt +1 -1
  35. package/android/detox/src/full/java/com/wix/detox/LaunchArgs.java +9 -0
  36. package/android/detox/src/full/java/com/wix/detox/TestEngineFacade.kt +1 -1
  37. package/android/detox/src/full/java/com/wix/detox/reactnative/ReactNativeExtension.kt +15 -2
  38. package/android/detox/src/full/java/com/wix/detox/reactnative/ReactNativeIdlingResources.kt +43 -38
  39. package/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/IdlingResourceDescription.kt +19 -13
  40. package/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/NetworkIdlingResource.java +33 -30
  41. package/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/timers/DelegatedIdleInterrogationStrategy.kt +7 -27
  42. package/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/timers/IdleInterrogationStrategy.kt +1 -11
  43. package/android/detox/src/main/java/com/wix/detox/common/TextFileReader.kt +1 -1
  44. package/android/detox/src/testFull/java/com/wix/detox/espresso/action/DetoxMultiTapSpec.kt +4 -3
  45. package/android/detox/src/testFull/java/com/wix/detox/reactnative/idlingresources/NetworkIdlingResourcesTest.kt +61 -0
  46. package/android/detox/src/testFull/java/com/wix/detox/reactnative/idlingresources/timers/DelegatedIdleInterrogationStrategySpec.kt +3 -11
  47. package/index.d.ts +195 -59
  48. package/internals.d.ts +205 -43
  49. package/local-cli/build.js +1 -1
  50. package/local-cli/cli.js +11 -6
  51. package/local-cli/init.js +61 -21
  52. package/local-cli/rebuild-framework-cache.js +1 -1
  53. package/local-cli/reset-lock-file.js +16 -0
  54. package/local-cli/templates/jest.js +13 -10
  55. package/local-cli/test.js +14 -8
  56. package/local-cli/test.test.js +142 -61
  57. package/local-cli/testCommand/TestRunnerCommand.js +97 -77
  58. package/local-cli/testCommand/TestRunnerError.js +17 -0
  59. package/local-cli/testCommand/TestRunnerError.test.js +25 -0
  60. package/local-cli/testCommand/builder.js +0 -1
  61. package/local-cli/testCommand/middlewares.js +4 -13
  62. package/local-cli/testCommand/warnings.js +0 -3
  63. package/local-cli/utils/jestInternals.js +4 -1
  64. package/package.json +23 -18
  65. package/runners/deprecation.js +42 -44
  66. package/runners/jest/globalSetup.js +1 -1
  67. package/runners/jest/globalTeardown.js +1 -1
  68. package/runners/jest/index.d.ts +60 -0
  69. package/runners/jest/index.js +3 -8
  70. package/runners/jest/index.test.js +13 -0
  71. package/runners/jest/reporters/DetoxReporter.js +33 -2
  72. package/runners/jest/testEnvironment/index.js +119 -69
  73. package/runners/jest/testEnvironment/listeners/DetoxCoreListener.js +93 -46
  74. package/runners/jest/testEnvironment/listeners/DetoxPlatformFilterListener.js +1 -1
  75. package/runners/jest/testEnvironment/listeners/SpecReporter.js +13 -15
  76. package/runners/jest/testEnvironment/listeners/WorkerAssignReporter.js +1 -5
  77. package/runners/jest/testEnvironment/utils/assertJestCircus27.js +17 -3
  78. package/runners/jest/testEnvironment/utils/assertJestCircus27.test.js +0 -1
  79. package/src/DetoxWorker.js +99 -62
  80. package/src/android/core/NativeElement.js +56 -20
  81. package/src/android/core/NativeExpect.js +28 -9
  82. package/src/android/interactions/native.js +25 -18
  83. package/src/artifacts/ArtifactsManager.js +14 -47
  84. package/src/artifacts/instruments/ios/SimulatorInstrumentsRecording.js +3 -3
  85. package/src/artifacts/log/ios/SimulatorLogRecording.js +1 -1
  86. package/src/artifacts/screenshot/SimulatorScreenshotPlugin.js +1 -1
  87. package/src/artifacts/templates/artifact/Artifact.js +1 -1
  88. package/src/artifacts/templates/plugin/ArtifactPlugin.js +1 -1
  89. package/src/artifacts/timeline/TimelineContextTypes.js +7 -0
  90. package/src/artifacts/utils/temporaryPath.js +49 -8
  91. package/src/artifacts/video/SimulatorRecordVideoPlugin.js +1 -1
  92. package/src/client/AsyncWebSocket.js +8 -17
  93. package/src/client/Client.js +19 -2
  94. package/src/client/actions/formatters/sync-resources/NetworkFormatter.js +1 -1
  95. package/src/configuration/collectCliConfig.js +1 -12
  96. package/src/configuration/composeAppsConfig.js +4 -0
  97. package/src/configuration/composeDeviceConfig.js +1 -1
  98. package/src/configuration/composeLoggerConfig.js +19 -10
  99. package/src/configuration/composeRunnerConfig.js +14 -9
  100. package/src/configuration/index.js +5 -1
  101. package/src/configuration/loadExternalConfig.js +1 -1
  102. package/src/devices/allocation/DeviceAllocator.js +3 -2
  103. package/src/devices/allocation/drivers/android/emulator/AVDValidator.js +5 -5
  104. package/src/devices/allocation/drivers/android/emulator/EmulatorAllocDriver.js +4 -3
  105. package/src/devices/allocation/drivers/android/emulator/EmulatorAllocationHelper.js +1 -1
  106. package/src/devices/allocation/drivers/android/emulator/EmulatorLauncher.js +6 -5
  107. package/src/devices/allocation/drivers/android/emulator/EmulatorVersionResolver.js +4 -6
  108. package/src/devices/allocation/drivers/android/emulator/launchEmulatorProcess.js +4 -17
  109. package/src/devices/allocation/drivers/android/genycloud/GenyInstanceAllocationHelper.js +1 -1
  110. package/src/devices/common/drivers/android/exec/ADB.js +4 -0
  111. package/src/devices/common/drivers/android/genycloud/services/GenyInstanceNaming.js +3 -3
  112. package/src/devices/common/drivers/android/genycloud/services/GenyRecipesService.js +1 -1
  113. package/src/devices/common/drivers/android/tools/EmulatorTelnet.js +1 -1
  114. package/src/devices/common/drivers/android/tools/FreeDeviceFinder.js +1 -1
  115. package/src/devices/common/drivers/android/tools/MonitoredInstrumentation.js +1 -1
  116. package/src/devices/common/drivers/ios/tools/AppleSimUtils.js +29 -3
  117. package/src/devices/lifecycle/GenyGlobalLifecycleHandler.js +13 -15
  118. package/src/devices/runtime/RuntimeDevice.js +19 -12
  119. package/src/devices/runtime/drivers/DeviceDriverBase.js +1 -1
  120. package/src/devices/runtime/drivers/android/AndroidDriver.js +10 -2
  121. package/src/devices/runtime/drivers/ios/SimulatorDriver.js +1 -1
  122. package/src/errors/DetoxConfigErrorComposer.js +14 -1
  123. package/src/errors/DetoxError.js +5 -1
  124. package/src/ios/expectTwo.js +153 -67
  125. package/src/ipc/IPCClient.js +12 -13
  126. package/src/ipc/IPCServer.js +28 -24
  127. package/src/ipc/{state.js → SessionState.js} +26 -53
  128. package/src/logger/DetoxLogger.js +287 -154
  129. package/src/logger/index.js +5 -0
  130. package/src/logger/utils/BunyanLogger.js +115 -0
  131. package/src/logger/utils/CategoryThreadDispatcher.js +37 -0
  132. package/src/logger/utils/DetoxLogFinalizer.js +162 -0
  133. package/src/logger/utils/MessageStack.js +35 -0
  134. package/src/logger/utils/ThreadDispatcher.js +61 -0
  135. package/src/logger/{customConsoleLogger.js → utils/customConsoleLogger.js} +23 -6
  136. package/src/logger/utils/getMainCategory.js +5 -0
  137. package/src/logger/utils/sanitizeBunyanContext.js +30 -0
  138. package/src/logger/utils/streams/BunyanTransformer.js +72 -0
  139. package/src/logger/utils/streams/ChromeTraceTransformer.js +127 -0
  140. package/src/logger/utils/streams/DetoxJSONLParser.js +31 -0
  141. package/src/logger/utils/streams/JSONLStringer.js +55 -0
  142. package/src/logger/utils/streams/index.js +7 -0
  143. package/src/logger/utils/streams/transformers.js +39 -0
  144. package/src/logger/utils/tracerLegacy.js +37 -0
  145. package/src/realms/DetoxContext.js +79 -65
  146. package/src/realms/DetoxInternalsFacade.js +8 -12
  147. package/src/realms/DetoxPrimaryContext.js +104 -70
  148. package/src/realms/DetoxSecondaryContext.js +29 -32
  149. package/src/server/DetoxConnection.js +18 -23
  150. package/src/server/DetoxServer.js +7 -10
  151. package/src/server/DetoxSession.js +6 -6
  152. package/src/server/DetoxSessionManager.js +1 -1
  153. package/src/server/handlers/RegisteredConnectionHandler.js +1 -2
  154. package/src/symbols.js +16 -22
  155. package/src/utils/Timer.js +55 -38
  156. package/src/utils/argparse.js +11 -0
  157. package/src/utils/childProcess/exec.js +1 -1
  158. package/src/utils/childProcess/spawn.js +1 -1
  159. package/src/utils/errorUtils.js +24 -3
  160. package/src/utils/invocationTraceDescriptions.js +43 -0
  161. package/src/utils/logger.js +1 -1
  162. package/src/utils/pathUtils.js +11 -0
  163. package/src/utils/shellUtils.js +17 -0
  164. package/src/utils/traceInvocationCall.js +21 -0
  165. package/src/utils/traceMethods.js +15 -0
  166. package/Detox-android/com/wix/detox/20.0.3-breaking.new-global-lifecycle.0/detox-20.0.3-breaking.new-global-lifecycle.0-javadoc.jar.md5 +0 -1
  167. package/Detox-android/com/wix/detox/20.0.3-breaking.new-global-lifecycle.0/detox-20.0.3-breaking.new-global-lifecycle.0-javadoc.jar.sha1 +0 -1
  168. package/Detox-android/com/wix/detox/20.0.3-breaking.new-global-lifecycle.0/detox-20.0.3-breaking.new-global-lifecycle.0-javadoc.jar.sha256 +0 -1
  169. package/Detox-android/com/wix/detox/20.0.3-breaking.new-global-lifecycle.0/detox-20.0.3-breaking.new-global-lifecycle.0-javadoc.jar.sha512 +0 -1
  170. package/Detox-android/com/wix/detox/20.0.3-breaking.new-global-lifecycle.0/detox-20.0.3-breaking.new-global-lifecycle.0-sources.jar.md5 +0 -1
  171. package/Detox-android/com/wix/detox/20.0.3-breaking.new-global-lifecycle.0/detox-20.0.3-breaking.new-global-lifecycle.0-sources.jar.sha1 +0 -1
  172. package/Detox-android/com/wix/detox/20.0.3-breaking.new-global-lifecycle.0/detox-20.0.3-breaking.new-global-lifecycle.0-sources.jar.sha256 +0 -1
  173. package/Detox-android/com/wix/detox/20.0.3-breaking.new-global-lifecycle.0/detox-20.0.3-breaking.new-global-lifecycle.0-sources.jar.sha512 +0 -1
  174. package/Detox-android/com/wix/detox/20.0.3-breaking.new-global-lifecycle.0/detox-20.0.3-breaking.new-global-lifecycle.0.aar +0 -0
  175. package/Detox-android/com/wix/detox/20.0.3-breaking.new-global-lifecycle.0/detox-20.0.3-breaking.new-global-lifecycle.0.aar.md5 +0 -1
  176. package/Detox-android/com/wix/detox/20.0.3-breaking.new-global-lifecycle.0/detox-20.0.3-breaking.new-global-lifecycle.0.aar.sha1 +0 -1
  177. package/Detox-android/com/wix/detox/20.0.3-breaking.new-global-lifecycle.0/detox-20.0.3-breaking.new-global-lifecycle.0.aar.sha256 +0 -1
  178. package/Detox-android/com/wix/detox/20.0.3-breaking.new-global-lifecycle.0/detox-20.0.3-breaking.new-global-lifecycle.0.aar.sha512 +0 -1
  179. package/Detox-android/com/wix/detox/20.0.3-breaking.new-global-lifecycle.0/detox-20.0.3-breaking.new-global-lifecycle.0.pom.md5 +0 -1
  180. package/Detox-android/com/wix/detox/20.0.3-breaking.new-global-lifecycle.0/detox-20.0.3-breaking.new-global-lifecycle.0.pom.sha1 +0 -1
  181. package/Detox-android/com/wix/detox/20.0.3-breaking.new-global-lifecycle.0/detox-20.0.3-breaking.new-global-lifecycle.0.pom.sha256 +0 -1
  182. package/Detox-android/com/wix/detox/20.0.3-breaking.new-global-lifecycle.0/detox-20.0.3-breaking.new-global-lifecycle.0.pom.sha512 +0 -1
  183. package/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/timers/DefaultIdleInterrogationStrategy.kt +0 -84
  184. package/android/detox/src/testFull/java/com/wix/detox/reactnative/idlingresources/timers/DefaultIdleInterrogationStrategySpec.kt +0 -115
  185. package/runners/jest/deprecation.js +0 -25
  186. package/src/configuration/utils/warnings.js +0 -12
  187. package/src/logger/DetoxTraceEventBuilder.js +0 -21
  188. package/src/logger/DetoxTracer.js +0 -133
  189. package/src/logger/TraceThreadDispatcher.js +0 -52
  190. package/src/utils/ChromeTracingExporter.js +0 -54
  191. package/src/utils/streamUtils.js +0 -214
  192. package/src/utils/trace.js +0 -19
@@ -1,24 +1,31 @@
1
- const path = require('path');
2
1
  const { URL } = require('url');
3
2
 
4
3
  const fs = require('fs-extra');
5
- const pipe = require('multipipe');
4
+ const onSignalExit = require('signal-exit');
6
5
 
7
6
  const temporary = require('../artifacts/utils/temporaryPath');
8
7
  const { DetoxRuntimeError } = require('../errors');
9
- const { PrimarySessionState } = require('../ipc/state');
8
+ const SessionState = require('../ipc/SessionState');
10
9
  const symbols = require('../symbols');
10
+ const { getCurrentCommand } = require('../utils/argparse');
11
+ const uuid = require('../utils/uuid');
11
12
 
12
13
  const DetoxContext = require('./DetoxContext');
13
14
 
14
- const { $logger, $restoreSessionState, $sessionState } = DetoxContext.protected;
15
+ // Protected symbols
16
+ const { $logFinalizer, $restoreSessionState, $sessionState, $worker } = DetoxContext.protected;
15
17
 
16
- const _finalizeLogs = Symbol('finalizeLogs');
18
+ //#region Private symbols
17
19
  const _globalLifecycleHandler = Symbol('globalLifecycleHandler');
18
20
  const _ipcServer = Symbol('ipcServer');
19
21
  const _resetLockFile = Symbol('resetLockFile');
20
22
  const _wss = Symbol('wss');
21
23
  const _dirty = Symbol('dirty');
24
+ const _emergencyTeardown = Symbol('emergencyTeardown');
25
+ const _lifecycleLogger = Symbol('lifecycleLogger');
26
+ const _sessionFile = Symbol('sessionFile');
27
+ const _logFinalError = Symbol('logFinalError');
28
+ //#endregion
22
29
 
23
30
  class DetoxPrimaryContext extends DetoxContext {
24
31
  constructor() {
@@ -27,21 +34,25 @@ class DetoxPrimaryContext extends DetoxContext {
27
34
  this[_dirty] = false;
28
35
  this[_wss] = null;
29
36
  this[_globalLifecycleHandler] = null;
37
+ /** Path to file where the initial session object is serialized */
38
+ this[_sessionFile] = '';
30
39
  /**
31
40
  * @type {import('../ipc/IPCServer') | null}
32
41
  */
33
42
  this[_ipcServer] = null;
43
+ /** @type {Detox.Logger} */
44
+ this[_lifecycleLogger] = this[symbols.logger].child({ cat: 'lifecycle' });
34
45
  }
35
46
 
36
47
  //#region Internal members
37
- async [symbols.reportFailedTests](testFilePaths, permanent = false) {
48
+ async [symbols.reportTestResults](testResults) {
38
49
  if (this[_ipcServer]) {
39
- this[_ipcServer].onFailedTests({ testFilePaths, permanent });
50
+ this[_ipcServer].onReportTestResults({ testResults });
40
51
  }
41
52
  }
42
53
 
43
54
  async [symbols.resolveConfig](opts = {}) {
44
- const session = this[symbols.session];
55
+ const session = this[$sessionState];
45
56
  if (!session.detoxConfig) {
46
57
  const configuration = require('../configuration');
47
58
  session.detoxConfig = await configuration.composeDetoxConfig(opts);
@@ -52,9 +63,9 @@ class DetoxPrimaryContext extends DetoxContext {
52
63
 
53
64
  /**
54
65
  * @override
55
- * @param {Partial<DetoxInternals.DetoxGlobalSetupOptions>} [opts]
66
+ * @param {Partial<DetoxInternals.DetoxInitOptions>} [opts]
56
67
  */
57
- async [symbols.globalSetup](opts) {
68
+ async [symbols.init](opts = {}) {
58
69
  if (this[_dirty]) {
59
70
  throw new DetoxRuntimeError({
60
71
  message: 'Cannot initialize primary Detox context more than once.',
@@ -63,6 +74,8 @@ class DetoxPrimaryContext extends DetoxContext {
63
74
  }
64
75
 
65
76
  this[_dirty] = true;
77
+ onSignalExit(this[_emergencyTeardown]);
78
+
66
79
  const detoxConfig = await this[symbols.resolveConfig](opts);
67
80
 
68
81
  const {
@@ -71,18 +84,17 @@ class DetoxPrimaryContext extends DetoxContext {
71
84
  logger: loggerConfig,
72
85
  session: sessionConfig
73
86
  } = detoxConfig;
74
- await this[$logger].setConfig(loggerConfig);
87
+ await this[symbols.logger].setConfig(loggerConfig);
75
88
 
76
- this.trace.begin({
77
- cat: 'lifecycle',
78
- args: this[$sessionState],
79
- name: process.argv.slice(1).join(' '),
80
- });
89
+ this[_lifecycleLogger].trace.begin({
90
+ cwd: process.cwd(),
91
+ data: this[$sessionState],
92
+ }, getCurrentCommand());
81
93
 
82
94
  const IPCServer = require('../ipc/IPCServer');
83
95
  this[_ipcServer] = new IPCServer({
84
96
  sessionState: this[$sessionState],
85
- logger: this[$logger],
97
+ logger: this[symbols.logger],
86
98
  });
87
99
 
88
100
  await this[_ipcServer].init();
@@ -111,101 +123,123 @@ class DetoxPrimaryContext extends DetoxContext {
111
123
  }
112
124
 
113
125
  if (!sessionConfig.server && this[_wss]) {
126
+ // @ts-ignore
114
127
  sessionConfig.server = `ws://localhost:${this[_wss].port}`;
115
128
  }
116
129
 
117
- await fs.writeFile(this[$sessionState].detoxConfigSnapshotPath, this[$sessionState].stringify());
118
- process.env.DETOX_CONFIG_SNAPSHOT_PATH = this[$sessionState].detoxConfigSnapshotPath;
130
+ this[_sessionFile] = temporary.for.json(this[$sessionState].id);
131
+ await fs.writeFile(this[_sessionFile], this[$sessionState].stringify());
132
+ process.env.DETOX_CONFIG_SNAPSHOT_PATH = this[_sessionFile];
133
+ this[_lifecycleLogger].trace(`Serialized the session state at: ${this[_sessionFile]}`);
119
134
 
120
- // TODO: think about signal-exit and cleaning up the logs
135
+ if (opts.workerId !== null) {
136
+ await this[symbols.installWorker](opts);
137
+ }
121
138
  }
122
139
 
123
140
  /**
124
141
  * @override
125
- * @param {Partial<DetoxInternals.DetoxConfigurationSetupOptions>} [opts]
142
+ * @param {Partial<DetoxInternals.DetoxInstallWorkerOptions>} [opts]
126
143
  */
127
- async [symbols.setup](opts) {
128
- const workerId = opts.workerId || 1;
144
+ async [symbols.installWorker](opts = {}) {
145
+ const workerId = opts.workerId || 'worker';
146
+
129
147
  this[$sessionState].workerId = workerId;
130
148
  this[_ipcServer].onRegisterWorker({ workerId });
131
- await super[symbols.setup](opts);
149
+
150
+ await super[symbols.installWorker]({ ...opts, workerId });
132
151
  }
133
152
 
134
153
  /** @override */
135
- async [symbols.globalTeardown]() {
154
+ async [symbols.cleanup]() {
155
+ try {
156
+ if (this[$worker]) {
157
+ await this[symbols.uninstallWorker]();
158
+ }
159
+ } finally {
160
+ if (this[_globalLifecycleHandler]) {
161
+ await this[_globalLifecycleHandler].globalCleanup();
162
+ this[_globalLifecycleHandler] = null;
163
+ }
164
+
165
+ if (this[_wss]) {
166
+ await this[_wss].close();
167
+ this[_wss] = null;
168
+ }
169
+
170
+ if (this[_ipcServer]) {
171
+ await this[_ipcServer].dispose();
172
+ this[_ipcServer] = null;
173
+ }
174
+
175
+ if (this[_sessionFile]) {
176
+ await fs.remove(this[_sessionFile]);
177
+ }
178
+
179
+ if (this[_dirty]) {
180
+ try {
181
+ this[_lifecycleLogger].trace.end();
182
+ await this[symbols.logger].close();
183
+ await this[$logFinalizer].finalize();
184
+ } catch (err) {
185
+ this[_logFinalError](err);
186
+ }
187
+ }
188
+ }
189
+ }
190
+
191
+ [_emergencyTeardown] = (_code, signal) => {
192
+ if (!signal) {
193
+ return;
194
+ }
195
+
136
196
  if (this[_globalLifecycleHandler]) {
137
- await this[_globalLifecycleHandler].globalCleanup();
197
+ this[_globalLifecycleHandler].emergencyCleanup();
138
198
  this[_globalLifecycleHandler] = null;
139
199
  }
140
200
 
141
201
  if (this[_wss]) {
142
- await this[_wss].close();
143
- this[_wss] = null;
202
+ this[_wss].close();
144
203
  }
145
204
 
146
205
  if (this[_ipcServer]) {
147
- await this[_ipcServer].dispose();
148
- this[_ipcServer] = null;
206
+ this[_ipcServer].dispose();
149
207
  }
150
208
 
151
- await fs.remove(this[$sessionState].detoxConfigSnapshotPath);
152
- delete process.env.DETOX_CONFIG_SNAPSHOT_PATH;
209
+ if (this[_sessionFile]) {
210
+ fs.removeSync(this[_sessionFile]);
211
+ }
153
212
 
154
213
  try {
155
- this.trace.end({ cat: 'lifecycle' });
156
- await this[_finalizeLogs]();
214
+ this[_lifecycleLogger].trace.end({ abortSignal: signal });
215
+ this[symbols.logger].close().catch(this[_logFinalError]);
216
+ this[$logFinalizer].finalizeSync();
157
217
  } catch (err) {
158
- this[$logger].error({ err }, 'Encountered an error while merging the process logs:');
218
+ this[_logFinalError](err);
159
219
  }
160
- }
220
+ };
221
+
222
+ [_logFinalError] = (err) => {
223
+ this[_lifecycleLogger].error(err, 'Encountered an error while merging the process logs:');
224
+ };
225
+
161
226
  //#endregion
162
227
 
163
228
  //#region Protected members
164
229
  /**
165
230
  * @protected
166
231
  * @override
167
- * @return {PrimarySessionState}
232
+ * @return {SessionState}
168
233
  */
169
234
  [$restoreSessionState]() {
170
- return new PrimarySessionState({
171
- detoxConfigSnapshotPath: temporary.for.json(),
235
+ return new SessionState({
236
+ id: uuid.UUID(),
172
237
  detoxIPCServer: `primary-${process.pid}`,
173
238
  });
174
239
  }
175
240
  //#endregion
176
241
 
177
242
  //#region Private members
178
- async[_finalizeLogs]() {
179
- const logs = [this[$logger].file, ...this[$sessionState].logFiles].filter(f => f && fs.existsSync(f));
180
- if (logs.length === 0) {
181
- return;
182
- }
183
-
184
- const streamUtils = require('../utils/streamUtils');
185
- const { rootDir, plugins } = this[symbols.config].artifacts || {};
186
- const logConfig = plugins && plugins.log || 'none';
187
- const enabled = rootDir && (typeof logConfig === 'string' ? logConfig !== 'none' : logConfig.enabled);
188
-
189
- if (enabled) {
190
- await fs.mkdirp(rootDir);
191
- const [out1Stream, out2Stream, out3Stream] = ['detox.log.jsonl', 'detox.log', 'detox.trace.json']
192
- .map((filename) => fs.createWriteStream(path.join(rootDir, filename)));
193
-
194
- const mergedStream = streamUtils
195
- .mergeSortedJSONL(
196
- logs.map(filePath => fs.createReadStream(filePath).pipe(streamUtils.readJSONL()))
197
- );
198
-
199
- await Promise.all([
200
- pipe(mergedStream, streamUtils.writeJSONL(), out1Stream),
201
- pipe(mergedStream, streamUtils.debugStream(this[$logger].config.options), out2Stream),
202
- pipe(mergedStream, streamUtils.chromeTraceStream(), streamUtils.writeJSON(), out3Stream),
203
- ]);
204
- }
205
-
206
- await Promise.all(logs.map(filepath => fs.remove(filepath)));
207
- }
208
-
209
243
  async[_resetLockFile]() {
210
244
  const DeviceRegistry = require('../devices/DeviceRegistry');
211
245
 
@@ -1,29 +1,33 @@
1
1
  const fs = require('fs');
2
2
 
3
3
  const { DetoxInternalError } = require('../errors');
4
- const { SecondarySessionState } = require('../ipc/state');
4
+ const SessionState = require('../ipc/SessionState');
5
5
  const symbols = require('../symbols');
6
6
 
7
7
  const DetoxContext = require('./DetoxContext');
8
8
 
9
- const { $logger, $restoreSessionState, $sessionState } = DetoxContext.protected;
9
+ // Protected symbols
10
+ const { $restoreSessionState, $sessionState, $worker } = DetoxContext.protected;
11
+
12
+ //#region Private symbols
10
13
  const _ipcClient = Symbol('ipcClient');
14
+ //#endregion
11
15
 
12
16
  class DetoxSecondaryContext extends DetoxContext {
13
17
  constructor() {
14
18
  super();
15
19
 
16
20
  /**
17
- * @protected
18
- * @type {*}
21
+ * @private
22
+ * @type {import('../ipc/IPCClient')}
19
23
  */
20
24
  this[_ipcClient] = null;
21
25
  }
22
26
 
23
27
  //#region Internal members
24
- async [symbols.reportFailedTests](testFilePaths, permanent = false) {
28
+ async [symbols.reportTestResults](testResults) {
25
29
  if (this[_ipcClient]) {
26
- await this[_ipcClient].reportFailedTests(testFilePaths, permanent);
30
+ await this[_ipcClient].reportTestResults(testResults);
27
31
  } else {
28
32
  throw new DetoxInternalError('Detected an attempt to report failed tests using a non-initialized context.');
29
33
  }
@@ -34,41 +38,28 @@ class DetoxSecondaryContext extends DetoxContext {
34
38
  }
35
39
 
36
40
  /** @override */
37
- async [symbols.globalSetup](_opts = {}) {
38
- // This is a no-op function.
39
- // It is forbidden to add any logic to `globalSetup` of the secondary context.
40
- // Violating this principle will almost definitely break some flows, where it is
41
- // not guaranteed that `globalSetup` will ever get called. See UML diagrams.
42
- }
43
-
44
- /** @override */
45
- async [symbols.globalTeardown]() {
46
- // This is a no-op function.
47
- // It is forbidden to add any logic to `globalTeardown` of the secondary context.
48
- // Violating this principle will almost definitely break some flows, where it is
49
- // not guaranteed that `globalTeardown` will ever get called. See UML diagrams.
50
- }
51
-
52
- /** @override */
53
- async [symbols.setup](opts) {
41
+ async [symbols.init](opts = {}) {
54
42
  const IPCClient = require('../ipc/IPCClient');
55
43
 
56
44
  this[_ipcClient] = new IPCClient({
57
45
  id: `secondary-${process.pid}`,
58
46
  state: this[$sessionState],
59
- logger: this[$logger],
47
+ logger: this[symbols.logger],
60
48
  });
61
49
 
62
- const workerId = opts.workerId || 1;
63
50
  await this[_ipcClient].init();
64
- await this[_ipcClient].registerWorker(workerId);
65
- await super[symbols.setup](opts);
51
+
52
+ if (opts.workerId !== null) {
53
+ await this[symbols.installWorker](opts);
54
+ }
66
55
  }
67
56
 
68
57
  /** @override */
69
- async [symbols.teardown]() {
58
+ async [symbols.cleanup]() {
70
59
  try {
71
- await super[symbols.teardown]();
60
+ if (this[$worker]) {
61
+ await this[symbols.uninstallWorker]();
62
+ }
72
63
  } finally {
73
64
  if (this[_ipcClient]) {
74
65
  await this[_ipcClient].dispose();
@@ -76,17 +67,23 @@ class DetoxSecondaryContext extends DetoxContext {
76
67
  }
77
68
  }
78
69
  }
70
+
71
+ /** @override */
72
+ async [symbols.installWorker](opts = {}) {
73
+ const workerId = opts.workerId || 'worker';
74
+ await this[_ipcClient].registerWorker(workerId);
75
+ await super[symbols.installWorker]({ ...opts, workerId });
76
+ }
79
77
  //#endregion
80
78
 
81
79
  //#region Protected members
82
-
83
80
  /**
84
81
  * @protected
85
82
  * @override
86
- * @return {SecondarySessionState}
83
+ * @return {SessionState}
87
84
  */
88
85
  [$restoreSessionState]() {
89
- return SecondarySessionState.parse(fs.readFileSync(process.env.DETOX_CONFIG_SNAPSHOT_PATH));
86
+ return SessionState.parse(fs.readFileSync(process.env.DETOX_CONFIG_SNAPSHOT_PATH));
90
87
  }
91
88
  //#endregion
92
89
  }
@@ -1,43 +1,37 @@
1
- // @ts-nocheck
2
1
  const _ = require('lodash');
3
- const { WebSocket } = require('ws'); // eslint-disable-line @typescript-eslint/no-unused-vars, no-unused-vars
4
2
 
5
3
  const DetoxRuntimeError = require('../errors/DetoxRuntimeError');
6
- const logger = require('../utils/logger').child({ __filename, cat: 'ws-server,ws' });
4
+ const logger = require('../utils/logger').child({ cat: 'ws-server,ws' });
7
5
 
8
6
  const AnonymousConnectionHandler = require('./handlers/AnonymousConnectionHandler');
9
7
 
10
- const EVENTS = {
11
- NEW: { event: 'WSS_CONNECTION' },
12
- GET: { event: 'WSS_GET_FROM' },
13
- SEND: { event: 'WSS_SEND_TO' },
14
- ERROR: { event: 'ERROR' },
15
- SOCKET_ERROR: { event: 'WSS_SOCKET_ERROR' },
16
- };
17
-
18
8
  class DetoxConnection {
19
9
  /**
20
- * @param {DetoxSessionManager} sessionManager
21
- * @param {WebSocket} webSocket
22
- * @param {Socket} socket
10
+ * @param {{
11
+ * sessionManager: import('./DetoxSessionManager');
12
+ * webSocket: import('ws');
13
+ * socket: import('net').Socket;
14
+ * }} config
23
15
  */
24
16
  constructor({ sessionManager, webSocket, socket }) {
25
17
  this._onMessage = this._onMessage.bind(this);
26
18
  this._onError = this._onError.bind(this);
27
19
  this._onClose = this._onClose.bind(this);
28
20
 
29
- this._log = logger.child({ trackingId: socket.remotePort });
21
+ this._log = logger.child({ id: socket.remotePort });
22
+ this._log.debug.begin(`connection :${socket.localPort}<->:${socket.remotePort}`);
23
+
30
24
  this._sessionManager = sessionManager;
31
25
  this._webSocket = webSocket;
32
26
  this._webSocket.on('message', this._onMessage);
33
27
  this._webSocket.on('error', this._onError);
34
28
  this._webSocket.on('close', this._onClose);
35
- this._log.debug(EVENTS.NEW, 'registered a new connection.');
36
29
 
37
- const log = this._log;
30
+ // eslint-disable-next-line unicorn/no-this-assignment
31
+ const self = this;
38
32
  this._handler = new AnonymousConnectionHandler({
39
33
  api: {
40
- get log() { return log; },
34
+ get log() { return self._log; },
41
35
  appendLogDetails: (details) => { this._log = this._log.child(details); },
42
36
 
43
37
  registerSession: (params) => this._sessionManager.registerSession(this, params),
@@ -49,13 +43,13 @@ class DetoxConnection {
49
43
 
50
44
  sendAction(action) {
51
45
  const messageAsString = JSON.stringify(action);
52
- this._log.trace(EVENTS.SEND, messageAsString);
46
+ this._log.trace({ data: action }, 'send');
53
47
  this._webSocket.send(messageAsString + '\n ');
54
48
  }
55
49
 
56
50
  _onMessage(rawData) {
57
51
  const data = _.isString(rawData) ? rawData : rawData.toString('utf8');
58
- this._log.trace(EVENTS.GET, data);
52
+ this._log.trace({ data }, 'get');
59
53
 
60
54
  try {
61
55
  let action;
@@ -84,16 +78,17 @@ class DetoxConnection {
84
78
  this._handler.onError(handlerError, action);
85
79
  }
86
80
  } catch (error) {
87
- this._log.warn({ ...EVENTS.ERROR }, error instanceof DetoxRuntimeError ? error.message : `${error}`);
81
+ this._log.warn({ error }, 'Caught unhandled error:');
88
82
  }
89
83
  }
90
84
 
91
- _onError(e) {
92
- this._log.warn(EVENTS.SOCKET_ERROR, DetoxRuntimeError.format(e));
85
+ _onError(error) {
86
+ this._log.warn({ error }, 'Caught socket error:');
93
87
  }
94
88
 
95
89
  _onClose() {
96
90
  this._sessionManager.unregisterConnection(this._webSocket);
91
+ this._log.debug.end();
97
92
  }
98
93
  }
99
94
 
@@ -4,7 +4,7 @@ const WebSocket = require('ws');
4
4
 
5
5
  const { DetoxInternalError, DetoxRuntimeError } = require('../errors');
6
6
  const Deferred = require('../utils/Deferred');
7
- const log = require('../utils/logger').child({ __filename });
7
+ const log = require('../utils/logger').child({ cat: 'ws-server,ws' });
8
8
 
9
9
  const DetoxSessionManager = require('./DetoxSessionManager');
10
10
 
@@ -40,18 +40,16 @@ class DetoxServer {
40
40
  await this._startListening();
41
41
 
42
42
  const level = this._options.standalone ? 'info' : 'debug';
43
- log[level]({ event: 'WSS_CREATE' }, `Detox server listening on localhost:${this.port}...`);
43
+ log[level](`Detox server listening on localhost:${this.port}...`);
44
44
  }
45
45
 
46
46
  async close() {
47
47
  try {
48
48
  await this._closeWithTimeout(10000);
49
- log.debug({ event: 'WSS_CLOSE' }, 'Detox server has been closed gracefully');
50
- } catch (e) {
51
- log.warn({ event: 'ERROR' },
52
- `Detox server has been closed abruptly! See the error details below:\n`
53
- + DetoxRuntimeError.format(e) + '\n'
54
- + DetoxRuntimeError.reportIssue
49
+ log.debug('Detox server has been closed gracefully');
50
+ } catch (err) {
51
+ log.warn({ err },
52
+ `Detox server has been closed abruptly! See the error details below:`
55
53
  );
56
54
  }
57
55
  }
@@ -90,8 +88,7 @@ class DetoxServer {
90
88
  } else if (this._closing) {
91
89
  this._closing.reject(err);
92
90
  } else {
93
- const formattedError = DetoxRuntimeError.format(err);
94
- log.error('Detox server has got an unhandled error:\n' + formattedError);
91
+ log.error({ err }, 'Detox server has got an unhandled error:');
95
92
  }
96
93
  }
97
94
 
@@ -1,6 +1,6 @@
1
1
  // @ts-nocheck
2
2
  const DetoxInternalError = require('../errors/DetoxInternalError');
3
- const log = require('../utils/logger').child({ __filename });
3
+ const log = require('../utils/logger').child({ cat: 'ws-server,ws-session' });
4
4
 
5
5
  class DetoxSession {
6
6
  /**
@@ -17,7 +17,7 @@ class DetoxSession {
17
17
  /** @type {boolean | null} */
18
18
  this._pendingTesterStatus = null;
19
19
 
20
- log.trace({ event: 'SESSION_CREATED' }, `created session ${id}`);
20
+ log.trace(`created session ${id}`);
21
21
  }
22
22
 
23
23
  get id() {
@@ -120,7 +120,7 @@ class DetoxSession {
120
120
  }
121
121
 
122
122
  _notifyAboutAppConnect() {
123
- log.trace({ event: 'SESSION_JOINED' }, `app joined session ${this.id}`);
123
+ log.trace(`app joined session ${this.id}`);
124
124
 
125
125
  if (!this._tester) {
126
126
  return;
@@ -132,7 +132,7 @@ class DetoxSession {
132
132
  }
133
133
 
134
134
  _notifyAboutAppDisconnect() {
135
- log.trace({ event: 'SESSION_TORN' }, `app exited session ${this.id}`);
135
+ log.trace(`app exited session ${this.id}`);
136
136
 
137
137
  if (!this._tester) {
138
138
  return;
@@ -144,11 +144,11 @@ class DetoxSession {
144
144
  }
145
145
 
146
146
  _notifyAboutTesterConnect() {
147
- log.trace({ event: 'SESSION_JOINED' }, `tester joined session ${this.id}`);
147
+ log.trace(`tester joined session ${this.id}`);
148
148
  }
149
149
 
150
150
  _notifyAboutTesterDisconnect() {
151
- log.trace({ event: 'SESSION_TORN' }, `tester exited session ${this.id}`);
151
+ log.trace(`tester exited session ${this.id}`);
152
152
 
153
153
  if (!this._app) {
154
154
  return;
@@ -1,6 +1,6 @@
1
1
  // @ts-nocheck
2
2
  const DetoxInternalError = require('../errors/DetoxInternalError');
3
- const log = require('../utils/logger').child({ __filename });
3
+ const log = require('../utils/logger').child({ cat: 'ws-server,ws' });
4
4
 
5
5
  const DetoxConnection = require('./DetoxConnection');
6
6
  const DetoxSession = require('./DetoxSession');
@@ -1,7 +1,6 @@
1
1
  // @ts-nocheck
2
2
  const { serializeError } = require('serialize-error');
3
3
 
4
- const DetoxError = require('../../errors/DetoxError');
5
4
  const DetoxInternalError = require('../../errors/DetoxInternalError');
6
5
 
7
6
  class RegisteredConnectionHandler {
@@ -41,7 +40,7 @@ class RegisteredConnectionHandler {
41
40
  messageId: action && action.messageId,
42
41
  });
43
42
  } catch (err) {
44
- this._api.log.error('Cannot forward the error details to the tester due to the error:\n' + DetoxError.format(err));
43
+ this._api.log.error({ err }, 'Cannot forward the error details to the tester due to the error:');
45
44
  throw error;
46
45
  }
47
46
  }