detox 19.3.1 → 19.4.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/Detox-android/com/wix/detox/19.4.0-alpha.0/detox-19.4.0-alpha.0-javadoc.jar +0 -0
  2. package/Detox-android/com/wix/detox/19.4.0-alpha.0/detox-19.4.0-alpha.0-javadoc.jar.md5 +1 -0
  3. package/Detox-android/com/wix/detox/19.4.0-alpha.0/detox-19.4.0-alpha.0-javadoc.jar.sha1 +1 -0
  4. package/Detox-android/com/wix/detox/19.4.0-alpha.0/detox-19.4.0-alpha.0-javadoc.jar.sha256 +1 -0
  5. package/Detox-android/com/wix/detox/19.4.0-alpha.0/detox-19.4.0-alpha.0-javadoc.jar.sha512 +1 -0
  6. package/Detox-android/com/wix/detox/{19.3.1/detox-19.3.1-sources.jar → 19.4.0-alpha.0/detox-19.4.0-alpha.0-sources.jar} +0 -0
  7. package/Detox-android/com/wix/detox/19.4.0-alpha.0/detox-19.4.0-alpha.0-sources.jar.md5 +1 -0
  8. package/Detox-android/com/wix/detox/19.4.0-alpha.0/detox-19.4.0-alpha.0-sources.jar.sha1 +1 -0
  9. package/Detox-android/com/wix/detox/19.4.0-alpha.0/detox-19.4.0-alpha.0-sources.jar.sha256 +1 -0
  10. package/Detox-android/com/wix/detox/19.4.0-alpha.0/detox-19.4.0-alpha.0-sources.jar.sha512 +1 -0
  11. package/Detox-android/com/wix/detox/19.4.0-alpha.0/detox-19.4.0-alpha.0.aar +0 -0
  12. package/Detox-android/com/wix/detox/19.4.0-alpha.0/detox-19.4.0-alpha.0.aar.md5 +1 -0
  13. package/Detox-android/com/wix/detox/19.4.0-alpha.0/detox-19.4.0-alpha.0.aar.sha1 +1 -0
  14. package/Detox-android/com/wix/detox/19.4.0-alpha.0/detox-19.4.0-alpha.0.aar.sha256 +1 -0
  15. package/Detox-android/com/wix/detox/19.4.0-alpha.0/detox-19.4.0-alpha.0.aar.sha512 +1 -0
  16. package/Detox-android/com/wix/detox/{19.3.1/detox-19.3.1.pom → 19.4.0-alpha.0/detox-19.4.0-alpha.0.pom} +5 -11
  17. package/Detox-android/com/wix/detox/19.4.0-alpha.0/detox-19.4.0-alpha.0.pom.md5 +1 -0
  18. package/Detox-android/com/wix/detox/19.4.0-alpha.0/detox-19.4.0-alpha.0.pom.sha1 +1 -0
  19. package/Detox-android/com/wix/detox/19.4.0-alpha.0/detox-19.4.0-alpha.0.pom.sha256 +1 -0
  20. package/Detox-android/com/wix/detox/19.4.0-alpha.0/detox-19.4.0-alpha.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/build.gradle +5 -5
  29. package/android/detox/build.gradle +23 -13
  30. package/android/detox/proguard-rules-app.pro +1 -0
  31. package/android/detox/publishing.gradle +17 -27
  32. package/android/detox/src/full/java/com/wix/detox/reactnative/ReactNativeIdlingResources.kt +1 -0
  33. package/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/uimodule/DispatchCommandOperationReflected.kt +36 -0
  34. package/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/uimodule/NativeHierarchyManagerReflected.kt +28 -0
  35. package/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/uimodule/RN66Workaround.kt +59 -0
  36. package/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/uimodule/UIManagerModuleReflected.kt +70 -0
  37. package/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/uimodule/UIModuleIdlingResource.kt +83 -0
  38. package/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/uimodule/ViewCommandOpsQueueReflected.kt +27 -0
  39. package/android/detox/src/testFull/java/com/wix/detox/reactnative/idlingresources/AsyncStorageIdlingResourceSpec.kt +1 -0
  40. package/android/detox/src/testFull/java/com/wix/detox/reactnative/idlingresources/timers/DefaultIdleInterrogationStrategySpec.kt +2 -0
  41. package/android/gradle/wrapper/gradle-wrapper.properties +1 -1
  42. package/package.json +3 -3
  43. package/src/devices/common/drivers/ios/tools/AppleSimUtils.js +1 -1
  44. package/src/utils/environment.js +2 -2
  45. package/Detox-android/com/wix/detox/19.3.1/detox-19.3.1-javadoc.jar +0 -0
  46. package/Detox-android/com/wix/detox/19.3.1/detox-19.3.1-javadoc.jar.md5 +0 -1
  47. package/Detox-android/com/wix/detox/19.3.1/detox-19.3.1-javadoc.jar.sha1 +0 -1
  48. package/Detox-android/com/wix/detox/19.3.1/detox-19.3.1-javadoc.jar.sha256 +0 -1
  49. package/Detox-android/com/wix/detox/19.3.1/detox-19.3.1-javadoc.jar.sha512 +0 -1
  50. package/Detox-android/com/wix/detox/19.3.1/detox-19.3.1-sources.jar.md5 +0 -1
  51. package/Detox-android/com/wix/detox/19.3.1/detox-19.3.1-sources.jar.sha1 +0 -1
  52. package/Detox-android/com/wix/detox/19.3.1/detox-19.3.1-sources.jar.sha256 +0 -1
  53. package/Detox-android/com/wix/detox/19.3.1/detox-19.3.1-sources.jar.sha512 +0 -1
  54. package/Detox-android/com/wix/detox/19.3.1/detox-19.3.1.aar +0 -0
  55. package/Detox-android/com/wix/detox/19.3.1/detox-19.3.1.aar.md5 +0 -1
  56. package/Detox-android/com/wix/detox/19.3.1/detox-19.3.1.aar.sha1 +0 -1
  57. package/Detox-android/com/wix/detox/19.3.1/detox-19.3.1.aar.sha256 +0 -1
  58. package/Detox-android/com/wix/detox/19.3.1/detox-19.3.1.aar.sha512 +0 -1
  59. package/Detox-android/com/wix/detox/19.3.1/detox-19.3.1.pom.md5 +0 -1
  60. package/Detox-android/com/wix/detox/19.3.1/detox-19.3.1.pom.sha1 +0 -1
  61. package/Detox-android/com/wix/detox/19.3.1/detox-19.3.1.pom.sha256 +0 -1
  62. package/Detox-android/com/wix/detox/19.3.1/detox-19.3.1.pom.sha512 +0 -1
  63. package/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/UIModuleIdlingResource.java +0 -148
