detox 20.25.6 → 20.26.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (85) hide show
  1. package/Detox-android/com/wix/detox/{20.25.6/detox-20.25.6-sources.jar → 20.26.1/detox-20.26.1-sources.jar} +0 -0
  2. package/Detox-android/com/wix/detox/20.26.1/detox-20.26.1-sources.jar.md5 +1 -0
  3. package/Detox-android/com/wix/detox/20.26.1/detox-20.26.1-sources.jar.sha1 +1 -0
  4. package/Detox-android/com/wix/detox/20.26.1/detox-20.26.1-sources.jar.sha256 +1 -0
  5. package/Detox-android/com/wix/detox/20.26.1/detox-20.26.1-sources.jar.sha512 +1 -0
  6. package/Detox-android/com/wix/detox/20.26.1/detox-20.26.1.aar +0 -0
  7. package/Detox-android/com/wix/detox/20.26.1/detox-20.26.1.aar.md5 +1 -0
  8. package/Detox-android/com/wix/detox/20.26.1/detox-20.26.1.aar.sha1 +1 -0
  9. package/Detox-android/com/wix/detox/20.26.1/detox-20.26.1.aar.sha256 +1 -0
  10. package/Detox-android/com/wix/detox/20.26.1/detox-20.26.1.aar.sha512 +1 -0
  11. package/Detox-android/com/wix/detox/{20.25.6/detox-20.25.6.pom → 20.26.1/detox-20.26.1.pom} +13 -13
  12. package/Detox-android/com/wix/detox/20.26.1/detox-20.26.1.pom.md5 +1 -0
  13. package/Detox-android/com/wix/detox/20.26.1/detox-20.26.1.pom.sha1 +1 -0
  14. package/Detox-android/com/wix/detox/20.26.1/detox-20.26.1.pom.sha256 +1 -0
  15. package/Detox-android/com/wix/detox/20.26.1/detox-20.26.1.pom.sha512 +1 -0
  16. package/Detox-android/com/wix/detox/maven-metadata.xml +4 -4
  17. package/Detox-android/com/wix/detox/maven-metadata.xml.md5 +1 -1
  18. package/Detox-android/com/wix/detox/maven-metadata.xml.sha1 +1 -1
  19. package/Detox-android/com/wix/detox/maven-metadata.xml.sha256 +1 -1
  20. package/Detox-android/com/wix/detox/maven-metadata.xml.sha512 +1 -1
  21. package/Detox-android/com/wix/detox-legacy/{20.25.6/detox-legacy-20.25.6-sources.jar → 20.26.1/detox-legacy-20.26.1-sources.jar} +0 -0
  22. package/Detox-android/com/wix/detox-legacy/20.26.1/detox-legacy-20.26.1-sources.jar.md5 +1 -0
  23. package/Detox-android/com/wix/detox-legacy/20.26.1/detox-legacy-20.26.1-sources.jar.sha1 +1 -0
  24. package/Detox-android/com/wix/detox-legacy/20.26.1/detox-legacy-20.26.1-sources.jar.sha256 +1 -0
  25. package/Detox-android/com/wix/detox-legacy/20.26.1/detox-legacy-20.26.1-sources.jar.sha512 +1 -0
  26. package/Detox-android/com/wix/detox-legacy/20.26.1/detox-legacy-20.26.1.aar +0 -0
  27. package/Detox-android/com/wix/detox-legacy/20.26.1/detox-legacy-20.26.1.aar.md5 +1 -0
  28. package/Detox-android/com/wix/detox-legacy/20.26.1/detox-legacy-20.26.1.aar.sha1 +1 -0
  29. package/Detox-android/com/wix/detox-legacy/20.26.1/detox-legacy-20.26.1.aar.sha256 +1 -0
  30. package/Detox-android/com/wix/detox-legacy/20.26.1/detox-legacy-20.26.1.aar.sha512 +1 -0
  31. package/Detox-android/com/wix/detox-legacy/{20.25.6/detox-legacy-20.25.6.pom → 20.26.1/detox-legacy-20.26.1.pom} +13 -13
  32. package/Detox-android/com/wix/detox-legacy/20.26.1/detox-legacy-20.26.1.pom.md5 +1 -0
  33. package/Detox-android/com/wix/detox-legacy/20.26.1/detox-legacy-20.26.1.pom.sha1 +1 -0
  34. package/Detox-android/com/wix/detox-legacy/20.26.1/detox-legacy-20.26.1.pom.sha256 +1 -0
  35. package/Detox-android/com/wix/detox-legacy/20.26.1/detox-legacy-20.26.1.pom.sha512 +1 -0
  36. package/Detox-android/com/wix/detox-legacy/maven-metadata.xml +4 -4
  37. package/Detox-android/com/wix/detox-legacy/maven-metadata.xml.md5 +1 -1
  38. package/Detox-android/com/wix/detox-legacy/maven-metadata.xml.sha1 +1 -1
  39. package/Detox-android/com/wix/detox-legacy/maven-metadata.xml.sha256 +1 -1
  40. package/Detox-android/com/wix/detox-legacy/maven-metadata.xml.sha512 +1 -1
  41. package/Detox-ios-framework.tbz +0 -0
  42. package/Detox-ios-src.tbz +0 -0
  43. package/Detox-ios-xcuitest.tbz +0 -0
  44. package/android/detox/build.gradle +8 -9
  45. package/android/detox/proguard-rules-app.pro +3 -0
  46. package/android/detox/src/full/java/com/wix/detox/Detox.java +5 -0
  47. package/android/detox/src/full/java/com/wix/detox/espresso/assertion/ViewAssertions.java +6 -8
  48. package/android/detox/src/full/java/com/wix/detox/espresso/hierarchy/RootViewsHelper.kt +51 -0
  49. package/android/detox/src/full/java/com/wix/detox/espresso/hierarchy/ViewHierarchyGenerator.kt +128 -0
  50. package/detox.d.ts +12 -0
  51. package/package.json +3 -2
  52. package/src/android/espressoapi/Detox.js +15 -0
  53. package/src/client/Client.js +6 -0
  54. package/src/client/actions/actions.js +21 -1
  55. package/src/copilot/CopilotDriver.js +140 -0
  56. package/src/devices/runtime/RuntimeDevice.js +5 -0
  57. package/src/devices/runtime/drivers/DeviceDriverBase.js +4 -0
  58. package/src/devices/runtime/drivers/android/AndroidDriver.js +5 -0
  59. package/src/devices/runtime/drivers/ios/SimulatorDriver.js +4 -0
  60. package/Detox-android/com/wix/detox/20.25.6/detox-20.25.6-sources.jar.md5 +0 -1
  61. package/Detox-android/com/wix/detox/20.25.6/detox-20.25.6-sources.jar.sha1 +0 -1
  62. package/Detox-android/com/wix/detox/20.25.6/detox-20.25.6-sources.jar.sha256 +0 -1
  63. package/Detox-android/com/wix/detox/20.25.6/detox-20.25.6-sources.jar.sha512 +0 -1
  64. package/Detox-android/com/wix/detox/20.25.6/detox-20.25.6.aar +0 -0
  65. package/Detox-android/com/wix/detox/20.25.6/detox-20.25.6.aar.md5 +0 -1
  66. package/Detox-android/com/wix/detox/20.25.6/detox-20.25.6.aar.sha1 +0 -1
  67. package/Detox-android/com/wix/detox/20.25.6/detox-20.25.6.aar.sha256 +0 -1
  68. package/Detox-android/com/wix/detox/20.25.6/detox-20.25.6.aar.sha512 +0 -1
  69. package/Detox-android/com/wix/detox/20.25.6/detox-20.25.6.pom.md5 +0 -1
  70. package/Detox-android/com/wix/detox/20.25.6/detox-20.25.6.pom.sha1 +0 -1
  71. package/Detox-android/com/wix/detox/20.25.6/detox-20.25.6.pom.sha256 +0 -1
  72. package/Detox-android/com/wix/detox/20.25.6/detox-20.25.6.pom.sha512 +0 -1
  73. package/Detox-android/com/wix/detox-legacy/20.25.6/detox-legacy-20.25.6-sources.jar.md5 +0 -1
  74. package/Detox-android/com/wix/detox-legacy/20.25.6/detox-legacy-20.25.6-sources.jar.sha1 +0 -1
  75. package/Detox-android/com/wix/detox-legacy/20.25.6/detox-legacy-20.25.6-sources.jar.sha256 +0 -1
  76. package/Detox-android/com/wix/detox-legacy/20.25.6/detox-legacy-20.25.6-sources.jar.sha512 +0 -1
  77. package/Detox-android/com/wix/detox-legacy/20.25.6/detox-legacy-20.25.6.aar +0 -0
  78. package/Detox-android/com/wix/detox-legacy/20.25.6/detox-legacy-20.25.6.aar.md5 +0 -1
  79. package/Detox-android/com/wix/detox-legacy/20.25.6/detox-legacy-20.25.6.aar.sha1 +0 -1
  80. package/Detox-android/com/wix/detox-legacy/20.25.6/detox-legacy-20.25.6.aar.sha256 +0 -1
  81. package/Detox-android/com/wix/detox-legacy/20.25.6/detox-legacy-20.25.6.aar.sha512 +0 -1
  82. package/Detox-android/com/wix/detox-legacy/20.25.6/detox-legacy-20.25.6.pom.md5 +0 -1
  83. package/Detox-android/com/wix/detox-legacy/20.25.6/detox-legacy-20.25.6.pom.sha1 +0 -1
  84. package/Detox-android/com/wix/detox-legacy/20.25.6/detox-legacy-20.25.6.pom.sha256 +0 -1
  85. package/Detox-android/com/wix/detox-legacy/20.25.6/detox-legacy-20.25.6.pom.sha512 +0 -1
