detox 20.12.2 → 20.14.0-smoke.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (139) hide show
  1. package/Detox-android/com/wix/detox/{20.12.2/detox-20.12.2-javadoc.jar → 20.14.0-smoke.0/detox-20.14.0-smoke.0-javadoc.jar} +0 -0
  2. package/Detox-android/com/wix/detox/20.14.0-smoke.0/detox-20.14.0-smoke.0-javadoc.jar.md5 +1 -0
  3. package/Detox-android/com/wix/detox/20.14.0-smoke.0/detox-20.14.0-smoke.0-javadoc.jar.sha1 +1 -0
  4. package/Detox-android/com/wix/detox/20.14.0-smoke.0/detox-20.14.0-smoke.0-javadoc.jar.sha256 +1 -0
  5. package/Detox-android/com/wix/detox/20.14.0-smoke.0/detox-20.14.0-smoke.0-javadoc.jar.sha512 +1 -0
  6. package/Detox-android/com/wix/detox/{20.12.2/detox-20.12.2-sources.jar → 20.14.0-smoke.0/detox-20.14.0-smoke.0-sources.jar} +0 -0
  7. package/Detox-android/com/wix/detox/20.14.0-smoke.0/detox-20.14.0-smoke.0-sources.jar.md5 +1 -0
  8. package/Detox-android/com/wix/detox/20.14.0-smoke.0/detox-20.14.0-smoke.0-sources.jar.sha1 +1 -0
  9. package/Detox-android/com/wix/detox/20.14.0-smoke.0/detox-20.14.0-smoke.0-sources.jar.sha256 +1 -0
  10. package/Detox-android/com/wix/detox/20.14.0-smoke.0/detox-20.14.0-smoke.0-sources.jar.sha512 +1 -0
  11. package/Detox-android/com/wix/detox/20.14.0-smoke.0/detox-20.14.0-smoke.0.aar +0 -0
  12. package/Detox-android/com/wix/detox/20.14.0-smoke.0/detox-20.14.0-smoke.0.aar.md5 +1 -0
  13. package/Detox-android/com/wix/detox/20.14.0-smoke.0/detox-20.14.0-smoke.0.aar.sha1 +1 -0
  14. package/Detox-android/com/wix/detox/20.14.0-smoke.0/detox-20.14.0-smoke.0.aar.sha256 +1 -0
  15. package/Detox-android/com/wix/detox/20.14.0-smoke.0/detox-20.14.0-smoke.0.aar.sha512 +1 -0
  16. package/Detox-android/com/wix/detox/{20.12.2/detox-20.12.2.pom → 20.14.0-smoke.0/detox-20.14.0-smoke.0.pom} +1 -1
  17. package/Detox-android/com/wix/detox/20.14.0-smoke.0/detox-20.14.0-smoke.0.pom.md5 +1 -0
  18. package/Detox-android/com/wix/detox/20.14.0-smoke.0/detox-20.14.0-smoke.0.pom.sha1 +1 -0
  19. package/Detox-android/com/wix/detox/20.14.0-smoke.0/detox-20.14.0-smoke.0.pom.sha256 +1 -0
  20. package/Detox-android/com/wix/detox/20.14.0-smoke.0/detox-20.14.0-smoke.0.pom.sha512 +1 -0
  21. package/Detox-android/com/wix/detox/maven-metadata.xml +4 -4
  22. package/Detox-android/com/wix/detox/maven-metadata.xml.md5 +1 -1
  23. package/Detox-android/com/wix/detox/maven-metadata.xml.sha1 +1 -1
  24. package/Detox-android/com/wix/detox/maven-metadata.xml.sha256 +1 -1
  25. package/Detox-android/com/wix/detox/maven-metadata.xml.sha512 +1 -1
  26. package/Detox-ios-src.tbz +0 -0
  27. package/Detox-ios.tbz +0 -0
  28. package/android/detox/src/full/java/com/wix/detox/ActivityLaunchHelper.kt +76 -0
  29. package/android/detox/src/full/java/com/wix/detox/Detox.java +8 -64
  30. package/android/detox/src/full/java/com/wix/detox/DetoxMain.kt +58 -16
  31. package/android/detox/src/full/java/com/wix/detox/LaunchIntentsFactory.kt +1 -1
  32. package/android/detox/src/full/java/com/wix/detox/adapters/server/DetoxActionHandlers.kt +15 -4
  33. package/android/detox/src/full/java/com/wix/detox/adapters/server/DetoxServerInfo.kt +4 -2
  34. package/android/detox/src/full/java/com/wix/detox/reactnative/ReactMarkersLogger.kt +44 -0
  35. package/android/detox/src/full/java/com/wix/detox/reactnative/ReactNativeExtension.kt +28 -21
  36. package/android/detox/src/main/java/com/wix/detox/espresso/UiControllerSpy.kt +0 -3
  37. package/local-cli/reset-lock-file.js +5 -9
  38. package/package.json +5 -6
  39. package/runners/jest/testEnvironment/index.js +1 -1
  40. package/src/DetoxWorker.js +5 -11
  41. package/src/android/espressoapi/Detox.js +0 -11
  42. package/src/artifacts/providers/index.js +3 -3
  43. package/src/artifacts/screenshot/SimulatorScreenshotPlugin.js +0 -17
  44. package/src/configuration/composeLoggerConfig.js +1 -0
  45. package/src/devices/allocation/DeviceAllocator.js +66 -20
  46. package/src/devices/allocation/DeviceList.js +44 -0
  47. package/src/devices/allocation/DeviceRegistry.js +189 -0
  48. package/src/devices/allocation/drivers/AllocationDriverBase.d.ts +15 -0
  49. package/src/devices/{common/drivers/android/tools → allocation/drivers/android}/FreeDeviceFinder.js +11 -10
  50. package/src/devices/allocation/drivers/android/attached/AttachedAndroidAllocDriver.js +22 -17
  51. package/src/devices/allocation/drivers/android/emulator/EmulatorAllocDriver.js +97 -38
  52. package/src/devices/allocation/drivers/android/emulator/EmulatorLauncher.js +32 -45
  53. package/src/devices/allocation/drivers/android/emulator/FreeEmulatorFinder.js +1 -1
  54. package/src/devices/allocation/drivers/android/emulator/FreePortFinder.js +37 -0
  55. package/src/devices/allocation/drivers/android/emulator/launchEmulatorProcess.js +3 -3
  56. package/src/devices/allocation/drivers/android/genycloud/GenyAllocDriver.js +104 -32
  57. package/src/devices/allocation/drivers/android/genycloud/GenyInstanceLauncher.js +40 -31
  58. package/src/devices/allocation/drivers/android/genycloud/GenyRegistry.js +121 -0
  59. package/src/devices/allocation/drivers/android/genycloud/services/GenyInstanceLifecycleService.js +24 -0
  60. package/src/devices/{common → allocation}/drivers/android/genycloud/services/GenyRecipesService.js +1 -1
  61. package/src/devices/allocation/drivers/android/genycloud/services/dto/GenyInstance.js +83 -0
  62. package/src/devices/allocation/drivers/android/genycloud/services/dto/GenyRecipe.js +25 -0
  63. package/src/devices/allocation/drivers/ios/SimulatorAllocDriver.js +94 -51
  64. package/src/devices/allocation/drivers/ios/SimulatorLauncher.js +11 -7
  65. package/src/devices/allocation/drivers/ios/SimulatorQuery.js +24 -0
  66. package/src/devices/allocation/factories/android.js +29 -35
  67. package/src/devices/allocation/factories/ios.js +7 -5
  68. package/src/devices/common/drivers/DeviceCookie.d.ts +12 -0
  69. package/src/devices/common/drivers/android/cookies.d.ts +11 -0
  70. package/src/devices/common/drivers/android/emulator/exec/EmulatorExec.js +17 -5
  71. package/src/devices/common/drivers/android/exec/ADB.js +1 -0
  72. package/src/devices/common/drivers/ios/cookies.d.ts +9 -0
  73. package/src/devices/cookies/index.js +0 -6
  74. package/src/devices/runtime/drivers/android/genycloud/GenyCloudDriver.js +7 -6
  75. package/src/devices/runtime/factories/android.js +3 -11
  76. package/src/devices/runtime/factories/ios.js +3 -2
  77. package/src/{servicelocator → devices/servicelocator}/android/emulatorServiceLocator.js +1 -1
  78. package/src/devices/servicelocator/android/genycloudServiceLocator.js +17 -0
  79. package/src/devices/servicelocator/android/index.js +23 -0
  80. package/src/{validation → devices/validation}/EnvironmentValidatorBase.js +1 -0
  81. package/src/{validation → devices/validation}/android/GenycloudEnvValidator.js +2 -2
  82. package/src/{validation → devices/validation}/factories/index.js +1 -1
  83. package/src/{validation → devices/validation}/ios/IosSimulatorEnvValidator.js +2 -2
  84. package/src/environmentFactory.js +1 -11
  85. package/src/ipc/IPCClient.js +17 -1
  86. package/src/ipc/IPCServer.js +27 -1
  87. package/src/logger/DetoxLogger.js +2 -2
  88. package/src/realms/DetoxContext.js +6 -0
  89. package/src/realms/DetoxPrimaryContext.js +42 -42
  90. package/src/realms/DetoxSecondaryContext.js +19 -0
  91. package/src/realms/symbols.js +4 -0
  92. package/src/utils/PIDService.js +27 -0
  93. package/src/utils/environment.js +8 -15
  94. package/src/utils/errorUtils.js +2 -2
  95. package/tsconfig.json +5 -3
  96. package/Detox-android/com/wix/detox/20.12.2/detox-20.12.2-javadoc.jar.md5 +0 -1
  97. package/Detox-android/com/wix/detox/20.12.2/detox-20.12.2-javadoc.jar.sha1 +0 -1
  98. package/Detox-android/com/wix/detox/20.12.2/detox-20.12.2-javadoc.jar.sha256 +0 -1
  99. package/Detox-android/com/wix/detox/20.12.2/detox-20.12.2-javadoc.jar.sha512 +0 -1
  100. package/Detox-android/com/wix/detox/20.12.2/detox-20.12.2-sources.jar.md5 +0 -1
  101. package/Detox-android/com/wix/detox/20.12.2/detox-20.12.2-sources.jar.sha1 +0 -1
  102. package/Detox-android/com/wix/detox/20.12.2/detox-20.12.2-sources.jar.sha256 +0 -1
  103. package/Detox-android/com/wix/detox/20.12.2/detox-20.12.2-sources.jar.sha512 +0 -1
  104. package/Detox-android/com/wix/detox/20.12.2/detox-20.12.2.aar +0 -0
  105. package/Detox-android/com/wix/detox/20.12.2/detox-20.12.2.aar.md5 +0 -1
  106. package/Detox-android/com/wix/detox/20.12.2/detox-20.12.2.aar.sha1 +0 -1
  107. package/Detox-android/com/wix/detox/20.12.2/detox-20.12.2.aar.sha256 +0 -1
  108. package/Detox-android/com/wix/detox/20.12.2/detox-20.12.2.aar.sha512 +0 -1
  109. package/Detox-android/com/wix/detox/20.12.2/detox-20.12.2.pom.md5 +0 -1
  110. package/Detox-android/com/wix/detox/20.12.2/detox-20.12.2.pom.sha1 +0 -1
  111. package/Detox-android/com/wix/detox/20.12.2/detox-20.12.2.pom.sha256 +0 -1
  112. package/Detox-android/com/wix/detox/20.12.2/detox-20.12.2.pom.sha512 +0 -1
  113. package/src/devices/DeviceRegistry.js +0 -176
  114. package/src/devices/allocation/drivers/AllocationDriverBase.js +0 -30
  115. package/src/devices/allocation/drivers/android/attached/AttachedAndroidLauncher.js +0 -13
  116. package/src/devices/allocation/drivers/android/emulator/EmulatorAllocationHelper.js +0 -72
  117. package/src/devices/allocation/drivers/android/genycloud/GenyDeviceRegistryFactory.js +0 -16
  118. package/src/devices/allocation/drivers/android/genycloud/GenyInstanceAllocationHelper.js +0 -65
  119. package/src/devices/common/drivers/DeviceAllocationHelper.js +0 -20
  120. package/src/devices/common/drivers/DeviceLauncher.js +0 -19
  121. package/src/devices/common/drivers/android/genycloud/services/GenyInstanceLifecycleService.js +0 -25
  122. package/src/devices/common/drivers/android/genycloud/services/GenyInstanceLookupService.js +0 -38
  123. package/src/devices/common/drivers/android/genycloud/services/GenyInstanceNaming.js +0 -14
  124. package/src/devices/common/drivers/android/genycloud/services/dto/GenyInstance.js +0 -66
  125. package/src/devices/common/drivers/android/genycloud/services/dto/GenyRecipe.js +0 -13
  126. package/src/devices/cookies/AndroidDeviceCookie.js +0 -13
  127. package/src/devices/cookies/AndroidEmulatorCookie.js +0 -6
  128. package/src/devices/cookies/AttachedAndroidDeviceCookie.js +0 -12
  129. package/src/devices/cookies/DeviceCookie.js +0 -4
  130. package/src/devices/cookies/GenycloudEmulatorCookie.js +0 -20
  131. package/src/devices/cookies/IosCookie.js +0 -6
  132. package/src/devices/cookies/IosSimulatorCookie.js +0 -10
  133. package/src/devices/lifecycle/GenyGlobalLifecycleHandler.js +0 -71
  134. package/src/devices/lifecycle/factories/GenyGlobalLifecycleHandlerFactory.js +0 -18
  135. package/src/servicelocator/android/genycloudServiceLocator.js +0 -21
  136. package/src/servicelocator/android/index.js +0 -25
  137. package/src/servicelocator/ios.js +0 -7
  138. /package/src/devices/{common → allocation}/drivers/android/genycloud/exec/GenyCloudExec.js +0 -0
  139. /package/src/devices/{common → allocation}/drivers/android/genycloud/services/GenyAuthService.js +0 -0
