@react-native-firebase/app 26.4.0 → 27.1.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 (242) hide show
  1. package/CHANGELOG.md +62 -0
  2. package/README.md +10 -27
  3. package/RNFBApp.podspec +13 -5
  4. package/android/build.gradle +3 -0
  5. package/android/src/main/java/io/invertase/firebase/common/RNFBHandleCollisionException.kt +29 -0
  6. package/android/src/main/java/io/invertase/firebase/common/RNFBHandleMap.kt +146 -0
  7. package/android/src/main/java/io/invertase/firebase/common/TaskExecutorService.kt +156 -0
  8. package/android/src/main/java/io/invertase/firebase/common/UniversalFirebaseModule.kt +44 -0
  9. package/android/src/main/java/io/invertase/firebase/common/UniversalFirebasePreferences.kt +100 -0
  10. package/android/src/reactnative/java/io/invertase/firebase/app/NativeRNFBTurboApp.kt +250 -0
  11. package/android/src/reactnative/java/io/invertase/firebase/app/ReactNativeFirebaseApp.kt +64 -0
  12. package/android/src/reactnative/java/io/invertase/firebase/app/{ReactNativeFirebaseAppInitProvider.java → ReactNativeFirebaseAppInitProvider.kt} +3 -4
  13. package/android/src/reactnative/java/io/invertase/firebase/app/ReactNativeFirebaseAppPackage.kt +47 -0
  14. package/android/src/reactnative/java/io/invertase/firebase/app/ReactNativeFirebaseAppRegistrar.kt +33 -0
  15. package/android/src/reactnative/java/io/invertase/firebase/app/ReactNativeFirebaseVersion.java +1 -1
  16. package/android/src/reactnative/java/io/invertase/firebase/common/RCTConvertFirebase.kt +185 -0
  17. package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseEvent.kt +35 -0
  18. package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseEventEmitter.kt +662 -0
  19. package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseJSON.kt +103 -0
  20. package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseMeta.kt +96 -0
  21. package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseModule.kt +140 -0
  22. package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebasePreferences.kt +109 -0
  23. package/android/src/reactnative/java/io/invertase/firebase/common/SharedUtils.kt +451 -0
  24. package/android/src/reactnative/java/io/invertase/firebase/interfaces/{ContextProvider.java → ContextProvider.kt} +8 -8
  25. package/android/src/reactnative/java/io/invertase/firebase/interfaces/{NativeError.java → NativeError.kt} +8 -8
  26. package/android/src/reactnative/java/io/invertase/firebase/interfaces/{NativeEvent.java → NativeEvent.kt} +6 -6
  27. package/android/src/reactnative/java/io/invertase/firebase/utils/NativeRNFBTurboUtils.kt +219 -0
  28. package/android/src/test/java/expo/core/ModuleRegistry.java +9 -0
  29. package/android/src/test/java/io/invertase/firebase/app/NativeRNFBTurboAppTest.java +182 -59
  30. package/android/src/test/java/io/invertase/firebase/app/ReactNativeFirebaseAppComponentsJavaCompatibilityTest.java +70 -0
  31. package/android/src/test/java/io/invertase/firebase/app/ReactNativeFirebaseAppJavaCompatibilityTest.java +60 -0
  32. package/android/src/test/java/io/invertase/firebase/app/ReactNativeFirebaseAppPackageTest.java +165 -0
  33. package/android/src/test/java/io/invertase/firebase/app/ReactNativeFirebaseAppTest.kt +167 -0
  34. package/android/src/test/java/io/invertase/firebase/common/RCTConvertFirebaseJavaCompatibilityTest.java +112 -0
  35. package/android/src/test/java/io/invertase/firebase/common/RCTConvertFirebaseTest.kt +317 -0
  36. package/android/src/test/java/io/invertase/firebase/common/RNFBHandleMapTest.kt +309 -0
  37. package/android/src/test/java/io/invertase/firebase/common/ReactNativeFirebaseEventEmitterJavaCompatibilityTest.java +176 -0
  38. package/android/src/test/java/io/invertase/firebase/common/ReactNativeFirebaseEventEmitterTest.java +143 -12
  39. package/android/src/test/java/io/invertase/firebase/common/ReactNativeFirebaseEventTest.kt +61 -0
  40. package/android/src/test/java/io/invertase/firebase/common/ReactNativeFirebaseJSONJavaCompatibilityTest.java +85 -0
  41. package/android/src/test/java/io/invertase/firebase/common/ReactNativeFirebaseJSONTest.kt +296 -0
  42. package/android/src/test/java/io/invertase/firebase/common/ReactNativeFirebaseMetaJavaCompatibilityTest.java +67 -0
  43. package/android/src/test/java/io/invertase/firebase/common/ReactNativeFirebaseMetaTest.kt +246 -0
  44. package/android/src/test/java/io/invertase/firebase/common/ReactNativeFirebaseModuleTest.kt +254 -0
  45. package/android/src/test/java/io/invertase/firebase/common/ReactNativeFirebasePreferencesJavaCompatibilityTest.java +87 -0
  46. package/android/src/test/java/io/invertase/firebase/common/ReactNativeFirebasePreferencesTest.kt +260 -0
  47. package/android/src/test/java/io/invertase/firebase/common/SharedUtilsJavaCompatibilityTest.java +255 -0
  48. package/android/src/test/java/io/invertase/firebase/common/SharedUtilsTest.kt +674 -0
  49. package/android/src/test/java/io/invertase/firebase/common/TaskExecutorServiceTest.kt +290 -0
  50. package/android/src/test/java/io/invertase/firebase/common/UniversalFirebaseModuleJavaCompatibilityTest.java +178 -0
  51. package/android/src/test/java/io/invertase/firebase/common/UniversalFirebasePreferencesJavaCompatibilityTest.java +99 -0
  52. package/android/src/test/java/io/invertase/firebase/common/UniversalFirebasePreferencesTest.kt +217 -0
  53. package/android/src/test/java/io/invertase/firebase/commoncompat/ReactNativeFirebaseModuleJavaCompatibilityTest.java +176 -0
  54. package/android/src/test/java/io/invertase/firebase/commoncompat/ReactNativeFirebaseModuleKotlinCompatibilityTest.kt +52 -0
  55. package/android/src/test/java/io/invertase/firebase/interfaces/InterfacesJavaCompatibilityTest.java +144 -0
  56. package/android/src/test/java/io/invertase/firebase/interfaces/NativeEventTest.kt +56 -0
  57. package/android/src/test/java/io/invertase/firebase/utils/NativeRNFBTurboUtilsTest.java +517 -21
  58. package/dist/module/FirebaseApp.js +10 -0
  59. package/dist/module/FirebaseApp.js.map +1 -1
  60. package/dist/module/common/deeps.js +3 -0
  61. package/dist/module/common/deeps.js.map +1 -1
  62. package/dist/module/internal/FirebaseModule.js.map +1 -1
  63. package/dist/module/internal/RNFBNativeEventEmitter.js +12 -1
  64. package/dist/module/internal/RNFBNativeEventEmitter.js.map +1 -1
  65. package/dist/module/internal/SharedEventEmitter.js +3 -1
  66. package/dist/module/internal/SharedEventEmitter.js.map +1 -1
  67. package/dist/module/internal/index.js +1 -0
  68. package/dist/module/internal/index.js.map +1 -1
  69. package/dist/module/internal/registry/app.js +7 -1
  70. package/dist/module/internal/registry/app.js.map +1 -1
  71. package/dist/module/types/app.js.map +1 -1
  72. package/dist/module/types/internal.js +2 -0
  73. package/dist/module/version.js +1 -1
  74. package/dist/typescript/lib/FirebaseApp.d.ts +7 -0
  75. package/dist/typescript/lib/FirebaseApp.d.ts.map +1 -1
  76. package/dist/typescript/lib/common/deeps.d.ts.map +1 -1
  77. package/dist/typescript/lib/internal/FirebaseModule.d.ts +2 -3
  78. package/dist/typescript/lib/internal/FirebaseModule.d.ts.map +1 -1
  79. package/dist/typescript/lib/internal/NativeModules.d.ts +4 -1
  80. package/dist/typescript/lib/internal/NativeModules.d.ts.map +1 -1
  81. package/dist/typescript/lib/internal/RNFBNativeEventEmitter.d.ts +2 -2
  82. package/dist/typescript/lib/internal/RNFBNativeEventEmitter.d.ts.map +1 -1
  83. package/dist/typescript/lib/internal/SharedEventEmitter.d.ts +3 -3
  84. package/dist/typescript/lib/internal/SharedEventEmitter.d.ts.map +1 -1
  85. package/dist/typescript/lib/internal/index.d.ts +1 -0
  86. package/dist/typescript/lib/internal/index.d.ts.map +1 -1
  87. package/dist/typescript/lib/internal/registry/app.d.ts.map +1 -1
  88. package/dist/typescript/lib/types/app.d.ts +10 -3
  89. package/dist/typescript/lib/types/app.d.ts.map +1 -1
  90. package/dist/typescript/lib/types/internal.d.ts +12 -0
  91. package/dist/typescript/lib/types/internal.d.ts.map +1 -1
  92. package/dist/typescript/lib/version.d.ts +1 -1
  93. package/firebase-schema.json +4 -0
  94. package/firebase_spm.rb +552 -96
  95. package/ios/RNFBApp/RCTConvert+FIRApp.h +2 -5
  96. package/ios/RNFBApp/RCTConvert+FIRApp.m +11 -6
  97. package/ios/RNFBApp/RCTConvert+FIROptions.h +2 -5
  98. package/ios/RNFBApp/RCTConvert+FIROptions.m +11 -10
  99. package/ios/RNFBApp/RCTConvertFIRApp.swift +86 -0
  100. package/ios/RNFBApp/RCTConvertFIROptions.swift +259 -0
  101. package/ios/RNFBApp/RNFBAppCustomAuthDomains.swift +63 -0
  102. package/ios/RNFBApp/RNFBAppInitializeOptionsMapper.swift +113 -0
  103. package/ios/RNFBApp/RNFBAppLogLevelMapper.swift +53 -0
  104. package/ios/RNFBApp/RNFBAppModule+CustomAuthDomain.m +35 -0
  105. package/ios/RNFBApp/RNFBAppModule.h +6 -2
  106. package/ios/RNFBApp/RNFBAppModule.mm +65 -228
  107. package/ios/RNFBApp/RNFBAppModuleFirebase.swift +439 -0
  108. package/ios/RNFBApp/RNFBAppModuleImplementation.h +68 -0
  109. package/ios/RNFBApp/RNFBAppModuleImplementation.m +195 -0
  110. package/ios/RNFBApp/RNFBHandleMap.m +27 -56
  111. package/ios/RNFBApp/RNFBHandleMapStorage.swift +90 -0
  112. package/ios/RNFBApp/RNFBInitializeAppArguments.swift +82 -0
  113. package/ios/RNFBApp/RNFBJSON.m +22 -38
  114. package/ios/RNFBApp/RNFBJSONImplementation.swift +71 -0
  115. package/ios/RNFBApp/RNFBMeta.m +24 -26
  116. package/ios/RNFBApp/RNFBMetaStorage.swift +76 -0
  117. package/ios/RNFBApp/RNFBNullSentinelDecoding.swift +135 -0
  118. package/ios/RNFBApp/RNFBNullSentinelInterceptor.h +30 -3
  119. package/ios/RNFBApp/RNFBNullSentinelInterceptor.m +28 -5
  120. package/ios/RNFBApp/RNFBPreferences.m +22 -20
  121. package/ios/RNFBApp/RNFBPreferencesStorage.swift +101 -0
  122. package/ios/RNFBApp/RNFBRCTEventEmitter.m +36 -93
  123. package/ios/RNFBApp/RNFBRCTEventEmitterCore.swift +161 -0
  124. package/ios/RNFBApp/RNFBSharedUtils.h +2 -5
  125. package/ios/RNFBApp/RNFBSharedUtils.m +109 -198
  126. package/ios/RNFBApp/RNFBSharedUtilsConfig.swift +72 -0
  127. package/ios/RNFBApp/RNFBSharedUtilsFIRApp.swift +271 -0
  128. package/ios/RNFBApp/RNFBSharedUtilsFormatting.swift +59 -0
  129. package/ios/RNFBApp/RNFBSharedUtilsPromiseRejection.swift +88 -0
  130. package/ios/RNFBApp/RNFBUtilsHelpers.swift +116 -0
  131. package/ios/RNFBApp/RNFBUtilsModule+Foundation.m +44 -0
  132. package/ios/RNFBApp/RNFBUtilsModule+PhotoAssets.m +47 -0
  133. package/ios/RNFBApp/RNFBUtilsModule.h +11 -1
  134. package/ios/RNFBApp/RNFBUtilsModule.mm +10 -85
  135. package/ios/RNFBApp/RNFBUtilsModuleImplementation.h +32 -0
  136. package/ios/RNFBApp/RNFBUtilsModuleImplementation.m +56 -0
  137. package/ios/RNFBApp/RNFBVersion.m +1 -1
  138. package/ios/RNFBApp.xcodeproj/project.pbxproj +100 -0
  139. package/ios/RNFBAppUnitTests/HostStubs/FirebaseCore/FIRApp.m +171 -0
  140. package/ios/RNFBAppUnitTests/HostStubs/FirebaseCore/FirebaseCore.h +78 -0
  141. package/ios/RNFBAppUnitTests/HostStubs/FirebaseInstallations/FIRInstallations.m +7 -0
  142. package/ios/RNFBAppUnitTests/HostStubs/FirebaseInstallations/FirebaseInstallations.h +8 -0
  143. package/ios/RNFBAppUnitTests/HostStubs/RNFBAppModuleHostStub.m +55 -0
  144. package/ios/RNFBAppUnitTests/HostStubs/RNFBAppTurboModules.h +89 -0
  145. package/ios/RNFBAppUnitTests/HostStubs/RNFBAppTurboModules.mm +30 -0
  146. package/ios/RNFBAppUnitTests/HostStubs/React/RCTBridge.h +19 -0
  147. package/ios/RNFBAppUnitTests/HostStubs/React/RCTBridge.m +32 -0
  148. package/ios/RNFBAppUnitTests/HostStubs/React/RCTBridgeModule.h +19 -0
  149. package/ios/RNFBAppUnitTests/HostStubs/React/RCTConvert.h +28 -0
  150. package/ios/RNFBAppUnitTests/HostStubs/React/RCTConvert.m +23 -0
  151. package/ios/RNFBAppUnitTests/HostStubs/React/RCTEventEmitter.h +9 -0
  152. package/ios/RNFBAppUnitTests/HostStubs/React/RCTInvalidating.h +24 -0
  153. package/ios/RNFBAppUnitTests/HostStubs/React/RCTUtils.h +9 -0
  154. package/ios/RNFBAppUnitTests/HostStubs/module.modulemap +13 -0
  155. package/ios/RNFBAppUnitTests/RCTConvertFIRAppFacadeTests.m +61 -0
  156. package/ios/RNFBAppUnitTests/RCTConvertFIRAppTests.swift +73 -0
  157. package/ios/RNFBAppUnitTests/RCTConvertFIROptionsFacadeTests.m +57 -0
  158. package/ios/RNFBAppUnitTests/RCTConvertFIROptionsTests.swift +243 -0
  159. package/ios/RNFBAppUnitTests/RNFBAppCustomAuthDomainsFacadeTests.m +73 -0
  160. package/ios/RNFBAppUnitTests/RNFBAppCustomAuthDomainsTests.swift +70 -0
  161. package/ios/RNFBAppUnitTests/RNFBAppInitializeOptionsMapperTests.swift +190 -0
  162. package/ios/RNFBAppUnitTests/RNFBAppLogLevelFacadeTests.m +76 -0
  163. package/ios/RNFBAppUnitTests/RNFBAppLogLevelMapperTests.swift +59 -0
  164. package/ios/RNFBAppUnitTests/RNFBAppModuleFirebaseFacadeTests.m +215 -0
  165. package/ios/RNFBAppUnitTests/RNFBAppModuleFirebaseTests.swift +430 -0
  166. package/ios/RNFBAppUnitTests/RNFBAppModuleLifecycleTests.m +206 -0
  167. package/ios/RNFBAppUnitTests/RNFBAppModuleShellTests.mm +367 -0
  168. package/ios/RNFBAppUnitTests/RNFBAppUnitTests.xcodeproj/project.pbxproj +355 -2
  169. package/ios/RNFBAppUnitTests/RNFBFirebaseAppClientTests.swift +165 -0
  170. package/ios/RNFBAppUnitTests/RNFBHandleMapStorageTests.swift +121 -0
  171. package/ios/RNFBAppUnitTests/RNFBInitializeAppArgumentsTests.swift +256 -0
  172. package/ios/RNFBAppUnitTests/RNFBJSONImplementationTests.swift +126 -0
  173. package/ios/RNFBAppUnitTests/RNFBJSONTests.m +172 -0
  174. package/ios/RNFBAppUnitTests/RNFBMetaStorageTests.swift +106 -0
  175. package/ios/RNFBAppUnitTests/RNFBMetaTests.m +65 -0
  176. package/ios/RNFBAppUnitTests/RNFBNullSentinelDecodingTests.swift +286 -0
  177. package/ios/RNFBAppUnitTests/RNFBNullSentinelInterceptorTests.m +312 -0
  178. package/ios/RNFBAppUnitTests/RNFBPreferencesStorageTests.swift +105 -0
  179. package/ios/RNFBAppUnitTests/RNFBPreferencesTests.m +110 -0
  180. package/ios/RNFBAppUnitTests/RNFBRCTEventEmitterCoreTests.swift +163 -0
  181. package/ios/RNFBAppUnitTests/RNFBRCTEventEmitterFacadeTests.m +141 -0
  182. package/ios/RNFBAppUnitTests/RNFBSharedUtilsConfigFacadeTests.m +100 -0
  183. package/ios/RNFBAppUnitTests/RNFBSharedUtilsConfigTests.swift +234 -0
  184. package/ios/RNFBAppUnitTests/RNFBSharedUtilsFIRAppFacadeTests.m +145 -0
  185. package/ios/RNFBAppUnitTests/RNFBSharedUtilsFIRAppTests.swift +173 -0
  186. package/ios/RNFBAppUnitTests/RNFBSharedUtilsFormattingFacadeTests.m +38 -0
  187. package/ios/RNFBAppUnitTests/RNFBSharedUtilsFormattingTests.swift +82 -0
  188. package/ios/RNFBAppUnitTests/RNFBSharedUtilsNullSentinelTests.m +35 -0
  189. package/ios/RNFBAppUnitTests/RNFBSharedUtilsPromiseRejectionFacadeTests.m +107 -0
  190. package/ios/RNFBAppUnitTests/RNFBSharedUtilsPromiseRejectionTests.swift +133 -0
  191. package/ios/RNFBAppUnitTests/RNFBUtilsHelpersTests.swift +144 -0
  192. package/ios/RNFBAppUnitTests/RNFBUtilsModuleFacadeTests.m +72 -0
  193. package/ios/RNFBAppUnitTests/RNFBUtilsModuleShellTests.mm +282 -0
  194. package/ios/RNFBFirebase/Package.swift +53 -0
  195. package/ios/RNFBFirebase/Sources/RNFBFirebase/RNFBFirebase.swift +285 -0
  196. package/ios/RNFBFirebase/Sources/RNFBFirebaseBridge/Public/.gitkeep +0 -0
  197. package/ios/RNFBFirebase/Sources/RNFBFirebaseBridge/RNFBFirebaseBridge.m +169 -0
  198. package/ios/RNFBFirebase/Sources/RNFBFirebaseBridge/include/RNFBFirebaseBridge.h +52 -0
  199. package/ios/RNFBFirebaseUnitTests/RNFBAppDynamicFacadeTests.swift +240 -0
  200. package/{android/src/main/java/io/invertase/firebase/common/RNFBHandleCollisionException.java → ios/RNFBFirebaseUnitTests/RNFBFirebaseClientImport.swift} +23 -14
  201. package/ios/RNFBFirebaseUnitTests/RNFBFirebaseUnitTests.xcodeproj/project.pbxproj +588 -0
  202. package/ios/RNFBFirebaseUnitTests/RNFBFirebaseUnitTests.xcodeproj/xcshareddata/xcschemes/RNFBFirebaseUnitTests.xcscheme +83 -0
  203. package/ios_config.sh +50 -22
  204. package/lib/FirebaseApp.ts +10 -0
  205. package/lib/common/deeps.ts +3 -0
  206. package/lib/internal/FirebaseModule.ts +6 -3
  207. package/lib/internal/NativeModules.ts +4 -1
  208. package/lib/internal/RNFBNativeEventEmitter.ts +14 -5
  209. package/lib/internal/SharedEventEmitter.ts +5 -1
  210. package/lib/internal/index.ts +1 -0
  211. package/lib/internal/react-native-vendor-emitter.d.ts +11 -0
  212. package/lib/internal/registry/app.ts +7 -1
  213. package/lib/types/app.ts +10 -3
  214. package/lib/types/internal.ts +19 -0
  215. package/lib/version.ts +1 -1
  216. package/package.json +8 -8
  217. package/plugin/build/ios/appDelegate.js +2 -2
  218. package/plugin/build/ios/podfile.js +16 -16
  219. package/plugin/build/pluginConfig.d.ts +4 -2
  220. package/plugin/src/ios/appDelegate.ts +2 -2
  221. package/plugin/src/ios/podfile.ts +20 -23
  222. package/plugin/src/pluginConfig.ts +4 -2
  223. package/android/src/main/java/io/invertase/firebase/common/RNFBHandleMap.java +0 -150
  224. package/android/src/main/java/io/invertase/firebase/common/TaskExecutorService.java +0 -148
  225. package/android/src/main/java/io/invertase/firebase/common/UniversalFirebaseModule.java +0 -62
  226. package/android/src/main/java/io/invertase/firebase/common/UniversalFirebasePreferences.java +0 -91
  227. package/android/src/reactnative/java/io/invertase/firebase/app/NativeRNFBTurboApp.java +0 -224
  228. package/android/src/reactnative/java/io/invertase/firebase/app/ReactNativeFirebaseApp.java +0 -46
  229. package/android/src/reactnative/java/io/invertase/firebase/app/ReactNativeFirebaseAppPackage.java +0 -49
  230. package/android/src/reactnative/java/io/invertase/firebase/app/ReactNativeFirebaseAppRegistrar.java +0 -35
  231. package/android/src/reactnative/java/io/invertase/firebase/common/RCTConvertFirebase.java +0 -192
  232. package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseEvent.java +0 -53
  233. package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseEventEmitter.java +0 -606
  234. package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseJSON.java +0 -109
  235. package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseMeta.java +0 -101
  236. package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseModule.java +0 -146
  237. package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebasePreferences.java +0 -96
  238. package/android/src/reactnative/java/io/invertase/firebase/common/SharedUtils.java +0 -441
  239. package/android/src/reactnative/java/io/invertase/firebase/utils/NativeRNFBTurboUtils.java +0 -223
  240. package/android/src/test/java/io/invertase/firebase/common/RNFBHandleMapTest.java +0 -275
  241. package/android/src/test/java/io/invertase/firebase/common/ReactNativeFirebaseJSONTest.java +0 -108
  242. package/android/src/test/java/io/invertase/firebase/common/TaskExecutorServiceTest.java +0 -97
