@react-native-firebase/app 26.4.0 → 27.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +62 -0
- package/README.md +10 -27
- package/RNFBApp.podspec +13 -5
- package/android/build.gradle +3 -0
- package/android/src/main/java/io/invertase/firebase/common/RNFBHandleCollisionException.kt +29 -0
- package/android/src/main/java/io/invertase/firebase/common/RNFBHandleMap.kt +146 -0
- package/android/src/main/java/io/invertase/firebase/common/TaskExecutorService.kt +156 -0
- package/android/src/main/java/io/invertase/firebase/common/UniversalFirebaseModule.kt +44 -0
- package/android/src/main/java/io/invertase/firebase/common/UniversalFirebasePreferences.kt +100 -0
- package/android/src/reactnative/java/io/invertase/firebase/app/NativeRNFBTurboApp.kt +250 -0
- package/android/src/reactnative/java/io/invertase/firebase/app/ReactNativeFirebaseApp.kt +64 -0
- package/android/src/reactnative/java/io/invertase/firebase/app/{ReactNativeFirebaseAppInitProvider.java → ReactNativeFirebaseAppInitProvider.kt} +3 -4
- package/android/src/reactnative/java/io/invertase/firebase/app/ReactNativeFirebaseAppPackage.kt +47 -0
- package/android/src/reactnative/java/io/invertase/firebase/app/ReactNativeFirebaseAppRegistrar.kt +33 -0
- package/android/src/reactnative/java/io/invertase/firebase/app/ReactNativeFirebaseVersion.java +1 -1
- package/android/src/reactnative/java/io/invertase/firebase/common/RCTConvertFirebase.kt +185 -0
- package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseEvent.kt +35 -0
- package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseEventEmitter.kt +662 -0
- package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseJSON.kt +103 -0
- package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseMeta.kt +96 -0
- package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseModule.kt +140 -0
- package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebasePreferences.kt +109 -0
- package/android/src/reactnative/java/io/invertase/firebase/common/SharedUtils.kt +451 -0
- package/android/src/reactnative/java/io/invertase/firebase/interfaces/{ContextProvider.java → ContextProvider.kt} +8 -8
- package/android/src/reactnative/java/io/invertase/firebase/interfaces/{NativeError.java → NativeError.kt} +8 -8
- package/android/src/reactnative/java/io/invertase/firebase/interfaces/{NativeEvent.java → NativeEvent.kt} +6 -6
- package/android/src/reactnative/java/io/invertase/firebase/utils/NativeRNFBTurboUtils.kt +219 -0
- package/android/src/test/java/expo/core/ModuleRegistry.java +9 -0
- package/android/src/test/java/io/invertase/firebase/app/NativeRNFBTurboAppTest.java +182 -59
- package/android/src/test/java/io/invertase/firebase/app/ReactNativeFirebaseAppComponentsJavaCompatibilityTest.java +70 -0
- package/android/src/test/java/io/invertase/firebase/app/ReactNativeFirebaseAppJavaCompatibilityTest.java +60 -0
- package/android/src/test/java/io/invertase/firebase/app/ReactNativeFirebaseAppPackageTest.java +165 -0
- package/android/src/test/java/io/invertase/firebase/app/ReactNativeFirebaseAppTest.kt +167 -0
- package/android/src/test/java/io/invertase/firebase/common/RCTConvertFirebaseJavaCompatibilityTest.java +112 -0
- package/android/src/test/java/io/invertase/firebase/common/RCTConvertFirebaseTest.kt +317 -0
- package/android/src/test/java/io/invertase/firebase/common/RNFBHandleMapTest.kt +309 -0
- package/android/src/test/java/io/invertase/firebase/common/ReactNativeFirebaseEventEmitterJavaCompatibilityTest.java +176 -0
- package/android/src/test/java/io/invertase/firebase/common/ReactNativeFirebaseEventEmitterTest.java +143 -12
- package/android/src/test/java/io/invertase/firebase/common/ReactNativeFirebaseEventTest.kt +61 -0
- package/android/src/test/java/io/invertase/firebase/common/ReactNativeFirebaseJSONJavaCompatibilityTest.java +85 -0
- package/android/src/test/java/io/invertase/firebase/common/ReactNativeFirebaseJSONTest.kt +296 -0
- package/android/src/test/java/io/invertase/firebase/common/ReactNativeFirebaseMetaJavaCompatibilityTest.java +67 -0
- package/android/src/test/java/io/invertase/firebase/common/ReactNativeFirebaseMetaTest.kt +246 -0
- package/android/src/test/java/io/invertase/firebase/common/ReactNativeFirebaseModuleTest.kt +254 -0
- package/android/src/test/java/io/invertase/firebase/common/ReactNativeFirebasePreferencesJavaCompatibilityTest.java +87 -0
- package/android/src/test/java/io/invertase/firebase/common/ReactNativeFirebasePreferencesTest.kt +260 -0
- package/android/src/test/java/io/invertase/firebase/common/SharedUtilsJavaCompatibilityTest.java +255 -0
- package/android/src/test/java/io/invertase/firebase/common/SharedUtilsTest.kt +674 -0
- package/android/src/test/java/io/invertase/firebase/common/TaskExecutorServiceTest.kt +290 -0
- package/android/src/test/java/io/invertase/firebase/common/UniversalFirebaseModuleJavaCompatibilityTest.java +178 -0
- package/android/src/test/java/io/invertase/firebase/common/UniversalFirebasePreferencesJavaCompatibilityTest.java +99 -0
- package/android/src/test/java/io/invertase/firebase/common/UniversalFirebasePreferencesTest.kt +217 -0
- package/android/src/test/java/io/invertase/firebase/commoncompat/ReactNativeFirebaseModuleJavaCompatibilityTest.java +176 -0
- package/android/src/test/java/io/invertase/firebase/commoncompat/ReactNativeFirebaseModuleKotlinCompatibilityTest.kt +52 -0
- package/android/src/test/java/io/invertase/firebase/interfaces/InterfacesJavaCompatibilityTest.java +144 -0
- package/android/src/test/java/io/invertase/firebase/interfaces/NativeEventTest.kt +56 -0
- package/android/src/test/java/io/invertase/firebase/utils/NativeRNFBTurboUtilsTest.java +517 -21
- package/dist/module/FirebaseApp.js +10 -0
- package/dist/module/FirebaseApp.js.map +1 -1
- package/dist/module/common/deeps.js +3 -0
- package/dist/module/common/deeps.js.map +1 -1
- package/dist/module/internal/FirebaseModule.js.map +1 -1
- package/dist/module/internal/RNFBNativeEventEmitter.js +12 -1
- package/dist/module/internal/RNFBNativeEventEmitter.js.map +1 -1
- package/dist/module/internal/SharedEventEmitter.js +3 -1
- package/dist/module/internal/SharedEventEmitter.js.map +1 -1
- package/dist/module/internal/index.js +1 -0
- package/dist/module/internal/index.js.map +1 -1
- package/dist/module/internal/registry/app.js +7 -1
- package/dist/module/internal/registry/app.js.map +1 -1
- package/dist/module/types/app.js.map +1 -1
- package/dist/module/types/internal.js +2 -0
- package/dist/module/version.js +1 -1
- package/dist/typescript/lib/FirebaseApp.d.ts +7 -0
- package/dist/typescript/lib/FirebaseApp.d.ts.map +1 -1
- package/dist/typescript/lib/common/deeps.d.ts.map +1 -1
- package/dist/typescript/lib/internal/FirebaseModule.d.ts +2 -3
- package/dist/typescript/lib/internal/FirebaseModule.d.ts.map +1 -1
- package/dist/typescript/lib/internal/NativeModules.d.ts +4 -1
- package/dist/typescript/lib/internal/NativeModules.d.ts.map +1 -1
- package/dist/typescript/lib/internal/RNFBNativeEventEmitter.d.ts +2 -2
- package/dist/typescript/lib/internal/RNFBNativeEventEmitter.d.ts.map +1 -1
- package/dist/typescript/lib/internal/SharedEventEmitter.d.ts +3 -3
- package/dist/typescript/lib/internal/SharedEventEmitter.d.ts.map +1 -1
- package/dist/typescript/lib/internal/index.d.ts +1 -0
- package/dist/typescript/lib/internal/index.d.ts.map +1 -1
- package/dist/typescript/lib/internal/registry/app.d.ts.map +1 -1
- package/dist/typescript/lib/types/app.d.ts +10 -3
- package/dist/typescript/lib/types/app.d.ts.map +1 -1
- package/dist/typescript/lib/types/internal.d.ts +12 -0
- package/dist/typescript/lib/types/internal.d.ts.map +1 -1
- package/dist/typescript/lib/version.d.ts +1 -1
- package/firebase-schema.json +4 -0
- package/firebase_spm.rb +552 -96
- package/ios/RNFBApp/RCTConvert+FIRApp.h +2 -5
- package/ios/RNFBApp/RCTConvert+FIRApp.m +11 -6
- package/ios/RNFBApp/RCTConvert+FIROptions.h +2 -5
- package/ios/RNFBApp/RCTConvert+FIROptions.m +11 -10
- package/ios/RNFBApp/RCTConvertFIRApp.swift +86 -0
- package/ios/RNFBApp/RCTConvertFIROptions.swift +259 -0
- package/ios/RNFBApp/RNFBAppCustomAuthDomains.swift +63 -0
- package/ios/RNFBApp/RNFBAppInitializeOptionsMapper.swift +113 -0
- package/ios/RNFBApp/RNFBAppLogLevelMapper.swift +53 -0
- package/ios/RNFBApp/RNFBAppModule+CustomAuthDomain.m +35 -0
- package/ios/RNFBApp/RNFBAppModule.h +6 -2
- package/ios/RNFBApp/RNFBAppModule.mm +65 -228
- package/ios/RNFBApp/RNFBAppModuleFirebase.swift +439 -0
- package/ios/RNFBApp/RNFBAppModuleImplementation.h +68 -0
- package/ios/RNFBApp/RNFBAppModuleImplementation.m +195 -0
- package/ios/RNFBApp/RNFBHandleMap.m +27 -56
- package/ios/RNFBApp/RNFBHandleMapStorage.swift +90 -0
- package/ios/RNFBApp/RNFBInitializeAppArguments.swift +82 -0
- package/ios/RNFBApp/RNFBJSON.m +22 -38
- package/ios/RNFBApp/RNFBJSONImplementation.swift +71 -0
- package/ios/RNFBApp/RNFBMeta.m +24 -26
- package/ios/RNFBApp/RNFBMetaStorage.swift +76 -0
- package/ios/RNFBApp/RNFBNullSentinelDecoding.swift +135 -0
- package/ios/RNFBApp/RNFBNullSentinelInterceptor.h +30 -3
- package/ios/RNFBApp/RNFBNullSentinelInterceptor.m +28 -5
- package/ios/RNFBApp/RNFBPreferences.m +22 -20
- package/ios/RNFBApp/RNFBPreferencesStorage.swift +101 -0
- package/ios/RNFBApp/RNFBRCTEventEmitter.m +36 -93
- package/ios/RNFBApp/RNFBRCTEventEmitterCore.swift +161 -0
- package/ios/RNFBApp/RNFBSharedUtils.h +2 -5
- package/ios/RNFBApp/RNFBSharedUtils.m +109 -198
- package/ios/RNFBApp/RNFBSharedUtilsConfig.swift +72 -0
- package/ios/RNFBApp/RNFBSharedUtilsFIRApp.swift +271 -0
- package/ios/RNFBApp/RNFBSharedUtilsFormatting.swift +59 -0
- package/ios/RNFBApp/RNFBSharedUtilsPromiseRejection.swift +88 -0
- package/ios/RNFBApp/RNFBUtilsHelpers.swift +116 -0
- package/ios/RNFBApp/RNFBUtilsModule+Foundation.m +44 -0
- package/ios/RNFBApp/RNFBUtilsModule+PhotoAssets.m +47 -0
- package/ios/RNFBApp/RNFBUtilsModule.h +11 -1
- package/ios/RNFBApp/RNFBUtilsModule.mm +10 -85
- package/ios/RNFBApp/RNFBUtilsModuleImplementation.h +32 -0
- package/ios/RNFBApp/RNFBUtilsModuleImplementation.m +56 -0
- package/ios/RNFBApp/RNFBVersion.m +1 -1
- package/ios/RNFBApp.xcodeproj/project.pbxproj +100 -0
- package/ios/RNFBAppUnitTests/HostStubs/FirebaseCore/FIRApp.m +171 -0
- package/ios/RNFBAppUnitTests/HostStubs/FirebaseCore/FirebaseCore.h +78 -0
- package/ios/RNFBAppUnitTests/HostStubs/FirebaseInstallations/FIRInstallations.m +7 -0
- package/ios/RNFBAppUnitTests/HostStubs/FirebaseInstallations/FirebaseInstallations.h +8 -0
- package/ios/RNFBAppUnitTests/HostStubs/RNFBAppModuleHostStub.m +55 -0
- package/ios/RNFBAppUnitTests/HostStubs/RNFBAppTurboModules.h +89 -0
- package/ios/RNFBAppUnitTests/HostStubs/RNFBAppTurboModules.mm +30 -0
- package/ios/RNFBAppUnitTests/HostStubs/React/RCTBridge.h +19 -0
- package/ios/RNFBAppUnitTests/HostStubs/React/RCTBridge.m +32 -0
- package/ios/RNFBAppUnitTests/HostStubs/React/RCTBridgeModule.h +19 -0
- package/ios/RNFBAppUnitTests/HostStubs/React/RCTConvert.h +28 -0
- package/ios/RNFBAppUnitTests/HostStubs/React/RCTConvert.m +23 -0
- package/ios/RNFBAppUnitTests/HostStubs/React/RCTEventEmitter.h +9 -0
- package/ios/RNFBAppUnitTests/HostStubs/React/RCTInvalidating.h +24 -0
- package/ios/RNFBAppUnitTests/HostStubs/React/RCTUtils.h +9 -0
- package/ios/RNFBAppUnitTests/HostStubs/module.modulemap +13 -0
- package/ios/RNFBAppUnitTests/RCTConvertFIRAppFacadeTests.m +61 -0
- package/ios/RNFBAppUnitTests/RCTConvertFIRAppTests.swift +73 -0
- package/ios/RNFBAppUnitTests/RCTConvertFIROptionsFacadeTests.m +57 -0
- package/ios/RNFBAppUnitTests/RCTConvertFIROptionsTests.swift +243 -0
- package/ios/RNFBAppUnitTests/RNFBAppCustomAuthDomainsFacadeTests.m +73 -0
- package/ios/RNFBAppUnitTests/RNFBAppCustomAuthDomainsTests.swift +70 -0
- package/ios/RNFBAppUnitTests/RNFBAppInitializeOptionsMapperTests.swift +190 -0
- package/ios/RNFBAppUnitTests/RNFBAppLogLevelFacadeTests.m +76 -0
- package/ios/RNFBAppUnitTests/RNFBAppLogLevelMapperTests.swift +59 -0
- package/ios/RNFBAppUnitTests/RNFBAppModuleFirebaseFacadeTests.m +215 -0
- package/ios/RNFBAppUnitTests/RNFBAppModuleFirebaseTests.swift +430 -0
- package/ios/RNFBAppUnitTests/RNFBAppModuleLifecycleTests.m +206 -0
- package/ios/RNFBAppUnitTests/RNFBAppModuleShellTests.mm +367 -0
- package/ios/RNFBAppUnitTests/RNFBAppUnitTests.xcodeproj/project.pbxproj +355 -2
- package/ios/RNFBAppUnitTests/RNFBFirebaseAppClientTests.swift +165 -0
- package/ios/RNFBAppUnitTests/RNFBHandleMapStorageTests.swift +121 -0
- package/ios/RNFBAppUnitTests/RNFBInitializeAppArgumentsTests.swift +256 -0
- package/ios/RNFBAppUnitTests/RNFBJSONImplementationTests.swift +126 -0
- package/ios/RNFBAppUnitTests/RNFBJSONTests.m +172 -0
- package/ios/RNFBAppUnitTests/RNFBMetaStorageTests.swift +106 -0
- package/ios/RNFBAppUnitTests/RNFBMetaTests.m +65 -0
- package/ios/RNFBAppUnitTests/RNFBNullSentinelDecodingTests.swift +286 -0
- package/ios/RNFBAppUnitTests/RNFBNullSentinelInterceptorTests.m +312 -0
- package/ios/RNFBAppUnitTests/RNFBPreferencesStorageTests.swift +105 -0
- package/ios/RNFBAppUnitTests/RNFBPreferencesTests.m +110 -0
- package/ios/RNFBAppUnitTests/RNFBRCTEventEmitterCoreTests.swift +163 -0
- package/ios/RNFBAppUnitTests/RNFBRCTEventEmitterFacadeTests.m +141 -0
- package/ios/RNFBAppUnitTests/RNFBSharedUtilsConfigFacadeTests.m +100 -0
- package/ios/RNFBAppUnitTests/RNFBSharedUtilsConfigTests.swift +234 -0
- package/ios/RNFBAppUnitTests/RNFBSharedUtilsFIRAppFacadeTests.m +145 -0
- package/ios/RNFBAppUnitTests/RNFBSharedUtilsFIRAppTests.swift +173 -0
- package/ios/RNFBAppUnitTests/RNFBSharedUtilsFormattingFacadeTests.m +38 -0
- package/ios/RNFBAppUnitTests/RNFBSharedUtilsFormattingTests.swift +82 -0
- package/ios/RNFBAppUnitTests/RNFBSharedUtilsNullSentinelTests.m +35 -0
- package/ios/RNFBAppUnitTests/RNFBSharedUtilsPromiseRejectionFacadeTests.m +107 -0
- package/ios/RNFBAppUnitTests/RNFBSharedUtilsPromiseRejectionTests.swift +133 -0
- package/ios/RNFBAppUnitTests/RNFBUtilsHelpersTests.swift +144 -0
- package/ios/RNFBAppUnitTests/RNFBUtilsModuleFacadeTests.m +72 -0
- package/ios/RNFBAppUnitTests/RNFBUtilsModuleShellTests.mm +282 -0
- package/ios/RNFBFirebase/Package.swift +53 -0
- package/ios/RNFBFirebase/Sources/RNFBFirebase/RNFBFirebase.swift +285 -0
- package/ios/RNFBFirebase/Sources/RNFBFirebaseBridge/Public/.gitkeep +0 -0
- package/ios/RNFBFirebase/Sources/RNFBFirebaseBridge/RNFBFirebaseBridge.m +169 -0
- package/ios/RNFBFirebase/Sources/RNFBFirebaseBridge/include/RNFBFirebaseBridge.h +52 -0
- package/ios/RNFBFirebaseUnitTests/RNFBAppDynamicFacadeTests.swift +240 -0
- package/{android/src/main/java/io/invertase/firebase/common/RNFBHandleCollisionException.java → ios/RNFBFirebaseUnitTests/RNFBFirebaseClientImport.swift} +23 -14
- package/ios/RNFBFirebaseUnitTests/RNFBFirebaseUnitTests.xcodeproj/project.pbxproj +588 -0
- package/ios/RNFBFirebaseUnitTests/RNFBFirebaseUnitTests.xcodeproj/xcshareddata/xcschemes/RNFBFirebaseUnitTests.xcscheme +83 -0
- package/ios_config.sh +50 -22
- package/lib/FirebaseApp.ts +10 -0
- package/lib/common/deeps.ts +3 -0
- package/lib/internal/FirebaseModule.ts +6 -3
- package/lib/internal/NativeModules.ts +4 -1
- package/lib/internal/RNFBNativeEventEmitter.ts +14 -5
- package/lib/internal/SharedEventEmitter.ts +5 -1
- package/lib/internal/index.ts +1 -0
- package/lib/internal/react-native-vendor-emitter.d.ts +11 -0
- package/lib/internal/registry/app.ts +7 -1
- package/lib/types/app.ts +10 -3
- package/lib/types/internal.ts +19 -0
- package/lib/version.ts +1 -1
- package/package.json +8 -8
- package/plugin/build/ios/appDelegate.js +2 -2
- package/plugin/build/ios/podfile.js +16 -16
- package/plugin/build/pluginConfig.d.ts +4 -2
- package/plugin/src/ios/appDelegate.ts +2 -2
- package/plugin/src/ios/podfile.ts +20 -23
- package/plugin/src/pluginConfig.ts +4 -2
- package/android/src/main/java/io/invertase/firebase/common/RNFBHandleMap.java +0 -150
- package/android/src/main/java/io/invertase/firebase/common/TaskExecutorService.java +0 -148
- package/android/src/main/java/io/invertase/firebase/common/UniversalFirebaseModule.java +0 -62
- package/android/src/main/java/io/invertase/firebase/common/UniversalFirebasePreferences.java +0 -91
- package/android/src/reactnative/java/io/invertase/firebase/app/NativeRNFBTurboApp.java +0 -224
- package/android/src/reactnative/java/io/invertase/firebase/app/ReactNativeFirebaseApp.java +0 -46
- package/android/src/reactnative/java/io/invertase/firebase/app/ReactNativeFirebaseAppPackage.java +0 -49
- package/android/src/reactnative/java/io/invertase/firebase/app/ReactNativeFirebaseAppRegistrar.java +0 -35
- package/android/src/reactnative/java/io/invertase/firebase/common/RCTConvertFirebase.java +0 -192
- package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseEvent.java +0 -53
- package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseEventEmitter.java +0 -606
- package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseJSON.java +0 -109
- package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseMeta.java +0 -101
- package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseModule.java +0 -146
- package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebasePreferences.java +0 -96
- package/android/src/reactnative/java/io/invertase/firebase/common/SharedUtils.java +0 -441
- package/android/src/reactnative/java/io/invertase/firebase/utils/NativeRNFBTurboUtils.java +0 -223
- package/android/src/test/java/io/invertase/firebase/common/RNFBHandleMapTest.java +0 -275
- package/android/src/test/java/io/invertase/firebase/common/ReactNativeFirebaseJSONTest.java +0 -108
- package/android/src/test/java/io/invertase/firebase/common/TaskExecutorServiceTest.java +0 -97
|
@@ -0,0 +1,172 @@
|
|
|
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 "RNFBJSON.h"
|
|
21
|
+
|
|
22
|
+
@interface RNFBJSONTests : XCTestCase
|
|
23
|
+
@end
|
|
24
|
+
|
|
25
|
+
@implementation RNFBJSONTests
|
|
26
|
+
|
|
27
|
+
- (RNFBJSON *)jsonWithObject:(NSObject *)object {
|
|
28
|
+
RNFBJSON *json = [[RNFBJSON alloc] init];
|
|
29
|
+
RNFBJSONImplementation *implementation =
|
|
30
|
+
[[RNFBJSONImplementation alloc] initWithJSONObject:object];
|
|
31
|
+
[json setValue:implementation forKey:@"implementation"];
|
|
32
|
+
return json;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
- (void)testSharedUsesStableDispatchOnceIdentity {
|
|
36
|
+
RNFBJSON *first = RNFBJSON.shared;
|
|
37
|
+
XCTAssertNotNil(first);
|
|
38
|
+
XCTAssertIdentical(first, RNFBJSON.shared);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
- (void)testPublicSelectorsAndReturnEncodingsAreUnchanged {
|
|
42
|
+
NSArray<NSString *> *selectorNames = @[
|
|
43
|
+
@"contains:",
|
|
44
|
+
@"getBooleanValue:defaultValue:",
|
|
45
|
+
@"getStringValue:defaultValue:",
|
|
46
|
+
@"getArrayValue:defaultValue:",
|
|
47
|
+
@"getAll",
|
|
48
|
+
@"getRawJSON",
|
|
49
|
+
];
|
|
50
|
+
for (NSString *selectorName in selectorNames) {
|
|
51
|
+
XCTAssertTrue([[RNFBJSON shared] respondsToSelector:NSSelectorFromString(selectorName)]);
|
|
52
|
+
}
|
|
53
|
+
XCTAssertTrue([RNFBJSON respondsToSelector:@selector(shared)]);
|
|
54
|
+
|
|
55
|
+
NSMethodSignature *contains = [RNFBJSON instanceMethodSignatureForSelector:@selector(contains:)];
|
|
56
|
+
XCTAssertEqual(strcmp(contains.methodReturnType, @encode(BOOL)), 0);
|
|
57
|
+
NSMethodSignature *boolean =
|
|
58
|
+
[RNFBJSON instanceMethodSignatureForSelector:@selector(getBooleanValue:defaultValue:)];
|
|
59
|
+
XCTAssertEqual(strcmp(boolean.methodReturnType, @encode(BOOL)), 0);
|
|
60
|
+
XCTAssertEqual(strcmp([boolean getArgumentTypeAtIndex:3], @encode(BOOL)), 0);
|
|
61
|
+
|
|
62
|
+
NSArray<NSString *> *objectReturnSelectors = @[
|
|
63
|
+
@"getStringValue:defaultValue:", @"getArrayValue:defaultValue:", @"getAll", @"getRawJSON"
|
|
64
|
+
];
|
|
65
|
+
for (NSString *selectorName in objectReturnSelectors) {
|
|
66
|
+
NSMethodSignature *signature =
|
|
67
|
+
[RNFBJSON instanceMethodSignatureForSelector:NSSelectorFromString(selectorName)];
|
|
68
|
+
XCTAssertEqual(strcmp(signature.methodReturnType, @encode(id)), 0);
|
|
69
|
+
}
|
|
70
|
+
NSMethodSignature *shared = [RNFBJSON methodSignatureForSelector:@selector(shared)];
|
|
71
|
+
XCTAssertEqual(strcmp(shared.methodReturnType, @encode(id)), 0);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
- (void)testFacadePreservesKVCContainsDefaultsAndUncheckedObjectReturns {
|
|
75
|
+
NSDictionary *dictionary = @{
|
|
76
|
+
@"boolean" : @YES,
|
|
77
|
+
@"booleanFalse" : @NO,
|
|
78
|
+
@"numericZero" : @0,
|
|
79
|
+
@"booleanString" : @"YES",
|
|
80
|
+
@"string" : @"value",
|
|
81
|
+
@"array" : @[ @"one" ],
|
|
82
|
+
@"numberAsString" : @42,
|
|
83
|
+
@"stringAsArray" : @"unchecked",
|
|
84
|
+
@"null" : NSNull.null,
|
|
85
|
+
@"count" : @"count value",
|
|
86
|
+
@"@count" : @"at-count value",
|
|
87
|
+
};
|
|
88
|
+
RNFBJSON *json = [self jsonWithObject:dictionary];
|
|
89
|
+
|
|
90
|
+
XCTAssertTrue([json contains:@"boolean"]);
|
|
91
|
+
XCTAssertTrue([json contains:@"booleanFalse"]);
|
|
92
|
+
XCTAssertTrue([json contains:@"numericZero"]);
|
|
93
|
+
XCTAssertTrue([json contains:@"null"]);
|
|
94
|
+
XCTAssertFalse([json contains:@"missing"]);
|
|
95
|
+
XCTAssertTrue([json getBooleanValue:@"boolean" defaultValue:NO]);
|
|
96
|
+
XCTAssertFalse([json getBooleanValue:@"booleanFalse" defaultValue:YES]);
|
|
97
|
+
XCTAssertFalse([json getBooleanValue:@"numericZero" defaultValue:YES]);
|
|
98
|
+
XCTAssertTrue([json getBooleanValue:@"booleanString" defaultValue:NO]);
|
|
99
|
+
XCTAssertTrue([json getBooleanValue:@"missing" defaultValue:YES]);
|
|
100
|
+
XCTAssertEqualObjects([json getStringValue:@"missing" defaultValue:@"fallback"], @"fallback");
|
|
101
|
+
XCTAssertEqualObjects([json getArrayValue:@"missing" defaultValue:@[ @"fallback" ]],
|
|
102
|
+
(@[ @"fallback" ]));
|
|
103
|
+
XCTAssertEqualObjects([json getStringValue:@"string" defaultValue:@"fallback"], @"value");
|
|
104
|
+
XCTAssertEqualObjects([json getArrayValue:@"array" defaultValue:@[]], (@[ @"one" ]));
|
|
105
|
+
|
|
106
|
+
id uncheckedString = [json getStringValue:@"numberAsString" defaultValue:@"fallback"];
|
|
107
|
+
id uncheckedArray = [json getArrayValue:@"stringAsArray" defaultValue:@[]];
|
|
108
|
+
XCTAssertEqualObjects(uncheckedString, @42);
|
|
109
|
+
XCTAssertEqualObjects(uncheckedArray, @"unchecked");
|
|
110
|
+
XCTAssertIdentical([json getStringValue:@"null" defaultValue:@"fallback"], NSNull.null);
|
|
111
|
+
|
|
112
|
+
for (NSString *key in @[ @"count", @"@count" ]) {
|
|
113
|
+
XCTAssertEqualObjects([json getStringValue:key defaultValue:@"fallback"],
|
|
114
|
+
[dictionary valueForKey:key]);
|
|
115
|
+
XCTAssertEqual([json contains:key], [dictionary valueForKey:key] != nil);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
- (void)testGetBooleanValueThrowsForNSNullArrayAndDictionaryReceivers {
|
|
120
|
+
NSDictionary *dictionary = @{
|
|
121
|
+
@"null" : NSNull.null,
|
|
122
|
+
@"array" : @[ @"one" ],
|
|
123
|
+
@"object" : @{@"nested" : @"value"},
|
|
124
|
+
};
|
|
125
|
+
RNFBJSON *json = [self jsonWithObject:dictionary];
|
|
126
|
+
|
|
127
|
+
XCTAssertThrowsSpecificNamed([json getBooleanValue:@"null" defaultValue:YES], NSException,
|
|
128
|
+
NSInvalidArgumentException);
|
|
129
|
+
XCTAssertThrowsSpecificNamed([json getBooleanValue:@"array" defaultValue:YES], NSException,
|
|
130
|
+
NSInvalidArgumentException);
|
|
131
|
+
XCTAssertThrowsSpecificNamed([json getBooleanValue:@"object" defaultValue:YES], NSException,
|
|
132
|
+
NSInvalidArgumentException);
|
|
133
|
+
|
|
134
|
+
@try {
|
|
135
|
+
[json getBooleanValue:@"null" defaultValue:YES];
|
|
136
|
+
XCTFail(@"expected NSNull boolValue to throw");
|
|
137
|
+
} @catch (NSException *exception) {
|
|
138
|
+
XCTAssertEqualObjects(exception.name, NSInvalidArgumentException);
|
|
139
|
+
XCTAssertTrue([exception.reason containsString:@"boolValue"]);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
- (void)testGetAllCopiesItemsAndReturnsIndependentImmutableSnapshot {
|
|
144
|
+
NSMutableString *mutableString = [NSMutableString stringWithString:@"before"];
|
|
145
|
+
NSMutableArray *mutableArray = [NSMutableArray arrayWithObject:@"first"];
|
|
146
|
+
NSDictionary *source = @{@"string" : mutableString, @"array" : mutableArray};
|
|
147
|
+
RNFBJSON *json = [self jsonWithObject:source];
|
|
148
|
+
|
|
149
|
+
NSDictionary *snapshot = [json getAll];
|
|
150
|
+
|
|
151
|
+
XCTAssertNotIdentical(snapshot, source);
|
|
152
|
+
XCTAssertNotIdentical(snapshot[@"string"], mutableString);
|
|
153
|
+
XCTAssertNotIdentical(snapshot[@"array"], mutableArray);
|
|
154
|
+
[mutableString appendString:@"-after"];
|
|
155
|
+
[mutableArray addObject:@"second"];
|
|
156
|
+
XCTAssertEqualObjects(snapshot[@"string"], @"before");
|
|
157
|
+
XCTAssertEqualObjects(snapshot[@"array"], (@[ @"first" ]));
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
- (void)testGetAllPreservesNonDictionaryExceptionBehavior {
|
|
161
|
+
RNFBJSON *json = [self jsonWithObject:@[ @"valid", @"JSON", @"array" ]];
|
|
162
|
+
|
|
163
|
+
XCTAssertThrowsSpecificNamed([json getAll], NSException, NSInvalidArgumentException);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
- (void)testRawFacadeUsesCurrentBundleValueAndSwiftDecoder {
|
|
167
|
+
NSString *raw = [[NSBundle mainBundle].infoDictionary valueForKey:@"firebase_json_raw"];
|
|
168
|
+
XCTAssertEqualObjects([RNFBJSON.shared getRawJSON],
|
|
169
|
+
[RNFBJSONImplementation rawJSONFromRawValue:raw]);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
@end
|
|
@@ -0,0 +1,106 @@
|
|
|
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 RNFBMetaStorageTests: XCTestCase {
|
|
21
|
+
private func storage(_ plist: [String: Any]) -> RNFBMetaStorage {
|
|
22
|
+
RNFBMetaStorage(infoDictionary: plist)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
func testMissingKeysUseDefaultsAndAreNotContained() {
|
|
26
|
+
let meta = storage([:])
|
|
27
|
+
|
|
28
|
+
XCTAssertFalse(meta.contains("missing"))
|
|
29
|
+
XCTAssertTrue(meta.getBooleanValue("missing", defaultValue: true))
|
|
30
|
+
XCTAssertFalse(meta.getBooleanValue("missing", defaultValue: false))
|
|
31
|
+
XCTAssertEqual(meta.getStringValue("missing", defaultValue: "fallback"), "fallback")
|
|
32
|
+
XCTAssertEqual(meta.getAll() as NSDictionary, NSDictionary())
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
func testPrefixIsAppliedAndUnprefixedKeysAreIgnored() {
|
|
36
|
+
let meta = storage([
|
|
37
|
+
"rnfirebase_present": "value",
|
|
38
|
+
"other_key": "ignored",
|
|
39
|
+
"rnfirebase": "not-prefixed-enough",
|
|
40
|
+
])
|
|
41
|
+
|
|
42
|
+
XCTAssertTrue(meta.contains("present"))
|
|
43
|
+
XCTAssertFalse(meta.contains("other_key"))
|
|
44
|
+
XCTAssertEqual(meta.getStringValue("present", defaultValue: "fallback"), "value")
|
|
45
|
+
XCTAssertEqual(meta.getStringValue("other_key", defaultValue: "fallback"), "fallback")
|
|
46
|
+
|
|
47
|
+
let all = meta.getAll()
|
|
48
|
+
XCTAssertEqual(all as NSDictionary, ["rnfirebase_present": "value"] as NSDictionary)
|
|
49
|
+
XCTAssertNil(all["other_key"])
|
|
50
|
+
XCTAssertNil(all["rnfirebase"])
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
func testGetAllReturnsPrefixedKeysUnstripped() {
|
|
54
|
+
let meta = storage([
|
|
55
|
+
"rnfirebase_string": "abc",
|
|
56
|
+
"rnfirebase_boolean_true": true,
|
|
57
|
+
"rnfirebase_boolean_false": false,
|
|
58
|
+
"unrelated": 1,
|
|
59
|
+
])
|
|
60
|
+
|
|
61
|
+
let all = meta.getAll()
|
|
62
|
+
XCTAssertEqual(Set(all.keys), Set([
|
|
63
|
+
"rnfirebase_string",
|
|
64
|
+
"rnfirebase_boolean_true",
|
|
65
|
+
"rnfirebase_boolean_false",
|
|
66
|
+
]))
|
|
67
|
+
XCTAssertEqual(all["rnfirebase_string"] as? String, "abc")
|
|
68
|
+
XCTAssertEqual(all["rnfirebase_boolean_true"] as? Bool, true)
|
|
69
|
+
XCTAssertEqual(all["rnfirebase_boolean_false"] as? Bool, false)
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
func testPresentBooleanFalseAndNumericZeroOverrideDefaultYes() {
|
|
73
|
+
let meta = storage([
|
|
74
|
+
"rnfirebase_boolFalse": false,
|
|
75
|
+
"rnfirebase_numericZero": 0,
|
|
76
|
+
"rnfirebase_boolTrue": true,
|
|
77
|
+
"rnfirebase_numericOne": 1,
|
|
78
|
+
"rnfirebase_boolStringYes": "YES",
|
|
79
|
+
"rnfirebase_boolStringNo": "0",
|
|
80
|
+
])
|
|
81
|
+
|
|
82
|
+
XCTAssertTrue(meta.contains("boolFalse"))
|
|
83
|
+
XCTAssertTrue(meta.contains("numericZero"))
|
|
84
|
+
XCTAssertFalse(meta.getBooleanValue("boolFalse", defaultValue: true))
|
|
85
|
+
XCTAssertFalse(meta.getBooleanValue("numericZero", defaultValue: true))
|
|
86
|
+
XCTAssertTrue(meta.getBooleanValue("boolTrue", defaultValue: false))
|
|
87
|
+
XCTAssertTrue(meta.getBooleanValue("numericOne", defaultValue: false))
|
|
88
|
+
XCTAssertTrue(meta.getBooleanValue("boolStringYes", defaultValue: false))
|
|
89
|
+
XCTAssertFalse(meta.getBooleanValue("boolStringNo", defaultValue: true))
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
func testStringLookupPreservesPresentValues() {
|
|
93
|
+
let meta = storage([
|
|
94
|
+
"rnfirebase_string": "abc",
|
|
95
|
+
])
|
|
96
|
+
|
|
97
|
+
XCTAssertEqual(meta.getStringValue("string", defaultValue: "fallback"), "abc")
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
func testDefaultInitializerUsesMainBundleInfoDictionary() {
|
|
101
|
+
let production = RNFBMetaStorage()
|
|
102
|
+
let fromBundle = RNFBMetaStorage(infoDictionary: Bundle.main.infoDictionary ?? [:])
|
|
103
|
+
|
|
104
|
+
XCTAssertEqual(production.getAll() as NSDictionary, fromBundle.getAll() as NSDictionary)
|
|
105
|
+
}
|
|
106
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
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 "RNFBMeta.h"
|
|
21
|
+
|
|
22
|
+
@interface RNFBMetaTests : XCTestCase
|
|
23
|
+
@end
|
|
24
|
+
|
|
25
|
+
@implementation RNFBMetaTests
|
|
26
|
+
|
|
27
|
+
- (void)testPublicClassSelectorsAndReturnEncodingsAreUnchanged {
|
|
28
|
+
NSArray<NSString *> *selectorNames = @[
|
|
29
|
+
@"contains:",
|
|
30
|
+
@"getBooleanValue:defaultValue:",
|
|
31
|
+
@"getStringValue:defaultValue:",
|
|
32
|
+
@"getAll",
|
|
33
|
+
];
|
|
34
|
+
for (NSString *selectorName in selectorNames) {
|
|
35
|
+
XCTAssertTrue([RNFBMeta respondsToSelector:NSSelectorFromString(selectorName)]);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
NSMethodSignature *contains = [RNFBMeta methodSignatureForSelector:@selector(contains:)];
|
|
39
|
+
XCTAssertEqual(strcmp(contains.methodReturnType, @encode(BOOL)), 0);
|
|
40
|
+
|
|
41
|
+
NSMethodSignature *boolean = [RNFBMeta methodSignatureForSelector:@selector(getBooleanValue:
|
|
42
|
+
defaultValue:)];
|
|
43
|
+
XCTAssertEqual(strcmp(boolean.methodReturnType, @encode(BOOL)), 0);
|
|
44
|
+
XCTAssertEqual(strcmp([boolean getArgumentTypeAtIndex:3], @encode(BOOL)), 0);
|
|
45
|
+
|
|
46
|
+
NSMethodSignature *string = [RNFBMeta methodSignatureForSelector:@selector(getStringValue:
|
|
47
|
+
defaultValue:)];
|
|
48
|
+
XCTAssertEqual(strcmp(string.methodReturnType, @encode(id)), 0);
|
|
49
|
+
|
|
50
|
+
NSMethodSignature *getAll = [RNFBMeta methodSignatureForSelector:@selector(getAll)];
|
|
51
|
+
XCTAssertEqual(strcmp(getAll.methodReturnType, @encode(id)), 0);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
- (void)testFacadeForwardsToSharedMainBundleStorage {
|
|
55
|
+
// Smoke: class methods are callable and getAll returns a dictionary (may be empty).
|
|
56
|
+
XCTAssertNotNil([RNFBMeta getAll]);
|
|
57
|
+
XCTAssertTrue([[RNFBMeta getAll] isKindOfClass:[NSDictionary class]]);
|
|
58
|
+
XCTAssertFalse([RNFBMeta contains:@"__rnfb_meta_unit_test_missing_key__"]);
|
|
59
|
+
XCTAssertTrue([RNFBMeta getBooleanValue:@"__rnfb_meta_unit_test_missing_key__" defaultValue:YES]);
|
|
60
|
+
XCTAssertEqualObjects([RNFBMeta getStringValue:@"__rnfb_meta_unit_test_missing_key__"
|
|
61
|
+
defaultValue:@"fallback"],
|
|
62
|
+
@"fallback");
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
@end
|
|
@@ -0,0 +1,286 @@
|
|
|
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 RNFBNullSentinelDecodingTests: XCTestCase {
|
|
21
|
+
private func decode(_ value: Any?) -> Any? {
|
|
22
|
+
RNFBNullSentinelDecoder.decodeNullSentinels(value)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
private func sentinel(_ flag: Any = true) -> NSDictionary {
|
|
26
|
+
["__rnfbNull": flag] as NSDictionary
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
private func serverTimestamp() -> NSDictionary {
|
|
30
|
+
[".sv": "timestamp"] as NSDictionary
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
func testNilAndNonContainersPreserveIdentity() {
|
|
34
|
+
XCTAssertNil(decode(nil))
|
|
35
|
+
|
|
36
|
+
let number = NSNumber(value: 42)
|
|
37
|
+
let string = "hello" as NSString
|
|
38
|
+
let date = NSDate()
|
|
39
|
+
let data = NSData()
|
|
40
|
+
let null = NSNull()
|
|
41
|
+
|
|
42
|
+
XCTAssertTrue(decode(number) as AnyObject === number)
|
|
43
|
+
XCTAssertTrue(decode(string) as AnyObject === string)
|
|
44
|
+
XCTAssertTrue(decode(date) as AnyObject === date)
|
|
45
|
+
XCTAssertTrue(decode(data) as AnyObject === data)
|
|
46
|
+
XCTAssertTrue(decode(null) as AnyObject === null)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
func testDecodeAndDecodeNullSentinelsSelectorsAreEquivalent() {
|
|
50
|
+
let input: NSDictionary = ["a": sentinel(), "b": "keep"]
|
|
51
|
+
let viaCanonical = RNFBNullSentinelDecoder.decodeNullSentinels(input) as! NSDictionary
|
|
52
|
+
let viaAlias = RNFBNullSentinelDecoder.decode(input) as! NSDictionary
|
|
53
|
+
XCTAssertEqual(viaCanonical, viaAlias)
|
|
54
|
+
XCTAssertTrue(viaCanonical["a"] is NSNull)
|
|
55
|
+
XCTAssertEqual(viaCanonical["b"] as? String, "keep")
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
func testRootSentinelBecomesNSNull() {
|
|
59
|
+
XCTAssertTrue(decode(sentinel()) is NSNull)
|
|
60
|
+
XCTAssertTrue(decode(sentinel(NSNumber(value: 1))) is NSNull)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
func testRootSentinelRequiresExactlyOneKeyAndTruthyFlag() {
|
|
64
|
+
XCTAssertFalse(decode(sentinel(false)) is NSNull)
|
|
65
|
+
XCTAssertEqual(decode(sentinel(false)) as? NSDictionary, ["__rnfbNull": false] as NSDictionary)
|
|
66
|
+
|
|
67
|
+
let extraKey = ["__rnfbNull": true, "other": 1] as NSDictionary
|
|
68
|
+
XCTAssertEqual(decode(extraKey) as? NSDictionary, extraKey)
|
|
69
|
+
|
|
70
|
+
let empty = decode(NSDictionary()) as! NSDictionary
|
|
71
|
+
XCTAssertEqual(empty.count, 0)
|
|
72
|
+
XCTAssertTrue(empty is NSMutableDictionary)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
func testStringFlagIsNotASentinel() {
|
|
76
|
+
for flag in ["true", "YES", "yes", "1"] as [NSString] {
|
|
77
|
+
let input = sentinel(flag)
|
|
78
|
+
XCTAssertEqual(decode(input) as? NSDictionary, input)
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
func testNonBoolRespondingFlagIsNotASentinel() {
|
|
83
|
+
let exotic = sentinel(NSDate())
|
|
84
|
+
let decoded = decode(exotic) as! NSDictionary
|
|
85
|
+
XCTAssertEqual(decoded.count, 1)
|
|
86
|
+
XCTAssertTrue(decoded["__rnfbNull"] is NSDate)
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
func testRootSentinelFlagNonNumberUnchangedWithoutCrash() {
|
|
90
|
+
let nullFlag = ["__rnfbNull": NSNull()] as NSDictionary
|
|
91
|
+
let dictFlag = ["__rnfbNull": ["a": 1] as NSDictionary] as NSDictionary
|
|
92
|
+
let arrayFlag = ["__rnfbNull": [1] as NSArray] as NSDictionary
|
|
93
|
+
|
|
94
|
+
XCTAssertEqual(decode(nullFlag) as? NSDictionary, nullFlag)
|
|
95
|
+
XCTAssertEqual(decode(dictFlag) as? NSDictionary, dictFlag)
|
|
96
|
+
XCTAssertEqual(decode(arrayFlag) as? NSDictionary, arrayFlag)
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
func testRootServerValueUnchanged() {
|
|
100
|
+
let input = serverTimestamp()
|
|
101
|
+
XCTAssertEqual(decode(input) as? NSDictionary, input)
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
func testNestedDictionarySentinelsBecomeNSNull() {
|
|
105
|
+
let input: NSDictionary = [
|
|
106
|
+
"a": sentinel(),
|
|
107
|
+
"b": "keep",
|
|
108
|
+
"nested": [
|
|
109
|
+
"inner": sentinel(),
|
|
110
|
+
"n": 1,
|
|
111
|
+
"falseFlag": sentinel(false),
|
|
112
|
+
"empty": NSDictionary(),
|
|
113
|
+
] as NSDictionary,
|
|
114
|
+
]
|
|
115
|
+
|
|
116
|
+
let result = decode(input) as! NSDictionary
|
|
117
|
+
XCTAssertTrue(result["a"] is NSNull)
|
|
118
|
+
XCTAssertEqual(result["b"] as? String, "keep")
|
|
119
|
+
let nested = result["nested"] as! NSDictionary
|
|
120
|
+
XCTAssertTrue(nested["inner"] is NSNull)
|
|
121
|
+
XCTAssertEqual(nested["n"] as? Int, 1)
|
|
122
|
+
XCTAssertEqual(nested["falseFlag"] as? NSDictionary, ["__rnfbNull": false] as NSDictionary)
|
|
123
|
+
XCTAssertEqual((nested["empty"] as? NSDictionary)?.count, 0)
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
func testNestedSentinelWithExtraKeysUnchanged() {
|
|
127
|
+
let input: NSDictionary = ["child": ["__rnfbNull": true, "other": "x"] as NSDictionary]
|
|
128
|
+
XCTAssertEqual(decode(input) as? NSDictionary, input)
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
func testNestedSentinelFlagNonNumberUnchanged() {
|
|
132
|
+
let input: NSDictionary = [
|
|
133
|
+
"nullFlag": ["__rnfbNull": NSNull()] as NSDictionary,
|
|
134
|
+
"dictFlag": ["__rnfbNull": ["a": 1] as NSDictionary] as NSDictionary,
|
|
135
|
+
"arrayFlag": ["__rnfbNull": [1] as NSArray] as NSDictionary,
|
|
136
|
+
"stringFlag": ["__rnfbNull": "true"] as NSDictionary,
|
|
137
|
+
]
|
|
138
|
+
XCTAssertEqual(decode(input) as? NSDictionary, input)
|
|
139
|
+
|
|
140
|
+
let arrayInput: NSArray = [
|
|
141
|
+
["__rnfbNull": NSNull()] as NSDictionary,
|
|
142
|
+
["__rnfbNull": ["a": 1] as NSDictionary] as NSDictionary,
|
|
143
|
+
["__rnfbNull": [1] as NSArray] as NSDictionary,
|
|
144
|
+
["__rnfbNull": "true"] as NSDictionary,
|
|
145
|
+
]
|
|
146
|
+
XCTAssertEqual(decode(arrayInput) as? NSArray, arrayInput)
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
func testValidSentinelSiblingDecodedWhileNonNumberFlagPassesThrough() {
|
|
150
|
+
let input: NSDictionary = [
|
|
151
|
+
"valid": sentinel(),
|
|
152
|
+
"guarded": ["__rnfbNull": NSNull()] as NSDictionary,
|
|
153
|
+
"list": [sentinel(), ["__rnfbNull": [1] as NSArray] as NSDictionary] as NSArray,
|
|
154
|
+
]
|
|
155
|
+
let result = decode(input) as! NSDictionary
|
|
156
|
+
XCTAssertTrue(result["valid"] is NSNull)
|
|
157
|
+
XCTAssertEqual(result["guarded"] as? NSDictionary, ["__rnfbNull": NSNull()] as NSDictionary)
|
|
158
|
+
let list = result["list"] as! NSArray
|
|
159
|
+
XCTAssertTrue(list[0] is NSNull)
|
|
160
|
+
XCTAssertEqual(list[1] as? NSDictionary, ["__rnfbNull": [1] as NSArray] as NSDictionary)
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
func testArrayWalkPreservesNSNullAndReplacesSentinels() {
|
|
164
|
+
let input: NSArray = [
|
|
165
|
+
sentinel(),
|
|
166
|
+
NSNull(),
|
|
167
|
+
"x",
|
|
168
|
+
3,
|
|
169
|
+
serverTimestamp(),
|
|
170
|
+
[sentinel(), 2] as NSArray,
|
|
171
|
+
]
|
|
172
|
+
|
|
173
|
+
let result = decode(input) as! NSArray
|
|
174
|
+
XCTAssertEqual(result.count, 6)
|
|
175
|
+
XCTAssertTrue(result[0] is NSNull)
|
|
176
|
+
XCTAssertTrue(result[1] is NSNull)
|
|
177
|
+
XCTAssertEqual(result[2] as? String, "x")
|
|
178
|
+
XCTAssertEqual(result[3] as? Int, 3)
|
|
179
|
+
XCTAssertEqual(result[4] as? NSDictionary, serverTimestamp())
|
|
180
|
+
let nested = result[5] as! NSArray
|
|
181
|
+
XCTAssertTrue(nested[0] is NSNull)
|
|
182
|
+
XCTAssertEqual(nested[1] as? Int, 2)
|
|
183
|
+
XCTAssertTrue(result is NSMutableArray)
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
func testRootEmptyArrayReturnsEmptyMutableArray() {
|
|
187
|
+
let decoded = decode([] as NSArray) as! NSArray
|
|
188
|
+
XCTAssertEqual(decoded.count, 0)
|
|
189
|
+
XCTAssertTrue(decoded is NSMutableArray)
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
func testNestedArraysSentinelsDecodedAtEveryLevel() {
|
|
193
|
+
let input: NSArray = [[sentinel(), [sentinel(), "leaf"] as NSArray] as NSArray, [] as NSArray]
|
|
194
|
+
let result = decode(input) as! NSArray
|
|
195
|
+
let first = result[0] as! NSArray
|
|
196
|
+
XCTAssertTrue(first[0] is NSNull)
|
|
197
|
+
XCTAssertTrue((first[1] as! NSArray)[0] is NSNull)
|
|
198
|
+
XCTAssertEqual((first[1] as! NSArray)[1] as? String, "leaf")
|
|
199
|
+
XCTAssertEqual((result[1] as! NSArray).count, 0)
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
func testArrayInsideDictionaryAndMixedMatrixDecoded() {
|
|
203
|
+
let input: NSDictionary = [
|
|
204
|
+
"list": [sentinel(), "x", [sentinel()] as NSArray] as NSArray,
|
|
205
|
+
"items": [
|
|
206
|
+
["id": 1, "note": sentinel()] as NSDictionary,
|
|
207
|
+
["id": 2, "tags": [sentinel()] as NSArray] as NSDictionary,
|
|
208
|
+
] as NSArray,
|
|
209
|
+
]
|
|
210
|
+
let result = decode(input) as! NSDictionary
|
|
211
|
+
let list = result["list"] as! NSArray
|
|
212
|
+
XCTAssertTrue(list[0] is NSNull)
|
|
213
|
+
XCTAssertEqual(list[1] as? String, "x")
|
|
214
|
+
XCTAssertTrue((list[2] as! NSArray)[0] is NSNull)
|
|
215
|
+
|
|
216
|
+
let items = result["items"] as! NSArray
|
|
217
|
+
XCTAssertTrue((items[0] as! NSDictionary)["note"] is NSNull)
|
|
218
|
+
XCTAssertTrue(((items[1] as! NSDictionary)["tags"] as! NSArray)[0] is NSNull)
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
func testChildAndParentTypeMatrix() {
|
|
222
|
+
let dictInput: NSDictionary = [
|
|
223
|
+
"dictChild": ["k": 1] as NSDictionary,
|
|
224
|
+
"arrayChild": ["leaf", [2] as NSArray, sentinel(), NSNull()] as NSArray,
|
|
225
|
+
"primitiveChild": "text",
|
|
226
|
+
"nullChild": NSNull(),
|
|
227
|
+
]
|
|
228
|
+
let arrayRoot: NSArray = [
|
|
229
|
+
["inner": sentinel()] as NSDictionary,
|
|
230
|
+
["nested"] as NSArray,
|
|
231
|
+
3,
|
|
232
|
+
sentinel(),
|
|
233
|
+
NSNull(),
|
|
234
|
+
]
|
|
235
|
+
|
|
236
|
+
let decodedDict = decode(dictInput) as! NSDictionary
|
|
237
|
+
XCTAssertEqual(decodedDict["dictChild"] as? NSDictionary, ["k": 1] as NSDictionary)
|
|
238
|
+
let arrayChild = decodedDict["arrayChild"] as! NSArray
|
|
239
|
+
XCTAssertEqual(arrayChild[0] as? String, "leaf")
|
|
240
|
+
XCTAssertTrue(arrayChild[2] is NSNull)
|
|
241
|
+
XCTAssertTrue(decodedDict["nullChild"] is NSNull)
|
|
242
|
+
|
|
243
|
+
let decodedArray = decode(arrayRoot) as! NSArray
|
|
244
|
+
XCTAssertTrue((decodedArray[0] as! NSDictionary)["inner"] is NSNull)
|
|
245
|
+
XCTAssertTrue(decodedArray[3] is NSNull)
|
|
246
|
+
XCTAssertTrue(decodedArray[4] is NSNull)
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
func testContainersReturnNewMutableCopiesEvenWithoutSentinels() {
|
|
250
|
+
let dict = ["k": "v"] as NSDictionary
|
|
251
|
+
let array = ["a", 1] as NSArray
|
|
252
|
+
|
|
253
|
+
let decodedDict = decode(dict)
|
|
254
|
+
let decodedArray = decode(array)
|
|
255
|
+
|
|
256
|
+
XCTAssertFalse(decodedDict as AnyObject === dict)
|
|
257
|
+
XCTAssertFalse(decodedArray as AnyObject === array)
|
|
258
|
+
XCTAssertTrue(decodedDict is NSMutableDictionary)
|
|
259
|
+
XCTAssertTrue(decodedArray is NSMutableArray)
|
|
260
|
+
XCTAssertEqual(decodedDict as? NSDictionary, dict)
|
|
261
|
+
XCTAssertEqual(decodedArray as? NSArray, array)
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
func testCountOneNumberFalseIsNotSentinel() {
|
|
265
|
+
let input: NSDictionary = [
|
|
266
|
+
"a": ["__rnfbNull": false] as NSDictionary,
|
|
267
|
+
"b": ["__rnfbNull": NSNumber(value: 0)] as NSDictionary,
|
|
268
|
+
]
|
|
269
|
+
XCTAssertEqual(decode(input) as? NSDictionary, input)
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
func testDeepNestingDoesNotOverflow() {
|
|
273
|
+
let depth = 1000
|
|
274
|
+
var leaf: Any = ["value": sentinel()] as NSDictionary
|
|
275
|
+
for _ in 0..<depth {
|
|
276
|
+
leaf = ["child": leaf] as NSDictionary
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
var cursor = decode(leaf) as! NSDictionary
|
|
280
|
+
for _ in 0..<depth {
|
|
281
|
+
XCTAssertTrue(cursor is NSMutableDictionary)
|
|
282
|
+
cursor = cursor["child"] as! NSDictionary
|
|
283
|
+
}
|
|
284
|
+
XCTAssertTrue(cursor["value"] is NSNull)
|
|
285
|
+
}
|
|
286
|
+
}
|