@react-native-firebase/app 26.3.3 → 27.0.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 (283) hide show
  1. package/CHANGELOG.md +75 -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 +208 -60
  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 +144 -13
  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 -23
  58. package/dist/module/FirebaseApp.js +10 -0
  59. package/dist/module/FirebaseApp.js.map +1 -1
  60. package/dist/module/common/Base64.js +13 -21
  61. package/dist/module/common/Base64.js.map +1 -1
  62. package/dist/module/common/deeps.js +3 -0
  63. package/dist/module/common/deeps.js.map +1 -1
  64. package/dist/module/common/index.js +17 -9
  65. package/dist/module/common/index.js.map +1 -1
  66. package/dist/module/internal/FirebaseModule.js.map +1 -1
  67. package/dist/module/internal/RNFBNativeEventEmitter.js +12 -1
  68. package/dist/module/internal/RNFBNativeEventEmitter.js.map +1 -1
  69. package/dist/module/internal/SharedEventEmitter.js +3 -1
  70. package/dist/module/internal/SharedEventEmitter.js.map +1 -1
  71. package/dist/module/internal/asyncStorage.js +7 -11
  72. package/dist/module/internal/asyncStorage.js.map +1 -1
  73. package/dist/module/internal/index.js +1 -0
  74. package/dist/module/internal/index.js.map +1 -1
  75. package/dist/module/internal/logger.js +44 -40
  76. package/dist/module/internal/logger.js.map +1 -1
  77. package/dist/module/internal/nativeModuleAndroidIos.js +2 -29
  78. package/dist/module/internal/nativeModuleAndroidIos.js.map +1 -1
  79. package/dist/module/internal/nativeModuleDebug.js +74 -0
  80. package/dist/module/internal/nativeModuleDebug.js.map +1 -0
  81. package/dist/module/internal/nativeModuleWeb.js +9 -29
  82. package/dist/module/internal/nativeModuleWeb.js.map +1 -1
  83. package/dist/module/internal/registry/app.js +8 -2
  84. package/dist/module/internal/registry/app.js.map +1 -1
  85. package/dist/module/internal/registry/modular.js +2 -2
  86. package/dist/module/internal/registry/modular.js.map +1 -1
  87. package/dist/module/internal/registry/nativeModule.js +3 -3
  88. package/dist/module/internal/registry/nativeModule.js.map +1 -1
  89. package/dist/module/internal/web/RNFBAppModule.js +16 -15
  90. package/dist/module/internal/web/RNFBAppModule.js.map +1 -1
  91. package/dist/module/internal/web/memidb/lib/FakeEventTarget.js +3 -1
  92. package/dist/module/internal/web/memidb/lib/FakeEventTarget.js.map +1 -1
  93. package/dist/module/types/app.js.map +1 -1
  94. package/dist/module/types/internal.js +2 -0
  95. package/dist/module/version.js +1 -1
  96. package/dist/typescript/lib/FirebaseApp.d.ts +7 -0
  97. package/dist/typescript/lib/FirebaseApp.d.ts.map +1 -1
  98. package/dist/typescript/lib/common/Base64.d.ts.map +1 -1
  99. package/dist/typescript/lib/common/deeps.d.ts.map +1 -1
  100. package/dist/typescript/lib/common/index.d.ts.map +1 -1
  101. package/dist/typescript/lib/internal/FirebaseModule.d.ts +2 -3
  102. package/dist/typescript/lib/internal/FirebaseModule.d.ts.map +1 -1
  103. package/dist/typescript/lib/internal/NativeModules.d.ts +4 -1
  104. package/dist/typescript/lib/internal/NativeModules.d.ts.map +1 -1
  105. package/dist/typescript/lib/internal/RNFBNativeEventEmitter.d.ts +2 -2
  106. package/dist/typescript/lib/internal/RNFBNativeEventEmitter.d.ts.map +1 -1
  107. package/dist/typescript/lib/internal/SharedEventEmitter.d.ts +3 -3
  108. package/dist/typescript/lib/internal/SharedEventEmitter.d.ts.map +1 -1
  109. package/dist/typescript/lib/internal/asyncStorage.d.ts.map +1 -1
  110. package/dist/typescript/lib/internal/index.d.ts +1 -0
  111. package/dist/typescript/lib/internal/index.d.ts.map +1 -1
  112. package/dist/typescript/lib/internal/logger.d.ts.map +1 -1
  113. package/dist/typescript/lib/internal/nativeModuleAndroidIos.d.ts.map +1 -1
  114. package/dist/typescript/lib/internal/nativeModuleDebug.d.ts +2 -0
  115. package/dist/typescript/lib/internal/nativeModuleDebug.d.ts.map +1 -0
  116. package/dist/typescript/lib/internal/nativeModuleWeb.d.ts.map +1 -1
  117. package/dist/typescript/lib/internal/registry/app.d.ts.map +1 -1
  118. package/dist/typescript/lib/internal/web/RNFBAppModule.d.ts +7 -7
  119. package/dist/typescript/lib/internal/web/RNFBAppModule.d.ts.map +1 -1
  120. package/dist/typescript/lib/types/app.d.ts +10 -3
  121. package/dist/typescript/lib/types/app.d.ts.map +1 -1
  122. package/dist/typescript/lib/types/internal.d.ts +12 -0
  123. package/dist/typescript/lib/types/internal.d.ts.map +1 -1
  124. package/dist/typescript/lib/version.d.ts +1 -1
  125. package/firebase-schema.json +5 -1
  126. package/firebase_spm.rb +552 -96
  127. package/ios/RNFBApp/RCTConvert+FIRApp.h +2 -5
  128. package/ios/RNFBApp/RCTConvert+FIRApp.m +11 -6
  129. package/ios/RNFBApp/RCTConvert+FIROptions.h +2 -5
  130. package/ios/RNFBApp/RCTConvert+FIROptions.m +11 -10
  131. package/ios/RNFBApp/RCTConvertFIRApp.swift +86 -0
  132. package/ios/RNFBApp/RCTConvertFIROptions.swift +259 -0
  133. package/ios/RNFBApp/RNFBAppCustomAuthDomains.swift +63 -0
  134. package/ios/RNFBApp/RNFBAppInitializeOptionsMapper.swift +113 -0
  135. package/ios/RNFBApp/RNFBAppLogLevelMapper.swift +53 -0
  136. package/ios/RNFBApp/RNFBAppModule+CustomAuthDomain.m +35 -0
  137. package/ios/RNFBApp/RNFBAppModule.h +6 -2
  138. package/ios/RNFBApp/RNFBAppModule.mm +67 -204
  139. package/ios/RNFBApp/RNFBAppModuleFirebase.swift +439 -0
  140. package/ios/RNFBApp/RNFBAppModuleImplementation.h +68 -0
  141. package/ios/RNFBApp/RNFBAppModuleImplementation.m +195 -0
  142. package/ios/RNFBApp/RNFBHandleMap.h +73 -0
  143. package/ios/RNFBApp/RNFBHandleMap.m +87 -0
  144. package/ios/RNFBApp/RNFBHandleMapStorage.swift +90 -0
  145. package/ios/RNFBApp/RNFBInitializeAppArguments.swift +82 -0
  146. package/ios/RNFBApp/RNFBJSON.m +22 -38
  147. package/ios/RNFBApp/RNFBJSONImplementation.swift +71 -0
  148. package/ios/RNFBApp/RNFBMeta.m +24 -26
  149. package/ios/RNFBApp/RNFBMetaStorage.swift +76 -0
  150. package/ios/RNFBApp/RNFBNullSentinelDecoding.swift +135 -0
  151. package/ios/RNFBApp/RNFBNullSentinelInterceptor.h +30 -3
  152. package/ios/RNFBApp/RNFBNullSentinelInterceptor.m +28 -5
  153. package/ios/RNFBApp/RNFBPreferences.m +22 -20
  154. package/ios/RNFBApp/RNFBPreferencesStorage.swift +101 -0
  155. package/ios/RNFBApp/RNFBRCTEventEmitter.m +36 -93
  156. package/ios/RNFBApp/RNFBRCTEventEmitterCore.swift +161 -0
  157. package/ios/RNFBApp/RNFBSharedUtils.h +2 -5
  158. package/ios/RNFBApp/RNFBSharedUtils.m +109 -197
  159. package/ios/RNFBApp/RNFBSharedUtilsConfig.swift +72 -0
  160. package/ios/RNFBApp/RNFBSharedUtilsFIRApp.swift +271 -0
  161. package/ios/RNFBApp/RNFBSharedUtilsFormatting.swift +59 -0
  162. package/ios/RNFBApp/RNFBSharedUtilsPromiseRejection.swift +88 -0
  163. package/ios/RNFBApp/RNFBUtilsHelpers.swift +116 -0
  164. package/ios/RNFBApp/RNFBUtilsModule+Foundation.m +44 -0
  165. package/ios/RNFBApp/RNFBUtilsModule+PhotoAssets.m +47 -0
  166. package/ios/RNFBApp/RNFBUtilsModule.h +11 -1
  167. package/ios/RNFBApp/RNFBUtilsModule.mm +10 -85
  168. package/ios/RNFBApp/RNFBUtilsModuleImplementation.h +32 -0
  169. package/ios/RNFBApp/RNFBUtilsModuleImplementation.m +56 -0
  170. package/ios/RNFBApp/RNFBVersion.m +1 -1
  171. package/ios/RNFBApp.xcodeproj/project.pbxproj +106 -0
  172. package/ios/RNFBAppUnitTests/HostStubs/FirebaseCore/FIRApp.m +171 -0
  173. package/ios/RNFBAppUnitTests/HostStubs/FirebaseCore/FirebaseCore.h +78 -0
  174. package/ios/RNFBAppUnitTests/HostStubs/FirebaseInstallations/FIRInstallations.m +7 -0
  175. package/ios/RNFBAppUnitTests/HostStubs/FirebaseInstallations/FirebaseInstallations.h +8 -0
  176. package/ios/RNFBAppUnitTests/HostStubs/RNFBAppModuleHostStub.m +55 -0
  177. package/ios/RNFBAppUnitTests/HostStubs/RNFBAppTurboModules.h +89 -0
  178. package/ios/RNFBAppUnitTests/HostStubs/RNFBAppTurboModules.mm +30 -0
  179. package/ios/RNFBAppUnitTests/HostStubs/React/RCTBridge.h +19 -0
  180. package/ios/RNFBAppUnitTests/HostStubs/React/RCTBridge.m +32 -0
  181. package/ios/RNFBAppUnitTests/HostStubs/React/RCTBridgeModule.h +19 -0
  182. package/ios/RNFBAppUnitTests/HostStubs/React/RCTConvert.h +28 -0
  183. package/ios/RNFBAppUnitTests/HostStubs/React/RCTConvert.m +23 -0
  184. package/ios/RNFBAppUnitTests/HostStubs/React/RCTEventEmitter.h +9 -0
  185. package/ios/RNFBAppUnitTests/HostStubs/React/RCTInvalidating.h +24 -0
  186. package/ios/RNFBAppUnitTests/HostStubs/React/RCTUtils.h +9 -0
  187. package/ios/RNFBAppUnitTests/HostStubs/module.modulemap +13 -0
  188. package/ios/RNFBAppUnitTests/RCTConvertFIRAppFacadeTests.m +61 -0
  189. package/ios/RNFBAppUnitTests/RCTConvertFIRAppTests.swift +73 -0
  190. package/ios/RNFBAppUnitTests/RCTConvertFIROptionsFacadeTests.m +57 -0
  191. package/ios/RNFBAppUnitTests/RCTConvertFIROptionsTests.swift +243 -0
  192. package/ios/RNFBAppUnitTests/RNFBAppCustomAuthDomainsFacadeTests.m +73 -0
  193. package/ios/RNFBAppUnitTests/RNFBAppCustomAuthDomainsTests.swift +70 -0
  194. package/ios/RNFBAppUnitTests/RNFBAppInitializeOptionsMapperTests.swift +190 -0
  195. package/ios/RNFBAppUnitTests/RNFBAppLogLevelFacadeTests.m +76 -0
  196. package/ios/RNFBAppUnitTests/RNFBAppLogLevelMapperTests.swift +59 -0
  197. package/ios/RNFBAppUnitTests/RNFBAppModuleFirebaseFacadeTests.m +215 -0
  198. package/ios/RNFBAppUnitTests/RNFBAppModuleFirebaseTests.swift +430 -0
  199. package/ios/RNFBAppUnitTests/RNFBAppModuleLifecycleTests.m +206 -0
  200. package/ios/RNFBAppUnitTests/RNFBAppModuleShellTests.mm +367 -0
  201. package/ios/RNFBAppUnitTests/RNFBAppUnitTests.xcodeproj/project.pbxproj +590 -0
  202. package/ios/RNFBAppUnitTests/RNFBAppUnitTests.xcodeproj/xcshareddata/xcschemes/RNFBAppUnitTests.xcscheme +69 -0
  203. package/ios/RNFBAppUnitTests/RNFBFirebaseAppClientTests.swift +165 -0
  204. package/ios/RNFBAppUnitTests/RNFBHandleMapStorageTests.swift +121 -0
  205. package/ios/RNFBAppUnitTests/RNFBHandleMapTests.m +238 -0
  206. package/ios/RNFBAppUnitTests/RNFBInitializeAppArgumentsTests.swift +256 -0
  207. package/ios/RNFBAppUnitTests/RNFBJSONImplementationTests.swift +126 -0
  208. package/ios/RNFBAppUnitTests/RNFBJSONTests.m +172 -0
  209. package/ios/RNFBAppUnitTests/RNFBMetaStorageTests.swift +106 -0
  210. package/ios/RNFBAppUnitTests/RNFBMetaTests.m +65 -0
  211. package/ios/RNFBAppUnitTests/RNFBNullSentinelDecodingTests.swift +286 -0
  212. package/ios/RNFBAppUnitTests/RNFBNullSentinelInterceptorTests.m +312 -0
  213. package/ios/RNFBAppUnitTests/RNFBPreferencesStorageTests.swift +105 -0
  214. package/ios/RNFBAppUnitTests/RNFBPreferencesTests.m +110 -0
  215. package/ios/RNFBAppUnitTests/RNFBRCTEventEmitterCoreTests.swift +163 -0
  216. package/ios/RNFBAppUnitTests/RNFBRCTEventEmitterFacadeTests.m +141 -0
  217. package/ios/RNFBAppUnitTests/RNFBSharedUtilsConfigFacadeTests.m +100 -0
  218. package/ios/RNFBAppUnitTests/RNFBSharedUtilsConfigTests.swift +234 -0
  219. package/ios/RNFBAppUnitTests/RNFBSharedUtilsFIRAppFacadeTests.m +145 -0
  220. package/ios/RNFBAppUnitTests/RNFBSharedUtilsFIRAppTests.swift +173 -0
  221. package/ios/RNFBAppUnitTests/RNFBSharedUtilsFormattingFacadeTests.m +38 -0
  222. package/ios/RNFBAppUnitTests/RNFBSharedUtilsFormattingTests.swift +82 -0
  223. package/ios/RNFBAppUnitTests/RNFBSharedUtilsNullSentinelTests.m +35 -0
  224. package/ios/RNFBAppUnitTests/RNFBSharedUtilsPromiseRejectionFacadeTests.m +107 -0
  225. package/ios/RNFBAppUnitTests/RNFBSharedUtilsPromiseRejectionTests.swift +133 -0
  226. package/ios/RNFBAppUnitTests/RNFBUtilsHelpersTests.swift +144 -0
  227. package/ios/RNFBAppUnitTests/RNFBUtilsModuleFacadeTests.m +72 -0
  228. package/ios/RNFBAppUnitTests/RNFBUtilsModuleShellTests.mm +282 -0
  229. package/ios/RNFBFirebase/Package.swift +53 -0
  230. package/ios/RNFBFirebase/Sources/RNFBFirebase/RNFBFirebase.swift +285 -0
  231. package/ios/RNFBFirebase/Sources/RNFBFirebaseBridge/Public/.gitkeep +0 -0
  232. package/ios/RNFBFirebase/Sources/RNFBFirebaseBridge/RNFBFirebaseBridge.m +169 -0
  233. package/ios/RNFBFirebase/Sources/RNFBFirebaseBridge/include/RNFBFirebaseBridge.h +52 -0
  234. package/ios/RNFBFirebaseUnitTests/RNFBAppDynamicFacadeTests.swift +240 -0
  235. package/{android/src/reactnative/java/io/invertase/firebase/app/ReactNativeFirebaseAppRegistrar.java → ios/RNFBFirebaseUnitTests/RNFBFirebaseClientImport.swift} +22 -17
  236. package/ios/RNFBFirebaseUnitTests/RNFBFirebaseUnitTests.xcodeproj/project.pbxproj +588 -0
  237. package/ios/RNFBFirebaseUnitTests/RNFBFirebaseUnitTests.xcodeproj/xcshareddata/xcschemes/RNFBFirebaseUnitTests.xcscheme +83 -0
  238. package/ios_config.sh +50 -22
  239. package/lib/FirebaseApp.ts +10 -0
  240. package/lib/common/Base64.ts +10 -16
  241. package/lib/common/deeps.ts +3 -0
  242. package/lib/common/index.ts +20 -9
  243. package/lib/internal/FirebaseModule.ts +6 -3
  244. package/lib/internal/NativeModules.ts +4 -1
  245. package/lib/internal/RNFBNativeEventEmitter.ts +14 -5
  246. package/lib/internal/SharedEventEmitter.ts +5 -1
  247. package/lib/internal/asyncStorage.ts +7 -11
  248. package/lib/internal/index.ts +1 -0
  249. package/lib/internal/logger.ts +53 -43
  250. package/lib/internal/nativeModuleAndroidIos.ts +2 -40
  251. package/lib/internal/nativeModuleDebug.ts +97 -0
  252. package/lib/internal/nativeModuleWeb.ts +10 -40
  253. package/lib/internal/react-native-vendor-emitter.d.ts +11 -0
  254. package/lib/internal/registry/app.ts +8 -2
  255. package/lib/internal/registry/modular.ts +2 -2
  256. package/lib/internal/registry/nativeModule.ts +3 -3
  257. package/lib/internal/web/RNFBAppModule.ts +16 -15
  258. package/lib/internal/web/memidb/lib/FakeEventTarget.js +3 -1
  259. package/lib/types/app.ts +10 -3
  260. package/lib/types/internal.ts +19 -0
  261. package/lib/version.ts +1 -1
  262. package/package.json +9 -8
  263. package/plugin/build/ios/appDelegate.js +19 -9
  264. package/plugin/build/ios/podfile.js +16 -16
  265. package/plugin/build/pluginConfig.d.ts +4 -2
  266. package/plugin/src/ios/appDelegate.ts +45 -15
  267. package/plugin/src/ios/podfile.ts +20 -23
  268. package/plugin/src/pluginConfig.ts +4 -2
  269. package/android/src/main/java/io/invertase/firebase/common/TaskExecutorService.java +0 -124
  270. package/android/src/main/java/io/invertase/firebase/common/UniversalFirebaseModule.java +0 -62
  271. package/android/src/main/java/io/invertase/firebase/common/UniversalFirebasePreferences.java +0 -91
  272. package/android/src/reactnative/java/io/invertase/firebase/app/NativeRNFBTurboApp.java +0 -222
  273. package/android/src/reactnative/java/io/invertase/firebase/app/ReactNativeFirebaseApp.java +0 -46
  274. package/android/src/reactnative/java/io/invertase/firebase/app/ReactNativeFirebaseAppPackage.java +0 -49
  275. package/android/src/reactnative/java/io/invertase/firebase/common/RCTConvertFirebase.java +0 -191
  276. package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseEvent.java +0 -53
  277. package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseEventEmitter.java +0 -606
  278. package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseJSON.java +0 -107
  279. package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseMeta.java +0 -101
  280. package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseModule.java +0 -146
  281. package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebasePreferences.java +0 -96
  282. package/android/src/reactnative/java/io/invertase/firebase/common/SharedUtils.java +0 -441
  283. package/android/src/reactnative/java/io/invertase/firebase/utils/NativeRNFBTurboUtils.java +0 -223