@@ -0,0 +1,674 @@
1
+ package io.invertase.firebase.common
2
+
3
+ /*
4
+ * Copyright (c) 2016-present Invertase Limited & Contributors
5
+ *
6
+ * Licensed under the Apache License, Version 2.0 (the "License");
7
+ * you may not use this library except in compliance with the License.
8
+ * You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing, software
13
+ * distributed under the License is distributed on an "AS IS" BASIS,
14
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ * See the License for the specific language governing permissions and
16
+ * limitations under the License.
17
+ */
18
+
19
+ import android.app.ActivityManager
20
+ import android.content.ComponentName
21
+ import android.content.Context
22
+ import android.content.Intent
23
+ import android.content.res.Resources
24
+ import android.graphics.Point
25
+ import android.graphics.Rect
26
+ import android.net.Uri
27
+ import android.os.Build
28
+ import android.util.Log
29
+ import com.facebook.react.bridge.Arguments
30
+ import com.facebook.react.bridge.ReactContext
31
+ import com.facebook.react.bridge.ReadableMap
32
+ import com.facebook.react.bridge.WritableArray
33
+ import com.facebook.react.bridge.WritableMap
34
+ import com.facebook.react.common.LifecycleState
35
+ import com.facebook.react.modules.core.DeviceEventManagerModule
36
+ import org.json.JSONArray
37
+ import org.json.JSONException
38
+ import org.json.JSONObject
39
+ import org.junit.After
40
+ import org.junit.Assert.assertArrayEquals
41
+ import org.junit.Assert.assertEquals
42
+ import org.junit.Assert.assertFalse
43
+ import org.junit.Assert.assertSame
44
+ import org.junit.Assert.assertThrows
45
+ import org.junit.Assert.assertTrue
46
+ import org.junit.Before
47
+ import org.junit.Test
48
+ import org.junit.runner.RunWith
49
+ import org.mockito.Mockito.inOrder
50
+ import org.mockito.Mockito.mock
51
+ import org.mockito.Mockito.mockStatic
52
+ import org.mockito.Mockito.never
53
+ import org.mockito.Mockito.verify
54
+ import org.mockito.Mockito.verifyNoInteractions
55
+ import org.mockito.Mockito.`when`
56
+ import org.robolectric.RobolectricTestRunner
57
+ import org.robolectric.util.ReflectionHelpers
58
+ import java.io.File
59
+ import java.util.Date
60
+
61
+ @RunWith(RobolectricTestRunner::class)
62
+ class SharedUtilsTest {
63
+ private lateinit var json: ReactNativeFirebaseJSON
64
+ private lateinit var jsonObjectField: java.lang.reflect.Field
65
+ private var originalJsonObject: Any? = null
66
+
67
+ @Before
68
+ fun setUp() {
69
+ json = ReactNativeFirebaseJSON.getSharedInstance()
70
+ jsonObjectField = ReactNativeFirebaseJSON::class.java.getDeclaredField("jsonObject")
71
+ jsonObjectField.isAccessible = true
72
+ originalJsonObject = jsonObjectField.get(json)
73
+ jsonObjectField.set(json, JSONObject())
74
+ }
75
+
76
+ @After
77
+ fun tearDown() {
78
+ jsonObjectField.set(json, originalJsonObject)
79
+ }
80
+
81
+ @Test
82
+ fun geometryConversionsPreserveEmptyCoordinatesAndNullElements() {
83
+ assertArrayEquals(intArrayOf(), SharedUtils.rectToIntArray(null))
84
+ assertArrayEquals(intArrayOf(), SharedUtils.rectToIntArray(Rect(0, 0, 0, 0)))
85
+ assertArrayEquals(intArrayOf(1, 2, 4, 8), SharedUtils.rectToIntArray(Rect(1, 2, 4, 8)))
86
+ assertArrayEquals(intArrayOf(), SharedUtils.pointToIntArray(null))
87
+ assertArrayEquals(intArrayOf(-3, 7), SharedUtils.pointToIntArray(Point(-3, 7)))
88
+
89
+ assertTrue(SharedUtils.pointsToIntsList(null).isEmpty())
90
+ val converted = SharedUtils.pointsToIntsList(arrayOf(Point(1, 2), null, Point(3, 4)))
91
+ assertArrayEquals(intArrayOf(1, 2), converted[0])
92
+ assertArrayEquals(intArrayOf(), converted[1])
93
+ assertArrayEquals(intArrayOf(3, 4), converted[2])
94
+ }
95
+
96
+ @Test
97
+ fun uriConversionPreservesSchemesAndDefaultsPlainPathsToFiles() {
98
+ assertEquals("https", SharedUtils.getUri("https://example.test/path").scheme)
99
+ assertEquals("content", SharedUtils.getUri("content://authority/path").scheme)
100
+
101
+ val file = SharedUtils.getUri("/tmp/file name.txt")
102
+ assertEquals("file", file.scheme)
103
+ assertEquals("/tmp/file name.txt", file.path)
104
+ assertThrows(NullPointerException::class.java) { SharedUtils.getUri(null) }
105
+ }
106
+
107
+ @Test
108
+ fun uriConversionTreatsAnExplicitEmptySchemeAsAFile() {
109
+ val parsed = mock(Uri::class.java)
110
+ val fileUri = mock(Uri::class.java)
111
+ `when`(parsed.scheme).thenReturn("")
112
+ mockStatic(Uri::class.java).use { uri ->
113
+ uri.`when`<Uri> { Uri.parse("empty") }.thenReturn(parsed)
114
+ uri.`when`<Uri> { Uri.fromFile(File("empty")) }.thenReturn(fileUri)
115
+
116
+ assertSame(fileUri, SharedUtils.getUri("empty"))
117
+ }
118
+ }
119
+
120
+ @Test
121
+ fun exceptionMapPreservesNullableMessageAndKeyOrder() {
122
+ val writableMap = mock(WritableMap::class.java)
123
+ mockStatic(Arguments::class.java).use { arguments ->
124
+ arguments.`when`<WritableMap>(Arguments::createMap).thenReturn(writableMap)
125
+
126
+ assertSame(writableMap, SharedUtils.getExceptionMap(Exception()))
127
+
128
+ val order = inOrder(writableMap)
129
+ order.verify(writableMap).putString("code", "unknown")
130
+ order.verify(writableMap).putString("nativeErrorCode", "unknown")
131
+ order.verify(writableMap).putString("message", null)
132
+ order.verify(writableMap).putString("nativeErrorMessage", null)
133
+ }
134
+ }
135
+
136
+ @Test
137
+ fun utcFormattingPreservesSecondConversionAndLongOverflow() {
138
+ assertEquals("1970-01-01T00:00:00Z", SharedUtils.timestampToUTC(0))
139
+ assertEquals("1969-12-31T23:59:59Z", SharedUtils.timestampToUTC(Long.MAX_VALUE))
140
+ assertEquals(
141
+ "2000-01-01T00:00:00Z",
142
+ SharedUtils.timestampToUTC(Date(946_684_800_000L).time / 1000),
143
+ )
144
+ }
145
+
146
+ @Test
147
+ fun sendEventEmitsBodyOrLogsMissingContext() {
148
+ val context = mock(ReactContext::class.java)
149
+ val emitter = mock(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
150
+ val body = Any()
151
+ `when`(
152
+ context.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java),
153
+ ).thenReturn(emitter)
154
+
155
+ SharedUtils.sendEvent(context, "event", body)
156
+
157
+ verify(emitter).emit("event", body)
158
+
159
+ mockStatic(Log::class.java).use { log ->
160
+ SharedUtils.sendEvent(null, "event", body)
161
+ log.verify { Log.d("Utils", "Missing context - cannot send event!") }
162
+ }
163
+ }
164
+
165
+ @Test
166
+ fun foregroundReturnsFalseWhenManagerOrProcessesAreMissing() {
167
+ val context = mock(Context::class.java)
168
+ `when`(context.getSystemService(Context.ACTIVITY_SERVICE)).thenReturn(null)
169
+ assertFalse(SharedUtils.isAppInForeground(context))
170
+
171
+ val manager = mock(ActivityManager::class.java)
172
+ `when`(context.getSystemService(Context.ACTIVITY_SERVICE)).thenReturn(manager)
173
+ `when`(manager.runningAppProcesses).thenReturn(null)
174
+ assertFalse(SharedUtils.isAppInForeground(context))
175
+ }
176
+
177
+ @Test
178
+ fun foregroundFiltersProcessesAndFallsBackForNonReactContexts() {
179
+ val manager = mock(ActivityManager::class.java)
180
+ val context = contextWith(manager, "app.package")
181
+ val background = process("app.package", ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND)
182
+ val other = process("other.package", ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND)
183
+ `when`(manager.runningAppProcesses).thenReturn(listOf(background, other))
184
+
185
+ assertFalse(SharedUtils.isAppInForeground(context))
186
+
187
+ `when`(manager.runningAppProcesses)
188
+ .thenReturn(
189
+ listOf(process("app.package", ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND)),
190
+ )
191
+ assertTrue(SharedUtils.isAppInForeground(context))
192
+ }
193
+
194
+ @Test
195
+ fun foregroundPreservesNullProcessNameFailureTiming() {
196
+ val manager = mock(ActivityManager::class.java)
197
+ val context = contextWith(manager, "app.package")
198
+ val process =
199
+ ActivityManager.RunningAppProcessInfo().apply {
200
+ processName = null
201
+ importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND
202
+ }
203
+ `when`(manager.runningAppProcesses).thenReturn(listOf(process))
204
+
205
+ assertThrows(NullPointerException::class.java) {
206
+ SharedUtils.isAppInForeground(context)
207
+ }
208
+ }
209
+
210
+ @Test
211
+ fun foregroundSkipsTaskLookupForConfiguredEmptyBackgroundList() {
212
+ configureBackgroundActivities()
213
+ val manager = mock(ActivityManager::class.java)
214
+ val context = contextWith(manager, "app.package")
215
+ `when`(manager.runningAppProcesses)
216
+ .thenReturn(
217
+ listOf(process("app.package", ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND)),
218
+ )
219
+
220
+ assertTrue(SharedUtils.isAppInForeground(context))
221
+ verify(manager, never()).appTasks
222
+ }
223
+
224
+ @Test
225
+ fun foregroundUsesReactLifecycleForMatchingForegroundProcess() {
226
+ val manager = mock(ActivityManager::class.java)
227
+ val context = mock(ReactContext::class.java)
228
+ `when`(context.getSystemService(Context.ACTIVITY_SERVICE)).thenReturn(manager)
229
+ `when`(context.packageName).thenReturn("app.package")
230
+ `when`(manager.runningAppProcesses)
231
+ .thenReturn(
232
+ listOf(process("app.package", ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND)),
233
+ )
234
+ `when`(context.lifecycleState).thenReturn(LifecycleState.RESUMED, LifecycleState.BEFORE_CREATE)
235
+
236
+ assertTrue(SharedUtils.isAppInForeground(context))
237
+ assertFalse(SharedUtils.isAppInForeground(context))
238
+ }
239
+
240
+ @Test
241
+ fun foregroundSdk23UsesBaseActivityAndHandlesMissingTasksAndBaseActivity() {
242
+ withSdk(23) {
243
+ configureBackgroundActivities(".Background")
244
+ val manager = mock(ActivityManager::class.java)
245
+ val context = contextWith(manager, "app.package")
246
+ val foreground = process("app.package", ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND)
247
+ `when`(manager.runningAppProcesses).thenReturn(listOf(foreground))
248
+ `when`(manager.appTasks).thenReturn(emptyList())
249
+
250
+ assertTrue(SharedUtils.isAppInForeground(context))
251
+
252
+ val task = ActivityManager.RecentTaskInfo()
253
+ val appTask = mock(ActivityManager.AppTask::class.java)
254
+ `when`(appTask.taskInfo).thenReturn(task)
255
+ `when`(manager.appTasks).thenReturn(listOf(appTask))
256
+
257
+ assertTrue(SharedUtils.isAppInForeground(context))
258
+
259
+ task.baseActivity = ComponentName("app.package", "app.package.Foreground")
260
+ assertTrue(SharedUtils.isAppInForeground(context))
261
+
262
+ task.baseActivity = ComponentName("app.package", "app.package.Background")
263
+ assertFalse(SharedUtils.isAppInForeground(context))
264
+ }
265
+ }
266
+
267
+ @Test
268
+ fun foregroundSdk21UsesOrigActivityThenBaseIntentComponent() {
269
+ withSdk(21) {
270
+ configureBackgroundActivities(".Background")
271
+ val manager = mock(ActivityManager::class.java)
272
+ val context = contextWith(manager, "app.package")
273
+ `when`(manager.runningAppProcesses)
274
+ .thenReturn(
275
+ listOf(process("app.package", ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND)),
276
+ )
277
+ val task = ActivityManager.RecentTaskInfo()
278
+ val appTask = mock(ActivityManager.AppTask::class.java)
279
+ `when`(appTask.taskInfo).thenReturn(task)
280
+ `when`(manager.appTasks).thenReturn(listOf(appTask))
281
+
282
+ task.origActivity = ComponentName("app.package", "app.package.Background")
283
+ assertFalse(SharedUtils.isAppInForeground(context))
284
+
285
+ task.origActivity = null
286
+ task.baseIntent = Intent().setComponent(ComponentName("app.package", "app.package.Background"))
287
+ assertFalse(SharedUtils.isAppInForeground(context))
288
+ }
289
+ }
290
+
291
+ @Test
292
+ fun foregroundPre21UsesDeprecatedRunningTasksBranch() {
293
+ withSdk(19) {
294
+ configureBackgroundActivities(".Background")
295
+ val manager = mock(ActivityManager::class.java)
296
+ val context = contextWith(manager, "app.package")
297
+ `when`(manager.runningAppProcesses)
298
+ .thenReturn(
299
+ listOf(process("app.package", ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND)),
300
+ )
301
+ `when`(manager.getRunningTasks(1)).thenReturn(emptyList())
302
+
303
+ assertTrue(SharedUtils.isAppInForeground(context))
304
+
305
+ val task = ActivityManager.RunningTaskInfo()
306
+ task.topActivity = ComponentName("app.package", "app.package.Background")
307
+ `when`(manager.getRunningTasks(1)).thenReturn(listOf(task))
308
+
309
+ assertFalse(SharedUtils.isAppInForeground(context))
310
+ verify(manager, never()).appTasks
311
+ }
312
+ }
313
+
314
+ @Test
315
+ fun resourceLookupReturnsIdentifierAndLogsMissingNames() {
316
+ val context = mock(Context::class.java)
317
+ val resources = mock(Resources::class.java)
318
+ `when`(context.resources).thenReturn(resources)
319
+ `when`(context.packageName).thenReturn("app.package")
320
+ `when`(resources.getIdentifier("present", "string", "app.package")).thenReturn(42)
321
+ `when`(resources.getIdentifier("missing", "string", "app.package")).thenReturn(0)
322
+
323
+ assertEquals(42, SharedUtils.getResId(context, "present"))
324
+
325
+ mockStatic(Log::class.java).use { log ->
326
+ assertEquals(0, SharedUtils.getResId(context, "missing"))
327
+ log.verify { Log.e("Utils", "resource missing could not be found") }
328
+ }
329
+ }
330
+
331
+ @Test
332
+ fun dynamicClassLookupFindsClassesAndHandlesFailures() {
333
+ assertTrue(SharedUtils.hasPackageClass("java.lang", "String").booleanValue())
334
+ assertFalse(SharedUtils.hasPackageClass("missing.package", "Missing").booleanValue())
335
+ assertFalse(SharedUtils.hasPackageClass("java.lang", null).booleanValue())
336
+
337
+ assertFalse(SharedUtils.reactNativeHasDevSupport().booleanValue())
338
+ assertTrue(SharedUtils.isExpo().booleanValue())
339
+ assertFalse(SharedUtils.isFlutter().booleanValue())
340
+ assertFalse(SharedUtils.isReactNative().booleanValue())
341
+ }
342
+
343
+ @Test
344
+ fun jsonObjectConversionRecursesAndOmitsUnknownValues() {
345
+ val writableMap = mock(WritableMap::class.java)
346
+ val nestedMap = mock(WritableMap::class.java)
347
+ val writableArray = mock(WritableArray::class.java)
348
+ val nestedObject = JSONObject().put("nested", "value")
349
+ val nestedArray = JSONArray().put(7)
350
+ val source =
351
+ JSONObject()
352
+ .put("float", 1.25)
353
+ .put("integer", 3)
354
+ .put("string", "text")
355
+ .put("object", nestedObject)
356
+ .put("array", nestedArray)
357
+ .put("null", JSONObject.NULL)
358
+ .put("unknown", true)
359
+
360
+ mockStatic(Arguments::class.java).use { arguments ->
361
+ arguments.`when`<WritableMap>(Arguments::createMap).thenReturn(writableMap, nestedMap)
362
+ arguments.`when`<WritableArray>(Arguments::createArray).thenReturn(writableArray)
363
+
364
+ assertSame(writableMap, SharedUtils.jsonObjectToWritableMap(source))
365
+
366
+ verify(writableMap).putDouble("float", 1.25)
367
+ verify(writableMap).putInt("integer", 3)
368
+ verify(writableMap).putString("string", "text")
369
+ verify(writableMap).putMap("object", nestedMap)
370
+ verify(writableMap).putArray("array", writableArray)
371
+ verify(writableMap).putNull("null")
372
+ verify(writableMap, never()).putNull("unknown")
373
+ verify(nestedMap).putString("nested", "value")
374
+ verify(writableArray).pushInt(7)
375
+ }
376
+ }
377
+
378
+ @Test
379
+ fun jsonObjectConversionPropagatesJsonExceptions() {
380
+ val source = mock(JSONObject::class.java)
381
+ `when`(source.keys()).thenReturn(listOf("bad").iterator())
382
+ `when`(source.get("bad")).thenThrow(JSONException("bad"))
383
+
384
+ mockStatic(Arguments::class.java).use { arguments ->
385
+ arguments.`when`<WritableMap>(Arguments::createMap).thenReturn(mock(WritableMap::class.java))
386
+
387
+ assertThrows(JSONException::class.java) {
388
+ SharedUtils.jsonObjectToWritableMap(source)
389
+ }
390
+ }
391
+ }
392
+
393
+ @Test
394
+ fun jsonObjectConversionWritesNothingForAnUnknownOnlyValue() {
395
+ val source = mock(JSONObject::class.java)
396
+ val writableMap = mock(WritableMap::class.java)
397
+ `when`(source.keys()).thenReturn(listOf("unknown").iterator())
398
+ `when`(source.get("unknown")).thenReturn(true)
399
+
400
+ mockStatic(Arguments::class.java).use { arguments ->
401
+ arguments.`when`<WritableMap>(Arguments::createMap).thenReturn(writableMap)
402
+
403
+ assertSame(writableMap, SharedUtils.jsonObjectToWritableMap(source))
404
+ verifyNoInteractions(writableMap)
405
+ }
406
+ }
407
+
408
+ @Test
409
+ fun jsonObjectConversionPreservesFloatDispatch() {
410
+ val source = mock(JSONObject::class.java)
411
+ val writableMap = mock(WritableMap::class.java)
412
+ `when`(source.keys()).thenReturn(listOf("float").iterator())
413
+ `when`(source.get("float")).thenReturn(1.25F)
414
+ `when`(source.getDouble("float")).thenReturn(1.25)
415
+
416
+ mockStatic(Arguments::class.java).use { arguments ->
417
+ arguments.`when`<WritableMap>(Arguments::createMap).thenReturn(writableMap)
418
+
419
+ SharedUtils.jsonObjectToWritableMap(source)
420
+
421
+ verify(writableMap).putDouble("float", 1.25)
422
+ }
423
+ }
424
+
425
+ @Test
426
+ fun jsonArrayConversionRecursesAndOmitsUnknownValues() {
427
+ val writableArray = mock(WritableArray::class.java)
428
+ val nestedArray = mock(WritableArray::class.java)
429
+ val writableMap = mock(WritableMap::class.java)
430
+ val source =
431
+ JSONArray()
432
+ .put(1.5)
433
+ .put(2)
434
+ .put("text")
435
+ .put(JSONObject().put("nested", 4))
436
+ .put(JSONArray().put("inner"))
437
+ .put(JSONObject.NULL)
438
+ .put(true)
439
+
440
+ mockStatic(Arguments::class.java).use { arguments ->
441
+ arguments.`when`<WritableArray>(Arguments::createArray).thenReturn(writableArray, nestedArray)
442
+ arguments.`when`<WritableMap>(Arguments::createMap).thenReturn(writableMap)
443
+
444
+ assertSame(writableArray, SharedUtils.jsonArrayToWritableArray(source))
445
+
446
+ verify(writableArray).pushDouble(1.5)
447
+ verify(writableArray).pushInt(2)
448
+ verify(writableArray).pushString("text")
449
+ verify(writableArray).pushMap(writableMap)
450
+ verify(writableArray).pushArray(nestedArray)
451
+ verify(writableArray).pushNull()
452
+ verify(writableMap).putInt("nested", 4)
453
+ verify(nestedArray).pushString("inner")
454
+ }
455
+ }
456
+
457
+ @Test
458
+ fun jsonArrayConversionPropagatesJsonExceptions() {
459
+ val source = mock(JSONArray::class.java)
460
+ `when`(source.length()).thenReturn(1)
461
+ `when`(source.get(0)).thenThrow(JSONException("bad"))
462
+
463
+ mockStatic(Arguments::class.java).use { arguments ->
464
+ arguments.`when`<WritableArray>(Arguments::createArray).thenReturn(mock(WritableArray::class.java))
465
+
466
+ assertThrows(JSONException::class.java) {
467
+ SharedUtils.jsonArrayToWritableArray(source)
468
+ }
469
+ }
470
+ }
471
+
472
+ @Test
473
+ fun jsonArrayConversionWritesNothingForAnUnknownOnlyValue() {
474
+ val source = mock(JSONArray::class.java)
475
+ val writableArray = mock(WritableArray::class.java)
476
+ `when`(source.length()).thenReturn(1)
477
+ `when`(source.get(0)).thenReturn(true)
478
+
479
+ mockStatic(Arguments::class.java).use { arguments ->
480
+ arguments.`when`<WritableArray>(Arguments::createArray).thenReturn(writableArray)
481
+
482
+ assertSame(writableArray, SharedUtils.jsonArrayToWritableArray(source))
483
+ verifyNoInteractions(writableArray)
484
+ }
485
+ }
486
+
487
+ @Test
488
+ fun jsonArrayConversionPreservesFloatDispatch() {
489
+ val source = mock(JSONArray::class.java)
490
+ val writableArray = mock(WritableArray::class.java)
491
+ `when`(source.length()).thenReturn(1)
492
+ `when`(source.get(0)).thenReturn(1.25F)
493
+ `when`(source.getDouble(0)).thenReturn(1.25)
494
+
495
+ mockStatic(Arguments::class.java).use { arguments ->
496
+ arguments.`when`<WritableArray>(Arguments::createArray).thenReturn(writableArray)
497
+
498
+ SharedUtils.jsonArrayToWritableArray(source)
499
+
500
+ verify(writableArray).pushDouble(1.25)
501
+ }
502
+ }
503
+
504
+ @Test
505
+ fun arrayPushValuePreservesEverySupportedWrapperConversion() {
506
+ val array = mock(WritableArray::class.java)
507
+
508
+ SharedUtils.arrayPushValue(null, array)
509
+ SharedUtils.arrayPushValue(JSONObject.NULL, array)
510
+ SharedUtils.arrayPushValue(true, array)
511
+ SharedUtils.arrayPushValue(Long.MAX_VALUE, array)
512
+ SharedUtils.arrayPushValue(1.25F, array)
513
+ SharedUtils.arrayPushValue(2.5, array)
514
+ SharedUtils.arrayPushValue(7, array)
515
+ SharedUtils.arrayPushValue("text", array)
516
+
517
+ verify(array, org.mockito.Mockito.times(2)).pushNull()
518
+ verify(array).pushBoolean(true)
519
+ verify(array).pushDouble(Long.MAX_VALUE.toDouble())
520
+ verify(array).pushDouble(1.25)
521
+ verify(array).pushDouble(2.5)
522
+ verify(array).pushInt(7)
523
+ verify(array).pushString("text")
524
+ }
525
+
526
+ @Test
527
+ fun arrayPushValueRecursesListsAndMapsAndNullsUnknownTypes() {
528
+ val array = mock(WritableArray::class.java)
529
+ val nestedArray = mock(WritableArray::class.java)
530
+ val nestedMap = mock(WritableMap::class.java)
531
+ mockStatic(Arguments::class.java).use { arguments ->
532
+ arguments.`when`<WritableArray>(Arguments::createArray).thenReturn(nestedArray)
533
+ arguments.`when`<WritableMap>(Arguments::createMap).thenReturn(nestedMap)
534
+
535
+ SharedUtils.arrayPushValue(listOf("nested"), array)
536
+ SharedUtils.arrayPushValue(linkedMapOf("key" to 3), array)
537
+ SharedUtils.arrayPushValue(JSONObject(), array)
538
+ SharedUtils.arrayPushValue(1.toShort(), array)
539
+
540
+ verify(array).pushArray(nestedArray)
541
+ verify(array).pushMap(nestedMap)
542
+ verify(array, org.mockito.Mockito.times(2)).pushNull()
543
+ verify(nestedArray).pushString("nested")
544
+ verify(nestedMap).putInt("key", 3)
545
+ }
546
+ }
547
+
548
+ @Test
549
+ fun mapPutValuePreservesEverySupportedWrapperConversion() {
550
+ val map = mock(WritableMap::class.java)
551
+
552
+ SharedUtils.mapPutValue("null", null, map)
553
+ SharedUtils.mapPutValue("jsonNull", JSONObject.NULL, map)
554
+ SharedUtils.mapPutValue("boolean", false, map)
555
+ SharedUtils.mapPutValue("long", Long.MAX_VALUE, map)
556
+ SharedUtils.mapPutValue("float", 1.25F, map)
557
+ SharedUtils.mapPutValue("double", 2.5, map)
558
+ SharedUtils.mapPutValue("integer", 7, map)
559
+ SharedUtils.mapPutValue("string", "text", map)
560
+
561
+ verify(map).putNull("null")
562
+ verify(map).putNull("jsonNull")
563
+ verify(map).putBoolean("boolean", false)
564
+ verify(map).putDouble("long", Long.MAX_VALUE.toDouble())
565
+ verify(map).putDouble("float", 1.25)
566
+ verify(map).putDouble("double", 2.5)
567
+ verify(map).putInt("integer", 7)
568
+ verify(map).putString("string", "text")
569
+ }
570
+
571
+ @Test
572
+ fun mapPutValueRecursesListsAndMapsAndNullsUnknownTypes() {
573
+ val map = mock(WritableMap::class.java)
574
+ val nestedArray = mock(WritableArray::class.java)
575
+ val nestedMap = mock(WritableMap::class.java)
576
+ mockStatic(Arguments::class.java).use { arguments ->
577
+ arguments.`when`<WritableArray>(Arguments::createArray).thenReturn(nestedArray)
578
+ arguments.`when`<WritableMap>(Arguments::createMap).thenReturn(nestedMap)
579
+
580
+ SharedUtils.mapPutValue("list", listOf(false), map)
581
+ SharedUtils.mapPutValue("map", linkedMapOf("key" to "value"), map)
582
+ SharedUtils.mapPutValue("json", JSONArray(), map)
583
+ SharedUtils.mapPutValue("unknown", Any(), map)
584
+
585
+ verify(map).putArray("list", nestedArray)
586
+ verify(map).putMap("map", nestedMap)
587
+ verify(map).putNull("json")
588
+ verify(map).putNull("unknown")
589
+ verify(nestedArray).pushBoolean(false)
590
+ verify(nestedMap).putString("key", "value")
591
+ }
592
+ }
593
+
594
+ @Test
595
+ fun mapConversionAndReadableMapMergeUseCreatedMap() {
596
+ val writableMap = mock(WritableMap::class.java)
597
+ val mergedMap = mock(WritableMap::class.java)
598
+ val readableMap = mock(ReadableMap::class.java)
599
+ mockStatic(Arguments::class.java).use { arguments ->
600
+ arguments.`when`<WritableMap>(Arguments::createMap).thenReturn(writableMap, mergedMap)
601
+
602
+ assertSame(
603
+ writableMap,
604
+ SharedUtils.mapToWritableMap(linkedMapOf("first" to true, "second" to null)),
605
+ )
606
+ assertSame(mergedMap, SharedUtils.readableMapToWritableMap(readableMap))
607
+
608
+ verify(writableMap).putBoolean("first", true)
609
+ verify(writableMap).putNull("second")
610
+ verify(mergedMap).merge(readableMap)
611
+ }
612
+ }
613
+
614
+ @Test
615
+ fun nullRequiredInputsFailAtOriginalDereferenceOrCallSites() {
616
+ mockStatic(Arguments::class.java).use { arguments ->
617
+ arguments.`when`<WritableMap>(Arguments::createMap).thenReturn(mock(WritableMap::class.java))
618
+ arguments.`when`<WritableArray>(Arguments::createArray).thenReturn(mock(WritableArray::class.java))
619
+ assertThrows(NullPointerException::class.java) { SharedUtils.getExceptionMap(null) }
620
+ assertThrows(NullPointerException::class.java) { SharedUtils.jsonArrayToWritableArray(null) }
621
+ assertThrows(NullPointerException::class.java) { SharedUtils.mapToWritableMap(null) }
622
+ }
623
+ assertThrows(NullPointerException::class.java) { SharedUtils.isAppInForeground(null) }
624
+ assertThrows(NullPointerException::class.java) { SharedUtils.getResId(null, "name") }
625
+ assertThrows(NullPointerException::class.java) { SharedUtils.jsonObjectToWritableMap(null) }
626
+ assertThrows(NullPointerException::class.java) {
627
+ SharedUtils.arrayPushValue("value", null)
628
+ }
629
+ assertThrows(NullPointerException::class.java) {
630
+ SharedUtils.mapPutValue("key", "value", null)
631
+ }
632
+ }
633
+
634
+ private fun contextWith(
635
+ manager: ActivityManager,
636
+ packageName: String,
637
+ ): Context {
638
+ val context = mock(Context::class.java)
639
+ `when`(context.getSystemService(Context.ACTIVITY_SERVICE)).thenReturn(manager)
640
+ `when`(context.packageName).thenReturn(packageName)
641
+ return context
642
+ }
643
+
644
+ private fun process(
645
+ processName: String,
646
+ importance: Int,
647
+ ): ActivityManager.RunningAppProcessInfo =
648
+ ActivityManager.RunningAppProcessInfo().apply {
649
+ this.processName = processName
650
+ this.importance = importance
651
+ }
652
+
653
+ private fun configureBackgroundActivities(vararg names: String) {
654
+ val array = JSONArray()
655
+ names.forEach(array::put)
656
+ jsonObjectField.set(
657
+ json,
658
+ JSONObject().put("android_background_activity_names", array),
659
+ )
660
+ }
661
+
662
+ private fun withSdk(
663
+ sdk: Int,
664
+ block: () -> Unit,
665
+ ) {
666
+ val original = Build.VERSION.SDK_INT
667
+ ReflectionHelpers.setStaticField(Build.VERSION::class.java, "SDK_INT", sdk)
668
+ try {
669
+ block()
670
+ } finally {
671
+ ReflectionHelpers.setStaticField(Build.VERSION::class.java, "SDK_INT", original)
672
+ }
673
+ }
674
+ }