@@ -0,0 +1 @@
1
+ 14335d4accfdb6db18c017d6d4c559bc
@@ -0,0 +1 @@
1
+ a79d71c2692fa83edc476d2ffa6496fbb1604763
@@ -0,0 +1 @@
1
+ 9842f3ec080250019cdc73325be798a37722e00bcde45f804980425e53ac9c2d
@@ -0,0 +1 @@
1
+ e70d36237404abd83bca254aebece2bae4eb35c9b80353c5e3b49a491a1ebea8d972d5870c3e57a8e8ce76c97a24547fc6231fce6b37f5ffa067516108cb6287
@@ -0,0 +1 @@
1
+ 1af7059a015aa9f321071ceab52be60f
@@ -0,0 +1 @@
1
+ a56771ac8e035424cc1c22a0a41dda08a172fc03
@@ -0,0 +1 @@
1
+ 3e02271c29f87482ad663a08d736c4e2614063c8b221704886bd6b7ef096eaa5
@@ -0,0 +1 @@
1
+ 16722733fee56837646224847fff8f835e029f5a17d2ae32960f99497c3cbf04f45ce1a3eb9dae92bc8ca4cbefa63e6e17600ba27ab70bace35cf5702816d6ca
@@ -0,0 +1 @@
1
+ db5438a69056782c6b65faf53f746bfe
@@ -0,0 +1 @@
1
+ 818e8057a07f4ea8145d6c0490906340ebad700d
@@ -0,0 +1 @@
1
+ 082dac5e9d4dba9ac093cb3f25b8bde915469055fe1c986a401ea65fb5f10d65
@@ -0,0 +1 @@
1
+ 878279c9e3df36b86a64f71f577138fbb7ebc9f8956e77d61c811c55d5f1f6d8cfa06750a29c2089905e1458fa0cac61c108fdacdfa89a05882c1e0dea54e077
@@ -3,7 +3,7 @@
3
3
  <modelVersion>4.0.0</modelVersion>
4
4
  <groupId>com.wix</groupId>
5
5
  <artifactId>detox</artifactId>
6
- <version>19.3.1</version>
6
+ <version>19.4.0-alpha.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>
@@ -33,31 +33,25 @@
33
33
  <dependency>
34
34
  <groupId>androidx.test.espresso</groupId>
35
35
  <artifactId>espresso-core</artifactId>
36
- <version>3.3.0</version>
36
+ <version>3.4.0</version>
37
37
  <scope>compile</scope>
38
- <exclusions>
39
- <exclusion>
40
- <groupId>com.google.code.findbugs</groupId>
41
- <artifactId>jsr305</artifactId>
42
- </exclusion>
43
- </exclusions>
44
38
  </dependency>
45
39
  <dependency>
46
40
  <groupId>androidx.test.espresso</groupId>
47
41
  <artifactId>espresso-web</artifactId>
48
- <version>3.3.0</version>
42
+ <version>3.4.0</version>
49
43
  <scope>compile</scope>
50
44
  </dependency>
51
45
  <dependency>
52
46
  <groupId>androidx.test</groupId>
53
47
  <artifactId>rules</artifactId>
54
- <version>1.2.0</version>
48
+ <version>1.4.0</version>
55
49
  <scope>compile</scope>
56
50
  </dependency>
57
51
  <dependency>
58
52
  <groupId>androidx.test.ext</groupId>
59
53
  <artifactId>junit</artifactId>
60
- <version>1.1.1</version>
54
+ <version>1.1.3</version>
61
55
  <scope>compile</scope>
62
56
  </dependency>
63
57
  <dependency>
@@ -0,0 +1 @@
1
+ a38333dfd1c07236c8b5d0eb10a08757
@@ -0,0 +1 @@
1
+ 2ddc1e10d6af2c7781ceb0ec9c668b7b90ce712b
@@ -0,0 +1 @@
1
+ 707e4c68172fbc8ec9a1f784042d111e39f11ca5717f18fa9049c2ad16a68106
@@ -0,0 +1 @@
1
+ 5b82f5611dd8d959c16d790134fa809d97fb3469108aa918179a7b26f14b016292598a3de8860d1cf4504220492db63d3d2df3b4d64face976404b6c2137b70d
@@ -3,11 +3,11 @@
3
3
  <groupId>com.wix</groupId>
4
4
  <artifactId>detox</artifactId>
5
5
  <versioning>
6
- <latest>19.3.1</latest>
7
- <release>19.3.1</release>
6
+ <latest>19.4.0-alpha.0</latest>
7
+ <release>19.4.0-alpha.0</release>
8
8
  <versions>
9
- <version>19.3.1</version>
9
+ <version>19.4.0-alpha.0</version>
10
10
  </versions>
11
- <lastUpdated>20211212121551</lastUpdated>
11
+ <lastUpdated>20211223152137</lastUpdated>
12
12
  </versioning>
13
13
  </metadata>