@@ -19,89 +19,583 @@ package io.invertase.firebase.utils;
19
19
 
20
20
  import static org.junit.Assert.assertEquals;
21
21
  import static org.junit.Assert.assertFalse;
22
+ import static org.junit.Assert.assertTrue;
23
+ import static org.mockito.ArgumentMatchers.any;
22
24
  import static org.mockito.ArgumentMatchers.anyInt;
23
25
  import static org.mockito.ArgumentMatchers.anyString;
26
+ import static org.mockito.ArgumentMatchers.eq;
24
27
  import static org.mockito.Mockito.mock;
28
+ import static org.mockito.Mockito.mockConstruction;
29
+ import static org.mockito.Mockito.mockStatic;
30
+ import static org.mockito.Mockito.never;
31
+ import static org.mockito.Mockito.verify;
32
+ import static org.mockito.Mockito.verifyNoInteractions;
25
33
  import static org.mockito.Mockito.when;
26
34
 
35
+ import android.app.Activity;
36
+ import android.app.Dialog;
37
+ import android.content.IntentSender;
27
38
  import android.content.pm.PackageInfo;
28
39
  import android.content.pm.PackageManager;
29
40
  import android.content.pm.PackageManager.NameNotFoundException;
41
+ import android.os.Build;
42
+ import android.os.Environment;
43
+ import android.provider.Settings;
44
+ import android.util.Log;
45
+ import com.facebook.fbreact.specs.NativeRNFBTurboUtilsSpec;
46
+ import com.facebook.react.bridge.Arguments;
47
+ import com.facebook.react.bridge.Promise;
30
48
  import com.facebook.react.bridge.ReactApplicationContext;
