detox 20.11.5-smoke.0 → 20.12.0-smoke.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (145) hide show
  1. package/Detox-android/com/wix/detox/{20.11.5-smoke.0/detox-20.11.5-smoke.0-javadoc.jar → 20.12.0-smoke.1/detox-20.12.0-smoke.1-javadoc.jar} +0 -0
  2. package/Detox-android/com/wix/detox/20.12.0-smoke.1/detox-20.12.0-smoke.1-javadoc.jar.md5 +1 -0
  3. package/Detox-android/com/wix/detox/20.12.0-smoke.1/detox-20.12.0-smoke.1-javadoc.jar.sha1 +1 -0
  4. package/Detox-android/com/wix/detox/20.12.0-smoke.1/detox-20.12.0-smoke.1-javadoc.jar.sha256 +1 -0
  5. package/Detox-android/com/wix/detox/20.12.0-smoke.1/detox-20.12.0-smoke.1-javadoc.jar.sha512 +1 -0
  6. package/Detox-android/com/wix/detox/{20.11.5-smoke.0/detox-20.11.5-smoke.0-sources.jar → 20.12.0-smoke.1/detox-20.12.0-smoke.1-sources.jar} +0 -0
  7. package/Detox-android/com/wix/detox/20.12.0-smoke.1/detox-20.12.0-smoke.1-sources.jar.md5 +1 -0
  8. package/Detox-android/com/wix/detox/20.12.0-smoke.1/detox-20.12.0-smoke.1-sources.jar.sha1 +1 -0
  9. package/Detox-android/com/wix/detox/20.12.0-smoke.1/detox-20.12.0-smoke.1-sources.jar.sha256 +1 -0
  10. package/Detox-android/com/wix/detox/20.12.0-smoke.1/detox-20.12.0-smoke.1-sources.jar.sha512 +1 -0
  11. package/Detox-android/com/wix/detox/20.12.0-smoke.1/detox-20.12.0-smoke.1.aar +0 -0
  12. package/Detox-android/com/wix/detox/20.12.0-smoke.1/detox-20.12.0-smoke.1.aar.md5 +1 -0
  13. package/Detox-android/com/wix/detox/20.12.0-smoke.1/detox-20.12.0-smoke.1.aar.sha1 +1 -0
  14. package/Detox-android/com/wix/detox/20.12.0-smoke.1/detox-20.12.0-smoke.1.aar.sha256 +1 -0
  15. package/Detox-android/com/wix/detox/20.12.0-smoke.1/detox-20.12.0-smoke.1.aar.sha512 +1 -0
  16. package/Detox-android/com/wix/detox/{20.11.5-smoke.0/detox-20.11.5-smoke.0.pom → 20.12.0-smoke.1/detox-20.12.0-smoke.1.pom} +1 -1
  17. package/Detox-android/com/wix/detox/20.12.0-smoke.1/detox-20.12.0-smoke.1.pom.md5 +1 -0
  18. package/Detox-android/com/wix/detox/20.12.0-smoke.1/detox-20.12.0-smoke.1.pom.sha1 +1 -0
  19. package/Detox-android/com/wix/detox/20.12.0-smoke.1/detox-20.12.0-smoke.1.pom.sha256 +1 -0
  20. package/Detox-android/com/wix/detox/20.12.0-smoke.1/detox-20.12.0-smoke.1.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/espresso/DetoxAssertion.java +44 -25
  29. package/android/detox/src/full/java/com/wix/detox/espresso/EspressoDetox.java +6 -7
  30. package/android/detox/src/full/java/com/wix/detox/espresso/action/GetAttributesAction.kt +4 -4
  31. package/android/detox/src/full/java/com/wix/detox/espresso/performer/MultipleViewsActionPerformer.kt +43 -0
  32. package/android/detox/src/full/java/com/wix/detox/espresso/performer/SingleViewActionPerformer.kt +19 -0
  33. package/android/detox/src/full/java/com/wix/detox/espresso/performer/ViewActionPerformer.kt +24 -0
  34. package/android/detox/src/full/java/com/wix/invoke/types/Invocation.java +5 -4
  35. package/android/detox/src/main/java/com/wix/detox/espresso/MultipleViewsAction.kt +4 -0
  36. package/android/detox/src/main/java/com/wix/detox/espresso/UiControllerSpy.kt +0 -1
  37. package/android/detox/src/main/java/com/wix/detox/espresso/ViewActionWithResult.kt +2 -1
  38. package/android/detox/src/testFull/java/com/wix/detox/espresso/action/GetAttributesActionTest.kt +6 -5
  39. package/android/detox/src/testFull/java/com/wix/detox/espresso/performer/ViewActionPerformerSpec.kt +37 -0
  40. package/index.d.ts +47 -3
  41. package/local-cli/reset-lock-file.js +5 -9
  42. package/package.json +6 -6
  43. package/runners/jest/testEnvironment/index.js +1 -0
  44. package/src/DetoxWorker.js +5 -11
  45. package/src/android/core/NativeElement.js +26 -29
  46. package/src/android/espressoapi/DetoxAssertion.js +16 -14
  47. package/src/android/espressoapi/EspressoDetox.js +9 -2
  48. package/src/android/interactions/native.js +2 -3
  49. package/src/artifacts/providers/index.js +3 -3
  50. package/src/artifacts/screenshot/SimulatorScreenshotPlugin.js +0 -17
  51. package/src/configuration/composeLoggerConfig.js +1 -0
  52. package/src/devices/allocation/DeviceAllocator.js +66 -20
  53. package/src/devices/allocation/DeviceList.js +44 -0
  54. package/src/devices/allocation/DeviceRegistry.js +189 -0
  55. package/src/devices/allocation/drivers/AllocationDriverBase.d.ts +15 -0
  56. package/src/devices/{common/drivers/android/tools → allocation/drivers/android}/FreeDeviceFinder.js +11 -10
  57. package/src/devices/allocation/drivers/android/attached/AttachedAndroidAllocDriver.js +22 -17
  58. package/src/devices/allocation/drivers/android/emulator/EmulatorAllocDriver.js +97 -38
  59. package/src/devices/allocation/drivers/android/emulator/EmulatorLauncher.js +32 -45
  60. package/src/devices/allocation/drivers/android/emulator/FreeEmulatorFinder.js +1 -1
  61. package/src/devices/allocation/drivers/android/emulator/FreePortFinder.js +16 -0
  62. package/src/devices/allocation/drivers/android/emulator/launchEmulatorProcess.js +3 -3
  63. package/src/devices/allocation/drivers/android/genycloud/GenyAllocDriver.js +104 -32
  64. package/src/devices/allocation/drivers/android/genycloud/GenyInstanceLauncher.js +40 -31
  65. package/src/devices/allocation/drivers/android/genycloud/GenyRegistry.js +121 -0
  66. package/src/devices/allocation/drivers/android/genycloud/services/GenyInstanceLifecycleService.js +24 -0
  67. package/src/devices/{common → allocation}/drivers/android/genycloud/services/GenyRecipesService.js +1 -1
  68. package/src/devices/{common → allocation}/drivers/android/genycloud/services/dto/GenyInstance.js +6 -1
  69. package/src/devices/allocation/drivers/ios/SimulatorAllocDriver.js +94 -51
  70. package/src/devices/allocation/drivers/ios/SimulatorLauncher.js +11 -7
  71. package/src/devices/allocation/drivers/ios/SimulatorQuery.js +24 -0
  72. package/src/devices/allocation/factories/android.js +29 -35
  73. package/src/devices/allocation/factories/ios.js +7 -5
  74. package/src/devices/common/drivers/DeviceCookie.d.ts +12 -0
  75. package/src/devices/common/drivers/android/cookies.d.ts +11 -0
  76. package/src/devices/common/drivers/android/emulator/exec/EmulatorExec.js +17 -5
  77. package/src/devices/common/drivers/android/exec/ADB.js +1 -0
  78. package/src/devices/common/drivers/ios/cookies.d.ts +9 -0
  79. package/src/devices/common/drivers/ios/tools/AppleSimUtils.js +2 -0
  80. package/src/devices/cookies/index.js +0 -6
  81. package/src/devices/runtime/drivers/android/genycloud/GenyCloudDriver.js +7 -6
  82. package/src/devices/runtime/factories/android.js +3 -11
  83. package/src/devices/runtime/factories/ios.js +3 -2
  84. package/src/{servicelocator → devices/servicelocator}/android/emulatorServiceLocator.js +1 -1
  85. package/src/devices/servicelocator/android/genycloudServiceLocator.js +17 -0
  86. package/src/devices/servicelocator/android/index.js +23 -0
  87. package/src/{validation → devices/validation}/EnvironmentValidatorBase.js +1 -0
  88. package/src/{validation → devices/validation}/android/GenycloudEnvValidator.js +2 -2
  89. package/src/{validation → devices/validation}/factories/index.js +1 -1
  90. package/src/{validation → devices/validation}/ios/IosSimulatorEnvValidator.js +2 -2
  91. package/src/environmentFactory.js +1 -11
  92. package/src/ipc/IPCClient.js +17 -1
  93. package/src/ipc/IPCServer.js +27 -1
  94. package/src/logger/DetoxLogger.js +2 -2
  95. package/src/realms/DetoxContext.js +6 -0
  96. package/src/realms/DetoxPrimaryContext.js +42 -42
  97. package/src/realms/DetoxSecondaryContext.js +19 -0
  98. package/src/realms/symbols.js +4 -0
  99. package/src/utils/PIDService.js +27 -0
  100. package/src/utils/environment.js +8 -15
  101. package/src/utils/errorUtils.js +3 -3
  102. package/tsconfig.json +5 -3
  103. package/Detox-android/com/wix/detox/20.11.5-smoke.0/detox-20.11.5-smoke.0-javadoc.jar.md5 +0 -1
  104. package/Detox-android/com/wix/detox/20.11.5-smoke.0/detox-20.11.5-smoke.0-javadoc.jar.sha1 +0 -1
  105. package/Detox-android/com/wix/detox/20.11.5-smoke.0/detox-20.11.5-smoke.0-javadoc.jar.sha256 +0 -1
  106. package/Detox-android/com/wix/detox/20.11.5-smoke.0/detox-20.11.5-smoke.0-javadoc.jar.sha512 +0 -1
  107. package/Detox-android/com/wix/detox/20.11.5-smoke.0/detox-20.11.5-smoke.0-sources.jar.md5 +0 -1
  108. package/Detox-android/com/wix/detox/20.11.5-smoke.0/detox-20.11.5-smoke.0-sources.jar.sha1 +0 -1
  109. package/Detox-android/com/wix/detox/20.11.5-smoke.0/detox-20.11.5-smoke.0-sources.jar.sha256 +0 -1
  110. package/Detox-android/com/wix/detox/20.11.5-smoke.0/detox-20.11.5-smoke.0-sources.jar.sha512 +0 -1
  111. package/Detox-android/com/wix/detox/20.11.5-smoke.0/detox-20.11.5-smoke.0.aar +0 -0
  112. package/Detox-android/com/wix/detox/20.11.5-smoke.0/detox-20.11.5-smoke.0.aar.md5 +0 -1
  113. package/Detox-android/com/wix/detox/20.11.5-smoke.0/detox-20.11.5-smoke.0.aar.sha1 +0 -1
  114. package/Detox-android/com/wix/detox/20.11.5-smoke.0/detox-20.11.5-smoke.0.aar.sha256 +0 -1
  115. package/Detox-android/com/wix/detox/20.11.5-smoke.0/detox-20.11.5-smoke.0.aar.sha512 +0 -1
  116. package/Detox-android/com/wix/detox/20.11.5-smoke.0/detox-20.11.5-smoke.0.pom.md5 +0 -1
  117. package/Detox-android/com/wix/detox/20.11.5-smoke.0/detox-20.11.5-smoke.0.pom.sha1 +0 -1
  118. package/Detox-android/com/wix/detox/20.11.5-smoke.0/detox-20.11.5-smoke.0.pom.sha256 +0 -1
  119. package/Detox-android/com/wix/detox/20.11.5-smoke.0/detox-20.11.5-smoke.0.pom.sha512 +0 -1
  120. package/src/devices/DeviceRegistry.js +0 -176
  121. package/src/devices/allocation/drivers/AllocationDriverBase.js +0 -30
  122. package/src/devices/allocation/drivers/android/attached/AttachedAndroidLauncher.js +0 -13
  123. package/src/devices/allocation/drivers/android/emulator/EmulatorAllocationHelper.js +0 -72
  124. package/src/devices/allocation/drivers/android/genycloud/GenyDeviceRegistryFactory.js +0 -16
  125. package/src/devices/allocation/drivers/android/genycloud/GenyInstanceAllocationHelper.js +0 -65
  126. package/src/devices/common/drivers/DeviceAllocationHelper.js +0 -20
  127. package/src/devices/common/drivers/DeviceLauncher.js +0 -19
  128. package/src/devices/common/drivers/android/genycloud/services/GenyInstanceLifecycleService.js +0 -25
  129. package/src/devices/common/drivers/android/genycloud/services/GenyInstanceLookupService.js +0 -38
  130. package/src/devices/common/drivers/android/genycloud/services/GenyInstanceNaming.js +0 -14
  131. package/src/devices/cookies/AndroidDeviceCookie.js +0 -13
  132. package/src/devices/cookies/AndroidEmulatorCookie.js +0 -6
  133. package/src/devices/cookies/AttachedAndroidDeviceCookie.js +0 -12
  134. package/src/devices/cookies/DeviceCookie.js +0 -4
  135. package/src/devices/cookies/GenycloudEmulatorCookie.js +0 -20
  136. package/src/devices/cookies/IosCookie.js +0 -6
  137. package/src/devices/cookies/IosSimulatorCookie.js +0 -10
  138. package/src/devices/lifecycle/GenyGlobalLifecycleHandler.js +0 -71
  139. package/src/devices/lifecycle/factories/GenyGlobalLifecycleHandlerFactory.js +0 -18
  140. package/src/servicelocator/android/genycloudServiceLocator.js +0 -21
  141. package/src/servicelocator/android/index.js +0 -25
  142. package/src/servicelocator/ios.js +0 -7
  143. /package/src/devices/{common → allocation}/drivers/android/genycloud/exec/GenyCloudExec.js +0 -0
  144. /package/src/devices/{common → allocation}/drivers/android/genycloud/services/GenyAuthService.js +0 -0
  145. /package/src/devices/{common → allocation}/drivers/android/genycloud/services/dto/GenyRecipe.js +0 -0