@@ -0,0 +1 @@
1
+ 0c2bae26c123edf10cb62b77d5e5acdd
@@ -0,0 +1 @@
1
+ 96b7351396c83931de86925d213b5bc9d12a827d
@@ -0,0 +1 @@
1
+ dbe5afc9df9a7c857a961781ebd58be8cf1d82c39771819b6c801f36b44434d4
@@ -0,0 +1 @@
1
+ 8e4f2278448ac644826386e11b95b24f44037c1483f0bae0c1347dfc0a01783e058f9b229b5d9e217f8be08984ff0035a8a9a028503f672f2baff523d3dc037c
@@ -0,0 +1 @@
1
+ 4db28745d12fb52a9b94eefe7aef7c6d
@@ -0,0 +1 @@
1
+ 5101597e82e164ba10f7ecd0e15ee7a4316fdccc
@@ -0,0 +1 @@
1
+ e7bc12d7cbefc0831194c059a2b62166bfda3a63e9e34d212418eed88155462f
@@ -0,0 +1 @@
1
+ 6cc5ce462ef6068c314ffa8d8a06d6c091b819baa7d3d1b329bd6a907e3c7909db097fac66381b3833bbfcb3bd1226f5c1e511cad080b1e2a3a914ff91af6f61
@@ -0,0 +1 @@
1
+ b8569c6d3b296face8b6d34037e27b6e
@@ -0,0 +1 @@
1
+ fe831778fa7fbeffb2ccdbb15bf3200ec0e641b2
@@ -0,0 +1 @@
1
+ 305c99310501d83ad114e4357d1af6efccf8ff774ec5ad25a04f7d9921203225
@@ -0,0 +1 @@
1
+ f02ad136e06b87c385b1ec7d8d9ad27259cdd2f9eec6dae79eb79eb9e7e78614b55bbb33773da61990ea5e594b0dff92c8013f5d3687c9c04710916e95d70418
@@ -3,7 +3,7 @@
3
3
  <modelVersion>4.0.0</modelVersion>