@@ -1 +1 @@
1
- a09e7c7ea6fad8e6d449ba92bffe9295
1
+ 3d2fd5ee475a78c4a312206c7c654bde
@@ -1 +1 @@
1
- 1e3977640e5bda05cc649dabe540e16031ac9269
1
+ 850604928677367ba747042ab7194f3f2f145fe6
@@ -1 +1 @@
1
- ada0c25b3200e63c5afd385b24d107c2ee86a70ef0b75ff4a8473ceec45a6901
1
+ 9ddbd8a3557e167a80a211bf2f3345f7ef8354160256d70c5afec52ce3080688
@@ -1 +1 @@
1
- 7a60028c1ad23d8c376721100f29339307471c493aa0bd7bf3c54ba51b0cf0917b417c25708d5a4635dfc9705e992bcd9261e2c48e460eefdbda59056e24ef0e
1
+ 893c523faf3edff5a02bf0d1d6f5cac1c55225690ac62bd820ed02a0ef6ae268fd96549a1edbeba8679863edccbe00fb391885beabefde6f434632c273753ba0
package/Detox-ios-src.tbz CHANGED
Binary file
package/Detox-ios.tbz CHANGED
Binary file
@@ -2,10 +2,10 @@ buildscript {
2
2
  ext {
3
3
  isOfficialDetoxLib = true
4
4
  kotlinVersion = '1.2.0'
5
- dokkaVersion = '0.9.18'
6
- buildToolsVersion = '29.0.3'
7
- compileSdkVersion = 29
8
- targetSdkVersion = 29
5
+ dokkaVersion = '1.6.0'
6
+ buildToolsVersion = '30.0.2'
7
+ compileSdkVersion = 31
8
+ targetSdkVersion = 31
9
9
  minSdkVersion = 21
10
10
  }
11
11
  ext.detoxKotlinVersion = ext.kotlinVersion
@@ -15,7 +15,7 @@ buildscript {
15
15
  google()
16
16
  }
17
17
  dependencies {
18
- classpath 'com.android.tools.build:gradle:4.1.0'
18
+ classpath 'com.android.tools.build:gradle:4.2.2'
19
19
  classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"
20
20
  classpath "org.jetbrains.dokka:dokka-gradle-plugin:$dokkaVersion"
21
21
 
@@ -3,9 +3,9 @@ apply plugin: 'kotlin-android'
3
3
  apply plugin: 'kotlin-android-extensions'
4
4
 
5
5
  def _ext = rootProject.ext
6
- def _compileSdkVersion = _ext.has('compileSdkVersion') ? _ext.compileSdkVersion : 29
7
- def _targetSdkVersion = _ext.has('targetSdkVersion') ? _ext.targetSdkVersion : 29
8
- def _buildToolsVersion = _ext.has('buildToolsVersion') ? _ext.buildToolsVersion : '29.0.3'
6
+ def _compileSdkVersion = _ext.has('compileSdkVersion') ? _ext.compileSdkVersion : 31
7
+ def _targetSdkVersion = _ext.has('targetSdkVersion') ? _ext.targetSdkVersion : 31
8
+ def _buildToolsVersion = _ext.has('buildToolsVersion') ? _ext.buildToolsVersion : '30.0.2'
9
9
  def _minSdkVersion = _ext.has('minSdkVersion') ? _ext.minSdkVersion : 18
10
10
  def _kotlinVersion = _ext.has('detoxKotlinVersion') ? _ext.detoxKotlinVersion : '1.2.0'
11
11
  def _kotlinStdlib = _ext.has('detoxKotlinStdlib') ? _ext.detoxKotlinStdlib : 'kotlin-stdlib-jdk8'
@@ -80,22 +80,30 @@ dependencies {
80
80
  }
81
81
 
82
82
  // androidx.test deps.
83
- // All are aligned with this release: https://developer.android.com/jetpack/androidx/releases/test#1.2.0
83
+ // All are aligned with this release: https://developer.android.com/jetpack/androidx/releases/test#1.4.0
84
84
  dependencies {
85
85
 
86
- // Versions are in-sync with the 'androidx-test-1.2.0' release/tag of the android-test github repo,
87
- // used by the Detox generator. See https://github.com/android/android-test/releases/tag/androidx-test-1.2.0
86
+ // Versions are in-sync with the 'androidx-test-1.4.0' release/tag of the android-test github repo,
87
+ // used by the Detox generator. See https://github.com/android/android-test/releases/tag/androidx-test-1.4.0
88
88
  // Important: Should remain so when generator tag is replaced!
89
- api('androidx.test.espresso:espresso-core:3.3.0') { // Needed all across Detox but also makes Espresso seamlessly provided to Detox users with hybrid apps/E2E-tests.
90
- exclude group: 'com.google.code.findbugs', module: 'jsr305'
89
+ api('androidx.test.espresso:espresso-core:3.4.0') {
90
+ because 'Needed all across Detox but also makes Espresso seamlessly provided to Detox users with hybrid apps/E2E-tests.'
91
+ }
92
+ api('androidx.test.espresso:espresso-web:3.4.0') {
93
+ because 'Web-View testing'
94
+ }
95
+ api('androidx.test:rules:1.4.0') {
96
+ because 'of ActivityTestRule. Needed by users *and* internally used by Detox.'
97
+ }
98
+ api('androidx.test.ext:junit:1.1.3') {
99
+ because 'Needed so as to seamlessly provide AndroidJUnit4 to Detox users. Depends on junit core.'
91
100
  }
92
- api 'androidx.test.espresso:espresso-web:3.3.0' // Web-View testing
93
- api 'androidx.test:rules:1.2.0' // Needed because of ActivityTestRule. Needed by users *and* internally used by Detox.
94
- api 'androidx.test.ext:junit:1.1.1' // Needed so as to seamlessly provide AndroidJUnit4 to Detox users. Depends on junit core.
95
101
 
96
102
  // Version is the latest; Cannot sync with the Github repo (e.g. android/android-test) because the androidx
97
103
  // packaging version of associated classes is simply not there...
98
- api 'androidx.test.uiautomator:uiautomator:2.2.0' // Needed by Detox but also makes UIAutomator seamlessly provided to Detox users with hybrid apps/E2E-tests.
104
+ api('androidx.test.uiautomator:uiautomator:2.2.0') {
105
+ because 'Needed by Detox but also makes UIAutomator seamlessly provided to Detox users with hybrid apps/E2E-tests.'
106
+ }
99
107
  }
100
108
 
101
109
  // Third-party/extension deps.
@@ -103,7 +111,9 @@ dependencies {
103
111
  implementation('com.google.android.material:material:1.2.1') {
104
112
  because 'Material components are mentioned explicitly (e.g. Slider in get-attributes handler)'
105
113
  }
106
- implementation 'org.apache.commons:commons-lang3:3.7' // Needed by invoke. Warning: Upgrading to newer versions is not seamless.
114
+ implementation('org.apache.commons:commons-lang3:3.7') {
115
+ because 'Needed by invoke. Warning: Upgrading to newer versions is not seamless.'
116
+ }
107
117
  implementation 'com.github.anrwatchdog:anrwatchdog:1.4.0'
108
118
 
109
119
  implementation fileTree(dir: '../libs', includes: ['*.jar']) // Includes: Genymotion SDK
@@ -12,3 +12,4 @@
12
12
  -keep class kotlin.collections.** { *; }
13
13
  -keep class kotlin.text.** { *; }
14
14
  -keep class kotlin.io.** { *; }
15
+ -keep class okhttp3.** { *; }
@@ -85,41 +85,31 @@ initPublishing()
85
85
  * Dokka is the official javadoc equivalent that supports kotlin KDoc (see https://github.com/Kotlin/dokka)
86
86
  */
87
87
 
88
- dokka {
89
- // Note: this only remains valid as long as we don't move kotlin code to src/main/kotlin instead of src/main/java.
90
- // Will have to keep this up to date if we decided to do so.
91
- sourceDirs = files(android.sourceSets.main.java.srcDirs)
92
-
93
- // Nothing to add to what kotlinTasks() resolves on its own
94
- // classpath = []
95
- // classpath += files(android.bootClasspath)
96
- // classpath += files(project.configurations.getByName('compile').asList())
97
- // classpath += files(android.libraryVariants.collect { variant ->
98
- // variant.javaCompile.classpath.files
99
- // }.flatten())
100
-
101
- reportUndocumented = false
102
- skipEmptyPackages = true
103
-
104
- outputFormat = 'javadoc' // https://github.com/Kotlin/dokka#output-formats
105
- outputDirectory = "$buildDir/dokkaDoc" // Temp 'exploded' dir for .jar creation (i.e. by dokkaDocJar task)
106
-
107
- def suppressedPackages = ["android_libs", "com.wix.detox.espresso.common.annot"]
108
- for (String packagePrefix: suppressedPackages) {
109
- packageOptions {
110
- prefix = packagePrefix
111
- suppress = true
88
+ tasks.named("dokkaJavadoc") {
89
+ File dokkaDoc = new File("$buildDir/dokkaDoc");
90
+ outputDirectory.set(dokkaDoc)
91
+ dokkaSourceSets {
92
+ named("main") {
93
+ sourceRoots.from(android.sourceSets.main.java.srcDirs)
94
+ reportUndocumented.set(false)
95
+ skipEmptyPackages.set(true)
96
+ def suppressedPackages = ["android_libs", "com.wix.detox.espresso.common.annot"]
97
+ for (String packagePrefix : suppressedPackages) {
98
+ packageOptions {
99
+ prefix = packagePrefix
100
+ suppress = true
101
+ }
102
+ }
112
103
  }
113
104
  }
114
-
105
+ }
115
106
  // Side note / TODO:
116
107
  // Dokka outputs R and BuildConfig; currently, there's nothing to do about it, as issues such as
117
108
  // this on - https://github.com/Kotlin/dokka/issues/419 are still open :-/
118
109
  // We might want to revisit this in the future -- see if they've decided to export a custom classes
119
110
  // suppression config var or something.
120
- }
121
111
 
122
- task dokkaDocJar(type: Jar, dependsOn: dokka) {
112
+ task dokkaDocJar(type: Jar, dependsOn: dokkaJavadoc) {
123
113
  from "$buildDir/dokkaDoc"
124
114
  classifier = 'javadoc'
125
115
  }
@@ -9,6 +9,7 @@ import com.wix.detox.LaunchArgs
9
9
  import com.wix.detox.reactnative.idlingresources.*
10
10
  import com.wix.detox.reactnative.idlingresources.timers.TimersIdlingResource
11
11
  import com.wix.detox.reactnative.idlingresources.timers.getInterrogationStrategy
12
+ import com.wix.detox.reactnative.idlingresources.uimodule.UIModuleIdlingResource
12
13
  import org.joor.Reflect
13
14
  import org.joor.ReflectException
14
15
  import java.util.Set
@@ -0,0 +1,36 @@
1
+ package com.wix.detox.reactnative.idlingresources.uimodule
2
+
3
+ import android.util.Log
4
+ import com.wix.detox.common.DetoxLog
5
+ import org.joor.Reflect
6
+ import org.joor.ReflectException
7
+
8
+ private const val FIELD_TAG = "mTag"
9
+ private const val FIELD_NUM_RETRIES = "numRetries"
10
+ private const val FIELD_COMMAND = "mCommand"
11
+
12
+ class DispatchCommandOperationReflected(val instance: Any?) {
13
+ val tag: Int?
14
+ get() = try {
15
+ Reflect.on(instance).field(FIELD_TAG).get<Int>()
16
+ } catch (e: ReflectException) {
17
+ Log.e(DetoxLog.LOG_TAG, "failed to get $FIELD_TAG ", e)
18
+ null
19
+ }
20
+
21
+ val numRetries: Int?
22
+ get() = try {
23
+ Reflect.on(instance).field(FIELD_NUM_RETRIES).get<Int>()
24
+ } catch (e: ReflectException) {
25
+ Log.e(DetoxLog.LOG_TAG, "failed to get $FIELD_NUM_RETRIES ", e)
26
+ 0
27
+ }
28
+
29
+ val viewCommand: String?
30
+ get() = try {
31
+ Reflect.on(instance).field(FIELD_COMMAND).get<String>()
32
+ } catch (e: ReflectException) {
33
+ Log.e(DetoxLog.LOG_TAG, "failed to get $FIELD_COMMAND ", e)
34
+ null
35
+ }
36
+ }
@@ -0,0 +1,28 @@
1
+ package com.wix.detox.reactnative.idlingresources.uimodule
2
+
3
+ import android.util.Log
4
+ import android.view.View
5
+ import com.facebook.react.uimanager.NativeViewHierarchyManager
6
+ import com.facebook.react.uimanager.UIViewOperationQueue
7
+ import com.wix.detox.common.DetoxLog.Companion.LOG_TAG
8
+ import org.joor.Reflect
9
+ import org.joor.ReflectException
10
+
11
+ private const val FIELD_NATIVE_HIERARCHY_MANAGER = "mNativeViewHierarchyManager"
12
+
13
+ class NativeHierarchyManagerReflected(uIViewOperationQueueInstance: UIViewOperationQueue) {
14
+ private val reflected = Reflect.on(uIViewOperationQueueInstance)
15
+
16
+ fun getViewClass(tag: Int): View? {
17
+ return nativeViewHierarchyManager()?.resolveView(tag)
18
+ }
19
+
20
+ private fun nativeViewHierarchyManager(): NativeViewHierarchyManager? {
21
+ return try {
22
+ reflected.field(FIELD_NATIVE_HIERARCHY_MANAGER).get<NativeViewHierarchyManager>()
23
+ } catch(e: ReflectException) {
24
+ Log.e(LOG_TAG, "failed to get $FIELD_NATIVE_HIERARCHY_MANAGER ", e.cause)
25
+ null
26
+ }
27
+ }
28
+ }
@@ -0,0 +1,59 @@
1
+ package com.wix.detox.reactnative.idlingresources.uimodule
2
+
3
+ import android.util.Log
4
+ import android.view.View
5
+ import com.wix.detox.common.DetoxLog.Companion.LOG_TAG
6
+ import java.lang.ref.WeakReference
7
+
8
+ private const val NUM_TIMES_BEFORE_NOTIFY_IDLE = 10
9
+ private const val SET_NATIVE_VALUE = "setNativeValue"
10
+ private const val CLASS_REACT_SWITCH = "com.facebook.react.views.switchview.ReactSwitch"
11
+
12
+ class RN66Workaround {
13
+ private var timesStuckQueueDetected = 0
14
+ private var stuckOperation: WeakReference<Any?>? = null
15
+
16
+ // This is a workaround for https://github.com/facebook/react-native/issues/32594
17
+ // uses duck typing heuristics to determine that this is probably the stuck Switch operation and if so, ignores it
18
+ fun isScarceUISwitchCommandStuckInQueue(uiManagerModuleReflected: UIManagerModuleReflected): Boolean {
19
+ var isStuckSwitchOperation = false
20
+
21
+ if (uiManagerModuleReflected.getUIOpsCount() == 1) {
22
+ val nextUIOperation = uiManagerModuleReflected.getNextUIOpReflected()
23
+ val view = getUIOpView(uiManagerModuleReflected, nextUIOperation)
24
+ val isReactSwitch = isReactSwitch(view)
25
+ val hasOneRetryIncremented = nextUIOperation?.numRetries == 1
26
+ val isSetNativeValueCommand = (nextUIOperation?.viewCommand ?: "") == SET_NATIVE_VALUE
27
+
28
+ if (isReactSwitch && hasOneRetryIncremented && isSetNativeValueCommand) {
29
+ if (stuckOperation?.get() == nextUIOperation?.instance) {
30
+ timesStuckQueueDetected++
31
+ } else {
32
+ stuckOperation = WeakReference(nextUIOperation?.instance)
33
+ timesStuckQueueDetected = 0
34
+ }
35
+ }
36
+
37
+ if (timesStuckQueueDetected >= NUM_TIMES_BEFORE_NOTIFY_IDLE) {
38
+ isStuckSwitchOperation = true
39
+ }
40
+ } else {
41
+ timesStuckQueueDetected = 0
42
+ }
43
+ return isStuckSwitchOperation
44
+ }
45
+
46
+ private fun getUIOpView(uiManagerModuleReflected: UIManagerModuleReflected, uiOperation: DispatchCommandOperationReflected?): View? {
47
+ val nativeViewHierarchyManager = uiManagerModuleReflected.nativeViewHierarchyManager() ?: return null
48
+ val tag = uiOperation?.tag ?: return null
49
+ return nativeViewHierarchyManager.getViewClass(tag)
50
+ }
51
+
52
+ private fun isReactSwitch(view: View?) = try {
53
+ val ReactSwitchClass: Class<*> = Class.forName(CLASS_REACT_SWITCH)
54
+ if (view != null) ReactSwitchClass.isAssignableFrom(view.javaClass) else false
55
+ } catch (e: ClassNotFoundException) {
56
+ Log.e(LOG_TAG, "failed to get $CLASS_REACT_SWITCH class ", e.cause)
57
+ false
58
+ }
59
+ }
@@ -0,0 +1,70 @@
1
+ package com.wix.detox.reactnative.idlingresources.uimodule
2
+
3
+ import android.util.Log
4
+ import com.facebook.react.bridge.ReactContext
5
+ import com.facebook.react.uimanager.UIViewOperationQueue
6
+ import com.wix.detox.common.DetoxLog.Companion.LOG_TAG
7
+ import org.joor.Reflect
8
+
9
+ private const val CLASS_UI_MANAGER_MODULE = "com.facebook.react.uimanager.UIManagerModule"
10
+ private const val METHOD_GET_NATIVE_MODULE = "getNativeModule"
11
+ private const val METHOD_GET_UI_IMPLEMENTATION = "getUIImplementation"
12
+ private const val FIELD_UI_OPERATION_QUEUE = "mOperationsQueue"
13
+ private const val FIELD_DISPATCH_RUNNABLES = "mDispatchUIRunnables"
14
+ private const val FIELD_DISPATCH_RUNNABLES_LOCK = "mDispatchRunnablesLock"
15
+ private const val FIELD_NON_BATCHED_OPS = "mNonBatchedOperations"
16
+ private const val FIELD_NON_BATCHED_OPS_LOCK = "mNonBatchedOperationsLock"
17
+ private const val METHOD_IS_EMPTY = "isEmpty"
18
+
19
+ class UIManagerModuleReflected(private val reactContext: ReactContext) {
20
+
21
+ fun getUIOpsCount(): Int = (viewCommandOperations()?.size ?: 0)
22
+ fun getNextUIOpReflected() = viewCommandOperations()?.firstCommandReflected()
23
+
24
+ fun nativeViewHierarchyManager(): NativeHierarchyManagerReflected? =
25
+ getUIOperationQueue()?.let {
26
+ NativeHierarchyManagerReflected(it)
27
+ }
28
+
29
+ fun isRunnablesListEmpty(): Boolean =
30
+ getUIOperationQueue()?.let {
31
+ synchronized(Reflect.on(it).field(FIELD_DISPATCH_RUNNABLES_LOCK).get()) {
32
+ Reflect.on(it)
33
+ .field(FIELD_DISPATCH_RUNNABLES)
34
+ .call(METHOD_IS_EMPTY).get<Boolean>()
35
+ }
36
+ } ?: true
37
+
38
+ fun isNonBatchOpsEmpty(): Boolean =
39
+ getUIOperationQueue()?.let {
40
+ synchronized(Reflect.on(it).field(FIELD_NON_BATCHED_OPS_LOCK).get()) {
41
+ Reflect.on(it)
42
+ .field(FIELD_NON_BATCHED_OPS)
43
+ .call(METHOD_IS_EMPTY).get<Boolean>()
44
+ }
45
+ } ?: true
46
+
47
+ fun isOperationQueueEmpty(): Boolean =
48
+ getUIOperationQueue()?.let {
49
+ Reflect.on(it).call(METHOD_IS_EMPTY).get<Boolean>()
50
+ } ?: true
51
+
52
+ private fun viewCommandOperations(): ViewCommandOpsQueueReflected? =
53
+ getUIOperationQueue()?.let {
54
+ ViewCommandOpsQueueReflected(it)
55
+ }
56
+
57
+
58
+ private fun getUIOperationQueue(): UIViewOperationQueue? =
59
+ try {
60
+ val uiModuleClass = Class.forName(CLASS_UI_MANAGER_MODULE)
61
+ Reflect.on(reactContext)
62
+ .call(METHOD_GET_NATIVE_MODULE, uiModuleClass)
63
+ .call(METHOD_GET_UI_IMPLEMENTATION)
64
+ .field(FIELD_UI_OPERATION_QUEUE)
65
+ .get()
66
+ } catch (e: Exception) {
67
+ Log.e(LOG_TAG, "failed to get $CLASS_UI_MANAGER_MODULE instance ", e)
68
+ null
69
+ }
70
+ }
@@ -0,0 +1,83 @@
1
+ package com.wix.detox.reactnative.idlingresources.uimodule
2
+
3
+ import android.util.Log
4
+ import android.view.Choreographer
5
+ import androidx.test.espresso.IdlingResource.ResourceCallback
6
+ import com.facebook.react.bridge.ReactContext
7
+ import com.wix.detox.reactnative.helpers.RNHelpers
8
+ import com.wix.detox.reactnative.idlingresources.DetoxBaseIdlingResource
9
+ import com.wix.detox.reactnative.idlingresources.IdlingResourceDescription
10
+ import org.joor.ReflectException
11
+
12
+ /**
13
+ * Espresso IdlingResource for React Native's UI Module.
14
+ * Hooks up to React Native internals to grab the pending ui operations from it.
15
+ */
16
+ class UIModuleIdlingResource(private val reactContext: ReactContext)
17
+ : DetoxBaseIdlingResource(), Choreographer.FrameCallback {
18
+
19
+ private val rn66workaround = RN66Workaround()
20
+ private val uiManagerModuleReflected = UIManagerModuleReflected(reactContext)
21
+ private var callback: ResourceCallback? = null
22
+
23
+ override fun getName(): String = UIModuleIdlingResource::class.java.name
24
+ override fun getDescription() =
25
+ IdlingResourceDescription.Builder()
26
+ .name("ui")
27
+ .addDescription("reason", "UI rendering activity")
28
+ .build()
29
+
30
+ override fun checkIdle(): Boolean {
31
+ try {
32
+ if (!reactContext.hasActiveCatalystInstance()) {
33
+ Log.e(LOG_TAG, "No active CatalystInstance. Should never see this.")
34
+ return false
35
+ }
36
+
37
+ if (RNHelpers.getNativeModule(reactContext, "com.facebook.react.uimanager.UIManagerModule") == null) {
38
+ notifyIdle()
39
+ return true
40
+ }
41
+
42
+ val runnablesAreEmpty = uiManagerModuleReflected.isRunnablesListEmpty()
43
+ val nonBatchesOpsEmpty = uiManagerModuleReflected.isNonBatchOpsEmpty()
44
+ var operationQueueEmpty = uiManagerModuleReflected.isOperationQueueEmpty()
45
+
46
+ if (!operationQueueEmpty) {
47
+ operationQueueEmpty = rn66workaround.isScarceUISwitchCommandStuckInQueue(uiManagerModuleReflected)
48
+ }
49
+
50
+ if (runnablesAreEmpty && nonBatchesOpsEmpty && operationQueueEmpty) {
51
+ notifyIdle()
52
+ return true
53
+ }
54
+
55
+ Log.i(LOG_TAG, "UIManagerModule is busy")
56
+ Choreographer.getInstance().postFrameCallback(this)
57
+ return false
58
+ } catch (e: ReflectException) {
59
+ Log.e(LOG_TAG, "Can't set up RN UIModule listener", e.cause)
60
+ }
61
+ notifyIdle()
62
+ return true
63
+ }
64
+
65
+ override fun registerIdleTransitionCallback(callback: ResourceCallback) {
66
+ this.callback = callback
67
+ Choreographer.getInstance().postFrameCallback(this)
68
+ }
69
+
70
+ override fun doFrame(frameTimeNanos: Long) {
71
+ isIdleNow
72
+ }
73
+
74
+ override fun notifyIdle() {
75
+ callback?.run {
76
+ onTransitionToIdle()
77
+ }
78
+ }
79
+
80
+ companion object {
81
+ private const val LOG_TAG = "Detox"
82
+ }
83
+ }
@@ -0,0 +1,27 @@
1
+ package com.wix.detox.reactnative.idlingresources.uimodule
2
+
3
+ import android.util.Log
4
+ import com.facebook.react.uimanager.UIViewOperationQueue
5
+ import com.wix.detox.common.DetoxLog.Companion.LOG_TAG
6
+ import org.joor.Reflect
7
+ import org.joor.ReflectException
8
+
9
+ private const val FIELD_VIEW_COMMAND_OPERATIONS = "mViewCommandOperations"
10
+
11
+ class ViewCommandOpsQueueReflected(uiViewOperationQueueInstance: UIViewOperationQueue) {
12
+ private val instance = Reflect.on(uiViewOperationQueueInstance)
13
+
14
+ val size: Int?
15
+ get() = viewCommandOperations()?.size
16
+
17
+ fun firstCommandReflected() = DispatchCommandOperationReflected(firstCommand())
18
+
19
+ private fun firstCommand() = viewCommandOperations()?.elementAt(0)
20
+ private fun viewCommandOperations(): Collection<Any>? =
21
+ try {
22
+ instance.field(FIELD_VIEW_COMMAND_OPERATIONS).get<Collection<Any>>()
23
+ } catch(e: ReflectException) {
24
+ Log.e(LOG_TAG, "could not get reflected field mViewCommandOperations ", e)
25
+ null
26
+ }
27
+ }
@@ -16,6 +16,7 @@ private class AsyncStorageModuleStub: NativeModule {
16
16
  override fun initialize() {}
17
17
  override fun canOverrideExistingModule() = false
18
18
  override fun onCatalystInstanceDestroy() {}
19
+ override fun invalidate() {}
19
20
  }
20
21
 
21
22
  class AsyncStorageIdlingResourceSpec: Spek({
@@ -22,6 +22,8 @@ class TimersNativeModuleStub : NativeModule {
22
22
  val mTimerGuard = "Lock-Mock"
23
23
 
24
24
  override fun onCatalystInstanceDestroy() {}
25
+ override fun invalidate() {}
26
+
25
27
  override fun getName(): String = "TimersNativeModuleStub"
26
28
  override fun canOverrideExistingModule() = false
27
29
  override fun initialize() {}
@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
3
3
  distributionPath=wrapper/dists
4
4
  zipStoreBase=GRADLE_USER_HOME
5
5
  zipStorePath=wrapper/dists
6
- distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip
6
+ distributionUrl=https\://services.gradle.org/distributions/gradle-6.9-all.zip
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": "19.3.1",
4
+ "version": "19.4.0-alpha.0",
5
5
  "bin": {
6
6
  "detox": "local-cli/cli.js"
7
7
  },
@@ -48,7 +48,7 @@
48
48
  "mocha": ">=6.0.0",
49
49
  "mockdate": "^2.0.1",
50
50
  "prettier": "1.7.0",
51
- "react-native": "0.64.1",
51
+ "react-native": "0.66.1",
52
52
  "react-native-codegen": "^0.0.8",
53
53
  "typescript": "^4.5.2",
54
54
  "wtfnode": "^0.9.1"
@@ -171,5 +171,5 @@
171
171
  }
172
172
  }
173
173
  },
174
- "gitHead": "97ac5df9e482fd12cfd1613d51ae496281060389"
174
+ "gitHead": "542893790005eeca88614955e02bbb2f26c1d073"
175
175
  }
@@ -344,7 +344,7 @@ class AppleSimUtils {
344
344
  }
345
345
 
346
346
  const cmdArgs = quote(_.flatten(this._mergeLaunchArgs(launchArgs, languageAndLocale)));
347
- let launchBin = `SIMCTL_CHILD_DYLD_INSERT_LIBRARIES="${dylibs}" ` +
347
+ let launchBin = `SIMCTL_CHILD_NSZombieEnabled=YES SIMCTL_CHILD_DYLD_INSERT_LIBRARIES="${dylibs}" ` +
348
348
  `/usr/bin/xcrun simctl launch ${udid} ${bundleId} --args ${cmdArgs}`;
349
349
 
350
350
  const result = await exec.execWithRetriesAndLogs(launchBin, {
@@ -55,11 +55,11 @@ function getAvdDir(avdName) {
55
55
  }
56
56
 
57
57
  function getAvdManagerPath() {
58
- return path.join(getAndroidSDKPath(), 'tools', 'bin', 'avdmanager');
58
+ return path.join(getAndroidSDKPath(), 'cmdline-tools', 'latest', 'bin', 'avdmanager');
59
59
  }
60
60
 
61
61
  function getAndroidSdkManagerPath() {
62
- return path.join(getAndroidSDKPath(), 'tools', 'bin', 'sdkmanager');
62
+ return path.join(getAndroidSDKPath(), 'cmdline-tools', 'latest', 'bin', 'sdkmanager');
63
63
  }
64
64
 
65
65
  function getAndroidEmulatorPath() {
@@ -1 +0,0 @@
1
- aa55c9b00e351521ce69399a8505e412
@@ -1 +0,0 @@
1
- 3f85c2fda9140c5b981ebd83c9b0316cdad5210a
@@ -1 +0,0 @@
1
- b24730ebdb6b47b3cd27f8195f632e1117fc46565c0d6ce684bc8c4a6a3fa15b
@@ -1 +0,0 @@
1
- b9442bd45c68c620ab97821382a095a4005326b4d1248fdb15d21f547b0f73701edd1009cdaf366c31cbf111b2a541f683e803e71f7b1951ec86480fa8bbb4a0
@@ -1 +0,0 @@
1
- 3a57b68454634485e89378b459cdce7d
@@ -1 +0,0 @@
1
- 18907b1f57b790f717095345d325c1b48730ca04
@@ -1 +0,0 @@
1
- 1522127c1dea373e9edf27a669431ba57bd1965aad9f1f30895d02a80dd55920
@@ -1 +0,0 @@
1
- 253133008032813ce6f15b399233521858dbf723911ea8a9afdf4e39886e4549cbc55cdfe89cb34c3f6e2135aab3730c7ead42a903f981d428f871b33d29e4a7
@@ -1 +0,0 @@
1
- a32fc8da8e9d97ddb6a7e33be3be4cea
@@ -1 +0,0 @@
1
- 702aded71e6e005899a7a4de7e0ebc918e1a246b
@@ -1 +0,0 @@
1
- eb0358d9b4e0e233fe61c516a7727154463639a206fa71341a5e9297147e3f2b
@@ -1 +0,0 @@
1
- c323c30943f8d8c27e1defa9a68c8af7da9f3f73b77942401692fa7f5bf99971df8b064b87a9f01544c2feb7f97c08bf95f47cd08c3e6bfddb74203a069913a9
@@ -1 +0,0 @@
1
- 4364b6e95e1a47da2cf7bf04a6d56c85
@@ -1 +0,0 @@
1
- 8e8d4e7e8e18abd8e7b67c980b95d7b1ff56536a
@@ -1 +0,0 @@
1
- 038995f2e2992c90bbb67f45e3946546961ac68ed0a5db04e17dbc8a21f1c6c8
@@ -1 +0,0 @@
1
- 2a49593c977fee87aa54ba67534f9326928b23c35d874e17ce6354cca843779bc832105732004ec5c1e36ed14c82a2db1ee378bfdf59d21753ca8dd813807c4c
@@ -1,148 +0,0 @@
1
- package com.wix.detox.reactnative.idlingresources;
2
-
3
- import java.util.ArrayList;
4
- import java.util.HashMap;
5
- import java.util.Map;
6
- import android.util.Log;
7
- import android.view.Choreographer;
8
-
9
- import org.jetbrains.annotations.NotNull;
10
- import org.joor.Reflect;
11
- import org.joor.ReflectException;
12
-
13
- import androidx.annotation.NonNull;
14
-
15
- /**
16
- * Created by simonracz on 26/07/2017.
17
- */
18
-
19
- /**
20
- * <p>
21
- * Espresso IdlingResource for React Native's UI Module.
22
- * </p>
23
- *
24
- * <p>
25
- * Hooks up to React Native internals to grab the pending ui operations from it.
26
- * </p>
27
- *
28
- * TODO Rewrite this awful, awful class
29
- */
30
- public class UIModuleIdlingResource extends DetoxBaseIdlingResource implements Choreographer.FrameCallback {
31
- private static final String LOG_TAG = "Detox";
32
-
33
- private final static String CLASS_UI_MANAGER_MODULE = "com.facebook.react.uimanager.UIManagerModule";
34
- private final static String METHOD_GET_NATIVE_MODULE = "getNativeModule";
35
- private final static String METHOD_HAS_NATIVE_MODULE = "hasNativeModule";
36
- private final static String METHOD_GET_UI_IMPLEMENTATION = "getUIImplementation";
37
- private final static String FIELD_UI_OPERATION_QUEUE = "mOperationsQueue";
38
- private final static String METHOD_IS_EMPTY = "isEmpty";
39
- private final static String FIELD_DISPATCH_RUNNABLES = "mDispatchUIRunnables";
40
- private final static String FIELD_NON_BATCHES_OPERATIONS = "mNonBatchedOperations";
41
- private final static String FIELD_CATALYST_INSTANCE = "mCatalystInstance";
42
- private final static String LOCK_RUNNABLES = "mDispatchRunnablesLock";
43
- private final static String LOCK_OPERATIONS = "mNonBatchedOperationsLock";
44
-
45
- private ResourceCallback callback;
46
- private Object reactContext;
47
-
48
- public UIModuleIdlingResource(@NonNull Object reactContext) {
49
- this.reactContext = reactContext;
50
- }
51
-
52
- @Override
53
- public String getName() {
54
- return UIModuleIdlingResource.class.getName();
55
- }
56
-
57
- @NotNull
58
- @Override
59
- public IdlingResourceDescription getDescription() {
60
- return new IdlingResourceDescription.Builder()
61
- .name("ui")
62
- .addDescription("reason", "UI rendering activity")
63
- .build();
64
- }
65
-
66
- @Override
67
- protected boolean checkIdle() {
68
- Class<?> uiModuleClass;
69
- try {
70
- uiModuleClass = Class.forName(CLASS_UI_MANAGER_MODULE);
71
- } catch (ClassNotFoundException e) {
72
- Log.e(LOG_TAG, "UIManagerModule is not on classpath.");
73
- notifyIdle();
74
- return true;
75
- }
76
-
77
- try {
78
- // reactContext.hasActiveCatalystInstance() should be always true here
79
- // if called right after onReactContextInitialized(...)
80
- if (Reflect.on(reactContext).field(FIELD_CATALYST_INSTANCE).get() == null) {
81
- Log.e(LOG_TAG, "No active CatalystInstance. Should never see this.");
82
- return false;
83
- }
84
-
85
- if (!(boolean)Reflect.on(reactContext).call(METHOD_HAS_NATIVE_MODULE, uiModuleClass).get()) {
86
- Log.e(LOG_TAG, "Can't find UIManagerModule.");
87
- notifyIdle();
88
- return true;
89
- }
90
-
91
- Object uiOperationQueue = Reflect.on(reactContext)
92
- .call(METHOD_GET_NATIVE_MODULE, uiModuleClass)
93
- .call(METHOD_GET_UI_IMPLEMENTATION)
94
- .field(FIELD_UI_OPERATION_QUEUE)
95
- .get();
96
- Object runnablesLock = Reflect.on(uiOperationQueue).field(LOCK_RUNNABLES).get();
97
- Object operationsLock = Reflect.on(uiOperationQueue).field(LOCK_OPERATIONS).get();
98
-
99
- boolean runnablesAreEmpty;
100
- boolean nonBatchesOpsEmpty;
101
- synchronized (runnablesLock) {
102
- runnablesAreEmpty = (boolean) Reflect.on(uiOperationQueue)
103
- .field(FIELD_DISPATCH_RUNNABLES)
104
- .call(METHOD_IS_EMPTY).get();
105
- }
106
- synchronized (operationsLock) {
107
- nonBatchesOpsEmpty = (boolean) Reflect.on(uiOperationQueue)
108
- .field(FIELD_NON_BATCHES_OPERATIONS)
109
- .call(METHOD_IS_EMPTY).get();
110
- }
111
-
112
- boolean isOperationQueueEmpty = (Boolean) Reflect.on(uiOperationQueue).call(METHOD_IS_EMPTY).get();
113
-
114
- if (runnablesAreEmpty && nonBatchesOpsEmpty && isOperationQueueEmpty) {
115
- notifyIdle();
116
- // Log.i(LOG_TAG, "UIManagerModule is idle.");
117
- return true;
118
- }
119
-
120
- Log.i(LOG_TAG, "UIManagerModule is busy");
121
- Choreographer.getInstance().postFrameCallback(this);
122
- return false;
123
- } catch (ReflectException e) {
124
- Log.e(LOG_TAG, "Can't set up RN UIModule listener", e.getCause());
125
- }
126
-
127
- notifyIdle();
128
- return true;
129
- }
130
-
131
- @Override
132
- public void registerIdleTransitionCallback(ResourceCallback callback) {
133
- this.callback = callback;
134
- Choreographer.getInstance().postFrameCallback(this);
135
- }
136
-
137
- @Override
138
- public void doFrame(long frameTimeNanos) {
139
- isIdleNow();
140
- }
141
-
142
- @Override
143
- protected void notifyIdle() {
144
- if (callback != null) {
145
- callback.onTransitionToIdle();
146
- }
147
- }
148
- }