@@ -0,0 +1 @@
1
+ edebe5e1a9db02c850b397c9bdae7c35
@@ -0,0 +1 @@
1
+ c11caea2687f5baf236d0b2268f4aab0fcd68813
@@ -0,0 +1 @@
1
+ 86c25ba9696844850bfc3d6b71b759955e64f8b581629930f613578138fde286
@@ -0,0 +1 @@
1
+ 41808b7ca13752c7c3e15e039f99cf7575f93f904179af2d88d79214bb428f1c81e9ddba2517f45f9c00fbd5163827b3e48e19e9e905243278531ef5f33f2f12
@@ -0,0 +1 @@
1
+ 9ef9088ef1d6cfd2b0988f9cee1c4424
@@ -0,0 +1 @@
1
+ 11098a07f999964bd82bb113fc74da517af629d3
@@ -0,0 +1 @@
1
+ 7c6310b102e8863703277d0698eb1ffec1abe22f81129c981576bfb51ba0da48
@@ -0,0 +1 @@
1
+ eec9403b4f9360afa3e7c2848ba3c47cc9b63892cbe4f0f9e705a344c7a2deae1ed950f652b493a0403f717ceb6271b1baa4121dabf97b44ece3462b7895aba5
@@ -0,0 +1 @@
1
+ c90cc85230997f3663da1741d1eabc0e
@@ -0,0 +1 @@
1
+ 0e17ccf18dbb2e0295e72b77cae67275591d956a
@@ -0,0 +1 @@
1
+ 00528b5d136df63bc93f55c2f890a1ad69179f341663310b520227f6b7aad63b
@@ -0,0 +1 @@
1
+ 37984e2491685ede0325d74f460ad2a13dc55bd906124e0932fa09e29e2394a91cbbf691aa854848503113f04dfe148a483e616c736918f6e0077af6aa311a31
@@ -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.11.5-smoke.0</version>
6
+ <version>20.12.0-smoke.1</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
+ 7849840b7e2d8078632fff04e8848c49
@@ -0,0 +1 @@
1
+ 5c35960d1a3b4d96819fbbd6f87e289c9602d099
@@ -0,0 +1 @@
1
+ 8121e46423a2a98094b21a1ace9c74d4700390c900c3f55554c0028c9ba742b0
@@ -0,0 +1 @@
1
+ 46b33643dde55e7a1ecc453b77a3ef62abaea450b07babe9e6cbe880bea191609ccfeb942c33baa899d8a6ed3c9a68ce089521da1fb975168a6e789f1a3b6503
@@ -3,11 +3,11 @@
3
3
  <groupId>com.wix</groupId>
