detox 19.9.0 → 21.0.0-breaking.new-global-lifecycle.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (219) hide show
  1. package/Detox-android/com/wix/detox/{19.9.0/detox-19.9.0-javadoc.jar → 21.0.0-breaking.new-global-lifecycle.0/detox-21.0.0-breaking.new-global-lifecycle.0-javadoc.jar} +0 -0
  2. package/Detox-android/com/wix/detox/21.0.0-breaking.new-global-lifecycle.0/detox-21.0.0-breaking.new-global-lifecycle.0-javadoc.jar.md5 +1 -0
  3. package/Detox-android/com/wix/detox/21.0.0-breaking.new-global-lifecycle.0/detox-21.0.0-breaking.new-global-lifecycle.0-javadoc.jar.sha1 +1 -0
  4. package/Detox-android/com/wix/detox/21.0.0-breaking.new-global-lifecycle.0/detox-21.0.0-breaking.new-global-lifecycle.0-javadoc.jar.sha256 +1 -0
  5. package/Detox-android/com/wix/detox/21.0.0-breaking.new-global-lifecycle.0/detox-21.0.0-breaking.new-global-lifecycle.0-javadoc.jar.sha512 +1 -0
  6. package/Detox-android/com/wix/detox/{19.9.0/detox-19.9.0-sources.jar → 21.0.0-breaking.new-global-lifecycle.0/detox-21.0.0-breaking.new-global-lifecycle.0-sources.jar} +0 -0
  7. package/Detox-android/com/wix/detox/21.0.0-breaking.new-global-lifecycle.0/detox-21.0.0-breaking.new-global-lifecycle.0-sources.jar.md5 +1 -0
  8. package/Detox-android/com/wix/detox/21.0.0-breaking.new-global-lifecycle.0/detox-21.0.0-breaking.new-global-lifecycle.0-sources.jar.sha1 +1 -0
  9. package/Detox-android/com/wix/detox/21.0.0-breaking.new-global-lifecycle.0/detox-21.0.0-breaking.new-global-lifecycle.0-sources.jar.sha256 +1 -0
  10. package/Detox-android/com/wix/detox/21.0.0-breaking.new-global-lifecycle.0/detox-21.0.0-breaking.new-global-lifecycle.0-sources.jar.sha512 +1 -0
  11. package/Detox-android/com/wix/detox/21.0.0-breaking.new-global-lifecycle.0/detox-21.0.0-breaking.new-global-lifecycle.0.aar +0 -0
  12. package/Detox-android/com/wix/detox/21.0.0-breaking.new-global-lifecycle.0/detox-21.0.0-breaking.new-global-lifecycle.0.aar.md5 +1 -0
  13. package/Detox-android/com/wix/detox/21.0.0-breaking.new-global-lifecycle.0/detox-21.0.0-breaking.new-global-lifecycle.0.aar.sha1 +1 -0
  14. package/Detox-android/com/wix/detox/21.0.0-breaking.new-global-lifecycle.0/detox-21.0.0-breaking.new-global-lifecycle.0.aar.sha256 +1 -0
  15. package/Detox-android/com/wix/detox/21.0.0-breaking.new-global-lifecycle.0/detox-21.0.0-breaking.new-global-lifecycle.0.aar.sha512 +1 -0
  16. package/Detox-android/com/wix/detox/{19.9.0/detox-19.9.0.pom → 21.0.0-breaking.new-global-lifecycle.0/detox-21.0.0-breaking.new-global-lifecycle.0.pom} +2 -2
  17. package/Detox-android/com/wix/detox/21.0.0-breaking.new-global-lifecycle.0/detox-21.0.0-breaking.new-global-lifecycle.0.pom.md5 +1 -0
  18. package/Detox-android/com/wix/detox/21.0.0-breaking.new-global-lifecycle.0/detox-21.0.0-breaking.new-global-lifecycle.0.pom.sha1 +1 -0
  19. package/Detox-android/com/wix/detox/21.0.0-breaking.new-global-lifecycle.0/detox-21.0.0-breaking.new-global-lifecycle.0.pom.sha256 +1 -0
  20. package/Detox-android/com/wix/detox/21.0.0-breaking.new-global-lifecycle.0/detox-21.0.0-breaking.new-global-lifecycle.0.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/android/build.gradle +2 -2
  29. package/android/detox/build.gradle +2 -2
  30. package/android/detox/publish-pom.gradle +1 -5
  31. package/android/detox/publishing.gradle +7 -9
  32. package/android/detox/src/full/java/com/wix/detox/Detox.java +2 -59
  33. package/android/detox/src/full/java/com/wix/detox/NotificationDataParser.kt +3 -3
  34. package/android/detox/src/full/java/com/wix/detox/adapters/server/WebSocketClient.java +1 -3
  35. package/android/detox/src/full/java/com/wix/detox/espresso/DetoxAction.java +3 -1
  36. package/android/detox/src/full/java/com/wix/detox/espresso/UiAutomatorHelper.java +1 -1
  37. package/android/detox/src/full/java/com/wix/detox/espresso/matcher/ViewMatchers.kt +23 -16
  38. package/android/detox/src/full/java/com/wix/detox/reactnative/ReactNativeLoadingMonitor.kt +8 -54
  39. package/android/detox/src/main/java/com/wix/detox/common/DetoxErrors.java +1 -4
  40. package/android/detox/src/main/java/com/wix/detox/espresso/UiControllerSpy.kt +1 -2
  41. package/android/detox/src/main/java/com/wix/detox/espresso/action/AdjustSliderToPositionAction.kt +36 -0
  42. package/android/detox/src/{full → main}/java/com/wix/detox/espresso/action/GetAttributesAction.kt +1 -13
  43. package/android/detox/src/main/java/com/wix/detox/espresso/action/common/utils/UiControllerUtils.kt +1 -1
  44. package/android/detox/src/testFull/java/com/wix/detox/espresso/action/AdjustSliderToPositionActionTest.kt +59 -0
  45. package/android/detox/src/testFull/java/com/wix/detox/espresso/action/GetAttributesActionTest.kt +3 -15
  46. package/android/gradle/wrapper/gradle-wrapper.properties +1 -2
  47. package/android/gradlew +107 -181
  48. package/index.d.ts +208 -186
  49. package/index.js +1 -0
  50. package/internals.d.ts +124 -0
  51. package/internals.js +4 -0
  52. package/local-cli/build-framework-cache.js +2 -2
  53. package/local-cli/build.js +7 -8
  54. package/local-cli/build.test.js +46 -40
  55. package/local-cli/clean-framework-cache.js +3 -3
  56. package/local-cli/cli.js +0 -1
  57. package/local-cli/init.js +20 -55
  58. package/local-cli/templates/jest.js +9 -34
  59. package/local-cli/test.js +18 -282
  60. package/local-cli/test.test.js +332 -673
  61. package/local-cli/testCommand/TestRunnerCommand.js +157 -0
  62. package/local-cli/{utils/testCommandArgs.js → testCommand/builder.js} +10 -35
  63. package/local-cli/testCommand/middlewares.js +75 -0
  64. package/local-cli/{utils → testCommand}/warnings.js +0 -10
  65. package/local-cli/utils/jestInternals.js +13 -2
  66. package/local-cli/utils/yargsUtils.js +67 -0
  67. package/package.json +28 -22
  68. package/runners/deprecation.js +47 -0
  69. package/runners/jest/JestCircusEnvironment.js +3 -38
  70. package/runners/jest/adapter.d.ts +4 -10
  71. package/runners/jest/adapter.js +3 -6
  72. package/runners/jest/assignReporter.d.ts +4 -1
  73. package/runners/jest/assignReporter.js +3 -6
  74. package/runners/jest/deprecation.js +25 -0
  75. package/runners/jest/globalSetup.js +1 -0
  76. package/runners/jest/globalTeardown.js +1 -0
  77. package/runners/jest/index.js +21 -0
  78. package/runners/jest/reporter.js +1 -0
  79. package/runners/jest/reporters/DetoxReporter.js +5 -0
  80. package/runners/jest/specReporter.d.ts +4 -9
  81. package/runners/jest/specReporter.js +3 -10
  82. package/runners/jest/streamlineReporter.js +3 -22
  83. package/runners/jest/testEnvironment/index.js +155 -0
  84. package/runners/{jest-circus → jest/testEnvironment}/listeners/DetoxCoreListener.js +35 -17
  85. package/runners/{jest-circus → jest/testEnvironment}/listeners/DetoxInitErrorListener.js +1 -1
  86. package/runners/jest/testEnvironment/listeners/DetoxPlatformFilterListener.js +27 -0
  87. package/runners/jest/{SpecReporterImpl.js → testEnvironment/listeners/SpecReporter.js} +61 -7
  88. package/runners/jest/testEnvironment/listeners/WorkerAssignReporter.js +34 -0
  89. package/runners/jest/testEnvironment/listeners/index.js +13 -0
  90. package/runners/{jest-circus → jest/testEnvironment}/utils/assertExistingContext.js +2 -2
  91. package/runners/jest/testEnvironment/utils/assertJestCircus27.js +56 -0
  92. package/runners/jest/testEnvironment/utils/assertJestCircus27.test.js +23 -0
  93. package/runners/jest/{utils → testEnvironment/utils}/getFullTestName.js +0 -0
  94. package/runners/jest/{utils → testEnvironment/utils}/hasTimedOut.js +0 -0
  95. package/runners/jest/{utils → testEnvironment/utils}/index.js +0 -0
  96. package/runners/jest/{utils → testEnvironment/utils}/stdout.js +0 -0
  97. package/runners/jest-circus/environment/index.js +6 -0
  98. package/runners/jest-circus/index.js +1 -10
  99. package/runners/jest-circus/reporter.js +1 -0
  100. package/runners/migration.js +37 -0
  101. package/runners/mocha/DetoxMochaAdapter.js +3 -35
  102. package/runners/mocha/adapter.d.ts +4 -7
  103. package/runners/mocha/adapter.js +3 -5
  104. package/src/{Detox.js → DetoxWorker.js} +131 -164
  105. package/src/artifacts/ArtifactsManager.js +51 -2
  106. package/src/artifacts/log/android/ADBLogcatRecording.js +28 -11
  107. package/src/artifacts/providers/index.js +0 -4
  108. package/src/artifacts/utils/buildDefaultArtifactsRootDirpath.js +2 -4
  109. package/src/artifacts/utils/temporaryPath.js +2 -0
  110. package/src/client/AsyncWebSocket.js +1 -1
  111. package/src/client/actions/actions.js +2 -2
  112. package/src/configuration/collectCliConfig.js +2 -4
  113. package/src/configuration/composeAppsConfig.js +9 -67
  114. package/src/configuration/composeArtifactsConfig.js +6 -32
  115. package/src/configuration/composeBehaviorConfig.js +3 -13
  116. package/src/configuration/composeDeviceConfig.js +37 -62
  117. package/src/configuration/composeLoggerConfig.js +50 -0
  118. package/src/configuration/composeRunnerConfig.js +74 -14
  119. package/src/configuration/composeSessionConfig.js +1 -3
  120. package/src/configuration/index.js +24 -23
  121. package/src/configuration/utils/deviceAppTypes.js +0 -1
  122. package/src/devices/allocation/DeviceAllocator.js +3 -3
  123. package/src/devices/allocation/drivers/android/emulator/EmulatorAllocDriver.js +4 -3
  124. package/src/devices/allocation/drivers/android/emulator/EmulatorLauncher.js +2 -6
  125. package/src/devices/allocation/drivers/android/genycloud/GenyAllocDriver.js +0 -1
  126. package/src/devices/allocation/drivers/ios/SimulatorAllocDriver.js +1 -1
  127. package/src/devices/allocation/drivers/ios/SimulatorLauncher.js +3 -3
  128. package/src/devices/allocation/factories/index.js +0 -1
  129. package/src/devices/common/drivers/DeviceLauncher.js +2 -2
  130. package/src/devices/common/drivers/android/emulator/exec/EmulatorExec.js +1 -1
  131. package/src/devices/common/drivers/android/exec/ADB.js +0 -5
  132. package/src/devices/common/drivers/android/genycloud/services/GenyInstanceNaming.js +4 -9
  133. package/src/devices/common/drivers/ios/tools/AppleSimUtils.js +34 -9
  134. package/src/devices/lifecycle/GenyGlobalLifecycleHandler.js +1 -1
  135. package/src/devices/runtime/RuntimeDevice.js +69 -81
  136. package/src/devices/runtime/drivers/index.js +0 -1
  137. package/src/devices/runtime/drivers/ios/SimulatorDriver.js +3 -2
  138. package/src/devices/runtime/factories/ios.js +1 -8
  139. package/src/devices/runtime/utils/LaunchArgsEditor.js +4 -59
  140. package/src/devices/runtime/utils/Storage.js +4 -0
  141. package/src/environmentFactory.js +0 -8
  142. package/src/errors/DetoxConfigErrorComposer.js +76 -29
  143. package/src/errors/DetoxError.js +4 -0
  144. package/src/errors/DetoxRuntimeError.js +5 -5
  145. package/src/errors/index.js +2 -0
  146. package/src/ipc/IPCClient.js +117 -0
  147. package/src/ipc/IPCServer.js +87 -0
  148. package/src/ipc/state.js +76 -0
  149. package/src/logger/DetoxLogger.js +244 -0
  150. package/src/logger/DetoxTraceEventBuilder.js +21 -0
  151. package/src/logger/DetoxTracer.js +133 -0
  152. package/src/logger/TraceThreadDispatcher.js +52 -0
  153. package/src/{utils → logger}/customConsoleLogger.js +1 -1
  154. package/src/realms/DetoxConstants.js +13 -0
  155. package/src/realms/DetoxContext.js +170 -0
  156. package/src/realms/DetoxInternalsFacade.js +35 -0
  157. package/src/realms/DetoxPrimaryContext.js +229 -0
  158. package/src/realms/DetoxSecondaryContext.js +94 -0
  159. package/src/realms/index.js +10 -0
  160. package/src/realms/primary.js +3 -0
  161. package/src/realms/secondary.js +3 -0
  162. package/src/server/DetoxConnection.js +1 -1
  163. package/src/symbols.js +56 -0
  164. package/src/utils/ChromeTracingExporter.js +5 -6
  165. package/src/utils/Timer.js +14 -6
  166. package/{local-cli/utils/misc.js → src/utils/envUtils.js} +0 -9
  167. package/src/utils/logger.js +2 -162
  168. package/src/utils/shellUtils.js +18 -0
  169. package/src/utils/streamUtils.js +214 -0
  170. package/src/utils/trace.js +9 -44
  171. package/Detox-android/com/wix/detox/19.9.0/detox-19.9.0-javadoc.jar.md5 +0 -1
  172. package/Detox-android/com/wix/detox/19.9.0/detox-19.9.0-javadoc.jar.sha1 +0 -1
  173. package/Detox-android/com/wix/detox/19.9.0/detox-19.9.0-javadoc.jar.sha256 +0 -1
  174. package/Detox-android/com/wix/detox/19.9.0/detox-19.9.0-javadoc.jar.sha512 +0 -1
  175. package/Detox-android/com/wix/detox/19.9.0/detox-19.9.0-sources.jar.md5 +0 -1
  176. package/Detox-android/com/wix/detox/19.9.0/detox-19.9.0-sources.jar.sha1 +0 -1
  177. package/Detox-android/com/wix/detox/19.9.0/detox-19.9.0-sources.jar.sha256 +0 -1
  178. package/Detox-android/com/wix/detox/19.9.0/detox-19.9.0-sources.jar.sha512 +0 -1
  179. package/Detox-android/com/wix/detox/19.9.0/detox-19.9.0.aar +0 -0
  180. package/Detox-android/com/wix/detox/19.9.0/detox-19.9.0.aar.md5 +0 -1
  181. package/Detox-android/com/wix/detox/19.9.0/detox-19.9.0.aar.sha1 +0 -1
  182. package/Detox-android/com/wix/detox/19.9.0/detox-19.9.0.aar.sha256 +0 -1
  183. package/Detox-android/com/wix/detox/19.9.0/detox-19.9.0.aar.sha512 +0 -1
  184. package/Detox-android/com/wix/detox/19.9.0/detox-19.9.0.pom.md5 +0 -1
  185. package/Detox-android/com/wix/detox/19.9.0/detox-19.9.0.pom.sha1 +0 -1
  186. package/Detox-android/com/wix/detox/19.9.0/detox-19.9.0.pom.sha256 +0 -1
  187. package/Detox-android/com/wix/detox/19.9.0/detox-19.9.0.pom.sha512 +0 -1
  188. package/android/detox/src/full/java/com/wix/detox/espresso/action/AdjustSliderToPositionAction.kt +0 -22
  189. package/android/detox/src/full/java/com/wix/detox/espresso/common/SliderHelper.kt +0 -75
  190. package/android/detox/src/main/java/com/wix/detox/espresso/action/common/ReflectUtils.kt +0 -10
  191. package/android/detox/src/testFull/java/com/wix/detox/espresso/common/SliderHelperTest.kt +0 -39
  192. package/local-cli/templates/mocha.js +0 -32
  193. package/local-cli/utils/splitArgv.js +0 -107
  194. package/runners/integration.js +0 -16
  195. package/runners/jest/DetoxAdapterCircus.js +0 -60
  196. package/runners/jest/DetoxAdapterImpl.js +0 -81
  197. package/runners/jest/DetoxAdapterJasmine.js +0 -67
  198. package/runners/jest/DetoxStreamlineJestReporter.js +0 -98
  199. package/runners/jest/FailingTestsReporter.js +0 -16
  200. package/runners/jest/SpecReporterCircus.js +0 -51
  201. package/runners/jest/SpecReporterJasmine.js +0 -39
  202. package/runners/jest/WorkerAssignReporterCircus.js +0 -17
  203. package/runners/jest/WorkerAssignReporterImpl.js +0 -21
  204. package/runners/jest/WorkerAssignReporterJasmine.js +0 -15
  205. package/runners/jest/runnerInfo.js +0 -9
  206. package/runners/jest-circus/environment.js +0 -206
  207. package/runners/jest-circus/utils/assertJestCircus26.js +0 -39
  208. package/runners/jest-circus/utils/wrapErrorWithNoopLifecycle.js +0 -14
  209. package/src/DetoxConstants.js +0 -13
  210. package/src/DetoxExportWrapper.js +0 -140
  211. package/src/artifacts/timeline/TimelineArtifactPlugin.js +0 -95
  212. package/src/devices/allocation/drivers/NoneAllocDriver.js +0 -10
  213. package/src/devices/allocation/factories/none.js +0 -11
  214. package/src/index.js +0 -6
  215. package/src/utils/MissingDetox.js +0 -78
  216. package/src/utils/fakeTimestampsProvider.js +0 -9
  217. package/src/utils/getWorkerId.js +0 -5
  218. package/src/utils/lastFailedTests.js +0 -38
  219. package/src/utils/sh.js +0 -18