@@ -0,0 +1 @@
1
+ cb52b8177078355afc457f45e128853d
@@ -0,0 +1 @@
1
+ df0ecd8aa3bd60c9f5d237dd729f579ba8a575db
@@ -0,0 +1 @@
1
+ df6bea449ff58dd7dac14039b07c04397365c255939def9242266e2272de1ea3
@@ -0,0 +1 @@
1
+ f55327a87712ff17a9d0ee1f606bc5c593b3ffb6c56245fa4d831c9f4ea0e7f25534c306f7529e8b0f34adbc60428ed019de1af58d0a67cf89e3d16fd6a2eb22
@@ -0,0 +1 @@
1
+ 19245568a5b1fc7e18eae4c34019b2d0
@@ -0,0 +1 @@
1
+ dfb1a4d4b6a06bbe8952fe821ab3278364fc3cf2
@@ -0,0 +1 @@
1
+ 294b99bfcfc4acf89c10c76c4cfb07b61dec92d8f45a2ed137092aa766d7e215
@@ -0,0 +1 @@
1
+ 546fa7e195d2c2077d9e41f2b003ead174c820ce45027752e86a366e673023cc41d09b5b5ccd3bdb693f403e6c8b65567af12208ece66e65d85937e9a65f677d
@@ -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.25.6</version>
6
+ <version>20.26.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>
@@ -30,22 +30,28 @@
30
30
  <url>https://github.com/wix/detox</url>
31
31
  </scm>
32
32
  <dependencies>
33
+ <dependency>
34
+ <groupId>org.jetbrains.kotlin</groupId>
35
+ <artifactId>kotlin-stdlib-jdk8</artifactId>
36
+ <version>1.8.0</version>
37
+ <scope>compile</scope>
38
+ </dependency>
33
39
  <dependency>
34
40
  <groupId>androidx.test.espresso</groupId>
35
41
  <artifactId>espresso-core</artifactId>
36
- <version>3.5.1</version>
42
+ <version>3.6.1</version>
37
43
  <scope>compile</scope>
38
44
  </dependency>
39
45
  <dependency>
40
46
  <groupId>androidx.test.espresso</groupId>
41
47
  <artifactId>espresso-web</artifactId>
42
- <version>3.5.1</version>
48
+ <version>3.6.1</version>
43
49
  <scope>compile</scope>
44
50
  </dependency>
45
51
  <dependency>
46
52
  <groupId>androidx.test.espresso</groupId>
47
53
  <artifactId>espresso-contrib</artifactId>
48
- <version>3.5.1</version>
54
+ <version>3.6.1</version>
49
55
  <scope>compile</scope>
50
56
  <exclusions>
51
57
  <exclusion>
@@ -63,27 +69,21 @@
63
69
  <dependency>
64
70
  <groupId>androidx.test</groupId>
65
71
  <artifactId>rules</artifactId>
66
- <version>1.5.0</version>
72
+ <version>1.6.1</version>
67
73
  <scope>compile</scope>
68
74
  </dependency>
69
75
  <dependency>
70
76
  <groupId>androidx.test.ext</groupId>
71
77
  <artifactId>junit</artifactId>
72
- <version>1.1.5</version>
78
+ <version>1.2.1</version>
73
79
  <scope>compile</scope>
74
80
  </dependency>
75
81
  <dependency>
76
82
  <groupId>androidx.test.uiautomator</groupId>
77
83
  <artifactId>uiautomator</artifactId>
78
- <version>2.2.0</version>
84
+ <version>2.3.0</version>
79
85
  <scope>compile</scope>