4
4
  <artifactId>detox</artifactId>
5
5
  <versioning>
6
- <latest>20.11.5-smoke.0</latest>
7
- <release>20.11.5-smoke.0</release>
6
+ <latest>20.12.0-smoke.1</latest>
7
+ <release>20.12.0-smoke.1</release>
8
8
  <versions>
9
- <version>20.11.5-smoke.0</version>
9
+ <version>20.12.0-smoke.1</version>
10
10
  </versions>
11
- <lastUpdated>20230830102548</lastUpdated>
11
+ <lastUpdated>20230920124201</lastUpdated>
12
12
  </versioning>
13
13
  </metadata>
@@ -1 +1 @@
1
- b66fe11b8db07e94d8899e61497ff262
1
+ b116f9a1d3518254a3f1b9f5207e9e34
@@ -1 +1 @@
1
- 5c083ffc3dc0b459da472f94acdf213e32320a29
1
+ 2dbf825c56bf137f96116e3502283796bcdc9562
@@ -1 +1 @@
1
- 2572bcdd8effd233f1ffe93cf27906f4fc2efeac59f00fa2b90bc687051c0c77
1
+ 33a56406ef8b07c398f97ce50ae6f130090e619de1b2a08ca18d6c9cc67a944e
@@ -1 +1 @@
1
- ca1b38083670c2cc34bdf67a3a032c0a89f9fb6f6ff766571af6048fc02661013619eeb87817d430933aea0aa149c29396973bd432182f30dab31536dbe186eb
1
+ 6e0c6c1c5d037648ef85ebac578dc0ca51165550c08f89a41741643a1b75d5fb3c180973481a4cbd53893d50731bfa91aef1697a8ec803aeb0c1aff04e1ac90c
package/Detox-ios-src.tbz CHANGED
Binary file
package/Detox-ios.tbz CHANGED
Binary file
@@ -24,42 +24,57 @@ import static org.hamcrest.Matchers.not;
24
24
 
