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

Sign up to get free protection for your applications and to get access to all the features.
Files changed (204) hide show
  1. package/Detox-android/com/wix/detox/{20.0.0-breaking.new-global-lifecycle.0/detox-20.0.0-breaking.new-global-lifecycle.0-javadoc.jar → 20.0.0/detox-20.0.0-javadoc.jar} +0 -0
  2. package/Detox-android/com/wix/detox/20.0.0/detox-20.0.0-javadoc.jar.md5 +1 -0
  3. package/Detox-android/com/wix/detox/20.0.0/detox-20.0.0-javadoc.jar.sha1 +1 -0
  4. package/Detox-android/com/wix/detox/20.0.0/detox-20.0.0-javadoc.jar.sha256 +1 -0
  5. package/Detox-android/com/wix/detox/20.0.0/detox-20.0.0-javadoc.jar.sha512 +1 -0
  6. package/Detox-android/com/wix/detox/{20.0.0-breaking.new-global-lifecycle.0/detox-20.0.0-breaking.new-global-lifecycle.0-sources.jar → 20.0.0/detox-20.0.0-sources.jar} +0 -0
  7. package/Detox-android/com/wix/detox/20.0.0/detox-20.0.0-sources.jar.md5 +1 -0
  8. package/Detox-android/com/wix/detox/20.0.0/detox-20.0.0-sources.jar.sha1 +1 -0
  9. package/Detox-android/com/wix/detox/20.0.0/detox-20.0.0-sources.jar.sha256 +1 -0
  10. package/Detox-android/com/wix/detox/20.0.0/detox-20.0.0-sources.jar.sha512 +1 -0
  11. package/Detox-android/com/wix/detox/20.0.0/detox-20.0.0.aar +0 -0
  12. package/Detox-android/com/wix/detox/20.0.0/detox-20.0.0.aar.md5 +1 -0
  13. package/Detox-android/com/wix/detox/20.0.0/detox-20.0.0.aar.sha1 +1 -0
  14. package/Detox-android/com/wix/detox/20.0.0/detox-20.0.0.aar.sha256 +1 -0
  15. package/Detox-android/com/wix/detox/20.0.0/detox-20.0.0.aar.sha512 +1 -0
  16. package/Detox-android/com/wix/detox/{20.0.0-breaking.new-global-lifecycle.0/detox-20.0.0-breaking.new-global-lifecycle.0.pom → 20.0.0/detox-20.0.0.pom} +2 -8
  17. package/Detox-android/com/wix/detox/20.0.0/detox-20.0.0.pom.md5 +1 -0
  18. package/Detox-android/com/wix/detox/20.0.0/detox-20.0.0.pom.sha1 +1 -0
  19. package/Detox-android/com/wix/detox/20.0.0/detox-20.0.0.pom.sha256 +1 -0
  20. package/Detox-android/com/wix/detox/20.0.0/detox-20.0.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/README.md +1 -1
  29. package/android/build.gradle +13 -8
  30. package/android/detox/build.gradle +14 -10
  31. package/android/detox/proguard-rules-app.pro +6 -0
  32. package/android/detox/proguard-rules.pro +3 -0
  33. package/android/detox/publish-pom.gradle +5 -1
  34. package/android/detox/publishing.gradle +35 -33
  35. package/android/detox/src/full/java/com/wix/detox/DetoxCrashHandler.kt +1 -1
  36. package/android/detox/src/full/java/com/wix/detox/LaunchArgs.java +9 -0
  37. package/android/detox/src/full/java/com/wix/detox/TestEngineFacade.kt +1 -1
  38. package/android/detox/src/full/java/com/wix/detox/adapters/server/WebSocketClient.java +3 -1
  39. package/android/detox/src/full/java/com/wix/detox/espresso/DetoxAction.java +1 -3
  40. package/android/detox/src/full/java/com/wix/detox/espresso/UiAutomatorHelper.java +1 -1
  41. package/android/detox/src/full/java/com/wix/detox/espresso/action/AdjustSliderToPositionAction.kt +22 -0
  42. package/android/detox/src/{main → full}/java/com/wix/detox/espresso/action/GetAttributesAction.kt +13 -1
  43. package/android/detox/src/full/java/com/wix/detox/espresso/common/SliderHelper.kt +75 -0
  44. package/android/detox/src/full/java/com/wix/detox/espresso/matcher/ViewMatchers.kt +16 -23
  45. package/android/detox/src/full/java/com/wix/detox/reactnative/ReactNativeExtension.kt +15 -2
  46. package/android/detox/src/full/java/com/wix/detox/reactnative/ReactNativeIdlingResources.kt +43 -38
  47. package/android/detox/src/full/java/com/wix/detox/reactnative/ReactNativeLoadingMonitor.kt +54 -8
  48. package/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/IdlingResourceDescription.kt +19 -13
  49. package/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/NetworkIdlingResource.java +33 -30
  50. package/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/timers/DelegatedIdleInterrogationStrategy.kt +7 -27
  51. package/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/timers/IdleInterrogationStrategy.kt +1 -11
  52. package/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/uimodule/RN66Workaround.kt +13 -4
  53. package/android/detox/src/main/java/com/wix/detox/common/DetoxErrors.java +4 -1
  54. package/android/detox/src/main/java/com/wix/detox/common/TextFileReader.kt +1 -1
  55. package/android/detox/src/main/java/com/wix/detox/espresso/UiControllerSpy.kt +2 -1
  56. package/android/detox/src/main/java/com/wix/detox/espresso/action/common/ReflectUtils.kt +10 -0
  57. package/android/detox/src/main/java/com/wix/detox/espresso/action/common/utils/UiControllerUtils.kt +1 -1
  58. package/android/detox/src/testFull/java/com/wix/detox/espresso/action/DetoxMultiTapSpec.kt +4 -3
  59. package/android/detox/src/testFull/java/com/wix/detox/espresso/action/GetAttributesActionTest.kt +15 -3
  60. package/android/detox/src/testFull/java/com/wix/detox/espresso/common/SliderHelperTest.kt +39 -0
  61. package/android/detox/src/testFull/java/com/wix/detox/reactnative/idlingresources/NetworkIdlingResourcesTest.kt +61 -0
  62. package/android/detox/src/testFull/java/com/wix/detox/reactnative/idlingresources/timers/DelegatedIdleInterrogationStrategySpec.kt +3 -11
  63. package/android/gradle/wrapper/gradle-wrapper.properties +2 -1
  64. package/android/gradlew +181 -107
  65. package/index.d.ts +198 -57
  66. package/internals.d.ts +220 -51
  67. package/local-cli/build.js +2 -2
  68. package/local-cli/build.test.js +14 -14
  69. package/local-cli/cli.js +8 -6
  70. package/local-cli/init.js +61 -21
  71. package/local-cli/rebuild-framework-cache.js +1 -1
  72. package/local-cli/reset-lock-file.js +16 -0
  73. package/local-cli/templates/jest.js +13 -10
  74. package/local-cli/test.js +14 -8
  75. package/local-cli/test.test.js +148 -61
  76. package/local-cli/testCommand/TestRunnerCommand.js +78 -71
  77. package/local-cli/testCommand/builder.js +0 -1
  78. package/local-cli/testCommand/middlewares.js +4 -13
  79. package/local-cli/testCommand/warnings.js +0 -3
  80. package/local-cli/utils/jestInternals.js +4 -1
  81. package/package.json +22 -15
  82. package/runners/deprecation.js +42 -44
  83. package/runners/jest/globalSetup.js +1 -1
  84. package/runners/jest/globalTeardown.js +1 -1
  85. package/runners/jest/index.d.ts +60 -0
  86. package/runners/jest/index.js +3 -8
  87. package/runners/jest/index.test.js +13 -0
  88. package/runners/jest/reporters/DetoxReporter.js +33 -2
  89. package/runners/jest/testEnvironment/index.js +119 -69
  90. package/runners/jest/testEnvironment/listeners/DetoxCoreListener.js +94 -51
  91. package/runners/jest/testEnvironment/listeners/DetoxPlatformFilterListener.js +1 -1
  92. package/runners/jest/testEnvironment/listeners/SpecReporter.js +14 -16
  93. package/runners/jest/testEnvironment/listeners/WorkerAssignReporter.js +2 -6
  94. package/runners/jest/testEnvironment/utils/assertJestCircus27.js +17 -3
  95. package/runners/jest/testEnvironment/utils/assertJestCircus27.test.js +0 -1
  96. package/src/DetoxWorker.js +107 -59
  97. package/src/android/core/NativeElement.js +56 -20
  98. package/src/android/core/NativeExpect.js +28 -9
  99. package/src/android/interactions/native.js +25 -18
  100. package/src/artifacts/ArtifactsManager.js +14 -47
  101. package/src/artifacts/instruments/ios/SimulatorInstrumentsRecording.js +3 -3
  102. package/src/artifacts/log/android/ADBLogcatRecording.js +11 -28
  103. package/src/artifacts/log/ios/SimulatorLogRecording.js +1 -1
  104. package/src/artifacts/screenshot/SimulatorScreenshotPlugin.js +1 -1
  105. package/src/artifacts/templates/artifact/Artifact.js +1 -1
  106. package/src/artifacts/templates/plugin/ArtifactPlugin.js +1 -1
  107. package/src/artifacts/timeline/TimelineContextTypes.js +7 -0
  108. package/src/artifacts/utils/temporaryPath.js +18 -7
  109. package/src/artifacts/video/SimulatorRecordVideoPlugin.js +1 -1
  110. package/src/client/AsyncWebSocket.js +8 -17
  111. package/src/client/Client.js +19 -2
  112. package/src/client/actions/formatters/sync-resources/NetworkFormatter.js +1 -1
  113. package/src/configuration/collectCliConfig.js +1 -12
  114. package/src/configuration/composeAppsConfig.js +5 -1
  115. package/src/configuration/composeDeviceConfig.js +1 -1
  116. package/src/configuration/composeLoggerConfig.js +19 -10
  117. package/src/configuration/composeRunnerConfig.js +62 -9
  118. package/src/configuration/index.js +14 -9
  119. package/src/configuration/loadExternalConfig.js +1 -1
  120. package/src/devices/allocation/DeviceAllocator.js +3 -2
  121. package/src/devices/allocation/drivers/android/emulator/AVDValidator.js +5 -5
  122. package/src/devices/allocation/drivers/android/emulator/EmulatorAllocDriver.js +4 -3
  123. package/src/devices/allocation/drivers/android/emulator/EmulatorAllocationHelper.js +1 -1
  124. package/src/devices/allocation/drivers/android/emulator/EmulatorLauncher.js +3 -2
  125. package/src/devices/allocation/drivers/android/emulator/EmulatorVersionResolver.js +4 -6
  126. package/src/devices/allocation/drivers/android/emulator/launchEmulatorProcess.js +1 -1
  127. package/src/devices/allocation/drivers/android/genycloud/GenyAllocDriver.js +1 -0
  128. package/src/devices/allocation/drivers/android/genycloud/GenyInstanceAllocationHelper.js +1 -1
  129. package/src/devices/common/drivers/android/exec/ADB.js +5 -0
  130. package/src/devices/common/drivers/android/genycloud/services/GenyInstanceNaming.js +3 -3
  131. package/src/devices/common/drivers/android/genycloud/services/GenyRecipesService.js +1 -1
  132. package/src/devices/common/drivers/android/tools/EmulatorTelnet.js +1 -1
  133. package/src/devices/common/drivers/android/tools/FreeDeviceFinder.js +1 -1
  134. package/src/devices/common/drivers/android/tools/MonitoredInstrumentation.js +1 -1
  135. package/src/devices/common/drivers/ios/tools/AppleSimUtils.js +29 -3
  136. package/src/devices/lifecycle/GenyGlobalLifecycleHandler.js +13 -15
  137. package/src/devices/runtime/RuntimeDevice.js +19 -12
  138. package/src/devices/runtime/drivers/DeviceDriverBase.js +1 -1
  139. package/src/devices/runtime/drivers/android/AndroidDriver.js +10 -2
  140. package/src/devices/runtime/drivers/ios/SimulatorDriver.js +1 -1
  141. package/src/errors/DetoxConfigErrorComposer.js +18 -3
  142. package/src/ios/expectTwo.js +153 -67
  143. package/src/ipc/IPCClient.js +12 -12
  144. package/src/ipc/IPCServer.js +34 -17
  145. package/src/ipc/{state.js → SessionState.js} +26 -31
  146. package/src/logger/DetoxLogger.js +261 -157
  147. package/src/logger/index.js +5 -0
  148. package/src/logger/utils/BunyanLogger.js +76 -0
  149. package/src/logger/utils/CategoryThreadDispatcher.js +36 -0
  150. package/src/logger/utils/DetoxLogFinalizer.js +140 -0
  151. package/src/logger/utils/MessageStack.js +24 -0
  152. package/src/logger/utils/ThreadDispatcher.js +61 -0
  153. package/src/logger/{customConsoleLogger.js → utils/customConsoleLogger.js} +5 -4
  154. package/src/logger/utils/sanitizeBunyanContext.js +30 -0
  155. package/src/{utils → logger/utils}/streamUtils.js +51 -17
  156. package/src/logger/utils/tracerLegacy.js +37 -0
  157. package/src/realms/DetoxContext.js +78 -65
  158. package/src/realms/DetoxInternalsFacade.js +8 -12
  159. package/src/realms/DetoxPrimaryContext.js +106 -73
  160. package/src/realms/DetoxSecondaryContext.js +29 -31
  161. package/src/server/DetoxConnection.js +18 -23
  162. package/src/server/DetoxServer.js +7 -10
  163. package/src/server/DetoxSession.js +6 -6
  164. package/src/server/DetoxSessionManager.js +1 -1
  165. package/src/server/handlers/RegisteredConnectionHandler.js +1 -2
  166. package/src/symbols.js +16 -22
  167. package/src/utils/Timer.js +55 -38
  168. package/src/utils/argparse.js +11 -0
  169. package/src/utils/childProcess/exec.js +1 -1
  170. package/src/utils/childProcess/spawn.js +1 -1
  171. package/src/utils/environment.js +30 -15
  172. package/src/utils/errorUtils.js +24 -3
  173. package/src/utils/invocationTraceDescriptions.js +43 -0
  174. package/src/utils/logger.js +1 -1
  175. package/src/utils/traceInvocationCall.js +21 -0
  176. package/src/utils/traceMethods.js +15 -0
  177. package/Detox-android/com/wix/detox/20.0.0-breaking.new-global-lifecycle.0/detox-20.0.0-breaking.new-global-lifecycle.0-javadoc.jar.md5 +0 -1
  178. package/Detox-android/com/wix/detox/20.0.0-breaking.new-global-lifecycle.0/detox-20.0.0-breaking.new-global-lifecycle.0-javadoc.jar.sha1 +0 -1
  179. package/Detox-android/com/wix/detox/20.0.0-breaking.new-global-lifecycle.0/detox-20.0.0-breaking.new-global-lifecycle.0-javadoc.jar.sha256 +0 -1
  180. package/Detox-android/com/wix/detox/20.0.0-breaking.new-global-lifecycle.0/detox-20.0.0-breaking.new-global-lifecycle.0-javadoc.jar.sha512 +0 -1
  181. package/Detox-android/com/wix/detox/20.0.0-breaking.new-global-lifecycle.0/detox-20.0.0-breaking.new-global-lifecycle.0-sources.jar.md5 +0 -1
  182. package/Detox-android/com/wix/detox/20.0.0-breaking.new-global-lifecycle.0/detox-20.0.0-breaking.new-global-lifecycle.0-sources.jar.sha1 +0 -1
  183. package/Detox-android/com/wix/detox/20.0.0-breaking.new-global-lifecycle.0/detox-20.0.0-breaking.new-global-lifecycle.0-sources.jar.sha256 +0 -1
  184. package/Detox-android/com/wix/detox/20.0.0-breaking.new-global-lifecycle.0/detox-20.0.0-breaking.new-global-lifecycle.0-sources.jar.sha512 +0 -1
  185. package/Detox-android/com/wix/detox/20.0.0-breaking.new-global-lifecycle.0/detox-20.0.0-breaking.new-global-lifecycle.0.aar +0 -0
  186. package/Detox-android/com/wix/detox/20.0.0-breaking.new-global-lifecycle.0/detox-20.0.0-breaking.new-global-lifecycle.0.aar.md5 +0 -1
  187. package/Detox-android/com/wix/detox/20.0.0-breaking.new-global-lifecycle.0/detox-20.0.0-breaking.new-global-lifecycle.0.aar.sha1 +0 -1
  188. package/Detox-android/com/wix/detox/20.0.0-breaking.new-global-lifecycle.0/detox-20.0.0-breaking.new-global-lifecycle.0.aar.sha256 +0 -1
  189. package/Detox-android/com/wix/detox/20.0.0-breaking.new-global-lifecycle.0/detox-20.0.0-breaking.new-global-lifecycle.0.aar.sha512 +0 -1
  190. package/Detox-android/com/wix/detox/20.0.0-breaking.new-global-lifecycle.0/detox-20.0.0-breaking.new-global-lifecycle.0.pom.md5 +0 -1
  191. package/Detox-android/com/wix/detox/20.0.0-breaking.new-global-lifecycle.0/detox-20.0.0-breaking.new-global-lifecycle.0.pom.sha1 +0 -1
  192. package/Detox-android/com/wix/detox/20.0.0-breaking.new-global-lifecycle.0/detox-20.0.0-breaking.new-global-lifecycle.0.pom.sha256 +0 -1
  193. package/Detox-android/com/wix/detox/20.0.0-breaking.new-global-lifecycle.0/detox-20.0.0-breaking.new-global-lifecycle.0.pom.sha512 +0 -1
  194. package/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/timers/DefaultIdleInterrogationStrategy.kt +0 -84
  195. package/android/detox/src/main/java/com/wix/detox/espresso/action/AdjustSliderToPositionAction.kt +0 -36
  196. package/android/detox/src/testFull/java/com/wix/detox/espresso/action/AdjustSliderToPositionActionTest.kt +0 -59
  197. package/android/detox/src/testFull/java/com/wix/detox/reactnative/idlingresources/timers/DefaultIdleInterrogationStrategySpec.kt +0 -115
  198. package/runners/jest/deprecation.js +0 -25
  199. package/src/configuration/utils/warnings.js +0 -12
  200. package/src/logger/DetoxTraceEventBuilder.js +0 -21
  201. package/src/logger/DetoxTracer.js +0 -133
  202. package/src/logger/TraceThreadDispatcher.js +0 -52
  203. package/src/utils/ChromeTracingExporter.js +0 -53
  204. 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.runnerConfig.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,54 +7,67 @@ 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 { DETOX_RERUN_INDEX } = process.env;