80
86
  </dependency>
81
- <dependency>
82
- <groupId>org.jetbrains.kotlin</groupId>
83
- <artifactId>kotlin-stdlib-jdk8</artifactId>
84
- <version>1.2.0</version>
85
- <scope>runtime</scope>
86
- </dependency>
87
87
  <dependency>
88
88
  <groupId>org.apache.commons</groupId>
89
89
  <artifactId>commons-lang3</artifactId>
@@ -0,0 +1 @@
1
+ 1bf631450249797e4ccaea1f57c7099b
@@ -0,0 +1 @@
1
+ 1dd770221e2a3611ee8c5c37c6b9b4c2f1bb760d
@@ -0,0 +1 @@
1
+ 17c6e7dc49f3b473f36510392b4e130717ef2f575f4b8d886062e09e6b0264e7
@@ -0,0 +1 @@
1
+ 6912f590491521686d812a294e692cb66c7c0342abd07cdab313f6c610b33f5e45eaa32466ed285f6a1b2e9f0b9aa9f030017803acb6775db1f8c89d54690ddc
@@ -3,11 +3,11 @@
3
3
  <groupId>com.wix</groupId>
4
4
  <artifactId>detox</artifactId>
5
5
  <versioning>
6
- <latest>20.25.6</latest>
7
- <release>20.25.6</release>
6
+ <latest>20.26.1</latest>
7
+ <release>20.26.1</release>
8
8
  <versions>
9
- <version>20.25.6</version>
9
+ <version>20.26.1</version>
10
10
  </versions>
11
- <lastUpdated>20240825174403</lastUpdated>
11
+ <lastUpdated>20240905072123</lastUpdated>
12
12
  </versioning>
13
13
  </metadata>
@@ -1 +1 @@
1
- 3ebd487874d7ca9ea9e79f14ae8b2228
1
+ 0eaed4043597835de00d112c3743048e
@@ -1 +1 @@
1
- 22de2239bc50b05a3d10d735a8435b281aa5aa77
1
+ 48836958569a492b65d2563d763a6530d661b78e
@@ -1 +1 @@
1
- 85fa4bb20d12f08cbc7ea2dfcd7245707cd1b7ba6047bd9f3b45582bceef0227
1
+ 40c848b9199cc3579c5293dcb4e883c87cad72531deff2c90fe525c814740589
@@ -1 +1 @@
1
- 7a948085b3d47fb26694edba0bfe6fef3805bf069873bd4273e57fa11ee49e36b2cf61e9f74cdd953c9763945b8666c4cd72b2bb3f450eadc0d2bf608f26f29d
1
+ 2a1e04c9c77232761a933190ac00b1155cf3f14df3abbacdb9b83c5963d2c40acfdff9a65fadfb5b7390d3b8577a6c0d192a825961b83876ad7e64a3a7c2c8e1
@@ -0,0 +1 @@
1
+ 0bd84ca1c587091c54ac240c0709623f
@@ -0,0 +1 @@
1
+ 908cc092b39693c1df99e58cdadc5220d2fcea44
@@ -0,0 +1 @@
1
+ c18e176a31e4f4e887c8be495579ac034933e2211aaf6a8fa16cf370fe71adcb
@@ -0,0 +1 @@
1
+ 0c0a7610c6abfcb512506ec97ed33074b814bf42f2323e5ce4e462108c0a55dd1b8febe0731cb6d46c60345efae3aa544773a9d66a657debb4567d0c9b25d7be
@@ -0,0 +1 @@
1
+ 0dd6f951f83bfb1c258c09e57291b5f3
@@ -0,0 +1 @@
1
+ 54212838677b6cf72c2eb964dc911a9a80cf54a7
@@ -0,0 +1 @@
1
+ c2452ceba0cb3a2a6517086d81a0e990d82ab263395a0e1166b8178769cd8a51
@@ -0,0 +1 @@
1
+ 3d71f12171376fcf35b46ebc6a6cf942e0a7151a8f26287b41b6e2807f4bd8d37704aeaa89b7b0231c2286a301ebbfa3ff77a0a9cee92c02463c0085a4190085
@@ -3,7 +3,7 @@
3
3
  <modelVersion>4.0.0</modelVersion>
4
4
  <groupId>com.wix</groupId>
5
5
  <artifactId>detox-legacy</artifactId>
6
- <version>20.25.6</version>
6
+ <version>20.26.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>
@@ -30,22 +30,28 @@
30
30
  <url>https://github.com/wix/detox</url>
31
31
  </scm>
32
32
  <dependencies>
33
+ <dependency>
34
+ <groupId>org.jetbrains.kotlin</groupId>
35
+ <artifactId>kotlin-stdlib-jdk8</artifactId>
36
+ <version>1.8.0</version>
37
+ <scope>compile</scope>
38
+ </dependency>
33
39
  <dependency>
34
40
  <groupId>androidx.test.espresso</groupId>
35
41
  <artifactId>espresso-core</artifactId>
36
- <version>3.5.1</version>
42
+ <version>3.6.1</version>
37
43
  <scope>compile</scope>
38
44
  </dependency>
39
45
  <dependency>
40
46
  <groupId>androidx.test.espresso</groupId>
41
47
  <artifactId>espresso-web</artifactId>
42
- <version>3.5.1</version>
48
+ <version>3.6.1</version>
43
49
  <scope>compile</scope>
44
50
  </dependency>
45
51
  <dependency>
46
52
  <groupId>androidx.test.espresso</groupId>
47
53
  <artifactId>espresso-contrib</artifactId>
48
- <version>3.5.1</version>
54
+ <version>3.6.1</version>
49
55
  <scope>compile</scope>
50
56
  <exclusions>
51
57
  <exclusion>
@@ -63,27 +69,21 @@
63
69
  <dependency>
64
70
  <groupId>androidx.test</groupId>
65
71
  <artifactId>rules</artifactId>
66
- <version>1.5.0</version>
72
+ <version>1.6.1</version>
67
73
  <scope>compile</scope>
68
74
  </dependency>
69
75
  <dependency>
70
76
  <groupId>androidx.test.ext</groupId>
71
77
  <artifactId>junit</artifactId>
72
- <version>1.1.5</version>
78
+ <version>1.2.1</version>
73
79
  <scope>compile</scope>
74
80
  </dependency>
75
81
  <dependency>
76
82
  <groupId>androidx.test.uiautomator</groupId>
77
83
  <artifactId>uiautomator</artifactId>
78
- <version>2.2.0</version>
84
+ <version>2.3.0</version>
79
85
  <scope>compile</scope>
80
86
  </dependency>