49
+ import com.facebook.react.bridge.UiThreadUtil;
50
+ import com.facebook.react.bridge.WritableMap;
51
+ import com.google.android.gms.common.ConnectionResult;
52
+ import com.google.android.gms.common.GoogleApiAvailability;
53
+ import com.google.android.gms.tasks.OnCompleteListener;
54
+ import com.google.android.gms.tasks.Task;
31
55
  import io.invertase.firebase.app.ReactNativeFirebaseApp;
56
+ import java.io.File;
57
+ import java.lang.reflect.Constructor;
32
58
  import java.lang.reflect.Method;
59
+ import java.lang.reflect.Modifier;
60
+ import java.lang.reflect.ParameterizedType;
33
61
  import java.util.Map;
62
+ import java.util.concurrent.atomic.AtomicReference;
63
+ import org.junit.After;
34
64
  import org.junit.Before;
35
65
  import org.junit.Test;
36
66
  import org.junit.runner.RunWith;
67
+ import org.mockito.MockedConstruction;
68
+ import org.mockito.MockedStatic;
37
69
  import org.robolectric.RobolectricTestRunner;
38
70
  import org.robolectric.RuntimeEnvironment;
39
- import org.robolectric.annotation.Config;
71
+ import org.robolectric.util.ReflectionHelpers;
40
72
 
