@react-native-firebase/app 26.4.0 → 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 (242) hide show
  1. package/CHANGELOG.md +48 -0
  2. package/README.md +10 -27
  3. package/RNFBApp.podspec +13 -5
  4. package/android/build.gradle +3 -0
  5. package/android/src/main/java/io/invertase/firebase/common/RNFBHandleCollisionException.kt +29 -0
  6. package/android/src/main/java/io/invertase/firebase/common/RNFBHandleMap.kt +146 -0
  7. package/android/src/main/java/io/invertase/firebase/common/TaskExecutorService.kt +156 -0
  8. package/android/src/main/java/io/invertase/firebase/common/UniversalFirebaseModule.kt +44 -0
  9. package/android/src/main/java/io/invertase/firebase/common/UniversalFirebasePreferences.kt +100 -0
  10. package/android/src/reactnative/java/io/invertase/firebase/app/NativeRNFBTurboApp.kt +250 -0
  11. package/android/src/reactnative/java/io/invertase/firebase/app/ReactNativeFirebaseApp.kt +64 -0
  12. package/android/src/reactnative/java/io/invertase/firebase/app/{ReactNativeFirebaseAppInitProvider.java → ReactNativeFirebaseAppInitProvider.kt} +3 -4
  13. package/android/src/reactnative/java/io/invertase/firebase/app/ReactNativeFirebaseAppPackage.kt +47 -0
  14. package/android/src/reactnative/java/io/invertase/firebase/app/ReactNativeFirebaseAppRegistrar.kt +33 -0
  15. package/android/src/reactnative/java/io/invertase/firebase/app/ReactNativeFirebaseVersion.java +1 -1
  16. package/android/src/reactnative/java/io/invertase/firebase/common/RCTConvertFirebase.kt +185 -0
  17. package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseEvent.kt +35 -0
  18. package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseEventEmitter.kt +662 -0
  19. package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseJSON.kt +103 -0
  20. package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseMeta.kt +96 -0
  21. package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseModule.kt +140 -0
  22. package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebasePreferences.kt +109 -0
  23. package/android/src/reactnative/java/io/invertase/firebase/common/SharedUtils.kt +451 -0
  24. package/android/src/reactnative/java/io/invertase/firebase/interfaces/{ContextProvider.java → ContextProvider.kt} +8 -8
  25. package/android/src/reactnative/java/io/invertase/firebase/interfaces/{NativeError.java → NativeError.kt} +8 -8
  26. package/android/src/reactnative/java/io/invertase/firebase/interfaces/{NativeEvent.java → NativeEvent.kt} +6 -6
  27. package/android/src/reactnative/java/io/invertase/firebase/utils/NativeRNFBTurboUtils.kt +219 -0
  28. package/android/src/test/java/expo/core/ModuleRegistry.java +9 -0
  29. package/android/src/test/java/io/invertase/firebase/app/NativeRNFBTurboAppTest.java +182 -59
  30. package/android/src/test/java/io/invertase/firebase/app/ReactNativeFirebaseAppComponentsJavaCompatibilityTest.java +70 -0
  31. package/android/src/test/java/io/invertase/firebase/app/ReactNativeFirebaseAppJavaCompatibilityTest.java +60 -0
  32. package/android/src/test/java/io/invertase/firebase/app/ReactNativeFirebaseAppPackageTest.java +165 -0
  33. package/android/src/test/java/io/invertase/firebase/app/ReactNativeFirebaseAppTest.kt +167 -0
  34. package/android/src/test/java/io/invertase/firebase/common/RCTConvertFirebaseJavaCompatibilityTest.java +112 -0
  35. package/android/src/test/java/io/invertase/firebase/common/RCTConvertFirebaseTest.kt +317 -0
  36. package/android/src/test/java/io/invertase/firebase/common/RNFBHandleMapTest.kt +309 -0
  37. package/android/src/test/java/io/invertase/firebase/common/ReactNativeFirebaseEventEmitterJavaCompatibilityTest.java +176 -0
  38. package/android/src/test/java/io/invertase/firebase/common/ReactNativeFirebaseEventEmitterTest.java +143 -12
  39. package/android/src/test/java/io/invertase/firebase/common/ReactNativeFirebaseEventTest.kt +61 -0
  40. package/android/src/test/java/io/invertase/firebase/common/ReactNativeFirebaseJSONJavaCompatibilityTest.java +85 -0
  41. package/android/src/test/java/io/invertase/firebase/common/ReactNativeFirebaseJSONTest.kt +296 -0
  42. package/android/src/test/java/io/invertase/firebase/common/ReactNativeFirebaseMetaJavaCompatibilityTest.java +67 -0
  43. package/android/src/test/java/io/invertase/firebase/common/ReactNativeFirebaseMetaTest.kt +246 -0
  44. package/android/src/test/java/io/invertase/firebase/common/ReactNativeFirebaseModuleTest.kt +254 -0
  45. package/android/src/test/java/io/invertase/firebase/common/ReactNativeFirebasePreferencesJavaCompatibilityTest.java +87 -0
  46. package/android/src/test/java/io/invertase/firebase/common/ReactNativeFirebasePreferencesTest.kt +260 -0
  47. package/android/src/test/java/io/invertase/firebase/common/SharedUtilsJavaCompatibilityTest.java +255 -0
  48. package/android/src/test/java/io/invertase/firebase/common/SharedUtilsTest.kt +674 -0
  49. package/android/src/test/java/io/invertase/firebase/common/TaskExecutorServiceTest.kt +290 -0
  50. package/android/src/test/java/io/invertase/firebase/common/UniversalFirebaseModuleJavaCompatibilityTest.java +178 -0
  51. package/android/src/test/java/io/invertase/firebase/common/UniversalFirebasePreferencesJavaCompatibilityTest.java +99 -0
  52. package/android/src/test/java/io/invertase/firebase/common/UniversalFirebasePreferencesTest.kt +217 -0
  53. package/android/src/test/java/io/invertase/firebase/commoncompat/ReactNativeFirebaseModuleJavaCompatibilityTest.java +176 -0
  54. package/android/src/test/java/io/invertase/firebase/commoncompat/ReactNativeFirebaseModuleKotlinCompatibilityTest.kt +52 -0
  55. package/android/src/test/java/io/invertase/firebase/interfaces/InterfacesJavaCompatibilityTest.java +144 -0
  56. package/android/src/test/java/io/invertase/firebase/interfaces/NativeEventTest.kt +56 -0
  57. package/android/src/test/java/io/invertase/firebase/utils/NativeRNFBTurboUtilsTest.java +517 -21
  58. package/dist/module/FirebaseApp.js +10 -0
  59. package/dist/module/FirebaseApp.js.map +1 -1
  60. package/dist/module/common/deeps.js +3 -0
  61. package/dist/module/common/deeps.js.map +1 -1
  62. package/dist/module/internal/FirebaseModule.js.map +1 -1
  63. package/dist/module/internal/RNFBNativeEventEmitter.js +12 -1
  64. package/dist/module/internal/RNFBNativeEventEmitter.js.map +1 -1
  65. package/dist/module/internal/SharedEventEmitter.js +3 -1
  66. package/dist/module/internal/SharedEventEmitter.js.map +1 -1
  67. package/dist/module/internal/index.js +1 -0
  68. package/dist/module/internal/index.js.map +1 -1
  69. package/dist/module/internal/registry/app.js +7 -1
  70. package/dist/module/internal/registry/app.js.map +1 -1
  71. package/dist/module/types/app.js.map +1 -1
  72. package/dist/module/types/internal.js +2 -0
  73. package/dist/module/version.js +1 -1
  74. package/dist/typescript/lib/FirebaseApp.d.ts +7 -0
  75. package/dist/typescript/lib/FirebaseApp.d.ts.map +1 -1
  76. package/dist/typescript/lib/common/deeps.d.ts.map +1 -1
  77. package/dist/typescript/lib/internal/FirebaseModule.d.ts +2 -3
  78. package/dist/typescript/lib/internal/FirebaseModule.d.ts.map +1 -1
  79. package/dist/typescript/lib/internal/NativeModules.d.ts +4 -1
  80. package/dist/typescript/lib/internal/NativeModules.d.ts.map +1 -1
  81. package/dist/typescript/lib/internal/RNFBNativeEventEmitter.d.ts +2 -2
  82. package/dist/typescript/lib/internal/RNFBNativeEventEmitter.d.ts.map +1 -1
  83. package/dist/typescript/lib/internal/SharedEventEmitter.d.ts +3 -3
  84. package/dist/typescript/lib/internal/SharedEventEmitter.d.ts.map +1 -1
  85. package/dist/typescript/lib/internal/index.d.ts +1 -0
  86. package/dist/typescript/lib/internal/index.d.ts.map +1 -1
  87. package/dist/typescript/lib/internal/registry/app.d.ts.map +1 -1
  88. package/dist/typescript/lib/types/app.d.ts +10 -3
  89. package/dist/typescript/lib/types/app.d.ts.map +1 -1
  90. package/dist/typescript/lib/types/internal.d.ts +12 -0
  91. package/dist/typescript/lib/types/internal.d.ts.map +1 -1
  92. package/dist/typescript/lib/version.d.ts +1 -1
  93. package/firebase-schema.json +4 -0
  94. package/firebase_spm.rb +552 -96
  95. package/ios/RNFBApp/RCTConvert+FIRApp.h +2 -5
  96. package/ios/RNFBApp/RCTConvert+FIRApp.m +11 -6
  97. package/ios/RNFBApp/RCTConvert+FIROptions.h +2 -5
  98. package/ios/RNFBApp/RCTConvert+FIROptions.m +11 -10
  99. package/ios/RNFBApp/RCTConvertFIRApp.swift +86 -0
  100. package/ios/RNFBApp/RCTConvertFIROptions.swift +259 -0
  101. package/ios/RNFBApp/RNFBAppCustomAuthDomains.swift +63 -0
  102. package/ios/RNFBApp/RNFBAppInitializeOptionsMapper.swift +113 -0
  103. package/ios/RNFBApp/RNFBAppLogLevelMapper.swift +53 -0
  104. package/ios/RNFBApp/RNFBAppModule+CustomAuthDomain.m +35 -0
  105. package/ios/RNFBApp/RNFBAppModule.h +6 -2
  106. package/ios/RNFBApp/RNFBAppModule.mm +65 -228
  107. package/ios/RNFBApp/RNFBAppModuleFirebase.swift +439 -0
  108. package/ios/RNFBApp/RNFBAppModuleImplementation.h +68 -0
  109. package/ios/RNFBApp/RNFBAppModuleImplementation.m +195 -0
  110. package/ios/RNFBApp/RNFBHandleMap.m +27 -56
  111. package/ios/RNFBApp/RNFBHandleMapStorage.swift +90 -0
  112. package/ios/RNFBApp/RNFBInitializeAppArguments.swift +82 -0
  113. package/ios/RNFBApp/RNFBJSON.m +22 -38
  114. package/ios/RNFBApp/RNFBJSONImplementation.swift +71 -0
  115. package/ios/RNFBApp/RNFBMeta.m +24 -26
  116. package/ios/RNFBApp/RNFBMetaStorage.swift +76 -0
  117. package/ios/RNFBApp/RNFBNullSentinelDecoding.swift +135 -0
  118. package/ios/RNFBApp/RNFBNullSentinelInterceptor.h +30 -3
  119. package/ios/RNFBApp/RNFBNullSentinelInterceptor.m +28 -5
  120. package/ios/RNFBApp/RNFBPreferences.m +22 -20
  121. package/ios/RNFBApp/RNFBPreferencesStorage.swift +101 -0
  122. package/ios/RNFBApp/RNFBRCTEventEmitter.m +36 -93
  123. package/ios/RNFBApp/RNFBRCTEventEmitterCore.swift +161 -0
  124. package/ios/RNFBApp/RNFBSharedUtils.h +2 -5
  125. package/ios/RNFBApp/RNFBSharedUtils.m +109 -198
  126. package/ios/RNFBApp/RNFBSharedUtilsConfig.swift +72 -0
  127. package/ios/RNFBApp/RNFBSharedUtilsFIRApp.swift +271 -0
  128. package/ios/RNFBApp/RNFBSharedUtilsFormatting.swift +59 -0
  129. package/ios/RNFBApp/RNFBSharedUtilsPromiseRejection.swift +88 -0
  130. package/ios/RNFBApp/RNFBUtilsHelpers.swift +116 -0
  131. package/ios/RNFBApp/RNFBUtilsModule+Foundation.m +44 -0
  132. package/ios/RNFBApp/RNFBUtilsModule+PhotoAssets.m +47 -0
  133. package/ios/RNFBApp/RNFBUtilsModule.h +11 -1
  134. package/ios/RNFBApp/RNFBUtilsModule.mm +10 -85
  135. package/ios/RNFBApp/RNFBUtilsModuleImplementation.h +32 -0
  136. package/ios/RNFBApp/RNFBUtilsModuleImplementation.m +56 -0
  137. package/ios/RNFBApp/RNFBVersion.m +1 -1
  138. package/ios/RNFBApp.xcodeproj/project.pbxproj +100 -0
  139. package/ios/RNFBAppUnitTests/HostStubs/FirebaseCore/FIRApp.m +171 -0
  140. package/ios/RNFBAppUnitTests/HostStubs/FirebaseCore/FirebaseCore.h +78 -0
  141. package/ios/RNFBAppUnitTests/HostStubs/FirebaseInstallations/FIRInstallations.m +7 -0
  142. package/ios/RNFBAppUnitTests/HostStubs/FirebaseInstallations/FirebaseInstallations.h +8 -0
  143. package/ios/RNFBAppUnitTests/HostStubs/RNFBAppModuleHostStub.m +55 -0
  144. package/ios/RNFBAppUnitTests/HostStubs/RNFBAppTurboModules.h +89 -0
  145. package/ios/RNFBAppUnitTests/HostStubs/RNFBAppTurboModules.mm +30 -0
  146. package/ios/RNFBAppUnitTests/HostStubs/React/RCTBridge.h +19 -0
  147. package/ios/RNFBAppUnitTests/HostStubs/React/RCTBridge.m +32 -0
  148. package/ios/RNFBAppUnitTests/HostStubs/React/RCTBridgeModule.h +19 -0
  149. package/ios/RNFBAppUnitTests/HostStubs/React/RCTConvert.h +28 -0
  150. package/ios/RNFBAppUnitTests/HostStubs/React/RCTConvert.m +23 -0
  151. package/ios/RNFBAppUnitTests/HostStubs/React/RCTEventEmitter.h +9 -0
  152. package/ios/RNFBAppUnitTests/HostStubs/React/RCTInvalidating.h +24 -0
  153. package/ios/RNFBAppUnitTests/HostStubs/React/RCTUtils.h +9 -0
  154. package/ios/RNFBAppUnitTests/HostStubs/module.modulemap +13 -0
  155. package/ios/RNFBAppUnitTests/RCTConvertFIRAppFacadeTests.m +61 -0
  156. package/ios/RNFBAppUnitTests/RCTConvertFIRAppTests.swift +73 -0
  157. package/ios/RNFBAppUnitTests/RCTConvertFIROptionsFacadeTests.m +57 -0
  158. package/ios/RNFBAppUnitTests/RCTConvertFIROptionsTests.swift +243 -0
  159. package/ios/RNFBAppUnitTests/RNFBAppCustomAuthDomainsFacadeTests.m +73 -0
  160. package/ios/RNFBAppUnitTests/RNFBAppCustomAuthDomainsTests.swift +70 -0
  161. package/ios/RNFBAppUnitTests/RNFBAppInitializeOptionsMapperTests.swift +190 -0
  162. package/ios/RNFBAppUnitTests/RNFBAppLogLevelFacadeTests.m +76 -0
  163. package/ios/RNFBAppUnitTests/RNFBAppLogLevelMapperTests.swift +59 -0
  164. package/ios/RNFBAppUnitTests/RNFBAppModuleFirebaseFacadeTests.m +215 -0
  165. package/ios/RNFBAppUnitTests/RNFBAppModuleFirebaseTests.swift +430 -0
  166. package/ios/RNFBAppUnitTests/RNFBAppModuleLifecycleTests.m +206 -0
  167. package/ios/RNFBAppUnitTests/RNFBAppModuleShellTests.mm +367 -0
  168. package/ios/RNFBAppUnitTests/RNFBAppUnitTests.xcodeproj/project.pbxproj +355 -2
  169. package/ios/RNFBAppUnitTests/RNFBFirebaseAppClientTests.swift +165 -0
  170. package/ios/RNFBAppUnitTests/RNFBHandleMapStorageTests.swift +121 -0
  171. package/ios/RNFBAppUnitTests/RNFBInitializeAppArgumentsTests.swift +256 -0
  172. package/ios/RNFBAppUnitTests/RNFBJSONImplementationTests.swift +126 -0
  173. package/ios/RNFBAppUnitTests/RNFBJSONTests.m +172 -0
  174. package/ios/RNFBAppUnitTests/RNFBMetaStorageTests.swift +106 -0
  175. package/ios/RNFBAppUnitTests/RNFBMetaTests.m +65 -0
  176. package/ios/RNFBAppUnitTests/RNFBNullSentinelDecodingTests.swift +286 -0
  177. package/ios/RNFBAppUnitTests/RNFBNullSentinelInterceptorTests.m +312 -0
  178. package/ios/RNFBAppUnitTests/RNFBPreferencesStorageTests.swift +105 -0
  179. package/ios/RNFBAppUnitTests/RNFBPreferencesTests.m +110 -0
  180. package/ios/RNFBAppUnitTests/RNFBRCTEventEmitterCoreTests.swift +163 -0
  181. package/ios/RNFBAppUnitTests/RNFBRCTEventEmitterFacadeTests.m +141 -0
  182. package/ios/RNFBAppUnitTests/RNFBSharedUtilsConfigFacadeTests.m +100 -0
  183. package/ios/RNFBAppUnitTests/RNFBSharedUtilsConfigTests.swift +234 -0
  184. package/ios/RNFBAppUnitTests/RNFBSharedUtilsFIRAppFacadeTests.m +145 -0
  185. package/ios/RNFBAppUnitTests/RNFBSharedUtilsFIRAppTests.swift +173 -0
  186. package/ios/RNFBAppUnitTests/RNFBSharedUtilsFormattingFacadeTests.m +38 -0
  187. package/ios/RNFBAppUnitTests/RNFBSharedUtilsFormattingTests.swift +82 -0
  188. package/ios/RNFBAppUnitTests/RNFBSharedUtilsNullSentinelTests.m +35 -0
  189. package/ios/RNFBAppUnitTests/RNFBSharedUtilsPromiseRejectionFacadeTests.m +107 -0
  190. package/ios/RNFBAppUnitTests/RNFBSharedUtilsPromiseRejectionTests.swift +133 -0
  191. package/ios/RNFBAppUnitTests/RNFBUtilsHelpersTests.swift +144 -0
  192. package/ios/RNFBAppUnitTests/RNFBUtilsModuleFacadeTests.m +72 -0
  193. package/ios/RNFBAppUnitTests/RNFBUtilsModuleShellTests.mm +282 -0
  194. package/ios/RNFBFirebase/Package.swift +53 -0
  195. package/ios/RNFBFirebase/Sources/RNFBFirebase/RNFBFirebase.swift +285 -0
  196. package/ios/RNFBFirebase/Sources/RNFBFirebaseBridge/Public/.gitkeep +0 -0
  197. package/ios/RNFBFirebase/Sources/RNFBFirebaseBridge/RNFBFirebaseBridge.m +169 -0
  198. package/ios/RNFBFirebase/Sources/RNFBFirebaseBridge/include/RNFBFirebaseBridge.h +52 -0
  199. package/ios/RNFBFirebaseUnitTests/RNFBAppDynamicFacadeTests.swift +240 -0
  200. package/{android/src/main/java/io/invertase/firebase/common/RNFBHandleCollisionException.java → ios/RNFBFirebaseUnitTests/RNFBFirebaseClientImport.swift} +23 -14
  201. package/ios/RNFBFirebaseUnitTests/RNFBFirebaseUnitTests.xcodeproj/project.pbxproj +588 -0
  202. package/ios/RNFBFirebaseUnitTests/RNFBFirebaseUnitTests.xcodeproj/xcshareddata/xcschemes/RNFBFirebaseUnitTests.xcscheme +83 -0
  203. package/ios_config.sh +50 -22
  204. package/lib/FirebaseApp.ts +10 -0
  205. package/lib/common/deeps.ts +3 -0
  206. package/lib/internal/FirebaseModule.ts +6 -3
  207. package/lib/internal/NativeModules.ts +4 -1
  208. package/lib/internal/RNFBNativeEventEmitter.ts +14 -5
  209. package/lib/internal/SharedEventEmitter.ts +5 -1
  210. package/lib/internal/index.ts +1 -0
  211. package/lib/internal/react-native-vendor-emitter.d.ts +11 -0
  212. package/lib/internal/registry/app.ts +7 -1
  213. package/lib/types/app.ts +10 -3
  214. package/lib/types/internal.ts +19 -0
  215. package/lib/version.ts +1 -1
  216. package/package.json +8 -8
  217. package/plugin/build/ios/appDelegate.js +2 -2
  218. package/plugin/build/ios/podfile.js +16 -16
  219. package/plugin/build/pluginConfig.d.ts +4 -2
  220. package/plugin/src/ios/appDelegate.ts +2 -2
  221. package/plugin/src/ios/podfile.ts +20 -23
  222. package/plugin/src/pluginConfig.ts +4 -2
  223. package/android/src/main/java/io/invertase/firebase/common/RNFBHandleMap.java +0 -150
  224. package/android/src/main/java/io/invertase/firebase/common/TaskExecutorService.java +0 -148
  225. package/android/src/main/java/io/invertase/firebase/common/UniversalFirebaseModule.java +0 -62
  226. package/android/src/main/java/io/invertase/firebase/common/UniversalFirebasePreferences.java +0 -91
  227. package/android/src/reactnative/java/io/invertase/firebase/app/NativeRNFBTurboApp.java +0 -224
  228. package/android/src/reactnative/java/io/invertase/firebase/app/ReactNativeFirebaseApp.java +0 -46
  229. package/android/src/reactnative/java/io/invertase/firebase/app/ReactNativeFirebaseAppPackage.java +0 -49
  230. package/android/src/reactnative/java/io/invertase/firebase/app/ReactNativeFirebaseAppRegistrar.java +0 -35
  231. package/android/src/reactnative/java/io/invertase/firebase/common/RCTConvertFirebase.java +0 -192
  232. package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseEvent.java +0 -53
  233. package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseEventEmitter.java +0 -606
  234. package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseJSON.java +0 -109
  235. package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseMeta.java +0 -101
  236. package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseModule.java +0 -146
  237. package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebasePreferences.java +0 -96
  238. package/android/src/reactnative/java/io/invertase/firebase/common/SharedUtils.java +0 -441
  239. package/android/src/reactnative/java/io/invertase/firebase/utils/NativeRNFBTurboUtils.java +0 -223
  240. package/android/src/test/java/io/invertase/firebase/common/RNFBHandleMapTest.java +0 -275
  241. package/android/src/test/java/io/invertase/firebase/common/ReactNativeFirebaseJSONTest.java +0 -108
  242. package/android/src/test/java/io/invertase/firebase/common/TaskExecutorServiceTest.java +0 -97