81
- <dependency>
82
- <groupId>org.jetbrains.kotlin</groupId>
83
- <artifactId>kotlin-stdlib-jdk8</artifactId>
84
- <version>1.2.0</version>
85
- <scope>runtime</scope>
86
- </dependency>
87
87
  <dependency>
88
88
  <groupId>org.apache.commons</groupId>
89
89
  <artifactId>commons-lang3</artifactId>
@@ -0,0 +1 @@
1
+ 6c50ab9fc402621ed054130c3ad29a50
@@ -0,0 +1 @@
1
+ cc1f5ce71a739209519424cd42dea3ec6c243d83
@@ -0,0 +1 @@
1
+ 22cab0ab0bc66e1faf2358620a6503287a55820a8b596a6b8ff47fd1f229e44d
@@ -0,0 +1 @@
1
+ 9b889b0af531796d582ccf4627756e259473f78ed04a7d687f9454048938f70bec5f5a4b2ab11a6236f618ec06e4ae3c34d0909a61258842a19509eb0544b1ff
@@ -3,11 +3,11 @@
3
3
  <groupId>com.wix</groupId>
4
4
  <artifactId>detox-legacy</artifactId>
5
5
  <versioning>
6
- <latest>20.25.6</latest>
7
- <release>20.25.6</release>
6
+ <latest>20.26.1</latest>
7
+ <release>20.26.1</release>
8
8
  <versions>
9
- <version>20.25.6</version>
9
+ <version>20.26.1</version>
10
10
  </versions>
11
- <lastUpdated>20240825174441</lastUpdated>
11
+ <lastUpdated>20240905072150</lastUpdated>
12
12
  </versioning>
13
13
  </metadata>
@@ -1 +1 @@
1
- e8677f5e1ebc2db6a82900c05f8d79dc
1
+ 4910f1ba303df535a12b451a5276bf85
@@ -1 +1 @@
1
- 12b4921860e458ca7333620fec5ca94bec62c05b
1
+ 49ee8cead5fee31eafaa5d6ca61e63ca6be3c519
@@ -1 +1 @@
1
- 74491490f648f58107b92765dd805167f3187b42ebf3a94408c017e654c46334
1
+ 9ec37c0d1a6cb2e02bbeec7e772e2af0b409dc9e4634b70d2b42d673983fe56f
@@ -1 +1 @@
1
- 7ce4eab1a1b798a283d6c22884823a9dfd7aa06b177889c1a7c305661fd3b2095703b8f9d3311907a6652d78763ece4aada1353f70b5f9b71bfd525981d93b70
1
+ 45e71b04bff51637e1bf1528b9ef2c70b0fd4b060851a9c3f06272a1d4574af330914d45fd62f5d3001f1e7154107d0f618b5261305167f8b632f03c8bc691f0
Binary file
package/Detox-ios-src.tbz CHANGED
Binary file
Binary file
@@ -2,7 +2,7 @@ apply plugin: 'com.android.library'
2
2
  apply plugin: 'kotlin-android'
3
3
  apply from: '../rninfo.gradle'
4
4
 
5
- def _kotlinMinVersion = '1.2.0'
5
+ def _kotlinMinVersion = '1.8.0'
6
6
  def _materialMinVersion = '1.11.0'
7
7
 
8
8
  def _ext = rootProject.ext
