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

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.2-breaking.new-global-lifecycle.0/detox-20.0.2-breaking.new-global-lifecycle.0-javadoc.jar → 20.0.2/detox-20.0.2-javadoc.jar} +0 -0
  2. package/Detox-android/com/wix/detox/20.0.2/detox-20.0.2-javadoc.jar.md5 +1 -0
  3. package/Detox-android/com/wix/detox/20.0.2/detox-20.0.2-javadoc.jar.sha1 +1 -0
  4. package/Detox-android/com/wix/detox/20.0.2/detox-20.0.2-javadoc.jar.sha256 +1 -0
  5. package/Detox-android/com/wix/detox/20.0.2/detox-20.0.2-javadoc.jar.sha512 +1 -0
  6. package/Detox-android/com/wix/detox/{20.0.2-breaking.new-global-lifecycle.0/detox-20.0.2-breaking.new-global-lifecycle.0-sources.jar → 20.0.2/detox-20.0.2-sources.jar} +0 -0
  7. package/Detox-android/com/wix/detox/20.0.2/detox-20.0.2-sources.jar.md5 +1 -0
  8. package/Detox-android/com/wix/detox/20.0.2/detox-20.0.2-sources.jar.sha1 +1 -0
  9. package/Detox-android/com/wix/detox/20.0.2/detox-20.0.2-sources.jar.sha256 +1 -0
  10. package/Detox-android/com/wix/detox/20.0.2/detox-20.0.2-sources.jar.sha512 +1 -0
  11. package/Detox-android/com/wix/detox/20.0.2/detox-20.0.2.aar +0 -0
  12. package/Detox-android/com/wix/detox/20.0.2/detox-20.0.2.aar.md5 +1 -0
  13. package/Detox-android/com/wix/detox/20.0.2/detox-20.0.2.aar.sha1 +1 -0
  14. package/Detox-android/com/wix/detox/20.0.2/detox-20.0.2.aar.sha256 +1 -0
  15. package/Detox-android/com/wix/detox/20.0.2/detox-20.0.2.aar.sha512 +1 -0
  16. package/Detox-android/com/wix/detox/{20.0.2-breaking.new-global-lifecycle.0/detox-20.0.2-breaking.new-global-lifecycle.0.pom → 20.0.2/detox-20.0.2.pom} +1 -7
  17. package/Detox-android/com/wix/detox/20.0.2/detox-20.0.2.pom.md5 +1 -0
  18. package/Detox-android/com/wix/detox/20.0.2/detox-20.0.2.pom.sha1 +1 -0
  19. package/Detox-android/com/wix/detox/20.0.2/detox-20.0.2.pom.sha256 +1 -0
  20. package/Detox-android/com/wix/detox/20.0.2/detox-20.0.2.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 +216 -49
  49. package/local-cli/build.js +2 -2
  50. package/local-cli/build.test.js +14 -14
  51. package/local-cli/cli.js +11 -6
  52. package/local-cli/init.js +61 -21
  53. package/local-cli/rebuild-framework-cache.js +1 -1
  54. package/local-cli/reset-lock-file.js +16 -0
  55. package/local-cli/templates/jest.js +13 -10
  56. package/local-cli/test.js +14 -8
  57. package/local-cli/test.test.js +143 -62
  58. package/local-cli/testCommand/TestRunnerCommand.js +97 -77
  59. package/local-cli/testCommand/TestRunnerError.js +17 -0
  60. package/local-cli/testCommand/TestRunnerError.test.js +25 -0
  61. package/local-cli/testCommand/builder.js +0 -1
  62. package/local-cli/testCommand/middlewares.js +4 -13
  63. package/local-cli/testCommand/warnings.js +0 -3
  64. package/local-cli/utils/jestInternals.js +4 -1
  65. package/package.json +23 -17
  66. package/runners/deprecation.js +42 -44
  67. package/runners/jest/globalSetup.js +1 -1
  68. package/runners/jest/globalTeardown.js +1 -1
  69. package/runners/jest/index.d.ts +60 -0
  70. package/runners/jest/index.js +3 -8
  71. package/runners/jest/index.test.js +13 -0
  72. package/runners/jest/reporters/DetoxReporter.js +33 -2
  73. package/runners/jest/testEnvironment/index.js +119 -69
  74. package/runners/jest/testEnvironment/listeners/DetoxCoreListener.js +94 -47
  75. package/runners/jest/testEnvironment/listeners/DetoxPlatformFilterListener.js +1 -1
  76. package/runners/jest/testEnvironment/listeners/SpecReporter.js +14 -16
  77. package/runners/jest/testEnvironment/listeners/WorkerAssignReporter.js +2 -6
  78. package/runners/jest/testEnvironment/utils/assertJestCircus27.js +17 -3
  79. package/runners/jest/testEnvironment/utils/assertJestCircus27.test.js +0 -1
  80. package/src/DetoxWorker.js +105 -62
  81. package/src/android/core/NativeElement.js +56 -20
  82. package/src/android/core/NativeExpect.js +28 -9
  83. package/src/android/interactions/native.js +25 -18
  84. package/src/artifacts/ArtifactsManager.js +14 -47
  85. package/src/artifacts/instruments/ios/SimulatorInstrumentsRecording.js +3 -3
  86. package/src/artifacts/log/ios/SimulatorLogRecording.js +1 -1
  87. package/src/artifacts/screenshot/SimulatorScreenshotPlugin.js +1 -1
  88. package/src/artifacts/templates/artifact/Artifact.js +1 -1
  89. package/src/artifacts/templates/plugin/ArtifactPlugin.js +1 -1
  90. package/src/artifacts/timeline/TimelineContextTypes.js +7 -0
  91. package/src/artifacts/utils/temporaryPath.js +49 -8
  92. package/src/artifacts/video/SimulatorRecordVideoPlugin.js +1 -1
  93. package/src/client/AsyncWebSocket.js +8 -17
  94. package/src/client/Client.js +19 -2
  95. package/src/client/actions/formatters/sync-resources/NetworkFormatter.js +1 -1
  96. package/src/configuration/collectCliConfig.js +1 -12
  97. package/src/configuration/composeAppsConfig.js +4 -0
  98. package/src/configuration/composeDeviceConfig.js +1 -1
  99. package/src/configuration/composeLoggerConfig.js +19 -10
  100. package/src/configuration/composeRunnerConfig.js +61 -9
  101. package/src/configuration/index.js +14 -9
  102. package/src/configuration/loadExternalConfig.js +1 -1
  103. package/src/devices/allocation/DeviceAllocator.js +3 -2
  104. package/src/devices/allocation/drivers/android/emulator/AVDValidator.js +5 -5
  105. package/src/devices/allocation/drivers/android/emulator/EmulatorAllocDriver.js +4 -3
  106. package/src/devices/allocation/drivers/android/emulator/EmulatorAllocationHelper.js +1 -1
  107. package/src/devices/allocation/drivers/android/emulator/EmulatorLauncher.js +3 -2
  108. package/src/devices/allocation/drivers/android/emulator/EmulatorVersionResolver.js +4 -6
  109. package/src/devices/allocation/drivers/android/emulator/launchEmulatorProcess.js +1 -1
  110. package/src/devices/allocation/drivers/android/genycloud/GenyInstanceAllocationHelper.js +1 -1
  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 +17 -2
  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 +111 -72
  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.2-breaking.new-global-lifecycle.0/detox-20.0.2-breaking.new-global-lifecycle.0-javadoc.jar.md5 +0 -1
  167. package/Detox-android/com/wix/detox/20.0.2-breaking.new-global-lifecycle.0/detox-20.0.2-breaking.new-global-lifecycle.0-javadoc.jar.sha1 +0 -1
  168. package/Detox-android/com/wix/detox/20.0.2-breaking.new-global-lifecycle.0/detox-20.0.2-breaking.new-global-lifecycle.0-javadoc.jar.sha256 +0 -1
  169. package/Detox-android/com/wix/detox/20.0.2-breaking.new-global-lifecycle.0/detox-20.0.2-breaking.new-global-lifecycle.0-javadoc.jar.sha512 +0 -1
  170. package/Detox-android/com/wix/detox/20.0.2-breaking.new-global-lifecycle.0/detox-20.0.2-breaking.new-global-lifecycle.0-sources.jar.md5 +0 -1
  171. package/Detox-android/com/wix/detox/20.0.2-breaking.new-global-lifecycle.0/detox-20.0.2-breaking.new-global-lifecycle.0-sources.jar.sha1 +0 -1
  172. package/Detox-android/com/wix/detox/20.0.2-breaking.new-global-lifecycle.0/detox-20.0.2-breaking.new-global-lifecycle.0-sources.jar.sha256 +0 -1
  173. package/Detox-android/com/wix/detox/20.0.2-breaking.new-global-lifecycle.0/detox-20.0.2-breaking.new-global-lifecycle.0-sources.jar.sha512 +0 -1
  174. package/Detox-android/com/wix/detox/20.0.2-breaking.new-global-lifecycle.0/detox-20.0.2-breaking.new-global-lifecycle.0.aar +0 -0
  175. package/Detox-android/com/wix/detox/20.0.2-breaking.new-global-lifecycle.0/detox-20.0.2-breaking.new-global-lifecycle.0.aar.md5 +0 -1
  176. package/Detox-android/com/wix/detox/20.0.2-breaking.new-global-lifecycle.0/detox-20.0.2-breaking.new-global-lifecycle.0.aar.sha1 +0 -1
  177. package/Detox-android/com/wix/detox/20.0.2-breaking.new-global-lifecycle.0/detox-20.0.2-breaking.new-global-lifecycle.0.aar.sha256 +0 -1
  178. package/Detox-android/com/wix/detox/20.0.2-breaking.new-global-lifecycle.0/detox-20.0.2-breaking.new-global-lifecycle.0.aar.sha512 +0 -1
  179. package/Detox-android/com/wix/detox/20.0.2-breaking.new-global-lifecycle.0/detox-20.0.2-breaking.new-global-lifecycle.0.pom.md5 +0 -1
  180. package/Detox-android/com/wix/detox/20.0.2-breaking.new-global-lifecycle.0/detox-20.0.2-breaking.new-global-lifecycle.0.pom.sha1 +0 -1
  181. package/Detox-android/com/wix/detox/20.0.2-breaking.new-global-lifecycle.0/detox-20.0.2-breaking.new-global-lifecycle.0.pom.sha256 +0 -1
  182. package/Detox-android/com/wix/detox/20.0.2-breaking.new-global-lifecycle.0/detox-20.0.2-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,8 +1,30 @@
