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,9 +1,11 @@
1
- // @ts-nocheck
2
- const maybeNodeEnvironment = require('jest-environment-node'); // eslint-disable-line node/no-extraneous-require
1
+ const path = require('path');
2
+
3
+ const resolveFrom = require('resolve-from');
4
+ const maybeNodeEnvironment = require(resolveFrom(process.cwd(), 'jest-environment-node'));
5
+ /** @type {typeof import('@jest/environment').JestEnvironment} */
3
6
  const NodeEnvironment = maybeNodeEnvironment.default || maybeNodeEnvironment;
4
7
 
5
8
  const detox = require('../../../internals');
6
- const { DetoxError } = require('../../../src/errors');
7
9
  const Timer = require('../../../src/utils/Timer');
8
10
 
9
11
  const {
@@ -24,6 +26,8 @@ const SYNC_CIRCUS_EVENTS = new Set([
24
26
  'error',
25
27
  ]);
26
28
 
29
+ const log = detox.log.child({ cat: 'lifecycle,jest-environment' });
30
+
27
31
  /**
28
32
  * @see https://www.npmjs.com/package/jest-circus#overview
29
33
  */
@@ -32,98 +36,92 @@ class DetoxCircusEnvironment extends NodeEnvironment {
32
36
  super(assertJestCircus27(config), assertExistingContext(context));
33
37
 
34
38
  /** @private */
35
- this._timer = null;
39
+ this._shouldManageDetox = detox.getStatus() === 'inactive';
36
40
  /** @private */
37
- this._listenerFactories = {
41
+ this._timer = new Timer();
42
+
43
+ /** @internal */
44
+ this.testPath = path.relative(process.cwd(), context.testPath);
45
+ /** @protected */
46
+ this.testEventListeners = [];
47
+ /** @protected */
48
+ this.setupTimeout = detox.config.testRunner.jest.setupTimeout;
49
+ /** @protected */
50
+ this.teardownTimeout = detox.config.testRunner.jest.teardownTimeout;
51
+
52
+ log.trace.begin(this.testPath);
53
+
54
+ this.setup = this._wrapSetup(this.setup);
55
+ this.teardown = this._wrapTeardown(this.teardown);
56
+
57
+ this.registerListeners({
38
58
  DetoxInitErrorListener,
39
59
  DetoxPlatformFilterListener,
40
60
  DetoxCoreListener,
41
61
  SpecReporter,
42
62
  WorkerAssignReporter,
43
- };
44
- /** @protected */
45
- this.testPath = context.testPath;
46
- /** @protected */
47
- this.testEventListeners = [];
48
- /** @protected */
49
- this.initTimeout = detox.config.testRunner.jest.initTimeout;
63
+ });
50
64
  }
51
65
 
52
66
  /** @override */
53
67
  async setup() {
54
68
  await super.setup();
55
-
56
- await Timer.run({
57
- description: `setting up Detox environment`,
58
- timeout: this.initTimeout,
59
- fn: async () => {
60
- await this.initDetox();
61
- this._instantiateListeners();
62
- },
63
- });
69
+ await this.initDetox();
64
70
  }
65
71
 
66
- /** @override */
67
- async handleTestEvent(event, state) {
68
- const { name } = event;
72
+ handleTestEvent = async (event, state) => {
73
+ this._timer.schedule(state.testTimeout != null ? state.testTimeout : this.setupTimeout);
69
74
 
70
- if (SYNC_CIRCUS_EVENTS.has(name)) {
71
- return this._handleTestEventSync(event, state);
75
+ if (SYNC_CIRCUS_EVENTS.has(event.name)) {
76
+ this._handleTestEventSync(event, state);
77
+ } else {
78
+ await this._handleTestEventAsync(event, state);
72
79
  }
80
+ };
73
81
 
74
- this._timer = new Timer({
75
- description: `handling jest-circus "${name}" event`,
76
- timeout: state.testTimeout != null ? state.testTimeout : this.initTimeout,
77
- });
78
-
82
+ /** @override */
83
+ async teardown() {
79
84
  try {
80
- for (const listener of this.testEventListeners) {
81
- if (typeof listener[name] !== 'function') {
82
- continue;
83
- }
84
-
85
- try {
86
- await this._timer.run(() => listener[name](event, state));
87
- } catch (listenerError) {
88
- this._logError(listenerError);
89
- break;
90
- }
91
- }
85
+ await this.cleanupDetox();
92
86
  } finally {
93
- this._timer.dispose();
94
- this._timer = null;
87
+ await super.teardown();
95
88
  }
96
89
  }
97
90
 
98
- /** @override */
99
- async teardown() {
100
- await Timer.run({
101
- description: `tearing down Detox environment`,
102
- timeout: this.initTimeout,
103
- fn: async () => {
104
- await this.cleanupDetox();
105
- },
106
- });
107
- }
108
-
109
91
  /** @protected */
110
92
  registerListeners(map) {
111
- Object.assign(this._listenerFactories, map);
93
+ for (const Listener of Object.values(map)) {
94
+ this.testEventListeners.push(new Listener({
95
+ env: this,
96
+ }));
97
+ }
112
98
  }
113
99
 
114
100
  /**
115
101
  * @protected
116
102
  */
117
103
  async initDetox() {
118
- await detox.setup({
104
+ const opts = {
119
105
  global: this.global,
120
- workerId: +process.env.JEST_WORKER_ID,
121
- });
106
+ workerId: `w${process.env.JEST_WORKER_ID}`,
107
+ };
108
+
109
+ if (this._shouldManageDetox) {
110
+ await detox.init(opts);
111
+ } else {
112
+ await detox.installWorker(opts);
113
+ }
114
+
115
+ return detox.worker;
122
116
  }
123
117
 
124
118
  /** @protected */
125
119
  async cleanupDetox() {
126
- await detox.teardown();
120
+ if (this._shouldManageDetox) {
121
+ await detox.cleanup();
122
+ } else {
123
+ await detox.uninstallWorker();
124
+ }
127
125
  }
128
126
 
129
127
  /** @private */
@@ -138,17 +136,69 @@ class DetoxCircusEnvironment extends NodeEnvironment {
138
136
  }
139
137
 
140
138
  /** @private */
141
- _instantiateListeners() {
142
- for (const Listener of Object.values(this._listenerFactories)) {
143
- this.testEventListeners.push(new Listener({
144
- env: this,
145
- }));
139
+ async _handleTestEventAsync(event, state = null) {
140
+ const description = `handling ${state ? 'jest-circus' : 'jest-environment'} "${event.name}" event`;
141
+
142
+ for (const listener of this.testEventListeners) {
143
+ if (typeof listener[event.name] !== 'function') {
144
+ continue;
145
+ }
146
+
147
+ try {
148
+ await this._timer.run(description, () => listener[event.name](event, state));
149
+ } catch (listenerError) {
150
+ log.error(listenerError);
151
+ if (this._timer.expired) {
152
+ break;
153
+ }
154
+ }
146
155
  }
147
156
  }
148
157
 
149
- /** @private */
150
- _logError(e) {
151
- detox.log.error(DetoxError.format(e));
158
+ _wrapSetup(fn) {
159
+ const _setup = fn.bind(this);
160
+
161
+ return async () => {
162
+ await log.trace.complete('set up environment', async () => {
163
+ try {
164
+ this._timer.schedule(this.setupTimeout);
165
+ await this._handleTestEventAsync({ name: 'environment_setup_start' });
166
+ await this._timer.run(`setting up Detox environment`, _setup);
167
+ await this._handleTestEventAsync({ name: 'environment_setup_success' });
168
+ } catch (error) {
169
+ this._timer.schedule(this.teardownTimeout);
170
+ await this._handleTestEventAsync({ name: 'environment_setup_failure', error });
171
+ throw error;
172
+ } finally {
173
+ this._timer.clear();
174
+ }
175
+ });
176
+ };
177
+ }
178
+
179
+ _wrapTeardown(fn) {
180
+ const _teardown = fn.bind(this);
181
+
182
+ return async () => {
183
+ await log.trace.complete('tear down environment', async () => {
184
+ try {
185
+ this._timer.schedule(this.teardownTimeout);
186
+ await this._handleTestEventAsync({ name: 'environment_teardown_start' });
187
+ await this._timer.run(`tearing down Detox environment`, _teardown);
188
+ await this._handleTestEventAsync({ name: 'environment_teardown_success' });
189
+ } catch (error) {
190
+ if (this._timer.expired) {
191
+ this._timer.schedule(this.teardownTimeout);
192
+ }
193
+
194
+ await this._handleTestEventAsync({ name: 'environment_teardown_failure', error });
195
+ throw error;
196
+ } finally {
197
+ this._timer.clear();
198
+ log.trace.end();
199
+ }
200
+ });
201
+ };
152
202
  }
153
203
  }
154
204
 
@@ -7,17 +7,14 @@ const { getFullTestName, hasTimedOut } = require('../utils');
7
7
 
8
8
  const RETRY_TIMES = Symbol.for('RETRY_TIMES');
9
9
 
10
+ const log = detoxInternals.log.child({ cat: 'lifecycle,jest-environment' });
11
+
10
12
  class DetoxCoreListener {
11
13
  constructor({ env }) {
12
- this._startedTests = new WeakSet();
13
- this._testsFailedBeforeStart = new WeakSet();
14
+ this._startedTests = new Set();
15
+ this._testsFailedBeforeStart = new Set();
14
16
  this._env = env;
15
- this._testRunTimes = 1;
16
- }
17
-
18
- _getTestInvocations(test) {
19
- const { testSessionIndex } = detoxInternals.session;
20
- return testSessionIndex * this._testRunTimes + test.invocations;
17
+ this._circusRetryTimes = 1;
21
18
  }
22
19
 
23
20
  async setup() {
@@ -27,29 +24,50 @@ class DetoxCoreListener {
27
24
  }
28
25
  }
29
26
 
30
- async run_describe_start({ describeBlock: { name, children } }) {
31
- if (children.length) {
32
- await detoxInternals.onRunDescribeStart({ name });
27
+ async run_describe_start({ describeBlock }) {
28
+ if (describeBlock.children.length) {
29
+ log.trace.begin(describeBlock.parent ? describeBlock.name : 'run the tests');
30
+ await detoxInternals.onRunDescribeStart({
31
+ name: describeBlock.name,
32
+ });
33
33
  }
34
34
  }
35
35
 
36
- async run_describe_finish({ describeBlock: { name, children } }) {
37
- if (children.length) {
38
- await detoxInternals.onRunDescribeFinish({ name });
36
+ async run_describe_finish({ describeBlock }) {
37
+ if (describeBlock.children.length) {
38
+ await detoxInternals.onRunDescribeFinish({ name: describeBlock.name });
39
+ log.trace.end();
39
40
  }
40
41
  }
41
42
 
42
43
  async test_start({ test }) {
43
- if (!_.isEmpty(test.errors)) {
44
+ const metadata = this._getTestMetadata(test);
45
+ if (metadata.status === 'failed') {
44
46
  this._testsFailedBeforeStart.add(test);
45
47
  }
46
48
 
49
+ const logTrace = this._isTestSkipped(test)
50
+ ? log.trace
51
+ : log.trace.begin;
52
+
53
+ logTrace({
54
+ context: 'test',
55
+ status: metadata.status,
56
+ fullName: metadata.fullName,
57
+ invocations: metadata.invocations,
58
+ }, metadata.title);
59
+
47
60
  const circusRetryTimes = +this._env.global[RETRY_TIMES];
48
- this._testRunTimes = isNaN(circusRetryTimes) ? 1 : 1 + circusRetryTimes;
61
+ this._circusRetryTimes = isNaN(circusRetryTimes) ? 1 : 1 + circusRetryTimes;
49
62
  }
50
63
 
51
- async hook_start(_event, state) {
64
+ async hook_start(event, state) {
52
65
  await this._onBeforeActualTestStart(state.currentlyRunningTest);
66
+ log.trace.begin({ functionCode: event.hook.fn.toString() }, event.hook.type);
67
+ }
68
+
69
+ async hook_success() {
70
+ log.trace.end({ success: true });
53
71
  }
54
72
 
55
73
  async hook_failure({ error, hook }) {
@@ -57,62 +75,91 @@ class DetoxCoreListener {
57
75
  error,
58
76
  hook: hook.type,
59
77
  });
78
+
79
+ log.trace.end({ success: false, error });
60
80
  }
61
81
 
62
82
  async test_fn_start({ test }) {
63
83
  await this._onBeforeActualTestStart(test);
84
+
85
+ if (!this._testsFailedBeforeStart.has(test)) {
86
+ // Jest bug workaround: beforeAll hook errors result into an unterminated test_fn_start event.
87
+ log.trace.begin({ functionCode: test.fn.toString() }, 'test_fn');
88
+ }
89
+ }
90
+
91
+ async test_fn_success() {
92
+ log.trace.end({ success: true });
64
93
  }
65
94
 
66
95
  async test_fn_failure({ error }) {
67
96
  await detoxInternals.onTestFnFailure({ error });
97
+ log.trace.end({ success: false, error });
98
+ }
99
+
100
+ async test_done({ test }) {
101
+ const metadata = this._getTestMetadata(test);
102
+
103
+ if (this._startedTests.has(test)) {
104
+ await detoxInternals.onTestDone(metadata);
105
+ this._startedTests.delete(test);
106
+ }
107
+
108
+ log.trace.end(_.pick(metadata, ['status', 'timedOut']));
68
109
  }
69
110
 
70
111
  async _onBeforeActualTestStart(test) {
71
- if (!test || test.status === 'skip' || this._startedTests.has(test) || this._testsFailedBeforeStart.has(test)) {
112
+ if (!this._isTestActuallyStarting(test)) {
72
113
  return;
73
114
  }
74
115
 
75
116
  this._startedTests.add(test);
117
+ await detoxInternals.onTestStart(this._getTestMetadata(test));
118
+ }
76
119
 
77
- await detoxInternals.onTestStart({
120
+ _isTestActuallyStarting(test) {
121
+ return test && !this._isTestSkipped(test) && !this._startedTests.has(test) && !this._testsFailedBeforeStart.has(test);
122
+ }
123
+
124
+ _isTestSkipped(test) {
125
+ return test && (test.mode === 'skip' || test.mode === 'todo');
126
+ }
127
+
128
+ _getTestMetadata(test) {
129
+ const result = {
78
130
  title: test.name,
79
131
  fullName: getFullTestName(test),
80
- status: 'running',
132
+ status: this._getTestStatus(test),
81
133
  invocations: this._getTestInvocations(test),
82
- });
83
- }
84
-
85
- async test_done({ test }) {
86
- if (this._startedTests.has(test)) {
87
- await detoxInternals.onTestDone({
88
- title: test.name,
89
- fullName: getFullTestName(test),
90
- status: test.errors.length ? 'failed' : 'passed',
91
- invocations: this._getTestInvocations(test),
92
- timedOut: hasTimedOut(test)
93
- });
134
+ };
94
135
 
95
- this._startedTests.delete(test);
136
+ if (result.status === 'failed') {
137
+ result.timedOut = hasTimedOut(test);
96
138
  }
139
+
140
+ return result;
97
141
  }
98
142
 
99
- async run_finish(_event, state) {
100
- if (this._hasFailedTests(state.rootDescribeBlock)) {
101
- const handledByJestCircus = this._testRunTimes > 1 && !detoxInternals.config.testRunner.jest.retryAfterCircusRetries;
102
- await detoxInternals.reportFailedTests([this._env.testPath], handledByJestCircus);
143
+ /** @returns { 'failed' | 'passed' | 'running' | 'skip' | 'todo' } */
144
+ _getTestStatus(test) {
145
+ if (!_.isEmpty(test.errors)) {
146
+ return 'failed';
103
147
  }
104
- }
105
148
 
106
- _hasFailedTests(block) {
107
- if (block.children) {
108
- for (const child of block.children) {
109
- if (this._hasFailedTests(child)) {
110
- return true;
111
- }
112
- }
149
+ if (this._isTestSkipped(test)) {
150
+ return test.mode;
113
151
  }
114
152
 
115
- return block.errors ? block.errors.length > 0 : false;
153
+ if (test.status === 'done') {
154
+ return 'passed';
155
+ } else {
156
+ return test.status || 'running';
157
+ }
158
+ }
159
+
160
+ _getTestInvocations(test) {
161
+ const { testSessionIndex } = detoxInternals.session;
162
+ return testSessionIndex * this._circusRetryTimes + test.invocations;
116
163
  }
117
164
  }
118
165
 
@@ -5,7 +5,7 @@ const { device } = require('../../../..');
5
5
  const PLATFORM_REGEXP = /^:([^:]+):/;
6
6
 
7
7
  class DetoxPlatformFilterListener {
8
- constructor() {
8
+ setup() {
9
9
  this._platform = device.getPlatform();
10
10
  }
11
11
 
@@ -1,4 +1,5 @@
1
1
  const chalk = require('chalk').default;
2
+ const noop = require('lodash/noop');
2
3
 
3
4
  const { config, log, session } = require('../../../../internals');
4
5
  const { traceln } = require('../utils/stdout');
@@ -15,16 +16,21 @@ class SpecReporter {
15
16
  this._suitesDesc = '';
16
17
  }
17
18
 
18
- get enabled() {
19
+ setup() {
19
20
  const jestSection = config.testRunner.jest;
20
21
  const reportSpecs = jestSection && jestSection.reportSpecs;
21
-
22
- return reportSpecs !== undefined ? reportSpecs : session.workersCount === 1;
22
+ const enabled = reportSpecs !== undefined ? reportSpecs : session.workersCount === 1;
23
+
24
+ if (!enabled) {
25
+ this.run_describe_start = noop;
26
+ this.run_describe_finish = noop;
27
+ this.test_start = noop;
28
+ this.test_done = noop;
29
+ this.test_skip = noop;
30
+ }
23
31
  }
24
32
 
25
33
  run_describe_start(event) {
26
- if (!this.enabled) return;
27
-
28
34
  if (event.describeBlock.parent !== undefined) {
29
35
  this._onSuiteStart({
30
36
  description: event.describeBlock.name,
@@ -33,16 +39,12 @@ class SpecReporter {
33
39
  }
34
40
 
35
41
  run_describe_finish(event) {
36
- if (!this.enabled) return;
37
-
38
42
  if (event.describeBlock.parent !== undefined) {
39
43
  this._onSuiteEnd();
40
44
  }
41
45
  }
42
46
 
43
47
  test_start(event) {
44
- if (!this.enabled) return;
45
-
46
48
  const { test } = event;
47
49
  this._onTestStart({
48
50
  description: test.name,
@@ -51,8 +53,6 @@ class SpecReporter {
51
53
  }
52
54
 
53
55
  test_done(event) {
54
- if (!this.enabled) return;
55
-
56
56
  const { test } = event;
57
57
  const testInfo = {
58
58
  description: test.name,
@@ -62,8 +62,6 @@ class SpecReporter {
62
62
  }
63
63
 
64
64
  test_skip(event) {
65
- if (!this.enabled) return;
66
-
67
65
  const testInfo = {
68
66
  description: event.test.name,
69
67
  };
@@ -110,7 +108,7 @@ class SpecReporter {
110
108
  .concat(suite.description)
111
109
  .concat((index === total - 1) ? ': ' : '');
112
110
  });
113
- this._suitesDesc = chalk.bold.white(this._suitesDesc);
111
+ this._suitesDesc = chalk.bold(this._suitesDesc);
114
112
  }
115
113
 
116
114
  _traceTest({ description, invocations }, _status = undefined) {
@@ -118,7 +116,7 @@ class SpecReporter {
118
116
  const retriesDescription = (invocations > 1) ? chalk.gray(` [Retry #${invocations - 1}]`) : '';
119
117
  const status = chalk.gray(_status ? ` [${_status}]` : '');
120
118
  const desc = this._suitesDesc + testDescription + retriesDescription + status;
121
- log.info({ event: 'SPEC_STATE_CHANGE' }, desc);
119
+ log.info({ cat: 'lifecycle' }, desc);
122
120
  }
123
121
  }
124
122
 
@@ -13,7 +13,7 @@ class WorkerAssignReporter {
13
13
 
14
14
  run_start() {
15
15
  if (config.testRunner.jest.reportWorkerAssign) {
16
- log.info({ event: 'WORKER_ASSIGN' }, `${this._formatTestName()} is assigned to ${this._formatDeviceName()}`);
16
+ log.info({ cat: 'lifecycle' }, `${chalk.bold(this._testName)} is assigned to ${this._formatDeviceName()}`);
17
17
  }
18
18
  }
19
19
 
@@ -25,10 +25,6 @@ class WorkerAssignReporter {
25
25
 
26
26
  return formattedDeviceName;
27
27
  }
28
-
29
- _formatTestName() {
30
- return chalk.whiteBright(this._testName);
31
- }
32
28
  }
33
29
 
34
30
  module.exports = WorkerAssignReporter;
@@ -1,8 +1,10 @@
1
1
  const fs = require('fs');
2
2
  const path = require('path');
3
3
 
4
+ const resolveFrom = require('resolve-from');
4
5
  const semver = require('semver');
5
6
 
7
+ const { log } = require('../../../../internals');
6
8
  const detoxPackageJson = require('../../../../package.json');
7
9
  const { DetoxRuntimeError } = require('../../../../src/errors');
8
10
 
@@ -25,6 +27,10 @@ function assertJestCircus27(maybeProjectConfig) {
25
27
  });
26
28
  }
27
29
 
30
+ const jestManifestPath = resolveFrom(process.cwd(), 'jest/package.json');
31
+ const jestManifest = require(jestManifestPath);
32
+ assertSupportedVersion(jestManifest.version);
33
+
28
34
  const circusVersion = require(circusPackageJson).version;
29
35
  if (!circusVersion) {
30
36
  throw new DetoxRuntimeError({
@@ -33,7 +39,14 @@ function assertJestCircus27(maybeProjectConfig) {
33
39
  });
34
40
  }
35
41
 
36
- assertSupportedVersion(circusVersion);
42
+ if (jestManifest.version !== circusVersion) {
43
+ log.warn([
44
+ `jest-circus@${circusVersion} does not match jest@${jestManifest.version}.\n`,
45
+ `- jest@${jestManifest.version} resolved path:\n\t${jestManifestPath}`,
46
+ `- jest-circus@${circusVersion} resolved path:\n\t${circusPackageJson}`,
47
+ `\nPlease make sure that your versions match to avoid unexpected behavior!`,
48
+ ].join('\n'));
49
+ }
37
50
 
38
51
  return maybeProjectConfig;
39
52
  }
@@ -41,11 +54,12 @@ function assertJestCircus27(maybeProjectConfig) {
41
54
  function assertSupportedVersion(actualVersion) {
42
55
  const supportedRange = detoxPackageJson.peerDependencies.jest;
43
56
  const minSupportedVersion = semver.minVersion(supportedRange);
57
+ const action = semver.lt(actualVersion, minSupportedVersion) ? 'upgrade' : 'downgrade';
44
58
 
45
- if (semver.lt(actualVersion, minSupportedVersion)) {
59
+ if (!semver.satisfies(actualVersion, supportedRange, { includePrerelease: true })) {
46
60
  throw new DetoxRuntimeError({
47
61
  message: `Detected an unsupported jest@${actualVersion} version.`,
48
- hint: `Please upgrade your Jest test runner to the supported range: ${supportedRange}.`
62
+ hint: `Please ${action} your Jest test runner to the supported range: ${supportedRange}.`
49
63
  });
50
64
  }
51
65
  }
@@ -9,7 +9,6 @@ describe('assertSupportedVersion', () => {
9
9
  ['28.0.0'],
10
10
  ['28.1.0'],
11
11
  ['29.0.0-next.0'],
12
- ['30.0.0'],
13
12
  ])('should pass for %j', (version) => {
14
13
  expect(() => assertSupportedVersion(version)).not.toThrow();
15
14
  });