@@ -111,7 +111,7 @@ android {
111
111
 
112
112
  // Fundamental deps.
113
113
  dependencies {
114
- implementation "org.jetbrains.kotlin:$_kotlinStdlib:$_kotlinMinVersion"
114
+ api "org.jetbrains.kotlin:$_kotlinStdlib:$_kotlinVersion"
115
115
 
116
116
  compileOnly "${_rnNativeArtifact}"
117
117
  }
@@ -123,29 +123,28 @@ dependencies {
123
123
  // Versions are in-sync with the 'androidx-test-1.4.0' release/tag of the android-test github repo,
124
124
  // used by the Detox generator. See https://github.com/android/android-test/releases/tag/androidx-test-1.4.0
125
125
  // Important: Should remain so when generator tag is replaced!
126
- api('androidx.test.espresso:espresso-core:3.5.1') {
126
+ api('androidx.test.espresso:espresso-core:3.6.1') {
127
127
  because 'Needed all across Detox but also makes Espresso seamlessly provided to Detox users with hybrid apps/E2E-tests.'
128
128
  }
129
- api('androidx.test.espresso:espresso-web:3.5.1') {
129
+ api('androidx.test.espresso:espresso-web:3.6.1') {
130
130
  because 'Web-View testing'
131
131
  }
132
- api('androidx.test.espresso:espresso-contrib:3.5.1') {
132
+ api('androidx.test.espresso:espresso-contrib:3.6.1') {
133
133
  because 'Android datepicker support'
134
134
  exclude group: "org.checkerframework", module: "checker"
135
135
  }
136
136
  api('org.hamcrest:hamcrest:2.2') {
137
137
  because 'See https://github.com/wix/Detox/issues/3920. Need to force hamcrest 2.2 win in battle of 2.2 vs. 1.3 (specified by Espresso).'
138
138
  }
139
- api('androidx.test:rules:1.5.0') {
139
+ api('androidx.test:rules:1.6.1') {
140
140
  because 'of ActivityTestRule. Needed by users *and* internally used by Detox.'
141
141
  }
142
- api('androidx.test.ext:junit:1.1.5') {
142
+ api('androidx.test.ext:junit:1.2.1') {
143
143
  because 'Needed so as to seamlessly provide AndroidJUnit4 to Detox users. Depends on junit core.'
144
144
  }
145
-
146
145
  // Version is the latest; Cannot sync with the Github repo (e.g. android/android-test) because the androidx
147
146
  // packaging version of associated classes is simply not there...
148
- api('androidx.test.uiautomator:uiautomator:2.2.0') {
147
+ api('androidx.test.uiautomator:uiautomator:2.3.0') {
149
148
  because 'Needed by Detox but also makes UIAutomator seamlessly provided to Detox users with hybrid apps/E2E-tests.'
150
149
  }
151
150
  }
@@ -14,11 +14,14 @@
14
14
  -keep class com.reactnativecommunity.slider.** { *; }
15
15
  -keep class com.reactnativecommunity.asyncstorage.** { *; }
16
16
 
17
+ -keep class kotlin.reflect.** { *; }
18
+ -keep class kotlin.coroutines.CoroutineDispatcher { *; }
17
19
  -keep class kotlin.jvm.** { *; }
18
20
  -keep class kotlin.collections.** { *; }
19
21
  -keep class kotlin.text.** { *; }
20
22
  -keep class kotlin.io.** { *; }
21
23
  -keep class okhttp3.** { *; }
24
+ -keep class kotlin.LazyKt { *; }
22
25
 
23
26
  -keep class androidx.concurrent.futures.** { *; }
24
27
 
@@ -7,6 +7,7 @@ import androidx.test.platform.app.InstrumentationRegistry;
7
7
  import androidx.test.rule.ActivityTestRule;
8
8
 
9
9
  import com.wix.detox.config.DetoxConfig;
10
+ import com.wix.detox.espresso.hierarchy.ViewHierarchyGenerator;
10
11
 
11
12
  /**
12
13
  * <p>Static class.</p>
@@ -141,4 +142,8 @@ public final class Detox {
141
142
  private static Context getAppContext() {
142
143
  return InstrumentationRegistry.getInstrumentation().getTargetContext().getApplicationContext();
143
144
  }
145
+
146
+ public static String generateViewHierarchyXml(boolean shouldInjectTestIds) {
147
+ return ViewHierarchyGenerator.generateXml(shouldInjectTestIds);
148
+ }
144
149
  }
@@ -1,16 +1,15 @@
1
1
  package com.wix.detox.espresso.assertion;
2
2
 
3
- import androidx.annotation.NonNull;
4
- import android.view.View;
3
+ import static androidx.test.espresso.matcher.ViewMatchers.assertThat;
5
4
 
6
- import org.hamcrest.Matcher;
7
- import org.hamcrest.StringDescription;
5
+ import android.view.View;
8
6
 
7
+ import androidx.annotation.NonNull;
9
8
  import androidx.test.espresso.NoMatchingViewException;
10
9
  import androidx.test.espresso.ViewAssertion;
11
10
 
12
- import static androidx.test.espresso.core.internal.deps.guava.base.Preconditions.checkNotNull;
13
- import static androidx.test.espresso.matcher.ViewMatchers.assertThat;
11
+ import org.hamcrest.Matcher;
12
+ import org.hamcrest.StringDescription;
14
13
 
15
14
  /**
16
15
  * A custom extension of {@link androidx.test.espresso.assertion.ViewAssertions}.
@@ -24,9 +23,8 @@ public class ViewAssertions {
24
23
  * which is more suitable for Detox' separated interaction-matcher architecture.
25
24
  * See {@link MatchesViewAssertion} for more details.
26
25
  */
27
- @SuppressWarnings("unchecked")
28
26
  public static ViewAssertion matches(final Matcher<? super View> viewMatcher) {
29
- return new MatchesViewAssertion((Matcher<? super View>) checkNotNull(viewMatcher));
27
+ return new MatchesViewAssertion(viewMatcher);
30
28
  }
31
29
 
32
30
  /**
@@ -0,0 +1,51 @@
1
+ package com.wix.detox.espresso.hierarchy
2
+
3
+ import android.annotation.SuppressLint
4
+ import android.view.View
5
+ import java.lang.reflect.Field
6
+ import java.lang.reflect.Method
7
+
8
+ object RootViewsHelper {
9
+
10
+ /**
11
+ * Get rootviews from RootViewImpl instances that are stored in WindowManagerGlobal.
12
+ */
13
+ fun getRootViews(): List<View?>? {
14
+ val rootViewsReflectedObjects = getAllViewRootObjects()
15
+ val rootViews = rootViewsReflectedObjects?.map {
16
+ // Root View is stored in the ViewRootImpl instance
17
+ val getViewMethod = it.javaClass.getDeclaredMethod("getView")
18
+ getViewMethod.isAccessible = true
19
+
20
+ // Invoke the method to get the root View
21
+ getViewMethod.invoke(it) as? View
22
+ }
23
+ return rootViews
24
+ }
25
+
26
+ @SuppressLint("PrivateApi", "DiscouragedPrivateApi")
27
+ private fun getAllViewRootObjects(): List<Any>? {
28
+ return try {
29
+ // Get the WindowManagerGlobal class
30
+ val windowManagerGlobalClass = Class.forName("android.view.WindowManagerGlobal")
31
+
32
+ // Get the getInstance method
33
+ val getInstanceMethod: Method = windowManagerGlobalClass.getDeclaredMethod("getInstance")
34
+ getInstanceMethod.isAccessible = true
35
+
36
+ // Get the single instance of WindowManagerGlobal
37
+ val windowManagerGlobal = getInstanceMethod.invoke(null)
38
+
39
+ // Get the mRoots field, which is a list of ViewRootImpl instances
40
+ val mRootsField: Field = windowManagerGlobalClass.getDeclaredField("mRoots")
41
+ mRootsField.isAccessible = true
42
+
43
+ // Return the list of ViewRootImpl instances
44
+ @Suppress("UNCHECKED_CAST")
45
+ mRootsField.get(windowManagerGlobal) as? List<Any>
46
+ } catch (e: Exception) {
47
+ e.printStackTrace()
48
+ null
49
+ }
50
+ }
51
+ }
@@ -0,0 +1,128 @@
1
+ package com.wix.detox.espresso.hierarchy
2
+
3
+ import android.util.Xml
4
+ import android.view.View
5
+ import android.view.ViewGroup
6
+ import android.widget.TextView
7
+ import com.wix.detox.reactnative.ui.getAccessibilityLabel
8
+ import org.xmlpull.v1.XmlSerializer
9
+ import java.io.StringWriter
10
+
11
+ object ViewHierarchyGenerator {
12
+ @JvmStatic
13
+ fun generateXml(shouldInjectTestIds: Boolean): String {
14
+ val rootViews = RootViewsHelper.getRootViews()
15
+ return generateXmlFromViews(rootViews, shouldInjectTestIds)
16
+ }
17
+
18
+ private fun generateXmlFromViews(rootViews: List<View?>?, shouldInjectTestIds: Boolean): String {
19
+ return StringWriter().use { writer ->
20
+ val serializer = Xml.newSerializer().apply {
21
+ setOutput(writer)
22
+ startDocument(Xml.Encoding.UTF_8.name, true)
23
+ setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true)
24
+ startTag("", "ViewHierarchy")
25
+ }
26
+
27
+ rootViews?.forEach { rootView ->
28
+ rootView?.let {
29
+ serializeViewHierarchy(it, serializer, shouldInjectTestIds, emptyList())
30
+ }
31
+ }
32
+
33
+ serializer.apply {
34
+ endTag("", "ViewHierarchy")
35
+ endDocument()
36
+ }
37
+
38
+ writer.toString()
39
+ }
40
+ }
41
+
42
+ private fun serializeViewHierarchy(
43
+ view: View,
44
+ serializer: XmlSerializer,
45
+ shouldInjectTestIds: Boolean,
46
+ indexPath: List<Int>
47
+ ) {
48
+ serializer.startTag("", view.javaClass.simpleName)
49
+ serializeViewAttributes(view, serializer, shouldInjectTestIds, indexPath)
50
+
51
+ if (view is ViewGroup) {
52
+ for (i in 0 until view.childCount) {
53
+ serializeViewHierarchy(
54
+ view.getChildAt(i),
55
+ serializer,
56
+ shouldInjectTestIds,
57
+ indexPath + i
58
+ )
59
+ }
60
+ }
61
+
62
+ serializer.endTag("", view.javaClass.simpleName)
63
+ }
64
+
65
+ private fun serializeViewAttributes(
66
+ view: View,
67
+ serializer: XmlSerializer,
68
+ shouldInjectTestIds: Boolean,
69
+ indexPath: List<Int>
70
+ ) {
71
+ val attributes = mutableMapOf(
72
+ "class" to view.javaClass.name,
73
+ "width" to view.width.toString(),
74
+ "height" to view.height.toString(),
75
+ "visibility" to view.visibilityToString(),
76
+ "alpha" to view.alpha.toString(),
77
+ "focused" to view.isFocused.toString(),
78
+ "value" to (view.contentDescription?.toString() ?: ""),
79
+ "label" to (view.getAccessibilityLabel()?.toString() ?: "")
80
+ )
81
+
82
+ view.id.takeIf { it != View.NO_ID }?.let {
83
+ attributes["id"] = try {
84
+ view.resources.getResourceName(it)
85
+ } catch (e: Exception) {
86
+ it.toString()
87
+ }
88
+ }
89
+
90
+ val location = IntArray(2).apply { view.getLocationInWindow(this) }
91
+ attributes["x"] = location[0].toString()
92
+ attributes["y"] = location[1].toString()
93
+
94
+ if (view is TextView) {
95
+ attributes["text"] = view.text.toString()
96
+ }
97
+
98
+ val currentTestId = view.tag?.toString() ?: ""
99
+
100
+ val injectedPrefix = "detox_temp_"
101
+ val isTestIdEmpty = currentTestId.isEmpty()
102
+ val isTestIdInjected = currentTestId.startsWith(injectedPrefix)
103
+ val shouldInjectNewTestId = shouldInjectTestIds && (isTestIdEmpty || isTestIdInjected)
104
+
105
+ if (shouldInjectNewTestId) {
106
+ val newTestId = "${injectedPrefix}${indexPath.joinToString("_")}"
107
+ view.tag = newTestId
108
+ attributes["testID"] = newTestId
109
+ } else {
110
+ attributes["testID"] = currentTestId
111
+ }
112
+
113
+ attributes
114
+ .filter { (_, value) ->
115
+ !value.isNullOrEmpty()
116
+ }
117
+ .forEach { (key, value) ->
118
+ serializer.attribute("", key, value)
119
+ }
120
+ }
121
+
122
+ private fun View.visibilityToString() = when (visibility) {
123
+ View.VISIBLE -> "visible"
124
+ View.INVISIBLE -> "invisible"
125
+ View.GONE -> "gone"
126
+ else -> "unknown"
127
+ }
128
+ }
package/detox.d.ts CHANGED
@@ -917,6 +917,18 @@ declare global {
917
917
  */
918
918
  captureViewHierarchy(name?: string): Promise<string>;
919
919
 
920
+ /**
921
+ * Dump the current view hierarchy of the app as an XML string.
922
+ * @param [shouldInjectTestIds=false] whether to inject testIDs into the view hierarchy when missing,
923
+ * to provide an identifiable reference for each element.
924
+ * @returns a string containing the XML representation of the view hierarchy.
925
+ * @example
926
+ * const viewHierarchy = await device.generateViewHierarchyXml();
927
+ * const viewHierarchyWithInjectedTestIds = await device.generateViewHierarchyXml(true);
928
+ * @note enabling shouldInjectTestIds changes the actual elements during the test run, use with caution.
929
+ */
930
+ generateViewHierarchyXml(shouldInjectTestIds?: boolean): Promise<string>;
931
+
920
932
  /**
921
933
  * Simulate shake (iOS Only)
922
934
  */
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "detox",
3
3
  "description": "E2E tests and automation for mobile",
4
- "version": "20.25.6",
4
+ "version": "20.26.1",
5
5
  "bin": {
6
6
  "detox": "local-cli/cli.js"
7
7
  },
@@ -71,6 +71,7 @@
71
71
  "caf": "^15.0.1",
72
72
  "chalk": "^4.0.0",
73
73
  "child-process-promise": "^2.2.0",
74
+ "detox-copilot": "^0.0.0",
74
75
  "execa": "^5.1.1",
75
76
  "find-up": "^5.0.0",
76
77
  "fs-extra": "^11.0.0",
@@ -115,5 +116,5 @@
115
116
  "browserslist": [
116
117
  "node 14"
117
118
  ],
118
- "gitHead": "0aa62157767805969e43dfe997f49d65652f76d2"
119
+ "gitHead": "deb90d069fcbbdb068602764465a2b77c443214a"
119
120
  }
@@ -69,6 +69,21 @@ class Detox {
69
69
  };
70
70
  }
71
71
 
72
+ static generateViewHierarchyXml(shouldInjectTestIds) {
73
+ if (typeof shouldInjectTestIds !== "boolean") throw new Error("shouldInjectTestIds should be a boolean, but got " + (shouldInjectTestIds + (" (" + (typeof shouldInjectTestIds + ")"))));
74
+ return {
75
+ target: {
76
+ type: "Class",
77
+ value: "com.wix.detox.Detox"
78
+ },
79
+ method: "generateViewHierarchyXml",
80
+ args: [{
81
+ type: "boolean",
82
+ value: shouldInjectTestIds
83
+ }]
84
+ };
85
+ }
86
+
72
87
  }
73
88
 
74
89
  module.exports = Detox;
@@ -225,6 +225,12 @@ class Client {
225
225
  }));
226
226
  }