4
4
  <groupId>com.wix</groupId>
5
5
  <artifactId>detox</artifactId>
6
- <version>20.12.2</version>
6
+ <version>20.14.0-smoke.0</version>
7
7
  <packaging>aar</packaging>
8
8
  <name>Detox</name>
9
9
  <description>Gray box end-to-end testing and automation library for mobile apps</description>
@@ -0,0 +1 @@
1
+ 84130ea1d35084f1db1652765a011da8
@@ -0,0 +1 @@
1
+ 0dc75a3ca7a62dadea9abdd8c20d8cade91ff0ad
@@ -0,0 +1 @@
1
+ cc11f65f610d8f9cc708b0295e6998ee7e819ae7dc34d9f54586790ee253d4b2
@@ -0,0 +1 @@
1
+ 592a6a8c132c98bb7e7cb531ec495cb83bd4bc004fd8388f361199359c293d10169e9af1a771efd9d79db0e9e65d2dd75cb3d4aa9b32909c01dc561368165ea0
@@ -3,11 +3,11 @@
3
3
  <groupId>com.wix</groupId>
4
4
  <artifactId>detox</artifactId>
5
5
  <versioning>
6
- <latest>20.12.2</latest>
7
- <release>20.12.2</release>
6
+ <latest>20.14.0-smoke.0</latest>
7
+ <release>20.14.0-smoke.0</release>
8
8
  <versions>