25
25
  public class DetoxAssertion {
26
26
 
27
+ private static final double NANOSECONDS_IN_A_SECOND = 1_000_000_000.0;
28
+
27
29
  private DetoxAssertion() {
28
- // static class
30
+ // This is a utility class and shouldn't be instantiated.
29
31
  }
30
32
 
31
- public static ViewInteraction assertMatcher(ViewInteraction i, Matcher<View> m) {
32
- return i.check(matches(m));
33
+ /**
34
+ * Asserts the given matcher for the provided view interaction.
35
+ */
36
+ public static ViewInteraction assertMatcher(ViewInteraction viewInteraction, Matcher<View> viewMatcher) {
37
+ return viewInteraction.check(matches(viewMatcher));
33
38
  }
34
39
 
35
- public static ViewInteraction assertNotVisible(ViewInteraction i) {
36
- ViewInteraction ret;
40
+ /**
41
+ * Asserts that the given view interaction is not visible.
42
+ */
43
+ public static ViewInteraction assertNotVisible(ViewInteraction viewInteraction) {
44
+ ViewInteraction result;
37
45
  try {
38
- ret = i.check(doesNotExist());
39
- return ret;
46
+ result = viewInteraction.check(doesNotExist());
47
+ return result;
40
48
  } catch (AssertionFailedError e) {
41
- ret = i.check(matches(not(isDisplayed())));
42
- return ret;
49
+ result = viewInteraction.check(matches(not(isDisplayed())));
50
+ return result;
43
51
  }
44
52
  }
45
53
 
46
- public static ViewInteraction assertNotExists(ViewInteraction i) {
47
- return i.check(doesNotExist());
54
+ /**
55
+ * Asserts that the given view interaction does not exist.
56
+ */
57
+ public static ViewInteraction assertNotExists(ViewInteraction viewInteraction) {
58
+ return viewInteraction.check(doesNotExist());
48
59
  }
49
60
 
50
- public static void waitForAssertMatcher(final ViewInteraction i, final Matcher<View> m, double timeoutSeconds) {
51
- final long originTime = System.nanoTime();
61
+ /**
62
+ * Waits until the provided matcher matches the view interaction or a timeout occurs.
63
+ */
64
+ public static void waitForAssertMatcher(final ViewInteraction viewInteraction, final Matcher<View> viewMatcher, double timeoutSeconds) {
65
+ final long startTime = System.nanoTime();
52
66
 
53
67
  while (true) {
54
68
  long currentTime = System.nanoTime();
55
- long elapsed = currentTime - originTime;
56
- double seconds = (double) elapsed / 1000000000.0;
57
- if (seconds >= timeoutSeconds) {
58
- throw new DetoxRuntimeException("" + timeoutSeconds + "sec timeout expired without matching of given matcher: " + m);
69
+ long elapsedTime = currentTime - startTime;
70
+ double elapsedSeconds = (double) elapsedTime / NANOSECONDS_IN_A_SECOND;
71
+ if (elapsedSeconds >= timeoutSeconds) {
72
+ throw new DetoxRuntimeException(
73
+ "" + timeoutSeconds + "sec timeout expired without matching of given matcher: " + viewMatcher);
59
74
  }
60
75
 
61
76
  try {
62
- i.check(matches(m));
77
+ viewInteraction.check(matches(viewMatcher));
63
78
  break;
64
79
  } catch (AssertionFailedError err) {
65
80
  UiAutomatorHelper.espressoSync(20);
@@ -67,21 +82,25 @@ public class DetoxAssertion {
67
82
  }
68
83
  }
69
84
 
85
+ /**
86
+ * Continually asserts the provided matcher until a search action returns a matching view or a
87
+ * `StaleActionException` error is thrown.
88
+ */
70
89
  public static void waitForAssertMatcherWithSearchAction(
71
- final ViewInteraction i,
72
- final Matcher<View> vm,
73
- final ViewAction searchAction,
74
- final Matcher<View> searchMatcher) {
75
-
90
+ final ViewInteraction viewInteraction,
91
+ final Matcher<View> viewMatcher,
92
+ final ViewAction searchAction,
93
+ final Matcher<View> searchMatcher
94
+ ) {
76
95
  while (true) {
77
96
  try {
78
- assertMatcher(i, vm);
97
+ assertMatcher(viewInteraction, viewMatcher);
79
98
  break;
80
99
  } catch (AssertionFailedError err) {
81
100
  try {
82
101
  onView(searchMatcher).perform(searchAction);
83
102
  } catch (StaleActionException exStaleAction) {
84
- assertMatcher(i, vm);
103
+ assertMatcher(viewInteraction, viewMatcher);
85
104
  break;
86
105
  }
87
106
  }
@@ -1,5 +1,7 @@
1
1
  package com.wix.detox.espresso;
2
2
 
3
+ import com.wix.detox.espresso.performer.ViewActionPerformer;
4
+
3
5
  import android.app.Activity;
4
6
  import android.content.Context;
5
7
  import android.content.ContextWrapper;
@@ -20,6 +22,7 @@ import java.util.ArrayList;
20
22
  import androidx.test.espresso.UiController;
21
23
  import androidx.test.espresso.ViewAction;
22
24
  import androidx.test.espresso.ViewInteraction;
25
+ import androidx.test.espresso.NoMatchingViewException;
23
26
  import androidx.test.platform.app.InstrumentationRegistry;
24
27
 
25
28
  import static androidx.test.espresso.Espresso.onView;
@@ -31,13 +34,9 @@ import static androidx.test.espresso.matcher.ViewMatchers.isRoot;
31
34
  public class EspressoDetox {
32
35
  private static final String LOG_TAG = "detox";
33
36
 
34
- public static Object perform(ViewInteraction interaction, ViewAction action) {
35
- interaction.perform(action);
36
-
37
- if (action instanceof ViewActionWithResult) {
38
- return ((ViewActionWithResult) action).getResult();
39
- }
40
- return null;
37
+ public static Object perform(Matcher<View> matcher, ViewAction action) {
38
+ ViewActionPerformer performer = ViewActionPerformer.forAction(action);
39
+ return performer.performOn(matcher);
41
40
  }
42
41
 
43
42
  public static Activity getActivity(Context context) {
@@ -9,6 +9,7 @@ import android.widget.TextView
9
9
  import androidx.test.espresso.UiController
10
10
  import com.google.android.material.slider.Slider
11
11
  import com.wix.detox.espresso.ViewActionWithResult
12
+ import com.wix.detox.espresso.MultipleViewsAction
12
13
  import com.wix.detox.espresso.common.SliderHelper
13
14
  import com.wix.detox.reactnative.ui.getAccessibilityLabel
14
15
  import org.hamcrest.Matcher
@@ -17,26 +18,25 @@ import org.hamcrest.Matchers.allOf
17
18
  import org.hamcrest.Matchers.notNullValue
18
19
  import org.json.JSONObject
19
20
 
20
- class GetAttributesAction() : ViewActionWithResult<String?> {
21
+ class GetAttributesAction() : ViewActionWithResult<JSONObject?>, MultipleViewsAction {
21
22
  private val commonAttributes = CommonAttributes()
22
23
  private val textViewAttributes = TextViewAttributes()
23
24
  private val checkBoxAttributes = CheckBoxAttributes()
24
25
  private val progressBarAttributes = ProgressBarAttributes()
25
26
  private val sliderAttributes = SliderAttributes()
26
- private var result: String = ""
27
+ private var result: JSONObject? = null
27
28
 
28
29
  override fun perform(uiController: UiController?, view: View?) {
29
30
  view!!
30
31
 
31
32
  val json = JSONObject()
32
-
33
33
  commonAttributes.get(json, view)
34
34
  textViewAttributes.get(json, view)
35
35
  checkBoxAttributes.get(json, view)
36
36
  progressBarAttributes.get(json, view)
37
37
  sliderAttributes.get(json, view)
38
38
 
39
- result = json.toString()
39
+ result = json
40
40
  }
41
41
 
42
42
  override fun getResult() = result
@@ -0,0 +1,43 @@
1
+ package com.wix.detox.espresso.performer
2
+
3
+ import com.wix.detox.espresso.DetoxMatcher
4
+ import com.wix.detox.espresso.ViewActionWithResult
5
+
6
+ import android.view.View
7
+ import androidx.test.espresso.Espresso.onView
8
+ import androidx.test.espresso.NoMatchingViewException
9
+ import androidx.test.espresso.ViewAction
10
+ import org.hamcrest.Matcher
11
+
12
+ class MultipleViewsActionPerformer(
13
+ private val action: ViewAction
14
+ ) : ViewActionPerformer {
15
+ override fun performOn(matcher: Matcher<View>): Any? {
16
+ val results = mutableListOf<Any?>()
17
+ var index = 0
18
+
19
+ while (true) {
20
+ val indexedMatcher = DetoxMatcher.matcherForAtIndex(index, matcher)
21
+
22
+ try {
23
+ onView(indexedMatcher).perform(action)
24
+
25
+ (action as? ViewActionWithResult<*>)?.getResult()?.let { results.add(it) }
26
+
27
+ index++
28
+ } catch (e: NoMatchingViewException) {
29
+ if (index == 0) {
30
+ throw e
31
+ }
32
+
33
+ break
34
+ }
35
+ }
36
+
37
+ return when {
38
+ results.isEmpty() -> null
39
+ results.size == 1 -> results.first()
40
+ else -> mapOf("elements" to results)
41
+ }
42
+ }
43
+ }
@@ -0,0 +1,19 @@
1
+ package com.wix.detox.espresso.performer
2
+
3
+ import com.wix.detox.espresso.ViewActionWithResult
4
+
5
+ import android.view.View
6
+ import androidx.test.espresso.Espresso.onView
7
+ import androidx.test.espresso.NoMatchingViewException
8
+ import androidx.test.espresso.ViewAction
9
+ import org.hamcrest.Matcher
10
+
11
+ class SingleViewActionPerformer(
12
+ private val action: ViewAction
13
+ ) : ViewActionPerformer {
14
+ override fun performOn(matcher: Matcher<View>): Any? {
15
+ onView(matcher).perform(action)
16
+
17
+ return (action as? ViewActionWithResult<*>)?.getResult()
18
+ }
19
+ }
@@ -0,0 +1,24 @@
1
+ package com.wix.detox.espresso.performer
2
+
3
+ import com.wix.detox.espresso.MultipleViewsAction
4
+
5
+ import android.view.View
6
+ import androidx.test.espresso.Espresso.onView
7
+ import androidx.test.espresso.NoMatchingViewException
8
+ import androidx.test.espresso.ViewAction
9
+ import org.hamcrest.Matcher
10
+
11
+ interface ViewActionPerformer {
12
+ fun performOn(matcher: Matcher<View>): Any?
13
+
14
+ companion object {
15
+ @JvmStatic
16
+ fun forAction(action: ViewAction): ViewActionPerformer {
17
+ return if (action is MultipleViewsAction) {
18
+ MultipleViewsActionPerformer(action)
19
+ } else {
20
+ SingleViewActionPerformer(action)
21
+ }
22
+ }
23
+ }
24
+ }
@@ -92,9 +92,9 @@ public class Invocation {
92
92
  } else if (type.equals("boolean")) {
93
93
  argument = jsonArgument.optBoolean("value");
94
94
  } else if (type.equals("Invocation")) {
95
- argument = new Invocation(jsonArgument.optJSONObject("value"));
95
+ argument = new Invocation(jsonArgument.optJSONObject("value"));
96
96
  } else {
97
- throw new RuntimeException("Unhandled arg type" + type);
97
+ throw new RuntimeException("Unhandled arg type " + type);
98
98
  }
99
99
  }
100
100
  }
@@ -105,6 +105,8 @@ public class Invocation {
105
105
  }
106
106
 
107
107
  public void setArgs(Object[] args) {
108
+ JsonParser parser = new JsonParser();
109
+
108
110
  for (int i = 0; i < args.length; i++) {
109
111
  Object argument = args[i];
110
112
  if (argument instanceof HashMap && !((HashMap) argument).isEmpty()) {
@@ -125,10 +127,9 @@ public class Invocation {
125
127
  } else if (type.equals("boolean")) {
126
128
  argument = ((Boolean) value).booleanValue();
127
129
  } else if (type.equals("Invocation")) {
128
- JsonParser parser = new JsonParser();
129
130
  argument = parser.parse((String)value);
130
131
  } else {
131
- throw new RuntimeException("Unhandled arg type" + type);
132
+ throw new RuntimeException("Unhandled arg type " + type);
132
133
  }
133
134
 
134
135
  args[i] = argument;
@@ -0,0 +1,4 @@
1
+ package com.wix.detox.espresso
2
+
3
+ // Marker interface for actions that should be applied to all matching elements without ambiguity.
4
+ interface MultipleViewsAction
@@ -1,4 +1,3 @@
1
-
2
1
  package com.wix.detox.espresso
3
2
 
4
3
  import androidx.test.espresso.UiController
@@ -2,6 +2,7 @@ package com.wix.detox.espresso
2
2
 
3
3
  import androidx.test.espresso.ViewAction
4
4
 
5
- interface ViewActionWithResult<R: Any?>: ViewAction {
5
+ // Interface for actions that return a result.
6
+ interface ViewActionWithResult<R: Any?> : ViewAction {
6
7
  fun getResult(): R
7
8
  }
@@ -37,7 +37,7 @@ class GetAttributesActionTest {
37
37
 
38
38
  private fun perform(v: View = view): JSONObject {
39
39
  uut.perform(null, v)
40
- return JSONObject(uut.getResult())
40
+ return uut.getResult()!!
41
41
  }
42
42
 
43
43
  @Test
@@ -135,10 +135,10 @@ class GetAttributesActionTest {
135
135
  }
136
136
 
137
137
  val resultJson = perform()
138
- assertThat(resultJson.opt("alpha")).isEqualTo(0.42)
138
+ assertThat(resultJson.opt("alpha")).isEqualTo(0.42f)
139
139
  assertThat(resultJson.opt("width")).isEqualTo(123)
140
140
  assertThat(resultJson.opt("height")).isEqualTo(456)
141
- assertThat(resultJson.opt("elevation")).isEqualTo(0.314)
141
+ assertThat(resultJson.opt("elevation")).isEqualTo(0.314f)
142
142
  }
143
143
 
144
144
  @Test
@@ -208,7 +208,8 @@ class GetAttributesActionTest {
208
208
  }
209
209
 
210
210
  val resultJson = perform(slider)
211
- assertThat(resultJson.opt("value")).isEqualTo(0.42)
211
+ android.util.Log.i("TESTS", "should return material-Slider state through value attribute: "+ resultJson)
212
+ assertThat(resultJson.opt("value")).isEqualTo(0.42f)
212
213
  }
213
214
 
214
215
  @Test
@@ -221,7 +222,7 @@ class GetAttributesActionTest {
221
222
 
222
223
  val resultJson = perform(textView)
223
224
  assertThat(resultJson.opt("text")).isEqualTo("mock-text")
224
- assertThat(resultJson.opt("textSize")).isEqualTo(24)
225
+ assertThat(resultJson.opt("textSize")).isEqualTo(24f)
225
226
  assertThat(resultJson.opt("length")).isEqualTo(111)
226
227
  }
227
228
 
@@ -0,0 +1,37 @@
1
+ package com.wix.detox.espresso.performer
2
+
3
+ import org.spekframework.spek2.Spek
4
+ import org.spekframework.spek2.style.specification.describe
5
+ import androidx.test.espresso.ViewAction
6
+ import com.wix.detox.espresso.MultipleViewsAction
7
+ import org.hamcrest.Matcher
8
+ import org.mockito.Mockito.*
9
+ import org.mockito.kotlin.mock
10
+
11
+ object ViewActionPerformerSpec : Spek({
12
+
13
+ describe("ViewActionPerformer") {
14
+ context("forAction") {
15
+ context("given a regular ViewAction") {
16
+ val action = mock(ViewAction::class.java)
17
+
18
+ it("should return a SingleViewActionPerformer") {
19
+ val performer = ViewActionPerformer.forAction(action)
20
+ assert(performer is SingleViewActionPerformer)
21
+ }
22
+ }
23
+
24
+ context("given a MultipleViewsAction") {
25
+ val multipleViewsAction: ViewAction = mock(
26
+ ViewAction::class.java,
27
+ withSettings().extraInterfaces(MultipleViewsAction::class.java)
28
+ )
29
+
30
+ it("should return a MultipleViewsActionPerformer") {
31
+ val performer = ViewActionPerformer.forAction(multipleViewsAction)
32
+ assert(performer is MultipleViewsActionPerformer)
33
+ }
34
+ }
35
+ }
36
+ }
37
+ })
package/index.d.ts CHANGED
@@ -624,6 +624,10 @@ declare global {
624
624
  get(): object;
625
625
  }
626
626
 
627
+ type DigitWithoutZero = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9;
628
+ type Digit = 0 | DigitWithoutZero;
629
+ type BatteryLevel = `${Digit}` | `${DigitWithoutZero}${Digit}` | "100";
630
+
627
631
  interface Device {
628
632
  /**
629
633
  * Holds the environment-unique ID of the device, namely, the adb ID on Android (e.g. emulator-5554) and the Mac-global simulator UDID on iOS -
@@ -789,6 +793,45 @@ declare global {
789
793
  */
790
794
  setLocation(lat: number, lon: number): Promise<void>;
791
795
 
796
+ /**
797
+ * (iOS only) Override simulator’s status bar.
798
+ * @platform iOS
799
+ * @param {config} config status bar configuration.
800
+ * @example
801
+ * await device.setStatusBar({
802
+ * time: "12:34",
803
+ * // Set the date or time to a fixed value.
804
+ * // If the string is a valid ISO date string it will also set the date on relevant devices.
805
+ * dataNetwork: "wifi",
806
+ * // If specified must be one of 'hide', 'wifi', '3g', '4g', 'lte', 'lte-a', 'lte+', '5g', '5g+', '5g-uwb', or '5g-uc'.
807
+ * wifiMode: "failed",
808
+ * // If specified must be one of 'searching', 'failed', or 'active'.
809
+ * wifiBars: "2",
810
+ * // If specified must be 0-3.
811
+ * cellularMode: "searching",
812
+ * // If specified must be one of 'notSupported', 'searching', 'failed', or 'active'.
813
+ * cellularBars: "3",
814
+ * // If specified must be 0-4.
815
+ * operatorName: "A1",
816
+ * // Set the cellular operator/carrier name. Use '' for the empty string.
817
+ * batteryState: "charging",
818
+ * // If specified must be one of 'charging', 'charged', or 'discharging'.
819
+ * batteryLevel: "50",
820
+ * // If specified must be 0-100.
821
+ * });
822
+ */
823
+ setStatusBar(config: {
824
+ time?: string,
825
+ dataNetwork?: "hide" | "wifi" | "3g" | "4g" | "lte" | "lte-a" | "lte+" | "5g" | "5g+" | "5g-uwb" | "5g-uc",
826
+ wifiMode?: "searching" |"failed" | "active",
827
+ wifiBars?: "0" | "1" | "2" | "3",
828
+ cellularMode?: "notSupported" | "searching" | "failed" | "active",
829
+ cellularBars?: "0" | "1" | "2" | "3" | "4",
830
+ operatorName?: string;
831
+ batteryState?: "charging" | "charged" | "discharging",
832
+ batteryLevel?: BatteryLevel,
833
+ }): Promise<void>;
834
+
792
835
  /**
793
836
  * Disable network synchronization mechanism on preferred endpoints. Useful if you want to on skip over synchronizing on certain URLs.
794
837
  *
@@ -1430,8 +1473,9 @@ declare global {
1430
1473
  takeScreenshot(name: string): Promise<string>;
1431
1474
 
1432
1475
  /**
1433
- * Gets the native (OS-dependent) attributes of the element.
1434
- * For more information, see {@link https://wix.github.io/Detox/docs/api/actions-on-element/#getattributes}
1476
+ * Retrieves the OS-dependent attributes of an element.
1477
+ * If there are multiple matches, it returns an array of attributes for all matched elements.
1478
+ * For detailed information, refer to {@link https://wix.github.io/Detox/docs/api/actions-on-element/#getattributes}
1435
1479
  *
1436
1480
  * @example
1437
1481
  * test('Get the attributes for my text element', async () => {
@@ -1445,7 +1489,7 @@ declare global {
1445
1489
  * jestExpect(attributes.width).toHaveValue(100);
1446
1490
  * })
1447
1491
  */
1448
- getAttributes(): Promise<IosElementAttributes | AndroidElementAttributes | { elements: IosElementAttributes[]; }>;
1492
+ getAttributes(): Promise<IosElementAttributes | AndroidElementAttributes | { elements: IosElementAttributes[] } | { elements: AndroidElementAttributes[] } >;
1449
1493
  }
1450
1494
 
1451
1495
  interface WebExpect<R = Promise<void>> {
@@ -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 all Detox lock files. Useful when you need to clean up leftover locks from a crashed Detox instance.';
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
  };