1
+ const vm = require('vm');
2
+
1
3
  const cycle = require('json-cycle');
2
4
 
3
- const uuid = require('../utils/uuid');
5
+ const context = vm.createContext({ require }, {
6
+ name: 'VM User Context',
7
+ });
4
8
 
5
9
  class SessionState {
10
+ constructor({
11
+ id = '',
12
+ contexts = [],
13
+ detoxConfig = null,
14
+ detoxIPCServer = '',
15
+ testResults = [],
16
+ testSessionIndex = 0,
17
+ workersCount = 0
18
+ }) {
19
+ this.id = id;
20
+ this.contexts = contexts;
21
+ this.detoxConfig = detoxConfig;
22
+ this.detoxIPCServer = detoxIPCServer;
23
+ this.testResults = testResults;
24
+ this.testSessionIndex = testSessionIndex;
25
+ this.workersCount = workersCount;
26
+ }
27
+
6
28
  patch(state) {
7
29
  Object.assign(this, state);
8
30
  }
@@ -21,8 +43,8 @@ class SessionState {
21
43
  }
22
44
 
23
45
  static reviver(key, val) {
24
- if (typeof val === 'object' && typeof val.$fn == 'string') {
25
- return eval(val.$fn);
46
+ if (typeof val === 'object' && val !== null && typeof val.$fn == 'string') {
47
+ return vm.runInContext(val.$fn, context);
26
48
  } else {
27
49
  return val;
28
50
  }
@@ -37,53 +59,4 @@ class SessionState {
37
59
  }
38
60
  }
39
61
 
40
- class SecondarySessionState extends SessionState {
41
- constructor({
42
- id = uuid.UUID(),
43
- detoxConfigSnapshotPath = '',
44
- detoxConfig = null,
45
- detoxIPCServer = '',
46
- failedTestFiles = [],
47
- testFilesToRetry = [],
48
- testSessionIndex = 0,
49
- workerId = undefined,
50
- workersCount = 0
51
- }) {
52
- super();
53
-
54
- this.id = id;
55
- this.detoxConfigSnapshotPath = detoxConfigSnapshotPath;
56
- this.detoxConfig = detoxConfig;
57
- this.detoxIPCServer = detoxIPCServer;
58
- this.failedTestFiles = failedTestFiles;
59
- this.testFilesToRetry = testFilesToRetry;
60
- this.testSessionIndex = testSessionIndex;
61
- this.workerId = workerId;
62
- this.workersCount = workersCount;
63
- }
64
- }
65
-
66
- class PrimarySessionState extends SecondarySessionState {
67
- constructor({
68
- contexts = [],
69
- logFiles = [],
70
- failedTestFiles = [],
71
- testFilesToRetry = [],
72
- testSessionIndex = 0,
73
- ...baseOpts
74
- }) {
75
- super(baseOpts);
76
-
77
- this.contexts = contexts;
78
- this.failedTestFiles = failedTestFiles;
79
- this.logFiles = logFiles;
80
- this.testSessionIndex = testSessionIndex;
81
- this.testFilesToRetry = testFilesToRetry;
82
- }
83
- }
84
-
85
- module.exports = {
86
- SessionState,
87
- PrimarySessionState,
88
- SecondarySessionState,
89
- };
62
+ module.exports = SessionState;
@@ -1,201 +1,359 @@
1
1
  const path = require('path');
2
- const { PassThrough } = require('stream');
3
2
 
4
- const bunyan = require('bunyan');
5
- const bunyanDebugStream = require('bunyan-debug-stream');
6
3
  const _ = require('lodash');
7
4
 
8
- const temporaryPath = require('../artifacts/utils/temporaryPath');
9
- const { DetoxInternalError } = require('../errors');
5
+ const { DetoxInternalError, DetoxError } = require('../errors');
10
6
  const { shortFormat } = require('../utils/dateUtils');
7
+ const isPromise = require('../utils/isPromise');
11
8
 
12
- const customConsoleLogger = require('./customConsoleLogger');
9
+ const BunyanLogger = require('./utils/BunyanLogger');
10
+ const CategoryThreadDispatcher = require('./utils/CategoryThreadDispatcher');
11
+ const MessageStack = require('./utils/MessageStack');
12
+ const customConsoleLogger = require('./utils/customConsoleLogger');
13
+ const sanitizeBunyanContext = require('./utils/sanitizeBunyanContext');
13
14
 
14
15
  /**
15
- * @typedef PrivateLoggerConfig
16
- * @property {string} [file]
16
+ * @typedef SharedLoggerConfig
17
+ * @property {string} file
18
+ * @property {Detox.DetoxLoggerConfig} [userConfig]
19
+ * @property {CategoryThreadDispatcher} [dispatcher]
20
+ * @property {BunyanLogger} [bunyan]
21
+ * @property {MessageStack} [messageStack]
22
+ * @property {boolean} [unsafeMode] Disables sanitization of user input, used for integration tests.
17
23
  */
18
24
 
19
25
  class DetoxLogger {
20
26
  /**
21
- * @param {Detox.DetoxLoggerConfig & PrivateLoggerConfig} [config]
27
+ * @param {SharedLoggerConfig} sharedConfig
22
28
  * @param {object} [context]
23
- * @param {bunyan} [bunyanLogger]
24
29
  */
25
- constructor(config, context, bunyanLogger) {
26
- // IMPORTANT: all the loggers should share the same object instance of this._config
27
- this._config = config || {
28
- level: 'info',
29
- overrideConsole: 'none',
30
- options: {
31
- showDate: true,
32
- showLoggerName: true,
33
- showPid: true,
34
- showMetadata: false,
35
- },
36
- };
37
-
38
- if (config && !context) {
39
- this._config.file = temporaryPath.for.jsonl();
40
- }
30
+ constructor(sharedConfig, context) {
31
+ /**
32
+ * @type {SharedLoggerConfig}
33
+ * IMPORTANT: all instances of {@link DetoxLogger} must share the same object instance of this._sharedConfig.
34
+ */
35
+ this._sharedConfig = sharedConfig;
41
36
 
42
37
  /** @type {object | undefined} */
43
38
  this._context = context;
44
- /** @type {bunyan} */
45
- this._bunyan = bunyanLogger || this._initBunyanLogger();
46
-
47
- this.fatal = this._forward.bind(this, 'fatal');
48
- this.error = this._forward.bind(this, 'error');
49
- this.warn = this._forward.bind(this, 'warn');
50
- this.info = this._forward.bind(this, 'info');
51
- this.debug = this._forward.bind(this, 'debug');
52
- this.trace = this._forward.bind(this, 'trace');
53
39
 
54
- this.overrideConsole();
40
+ /** @public */
41
+ this.fatal = this._setupLogMethod('fatal');
42
+ /** @public */
43
+ this.error = this._setupLogMethod('error');
44
+ /** @public */
45
+ this.warn = this._setupLogMethod('warn');
46
+ /** @public */
47
+ this.info = this._setupLogMethod('info');
48
+ /** @public */
49
+ this.debug = this._setupLogMethod('debug');
50
+ /** @public */
51
+ this.trace = this._setupLogMethod('trace');
52
+
53
+ if (!context) {
54
+ // In this branch, `this` refers to the first (root) logger instance.
55
+
56
+ this._sharedConfig.userConfig = this._sharedConfig.userConfig || {
57
+ level: 'info',
58
+ overrideConsole: false,
59
+ options: {
60
+ showDate: false,
61
+ showLoggerName: false,
62
+ showProcess: false,
63
+ showPid: false,
64
+ showLevel: false,
65
+ showPrefixes: false,
66
+ showMetadata: false,
67
+ },
68
+ };
69
+
70
+ this._sharedConfig.bunyan = new BunyanLogger()
71
+ .installFileStream(this.file)
72
+ .installDebugStream(this.config);
73
+
74
+ this._sharedConfig.dispatcher = new CategoryThreadDispatcher();
75
+ this._sharedConfig.messageStack = new MessageStack();
76
+
77
+ this.overrideConsole();
78
+ }
55
79
  }
56
80
 
57
81
  /**
58
- * @internal
82
+ * @public
83
+ * @returns {Detox.DetoxLogLevel}
59
84
  */
60
- get config() {
61
- return this._config;
62
- }
63
-
64
- /** @returns {Detox.DetoxLogLevel} */
65
85
  get level() {
66
- return this._config.level;
86
+ return this.config.level;
67
87
  }
68
88
 
69
89
  /**
70
- * @internal
90
+ * @public
91
+ * @param {object} [overrides]
92
+ * @returns {DetoxLogger}
71
93
  */
94
+ child(overrides) {
95
+ const merged = this._mergeContexts(this._context, this._sanitizeContext(overrides));
96
+ return new DetoxLogger(this._sharedConfig, merged);
97
+ }
98
+
99
+ /** @internal */
100
+ get config() {
101
+ return this._sharedConfig.userConfig;
102
+ }
103
+
104
+ /** @internal */
72
105
  get file() {
73
- return this._config.file;
106
+ return this._sharedConfig.file;
74
107
  }
75
108
 
76
109
  /**
110
+ * @internal
77
111
  * @param config
78
112
  */
79
113
  async setConfig(config) {
80
- if (this._context !== undefined) {
81
- throw new DetoxInternalError('Trying to set a config for a non-root logger');
114
+ if (this._context) {
115
+ throw new DetoxInternalError('Trying to set a config in a non-root logger');
82
116
  }
83
117
 
84
- if (this.file) {
85
- throw new DetoxInternalError('Trying to set a config for a fully initialized logger');
86
- }
118
+ _.merge(this.config, config);
119
+ this._sharedConfig.bunyan.installDebugStream(this.config);
120
+ this.overrideConsole();
121
+ }
87
122
 
88
- _.merge(this._config, config);
123
+ /**
124
+ * Closes the file descriptors to make sure that the temporary
125
+ * JSONL files are flushed and contain the last error messages.
126
+ * This safety measure is especially important for Windows OS.
127
+ *
128
+ * @async
129
+ * @internal
130
+ */
131
+ async close() {
132
+ if (this._context) {
133
+ throw new DetoxInternalError(
134
+ 'Trying to close file streams from a non-root logger.\n' +
135
+ 'If you are not fiddling with Detox internals on purpose, yet you see this error, then...'
136
+ );
137
+ }
89
138
 
90
- // @ts-ignore
91
- const [oldStream] = this._bunyan.streams.splice(0, 1);
92
- oldStream.stream.end();
93
- this._bunyan.addStream(this._createDebugStream());
139
+ await this._sharedConfig.bunyan.closeFileStreams();
140
+ }
94
141
 
95
- this._config.file = temporaryPath.for.jsonl();
96
- this._bunyan.addStream({
97
- level: 'trace',
98
- path: this._config.file,
99
- });
142
+ /**
143
+ * @internal
144
+ */
145
+ overrideConsole(sandbox) {
146
+ const enabled = this.config.overrideConsole;
147
+ if (!enabled) {
148
+ return;
149
+ }
100
150
 
101
- this.overrideConsole();
151
+ customConsoleLogger.overrideConsoleMethods((sandbox || global).console, this);
102
152
  }
103
153
 
104
154
  /**
105
- * @param {object} [overrides]
106
- * @returns {DetoxLogger}
155
+ * @private
107
156
  */
108
- child(overrides) {
109
- if (overrides && overrides.__filename) {
110
- overrides.__filename = path.basename(overrides.__filename, '.js');
157
+ _mergeContexts(...contexts) {
158
+ const context = Object.assign({}, ...contexts);
159
+ const categories = _(contexts).flatMap((c) => {
160
+ if (c && c.cat) {
161
+ return _.isArray(c.cat) ? c.cat : c.cat.split(',');
162
+ }
163
+
164
+ return [];
165
+ }).uniq().join(',');
166
+
167
+ if (context.error || context.err) {
168
+ context.error = DetoxError.format(context.error || context.err);
169
+ delete context.err;
170
+ }
171
+
172
+ if (categories) {
173
+ context.cat = categories;
174
+ } else {
175
+ delete context.cat;
176
+ }
177
+
178
+ if (context.__filename) {
179
+ context.__filename = path.basename(context.__filename);
111
180
  }
112
181
 
113
- return new DetoxLogger(this._config, {
114
- ...this._context,
115
- ...overrides,
116
- }, this._bunyan);
182
+ context.ph = context.ph || 'i';
183
+ context.tid = this._sharedConfig.dispatcher.resolve(
184
+ context.ph,
185
+ context.cat,
186
+ context.id || 0
187
+ );
188
+
189
+ return context;
117
190
  }
118
191
 
119
192
  /**
120
- * @param {bunyan.LogLevel} level
121
- * @param {any[]} args
122
193
  * @private
194
+ * @param {Detox.DetoxLogLevel} level
195
+ * @returns {Detox._LogMethod}
123
196
  */
124
- _forward(level, ...args) {
125
- const msgContext = _.isError(args[0]) ? { err: args[0] } : _.isObject(args[0]) ? args[0] : undefined;
126
- const msgArgs = msgContext !== undefined ? args.slice(1) : args;
127
- const mergedContext = sanitizeBunyanContext({
128
- ...this._context,
129
- ...msgContext,
197
+ _setupLogMethod(level) {
198
+ const logMethod = this[level] = this._instant.bind(this, level);
199
+
200
+ return Object.assign(logMethod, {
201
+ begin: this._begin.bind(this, level),
202
+ complete: this._complete.bind(this, level),
203
+ end: this._end.bind(this, level),
130
204
  });
205
+ }
131
206
 
132
- this._bunyan[level](mergedContext, ...msgArgs);
207
+ /** @private */
208
+ _begin(level, ...args) {
209
+ const { context, msg } = this._parseArgs({ ph: 'B' }, args);
210
+ this._beginInternal(level, context, msg);
133
211
  }
134
212
 
135
- _initBunyanLogger() {
136
- /** @type {bunyan.Stream[]} */
137
- const streams = [this._createDebugStream()];
213
+ /** @private */
214
+ _beginInternal(level, context, msg) {
215
+ this._sharedConfig.messageStack.push(context, msg);
216
+ this._sharedConfig.bunyan.logger[level](context, ...msg);
217
+ }
218
+
219
+ /** @private */
220
+ _end(level, ...args) {
221
+ let { context, msg } = this._parseArgs({ ph: 'E' }, args);
222
+ this._endInternal(level, context, msg);
223
+ }
138
224
 
139
- if (this._config.file) {
140
- streams.push({
141
- level: 'trace',
142
- path: this._config.file,
143
- });
225
+ /** @private */
226
+ _endInternal(level, context, msg) {
227
+ const beginMsg = this._sharedConfig.messageStack.pop(context);
228
+ if (msg.length === 0) {
229
+ msg = beginMsg;
144
230
  }
145
231
 
146
- return bunyan.createLogger({ name: 'detox', streams });
232
+ this._sharedConfig.bunyan.logger[level](context, ...msg);
147
233
  }
148
234
 
149
- _createDebugStream() {
150
- const { out = process.stderr, ...streamOptions } = this._config.options;
151
- const passthrough = new PassThrough().pipe(out);
152
-
153
- return {
154
- type: 'raw',
155
- level: this._config.level,
156
- stream: bunyanDebugStream.default({
157
- ...streamOptions,
158
- out: passthrough,
159
- }),
160
- };
235
+ /**
236
+ * @private
237
+ * @param {import('bunyan').LogLevel} level
238
+ * @param {any[]} args
239
+ */
240
+ _instant(level, ...args) {
241
+ const { context, msg } = this._parseArgs(null, args);
242
+ this._sharedConfig.bunyan.logger[level](context, ...msg);
161
243
  }
162
244
 
163
- overrideConsole(sandbox) {
164
- const option = this._config.overrideConsole;
165
- if (option === 'none') {
166
- return;
245
+ /**
246
+ * @param {import('bunyan').LogLevel} level
247
+ * @private
248
+ */
249
+ _complete(level, maybeContext, maybeMessage, maybeAction) {
250
+ const action = typeof maybeContext !== 'string' ? maybeAction : maybeMessage;
251
+ const args = maybeAction === action ? [maybeContext, maybeMessage] : [maybeContext];
252
+ const { context, msg } = this._parseArgs(null, args);
253
+ const end = (ctx) => this[level].end({
254
+ id: context.id,
255
+ cat: context.cat,
256
+ ...ctx,
257
+ });
258
+
259
+ let result;
260
+ this._beginInternal(level, { ...context, ph: 'B' }, msg);
261
+ try {
262
+ result = typeof action === 'function'
263
+ ? action()
264
+ : action;
265
+
266
+ if (!isPromise(result)) {
267
+ end({ success: true });
268
+ } else {
269
+ result.then(
270
+ () => end({ success: true }),
271
+ (err) => end({ success: false, err }),
272
+ );
273
+ }
274
+
275
+ return result;
276
+ } catch (err) {
277
+ end({ success: false, err });
278
+ throw err;
167
279
  }
280
+ }
281
+
282
+ /** @private */
283
+ _parseArgs(boundContext, args) {
284
+ const userContext = _.isError(args[0])
285
+ ? { err: args[0] }
286
+ : _.isObject(args[0])
287
+ ? args[0]
288
+ : undefined;
289
+
290
+ const msg = userContext !== undefined ? args.slice(1) : args;
168
291
 
169
- if ((option === 'sandbox' && sandbox) || option === 'all') {
170
- customConsoleLogger.overrideConsoleMethods((sandbox || global).console, this);
292
+ const context = this._mergeContexts(
293
+ this._context,
294
+ boundContext,
295
+ this._sanitizeContext(userContext),
296
+ );
297
+
298
+ return { context, msg };
299
+ }
300
+
301
+ /** @private */
302
+ _sanitizeContext(context) {
303
+ if (this._sharedConfig.unsafeMode) {
304
+ return context;
171
305
  }
306
+
307
+ return sanitizeBunyanContext(context);
172
308
  }
173
309
 
174
- /** @type {bunyanDebugStream.BunyanDebugStreamOptions} */
175
- static defaultOptions = {
176
- showDate: shortFormat,
177
- showLoggerName: true,
178
- showPid: true,
179
- showMetadata: false,
180
- basepath: path.join(__dirname, '..'),
181
- prefixers: {
182
- '__filename': (filename, { entry }) => {
183
- if (entry.event === 'USER_LOG') {
184
- return '';
185
- }
186
-
187
- if (entry.event === 'ERROR') {
188
- return `${filename}/${entry.event}`;
189
- }
190
-
191
- return entry.event ? entry.event : filename;
192
- },
193
- 'trackingId': id => ` #${id}`,
194
- 'cpid': pid => ` cpid=${pid}`,
195
- },
196
- };
310
+ /** @internal */
311
+ static defaultOptions({ level }) {
312
+ const ph = level === 'trace' || level === 'debug'
313
+ ? value => require('chalk').grey(value) + ' '
314
+ : value => require('chalk').grey(value);
315
+
316
+ const id = level === 'trace'
317
+ ? value => require('chalk').yellow(`@${value}`)
318
+ : undefined;
319
+
320
+ const cat = level === 'trace' || level === 'debug'
321
+ ? (value) => require('chalk').yellow(`${value}`.split(',', 1)[0])
322
+ : undefined;
323
+
324
+ const event = level === 'trace' || level === 'debug'
325
+ ? (value) => require('chalk').grey(`:${value}`)
326
+ : undefined;
327
+
328
+ const identity = x => x;
329
+
330
+ return ({
331
+ showDate: shortFormat,
332
+ showLoggerName: true,
333
+ showPid: true,
334
+ showLevel: false,
335
+ showMetadata: false,
336
+ showPrefixes: (p) => p.join(''),
337
+ basepath: path.join(__dirname, '..'),
338
+ prefixers: _.omitBy({
339
+ ph,
340
+ cat,
341
+ event,
342
+ id,
343
+ }, _.isUndefined),
344
+ stringifiers: _.omitBy({
345
+ // eslint-disable-next-line unicorn/no-array-method-this-argument
346
+ 'args': args => `(${require('lodash').map(args, a => JSON.stringify(a)).join(', ')})`,
347
+ 'error': identity,
348
+ 'data': json => typeof json === 'string' ? json : JSON.stringify(json, null, 2),
349
+ 'stack': level === 'trace' || level === 'debug' ? identity : undefined,
350
+ 'origin': level === 'trace' || level === 'debug' ? identity : undefined,
351
+ }, _.isUndefined),
352
+ });
353
+ }
197
354
 
198
355
  /**
356
+ * @internal
199
357
  * @param {string} level
200
358
  * @returns {Detox.DetoxLogLevel}
201
359
  */
@@ -216,29 +374,4 @@ class DetoxLogger {
216
374
  }
217
375
  }
218
376
 
219
- const RESERVED_PROPERTIES = [
220
- 'hostname',
221
- 'level',
222
- 'msg',
223
- 'name',
224
- 'pid',
225
- 'time',
226
- ];
227
-
228
- function hasProperty(p) {
229
- return _.has(this, p);
230
- }
231
-
232
- function hasReservedProperties(o) {
233
- return RESERVED_PROPERTIES.some(hasProperty, o); // eslint-disable-line unicorn/no-array-method-this-argument
234
- }
235
-
236
- function escapeCallback(value, key) {
237
- return RESERVED_PROPERTIES.includes(key) ? `${key}$` : key;
238
- }
239
-
240
- function sanitizeBunyanContext(context) {
241
- return hasReservedProperties(context) ? _.mapKeys(context, escapeCallback) : context;
242
- }
243
-
244
377
  module.exports = DetoxLogger;
@@ -0,0 +1,5 @@
1
+ module.exports = {
2
+ DetoxLogger: require('./DetoxLogger'),
3
+ DetoxLogFinalizer: require('./utils/DetoxLogFinalizer'),
4
+ installLegacyTracerInterface: require('./utils/tracerLegacy').install,
5
+ };