227
227
 
228
+ async generateViewHierarchyXml({ shouldInjectTestIds }) {
229
+ return await this.sendAction(new actions.GenerateViewHierarchyXml({
230
+ shouldInjectTestIds
231
+ }));
232
+ }
233
+
228
234
  async currentStatus() {
229
235
  return await this.sendAction(new actions.CurrentStatus());
230
236
  }
@@ -292,6 +292,25 @@ class SetInstrumentsRecordingState extends Action {
292
292
  }
293
293
  }
294
294
 
295
+ class GenerateViewHierarchyXml extends Action {
296
+ constructor(params) {
297
+ super('generateViewHierarchyXml', params);
298
+ }
299
+
300
+ get isAtomic() {
301
+ return false;
302
+ }
303
+
304
+ get timeout() {
305
+ return 0;
306
+ }
307
+
308
+ async handle(response) {
309
+ this.expectResponseOfType(response, 'generateViewHierarchyXmlResult');
310
+ return response.params.viewHierarchy;
311
+ }
312
+ }
313
+
295
314
  class CaptureViewHierarchy extends Action {
296
315
  constructor(params) {
297
316
  super('captureViewHierarchy', params);
@@ -312,7 +331,7 @@ class CaptureViewHierarchy extends Action {
312
331
  if (captureViewHierarchyError) {
313
332
  throw new DetoxRuntimeError({
314
333
  message: 'Failed to capture view hierarchy. Reason:\n',
315
- debugInfo: captureViewHierarchyError,
334
+ debugInfo: captureViewHierarchyError
316
335
  });
317
336
  }
318
337
 
@@ -336,4 +355,5 @@ module.exports = {
336
355
  SetOrientation,
337
356
  SetInstrumentsRecordingState,
338
357
  CaptureViewHierarchy,
358
+ GenerateViewHierarchyXml
339
359
  };
@@ -0,0 +1,140 @@
1
+ const { device } = require('../..');
2
+
3
+ class DetoxDriver {
4
+ constructor() {
5
+ this.availableAPI = {
6
+ matchers: [
7
+ {
8
+ signature: 'by.id(id: string)',
9
+ description: 'Matches elements by their test ID.',
10
+ example: "element(by.id('loginButton'))",
11
+ guidelines: ['Always use test-ids (accessibility identifiers) from the UI hierarchy to identify elements.']
12
+ },
13
+ {
14
+ signature: 'by.text(text: string)',
15
+ description: 'Matches elements by their text.',
16
+ example: "element(by.text('Login'))",
17
+ guidelines: ['Avoid using text matchers when possible, prefer test-ids.']
18
+ },
19
+ {
20
+ signature: 'by.type(type: string)',
21
+ description: 'Matches elements by their type.',
22
+ example: "element(by.type('RCTTextInput'))",
23
+ guidelines: ['Use type matchers as a last resort, prefer test-ids.']
24
+ }
25
+ ],
26
+ actions: [
27
+ {
28
+ signature: 'tap(point?: Point2D)',
29
+ description: 'Simulates tap on an element',
30
+ example: "await element(by.id('loginButton')).tap();",
31
+ guidelines: ['Use element(by.id(\'testID\')) to locate elements.']
32
+ },
33
+ {
34
+ signature: 'longPress(point?: Point2D, duration?: number)',
35
+ description: 'Simulates long press on an element',
36
+ example: "await element(by.id('menuItem')).longPress();",
37
+ guidelines: ['If the target element is not accessible, interact with its container or the most relevant parent element.']
38
+ },
39
+ {
40
+ signature: 'typeText(text: string)',
41
+ description: 'Types text into a text field',
42
+ example: "await element(by.id('usernameInput')).typeText('myusername');",
43
+ guidelines: ['Typing can only be done on text field elements.']
44
+ },
45
+ {
46
+ signature: 'replaceText(text: string)',
47
+ description: 'Replaces text in a text field',
48
+ example: "await element(by.id('usernameInput')).replaceText('newusername');",
49
+ guidelines: ['Use this to replace existing text in a field.']
50
+ },
51
+ {
52
+ signature: 'clearText()',
53
+ description: 'Clears text from a text field',
54
+ example: "await element(by.id('usernameInput')).clearText();",
55
+ guidelines: ['Use this to clear existing text from a field.']
56
+ },
57
+ {
58
+ signature: 'scrollTo(edge: Direction, startPositionX?: number, startPositionY?: number)',
59
+ description: 'Scrolls to an edge',
60
+ example: "await element(by.id('scrollView')).scrollTo('bottom');",
61
+ guidelines: ['Scrolling must be done only on scroll-view elements.']
62
+ },
63
+ {
64
+ signature: 'scrollToIndex(index: Number)',
65
+ description: 'Scrolls to a specific index',
66
+ example: "await element(by.id('flatList')).scrollToIndex(5);",
67
+ guidelines: ['Use this for scrolling to a specific item in a list.']
68
+ },
69
+ {
70
+ signature: 'adjustSliderToPosition(newPosition: number)',
71
+ description: 'Adjusts slider to a position',
72
+ example: "await element(by.id('slider')).adjustSliderToPosition(0.75);",
73
+ guidelines: ['The position should be a number between 0 and 1.']
74
+ },
75
+ {
76
+ signature: 'setColumnToValue(column: number, value: string)',
77
+ description: 'Sets picker view column to a value (iOS only)',
78
+ example: "await element(by.id('datePicker')).setColumnToValue(1, '2023');",
79
+ guidelines: ['This is only available on iOS.']
80
+ },
81
+ {
82
+ signature: 'performAccessibilityAction(actionName: string)',
83
+ description: 'Triggers an accessibility action',
84
+ example: "await element(by.id('button')).performAccessibilityAction('longpress');",
85
+ guidelines: ['Use the provided value from the intent and do not change it.']
86
+ },
87
+ {
88
+ signature: 'swipe(direction: Direction, speed?: Speed, percentage?: number)',
89
+ description: 'Swipes in the specified direction',
90
+ example: "await element(by.id('card')).swipe('left', 'fast');",
91
+ guidelines: ['Use this for swiping gestures on elements.']
92
+ },
93
+ {
94
+ signature: 'pinch(scale: number, speed?: Speed, angle?: number)',
95
+ description: 'Performs a pinch gesture (iOS only)',
96
+ example: "await element(by.id('image')).pinch(0.5);",
97
+ guidelines: ['This is only available on iOS. Scale < 1 zooms out, scale > 1 zooms in.']
98
+ }
99
+ ],
100
+ assertions: [
101
+ {
102
+ signature: 'toBeVisible()',
103
+ description: 'Asserts that the element is visible',
104
+ example: "await expect(element(by.id('loginButton'))).toBeVisible();",
105
+ guidelines: ['Use this to check if an element is visible on the screen.']
106
+ },
107
+ {
108
+ signature: 'toExist()',
109
+ description: 'Asserts that the element exists',
110
+ example: "await expect(element(by.id('username'))).toExist();",
111
+ guidelines: ['Use this to check if an element exists in the hierarchy, even if not visible.']
112
+ },
113
+ {
114
+ signature: 'toHaveText(text: string)',
115
+ description: 'Asserts that the element has the specified text',
116
+ example: "await expect(element(by.id('label'))).toHaveText('Hello, World!');",
117
+ guidelines: ['Use this to check the text content of an element.']
118
+ },
119
+ {
120
+ signature: 'toHaveValue(value: string)',
121
+ description: 'Asserts that the element has the specified value',
122
+ example: "await expect(element(by.id('slider'))).toHaveValue('0.5');",
123
+ guidelines: ['Use this to check the value of an element.']
124
+ }
125
+ ]
126
+ };
127
+ }
128
+
129
+ async captureSnapshotImage() {
130
+ const fileName = `snapshot_${Date.now()}.png`;
131
+ await device.takeScreenshot(fileName);
132
+ return fileName;
133
+ }
134
+
135
+ async captureViewHierarchyString() {
136
+ return device.generateViewHierarchyXml();
137
+ }
138
+ }
139
+
140
+ module.exports = DetoxDriver;
@@ -20,6 +20,7 @@ class RuntimeDevice {
20
20
  'clearKeychain',
21
21
  'disableSynchronization',
22
22
  'enableSynchronization',
23
+ 'generateViewHierarchyXml',
23
24
  'installApp',
24
25
  'installUtilBinaries',
25
26
  'launchApp',
@@ -195,6 +196,10 @@ class RuntimeDevice {
195
196
  return this.deviceDriver.captureViewHierarchy(name);
196
197
  }
197
198
 
199
+ async generateViewHierarchyXml(shouldInjectTestIds = false) {
200
+ return await this.deviceDriver.generateViewHierarchyXml(shouldInjectTestIds);
201
+ }
202
+
198
203
  async sendToHome() {
199
204
  await this.deviceDriver.sendToHome();
200
205
  await this.deviceDriver.waitForBackground();
@@ -222,6 +222,10 @@ class DeviceDriverBase {
222
222
  async captureViewHierarchy() {
223
223
  return '';
224
224
  }
225
+
226
+ async generateViewHierarchyXml(_shouldInjectTestIds) {
227
+ return '';
228
+ }
225
229
  }
226
230
 
227
231
  module.exports = DeviceDriverBase;
@@ -245,6 +245,11 @@ class AndroidDriver extends DeviceDriverBase {
245
245
  await this.invocationManager.execute(call);
246
246
  }
247
247
 
248
+ async generateViewHierarchyXml(shouldInjectTestIds) {
249
+ const hierarchy = await this.invocationManager.execute(DetoxApi.generateViewHierarchyXml(shouldInjectTestIds));
250
+ return hierarchy.result;
251
+ }
252
+
248
253
  _getAppInstallPaths(_appBinaryPath, _testBinaryPath) {
249
254
  const appBinaryPath = getAbsoluteBinaryPath(_appBinaryPath);
250
255
  const testBinaryPath = _testBinaryPath ? getAbsoluteBinaryPath(_testBinaryPath) : this._getTestApkPath(appBinaryPath);
@@ -194,6 +194,10 @@ class SimulatorDriver extends IosDriver {
194
194
  return viewHierarchyURL;
195
195
  }
196
196
 
197
+ async generateViewHierarchyXml(shouldInjectTestIds) {
198
+ return await this.client.generateViewHierarchyXml({ shouldInjectTestIds });
199
+ }
200
+
197
201
  async setStatusBar(flags) {
198
202
  await this._applesimutils.statusBarOverride(this.udid, flags);
199
203
  }
@@ -1 +0,0 @@
1
- 94c7ef8a28dc964b657eea2fe3b976a0
@@ -1 +0,0 @@
1
- b7253a70da80514f9fb458066ba45f5aeda16686
@@ -1 +0,0 @@
1
- 21b3215e69149679168a08bfa855a0089455f54ba9ab883ef1b268c001ce2216
@@ -1 +0,0 @@
1
- a119637d941ad18e51e753ea1ee6a3cd6d068166cafb54cb0474373f48e84647875c742c4c54670af01f8d3f055c3e1907945b8811c5c1206aec0152c4186460
@@ -1 +0,0 @@
1
- f8f2a2bd622fadc1baf0d5be4f21622f
@@ -1 +0,0 @@
1
- 3ce2c636fb75e7758525c444e9b19f7a69ff7aa2
@@ -1 +0,0 @@
1
- b6d5ba6221494632ff63d50785be381add4d688d167e1696d3f027d76a768042
@@ -1 +0,0 @@
1
- 0b22922e5fb5f7c8d8851661cf96982870f7a942939f5648ad4f72da1711515be0a6198fd9d789c2d45deedb0129452a6167f7068ab68b92c39d890fd2e467aa
@@ -1 +0,0 @@
1
- 48e491ac5e2166bc14b836ac291d9a10
@@ -1 +0,0 @@
1
- 874588e8c8d28d2cf1ef211ece43cb92dd4dd0ba
@@ -1 +0,0 @@
1
- 69b0bb114b00a7419670658bc0326c64dde8b2b4a4ec49c540de1f9186d8c324
@@ -1 +0,0 @@
1
- 472e53824831f47311d2848f3b6093d269f5dab58e01bded5ce08b3421e80916336d4f5001e8b9e1409b1a1e214023fc62de45d46931647aaee268af3c858947
@@ -1 +0,0 @@
1
- 208d53855f5405b6ca2ec1a57b08aa8a
@@ -1 +0,0 @@
1
- 4039b32649b959622a11f2da5640e3cd05d257da
@@ -1 +0,0 @@
1
- 1f35717c6a33f825af51b62048b2d63c8a8f9d1de927f8226af66b33f38ee0ea
@@ -1 +0,0 @@
1
- 2ffecf597779fcbe167e95d8bd43ae895f3484fe4f755624894f1be22e840242b8d6a57edb20996d36276757ea11a41c22cc892517e3a70a5f6952726b6c7032
@@ -1 +0,0 @@
1
- d271489c0570c8529c634b79843bc0a0
@@ -1 +0,0 @@
1
- e0bceb0063fccfb5b5a0c173587a33720eca9d8d
@@ -1 +0,0 @@
1
- 328f2d83c0c54a3ac3e8cc0aadadd27f622c79d5c6f4490c2852ca8ef5f76b8f
@@ -1 +0,0 @@
1
- 22fe1aa0a7686ab99c4c5cb81bbf8c16e35c79039fc2dc070c9c6c14687042cd3182cc554ee0da4c48b5ec8330fa98b9887a8e7cf06f04c66f30612e919cbc2a
@@ -1 +0,0 @@
1
- 3e46d6dfb8ac381ce01685ebc04694e4
@@ -1 +0,0 @@
1
- 08e1e7773a8fb58ce4acac2310157b186767b361
@@ -1 +0,0 @@
1
- 29a7dee48d0b9f065ae740b3da5e2b5f57d208ac7ad856947f8b94db980d431a
@@ -1 +0,0 @@
1
- ad4d04e5db6c1f7d4430107cdbf7a52c3f9da6e5b53c3111288bf328ea8c0598a9fc481681781a7119994457bc0a1ff3968b5fdf38d5d1a36e40363be4cbbbe7