@@ -0,0 +1,144 @@
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 RNFBUtilsHelpersTests: XCTestCase {
21
+ func testPathForDirectoryReturnsSearchPathFirstObject() {
22
+ let caches = RNFBUtilsHelpers.path(
23
+ forDirectory: Int32(FileManager.SearchPathDirectory.cachesDirectory.rawValue)
24
+ )
25
+ let expected = NSSearchPathForDirectoriesInDomains(.cachesDirectory, .userDomainMask, true)
26
+ .first
27
+ XCTAssertEqual(caches, expected)
28
+ XCTAssertNotNil(caches)
29
+ }
30
+
31
+ func testUtilsConstantsDictionaryIncludesRequiredKeys() {
32
+ let constants = RNFBUtilsHelpers.utilsConstantsDictionary(
33
+ bundlePath: "/App.app",
34
+ appVersion: "1.2.3",
35
+ pathProvider: { directory in "path-\(directory)" },
36
+ temporaryDirectory: "/tmp/rnfb"
37
+ )
38
+
39
+ XCTAssertEqual(constants["isRunningInTestLab"] as? Bool, false)
40
+ XCTAssertEqual(constants["MAIN_BUNDLE"] as? String, "/App.app")
41
+ XCTAssertEqual(
42
+ constants["CACHES_DIRECTORY"] as? String,
43
+ "path-\(FileManager.SearchPathDirectory.cachesDirectory.rawValue)"
44
+ )
45
+ XCTAssertEqual(
46
+ constants["DOCUMENT_DIRECTORY"] as? String,
47
+ "path-\(FileManager.SearchPathDirectory.documentDirectory.rawValue)"
48
+ )
49
+ XCTAssertEqual(
50
+ constants["PICTURES_DIRECTORY"] as? String,
51
+ "path-\(FileManager.SearchPathDirectory.picturesDirectory.rawValue)"
52
+ )
53
+ XCTAssertEqual(
54
+ constants["MOVIES_DIRECTORY"] as? String,
55
+ "path-\(FileManager.SearchPathDirectory.moviesDirectory.rawValue)"
56
+ )
57
+ XCTAssertEqual(constants["TEMP_DIRECTORY"] as? String, "/tmp/rnfb")
58
+ XCTAssertEqual(
59
+ constants["LIBRARY_DIRECTORY"] as? String,
60
+ "path-\(FileManager.SearchPathDirectory.libraryDirectory.rawValue)"
61
+ )
62
+ XCTAssertEqual(constants["appVersion"] as? String, "1.2.3")
63
+ }
64
+
65
+ func testUtilsConstantsDictionaryOmitsAppVersionWhenMissingEmptyOrNonString() {
66
+ let pathProvider: RNFBUtilsPathProvider = { _ in "/p" }
67
+
68
+ let missing = RNFBUtilsHelpers.utilsConstantsDictionary(
69
+ bundlePath: "/b",
70
+ appVersion: nil,
71
+ pathProvider: pathProvider,
72
+ temporaryDirectory: "/t"
73
+ )
74
+ XCTAssertNil(missing["appVersion"])
75
+
76
+ let empty = RNFBUtilsHelpers.utilsConstantsDictionary(
77
+ bundlePath: "/b",
78
+ appVersion: "",
79
+ pathProvider: pathProvider,
80
+ temporaryDirectory: "/t"
81
+ )
82
+ XCTAssertNil(empty["appVersion"])
83
+
84
+ let nonString = RNFBUtilsHelpers.utilsConstantsDictionary(
85
+ bundlePath: "/b",
86
+ appVersion: NSNumber(value: 42),
87
+ pathProvider: pathProvider,
88
+ temporaryDirectory: "/t"
89
+ )
90
+ XCTAssertNil(nonString["appVersion"])
91
+ }
92
+
93
+ func testUtilsConstantsDictionaryDefaultUsesMainBundle() {
94
+ let constants = RNFBUtilsHelpers.utilsConstantsDictionary()
95
+ XCTAssertEqual(constants["MAIN_BUNDLE"] as? String, Bundle.main.bundlePath)
96
+ XCTAssertEqual(constants["isRunningInTestLab"] as? Bool, false)
97
+ XCTAssertNotNil(constants["CACHES_DIRECTORY"])
98
+ XCTAssertNotNil(constants["TEMP_DIRECTORY"])
99
+ }
100
+
101
+ func testIsRemoteAssetPrefixChecks() {
102
+ XCTAssertTrue(RNFBUtilsHelpers.isRemoteAsset("assets-library://asset/foo"))
103
+ XCTAssertTrue(RNFBUtilsHelpers.isRemoteAsset("ph://LOCAL-ID"))
104
+ XCTAssertFalse(RNFBUtilsHelpers.isRemoteAsset("file:///tmp/x.jpg"))
105
+ XCTAssertFalse(RNFBUtilsHelpers.isRemoteAsset(""))
106
+ XCTAssertFalse(RNFBUtilsHelpers.isRemoteAsset(nil))
107
+ }
108
+
109
+ func testUnusedIsHeicCaseInsensitiveAndNilMessaging() {
110
+ XCTAssertTrue(RNFBUtilsHelpers.unusedIsHeic("photo.heic"))
111
+ XCTAssertTrue(RNFBUtilsHelpers.unusedIsHeic("photo.HEIC"))
112
+ XCTAssertTrue(RNFBUtilsHelpers.unusedIsHeic("photo.Heic"))
113
+ XCTAssertFalse(RNFBUtilsHelpers.unusedIsHeic("photo.jpg"))
114
+ XCTAssertFalse(RNFBUtilsHelpers.unusedIsHeic("heic"))
115
+ // Pre-port ObjC nil messaging → YES
116
+ XCTAssertTrue(RNFBUtilsHelpers.unusedIsHeic(nil))
117
+ }
118
+
119
+ func testValueForKeyFromQueryItemsUsesNamePredicateAndFirstObject() {
120
+ let items = [
121
+ URLQueryItem(name: "other", value: "a"),
122
+ URLQueryItem(name: "id", value: "first-id"),
123
+ URLQueryItem(name: "id", value: "second-id"),
124
+ ]
125
+
126
+ XCTAssertEqual(
127
+ RNFBUtilsHelpers.value(forKey: "id", fromQueryItems: items),
128
+ "first-id"
129
+ )
130
+ XCTAssertEqual(
131
+ RNFBUtilsHelpers.value(forKey: "other", fromQueryItems: items),
132
+ "a"
133
+ )
134
+ XCTAssertNil(RNFBUtilsHelpers.value(forKey: "missing", fromQueryItems: items))
135
+ XCTAssertNil(RNFBUtilsHelpers.value(forKey: "id", fromQueryItems: nil))
136
+ XCTAssertNil(RNFBUtilsHelpers.value(forKey: "id", fromQueryItems: []))
137
+ XCTAssertNil(
138
+ RNFBUtilsHelpers.value(
139
+ forKey: "id",
140
+ fromQueryItems: [URLQueryItem(name: "id", value: nil)]
141
+ )
142
+ )
143
+ }
144
+ }
@@ -0,0 +1,72 @@
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 "RNFBHandleMapStorage-Swift.inc"
20
+ #import "RNFBUtilsModule.h"
21
+
22
+ @interface RNFBUtilsModuleFacadeTests : XCTestCase
23
+ @end
24
+
25
+ @implementation RNFBUtilsModuleFacadeTests
26
+
27
+ - (void)testFacadePathForDirectoryMatchesSearchPath {
28
+ NSString *path = [RNFBUtilsHelpers pathForDirectory:(int)NSCachesDirectory];
29
+ NSString *expected =
30
+ [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject];
31
+ XCTAssertEqualObjects(path, expected);
32
+ }
33
+
34
+ - (void)testFacadeUtilsConstantsDictionaryKeys {
35
+ NSDictionary *constants = [RNFBUtilsHelpers
36
+ utilsConstantsDictionaryWithBundlePath:@"/Bundle.app"
37
+ appVersion:@"9.9.9"
38
+ pathProvider:^NSString *(int directory) {
39
+ return [NSString stringWithFormat:@"dir-%d", directory];
40
+ }
41
+ temporaryDirectory:@"/tmp/facade"];
42
+
43
+ XCTAssertEqualObjects(constants[@"isRunningInTestLab"], @NO);
44
+ XCTAssertEqualObjects(constants[@"MAIN_BUNDLE"], @"/Bundle.app");
45
+ XCTAssertEqualObjects(constants[@"TEMP_DIRECTORY"], @"/tmp/facade");
46
+ XCTAssertEqualObjects(constants[@"appVersion"], @"9.9.9");
47
+ XCTAssertEqualObjects(constants[@"CACHES_DIRECTORY"],
48
+ ([NSString stringWithFormat:@"dir-%d", (int)NSCachesDirectory]));
49
+ }
50
+
51
+ - (void)testFacadeIsRemoteAsset {
52
+ XCTAssertTrue([RNFBUtilsModule isRemoteAsset:@"assets-library://x"]);
53
+ XCTAssertTrue([RNFBUtilsModule isRemoteAsset:@"ph://y"]);
54
+ XCTAssertFalse([RNFBUtilsModule isRemoteAsset:@"/local/file.jpg"]);
55
+ }
56
+
57
+ - (void)testFacadeUnusedIsHeic {
58
+ XCTAssertTrue([RNFBUtilsModule unused_isHeic:@"a.HEIC"]);
59
+ XCTAssertFalse([RNFBUtilsModule unused_isHeic:@"a.png"]);
60
+ }
61
+
62
+ - (void)testFacadeValueForKeyFromQueryItems {
63
+ NSArray *items = @[
64
+ [NSURLQueryItem queryItemWithName:@"id" value:@"asset-1"],
65
+ [NSURLQueryItem queryItemWithName:@"w" value:@"100"],
66
+ ];
67
+ XCTAssertEqualObjects([RNFBUtilsModule valueForKey:@"id" fromQueryItems:items], @"asset-1");
68
+ XCTAssertEqualObjects([RNFBUtilsModule valueForKey:@"w" fromQueryItems:items], @"100");
69
+ XCTAssertNil([RNFBUtilsModule valueForKey:@"missing" fromQueryItems:items]);
70
+ }
71
+
72
+ @end
@@ -0,0 +1,282 @@
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 <Photos/Photos.h>
18
+ #import <XCTest/XCTest.h>
19
+ #import <objc/runtime.h>
20
+
21
+ #import "RNFBAppTurboModules.h"
22
+ #import "RNFBUtilsModule.h"
23
+ #import "RNFBUtilsModuleImplementation.h"
24
+
25
+ /**
26
+ * Exercises the shipped `RNFBUtilsModule.mm` shell, the Android-only stubs in
27
+ * `RNFBUtilsModuleImplementation.m` and the PhotoKit category in
28
+ * `RNFBUtilsModule+PhotoAssets.m`. All three are compiled into this target.
29
+ */
30
+ @interface RNFBUtilsModule (ShellTesting)
31
+ - (facebook::react::ModuleConstants<JS::NativeRNFBTurboUtils::Constants>)constantsToExport;
32
+ - (facebook::react::ModuleConstants<JS::NativeRNFBTurboUtils::Constants>)getConstants;
33
+ - (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
34
+ (const facebook::react::ObjCTurboModule::InitParams &)params;
35
+ + (BOOL)requiresMainQueueSetup;
36
+ + (NSString *)moduleName;
37
+ - (void)androidGetPlayServicesStatus:(RCTPromiseResolveBlock)resolve
38
+ reject:(RCTPromiseRejectBlock)reject;
39
+ - (void)androidPromptForPlayServices:(RCTPromiseResolveBlock)resolve
40
+ reject:(RCTPromiseRejectBlock)reject;
41
+ - (void)androidResolutionForPlayServices:(RCTPromiseResolveBlock)resolve
42
+ reject:(RCTPromiseRejectBlock)reject;
43
+ - (void)androidMakePlayServicesAvailable:(RCTPromiseResolveBlock)resolve
44
+ reject:(RCTPromiseRejectBlock)reject;
45
+ @end
46
+
47
+ /** `PHFetchResult` stand-in whose `firstObject` is controlled by the test. */
48
+ @interface RNFBFakeFetchResult : PHFetchResult
49
+ @property(nonatomic, strong, nullable) PHAsset *stubbedFirstObject;
50
+ @end
51
+
52
+ @implementation RNFBFakeFetchResult
53
+ - (id)firstObject {
54
+ return self.stubbedFirstObject;
55
+ }
56
+ @end
57
+
58
+ static SEL PHAssetFetchSelector(void) {
59
+ return @selector(fetchAssetsWithLocalIdentifiers:options:);
60
+ }
61
+
62
+ @interface RNFBUtilsModuleShellTests : XCTestCase
63
+ @property(nonatomic, strong) PHAsset *fakeAsset;
64
+ @property(nonatomic, strong) NSMutableArray<NSArray<NSString *> *> *fetchedIdentifiers;
65
+ @property(nonatomic, strong) NSMutableArray<NSNumber *> *fetchedOptionsWereNil;
66
+ @property(nonatomic, assign) IMP originalFetchImplementation;
67
+ @end
68
+
69
+ @implementation RNFBUtilsModuleShellTests
70
+
71
+ #pragma mark - Module shell
72
+
73
+ - (void)testExportedModuleNameAndMainQueueSetup {
74
+ XCTAssertEqualObjects([RNFBUtilsModule moduleName], @"NativeRNFBTurboUtils");
75
+ XCTAssertFalse([RNFBUtilsModule requiresMainQueueSetup]);
76
+ }
77
+
78
+ - (void)testGetTurboModuleCreatesTheUtilsSpecModule {
79
+ RNFBUtilsModule *module = [[RNFBUtilsModule alloc] init];
80
+ facebook::react::ObjCTurboModule::InitParams params;
81
+
82
+ auto turboModule = [module getTurboModule:params];
83
+
84
+ XCTAssertTrue(turboModule != nullptr);
85
+ XCTAssertTrue(std::dynamic_pointer_cast<facebook::react::NativeRNFBTurboUtilsSpecJSI>(
86
+ turboModule) != nullptr);
87
+ }
88
+
89
+ - (void)testConstantsToExportAndGetConstantsReturnUtilsConstants {
90
+ RNFBUtilsModule *module = [[RNFBUtilsModule alloc] init];
91
+
92
+ auto exported = [module constantsToExport];
93
+ auto fetched = [module getConstants];
94
+
95
+ for (NSDictionary *constants in @[ exported.dictionary, fetched.dictionary ]) {
96
+ XCTAssertEqualObjects(constants[@"isRunningInTestLab"], @NO);
97
+ XCTAssertNotNil(constants[@"MAIN_BUNDLE"]);
98
+ XCTAssertNotNil(constants[@"TEMP_DIRECTORY"]);
99
+ XCTAssertNotNil(constants[@"CACHES_DIRECTORY"]);
100
+ }
101
+ XCTAssertEqualObjects(RNFBUtilsModuleConstantsDictionary()[@"isRunningInTestLab"], @NO);
102
+ }
103
+
104
+ #pragma mark - Android-only stubs
105
+
106
+ - (void)testAndroidPlayServicesStatusReportsAvailableOnIOS {
107
+ RNFBUtilsModule *module = [[RNFBUtilsModule alloc] init];
108
+ __block NSDictionary *viaModule = nil;
109
+ __block NSDictionary *viaFunction = nil;
110
+
111
+ [module
112
+ androidGetPlayServicesStatus:^(id result) {
113
+ viaModule = result;
114
+ }
115
+ reject:^(NSString *code, NSString *message, NSError *error) {
116
+ XCTFail(@"unexpected reject %@", message);
117
+ }];
118
+ RNFBUtilsModuleAndroidGetPlayServicesStatus(
119
+ ^(id result) {
120
+ viaFunction = result;
121
+ },
122
+ ^(NSString *code, NSString *message, NSError *error) {
123
+ XCTFail(@"unexpected reject %@", message);
124
+ });
125
+
126
+ NSDictionary *expected = @{
127
+ @"isAvailable" : @YES,
128
+ @"status" : @0,
129
+ @"hasResolution" : @NO,
130
+ @"isUserResolvableError" : @NO,
131
+ };
132
+ XCTAssertEqualObjects(viaModule, expected);
133
+ XCTAssertEqualObjects(viaFunction, expected);
134
+ }
135
+
136
+ - (void)testAndroidPromptResolutionAndMakeAvailableResolveNil {
137
+ RNFBUtilsModule *module = [[RNFBUtilsModule alloc] init];
138
+ RCTPromiseRejectBlock failOnReject = ^(NSString *code, NSString *message, NSError *error) {
139
+ XCTFail(@"unexpected reject %@", message);
140
+ };
141
+ __block NSUInteger resolveCount = 0;
142
+ __block BOOL sawNonNil = NO;
143
+ RCTPromiseResolveBlock countNil = ^(id result) {
144
+ resolveCount += 1;
145
+ sawNonNil = sawNonNil || result != nil;
146
+ };
147
+
148
+ [module androidPromptForPlayServices:countNil reject:failOnReject];
149
+ [module androidResolutionForPlayServices:countNil reject:failOnReject];
150
+ [module androidMakePlayServicesAvailable:countNil reject:failOnReject];
151
+ RNFBUtilsModuleAndroidPromptForPlayServices(countNil, failOnReject);
152
+ RNFBUtilsModuleAndroidResolutionForPlayServices(countNil, failOnReject);
153
+ RNFBUtilsModuleAndroidMakePlayServicesAvailable(countNil, failOnReject);
154
+
155
+ XCTAssertEqual(resolveCount, 6);
156
+ XCTAssertFalse(sawNonNil);
157
+ }
158
+
159
+ #pragma mark - PhotoKit category
160
+
161
+ - (void)testAssetsLibraryPathsAreUnsupportedAndNeverQueryPhotos {
162
+ [self stubPhotoLibraryReturning:[self fetchResultContaining:self.fakeAsset]];
163
+
164
+ // The one-time warning is suppressed on later calls; the result stays nil and PhotoKit is never
165
+ // consulted for the removed `assets-library://` scheme, even when an id is present.
166
+ XCTAssertNil([RNFBUtilsModule fetchAssetForPath:@"assets-library://asset/asset.JPG?id=1"]);
167
+ XCTAssertNil([RNFBUtilsModule fetchAssetForPath:@"assets-library://asset/asset.JPG?id=2"]);
168
+
169
+ XCTAssertEqual(self.fetchedIdentifiers.count, 0);
170
+ }
171
+
172
+ - (void)testPhotoLibraryPathPassesEverythingAfterTheSchemeToPhotoKit {
173
+ [self stubPhotoLibraryReturning:[self fetchResultContaining:self.fakeAsset]];
174
+
175
+ PHAsset *asset = [RNFBUtilsModule fetchAssetForPath:@"ph://ABC-123/L0/001"];
176
+
177
+ XCTAssertEqual(asset, self.fakeAsset);
178
+ XCTAssertEqualObjects(self.fetchedIdentifiers, @[ @[ @"ABC-123/L0/001" ] ]);
179
+ XCTAssertEqual(self.fetchedOptionsWereNil.count, 1);
180
+ XCTAssertEqualObjects(self.fetchedOptionsWereNil.firstObject, @YES);
181
+ }
182
+
183
+ - (void)testPhotoLibraryPathWithNoMatchingAssetReturnsNil {
184
+ [self stubPhotoLibraryReturning:[self fetchResultContaining:nil]];
185
+
186
+ XCTAssertNil([RNFBUtilsModule fetchAssetForPath:@"ph://missing-local-identifier"]);
187
+ XCTAssertEqualObjects(self.fetchedIdentifiers, @[ @[ @"missing-local-identifier" ] ]);
188
+ }
189
+
190
+ - (void)testPhotoLibraryPathWithNoIdentifierLooksUpTheEmptyIdentifier {
191
+ [self stubPhotoLibraryReturning:[self fetchResultContaining:nil]];
192
+
193
+ XCTAssertNil([RNFBUtilsModule fetchAssetForPath:@"ph://"]);
194
+ XCTAssertEqualObjects(self.fetchedIdentifiers, @[ @[ @"" ] ]);
195
+ }
196
+
197
+ - (void)testOtherPathsLookUpTheIdQueryItem {
198
+ [self stubPhotoLibraryReturning:[self fetchResultContaining:self.fakeAsset]];
199
+
200
+ PHAsset *asset =
201
+ [RNFBUtilsModule fetchAssetForPath:@"file:///asset.jpg?w=100&id=local-identifier&h=50"];
202
+
203
+ XCTAssertEqual(asset, self.fakeAsset);
204
+ XCTAssertEqualObjects(self.fetchedIdentifiers, @[ @[ @"local-identifier" ] ]);
205
+ XCTAssertEqualObjects(self.fetchedOptionsWereNil.firstObject, @YES);
206
+ }
207
+
208
+ - (void)testOtherPathsWithNoMatchingAssetReturnNil {
209
+ [self stubPhotoLibraryReturning:[self fetchResultContaining:nil]];
210
+
211
+ XCTAssertNil(
212
+ [RNFBUtilsModule fetchAssetForPath:@"file:///asset.jpg?id=missing-local-identifier"]);
213
+ XCTAssertEqualObjects(self.fetchedIdentifiers, @[ @[ @"missing-local-identifier" ] ]);
214
+ }
215
+
216
+ - (void)testOtherPathsWithoutAnIdQueryItemRaiseBeforeQueryingPhotos {
217
+ [self stubPhotoLibraryReturning:[self fetchResultContaining:self.fakeAsset]];
218
+
219
+ // Pre-port parity: a missing `id` yields a nil identifier and the `@[ assetId ]` literal
220
+ // raises. `RNFBStorageCommon` only reaches this method for `ph://` / `assets-library://`
221
+ // paths (`isRemoteAsset:`), so this is not reachable from the storage upload flow.
222
+ for (NSString *path in @[ @"file:///asset.jpg", @"file:///asset.jpg?other=1", @"" ]) {
223
+ XCTAssertThrowsSpecificNamed([RNFBUtilsModule fetchAssetForPath:path], NSException,
224
+ NSInvalidArgumentException, @"%@", path);
225
+ }
226
+ XCTAssertEqual(self.fetchedIdentifiers.count, 0);
227
+ }
228
+
229
+ - (void)testUnknownIdentifiersReturnNilWhenPhotoKitFindsNothing {
230
+ // Hostless macOS XCTest has no NSPhotoLibraryUsageDescription; never touch live PhotoKit.
231
+ // Stub an empty fetch for both lookup branches (`ph://` and `file://?id=`).
232
+ [self stubPhotoLibraryReturning:[self fetchResultContaining:nil]];
233
+
234
+ XCTAssertNil([RNFBUtilsModule fetchAssetForPath:@"ph://missing-local-identifier"]);
235
+ XCTAssertNil(
236
+ [RNFBUtilsModule fetchAssetForPath:@"file:///asset.jpg?id=missing-local-identifier"]);
237
+ XCTAssertEqualObjects(self.fetchedIdentifiers, (@[
238
+ @[ @"missing-local-identifier" ],
239
+ @[ @"missing-local-identifier" ],
240
+ ]));
241
+ }
242
+
243
+ #pragma mark - PhotoKit stubbing
244
+
245
+ - (void)setUp {
246
+ [super setUp];
247
+ self.fakeAsset = (PHAsset *)class_createInstance([PHAsset class], 0);
248
+ self.fetchedIdentifiers = [NSMutableArray array];
249
+ self.fetchedOptionsWereNil = [NSMutableArray array];
250
+ }
251
+
252
+ - (void)tearDown {
253
+ if (self.originalFetchImplementation != NULL) {
254
+ Method method = class_getClassMethod([PHAsset class], PHAssetFetchSelector());
255
+ method_setImplementation(method, self.originalFetchImplementation);
256
+ self.originalFetchImplementation = NULL;
257
+ }
258
+ [super tearDown];
259
+ }
260
+
261
+ - (id)fetchResultContaining:(PHAsset *)asset {
262
+ RNFBFakeFetchResult *result =
263
+ (RNFBFakeFetchResult *)class_createInstance([RNFBFakeFetchResult class], 0);
264
+ result.stubbedFirstObject = asset;
265
+ return result;
266
+ }
267
+
268
+ /** Replaces `+[PHAsset fetchAssetsWithLocalIdentifiers:options:]`, recording each call. */
269
+ - (void)stubPhotoLibraryReturning:(id)fetchResult {
270
+ Method method = class_getClassMethod([PHAsset class], PHAssetFetchSelector());
271
+ self.originalFetchImplementation = method_getImplementation(method);
272
+ __weak RNFBUtilsModuleShellTests *weakSelf = self;
273
+ IMP stub = imp_implementationWithBlock(
274
+ ^id(id _self, NSArray<NSString *> *identifiers, PHFetchOptions *options) {
275
+ [weakSelf.fetchedIdentifiers addObject:identifiers];
276
+ [weakSelf.fetchedOptionsWereNil addObject:@(options == nil)];
277
+ return fetchResult;
278
+ });
279
+ method_setImplementation(method, stub);
280
+ }
281
+
282
+ @end
@@ -0,0 +1,53 @@
1
+ // swift-tools-version: 5.9
2
+ //
3
+ // CI probe only (RNFB_TEST_RN_BARE_DYNAMIC_FIREBASE=1). Shipped podspecs keep
4
+ // spm_dependency on firebase-ios-sdk. Exact pin tracks packages/app/package.json
5
+ // sdkVersions.ios.firebase (checked by .github/workflows/scripts/check-ios-probe-sdk-pin.js).
6
+ //
7
+ // This package resolver rejects mixed Swift and Objective-C sources in one
8
+ // target. SDK calls live in RNFBFirebaseBridge. The dynamic product links that
9
+ // target beside the Swift target. The Swift target does not depend on it, so
10
+ // the emitted module does not record FirebaseCore for clients.
11
+
12
+ import PackageDescription
13
+
14
+ let package = Package(
15
+ name: "RNFBFirebase",
16
+ platforms: [
17
+ .iOS(.v15),
18
+ .macOS(.v11),
19
+ .tvOS(.v15),
20
+ ],
21
+ products: [
22
+ .library(
23
+ name: "RNFBFirebase",
24
+ type: .dynamic,
25
+ targets: ["RNFBFirebase", "RNFBFirebaseBridge"]
26
+ ),
27
+ ],
28
+ dependencies: [
29
+ .package(
30
+ url: "https://github.com/firebase/firebase-ios-sdk.git",
31
+ exact: "13.0.0"
32
+ ),
33
+ ],
34
+ targets: [
35
+ .target(
36
+ name: "RNFBFirebaseBridge",
37
+ dependencies: [
38
+ .product(name: "FirebaseCore", package: "firebase-ios-sdk"),
39
+ .product(name: "FirebaseInstallations", package: "firebase-ios-sdk"),
40
+ ],
41
+ // Public headers stay empty so this clang target does not publish a
42
+ // module. The dynamic product still links the object file. The Swift
43
+ // target does not depend on it, so clients do not inherit FirebaseCore.
44
+ publicHeadersPath: "Public",
45
+ cSettings: [
46
+ .headerSearchPath("include"),
47
+ ]
48
+ ),
49
+ .target(
50
+ name: "RNFBFirebase"
51
+ ),
52
+ ]
53
+ )