20
-
21
- if (!isNaN(DETOX_RERUN_INDEX)) {
22
- return Number(DETOX_RERUN_INDEX) * this._testRunTimes + test.invocations;
23
- } else {
24
- return test.invocations;
25
- }
17
+ this._circusRetryTimes = 1;
26
18
  }
27
19
 
28
20
  async setup() {
29
21
  // Workaround to override Jest's expect
30
- if (detoxInternals.config.behaviorConfig.init.exposeGlobals) {
22
+ if (detoxInternals.config.behavior.init.exposeGlobals) {
31
23
  this._env.global.expect = detox.expect;
32
24
  }
33
25
  }
34
26
 
35
- async run_describe_start({ describeBlock: { name, children } }) {
36
- if (children.length) {
37
- 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
+ });
38
33
  }
39
34
  }
40
35
 
41
- async run_describe_finish({ describeBlock: { name, children } }) {
42
- if (children.length) {
43
- 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();
44
40
  }
45
41
  }
46
42
 
47
43
  async test_start({ test }) {
48
- if (!_.isEmpty(test.errors)) {
44
+ const metadata = this._getTestMetadata(test);
45
+ if (metadata.status === 'failed') {
49
46
  this._testsFailedBeforeStart.add(test);
50
47
  }
51
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
+
52
60
  const circusRetryTimes = +this._env.global[RETRY_TIMES];
53
- this._testRunTimes = isNaN(circusRetryTimes) ? 1 : 1 + circusRetryTimes;
61
+ this._circusRetryTimes = isNaN(circusRetryTimes) ? 1 : 1 + circusRetryTimes;
54
62
  }
55
63
 
56
- async hook_start(_event, state) {
64
+ async hook_start(event, state) {
57
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 });
58
71
  }