9
- <version>20.12.2</version>
9
+ <version>20.14.0-smoke.0</version>
10
10
  </versions>
11
- <lastUpdated>20230927202100</lastUpdated>
11
+ <lastUpdated>20231004101112</lastUpdated>
12
12
  </versioning>
13
13
  </metadata>
@@ -1 +1 @@
1
- c4e29695a8333254dfdb58e83b723a94
1
+ db9bf329cefd7a3174b46ce70f497a99
@@ -1 +1 @@
1
- 8c90e83ee27dd4d9370742524f141054555c926b
1
+ 2166ac54d8a199afca7309e193e586480014f074
@@ -1 +1 @@
1
- 5fb1606470374345397232c3529c053c5aa26fd8650b3f7d9706f251a7f2e3b8
1
+ d872213b54196e083fdfac1b0f921ba338e96aa4d21e1971ac9f8e70cd20003c
@@ -1 +1 @@
1
- 541d2924f1ccdd6c901ba584a978d8d26ba3027c6abca381dcb6b2553b4b730ca428d6743bc9d1fe0836e2662a4e81f5d53049fa164376173e76960fcdc33ccc
1
+ 1ca24fd031e6a4bd8ac6197a4ff263b33a25a60b075291dac8ea33c8127623a8dbf65462f9e65d77ce493f1a2f07e09fbb5e9219e52e8ed457a3c293a86b118b
package/Detox-ios-src.tbz CHANGED
Binary file
package/Detox-ios.tbz CHANGED
Binary file
@@ -0,0 +1,76 @@
1
+ package com.wix.detox
2
+
3
+ import android.app.Instrumentation.ActivityMonitor
4
+ import android.content.Context
5
+ import android.content.Intent
6
+ import androidx.test.platform.app.InstrumentationRegistry
7
+ import androidx.test.rule.ActivityTestRule
8
+
9
+ class ActivityLaunchHelper(private val activityTestRule: ActivityTestRule<*>) {
10
+
11
+ private val launchArgs = LaunchArgs()
12
+ private val intentsFactory = LaunchIntentsFactory()
13
+
14
+ fun launchActivityUnderTest() {
15
+ val intent = extractInitialIntent()
16
+ activityTestRule.launchActivity(intent)
17
+ }
18
+
19
+ fun launchMainActivity() {
20
+ val activity = activityTestRule.activity
21
+ launchActivitySync(intentsFactory.activityLaunchIntent(activity))
22
+ }
23
+
24
+ fun startActivityFromUrl(url: String) {
25
+ launchActivitySync(intentsFactory.intentWithUrl(url, false))
26
+ }
27
+
28
+ fun startActivityFromNotification(dataFilePath: String) {
29
+ val notificationData = NotificationDataParser(dataFilePath!!).toBundle()
30
+ val intent = intentsFactory.intentWithNotificationData(appContext, notificationData, false)
31
+ launchActivitySync(intent)
32
+ }
33
+
34
+ private fun extractInitialIntent(): Intent =
35
+ if (launchArgs.hasUrlOverride()) {
36
+ intentsFactory.intentWithUrl(launchArgs.urlOverride, true)
37
+ } else if (launchArgs.hasNotificationPath()) {
38
+ val notificationData = NotificationDataParser(launchArgs.notificationPath).toBundle()
39
+ intentsFactory.intentWithNotificationData(appContext, notificationData, true)
40
+ } else {
41
+ intentsFactory.cleanIntent()
42
+ }.also {
43
+ it.putExtra(INTENT_LAUNCH_ARGS_KEY, launchArgs.asIntentBundle())
44
+ }
45
+
46
+ private fun launchActivitySync(intent: Intent) {
47
+ // Ideally, we would just call sActivityTestRule.launchActivity(intent) and get it over with.
48
+ // BUT!!! as it turns out, Espresso has an issue where doing this for an activity running in the background
49
+ // would have Espresso set up an ActivityMonitor which will spend its time waiting for the activity to load, *without
50
+ // ever being released*. It will finally fail after a 45 seconds timeout.
51
+ // Without going into full details, it seems that activity test rules were not meant to be used this way. However,
52
+ // the all-new ActivityScenario implementation introduced in androidx could probably support this (e.g. by using
53
+ // dedicated methods such as moveToState(), which give better control over the lifecycle).
54
+ // In any case, this is the core reason for this issue: https://github.com/wix/Detox/issues/1125
55
+ // What it forces us to do, then, is this -
56
+ // 1. Launch the activity by "ourselves" from the OS (i.e. using context.startActivity()).
57
+ // 2. Set up an activity monitor by ourselves -- such that it would block until the activity is ready.
58
+ // ^ Hence the code below.
59
+ val activity = activityTestRule.activity
60
+ val activityMonitor = ActivityMonitor(activity.javaClass.name, null, true)
61
+ activity.startActivity(intent)
62
+
63
+ InstrumentationRegistry.getInstrumentation().run {
64
+ addMonitor(activityMonitor)
65
+ waitForMonitorWithTimeout(activityMonitor, ACTIVITY_LAUNCH_TIMEOUT)
66
+ }
67
+ }
68
+
69
+ private val appContext: Context
70
+ get() = InstrumentationRegistry.getInstrumentation().targetContext.applicationContext
71
+
72
+ companion object {
73
+ private const val INTENT_LAUNCH_ARGS_KEY = "launchArgs"
74
+ private const val ACTIVITY_LAUNCH_TIMEOUT = 10000L
75
+ }
76
+ }
@@ -1,18 +1,13 @@
1
1
  package com.wix.detox;
