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
@@ -409,7 +409,7 @@ Please check your Detox config${this._atPath()}`,
409
409
  case 'gpuMode':
410
410
  return this._unsupportedPropertyByDeviceType('gpuMode', ['android.emulator'], deviceAlias);
411
411
  case 'headless':
412
- return this._unsupportedPropertyByDeviceType('headless', ['android.emulator'], deviceAlias);
412
+ return this._unsupportedPropertyByDeviceType('headless', ['ios.simulator', 'android.emulator'], deviceAlias);
413
413
  case 'readonly':
414
414
  return this._unsupportedPropertyByDeviceType('readonly', ['android.emulator'], deviceAlias);
415
415
  case 'utilBinaryPaths':
@@ -507,6 +507,14 @@ Examine your Detox config${this._atPath()}`,
507
507
  });
508
508
  }
509
509
 
510
+ unsupportedReversePorts(appPath) {
511
+ return new DetoxConfigError({
512
+ message: `Non-Android app configs cannot have "reversePorts" property:`,
513
+ debugInfo: this._focusOnAppConfig(appPath),
514
+ inspectOptions: { depth: 4 },
515
+ });
516
+ }
517
+
510
518
  missingAppBinaryPath(appPath) {
511
519
  return new DetoxConfigError({
512
520
  message: `Missing "binaryPath" property in the app config.\nExpected a string:`,
@@ -656,12 +664,19 @@ Examine your Detox config${this._atPath()}`,
656
664
  }
657
665
 
658
666
  invalidTestRunnerProperty(isGlobal) {
667
+ const testRunner = _.get(
668
+ isGlobal
669
+ ? this.contents
670
+ : this._getSelectedConfiguration(),
671
+ ['testRunner']
672
+ );
673
+
659
674
  return new DetoxConfigError({
660
- message: `testRunner should be an object, not a string`,
675
+ message: `testRunner should be an object, not a ${typeof testRunner}`,
661
676
  hint: `Check that in your Detox config${this._atPath()}`,
662
677
  inspectOptions: { depth: isGlobal ? 0 : 3 },
663
678
  debugInfo: isGlobal ? {
664
- testRunner: _.get(this.contents, ['testRunner']),
679
+ testRunner,
665
680
  ...this.contents,
666
681
  } : {
667
682
  ...this._focusOnConfiguration(c => _.pick(c, ['testRunner'])),
@@ -1,4 +1,5 @@
1
1
  // @ts-nocheck
2
+ const assert = require('assert');
2
3
  const path = require('path');
3
4
 
4
5
  const fs = require('fs-extra');
@@ -6,6 +7,9 @@ const _ = require('lodash');
6
7
  const tempfile = require('tempfile');
7
8
 
8
9
  const { assertEnum, assertNormalized } = require('../utils/assertArgument');
10
+ const { actionDescription, expectDescription } = require('../utils/invocationTraceDescriptions');
11
+ const log = require('../utils/logger').child({ cat: 'ws-client, ws' });
12
+ const traceInvocationCall = require('../utils/traceInvocationCall').bind(null, log);
9
13
 
10
14
  const assertDirection = assertEnum(['left', 'right', 'up', 'down']);
11
15
  const assertSpeed = assertEnum(['fast', 'slow']);
@@ -23,7 +27,8 @@ class Expect {
23
27
  + (percent + (' (' + (typeof percent + ')'))));
24
28
  }
25
29
 
26
- return this.expect('toBeVisible', percent);
30
+ const traceDescription = expectDescription.toBeVisible(percent);
31
+ return this.expect('toBeVisible', traceDescription, percent);
27
32
  }
28
33
 
29
34
  toBeNotVisible() {
@@ -31,7 +36,8 @@ class Expect {
31
36
  }
32
37
 
33
38
  toBeFocused() {
34
- return this.expect('toBeFocused');
39
+ const traceDescription = expectDescription.toBeFocused();
40
+ return this.expect('toBeFocused', traceDescription);
35
41
  }
36
42
 
37
43
  toBeNotFocused() {
@@ -39,7 +45,8 @@ class Expect {
39
45
  }
40
46
 
41
47
  toExist() {
42
- return this.expect('toExist');
48
+ const traceDescription = expectDescription.toExist();
49
+ return this.expect('toExist', traceDescription);
43
50
  }
44
51
 
45
52
  toNotExist() {
@@ -47,7 +54,8 @@ class Expect {
47
54
  }
48
55
 
49
56
  toHaveText(text) {
50
- return this.expect('toHaveText', text);
57
+ const traceDescription = expectDescription.toHaveText(text);
58
+ return this.expect('toHaveText', traceDescription, text);
51
59
  }
52
60
 
53
61
  toNotHaveText(text) {
@@ -55,7 +63,8 @@ class Expect {
55
63
  }
56
64
 
57
65
  toHaveLabel(label) {
58
- return this.expect('toHaveLabel', label);
66
+ const traceDescription = expectDescription.toHaveLabel(label);
67
+ return this.expect('toHaveLabel', traceDescription, label);
59
68
  }
60
69
 
61
70
  toNotHaveLabel(label) {
@@ -63,7 +72,8 @@ class Expect {
63
72
  }
64
73
 
65
74
  toHaveId(id) {
66
- return this.expect('toHaveId', id);
75
+ const traceDescription = expectDescription.toHaveId(id);
76
+ return this.expect('toHaveId', traceDescription, id);
67
77
  }
68
78
 
69
79
  toNotHaveId(id) {
@@ -71,7 +81,8 @@ class Expect {
71
81
  }
72
82
 
73
83
  toHaveValue(value) {
74
- return this.expect('toHaveValue', value);
84
+ const traceDescription = expectDescription.toHaveValue(value);
85
+ return this.expect('toHaveValue', traceDescription, value);
75
86
  }
76
87
 
77
88
  toNotHaveValue(value) {
@@ -79,7 +90,8 @@ class Expect {
79
90
  }
80
91
 
81
92
  toHaveSliderPosition(position, tolerance = 0) {
82
- return this.expect('toHaveSliderPosition', position, tolerance);
93
+ const traceDescription = expectDescription.toHaveSliderPosition(position, tolerance);
94
+ return this.expect('toHaveSliderPosition', traceDescription, position, tolerance);
83
95
  }
84
96
 
85
97
  toHaveToggleValue(value) {
@@ -103,16 +115,18 @@ class Expect {
103
115
  };
104
116
  }
105
117
 
106
- expect(expectation, ...params) {
118
+ expect(expectation, traceDescription, ...params) {
119
+ assert(traceDescription, `must provide trace description for expectation: \n ${JSON.stringify(expectation)}`);
120
+
107
121
  const invocation = this.createInvocation(expectation, ...params);
108
- return this._invocationManager.execute(invocation);
122
+ traceDescription = expectDescription.full(traceDescription, this.modifiers.includes('not'));
123
+ return _executeInvocation(this._invocationManager, invocation, traceDescription);
109
124
  }
110
125
  }
111
126
 
112
127
  class InternalExpect extends Expect {
113
- expect(expectation, ...params) {
114
- const invocation = this.createInvocation(expectation, ...params);
115
- return invocation;
128
+ expect(expectation, _traceDescription, ...params) {
129
+ return this.createInvocation(expectation, ...params);
116
130
  }
117
131
  }
118
132
 
@@ -131,7 +145,8 @@ class Element {
131
145
  }
132
146
 
133
147
  getAttributes() {
134
- return this.withAction('getAttributes');
148
+ const traceDescription = actionDescription.getAttributes();
149
+ return this.withAction('getAttributes', traceDescription);
135
150
  }
136
151
 
137
152
  tap(point) {
@@ -140,12 +155,16 @@ class Element {
140
155
  if (typeof point.x !== 'number') throw new Error('point.x should be a number, but got ' + (point.x + (' (' + (typeof point.x + ')'))));
141
156
  if (typeof point.y !== 'number') throw new Error('point.y should be a number, but got ' + (point.y + (' (' + (typeof point.y + ')'))));
142
157
  }
143
- return this.withAction('tap', point);
158
+
159
+ const traceDescription = actionDescription.tapAtPoint(point);
160
+ return this.withAction('tap', traceDescription, point);
144
161
  }
145
162
 
146
163
  longPress(duration = 1000) {
147
164
  if (typeof duration !== 'number') throw new Error('duration should be a number, but got ' + (duration + (' (' + (typeof duration + ')'))));
148
- return this.withAction('longPress', duration);
165
+
166
+ const traceDescription = actionDescription.longPress(duration);
167
+ return this.withAction('longPress', traceDescription, duration);
149
168
  }
150
169
 
151
170
  longPressAndDrag(duration, normalizedPositionX, normalizedPositionY, targetElement,
@@ -162,13 +181,18 @@ class Element {
162
181
  assertNormalized({ normalizedTargetPositionX });
163
182
  assertNormalized({ normalizedTargetPositionY });
164
183
 
165
- return this.withActionAndTargetElement('longPress', targetElement, duration, normalizedPositionX, normalizedPositionY,
184
+ const traceDescription = actionDescription.longPressAndDrag(duration, normalizedPositionX, normalizedPositionY, targetElement,
185
+ normalizedTargetPositionX, normalizedTargetPositionY, speed, holdDuration);
186
+ return this.withActionAndTargetElement('longPress', targetElement, traceDescription, duration, normalizedPositionX, normalizedPositionY,
166
187
  normalizedTargetPositionX, normalizedTargetPositionY, speed, holdDuration);
167
188
  }
168
189
 
169
190
  multiTap(times) {
170
191
  if (typeof times !== 'number') throw new Error('times should be a number, but got ' + (times + (' (' + (typeof times + ')'))));
171
- return this.withAction('multiTap', times);
192
+ if (times < 1) throw new Error('times should be greater than 0, but got ' + times);
193
+
194
+ const traceDescription = actionDescription.multiTap(times);
195
+ return this.withAction('multiTap', traceDescription, times);
172
196
  }
173
197
 
174
198
  tapAtPoint(point) {
@@ -176,25 +200,32 @@ class Element {
176
200
  }
177
201
 
178
202
  tapBackspaceKey() {
179
- return this.withAction('tapBackspaceKey');
203
+ const traceDescription = actionDescription.tapBackspaceKey();
204
+ return this.withAction('tapBackspaceKey', traceDescription);
180
205
  }
181
206
 
182
207
  tapReturnKey() {
183
- return this.withAction('tapReturnKey');
208
+ const traceDescription = actionDescription.tapReturnKey();
209
+ return this.withAction('tapReturnKey', traceDescription);
184
210
  }
185
211
 
186
212
  typeText(text) {
187
213
  if (typeof text !== 'string') throw new Error('text should be a string, but got ' + (text + (' (' + (typeof text + ')'))));
188
- return this.withAction('typeText', text);
214
+
215
+ const traceDescription = actionDescription.typeText(text);
216
+ return this.withAction('typeText', traceDescription, text);
189
217
  }
190
218
 
191
219
  replaceText(text) {
192
220
  if (typeof text !== 'string') throw new Error('text should be a string, but got ' + (text + (' (' + (typeof text + ')'))));
193
- return this.withAction('replaceText', text);
221
+
222
+ const traceDescription = actionDescription.replaceText(text);
223
+ return this.withAction('replaceText', traceDescription, text);
194
224
  }
195
225
 
196
226
  clearText() {
197
- return this.withAction('clearText');
227
+ const traceDescription = actionDescription.clearText();
228
+ return this.withAction('clearText', traceDescription);
198
229
  }
199
230
 
200
231
  scroll(pixels, direction = 'down', startPositionX = NaN, startPositionY = NaN) {
@@ -202,12 +233,15 @@ class Element {
202
233
  if (typeof pixels !== 'number') throw new Error('amount of pixels should be a number, but got ' + (pixels + (' (' + (typeof pixels + ')'))));
203
234
  if (typeof startPositionX !== 'number') throw new Error('startPositionX should be a number, but got ' + (startPositionX + (' (' + (typeof startPositionX + ')'))));
204
235
  if (typeof startPositionY !== 'number') throw new Error('startPositionY should be a number, but got ' + (startPositionY + (' (' + (typeof startPositionY + ')'))));
205
- return this.withAction('scroll', pixels, direction, startPositionX, startPositionY);
236
+
237
+ const traceDescription = actionDescription.scroll(pixels, direction, startPositionX, startPositionY);
238
+ return this.withAction('scroll', traceDescription, pixels, direction, startPositionX, startPositionY);
206
239
  }
207
240
 
208
241
  scrollTo(edge) {
209
242
  if (!['left', 'right', 'top', 'bottom'].some(option => option === edge)) throw new Error('edge should be one of [left, right, top, bottom], but got ' + edge);
210
- return this.withAction('scrollTo', edge);
243
+ const traceDescription = actionDescription.scrollTo(edge);
244
+ return this.withAction('scrollTo', traceDescription, edge);
211
245
  }
212
246
 
213
247
  swipe(direction, speed = 'fast', normalizedSwipeOffset = NaN, normalizedStartingPointX = NaN, normalizedStartingPointY = NaN) {
@@ -218,42 +252,62 @@ class Element {
218
252
  assertNormalized({ normalizedStartingPointY });
219
253
 
220
254
  normalizedSwipeOffset = Number.isNaN(normalizedSwipeOffset) ? 0.75 : normalizedSwipeOffset;
221
- return this.withAction('swipe', direction, speed, normalizedSwipeOffset, normalizedStartingPointX, normalizedStartingPointY);
255
+ const traceDescription = actionDescription.swipe(direction, speed, normalizedSwipeOffset, normalizedStartingPointX, normalizedStartingPointY);
256
+ return this.withAction(
257
+ 'swipe',
258
+ traceDescription,
259
+ direction,
260
+ speed,
261
+ normalizedSwipeOffset,
262
+ normalizedStartingPointX,
263
+ normalizedStartingPointY
264
+ );
222
265
  }
223
266
 
224
267
  setColumnToValue(column, value) {
225
268
  if (typeof column !== 'number') throw new Error('column should be a number, but got ' + (column + (' (' + (typeof column + ')'))));
226
269
  if (typeof value !== 'string') throw new Error('value should be a string, but got ' + (value + (' (' + (typeof value + ')'))));
227
- return this.withAction('setColumnToValue', column, value);
270
+
271
+ const traceDescription = actionDescription.setColumnToValue(column, value);
272
+ return this.withAction('setColumnToValue', traceDescription, column, value);
228
273
  }
229
274
 
230
275
  setDatePickerDate(dateString, dateFormat) {
231
276
  if (typeof dateString !== 'string') throw new Error('dateString should be a string, but got ' + (dateString + (' (' + (typeof dateString + ')'))));
232
277
  if (typeof dateFormat !== 'string') throw new Error('dateFormat should be a string, but got ' + (dateFormat + (' (' + (typeof dateFormat + ')'))));
233
- return this.withAction('setDatePickerDate', dateString, dateFormat);
278
+
279
+ const traceDescription = actionDescription.setDatePickerDate(dateString, dateFormat);
280
+ return this.withAction('setDatePickerDate', traceDescription, dateString, dateFormat);
234
281
  }
235
282
 
236
283
  pinch(scale, speed = 'fast', angle = 0) {
237
284
  if (typeof scale !== 'number' || !Number.isFinite(scale) || scale < 0) throw new Error(`pinch scale must be a finite number larger than zero`);
238
285
  if (!['slow', 'fast'].includes(speed)) throw new Error(`pinch speed is either 'slow' or 'fast'`);
239
286
  if (typeof angle !== 'number' || !Number.isFinite(angle)) throw new Error(`pinch angle must be a finite number (radian)`);
240
- return this.withAction('pinch', scale, speed, angle);
287
+
288
+ const traceDescription = actionDescription.pinch(scale, speed, angle);
289
+ return this.withAction('pinch', traceDescription, scale, speed, angle);
241
290
  }
242
291
 
243
292
  pinchWithAngle(direction, speed = 'slow', angle = 0) {
244
293
  if (!['inward', 'outward'].includes(direction)) throw new Error(`pinchWithAngle direction is either 'inward' or 'outward'`);
245
294
  if (!['slow', 'fast'].includes(speed)) throw new Error(`pinchWithAngle speed is either 'slow' or 'fast'`);
246
295
  if (typeof angle !== 'number') throw new Error(`pinchWithAngle angle must be a number (radiant), got ${typeof angle}`);
247
- return this.withAction('pinchWithAngle', direction, speed, angle);
296
+
297
+ const traceDescription = actionDescription.pinchWithAngle(direction, speed, angle);
298
+ return this.withAction('pinchWithAngle', traceDescription, direction, speed, angle);
248
299
  }
249
300
 
250
301
  adjustSliderToPosition(position) {
251
302
  if (!(typeof position === 'number' && position >= 0 && position <= 1)) throw new Error('position should be a number [0.0, 1.0], but got ' + (position + (' (' + (typeof position + ')'))));
252
- return this.withAction('adjustSliderToPosition', position);
303
+
304
+ const traceDescription = actionDescription.adjustSliderToPosition(position);
305
+ return this.withAction('adjustSliderToPosition', traceDescription, position);
253
306
  }
254
307
 
255
308
  async takeScreenshot(fileName) {
256
- const { screenshotPath } = await this.withAction('takeScreenshot', fileName);
309
+ const traceDescription = actionDescription.takeScreenshot(fileName);
310
+ const { screenshotPath } = await this.withAction('takeScreenshot', traceDescription, fileName);
257
311
 
258
312
  const filePath = tempfile('.detox.element-screenshot.png');
259
313
  await fs.move(screenshotPath, filePath);
@@ -287,22 +341,20 @@ class Element {
287
341
  return invocation;
288
342
  }
289
343
 
290
- withAction(action, ...params) {
344
+ withAction(action, traceDescription, ...params) {
291
345
  const invocation = this.createInvocation(action, null, ...params);
292
- return this._invocationManager.execute(invocation);
346
+ return _executeInvocation(this._invocationManager, invocation, traceDescription);
293
347
  }
294
348
 
295
- withActionAndTargetElement(action, targetElement, ...params) {
349
+ withActionAndTargetElement(action, targetElement, traceDescription, ...params) {
296
350
  const invocation = this.createInvocation(action, targetElement, ...params);
297
- return this._invocationManager.execute(invocation);
351
+ return _executeInvocation(this._invocationManager, invocation, traceDescription);
298
352
  }
299
353
  }
300
354
 
301
355
  class InternalElement extends Element {
302
-
303
- withAction(action, ...params) {
304
- const invocation = this.createInvocation(action, null, ...params);
305
- return invocation;
356
+ withAction(action, _traceDescription, ...params) {
357
+ return this.createInvocation(action, null, ...params);
306
358
  }
307
359
  }
308
360
 
@@ -341,7 +393,6 @@ class By {
341
393
  }
342
394
 
343
395
  class Matcher {
344
-
345
396
  accessibilityLabel(label) {
346
397
  return this.label(label);
347
398
  }
@@ -395,14 +446,12 @@ class Matcher {
395
446
  if (!(matcher instanceof Matcher)) {
396
447
  throwMatcherError(matcher);
397
448
  }
449
+
398
450
  this.and({ predicate: { type: 'descendant', predicate: matcher.predicate } });
399
451
  return this;
400
452
  }
401
453
 
402
454
  and(matcher) {
403
- // if (!(matcher instanceof Matcher)) {
404
- // throwMatcherError(matcher);
405
- // }
406
455
  const tempPredicate = this.predicate;
407
456
  delete this.predicate;
408
457
  this.predicate = { type: 'and', predicates: [] };
@@ -493,7 +542,9 @@ class WaitFor {
493
542
  if (typeof timeout !== 'number') throw new Error('text should be a number, but got ' + (timeout + (' (' + (typeof timeout + ')'))));
494
543
  if (timeout < 0) throw new Error('timeout must be larger than 0');
495
544
  this.timeout = timeout;
496
- return this.waitForWithTimeout();
545
+
546
+ const traceDescription = expectDescription.withTimeout(timeout);
547
+ return this.waitForWithTimeout(traceDescription);
497
548
  }
498
549
 
499
550
  whileElement(matcher) {
@@ -504,106 +555,137 @@ class WaitFor {
504
555
 
505
556
  tap(point) {
506
557
  this.action = this.actionableElement.tap(point);
507
- return this.waitForWithAction();
558
+ const traceDescription = actionDescription.tapAtPoint(point);
559
+ return this.waitForWithAction(traceDescription);
508
560
  }
509
561
 
510
562
  longPress(duration) {
511
563
  this.action = this.actionableElement.longPress(duration);
512
- return this.waitForWithAction();
564
+ const traceDescription = actionDescription.longPress(duration);
565
+ return this.waitForWithAction(traceDescription);
513
566
  }
514
567
 
515
568
  multiTap(times) {
516
569
  this.action = this.actionableElement.multiTap(times);
517
- return this.waitForWithAction();
570
+ const traceDescription = actionDescription.multiTap(times);
571
+ return this.waitForWithAction(traceDescription);
518
572
  }
519
573
 
520
574
  tapAtPoint(point) {
521
575
  this.action = this.actionableElement.tap(point);
522
- return this.waitForWithAction();
576
+ const traceDescription = actionDescription.tapAtPoint(point);
577
+ return this.waitForWithAction(traceDescription);
523
578
  }
524
579
 
525
580
  tapBackspaceKey() {
526
581
  this.action = this.actionableElement.tapBackspaceKey();
527
- return this.waitForWithAction();
582
+ const traceDescription = actionDescription.tapBackspaceKey();
583
+ return this.waitForWithAction(traceDescription);
528
584
  }
529
585
 
530
586
  tapReturnKey() {
531
587
  this.action = this.actionableElement.tapReturnKey();
532
- return this.waitForWithAction();
588
+ const traceDescription = actionDescription.tapReturnKey();
589
+ return this.waitForWithAction(traceDescription);
533
590
  }
534
591
 
535
592
  typeText(text) {
536
593
  this.action = this.actionableElement.typeText(text);
537
- return this.waitForWithAction();
594
+ const traceDescription = actionDescription.typeText(text);
595
+ return this.waitForWithAction(traceDescription);
538
596
  }
539
597
 
540
598
  replaceText(text) {
541
599
  this.action = this.actionableElement.replaceText(text);
542
- return this.waitForWithAction();
600
+ const traceDescription = actionDescription.replaceText(text);
601
+ return this.waitForWithAction(traceDescription);
543
602
  }
544
603
 
545
604
  clearText() {
546
605
  this.action = this.actionableElement.clearText();
547
- return this.waitForWithAction();
606
+ const traceDescription = actionDescription.clearText();
607
+ return this.waitForWithAction(traceDescription);
548
608
  }
549
609
 
550
610
  scroll(pixels, direction, startPositionX, startPositionY) {
551
611
  this.action = this.actionableElement.scroll(pixels, direction, startPositionX, startPositionY);
552
- return this.waitForWithAction();
612
+
613
+ const traceDescription = actionDescription.scroll(pixels, direction, startPositionX, startPositionY);
614
+ return this.waitForWithAction(traceDescription);
553
615
  }
554
616
 
555
617
  scrollTo(edge) {
556
618
  this.action = this.actionableElement.scrollTo(edge);
557
- return this.waitForWithAction();
619
+ const traceDescription = actionDescription.scrollTo(edge);
620
+ return this.waitForWithAction(traceDescription);
558
621
  }
559
622
 
560
623
  swipe(direction, speed, percentage) {
561
624
  this.action = this.actionableElement.swipe(direction, speed, percentage);
562
- return this.waitForWithAction();
625
+ const traceDescription = actionDescription.swipe(direction, speed, percentage);
626
+ return this.waitForWithAction(traceDescription);
563
627
  }
564
628
 
565
629
  setColumnToValue(column, value) {
566
630
  this.action = this.actionableElement.setColumnToValue(column, value);
567
- return this.waitForWithAction();
631
+ const traceDescription = actionDescription.setColumnToValue(column, value);
632
+ return this.waitForWithAction(traceDescription);
568
633
  }
569
634
 
570
635
  setDatePickerDate(dateString, dateFormat) {
571
636
  this.action = this.actionableElement.setDatePickerDate(dateString, dateFormat);
572
- return this.waitForWithAction();
637
+ const traceDescription = actionDescription.setDatePickerDate(dateString, dateFormat);
638
+ return this.waitForWithAction(traceDescription);
573
639
  }
574
640
 
575
641
  pinch(scale, speed, angle) {
576
642
  this.action = this.actionableElement.pinch(scale, speed, angle);
577
- return this.waitForWithAction();
643
+ const traceDescription = actionDescription.pinch(scale, speed, angle);
644
+ return this.waitForWithAction(traceDescription);
578
645
  }
579
646
 
580
647
  pinchWithAngle(direction, speed, angle) {
581
648
  this.action = this.actionableElement.pinchWithAngle(direction, speed, angle);
582
- return this.waitForWithAction();
649
+ const traceDescription = actionDescription.pinchWithAngle(direction, speed, angle);
650
+ return this.waitForWithAction(traceDescription);
583
651
  }
584
652
 
585
- waitForWithAction() {
653
+ waitForWithAction(actionTraceDescription) {
586
654
  const expectation = this.expectation;
587
655
  const action = this.action;
588
656
 
589
- return this._invocationManager.execute({
657
+ const invocation = this.createWaitForWithActionInvocation(expectation, action);
658
+
659
+ const traceDescription = expectDescription.waitFor(actionTraceDescription);
660
+ return _executeInvocation(this._invocationManager, invocation, traceDescription);
661
+ }
662
+
663
+ createWaitForWithActionInvocation(expectation, action) {
664
+ return {
590
665
  ...action,
591
666
  while: {
592
667
  ...expectation
593
668
  }
594
- });
669
+ };
595
670
  }
596
671
 
597
- waitForWithTimeout() {
672
+ waitForWithTimeout(expectTraceDescription) {
598
673
  const expectation = this.expectation;
599
674
  const action = this.action;
600
675
  const timeout = this.timeout;
601
676
 
602
- return this._invocationManager.execute({
677
+ const invocation = this.createWaitForWithTimeoutInvocation(expectation, action, timeout);
678
+
679
+ const traceDescription = expectDescription.waitForWithTimeout(expectTraceDescription, timeout);
680
+ return _executeInvocation(this._invocationManager, invocation, traceDescription);
681
+ }
682
+
683
+ createWaitForWithTimeoutInvocation(expectation, action, timeout) {
684
+ return {
603
685
  ...action,
604
686
  ...expectation,
605
687
  timeout
606
- });
688
+ };
607
689
  }
608
690
  }
609
691
 
@@ -665,4 +747,8 @@ function throwElementError(param) {
665
747
  throw new Error(`${param} is not a Detox element. More about Detox elements here: https://wix.github.io/Detox/docs/api/matchers`);
666
748
  }
667
749
 
750
+ function _executeInvocation(invocationManager, invocation, traceDescription) {
751
+ return traceInvocationCall(traceDescription, invocation, invocationManager.execute(invocation));
752
+ }
753
+
668
754
  module.exports = IosExpect;
@@ -1,13 +1,14 @@
1
1
  const { IPC } = require('node-ipc');
2
2
 
3
3
  const { DetoxInternalError } = require('../errors');
4
+ const { serializeObjectWithError } = require('../utils/errorUtils');
4
5
 
5
6
  class IPCClient {
6
7
  constructor({ id, logger, state }) {
7
8
  this._id = id;
8
9
  /** @type {import('../logger/DetoxLogger')} logger */
9
- this._logger = logger.child({ __filename, cat: 'ipc' });
10
- /** @type {import('./state').SecondarySessionState} */
10
+ this._logger = logger.child({ cat: 'ipc' });
11
+ /** @type {import('./SessionState')} */
11
12
  this._state = state;
12
13
 
13
14
  this._client = null;
@@ -47,15 +48,18 @@ class IPCClient {
47
48
  }
48
49
 
49
50
  async registerWorker(workerId) {
50
- this._state.workerId = workerId;
51
- await this._emit('registerWorker', { workerId });
51
+ const sessionState = await this._emit('registerWorker', { workerId });
52
+ this._state.patch(sessionState);
52
53
  }
53
54
 
54
55
  /**
55
- * @param {string[]} testFilePaths
56
+ * @param {DetoxInternals.DetoxTestFileReport[]} testResults
56
57
  */
57
- async reportFailedTests(testFilePaths) {
58
- await this._emit('failedTests', { testFilePaths });
58
+ async reportTestResults(testResults) {
59
+ const sessionState = await this._emit('reportTestResults', {
60
+ testResults: testResults.map(r => serializeObjectWithError(r, 'testExecError')),
61
+ });
62
+ this._state.patch(sessionState);
59
63
  }
60
64
 
61
65
  async _connectToServer() {
@@ -74,11 +78,7 @@ class IPCClient {
74
78
  }
75
79
 
76
80
  async _registerContext() {
77
- const sessionState = await this._emit('registerContext', {
78
- id: this._id,
79
- logFile: this._logger.file,
80
- });
81
-
81
+ const sessionState = await this._emit('registerContext', { id: this._id });
82
82
  this._state.patch(sessionState);
83
83
  }
84
84