59
72
 
60
73
  async hook_failure({ error, hook }) {
@@ -62,61 +75,91 @@ class DetoxCoreListener {
62
75
  error,
63
76
  hook: hook.type,
64
77
  });
78
+
79
+ log.trace.end({ success: false, error });
65
80
  }
66
81
 
67
82
  async test_fn_start({ test }) {
68
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 });
69
93
  }
70
94
 
71
95
  async test_fn_failure({ error }) {
72
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']));
73
109
  }
74
110
 
75
111
  async _onBeforeActualTestStart(test) {
76
- if (!test || test.status === 'skip' || this._startedTests.has(test) || this._testsFailedBeforeStart.has(test)) {
112
+ if (!this._isTestActuallyStarting(test)) {
77
113
  return;
78
114
  }
79
115
 
80
116
  this._startedTests.add(test);
117
+ await detoxInternals.onTestStart(this._getTestMetadata(test));
118
+ }
119
+
120
+ _isTestActuallyStarting(test) {
121
+ return test && !this._isTestSkipped(test) && !this._startedTests.has(test) && !this._testsFailedBeforeStart.has(test);
122
+ }
81
123
 
82
- await detoxInternals.onTestStart({
124
+ _isTestSkipped(test) {
125
+ return test && (test.mode === 'skip' || test.mode === 'todo');
126
+ }
127
+
128
+ _getTestMetadata(test) {
129
+ const result = {
83
130
  title: test.name,
84
131
  fullName: getFullTestName(test),
85
- status: 'running',
132
+ status: this._getTestStatus(test),
86
133
  invocations: this._getTestInvocations(test),
87
- });
88
- }
134
+ };
89
135
 
90
- async test_done({ test }) {
91
- if (this._startedTests.has(test)) {
92
- await detoxInternals.onTestDone({
93
- title: test.name,
94
- fullName: getFullTestName(test),
95
- status: test.errors.length ? 'failed' : 'passed',
96
- invocations: this._getTestInvocations(test),
97
- timedOut: hasTimedOut(test)
98
- });
99
-
100
- this._startedTests.delete(test);
136
+ if (result.status === 'failed') {
137
+ result.timedOut = hasTimedOut(test);
101
138
  }
139
+
140
+ return result;
102
141
  }
103
142
 
104
- async run_finish(_event, state) {
105
- if (this._hasFailedTests(state.rootDescribeBlock)) {
106
- await detoxInternals.reportFailedTests([this._env.testPath]);
143
+ /** @returns { 'failed' | 'passed' | 'running' | 'skip' | 'todo' } */
144
+ _getTestStatus(test) {
145
+ if (!_.isEmpty(test.errors)) {
146
+ return 'failed';
107
147
  }
108
- }
109
148
 
110
- _hasFailedTests(block) {
111
- if (block.children) {
112
- for (const child of block.children) {
113
- if (this._hasFailedTests(child)) {
114
- return true;
115
- }
116
- }
149
+ if (this._isTestSkipped(test)) {
150
+ return test.mode;
117
151
  }
118
152
 
119
- 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;
120
163
  }
121
164
  }
122
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
- const jestSection = config.runnerConfig.jest;
19
+ setup() {
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
 
@@ -12,8 +12,8 @@ class WorkerAssignReporter {
12
12
  }
13
13
 
14
14
  run_start() {
15
- if (config.runnerConfig.jest.reportWorkerAssign) {
16
- log.info({ event: 'WORKER_ASSIGN' }, `${this._formatTestName()} is assigned to ${this._formatDeviceName()}`);
15
+ if (config.testRunner.jest.reportWorkerAssign) {
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
  });