@@ -0,0 +1,117 @@
1
+ const { IPC } = require('node-ipc');
2
+
3
+ const { DetoxInternalError } = require('../errors');
4
+
5
+ class IPCClient {
6
+ constructor({ id, logger, state }) {
7
+ this._id = id;
8
+ /** @type {import('../logger/DetoxLogger')} logger */
9
+ this._logger = logger.child({ __filename, cat: 'ipc' });
10
+ /** @type {import('./state').SecondarySessionState} */
11
+ this._state = state;
12
+
13
+ this._client = null;
14
+ this._serverConnection = null;
15
+ }
16
+
17
+ async init() {
18
+ this._client = new IPC();
19
+
20
+ Object.assign(this._client.config, {
21
+ id: this._id,
22
+ appspace: 'detox.',
23
+ logger: (msg) => this._logger.trace(msg),
24
+ stopRetrying: 0,
25
+ maxRetries: 0,
26
+ });
27
+
28
+ await this._connectToServer();
29
+ await this._registerContext();
30
+ }
31
+
32
+ async dispose() {
33
+ this._serverConnection = null;
34
+
35
+ if (this._client) {
36
+ this._client.disconnect(this.serverId);
37
+ this._client = null;
38
+ }
39
+ }
40
+
41
+ get sessionState() {
42
+ return this._state;
43
+ }
44
+
45
+ get serverId() {
46
+ return this.sessionState.detoxIPCServer;
47
+ }
48
+
49
+ async registerWorker(workerId) {
50
+ this._state.workerId = workerId;
51
+ await this._emit('registerWorker', { workerId });
52
+ }
53
+
54
+ /**
55
+ * @param {string[]} testFilePaths
56
+ */
57
+ async reportFailedTests(testFilePaths) {
58
+ await this._emit('failedTests', { testFilePaths });
59
+ }
60
+
61
+ async _connectToServer() {
62
+ const serverId = this.serverId;
63
+
64
+ this._serverConnection = await new Promise((resolve, reject) => {
65
+ this._client.connectTo(serverId, (client) => {
66
+ client.of[serverId]
67
+ .on('error', reject)
68
+ .on('disconnect', () => reject(new DetoxInternalError('IPC server has unexpectedly disconnected.')))
69
+ .on('connect', () => resolve(client.of[serverId]));
70
+ });
71
+ });
72
+
73
+ this._serverConnection.on('sessionStateUpdate', this._onSessionStateUpdate);
74
+ }
75
+
76
+ async _registerContext() {
77
+ const sessionState = await this._emit('registerContext', {
78
+ id: this._id,
79
+ logFile: this._logger.file,
80
+ });
81
+
82
+ this._state.patch(sessionState);
83
+ }
84
+
85
+ async _emit(event, payload) {
86
+ if (!this._serverConnection) {
87
+ throw new DetoxInternalError(`IPC server ${this.serverId} has unexpectedly disconnected.`);
88
+ }
89
+
90
+ return new Promise((resolve, reject) => {
91
+ const server = this._serverConnection;
92
+
93
+ function onError(err) {
94
+ server.off('error', onError);
95
+ server.off(`${event}Done`, onDone);
96
+ reject(err);
97
+ }
98
+
99
+ function onDone(response) {
100
+ server.off(`${event}Done`, onDone);
101
+ server.off('error', onError);
102
+ resolve(response);
103
+ }
104
+
105
+ server
106
+ .on('error', onError)
107
+ .on(`${event}Done`, onDone)
108
+ .emit(event, payload);
109
+ });
110
+ }
111
+
112
+ _onSessionStateUpdate = (payload) => {
113
+ this._state.patch(payload);
114
+ };
115
+ }
116
+
117
+ module.exports = IPCClient;
@@ -0,0 +1,87 @@
1
+ const { IPC } = require('node-ipc');
2
+
3
+ class IPCServer {
4
+ /**
5
+ * @param {object} options
6
+ * @param {import('./state').PrimarySessionState} options.sessionState
7
+ * @param {Detox.Logger} options.logger
8
+ */
9
+ constructor({ sessionState, logger }) {
10
+ this._sessionState = sessionState;
11
+ this._logger = logger.child({ __filename, cat: 'ipc' });
12
+ this._ipc = null;
13
+ }
14
+
15
+ get id() {
16
+ return this._sessionState.detoxIPCServer;
17
+ }
18
+
19
+ get sessionState() {
20
+ return this._sessionState;
21
+ }
22
+
23
+ async init() {
24
+ this._ipc = new IPC();
25
+ this._ipc.config.id = this.id;
26
+ this._ipc.config.appspace = 'detox.';
27
+ this._ipc.config.logger = (msg) => this._logger.trace(msg);
28
+
29
+ await new Promise((resolve) => {
30
+ // TODO: handle reject
31
+ this._ipc.serve(() => resolve());
32
+ this._ipc.server.on('registerContext', this.onRegisterContext.bind(this));
33
+ this._ipc.server.on('registerWorker', this.onRegisterWorker.bind(this));
34
+ this._ipc.server.on('failedTests', this.onFailedTests.bind(this));
35
+ this._ipc.server.start();
36
+ });
37
+ }
38
+
39
+ async dispose() {
40
+ if (!this._ipc) {
41
+ return;
42
+ }
43
+
44
+ return new Promise((resolve, reject) =>{
45
+ // @ts-ignore
46
+ this._ipc.server.server.close(e => e ? reject(e) : resolve());
47
+ this._ipc.server.stop();
48
+ });
49
+ }
50
+
51
+ onRegisterContext({ id, logFile }, socket) {
52
+ this._sessionState.contexts.push(id);
53
+
54
+ if (logFile && !this._sessionState.logFiles.includes(logFile)) {
55
+ this._sessionState.logFiles.push(logFile);
56
+ }
57
+
58
+ this._ipc.server.emit(socket, 'registerContextDone', {
59
+ failedTestFiles: this._sessionState.failedTestFiles,
60
+ });
61
+ }
62
+
63
+ onRegisterWorker({ workerId }, socket) {
64
+ if (socket) {
65
+ this._ipc.server.emit(socket, 'registerWorkerDone', {});
66
+ }
67
+
68
+ if (workerId > this._sessionState.workersCount) {
69
+ const workersCount = this._sessionState.workersCount = workerId;
70
+ this._ipc.server.broadcast('sessionStateUpdate', { workersCount });
71
+ }
72
+ }
73
+
74
+ onFailedTests({ testFilePaths }, socket) {
75
+ this._sessionState.failedTestFiles.push(...testFilePaths);
76
+
77
+ if (socket) {
78
+ this._ipc.server.emit(socket, 'failedTestsDone', {});
79
+ }
80
+
81
+ this._ipc.server.broadcast('sessionStateUpdate', {
82
+ failedTestFiles: this._sessionState.failedTestFiles,
83
+ });
84
+ }
85
+ }
86
+
87
+ module.exports = IPCServer;
@@ -0,0 +1,76 @@
1
+ const cycle = require('json-cycle');
2
+
3
+ const uuid = require('../utils/uuid');
4
+
5
+ class SessionState {
6
+ patch(state) {
7
+ Object.assign(this, state);
8
+ }
9
+
10
+ stringify() {
11
+ return cycle.stringify(this, SessionState.stringifier);
12
+ }
13
+
14
+ /**
15
+ * @return {*}
16
+ */
17
+ static parse(stringified) {
18
+ const Class = this; // eslint-disable-line unicorn/no-this-assignment
19
+ // @ts-ignore
20
+ return new Class(cycle.parse(stringified, SessionState.reviver));
21
+ }
22
+
23
+ static reviver(key, val) {
24
+ if (typeof val === 'object' && typeof val.$fn == 'string') {
25
+ return eval(val.$fn);
26
+ } else {
27
+ return val;
28
+ }
29
+ }
30
+
31
+ static stringifier(key, val) {
32
+ if (typeof val === 'function') {
33
+ return { $fn: `(${val})` };
34
+ } else {
35
+ return val;
36
+ }
37
+ }
38
+ }
39
+
40
+ class SecondarySessionState extends SessionState {
41
+ constructor({
42
+ id = uuid.UUID(),
43
+ detoxConfigSnapshotPath = '',
44
+ detoxConfig = null,
45
+ detoxIPCServer = '',
46
+ failedTestFiles = [],
47
+ workerId = undefined,
48
+ workersCount = 0
49
+ }) {
50
+ super();
51
+
52
+ this.id = id;
53
+ this.detoxConfigSnapshotPath = detoxConfigSnapshotPath;
54
+ this.detoxConfig = detoxConfig;
55
+ this.detoxIPCServer = detoxIPCServer;
56
+ this.failedTestFiles = failedTestFiles;
57
+ this.workerId = workerId;
58
+ this.workersCount = workersCount;
59
+ }
60
+ }
61
+
62
+ class PrimarySessionState extends SecondarySessionState {
63
+ constructor({ contexts = [], failedTestFiles = [], logFiles = [], ...baseOpts }) {
64
+ super(baseOpts);
65
+
66
+ this.contexts = contexts;
67
+ this.failedTestFiles = failedTestFiles;
68
+ this.logFiles = logFiles;
69
+ }
70
+ }
71
+
72
+ module.exports = {
73
+ SessionState,
74
+ PrimarySessionState,
75
+ SecondarySessionState,
76
+ };
@@ -0,0 +1,244 @@
1
+ const path = require('path');
2
+ const { PassThrough } = require('stream');
3
+
4
+ const bunyan = require('bunyan');
5
+ const bunyanDebugStream = require('bunyan-debug-stream');
6
+ const _ = require('lodash');
7
+
8
+ const temporaryPath = require('../artifacts/utils/temporaryPath');
9
+ const { DetoxInternalError } = require('../errors');
10
+ const { shortFormat } = require('../utils/dateUtils');
11
+
12
+ const customConsoleLogger = require('./customConsoleLogger');
13
+
14
+ /**
15
+ * @typedef PrivateLoggerConfig
16
+ * @property {string} [file]
17
+ */
18
+
19
+ class DetoxLogger {
20
+ /**
21
+ * @param {Detox.DetoxLoggerConfig & PrivateLoggerConfig} [config]
22
+ * @param {object} [context]
23
+ * @param {bunyan} [bunyanLogger]
24
+ */
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
+ }
41
+
42
+ /** @type {object | undefined} */
43
+ 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
+
54
+ this.overrideConsole();
55
+ }
56
+
57
+ /**
58
+ * @internal
59
+ */
60
+ get config() {
61
+ return this._config;
62
+ }
63
+
64
+ /** @returns {Detox.DetoxLogLevel} */
65
+ get level() {
66
+ return this._config.level;
67
+ }
68
+
69
+ /**
70
+ * @internal
71
+ */
72
+ get file() {
73
+ return this._config.file;
74
+ }
75
+
76
+ /**
77
+ * @param config
78
+ */
79
+ async setConfig(config) {
80
+ if (this._context !== undefined) {
81
+ throw new DetoxInternalError('Trying to set a config for a non-root logger');
82
+ }
83
+
84
+ if (this.file) {
85
+ throw new DetoxInternalError('Trying to set a config for a fully initialized logger');
86
+ }
87
+
88
+ _.merge(this._config, config);
89
+
90
+ // @ts-ignore
91
+ const [oldStream] = this._bunyan.streams.splice(0, 1);
92
+ oldStream.stream.end();
93
+ this._bunyan.addStream(this._createDebugStream());
94
+
95
+ this._config.file = temporaryPath.for.jsonl();
96
+ this._bunyan.addStream({
97
+ level: 'trace',
98
+ path: this._config.file,
99
+ });
100
+
101
+ this.overrideConsole();
102
+ }
103
+
104
+ /**
105
+ * @param {object} [overrides]
106
+ * @returns {DetoxLogger}
107
+ */
108
+ child(overrides) {
109
+ if (overrides && overrides.__filename) {
110
+ overrides.__filename = path.basename(overrides.__filename, '.js');
111
+ }
112
+
113
+ return new DetoxLogger(this._config, {
114
+ ...this._context,
115
+ ...overrides,
116
+ }, this._bunyan);
117
+ }
118
+
119
+ /**
120
+ * @param {bunyan.LogLevel} level
121
+ * @param {any[]} args
122
+ * @private
123
+ */
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,
130
+ });
131
+
132
+ this._bunyan[level](mergedContext, ...msgArgs);
133
+ }
134
+
135
+ _initBunyanLogger() {
136
+ /** @type {bunyan.Stream[]} */
137
+ const streams = [this._createDebugStream()];
138
+
139
+ if (this._config.file) {
140
+ streams.push({
141
+ level: 'trace',
142
+ path: this._config.file,
143
+ });
144
+ }
145
+
146
+ return bunyan.createLogger({ name: 'detox', streams });
147
+ }
148
+
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
+ };
161
+ }
162
+
163
+ overrideConsole(sandbox) {
164
+ const option = this._config.overrideConsole;
165
+ if (option === 'none') {
166
+ return;
167
+ }
168
+
169
+ if ((option === 'sandbox' && sandbox) || option === 'all') {
170
+ customConsoleLogger.overrideConsoleMethods((sandbox || global).console, this);
171
+ }
172
+ }
173
+
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
+ };
197
+
198
+ /**
199
+ * @param {string} level
200
+ * @returns {Detox.DetoxLogLevel}
201
+ */
202
+ static castLevel(level) {
203
+ switch (level) {
204
+ case 'fatal':
205
+ case 'error':
206
+ case 'warn':
207
+ case 'info':
208
+ case 'debug':
209
+ case 'trace':
210
+ return level;
211
+ case 'verbose':
212
+ return 'debug';
213
+ default:
214
+ return 'info';
215
+ }
216
+ }
217
+ }
218
+
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
+ module.exports = DetoxLogger;
@@ -0,0 +1,21 @@
1
+ const { AbstractEventBuilder } = require('trace-event-lib');
2
+
3
+ class DetoxTraceEventBuilder extends AbstractEventBuilder {
4
+ constructor(forward) {
5
+ super();
6
+
7
+ this._forward = forward;
8
+ }
9
+
10
+ send(event) {
11
+ // eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars
12
+ const { pid, ts, name, args = {}, ...trace } = event;
13
+ if (trace.ph === 'E') {
14
+ this._forward({ ...args, trace }, `end`);
15
+ } else {
16
+ this._forward({ ...args, trace }, name);
17
+ }
18
+ }
19
+ }
20
+
21
+ module.exports = DetoxTraceEventBuilder;
@@ -0,0 +1,133 @@
1
+ const _ = require('lodash');
2
+
3
+ const isPromise = require('../utils/isPromise');
4
+
5
+ const DetoxTraceEventBuilder = require('./DetoxTraceEventBuilder');
6
+ const TraceThreadDispatcher = require('./TraceThreadDispatcher');
7
+
8
+ class DetoxTracer {
9
+ /**
10
+ * @param {object} options
11
+ * @param {Detox.Logger} options.logger
12
+ */
13
+ constructor({ logger }) {
14
+ this.logger = logger;
15
+ this.builder = new DetoxTraceEventBuilder(this.logger.trace);
16
+ this.categories = {};
17
+ this.defaultEventDispatcher = new TraceThreadDispatcher({
18
+ logger,
19
+ name: 'Default',
20
+ min: 10000,
21
+ });
22
+ this.eventDispatchers = { '': this.defaultEventDispatcher };
23
+ }
24
+
25
+ /**
26
+ * @param {Detox.TraceEvent | string} eventOrName
27
+ * @param {Detox.TraceEvent['args']} [args]
28
+ * @returns {import('trace-event-lib').EndHandle<Detox.TraceEvent>}
29
+ */
30
+ begin(eventOrName, args) {
31
+ const event = typeof eventOrName === 'string' ? { name: eventOrName, args } : eventOrName;
32
+ const mainCategory = event.cat ? event.cat.split(',', 1)[0] : '';
33
+ const dispatcher = this.eventDispatchers[mainCategory] || this.defaultEventDispatcher;
34
+ const tid = dispatcher.begin(event.id);
35
+
36
+ return this.builder.begin({
37
+ args: event.args,
38
+ cat: event.cat || '',
39
+ cname: event.cname,
40
+ name: event.name,
41
+ tid,
42
+ });
43
+ }
44
+
45
+ end(eventOrName, args) {
46
+ const event = typeof eventOrName === 'string' ? { name: eventOrName, args } : eventOrName || {};
47
+ const mainCategory = event.cat ? event.cat.split(',', 1)[0] : '';
48
+ const dispatcher = this.eventDispatchers[mainCategory] || this.defaultEventDispatcher;
49
+ const tid = dispatcher.end(event.id);
50
+
51
+ this.builder.end({
52
+ args: event.args,
53
+ cname: event.cname,
54
+ tid,
55
+ });
56
+ }
57
+
58
+ section(sectionName, func) {
59
+ let result;
60
+
61
+ this.begin(sectionName);
62
+ try {
63
+ result = func();
64
+ if (!isPromise(result)) {
65
+ this.end(sectionName, { success: true });
66
+ } else {
67
+ result.then(
68
+ () => this.end(sectionName, { success: true }),
69
+ (err) => this.end(sectionName, { success: false, err }),
70
+ );
71
+ }
72
+ } catch (err) {
73
+ this.end(sectionName, { success: false, err });
74
+ throw err;
75
+ }
76
+
77
+ return result;
78
+ }
79
+
80
+ registerThreads(event, [min, max]) {
81
+ this.eventDispatchers[event] = new TraceThreadDispatcher({
82
+ logger: this.logger,
83
+ name: event,
84
+ min,
85
+ max,
86
+ });
87
+
88
+ return this;
89
+ }
90
+
91
+ static default(options) {
92
+ const tracer = new DetoxTracer(options);
93
+ for (const [key, range] of Object.entries(this.CATEGORIES)) {
94
+ tracer.registerThreads(key, range);
95
+ }
96
+
97
+ return Object.assign(
98
+ tracer.section.bind(tracer),
99
+ {
100
+ begin: tracer.begin.bind(tracer),
101
+ startSection: tracer.begin.bind(tracer),
102
+ end: tracer.end.bind(tracer),
103
+ endSection: tracer.end.bind(tracer),
104
+ });
105
+ }
106
+
107
+ static categorize(tid) {
108
+ return _.findKey(this.CATEGORIES, ([min, max]) => min <= tid && tid <= max) || 'user';
109
+ }
110
+
111
+ static threadize(cat) {
112
+ const [mainCategory] = cat ? cat.split(',', 1) : 'user';
113
+ const threads = _.find(this.CATEGORIES, (_, key) => key === mainCategory);
114
+ return threads ? threads[0] : 10000;
115
+ }
116
+
117
+ /**
118
+ * @type {Record<string, [number, number]>}
119
+ */
120
+ static CATEGORIES = {
121
+ 'lifecycle': [0, 0],
122
+ 'ipc': [29, 29],
123
+ 'ws-server': [50, 99],
124
+ 'ws-client': [100, 149],
125
+ 'device': [150, 159],
126
+ 'artifacts-manager': [300, 300],
127
+ 'artifact-plugin': [310, 349],
128
+ 'artifact': [350, 399],
129
+ 'child-process': [400, 499],
130
+ };
131
+ }
132
+
133
+ module.exports = DetoxTracer;