2
2
 
3
- import android.app.Activity;
4
- import android.app.Instrumentation;
5
3
  import android.content.Context;
6
- import android.content.Intent;
7
- import android.os.Bundle;
8
-
9
- import com.wix.detox.config.DetoxConfig;
10
- import com.wix.detox.espresso.UiControllerSpy;
11
4
 
12
5
  import androidx.annotation.NonNull;
13
6
  import androidx.test.platform.app.InstrumentationRegistry;
14
7
  import androidx.test.rule.ActivityTestRule;
15
8
 
9
+ import com.wix.detox.config.DetoxConfig;
10
+
16
11
  /**
17
12
  * <p>Static class.</p>
18
13
  *
@@ -67,12 +62,7 @@ import androidx.test.rule.ActivityTestRule;
67
62
  * <p>If not set, then Detox tests are no ops. So it's safe to mix it with other tests.</p>
68
63
  */
69
64
  public final class Detox {
70
- private static final String INTENT_LAUNCH_ARGS_KEY = "launchArgs";
71
- private static final long ACTIVITY_LAUNCH_TIMEOUT = 10000L;
72
-
73
- private static final LaunchArgs sLaunchArgs = new LaunchArgs();
74
- private static final LaunchIntentsFactory sIntentsFactory = new LaunchIntentsFactory();
75
- private static ActivityTestRule sActivityTestRule;
65
+ private static ActivityLaunchHelper sActivityLaunchHelper;
76
66
 
77
67
  private Detox() {
78
68
  }
@@ -132,15 +122,10 @@ public final class Detox {
132
122
  DetoxConfig.CONFIG = detoxConfig;
133
123
  DetoxConfig.CONFIG.apply();
134
124
 
135
- sActivityTestRule = activityTestRule;
136
-
137
- UiControllerSpy.attachThroughProxy();
138
-
139
- Intent intent = extractInitialIntent();
140
- sActivityTestRule.launchActivity(intent);
125
+ sActivityLaunchHelper = new ActivityLaunchHelper(activityTestRule);
141
126
 
142
127
  try {
143
- DetoxMain.run(context);
128
+ DetoxMain.run(context, sActivityLaunchHelper);
144
129
  } catch (Exception e) {
145
130
  Thread.currentThread().interrupt();
146
131
  throw new RuntimeException("Detox got interrupted prematurely", e);
@@ -148,56 +133,15 @@ public final class Detox {
148
133
  }
149
134
 
150
135
  public static void launchMainActivity() {
151
- final Activity activity = sActivityTestRule.getActivity();
152
- launchActivitySync(sIntentsFactory.activityLaunchIntent(activity));
136
+ sActivityLaunchHelper.launchMainActivity();
153
137
  }
154
138
 
155
139
  public static void startActivityFromUrl(String url) {
156
- launchActivitySync(sIntentsFactory.intentWithUrl(url, false));
140
+ sActivityLaunchHelper.startActivityFromUrl(url);
157
141
  }
158
142
 
159
143
  public static void startActivityFromNotification(String dataFilePath) {
160
- Bundle notificationData = new NotificationDataParser(dataFilePath).toBundle();
161
- Intent intent = sIntentsFactory.intentWithNotificationData(getAppContext(), notificationData, false);
162
- launchActivitySync(intent);
163
- }
164
-
165
- private static Intent extractInitialIntent() {
166
- Intent intent;
167
-
168
- if (sLaunchArgs.hasUrlOverride()) {
169
- intent = sIntentsFactory.intentWithUrl(sLaunchArgs.getUrlOverride(), true);
170
- } else if (sLaunchArgs.hasNotificationPath()) {
171
- Bundle notificationData = new NotificationDataParser(sLaunchArgs.getNotificationPath()).toBundle();
172
- intent = sIntentsFactory.intentWithNotificationData(getAppContext(), notificationData, true);
173
- } else {
174
- intent = sIntentsFactory.cleanIntent();
175
- }
176
- intent.putExtra(INTENT_LAUNCH_ARGS_KEY, sLaunchArgs.asIntentBundle());
177
- return intent;
178
- }
179
-
180
- private static void launchActivitySync(Intent intent) {
181
- // Ideally, we would just call sActivityTestRule.launchActivity(intent) and get it over with.
182
- // BUT!!! as it turns out, Espresso has an issue where doing this for an activity running in the background
183
- // would have Espresso set up an ActivityMonitor which will spend its time waiting for the activity to load, *without
184
- // ever being released*. It will finally fail after a 45 seconds timeout.
185
- // Without going into full details, it seems that activity test rules were not meant to be used this way. However,
186
- // the all-new ActivityScenario implementation introduced in androidx could probably support this (e.g. by using
187
- // dedicated methods such as moveToState(), which give better control over the lifecycle).
188
- // In any case, this is the core reason for this issue: https://github.com/wix/Detox/issues/1125
189
- // What it forces us to do, then, is this -
190
- // 1. Launch the activity by "ourselves" from the OS (i.e. using context.startActivity()).
191
- // 2. Set up an activity monitor by ourselves -- such that it would block until the activity is ready.
192
- // ^ Hence the code below.
193
-
194
- final Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
195
- final Activity activity = sActivityTestRule.getActivity();
196
- final Instrumentation.ActivityMonitor activityMonitor = new Instrumentation.ActivityMonitor(activity.getClass().getName(), null, true);
197
-
198
- activity.startActivity(intent);
199
- instrumentation.addMonitor(activityMonitor);
200
- instrumentation.waitForMonitorWithTimeout(activityMonitor, ACTIVITY_LAUNCH_TIMEOUT);
144
+ sActivityLaunchHelper.startActivityFromNotification(dataFilePath);
201
145
  }
202
146
 
203
147
  private static Context getAppContext() {
@@ -2,8 +2,21 @@ package com.wix.detox
2
2
 
3
3
  import android.content.Context
4
4
  import android.util.Log
5
- import com.wix.detox.adapters.server.*
6
- import com.wix.detox.common.DetoxLog.Companion.LOG_TAG
5
+ import com.wix.detox.adapters.server.CleanupActionHandler
6
+ import com.wix.detox.adapters.server.DetoxActionHandler
7
+ import com.wix.detox.adapters.server.DetoxActionsDispatcher
8
+ import com.wix.detox.adapters.server.DetoxServerAdapter
9
+ import com.wix.detox.adapters.server.DetoxServerInfo
10
+ import com.wix.detox.adapters.server.InstrumentsEventsActionsHandler
11
+ import com.wix.detox.adapters.server.InstrumentsRecordingStateActionHandler
12
+ import com.wix.detox.adapters.server.InvokeActionHandler
13
+ import com.wix.detox.adapters.server.OutboundServerAdapter
14
+ import com.wix.detox.adapters.server.PrematureReadyHandler
15
+ import com.wix.detox.adapters.server.QueryStatusActionHandler
16
+ import com.wix.detox.adapters.server.ReactNativeReloadActionHandler
17
+ import com.wix.detox.adapters.server.ReadyActionHandler
18
+ import com.wix.detox.common.DetoxLog
19
+ import com.wix.detox.espresso.UiControllerSpy
7
20
  import com.wix.detox.instruments.DetoxInstrumentsManager
8
21
  import com.wix.detox.reactnative.ReactNativeExtension
9
22
  import com.wix.invoke.MethodInvocation
@@ -14,24 +27,28 @@ private const val TERMINATION_ACTION = "_terminate"
14
27
 
15
28
  object DetoxMain {
16
29
  @JvmStatic
17
- fun run(rnHostHolder: Context) {
30
+ fun run(rnHostHolder: Context, activityLaunchHelper: ActivityLaunchHelper) {
18
31
  val detoxServerInfo = DetoxServerInfo()
19
- Log.i(LOG_TAG, "Detox server connection details: $detoxServerInfo")
20
-
21
32
  val testEngineFacade = TestEngineFacade()
22
33
  val actionsDispatcher = DetoxActionsDispatcher()
23
34
  val externalAdapter = DetoxServerAdapter(actionsDispatcher, detoxServerInfo, IS_READY_ACTION, TERMINATION_ACTION)
24
- initActionHandlers(actionsDispatcher, externalAdapter, testEngineFacade, rnHostHolder)
35
+
36
+ initActionHandlers(activityLaunchHelper, actionsDispatcher, externalAdapter, testEngineFacade, rnHostHolder)
25
37
  actionsDispatcher.dispatchAction(INIT_ACTION, "", 0)
26
38
  actionsDispatcher.join()
27
39
  }
28
40
 
29
- private fun doInit(externalAdapter: DetoxServerAdapter, rnHostHolder: Context) {
30
- externalAdapter.connect()
31
-
41
+ private fun doInit(externalAdapter: DetoxServerAdapter) {
32
42
  initCrashHandler(externalAdapter)
33
43
  initANRListener(externalAdapter)
34
- initReactNativeIfNeeded(rnHostHolder)
44
+ initEspresso()
45
+ initReactNative()
46
+
47
+ externalAdapter.connect()
48
+ }
49
+
50
+ private fun onConnected(activityLaunchHelper: ActivityLaunchHelper, rnHostHolder: Context) {
51
+ launchApp(rnHostHolder, activityLaunchHelper)
35
52
  }
36
53
 
37
54
  private fun doTeardown(serverAdapter: DetoxServerAdapter, actionsDispatcher: DetoxActionsDispatcher, testEngineFacade: TestEngineFacade) {
@@ -41,20 +58,35 @@ object DetoxMain {
41
58
  actionsDispatcher.teardown()
42
59
  }
43
60
 
44
- private fun initActionHandlers(actionsDispatcher: DetoxActionsDispatcher, serverAdapter: DetoxServerAdapter, testEngineFacade: TestEngineFacade, rnHostHolder: Context) {
61
+ private fun initActionHandlers(activityLaunchHelper: ActivityLaunchHelper, actionsDispatcher: DetoxActionsDispatcher, serverAdapter: DetoxServerAdapter, testEngineFacade: TestEngineFacade, rnHostHolder: Context) {
45
62
  // Primary actions
46
63
  with(actionsDispatcher) {
64
+ var prematureIsReadyHandler: PrematureReadyHandler? = PrematureReadyHandler()
47
65
  val rnReloadHandler = ReactNativeReloadActionHandler(rnHostHolder, serverAdapter, testEngineFacade)
48
66
 
49
- associateActionHandler(INIT_ACTION, object : DetoxActionHandler {
67
+ associateActionHandler(INIT_ACTION, object: DetoxActionHandler {
50
68
  override fun handle(params: String, messageId: Long) =
51
69
  synchronized(this@DetoxMain) {
52
- this@DetoxMain.doInit(serverAdapter, rnHostHolder)
70
+ this@DetoxMain.doInit(serverAdapter)
53
71
  }
54
72
  })
55
- associateActionHandler(IS_READY_ACTION, ReadyActionHandler(serverAdapter, testEngineFacade))
73
+ associateActionHandler(IS_READY_ACTION, prematureIsReadyHandler!!)
56
74
 
57
- associateActionHandler("loginSuccess", ScarceActionHandler())
75
+ associateActionHandler("loginSuccess", object: DetoxActionHandler {
76
+ override fun handle(params: String, messageId: Long) {
77
+ synchronized(this@DetoxMain) {
78
+ this@DetoxMain.onConnected(activityLaunchHelper, rnHostHolder)
79
+ associateActionHandler(IS_READY_ACTION, ReadyActionHandler(serverAdapter, testEngineFacade))
80
+
81
+ prematureIsReadyHandler?.let {
82
+ if (it.isActionPending) {
83
+ actionsDispatcher.dispatchAction(IS_READY_ACTION, it.params!!, it.messageId!!)
84
+ }
85
+ prematureIsReadyHandler = null
86
+ }
87
+ }
88
+ }
89
+ })
58
90
  associateActionHandler("reactNativeReload", object: DetoxActionHandler {
59
91
  override fun handle(params: String, messageId: Long) =
60
92
  synchronized(this@DetoxMain) {
@@ -98,7 +130,17 @@ object DetoxMain {
98
130
  DetoxANRHandler(outboundServerAdapter).attach()
99
131
  }
100
132
 
101
- private fun initReactNativeIfNeeded(rnHostHolder: Context) {
133
+ private fun initEspresso() {
134
+ UiControllerSpy.attachThroughProxy()
135
+ }
136
+
137
+ private fun initReactNative() {
138
+ ReactNativeExtension.initIfNeeded()
139
+ }
140
+
141
+ private fun launchApp(rnHostHolder: Context, activityLaunchHelper: ActivityLaunchHelper) {
142
+ Log.i(DetoxLog.LOG_TAG, "Launching the tested activity!")
143
+ activityLaunchHelper.launchActivityUnderTest()
102
144
  ReactNativeExtension.waitForRNBootstrap(rnHostHolder)
103
145
  }
104
146
  }
@@ -6,7 +6,7 @@ import android.content.Intent
6
6
  import android.net.Uri
7
7
  import android.os.Bundle
8
8
 
9
- internal class LaunchIntentsFactory {
9
+ class LaunchIntentsFactory {
10
10
 
11
11
  /**
12
12
  * Constructs an intent tightly associated with a specific activity.
@@ -3,6 +3,7 @@ package com.wix.detox.adapters.server
3
3
  import android.content.Context
4
4
  import android.util.Log
5
5
  import com.wix.detox.TestEngineFacade
6
+ import com.wix.detox.common.DetoxLog
6
7
  import com.wix.detox.common.extractRootCause
7
8
  import com.wix.detox.instruments.DetoxInstrumentsException
8
9
  import com.wix.detox.instruments.DetoxInstrumentsManager
@@ -27,6 +28,20 @@ class ReadyActionHandler(
27
28
  }
28
29
  }
29
30
 
31
+ class PrematureReadyHandler(): DetoxActionHandler {
32
+ var isActionPending = false
33
+ var params: String? = null
34
+ var messageId: Long? = null
35
+
36
+ override fun handle(params: String, messageId: Long) {
37
+ Log.i(DetoxLog.LOG_TAG, "Got a premature ready action, saving for later...")
38
+
39
+ this.isActionPending = true
40
+ this.params = params
41
+ this.messageId = messageId
42
+ }
43
+ }
44
+
30
45
  open class ReactNativeReloadActionHandler(
31
46
  private val appContext: Context,
32
47
  private val outboundServerAdapter: OutboundServerAdapter,
@@ -152,7 +167,3 @@ class InstrumentsEventsActionsHandler(
152
167
  outboundServerAdapter.sendMessage("eventDone", emptyMap<String, Any>(), messageId)
153
168
  }
154
169
  }
155
-
156
- class ScarceActionHandler: DetoxActionHandler {
157
- override fun handle(params: String, messageId: Long) {}
158
- }
@@ -1,7 +1,9 @@
1
1
  package com.wix.detox.adapters.server
2
2
 
3
+ import android.util.Log
3
4
  import androidx.test.platform.app.InstrumentationRegistry
4
5
  import com.wix.detox.LaunchArgs
6
+ import com.wix.detox.common.DetoxLog
5
7
 
6
8
  private const val DEFAULT_URL = "ws://localhost:8099"
7
9
 
@@ -9,7 +11,7 @@ class DetoxServerInfo internal constructor(launchArgs: LaunchArgs = LaunchArgs()
9
11
  val serverUrl: String = launchArgs.detoxServerUrl ?: DEFAULT_URL
10
12
  val sessionId: String = launchArgs.detoxSessionId ?: InstrumentationRegistry.getInstrumentation().targetContext.applicationInfo.packageName
11
13
 
12
- override fun toString(): String {
13
- return "url=$serverUrl, sessionId=$sessionId"
14
+ init {
15
+ Log.i(DetoxLog.LOG_TAG, "Detox server connection details: url=$serverUrl, sessionId=$sessionId")
14
16
  }
15
17
  }
@@ -0,0 +1,44 @@
1
+ package com.wix.detox.reactnative
2
+
3
+ import android.util.Log
4
+ import com.facebook.react.bridge.ReactMarker
5
+ import com.facebook.react.bridge.ReactMarkerConstants
6
+ import com.facebook.react.bridge.ReactMarkerConstants.*
7
+
8
+ object ReactMarkersLogger : ReactMarker.MarkerListener {
9
+
10
+ fun attach() {
11
+ ReactMarker.addListener(this)
12
+ }
13
+
14
+ override fun logMarker(marker: ReactMarkerConstants, p1: String?, p2: Int) {
15
+ when {
16
+ marker == DOWNLOAD_START ||
17
+ marker == DOWNLOAD_END ||
18
+ marker == BUILD_REACT_INSTANCE_MANAGER_START ||
19
+ marker == BUILD_REACT_INSTANCE_MANAGER_END ||
20
+ marker == REACT_BRIDGE_LOADING_START ||
21
+ marker == REACT_BRIDGE_LOADING_END ||
22
+ marker == REACT_BRIDGELESS_LOADING_START ||
23
+ marker == REACT_BRIDGELESS_LOADING_END ||
24
+ marker == CREATE_MODULE_START ||
25
+ marker == CREATE_MODULE_END ||
26
+ marker == NATIVE_MODULE_SETUP_START ||
27
+ marker == NATIVE_MODULE_SETUP_END ||
28
+ marker == PRE_RUN_JS_BUNDLE_START ||
29
+ marker == RUN_JS_BUNDLE_START ||
30
+ marker == RUN_JS_BUNDLE_END ||
31
+ marker == CONTENT_APPEARED ||
32
+ marker == CREATE_CATALYST_INSTANCE_START ||
33
+ marker == CREATE_CATALYST_INSTANCE_END ||
34
+ marker == DESTROY_CATALYST_INSTANCE_START ||
35
+ marker == DESTROY_CATALYST_INSTANCE_END ||
36
+ marker == CREATE_REACT_CONTEXT_START ||
37
+ marker == CREATE_REACT_CONTEXT_END ||
38
+ marker == PROCESS_PACKAGES_START ||
39
+ marker == PROCESS_PACKAGES_END ||
40
+ false ->
41
+ Log.d("Detox.RNMarker", "$marker ($p1)")
42
+ }
43
+ }
44
+ }
@@ -14,6 +14,32 @@ private const val LOG_TAG = "DetoxRNExt"
14
14
  object ReactNativeExtension {
15
15
  private var rnIdlingResources: ReactNativeIdlingResources? = null
16
16
 
17
+ fun initIfNeeded() {
18
+ if (!ReactNativeInfo.isReactNativeApp()) {
19
+ return
20
+ }
21
+
22
+ ReactMarkersLogger.attach()
23
+ }
24
+
25
+ /**
26
+ * Wait for React-Native to finish loading (i.e. make RN context available).
27
+ *
28
+ * @param applicationContext The app context, implicitly assumed to be a [ReactApplication] instance.
29
+ */
30
+ fun waitForRNBootstrap(applicationContext: Context) {
31
+ if (!ReactNativeInfo.isReactNativeApp()) {
32
+ return
33
+ }
34
+
35
+ (applicationContext as ReactApplication).let {
36
+ val reactContext = awaitNewReactNativeContext(it, null)
37
+
38
+ enableOrDisableSynchronization(reactContext)
39
+ hackRN50WaitForReady()
40
+ }
41
+ }
42
+
17
43
  /**
18
44
  * Reloads the React Native context and thus all javascript code.
19
45
  *
@@ -40,26 +66,7 @@ object ReactNativeExtension {
40
66
  val reactContext = awaitNewReactNativeContext(it, previousReactContext)
41
67
 
42
68
  enableOrDisableSynchronization(reactContext, networkSyncEnabled)
43
- hackRN50OrHigherWaitForReady()
44
- }
45
- }
46
-
47
- /**
48
- * Wait for React-Native to finish loading (i.e. make RN context available).
49
- *
50
- * @param applicationContext The app context, implicitly assumed to be a [ReactApplication] instance.
51
- */
52
- @JvmStatic
53
- fun waitForRNBootstrap(applicationContext: Context) {
54
- if (!ReactNativeInfo.isReactNativeApp()) {
55
- return
56
- }
57
-
58
- (applicationContext as ReactApplication).let {
59
- val reactContext = awaitNewReactNativeContext(it, null)
60
-
61
- enableOrDisableSynchronization(reactContext)
62
- hackRN50OrHigherWaitForReady()
69
+ hackRN50WaitForReady()
63
70
  }
64
71
  }
65
72
 
@@ -145,7 +152,7 @@ object ReactNativeExtension {
145
152
  }
146
153
  }
147
154
 
148
- private fun hackRN50OrHigherWaitForReady() {
155
+ private fun hackRN50WaitForReady() {
149
156
  if (ReactNativeInfo.rnVersion().minor in 50..62) {
150
157
  try {
151
158
  //TODO- Temp hack to make Detox usable for RN>=50 till we find a better sync solution.
@@ -11,11 +11,8 @@ class UiControllerSpy: MethodsSpy("uiController") {
11
11
  fun eventInjectionsIterator(): Iterator<CallInfo?> = historyOf("injectMotionEvent").iterator()
12
12
 
13
13
  companion object {
14
- @JvmStatic
15
14
  val instance = UiControllerSpy()
16
15
 
17
- @JvmStatic
18
- @JvmOverloads
19
16
  fun attachThroughProxy(spy: UiControllerSpy = instance) {
20
17
  val eventsInjectorReflected = EventsInjectorReflected(getUiController())
21
18
 
@@ -1,16 +1,12 @@
1
1
  const { log } = require('../internals');
2
- const DeviceRegistry = require('../src/devices/DeviceRegistry');
3
- const { getDetoxLibraryRootPath } = require('../src/utils/environment');
4
-
2
+ const DeviceRegistry = require('../src/devices/allocation/DeviceRegistry');
5
3
 
6
4
  module.exports.command = 'reset-lock-file';
7
- module.exports.desc = 'Resets all Detox lock files. Useful when you need to run multiple `detox test` commands in parallel with --keepLockFile.';
5
+ module.exports.desc = 'Resets Detox lock file completely - all devices are marked as available after that.';
8
6
 
9
7
  module.exports.handler = async function resetLockFile() {
10
- await Promise.all([
11
- DeviceRegistry.forIOS().reset(),
12
- DeviceRegistry.forAndroid().reset(),
13
- ]);
8
+ const registry = new DeviceRegistry();
9
+ await registry.reset();
14
10
 
15
- log.info(`Cleaned lock files from: ${getDetoxLibraryRootPath()}`);
11
+ log.info(`Cleaned lock file at: ${registry.lockFilePath}`);
16
12
  };