@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
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Copyright (c) 2016-present Invertase Limited & Contributors
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this library except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ import Foundation
18
+ import XCTest
19
+
20
+ final class RNFBAppLogLevelMapperTests: XCTestCase {
21
+ /// `FIRLoggerLevelError`
22
+ private let errorLevel = 3
23
+ /// `FIRLoggerLevelWarning`
24
+ private let warningLevel = 4
25
+ /// `FIRLoggerLevelInfo`
26
+ private let infoLevel = 6
27
+ /// `FIRLoggerLevelDebug`
28
+ private let debugLevel = 7
29
+
30
+ func testVerboseMapsToDebug() {
31
+ XCTAssertEqual(RNFBAppLogLevelMapper.loggerLevel(forString: "verbose"), debugLevel)
32
+ }
33
+
34
+ func testDebugMapsToDebug() {
35
+ XCTAssertEqual(RNFBAppLogLevelMapper.loggerLevel(forString: "debug"), debugLevel)
36
+ }
37
+
38
+ func testInfoMapsToInfo() {
39
+ XCTAssertEqual(RNFBAppLogLevelMapper.loggerLevel(forString: "info"), infoLevel)
40
+ }
41
+
42
+ func testWarnMapsToWarning() {
43
+ XCTAssertEqual(RNFBAppLogLevelMapper.loggerLevel(forString: "warn"), warningLevel)
44
+ }
45
+
46
+ func testUnknownMapsToError() {
47
+ XCTAssertEqual(RNFBAppLogLevelMapper.loggerLevel(forString: "silent"), errorLevel)
48
+ XCTAssertEqual(RNFBAppLogLevelMapper.loggerLevel(forString: "error"), errorLevel)
49
+ XCTAssertEqual(RNFBAppLogLevelMapper.loggerLevel(forString: "bogus"), errorLevel)
50
+ }
51
+
52
+ func testNilMapsToError() {
53
+ XCTAssertEqual(RNFBAppLogLevelMapper.loggerLevel(forString: nil), errorLevel)
54
+ }
55
+
56
+ func testEmptyStringMapsToError() {
57
+ XCTAssertEqual(RNFBAppLogLevelMapper.loggerLevel(forString: ""), errorLevel)
58
+ }
59
+ }
@@ -0,0 +1,215 @@
1
+ /**
2
+ * Copyright (c) 2016-present Invertase Limited & Contributors
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this library except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ #import <XCTest/XCTest.h>
18
+
19
+ #import "FirebaseCore/FirebaseCore.h"
20
+ #import "RNFBHandleMapStorage-Swift.inc"
21
+
22
+ @interface RNFBAppModuleFirebaseFacadeTests : XCTestCase
23
+ @end
24
+
25
+ @implementation RNFBAppModuleFirebaseFacadeTests
26
+
27
+ - (void)tearDown {
28
+ [FIRApp resetRegistryForTesting];
29
+ [FIRConfiguration resetForTesting];
30
+ [RNFBAppModuleFirebase resetRegisterLibraryOnceForTesting];
31
+ [RNFBAppCustomAuthDomains resetCustomDomainsForTesting];
32
+ [super tearDown];
33
+ }
34
+
35
+ - (void)testFacadeOptionsFactoryCreatesFIROptions {
36
+ id<RNFBFIROptionsCreating> factory = [RNFBAppModuleFirebase optionsFactory];
37
+ id options = [factory createWithGoogleAppID:@"app-id" gcmSenderID:@"sender-id"];
38
+ XCTAssertTrue([options isKindOfClass:NSClassFromString(@"RNFBFIROptionsConfiguringAdapter")]);
39
+ FIROptions *firOptions = [options valueForKey:@"options"];
40
+
41
+ XCTAssertEqualObjects(firOptions.googleAppID, @"app-id");
42
+ XCTAssertEqualObjects(firOptions.GCMSenderID, @"sender-id");
43
+ }
44
+
45
+ - (void)testFacadeOptionsFactoryForwardsNilGoogleAppIDAndSenderID {
46
+ id<RNFBFIROptionsCreating> factory = [RNFBAppModuleFirebase optionsFactory];
47
+ id options = [factory createWithGoogleAppID:nil gcmSenderID:nil];
48
+ XCTAssertTrue([options isKindOfClass:NSClassFromString(@"RNFBFIROptionsConfiguringAdapter")]);
49
+ FIROptions *firOptions = [options valueForKey:@"options"];
50
+
51
+ XCTAssertNil(firOptions.googleAppID);
52
+ XCTAssertNil(firOptions.GCMSenderID);
53
+ }
54
+
55
+ - (void)testFacadeAllAppsIncludesConfiguredDefaultAndNamed {
56
+ FIROptions *options = [[FIROptions alloc] initWithGoogleAppID:@"app-id" GCMSenderID:@"sender"];
57
+ [FIRApp configureWithOptions:options];
58
+ [FIRApp configureWithName:@"secondary" options:options];
59
+
60
+ NSArray *apps = [RNFBAppModuleFirebase allApps];
61
+ XCTAssertEqual(apps.count, 2);
62
+ }
63
+
64
+ - (void)testFacadeConfigureOrReuseDefaultReusesExisting {
65
+ FIROptions *options = [[FIROptions alloc] initWithGoogleAppID:@"app-id" GCMSenderID:@"sender"];
66
+ [FIRApp configureWithOptions:options];
67
+ FIRApp *existing = [FIRApp defaultApp];
68
+
69
+ RNFBAppInitializeNameResolution *names =
70
+ [[RNFBAppInitializeNameResolution alloc] initWithAppName:@"[DEFAULT]"
71
+ jsAppName:@"[DEFAULT]"
72
+ isDefaultApp:YES];
73
+ id result = [RNFBAppModuleFirebase configureOrReuseAppWithOptions:(id)options
74
+ nameResolution:names];
75
+
76
+ XCTAssertEqual(result, existing);
77
+ }
78
+
79
+ - (void)testFacadeConfigureOrReuseDefaultConfiguresWhenMissing {
80
+ FIROptions *options = [[FIROptions alloc] initWithGoogleAppID:@"app-id" GCMSenderID:@"sender"];
81
+ RNFBAppInitializeNameResolution *names =
82
+ [[RNFBAppInitializeNameResolution alloc] initWithAppName:nil
83
+ jsAppName:@"[DEFAULT]"
84
+ isDefaultApp:YES];
85
+
86
+ id result = [RNFBAppModuleFirebase configureOrReuseAppWithOptions:(id)options
87
+ nameResolution:names];
88
+
89
+ XCTAssertEqual(result, [FIRApp defaultApp]);
90
+ XCTAssertEqualObjects(((FIRApp *)result).options.googleAppID, @"app-id");
91
+ }
92
+
93
+ - (void)testFacadeConfigureOrReuseNamed {
94
+ FIROptions *options = [[FIROptions alloc] initWithGoogleAppID:@"app-id" GCMSenderID:@"sender"];
95
+ RNFBAppInitializeNameResolution *names =
96
+ [[RNFBAppInitializeNameResolution alloc] initWithAppName:@"secondary"
97
+ jsAppName:@"secondary"
98
+ isDefaultApp:NO];
99
+
100
+ id result = [RNFBAppModuleFirebase configureOrReuseAppWithOptions:(id)options
101
+ nameResolution:names];
102
+
103
+ XCTAssertEqual(result, [FIRApp appNamed:@"secondary"]);
104
+ }
105
+
106
+ - (void)testFacadeRegisterLibraryOnceRecordsNameAndVersion {
107
+ [RNFBAppModuleFirebase registerLibraryOnceWithName:@"react-native-firebase" version:@"9.9.9"];
108
+ [RNFBAppModuleFirebase registerLibraryOnceWithName:@"react-native-firebase" version:@"ignored"];
109
+
110
+ XCTAssertEqualObjects([FIRApp lastRegisteredLibraryNameForTesting], @"react-native-firebase");
111
+ XCTAssertEqualObjects([FIRApp lastRegisteredLibraryVersionForTesting], @"9.9.9");
112
+ }
113
+
114
+ - (void)testFacadeSetLoggerLevelAppliesDebug {
115
+ [RNFBAppModuleFirebase setLoggerLevel:FIRLoggerLevelDebug];
116
+ XCTAssertEqual([FIRConfiguration sharedInstance].loggerLevel, FIRLoggerLevelDebug);
117
+ }
118
+
119
+ - (void)testFacadeSetLoggerLevelPassesThroughUnknownRawValue {
120
+ [RNFBAppModuleFirebase setLoggerLevel:99];
121
+ XCTAssertEqual([FIRConfiguration sharedInstance].loggerLevel, (FIRLoggerLevel)99);
122
+ }
123
+
124
+ - (void)testFacadeSetAutomaticDataCollectionEnabled {
125
+ FIROptions *options = [[FIROptions alloc] initWithGoogleAppID:@"app-id" GCMSenderID:@"sender"];
126
+ FIRApp *app = [[FIRApp alloc] initWithName:@"secondary" options:options];
127
+ [FIRApp registerAppForTesting:app];
128
+
129
+ [RNFBAppModuleFirebase setAutomaticDataCollectionEnabled:YES forAppName:@"secondary"];
130
+ XCTAssertTrue(app.isDataCollectionDefaultEnabled);
131
+ }
132
+
133
+ - (void)testFacadeSetAutomaticDataCollectionEnabledMissingAppReturnsEarly {
134
+ FIROptions *options = [[FIROptions alloc] initWithGoogleAppID:@"app-id" GCMSenderID:@"sender"];
135
+ FIRApp *app = [[FIRApp alloc] initWithName:@"secondary" options:options];
136
+ [FIRApp registerAppForTesting:app];
137
+
138
+ [RNFBAppModuleFirebase setAutomaticDataCollectionEnabled:YES forAppName:@"missing"];
139
+ XCTAssertFalse(app.isDataCollectionDefaultEnabled);
140
+ }
141
+
142
+ - (void)testFacadeSetDataCollectionDefaultEnabled {
143
+ FIROptions *options = [[FIROptions alloc] initWithGoogleAppID:@"app-id" GCMSenderID:@"sender"];
144
+ FIRApp *app = [[FIRApp alloc] initWithName:@"secondary" options:options];
145
+
146
+ [RNFBAppModuleFirebase setDataCollectionDefaultEnabled:YES forApp:app];
147
+ XCTAssertTrue(app.isDataCollectionDefaultEnabled);
148
+ }
149
+
150
+ - (void)testFacadeSetDataCollectionDefaultEnabledNonFirebaseAppReturnsEarly {
151
+ FIROptions *options = [[FIROptions alloc] initWithGoogleAppID:@"app-id" GCMSenderID:@"sender"];
152
+ FIRApp *app = [[FIRApp alloc] initWithName:@"secondary" options:options];
153
+ [FIRApp registerAppForTesting:app];
154
+
155
+ [RNFBAppModuleFirebase setDataCollectionDefaultEnabled:YES forApp:[NSObject new]];
156
+ XCTAssertFalse(app.isDataCollectionDefaultEnabled);
157
+ }
158
+
159
+ - (void)testFacadeDeleteAppRemovesFromRegistry {
160
+ FIROptions *options = [[FIROptions alloc] initWithGoogleAppID:@"app-id" GCMSenderID:@"sender"];
161
+ FIRApp *app = [[FIRApp alloc] initWithName:@"secondary" options:options];
162
+ [FIRApp registerAppForTesting:app];
163
+
164
+ XCTestExpectation *expectation = [self expectationWithDescription:@"delete"];
165
+ [RNFBAppModuleFirebase deleteApp:app
166
+ completion:^(BOOL success) {
167
+ XCTAssertTrue(success);
168
+ [expectation fulfill];
169
+ }];
170
+ [self waitForExpectationsWithTimeout:1 handler:nil];
171
+ XCTAssertNil([FIRApp appNamed:@"secondary"]);
172
+ }
173
+
174
+ - (void)testFacadeDeleteAppNamedMissingResolvesNull {
175
+ XCTestExpectation *expectation = [self expectationWithDescription:@"missing"];
176
+ [RNFBAppModuleFirebase deleteAppNamed:@"does-not-exist"
177
+ resolve:^(id result) {
178
+ XCTAssertEqual(result, [NSNull null]);
179
+ [expectation fulfill];
180
+ }
181
+ reject:^(NSString *code, NSString *message, NSError *error) {
182
+ XCTFail(@"should resolve");
183
+ }];
184
+ [self waitForExpectationsWithTimeout:1 handler:nil];
185
+ }
186
+
187
+ - (void)testFacadeDeleteAppNamedSuccessClearsDomain {
188
+ FIROptions *options = [[FIROptions alloc] initWithGoogleAppID:@"app-id" GCMSenderID:@"sender"];
189
+ FIRApp *app = [[FIRApp alloc] initWithName:@"secondary" options:options];
190
+ [FIRApp registerAppForTesting:app];
191
+ [RNFBAppCustomAuthDomains setCustomDomain:@"auth.example.com" forAppName:@"secondary"];
192
+
193
+ XCTestExpectation *expectation = [self expectationWithDescription:@"delete-named"];
194
+ [RNFBAppModuleFirebase deleteAppNamed:@"secondary"
195
+ resolve:^(id result) {
196
+ XCTAssertEqual(result, [NSNull null]);
197
+ [expectation fulfill];
198
+ }
199
+ reject:^(NSString *code, NSString *message, NSError *error) {
200
+ XCTFail(@"should resolve");
201
+ }];
202
+ [self waitForExpectationsWithTimeout:1 handler:nil];
203
+ XCTAssertNil([FIRApp appNamed:@"secondary"]);
204
+ XCTAssertNil([RNFBAppCustomAuthDomains getCustomDomain:@"secondary"]);
205
+ }
206
+
207
+ - (void)testFacadeAppForNameUsesDefaultDisplayName {
208
+ FIROptions *options = [[FIROptions alloc] initWithGoogleAppID:@"app-id" GCMSenderID:@"sender"];
209
+ [FIRApp configureWithOptions:options];
210
+
211
+ id result = [RNFBAppModuleFirebase appForName:@"[DEFAULT]"];
212
+ XCTAssertEqual(result, [FIRApp defaultApp]);
213
+ }
214
+
215
+ @end
@@ -0,0 +1,430 @@
1
+ /**
2
+ * Copyright (c) 2016-present Invertase Limited & Contributors
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this library except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ import FirebaseCore
18
+ import Foundation
19
+ import XCTest
20
+
21
+ private final class StubFIRAppToken: NSObject {
22
+ let label: String
23
+ init(label: String) {
24
+ self.label = label
25
+ }
26
+ }
27
+
28
+ private final class StubFIRAppLifecycle: NSObject, RNFBFIRAppLifecycle {
29
+ var defaultAppValue: AnyObject?
30
+ var namedApps: [String: AnyObject] = [:]
31
+ var allAppsValue: [AnyHashable: Any]?
32
+ var lastConfigureOptions: AnyObject?
33
+ var lastConfigureName: String?
34
+ var configureDefaultCalled = false
35
+ /// When false, configure succeeds without registering an app (SDK read-back returns nil).
36
+ var registersApps = true
37
+
38
+ func defaultApp() -> AnyObject? {
39
+ defaultAppValue
40
+ }
41
+
42
+ func appNamed(_ name: String) -> AnyObject? {
43
+ namedApps[name]
44
+ }
45
+
46
+ func allApps() -> [AnyHashable: Any]? {
47
+ allAppsValue
48
+ }
49
+
50
+ func configure(withOptions options: AnyObject) {
51
+ configureDefaultCalled = true
52
+ lastConfigureOptions = options
53
+ guard registersApps else { return }
54
+ let app = StubFIRAppToken(label: "configured-default")
55
+ defaultAppValue = app
56
+ }
57
+
58
+ func configure(withName name: String, options: AnyObject) {
59
+ lastConfigureName = name
60
+ lastConfigureOptions = options
61
+ guard registersApps else { return }
62
+ let app = StubFIRAppToken(label: "configured-\(name)")
63
+ namedApps[name] = app
64
+ }
65
+ }
66
+
67
+ private final class StubFIRLibraryRegistrar: NSObject, RNFBFIRLibraryRegistering {
68
+ var names: [String] = []
69
+ var versions: [String] = []
70
+
71
+ func registerLibrary(_ name: String, withVersion version: String) {
72
+ names.append(name)
73
+ versions.append(version)
74
+ }
75
+ }
76
+
77
+ private final class StubFIRLoggerConfiguration: NSObject, RNFBFIRLoggerConfiguring {
78
+ var levels: [Int] = []
79
+
80
+ func setLoggerLevel(_ level: Int) {
81
+ levels.append(level)
82
+ }
83
+ }
84
+
85
+ private final class StubFIRAppMutating: NSObject, RNFBFIRAppMutating {
86
+ var dataCollectionEnabled: Bool?
87
+ var deleteResults: [Bool]
88
+ var deleteCallCount = 0
89
+
90
+ init(deleteResults: [Bool] = [true]) {
91
+ self.deleteResults = deleteResults
92
+ }
93
+
94
+ func setDataCollectionDefaultEnabled(_ enabled: Bool) {
95
+ dataCollectionEnabled = enabled
96
+ }
97
+
98
+ func deleteApp(_ completion: @escaping (Bool) -> Void) {
99
+ let index = min(deleteCallCount, deleteResults.count - 1)
100
+ let result = deleteResults[index]
101
+ deleteCallCount += 1
102
+ completion(result)
103
+ }
104
+ }
105
+
106
+ final class RNFBAppModuleFirebaseTests: XCTestCase {
107
+ override func tearDown() {
108
+ RNFBAppModuleFirebase.resetRegisterLibraryOnceForTesting()
109
+ RNFBAppCustomAuthDomains.resetCustomDomainsForTesting()
110
+ super.tearDown()
111
+ }
112
+
113
+ func testAllAppsReturnsValuesWhenPresent() {
114
+ let lifecycle = StubFIRAppLifecycle()
115
+ let appA = StubFIRAppToken(label: "a")
116
+ let appB = StubFIRAppToken(label: "b")
117
+ lifecycle.allAppsValue = ["a": appA, "b": appB]
118
+
119
+ let result = RNFBAppModuleFirebase.allApps(lifecycle: lifecycle)
120
+
121
+ XCTAssertEqual(result.count, 2)
122
+ XCTAssertTrue(result.contains { $0 === appA })
123
+ XCTAssertTrue(result.contains { $0 === appB })
124
+ }
125
+
126
+ func testAllAppsReturnsEmptyWhenNil() {
127
+ let lifecycle = StubFIRAppLifecycle()
128
+ XCTAssertEqual(RNFBAppModuleFirebase.allApps(lifecycle: lifecycle).count, 0)
129
+ }
130
+
131
+ func testConfigureOrReuseDefaultReusesExisting() {
132
+ let lifecycle = StubFIRAppLifecycle()
133
+ let existing = StubFIRAppToken(label: "existing-default")
134
+ lifecycle.defaultAppValue = existing
135
+ let names = RNFBAppInitializeNameResolution(
136
+ appName: "[DEFAULT]",
137
+ jsAppName: "[DEFAULT]",
138
+ isDefaultApp: true
139
+ )
140
+
141
+ let result = RNFBAppModuleFirebase.configureOrReuseApp(
142
+ options: ConfiguringOptionsStub(),
143
+ nameResolution: names,
144
+ lifecycle: lifecycle
145
+ )
146
+
147
+ XCTAssertTrue(result === existing)
148
+ XCTAssertFalse(lifecycle.configureDefaultCalled)
149
+ }
150
+
151
+ func testConfigureOrReuseDefaultConfiguresWhenMissing() {
152
+ let lifecycle = StubFIRAppLifecycle()
153
+ let names = RNFBAppInitializeNameResolution(
154
+ appName: nil,
155
+ jsAppName: "[DEFAULT]",
156
+ isDefaultApp: true
157
+ )
158
+ let configuring = ConfiguringOptionsStub()
159
+ let result = RNFBAppModuleFirebase.configureOrReuseApp(
160
+ options: configuring,
161
+ nameResolution: names,
162
+ lifecycle: lifecycle
163
+ )
164
+
165
+ XCTAssertTrue(lifecycle.configureDefaultCalled)
166
+ XCTAssertTrue(result === lifecycle.defaultAppValue)
167
+ }
168
+
169
+ func testConfigureOrReuseNamedUsesConfigureWithName() {
170
+ let lifecycle = StubFIRAppLifecycle()
171
+ let names = RNFBAppInitializeNameResolution(
172
+ appName: "secondary",
173
+ jsAppName: "secondary",
174
+ isDefaultApp: false
175
+ )
176
+ let configuring = ConfiguringOptionsStub()
177
+
178
+ let result = RNFBAppModuleFirebase.configureOrReuseApp(
179
+ options: configuring,
180
+ nameResolution: names,
181
+ lifecycle: lifecycle
182
+ )
183
+
184
+ XCTAssertEqual(lifecycle.lastConfigureName, "secondary")
185
+ XCTAssertTrue(result === lifecycle.namedApps["secondary"])
186
+ }
187
+
188
+ func testConfigureOrReuseDefaultReturnsNilInsteadOfTrappingWhenReadBackIsNil() {
189
+ let lifecycle = StubFIRAppLifecycle()
190
+ lifecycle.registersApps = false
191
+ let names = RNFBAppInitializeNameResolution(
192
+ appName: nil,
193
+ jsAppName: "[DEFAULT]",
194
+ isDefaultApp: true
195
+ )
196
+
197
+ let result = RNFBAppModuleFirebase.configureOrReuseApp(
198
+ options: ConfiguringOptionsStub(),
199
+ nameResolution: names,
200
+ lifecycle: lifecycle
201
+ )
202
+
203
+ XCTAssertTrue(lifecycle.configureDefaultCalled)
204
+ XCTAssertNil(result)
205
+ }
206
+
207
+ func testConfigureOrReuseNamedReturnsNilInsteadOfTrappingWhenReadBackIsNil() {
208
+ let lifecycle = StubFIRAppLifecycle()
209
+ lifecycle.registersApps = false
210
+ let names = RNFBAppInitializeNameResolution(
211
+ appName: "secondary",
212
+ jsAppName: "secondary",
213
+ isDefaultApp: false
214
+ )
215
+
216
+ let result = RNFBAppModuleFirebase.configureOrReuseApp(
217
+ options: ConfiguringOptionsStub(),
218
+ nameResolution: names,
219
+ lifecycle: lifecycle
220
+ )
221
+
222
+ XCTAssertEqual(lifecycle.lastConfigureName, "secondary")
223
+ XCTAssertNil(result)
224
+ }
225
+
226
+ func testConfigureOrReuseUnwrapsConfiguringAdapterToLiveOptions() {
227
+ let lifecycle = StubFIRAppLifecycle()
228
+ let names = RNFBAppInitializeNameResolution(
229
+ appName: "secondary",
230
+ jsAppName: "secondary",
231
+ isDefaultApp: false
232
+ )
233
+ let live = FirebaseOptions(googleAppID: "app-id", gcmSenderID: "sender-id")
234
+ let adapter = RNFBFIROptionsConfiguringAdapter(live)
235
+
236
+ _ = RNFBAppModuleFirebase.configureOrReuseApp(
237
+ options: adapter,
238
+ nameResolution: names,
239
+ lifecycle: lifecycle
240
+ )
241
+
242
+ XCTAssertTrue(lifecycle.lastConfigureOptions === live)
243
+ }
244
+
245
+ func testOptionsFactoryReleasesOptionsAndPreservesNilIdentifiers() {
246
+ weak var releasedOptions: FirebaseOptions?
247
+
248
+ autoreleasepool {
249
+ let configured = RNFBAppModuleFirebase.optionsFactory().create(
250
+ googleAppID: nil,
251
+ gcmSenderID: nil
252
+ )
253
+ let adapter = configured as! RNFBFIROptionsConfiguringAdapter
254
+ releasedOptions = adapter.options
255
+
256
+ XCTAssertNil(adapter.options.googleAppID)
257
+ XCTAssertNil(adapter.options.gcmSenderID)
258
+ }
259
+
260
+ XCTAssertNil(releasedOptions)
261
+ }
262
+
263
+ func testDirectRegisterLibrarySkipsMissingSelectorAndForwardsWhenPresent() {
264
+ FirebaseApp.resetRegistryForTesting()
265
+ RNFBFIRLibraryRegisteringAdapter.registerLibrary("skipped", version: "0", on: NSObject.self)
266
+ XCTAssertNil(FirebaseApp.lastRegisteredLibraryNameForTesting())
267
+
268
+ RNFBFIRLibraryRegisteringAdapter.registerLibrary(
269
+ "react-native-firebase",
270
+ version: "1.0.0",
271
+ on: FirebaseApp.self
272
+ )
273
+ XCTAssertEqual(FirebaseApp.lastRegisteredLibraryNameForTesting(), "react-native-firebase")
274
+ XCTAssertEqual(FirebaseApp.lastRegisteredLibraryVersionForTesting(), "1.0.0")
275
+ }
276
+
277
+ func testRegisterLibraryOnceOnlyRegistersOnce() {
278
+ let registrar = StubFIRLibraryRegistrar()
279
+
280
+ RNFBAppModuleFirebase.registerLibraryOnce(
281
+ name: "react-native-firebase",
282
+ version: "1.2.3",
283
+ registrar: registrar
284
+ )
285
+ RNFBAppModuleFirebase.registerLibraryOnce(
286
+ name: "react-native-firebase",
287
+ version: "9.9.9",
288
+ registrar: registrar
289
+ )
290
+
291
+ XCTAssertEqual(registrar.names, ["react-native-firebase"])
292
+ XCTAssertEqual(registrar.versions, ["1.2.3"])
293
+ }
294
+
295
+ func testSetLoggerLevelForwardsToConfiguration() {
296
+ let configuration = StubFIRLoggerConfiguration()
297
+ RNFBAppModuleFirebase.setLoggerLevel(7, configuration: configuration)
298
+ XCTAssertEqual(configuration.levels, [7])
299
+ }
300
+
301
+ func testDeleteAppForwardsToMutating() {
302
+ let mutating = StubFIRAppMutating(deleteResults: [true])
303
+ let app = StubFIRAppToken(label: "app")
304
+ let expectation = expectation(description: "delete")
305
+
306
+ RNFBAppModuleFirebase.deleteApp(app, mutating: mutating) { success in
307
+ XCTAssertTrue(success)
308
+ expectation.fulfill()
309
+ }
310
+
311
+ waitForExpectations(timeout: 1)
312
+ XCTAssertEqual(mutating.deleteCallCount, 1)
313
+ }
314
+ func testDeleteAppCastFailureCompletesFalse() {
315
+ let expectation = expectation(description: "cast-failure")
316
+ RNFBAppModuleFirebase.deleteApp(StubFIRAppToken(label: "not-firebase")) { success in
317
+ XCTAssertFalse(success)
318
+ expectation.fulfill()
319
+ }
320
+ waitForExpectations(timeout: 1)
321
+ }
322
+
323
+ func testDeleteAppNamedResolvesNullWhenMissing() {
324
+ let expectation = expectation(description: "missing")
325
+ RNFBAppModuleFirebase.deleteApp(
326
+ named: "missing",
327
+ resolve: { result in
328
+ XCTAssertTrue(result is NSNull)
329
+ expectation.fulfill()
330
+ },
331
+ reject: { _, _, _ in
332
+ XCTFail("should resolve, not reject")
333
+ },
334
+ appLookup: { _ in nil },
335
+ performDelete: { _, _ in
336
+ XCTFail("should not delete")
337
+ }
338
+ )
339
+ waitForExpectations(timeout: 1)
340
+ }
341
+
342
+ func testDeleteAppNamedResolvesOnFirstSuccess() {
343
+ let app = StubFIRAppToken(label: "app")
344
+ var deleteCalls = 0
345
+ RNFBAppCustomAuthDomains.setCustomDomain("auth.example.com", forAppName: "secondary")
346
+ let expectation = expectation(description: "first-success")
347
+
348
+ RNFBAppModuleFirebase.deleteApp(
349
+ named: "secondary",
350
+ resolve: { result in
351
+ XCTAssertTrue(result is NSNull)
352
+ expectation.fulfill()
353
+ },
354
+ reject: { _, _, _ in
355
+ XCTFail("should resolve")
356
+ },
357
+ appLookup: { _ in app },
358
+ performDelete: { _, completion in
359
+ deleteCalls += 1
360
+ completion(true)
361
+ }
362
+ )
363
+
364
+ waitForExpectations(timeout: 1)
365
+ XCTAssertEqual(deleteCalls, 1)
366
+ XCTAssertNil(RNFBAppCustomAuthDomains.getCustomDomain("secondary"))
367
+ }
368
+
369
+ func testDeleteAppNamedRetriesOnceThenResolves() {
370
+ let app = StubFIRAppToken(label: "app")
371
+ var deleteCalls = 0
372
+ let expectation = expectation(description: "retry-success")
373
+
374
+ RNFBAppModuleFirebase.deleteApp(
375
+ named: "secondary",
376
+ resolve: { result in
377
+ XCTAssertTrue(result is NSNull)
378
+ expectation.fulfill()
379
+ },
380
+ reject: { _, _, _ in
381
+ XCTFail("should resolve after retry")
382
+ },
383
+ appLookup: { _ in app },
384
+ performDelete: { _, completion in
385
+ deleteCalls += 1
386
+ completion(deleteCalls > 1)
387
+ }
388
+ )
389
+
390
+ waitForExpectations(timeout: 1)
391
+ XCTAssertEqual(deleteCalls, 2)
392
+ }
393
+
394
+ func testDeleteAppNamedRejectsWhenBothDeletesFail() {
395
+ let app = StubFIRAppToken(label: "app")
396
+ var deleteCalls = 0
397
+ let expectation = expectation(description: "reject")
398
+
399
+ RNFBAppModuleFirebase.deleteApp(
400
+ named: "secondary",
401
+ resolve: { _ in
402
+ XCTFail("should reject")
403
+ },
404
+ reject: { code, message, _ in
405
+ XCTAssertEqual(code, "app/delete-app-failed")
406
+ XCTAssertEqual(message, "Failed to delete the specified app.")
407
+ expectation.fulfill()
408
+ },
409
+ appLookup: { _ in app },
410
+ performDelete: { _, completion in
411
+ deleteCalls += 1
412
+ completion(false)
413
+ }
414
+ )
415
+
416
+ waitForExpectations(timeout: 1)
417
+ XCTAssertEqual(deleteCalls, 2)
418
+ }
419
+
420
+ }
421
+
422
+ private final class ConfiguringOptionsStub: NSObject, RNFBFIROptionsConfiguring {
423
+ var APIKey: String?
424
+ var projectID: String?
425
+ var clientID: String?
426
+ var databaseURL: String?
427
+ var storageBucket: String?
428
+ var bundleID: String?
429
+ var appGroupID: String?
430
+ }