41
- /**
42
- * JVM coverage for {@link NativeRNFBTurboUtils} appVersion constant export branches (null, empty,
43
- * package-manager failure).
44
- */
73
+ /** JVM branch and ABI coverage for {@link NativeRNFBTurboUtils}. */
45
74
  @RunWith(RobolectricTestRunner.class)
46
- @Config(sdk = 34)
47
75
  public class NativeRNFBTurboUtilsTest {
48
76
 
77
+ private android.app.Application application;
49
78
  private ReactApplicationContext reactContext;
50
79
  private PackageManager packageManager;
51
80
  private String packageName;
81
+ private File filesDirectory;
82
+ private File cacheDirectory;
83
+ private File externalDirectory;
52
84
 
53
85
  @Before
54
86
  public void setUp() {
55
- android.app.Application application = RuntimeEnvironment.getApplication();
87
+ application = RuntimeEnvironment.getApplication();
56
88
  ReactNativeFirebaseApp.setApplicationContext(application);
89
+ Settings.System.putString(application.getContentResolver(), "firebase.test.lab", null);
57
90
 
58
91
  packageName = application.getPackageName();
59
92
  packageManager = mock(PackageManager.class);
93
+ filesDirectory = new File("/data/files");
94
+ cacheDirectory = new File("/data/cache");
95
+ externalDirectory = new File("/external/app");
60
96
 
61
97
  reactContext = mock(ReactApplicationContext.class);
62
98
  when(reactContext.getApplicationContext()).thenReturn(application);
63
99
  when(reactContext.getPackageName()).thenReturn(packageName);
64
100
  when(reactContext.getPackageManager()).thenReturn(packageManager);
65
- when(reactContext.getFilesDir()).thenReturn(application.getFilesDir());
66
- when(reactContext.getCacheDir()).thenReturn(application.getCacheDir());
67
- when(reactContext.getExternalFilesDir(null)).thenReturn(application.getExternalFilesDir(null));
101
+ when(reactContext.getFilesDir()).thenReturn(filesDirectory);
102
+ when(reactContext.getCacheDir()).thenReturn(cacheDirectory);
103
+ when(reactContext.getExternalFilesDir(null)).thenReturn(externalDirectory);
104
+ }
105
+
106
+ @After
107
+ public void tearDown() {
108
+ Settings.System.putString(application.getContentResolver(), "firebase.test.lab", null);
109
+ }
110
+
111
+ @Test
112
+ public void javaAbi_preservesOpenClassPublicConstructorSpecAndConstantsSignature()
113
+ throws Exception {
114
+ assertTrue(Modifier.isPublic(NativeRNFBTurboUtils.class.getModifiers()));
115
+ assertFalse(Modifier.isFinal(NativeRNFBTurboUtils.class.getModifiers()));
116
+ assertEquals(NativeRNFBTurboUtilsSpec.class, NativeRNFBTurboUtils.class.getSuperclass());
117
+
118
+ Constructor<NativeRNFBTurboUtils> constructor =
119
+ NativeRNFBTurboUtils.class.getDeclaredConstructor(ReactApplicationContext.class);
120
+ assertTrue(Modifier.isPublic(constructor.getModifiers()));
121
+
122
+ Method constants = NativeRNFBTurboUtils.class.getDeclaredMethod("getTypedExportedConstants");
123
+ assertTrue(Modifier.isProtected(constants.getModifiers()));
124
+ assertEquals(Map.class, constants.getReturnType());
125
+ ParameterizedType returnType = (ParameterizedType) constants.getGenericReturnType();
126
+ assertEquals(String.class, returnType.getActualTypeArguments()[0]);
127
+ assertEquals(Object.class, returnType.getActualTypeArguments()[1]);
128
+ }
129
+
130
+ @Test
131
+ public void androidGetPlayServicesStatus_successReturnsOnlyStatusAndAvailability() {
132
+ Promise promise = mock(Promise.class);
133
+ WritableMap result = mock(WritableMap.class);
134
+ GoogleApiAvailability gapi = mock(GoogleApiAvailability.class);
135
+ when(gapi.isGooglePlayServicesAvailable(reactContext)).thenReturn(ConnectionResult.SUCCESS);
136
+
137
+ try (MockedStatic<GoogleApiAvailability> googleApis = mockStatic(GoogleApiAvailability.class);
138
+ MockedStatic<Arguments> arguments = mockStatic(Arguments.class)) {
139
+ googleApis.when(GoogleApiAvailability::getInstance).thenReturn(gapi);
140
+ arguments.when(Arguments::createMap).thenReturn(result);
141
+
142
+ new NativeRNFBTurboUtils(reactContext).androidGetPlayServicesStatus(promise);
143
+
144
+ verify(result).putInt("status", ConnectionResult.SUCCESS);
145
+ verify(result).putBoolean("isAvailable", true);
146
+ verify(result, never()).putString(eq("error"), anyString());
147
+ verify(result, never()).putBoolean(eq("isUserResolvableError"), any(Boolean.class));
148
+ verify(result, never()).putBoolean(eq("hasResolution"), any(Boolean.class));
149
+ verify(promise).resolve(result);
150
+ }
151
+ }
152
+
153
+ @Test
154
+ public void androidGetPlayServicesStatus_failureReturnsExactErrorShape() {
155
+ Promise promise = mock(Promise.class);
156
+ WritableMap result = mock(WritableMap.class);
157
+ GoogleApiAvailability gapi = mock(GoogleApiAvailability.class);
158
+ int status = ConnectionResult.SERVICE_VERSION_UPDATE_REQUIRED;
159
+ when(gapi.isGooglePlayServicesAvailable(reactContext)).thenReturn(status);
160
+ when(gapi.getErrorString(status)).thenReturn("SERVICE_VERSION_UPDATE_REQUIRED");
161
+ when(gapi.isUserResolvableError(status)).thenReturn(true);
162
+ AtomicReference<Object> constructedStatus = new AtomicReference<>();
163
+
164
+ try (MockedStatic<GoogleApiAvailability> googleApis = mockStatic(GoogleApiAvailability.class);
165
+ MockedStatic<Arguments> arguments = mockStatic(Arguments.class);
166
+ MockedConstruction<ConnectionResult> connectionResults =
167
+ mockConstruction(
168
+ ConnectionResult.class,
169
+ (mock, context) -> {
170
+ constructedStatus.set(context.arguments().get(0));
171
+ when(mock.hasResolution()).thenReturn(true);
172
+ })) {
173
+ googleApis.when(GoogleApiAvailability::getInstance).thenReturn(gapi);
174
+ arguments.when(Arguments::createMap).thenReturn(result);
175
+
176
+ new NativeRNFBTurboUtils(reactContext).androidGetPlayServicesStatus(promise);
177
+
178
+ assertEquals(status, constructedStatus.get());
179
+ verify(result).putInt("status", status);
180
+ verify(result).putBoolean("isAvailable", false);
181
+ verify(result).putString("error", "SERVICE_VERSION_UPDATE_REQUIRED");
182
+ verify(result).putBoolean("isUserResolvableError", true);
183
+ verify(result).putBoolean("hasResolution", true);
184
+ verify(promise).resolve(result);
185
+ }
186
+ }
187
+
188
+ @Test
189
+ public void androidPromptForPlayServices_getsStatusBeforeGapiAndShowsDialog() {
190
+ Promise promise = mock(Promise.class);
191
+ Activity activity = mock(Activity.class);
192
+ Dialog dialog = mock(Dialog.class);
193
+ GoogleApiAvailability gapi = mock(GoogleApiAvailability.class);
194
+ int status = ConnectionResult.SERVICE_MISSING;
195
+ when(reactContext.getCurrentActivity()).thenReturn(activity);
196
+ when(gapi.isGooglePlayServicesAvailable(reactContext)).thenReturn(status);
197
+ when(gapi.isUserResolvableError(status)).thenReturn(true);
198
+ when(gapi.getErrorDialog(activity, status, status)).thenReturn(dialog);
199
+
200
+ AtomicReference<Integer> getInstanceCalls = new AtomicReference<>(0);
201
+ try (MockedStatic<GoogleApiAvailability> googleApis = mockStatic(GoogleApiAvailability.class)) {
202
+ googleApis
203
+ .when(GoogleApiAvailability::getInstance)
204
+ .thenAnswer(
205
+ invocation -> {
206
+ getInstanceCalls.set(getInstanceCalls.get() + 1);
207
+ return gapi;
208
+ });
209
+
210
+ new NativeRNFBTurboUtils(reactContext).androidPromptForPlayServices(promise);
211
+
212
+ assertEquals(Integer.valueOf(2), getInstanceCalls.get());
213
+ verify(gapi).isGooglePlayServicesAvailable(reactContext);
214
+ verify(gapi).isUserResolvableError(status);
215
+ verify(gapi).getErrorDialog(activity, status, status);
216
+ verify(dialog).show();
217
+ verify(promise).resolve(null);
218
+ }
219
+ }
220
+
221
+ @Test
222
+ public void androidPromptForPlayServices_skipsDialogForSuccessUnresolvableOrNullActivity() {
223
+ assertPromptSkipsDialog(ConnectionResult.SUCCESS, true, mock(Activity.class));
224
+ assertPromptSkipsDialog(ConnectionResult.SERVICE_INVALID, false, mock(Activity.class));
225
+ assertPromptSkipsDialog(ConnectionResult.SERVICE_MISSING, true, null);
226
+ }
227
+
228
+ @Test
229
+ public void androidResolutionForPlayServices_startsResolutionAndAlwaysResolves()
230
+ throws Exception {
231
+ Promise promise = mock(Promise.class);
232
+ Activity activity = mock(Activity.class);
233
+ GoogleApiAvailability gapi = mock(GoogleApiAvailability.class);
234
+ int status = ConnectionResult.RESOLUTION_REQUIRED;
235
+ when(reactContext.getCurrentActivity()).thenReturn(activity);
236
+ when(gapi.isGooglePlayServicesAvailable(reactContext)).thenReturn(status);
237
+ AtomicReference<Object> constructedStatus = new AtomicReference<>();
238
+
239
+ try (MockedStatic<GoogleApiAvailability> googleApis = mockStatic(GoogleApiAvailability.class);
240
+ MockedConstruction<ConnectionResult> connectionResults =
241
+ mockConstruction(
242
+ ConnectionResult.class,
243
+ (mock, context) -> {
244
+ constructedStatus.set(context.arguments().get(0));
245
+ when(mock.isSuccess()).thenReturn(false);
246
+ when(mock.hasResolution()).thenReturn(true);
247
+ })) {
248
+ googleApis.when(GoogleApiAvailability::getInstance).thenReturn(gapi);
249
+
250
+ new NativeRNFBTurboUtils(reactContext).androidResolutionForPlayServices(promise);
251
+
252
+ assertEquals(status, constructedStatus.get());
253
+ verify(connectionResults.constructed().get(0)).startResolutionForResult(activity, status);
254
+ verify(promise).resolve(null);
255
+ }
256
+ }
257
+
258
+ @Test
259
+ public void androidResolutionForPlayServices_skipsSuccessNoResolutionAndNullActivity() {
260
+ assertResolutionSkipped(true, true, mock(Activity.class));
261
+ assertResolutionSkipped(false, false, mock(Activity.class));
262
+ assertResolutionSkipped(false, true, null);
263
+ }
264
+
265
+ @Test
266
+ public void androidResolutionForPlayServices_logsSendIntentExceptionAndResolves()
267
+ throws Exception {
268
+ Promise promise = mock(Promise.class);
269
+ Activity activity = mock(Activity.class);
270
+ GoogleApiAvailability gapi = mock(GoogleApiAvailability.class);
271
+ IntentSender.SendIntentException error = new IntentSender.SendIntentException("send failed");
272
+ int status = ConnectionResult.RESOLUTION_REQUIRED;
273
+ when(reactContext.getCurrentActivity()).thenReturn(activity);
274
+ when(gapi.isGooglePlayServicesAvailable(reactContext)).thenReturn(status);
275
+
276
+ try (MockedStatic<GoogleApiAvailability> googleApis = mockStatic(GoogleApiAvailability.class);
277
+ MockedConstruction<ConnectionResult> connectionResults =
278
+ mockConstruction(
279
+ ConnectionResult.class,
280
+ (mock, context) -> {
281
+ when(mock.isSuccess()).thenReturn(false);
282
+ when(mock.hasResolution()).thenReturn(true);
283
+ org.mockito.Mockito.doThrow(error)
284
+ .when(mock)
285
+ .startResolutionForResult(activity, status);
286
+ });
287
+ MockedStatic<Log> logs = mockStatic(Log.class)) {
288
+ googleApis.when(GoogleApiAvailability::getInstance).thenReturn(gapi);
289
+
290
+ new NativeRNFBTurboUtils(reactContext).androidResolutionForPlayServices(promise);
291
+
292
+ logs.verify(() -> Log.d("Utils", "resolutionForPlayServices", error));
293
+ verify(promise).resolve(null);
294
+ }
295
+ }
296
+
297
+ @Test
298
+ public void androidMakePlayServicesAvailable_successStatusResolvesImmediately() {
299
+ Promise promise = mock(Promise.class);
300
+ GoogleApiAvailability gapi = mock(GoogleApiAvailability.class);
301
+ when(gapi.isGooglePlayServicesAvailable(reactContext)).thenReturn(ConnectionResult.SUCCESS);
302
+
303
+ try (MockedStatic<GoogleApiAvailability> googleApis = mockStatic(GoogleApiAvailability.class);
304
+ MockedStatic<UiThreadUtil> uiThread = mockStatic(UiThreadUtil.class)) {
305
+ googleApis.when(GoogleApiAvailability::getInstance).thenReturn(gapi);
306
+
307
+ new NativeRNFBTurboUtils(reactContext).androidMakePlayServicesAvailable(promise);
308
+
309
+ verify(promise).resolve(null);
310
+ uiThread.verifyNoInteractions();
311
+ }
312
+ }
313
+
314
+ @Test
315
+ public void androidMakePlayServicesAvailable_nonSuccessSchedulesUiAndNullActivityResolves() {
316
+ Promise promise = mock(Promise.class);
317
+ GoogleApiAvailability gapi = mock(GoogleApiAvailability.class);
318
+ when(gapi.isGooglePlayServicesAvailable(reactContext))
319
+ .thenReturn(ConnectionResult.SERVICE_MISSING);
320
+ when(reactContext.getCurrentActivity()).thenReturn(null);
321
+ AtomicReference<Runnable> scheduled = new AtomicReference<>();
322
+
323
+ try (MockedStatic<GoogleApiAvailability> googleApis = mockStatic(GoogleApiAvailability.class);
324
+ MockedStatic<UiThreadUtil> uiThread = mockStatic(UiThreadUtil.class)) {
325
+ googleApis.when(GoogleApiAvailability::getInstance).thenReturn(gapi);
326
+ uiThread
327
+ .when(() -> UiThreadUtil.runOnUiThread(any(Runnable.class)))
328
+ .thenAnswer(
329
+ invocation -> {
330
+ scheduled.set(invocation.getArgument(0));
331
+ return null;
332
+ });
333
+
334
+ new NativeRNFBTurboUtils(reactContext).androidMakePlayServicesAvailable(promise);
335
+
336
+ verifyNoInteractions(promise);
337
+ scheduled.get().run();
338
+ verify(promise).resolve(null);
339
+ verify(gapi, never()).makeGooglePlayServicesAvailable(any(Activity.class));
340
+ }
68
341
  }
69
342
 
70
343
  @Test
71
- public void getTypedExportedConstants_includesAppVersionWhenPresent() throws Exception {
344
+ public void androidMakePlayServicesAvailable_taskSuccessResolvesOnlyOnCompletion() {
345
+ Task<Void> task = taskForCompletion(true, false, null);
346
+ Promise promise = runMakeAvailableAndComplete(task);
347
+ verify(promise).resolve(null);
348
+ }
349
+
350
+ @Test
351
+ public void androidMakePlayServicesAvailable_taskCancellationUsesExactPromiseOverload() {
352
+ Task<Void> task = taskForCompletion(false, true, null);
353
+ Promise promise = runMakeAvailableAndComplete(task);
354
+ verify(promise)
355
+ .reject("play-services-update-canceled", "Play Services update was canceled by the user");
356
+ }
357
+
358
+ @Test
359
+ public void androidMakePlayServicesAvailable_taskFailureUsesExceptionMessageAndCause() {
360
+ Exception error = new Exception("update failed");
361
+ Task<Void> task = taskForCompletion(false, false, error);
362
+ Promise promise = runMakeAvailableAndComplete(task);
363
+ verify(promise).reject("play-services-update-failed", "update failed", error);
364
+ }
365
+
366
+ @Test
367
+ public void androidMakePlayServicesAvailable_taskFailurePreservesNullExceptionMessage() {
368
+ Exception error = new Exception((String) null);
369
+ Task<Void> task = taskForCompletion(false, false, error);
370
+ Promise promise = runMakeAvailableAndComplete(task);
371
+ verify(promise).reject("play-services-update-failed", null, error);
372
+ }
373
+
374
+ @Test
375
+ public void androidMakePlayServicesAvailable_taskFailureWithoutExceptionUsesUnknownError() {
376
+ Task<Void> task = taskForCompletion(false, false, null);
377
+ Promise promise = runMakeAvailableAndComplete(task);
378
+ verify(promise).reject("play-services-update-failed", "Unknown error", (Throwable) null);
379
+ }
380
+
381
+ @Test
382
+ public void getTypedExportedConstants_readsGlobalTestLabSettingWithExactTrueSemantics()
383
+ throws Exception {
384
+ Settings.System.putString(application.getContentResolver(), "firebase.test.lab", "true");
385
+ Map<String, Object> constants = invokeGetTypedExportedConstants();
386
+ assertEquals(true, constants.get("isRunningInTestLab"));
387
+
388
+ Settings.System.putString(application.getContentResolver(), "firebase.test.lab", "TRUE");
389
+ constants = invokeGetTypedExportedConstants();
390
+ assertEquals(false, constants.get("isRunningInTestLab"));
391
+ }
392
+
393
+ @Test
394
+ public void getTypedExportedConstants_usesLegacyPackageManagerOverloadOnApi33Plus()
395
+ throws Exception {
72
396
  stubVersionName("4.5.6");
73
397
 
74
398
  Map<String, Object> constants = invokeGetTypedExportedConstants();
75
399
 
76
400
  assertEquals("4.5.6", constants.get("appVersion"));
401
+ verify(packageManager).getPackageInfo(packageName, 0);
77
402
  }
78
403
 
79
404
  @Test
80
- public void getTypedExportedConstants_omitsAppVersionWhenNull() throws Exception {
81
- stubVersionName(null);
405
+ public void getTypedExportedConstants_usesSameLegacyOverloadBeforeApi33() throws Exception {
406
+ int originalSdk = Build.VERSION.SDK_INT;
407
+ ReflectionHelpers.setStaticField(Build.VERSION.class, "SDK_INT", Build.VERSION_CODES.S_V2);
408
+ try {
409
+ stubVersionName("4.5.6");
82
410
 
83
- Map<String, Object> constants = invokeGetTypedExportedConstants();
411
+ Map<String, Object> constants = invokeGetTypedExportedConstants();
84
412
 
85
- assertFalse(constants.containsKey("appVersion"));
413
+ assertEquals("4.5.6", constants.get("appVersion"));
414
+ verify(packageManager).getPackageInfo(packageName, 0);
415
+ } finally {
416
+ ReflectionHelpers.setStaticField(Build.VERSION.class, "SDK_INT", originalSdk);
417
+ }
86
418
  }
87
419
 
88
420
  @Test
89
- public void getTypedExportedConstants_omitsAppVersionWhenEmpty() throws Exception {
421
+ public void getTypedExportedConstants_omitsNullEmptyAndFailedAppVersions() throws Exception {
422
+ stubVersionName(null);
423
+ assertFalse(invokeGetTypedExportedConstants().containsKey("appVersion"));
424
+
90
425
  stubVersionName("");
426
+ assertFalse(invokeGetTypedExportedConstants().containsKey("appVersion"));
91
427
 
92
- Map<String, Object> constants = invokeGetTypedExportedConstants();
428
+ NameNotFoundException error = new NameNotFoundException(packageName);
429
+ when(packageManager.getPackageInfo(anyString(), anyInt())).thenThrow(error);
430
+ try (MockedStatic<Log> logs = mockStatic(Log.class)) {
431
+ assertFalse(invokeGetTypedExportedConstants().containsKey("appVersion"));
432
+ logs.verify(() -> Log.d("Utils", "getAppVersionName", error));
433
+ }
434
+ }
435
+
436
+ @Test
437
+ public void getTypedExportedConstants_exportsExactPathsAndKeys() throws Exception {
438
+ stubVersionName("1.0");
439
+ File pictures = new File("/storage/Pictures");
440
+ File movies = new File("/storage/Movies");
441
+ File storage = new File("/storage");
93
442
 
94
- assertFalse(constants.containsKey("appVersion"));
443
+ try (MockedStatic<Environment> environment = mockStatic(Environment.class)) {
444
+ environment
445
+ .when(() -> Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES))
446
+ .thenReturn(pictures);
447
+ environment
448
+ .when(() -> Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES))
449
+ .thenReturn(movies);
450
+ environment.when(Environment::getExternalStorageDirectory).thenReturn(storage);
451
+
452
+ Map<String, Object> constants = invokeGetTypedExportedConstants();
453
+
454
+ assertEquals(11, constants.size());
455
+ assertEquals("", constants.get("MAIN_BUNDLE"));
456
+ assertEquals(filesDirectory.getAbsolutePath(), constants.get("LIBRARY_DIRECTORY"));
457
+ assertEquals(externalDirectory.getAbsolutePath(), constants.get("DOCUMENT_DIRECTORY"));
458
+ assertEquals(externalDirectory.getAbsolutePath(), constants.get("EXTERNAL_DIRECTORY"));
459
+ assertEquals(storage.getAbsolutePath(), constants.get("EXTERNAL_STORAGE_DIRECTORY"));
460
+ assertEquals(pictures.getAbsolutePath(), constants.get("PICTURES_DIRECTORY"));
461
+ assertEquals(movies.getAbsolutePath(), constants.get("MOVIES_DIRECTORY"));
462
+ assertEquals(cacheDirectory.getAbsolutePath(), constants.get("TEMP_DIRECTORY"));
463
+ assertEquals(cacheDirectory.getAbsolutePath(), constants.get("CACHES_DIRECTORY"));
464
+ }
95
465
  }
96
466
 
97
467
  @Test
98
- public void getTypedExportedConstants_omitsAppVersionOnNameNotFound() throws Exception {
99
- when(packageManager.getPackageInfo(anyString(), anyInt()))
100
- .thenThrow(new NameNotFoundException(packageName));
468
+ public void getTypedExportedConstants_handlesNullExternalDirectoriesAndOmitsOptionalKeys()
469
+ throws Exception {
470
+ stubVersionName(null);
471
+ when(reactContext.getExternalFilesDir(null)).thenReturn(null);
101
472
 
102
- Map<String, Object> constants = invokeGetTypedExportedConstants();
473
+ try (MockedStatic<Environment> environment = mockStatic(Environment.class)) {
474
+ environment
475
+ .when(() -> Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES))
476
+ .thenReturn(null);
477
+ environment
478
+ .when(() -> Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES))
479
+ .thenReturn(null);
480
+ environment.when(Environment::getExternalStorageDirectory).thenReturn(null);
481
+
482
+ Map<String, Object> constants = invokeGetTypedExportedConstants();
483
+
484
+ assertEquals(filesDirectory.getAbsolutePath(), constants.get("DOCUMENT_DIRECTORY"));
485
+ assertEquals("", constants.get("PICTURES_DIRECTORY"));
486
+ assertEquals("", constants.get("MOVIES_DIRECTORY"));
487
+ assertFalse(constants.containsKey("EXTERNAL_DIRECTORY"));
488
+ assertFalse(constants.containsKey("EXTERNAL_STORAGE_DIRECTORY"));
489
+ assertFalse(constants.containsKey("appVersion"));
490
+ }
491
+ }
492
+
493
+ @Test
494
+ public void getTypedExportedConstants_usesDocumentFallbackBeforeKitkat() throws Exception {
495
+ int originalSdk = Build.VERSION.SDK_INT;
496
+ ReflectionHelpers.setStaticField(
497
+ Build.VERSION.class, "SDK_INT", Build.VERSION_CODES.JELLY_BEAN_MR2);
498
+ try {
499
+ stubVersionName(null);
500
+
501
+ Map<String, Object> constants = invokeGetTypedExportedConstants();
502
+
503
+ assertEquals(filesDirectory.getAbsolutePath(), constants.get("DOCUMENT_DIRECTORY"));
504
+ assertEquals(externalDirectory.getAbsolutePath(), constants.get("EXTERNAL_DIRECTORY"));
505
+ } finally {
506
+ ReflectionHelpers.setStaticField(Build.VERSION.class, "SDK_INT", originalSdk);
507
+ }
508
+ }
509
+
510
+ private void assertPromptSkipsDialog(int status, boolean resolvable, Activity activity) {
511
+ Promise promise = mock(Promise.class);
512
+ GoogleApiAvailability gapi = mock(GoogleApiAvailability.class);
513
+ when(reactContext.getCurrentActivity()).thenReturn(activity);
514
+ when(gapi.isGooglePlayServicesAvailable(reactContext)).thenReturn(status);
515
+ when(gapi.isUserResolvableError(status)).thenReturn(resolvable);
516
+
517
+ try (MockedStatic<GoogleApiAvailability> googleApis = mockStatic(GoogleApiAvailability.class)) {
518
+ googleApis.when(GoogleApiAvailability::getInstance).thenReturn(gapi);
519
+
520
+ new NativeRNFBTurboUtils(reactContext).androidPromptForPlayServices(promise);
521
+
522
+ verify(gapi, never()).getErrorDialog(any(Activity.class), anyInt(), anyInt());
523
+ verify(promise).resolve(null);
524
+ }
525
+ }
526
+
527
+ private void assertResolutionSkipped(boolean success, boolean hasResolution, Activity activity) {
528
+ Promise promise = mock(Promise.class);
529
+ GoogleApiAvailability gapi = mock(GoogleApiAvailability.class);
530
+ int status = ConnectionResult.SERVICE_MISSING;
531
+ when(reactContext.getCurrentActivity()).thenReturn(activity);
532
+ when(gapi.isGooglePlayServicesAvailable(reactContext)).thenReturn(status);
533
+
534
+ try (MockedStatic<GoogleApiAvailability> googleApis = mockStatic(GoogleApiAvailability.class);
535
+ MockedConstruction<ConnectionResult> connectionResults =
536
+ mockConstruction(
537
+ ConnectionResult.class,
538
+ (mock, context) -> {
539
+ when(mock.isSuccess()).thenReturn(success);
540
+ when(mock.hasResolution()).thenReturn(hasResolution);
541
+ })) {
542
+ googleApis.when(GoogleApiAvailability::getInstance).thenReturn(gapi);
543
+
544
+ new NativeRNFBTurboUtils(reactContext).androidResolutionForPlayServices(promise);
545
+
546
+ verify(connectionResults.constructed().get(0), never())
547
+ .startResolutionForResult(any(Activity.class), anyInt());
548
+ verify(promise).resolve(null);
549
+ } catch (IntentSender.SendIntentException impossible) {
550
+ throw new AssertionError(impossible);
551
+ }
552
+ }
553
+
554
+ @SuppressWarnings("unchecked")
555
+ private Task<Void> taskForCompletion(boolean successful, boolean canceled, Exception exception) {
556
+ Task<Void> task = mock(Task.class);
557
+ when(task.isSuccessful()).thenReturn(successful);
558
+ when(task.isCanceled()).thenReturn(canceled);
559
+ when(task.getException()).thenReturn(exception);
560
+ return task;
561
+ }
562
+
563
+ private Promise runMakeAvailableAndComplete(Task<Void> task) {
564
+ Promise promise = mock(Promise.class);
565
+ Activity activity = mock(Activity.class);
566
+ GoogleApiAvailability gapi = mock(GoogleApiAvailability.class);
567
+ when(reactContext.getCurrentActivity()).thenReturn(activity);
568
+ when(gapi.isGooglePlayServicesAvailable(reactContext))
569
+ .thenReturn(ConnectionResult.SERVICE_MISSING);
570
+ when(gapi.makeGooglePlayServicesAvailable(activity)).thenReturn(task);
571
+ AtomicReference<Runnable> scheduled = new AtomicReference<>();
572
+ AtomicReference<OnCompleteListener<Void>> listener = new AtomicReference<>();
573
+ when(task.addOnCompleteListener(any()))
574
+ .thenAnswer(
575
+ invocation -> {
576
+ listener.set(invocation.getArgument(0));
577
+ return task;
578
+ });
579
+
580
+ try (MockedStatic<GoogleApiAvailability> googleApis = mockStatic(GoogleApiAvailability.class);
581
+ MockedStatic<UiThreadUtil> uiThread = mockStatic(UiThreadUtil.class)) {
582
+ googleApis.when(GoogleApiAvailability::getInstance).thenReturn(gapi);
583
+ uiThread
584
+ .when(() -> UiThreadUtil.runOnUiThread(any(Runnable.class)))
585
+ .thenAnswer(
586
+ invocation -> {
587
+ scheduled.set(invocation.getArgument(0));
588
+ return null;
589
+ });
590
+
591
+ new NativeRNFBTurboUtils(reactContext).androidMakePlayServicesAvailable(promise);
103
592
 
104
- assertFalse(constants.containsKey("appVersion"));
593
+ verifyNoInteractions(promise);
594
+ scheduled.get().run();
595
+ verifyNoInteractions(promise);
596
+ listener.get().onComplete(task);
597
+ return promise;
598
+ }
105
599
  }
106
600
 
107
601
  private void stubVersionName(String versionName) throws Exception {
@@ -50,6 +50,16 @@ export default class FirebaseApp {
50
50
  getAppModule().setAutomaticDataCollectionEnabled(this.name, enabled);
51
51
  this._automaticDataCollectionEnabled = enabled;
52
52
  }
53
+
54
+ /**
55
+ * Package-internal: seeds the cached flag from the value the native SDK resolved at
56
+ * initialization, without calling back into native (unlike the public setter).
57
+ *
58
+ * @internal
59
+ */
60
+ _setAutomaticDataCollectionEnabledFromNative(enabled) {
61
+ this._automaticDataCollectionEnabled = enabled;
62
+ }
53
63
  _checkDestroyed() {
54
64
  if (this._deleted) {
55
65
  throw new Error(`Firebase App named '${this._name}' already deleted`);
@@ -1 +1 @@
1
- {"version":3,"names":["getAppModule","FirebaseApp","constructor","options","appConfig","fromNative","deleteApp","name","automaticDataCollectionEnabled","_name","_deleted","_deleteApp","_options","Object","assign","_automaticDataCollectionEnabled","_initialized","_nativeInitialized","enabled","_checkDestroyed","setAutomaticDataCollectionEnabled","Error","extendApp","extendedProps","delete","toString"],"sourceRoot":"../../lib","sources":["FirebaseApp.ts"],"mappings":";;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAASA,YAAY,QAAQ,qCAAkC;AAG/D,eAAe,MAAMC,WAAW,CAAgD;EAS9EC,WAAWA,CACTC,OAA+C,EAC/CC,SAAgD,EAChDC,UAAmB,EACnBC,SAA8B,EAC9B;IACA,MAAM;MAAEC,IAAI,GAAG,WAAW;MAAEC;IAA+B,CAAC,GAAGJ,SAAS;IAExE,IAAI,CAACK,KAAK,GAAGF,IAAI;IACjB,IAAI,CAACG,QAAQ,GAAG,KAAK;IACrB,IAAI,CAACC,UAAU,GAAGL,SAAS;IAC3B,IAAI,CAACM,QAAQ,GAAGC,MAAM,CAACC,MAAM,CAAC,CAAC,CAAC,EAAEX,OAAO,CAAC;IAC1C,IAAI,CAACY,+BAA+B,GAAG,CAAC,CAACP,8BAA8B;IAEvE,IAAIH,UAAU,EAAE;MACd,IAAI,CAACW,YAAY,GAAG,IAAI;MACxB,IAAI,CAACC,kBAAkB,GAAG,IAAI;IAChC,CAAC,MAAM;MACL,IAAI,CAACD,YAAY,GAAG,KAAK;MACzB,IAAI,CAACC,kBAAkB,GAAG,KAAK;IACjC;EACF;EAEA,IAAIV,IAAIA,CAAA,EAAW;IACjB,OAAO,IAAI,CAACE,KAAK;EACnB;EAEA,IAAIN,OAAOA,CAAA,EAA2C;IACpD,OAAOU,MAAM,CAACC,MAAM,CAAC,CAAC,CAAC,EAAE,IAAI,CAACF,QAAQ,CAAC;EACzC;EAEA,IAAIJ,8BAA8BA,CAAA,EAAY;IAC5C,OAAO,IAAI,CAACO,+BAA+B;EAC7C;EAEA,IAAIP,8BAA8BA,CAACU,OAAgB,EAAE;IACnD,IAAI,CAACC,eAAe,CAAC,CAAC;IACtBnB,YAAY,CAAC,CAAC,CAACoB,iCAAiC,CAAC,IAAI,CAACb,IAAI,EAAEW,OAAO,CAAC;IACpE,IAAI,CAACH,+BAA+B,GAAGG,OAAO;EAChD;EAEQC,eAAeA,CAAA,EAAS;IAC9B,IAAI,IAAI,CAACT,QAAQ,EAAE;MACjB,MAAM,IAAIW,KAAK,CAAC,uBAAuB,IAAI,CAACZ,KAAK,mBAAmB,CAAC;IACvE;EACF;EAEAa,SAASA,CAACC,aAAsC,EAAQ;IACtD,IAAI,CAACJ,eAAe,CAAC,CAAC;IACtBN,MAAM,CAACC,MAAM,CAAC,IAAI,EAAES,aAAa,CAAC;EACpC;EAEAC,MAAMA,CAAA,EAAkB;IACtB,IAAI,CAACL,eAAe,CAAC,CAAC;IACtB,OAAO,IAAI,CAACR,UAAU,CAAC,CAAC;EAC1B;EAEAc,QAAQA,CAAA,EAAW;IACjB,OAAO,IAAI,CAAClB,IAAI;EAClB;AACF","ignoreList":[]}
1
+ {"version":3,"names":["getAppModule","FirebaseApp","constructor","options","appConfig","fromNative","deleteApp","name","automaticDataCollectionEnabled","_name","_deleted","_deleteApp","_options","Object","assign","_automaticDataCollectionEnabled","_initialized","_nativeInitialized","enabled","_checkDestroyed","setAutomaticDataCollectionEnabled","_setAutomaticDataCollectionEnabledFromNative","Error","extendApp","extendedProps","delete","toString"],"sourceRoot":"../../lib","sources":["FirebaseApp.ts"],"mappings":";;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAASA,YAAY,QAAQ,qCAAkC;AAG/D,eAAe,MAAMC,WAAW,CAAgD;EAS9EC,WAAWA,CACTC,OAA+C,EAC/CC,SAAgD,EAChDC,UAAmB,EACnBC,SAA8B,EAC9B;IACA,MAAM;MAAEC,IAAI,GAAG,WAAW;MAAEC;IAA+B,CAAC,GAAGJ,SAAS;IAExE,IAAI,CAACK,KAAK,GAAGF,IAAI;IACjB,IAAI,CAACG,QAAQ,GAAG,KAAK;IACrB,IAAI,CAACC,UAAU,GAAGL,SAAS;IAC3B,IAAI,CAACM,QAAQ,GAAGC,MAAM,CAACC,MAAM,CAAC,CAAC,CAAC,EAAEX,OAAO,CAAC;IAC1C,IAAI,CAACY,+BAA+B,GAAG,CAAC,CAACP,8BAA8B;IAEvE,IAAIH,UAAU,EAAE;MACd,IAAI,CAACW,YAAY,GAAG,IAAI;MACxB,IAAI,CAACC,kBAAkB,GAAG,IAAI;IAChC,CAAC,MAAM;MACL,IAAI,CAACD,YAAY,GAAG,KAAK;MACzB,IAAI,CAACC,kBAAkB,GAAG,KAAK;IACjC;EACF;EAEA,IAAIV,IAAIA,CAAA,EAAW;IACjB,OAAO,IAAI,CAACE,KAAK;EACnB;EAEA,IAAIN,OAAOA,CAAA,EAA2C;IACpD,OAAOU,MAAM,CAACC,MAAM,CAAC,CAAC,CAAC,EAAE,IAAI,CAACF,QAAQ,CAAC;EACzC;EAEA,IAAIJ,8BAA8BA,CAAA,EAAY;IAC5C,OAAO,IAAI,CAACO,+BAA+B;EAC7C;EAEA,IAAIP,8BAA8BA,CAACU,OAAgB,EAAE;IACnD,IAAI,CAACC,eAAe,CAAC,CAAC;IACtBnB,YAAY,CAAC,CAAC,CAACoB,iCAAiC,CAAC,IAAI,CAACb,IAAI,EAAEW,OAAO,CAAC;IACpE,IAAI,CAACH,+BAA+B,GAAGG,OAAO;EAChD;;EAEA;AACF;AACA;AACA;AACA;AACA;EACEG,4CAA4CA,CAACH,OAAgB,EAAQ;IACnE,IAAI,CAACH,+BAA+B,GAAGG,OAAO;EAChD;EAEQC,eAAeA,CAAA,EAAS;IAC9B,IAAI,IAAI,CAACT,QAAQ,EAAE;MACjB,MAAM,IAAIY,KAAK,CAAC,uBAAuB,IAAI,CAACb,KAAK,mBAAmB,CAAC;IACvE;EACF;EAEAc,SAASA,CAACC,aAAsC,EAAQ;IACtD,IAAI,CAACL,eAAe,CAAC,CAAC;IACtBN,MAAM,CAACC,MAAM,CAAC,IAAI,EAAEU,aAAa,CAAC;EACpC;EAEAC,MAAMA,CAAA,EAAkB;IACtB,IAAI,CAACN,eAAe,CAAC,CAAC;IACtB,OAAO,IAAI,CAACR,UAAU,CAAC,CAAC;EAC1B;EAEAe,QAAQA,CAAA,EAAW;IACjB,OAAO,IAAI,CAACnB,IAAI;EAClB;AACF","ignoreList":[]}