diff --git a/.github/workflows/verify.yml b/.github/workflows/verify.yml index 92bc6a408..9158493b5 100644 --- a/.github/workflows/verify.yml +++ b/.github/workflows/verify.yml @@ -13,37 +13,13 @@ jobs: steps: - name: Check out code uses: actions/checkout@v4 - - name: Set up Ruby 2.7 - uses: ruby/setup-ruby@v1 - with: - ruby-version: '2.7' - - name: Restore cache - uses: actions/cache@v3 - with: - path: | - vendor - Branch-TestBed/Pods - key: ${{ runner.os }}-${{ hashFiles('Gemfile.lock','Branch-TestBed/Podfile.lock') }} - restore-keys: | - ${{ runner.os }}- - - name: Install Ruby dependencies - run: | - bundle config set --local path vendor - bundle check || bundle install - # This happens automatically with the unit_tests lane, but adding it here - # makes it easier to keep track of installation time via GHA without - # adding execution time to the next step. - #- name: Install CocoaPods dependencies - # run: bundle exec fastlane prepare_pods - name: Run unit tests - run: bundle exec fastlane unit_tests - - name: Upload test results - uses: actions/upload-artifact@v4 - if: always() # even if tests fail - with: - name: test-results - path: fastlane/test_output - - name: Upload codecov results - uses: codecov/codecov-action@v5 - with: - files: ./fastlane/test_output/cobertura.xml + run: | + echo "branch=${{ github.ref }}" >> $GITHUB_OUTPUT + ./scripts/getSimulator + DESTINATION="platform=iOS Simulator,name=$(cat ./iphoneSim),OS=latest" + xcodebuild test \ + -project BranchSDK.xcodeproj \ + -scheme BranchSDKTests \ + -destination "$DESTINATION" \ + -testPlan BranchSDKTests | xcpretty && exit ${PIPESTATUS[0]} diff --git a/BranchSDK.xcodeproj/project.pbxproj b/BranchSDK.xcodeproj/project.pbxproj index 02d51e7fa..b1a16d9c1 100644 --- a/BranchSDK.xcodeproj/project.pbxproj +++ b/BranchSDK.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 55; + objectVersion = 73; objects = { /* Begin PBXAggregateTarget section */ @@ -54,25 +54,12 @@ /* End PBXAggregateTarget section */ /* Begin PBXBuildFile section */ - 5F2211722894A9C000C5B190 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F2211712894A9C000C5B190 /* AppDelegate.swift */; }; - 5F2211742894A9C000C5B190 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F2211732894A9C000C5B190 /* SceneDelegate.swift */; }; - 5F2211762894A9C000C5B190 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F2211752894A9C000C5B190 /* ViewController.swift */; }; - 5F2211792894A9C000C5B190 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 5F2211772894A9C000C5B190 /* Main.storyboard */; }; - 5F22117B2894A9C100C5B190 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 5F22117A2894A9C100C5B190 /* Assets.xcassets */; }; - 5F22117E2894A9C100C5B190 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 5F22117C2894A9C100C5B190 /* LaunchScreen.storyboard */; }; - 5F2211892894A9C100C5B190 /* TestHostTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F2211882894A9C100C5B190 /* TestHostTests.swift */; }; - 5F2211932894A9C100C5B190 /* TestHostUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F2211922894A9C100C5B190 /* TestHostUITests.swift */; }; - 5F2211952894A9C100C5B190 /* TestHostUITestsLaunchTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F2211942894A9C100C5B190 /* TestHostUITestsLaunchTests.swift */; }; 5F5FDA162B7DE2FE00F14A43 /* BranchLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F5FDA152B7DE2FE00F14A43 /* BranchLogger.m */; }; 5F5FDA172B7DE2FE00F14A43 /* BranchLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F5FDA152B7DE2FE00F14A43 /* BranchLogger.m */; }; 5F5FDA182B7DE2FE00F14A43 /* BranchLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F5FDA152B7DE2FE00F14A43 /* BranchLogger.m */; }; 5F5FDA1A2B7DE31E00F14A43 /* BranchLogger.h in Headers */ = {isa = PBXBuildFile; fileRef = 5F5FDA192B7DE31E00F14A43 /* BranchLogger.h */; settings = {ATTRIBUTES = (Public, ); }; }; 5F5FDA1B2B7DE31E00F14A43 /* BranchLogger.h in Headers */ = {isa = PBXBuildFile; fileRef = 5F5FDA192B7DE31E00F14A43 /* BranchLogger.h */; settings = {ATTRIBUTES = (Public, ); }; }; 5F5FDA1C2B7DE31E00F14A43 /* BranchLogger.h in Headers */ = {isa = PBXBuildFile; fileRef = 5F5FDA192B7DE31E00F14A43 /* BranchLogger.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 5F6DD2482894AEBD00AE9FB0 /* BranchSDK.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5F22101D2894A0DB00C5B190 /* BranchSDK.framework */; }; - 5F6DD24C2894AF5E00AE9FB0 /* NSURLSession+Branch.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F6DD24A2894AF5E00AE9FB0 /* NSURLSession+Branch.m */; }; - 5F73EBFA28ECE65400608601 /* BranchSDK.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5F73EBF428ECE65400608601 /* BranchSDK.framework */; }; - 5F73EBFB28ECE65400608601 /* BranchSDK.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 5F73EBF428ECE65400608601 /* BranchSDK.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 5FA71BA82B7AE6B2008009CA /* Branch.h in Headers */ = {isa = PBXBuildFile; fileRef = 5FCDD3A22B7AC6A100EAF29F /* Branch.h */; settings = {ATTRIBUTES = (Public, ); }; }; 5FC446652ACCB97000FF1C87 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 5FC446642ACCB96000FF1C87 /* PrivacyInfo.xcprivacy */; }; 5FC446662ACCB97100FF1C87 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 5FC446642ACCB96000FF1C87 /* PrivacyInfo.xcprivacy */; }; @@ -499,48 +486,53 @@ E7931D842E01C8AE0007A374 /* ConfigurationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E7931D832E01C8AE0007A374 /* ConfigurationController.swift */; }; E7931D852E01C8AE0007A374 /* ConfigurationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E7931D832E01C8AE0007A374 /* ConfigurationController.swift */; }; E7931D862E01C8AE0007A374 /* ConfigurationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E7931D832E01C8AE0007A374 /* ConfigurationController.swift */; }; + E7CA74EF2E1B4F75002EFB40 /* BranchSDK.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5F22101D2894A0DB00C5B190 /* BranchSDK.framework */; settings = {ATTRIBUTES = (Required, ); }; }; + E7CA75B92E1B994B002EFB40 /* AdServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7CA75B82E1B994B002EFB40 /* AdServices.framework */; }; + E7CA75BB2E1B9951002EFB40 /* AdSupport.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7CA75BA2E1B9951002EFB40 /* AdSupport.framework */; }; + E7CA75BC2E1B9957002EFB40 /* BranchSDK.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5F22101D2894A0DB00C5B190 /* BranchSDK.framework */; }; + E7CA75BD2E1B9957002EFB40 /* BranchSDK.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 5F22101D2894A0DB00C5B190 /* BranchSDK.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; E7F311AE2DACB4D400F824A7 /* BNCODMInfoCollector.m in Sources */ = {isa = PBXBuildFile; fileRef = E7F311AD2DACB4D400F824A7 /* BNCODMInfoCollector.m */; }; E7F311AF2DACB4D400F824A7 /* BNCODMInfoCollector.m in Sources */ = {isa = PBXBuildFile; fileRef = E7F311AD2DACB4D400F824A7 /* BNCODMInfoCollector.m */; }; E7F311B12DACB54100F824A7 /* BNCODMInfoCollector.h in Headers */ = {isa = PBXBuildFile; fileRef = E7F311B02DACB54100F824A7 /* BNCODMInfoCollector.h */; }; E7F311B22DACB54100F824A7 /* BNCODMInfoCollector.h in Headers */ = {isa = PBXBuildFile; fileRef = E7F311B02DACB54100F824A7 /* BNCODMInfoCollector.h */; }; E7F311B32DACB54100F824A7 /* BNCODMInfoCollector.h in Headers */ = {isa = PBXBuildFile; fileRef = E7F311B02DACB54100F824A7 /* BNCODMInfoCollector.h */; }; - E7FBA85F2E14492700E7AAD9 /* BranchConstants.h in Headers */ = {isa = PBXBuildFile; fileRef = E7FBA85E2E14492600E7AAD9 /* BranchConstants.h */; settings = {ATTRIBUTES = (Public, ); }; }; - E7FBA8602E1449D100E7AAD9 /* BranchConstants.h in Headers */ = {isa = PBXBuildFile; fileRef = E7FBA85E2E14492600E7AAD9 /* BranchConstants.h */; settings = {ATTRIBUTES = (Public, ); }; }; - E7FBA8612E1449D100E7AAD9 /* BranchConstants.h in Headers */ = {isa = PBXBuildFile; fileRef = E7FBA85E2E14492600E7AAD9 /* BranchConstants.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E7FAF6A02E26E497006C167F /* BranchConstants.h in Headers */ = {isa = PBXBuildFile; fileRef = E7FAF69F2E26E497006C167F /* BranchConstants.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E7FAF6A12E26E497006C167F /* BranchConstants.h in Headers */ = {isa = PBXBuildFile; fileRef = E7FAF69F2E26E497006C167F /* BranchConstants.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E7FAF6A22E26E497006C167F /* BranchConstants.h in Headers */ = {isa = PBXBuildFile; fileRef = E7FAF69F2E26E497006C167F /* BranchConstants.h */; settings = {ATTRIBUTES = (Public, ); }; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ - 5F2211852894A9C100C5B190 /* PBXContainerItemProxy */ = { + E7CA75592E1B52F4002EFB40 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 5F2210142894A0DB00C5B190 /* Project object */; proxyType = 1; - remoteGlobalIDString = 5F22116E2894A9C000C5B190; - remoteInfo = TestHost; + remoteGlobalIDString = 5F22101C2894A0DB00C5B190; + remoteInfo = BranchSDK; }; - 5F22118F2894A9C100C5B190 /* PBXContainerItemProxy */ = { + E7CA75A62E1B79CD002EFB40 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 5F2210142894A0DB00C5B190 /* Project object */; proxyType = 1; - remoteGlobalIDString = 5F22116E2894A9C000C5B190; - remoteInfo = TestHost; + remoteGlobalIDString = E7CA755E2E1B59F5002EFB40; + remoteInfo = BranchSDKTestsHostApp; }; - 5F73EBF828ECE65400608601 /* PBXContainerItemProxy */ = { + E7CA75BE2E1B9957002EFB40 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 5F2210142894A0DB00C5B190 /* Project object */; proxyType = 1; - remoteGlobalIDString = 5F73EBF328ECE65400608601; - remoteInfo = "BranchSDK-static"; + remoteGlobalIDString = 5F22101C2894A0DB00C5B190; + remoteInfo = BranchSDK; }; /* End PBXContainerItemProxy section */ /* Begin PBXCopyFilesBuildPhase section */ - 5F73EBFF28ECE65400608601 /* Embed Frameworks */ = { + E7CA75C02E1B9957002EFB40 /* Embed Frameworks */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; dstPath = ""; dstSubfolderSpec = 10; files = ( - 5F73EBFB28ECE65400608601 /* BranchSDK.framework in Embed Frameworks */, + E7CA75BD2E1B9957002EFB40 /* BranchSDK.framework in Embed Frameworks */, ); name = "Embed Frameworks"; runOnlyForDeploymentPostprocessing = 0; @@ -549,24 +541,8 @@ /* Begin PBXFileReference section */ 5F22101D2894A0DB00C5B190 /* BranchSDK.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = BranchSDK.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 5F22116F2894A9C000C5B190 /* TestHost.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TestHost.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 5F2211712894A9C000C5B190 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - 5F2211732894A9C000C5B190 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; - 5F2211752894A9C000C5B190 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; - 5F2211782894A9C000C5B190 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - 5F22117A2894A9C100C5B190 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; - 5F22117D2894A9C100C5B190 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; - 5F22117F2894A9C100C5B190 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 5F2211842894A9C100C5B190 /* TestHostTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = TestHostTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 5F2211882894A9C100C5B190 /* TestHostTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestHostTests.swift; sourceTree = ""; }; - 5F22118E2894A9C100C5B190 /* TestHostUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = TestHostUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 5F2211922894A9C100C5B190 /* TestHostUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestHostUITests.swift; sourceTree = ""; }; - 5F2211942894A9C100C5B190 /* TestHostUITestsLaunchTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestHostUITestsLaunchTests.swift; sourceTree = ""; }; 5F5FDA152B7DE2FE00F14A43 /* BranchLogger.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BranchLogger.m; sourceTree = ""; }; 5F5FDA192B7DE31E00F14A43 /* BranchLogger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BranchLogger.h; sourceTree = ""; }; - 5F6DD2492894AF5E00AE9FB0 /* TestHost-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "TestHost-Bridging-Header.h"; sourceTree = ""; }; - 5F6DD24A2894AF5E00AE9FB0 /* NSURLSession+Branch.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSURLSession+Branch.m"; sourceTree = ""; }; - 5F6DD24B2894AF5E00AE9FB0 /* NSURLSession+Branch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSURLSession+Branch.h"; sourceTree = ""; }; 5F73EBF428ECE65400608601 /* BranchSDK.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = BranchSDK.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 5F73EC0028EDEAC200608601 /* build_static_xcframework_noidfa.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = build_static_xcframework_noidfa.sh; sourceTree = ""; }; 5F73EC0128EDEAC200608601 /* build_static_xcframework.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = build_static_xcframework.sh; sourceTree = ""; }; @@ -720,53 +696,103 @@ E71E396D2DD3A92900110F59 /* BNCInAppBrowser.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BNCInAppBrowser.h; sourceTree = ""; }; E71E396E2DD3A92900110F59 /* BNCInAppBrowser.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BNCInAppBrowser.m; sourceTree = ""; }; E7931D832E01C8AE0007A374 /* ConfigurationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = ConfigurationController.swift; path = ../BranchSDK_Swift/ConfigurationController.swift; sourceTree = ""; }; + E7CA74EB2E1B4F75002EFB40 /* BranchSDKTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = BranchSDKTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + E7CA755F2E1B59F5002EFB40 /* BranchSDKTestsHostApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = BranchSDKTestsHostApp.app; sourceTree = BUILT_PRODUCTS_DIR; }; + E7CA75B82E1B994B002EFB40 /* AdServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AdServices.framework; path = System/Library/Frameworks/AdServices.framework; sourceTree = SDKROOT; }; + E7CA75BA2E1B9951002EFB40 /* AdSupport.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AdSupport.framework; path = System/Library/Frameworks/AdSupport.framework; sourceTree = SDKROOT; }; E7F311AD2DACB4D400F824A7 /* BNCODMInfoCollector.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BNCODMInfoCollector.m; sourceTree = ""; }; E7F311B02DACB54100F824A7 /* BNCODMInfoCollector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BNCODMInfoCollector.h; sourceTree = ""; }; - E7FBA85E2E14492600E7AAD9 /* BranchConstants.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = BranchConstants.h; path = ../../BranchSDK_ObjC/Public/BranchConstants.h; sourceTree = ""; }; + E7FAF69F2E26E497006C167F /* BranchConstants.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = BranchConstants.h; path = Sources/BranchSDK_ObjC/Public/BranchConstants.h; sourceTree = SOURCE_ROOT; }; /* End PBXFileReference section */ -/* Begin PBXFrameworksBuildPhase section */ - 5F22101A2894A0DB00C5B190 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( +/* Begin PBXFileSystemSynchronizedBuildFileExceptionSet section */ + E7CA75552E1B504C002EFB40 /* PBXFileSystemSynchronizedBuildFileExceptionSet */ = { + isa = PBXFileSystemSynchronizedBuildFileExceptionSet; + membershipExceptions = ( + Info.plist, ); - runOnlyForDeploymentPostprocessing = 0; + target = E7CA74EA2E1B4F75002EFB40 /* BranchSDKTests */; + }; + E7CA758B2E1B59F7002EFB40 /* PBXFileSystemSynchronizedBuildFileExceptionSet */ = { + isa = PBXFileSystemSynchronizedBuildFileExceptionSet; + membershipExceptions = ( + Info.plist, + ); + target = E7CA755E2E1B59F5002EFB40 /* BranchSDKTestsHostApp */; + }; + E7CA75B12E1B7B02002EFB40 /* PBXFileSystemSynchronizedBuildFileExceptionSet */ = { + isa = PBXFileSystemSynchronizedBuildFileExceptionSet; + membershipExceptions = ( + cannedData/example.json, + cannedData/latd_empty_data.json, + cannedData/latd_missing_data.json, + cannedData/latd_missing_window.json, + cannedData/latd.json, + ); + target = E7CA74EA2E1B4F75002EFB40 /* BranchSDKTests */; + }; + E7F2461F2E26B8F90083FDE1 /* PBXFileSystemSynchronizedBuildFileExceptionSet */ = { + isa = PBXFileSystemSynchronizedBuildFileExceptionSet; + membershipExceptions = ( + BranchSDKTests.xctestplan, + ); + target = E7CA755E2E1B59F5002EFB40 /* BranchSDKTestsHostApp */; }; - 5F22116C2894A9C000C5B190 /* Frameworks */ = { +/* End PBXFileSystemSynchronizedBuildFileExceptionSet section */ + +/* Begin PBXFileSystemSynchronizedGroupBuildPhaseMembershipExceptionSet section */ + E7CA75562E1B504C002EFB40 /* PBXFileSystemSynchronizedGroupBuildPhaseMembershipExceptionSet */ = { + isa = PBXFileSystemSynchronizedGroupBuildPhaseMembershipExceptionSet; + buildPhase = E7CA74E72E1B4F75002EFB40 /* Sources */; + membershipExceptions = ( + BNCJsonLoader.h, + "Branch-SDK-Tests-Bridging-Header.h", + ); + }; +/* End PBXFileSystemSynchronizedGroupBuildPhaseMembershipExceptionSet section */ + +/* Begin PBXFileSystemSynchronizedRootGroup section */ + E7CA74EC2E1B4F75002EFB40 /* BranchSDKTests */ = {isa = PBXFileSystemSynchronizedRootGroup; exceptions = (E7CA75552E1B504C002EFB40 /* PBXFileSystemSynchronizedBuildFileExceptionSet */, E7CA75562E1B504C002EFB40 /* PBXFileSystemSynchronizedGroupBuildPhaseMembershipExceptionSet */, E7F2461F2E26B8F90083FDE1 /* PBXFileSystemSynchronizedBuildFileExceptionSet */, ); explicitFileTypes = {}; explicitFolders = (); path = BranchSDKTests; sourceTree = ""; }; + E7CA75602E1B59F5002EFB40 /* BranchSDKTestsHostApp */ = {isa = PBXFileSystemSynchronizedRootGroup; exceptions = (E7CA75B12E1B7B02002EFB40 /* PBXFileSystemSynchronizedBuildFileExceptionSet */, E7CA758B2E1B59F7002EFB40 /* PBXFileSystemSynchronizedBuildFileExceptionSet */, ); explicitFileTypes = {}; explicitFolders = (); path = BranchSDKTestsHostApp; sourceTree = ""; }; +/* End PBXFileSystemSynchronizedRootGroup section */ + +/* Begin PBXFrameworksBuildPhase section */ + 5F22101A2894A0DB00C5B190 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 5F6DD2482894AEBD00AE9FB0 /* BranchSDK.framework in Frameworks */, - 5F73EBFA28ECE65400608601 /* BranchSDK.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; - 5F2211812894A9C100C5B190 /* Frameworks */ = { + 5F73EBF128ECE65400608601 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; - 5F22118B2894A9C100C5B190 /* Frameworks */ = { + 5F79038928B5765D003144CD /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; - 5F73EBF128ECE65400608601 /* Frameworks */ = { + E7CA74E82E1B4F75002EFB40 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + E7CA74EF2E1B4F75002EFB40 /* BranchSDK.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; - 5F79038928B5765D003144CD /* Frameworks */ = { + E7CA755C2E1B59F5002EFB40 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + E7CA75BC2E1B9957002EFB40 /* BranchSDK.framework in Frameworks */, + E7CA75B92E1B994B002EFB40 /* AdServices.framework in Frameworks */, + E7CA75BB2E1B9951002EFB40 /* AdSupport.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -777,11 +803,11 @@ isa = PBXGroup; children = ( 5FCDD36B2B7AC6A100EAF29F /* BranchSDK */, - 5F2211702894A9C000C5B190 /* TestHost */, - 5F2211872894A9C100C5B190 /* TestHostTests */, - 5F2211912894A9C100C5B190 /* TestHostUITests */, 5FF2AFDD28E7C1F200393216 /* Framework */, 5FF2AFDB28E7BF5500393216 /* Scripts */, + E7CA74EC2E1B4F75002EFB40 /* BranchSDKTests */, + E7CA75602E1B59F5002EFB40 /* BranchSDKTestsHostApp */, + E7CA75B72E1B994B002EFB40 /* Frameworks */, 5F22101E2894A0DB00C5B190 /* Products */, ); sourceTree = ""; @@ -790,49 +816,14 @@ isa = PBXGroup; children = ( 5F22101D2894A0DB00C5B190 /* BranchSDK.framework */, - 5F22116F2894A9C000C5B190 /* TestHost.app */, - 5F2211842894A9C100C5B190 /* TestHostTests.xctest */, - 5F22118E2894A9C100C5B190 /* TestHostUITests.xctest */, 5F79038C28B5765D003144CD /* BranchSDK.framework */, 5F73EBF428ECE65400608601 /* BranchSDK.framework */, + E7CA74EB2E1B4F75002EFB40 /* BranchSDKTests.xctest */, + E7CA755F2E1B59F5002EFB40 /* BranchSDKTestsHostApp.app */, ); name = Products; sourceTree = ""; }; - 5F2211702894A9C000C5B190 /* TestHost */ = { - isa = PBXGroup; - children = ( - 5F2211712894A9C000C5B190 /* AppDelegate.swift */, - 5F2211732894A9C000C5B190 /* SceneDelegate.swift */, - 5F2211752894A9C000C5B190 /* ViewController.swift */, - 5F6DD24B2894AF5E00AE9FB0 /* NSURLSession+Branch.h */, - 5F6DD24A2894AF5E00AE9FB0 /* NSURLSession+Branch.m */, - 5F2211772894A9C000C5B190 /* Main.storyboard */, - 5F22117A2894A9C100C5B190 /* Assets.xcassets */, - 5F22117C2894A9C100C5B190 /* LaunchScreen.storyboard */, - 5F22117F2894A9C100C5B190 /* Info.plist */, - 5F6DD2492894AF5E00AE9FB0 /* TestHost-Bridging-Header.h */, - ); - path = TestHost; - sourceTree = ""; - }; - 5F2211872894A9C100C5B190 /* TestHostTests */ = { - isa = PBXGroup; - children = ( - 5F2211882894A9C100C5B190 /* TestHostTests.swift */, - ); - path = TestHostTests; - sourceTree = ""; - }; - 5F2211912894A9C100C5B190 /* TestHostUITests */ = { - isa = PBXGroup; - children = ( - 5F2211922894A9C100C5B190 /* TestHostUITests.swift */, - 5F2211942894A9C100C5B190 /* TestHostUITestsLaunchTests.swift */, - ); - path = TestHostUITests; - sourceTree = ""; - }; 5FCDD36B2B7AC6A100EAF29F /* BranchSDK */ = { isa = PBXGroup; children = ( @@ -919,6 +910,7 @@ 5FCDD3982B7AC6A100EAF29F /* Public */ = { isa = PBXGroup; children = ( + E7FAF69F2E26E497006C167F /* BranchConstants.h */, 5FCDD3A42B7AC6A100EAF29F /* BNCCallbacks.h */, 5FCDD3A02B7AC6A100EAF29F /* BNCCurrency.h */, 5FCDD3A72B7AC6A100EAF29F /* BNCInitSessionResponse.h */, @@ -1027,6 +1019,15 @@ path = Framework; sourceTree = ""; }; + E7CA75B72E1B994B002EFB40 /* Frameworks */ = { + isa = PBXGroup; + children = ( + E7CA75BA2E1B9951002EFB40 /* AdSupport.framework */, + E7CA75B82E1B994B002EFB40 /* AdServices.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ @@ -1034,7 +1035,7 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - E7FBA85F2E14492700E7AAD9 /* BranchConstants.h in Headers */, + E7FAF6A02E26E497006C167F /* BranchConstants.h in Headers */, 5FCDD52E2B7AC6A300EAF29F /* Branch+Validator.h in Headers */, 5FCDD4A42B7AC6A200EAF29F /* BNCCallbacks.h in Headers */, 5FCDD4922B7AC6A100EAF29F /* BranchLinkProperties.h in Headers */, @@ -1117,7 +1118,7 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - E7FBA8602E1449D100E7AAD9 /* BranchConstants.h in Headers */, + E7FAF6A22E26E497006C167F /* BranchConstants.h in Headers */, 5FCDD52F2B7AC6A300EAF29F /* Branch+Validator.h in Headers */, 5FCDD4A52B7AC6A200EAF29F /* BNCCallbacks.h in Headers */, 5FCDD4932B7AC6A100EAF29F /* BranchLinkProperties.h in Headers */, @@ -1200,7 +1201,7 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - E7FBA8612E1449D100E7AAD9 /* BranchConstants.h in Headers */, + E7FAF6A12E26E497006C167F /* BranchConstants.h in Headers */, 5FCDD4BB2B7AC6A200EAF29F /* BranchPasteControl.h in Headers */, 5FCDD5302B7AC6A300EAF29F /* Branch+Validator.h in Headers */, 5FCDD4A62B7AC6A200EAF29F /* BNCCallbacks.h in Headers */, @@ -1300,61 +1301,6 @@ productReference = 5F22101D2894A0DB00C5B190 /* BranchSDK.framework */; productType = "com.apple.product-type.framework"; }; - 5F22116E2894A9C000C5B190 /* TestHost */ = { - isa = PBXNativeTarget; - buildConfigurationList = 5F2211962894A9C100C5B190 /* Build configuration list for PBXNativeTarget "TestHost" */; - buildPhases = ( - 5F22116B2894A9C000C5B190 /* Sources */, - 5F22116C2894A9C000C5B190 /* Frameworks */, - 5F22116D2894A9C000C5B190 /* Resources */, - 5F73EBFF28ECE65400608601 /* Embed Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - 5F73EBF928ECE65400608601 /* PBXTargetDependency */, - ); - name = TestHost; - productName = TestHost; - productReference = 5F22116F2894A9C000C5B190 /* TestHost.app */; - productType = "com.apple.product-type.application"; - }; - 5F2211832894A9C100C5B190 /* TestHostTests */ = { - isa = PBXNativeTarget; - buildConfigurationList = 5F2211992894A9C100C5B190 /* Build configuration list for PBXNativeTarget "TestHostTests" */; - buildPhases = ( - 5F2211802894A9C100C5B190 /* Sources */, - 5F2211812894A9C100C5B190 /* Frameworks */, - 5F2211822894A9C100C5B190 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - 5F2211862894A9C100C5B190 /* PBXTargetDependency */, - ); - name = TestHostTests; - productName = TestHostTests; - productReference = 5F2211842894A9C100C5B190 /* TestHostTests.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; - }; - 5F22118D2894A9C100C5B190 /* TestHostUITests */ = { - isa = PBXNativeTarget; - buildConfigurationList = 5F22119C2894A9C100C5B190 /* Build configuration list for PBXNativeTarget "TestHostUITests" */; - buildPhases = ( - 5F22118A2894A9C100C5B190 /* Sources */, - 5F22118B2894A9C100C5B190 /* Frameworks */, - 5F22118C2894A9C100C5B190 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - 5F2211902894A9C100C5B190 /* PBXTargetDependency */, - ); - name = TestHostUITests; - productName = TestHostUITests; - productReference = 5F22118E2894A9C100C5B190 /* TestHostUITests.xctest */; - productType = "com.apple.product-type.bundle.ui-testing"; - }; 5F73EBF328ECE65400608601 /* BranchSDK-static */ = { isa = PBXNativeTarget; buildConfigurationList = 5F73EBFC28ECE65400608601 /* Build configuration list for PBXNativeTarget "BranchSDK-static" */; @@ -1391,6 +1337,54 @@ productReference = 5F79038C28B5765D003144CD /* BranchSDK.framework */; productType = "com.apple.product-type.framework"; }; + E7CA74EA2E1B4F75002EFB40 /* BranchSDKTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = E7CA74F42E1B4F75002EFB40 /* Build configuration list for PBXNativeTarget "BranchSDKTests" */; + buildPhases = ( + E7CA74E72E1B4F75002EFB40 /* Sources */, + E7CA74E82E1B4F75002EFB40 /* Frameworks */, + E7CA74E92E1B4F75002EFB40 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + E7CA755A2E1B52F4002EFB40 /* PBXTargetDependency */, + E7CA75A72E1B79CD002EFB40 /* PBXTargetDependency */, + ); + fileSystemSynchronizedGroups = ( + E7CA74EC2E1B4F75002EFB40 /* BranchSDKTests */, + ); + name = BranchSDKTests; + packageProductDependencies = ( + ); + productName = BranchSDKTests; + productReference = E7CA74EB2E1B4F75002EFB40 /* BranchSDKTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + E7CA755E2E1B59F5002EFB40 /* BranchSDKTestsHostApp */ = { + isa = PBXNativeTarget; + buildConfigurationList = E7CA758C2E1B59F7002EFB40 /* Build configuration list for PBXNativeTarget "BranchSDKTestsHostApp" */; + buildPhases = ( + E7CA755B2E1B59F5002EFB40 /* Sources */, + E7CA755C2E1B59F5002EFB40 /* Frameworks */, + E7CA755D2E1B59F5002EFB40 /* Resources */, + E7CA75C02E1B9957002EFB40 /* Embed Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + E7CA75BF2E1B9957002EFB40 /* PBXTargetDependency */, + ); + fileSystemSynchronizedGroups = ( + E7CA75602E1B59F5002EFB40 /* BranchSDKTestsHostApp */, + ); + name = BranchSDKTestsHostApp; + packageProductDependencies = ( + ); + productName = BranchSDKTestsHostApp; + productReference = E7CA755F2E1B59F5002EFB40 /* BranchSDKTestsHostApp.app */; + productType = "com.apple.product-type.application"; + }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ @@ -1408,18 +1402,6 @@ 5F2211672894A90500C5B190 = { CreatedOnToolsVersion = 13.4.1; }; - 5F22116E2894A9C000C5B190 = { - CreatedOnToolsVersion = 13.4.1; - LastSwiftMigration = 1340; - }; - 5F2211832894A9C100C5B190 = { - CreatedOnToolsVersion = 13.4.1; - TestTargetID = 5F22116E2894A9C000C5B190; - }; - 5F22118D2894A9C100C5B190 = { - CreatedOnToolsVersion = 13.4.1; - TestTargetID = 5F22116E2894A9C000C5B190; - }; 5F73EBF328ECE65400608601 = { CreatedOnToolsVersion = 14.0; LastSwiftMigration = 1640; @@ -1437,10 +1419,16 @@ 5FF9DEF428EE7C3600D62DE1 = { CreatedOnToolsVersion = 14.0; }; + E7CA74EA2E1B4F75002EFB40 = { + CreatedOnToolsVersion = 16.4; + TestTargetID = E7CA755E2E1B59F5002EFB40; + }; + E7CA755E2E1B59F5002EFB40 = { + CreatedOnToolsVersion = 16.4; + }; }; }; buildConfigurationList = 5F2210172894A0DB00C5B190 /* Build configuration list for PBXProject "BranchSDK" */; - compatibilityVersion = "Xcode 13.0"; developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( @@ -1448,6 +1436,7 @@ Base, ); mainGroup = 5F2210132894A0DB00C5B190; + preferredProjectObjectVersion = 55; productRefGroup = 5F22101E2894A0DB00C5B190 /* Products */; projectDirPath = ""; projectRoot = ""; @@ -1455,13 +1444,12 @@ 5F22101C2894A0DB00C5B190 /* BranchSDK */, 5F73EBF328ECE65400608601 /* BranchSDK-static */, 5F79038B28B5765D003144CD /* BranchSDK-tvOS */, - 5F22116E2894A9C000C5B190 /* TestHost */, - 5F2211832894A9C100C5B190 /* TestHostTests */, - 5F22118D2894A9C100C5B190 /* TestHostUITests */, 5F2211672894A90500C5B190 /* xcframework */, 5FF9DEEC28EE7C0D00D62DE1 /* xcframework-noidfa */, 5FF9DEF428EE7C3600D62DE1 /* static-xcframework */, 5FF9DEF028EE7C2200D62DE1 /* static-xcframework-noidfa */, + E7CA74EA2E1B4F75002EFB40 /* BranchSDKTests */, + E7CA755E2E1B59F5002EFB40 /* BranchSDKTestsHostApp */, ); }; /* End PBXProject section */ @@ -1475,43 +1463,33 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 5F22116D2894A9C000C5B190 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 5F22117E2894A9C100C5B190 /* LaunchScreen.storyboard in Resources */, - 5F22117B2894A9C100C5B190 /* Assets.xcassets in Resources */, - 5F2211792894A9C000C5B190 /* Main.storyboard in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 5F2211822894A9C100C5B190 /* Resources */ = { + 5F73EBF228ECE65400608601 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + 5FC446662ACCB97100FF1C87 /* PrivacyInfo.xcprivacy in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; - 5F22118C2894A9C100C5B190 /* Resources */ = { + 5F79038A28B5765D003144CD /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + 5FC446672ACCB97200FF1C87 /* PrivacyInfo.xcprivacy in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; - 5F73EBF228ECE65400608601 /* Resources */ = { + E7CA74E92E1B4F75002EFB40 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - 5FC446662ACCB97100FF1C87 /* PrivacyInfo.xcprivacy in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; - 5F79038A28B5765D003144CD /* Resources */ = { + E7CA755D2E1B59F5002EFB40 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - 5FC446672ACCB97200FF1C87 /* PrivacyInfo.xcprivacy in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1673,34 +1651,6 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 5F22116B2894A9C000C5B190 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 5F2211762894A9C000C5B190 /* ViewController.swift in Sources */, - 5F6DD24C2894AF5E00AE9FB0 /* NSURLSession+Branch.m in Sources */, - 5F2211722894A9C000C5B190 /* AppDelegate.swift in Sources */, - 5F2211742894A9C000C5B190 /* SceneDelegate.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 5F2211802894A9C100C5B190 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 5F2211892894A9C100C5B190 /* TestHostTests.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 5F22118A2894A9C100C5B190 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 5F2211952894A9C100C5B190 /* TestHostUITestsLaunchTests.swift in Sources */, - 5F2211932894A9C100C5B190 /* TestHostUITests.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; 5F73EBF028ECE65400608601 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -1851,45 +1801,40 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + E7CA74E72E1B4F75002EFB40 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + E7CA755B2E1B59F5002EFB40 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ - 5F2211862894A9C100C5B190 /* PBXTargetDependency */ = { + E7CA755A2E1B52F4002EFB40 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = 5F22116E2894A9C000C5B190 /* TestHost */; - targetProxy = 5F2211852894A9C100C5B190 /* PBXContainerItemProxy */; + target = 5F22101C2894A0DB00C5B190 /* BranchSDK */; + targetProxy = E7CA75592E1B52F4002EFB40 /* PBXContainerItemProxy */; }; - 5F2211902894A9C100C5B190 /* PBXTargetDependency */ = { + E7CA75A72E1B79CD002EFB40 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = 5F22116E2894A9C000C5B190 /* TestHost */; - targetProxy = 5F22118F2894A9C100C5B190 /* PBXContainerItemProxy */; + target = E7CA755E2E1B59F5002EFB40 /* BranchSDKTestsHostApp */; + targetProxy = E7CA75A62E1B79CD002EFB40 /* PBXContainerItemProxy */; }; - 5F73EBF928ECE65400608601 /* PBXTargetDependency */ = { + E7CA75BF2E1B9957002EFB40 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = 5F73EBF328ECE65400608601 /* BranchSDK-static */; - targetProxy = 5F73EBF828ECE65400608601 /* PBXContainerItemProxy */; + target = 5F22101C2894A0DB00C5B190 /* BranchSDK */; + targetProxy = E7CA75BE2E1B9957002EFB40 /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ -/* Begin PBXVariantGroup section */ - 5F2211772894A9C000C5B190 /* Main.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 5F2211782894A9C000C5B190 /* Base */, - ); - name = Main.storyboard; - sourceTree = ""; - }; - 5F22117C2894A9C100C5B190 /* LaunchScreen.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 5F22117D2894A9C100C5B190 /* Base */, - ); - name = LaunchScreen.storyboard; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - /* Begin XCBuildConfiguration section */ 5F2210222894A0DB00C5B190 /* Debug */ = { isa = XCBuildConfiguration; @@ -2106,156 +2051,6 @@ }; name = Release; }; - 5F2211972894A9C100C5B190 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; - CLANG_ENABLE_MODULES = YES; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_TEAM = R63EM248DP; - GENERATE_INFOPLIST_FILE = YES; - INFOPLIST_FILE = TestHost/Info.plist; - INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; - INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; - INFOPLIST_KEY_UIMainStoryboardFile = Main; - INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; - INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; - IPHONEOS_DEPLOYMENT_TARGET = 15.5; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = io.branch.TestHost; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; - SWIFT_EMIT_LOC_STRINGS = YES; - SWIFT_OBJC_BRIDGING_HEADER = "TestHost/TestHost-Bridging-Header.h"; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 5F2211982894A9C100C5B190 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; - CLANG_ENABLE_MODULES = YES; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_TEAM = R63EM248DP; - GENERATE_INFOPLIST_FILE = YES; - INFOPLIST_FILE = TestHost/Info.plist; - INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; - INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; - INFOPLIST_KEY_UIMainStoryboardFile = Main; - INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; - INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; - IPHONEOS_DEPLOYMENT_TARGET = 15.5; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = io.branch.TestHost; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_COMPILATION_MODE = wholemodule; - SWIFT_EMIT_LOC_STRINGS = YES; - SWIFT_OBJC_BRIDGING_HEADER = "TestHost/TestHost-Bridging-Header.h"; - SWIFT_OPTIMIZATION_LEVEL = "-O"; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Release; - }; - 5F22119A2894A9C100C5B190 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; - BUNDLE_LOADER = "$(TEST_HOST)"; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_TEAM = R63EM248DP; - GENERATE_INFOPLIST_FILE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 15.5; - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = io.branch.TestHostTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; - SWIFT_EMIT_LOC_STRINGS = NO; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/TestHost.app/TestHost"; - }; - name = Debug; - }; - 5F22119B2894A9C100C5B190 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; - BUNDLE_LOADER = "$(TEST_HOST)"; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_TEAM = R63EM248DP; - GENERATE_INFOPLIST_FILE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 15.5; - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = io.branch.TestHostTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_COMPILATION_MODE = wholemodule; - SWIFT_EMIT_LOC_STRINGS = NO; - SWIFT_OPTIMIZATION_LEVEL = "-O"; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/TestHost.app/TestHost"; - }; - name = Release; - }; - 5F22119D2894A9C100C5B190 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_TEAM = R63EM248DP; - GENERATE_INFOPLIST_FILE = YES; - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = io.branch.TestHostUITests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; - SWIFT_EMIT_LOC_STRINGS = NO; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - TEST_TARGET_NAME = TestHost; - }; - name = Debug; - }; - 5F22119E2894A9C100C5B190 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_TEAM = R63EM248DP; - GENERATE_INFOPLIST_FILE = YES; - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = io.branch.TestHostUITests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_COMPILATION_MODE = wholemodule; - SWIFT_EMIT_LOC_STRINGS = NO; - SWIFT_OPTIMIZATION_LEVEL = "-O"; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - TEST_TARGET_NAME = TestHost; - }; - name = Release; - }; 5F73EBFD28ECE65400608601 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -2479,6 +2274,123 @@ }; name = Release; }; + E7CA74F22E1B4F75002EFB40 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + BUNDLE_LOADER = "$(TEST_HOST)"; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = R63EM248DP; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GENERATE_INFOPLIST_FILE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 18.5; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = branch.BranchSDKTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_VERSION = 6.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/BranchSDKTestsHostApp.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/BranchSDKTestsHostApp"; + }; + name = Debug; + }; + E7CA74F32E1B4F75002EFB40 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + BUNDLE_LOADER = "$(TEST_HOST)"; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = R63EM248DP; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GENERATE_INFOPLIST_FILE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 18.5; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = branch.BranchSDKTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_VERSION = 6.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/BranchSDKTestsHostApp.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/BranchSDKTestsHostApp"; + }; + name = Release; + }; + E7CA758D2E1B59F7002EFB40 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = R63EM248DP; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = BranchSDKTestsHostApp/Info.plist; + INFOPLIST_KEY_CFBundleDisplayName = BranchSDKTestsHostApp; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; + INFOPLIST_KEY_UIMainStoryboardFile = Main; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + IPHONEOS_DEPLOYMENT_TARGET = 18.5; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = branch.BranchSDKTestsHostApp; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + E7CA758E2E1B59F7002EFB40 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CODE_SIGN_ENTITLEMENTS = BranchSDKTestsHostApp/BranchSDKTestsHostAppRelease.entitlements; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = R63EM248DP; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = BranchSDKTestsHostApp/Info.plist; + INFOPLIST_KEY_CFBundleDisplayName = BranchSDKTestsHostApp; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; + INFOPLIST_KEY_UIMainStoryboardFile = Main; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + IPHONEOS_DEPLOYMENT_TARGET = 18.5; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = branch.BranchSDKTestsHostApp; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ @@ -2509,33 +2421,6 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 5F2211962894A9C100C5B190 /* Build configuration list for PBXNativeTarget "TestHost" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 5F2211972894A9C100C5B190 /* Debug */, - 5F2211982894A9C100C5B190 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 5F2211992894A9C100C5B190 /* Build configuration list for PBXNativeTarget "TestHostTests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 5F22119A2894A9C100C5B190 /* Debug */, - 5F22119B2894A9C100C5B190 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 5F22119C2894A9C100C5B190 /* Build configuration list for PBXNativeTarget "TestHostUITests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 5F22119D2894A9C100C5B190 /* Debug */, - 5F22119E2894A9C100C5B190 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; 5F73EBFC28ECE65400608601 /* Build configuration list for PBXNativeTarget "BranchSDK-static" */ = { isa = XCConfigurationList; buildConfigurations = ( @@ -2581,6 +2466,24 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + E7CA74F42E1B4F75002EFB40 /* Build configuration list for PBXNativeTarget "BranchSDKTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + E7CA74F22E1B4F75002EFB40 /* Debug */, + E7CA74F32E1B4F75002EFB40 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + E7CA758C2E1B59F7002EFB40 /* Build configuration list for PBXNativeTarget "BranchSDKTestsHostApp" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + E7CA758D2E1B59F7002EFB40 /* Debug */, + E7CA758E2E1B59F7002EFB40 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; /* End XCConfigurationList section */ }; rootObject = 5F2210142894A0DB00C5B190 /* Project object */; diff --git a/TestDeepLinking/TestDeepLinking.xcodeproj/xcshareddata/xcschemes/TestDeepLinking.xcscheme b/BranchSDK.xcodeproj/xcshareddata/xcschemes/BranchSDKTests.xcscheme similarity index 56% rename from TestDeepLinking/TestDeepLinking.xcodeproj/xcshareddata/xcschemes/TestDeepLinking.xcscheme rename to BranchSDK.xcodeproj/xcshareddata/xcschemes/BranchSDKTests.xcscheme index fe40949b8..f32d4b149 100644 --- a/TestDeepLinking/TestDeepLinking.xcodeproj/xcshareddata/xcschemes/TestDeepLinking.xcscheme +++ b/BranchSDK.xcodeproj/xcshareddata/xcschemes/BranchSDKTests.xcscheme @@ -1,10 +1,11 @@ + LastUpgradeVersion = "1640" + version = "2.1"> + buildImplicitDependencies = "YES" + buildArchitectures = "Automatic"> + BlueprintIdentifier = "E7CA755E2E1B59F5002EFB40" + BuildableName = "BranchSDKTestsHostApp.app" + BlueprintName = "BranchSDKTestsHostApp" + ReferencedContainer = "container:BranchSDK.xcodeproj"> + + + + + skipped = "NO" + parallelizable = "YES"> - - - - + BlueprintIdentifier = "E7CA74EA2E1B4F75002EFB40" + BuildableName = "BranchSDKTests.xctest" + BlueprintName = "BranchSDKTests" + ReferencedContainer = "container:BranchSDK.xcodeproj"> @@ -70,10 +72,10 @@ runnableDebuggingMode = "0"> + BlueprintIdentifier = "E7CA755E2E1B59F5002EFB40" + BuildableName = "BranchSDKTestsHostApp.app" + BlueprintName = "BranchSDKTestsHostApp" + ReferencedContainer = "container:BranchSDK.xcodeproj"> @@ -83,16 +85,15 @@ savedToolIdentifier = "" useCustomWorkingDirectory = "NO" debugDocumentVersioning = "YES"> - + + BlueprintIdentifier = "E7CA755E2E1B59F5002EFB40" + BuildableName = "BranchSDKTestsHostApp.app" + BlueprintName = "BranchSDKTestsHostApp" + ReferencedContainer = "container:BranchSDK.xcodeproj"> - + diff --git a/BranchSDKTests/BNCAPIServerTest.m b/BranchSDKTests/BNCAPIServerTest.m new file mode 100644 index 000000000..eb9165001 --- /dev/null +++ b/BranchSDKTests/BNCAPIServerTest.m @@ -0,0 +1,508 @@ +// +// BNCAPIServerTest.m +// Branch-SDK-Tests +// +// Created by Nidhi Dixit on 9/6/23. +// Copyright © 2023 Branch, Inc. All rights reserved. +// + +#import +#import "BNCServerAPI.h" +#import "BNCSystemObserver.h" +#import "BNCConfig.h" +#import "BranchConstants.h" +#import "Branch.h" + +@interface BNCAPIServerTest : XCTestCase + +@end + +@implementation BNCAPIServerTest + +- (void)testInstallServiceURL { + BNCServerAPI *serverAPI = [BNCServerAPI new]; + serverAPI.automaticallyEnableTrackingDomain = NO; + + NSString *url = [serverAPI installServiceURL]; + NSString *expectedUrlStr = @"https://api3.branch.io/v1/install"; + + XCTAssertTrue([url isEqualToString:expectedUrlStr]); +} + +- (void)testOpenServiceURL { + BNCServerAPI *serverAPI = [BNCServerAPI new]; + serverAPI.automaticallyEnableTrackingDomain = NO; + + NSString *url = [serverAPI openServiceURL]; + NSString *expectedUrlStr = @"https://api3.branch.io/v1/open"; + + XCTAssertTrue([url isEqualToString:expectedUrlStr]); +} + +- (void)testStandardEventServiceURL { + BNCServerAPI *serverAPI = [BNCServerAPI new]; + serverAPI.automaticallyEnableTrackingDomain = NO; + + NSString *url = [serverAPI standardEventServiceURL]; + NSString *expectedUrlStr = @"https://api3.branch.io/v2/event/standard"; + + XCTAssertTrue([url isEqualToString:expectedUrlStr]); +} + +- (void)testCustomEventServiceURL { + BNCServerAPI *serverAPI = [BNCServerAPI new]; + serverAPI.automaticallyEnableTrackingDomain = NO; + + NSString *url = [serverAPI customEventServiceURL]; + NSString *expectedUrlStr = @"https://api3.branch.io/v2/event/custom"; + + XCTAssertTrue([url isEqualToString:expectedUrlStr]); +} + +- (void)testLinkServiceURL { + BNCServerAPI *serverAPI = [BNCServerAPI new]; + serverAPI.automaticallyEnableTrackingDomain = NO; + + NSString *url = [serverAPI linkServiceURL]; + NSString *expectedUrlStr = @"https://api3.branch.io/v1/url"; + + XCTAssertTrue([url isEqualToString:expectedUrlStr]); +} + +- (void)testQRCodeServiceURL { + BNCServerAPI *serverAPI = [BNCServerAPI new]; + serverAPI.automaticallyEnableTrackingDomain = NO; + + NSString *url = [serverAPI qrcodeServiceURL]; + NSString *expectedUrlStr = @"https://api3.branch.io/v1/qr-code"; + + XCTAssertTrue([url isEqualToString:expectedUrlStr]); +} + +- (void)testLATDServiceURL { + BNCServerAPI *serverAPI = [BNCServerAPI new]; + serverAPI.automaticallyEnableTrackingDomain = NO; + + NSString *url = [serverAPI latdServiceURL]; + NSString *expectedUrlStr = @"https://api3.branch.io/v1/cpid/latd"; + + XCTAssertTrue([url isEqualToString:expectedUrlStr]); +} + +- (void)testValidationServiceURL { + BNCServerAPI *serverAPI = [BNCServerAPI new]; + serverAPI.automaticallyEnableTrackingDomain = NO; + + NSString *url = [serverAPI validationServiceURL]; + NSString *expectedUrlPrefix= @"https://api3.branch.io/v1/app-link-settings"; + + XCTAssertTrue([url hasPrefix:expectedUrlPrefix]); +} + +- (void)testInstallServiceURL_Tracking { + BNCServerAPI *serverAPI = [BNCServerAPI new]; + serverAPI.automaticallyEnableTrackingDomain = NO; + serverAPI.useTrackingDomain = YES; + + NSString *url = [serverAPI installServiceURL]; + NSString *expectedUrlStr = @"https://api-safetrack.branch.io/v1/install"; + + XCTAssertTrue([url isEqualToString:expectedUrlStr]); +} + +- (void)testOpenServiceURL_Tracking { + BNCServerAPI *serverAPI = [BNCServerAPI new]; + serverAPI.automaticallyEnableTrackingDomain = NO; + serverAPI.useTrackingDomain = YES; + + NSString *url = [serverAPI openServiceURL]; + NSString *expectedUrlStr = @"https://api-safetrack.branch.io/v1/open"; + + XCTAssertTrue([url isEqualToString:expectedUrlStr]); +} + +- (void)testStandardEventServiceURL_Tracking { + BNCServerAPI *serverAPI = [BNCServerAPI new]; + serverAPI.automaticallyEnableTrackingDomain = NO; + serverAPI.useTrackingDomain = YES; + + NSString *url = [serverAPI standardEventServiceURL]; + NSString *expectedUrlStr = @"https://api-safetrack.branch.io/v2/event/standard"; + + XCTAssertTrue([url isEqualToString:expectedUrlStr]); +} + +- (void)testCustomEventServiceURL_Tracking { + BNCServerAPI *serverAPI = [BNCServerAPI new]; + serverAPI.automaticallyEnableTrackingDomain = NO; + serverAPI.useTrackingDomain = YES; + + NSString *url = [serverAPI customEventServiceURL]; + NSString *expectedUrlStr = @"https://api-safetrack.branch.io/v2/event/custom"; + + XCTAssertTrue([url isEqualToString:expectedUrlStr]); +} + +- (void)testLinkServiceURL_Tracking { + BNCServerAPI *serverAPI = [BNCServerAPI new]; + serverAPI.automaticallyEnableTrackingDomain = NO; + serverAPI.useTrackingDomain = YES; + + NSString *url = [serverAPI linkServiceURL]; + NSString *expectedUrlStr = @"https://api3.branch.io/v1/url"; + + XCTAssertTrue([url isEqualToString:expectedUrlStr]); +} + +- (void)testQRCodeServiceURL_Tracking { + BNCServerAPI *serverAPI = [BNCServerAPI new]; + serverAPI.automaticallyEnableTrackingDomain = NO; + serverAPI.useTrackingDomain = YES; + + NSString *url = [serverAPI qrcodeServiceURL]; + NSString *expectedUrlStr = @"https://api3.branch.io/v1/qr-code"; + + XCTAssertTrue([url isEqualToString:expectedUrlStr]); +} + +- (void)testLATDServiceURL_Tracking { + BNCServerAPI *serverAPI = [BNCServerAPI new]; + serverAPI.automaticallyEnableTrackingDomain = NO; + serverAPI.useTrackingDomain = YES; + + NSString *url = [serverAPI latdServiceURL]; + NSString *expectedUrlStr = @"https://api3.branch.io/v1/cpid/latd"; + + XCTAssertTrue([url isEqualToString:expectedUrlStr]); +} + +- (void)testValidationServiceURL_Tracking { + BNCServerAPI *serverAPI = [BNCServerAPI new]; + serverAPI.automaticallyEnableTrackingDomain = NO; + serverAPI.useTrackingDomain = YES; + + NSString *url = [serverAPI validationServiceURL]; + NSString *expectedUrlPrefix= @"https://api3.branch.io/v1/app-link-settings"; + + XCTAssertTrue([url hasPrefix:expectedUrlPrefix]); +} + +- (void)testInstallServiceURL_EU { + BNCServerAPI *serverAPI = [BNCServerAPI new]; + serverAPI.automaticallyEnableTrackingDomain = NO; + serverAPI.useEUServers = YES; + + NSString *url = [serverAPI installServiceURL]; + NSString *expectedUrlStr = @"https://api3-eu.branch.io/v1/install"; + + XCTAssertTrue([url isEqualToString:expectedUrlStr]); +} + +- (void)testOpenServiceURL_EU { + BNCServerAPI *serverAPI = [BNCServerAPI new]; + serverAPI.automaticallyEnableTrackingDomain = NO; + serverAPI.useEUServers = YES; + + NSString *url = [serverAPI openServiceURL]; + NSString *expectedUrlStr = @"https://api3-eu.branch.io/v1/open"; + + XCTAssertTrue([url isEqualToString:expectedUrlStr]); +} + +- (void)testStandardEventServiceURL_EU { + BNCServerAPI *serverAPI = [BNCServerAPI new]; + serverAPI.automaticallyEnableTrackingDomain = NO; + serverAPI.useEUServers = YES; + + NSString *url = [serverAPI standardEventServiceURL]; + NSString *expectedUrlStr = @"https://api3-eu.branch.io/v2/event/standard"; + + XCTAssertTrue([url isEqualToString:expectedUrlStr]); +} + +- (void)testCustomEventServiceURL_EU { + BNCServerAPI *serverAPI = [BNCServerAPI new]; + serverAPI.automaticallyEnableTrackingDomain = NO; + serverAPI.useEUServers = YES; + + NSString *url = [serverAPI customEventServiceURL]; + NSString *expectedUrlStr = @"https://api3-eu.branch.io/v2/event/custom"; + + XCTAssertTrue([url isEqualToString:expectedUrlStr]); +} + +- (void)testLinkServiceURL_EU { + BNCServerAPI *serverAPI = [BNCServerAPI new]; + serverAPI.automaticallyEnableTrackingDomain = NO; + serverAPI.useEUServers = YES; + + NSString *url = [serverAPI linkServiceURL]; + NSString *expectedUrlStr = @"https://api3-eu.branch.io/v1/url"; + + XCTAssertTrue([url isEqualToString:expectedUrlStr]); +} + +- (void)testQRCodeServiceURL_EU { + BNCServerAPI *serverAPI = [BNCServerAPI new]; + serverAPI.automaticallyEnableTrackingDomain = NO; + serverAPI.useEUServers = YES; + + NSString *url = [serverAPI qrcodeServiceURL]; + NSString *expectedUrlStr = @"https://api3-eu.branch.io/v1/qr-code"; + + XCTAssertTrue([url isEqualToString:expectedUrlStr]); +} + +- (void)testLATDServiceURL_EU { + BNCServerAPI *serverAPI = [BNCServerAPI new]; + serverAPI.automaticallyEnableTrackingDomain = NO; + serverAPI.useEUServers = YES; + + NSString *url = [serverAPI latdServiceURL]; + NSString *expectedUrlStr = @"https://api3-eu.branch.io/v1/cpid/latd"; + + XCTAssertTrue([url isEqualToString:expectedUrlStr]); +} + +- (void)testValidationServiceURL_EU { + BNCServerAPI *serverAPI = [BNCServerAPI new]; + serverAPI.automaticallyEnableTrackingDomain = NO; + serverAPI.useEUServers = YES; + + NSString *url = [serverAPI validationServiceURL]; + NSString *expectedUrlPrefix= @"https://api3-eu.branch.io/v1/app-link-settings"; + + XCTAssertTrue([url hasPrefix:expectedUrlPrefix]); +} + +- (void)testInstallServiceURL_EUTracking { + BNCServerAPI *serverAPI = [BNCServerAPI new]; + serverAPI.automaticallyEnableTrackingDomain = NO; + serverAPI.useEUServers = YES; + serverAPI.useTrackingDomain = YES; + + NSString *url = [serverAPI installServiceURL]; + NSString *expectedUrlStr = @"https://api-safetrack-eu.branch.io/v1/install"; + + XCTAssertTrue([url isEqualToString:expectedUrlStr]); +} + +- (void)testOpenServiceURL_EUTracking { + BNCServerAPI *serverAPI = [BNCServerAPI new]; + serverAPI.automaticallyEnableTrackingDomain = NO; + serverAPI.useEUServers = YES; + serverAPI.useTrackingDomain = YES; + + NSString *url = [serverAPI openServiceURL]; + NSString *expectedUrlStr = @"https://api-safetrack-eu.branch.io/v1/open"; + + XCTAssertTrue([url isEqualToString:expectedUrlStr]); +} + +- (void)testStandardEventServiceURL_EUTracking { + BNCServerAPI *serverAPI = [BNCServerAPI new]; + serverAPI.automaticallyEnableTrackingDomain = NO; + serverAPI.useEUServers = YES; + serverAPI.useTrackingDomain = YES; + + NSString *url = [serverAPI standardEventServiceURL]; + NSString *expectedUrlStr = @"https://api-safetrack-eu.branch.io/v2/event/standard"; + + XCTAssertTrue([url isEqualToString:expectedUrlStr]); +} + +- (void)testCustomEventServiceURL_EUTracking { + BNCServerAPI *serverAPI = [BNCServerAPI new]; + serverAPI.automaticallyEnableTrackingDomain = NO; + serverAPI.useEUServers = YES; + serverAPI.useTrackingDomain = YES; + + NSString *url = [serverAPI customEventServiceURL]; + NSString *expectedUrlStr = @"https://api-safetrack-eu.branch.io/v2/event/custom"; + + XCTAssertTrue([url isEqualToString:expectedUrlStr]); +} + +- (void)testLinkServiceURL_EUTracking { + BNCServerAPI *serverAPI = [BNCServerAPI new]; + serverAPI.automaticallyEnableTrackingDomain = NO; + serverAPI.useEUServers = YES; + serverAPI.useTrackingDomain = YES; + + NSString *url = [serverAPI linkServiceURL]; + NSString *expectedUrlStr = @"https://api3-eu.branch.io/v1/url"; + + XCTAssertTrue([url isEqualToString:expectedUrlStr]); +} + +- (void)testQRCodeServiceURL_EUTracking { + BNCServerAPI *serverAPI = [BNCServerAPI new]; + serverAPI.automaticallyEnableTrackingDomain = NO; + serverAPI.useEUServers = YES; + serverAPI.useTrackingDomain = YES; + + NSString *url = [serverAPI qrcodeServiceURL]; + NSString *expectedUrlStr = @"https://api3-eu.branch.io/v1/qr-code"; + + XCTAssertTrue([url isEqualToString:expectedUrlStr]); +} + +- (void)testLATDServiceURL_EUTracking { + BNCServerAPI *serverAPI = [BNCServerAPI new]; + serverAPI.automaticallyEnableTrackingDomain = NO; + serverAPI.useEUServers = YES; + serverAPI.useTrackingDomain = YES; + + NSString *url = [serverAPI latdServiceURL]; + NSString *expectedUrlStr = @"https://api3-eu.branch.io/v1/cpid/latd"; + + XCTAssertTrue([url isEqualToString:expectedUrlStr]); +} + +- (void)testValidationServiceURL_EUTracking { + BNCServerAPI *serverAPI = [BNCServerAPI new]; + serverAPI.automaticallyEnableTrackingDomain = NO; + serverAPI.useEUServers = YES; + serverAPI.useTrackingDomain = YES; + + NSString *url = [serverAPI validationServiceURL]; + NSString *expectedUrlPrefix= @"https://api3-eu.branch.io/v1/app-link-settings"; + + XCTAssertTrue([url hasPrefix:expectedUrlPrefix]); +} + +- (void)testDefaultAPIURL { + BNCServerAPI *serverAPI = [BNCServerAPI new]; + XCTAssertNil(serverAPI.customAPIURL); + + NSString *storedUrl = [[BNCServerAPI sharedInstance] installServiceURL]; + NSString *expectedUrl = [BNC_API_URL stringByAppendingString: @"/v1/install"]; + XCTAssertEqualObjects(storedUrl, expectedUrl); +} + +- (void)testSetAPIURL_Example { + NSString *url = @"https://www.example.com"; + [Branch setAPIUrl:url]; + + NSString *storedUrl = [[BNCServerAPI sharedInstance] installServiceURL]; + NSString *expectedUrl = [url stringByAppendingString: @"/v1/install"]; + XCTAssertEqualObjects(storedUrl, expectedUrl); + + [Branch setAPIUrl:BNC_API_URL]; +} + +- (void)testSetAPIURL_InvalidHttp { + NSString *url = @"Invalid://www.example.com"; + [Branch setAPIUrl:url]; + + NSString *storedUrl = [[BNCServerAPI sharedInstance] installServiceURL]; + NSString *expectedUrl = [BNC_API_URL stringByAppendingString: @"/v1/install"]; + XCTAssertEqualObjects(storedUrl, expectedUrl); +} + +- (void)testSetAPIURL_InvalidEmpty { + NSString *url = @""; + [Branch setAPIUrl:url]; + + NSString *storedUrl = [[BNCServerAPI sharedInstance] installServiceURL]; + NSString *expectedUrl = [BNC_API_URL stringByAppendingString: @"/v1/install"]; + XCTAssertEqualObjects(storedUrl, expectedUrl); +} + + +- (void)testSetSafeTrackServiceURLWithUserTrackingDomain { + NSString *url = @"https://links.toTestDomain.com"; + NSString *safeTrackUrl = @"https://links.toTestDomain-safeTrack.com"; + + [Branch setAPIUrl:url]; + [Branch setSafetrackAPIURL:safeTrackUrl]; + + BNCServerAPI *serverAPI = [BNCServerAPI sharedInstance]; + serverAPI.automaticallyEnableTrackingDomain = NO; + serverAPI.useTrackingDomain = YES; + + NSString *storedUrl = [[BNCServerAPI sharedInstance] installServiceURL]; + NSString *expectedUrl = @"https://links.toTestDomain-safeTrack.com/v1/install"; + XCTAssertEqualObjects(storedUrl, expectedUrl); + + storedUrl = [[BNCServerAPI sharedInstance] openServiceURL]; + expectedUrl = @"https://links.toTestDomain-safeTrack.com/v1/open"; + XCTAssertEqualObjects(storedUrl, expectedUrl); + + storedUrl = [[BNCServerAPI sharedInstance] standardEventServiceURL]; + expectedUrl = @"https://links.toTestDomain-safeTrack.com/v2/event/standard"; + XCTAssertEqualObjects(storedUrl, expectedUrl); + + storedUrl = [[BNCServerAPI sharedInstance] customEventServiceURL]; + expectedUrl = @"https://links.toTestDomain-safeTrack.com/v2/event/custom"; + XCTAssertEqualObjects(storedUrl, expectedUrl); + + storedUrl = [[BNCServerAPI sharedInstance] linkServiceURL]; + expectedUrl = @"https://links.toTestDomain.com/v1/url"; + XCTAssertEqualObjects(storedUrl, expectedUrl); + + storedUrl = [[BNCServerAPI sharedInstance] qrcodeServiceURL]; + expectedUrl = @"https://links.toTestDomain.com/v1/qr-code"; + XCTAssertEqualObjects(storedUrl, expectedUrl); + + storedUrl = [[BNCServerAPI sharedInstance] latdServiceURL]; + expectedUrl = @"https://links.toTestDomain.com/v1/cpid/latd"; + XCTAssertEqualObjects(storedUrl, expectedUrl); + + + [BNCServerAPI sharedInstance].useTrackingDomain = NO; + [BNCServerAPI sharedInstance].useEUServers = NO; + [BNCServerAPI sharedInstance].automaticallyEnableTrackingDomain = YES; + [BNCServerAPI sharedInstance].customAPIURL = nil; + [BNCServerAPI sharedInstance].customSafeTrackAPIURL = nil; + +} + +- (void)testSetSafeTrackServiceURLWithOutUserTrackingDomain { + NSString *url = @"https://links.toTestDomain.com"; + NSString *safeTrackUrl = @"https://links.toTestDomain-safeTrack.com"; + + [Branch setAPIUrl:url]; + [Branch setSafetrackAPIURL:safeTrackUrl]; + + BNCServerAPI *serverAPI = [BNCServerAPI sharedInstance]; + serverAPI.automaticallyEnableTrackingDomain = NO; + serverAPI.useTrackingDomain = NO; + + NSString *storedUrl = [[BNCServerAPI sharedInstance] installServiceURL]; + NSString *expectedUrl = @"https://links.toTestDomain.com/v1/install"; + XCTAssertEqualObjects(storedUrl, expectedUrl); + + storedUrl = [[BNCServerAPI sharedInstance] openServiceURL]; + expectedUrl = @"https://links.toTestDomain.com/v1/open"; + XCTAssertEqualObjects(storedUrl, expectedUrl); + + storedUrl = [[BNCServerAPI sharedInstance] standardEventServiceURL]; + expectedUrl = @"https://links.toTestDomain.com/v2/event/standard"; + XCTAssertEqualObjects(storedUrl, expectedUrl); + + storedUrl = [[BNCServerAPI sharedInstance] customEventServiceURL]; + expectedUrl = @"https://links.toTestDomain.com/v2/event/custom"; + XCTAssertEqualObjects(storedUrl, expectedUrl); + + storedUrl = [[BNCServerAPI sharedInstance] linkServiceURL]; + expectedUrl = @"https://links.toTestDomain.com/v1/url"; + XCTAssertEqualObjects(storedUrl, expectedUrl); + + storedUrl = [[BNCServerAPI sharedInstance] qrcodeServiceURL]; + expectedUrl = @"https://links.toTestDomain.com/v1/qr-code"; + XCTAssertEqualObjects(storedUrl, expectedUrl); + + storedUrl = [[BNCServerAPI sharedInstance] latdServiceURL]; + expectedUrl = @"https://links.toTestDomain.com/v1/cpid/latd"; + XCTAssertEqualObjects(storedUrl, expectedUrl); + + [BNCServerAPI sharedInstance].useTrackingDomain = NO; + [BNCServerAPI sharedInstance].useEUServers = NO; + [BNCServerAPI sharedInstance].automaticallyEnableTrackingDomain = YES; + [BNCServerAPI sharedInstance].customAPIURL = nil; + [BNCServerAPI sharedInstance].customSafeTrackAPIURL = nil; + +} + +@end diff --git a/BranchSDKTests/BNCAppleReceiptTests.m b/BranchSDKTests/BNCAppleReceiptTests.m new file mode 100644 index 000000000..faff0ef96 --- /dev/null +++ b/BranchSDKTests/BNCAppleReceiptTests.m @@ -0,0 +1,33 @@ +// +// BNCAppleReceiptTests.m +// Branch-SDK-Tests +// +// Created by Ernest Cho on 7/15/19. +// Copyright © 2019 Branch, Inc. All rights reserved. +// + +#import +#import "BNCAppleReceipt.h" + +@interface BNCAppleReceiptTests : XCTestCase + +@end + +@implementation BNCAppleReceiptTests + +- (void)setUp { + +} + +- (void)tearDown { + +} + +- (void)testReceiptOnSimulator { + BNCAppleReceipt *receipt = [[BNCAppleReceipt alloc] init]; + // Appears the simulator can have a receipt + //XCTAssertNil([receipt installReceipt]); + XCTAssertFalse([receipt isTestFlight]); +} + +@end diff --git a/BranchSDKTests/BNCApplicationTests.m b/BranchSDKTests/BNCApplicationTests.m new file mode 100644 index 000000000..147a2a665 --- /dev/null +++ b/BranchSDKTests/BNCApplicationTests.m @@ -0,0 +1,75 @@ +// +// BNCApplication.Test.m +// Branch-SDK-Tests +// +// Created by Edward on 1/10/18. +// Copyright © 2018 Branch, Inc. All rights reserved. +// + +#import +#import "BNCApplication.h" +#import "BNCKeyChain.h" + +@interface BNCApplicationTests : XCTestCase +@end + +@implementation BNCApplicationTests + +- (void)setUp { + // Put setup code here. This method is called before the invocation of each test method in the class. +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. +} + +- (void)testApplication { + // Test general info: + + if ([UIApplication sharedApplication] == nil) { + NSLog(@"No host application for BNCApplication testing!"); + return; + } + + BNCApplication *application = [BNCApplication currentApplication]; + XCTAssertEqualObjects(application.bundleID, @"branch.BranchSDKTestsHostApp"); + XCTAssertEqualObjects(application.displayName, @"BranchSDKTestsHostApp"); + XCTAssertEqualObjects(application.shortDisplayName, @"BranchSDKTestsHostApp"); + XCTAssertEqualObjects(application.displayVersionString, @"1.0"); + XCTAssertEqualObjects(application.versionString, @"1"); +} + +- (void) testAppDates { + // App dates. Not a great test but tests basic function: + + if ([UIApplication sharedApplication] == nil) { + NSLog(@"No host application for BNCApplication testing!"); + return; + } + + NSTimeInterval const kOneYearAgo = -365.0 * 24.0 * 60.0 * 60.0; + + BNCApplication *application = [BNCApplication currentApplication]; + XCTAssertTrue(application.firstInstallDate && [application.firstInstallDate timeIntervalSinceNow] > kOneYearAgo); + XCTAssertTrue(application.firstInstallBuildDate && [application.firstInstallBuildDate timeIntervalSinceNow] > kOneYearAgo); + XCTAssertTrue(application.currentInstallDate && [application.currentInstallDate timeIntervalSinceNow] > kOneYearAgo); + XCTAssertTrue(application.currentBuildDate && [application.currentBuildDate timeIntervalSinceNow] > kOneYearAgo); + + NSString*const kBranchKeychainService = @"BranchKeychainService"; + NSString*const kBranchKeychainFirstBuildKey = @"BranchKeychainFirstBuild"; + NSString*const kBranchKeychainFirstInstalldKey = @"BranchKeychainFirstInstall"; + + NSDate * firstBuildDate = + [BNCKeyChain retrieveDateForService:kBranchKeychainService + key:kBranchKeychainFirstBuildKey + error:nil]; + XCTAssertEqualObjects(application.firstInstallBuildDate, firstBuildDate); + + NSDate * firstInstallDate = + [BNCKeyChain retrieveDateForService:kBranchKeychainService + key:kBranchKeychainFirstInstalldKey + error:nil]; + XCTAssertEqualObjects(application.firstInstallDate, firstInstallDate); +} + +@end diff --git a/BranchSDKTests/BNCCallbackMapTests.m b/BranchSDKTests/BNCCallbackMapTests.m new file mode 100644 index 000000000..4d5482499 --- /dev/null +++ b/BranchSDKTests/BNCCallbackMapTests.m @@ -0,0 +1,134 @@ +// +// BNCCallbackMapTests.m +// Branch-SDK-Tests +// +// Created by Ernest Cho on 2/25/20. +// Copyright © 2020 Branch, Inc. All rights reserved. +// + +#import +#import "BNCCallbackMap.h" +#import "NSError+Branch.h" + +// expose private storage object for state checks +@interface BNCCallbackMap() +@property (nonatomic, strong, readwrite) NSMapTable *callbacks; +@end + +@interface BNCCallbackMapTests : XCTestCase + +@end + +@implementation BNCCallbackMapTests + +- (void)setUp { + // Put setup code here. This method is called before the invocation of each test method in the class. +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. +} + +- (void)testRequestSaveAndCallback { + BNCCallbackMap *map = [BNCCallbackMap new]; + + __block BOOL successResult = NO; + __block NSError *errorResult = nil; + + // store a request and callback block + BNCServerRequest *request = [BNCServerRequest new]; + [map storeRequest:request withCompletion:^(BOOL success, NSError * _Nullable error) { + successResult = success; + errorResult = error; + }]; + + // confirm there's one entry + XCTAssert([map containsRequest:request] != NO); + XCTAssert(map.callbacks.count == 1); + + // call callback + [map callCompletionForRequest:request withSuccessStatus:YES error:nil]; + + // check if variable was updated + XCTAssertTrue(successResult); + XCTAssertNil(errorResult); +} + +- (void)testRequestSaveAndCallbackWithError { + BNCCallbackMap *map = [BNCCallbackMap new]; + + __block BOOL successResult = YES; + __block NSError *errorResult = nil; + + // store a request and callback block + BNCServerRequest *request = [BNCServerRequest new]; + [map storeRequest:request withCompletion:^(BOOL success, NSError * _Nullable error) { + successResult = success; + errorResult = error; + }]; + + // confirm there's one entry + XCTAssert([map containsRequest:request] != NO); + XCTAssert(map.callbacks.count == 1); + + // call callback + [map callCompletionForRequest:request withSuccessStatus:NO error:[NSError branchErrorWithCode:BNCGeneralError localizedMessage:@"Test Error"]]; + + // check if variable was updated + XCTAssertFalse(successResult); + XCTAssert([@"Test Error" isEqualToString:errorResult.localizedFailureReason]); +} + +- (void)testAttemptCallbackWithUnsavedRequest { + BNCCallbackMap *map = [BNCCallbackMap new]; + + __block BOOL successResult = NO; + __block NSError *errorResult = nil; + + // store a request and callback block + BNCServerRequest *request = [BNCServerRequest new]; + [map storeRequest:request withCompletion:^(BOOL success, NSError * _Nullable error) { + successResult = success; + errorResult = error; + }]; + + // confirm there's one entry + XCTAssert([map containsRequest:request] != NO); + XCTAssert(map.callbacks.count == 1); + + // confirm a new request results in no callback + request = [BNCServerRequest new]; + XCTAssert([map containsRequest:request] == NO); + [map callCompletionForRequest:request withSuccessStatus:YES error:nil]; + + // check if variable was updated + XCTAssertFalse(successResult); + XCTAssertNil(errorResult); +} + +- (void)testRequestsGetReleasedAutomatically { + BNCCallbackMap *map = [BNCCallbackMap new]; + + __block int count = 0; + + BNCServerRequest *request = [BNCServerRequest new]; + [map storeRequest:request withCompletion:^(BOOL success, NSError * _Nullable error) { + count++; + }]; + + for (int i=0; i<100; i++) { + BNCServerRequest *tmp = [BNCServerRequest new]; + [map storeRequest:tmp withCompletion:^(BOOL success, NSError * _Nullable error) { + count++; + }]; + } + + // confirm there's less than 100 entries. By not retaining the tmp request, they should be getting ARC'd + XCTAssert(map.callbacks.count < 100); + + // confirm the one request we held does get a callback + [map callCompletionForRequest:request withSuccessStatus:YES error:nil]; + XCTAssert(count == 1); +} + +@end diff --git a/BranchSDKTests/BNCClassSerializationTests.m b/BranchSDKTests/BNCClassSerializationTests.m new file mode 100644 index 000000000..f1af287d9 --- /dev/null +++ b/BranchSDKTests/BNCClassSerializationTests.m @@ -0,0 +1,120 @@ +// +// BNCClassSerializationTests.m +// Branch-SDK-Tests +// +// Created by Ernest Cho on 3/28/24. +// Copyright © 2024 Branch, Inc. All rights reserved. +// + +#import +#import "BranchEvent.h" +#import "BranchOpenRequest.h" +#import "BranchInstallRequest.h" + +@interface BranchEvent() +// private BranchEvent methods used to build a BranchEventRequest +- (NSDictionary *)buildEventDictionary; +@end + +@interface BranchOpenRequest() +- (NSString *)getActionName; +@end + +@interface BNCClassSerializationTests : XCTestCase + +@end + +// Test serialization of replayable requests +@implementation BNCClassSerializationTests + +- (void)setUp { + // Put setup code here. This method is called before the invocation of each test method in the class. +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. +} + +// BranchEventRequest is creation is tightly coupled with the BranchEvent class +// In order to test building it, we need to expose some private methods. :( +- (BranchEventRequest *)buildBranchEventRequest { + BranchEvent *event = [BranchEvent standardEvent:BranchStandardEventPurchase]; + NSURL *url = [NSURL URLWithString:@"https://api3.branch.io/v2/event/standard"]; + NSDictionary *eventDictionary = [event buildEventDictionary]; + + BranchEventRequest *request = [[BranchEventRequest alloc] initWithServerURL:url eventDictionary:eventDictionary completion:nil]; + return request; +} + +- (void)testBranchEventRequestArchive { + BranchEventRequest *request = [self buildBranchEventRequest]; + + // archive the event + NSError *error = nil; + NSData *data = [NSKeyedArchiver archivedDataWithRootObject:request requiringSecureCoding:YES error:&error]; + XCTAssertNil(error); + XCTAssertNotNil(data); + + // unarchive the event + id object = [NSKeyedUnarchiver unarchivedObjectOfClasses:[NSSet setWithArray:@[BranchEventRequest.class]] fromData:data error:&error]; + XCTAssertNil(error); + XCTAssertNotNil(object); + + // check object + XCTAssertTrue([object isKindOfClass:BranchEventRequest.class]); + BranchEventRequest *unarchivedRequest = (BranchEventRequest *)object; + + XCTAssertTrue([request.serverURL.absoluteString isEqualToString:unarchivedRequest.serverURL.absoluteString]); + XCTAssertTrue(request.eventDictionary.count == unarchivedRequest.eventDictionary.count); + XCTAssertNil(unarchivedRequest.completion); +} + +- (void)testBranchOpenRequestArchive { + BranchOpenRequest *request = [[BranchOpenRequest alloc] initWithCallback:nil]; + request.urlString = @"https://branch.io"; + + // archive the event + NSError *error = nil; + NSData *data = [NSKeyedArchiver archivedDataWithRootObject:request requiringSecureCoding:YES error:&error]; + XCTAssertNil(error); + XCTAssertNotNil(data); + + // unarchive the event + id object = [NSKeyedUnarchiver unarchivedObjectOfClasses:[NSSet setWithArray:@[BranchOpenRequest.class]] fromData:data error:&error]; + XCTAssertNil(error); + XCTAssertNotNil(object); + + // check object + XCTAssertTrue([object isKindOfClass:BranchOpenRequest.class]); + BranchOpenRequest *unarchivedRequest = (BranchOpenRequest *)object; + + XCTAssertTrue([request.urlString isEqualToString:unarchivedRequest.urlString]); + XCTAssertNil(unarchivedRequest.callback); + XCTAssertTrue([@"open" isEqualToString:[unarchivedRequest getActionName]]); +} + +- (void)testBranchInstallRequestArchive { + BranchInstallRequest *request = [[BranchInstallRequest alloc] initWithCallback:nil]; + request.urlString = @"https://branch.io"; + + // archive the event + NSError *error = nil; + NSData *data = [NSKeyedArchiver archivedDataWithRootObject:request requiringSecureCoding:YES error:&error]; + XCTAssertNil(error); + XCTAssertNotNil(data); + + // unarchive the event + id object = [NSKeyedUnarchiver unarchivedObjectOfClasses:[NSSet setWithArray:@[BranchInstallRequest.class]] fromData:data error:&error]; + XCTAssertNil(error); + XCTAssertNotNil(object); + + // check object + XCTAssertTrue([object isKindOfClass:BranchInstallRequest.class]); + BranchInstallRequest *unarchivedRequest = (BranchInstallRequest *)object; + + XCTAssertTrue([request.urlString isEqualToString:unarchivedRequest.urlString]); + XCTAssertNil(unarchivedRequest.callback); + XCTAssertTrue([@"install" isEqualToString:[unarchivedRequest getActionName]]); +} + +@end diff --git a/BranchSDKTests/BNCCrashlyticsWrapperTests.m b/BranchSDKTests/BNCCrashlyticsWrapperTests.m new file mode 100644 index 000000000..4b9be75a4 --- /dev/null +++ b/BranchSDKTests/BNCCrashlyticsWrapperTests.m @@ -0,0 +1,68 @@ +// +// BNCCrashlyticsWrapperTest.m +// Branch-TestBed +// +// Created by Jimmy Dee on 7/18/17. +// Copyright © 2017 Branch Metrics. All rights reserved. +// + +#import +#import "BNCCrashlyticsWrapper.h" + +#pragma mark Crashlytics SDK Stand-In + +@interface FIRCrashlytics : NSObject ++ (FIRCrashlytics *)crashlytics; +@property NSMutableDictionary *values; +- (void)setCustomValue:(id)value forKey:(NSString *)key; +-(id)getCustomValueForKey:(NSString *)key; +@end + +@implementation FIRCrashlytics + ++ (FIRCrashlytics *)crashlytics { + @synchronized (self) { + static FIRCrashlytics * sharedCrashlytics = nil; + if (!sharedCrashlytics) sharedCrashlytics = [[self alloc] init]; + return sharedCrashlytics; + } +} + +- (void)setCustomValue:(id)value forKey:(NSString *)key { + if (!_values) { + _values = [[NSMutableDictionary alloc] init]; + } + [_values setObject:value forKey:key]; +} + +-(id)getCustomValueForKey:(NSString *)key { + return [_values valueForKey:key]; +} +@end + +#pragma mark - BNCCrashlyticsWrapperTest + +@interface BNCCrashlyticsWrapperTests : XCTestCase +@end + +@implementation BNCCrashlyticsWrapperTests + +- (void)setUp { + // Put setup code here. This method is called before the invocation of each test method in the class. +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. +} + +- (void)testSetValue { + BNCCrashlyticsWrapper *wrapper = [BNCCrashlyticsWrapper wrapper]; + NSString *value = @"TestString"; + NSString *key = @"TestKey"; + + [wrapper setCustomValue:value forKey:key]; + + XCTAssertEqual([[FIRCrashlytics crashlytics] getCustomValueForKey:key], value); +} + +@end diff --git a/BranchSDKTests/BNCCurrencyTests.m b/BranchSDKTests/BNCCurrencyTests.m new file mode 100644 index 000000000..ec24da0f8 --- /dev/null +++ b/BranchSDKTests/BNCCurrencyTests.m @@ -0,0 +1,194 @@ +// +// BNCCurrencyTests.m +// Branch-SDK-Tests +// +// Created by Nipun Singh on 9/21/23. +// Copyright © 2023 Branch, Inc. All rights reserved. +// + +#import +#import "BNCCurrency.h" + +@interface BNCCurrencyTests : XCTestCase +@end + +@implementation BNCCurrencyTests + +- (void)testEnumValues { + XCTAssertEqualObjects(BNCCurrencyAED, @"AED"); + XCTAssertEqualObjects(BNCCurrencyAFN, @"AFN"); + XCTAssertEqualObjects(BNCCurrencyALL, @"ALL"); + XCTAssertEqualObjects(BNCCurrencyAMD, @"AMD"); + XCTAssertEqualObjects(BNCCurrencyANG, @"ANG"); + XCTAssertEqualObjects(BNCCurrencyAOA, @"AOA"); + XCTAssertEqualObjects(BNCCurrencyARS, @"ARS"); + XCTAssertEqualObjects(BNCCurrencyAUD, @"AUD"); + XCTAssertEqualObjects(BNCCurrencyAWG, @"AWG"); + XCTAssertEqualObjects(BNCCurrencyAZN, @"AZN"); + XCTAssertEqualObjects(BNCCurrencyBAM, @"BAM"); + XCTAssertEqualObjects(BNCCurrencyBBD, @"BBD"); + XCTAssertEqualObjects(BNCCurrencyBDT, @"BDT"); + XCTAssertEqualObjects(BNCCurrencyBGN, @"BGN"); + XCTAssertEqualObjects(BNCCurrencyBHD, @"BHD"); + XCTAssertEqualObjects(BNCCurrencyBIF, @"BIF"); + XCTAssertEqualObjects(BNCCurrencyBMD, @"BMD"); + XCTAssertEqualObjects(BNCCurrencyBND, @"BND"); + XCTAssertEqualObjects(BNCCurrencyBOB, @"BOB"); + XCTAssertEqualObjects(BNCCurrencyBOV, @"BOV"); + XCTAssertEqualObjects(BNCCurrencyBRL, @"BRL"); + XCTAssertEqualObjects(BNCCurrencyBSD, @"BSD"); + XCTAssertEqualObjects(BNCCurrencyBTN, @"BTN"); + XCTAssertEqualObjects(BNCCurrencyBWP, @"BWP"); + XCTAssertEqualObjects(BNCCurrencyBYN, @"BYN"); + XCTAssertEqualObjects(BNCCurrencyBYR, @"BYR"); + XCTAssertEqualObjects(BNCCurrencyBZD, @"BZD"); + XCTAssertEqualObjects(BNCCurrencyCAD, @"CAD"); + XCTAssertEqualObjects(BNCCurrencyCDF, @"CDF"); + XCTAssertEqualObjects(BNCCurrencyCHE, @"CHE"); + XCTAssertEqualObjects(BNCCurrencyCHF, @"CHF"); + XCTAssertEqualObjects(BNCCurrencyCHW, @"CHW"); + XCTAssertEqualObjects(BNCCurrencyCLF, @"CLF"); + XCTAssertEqualObjects(BNCCurrencyCLP, @"CLP"); + XCTAssertEqualObjects(BNCCurrencyCNY, @"CNY"); + XCTAssertEqualObjects(BNCCurrencyCOP, @"COP"); + XCTAssertEqualObjects(BNCCurrencyCOU, @"COU"); + XCTAssertEqualObjects(BNCCurrencyCRC, @"CRC"); + XCTAssertEqualObjects(BNCCurrencyCUC, @"CUC"); + XCTAssertEqualObjects(BNCCurrencyCUP, @"CUP"); + XCTAssertEqualObjects(BNCCurrencyCVE, @"CVE"); + XCTAssertEqualObjects(BNCCurrencyCZK, @"CZK"); + XCTAssertEqualObjects(BNCCurrencyDJF, @"DJF"); + XCTAssertEqualObjects(BNCCurrencyDKK, @"DKK"); + XCTAssertEqualObjects(BNCCurrencyDOP, @"DOP"); + XCTAssertEqualObjects(BNCCurrencyDZD, @"DZD"); + XCTAssertEqualObjects(BNCCurrencyEGP, @"EGP"); + XCTAssertEqualObjects(BNCCurrencyERN, @"ERN"); + XCTAssertEqualObjects(BNCCurrencyETB, @"ETB"); + XCTAssertEqualObjects(BNCCurrencyEUR, @"EUR"); + XCTAssertEqualObjects(BNCCurrencyFJD, @"FJD"); + XCTAssertEqualObjects(BNCCurrencyFKP, @"FKP"); + XCTAssertEqualObjects(BNCCurrencyGBP, @"GBP"); + XCTAssertEqualObjects(BNCCurrencyGEL, @"GEL"); + XCTAssertEqualObjects(BNCCurrencyGHS, @"GHS"); + XCTAssertEqualObjects(BNCCurrencyGIP, @"GIP"); + XCTAssertEqualObjects(BNCCurrencyGMD, @"GMD"); + XCTAssertEqualObjects(BNCCurrencyGNF, @"GNF"); + XCTAssertEqualObjects(BNCCurrencyGTQ, @"GTQ"); + XCTAssertEqualObjects(BNCCurrencyGYD, @"GYD"); + XCTAssertEqualObjects(BNCCurrencyHKD, @"HKD"); + XCTAssertEqualObjects(BNCCurrencyHNL, @"HNL"); + XCTAssertEqualObjects(BNCCurrencyHRK, @"HRK"); + XCTAssertEqualObjects(BNCCurrencyHTG, @"HTG"); + XCTAssertEqualObjects(BNCCurrencyHUF, @"HUF"); + XCTAssertEqualObjects(BNCCurrencyIDR, @"IDR"); + XCTAssertEqualObjects(BNCCurrencyILS, @"ILS"); + XCTAssertEqualObjects(BNCCurrencyINR, @"INR"); + XCTAssertEqualObjects(BNCCurrencyIQD, @"IQD"); + XCTAssertEqualObjects(BNCCurrencyIRR, @"IRR"); + XCTAssertEqualObjects(BNCCurrencyISK, @"ISK"); + XCTAssertEqualObjects(BNCCurrencyJMD, @"JMD"); + XCTAssertEqualObjects(BNCCurrencyJOD, @"JOD"); + XCTAssertEqualObjects(BNCCurrencyJPY, @"JPY"); + XCTAssertEqualObjects(BNCCurrencyKES, @"KES"); + XCTAssertEqualObjects(BNCCurrencyKGS, @"KGS"); + XCTAssertEqualObjects(BNCCurrencyKHR, @"KHR"); + XCTAssertEqualObjects(BNCCurrencyKMF, @"KMF"); + XCTAssertEqualObjects(BNCCurrencyKPW, @"KPW"); + XCTAssertEqualObjects(BNCCurrencyKRW, @"KRW"); + XCTAssertEqualObjects(BNCCurrencyKWD, @"KWD"); + XCTAssertEqualObjects(BNCCurrencyKYD, @"KYD"); + XCTAssertEqualObjects(BNCCurrencyKZT, @"KZT"); + XCTAssertEqualObjects(BNCCurrencyLAK, @"LAK"); + XCTAssertEqualObjects(BNCCurrencyLBP, @"LBP"); + XCTAssertEqualObjects(BNCCurrencyLKR, @"LKR"); + XCTAssertEqualObjects(BNCCurrencyLRD, @"LRD"); + XCTAssertEqualObjects(BNCCurrencyLSL, @"LSL"); + XCTAssertEqualObjects(BNCCurrencyLYD, @"LYD"); + XCTAssertEqualObjects(BNCCurrencyMAD, @"MAD"); + XCTAssertEqualObjects(BNCCurrencyMDL, @"MDL"); + XCTAssertEqualObjects(BNCCurrencyMGA, @"MGA"); + XCTAssertEqualObjects(BNCCurrencyMKD, @"MKD"); + XCTAssertEqualObjects(BNCCurrencyMMK, @"MMK"); + XCTAssertEqualObjects(BNCCurrencyMNT, @"MNT"); + XCTAssertEqualObjects(BNCCurrencyMOP, @"MOP"); + XCTAssertEqualObjects(BNCCurrencyMRO, @"MRO"); + XCTAssertEqualObjects(BNCCurrencyMUR, @"MUR"); + XCTAssertEqualObjects(BNCCurrencyMVR, @"MVR"); + XCTAssertEqualObjects(BNCCurrencyMWK, @"MWK"); + XCTAssertEqualObjects(BNCCurrencyMXN, @"MXN"); + XCTAssertEqualObjects(BNCCurrencyMXV, @"MXV"); + XCTAssertEqualObjects(BNCCurrencyMYR, @"MYR"); + XCTAssertEqualObjects(BNCCurrencyMZN, @"MZN"); + XCTAssertEqualObjects(BNCCurrencyNAD, @"NAD"); + XCTAssertEqualObjects(BNCCurrencyNGN, @"NGN"); + XCTAssertEqualObjects(BNCCurrencyNIO, @"NIO"); + XCTAssertEqualObjects(BNCCurrencyNOK, @"NOK"); + XCTAssertEqualObjects(BNCCurrencyNPR, @"NPR"); + XCTAssertEqualObjects(BNCCurrencyNZD, @"NZD"); + XCTAssertEqualObjects(BNCCurrencyOMR, @"OMR"); + XCTAssertEqualObjects(BNCCurrencyPAB, @"PAB"); + XCTAssertEqualObjects(BNCCurrencyPEN, @"PEN"); + XCTAssertEqualObjects(BNCCurrencyPGK, @"PGK"); + XCTAssertEqualObjects(BNCCurrencyPHP, @"PHP"); + XCTAssertEqualObjects(BNCCurrencyPKR, @"PKR"); + XCTAssertEqualObjects(BNCCurrencyPLN, @"PLN"); + XCTAssertEqualObjects(BNCCurrencyPYG, @"PYG"); + XCTAssertEqualObjects(BNCCurrencyQAR, @"QAR"); + XCTAssertEqualObjects(BNCCurrencyRON, @"RON"); + XCTAssertEqualObjects(BNCCurrencyRSD, @"RSD"); + XCTAssertEqualObjects(BNCCurrencyRUB, @"RUB"); + XCTAssertEqualObjects(BNCCurrencyRWF, @"RWF"); + XCTAssertEqualObjects(BNCCurrencySAR, @"SAR"); + XCTAssertEqualObjects(BNCCurrencySBD, @"SBD"); + XCTAssertEqualObjects(BNCCurrencySCR, @"SCR"); + XCTAssertEqualObjects(BNCCurrencySDG, @"SDG"); + XCTAssertEqualObjects(BNCCurrencySEK, @"SEK"); + XCTAssertEqualObjects(BNCCurrencySGD, @"SGD"); + XCTAssertEqualObjects(BNCCurrencySHP, @"SHP"); + XCTAssertEqualObjects(BNCCurrencySLL, @"SLL"); + XCTAssertEqualObjects(BNCCurrencySOS, @"SOS"); + XCTAssertEqualObjects(BNCCurrencySRD, @"SRD"); + XCTAssertEqualObjects(BNCCurrencySSP, @"SSP"); + XCTAssertEqualObjects(BNCCurrencySTD, @"STD"); + XCTAssertEqualObjects(BNCCurrencySYP, @"SYP"); + XCTAssertEqualObjects(BNCCurrencySZL, @"SZL"); + XCTAssertEqualObjects(BNCCurrencyTHB, @"THB"); + XCTAssertEqualObjects(BNCCurrencyTJS, @"TJS"); + XCTAssertEqualObjects(BNCCurrencyTMT, @"TMT"); + XCTAssertEqualObjects(BNCCurrencyTND, @"TND"); + XCTAssertEqualObjects(BNCCurrencyTOP, @"TOP"); + XCTAssertEqualObjects(BNCCurrencyTRY, @"TRY"); + XCTAssertEqualObjects(BNCCurrencyTTD, @"TTD"); + XCTAssertEqualObjects(BNCCurrencyTWD, @"TWD"); + XCTAssertEqualObjects(BNCCurrencyTZS, @"TZS"); + XCTAssertEqualObjects(BNCCurrencyUAH, @"UAH"); + XCTAssertEqualObjects(BNCCurrencyUGX, @"UGX"); + XCTAssertEqualObjects(BNCCurrencyUSD, @"USD"); + XCTAssertEqualObjects(BNCCurrencyUSN, @"USN"); + XCTAssertEqualObjects(BNCCurrencyUYI, @"UYI"); + XCTAssertEqualObjects(BNCCurrencyUYU, @"UYU"); + XCTAssertEqualObjects(BNCCurrencyUZS, @"UZS"); + XCTAssertEqualObjects(BNCCurrencyVEF, @"VEF"); + XCTAssertEqualObjects(BNCCurrencyVND, @"VND"); + XCTAssertEqualObjects(BNCCurrencyVUV, @"VUV"); + XCTAssertEqualObjects(BNCCurrencyWST, @"WST"); + XCTAssertEqualObjects(BNCCurrencyXAF, @"XAF"); + XCTAssertEqualObjects(BNCCurrencyXAG, @"XAG"); + XCTAssertEqualObjects(BNCCurrencyXAU, @"XAU"); + XCTAssertEqualObjects(BNCCurrencyXCD, @"XCD"); + XCTAssertEqualObjects(BNCCurrencyXDR, @"XDR"); + XCTAssertEqualObjects(BNCCurrencyXOF, @"XOF"); + XCTAssertEqualObjects(BNCCurrencyXPD, @"XPD"); + XCTAssertEqualObjects(BNCCurrencyXPF, @"XPF"); + XCTAssertEqualObjects(BNCCurrencyXPT, @"XPT"); + XCTAssertEqualObjects(BNCCurrencyXSU, @"XSU"); + XCTAssertEqualObjects(BNCCurrencyXTS, @"XTS"); + XCTAssertEqualObjects(BNCCurrencyXUA, @"XUA"); + XCTAssertEqualObjects(BNCCurrencyXXX, @"XXX"); + XCTAssertEqualObjects(BNCCurrencyYER, @"YER"); + XCTAssertEqualObjects(BNCCurrencyZAR, @"ZAR"); + XCTAssertEqualObjects(BNCCurrencyZMW, @"ZMW"); +} + + +@end diff --git a/BranchSDKTests/BNCDeviceInfoTests.m b/BranchSDKTests/BNCDeviceInfoTests.m new file mode 100644 index 000000000..39b4ee5d8 --- /dev/null +++ b/BranchSDKTests/BNCDeviceInfoTests.m @@ -0,0 +1,190 @@ +// +// BNCDeviceInfoTests.m +// Branch-SDK-Tests +// +// Created by Ernest Cho on 11/21/19. +// Copyright © 2019 Branch, Inc. All rights reserved. +// + +#import +#import "BNCDeviceInfo.h" +#import "BNCUserAgentCollector.h" + +@interface BNCDeviceInfoTests : XCTestCase +@property (nonatomic, strong, readwrite) BNCDeviceInfo *deviceInfo; +@end + +@implementation BNCDeviceInfoTests + +- (void)setUp { + [self workaroundUserAgentLazyLoad]; + self.deviceInfo = [BNCDeviceInfo new]; +} + +// user agent needs to be loaded +- (void)workaroundUserAgentLazyLoad { + __block XCTestExpectation *expectation = [self expectationWithDescription:@"setup"]; + [[BNCUserAgentCollector instance] loadUserAgentWithCompletion:^(NSString * _Nullable userAgent) { + [expectation fulfill]; + }]; + [self waitForExpectationsWithTimeout:5.0 handler:^(NSError * _Nullable error) { }]; +} + +- (void)tearDown { + +} + +- (void)testHardwareId { + XCTAssertNotNil(self.deviceInfo.hardwareId); + + // verify hardwareId is a valid UUID + NSUUID *hardwareId = [[NSUUID alloc] initWithUUIDString:self.deviceInfo.hardwareId]; + XCTAssertNotNil(hardwareId); +} + +- (void)testHardwareIdType { + // without ATT, this is the IDFV. Branch servers expect it as vendor_id + XCTAssert([self.deviceInfo.hardwareIdType isEqualToString:@"vendor_id"]); +} + +- (void)testIsRealHardwareId { + XCTAssert(self.deviceInfo.isRealHardwareId); +} + +- (void)testAdvertiserId { + // the testbed does not show the ATT prompt. + XCTAssertNil(self.deviceInfo.advertiserId); +} + +- (void)testVendorId { + XCTAssertNotNil(self.deviceInfo.vendorId); + + // verify vendorId is a valid UUID + NSUUID *vendorId = [[NSUUID alloc] initWithUUIDString:self.deviceInfo.vendorId]; + XCTAssertNotNil(vendorId); +} + +- (void)testAnonId { + XCTAssertNotNil(self.deviceInfo.anonId); + + // verify anonId is a valid UUID + NSUUID *anonId = [[NSUUID alloc] initWithUUIDString:self.deviceInfo.anonId]; + XCTAssertNotNil(anonId); +} + +- (void)testOptedInStatus { + // the testbed does not show the ATT prompt. + XCTAssert([self.deviceInfo.optedInStatus isEqualToString:@"not_determined"]); +} + +- (void)testIsFirstOptIn { + // the testbed does not show the ATT prompt. + XCTAssert(self.deviceInfo.isFirstOptIn == NO); +} + +- (void)testLocalIPAddress { + NSString *address = [self.deviceInfo localIPAddress]; + XCTAssertNotNil(address); + XCTAssert(address.length > 7); +} + +- (void)testConnectionType { + // simulator is on wifi + XCTAssert([[self.deviceInfo connectionType] isEqualToString:@"wifi"]); +} + +- (void)testBrandName { + XCTAssert([@"Apple" isEqualToString:self.deviceInfo.brandName]); +} + +- (void)testModelName_Simulator { + // intel processor + bool x86_64 = [@"x86_64" isEqualToString:self.deviceInfo.modelName]; + + // apple processor + bool arm64 = [@"arm64" isEqualToString:self.deviceInfo.modelName]; + + XCTAssert(x86_64 || arm64); +} + +- (void)testOSName { + XCTAssertNotNil(self.deviceInfo.osName); + XCTAssert([@"iOS" isEqualToString:self.deviceInfo.osName]); +} + +- (void)testOSVersion { + XCTAssertNotNil(self.deviceInfo.osVersion); + XCTAssert([self.deviceInfo.osVersion isEqualToString:[UIDevice currentDevice].systemVersion]); +} + +- (void)testOSBuildVersion { + XCTAssertNotNil(self.deviceInfo.osBuildVersion); +} + +- (void)testEnvironment { + // currently not running unit tests on extensions + XCTAssert([@"FULL_APP" isEqualToString:self.deviceInfo.environment]); +} + +- (void)testCpuType_Simulator { + // intel processors + bool x86 = [@"7" isEqualToString:self.deviceInfo.cpuType]; + + // apple processors + bool arm = [@"16777228" isEqualToString:self.deviceInfo.cpuType]; + + XCTAssert(x86 || arm); +} + +- (void)testScreenWidth { + XCTAssert(self.deviceInfo.screenWidth.intValue >= 320); +} + +- (void)testScreenHeight { + XCTAssert(self.deviceInfo.screenHeight.intValue >= 320); +} + +- (void)testScreenScale { + XCTAssert(self.deviceInfo.screenScale.intValue >= 1); +} + +- (void)testLocale { + NSString *locale = [NSLocale currentLocale].localeIdentifier; + XCTAssertNotNil(locale); + XCTAssert([locale isEqualToString:self.deviceInfo.locale]); +} + +- (void)testCountry { + NSString *locale = [NSLocale currentLocale].localeIdentifier; + XCTAssertNotNil(locale); + XCTAssert([locale containsString:self.deviceInfo.country]); +} + +- (void)testLanguage { + NSString *locale = [NSLocale currentLocale].localeIdentifier; + XCTAssertNotNil(locale); + XCTAssert([locale containsString:self.deviceInfo.language]); +} + +- (void)testUserAgentString { + XCTAssert([self.deviceInfo.userAgentString containsString:@"AppleWebKit"]); +} + +- (void)testApplicationVersion_TestBed { + XCTAssert([@"1.0" isEqualToString:self.deviceInfo.applicationVersion]); +} + +- (void)testRegisterPluginNameVersion { + XCTAssertNil(self.deviceInfo.pluginName); + XCTAssertNil(self.deviceInfo.pluginVersion); + + NSString *expectedName = @"react native"; + NSString *expectedVersion = @"1.0.0"; + + [self.deviceInfo registerPluginName:expectedName version:expectedVersion]; + + XCTAssert([expectedName isEqualToString:self.deviceInfo.pluginName]); + XCTAssert([expectedVersion isEqualToString:self.deviceInfo.pluginVersion]); +} + +@end diff --git a/BranchSDKTests/BNCDeviceSystemTests.m b/BranchSDKTests/BNCDeviceSystemTests.m new file mode 100644 index 000000000..0a47b73d9 --- /dev/null +++ b/BranchSDKTests/BNCDeviceSystemTests.m @@ -0,0 +1,62 @@ +// +// BNCDeviceSystemTests.m +// Branch-SDK-Tests +// +// Created by Ernest Cho on 11/14/19. +// Copyright © 2019 Branch, Inc. All rights reserved. +// + +#import +#import "BNCDeviceSystem.h" + +@interface BNCDeviceSystemTests : XCTestCase + +@property (nonatomic, strong, readwrite) BNCDeviceSystem *deviceSystem; + +@end + +@implementation BNCDeviceSystemTests + +- (void)setUp { + self.deviceSystem = [BNCDeviceSystem new]; +} + +- (void)tearDown { + +} + +- (void)testSystemBuildVersion { + XCTAssertNotNil(self.deviceSystem.systemBuildVersion); + XCTAssert(self.deviceSystem.systemBuildVersion.length > 0); +} + +- (void)testMachine_Simulator { + // intel processor + bool x86_64 = [@"x86_64" isEqualToString:self.deviceSystem.machine]; + + // apple processor + bool arm64 = [@"arm64" isEqualToString:self.deviceSystem.machine]; + + XCTAssert(x86_64 || arm64); +} + +- (void)testCPUType_Simulator { + // intel processor + bool x86 = [@(7) isEqualToNumber:self.deviceSystem.cpuType]; + bool x86_sub = [@(8) isEqualToNumber:self.deviceSystem.cpuSubType]; + + // apple processor + bool arm = [@(16777228) isEqualToNumber:self.deviceSystem.cpuType]; + bool arm_sub = [@(2) isEqualToNumber:self.deviceSystem.cpuSubType]; + + XCTAssert(x86 || arm); + +// cpu subtype is different on cloud runners +// if (x86) { +// XCTAssert(x86_sub); +// } else { +// XCTAssert(arm_sub); +// } +} + +@end diff --git a/BranchSDKTests/BNCDisableAdNetworkCalloutsTests.m b/BranchSDKTests/BNCDisableAdNetworkCalloutsTests.m new file mode 100644 index 000000000..ea277ac39 --- /dev/null +++ b/BranchSDKTests/BNCDisableAdNetworkCalloutsTests.m @@ -0,0 +1,59 @@ +// +// BNCDisableAdNetworkCalloutsTests.m +// Branch-SDK-Tests +// +// Created by Ernest Cho on 3/2/20. +// Copyright © 2020 Branch, Inc. All rights reserved. +// + +#import +#import "BNCPreferenceHelper.h" +#import "BNCDeviceInfo.h" +#import "BNCServerInterface.h" +@import BranchSDK; + +@interface BNCServerInterface() +- (void)updateDeviceInfoToMutableDictionary:(NSMutableDictionary *)dict; +@end + +@interface BNCDisableAdNetworkCalloutsTests : XCTestCase + +@end + +// These tests are not parallelizable and therefore disabled by default +// This is due to the tight coupling between BNCPreferenceHelper and BNCDeviceInfo +@implementation BNCDisableAdNetworkCalloutsTests +/* +- (void)setUp { + [BNCPreferenceHelper preferenceHelper].disableAdNetworkCallouts = YES; +} + +- (void)tearDown { + [BNCPreferenceHelper preferenceHelper].disableAdNetworkCallouts = NO; +} + +// check on the V2 dictionary +- (void)testV2Dictionary { + NSDictionary *dict = [[BNCDeviceInfo getInstance] v2dictionary]; + XCTAssertNotNil(dict); + XCTAssertNotNil(dict[@"brand"]); + XCTAssertNotNil(dict[@"os"]); + XCTAssertNotNil(dict[@"sdk"]); + XCTAssertNotNil(dict[@"sdk_version"]); + + XCTAssertTrue(dict[@"disable_ad_network_callouts"]); +} + +// check on V1 payload +- (void)testV1Payload { + BNCServerInterface *interface = [BNCServerInterface new]; + interface.preferenceHelper = [BNCPreferenceHelper preferenceHelper]; + + NSMutableDictionary *tmp = [NSMutableDictionary new]; + [interface updateDeviceInfoToMutableDictionary:tmp]; + + XCTAssertNotNil(tmp); + XCTAssertTrue(tmp[@"disable_ad_network_callouts"]); +} +*/ +@end diff --git a/BranchSDKTests/BNCEncodingUtilsTests.m b/BranchSDKTests/BNCEncodingUtilsTests.m new file mode 100644 index 000000000..0b18fe51a --- /dev/null +++ b/BranchSDKTests/BNCEncodingUtilsTests.m @@ -0,0 +1,609 @@ +// +// BNCEncodingUtils.m +// Branch +// +// Created by Graham Mueller on 4/1/15. +// Copyright (c) 2015 Branch Metrics. All rights reserved. +// + +#import +#import "BNCEncodingUtils.h" + +@interface BNCEncodingUtilsTests : XCTestCase +@end + +@implementation BNCEncodingUtilsTests + +- (void)setUp { + // Put setup code here. This method is called before the invocation of each test method in the class. +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. +} + +#pragma mark - EncodeDictionaryToJsonString tests + +- (void)testEncodeDictionaryToJsonStringWithExpectedParams { + NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; + [dateFormatter setLocale:[NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"]]; + [dateFormatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ssZZZZZ"]; + NSDate *date = [dateFormatter dateFromString:@"2015-04-01T00:00:00-05:00"]; + NSString *formattedDateString = [dateFormatter stringFromDate:date]; + + NSURL *someUrl = [NSURL URLWithString:@"https://branch.io"]; + NSDictionary *dataDict = @{ + @"foo": @"bar", + @"num": @1, + @"array": @[ @"array", @"items" ], + @"dict": @{ @"sub": @1 }, + @"url": someUrl, + @"date": date + }; + NSString *expectedEncodedString = [NSString stringWithFormat: + @"{\"foo\":\"bar\",\"num\":1,\"array\":[\"array\",\"items\"],\"dict\":{\"sub\":1},\"url\":\"https://branch.io\",\"date\":\"%@\"}", + formattedDateString]; + NSString *encodedValue = [BNCEncodingUtils encodeDictionaryToJsonString:dataDict]; + + XCTAssertEqualObjects(expectedEncodedString, encodedValue); +} + +- (void)testEncodeDictionaryToJsonStringWithUnexpectedParams { + NSObject *arbitraryObj = [[NSObject alloc] init]; + NSDictionary *dataDict = @{ @"foo": @"bar", @"random": arbitraryObj }; + NSString *expectedEncodedString = @"{\"foo\":\"bar\"}"; + + NSString *encodedValue = [BNCEncodingUtils encodeDictionaryToJsonString:dataDict]; + + XCTAssertEqualObjects(expectedEncodedString, encodedValue); +} + +- (void)testEncodeDictionaryToJsonStringStringWithNull { + NSDictionary *dataDict = @{ @"foo": [NSNull null] }; + NSString *expectedEncodedString = @"{\"foo\":null}"; + + NSString *encodedValue = [BNCEncodingUtils encodeDictionaryToJsonString:dataDict]; + + XCTAssertEqualObjects(expectedEncodedString, encodedValue); +} + +- (void)testEncodingNilDictionaryToJsonString { + NSDictionary *dataDict = nil; + NSString *expectedEncodedString = @"{}"; + + NSString *encodedValue = [BNCEncodingUtils encodeDictionaryToJsonString:dataDict]; + + XCTAssertEqualObjects(expectedEncodedString, encodedValue); +} + +- (void)testEncodeDictionaryToJsonStringWithNoKeys { + NSDictionary *emptyDict = @{ }; + NSString *expectedEncodedString = @"{}"; + + NSString *encodedValue = [BNCEncodingUtils encodeDictionaryToJsonString:emptyDict]; + + XCTAssertEqualObjects(expectedEncodedString, encodedValue); +} + +- (void)testEncodeDictionaryToJsonStringWithQuotes { + NSDictionary *dictionaryWithQuotes = @{ @"my\"cool\"key": @"my\"cool\"value" }; + NSString *expectedEncodedString = @"{\"my\\\"cool\\\"key\":\"my\\\"cool\\\"value\"}"; + + NSString *encodedValue = [BNCEncodingUtils encodeDictionaryToJsonString:dictionaryWithQuotes]; + + XCTAssertEqualObjects(expectedEncodedString, encodedValue); +} + +- (void)testSimpleEncodeDictionaryToJsonData { + NSDictionary *dataDict = @{ @"foo": @"bar" }; + NSData *expectedEncodedData = [@"{\"foo\":\"bar\"}" dataUsingEncoding:NSUTF8StringEncoding]; + + NSData *encodedValue = [BNCEncodingUtils encodeDictionaryToJsonData:dataDict]; + + XCTAssertEqualObjects(expectedEncodedData, encodedValue); +} + +- (void)testEncodeDictionaryToQueryString { + NSDictionary *dataDict = @{ @"foo": @"bar", @"something": @"something & something" }; + NSString *expectedEncodedString = @"?foo=bar&something=something%20%26%20something"; + + NSString *encodedValue = [BNCEncodingUtils encodeDictionaryToQueryString:dataDict]; + + XCTAssertEqualObjects(expectedEncodedString, encodedValue); +} + + +#pragma mark - EncodeArrayToJsonString + +- (void)testEncodeArrayToJsonStringWithExpectedParams { + NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; + [dateFormatter setLocale:[NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"]]; + [dateFormatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ssZZZZZ"]; + NSDate *date = [dateFormatter dateFromString:@"2015-04-01T00:00:00Z"]; + NSString *formattedDateString = [dateFormatter stringFromDate:date]; + + NSURL *someUrl = [NSURL URLWithString:@"https://branch.io"]; + NSArray *dataArray = @[ @"bar", @1, @[ @"array", @"items" ], @{ @"sub": @1 }, someUrl, date ]; + NSString *expectedEncodedString = [NSString stringWithFormat:@"[\"bar\",1,[\"array\",\"items\"],{\"sub\":1},\"https://branch.io\",\"%@\"]", formattedDateString]; + + NSString *encodedValue = [BNCEncodingUtils encodeArrayToJsonString:dataArray]; + + XCTAssertEqualObjects(expectedEncodedString, encodedValue); +} + +- (void)testEncodeArrayToJsonStringWithUnexpectedParams { + NSObject *arbitraryObj = [[NSObject alloc] init]; + NSArray *dataArray = @[ @"bar", arbitraryObj ]; + NSString *expectedEncodedString = @"[\"bar\"]"; + + NSString *encodedValue = [BNCEncodingUtils encodeArrayToJsonString:dataArray]; + + XCTAssertEqualObjects(expectedEncodedString, encodedValue); +} + +- (void)testEncodeArrayToJsonStringStringWithNull { + NSArray *dataArray = @[ [NSNull null] ]; + NSString *expectedEncodedString = @"[null]"; + + NSString *encodedValue = [BNCEncodingUtils encodeArrayToJsonString:dataArray]; + + XCTAssertEqualObjects(expectedEncodedString, encodedValue); +} + +- (void)testEncodeArrayToJsonStringWithNoValues { + NSArray *emptyArray = @[ ]; + NSString *expectedEncodedString = @"[]"; + + NSString *encodedValue = [BNCEncodingUtils encodeArrayToJsonString:emptyArray]; + + XCTAssertEqualObjects(expectedEncodedString, encodedValue); +} + +- (void)testEncodingEmptyArrayToJsonString { + NSArray *emptyArray = nil; + NSString *expectedEncodedString = @"[]"; + + NSString *encodedValue = [BNCEncodingUtils encodeArrayToJsonString:emptyArray]; + + XCTAssertEqualObjects(expectedEncodedString, encodedValue); +} + +- (void)testEncodeArrayToJsonStringWithQuotes { + NSArray *arrayWithQuotes = @[ @"my\"cool\"value1", @"my\"cool\"value2" ]; + NSString *expectedEncodedString = @"[\"my\\\"cool\\\"value1\",\"my\\\"cool\\\"value2\"]"; + + NSString *encodedValue = [BNCEncodingUtils encodeArrayToJsonString:arrayWithQuotes]; + + XCTAssertEqualObjects(expectedEncodedString, encodedValue); +} + + +#pragma mark - Character Length tests + +- (void)testChineseCharactersWithLengthGreaterThanOne { + NSString *multiCharacterString = @"𥑮"; + NSDictionary *jsonDict = @{ @"foo": multiCharacterString }; + NSString *expectedEncoding = @"{\"foo\":\"𥑮\"}"; + NSInteger expectedLength = [expectedEncoding lengthOfBytesUsingEncoding:NSUTF8StringEncoding]; + + NSData *encodedValue = [BNCEncodingUtils encodeDictionaryToJsonData:jsonDict]; + + XCTAssertEqual(expectedLength, [encodedValue length]); +} + + +#pragma mark - DecodeToDictionary tests + +- (void)testDecodeJsonDataToDictionary { + NSData *encodedData = [@"{\"foo\":\"bar\"}" dataUsingEncoding:NSUTF8StringEncoding]; + NSDictionary *expectedDataDict = @{ @"foo": @"bar" }; + + NSDictionary *decodedValue = [BNCEncodingUtils decodeJsonDataToDictionary:encodedData]; + + XCTAssertEqualObjects(decodedValue, expectedDataDict); +} + +- (void)testDecodeJsonStringToDictionary { + NSString *encodedString = @"{\"foo\":\"bar\"}"; + NSDictionary *expectedDataDict = @{ @"foo": @"bar" }; + + NSDictionary *decodedValue = [BNCEncodingUtils decodeJsonStringToDictionary:encodedString]; + + XCTAssertEqualObjects(decodedValue, expectedDataDict); +} + +#if 0 + +// From Ed: See note below +- (void)testDecodeJsonStringToDictionaryWithNilDecodedString { + char badCStr[5] = { '{', 'f', ':', 'o', '}' }; // not nil terminated + NSString *encodedString = [NSString stringWithUTF8String:badCStr]; + NSDictionary *expectedDataDict = @{ }; + + NSDictionary *decodedValue = [BNCEncodingUtils decodeJsonStringToDictionary:encodedString]; + + XCTAssertEqualObjects(decodedValue, expectedDataDict); +} + +#else + +- (void)testDecodeJsonStringToDictionaryWithNilDecodedString { + NSString *encodedString = nil; + NSDictionary *expectedDataDict = @{ }; + NSDictionary *decodedValue = [BNCEncodingUtils decodeJsonStringToDictionary:encodedString]; + XCTAssertEqualObjects(decodedValue, expectedDataDict); +} + +#endif + +- (void)testDecodeBase64EncodedJsonStringToDictionary { + NSString *encodedString = [BNCEncodingUtils base64EncodeStringToString:@"{\"foo\":\"bar\"}"]; + NSDictionary *expectedDataDict = @{ @"foo": @"bar" }; + + NSDictionary *decodedValue = [BNCEncodingUtils decodeJsonStringToDictionary:encodedString]; + + XCTAssertEqualObjects(decodedValue, expectedDataDict); +} + +- (void)testDecodeNonASCIIString { + // Should fail, but not crash. + NSString* result = [BNCEncodingUtils base64DecodeStringToString:@"𝄞"]; + XCTAssertNil(result); +} + +#if 0 + +// From Ed: I don't get the point of this test. +// It reads memory from the stack as a C string and decodes it as an NSString? +// The test itself won't run consistently and may fault sometimes. +- (void)testDecodeBase64JsonStringToDictionaryWithNilDecodedString { + char badCStr[5] = { '{', 'f', ':', 'o', '}' }; // not nil terminated + NSString *encodedString = [NSString stringWithUTF8String:badCStr]; + NSString *base64EncodedString = [BNCEncodingUtils base64EncodeStringToString:encodedString]; + NSDictionary *expectedDataDict = @{ }; + + NSDictionary *decodedValue = [BNCEncodingUtils decodeJsonStringToDictionary:base64EncodedString]; + + XCTAssertEqualObjects(decodedValue, expectedDataDict); +} + +#else + +// This should do the same thing without faulting during the test. +- (void)testDecodeBase64JsonStringToDictionaryWithNilDecodedString { + NSString *base64EncodedString = nil; + NSDictionary *expectedDataDict = @{ }; + NSDictionary *decodedValue = [BNCEncodingUtils decodeJsonStringToDictionary:base64EncodedString]; + XCTAssertEqualObjects(decodedValue, expectedDataDict); +} + +#endif + +- (void)testDecodeQueryStringToDictionary { + NSString *encodedString = @"foo=bar&baz=1&quux=&quo=Hi%20there"; + NSDictionary *expectedDataDict = @{ @"foo": @"bar", @"baz": @"1", @"quo": @"Hi there" }; // always goes to string + + NSDictionary *decodedValue = [BNCEncodingUtils decodeQueryStringToDictionary:encodedString]; + + XCTAssertEqualObjects(decodedValue, expectedDataDict); +} + +#pragma mark - Test Util methods + +- (NSString *)stringForDate:(NSDate *)date { + static NSDateFormatter *dateFormatter = nil; + static dispatch_once_t onceToken = 0; + + dispatch_once(&onceToken, ^{ + dateFormatter = [[NSDateFormatter alloc] init]; + [dateFormatter setLocale:[NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"]]; // POSIX to avoid weird issues + [dateFormatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ssZZZZZ"]; + }); + + return [dateFormatter stringFromDate:date]; +} + +#pragma mark - Base64EncodeData Tests + +#define _countof(array) (sizeof(array)/sizeof(array[0])) + +- (void)testBase64EncodeData { + NSData *data = nil; + NSString *truth = nil; + NSString *string = nil; + + string = [BNCEncodingUtils base64EncodeData:nil]; + XCTAssertEqualObjects(string, @""); + + string = [BNCEncodingUtils base64EncodeData:[NSData new]]; + XCTAssertEqualObjects(string, @""); + + uint8_t b1[] = {0, 1, 2, 3, 4, 5}; + data = [[NSData alloc] initWithBytes:b1 length:_countof(b1)]; + truth = @"AAECAwQF"; + string = [BNCEncodingUtils base64EncodeData:data]; + XCTAssertEqualObjects(string, truth); + + // Test that 1, 2, 3, 4, 5 length data encode correctly. + + data = [[NSData alloc] initWithBytes:b1 length:1]; + truth = @"AA=="; + string = [BNCEncodingUtils base64EncodeData:data]; + XCTAssertEqualObjects(string, truth); + + data = [[NSData alloc] initWithBytes:b1 length:2]; + truth = @"AAE="; + string = [BNCEncodingUtils base64EncodeData:data]; + XCTAssertEqualObjects(string, truth); + + data = [[NSData alloc] initWithBytes:b1 length:3]; + truth = @"AAEC"; + string = [BNCEncodingUtils base64EncodeData:data]; + XCTAssertEqualObjects(string, truth); + + data = [[NSData alloc] initWithBytes:b1 length:4]; + truth = @"AAECAw=="; + string = [BNCEncodingUtils base64EncodeData:data]; + XCTAssertEqualObjects(string, truth); + + data = [[NSData alloc] initWithBytes:b1 length:5]; + truth = @"AAECAwQ="; + string = [BNCEncodingUtils base64EncodeData:data]; + XCTAssertEqualObjects(string, truth); + + uint8_t b2[] = { + 0x00, 0x10, 0x83, 0x10, 0x51, 0x87, 0x20, 0x92, 0x8B, 0x30, 0xD3, 0x8F, 0x41, 0x14, 0x93, 0x51, + 0x55, 0x97, 0x61, 0x96, 0x9B, 0x71, 0xD7, 0x9F, 0x82, 0x18, 0xA3, 0x92, 0x59, 0xA7, 0xA2, 0x9A, + 0xAB, 0xB2, 0xDB, 0xAF, 0xC3, 0x1C, 0xB3, 0xD3, 0x5D, 0xB7, 0xE3, 0x9E, 0xBB, 0xF3, 0xDF, 0xBF, + }; + data = [[NSData alloc] initWithBytes:b2 length:_countof(b2)]; + truth = @"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + string = [BNCEncodingUtils base64EncodeData:data]; + XCTAssertEqualObjects(string, truth); +} + +- (void)testBase64DecodeString { + NSData *data = nil; + + data = [BNCEncodingUtils base64DecodeString:nil]; + XCTAssertEqual(data, nil); + + data = [BNCEncodingUtils base64DecodeString:@""]; + XCTAssertEqualObjects(data, [NSData new]); + + uint8_t truth[] = {0, 1, 2, 3, 4, 5}; + + data = [BNCEncodingUtils base64DecodeString:@"AAECAwQF"]; + XCTAssertTrue( data.length == 6 && memcmp(data.bytes, truth, 6) == 0 ); + + // Test that 1, 2, 3, 4, 5 length data encode correctly. + + #define testDecode(string, dataLength) { \ + data = [BNCEncodingUtils base64DecodeString:string]; \ + XCTAssertTrue( data.length == dataLength && memcmp(data.bytes, truth, dataLength) == 0 ); \ + } + + testDecode(@"AA==", 1); + testDecode(@"AAE=", 2); + testDecode(@"AAEC", 3); + testDecode(@"AAECAw==", 4); + testDecode(@"AAECAwQ=", 5); + + uint8_t b2[] = { + 0x00, 0x10, 0x83, 0x10, 0x51, 0x87, 0x20, 0x92, 0x8B, 0x30, 0xD3, 0x8F, 0x41, 0x14, 0x93, 0x51, + 0x55, 0x97, 0x61, 0x96, 0x9B, 0x71, 0xD7, 0x9F, 0x82, 0x18, 0xA3, 0x92, 0x59, 0xA7, 0xA2, 0x9A, + 0xAB, 0xB2, 0xDB, 0xAF, 0xC3, 0x1C, 0xB3, 0xD3, 0x5D, 0xB7, 0xE3, 0x9E, 0xBB, 0xF3, 0xDF, 0xBF, + }; + data = [BNCEncodingUtils base64DecodeString: + @"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"]; + XCTAssertTrue( data.length == _countof(b2) && memcmp(data.bytes, b2, _countof(b2)) == 0 ); + + // Test decode invalid data + data = [BNCEncodingUtils base64DecodeString: + @"ABCDEFGHIJKLMNOPQRSTUVWXYZabcde (Junk:%&*^**) fghijklmnopqrstuvwxyz0123456789+/"]; + XCTAssertEqual(data, nil); +} + +#pragma mark - Hex String Tests + +- (void) testHexStringFromData { + + NSString *s = nil; + + s = [BNCEncodingUtils hexStringFromData:[NSData data]]; + XCTAssertEqualObjects(s, @""); + + unsigned char bytes1[] = { 0x01 }; + s = [BNCEncodingUtils hexStringFromData:[NSData dataWithBytes:bytes1 length:1]]; + XCTAssertEqualObjects(s, @"01"); + + unsigned char bytes2[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef + }; + NSString *truth = + @"000102030405060708090A0B0C0D0E0F" + "E0E1E2E3E4E5E6E7E8E9EAEBECEDEEEF"; + + s = [BNCEncodingUtils hexStringFromData:[NSData dataWithBytes:bytes2 length:sizeof(bytes2)]]; + XCTAssertEqualObjects(s, truth); +} + +- (void) testDataFromHexString { + + NSData *data = nil; + + // nil + data = [BNCEncodingUtils dataFromHexString:nil]; + XCTAssertEqual(data, nil); + + // empty string + data = [BNCEncodingUtils dataFromHexString:@""]; + XCTAssertEqualObjects(data, [NSData data]); + + // upper string + unsigned char bytes[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef + }; + + NSString *stringUpper = + @"000102030405060708090A0B0C0D0E0F" + "E0E1E2E3E4E5E6E7E8E9EAEBECEDEEEF"; + + data = [BNCEncodingUtils dataFromHexString:stringUpper]; + XCTAssertEqualObjects(data, [NSData dataWithBytes:bytes length:sizeof(bytes)]); + + // lower string + + NSString *stringLower = + @"000102030405060708090a0b0c0d0e0f" + "e0e1e2e3e4e5e6e7e8e9eaebecedeeef"; + + data = [BNCEncodingUtils dataFromHexString:stringLower]; + XCTAssertEqualObjects(data, [NSData dataWithBytes:bytes length:sizeof(bytes)]); + + // white space + + NSString *stringWS = + @" 000102030405060708090a0b0c0d0e0f\n" + "e0e1e2e3e4e5e6\t\t\te7e8e9eaebeced\vee\ref"; + + data = [BNCEncodingUtils dataFromHexString:stringWS]; + XCTAssertEqualObjects(data, [NSData dataWithBytes:bytes length:sizeof(bytes)]); + + // odd number of charaters + + NSString *stringShort = + @"000102030405060708090a0b0c0d0e0f" + "e0e1e2e3e4e5e6e7e8e9eaebecedeee"; + + data = [BNCEncodingUtils dataFromHexString:stringShort]; + XCTAssertEqual(data, nil); + + // invalid characters + + NSString *stringInvalid = + @"000102030405060708090a0b0c0d0e0fInvalid" + "e0e1e2e3e4e5e6e7e8e9eaebecedeeef"; + + data = [BNCEncodingUtils dataFromHexString:stringInvalid]; + XCTAssertEqual(data, nil); + + // singles + + NSString *stringShortShort1 = @"A"; + data = [BNCEncodingUtils dataFromHexString:stringShortShort1]; + XCTAssertEqual(data, nil); + + NSString *stringShortShort2 = @"af"; + unsigned char stringShortShort2Bytes[] = { 0xaf }; + data = [BNCEncodingUtils dataFromHexString:stringShortShort2]; + XCTAssertEqualObjects(data, [NSData dataWithBytes:stringShortShort2Bytes length:1]); +} + +- (void) testPercentDecoding { + + NSString *s = nil; + s = [BNCEncodingUtils stringByPercentDecodingString:nil]; + XCTAssert(s == nil); + + NSArray* tests = @[ + @"", + @"", + + @"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", + @"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", + + @"-._~", + @"-._~", + + @"one%20two", + @"one two", + + // @"one+two", + // @"one two", + + @"one%2Btwo", + @"one+two", + + @"%21%23%24%26%27%28%29%2A%2B%2C%3A%3B%3D%40%5B%5D", + @"!#$&'()*+,:;=@[]", + ]; + + for (int i = 0; i < tests.count; i+=2) { + NSString *result = [BNCEncodingUtils stringByPercentDecodingString:tests[i]]; + XCTAssertEqualObjects(result, tests[i+1]); + } +} + +- (void) testQueryItems { + + NSURL *URL = nil; + NSArray* items = nil; + NSArray* expected = nil; + + items = [BNCEncodingUtils queryItems:URL]; + XCTAssert(items != nil && items.count == 0); + + URL = [NSURL URLWithString:@"http://example.com/thus?a=1&a=2&b=3"]; + items = [BNCEncodingUtils queryItems:URL]; + expected = @[ [BNCKeyValue key:@"a" value:@"1"], [BNCKeyValue key:@"a" value:@"2"], [BNCKeyValue key:@"b" value:@"3"] ]; + XCTAssertEqualObjects(items, expected); + + URL = [NSURL URLWithString:@"http://example.com/thus"]; + items = [BNCEncodingUtils queryItems:URL]; + expected = @[ ]; + XCTAssertEqualObjects(items, expected); + + URL = [NSURL URLWithString:@"http://example.com/thus?"]; + items = [BNCEncodingUtils queryItems:URL]; + expected = @[ ]; + XCTAssertEqualObjects(items, expected); + + URL = [NSURL URLWithString:@"http://example.com/thus?="]; + items = [BNCEncodingUtils queryItems:URL]; + expected = @[ ]; + XCTAssertEqualObjects(items, expected); + + URL = [NSURL URLWithString:@"http://example.com/thus?a="]; + items = [BNCEncodingUtils queryItems:URL]; + expected = @[ [BNCKeyValue key:@"a" value:@""] ]; + XCTAssertEqualObjects(items, expected); + + URL = [NSURL URLWithString:@"http://example.com/thus?=1"]; + items = [BNCEncodingUtils queryItems:URL]; + expected = @[ [BNCKeyValue key:@"" value:@"1"] ]; + XCTAssertEqualObjects(items, expected); + + URL = [NSURL URLWithString:@"http://example.com/thus?a=1&"]; + items = [BNCEncodingUtils queryItems:URL]; + expected = @[ [BNCKeyValue key:@"a" value:@"1"] ]; + XCTAssertEqualObjects(items, expected); + + URL = [NSURL URLWithString:@"http://example.com/thus?a=1&&b=2"]; + items = [BNCEncodingUtils queryItems:URL]; + expected = @[ [BNCKeyValue key:@"a" value:@"1"], [BNCKeyValue key:@"b" value:@"2"] ]; + XCTAssertEqualObjects(items, expected); + + URL = [NSURL URLWithString:@"http://example.com/thus?a=1&b==2"]; + items = [BNCEncodingUtils queryItems:URL]; + expected = @[ [BNCKeyValue key:@"a" value:@"1"], [BNCKeyValue key:@"b" value:@"=2"] ]; + XCTAssertEqualObjects(items, expected); +} + +- (void) testSanitzeString { + NSString*test = @"\b\f\n\r\t\"`\\"; + NSString*truth = @"\\b\\f\\n\\r\\t\\\"'\\\\"; + NSString*result = [BNCEncodingUtils sanitizedStringFromString:test]; + XCTAssertEqualObjects(result, truth); +} + +// Branch servers never return a json array at the top level. However, our parser should enforce it. +- (void)testArrayJSON { + NSString *test = @"[\"helloworld\"]"; + NSDictionary *tmp = [BNCEncodingUtils decodeJsonStringToDictionary:test]; + XCTAssert([tmp isKindOfClass:[NSDictionary class]]); +} + +@end diff --git a/BranchSDKTests/BNCJSONUtilityTests.m b/BranchSDKTests/BNCJSONUtilityTests.m new file mode 100644 index 000000000..7f5f1c1cf --- /dev/null +++ b/BranchSDKTests/BNCJSONUtilityTests.m @@ -0,0 +1,188 @@ +// +// BNCJSONUtilityTests.m +// Branch-SDK-Tests +// +// Created by Ernest Cho on 9/17/19. +// Copyright © 2019 Branch, Inc. All rights reserved. +// + +#import +#import "BNCJSONUtility.h" +#import "BNCJsonLoader.h" + +@interface BNCJSONUtilityTests : XCTestCase +@property (nonatomic, strong, readwrite) NSDictionary *json; +@end + +@implementation BNCJSONUtilityTests + +- (void)setUp { + self.json = [BNCJsonLoader dictionaryFromJSONFileNamed:@"example"]; + XCTAssertNotNil(self.json); +} + +- (void)tearDown { + +} + +- (void)testIsNumber { + NSNumber *number = [NSNumber numberWithInt:314]; + XCTAssertTrue([BNCJSONUtility isNumber:number]); +} + +- (void)testIsNumber_Boxed { + XCTAssertTrue([BNCJSONUtility isNumber:@(1.0)]); +} + +- (void)testIsNumber_Nil { + XCTAssertFalse([BNCJSONUtility isNumber:nil]); +} + +- (void)testIsNumber_String { + XCTAssertFalse([BNCJSONUtility isNumber:@"1.0"]); +} + +- (void)testIsString { + XCTAssertTrue([BNCJSONUtility isString:@"1.0"]); +} + +- (void)testIsString_MutableString { + NSMutableString *string = [NSMutableString new]; + XCTAssertTrue([BNCJSONUtility isString:string]); +} + +- (void)testIsString_EmptyString { + XCTAssertTrue([BNCJSONUtility isString:@""]); +} + +- (void)testIsString_Nil { + XCTAssertFalse([BNCJSONUtility isString:nil]); +} + +- (void)testIsString_Number { + XCTAssertFalse([BNCJSONUtility isString:@(1.0)]); +} + +- (void)testIsArray { + NSArray *tmp = @[@1, @2]; + XCTAssertTrue([BNCJSONUtility isArray:tmp]); +} + +- (void)testIsArray_MutableArray { + NSMutableArray *tmp = [NSMutableArray new]; + XCTAssertTrue([BNCJSONUtility isArray:tmp]); +} + +- (void)testIsArray_EmptyArray { + XCTAssertTrue([BNCJSONUtility isArray:@[]]); +} + +- (void)testIsArray_Nil { + XCTAssertFalse([BNCJSONUtility isArray:nil]); +} + +- (void)testIsArray_Dictionary { + XCTAssertFalse([BNCJSONUtility isArray:[NSDictionary new]]); +} + +// successful call on untyped dictionary +- (void)testUntypedDictionary_CorrectType { + NSString *string = self.json[@"user_string"]; + XCTAssertNotNil(string); + XCTAssertTrue(([string isKindOfClass:[NSString class]] || [string isKindOfClass:[NSMutableString class]])); +} + +// demonstrates that an untyped dictionary can lead to type mismatches cause it always returns id +- (void)testUntypedDictionary_IncorrectType { + NSString *string = self.json[@"user_number"]; + XCTAssertNotNil(string); + XCTAssertTrue(([string isKindOfClass:[NSNumber class]])); +} + +- (void)testStringForKey_InvalidKey { + id key = @(1); + NSString *string = [BNCJSONUtility stringForKey:key json:self.json]; + XCTAssertNil(string); +} + +- (void)testStringForKey { + NSString *string = [BNCJSONUtility stringForKey:@"user_string" json:self.json]; + XCTAssertNotNil(string); + XCTAssertTrue(([string isKindOfClass:[NSString class]] || [string isKindOfClass:[NSMutableString class]])); +} + +- (void)testStringForKey_IncorrectType { + NSString *string = [BNCJSONUtility stringForKey:@"user_number" json:self.json]; + XCTAssertNil(string); +} + +- (void)testNumberForKey { + NSNumber *number = [BNCJSONUtility numberForKey:@"user_number" json:self.json]; + XCTAssertNotNil(number); + XCTAssertTrue([number isKindOfClass:[NSNumber class]]); +} + +- (void)testNumberForKey_IncorrectType { + NSNumber *number = [BNCJSONUtility numberForKey:@"user_string" json:self.json]; + XCTAssertNil(number); +} + +- (void)testDictionaryForKey { + NSDictionary *dict = [BNCJSONUtility dictionaryForKey:@"user_dict" json:self.json]; + XCTAssertNotNil(dict); + XCTAssertTrue(([dict isKindOfClass:NSDictionary.class] || [dict isKindOfClass:NSMutableDictionary.class])); +} + +- (void)testDictionaryForKey_IncorrectType { + NSDictionary *dict = [BNCJSONUtility dictionaryForKey:@"user_array" json:self.json]; + XCTAssertNil(dict); +} + +- (void)testArrayForKey { + NSArray *array = [BNCJSONUtility arrayForKey:@"user_array" json:self.json]; + XCTAssertNotNil(array); + XCTAssertTrue(([array isKindOfClass:[NSArray class]] || [array isKindOfClass:[NSMutableArray class]])); +} + +- (void)testArrayForKey_IncorrectType { + NSArray *array = [BNCJSONUtility arrayForKey:@"user_dict" json:self.json]; + XCTAssertNil(array); +} + +- (void)testStringArrayForKey { + NSArray *array = [BNCJSONUtility stringArrayForKey:@"user_array" json:self.json]; + XCTAssertNotNil(array); + XCTAssertTrue(array.count > 0); +} + +- (void)testStringArrayForKey_MixedTypes { + NSArray *array = [BNCJSONUtility stringArrayForKey:@"user_array_mixed" json:self.json]; + XCTAssertNotNil(array); + XCTAssertTrue(array.count > 0); +} + +- (void)testStringArrayForKey_Numbers { + NSArray *array = [BNCJSONUtility stringArrayForKey:@"user_array_numbers" json:self.json]; + XCTAssertNotNil(array); + XCTAssertTrue(array.count == 0); +} + +- (void)testStringDictionaryForKey { + NSDictionary *dict = [BNCJSONUtility stringDictionaryForKey:@"user_dict" json:self.json]; + XCTAssertNotNil(dict); + XCTAssertTrue(dict.count > 0); +} + +- (void)testStringDictionaryForKey_MixedTypes { + NSDictionary *dict = [BNCJSONUtility stringDictionaryForKey:@"user_dict_mixed" json:self.json]; + XCTAssertNotNil(dict); + XCTAssertTrue(dict.count > 0); +} + +- (void)testStringDictionaryForKey_Numbers { + NSDictionary *dict = [BNCJSONUtility stringDictionaryForKey:@"user_dict_numbers" json:self.json]; + XCTAssertNotNil(dict); + XCTAssertTrue(dict.count == 0); +} + +@end diff --git a/BranchSDKTests/BNCJsonLoader.h b/BranchSDKTests/BNCJsonLoader.h new file mode 100644 index 000000000..6df022300 --- /dev/null +++ b/BranchSDKTests/BNCJsonLoader.h @@ -0,0 +1,20 @@ +// +// BNCJsonLoader.h +// Branch-TestBed +// +// Created by Ernest Cho on 9/16/19. +// Copyright © 2019 Branch, Inc. All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface BNCJsonLoader : NSObject + +// test utility that loads json files from the Test Bundle. only works on hosted tests ++ (NSDictionary *)dictionaryFromJSONFileNamed:(NSString *)fileName; + +@end + +NS_ASSUME_NONNULL_END diff --git a/BranchSDKTests/BNCJsonLoader.m b/BranchSDKTests/BNCJsonLoader.m new file mode 100644 index 000000000..098798ba8 --- /dev/null +++ b/BranchSDKTests/BNCJsonLoader.m @@ -0,0 +1,27 @@ +// +// BNCJsonLoader.m +// Branch-TestBed +// +// Created by Ernest Cho on 9/16/19. +// Copyright © 2019 Branch, Inc. All rights reserved. +// + +#import "BNCJsonLoader.h" + +@implementation BNCJsonLoader + ++ (NSDictionary *)dictionaryFromJSONFileNamed:(NSString *)fileName { + + // Since this class is part of the Test target, [self class] returns the Test Bundle + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:fileName ofType:@"json"]; + + NSString *jsonString = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:NULL]; + + id dict = [NSJSONSerialization JSONObjectWithData:[jsonString dataUsingEncoding:NSUTF8StringEncoding] options:0 error:nil]; + if ([dict isKindOfClass:NSDictionary.class]) { + return dict; + } + return nil; +} + +@end diff --git a/BranchSDKTests/BNCKeyChainTests.m b/BranchSDKTests/BNCKeyChainTests.m new file mode 100644 index 000000000..07af91a22 --- /dev/null +++ b/BranchSDKTests/BNCKeyChainTests.m @@ -0,0 +1,121 @@ +// +// BNCKeyChainTests.m +// Branch-SDK-Tests +// +// Created by Ernest Cho on 1/6/22. +// Copyright © 2022 Branch, Inc. All rights reserved. +// + +#import +#import "BNCKeyChain.h" + +@interface BNCKeyChainTests : XCTestCase +@property (nonatomic, copy, readwrite) NSString *serviceName; +@end + +@implementation BNCKeyChainTests + +- (void)setUp { + self.serviceName = @"Service"; +} + +- (void)tearDown { + +} + +- (void)testEnvironment { + // Keychain tests must be hosted in an app, otherwise it won't have security access. + XCTAssertFalse([UIApplication sharedApplication] == nil); + + NSString *group = [BNCKeyChain securityAccessGroup]; + XCTAssertTrue(group.length > 0); +} + +- (void)testRemoveValues_Empty { + NSError *error = [BNCKeyChain removeValuesForService:nil key:nil]; + XCTAssertTrue(error == nil); +} + +- (void)testRetrieveDate_Empty { + NSError *error; + NSDate *date = [BNCKeyChain retrieveDateForService:self.serviceName key:@"testKey" error:&error]; + XCTAssertTrue(date == nil && error.code == errSecItemNotFound); +} + +- (void)testStoreAndRetrieveDate { + NSError *error; + NSString *key = @"testKey"; + NSDate *date = [NSDate date]; + + [BNCKeyChain storeDate:date forService:self.serviceName key:key cloudAccessGroup:nil]; + NSDate *tmp = [BNCKeyChain retrieveDateForService:self.serviceName key:key error:&error]; + XCTAssertNil(error); + XCTAssertTrue([date isEqualToDate:tmp]); + + // cleanup + error = [BNCKeyChain removeValuesForService:self.serviceName key:key]; + XCTAssertNil(error); +} + +- (void)testStore_Nil { + NSError *error; + NSString *key = @"testKey"; + NSDate *date = nil; + + error = [BNCKeyChain storeDate:date forService:self.serviceName key:key cloudAccessGroup:nil]; + XCTAssertTrue(error.code == errSecParam); + + NSDate *tmp = [BNCKeyChain retrieveDateForService:self.serviceName key:key error:&error]; + XCTAssertNil(tmp); + XCTAssertTrue(error.code == errSecItemNotFound); +} + +- (void)testStoreAndRetrieveMultipleDates { + NSError *error; + NSString *keyA = @"testKeyA"; + NSString *keyB = @"testKeyB"; + + NSDate *dateA = [NSDate date]; + NSDate *dateB = [NSDate dateWithTimeIntervalSinceNow:1]; + XCTAssertFalse([dateA isEqualToDate:dateB]); + + [BNCKeyChain storeDate:dateA forService:self.serviceName key:keyA cloudAccessGroup:nil]; + [BNCKeyChain storeDate:dateB forService:self.serviceName key:keyB cloudAccessGroup:nil]; + + NSDate *tmpA = [BNCKeyChain retrieveDateForService:self.serviceName key:keyA error:&error]; + XCTAssertNil(error); + XCTAssertTrue([dateA isEqualToDate:tmpA]); + + NSDate *tmpB = [BNCKeyChain retrieveDateForService:self.serviceName key:keyB error:&error]; + XCTAssertNil(error); + XCTAssertTrue([dateB isEqualToDate:tmpB]); + + XCTAssertFalse([tmpA isEqualToDate:tmpB]); + + // cleanup + error = [BNCKeyChain removeValuesForService:self.serviceName key:keyA]; + XCTAssertNil(error); + error = [BNCKeyChain removeValuesForService:self.serviceName key:keyB]; + XCTAssertNil(error); +} + +- (void)testStoreAndRetrieveDate_retrieveWrongKey { + NSError *error; + NSString *keyA = @"testKeyA"; + NSString *keyB = @"testKeyB"; + NSDate *date = [NSDate date]; + + [BNCKeyChain storeDate:date forService:self.serviceName key:keyA cloudAccessGroup:nil]; + NSDate *tmp = [BNCKeyChain retrieveDateForService:self.serviceName key:keyB error:&error]; + XCTAssertNil(tmp); + XCTAssertTrue(error.code == errSecItemNotFound); + + // cleanup + error = [BNCKeyChain removeValuesForService:self.serviceName key:keyA]; + XCTAssertNil(error); + error = [BNCKeyChain removeValuesForService:self.serviceName key:keyB]; + XCTAssertNil(error); +} + + +@end diff --git a/BranchSDKTests/BNCLinkDataTests.m b/BranchSDKTests/BNCLinkDataTests.m new file mode 100644 index 000000000..10eb3cb25 --- /dev/null +++ b/BranchSDKTests/BNCLinkDataTests.m @@ -0,0 +1,103 @@ +// +// BNCLinkDataTests.m +// Branch-TestBed +// +// Created by Graham Mueller on 6/15/15. +// Copyright (c) 2015 Branch Metrics. All rights reserved. +// + +#import +#import "BNCLinkData.h" + +@interface BNCLinkDataTests : XCTestCase +@end + +@implementation BNCLinkDataTests + +- (void)setUp { + // Put setup code here. This method is called before the invocation of each test method in the class. +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. +} + +- (void)testBasicObjectHash { + BNCLinkData *a = [[BNCLinkData alloc] init]; + BNCLinkData *b = [[BNCLinkData alloc] init]; + + XCTAssertEqual([a hash], [b hash]); +} + +- (void)testObjectHashWithSameValuesForKeys { + NSArray * const TAGS = @[ @"foo-tag" ]; + NSString * const ALIAS = @"foo-alias"; + BranchLinkType const LINK_TYPE = BranchLinkTypeOneTimeUse; + NSString * const CHANNEL = @"foo-channel"; + NSString * const FEATURE = @"foo-feature"; + NSString * const STAGE = @"foo-stage"; + NSDictionary * const PARAMS = @{ @"foo-key": @"foo-value" }; + NSInteger const DURATION = 1; + NSString * const IGNORE_UA = @"foo-ua"; + + BNCLinkData *a = [[BNCLinkData alloc] init]; + [a setupTags:TAGS]; + [a setupAlias:ALIAS]; + [a setupType:LINK_TYPE]; + [a setupChannel:CHANNEL]; + [a setupFeature:FEATURE]; + [a setupStage:STAGE]; + [a setupParams:PARAMS]; + [a setupMatchDuration:DURATION]; + [a setupIgnoreUAString:IGNORE_UA]; + + BNCLinkData *b = [[BNCLinkData alloc] init]; + [b setupTags:TAGS]; + [b setupAlias:ALIAS]; + [b setupType:LINK_TYPE]; + [b setupChannel:CHANNEL]; + [b setupFeature:FEATURE]; + [b setupStage:STAGE]; + [b setupParams:PARAMS]; + [b setupMatchDuration:DURATION]; + [b setupIgnoreUAString:IGNORE_UA]; + + XCTAssertEqual([a hash], [b hash]); +} + +- (void)testObjectHashWithDifferentValuesForSameKeys { + BNCLinkData *a = [[BNCLinkData alloc] init]; + [a setupTags:@[ @"foo-tags" ]]; + [a setupAlias:@"foo-alias"]; + [a setupType:BranchLinkTypeOneTimeUse]; + [a setupChannel:@"foo-channel"]; + [a setupFeature:@"foo-feature"]; + [a setupStage:@"foo-stage"]; + [a setupParams:@{ @"foo-key": @"foo-value" }]; + [a setupMatchDuration:1]; + [a setupIgnoreUAString:@"foo-ua"]; + + BNCLinkData *b = [[BNCLinkData alloc] init]; + [b setupTags:@[ @"bar-tag" ]]; + [b setupAlias:@"bar-alias"]; + [b setupType:BranchLinkTypeUnlimitedUse]; + [b setupChannel:@"bar-channel"]; + [b setupFeature:@"bar-feature"]; + [b setupStage:@"bar-stage"]; + [b setupParams:@{ @"bar-key": @"bar-value" }]; + [b setupMatchDuration:2]; + [b setupIgnoreUAString:@"bar-ua"]; + + XCTAssertNotEqual([a hash], [b hash]); +} + +- (void)testObjectHashWithDifferentCasedValues { + BNCLinkData *a = [[BNCLinkData alloc] init]; + [a setupAlias:@"foo-alias"]; + BNCLinkData *b = [[BNCLinkData alloc] init]; + [b setupAlias:@"FOO-ALIAS"]; + + XCTAssertNotEqual([a hash], [b hash]); +} + +@end diff --git a/BranchSDKTests/BNCNetworkInterfaceTests.m b/BranchSDKTests/BNCNetworkInterfaceTests.m new file mode 100644 index 000000000..8869ecc37 --- /dev/null +++ b/BranchSDKTests/BNCNetworkInterfaceTests.m @@ -0,0 +1,82 @@ +// +// BNCNetworkInterfaceTests.m +// Branch-SDK-Tests +// +// Created by Ernest Cho on 3/10/23. +// Copyright © 2023 Branch, Inc. All rights reserved. +// + +#import +#import +#import "BNCNetworkInterface.h" + +// Category using inet_pton to validate +@implementation NSString (Test) + +- (BOOL)isValidIPAddress { + const char *utf8 = [self UTF8String]; + int success; + + struct in_addr dst; + success = inet_pton(AF_INET, utf8, &dst); + if (success != 1) { + struct in6_addr dst6; + success = inet_pton(AF_INET6, utf8, &dst6); + } + + return success == 1; +} + +@end + +@interface BNCNetworkInterfaceTests : XCTestCase + +@end + +@implementation BNCNetworkInterfaceTests + +- (void)setUp { + +} + +- (void)tearDown { + +} + +// verify tooling method works +- (void)testIPValidationCategory { + XCTAssert(![@"" isValidIPAddress]); + + // ipv4 + XCTAssert([@"0.0.0.0" isValidIPAddress]); + XCTAssert([@"127.0.0.1" isValidIPAddress]); + XCTAssert([@"10.1.2.3" isValidIPAddress]); + XCTAssert([@"172.0.0.0" isValidIPAddress]); + XCTAssert([@"192.0.0.0" isValidIPAddress]); + XCTAssert([@"255.255.255.255" isValidIPAddress]); + + // invalid ipv4 + XCTAssert(![@"-1.0.0.0" isValidIPAddress]); + XCTAssert(![@"256.0.0.0" isValidIPAddress]); + + // ipv6 + XCTAssert([@"2001:0db8:0000:0000:0000:8a2e:0370:7334" isValidIPAddress]); + XCTAssert([@"2001:db8::8a2e:370:7334" isValidIPAddress]); + + // invalid ipv6 + XCTAssert(![@"2001:0db8:0000:0000:0000:8a2e:0370:733g" isValidIPAddress]); + XCTAssert(![@"2001:0db8:0000:0000:0000:8a2e:0370:7330:1234" isValidIPAddress]); +} + +- (void)testLocalIPAddress { + XCTAssert([[BNCNetworkInterface localIPAddress] isValidIPAddress]); +} + +- (void)testAllIPAddresses { + // All IP addresses is a debug method that returns object descriptions + for (NSString *address in BNCNetworkInterface.allIPAddresses) { + XCTAssert([address containsString:@"BNCNetworkInterface"]); + } +} + +@end diff --git a/BranchSDKTests/BNCODMTests.m b/BranchSDKTests/BNCODMTests.m new file mode 100644 index 000000000..38d1b0cc2 --- /dev/null +++ b/BranchSDKTests/BNCODMTests.m @@ -0,0 +1,102 @@ +// +// BNCODMTests.m +// Branch-SDK-Tests +// +// Created by Nidhi Dixit on 4/16/25. +// Copyright © 2025 Branch, Inc. All rights reserved. +// + +#import +#import "Branch.h" +#import "BNCPreferenceHelper.h" +#import "BNCRequestFactory.h" +#import "BNCEncodingUtils.h" +#import "BNCODMInfoCollector.h" +#import "NSError+Branch.h" + +@interface BNCODMTests : XCTestCase +@property (nonatomic, strong, readwrite) BNCPreferenceHelper *prefHelper; +@end + +@implementation BNCODMTests + +- (void)setUp { + _prefHelper = [BNCPreferenceHelper sharedInstance]; +} + +- (void)testSetODM { + NSString *odm = @"testODMString"; + NSDate *firstOpenTS = [NSDate date]; + [Branch setODMInfo:odm andFirstOpenTimestamp:firstOpenTS]; + XCTAssertTrue([_prefHelper.odmInfo isEqualToString:odm]); + XCTAssertTrue([_prefHelper.odmInfoInitDate isEqualToDate:firstOpenTS]); + +} + +- (void)testSetODMandSDKRequests { + NSString* requestUUID = [[NSUUID UUID ] UUIDString]; + NSNumber* requestCreationTimeStamp = BNCWireFormatFromDate([NSDate date]); + NSString *odm = @"testODMString"; + NSDate *firstOpenTS = [NSDate date]; + + [Branch setODMInfo:odm andFirstOpenTimestamp:firstOpenTS]; + + [[Branch getInstance] setConsumerProtectionAttributionLevel:BranchAttributionLevelFull]; + BNCRequestFactory *factory = [[BNCRequestFactory alloc] initWithBranchKey:@"key_abcd" UUID:requestUUID TimeStamp:requestCreationTimeStamp]; + NSDictionary *jsonInstall = [factory dataForInstallWithURLString:@"https://branch.io"]; + XCTAssertTrue([odm isEqualToString:[jsonInstall objectForKey:@"odm_info"]]); + + NSDictionary *jsonOpen = [factory dataForOpenWithURLString:@"https://branch.io"]; + XCTAssertTrue([odm isEqualToString:[jsonOpen objectForKey:@"odm_info"]]); + + NSDictionary *event = @{@"name": @"ADD_TO_CART"}; + NSDictionary *jsonEvent = [factory dataForEventWithEventDictionary:[event mutableCopy]]; + XCTAssertTrue([jsonEvent objectForKey:@"odm_info"] == nil); + + [[Branch getInstance] setConsumerProtectionAttributionLevel:BranchAttributionLevelReduced]; + jsonInstall = [factory dataForInstallWithURLString:@"https://branch.io"]; + XCTAssertTrue([jsonInstall objectForKey:@"odm_info"] == nil); + + jsonOpen = [factory dataForOpenWithURLString:@"https://branch.io"]; + XCTAssertTrue([jsonOpen objectForKey:@"odm_info"] == nil); + + self.prefHelper.odmInfo = nil; + self.prefHelper.odmInfoInitDate = nil; +} + +- (void)testODMTimeOut { + + NSString* requestUUID = [[NSUUID UUID ] UUIDString]; + NSNumber* requestCreationTimeStamp = BNCWireFormatFromDate([NSDate date]); + NSString *odm = @"testODMString"; + NSDate *firstOpenTS = [[NSDate date] dateByAddingTimeInterval:-((180*24*3600) - 5)]; + + [Branch setODMInfo:odm andFirstOpenTimestamp:firstOpenTS]; + + [[Branch getInstance] setConsumerProtectionAttributionLevel:BranchAttributionLevelFull]; + BNCRequestFactory *factory = [[BNCRequestFactory alloc] initWithBranchKey:@"key_abcd" UUID:requestUUID TimeStamp:requestCreationTimeStamp]; + NSDictionary *jsonInstall = [factory dataForInstallWithURLString:@"https://branch.io"]; + XCTAssertTrue([odm isEqualToString:[jsonInstall objectForKey:@"odm_info"]]); + + sleep(10); + + NSDictionary *jsonOpen = [factory dataForOpenWithURLString:@"https://branch.io"]; + XCTAssertTrue(![odm isEqualToString:[jsonOpen objectForKey:@"odm_info"]]); + + self.prefHelper.odmInfo = nil; + self.prefHelper.odmInfoInitDate = nil; + +} + + +- (void) testODMAPIsNotLoaded { + XCTestExpectation *expectation = [self expectationWithDescription:@"Check if ODCManager class is loaded."]; + [[BNCODMInfoCollector instance ] loadODMInfoWithTimeOut:DISPATCH_TIME_FOREVER andCompletionHandler:^(NSString * _Nullable odmInfo, NSError * _Nullable error) { + if (error.code == BNCClassNotFoundError){ + [expectation fulfill]; + } + }]; + [self waitForExpectationsWithTimeout:15 handler:nil]; +} + +@end diff --git a/BranchSDKTests/BNCPartnerParametersTests.m b/BranchSDKTests/BNCPartnerParametersTests.m new file mode 100644 index 000000000..7fad38ac2 --- /dev/null +++ b/BranchSDKTests/BNCPartnerParametersTests.m @@ -0,0 +1,219 @@ +// +// BNCPartnerParametersTests.m +// Branch-SDK-Tests +// +// Created by Ernest Cho on 12/9/20. +// Copyright © 2020 Branch, Inc. All rights reserved. +// + +#import +#import "BNCPartnerParameters.h" + +// expose private methods for testing +@interface BNCPartnerParameters() +- (BOOL)sha256HashSanityCheckValue:(NSString *)value; +- (BOOL)isStringHex:(NSString *)string; +@end + +@interface BNCPartnerParametersTests : XCTestCase +@property (nonatomic, strong, readwrite) BNCPartnerParameters *partnerParams; +@end + +@implementation BNCPartnerParametersTests + +- (void)setUp { + self.partnerParams = [BNCPartnerParameters new]; +} + +- (void)tearDown { + +} + +- (void)testStringHexNil { + XCTAssertFalse([self.partnerParams isStringHex:nil]); +} + +- (void)testStringHexEmpty { + XCTAssertTrue([self.partnerParams isStringHex:@""]); +} + +- (void)testStringHexDash { + XCTAssertFalse([self.partnerParams isStringHex:@"-1"]); +} + +- (void)testStringHexDecimal { + XCTAssertFalse([self.partnerParams isStringHex:@"1.0"]); +} + +- (void)testStringHexFraction { + XCTAssertFalse([self.partnerParams isStringHex:@"2/4"]); +} + +- (void)testStringHexAt { + XCTAssertFalse([self.partnerParams isStringHex:@"test@12345"]); +} + +- (void)testStringHexUpperG { + XCTAssertFalse([self.partnerParams isStringHex:@"0123456789ABCDEFG"]); +} + +- (void)testStringHexLowerG { + XCTAssertFalse([self.partnerParams isStringHex:@"0123456789abcdefg"]); +} + +- (void)testStringHexUpperCase { + XCTAssertTrue([self.partnerParams isStringHex:@"0123456789ABCDEF"]); +} + +- (void)testStringHexLowerCase { + XCTAssertTrue([self.partnerParams isStringHex:@"0123456789abcdef"]); +} + +- (void)testSha256HashSanityCheckValueNil { + XCTAssertFalse([self.partnerParams sha256HashSanityCheckValue:nil]); +} + +- (void)testSha256HashSanityCheckValueEmpty { + XCTAssertFalse([self.partnerParams sha256HashSanityCheckValue:@""]); +} + +- (void)testSha256HashSanityCheckValueTooShort { + // 63 char string + XCTAssertFalse([self.partnerParams sha256HashSanityCheckValue:@"1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcde"]); +} + +- (void)testSha256HashSanityCheckValueTooLong { + // 65 char string + XCTAssertFalse([self.partnerParams sha256HashSanityCheckValue:@"1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdeff"]); +} + +- (void)testSha256HashSanityCheckValueLowerCase { + // 64 char string + XCTAssertTrue([self.partnerParams sha256HashSanityCheckValue:@"1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"]); +} + +- (void)testSha256HashSanityCheckValueUpperCase { + // 64 char string + XCTAssertTrue([self.partnerParams sha256HashSanityCheckValue:@"0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF"]); +} + +- (void)testSha256HashSanityCheckValueMixedCase { + // 64 char string + XCTAssertTrue([self.partnerParams sha256HashSanityCheckValue:@"0123456789ABCDEF0123456789ABCDEF1234567890abcdef1234567890abcdef"]); +} + +- (void)testJsonEmpty { + NSString *jsonString = [self jsonStringFromDictionary:[self.partnerParams parameterJson]]; + XCTAssertTrue([@"{}" isEqualToString:jsonString]); +} + +- (void)testJsonFBParameterEmpty { + [self.partnerParams addFacebookParameterWithName:@"em" value:@""]; + NSString *jsonString = [self jsonStringFromDictionary:[self.partnerParams parameterJson]]; + XCTAssertTrue([@"{}" isEqualToString:jsonString]); +} + +- (void)testJsonFBParameterShort { + [self.partnerParams addFacebookParameterWithName:@"em" value:@"0123456789ABCDEF0123456789ABCDEF1234567890abcdef1234567890abcde"]; + NSString *jsonString = [self jsonStringFromDictionary:[self.partnerParams parameterJson]]; + XCTAssertTrue([@"{}" isEqualToString:jsonString]); +} + +- (void)testJsonFBParameterPhoneNumberIsIgnored { + [self.partnerParams addFacebookParameterWithName:@"em" value:@"1-555-555-5555"]; + NSString *jsonString = [self jsonStringFromDictionary:[self.partnerParams parameterJson]]; + XCTAssertTrue([@"{}" isEqualToString:jsonString]); +} + +- (void)testJsonFBParameterEmailIsIgnored { + [self.partnerParams addFacebookParameterWithName:@"em" value:@"test@branch.io"]; + NSString *jsonString = [self jsonStringFromDictionary:[self.partnerParams parameterJson]]; + XCTAssertTrue([@"{}" isEqualToString:jsonString]); +} + +- (void)testJsonFBParameterBase64EncodedIsIgnored { + // 123456789012345678901234567890123456789012345678 -> MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4 + [self.partnerParams addFacebookParameterWithName:@"em" value:@"MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4"]; + NSString *jsonString = [self jsonStringFromDictionary:[self.partnerParams parameterJson]]; + XCTAssertTrue([@"{}" isEqualToString:jsonString]); +} + +- (void)testJsonFBParameterHashedValue { + [self.partnerParams addFacebookParameterWithName:@"em" value:@"11234e56af071e9c79927651156bd7a10bca8ac34672aba121056e2698ee7088"]; + NSString *jsonString = [self jsonStringFromDictionary:[self.partnerParams parameterJson]]; + XCTAssertTrue([@"{\"fb\":{\"em\":\"11234e56af071e9c79927651156bd7a10bca8ac34672aba121056e2698ee7088\"}}" isEqualToString:jsonString]); +} + +- (void)testJsonFBParameterExample { + [self.partnerParams addFacebookParameterWithName:@"em" value:@"11234e56af071e9c79927651156bd7a10bca8ac34672aba121056e2698ee7088"]; + [self.partnerParams addFacebookParameterWithName:@"ph" value:@"b90598b67534f00b1e3e68e8006631a40d24fba37a3a34e2b84922f1f0b3b29b"]; + NSString *jsonString = [self jsonStringFromDictionary:[self.partnerParams parameterJson]]; + + XCTAssertTrue([@"{\"fb\":{\"ph\":\"b90598b67534f00b1e3e68e8006631a40d24fba37a3a34e2b84922f1f0b3b29b\",\"em\":\"11234e56af071e9c79927651156bd7a10bca8ac34672aba121056e2698ee7088\"}}" isEqualToString:jsonString]); +} + +- (void)testJsonSnapParameterExample { + [self.partnerParams addSnapParameterWithName:@"hashed_email_address" value:@"11234e56af071e9c79927651156bd7a10bca8ac34672aba121056e2698ee7088"]; + [self.partnerParams addSnapParameterWithName:@"hashed_phone_number" value:@"b90598b67534f00b1e3e68e8006631a40d24fba37a3a34e2b84922f1f0b3b29b"]; + NSString *jsonString = [self jsonStringFromDictionary:[self.partnerParams parameterJson]]; + + XCTAssertTrue([@"{\"snap\":{\"hashed_phone_number\":\"b90598b67534f00b1e3e68e8006631a40d24fba37a3a34e2b84922f1f0b3b29b\",\"hashed_email_address\":\"11234e56af071e9c79927651156bd7a10bca8ac34672aba121056e2698ee7088\"}}" isEqualToString:jsonString]); +} + + +- (void)testJsonMultipleParameterExample { + [self.partnerParams addFacebookParameterWithName:@"em" value:@"11234e56af071e9c79927651156bd7a10bca8ac34672aba121056e2698ee7088"]; + [self.partnerParams addFacebookParameterWithName:@"ph" value:@"b90598b67534f00b1e3e68e8006631a40d24fba37a3a34e2b84922f1f0b3b29b"]; + [self.partnerParams addSnapParameterWithName:@"hashed_email_address" value:@"11234e56af071e9c79927651156bd7a10bca8ac34672aba121056e2698ee7088"]; + [self.partnerParams addSnapParameterWithName:@"hashed_phone_number" value:@"b90598b67534f00b1e3e68e8006631a40d24fba37a3a34e2b84922f1f0b3b29b"]; + NSString *jsonString = [self jsonStringFromDictionary:[self.partnerParams parameterJson]]; + + NSString *expectedJsonString = @"{\"snap\":{\"hashed_phone_number\":\"b90598b67534f00b1e3e68e8006631a40d24fba37a3a34e2b84922f1f0b3b29b\",\"hashed_email_address\":\"11234e56af071e9c79927651156bd7a10bca8ac34672aba121056e2698ee7088\"},\"fb\":{\"ph\":\"b90598b67534f00b1e3e68e8006631a40d24fba37a3a34e2b84922f1f0b3b29b\",\"em\":\"11234e56af071e9c79927651156bd7a10bca8ac34672aba121056e2698ee7088\"}}"; + + XCTAssertTrue([expectedJsonString isEqualToString:jsonString]); +} + +- (void)testParameterClear { + [self.partnerParams addFacebookParameterWithName:@"em" value:@"11234e56af071e9c79927651156bd7a10bca8ac34672aba121056e2698ee7088"]; + [self.partnerParams addFacebookParameterWithName:@"ph" value:@"b90598b67534f00b1e3e68e8006631a40d24fba37a3a34e2b84922f1f0b3b29b"]; + [self.partnerParams addSnapParameterWithName:@"hashed_email_address" value:@"11234e56af071e9c79927651156bd7a10bca8ac34672aba121056e2698ee7088"]; + [self.partnerParams addSnapParameterWithName:@"hashed_phone_number" value:@"b90598b67534f00b1e3e68e8006631a40d24fba37a3a34e2b84922f1f0b3b29b"]; + [self.partnerParams clearAllParameters]; + + NSString *jsonString = [self jsonStringFromDictionary:[self.partnerParams parameterJson]]; + XCTAssertTrue([@"{}" isEqualToString:jsonString]); +} + +// sanity check test func on an empty dictionary +- (void)testEmptyJson { + NSString *jsonString = [self jsonStringFromDictionary:@{}]; + XCTAssertTrue([@"{}" isEqualToString:jsonString]); +} + +// sanity check test func on the sample json dictionary +- (void)testSampleJson { + NSString *jsonString = [self jsonStringFromDictionary:@{ + @"fb": @{ + @"ph": @"b90598b67534f00b1e3e68e8006631a40d24fba37a3a34e2b84922f1f0b3b29b", + @"em": @"11234e56af071e9c79927651156bd7a10bca8ac34672aba121056e2698ee7088" + } + }]; + + XCTAssertTrue([@"{\"fb\":{\"ph\":\"b90598b67534f00b1e3e68e8006631a40d24fba37a3a34e2b84922f1f0b3b29b\",\"em\":\"11234e56af071e9c79927651156bd7a10bca8ac34672aba121056e2698ee7088\"}}" isEqualToString:jsonString] || [@"{\"fb\":{\"em\":\"11234e56af071e9c79927651156bd7a10bca8ac34672aba121056e2698ee7088\",\"ph\":\"b90598b67534f00b1e3e68e8006631a40d24fba37a3a34e2b84922f1f0b3b29b\"}}" isEqualToString:jsonString]); +} + +// There is an assumption that this code always results in the same string for the same json data. +// This appears to be true, but I haven't found documentation to confirm it. +- (NSString *)jsonStringFromDictionary:(NSDictionary *)dictionary { + NSError *error; + NSData *json = [NSJSONSerialization dataWithJSONObject:dictionary options:0 error:&error]; + + if (!error) { + NSString *tmp = [[NSString alloc] initWithData:json encoding:NSUTF8StringEncoding]; + return tmp; + } else { + return @""; + } +} + +@end diff --git a/BranchSDKTests/BNCPasteboardTests.m b/BranchSDKTests/BNCPasteboardTests.m new file mode 100644 index 000000000..6a3a4d69c --- /dev/null +++ b/BranchSDKTests/BNCPasteboardTests.m @@ -0,0 +1,170 @@ +// +// BNCPasteboardTests.m +// Branch-SDK-Tests +// +// Created by Ernest Cho on 7/19/21. +// Copyright © 2021 Branch, Inc. All rights reserved. +// + +#import +#import "BNCPasteboard.h" +#import "Branch.h" + +@interface BNCPasteboardTests : XCTestCase + +@property (nonatomic, assign, readwrite) NSString *testString; +@property (nonatomic, strong, readwrite) NSURL *testBranchURL; + +@end + +@implementation BNCPasteboardTests + +- (void)setUp { + // Put setup code here. This method is called before the invocation of each test method in the class. + self.testString = @"Pasteboard String"; + self.testBranchURL = [NSURL URLWithString:@"https://123.app.link"]; +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. +} + +- (void)addStringToPasteboard { +#if !TARGET_OS_TV + [UIPasteboard.generalPasteboard setString:self.testString]; +#endif +} + +- (void)addBranchURLToPasteboard { +#if !TARGET_OS_TV + [UIPasteboard.generalPasteboard setURL:self.testBranchURL]; +#endif +} + +- (void)addNonBranchURLToPasteboard { +#if !TARGET_OS_TV + [UIPasteboard.generalPasteboard setURL:[NSURL URLWithString:@"https://www.apple.com"]]; +#endif +} + +- (void)clearPasteboard { +#if !TARGET_OS_TV + // cannot delete items from the pasteboard, but we can put something else on there + [[UIPasteboard generalPasteboard] setString:@""]; +#endif +} + +- (NSString *)getStringFromClipboard { + NSString *string = nil; +#if !TARGET_OS_TV + string = [UIPasteboard.generalPasteboard string]; +#endif + return string; +} + +- (NSURL *)getURLFromPasteboard { + NSURL *url = nil; +#if !TARGET_OS_TV + url = [UIPasteboard.generalPasteboard URL]; +#endif + return url; +} + +- (void)testStringUtilityMethods { + + // set and retrieve a string + [self addStringToPasteboard]; + NSString *tmp = [self getStringFromClipboard]; + XCTAssert([self.testString isEqualToString:tmp]); + + // overwrite the pasteboard + [self clearPasteboard]; + tmp = [self getStringFromClipboard]; + XCTAssert([@"" isEqualToString:tmp]); +} + +- (void)testURLUtilityMethods { + + // set and retrieve a url + [self addBranchURLToPasteboard]; + NSURL *tmp = [self getURLFromPasteboard]; + XCTAssert([self.testBranchURL.absoluteString isEqualToString:tmp.absoluteString]); + + // overwrite the pasteboard + [self clearPasteboard]; + tmp = [self getURLFromPasteboard]; + XCTAssertNil(tmp); +} + +- (void)testDefaultState { + // host app sets this to true, should consider a no-op test host + XCTAssertFalse([BNCPasteboard sharedInstance].checkOnInstall); +} + +- (void)testIsUrlOnPasteboard { + XCTAssertFalse([[BNCPasteboard sharedInstance] isUrlOnPasteboard]); + + [self addBranchURLToPasteboard]; + XCTAssertTrue([[BNCPasteboard sharedInstance] isUrlOnPasteboard]); + + [self clearPasteboard]; + XCTAssertFalse([[BNCPasteboard sharedInstance] isUrlOnPasteboard]); +} + +- (void)testCheckForBranchLink { + [self addBranchURLToPasteboard]; + XCTAssertTrue([[BNCPasteboard sharedInstance] isUrlOnPasteboard]); + + NSURL *tmp = [[BNCPasteboard sharedInstance] checkForBranchLink]; + XCTAssert([self.testBranchURL.absoluteString isEqualToString:tmp.absoluteString]); + + [self clearPasteboard]; +} + +- (void)testCheckForBranchLink_nonBranchLink { + [self addNonBranchURLToPasteboard]; + XCTAssertTrue([[BNCPasteboard sharedInstance] isUrlOnPasteboard]); + + NSURL *tmp = [[BNCPasteboard sharedInstance] checkForBranchLink]; + XCTAssertNil(tmp); + + [self clearPasteboard]; +} + +- (void)testCheckForBranchLink_noLink { + [self addStringToPasteboard]; + XCTAssertFalse([[BNCPasteboard sharedInstance] isUrlOnPasteboard]); + + NSURL *tmp = [[BNCPasteboard sharedInstance] checkForBranchLink]; + XCTAssertNil(tmp); + + [self clearPasteboard]; +} + +#if 0 +// This test fails intermittently when executed with other tests - depending upon the order in which its executed +- (void) testPassPasteControl { +#if !TARGET_OS_TV + if (@available(iOS 16.0, macCatalyst 16.0, *)) { + + long long timeStamp = ([[NSDate date] timeIntervalSince1970] - 5*60)*1000; // 5 minute earlier timestamp + NSString *urlString = [NSString stringWithFormat:@"https://bnctestbed-alternate.app.link/9R7MbTmnRtb?__branch_flow_type=viewapp&__branch_flow_id=1105940563590163783&__branch_mobile_deepview_type=1&nl_opt_in=1&_cpts=%lld", timeStamp]; + NSURL *testURL = [[NSURL alloc] initWithString:urlString]; + + NSArray *itemProviders = @[[[NSItemProvider alloc] initWithItem:testURL typeIdentifier:UTTypeURL.identifier]]; + XCTestExpectation *openExpectation = [self expectationWithDescription:@"Test open"]; + + [[Branch getInstance] initSessionWithLaunchOptions:@{} andRegisterDeepLinkHandler:^(NSDictionary *params, NSError *error) { + [openExpectation fulfill]; + XCTAssertNil(error); + }]; + + [[Branch getInstance] passPasteItemProviders:itemProviders]; + [self waitForExpectationsWithTimeout:5.0 handler:NULL]; + + } +#endif +} +#endif + +@end diff --git a/BranchSDKTests/BNCPreferenceHelperTests.m b/BranchSDKTests/BNCPreferenceHelperTests.m new file mode 100644 index 000000000..5269501b3 --- /dev/null +++ b/BranchSDKTests/BNCPreferenceHelperTests.m @@ -0,0 +1,417 @@ +// +// BNCPreferenceHelperTests.m +// Branch-TestBed +// +// Created by Graham Mueller on 4/2/15. +// Copyright (c) 2015 Branch Metrics. All rights reserved. +// + +#import +#import "BNCPreferenceHelper.h" +#import "BNCEncodingUtils.h" +#import "Branch.h" +#import "BNCConfig.h" + +@interface BNCPreferenceHelper() + +// expose private methods for testing +- (NSMutableDictionary *)deserializePrefDictFromData:(NSData *)data; +- (NSData *)serializePrefDict:(NSMutableDictionary *)dict; + +@end + +@interface BNCPreferenceHelperTests : XCTestCase +@property (nonatomic, strong, readwrite) BNCPreferenceHelper *prefHelper; +@end + +@implementation BNCPreferenceHelperTests + +- (void)setUp { + self.prefHelper = [BNCPreferenceHelper new]; +} + +- (void)tearDown { + +} + +- (void)testPreferenceDefaults { + XCTAssertEqual(self.prefHelper.timeout, 5.5); + XCTAssertEqual(self.prefHelper.retryInterval, 0); + XCTAssertEqual(self.prefHelper.retryCount, 3); + XCTAssertFalse(self.prefHelper.disableAdNetworkCallouts); +} + +- (void)testPreferenceSets { + self.prefHelper.retryCount = NSIntegerMax; + self.prefHelper.retryInterval = NSIntegerMax; + self.prefHelper.timeout = NSIntegerMax; + + XCTAssertEqual(self.prefHelper.retryCount, NSIntegerMax); + XCTAssertEqual(self.prefHelper.retryInterval, NSIntegerMax); + XCTAssertEqual(self.prefHelper.timeout, NSIntegerMax); +} + +// This test is not reliable when run concurrently with other tests that set the patterListURL +- (void)testURLFilter { + XCTAssertTrue([@"https://cdn.branch.io" isEqualToString:self.prefHelper.patternListURL]); + + NSString *customURL = @"https://banned.branch.io"; + self.prefHelper.patternListURL = customURL; + XCTAssertTrue([customURL isEqualToString:self.prefHelper.patternListURL]); +} + +- (void)testSerializeDict_Nil { + NSMutableDictionary *dict = nil; + NSData *data = [self.prefHelper serializePrefDict:dict]; + XCTAssert(data == nil); +} + +- (void)testSerializeDict_Empty { + NSMutableDictionary *dict = [NSMutableDictionary new]; + NSData *data = [self.prefHelper serializePrefDict:dict]; + NSMutableDictionary *tmp = [self.prefHelper deserializePrefDictFromData:data]; + + XCTAssert(tmp != nil); + XCTAssert([tmp isKindOfClass:NSMutableDictionary.class]); + XCTAssert(tmp.count == 0); +} + +- (void)testSerializeDict_String { + NSMutableDictionary *dict = [NSMutableDictionary new]; + NSString *value = @"the quick brown fox jumps over the lazy dog"; + NSString *key = @"test"; + [dict setObject:value forKey:key]; + + NSData *data = [self.prefHelper serializePrefDict:dict]; + NSMutableDictionary *tmp = [self.prefHelper deserializePrefDictFromData:data]; + + XCTAssert(tmp != nil); + XCTAssert([tmp isKindOfClass:NSMutableDictionary.class]); + XCTAssert(tmp.count == 1); + + XCTAssert([[tmp objectForKey:key] isEqualToString:value]); +} + +- (void)testSerializeDict_Date { + NSMutableDictionary *dict = [NSMutableDictionary new]; + NSDate *value = [NSDate date]; + NSString *key = @"test"; + [dict setObject:value forKey:key]; + + NSData *data = [self.prefHelper serializePrefDict:dict]; + NSMutableDictionary *tmp = [self.prefHelper deserializePrefDictFromData:data]; + + XCTAssert(tmp != nil); + XCTAssert([tmp isKindOfClass:NSMutableDictionary.class]); + XCTAssert(tmp.count == 1); + + XCTAssert([[tmp objectForKey:key] isEqual:value]); +} + +- (void)testSerializeDict_Bool { + NSMutableDictionary *dict = [NSMutableDictionary new]; + bool value = YES; + NSString *key = @"test"; + [dict setObject:@(value) forKey:key]; + + NSData *data = [self.prefHelper serializePrefDict:dict]; + NSMutableDictionary *tmp = [self.prefHelper deserializePrefDictFromData:data]; + + XCTAssert(tmp != nil); + XCTAssert([tmp isKindOfClass:NSMutableDictionary.class]); + XCTAssert(tmp.count == 1); + + XCTAssert([[tmp objectForKey:key] isEqual:@(value)]); +} + +- (void)testSerializeDict_Integer { + NSMutableDictionary *dict = [NSMutableDictionary new]; + NSInteger value = 1234; + NSString *key = @"test"; + [dict setObject:@(value) forKey:key]; + + NSData *data = [self.prefHelper serializePrefDict:dict]; + NSMutableDictionary *tmp = [self.prefHelper deserializePrefDictFromData:data]; + + XCTAssert(tmp != nil); + XCTAssert([tmp isKindOfClass:NSMutableDictionary.class]); + XCTAssert(tmp.count == 1); + + XCTAssert([[tmp objectForKey:key] isEqual:@(value)]); +} + +- (void)testSerializeDict_All { + NSMutableDictionary *dict = [NSMutableDictionary new]; + + NSString *value1 = @"the quick brown fox jumps over the lazy dog"; + NSString *key1 = @"test1"; + [dict setObject:value1 forKey:key1]; + + NSDate *value2 = [NSDate date]; + NSString *key2 = @"test2"; + [dict setObject:value2 forKey:key2]; + + bool value3 = YES; + NSString *key3 = @"test3"; + [dict setObject:@(value3) forKey:key3]; + + NSInteger value4 = 1234; + NSString *key4 = @"test4"; + [dict setObject:@(value4) forKey:key4]; + + NSData *data = [self.prefHelper serializePrefDict:dict]; + NSMutableDictionary *tmp = [self.prefHelper deserializePrefDictFromData:data]; + + XCTAssert(tmp != nil); + XCTAssert([tmp isKindOfClass:NSMutableDictionary.class]); + XCTAssert(tmp.count == 4); + + XCTAssert([[tmp objectForKey:key1] isEqualToString:value1]); + XCTAssert([[tmp objectForKey:key2] isEqual:value2]); + XCTAssert([[tmp objectForKey:key3] isEqual:@(value3)]); + XCTAssert([[tmp objectForKey:key4] isEqual:@(value4)]); +} + +- (void)testURLSkipList { + NSMutableDictionary *dict = [NSMutableDictionary new]; + NSString *key = @"test"; + NSArray *value = @[ + @"^fb\\d+:", + @"^li\\d+:", + @"^pdk\\d+:", + @"^twitterkit-.*:", + @"^com\\.googleusercontent\\.apps\\.\\d+-.*:\\/oauth", + @"^(?i)(?!(http|https):).*(:|:.*\\b)(password|o?auth|o?auth.?token|access|access.?token)\\b", + @"^(?i)((http|https):\\/\\/).*[\\/|?|#].*\\b(password|o?auth|o?auth.?token|access|access.?token)\\b", + ]; + [dict setObject:value forKey:key]; + NSData *data = [self.prefHelper serializePrefDict:dict]; + + NSMutableDictionary *tmp = [self.prefHelper deserializePrefDictFromData:data]; + + XCTAssert(tmp != nil); + XCTAssert([tmp isKindOfClass:NSMutableDictionary.class]); + + NSArray *filter = [tmp objectForKey:key]; + + NSString *filterDesc = filter.description; + NSString *valueDesc = value.description; + XCTAssert([filterDesc isEqualToString:valueDesc]); +} + +- (void)testSetCDNBaseURL_Example { + + NSString *url = @"https://www.example.com/"; + [self.prefHelper setPatternListURL:url]; + + NSString *urlStored = self.prefHelper.patternListURL ; + XCTAssert([url isEqualToString:urlStored]); +} + +- (void)testSetCDNBaseURL_InvalidHttp { + + NSString *url = @"Invalid://www.example.com/"; + [self.prefHelper setPatternListURL:url] ; + + NSString *urlStored = self.prefHelper.patternListURL ; + XCTAssert(![url isEqualToString:urlStored]); + XCTAssert([urlStored isEqualToString:BNC_CDN_URL]); +} + +- (void)testSetCDNBaseURL_InvalidEmpty { + + [self.prefHelper setPatternListURL:@""] ; + + NSString *urlStored = self.prefHelper.patternListURL ; + XCTAssert(![urlStored isEqualToString:@""]); + XCTAssert([urlStored isEqualToString:BNC_CDN_URL]); +} + +- (void)testSetPatternListURL { + NSString *expectedURL = @"https://example.com"; + [self.prefHelper setPatternListURL:expectedURL]; + + NSString *patternListURL = self.prefHelper.patternListURL; + XCTAssert([patternListURL isEqualToString: expectedURL]); +} + +- (void)testSetLastStrongMatchDate { + NSDate *expectedDate = [NSDate date]; + [self.prefHelper setLastStrongMatchDate: expectedDate]; + + NSDate *actualDate = [self.prefHelper lastStrongMatchDate]; + XCTAssertEqualObjects(expectedDate, actualDate); +} + +- (void)testSetAppVersion { + NSString *expectedVersion = @"1.0.0"; + [self.prefHelper setAppVersion: expectedVersion]; + + NSString *actualVersion = [self.prefHelper appVersion]; + XCTAssertEqualObjects(expectedVersion, actualVersion); +} + +- (void)testSetLocalUrl { + NSString *expectedLocalURL = @"https://local.example.com"; + [self.prefHelper setLocalUrl:expectedLocalURL]; + + NSString *localURL = [self.prefHelper localUrl]; + XCTAssertEqualObjects(localURL, expectedLocalURL); +} + +- (void)testSetInitialReferrer { + NSString *expectedReferrer = @"referrer.example.com"; + [self.prefHelper setInitialReferrer:expectedReferrer]; + + NSString *actualReferrer = [self.prefHelper initialReferrer]; + XCTAssertEqualObjects(actualReferrer, expectedReferrer); +} + +- (void)testSetAppleAttributionTokenChecked { + BOOL expectedValue = YES; + [self.prefHelper setAppleAttributionTokenChecked:expectedValue]; + + BOOL actualValue = [self.prefHelper appleAttributionTokenChecked]; + XCTAssertEqual(expectedValue, actualValue); +} + +- (void)testSetHasOptedInBefore { + BOOL expectedValue = YES; + [self.prefHelper setHasOptedInBefore:expectedValue]; + + BOOL actualValue = [self.prefHelper hasOptedInBefore]; + XCTAssertEqual(expectedValue, actualValue); +} + +- (void)testSetHasCalledHandleATTAuthorizationStatus { + BOOL expectedValue = YES; + [self.prefHelper setHasCalledHandleATTAuthorizationStatus:expectedValue]; + + BOOL actualValue = [self.prefHelper hasCalledHandleATTAuthorizationStatus]; + XCTAssertEqual(expectedValue, actualValue); +} + +- (void)testSetRequestMetadataKeyValidKeyValue { + NSString *key = @"testKey"; + NSString *value = @"testValue"; + + [self.prefHelper setRequestMetadataKey:key value:value]; + + NSObject *retrievedValue = [self.prefHelper.requestMetadataDictionary objectForKey:key]; + XCTAssertEqualObjects(retrievedValue, value); +} + +- (void)testSetRequestMetadataKeyValidKeyNilValue { + NSString *key = @"testKey"; + NSString *value = @"testValue"; + + [self.prefHelper.requestMetadataDictionary setObject:value forKey:key]; + + [self.prefHelper setRequestMetadataKey:key value:nil]; + + NSObject *retrievedValue = [self.prefHelper.requestMetadataDictionary objectForKey:key]; + XCTAssertNil(retrievedValue); +} + +- (void)testSetRequestMetadataKeyValidKeyNilValueKeyNotExists { + NSString *key = @"testKeyNotExists"; + + NSUInteger initialDictCount = [self.prefHelper.requestMetadataDictionary count]; + + [self.prefHelper setRequestMetadataKey:key value:nil]; + + NSUInteger postActionDictCount = [self.prefHelper.requestMetadataDictionary count]; + XCTAssertEqual(initialDictCount, postActionDictCount); +} + +- (void)testSetRequestMetadataKeyNilKey { + NSString *value = @"testValue"; + NSUInteger initialDictCount = [self.prefHelper.requestMetadataDictionary count]; + + [self.prefHelper setRequestMetadataKey:nil value:value]; + + NSUInteger postActionDictCount = [self.prefHelper.requestMetadataDictionary count]; + XCTAssertEqual(initialDictCount, postActionDictCount); +} + +- (void)testSetLimitFacebookTracking { + BOOL expectedValue = YES; + + [self.prefHelper setLimitFacebookTracking:expectedValue]; + + BOOL storedValue = [self.prefHelper limitFacebookTracking]; + + XCTAssertEqual(expectedValue, storedValue); +} + +- (void)testSetTrackingDisabled_YES { + [self.prefHelper setTrackingDisabled:YES]; + + BOOL storedValue = [self.prefHelper trackingDisabled]; + XCTAssertTrue(storedValue); + [self.prefHelper setTrackingDisabled:NO]; +} + +- (void)testSetTrackingDisabled_NO { + [self.prefHelper setTrackingDisabled:NO]; + + BOOL storedValue = [self.prefHelper trackingDisabled]; + XCTAssertFalse(storedValue); +} + +// TODO: rethink this test as these values are not set in a freshly instantiated prefHelper +- (void)testClearTrackingInformation { + [self.prefHelper clearTrackingInformation]; + + XCTAssertNil(self.prefHelper.sessionID); + XCTAssertNil(self.prefHelper.linkClickIdentifier); + XCTAssertNil(self.prefHelper.spotlightIdentifier); + XCTAssertNil(self.prefHelper.referringURL); + XCTAssertNil(self.prefHelper.universalLinkUrl); + XCTAssertNil(self.prefHelper.initialReferrer); + XCTAssertNil(self.prefHelper.installParams); + XCTAssertNil(self.prefHelper.sessionParams); + XCTAssertNil(self.prefHelper.externalIntentURI); + XCTAssertNil(self.prefHelper.savedAnalyticsData); + XCTAssertNil(self.prefHelper.previousAppBuildDate); + XCTAssertEqual(self.prefHelper.requestMetadataDictionary.count, 0); + XCTAssertNil(self.prefHelper.lastStrongMatchDate); + XCTAssertNil(self.prefHelper.userIdentity); + XCTAssertNil(self.prefHelper.referringURLQueryParameters); + XCTAssertNil(self.prefHelper.anonID); +} + +- (void)testSaveBranchAnalyticsData { + NSString *dummySessionID = @"testSession123"; + NSDictionary *dummyAnalyticsData = @{ @"key1": @"value1", @"key2": @"value2" }; + + self.prefHelper.sessionID = dummySessionID; + + [self.prefHelper saveBranchAnalyticsData:dummyAnalyticsData]; + + NSMutableDictionary *retrievedData = [self.prefHelper getBranchAnalyticsData]; + + NSArray *viewDataArray = [retrievedData objectForKey:dummySessionID]; + XCTAssertNotNil(viewDataArray); + XCTAssertEqual(viewDataArray.count, 1); + XCTAssertEqualObjects(viewDataArray.firstObject, dummyAnalyticsData); +} + +- (void)testClearBranchAnalyticsData { + [self.prefHelper clearBranchAnalyticsData]; + + NSMutableDictionary *retrievedData = [self.prefHelper getBranchAnalyticsData]; + XCTAssertEqual(retrievedData.count, 0); +} + +- (void)testSaveContentAnalyticsManifest { + NSDictionary *dummyManifest = @{ @"manifestKey1": @"manifestValue1", @"manifestKey2": @"manifestValue2" }; + + [self.prefHelper saveContentAnalyticsManifest:dummyManifest]; + + NSDictionary *retrievedManifest = [self.prefHelper getContentAnalyticsManifest]; + + XCTAssertEqualObjects(retrievedManifest, dummyManifest); +} + +@end diff --git a/BranchSDKTests/BNCReachabilityTests.m b/BranchSDKTests/BNCReachabilityTests.m new file mode 100644 index 000000000..3f159c1e3 --- /dev/null +++ b/BranchSDKTests/BNCReachabilityTests.m @@ -0,0 +1,45 @@ +// +// BNCReachabilityTests.m +// Branch-SDK-Tests +// +// Created by Ernest Cho on 11/18/19. +// Copyright © 2019 Branch, Inc. All rights reserved. +// + +#import +#import "BNCReachability.h" + +@interface BNCReachabilityTests : XCTestCase +@property (nonatomic, strong, readwrite) BNCReachability *reachability; +@end + +@implementation BNCReachabilityTests + +- (void)setUp { + self.reachability = [BNCReachability new]; +} + +- (void)tearDown { + +} + +- (void)testSimulator_WIFI { + NSString *status = [self.reachability reachabilityStatus]; + XCTAssertNotNil(status); + XCTAssert([@"wifi" isEqualToString:status]); +} + +// Only works on a device with cell +//- (void)testDevice_Cell { +// NSString *status = [self.reachability reachabilityStatus]; +// XCTAssertNotNil(status); +// XCTAssert([@"mobile" isEqualToString:status]); +//} + +// Only works on a device in Airplane mode +//- (void)testDevice_AirplaneMode { +// NSString *status = [self.reachability reachabilityStatus]; +// XCTAssertNil(status); +//} + +@end diff --git a/BranchSDKTests/BNCReferringURLUtilityTests.m b/BranchSDKTests/BNCReferringURLUtilityTests.m new file mode 100644 index 000000000..b76f91b4d --- /dev/null +++ b/BranchSDKTests/BNCReferringURLUtilityTests.m @@ -0,0 +1,538 @@ +// +// BNCReferringURLUtilityTests.m +// Branch-SDK-Tests +// +// Created by Nipun Singh on 3/9/23. +// Copyright © 2023 Branch, Inc. All rights reserved. +// + +#import +#import "BNCReferringURLUtility.h" +#import "BNCUrlQueryParameter.h" +#import "BNCPreferenceHelper.h" + +@interface BNCReferringURLUtility(Test) +// expose the private data structure so tests can clear it +@property (strong, readwrite, nonatomic) NSMutableDictionary *urlQueryParameters; + +// expose private methods to test data migration +- (void)checkForAndMigrateOldGbraid; +@end + +@interface BNCReferringURLUtilityTests : XCTestCase + +@end + +@implementation BNCReferringURLUtilityTests + +// test constants +static NSString *openEndpoint = @"/v1/open"; +static NSString *eventEndpoint = @"/v2/event"; + ++ (void)tearDown { + // clear test data from global storage + [BNCPreferenceHelper sharedInstance].referringURLQueryParameters = nil; + [BNCPreferenceHelper sharedInstance].referrerGBRAID = nil; + [BNCPreferenceHelper sharedInstance].referrerGBRAIDValidityWindow = 0; + [BNCPreferenceHelper sharedInstance].referrerGBRAIDInitDate = nil; +} + +// workaround for BNCPreferenceHelper being persistent across tests and not currently mockable +- (BNCReferringURLUtility *)referringUtilityForTests { + BNCReferringURLUtility *utility = [BNCReferringURLUtility new]; + utility.urlQueryParameters = [NSMutableDictionary new]; + return utility; +} + +// make gbraid equality check simpler by excluding timestamp +- (NSDictionary *)removeTimestampFromParams:(NSDictionary *)params { + NSMutableDictionary *paramsWithoutTimestamp = [params mutableCopy]; + paramsWithoutTimestamp[@"gbraid_timestamp"] = nil; + return paramsWithoutTimestamp; +} + +// gbraid timestamp is a string representing time in millis +- (void)validateGbraidTimestampInReferringParameters:(NSDictionary *)params { + id timestamp = params[@"gbraid_timestamp"]; + XCTAssert(timestamp != nil); + XCTAssert([timestamp isKindOfClass:NSString.class]); +} + +- (void)expireValidityWindowsInUtility:(BNCReferringURLUtility *)utility { + for (NSString *paramName in utility.urlQueryParameters.allKeys) { + BNCUrlQueryParameter *param = utility.urlQueryParameters[paramName]; + + // currently the longest validity window is 30 days + NSTimeInterval sixtyDaysAgo = -1 * 60 * 24 * 60 * 60; + param.timestamp = [NSDate dateWithTimeIntervalSinceNow:sixtyDaysAgo]; + } +} + +- (void)testReferringURLWithNoParams { + NSURL *url = [NSURL URLWithString:@"https://bnctestbed.app.link"]; + NSDictionary *expected = @{}; + + BNCReferringURLUtility *utility = [self referringUtilityForTests]; + [utility parseReferringURL:url]; + NSDictionary *params = [utility referringURLQueryParamsForEndpoint:openEndpoint]; + + XCTAssert([expected isEqualToDictionary:params]); +} + +- (void)testNilReferringURL { + NSURL *url = nil; + NSDictionary *expected = @{}; + + BNCReferringURLUtility *utility = [self referringUtilityForTests]; + [utility parseReferringURL:url]; + NSDictionary *params = [utility referringURLQueryParamsForEndpoint:openEndpoint]; + + XCTAssert([expected isEqualToDictionary:params]); +} + +- (void)testReferringURLIgnoredParam { + NSURL *url = [NSURL URLWithString:@"https://bnctestbed.app.link?other=12345"]; + NSDictionary *expected = @{ }; + + BNCReferringURLUtility *utility = [self referringUtilityForTests]; + [utility parseReferringURL:url]; + NSDictionary *params = [utility referringURLQueryParamsForEndpoint:openEndpoint]; + + XCTAssert([expected isEqualToDictionary:params]); +} + +- (void)testReferringURLWithGclid { + NSURL *url = [NSURL URLWithString:@"https://bnctestbed.app.link?gclid=12345"]; + NSDictionary *expected = @{ + @"gclid": @"12345" + }; + + BNCReferringURLUtility *utility = [self referringUtilityForTests]; + [utility parseReferringURL:url]; + NSDictionary *params = [utility referringURLQueryParamsForEndpoint:openEndpoint]; + + XCTAssert([expected isEqualToDictionary:params]); +} + +// NSURL treats URI schemes in a consistent manner with Universal Links +- (void)testReferringURLWithURISchemeSanityCheck{ + NSURL *url = [NSURL URLWithString:@"branchtest://?gclid=12345"]; + NSDictionary *expected = @{ + @"gclid": @"12345" + }; + + BNCReferringURLUtility *utility = [self referringUtilityForTests]; + [utility parseReferringURL:url]; + NSDictionary *params = [utility referringURLQueryParamsForEndpoint:openEndpoint]; + + XCTAssert([expected isEqualToDictionary:params]); +} + +- (void)testReferringURLWithGclidCapitalized { + NSURL *url = [NSURL URLWithString:@"https://bnctestbed.app.link?GCLID=12345"]; + NSDictionary *expected = @{ + @"gclid": @"12345" + }; + + BNCReferringURLUtility *utility = [self referringUtilityForTests]; + [utility parseReferringURL:url]; + NSDictionary *params = [utility referringURLQueryParamsForEndpoint:openEndpoint]; + + XCTAssert([expected isEqualToDictionary:params]); +} + +- (void)testReferringURLWithGclidMixedCase { + NSURL *url = [NSURL URLWithString:@"https://bnctestbed.app.link?GcLiD=12345"]; + NSDictionary *expected = @{ + @"gclid": @"12345" + }; + + BNCReferringURLUtility *utility = [self referringUtilityForTests]; + [utility parseReferringURL:url]; + NSDictionary *params = [utility referringURLQueryParamsForEndpoint:openEndpoint]; + + XCTAssert([expected isEqualToDictionary:params]); +} + +- (void)testReferringURLWithGclidNoValue { + NSURL *url = [NSURL URLWithString:@"https://bnctestbed.app.link?gclid="]; + NSDictionary *expected = @{ + @"gclid": @"" + }; + + BNCReferringURLUtility *utility = [self referringUtilityForTests]; + [utility parseReferringURL:url]; + NSDictionary *params = [utility referringURLQueryParamsForEndpoint:openEndpoint]; + + XCTAssert([expected isEqualToDictionary:params]); +} + +- (void)testReferringURLWithGclidValueCasePreserved { + NSURL *url = [NSURL URLWithString:@"https://bnctestbed.app.link?gclid=aAbBcC"]; + NSDictionary *expected = @{ + @"gclid": @"aAbBcC" + }; + + BNCReferringURLUtility *utility = [self referringUtilityForTests]; + [utility parseReferringURL:url]; + NSDictionary *params = [utility referringURLQueryParamsForEndpoint:openEndpoint]; + + XCTAssert([expected isEqualToDictionary:params]); +} + +- (void)testReferringURLWithGclidIgnoredParam { + NSURL *url = [NSURL URLWithString:@"https://bnctestbed.app.link?gclid=12345&other=abcde"]; + NSDictionary *expected = @{ + @"gclid": @"12345" + }; + + BNCReferringURLUtility *utility = [self referringUtilityForTests]; + [utility parseReferringURL:url]; + NSDictionary *params = [utility referringURLQueryParamsForEndpoint:openEndpoint]; + + XCTAssert([expected isEqualToDictionary:params]); +} + +- (void)testReferringURLWithGclidFragment{ + NSURL *url = [NSURL URLWithString:@"https://bnctestbed.app.link?gclid=12345#header"]; + NSDictionary *expected = @{ + @"gclid": @"12345" + }; + + BNCReferringURLUtility *utility = [self referringUtilityForTests]; + [utility parseReferringURL:url]; + NSDictionary *params = [utility referringURLQueryParamsForEndpoint:openEndpoint]; + + XCTAssert([expected isEqualToDictionary:params]); +} + +- (void)testReferringURLWithGclidAsFragment{ + NSURL *url = [NSURL URLWithString:@"https://bnctestbed.app.link?other=abcde#gclid=12345"]; + NSDictionary *expected = @{ }; + + BNCReferringURLUtility *utility = [self referringUtilityForTests]; + [utility parseReferringURL:url]; + NSDictionary *params = [utility referringURLQueryParamsForEndpoint:openEndpoint]; + + XCTAssert([expected isEqualToDictionary:params]); +} + +- (void)testReferringURLWithGclidOverwritesValue { + NSURL *url = [NSURL URLWithString:@"https://bnctestbed.app.link?gclid=12345"]; + NSDictionary *expected = @{ + @"gclid": @"12345" + }; + + NSURL *url2 = [NSURL URLWithString:@"https://bnctestbed.app.link?gclid=abcde"]; + NSDictionary *expected2 = @{ + @"gclid": @"abcde" + }; + + BNCReferringURLUtility *utility = [self referringUtilityForTests]; + [utility parseReferringURL:url]; + NSDictionary *params = [utility referringURLQueryParamsForEndpoint:openEndpoint]; + XCTAssert([expected isEqualToDictionary:params]); + + [utility parseReferringURL:url2]; + NSDictionary *params2 = [utility referringURLQueryParamsForEndpoint:openEndpoint]; + + XCTAssert([expected2 isEqualToDictionary:params2]); +} + +- (void)testReferringURLWithMetaCampaignIdsAndInvalidURL { + NSURL *url = [NSURL URLWithString:@"https://bnctestbed.app.link?al_applink_data=[]#target_url%22%3A%22http%3A%5C%2F%5C%2Fitunes.apple.com%5C%2Fapp%5C%2Fid880047117%22%2C%22extras%22%3A%7B%22fb_app_id%22%3A2020399148181142%7D%2C%22referer_app_link%22%3A%7B%22url%22%3A%22fb%3A%5C%2F%5C%2F%5C%2F%3Fapp_id%3D2020399148181142%22%2C%22app_name%22%3A%22Facebook%22%7D%2C%22acs_token%22%3A%22debuggingtoken%22%2C%22campaign_ids%22%3A%22ARFUlbyOurYrHT2DsknR7VksCSgN4tiH8TzG8RIvVoUQoYog5bVCvADGJil5kFQC6tQm-fFJQH0w8wCi3NbOmEHHrtgCNglkXNY-bECEL0aUhj908hIxnBB0tchJCqwxHjorOUqyk2v4bTF75PyWvxOksZ6uTzBmr7wJq8XnOav0bA%22%2C%22test_deeplink%22%3A1%7D"]; + NSDictionary *expected = @{}; + + BNCReferringURLUtility *utility = [self referringUtilityForTests]; + [utility parseReferringURL:url]; + NSDictionary *params = [utility referringURLQueryParamsForEndpoint:openEndpoint]; + + XCTAssert([expected isEqualToDictionary:params]); +} + +- (void)testReferringURLWithMetaCampaignIds { + NSURL *url = [NSURL URLWithString:@"https://bnctestbed.app.link?al_applink_data=%7B%22target_url%22%3A%22http%3A%5C%2F%5C%2Fitunes.apple.com%5C%2Fapp%5C%2Fid880047117%22%2C%22extras%22%3A%7B%22fb_app_id%22%3A2020399148181142%7D%2C%22referer_app_link%22%3A%7B%22url%22%3A%22fb%3A%5C%2F%5C%2F%5C%2F%3Fapp_id%3D2020399148181142%22%2C%22app_name%22%3A%22Facebook%22%7D%2C%22acs_token%22%3A%22debuggingtoken%22%2C%22campaign_ids%22%3A%22ARFUlbyOurYrHT2DsknR7VksCSgN4tiH8TzG8RIvVoUQoYog5bVCvADGJil5kFQC6tQm-fFJQH0w8wCi3NbOmEHHrtgCNglkXNY-bECEL0aUhj908hIxnBB0tchJCqwxHjorOUqyk2v4bTF75PyWvxOksZ6uTzBmr7wJq8XnOav0bA%22%2C%22test_deeplink%22%3A1%7D"]; + NSDictionary *expected = @{ + @"meta_campaign_ids": @"ARFUlbyOurYrHT2DsknR7VksCSgN4tiH8TzG8RIvVoUQoYog5bVCvADGJil5kFQC6tQm-fFJQH0w8wCi3NbOmEHHrtgCNglkXNY-bECEL0aUhj908hIxnBB0tchJCqwxHjorOUqyk2v4bTF75PyWvxOksZ6uTzBmr7wJq8XnOav0bA" + }; + + BNCReferringURLUtility *utility = [self referringUtilityForTests]; + [utility parseReferringURL:url]; + NSDictionary *params = [utility referringURLQueryParamsForEndpoint:openEndpoint]; + + XCTAssert([expected isEqualToDictionary:params]); +} + +- (void)testReferringURLWithMetaCampaignIdsExpired { + NSURL *url = [NSURL URLWithString:@"https://bnctestbed.app.link?al_applink_data=%7B%22target_url%22%3A%22http%3A%5C%2F%5C%2Fitunes.apple.com%5C%2Fapp%5C%2Fid880047117%22%2C%22extras%22%3A%7B%22fb_app_id%22%3A2020399148181142%7D%2C%22referer_app_link%22%3A%7B%22url%22%3A%22fb%3A%5C%2F%5C%2F%5C%2F%3Fapp_id%3D2020399148181142%22%2C%22app_name%22%3A%22Facebook%22%7D%2C%22acs_token%22%3A%22debuggingtoken%22%2C%22campaign_ids%22%3A%22ARFUlbyOurYrHT2DsknR7VksCSgN4tiH8TzG8RIvVoUQoYog5bVCvADGJil5kFQC6tQm-fFJQH0w8wCi3NbOmEHHrtgCNglkXNY-bECEL0aUhj908hIxnBB0tchJCqwxHjorOUqyk2v4bTF75PyWvxOksZ6uTzBmr7wJq8XnOav0bA%22%2C%22test_deeplink%22%3A1%7D"]; + NSDictionary *expected = @{ }; + + BNCReferringURLUtility *utility = [self referringUtilityForTests]; + [utility parseReferringURL:url]; + [self expireValidityWindowsInUtility:utility]; + NSDictionary *params = [utility referringURLQueryParamsForEndpoint:openEndpoint]; + + XCTAssert([expected isEqualToDictionary:params]); +} + +- (void)testReferringURLWithMetaNoCampaignIds { + NSURL *url = [NSURL URLWithString:@"https://bnctestbed.app.link?al_applink_data=%7B%22target_url%22%3A%22http%3A%5C%2F%5C%2Fitunes.apple.com%5C%2Fapp%5C%2Fid880047117%22%2C%22extras%22%3A%7B%22fb_app_id%22%3A2020399148181142%7D%2C%22referer_app_link%22%3A%7B%22url%22%3A%22fb%3A%5C%2F%5C%2F%5C%2F%3Fapp_id%3D2020399148181142%22%2C%22app_name%22%3A%22Facebook%22%7D%2C%22acs_token%22%3A%22debuggingtoken%22%2C%22test_deeplink%22%3A1%7D"]; + NSDictionary *expected = @{ }; + + BNCReferringURLUtility *utility = [self referringUtilityForTests]; + [utility parseReferringURL:url]; + NSDictionary *params = [utility referringURLQueryParamsForEndpoint:openEndpoint]; + + XCTAssert([expected isEqualToDictionary:params]); +} + +- (void)testReferringURLWithGbraid { + NSURL *url = [NSURL URLWithString:@"https://bnctestbed.app.link?gbraid=abcde"]; + NSDictionary *expected = @{ + @"gbraid": @"abcde", + @"is_deeplink_gbraid": @(true) + }; + + BNCReferringURLUtility *utility = [self referringUtilityForTests]; + [utility parseReferringURL:url]; + NSDictionary *params = [utility referringURLQueryParamsForEndpoint:openEndpoint]; + + [self validateGbraidTimestampInReferringParameters:params]; + NSDictionary *paramsWithoutTimestamp = [self removeTimestampFromParams:params]; + XCTAssert([expected isEqualToDictionary:paramsWithoutTimestamp]); +} + +- (void)testReferringURLWithGbraidOnEvent { + NSURL *url = [NSURL URLWithString:@"https://bnctestbed.app.link?gbraid=abcde"]; + NSDictionary *expected = @{ + @"gbraid": @"abcde" + }; + + BNCReferringURLUtility *utility = [self referringUtilityForTests]; + [utility parseReferringURL:url]; + NSDictionary *params = [utility referringURLQueryParamsForEndpoint:eventEndpoint]; + + [self validateGbraidTimestampInReferringParameters:params]; + NSDictionary *paramsWithoutTimestamp = [self removeTimestampFromParams:params]; + XCTAssert([expected isEqualToDictionary:paramsWithoutTimestamp]); +} + +- (void)testReferringURLWithGbraidExpired { + NSURL *url = [NSURL URLWithString:@"https://bnctestbed.app.link?gbraid=abcde"]; + NSDictionary *expected = @{ }; + + BNCReferringURLUtility *utility = [self referringUtilityForTests]; + [utility parseReferringURL:url]; + [self expireValidityWindowsInUtility:utility]; + NSDictionary *params = [utility referringURLQueryParamsForEndpoint:openEndpoint]; + + XCTAssert([expected isEqualToDictionary:params]); +} + +- (void)testReferringURLPreservesNonZeroValidityWindowForGbraid { + NSURL *url = [NSURL URLWithString:@"https://bnctestbed.app.link?gbraid=12345"]; + + BNCReferringURLUtility *utility = [self referringUtilityForTests]; + + // pretend this object was loaded from disk + // this simulates setting a custom non-zero validity window, only supported for gbraid + BNCUrlQueryParameter *existingParam = [BNCUrlQueryParameter new]; + existingParam.name = @"gbraid"; + existingParam.value = @""; + existingParam.timestamp = [NSDate date]; + existingParam.validityWindow = 5; // not the default gbraid window + utility.urlQueryParameters[@"gbraid"] = existingParam; + + [utility parseReferringURL:url]; + + // verify validity window was not changed + XCTAssert(utility.urlQueryParameters[@"gbraid"].validityWindow == 5); +} + +- (void)testReferringURLOverwritesZeroValidityWindowForGbraid { + NSURL *url = [NSURL URLWithString:@"https://bnctestbed.app.link?gbraid=12345"]; + + BNCReferringURLUtility *utility = [self referringUtilityForTests]; + + // pretend this object was loaded from disk + // for gbraid, or any param, we overwrite the 0 validity windows with the default + BNCUrlQueryParameter *existingParam = [BNCUrlQueryParameter new]; + existingParam.name = @"gbraid"; + existingParam.value = @""; + existingParam.timestamp = [NSDate date]; + existingParam.validityWindow = 0; + utility.urlQueryParameters[@"gbraid"] = existingParam; + + [utility parseReferringURL:url]; + + // verify validity window was changed + XCTAssert(utility.urlQueryParameters[@"gbraid"].validityWindow != 0); +} + +- (void)testReferringURLWithGclidGbraid { + NSURL *url = [NSURL URLWithString:@"https://bnctestbed.app.link?gclid=12345&gbraid=abcde"]; + NSDictionary *expected = @{ + @"gclid": @"12345", + @"gbraid": @"abcde", + @"is_deeplink_gbraid": @(true) + }; + + BNCReferringURLUtility *utility = [self referringUtilityForTests]; + [utility parseReferringURL:url]; + NSDictionary *params = [utility referringURLQueryParamsForEndpoint:openEndpoint]; + + [self validateGbraidTimestampInReferringParameters:params]; + NSDictionary *paramsWithoutTimestamp = [self removeTimestampFromParams:params]; + XCTAssert([expected isEqualToDictionary:paramsWithoutTimestamp]); +} + +- (void)testGbraidDataMigration { + // Manipulates the global BNCPreferenceHelper. + // This is not safe for concurrent unit tests, so only the happy path is tested. + [self clearCurrentQueryParameters]; + [self addOldGbraidData]; + + NSDictionary *expected = @{ + @"gbraid": @"abcde", + @"is_deeplink_gbraid": @(false) + }; + + BNCReferringURLUtility *utility = [BNCReferringURLUtility new]; + NSDictionary *params = [utility referringURLQueryParamsForEndpoint:openEndpoint]; + + [self validateGbraidTimestampInReferringParameters:params]; + NSDictionary *paramsWithoutTimestamp = [self removeTimestampFromParams:params]; + XCTAssert([expected isEqualToDictionary:paramsWithoutTimestamp]); + + [self verifyOldGbraidDataIsCleared]; +} + +- (void)clearCurrentQueryParameters { + [BNCPreferenceHelper sharedInstance].referringURLQueryParameters = nil; +} + +- (void)addOldGbraidData { + [BNCPreferenceHelper sharedInstance].referrerGBRAID = @"abcde"; + [BNCPreferenceHelper sharedInstance].referrerGBRAIDValidityWindow = 2592000; + [BNCPreferenceHelper sharedInstance].referrerGBRAIDInitDate = [NSDate date]; +} + +- (void)verifyOldGbraidDataIsCleared { + XCTAssertNil([BNCPreferenceHelper sharedInstance].referrerGBRAID); + XCTAssert([BNCPreferenceHelper sharedInstance].referrerGBRAIDValidityWindow == 0); + XCTAssertNil([BNCPreferenceHelper sharedInstance].referrerGBRAIDInitDate); +} + +- (void)testReferringURLWithSccid { + NSURL *url = [NSURL URLWithString:@"https://bnctestbed.app.link?sccid=12345"]; + NSDictionary *expected = @{ + @"sccid": @"12345" + }; + + BNCReferringURLUtility *utility = [self referringUtilityForTests]; + [utility parseReferringURL:url]; + NSDictionary *params = [utility referringURLQueryParamsForEndpoint:openEndpoint]; + + XCTAssert([expected isEqualToDictionary:params]); +} + +- (void)testReferringURLWithSccidMixedCase { + NSURL *url = [NSURL URLWithString:@"https://bnctestbed.app.link?ScCiD=12345"]; + NSDictionary *expected = @{ + @"sccid": @"12345" + }; + + BNCReferringURLUtility *utility = [self referringUtilityForTests]; + [utility parseReferringURL:url]; + NSDictionary *params = [utility referringURLQueryParamsForEndpoint:openEndpoint]; + + XCTAssert([expected isEqualToDictionary:params]); +} + +- (void)testReferringURLWithSccidNoValue { + NSURL *url = [NSURL URLWithString:@"https://bnctestbed.app.link?sccid="]; + NSDictionary *expected = @{ + @"sccid": @"" + }; + + BNCReferringURLUtility *utility = [self referringUtilityForTests]; + [utility parseReferringURL:url]; + NSDictionary *params = [utility referringURLQueryParamsForEndpoint:openEndpoint]; + + XCTAssert([expected isEqualToDictionary:params]); +} + +- (void)testReferringURLWithSccidValueCasePreserved { + NSURL *url = [NSURL URLWithString:@"https://bnctestbed.app.link?sccid=aAbBcC"]; + NSDictionary *expected = @{ + @"sccid": @"aAbBcC" + }; + + BNCReferringURLUtility *utility = [self referringUtilityForTests]; + [utility parseReferringURL:url]; + NSDictionary *params = [utility referringURLQueryParamsForEndpoint:openEndpoint]; + + XCTAssert([expected isEqualToDictionary:params]); +} + +- (void)testReferringURLWithSccidIgnoredParam { + NSURL *url = [NSURL URLWithString:@"https://bnctestbed.app.link?sccid=12345&other=abcde"]; + NSDictionary *expected = @{ + @"sccid": @"12345" + }; + + BNCReferringURLUtility *utility = [self referringUtilityForTests]; + [utility parseReferringURL:url]; + NSDictionary *params = [utility referringURLQueryParamsForEndpoint:openEndpoint]; + + XCTAssert([expected isEqualToDictionary:params]); +} + +- (void)testReferringURLWithSccidFragment{ + NSURL *url = [NSURL URLWithString:@"https://bnctestbed.app.link?sccid=12345#header"]; + NSDictionary *expected = @{ + @"sccid": @"12345" + }; + + BNCReferringURLUtility *utility = [self referringUtilityForTests]; + [utility parseReferringURL:url]; + NSDictionary *params = [utility referringURLQueryParamsForEndpoint:openEndpoint]; + + XCTAssert([expected isEqualToDictionary:params]); +} + +- (void)testReferringURLWithSccidAsFragment{ + NSURL *url = [NSURL URLWithString:@"https://bnctestbed.app.link?other=abcde#sccid=12345"]; + NSDictionary *expected = @{ }; + + BNCReferringURLUtility *utility = [self referringUtilityForTests]; + [utility parseReferringURL:url]; + NSDictionary *params = [utility referringURLQueryParamsForEndpoint:openEndpoint]; + + XCTAssert([expected isEqualToDictionary:params]); +} + +- (void)testReferringURLWithSccidOverwritesValue { + NSURL *url = [NSURL URLWithString:@"https://bnctestbed.app.link?sccid=12345"]; + NSDictionary *expected = @{ + @"sccid": @"12345" + }; + + NSURL *url2 = [NSURL URLWithString:@"https://bnctestbed.app.link?sccid=abcde"]; + NSDictionary *expected2 = @{ + @"sccid": @"abcde" + }; + + BNCReferringURLUtility *utility = [self referringUtilityForTests]; + [utility parseReferringURL:url]; + NSDictionary *params = [utility referringURLQueryParamsForEndpoint:openEndpoint]; + XCTAssert([expected isEqualToDictionary:params]); + + [utility parseReferringURL:url2]; + NSDictionary *params2 = [utility referringURLQueryParamsForEndpoint:openEndpoint]; + + XCTAssert([expected2 isEqualToDictionary:params2]); +} + + +@end diff --git a/BranchSDKTests/BNCRequestFactoryTests.m b/BranchSDKTests/BNCRequestFactoryTests.m new file mode 100644 index 000000000..c28d3b6e0 --- /dev/null +++ b/BranchSDKTests/BNCRequestFactoryTests.m @@ -0,0 +1,234 @@ +// +// BNCRequestFactoryTests.m +// Branch-SDK-Tests +// +// Created by Ernest Cho on 8/21/23. +// Copyright © 2023 Branch, Inc. All rights reserved. +// + +#import +#import "BNCRequestFactory.h" +#import "BranchConstants.h" +#import "BNCEncodingUtils.h" + +@interface BNCRequestFactoryTests : XCTestCase +@property (nonatomic, copy, readwrite) NSString *requestUUID; +@property (nonatomic, copy, readwrite) NSNumber *requestCreationTimeStamp; +@end + +@implementation BNCRequestFactoryTests + +- (void)setUp { + _requestUUID = [[NSUUID UUID ] UUIDString]; + _requestCreationTimeStamp = BNCWireFormatFromDate([NSDate date]); +} + +- (void)tearDown { + +} + +- (void)testInitWithBranchKeyNil { + BNCRequestFactory *factory = [[BNCRequestFactory alloc] initWithBranchKey:nil UUID:_requestUUID TimeStamp:_requestCreationTimeStamp]; + NSDictionary *json = [factory dataForInstallWithURLString:@"https://branch.io"]; + XCTAssertNotNil(json); + + // key is omitted when nil + XCTAssertNil([json objectForKey:@"branch_key"]); + XCTAssertTrue(self.requestCreationTimeStamp == [json objectForKey:BRANCH_REQUEST_KEY_REQUEST_CREATION_TIME_STAMP]); + XCTAssertTrue([self.requestUUID isEqualToString:[json objectForKey:BRANCH_REQUEST_KEY_REQUEST_UUID]]); +} + +- (void)testInitWithBranchKeyEmpty { + BNCRequestFactory *factory = [[BNCRequestFactory alloc] initWithBranchKey:@"" UUID:self.requestUUID TimeStamp:self.requestCreationTimeStamp]; + NSDictionary *json = [factory dataForInstallWithURLString:@"https://branch.io"]; + XCTAssertNotNil(json); + + // empty string is allowed + XCTAssertTrue([@"" isEqualToString:[json objectForKey:@"branch_key"]]); + + XCTAssertTrue(self.requestCreationTimeStamp == [json objectForKey:BRANCH_REQUEST_KEY_REQUEST_CREATION_TIME_STAMP]); + XCTAssertTrue([self.requestUUID isEqualToString:[json objectForKey:BRANCH_REQUEST_KEY_REQUEST_UUID]]); +} + +- (void)testInitWithBranchKey { + BNCRequestFactory *factory = [[BNCRequestFactory alloc] initWithBranchKey:@"key_abcd" UUID:self.requestUUID TimeStamp:self.requestCreationTimeStamp]; + NSDictionary *json = [factory dataForInstallWithURLString:@"https://branch.io"]; + XCTAssertNotNil(json); + XCTAssertTrue([@"key_abcd" isEqualToString:[json objectForKey:@"branch_key"]]); + + XCTAssertTrue(self.requestCreationTimeStamp == [json objectForKey:BRANCH_REQUEST_KEY_REQUEST_CREATION_TIME_STAMP]); + XCTAssertTrue([self.requestUUID isEqualToString:[json objectForKey:BRANCH_REQUEST_KEY_REQUEST_UUID]]); +} + +- (void)testDataForInstall { + BNCRequestFactory *factory = [[BNCRequestFactory alloc] initWithBranchKey:@"key_abcd" UUID:self.requestUUID TimeStamp:self.requestCreationTimeStamp]; + NSDictionary *json = [factory dataForInstallWithURLString:@"https://branch.io"]; + XCTAssertNotNil(json); + + XCTAssertTrue([@"key_abcd" isEqualToString:[json objectForKey:@"branch_key"]]); + XCTAssertNotNil([json objectForKey:@"sdk"]); + XCTAssertTrue([@"Apple" isEqualToString:[json objectForKey:@"brand"]]); + XCTAssertNotNil([json objectForKey:@"ios_vendor_id"]); + + // not present on installs + XCTAssertNil([json objectForKey:@"randomized_bundle_token"]); + + XCTAssertTrue(self.requestCreationTimeStamp == [json objectForKey:BRANCH_REQUEST_KEY_REQUEST_CREATION_TIME_STAMP]); + XCTAssertTrue([self.requestUUID isEqualToString:[json objectForKey:BRANCH_REQUEST_KEY_REQUEST_UUID]]); +} + +- (void)testDataForOpen { + BNCRequestFactory *factory = [[BNCRequestFactory alloc] initWithBranchKey:@"key_abcd" UUID:self.requestUUID TimeStamp:self.requestCreationTimeStamp]; + NSDictionary *json = [factory dataForOpenWithURLString:@"https://branch.io"]; + XCTAssertNotNil(json); + + XCTAssertTrue([@"key_abcd" isEqualToString:[json objectForKey:@"branch_key"]]); + XCTAssertNotNil([json objectForKey:@"sdk"]); + XCTAssertTrue([@"Apple" isEqualToString:[json objectForKey:@"brand"]]); + XCTAssertNotNil([json objectForKey:@"ios_vendor_id"]); + + // Present only on opens. Assumes test runs after the host app completes an install. + // This is not a reliable assumption on test runners + //XCTAssertNotNil([json objectForKey:@"randomized_bundle_token"]); + + XCTAssertTrue(self.requestCreationTimeStamp == [json objectForKey:BRANCH_REQUEST_KEY_REQUEST_CREATION_TIME_STAMP]); + XCTAssertTrue([self.requestUUID isEqualToString:[json objectForKey:BRANCH_REQUEST_KEY_REQUEST_UUID]]); +} + +- (void)testDataForEvent { + NSDictionary *event = @{@"name": @"ADD_TO_CART"}; + + BNCRequestFactory *factory = [[BNCRequestFactory alloc] initWithBranchKey:@"key_abcd" UUID:self.requestUUID TimeStamp:self.requestCreationTimeStamp]; + NSDictionary *json = [factory dataForEventWithEventDictionary:[event mutableCopy]]; + XCTAssertNotNil(json); + + XCTAssertTrue([@"ADD_TO_CART" isEqualToString:[json objectForKey:@"name"]]); + + NSDictionary *userData = [json objectForKey:@"user_data"]; + XCTAssertNotNil(userData); + XCTAssertNotNil([userData objectForKey:@"idfv"]); + + XCTAssertTrue(self.requestCreationTimeStamp == [json objectForKey:BRANCH_REQUEST_KEY_REQUEST_CREATION_TIME_STAMP]); + XCTAssertTrue([self.requestUUID isEqualToString:[json objectForKey:BRANCH_REQUEST_KEY_REQUEST_UUID]]); +} + +- (void)testDataForEventWithContentItem { + NSDictionary *event = @{ + @"name": @"ADD_TO_CART", + @"content_items": @[ + @{ + @"$og_title": @"TestTitle", + @"$quantity": @(2), + @"$product_name": @"TestProduct", + @"$price": @(10) + } + ] + }; + + BNCRequestFactory *factory = [[BNCRequestFactory alloc] initWithBranchKey:@"key_abcd" UUID:self.requestUUID TimeStamp:self.requestCreationTimeStamp]; + NSDictionary *json = [factory dataForEventWithEventDictionary:[event mutableCopy]]; + XCTAssertNotNil(json); + + XCTAssertTrue([@"ADD_TO_CART" isEqualToString:[json objectForKey:@"name"]]); + + NSDictionary *contentItems = [json objectForKey:@"content_items"]; + XCTAssertNotNil(contentItems); + XCTAssertTrue(contentItems.count == 1); + + NSDictionary *userData = [json objectForKey:@"user_data"]; + XCTAssertNotNil(userData); + XCTAssertNotNil([userData objectForKey:@"idfv"]); + + XCTAssertTrue(self.requestCreationTimeStamp == [json objectForKey:BRANCH_REQUEST_KEY_REQUEST_CREATION_TIME_STAMP]); + XCTAssertTrue([self.requestUUID isEqualToString:[json objectForKey:BRANCH_REQUEST_KEY_REQUEST_UUID]]); +} + +- (void)testDataForEventWithTwoContentItem { + NSDictionary *event = @{ + @"name": @"ADD_TO_CART", + @"content_items": @[ + @{ + @"$og_title": @"TestTitle1", + @"$quantity": @(2), + @"$product_name": @"TestProduct1", + @"$price": @(10) + }, + @{ + @"$og_title": @"TestTitle2", + @"$quantity": @(3), + @"$product_name": @"TestProduct2", + @"$price": @(20) + } + ] + }; + + BNCRequestFactory *factory = [[BNCRequestFactory alloc] initWithBranchKey:@"key_abcd" UUID:self.requestUUID TimeStamp:self.requestCreationTimeStamp]; + NSDictionary *json = [factory dataForEventWithEventDictionary:[event mutableCopy]]; + XCTAssertNotNil(json); + + XCTAssertTrue([@"ADD_TO_CART" isEqualToString:[json objectForKey:@"name"]]); + + NSDictionary *contentItems = [json objectForKey:@"content_items"]; + XCTAssertNotNil(contentItems); + XCTAssertTrue(contentItems.count == 2); + + NSDictionary *userData = [json objectForKey:@"user_data"]; + XCTAssertNotNil(userData); + XCTAssertNotNil([userData objectForKey:@"idfv"]); + + XCTAssertTrue(self.requestCreationTimeStamp == [json objectForKey:BRANCH_REQUEST_KEY_REQUEST_CREATION_TIME_STAMP]); + XCTAssertTrue([self.requestUUID isEqualToString:[json objectForKey:BRANCH_REQUEST_KEY_REQUEST_UUID]]); +} + +- (void)testDataForEventEmpty { + NSDictionary *event = @{}; + + BNCRequestFactory *factory = [[BNCRequestFactory alloc] initWithBranchKey:@"key_abcd" UUID:self.requestUUID TimeStamp:self.requestCreationTimeStamp]; + NSDictionary *json = [factory dataForEventWithEventDictionary:[event mutableCopy]]; + XCTAssertNotNil(json); + + XCTAssertNil([json objectForKey:@"name"]); + + NSDictionary *userData = [json objectForKey:@"user_data"]; + XCTAssertNotNil(userData); + XCTAssertNotNil([userData objectForKey:@"idfv"]); + + XCTAssertTrue(self.requestCreationTimeStamp == [json objectForKey:BRANCH_REQUEST_KEY_REQUEST_CREATION_TIME_STAMP]); + XCTAssertTrue([self.requestUUID isEqualToString:[json objectForKey:BRANCH_REQUEST_KEY_REQUEST_UUID]]); +} + +- (void)testDataForEventNil { + BNCRequestFactory *factory = [[BNCRequestFactory alloc] initWithBranchKey:@"key_abcd" UUID:self.requestUUID TimeStamp:self.requestCreationTimeStamp]; + NSDictionary *json = [factory dataForEventWithEventDictionary:nil]; + XCTAssertNotNil(json); + + XCTAssertNil([json objectForKey:@"name"]); + + NSDictionary *userData = [json objectForKey:@"user_data"]; + XCTAssertNotNil(userData); + XCTAssertNotNil([userData objectForKey:@"idfv"]); + + XCTAssertTrue(self.requestCreationTimeStamp == [json objectForKey:BRANCH_REQUEST_KEY_REQUEST_CREATION_TIME_STAMP]); + XCTAssertTrue([self.requestUUID isEqualToString:[json objectForKey:BRANCH_REQUEST_KEY_REQUEST_UUID]]); +} + + +- (void)testDataForShortURL { + BNCRequestFactory *factory = [[BNCRequestFactory alloc] initWithBranchKey:@"key_abcd" UUID:self.requestUUID TimeStamp:self.requestCreationTimeStamp]; + NSDictionary *json = [factory dataForShortURLWithLinkDataDictionary:@{}.mutableCopy isSpotlightRequest:NO]; + XCTAssertNotNil(json); + + XCTAssertTrue(self.requestCreationTimeStamp == [json objectForKey:BRANCH_REQUEST_KEY_REQUEST_CREATION_TIME_STAMP]); + XCTAssertTrue([self.requestUUID isEqualToString:[json objectForKey:BRANCH_REQUEST_KEY_REQUEST_UUID]]); +} + +- (void)testDataForLATD { + BNCRequestFactory *factory = [[BNCRequestFactory alloc] initWithBranchKey:@"key_abcd" UUID:self.requestUUID TimeStamp:self.requestCreationTimeStamp]; + NSDictionary *json = [factory dataForLATDWithDataDictionary:@{}.mutableCopy]; + XCTAssertNotNil(json); + + XCTAssertTrue(self.requestCreationTimeStamp == [json objectForKey:BRANCH_REQUEST_KEY_REQUEST_CREATION_TIME_STAMP]); + XCTAssertTrue([self.requestUUID isEqualToString:[json objectForKey:BRANCH_REQUEST_KEY_REQUEST_UUID]]); +} + +@end diff --git a/BranchSDKTests/BNCSKAdNetworkTests.m b/BranchSDKTests/BNCSKAdNetworkTests.m new file mode 100644 index 000000000..d71cf203a --- /dev/null +++ b/BranchSDKTests/BNCSKAdNetworkTests.m @@ -0,0 +1,264 @@ +// +// BNCSKAdNetworkTests.m +// Branch-SDK-Tests +// +// Created by Ernest Cho on 8/13/20. +// Copyright © 2020 Branch, Inc. All rights reserved. +// + +#import +#import "BNCSKAdNetwork.h" +#import "BranchEvent.h" + +// Expose private methods for testing +@interface BNCSKAdNetwork() + +@property (nonatomic, copy, readwrite) NSDate *installDate; + +- (BOOL)shouldAttemptSKAdNetworkCallout; + +@end + +@interface BranchEvent() + +// private BranchEvent methods used to check data before sending to network service. +- (NSDictionary *)buildEventDictionary; +- (BranchEventRequest *)buildRequestWithEventDictionary:(NSDictionary *)eventDictionary; + +@end + + +@interface BNCSKAdNetworkTests : XCTestCase + +@property (nonatomic, strong, readwrite) BNCSKAdNetwork *skAdNetwork; + +@end + +@implementation BNCSKAdNetworkTests + +- (void)setUp { + self.skAdNetwork = [BNCSKAdNetwork new]; + self.skAdNetwork.installDate = [NSDate date]; +} + +- (void)tearDown { + +} + +- (void)testDefaultMaxTimeout { + NSTimeInterval days; + if (@available(iOS 16.1, macCatalyst 16.1, *)) { + days = 3600.0 * 24.0 * 60.0; // one day + } else { + days = 3600.0 * 24.0; // one day + } + XCTAssertTrue(self.skAdNetwork.maxTimeSinceInstall == days); +} + +- (void)testShouldAttemptSKAdNetworkCallout { + XCTAssertTrue([self.skAdNetwork shouldAttemptSKAdNetworkCallout]); +} + +- (void)testShouldAttemptSKAdNetworkCalloutFalse { + self.skAdNetwork.maxTimeSinceInstall = 0.0; + XCTAssertFalse([self.skAdNetwork shouldAttemptSKAdNetworkCallout]); +} + +- (void)testPostbackCall { + + if (@available(iOS 16.1, macCatalyst 16.1, *)) { + self.skAdNetwork.maxTimeSinceInstall = 3600.0 * 24.0 * 60.0; + } else { + self.skAdNetwork.maxTimeSinceInstall = 3600.0 * 24.0; // one day + } + + XCTAssertTrue([self.skAdNetwork shouldAttemptSKAdNetworkCallout]); + + [[BNCSKAdNetwork sharedInstance] registerAppForAdNetworkAttribution]; + + BranchEvent *event = [BranchEvent standardEvent:BranchStandardEventInvite]; + NSDictionary *eventDictionary = [event buildEventDictionary]; + BranchEventRequest *request = [event buildRequestWithEventDictionary:eventDictionary]; + + XCTestExpectation *expectation = [self expectationWithDescription:@"TestPostback"]; + BNCServerResponse *openInstallResponse = [[BNCServerResponse alloc] init]; + + openInstallResponse.data = @{ @"update_conversion_value": @60 }; + request.completion = ^(NSDictionary*_Nullable response, NSError*_Nullable error){ + [expectation fulfill]; + }; + [request processResponse:openInstallResponse error:Nil]; + + [self waitForExpectationsWithTimeout:5.0 handler:nil]; +} + +- (void)testSKAN4ParamsDefaultValues { + + if (@available(iOS 16.1, macCatalyst 16.1, *)) { + NSString *coarseValue = [[BNCSKAdNetwork sharedInstance] getCoarseConversionValueFromDataResponse:@{}]; + XCTAssertTrue([coarseValue isEqualToString:@"low"]); + + BOOL isLocked = [[BNCSKAdNetwork sharedInstance] getLockedStatusFromDataResponse:@{}]; + XCTAssertFalse(isLocked); + + BOOL ascendingOnly = [[BNCSKAdNetwork sharedInstance] getAscendingOnlyFromDataResponse:@{}]; + XCTAssertTrue(ascendingOnly); + } +} + +- (void)testSKAN4ParamsValues { + + if (@available(iOS 16.1, macCatalyst 16.1, *)) { + + NSDictionary *response = @{@"update_conversion_value": @16, @"coarse_key": @"high", @"locked": @YES, @"ascending_only":@NO }; + BNCSKAdNetwork *adNetwork = [BNCSKAdNetwork sharedInstance]; + + NSString *coarseValue = [adNetwork getCoarseConversionValueFromDataResponse:response]; + XCTAssertTrue([coarseValue isEqualToString:@"high"]); + + BOOL isLocked = [adNetwork getLockedStatusFromDataResponse:response]; + XCTAssertTrue(isLocked); + + BOOL ascendingOnly = [adNetwork getAscendingOnlyFromDataResponse:response]; + XCTAssertFalse(ascendingOnly); + } +} + +- (void)testSKAN4CurrentWindow { + + BNCSKAdNetwork *adNetwork = [BNCSKAdNetwork sharedInstance]; + BNCPreferenceHelper *prefs = [BNCPreferenceHelper sharedInstance]; + + NSDate *currentDateAndTime = [NSDate date]; + prefs.firstAppLaunchTime = [currentDateAndTime dateByAddingTimeInterval:-30]; + NSInteger win = [adNetwork calculateSKANWindowForTime:currentDateAndTime]; + XCTAssertTrue(win == 1); + + win = [adNetwork calculateSKANWindowForTime: [ currentDateAndTime dateByAddingTimeInterval:24*3600*3 ]]; + XCTAssertTrue(win == 2); + + win = [adNetwork calculateSKANWindowForTime: [ currentDateAndTime dateByAddingTimeInterval:24*3600*10 ]]; + XCTAssertTrue(win == 3); + + win = [adNetwork calculateSKANWindowForTime: [ currentDateAndTime dateByAddingTimeInterval:24*3600*36 ]]; + XCTAssertTrue(win == 0); + + prefs.firstAppLaunchTime = nil; + [prefs synchronize]; + win = [adNetwork calculateSKANWindowForTime: currentDateAndTime]; + XCTAssertTrue(win == 0); +} + +- (void)testSKAN4HighestConversionValue { + + BNCSKAdNetwork *adNetwork = [BNCSKAdNetwork sharedInstance]; + BNCPreferenceHelper *prefs = [BNCPreferenceHelper sharedInstance]; + + prefs.highestConversionValueSent = 0; + prefs.skanCurrentWindow = 0; + NSDate *currentDateAndTime = [NSDate date]; + prefs.invokeRegisterApp = YES; + + prefs.firstAppLaunchTime = [currentDateAndTime dateByAddingTimeInterval:-30 ]; + [adNetwork shouldCallPostbackForDataResponse:@{}]; + XCTAssertTrue(prefs.highestConversionValueSent == 0); + + [adNetwork shouldCallPostbackForDataResponse:@{@"update_conversion_value": @6}]; + XCTAssertTrue(prefs.highestConversionValueSent == 6); + + [adNetwork shouldCallPostbackForDataResponse:@{@"update_conversion_value": @3}]; + XCTAssertTrue(prefs.highestConversionValueSent == 6); + + + prefs.firstAppLaunchTime = [currentDateAndTime dateByAddingTimeInterval:-24*3600*3 ]; + [adNetwork shouldCallPostbackForDataResponse:@{}]; + XCTAssertTrue(prefs.highestConversionValueSent == 0); +} + +- (void)testSKAN4ShouldCallPostback { + + BNCSKAdNetwork *adNetwork = [BNCSKAdNetwork sharedInstance]; + BNCPreferenceHelper *prefs = [BNCPreferenceHelper sharedInstance]; + + prefs.firstAppLaunchTime = nil; + [prefs synchronize]; + + NSDictionary *response = @{@"update_conversion_value": @16, @"coarse_key": @"high", @"locked": @YES, @"ascending_only":@NO }; + + BOOL shouldCall = [adNetwork shouldCallPostbackForDataResponse:response]; + XCTAssertFalse(shouldCall); + +} + +- (void)testSKAN4ShouldCallPostback2 { + + BNCSKAdNetwork *adNetwork = [BNCSKAdNetwork sharedInstance]; + BNCPreferenceHelper *prefs = [BNCPreferenceHelper sharedInstance]; + + prefs.invokeRegisterApp = YES; + prefs.highestConversionValueSent = 0; + prefs.firstAppLaunchTime = [NSDate date]; + prefs.skanCurrentWindow = 0; + [prefs synchronize]; + + NSMutableDictionary *response = [[NSMutableDictionary alloc] initWithDictionary: + @{@"update_conversion_value": @16, @"coarse_key": @"high", @"locked": @YES, @"ascending_only":@YES }]; + + BOOL shouldCall = [adNetwork shouldCallPostbackForDataResponse:response]; + XCTAssertTrue(shouldCall); + + shouldCall = [adNetwork shouldCallPostbackForDataResponse:response]; + XCTAssertFalse(shouldCall); + + response[@"update_conversion_value"] = @14; + shouldCall = [adNetwork shouldCallPostbackForDataResponse:response]; + XCTAssertFalse(shouldCall); + + response[@"update_conversion_value"] = @18; + shouldCall = [adNetwork shouldCallPostbackForDataResponse:response]; + XCTAssertTrue(shouldCall); + + prefs.firstAppLaunchTime = nil; + prefs.firstAppLaunchTime = [[NSDate date] dateByAddingTimeInterval:-24*3600*3]; + shouldCall = [adNetwork shouldCallPostbackForDataResponse:response]; + NSLog(@"Conv : %ld", prefs.highestConversionValueSent); + XCTAssertTrue(shouldCall); + + shouldCall = [adNetwork shouldCallPostbackForDataResponse:response]; + XCTAssertFalse(shouldCall); +} + +- (void)testSKAN4ShouldCallPostback3 { + BNCSKAdNetwork *adNetwork = [BNCSKAdNetwork sharedInstance]; + BNCPreferenceHelper *prefs = [BNCPreferenceHelper sharedInstance]; + + prefs.invokeRegisterApp = YES; + prefs.highestConversionValueSent = 0; + prefs.firstAppLaunchTime = [NSDate date]; + [prefs synchronize]; + + NSMutableDictionary *response = [[NSMutableDictionary alloc] initWithDictionary: + @{@"update_conversion_value": @16, @"coarse_key": @"high", @"locked": @YES, @"ascending_only":@NO }]; + + BOOL shouldCall = [adNetwork shouldCallPostbackForDataResponse:response]; + XCTAssertTrue(shouldCall); + + shouldCall = [adNetwork shouldCallPostbackForDataResponse:response]; + XCTAssertTrue(shouldCall); + + response[@"update_conversion_value"] = @14; + shouldCall = [adNetwork shouldCallPostbackForDataResponse:response]; + XCTAssertTrue(shouldCall); + + response[@"update_conversion_value"] = @18; + shouldCall = [adNetwork shouldCallPostbackForDataResponse:response]; + XCTAssertTrue(shouldCall); + + prefs.firstAppLaunchTime = [[NSDate date] dateByAddingTimeInterval:-24*3600*3]; + //NSLog(@"Conv : %ld", (long)prefs.highestConversionValueSent); + shouldCall = [adNetwork shouldCallPostbackForDataResponse:response]; + NSLog(@"Conv : %ld", prefs.highestConversionValueSent); + XCTAssertTrue(shouldCall); +} + +@end diff --git a/BranchSDKTests/BNCSystemObserverTests.m b/BranchSDKTests/BNCSystemObserverTests.m new file mode 100644 index 000000000..8cc54f632 --- /dev/null +++ b/BranchSDKTests/BNCSystemObserverTests.m @@ -0,0 +1,139 @@ +// +// BNCSystemObserverTests.m +// Branch-TestBed +// +// Created by Graham Mueller on 4/22/15. +// Copyright (c) 2015 Branch Metrics. All rights reserved. +// + +#import +#import "BNCSystemObserver.h" + +@interface BNCSystemObserver () ++ (BOOL)compareUriSchemes:(NSString *)serverUriScheme With:(NSArray *)urlTypes; +@end + +@interface BNCSystemObserverTests : XCTestCase + +@end + +@implementation BNCSystemObserverTests + +- (void)testDefaultURIScheme_TestBed { + //ND XCTAssert([[BNCSystemObserver defaultURIScheme] isEqualToString:@"branchtest"]); +} + +- (void)testAppVersion_TestBed { + XCTAssert([[BNCSystemObserver applicationVersion] isEqualToString:@"1.0"]); +} + +- (void)testBundleIdentifier_TestBed { + NSString *bundleId = [BNCSystemObserver bundleIdentifier]; + XCTAssert([bundleId isEqualToString:@"branch.BranchSDKTestsHostApp"]); +} + +- (void)testBrand { + XCTAssert([[BNCSystemObserver brand] isEqualToString:@"Apple"]); +} + +- (void)testModel_Simulator { + // simulator models + NSString *tmp = [BNCSystemObserver model]; + XCTAssert([tmp containsString:@"arm64"] || [tmp containsString:@"x86_64"]); +} + +//- (void)testModelName_iPhone7 { +// XCTAssert([@"iPhone9,3" isEqualToString:[BNCSystemObserver model]]); +//} + +- (void)testOSName { + XCTAssertNotNil([BNCSystemObserver osName]); + + // This is not the system name, but rather the name Branch server expects + // XCTAssert([self.deviceInfo.osName isEqualToString:[UIDevice currentDevice].systemName]); + XCTAssert([@"iOS" isEqualToString:[BNCSystemObserver osName]] || [@"tv_OS" isEqualToString:[BNCSystemObserver osName]]); +} + +- (void)testOSVersion { + XCTAssertNotNil([BNCSystemObserver osVersion]); + XCTAssert([[BNCSystemObserver osVersion] isEqualToString:[UIDevice currentDevice].systemVersion]); +} + +/* + * Sample device screens + * original iPhone 320x480 1 + * iPad Pro (6th gen 12.9") 2048x2732 2 + * iPhone 14 Pro max 1290x2796 3 + */ + +- (void)testScreenWidth { + XCTAssert([BNCSystemObserver screenWidth].intValue >= 320 && [BNCSystemObserver screenWidth].intValue <= 2796); +} + +- (void)testScreenHeight { + XCTAssert([BNCSystemObserver screenHeight].intValue >= 320 && [BNCSystemObserver screenWidth].intValue <= 2796); +} + +- (void)testScreenScale { + XCTAssert([BNCSystemObserver screenScale].intValue >= 1 && [BNCSystemObserver screenScale].intValue <= 3); +} + +- (void)testIsSimulator_Simulator { + XCTAssert([BNCSystemObserver isSimulator]); +} + +- (void)testAdvertiserIdentifier_NoATTPrompt { + XCTAssertNil([BNCSystemObserver advertiserIdentifier]); +} + +- (void)testOptedInStatus_NoATTPrompt { + XCTAssert([[BNCSystemObserver attOptedInStatus] isEqualToString:@"not_determined"]); +} + +- (void)testAppleAttributionToken_Simulator { + NSString *token = [BNCSystemObserver appleAttributionToken]; + XCTAssertNil(token); +} + +- (void)testEnvironment { + // currently not running unit tests on extensions + XCTAssert([@"FULL_APP" isEqualToString:[BNCSystemObserver environment]]); +} + +- (void)testIsAppClip { + // currently not running unit tests on extensions + XCTAssert(![BNCSystemObserver isAppClip]); +} + +- (void)testCompareURIScemes { + + NSString *serverUriScheme = @"bnctest://"; + NSArray *urlTypes = @[@{@"CFBundleURLSchemes" : @[@""]}, @{@"CFBundleURLSchemes" : @[@"bnctest", @"xyzs"]}]; + + XCTAssertTrue([BNCSystemObserver compareUriSchemes:serverUriScheme With:urlTypes]); + + XCTAssertFalse([BNCSystemObserver compareUriSchemes:serverUriScheme With:nil]); + + XCTAssertFalse([BNCSystemObserver compareUriSchemes:nil With:nil]); + + XCTAssertFalse([BNCSystemObserver compareUriSchemes:nil With:urlTypes]); + + serverUriScheme = @":/"; + XCTAssertFalse([BNCSystemObserver compareUriSchemes:serverUriScheme With:urlTypes]); + + serverUriScheme = @"bnctest"; + XCTAssertTrue([BNCSystemObserver compareUriSchemes:serverUriScheme With:urlTypes]); + + serverUriScheme = @"bnctest://"; + urlTypes = @[ @{@"CFBundleURLSchemes" : @[@"bnctestX", @"xyzs"]}]; + XCTAssertFalse([BNCSystemObserver compareUriSchemes:serverUriScheme With:urlTypes]); + + serverUriScheme = @"://"; + XCTAssertFalse([BNCSystemObserver compareUriSchemes:serverUriScheme With:urlTypes]); + + XCTAssertFalse([BNCSystemObserver compareUriSchemes:@"" With:urlTypes]); + + XCTAssertFalse([BNCSystemObserver compareUriSchemes:@"" With:@[@{}]]); +} + +@end diff --git a/BranchSDKTests/BNCURLFilterSkiplistUpgradeTests.m b/BranchSDKTests/BNCURLFilterSkiplistUpgradeTests.m new file mode 100644 index 000000000..ad7d5b029 --- /dev/null +++ b/BranchSDKTests/BNCURLFilterSkiplistUpgradeTests.m @@ -0,0 +1,273 @@ +// +// BNCURLFilterSkiplistUpgradeTests.m +// Branch-SDK-Tests +// +// Created by Ernest Cho on 4/4/23. +// Copyright © 2023 Branch, Inc. All rights reserved. +// + +#import +#import "BNCURLFilter.h" + +@interface BNCURLFilterSkiplistUpgradeTests : XCTestCase + +@end + +@implementation BNCURLFilterSkiplistUpgradeTests + +- (void)setUp { + +} + +- (void)tearDown { + +} + + // v0 list + // https://cdn.branch.io/sdk/uriskiplist_v0.json +- (NSArray *)v0PatternList { + NSArray *patternList = @[ + @"^fb\\d+:", + @"^li\\d+:", + @"^pdk\\d+:", + @"^twitterkit-.*:", + @"^com\\.googleusercontent\\.apps\\.\\d+-.*:\\/oauth", + @"^(?i)(?!(http|https):).*(:|:.*\\b)(password|o?auth|o?auth.?token|access|access.?token)\\b", + @"^(?i)((http|https):\\/\\/).*[\\/|?|#].*\\b(password|o?auth|o?auth.?token|access|access.?token)\\b" + ]; + return patternList; +} + +// v1 list +// https://cdn.branch.io/sdk/uriskiplist_v1.json +- (NSArray *)v1PatternList { + NSArray *patternList = @[ + @"^fb\\d+:", + @"^li\\d+:", + @"^pdk\\d+:", + @"^twitterkit-.*:", + @"^com\\.googleusercontent\\.apps\\.\\d+-.*:\\/oauth", + @"^(?i)(?!(http|https):).*(:|:.*\\b)(password|o?auth|o?auth.?token|access|access.?token)\\b", + @"^(?i)((http|https):\\/\\/).*[\\/|?|#].*\\b(password|o?auth|o?auth.?token|access|access.?token)\\b" + ]; + return patternList; +} + +// v2 list +// https://cdn.branch.io/sdk/uriskiplist_v2.json +- (NSArray *)v2PatternList { + NSArray *patternList = @[ + @"^fb\\d+:((?!campaign_ids).)*$", + @"^li\\d+:", + @"^pdk\\d+:", + @"^twitterkit-.*:", + @"^com\\.googleusercontent\\.apps\\.\\d+-.*:\\/oauth", + @"^(?i)(?!(http|https):).*(:|:.*\\b)(password|o?auth|o?auth.?token|access|access.?token)\\b", + @"^(?i)((http|https):\\/\\/).*[\\/|?|#].*\\b(password|o?auth|o?auth.?token|access|access.?token)\\b" + ]; + return patternList; +} + +- (BNCURLFilter *)filterWithV0List { + BNCURLFilter *filter = [BNCURLFilter new]; + [self migrateFilter:filter patternList:[self v1PatternList]]; + return filter; +} + +- (BNCURLFilter *)filterWithV1List { + BNCURLFilter *filter = [BNCURLFilter new]; + [self migrateFilter:filter patternList:[self v1PatternList]]; + return filter; +} + +- (BNCURLFilter *)filterWithV2List { + BNCURLFilter *filter = [BNCURLFilter new]; + [self migrateFilter:filter patternList:[self v2PatternList]]; + return filter; +} + +- (void)migrateFilter:(BNCURLFilter *)filter patternList:(NSArray *)patternList { + [filter useCustomPatternList:patternList]; +} + +- (NSArray *)badURLs { + NSArray *kBadURLs = @[ + @"fb123456:login/464646", + @"twitterkit-.4545:", + @"shsh:oauth/login", + @"https://myapp.app.link/oauth_token=fred", + @"https://myapp.app.link/auth_token=fred", + @"https://myapp.app.link/authtoken=fred", + @"https://myapp.app.link/auth=fred", + @"fb1234:", + @"fb1234:/", + @"fb1234:/this-is-some-extra-info/?whatever", + @"fb1234:/this-is-some-extra-info/?whatever:andstuff", + @"myscheme:path/to/resource?oauth=747474", + @"myscheme:oauth=747474", + @"myscheme:/oauth=747474", + @"myscheme://oauth=747474", + @"myscheme://path/oauth=747474", + @"myscheme://path/:oauth=747474", + @"https://google.com/userprofile/devonbanks=oauth?", + ]; + return kBadURLs; +} + +- (NSArray *)goodURLs { + NSArray *kGoodURLs = @[ + @"shshs:/content/path", + @"shshs:content/path", + @"https://myapp.app.link/12345/link", + @"fb123x:/", + @"https://myapp.app.link?authentic=true&tokemonsta=false", + @"myscheme://path/brauth=747474", + ]; + return kGoodURLs; +} + +- (void)testOldBadURLsWithV0 { + BNCURLFilter *filter = [self filterWithV0List]; + NSArray *list = [self badURLs]; + for (NSString *string in list) { + NSURL *url = [NSURL URLWithString:string]; + if (url) { + XCTAssertTrue([filter shouldIgnoreURL:url], @"Checking '%@'.", url); + } + } +} + +- (void)testOldGoodURLsWithV0 { + BNCURLFilter *filter = [self filterWithV0List]; + NSArray *list = [self goodURLs]; + for (NSString *string in list) { + NSURL *url = [NSURL URLWithString:string]; + if (url) { + XCTAssertFalse([filter shouldIgnoreURL:url], @"Checking '%@'.", url); + } + } +} + +- (void)testOldBadURLsWithV2 { + BNCURLFilter *filter = [self filterWithV2List]; + NSArray *list = [self badURLs]; + for (NSString *string in list) { + NSURL *url = [NSURL URLWithString:string]; + if (url) { + XCTAssertTrue([filter shouldIgnoreURL:url], @"Checking '%@'.", url); + } + } +} + +- (void)testOldGoodURLsWithV2 { + BNCURLFilter *filter = [self filterWithV2List]; + NSArray *list = [self goodURLs]; + for (NSString *string in list) { + NSURL *url = [NSURL URLWithString:string]; + if (url) { + XCTAssertFalse([filter shouldIgnoreURL:url], @"Checking '%@'.", url); + } + } +} + +- (void)testMetaAEMWithV0 { + NSString *string = @"fb1://?campaign_ids=a"; + NSURL *url = [NSURL URLWithString:string]; + if (url) { + BNCURLFilter *filter = [self filterWithV0List]; + XCTAssertTrue([filter shouldIgnoreURL:url]); + } +} + +- (void)testMetaAEMWithV2 { + NSString *string = @"fb1://?campaign_ids=a"; + NSURL *url = [NSURL URLWithString:string]; + if (url) { + BNCURLFilter *filter = [self filterWithV2List]; + XCTAssertFalse([filter shouldIgnoreURL:url]); + } +} + +- (void)testMetaAEMWithV2WithTrailingParameters { + NSString *string = @"fb1://?campaign_ids=a&token=abcde"; + NSURL *url = [NSURL URLWithString:string]; + if (url) { + BNCURLFilter *filter = [self filterWithV2List]; + XCTAssertFalse([filter shouldIgnoreURL:url]); + } +} + +- (void)testMetaAEMWithV2WithPrecedingParameters { + NSString *string = @"fb1://?brand=abcde&campaign_ids=a"; + NSURL *url = [NSURL URLWithString:string]; + if (url) { + BNCURLFilter *filter = [self filterWithV2List]; + XCTAssertFalse([filter shouldIgnoreURL:url]); + } +} + +- (void)testMetaAEMWithV2WithPrecedingAndTrailingParameters { + NSString *string = @"fb1://?brand=abcde&campaign_ids=a&link=12345"; + NSURL *url = [NSURL URLWithString:string]; + if (url) { + BNCURLFilter *filter = [self filterWithV2List]; + XCTAssertFalse([filter shouldIgnoreURL:url]); + } +} + +- (void)testSampleMetaAEMWithV0 { + NSString *string = @"fb123456789://products/next?al_applink_data=%7B%22target_url%22%3A%22http%3A%5C%2F%5C%2Fitunes.apple.com%5C%2Fapp%5C%2Fid880047117%22%2C%22extras%22%3A%7B%22fb_app_id%22%3A2020399148181142%7D%2C%22referer_app_link%22%3A%7B%22url%22%3A%22fb%3A%5C%2F%5C%2F%5C%2F%3Fapp_id%3D2020399148181142%22%2C%22app_name%22%3A%22Facebook%22%7D%2C%22acs_token%22%3A%22debuggingtoken%22%2C%22campaign_ids%22%3A%22ARFUlbyOurYrHT2DsknR7VksCSgN4tiH8TzG8RIvVoUQoYog5bVCvADGJil5kFQC6tQm-fFJQH0w8wCi3NbOmEHHrtgCNglkXNY-bECEL0aUhj908hIxnBB0tchJCqwxHjorOUqyk2v4bTF75PyWvxOksZ6uTzBmr7wJq8XnOav0bA%22%2C%22test_deeplink%22%3A1%7D"; + NSURL *url = [NSURL URLWithString:string]; + if (url) { + BNCURLFilter *filter = [self filterWithV0List]; + XCTAssertTrue([filter shouldIgnoreURL:url]); + } +} + +- (void)testSampleMetaAEMWithV1 { + NSString *string = @"fb123456789://products/next?al_applink_data=%7B%22target_url%22%3A%22http%3A%5C%2F%5C%2Fitunes.apple.com%5C%2Fapp%5C%2Fid880047117%22%2C%22extras%22%3A%7B%22fb_app_id%22%3A2020399148181142%7D%2C%22referer_app_link%22%3A%7B%22url%22%3A%22fb%3A%5C%2F%5C%2F%5C%2F%3Fapp_id%3D2020399148181142%22%2C%22app_name%22%3A%22Facebook%22%7D%2C%22acs_token%22%3A%22debuggingtoken%22%2C%22campaign_ids%22%3A%22ARFUlbyOurYrHT2DsknR7VksCSgN4tiH8TzG8RIvVoUQoYog5bVCvADGJil5kFQC6tQm-fFJQH0w8wCi3NbOmEHHrtgCNglkXNY-bECEL0aUhj908hIxnBB0tchJCqwxHjorOUqyk2v4bTF75PyWvxOksZ6uTzBmr7wJq8XnOav0bA%22%2C%22test_deeplink%22%3A1%7D"; + NSURL *url = [NSURL URLWithString:string]; + if (url) { + BNCURLFilter *filter = [self filterWithV1List]; + XCTAssertTrue([filter shouldIgnoreURL:url]); + } +} + +// This one is not filtered! +- (void)testSampleMetaAEMWithV2 { + NSString *string = @"fb123456789://products/next?al_applink_data=%7B%22target_url%22%3A%22http%3A%5C%2F%5C%2Fitunes.apple.com%5C%2Fapp%5C%2Fid880047117%22%2C%22extras%22%3A%7B%22fb_app_id%22%3A2020399148181142%7D%2C%22referer_app_link%22%3A%7B%22url%22%3A%22fb%3A%5C%2F%5C%2F%5C%2F%3Fapp_id%3D2020399148181142%22%2C%22app_name%22%3A%22Facebook%22%7D%2C%22acs_token%22%3A%22debuggingtoken%22%2C%22campaign_ids%22%3A%22ARFUlbyOurYrHT2DsknR7VksCSgN4tiH8TzG8RIvVoUQoYog5bVCvADGJil5kFQC6tQm-fFJQH0w8wCi3NbOmEHHrtgCNglkXNY-bECEL0aUhj908hIxnBB0tchJCqwxHjorOUqyk2v4bTF75PyWvxOksZ6uTzBmr7wJq8XnOav0bA%22%2C%22test_deeplink%22%3A1%7D"; + NSURL *url = [NSURL URLWithString:string]; + if (url) { + BNCURLFilter *filter = [self filterWithV2List]; + XCTAssertFalse([filter shouldIgnoreURL:url]); + } +} + +- (void)testSampleMetaAEMNoCampignIDsWithV0 { + NSString *string = @"fb123456789://products/next?al_applink_data=%7B%22target_url%22%3A%22http%3A%5C%2F%5C%2Fitunes.apple.com%5C%2Fapp%5C%2Fid880047117%22%2C%22extras%22%3A%7B%22fb_app_id%22%3A2020399148181142%7D%2C%22referer_app_link%22%3A%7B%22url%22%3A%22fb%3A%5C%2F%5C%2F%5C%2F%3Fapp_id%3D2020399148181142%22%2C%22app_name%22%3A%22Facebook%22%7D%2C%22acs_token%22%3A%22debuggingtoken%22%2C%22test_deeplink%22%3A1%7D"; + NSURL *url = [NSURL URLWithString:string]; + if (url) { + BNCURLFilter *filter = [self filterWithV0List]; + XCTAssertTrue([filter shouldIgnoreURL:url]); + } +} + +- (void)testSampleMetaAEMNoCampignIDsWithV1 { + NSString *string = @"fb123456789://products/next?al_applink_data=%7B%22target_url%22%3A%22http%3A%5C%2F%5C%2Fitunes.apple.com%5C%2Fapp%5C%2Fid880047117%22%2C%22extras%22%3A%7B%22fb_app_id%22%3A2020399148181142%7D%2C%22referer_app_link%22%3A%7B%22url%22%3A%22fb%3A%5C%2F%5C%2F%5C%2F%3Fapp_id%3D2020399148181142%22%2C%22app_name%22%3A%22Facebook%22%7D%2C%22acs_token%22%3A%22debuggingtoken%22%2C%22test_deeplink%22%3A1%7D"; + NSURL *url = [NSURL URLWithString:string]; + if (url) { + BNCURLFilter *filter = [self filterWithV1List]; + XCTAssertTrue([filter shouldIgnoreURL:url]); + } +} + +- (void)testSampleMetaAEMNoCampignIDsWithV2 { + NSString *string = @"fb123456789://products/next?al_applink_data=%7B%22target_url%22%3A%22http%3A%5C%2F%5C%2Fitunes.apple.com%5C%2Fapp%5C%2Fid880047117%22%2C%22extras%22%3A%7B%22fb_app_id%22%3A2020399148181142%7D%2C%22referer_app_link%22%3A%7B%22url%22%3A%22fb%3A%5C%2F%5C%2F%5C%2F%3Fapp_id%3D2020399148181142%22%2C%22app_name%22%3A%22Facebook%22%7D%2C%22acs_token%22%3A%22debuggingtoken%22%2C%22test_deeplink%22%3A1%7D"; + NSURL *url = [NSURL URLWithString:string]; + if (url) { + BNCURLFilter *filter = [self filterWithV2List]; + XCTAssertTrue([filter shouldIgnoreURL:url]); + } +} + +@end diff --git a/BranchSDKTests/BNCURLFilterTests.m b/BranchSDKTests/BNCURLFilterTests.m new file mode 100644 index 000000000..1573bc36e --- /dev/null +++ b/BranchSDKTests/BNCURLFilterTests.m @@ -0,0 +1,168 @@ +/** + @file BNCURLFilterTests.m + @package Branch-SDK-Tests + @brief BNCURLFilter tests. + + @author Edward Smith + @date February 14, 2018 + @copyright Copyright © 2018 Branch. All rights reserved. +*/ + +#import +#import "BNCURLFilter.h" + +@interface BNCURLFilterTests : XCTestCase +@end + +@implementation BNCURLFilterTests + +- (void)setUp { + // Put setup code here. This method is called before the invocation of each test method in the class. +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. +} + +- (void)testPatternMatchingURL_nil { + BNCURLFilter *filter = [BNCURLFilter new]; + NSURL *url = nil; + NSString *matchingRegex = [filter patternMatchingURL:url]; + XCTAssertNil(matchingRegex); +} + +- (void)testPatternMatchingURL_emptyString { + BNCURLFilter *filter = [BNCURLFilter new]; + NSURL *url = [NSURL URLWithString:@""]; + NSString *matchingRegex = [filter patternMatchingURL:url]; + XCTAssertNil(matchingRegex); +} + +- (void)testPatternMatchingURL_fbRegexMatches { + NSString *pattern = @"^fb\\d+:((?!campaign_ids).)*$"; + NSString *sampleURL = @"fb12345://"; + + BNCURLFilter *filter = [BNCURLFilter new]; + NSURL *url = [NSURL URLWithString:sampleURL]; + NSString *matchingRegex = [filter patternMatchingURL:url]; + XCTAssertTrue([pattern isEqualToString:matchingRegex]); +} + +- (void)testPatternMatchingURL_fbRegexDoesNotMatch { + NSString *pattern = @"^fb\\d+:((?!campaign_ids).)*$"; + NSString *sampleURL = @"fb12345://campaign_ids"; + + BNCURLFilter *filter = [BNCURLFilter new]; + NSURL *url = [NSURL URLWithString:sampleURL]; + NSString *matchingRegex = [filter patternMatchingURL:url]; + XCTAssertFalse([pattern isEqualToString:matchingRegex]); +} + + +- (void)testIgnoredSuspectedAuthURLs { + NSArray *urls = @[ + @"fb123456:login/464646", + @"shsh:oauth/login", + @"https://myapp.app.link/oauth_token=fred", + @"https://myapp.app.link/auth_token=fred", + @"https://myapp.app.link/authtoken=fred", + @"https://myapp.app.link/auth=fred", + @"myscheme:path/to/resource?oauth=747474", + @"myscheme:oauth=747474", + @"myscheme:/oauth=747474", + @"myscheme://oauth=747474", + @"myscheme://path/oauth=747474", + @"myscheme://path/:oauth=747474", + @"https://google.com/userprofile/devonbanks=oauth?" + ]; + + BNCURLFilter *filter = [BNCURLFilter new]; + for (NSString *string in urls) { + NSURL *URL = [NSURL URLWithString:string]; + XCTAssertTrue([filter shouldIgnoreURL:URL], @"Checking '%@'.", URL); + } +} + +- (void)testAllowedURLsSimilarToAuthURLs { + NSArray *urls = @[ + @"shshs:/content/path", + @"shshs:content/path", + @"https://myapp.app.link/12345/link", + @"https://myapp.app.link?authentic=true&tokemonsta=false", + @"myscheme://path/brauth=747474" + ]; + + BNCURLFilter *filter = [BNCURLFilter new]; + for (NSString *string in urls) { + NSURL *URL = [NSURL URLWithString:string]; + XCTAssertFalse([filter shouldIgnoreURL:URL], @"Checking '%@'", URL); + } +} + +- (void)testIgnoredFacebookURLs { + // Most FB URIs are ignored + NSArray *urls = @[ + @"fb123456://login/464646", + @"fb1234:", + @"fb1234:/", + @"fb1234:/this-is-some-extra-info/?whatever", + @"fb1234:/this-is-some-extra-info/?whatever:andstuff" + ]; + + BNCURLFilter *filter = [BNCURLFilter new]; + for (NSString *string in urls) { + NSURL *URL = [NSURL URLWithString:string]; + XCTAssertTrue([filter shouldIgnoreURL:URL], @"Checking '%@'.", URL); + } +} + +- (void)testAllowedFacebookURLs { + NSArray *urls = @[ + // Facebook URIs do not contain letters other than an fb prefix + @"fb123x://", + // FB URIs with campaign ids are allowed + @"fb1234://helloworld?al_applink_data=%7B%22target_url%22%3A%22http%3A%5C%2F%5C%2Fitunes.apple.com%5C%2Fapp%5C%2Fid880047117%22%2C%22extras%22%3A%7B%22fb_app_id%22%3A2020399148181142%7D%2C%22referer_app_link%22%3A%7B%22url%22%3A%22fb%3A%5C%2F%5C%2F%5C%2F%3Fapp_id%3D2020399148181142%22%2C%22app_name%22%3A%22Facebook%22%7D%2C%22acs_token%22%3A%22debuggingtoken%22%2C%22campaign_ids%22%3A%22ARFUlbyOurYrHT2DsknR7VksCSgN4tiH8TzG8RIvVoUQoYog5bVCvADGJil5kFQC6tQm-fFJQH0w8wCi3NbOmEHHrtgCNglkXNY-bECEL0aUhj908hIxnBB0tchJCqwxHjorOUqyk2v4bTF75PyWvxOksZ6uTzBmr7wJq8XnOav0bA%22%2C%22test_deeplink%22%3A1%7D" + ]; + + BNCURLFilter *filter = [BNCURLFilter new]; + for (NSString *string in urls) { + NSURL *URL = [NSURL URLWithString:string]; + XCTAssertFalse([filter shouldIgnoreURL:URL], @"Checking '%@'", URL); + } +} + +- (void)testCustomPatternList { + BNCURLFilter *filter = [BNCURLFilter new]; + + // sanity check default pattern list + XCTAssertTrue([filter shouldIgnoreURL:[NSURL URLWithString:@"fb123://"]]); + XCTAssertFalse([filter shouldIgnoreURL:[NSURL URLWithString:@"branch123://"]]); + + // confirm new pattern list is enforced + [filter useCustomPatternList:@[@"^branch\\d+:"]]; + XCTAssertFalse([filter shouldIgnoreURL:[NSURL URLWithString:@"fb123://"]]); + XCTAssertTrue([filter shouldIgnoreURL:[NSURL URLWithString:@"branch123://"]]); +} + +// This is an end to end test and relies on a server call +- (void)testUpdatePatternListFromServer { + BNCURLFilter *filter = [BNCURLFilter new]; + + // confirm new pattern list is enforced + [filter useCustomPatternList:@[@"^branch\\d+:"]]; + XCTAssertFalse([filter shouldIgnoreURL:[NSURL URLWithString:@"fb123://"]]); + XCTAssertTrue([filter shouldIgnoreURL:[NSURL URLWithString:@"branch123://"]]); + + __block XCTestExpectation *expectation = [self expectationWithDescription:@"List updated"]; + [filter updatePatternListFromServerWithCompletion:^{ + [expectation fulfill]; + }]; + + [self waitForExpectationsWithTimeout:5.0 handler:^(NSError * _Nullable error) { }]; + + // the retrieved list should match default pattern list + XCTAssertTrue([filter shouldIgnoreURL:[NSURL URLWithString:@"fb123://"]]); + XCTAssertFalse([filter shouldIgnoreURL:[NSURL URLWithString:@"branch123://"]]); +} + +@end diff --git a/BranchSDKTests/BNCUserAgentCollectorTests.m b/BranchSDKTests/BNCUserAgentCollectorTests.m new file mode 100644 index 000000000..e54cca1bc --- /dev/null +++ b/BranchSDKTests/BNCUserAgentCollectorTests.m @@ -0,0 +1,111 @@ +// +// BNCUserAgentCollectorTests.m +// Branch-SDK-Tests +// +// Created by Ernest Cho on 8/29/19. +// Copyright © 2019 Branch, Inc. All rights reserved. +// + +#import +#import "BNCPreferenceHelper.h" +#import "BNCDeviceSystem.h" +#import "BNCUserAgentCollector.h" + +// expose private methods for unit testing +@interface BNCUserAgentCollector() + +- (NSString *)loadUserAgentForSystemBuildVersion:(NSString *)systemBuildVersion; +- (void)saveUserAgent:(NSString *)userAgent forSystemBuildVersion:(NSString *)systemBuildVersion; +- (void)collectUserAgentWithCompletion:(void (^)(NSString * _Nullable userAgent))completion; + +@end + +@interface BNCUserAgentCollectorTests : XCTestCase + +@end + +@implementation BNCUserAgentCollectorTests + ++ (void)setUp { + [BNCUserAgentCollectorTests resetPersistentData]; +} + +- (void)setUp { + +} + +- (void)tearDown { + [BNCUserAgentCollectorTests resetPersistentData]; +} + ++ (void)resetPersistentData { + BNCPreferenceHelper *preferences = [BNCPreferenceHelper sharedInstance]; + preferences.browserUserAgentString = nil; + preferences.lastSystemBuildVersion = nil; +} + +- (void)testResetPersistentData { + BNCPreferenceHelper *preferences = [BNCPreferenceHelper sharedInstance]; + XCTAssertNil(preferences.browserUserAgentString); + XCTAssertNil(preferences.lastSystemBuildVersion); +} + +- (void)testSaveAndLoadUserAgent { + NSString *systemBuildVersion = @"test"; + NSString *userAgent = @"UserAgent"; + + BNCUserAgentCollector *collector = [BNCUserAgentCollector new]; + [collector saveUserAgent:userAgent forSystemBuildVersion:systemBuildVersion]; + NSString *expected = [collector loadUserAgentForSystemBuildVersion:systemBuildVersion]; + XCTAssertTrue([userAgent isEqualToString:expected]); +} + +- (void)testCollectUserAgent { + XCTestExpectation *expectation = [self expectationWithDescription:@"expectation"]; + + BNCUserAgentCollector *collector = [BNCUserAgentCollector new]; + [collector collectUserAgentWithCompletion:^(NSString * _Nullable userAgent) { + XCTAssertNotNil(userAgent); + XCTAssertTrue([userAgent containsString:@"AppleWebKit"]); + [expectation fulfill]; + }]; + + [self waitForExpectationsWithTimeout:4.0 handler:^(NSError * _Nullable error) { + + }]; +} + +- (void)testLoadUserAgent_EmptyDataStore { + XCTestExpectation *expectation = [self expectationWithDescription:@"expectation"]; + + BNCUserAgentCollector *collector = [BNCUserAgentCollector new]; + [collector loadUserAgentWithCompletion:^(NSString * _Nullable userAgent) { + XCTAssertNotNil(userAgent); + XCTAssertTrue([userAgent containsString:@"AppleWebKit"]); + [expectation fulfill]; + }]; + + [self waitForExpectationsWithTimeout:2.0 handler:^(NSError * _Nullable error) { + + }]; +} + +- (void)testLoadUserAgent_FilledDataStore { + XCTestExpectation *expectation = [self expectationWithDescription:@"expectation"]; + NSString *savedUserAgent = @"UserAgent"; + + BNCUserAgentCollector *collector = [BNCUserAgentCollector new]; + [collector saveUserAgent:savedUserAgent forSystemBuildVersion:[BNCDeviceSystem new].systemBuildVersion]; + [collector loadUserAgentWithCompletion:^(NSString * _Nullable userAgent) { + XCTAssertNotNil(userAgent); + XCTAssertTrue([userAgent isEqualToString:savedUserAgent]); + XCTAssertFalse([userAgent containsString:@"AppleWebKit"]); + [expectation fulfill]; + }]; + + [self waitForExpectationsWithTimeout:2.0 handler:^(NSError * _Nullable error) { + + }]; +} + +@end diff --git a/BranchSDKTests/Branch-SDK-Tests-Bridging-Header.h b/BranchSDKTests/Branch-SDK-Tests-Bridging-Header.h new file mode 100644 index 000000000..169bd50f3 --- /dev/null +++ b/BranchSDKTests/Branch-SDK-Tests-Bridging-Header.h @@ -0,0 +1,5 @@ +// +// Module headers for Branch SDK unit testing. +// + +#import "Branch.h" diff --git a/BranchSDKTests/BranchActivityItemTests.m b/BranchSDKTests/BranchActivityItemTests.m new file mode 100644 index 000000000..f117859f7 --- /dev/null +++ b/BranchSDKTests/BranchActivityItemTests.m @@ -0,0 +1,39 @@ +// +// BranchActivityItemTests.m +// Branch-SDK-Tests +// +// Created by Nipun Singh on 9/21/23. +// Copyright © 2023 Branch, Inc. All rights reserved. +// + +#import +#import "Branch.h" + +@interface BranchActivityItemTests: XCTestCase +@end + +@implementation BranchActivityItemTests + +// Rework this test, it's not reliable. +//- (void)testGetBranchActivityItemWithAllParams { +// NSDictionary *params = @{@"key": @"value"}; +// NSString *feature = @"feature4"; +// NSString *stage = @"stage3"; +// NSArray *tags = @[@"tag3", @"tag4"]; +// NSString *campaign = @"campaign1"; +// NSString *alias = [[NSUUID UUID] UUIDString]; +// BranchActivityItemProvider *provider = [Branch getBranchActivityItemWithParams:params feature:feature stage:stage campaign:campaign tags:tags alias:alias]; +// sleep(2000); +// if ([[provider item] isKindOfClass:[NSURL class]]) { +// NSURL *urlObject = (NSURL *)[provider item]; +// NSString *url = [urlObject absoluteString]; +// +// NSLog(@"Provider URL as String: %@", url); +// +// XCTAssertTrue([url isEqualToString:[@"https://bnctestbed.app.link/" stringByAppendingString:alias]]); +// } else { +// XCTFail("Provider Data is not of type NSURL"); +// } +//} + +@end diff --git a/BranchSDKTests/BranchClassTests.m b/BranchSDKTests/BranchClassTests.m new file mode 100644 index 000000000..d1e7713f1 --- /dev/null +++ b/BranchSDKTests/BranchClassTests.m @@ -0,0 +1,265 @@ +// +// BranchClassTests.m +// Branch-SDK-Tests +// +// Created by Nipun Singh on 9/25/23. +// Copyright © 2023 Branch, Inc. All rights reserved. +// + +#import +#import "Branch.h" +#import "BranchConstants.h" +#import "BNCPasteboard.h" +#import "BNCAppGroupsData.h" +#import "BNCPartnerParameters.h" + +@interface BNCPreferenceHelper(Test) +// Expose internal private method to clear EEA data +- (void)writeObjectToDefaults:(NSString *)key value:(NSObject *)value; +@end + +@interface BranchClassTests : XCTestCase +@property (nonatomic, strong) Branch *branch; +@end + +@implementation BranchClassTests + +- (void)setUp { + [super setUp]; + self.branch = [Branch getInstance]; +} + +- (void)tearDown { + self.branch = nil; + [super tearDown]; +} + +- (void)testIsUserIdentified { + [self.branch setIdentity: @"userId"]; + XCTAssertTrue([self.branch isUserIdentified], @"User should be identified"); +} + +- (void)testDisableAdNetworkCallouts { + [self.branch disableAdNetworkCallouts:YES]; + XCTAssertTrue([BNCPreferenceHelper sharedInstance].disableAdNetworkCallouts, @"AdNetwork callouts should be disabled"); +} + +- (void)testSetNetworkTimeout { + [self.branch setNetworkTimeout:5.0]; + XCTAssertEqual([BNCPreferenceHelper sharedInstance].timeout, 5.0, @"Network timeout should be set to 5.0"); +} + +//- (void)testSetMaxRetries { +// [self.branch setMaxRetries:3]; +// XCTAssertEqual([BNCPreferenceHelper sharedInstance].retryCount, 3, @"Max retries should be set to 3"); +//} + +- (void)testSetRetryInterval { + [self.branch setRetryInterval:2.0]; + XCTAssertEqual([BNCPreferenceHelper sharedInstance].retryInterval, 2.0, @"Retry interval should be set to 2.0"); +} + +- (void)testSetRequestMetadataKeyAndValue { + [self.branch setRequestMetadataKey:@"key" value:@"value"]; + NSDictionary *metadata = [BNCPreferenceHelper sharedInstance].requestMetadataDictionary; + XCTAssertEqualObjects(metadata[@"key"], @"value"); +} + +- (void)testSetTrackingDisabled { + XCTAssertFalse([BNCPreferenceHelper sharedInstance].trackingDisabled); + + [Branch setTrackingDisabled:YES]; + XCTAssertTrue([BNCPreferenceHelper sharedInstance].trackingDisabled); + + [Branch setTrackingDisabled:NO]; + XCTAssertFalse([BNCPreferenceHelper sharedInstance].trackingDisabled); +} + +- (void)testCheckPasteboardOnInstall { + [self.branch checkPasteboardOnInstall]; + BOOL checkOnInstall = [BNCPasteboard sharedInstance].checkOnInstall; + XCTAssertTrue(checkOnInstall); +} + +- (void)testWillShowPasteboardToast_ShouldReturnYes { + [BNCPreferenceHelper sharedInstance].randomizedBundleToken = nil; + [BNCPasteboard sharedInstance].checkOnInstall = YES; + UIPasteboard.generalPasteboard.URL = [NSURL URLWithString:@"https://example.com"]; + + BOOL result = [self.branch willShowPasteboardToast]; + XCTAssertTrue(result); +} + +- (void)testWillShowPasteboardToast_ShouldReturnNo { + [BNCPreferenceHelper sharedInstance].randomizedBundleToken = @"some_token"; + [BNCPasteboard sharedInstance].checkOnInstall = NO; + + BOOL result = [self.branch willShowPasteboardToast]; + XCTAssertFalse(result); +} + +- (void)testSetAppClipAppGroup { + NSString *testAppGroup = @"testAppGroup"; + [self.branch setAppClipAppGroup:testAppGroup]; + NSString *actualAppGroup = [BNCAppGroupsData shared].appGroup; + + XCTAssertEqualObjects(testAppGroup, actualAppGroup); +} + +- (void)testClearPartnerParameters { + [self.branch addFacebookPartnerParameterWithName:@"ph" value:@"123456789"]; + [[BNCPartnerParameters shared] clearAllParameters]; + + NSDictionary *result = [[BNCPartnerParameters shared] parameterJson]; + XCTAssertEqual([result count], 0, @"Parameters should be empty after calling clearAllParameters"); +} + +- (void)testAddFacebookParameterWithName_Value { + [self.branch addFacebookPartnerParameterWithName:@"name" value:@"3D4F2BF07DC1BE38B20C653EE9A7E446158F84E525BBB98FEDF721CB5A40A346"]; + + NSDictionary *result = [[BNCPartnerParameters shared] parameterJson][@"fb"]; + XCTAssertEqualObjects(result[@"name"], @"3D4F2BF07DC1BE38B20C653EE9A7E446158F84E525BBB98FEDF721CB5A40A346", @"Should add parameter for Facebook"); +} + +- (void)testAddSnapParameterWithName_Value { + [self.branch addSnapPartnerParameterWithName:@"name" value:@"3D4F2BF07DC1BE38B20C653EE9A7E446158F84E525BBB98FEDF721CB5A40A346"]; + + NSDictionary *result = [[BNCPartnerParameters shared] parameterJson][@"snap"]; + XCTAssertEqualObjects(result[@"name"], @"3D4F2BF07DC1BE38B20C653EE9A7E446158F84E525BBB98FEDF721CB5A40A346", @"Should add parameter for Snap"); +} + +- (void)testGetFirstReferringBranchUniversalObject_ClickedBranchLink { + NSString *installParamsString = @"{\"$canonical_identifier\":\"content/12345\",\"$creation_timestamp\":1694557342247,\"$desktop_url\":\"https://example.com/home\",\"$og_description\":\"My Content Description\",\"$og_title\":\"My Content Title\",\"+click_timestamp\":1695749249,\"+clicked_branch_link\":1,\"+is_first_session\":1,\"+match_guaranteed\":1,\"custom\":\"data\",\"key1\":\"value1\",\"~campaign\":\"content 123 launch\",\"~channel\":\"facebook\",\"~creation_source\":3,\"~feature\":\"sharing\",\"~id\":1230269548213984984,\"~referring_link\":\"https://bnctestbed.app.link/uSPHktjO2Cb\"}"; + [[BNCPreferenceHelper sharedInstance] setInstallParams: installParamsString]; + + BranchUniversalObject *result = [self.branch getFirstReferringBranchUniversalObject];\ + XCTAssertNotNil(result); + XCTAssertEqualObjects(result.title, @"My Content Title"); + XCTAssertEqualObjects(result.canonicalIdentifier, @"content/12345"); +} + +- (void)testGetFirstReferringBranchUniversalObject_NotClickedBranchLink { + NSString *installParamsString = @"{\"+clicked_branch_link\":false,\"+is_first_session\":true}"; + [[BNCPreferenceHelper sharedInstance] setInstallParams: installParamsString]; + + BranchUniversalObject *result = [self.branch getFirstReferringBranchUniversalObject]; + XCTAssertNil(result); +} + +- (void)testGetFirstReferringBranchLinkProperties_ClickedBranchLink { + NSString *installParamsString = @"{\"+clicked_branch_link\":1,\"+is_first_session\":1,\"~campaign\":\"content 123 launch\"}"; + [[BNCPreferenceHelper sharedInstance] setInstallParams:installParamsString]; + + BranchLinkProperties *result = [self.branch getFirstReferringBranchLinkProperties]; + XCTAssertNotNil(result); + XCTAssertEqualObjects(result.campaign, @"content 123 launch"); +} + +- (void)testGetFirstReferringBranchLinkProperties_NotClickedBranchLink { + NSString *installParamsString = @"{\"+clicked_branch_link\":false,\"+is_first_session\":true}"; + [[BNCPreferenceHelper sharedInstance] setInstallParams:installParamsString]; + + BranchLinkProperties *result = [self.branch getFirstReferringBranchLinkProperties]; + XCTAssertNil(result); +} + +- (void)testGetFirstReferringParams { + NSString *installParamsString = @"{\"+clicked_branch_link\":true,\"+is_first_session\":true}"; + [[BNCPreferenceHelper sharedInstance] setInstallParams:installParamsString]; + + NSDictionary *result = [self.branch getFirstReferringParams]; + XCTAssertEqualObjects([result objectForKey:@"+clicked_branch_link"], @true); +} + +- (void)testGetLatestReferringParams { + NSString *sessionParamsString = @"{\"+clicked_branch_link\":true,\"+is_first_session\":false}"; + [[BNCPreferenceHelper sharedInstance] setSessionParams:sessionParamsString]; + + NSDictionary *result = [self.branch getLatestReferringParams]; + XCTAssertEqualObjects([result objectForKey:@"+clicked_branch_link"], @true); +} + +//- (void)testGetLatestReferringParamsSynchronous { +// NSString *sessionParamsString = @"{\"+clicked_branch_link\":true,\"+is_first_session\":false}"; +// [[BNCPreferenceHelper sharedInstance] setSessionParams:sessionParamsString]; +// +// NSDictionary *result = [self.branch getLatestReferringParamsSynchronous]; +// XCTAssertEqualObjects([result objectForKey:@"+clicked_branch_link"], @true); +//} + +- (void)testGetLatestReferringBranchUniversalObject_ClickedBranchLink { + NSString *sessionParamsString = @"{\"+clicked_branch_link\":1,\"+is_first_session\":false,\"$og_title\":\"My Latest Content\"}"; + [[BNCPreferenceHelper sharedInstance] setSessionParams:sessionParamsString]; + + BranchUniversalObject *result = [self.branch getLatestReferringBranchUniversalObject]; + XCTAssertNotNil(result); + XCTAssertEqualObjects(result.title, @"My Latest Content"); +} + +- (void)testGetLatestReferringBranchLinkProperties_ClickedBranchLink { + NSString *sessionParamsString = @"{\"+clicked_branch_link\":true,\"+is_first_session\":false,\"~campaign\":\"latest campaign\"}"; + [[BNCPreferenceHelper sharedInstance] setSessionParams:sessionParamsString]; + + BranchLinkProperties *result = [self.branch getLatestReferringBranchLinkProperties]; + XCTAssertNotNil(result); + XCTAssertEqualObjects(result.campaign, @"latest campaign"); +} + +- (void)testGetShortURL { + NSString *shortURL = [self.branch getShortURL]; + XCTAssertNotNil(shortURL, @"URL should not be nil"); + XCTAssertTrue([shortURL hasPrefix:@"https://"], @"URL should start with 'https://'"); +} + +- (void)testGetLongURLWithParamsAndChannelAndTagsAndFeatureAndStageAndAlias { + NSDictionary *params = @{@"key": @"value"}; + NSString *channel = @"channel1"; + NSArray *tags = @[@"tag1", @"tag2"]; + NSString *feature = @"feature1"; + NSString *stage = @"stage1"; + NSString *alias = @"alias1"; + + NSString *generatedURL = [self.branch getLongURLWithParams:params andChannel:channel andTags:tags andFeature:feature andStage:stage andAlias:alias]; + NSString *expectedURL = @"https://bnc.lt/a/key_live_hcnegAumkH7Kv18M8AOHhfgiohpXq5tB?tags=tag1&tags=tag2&alias=alias1&feature=feature1&stage=stage1&source=ios&data=eyJrZXkiOiJ2YWx1ZSJ9"; + + XCTAssertEqualObjects(generatedURL, expectedURL, @"URL should match the expected format"); +} + +- (void)testSetDMAParamsForEEA { + XCTAssertFalse([[BNCPreferenceHelper sharedInstance] eeaRegionInitialized]); + + [Branch setDMAParamsForEEA:FALSE AdPersonalizationConsent:TRUE AdUserDataUsageConsent:TRUE]; + XCTAssertTrue([[BNCPreferenceHelper sharedInstance] eeaRegionInitialized]); + XCTAssertFalse([BNCPreferenceHelper sharedInstance].eeaRegion); + XCTAssertTrue([BNCPreferenceHelper sharedInstance].adPersonalizationConsent); + XCTAssertTrue([BNCPreferenceHelper sharedInstance].adUserDataUsageConsent); + + // Manually clear values after testing + // By design, this API is meant to be set once and always set. However, in a test scenario it needs to be cleared. + [[BNCPreferenceHelper sharedInstance] writeObjectToDefaults:@"bnc_dma_eea" value:nil]; + [[BNCPreferenceHelper sharedInstance] writeObjectToDefaults:@"bnc_dma_ad_personalization" value:nil]; + [[BNCPreferenceHelper sharedInstance] writeObjectToDefaults:@"bnc_dma_ad_user_data" value:nil]; +} + +- (void)testSetConsumerProtectionAttributionLevel { + // Set to Reduced and check + Branch *branch = [Branch getInstance]; + [branch setConsumerProtectionAttributionLevel:BranchAttributionLevelReduced]; + XCTAssertEqual([BNCPreferenceHelper sharedInstance].attributionLevel, BranchAttributionLevelReduced); + + // Set to Minimal and check + [branch setConsumerProtectionAttributionLevel:BranchAttributionLevelMinimal]; + XCTAssertEqual([BNCPreferenceHelper sharedInstance].attributionLevel, BranchAttributionLevelMinimal); + + // Set to None and check + [branch setConsumerProtectionAttributionLevel:BranchAttributionLevelNone]; + XCTAssertEqual([BNCPreferenceHelper sharedInstance].attributionLevel, BranchAttributionLevelNone); + + // Set to Full and check + [branch setConsumerProtectionAttributionLevel:BranchAttributionLevelFull]; + XCTAssertEqual([BNCPreferenceHelper sharedInstance].attributionLevel, BranchAttributionLevelFull); + +} + + +@end diff --git a/BranchSDKTests/BranchConfigurationControllerTests.m b/BranchSDKTests/BranchConfigurationControllerTests.m new file mode 100644 index 000000000..74acc4106 --- /dev/null +++ b/BranchSDKTests/BranchConfigurationControllerTests.m @@ -0,0 +1,105 @@ +// +// BranchConfigurationControllerTests.m +// Branch-SDK-Tests +// +// Created by Nidhi Dixit on 6/12/25. +// + + +#import +#import "BranchConstants.h" +#import "BNCRequestFactory.h" +#import "BNCEncodingUtils.h" + +#if SWIFT_PACKAGE +@import BranchSwiftSDK; +#else +#import "BranchSDK/BranchSDK-Swift.h" +#endif + +@interface BranchConfigurationControllerTests : XCTestCase +@end + +@implementation BranchConfigurationControllerTests + +- (void)testSingletonInstance { + + ConfigurationController *instance1 = [ConfigurationController shared]; + XCTAssertNotNil(instance1); + + ConfigurationController *instance2 = [ConfigurationController shared]; + XCTAssertEqual(instance1, instance2); +} + +- (void)testPropertySettersAndGetters { + ConfigurationController *configController = [ConfigurationController shared]; + + NSString *keySource = BRANCH_KEY_SOURCE_GET_INSTANCE_API; + configController.branchKeySource = keySource; + XCTAssertTrue([configController.branchKeySource isEqualToString:keySource]); + + configController.deferInitForPluginRuntime = YES; + XCTAssertTrue(configController.deferInitForPluginRuntime); + configController.deferInitForPluginRuntime = NO; + XCTAssertFalse(configController.deferInitForPluginRuntime); + + configController.checkPasteboardOnInstall = YES; + XCTAssertTrue(configController.checkPasteboardOnInstall); + configController.checkPasteboardOnInstall = NO; + XCTAssertFalse(configController.checkPasteboardOnInstall); +} + +- (void)testGetConfiguration { + ConfigurationController *configController = [ConfigurationController shared]; + configController.branchKeySource = BRANCH_KEY_SOURCE_INFO_PLIST; + configController.deferInitForPluginRuntime = YES; + configController.checkPasteboardOnInstall = YES; + + NSDictionary *configDict = [configController getConfiguration]; + XCTAssertNotNil(configDict); + + XCTAssertTrue([configDict[BRANCH_REQUEST_KEY_BRANCH_KEY_SOURCE] isEqualToString:BRANCH_KEY_SOURCE_INFO_PLIST]); + XCTAssertEqualObjects(configDict[BRANCH_REQUEST_KEY_DEFER_INIT_FOR_PLUGIN_RUNTIME], @(YES)); + XCTAssertEqualObjects(configDict[BRANCH_REQUEST_KEY_CHECK_PASTEBOARD_ON_INSTALL], @(YES)); + + NSDictionary *frameworks = configDict[BRANCH_REQUEST_KEY_LINKED_FRAMEORKS]; + XCTAssertNotNil(frameworks); + + XCTAssertEqualObjects(frameworks[FRAMEWORK_AD_SUPPORT], @(YES)); + XCTAssertEqualObjects(frameworks[FRAMEWORK_ATT_TRACKING_MANAGER], @(YES)); + XCTAssertEqualObjects(frameworks[FRAMEWORK_AD_FIREBASE_CRASHLYTICS], @(YES)); + XCTAssertEqualObjects(frameworks[FRAMEWORK_AD_SAFARI_SERVICES], @(NO)); + XCTAssertEqualObjects(frameworks[FRAMEWORK_AD_APP_ADS_ONDEVICE_CONVERSION], @(NO)); + +} + +- (void)testInstallRequestParams { + ConfigurationController *configController = [ConfigurationController shared]; + configController.branchKeySource = BRANCH_KEY_SOURCE_INFO_PLIST; + configController.deferInitForPluginRuntime = YES; + configController.checkPasteboardOnInstall = YES; + + NSString* requestUUID = [[NSUUID UUID ] UUIDString]; + NSNumber* requestCreationTimeStamp = BNCWireFormatFromDate([NSDate date]); + BNCRequestFactory *factory = [[BNCRequestFactory alloc] initWithBranchKey:@"key_abcd" UUID:requestUUID TimeStamp:requestCreationTimeStamp]; + NSDictionary *installDict = [factory dataForInstallWithURLString:@"https://branch.io"]; + + NSDictionary *configDict = installDict[BRANCH_REQUEST_KEY_OPERATIONAL_METRICS]; + XCTAssertNotNil(configDict); + + XCTAssertTrue([configDict[BRANCH_REQUEST_KEY_BRANCH_KEY_SOURCE] isEqualToString:BRANCH_KEY_SOURCE_INFO_PLIST]); + XCTAssertEqualObjects(configDict[BRANCH_REQUEST_KEY_DEFER_INIT_FOR_PLUGIN_RUNTIME], @(YES)); + XCTAssertEqualObjects(configDict[BRANCH_REQUEST_KEY_CHECK_PASTEBOARD_ON_INSTALL], @(YES)); + + NSDictionary *frameworks = configDict[BRANCH_REQUEST_KEY_LINKED_FRAMEORKS]; + XCTAssertNotNil(frameworks); + + XCTAssertEqualObjects(frameworks[FRAMEWORK_AD_SUPPORT], @(YES)); + XCTAssertEqualObjects(frameworks[FRAMEWORK_ATT_TRACKING_MANAGER], @(YES)); + XCTAssertEqualObjects(frameworks[FRAMEWORK_AD_FIREBASE_CRASHLYTICS], @(YES)); + XCTAssertEqualObjects(frameworks[FRAMEWORK_AD_SAFARI_SERVICES], @(NO)); + XCTAssertEqualObjects(frameworks[FRAMEWORK_AD_APP_ADS_ONDEVICE_CONVERSION], @(NO)); + +} + +@end diff --git a/BranchSDKTests/BranchEvent.Test.m b/BranchSDKTests/BranchEvent.Test.m new file mode 100644 index 000000000..ddb3d220f --- /dev/null +++ b/BranchSDKTests/BranchEvent.Test.m @@ -0,0 +1,575 @@ +// +// BranchEvent.Test.m +// Branch-SDK-Tests +// +// Created by Edward Smith on 8/15/17. +// Copyright © 2017 Branch Metrics. All rights reserved. +// +#import +#import "BNCPreferenceHelper.h" +#import "BranchConstants.h" +#import "BranchEvent.h" +#import "BNCDeviceInfo.h" +#import "NSError+Branch.h" + +@interface Branch (BranchEventTest) +- (void) processNextQueueItem; +@end + +@interface BranchEvent() + +- (NSString *)jsonStringForAdType:(BranchEventAdType)adType; + +// private BranchEvent methods used to check data before sending to network service. +- (NSDictionary *)buildEventDictionary; +- (BranchEventRequest *)buildRequestWithEventDictionary:(NSDictionary *)eventDictionary; + +@end + +@interface BranchEventTest : XCTestCase +@end + +@implementation BranchEventTest + +- (void)setUp { + [BNCPreferenceHelper sharedInstance].randomizedBundleToken = @"575759106028389737"; + [[BNCPreferenceHelper sharedInstance] clearInstrumentationDictionary]; +} + +- (void)tearDown { + +} + +// TODO: fix this test +- (void)testDescription { + BranchEvent *event = [BranchEvent standardEvent:BranchStandardEventPurchase]; + event.transactionID = @"1234"; + event.currency = BNCCurrencyUSD; + event.revenue = [NSDecimalNumber decimalNumberWithString:@"10.50"]; + event.eventDescription= @"Event description."; + event.customData = (NSMutableDictionary*) @{ + @"Key1": @"Value1" + }; + + NSString *d = event.description; +// BNCTAssertEqualMaskedString(d, +// @""); +} + +- (void)testExampleSyntax { + BranchUniversalObject *contentItem = [BranchUniversalObject new]; + contentItem.canonicalIdentifier = @"item/123"; + contentItem.canonicalUrl = @"https://branch.io/item/123"; + contentItem.contentMetadata.ratingAverage = 5.0; + + BranchEvent *event = [BranchEvent standardEvent:BranchStandardEventCompleteRegistration]; + event.eventDescription = @"Product Search"; + event.searchQuery = @"product name"; + event.customData = @{ @"rating": @"5" }; + + [event logEvent]; +} + +- (void)testStandardInviteEvent { + + BranchEvent *event = [BranchEvent standardEvent:BranchStandardEventInvite]; + + BranchUniversalObject *buo = [BranchUniversalObject new]; + buo.canonicalIdentifier = @"item/12345"; + buo.canonicalUrl = @"https://branch.io/deepviews"; + buo.title = @"My Content Title"; + buo.contentDescription = @"my_product_description1"; + + NSMutableArray *contentItems = [NSMutableArray new]; + [contentItems addObject:buo]; + event.contentItems = contentItems; + + NSDictionary *eventDictionary = [event buildEventDictionary]; + + XCTAssertNotNil(eventDictionary); + XCTAssert([eventDictionary[@"name"] isEqualToString:@"INVITE"]); + + BranchEventRequest *request = [event buildRequestWithEventDictionary:eventDictionary]; + XCTAssert([request.serverURL.absoluteString containsString:@"branch.io/v2/event/standard"]); +} + +- (void)testCustomInviteEvent { + + BranchEvent *event = [BranchEvent customEventWithName:@"INVITE"]; + + BranchUniversalObject *buo = [BranchUniversalObject new]; + buo.canonicalIdentifier = @"item/12345"; + buo.canonicalUrl = @"https://branch.io/deepviews"; + buo.title = @"My Content Title"; + buo.contentDescription = @"my_product_description1"; + + NSMutableArray *contentItems = [NSMutableArray new]; + [contentItems addObject:buo]; + event.contentItems = contentItems; + + NSDictionary *eventDictionary = [event buildEventDictionary]; + XCTAssertNotNil(eventDictionary); + XCTAssert([eventDictionary[@"name"] isEqualToString:@"INVITE"]); + XCTAssertNotNil(eventDictionary[@"content_items"]); + + BranchEventRequest *request = [event buildRequestWithEventDictionary:eventDictionary]; + XCTAssert([request.serverURL.absoluteString containsString:@"branch.io/v2/event/standard"]); +} + +- (void)testStandardLoginEvent { + + BranchEvent *event = [BranchEvent standardEvent:BranchStandardEventLogin]; + + BranchUniversalObject *buo = [BranchUniversalObject new]; + buo.canonicalIdentifier = @"item/12345"; + buo.canonicalUrl = @"https://branch.io/deepviews"; + buo.title = @"My Content Title"; + buo.contentDescription = @"my_product_description1"; + + NSMutableArray *contentItems = [NSMutableArray new]; + [contentItems addObject:buo]; + event.contentItems = contentItems; + + NSDictionary *eventDictionary = [event buildEventDictionary]; + + XCTAssertNotNil(eventDictionary); + XCTAssert([eventDictionary[@"name"] isEqualToString:@"LOGIN"]); + + BranchEventRequest *request = [event buildRequestWithEventDictionary:eventDictionary]; + XCTAssert([request.serverURL.absoluteString containsString:@"branch.io/v2/event/standard"]); +} + +- (void)testCustomLoginEvent { + + BranchEvent *event = [BranchEvent customEventWithName:@"LOGIN"]; + + BranchUniversalObject *buo = [BranchUniversalObject new]; + buo.canonicalIdentifier = @"item/12345"; + buo.canonicalUrl = @"https://branch.io/deepviews"; + buo.title = @"My Content Title"; + buo.contentDescription = @"my_product_description1"; + + NSMutableArray *contentItems = [NSMutableArray new]; + [contentItems addObject:buo]; + event.contentItems = contentItems; + + NSDictionary *eventDictionary = [event buildEventDictionary]; + XCTAssertNotNil(eventDictionary); + XCTAssert([eventDictionary[@"name"] isEqualToString:@"LOGIN"]); + XCTAssertNotNil(eventDictionary[@"content_items"]); + + BranchEventRequest *request = [event buildRequestWithEventDictionary:eventDictionary]; + XCTAssert([request.serverURL.absoluteString containsString:@"branch.io/v2/event/standard"]); +} + +- (void)testStandardReserveEvent { + + BranchEvent *event = [BranchEvent standardEvent:BranchStandardEventReserve]; + + BranchUniversalObject *buo = [BranchUniversalObject new]; + buo.canonicalIdentifier = @"item/12345"; + buo.canonicalUrl = @"https://branch.io/deepviews"; + buo.title = @"My Content Title"; + buo.contentDescription = @"my_product_description1"; + + NSMutableArray *contentItems = [NSMutableArray new]; + [contentItems addObject:buo]; + event.contentItems = contentItems; + + NSDictionary *eventDictionary = [event buildEventDictionary]; + + XCTAssertNotNil(eventDictionary); + XCTAssert([eventDictionary[@"name"] isEqualToString:@"RESERVE"]); + XCTAssertNotNil(eventDictionary[@"content_items"]); + + BranchEventRequest *request = [event buildRequestWithEventDictionary:eventDictionary]; + XCTAssert([request.serverURL.absoluteString containsString:@"branch.io/v2/event/standard"]); +} + +- (void)testCustomReserveEvent { + + BranchEvent *event = [BranchEvent customEventWithName:@"RESERVE"]; + + BranchUniversalObject *buo = [BranchUniversalObject new]; + buo.canonicalIdentifier = @"item/12345"; + buo.canonicalUrl = @"https://branch.io/deepviews"; + buo.title = @"My Content Title"; + buo.contentDescription = @"my_product_description1"; + + NSMutableArray *contentItems = [NSMutableArray new]; + [contentItems addObject:buo]; + event.contentItems = contentItems; + + NSDictionary *eventDictionary = [event buildEventDictionary]; + + XCTAssertNotNil(eventDictionary); + XCTAssert([eventDictionary[@"name"] isEqualToString:@"RESERVE"]); + XCTAssertNotNil(eventDictionary[@"content_items"]); + + BranchEventRequest *request = [event buildRequestWithEventDictionary:eventDictionary]; + XCTAssert([request.serverURL.absoluteString containsString:@"branch.io/v2/event/standard"]); +} + +- (void)testStandardSubscribeEvent { + BranchEvent *event = [BranchEvent standardEvent:BranchStandardEventSubscribe]; + event.currency = BNCCurrencyUSD; + event.revenue = [NSDecimalNumber decimalNumberWithString:@"1.0"]; + + BranchUniversalObject *buo = [BranchUniversalObject new]; + buo.canonicalIdentifier = @"item/12345"; + buo.canonicalUrl = @"https://branch.io/deepviews"; + buo.title = @"My Content Title"; + buo.contentDescription = @"my_product_description1"; + + NSMutableArray *contentItems = [NSMutableArray new]; + [contentItems addObject:buo]; + event.contentItems = contentItems; + + NSDictionary *eventDictionary = [event buildEventDictionary]; + + XCTAssertNotNil(eventDictionary); + XCTAssert([eventDictionary[@"name"] isEqualToString:@"SUBSCRIBE"]); + + NSDictionary *eventData = eventDictionary[@"event_data"]; + XCTAssert([eventData[@"currency"] isEqualToString:BNCCurrencyUSD]); + XCTAssert([eventData[@"revenue"] isEqual:[NSDecimalNumber decimalNumberWithString:@"1.0"]]); + + BranchEventRequest *request = [event buildRequestWithEventDictionary:eventDictionary]; + XCTAssert([request.serverURL.absoluteString containsString:@"branch.io/v2/event/standard"]); +} + +- (void)testCustomSubscribeEvent { + + BranchEvent *event = [BranchEvent customEventWithName:@"SUBSCRIBE"]; + event.currency = BNCCurrencyUSD; + event.revenue = [NSDecimalNumber decimalNumberWithString:@"1.0"]; + + BranchUniversalObject *buo = [BranchUniversalObject new]; + buo.canonicalIdentifier = @"item/12345"; + buo.canonicalUrl = @"https://branch.io/deepviews"; + buo.title = @"My Content Title"; + buo.contentDescription = @"my_product_description1"; + + NSMutableArray *contentItems = [NSMutableArray new]; + [contentItems addObject:buo]; + event.contentItems = contentItems; + + NSDictionary *eventDictionary = [event buildEventDictionary]; + + XCTAssertNotNil(eventDictionary); + XCTAssert([eventDictionary[@"name"] isEqualToString:@"SUBSCRIBE"]); + XCTAssertNotNil(eventDictionary[@"content_items"]); + + NSDictionary *eventData = eventDictionary[@"event_data"]; + XCTAssert([eventData[@"currency"] isEqualToString:BNCCurrencyUSD]); + XCTAssert([eventData[@"revenue"] isEqual:[NSDecimalNumber decimalNumberWithString:@"1.0"]]); + + BranchEventRequest *request = [event buildRequestWithEventDictionary:eventDictionary]; + XCTAssert([request.serverURL.absoluteString containsString:@"branch.io/v2/event/standard"]); +} + +- (void)testStandardStartTrialEvent { + BranchEvent *event = [BranchEvent standardEvent:BranchStandardEventStartTrial]; + event.currency = BNCCurrencyUSD; + event.revenue = [NSDecimalNumber decimalNumberWithString:@"1.0"]; + + BranchUniversalObject *buo = [BranchUniversalObject new]; + buo.canonicalIdentifier = @"item/12345"; + buo.canonicalUrl = @"https://branch.io/deepviews"; + buo.title = @"My Content Title"; + buo.contentDescription = @"my_product_description1"; + + NSMutableArray *contentItems = [NSMutableArray new]; + [contentItems addObject:buo]; + event.contentItems = contentItems; + + NSDictionary *eventDictionary = [event buildEventDictionary]; + + XCTAssertNotNil(eventDictionary); + XCTAssert([eventDictionary[@"name"] isEqualToString:@"START_TRIAL"]); + + NSDictionary *eventData = eventDictionary[@"event_data"]; + XCTAssert([eventData[@"currency"] isEqualToString:BNCCurrencyUSD]); + XCTAssert([eventData[@"revenue"] isEqual:[NSDecimalNumber decimalNumberWithString:@"1.0"]]); + + BranchEventRequest *request = [event buildRequestWithEventDictionary:eventDictionary]; + XCTAssert([request.serverURL.absoluteString containsString:@"branch.io/v2/event/standard"]); +} + +- (void)testCustomStartTrialEvent { + + BranchEvent *event = [BranchEvent customEventWithName:@"START_TRIAL"]; + event.currency = BNCCurrencyUSD; + event.revenue = [NSDecimalNumber decimalNumberWithString:@"1.0"]; + + BranchUniversalObject *buo = [BranchUniversalObject new]; + buo.canonicalIdentifier = @"item/12345"; + buo.canonicalUrl = @"https://branch.io/deepviews"; + buo.title = @"My Content Title"; + buo.contentDescription = @"my_product_description1"; + + NSMutableArray *contentItems = [NSMutableArray new]; + [contentItems addObject:buo]; + event.contentItems = contentItems; + + NSDictionary *eventDictionary = [event buildEventDictionary]; + + XCTAssertNotNil(eventDictionary); + XCTAssert([eventDictionary[@"name"] isEqualToString:@"START_TRIAL"]); + XCTAssertNotNil(eventDictionary[@"content_items"]); + + NSDictionary *eventData = eventDictionary[@"event_data"]; + XCTAssert([eventData[@"currency"] isEqualToString:BNCCurrencyUSD]); + XCTAssert([eventData[@"revenue"] isEqual:[NSDecimalNumber decimalNumberWithString:@"1.0"]]); + + BranchEventRequest *request = [event buildRequestWithEventDictionary:eventDictionary]; + XCTAssert([request.serverURL.absoluteString containsString:@"branch.io/v2/event/standard"]); +} + +- (void)testStandardClickAdEvent { + BranchEvent *event = [BranchEvent standardEvent:BranchStandardEventClickAd]; + event.adType = BranchEventAdTypeBanner; + + BranchUniversalObject *buo = [BranchUniversalObject new]; + buo.canonicalIdentifier = @"item/12345"; + buo.canonicalUrl = @"https://branch.io/deepviews"; + buo.title = @"My Content Title"; + buo.contentDescription = @"my_product_description1"; + + NSMutableArray *contentItems = [NSMutableArray new]; + [contentItems addObject:buo]; + event.contentItems = contentItems; + + NSDictionary *eventDictionary = [event buildEventDictionary]; + + XCTAssertNotNil(eventDictionary); + XCTAssert([eventDictionary[@"name"] isEqualToString:@"CLICK_AD"]); + + NSDictionary *eventData = eventDictionary[@"event_data"]; + XCTAssert([eventData[@"ad_type"] isEqual:[event jsonStringForAdType:event.adType]]); + + BranchEventRequest *request = [event buildRequestWithEventDictionary:eventDictionary]; + XCTAssert([request.serverURL.absoluteString containsString:@"branch.io/v2/event/standard"]); +} + +- (void)testCustomClickAdEvent { + + BranchEvent *event = [BranchEvent customEventWithName:@"CLICK_AD"]; + event.adType = BranchEventAdTypeBanner; + + BranchUniversalObject *buo = [BranchUniversalObject new]; + buo.canonicalIdentifier = @"item/12345"; + buo.canonicalUrl = @"https://branch.io/deepviews"; + buo.title = @"My Content Title"; + buo.contentDescription = @"my_product_description1"; + + NSMutableArray *contentItems = [NSMutableArray new]; + [contentItems addObject:buo]; + event.contentItems = contentItems; + + NSDictionary *eventDictionary = [event buildEventDictionary]; + + XCTAssertNotNil(eventDictionary); + XCTAssert([eventDictionary[@"name"] isEqualToString:@"CLICK_AD"]); + XCTAssertNotNil(eventDictionary[@"content_items"]); + + NSDictionary *eventData = eventDictionary[@"event_data"]; + XCTAssert([eventData[@"ad_type"] isEqual:[event jsonStringForAdType:event.adType]]); + + BranchEventRequest *request = [event buildRequestWithEventDictionary:eventDictionary]; + XCTAssert([request.serverURL.absoluteString containsString:@"branch.io/v2/event/standard"]); +} + +- (void)testStandardViewAdEvent { + BranchEvent *event = [BranchEvent standardEvent:BranchStandardEventViewAd]; + event.adType = BranchEventAdTypeBanner; + + BranchUniversalObject *buo = [BranchUniversalObject new]; + buo.canonicalIdentifier = @"item/12345"; + buo.canonicalUrl = @"https://branch.io/deepviews"; + buo.title = @"My Content Title"; + buo.contentDescription = @"my_product_description1"; + + NSMutableArray *contentItems = [NSMutableArray new]; + [contentItems addObject:buo]; + event.contentItems = contentItems; + + NSDictionary *eventDictionary = [event buildEventDictionary]; + + XCTAssertNotNil(eventDictionary); + XCTAssert([eventDictionary[@"name"] isEqualToString:@"VIEW_AD"]); + + NSDictionary *eventData = eventDictionary[@"event_data"]; + XCTAssert([eventData[@"ad_type"] isEqual:[event jsonStringForAdType:event.adType]]); + + BranchEventRequest *request = [event buildRequestWithEventDictionary:eventDictionary]; + XCTAssert([request.serverURL.absoluteString containsString:@"branch.io/v2/event/standard"]); +} + +- (void)testCustomViewAdEvent { + + BranchEvent *event = [BranchEvent customEventWithName:@"VIEW_AD"]; + event.adType = BranchEventAdTypeBanner; + + BranchUniversalObject *buo = [BranchUniversalObject new]; + buo.canonicalIdentifier = @"item/12345"; + buo.canonicalUrl = @"https://branch.io/deepviews"; + buo.title = @"My Content Title"; + buo.contentDescription = @"my_product_description1"; + + NSMutableArray *contentItems = [NSMutableArray new]; + [contentItems addObject:buo]; + event.contentItems = contentItems; + + NSDictionary *eventDictionary = [event buildEventDictionary]; + + XCTAssertNotNil(eventDictionary); + XCTAssert([eventDictionary[@"name"] isEqualToString:@"VIEW_AD"]); + XCTAssertNotNil(eventDictionary[@"content_items"]); + + NSDictionary *eventData = eventDictionary[@"event_data"]; + XCTAssert([eventData[@"ad_type"] isEqual:[event jsonStringForAdType:event.adType]]); + + BranchEventRequest *request = [event buildRequestWithEventDictionary:eventDictionary]; + XCTAssert([request.serverURL.absoluteString containsString:@"branch.io/v2/event/standard"]); +} + +- (void)testStandardOptInEvent { + BranchEvent *event = [BranchEvent standardEvent:BranchStandardEventOptIn]; + + NSDictionary *eventDictionary = [event buildEventDictionary]; + XCTAssertNotNil(eventDictionary); + XCTAssert([eventDictionary[@"name"] isEqualToString:@"OPT_IN"]); + + BranchEventRequest *request = [event buildRequestWithEventDictionary:eventDictionary]; + XCTAssert([request.serverURL.absoluteString containsString:@"branch.io/v2/event/standard"]); +} + +- (void)testCustomOptInEvent { + BranchEvent *event = [BranchEvent customEventWithName:@"OPT_IN"]; + + NSDictionary *eventDictionary = [event buildEventDictionary]; + XCTAssertNotNil(eventDictionary); + XCTAssert([eventDictionary[@"name"] isEqualToString:@"OPT_IN"]); + + BranchEventRequest *request = [event buildRequestWithEventDictionary:eventDictionary]; + XCTAssert([request.serverURL.absoluteString containsString:@"branch.io/v2/event/standard"]); +} + +- (void)testStandardOptOutEvent { + BranchEvent *event = [BranchEvent standardEvent:BranchStandardEventOptOut]; + + NSDictionary *eventDictionary = [event buildEventDictionary]; + XCTAssertNotNil(eventDictionary); + XCTAssert([eventDictionary[@"name"] isEqualToString:@"OPT_OUT"]); + + BranchEventRequest *request = [event buildRequestWithEventDictionary:eventDictionary]; + XCTAssert([request.serverURL.absoluteString containsString:@"branch.io/v2/event/standard"]); +} + +- (void)testCustomOptOutEvent { + BranchEvent *event = [BranchEvent customEventWithName:@"OPT_OUT"]; + + NSDictionary *eventDictionary = [event buildEventDictionary]; + XCTAssertNotNil(eventDictionary); + XCTAssert([eventDictionary[@"name"] isEqualToString:@"OPT_OUT"]); + + BranchEventRequest *request = [event buildRequestWithEventDictionary:eventDictionary]; + XCTAssert([request.serverURL.absoluteString containsString:@"branch.io/v2/event/standard"]); +} + + +- (void)testStandardInitiateStreamEvent { + BranchEvent *event = [BranchEvent standardEvent:BranchStandardEventInitiateStream]; + + NSDictionary *eventDictionary = [event buildEventDictionary]; + XCTAssertNotNil(eventDictionary); + XCTAssert([eventDictionary[@"name"] isEqualToString:@"INITIATE_STREAM"]); + + BranchEventRequest *request = [event buildRequestWithEventDictionary:eventDictionary]; + XCTAssert([request.serverURL.absoluteString containsString:@"branch.io/v2/event/standard"]); +} + +- (void)testCustomInitiateStreamEvent { + BranchEvent *event = [BranchEvent customEventWithName:@"INITIATE_STREAM"]; + + NSDictionary *eventDictionary = [event buildEventDictionary]; + XCTAssertNotNil(eventDictionary); + XCTAssert([eventDictionary[@"name"] isEqualToString:@"INITIATE_STREAM"]); + + BranchEventRequest *request = [event buildRequestWithEventDictionary:eventDictionary]; + XCTAssert([request.serverURL.absoluteString containsString:@"branch.io/v2/event/standard"]); +} + +- (void)testStandardCompleteStreamEvent { + BranchEvent *event = [BranchEvent standardEvent:BranchStandardEventCompleteStream]; + + NSDictionary *eventDictionary = [event buildEventDictionary]; + XCTAssertNotNil(eventDictionary); + XCTAssert([eventDictionary[@"name"] isEqualToString:@"COMPLETE_STREAM"]); + + BranchEventRequest *request = [event buildRequestWithEventDictionary:eventDictionary]; + XCTAssert([request.serverURL.absoluteString containsString:@"branch.io/v2/event/standard"]); +} + +- (void)testCustomCompleteStreamEvent { + BranchEvent *event = [BranchEvent customEventWithName:@"COMPLETE_STREAM"]; + + NSDictionary *eventDictionary = [event buildEventDictionary]; + XCTAssertNotNil(eventDictionary); + XCTAssert([eventDictionary[@"name"] isEqualToString:@"COMPLETE_STREAM"]); + + BranchEventRequest *request = [event buildRequestWithEventDictionary:eventDictionary]; + XCTAssert([request.serverURL.absoluteString containsString:@"branch.io/v2/event/standard"]); +} + +- (void)testJsonStringForAdTypeNone { + BranchEvent *event = [BranchEvent standardEvent:BranchStandardEventViewAd]; + XCTAssertNil([event jsonStringForAdType:BranchEventAdTypeNone]); +} + +- (void)testJsonStringForAdTypeBanner { + BranchEvent *event = [BranchEvent standardEvent:BranchStandardEventViewAd]; + XCTAssertTrue([[event jsonStringForAdType:BranchEventAdTypeBanner] isEqualToString:@"BANNER"]); +} + +- (void)testJsonStringForAdTypeInterstitial { + BranchEvent *event = [BranchEvent standardEvent:BranchStandardEventViewAd]; + XCTAssertTrue([[event jsonStringForAdType:BranchEventAdTypeInterstitial] isEqualToString:@"INTERSTITIAL"]); +} + +- (void)testJsonStringForAdTypeRewardedVideo { + BranchEvent *event = [BranchEvent standardEvent:BranchStandardEventViewAd]; + XCTAssertTrue([[event jsonStringForAdType:BranchEventAdTypeRewardedVideo] isEqualToString:@"REWARDED_VIDEO"]); +} + +- (void)testJsonStringForAdTypeNative { + BranchEvent *event = [BranchEvent standardEvent:BranchStandardEventViewAd]; + XCTAssertTrue([[event jsonStringForAdType:BranchEventAdTypeNative] isEqualToString:@"NATIVE"]); +} + +- (void) testCustomEventWithContentItem { + BranchUniversalObject *buo = [[BranchUniversalObject new] initWithTitle:@"buoTitle"]; + BranchEvent *event = [BranchEvent customEventWithName:@"testEvent" contentItem:buo]; + + XCTAssertTrue(event.contentItems.count == 1); + XCTAssertTrue([event.contentItems.firstObject.title isEqualToString:@"buoTitle"]); +} + +- (void)testLogEventWithCompletion_InvalidEventName { + XCTestExpectation *expectation = [self expectationWithDescription:@"Logging Event"]; + BranchEvent *event = [BranchEvent customEventWithName:@""]; + + [event logEventWithCompletion:^(BOOL success, NSError * _Nullable error) { + XCTAssertFalse(success, @"Success should be NO for invalid event name"); + XCTAssertNotNil(error, @"Error should not be nil for invalid event name"); + XCTAssertEqual(error.code, BNCGeneralError, @"Error code should match expected value for invalid event name"); + [expectation fulfill]; + }]; + + [self waitForExpectationsWithTimeout:5 handler:nil]; +} + + +@end diff --git a/BranchSDKTests/BranchEvent.Test.swift b/BranchSDKTests/BranchEvent.Test.swift new file mode 100644 index 000000000..49d819cc9 --- /dev/null +++ b/BranchSDKTests/BranchEvent.Test.swift @@ -0,0 +1,129 @@ +// +// BranchEvent.Test.swift +// Branch-SDK-Tests +// +// Created by edward on 10/9/17. +// Copyright © 2017 Branch, Inc. All rights reserved. +// + +import XCTest +/* +// TODO: fix this test class, requires modules which our testbed is not using +final class BranchEventTestSwift : XCTestCase { + + override func setUpWithError() throws { + // Put setup code here. This method is called before the invocation of each test method in the class. + + Branch.getInstance("key_live_foo") + } + + override func tearDownWithError() throws { + // Put teardown code here. This method is called after the invocation of each test method in the class. + } + + func testBranchEvent() throws { + + // Set up the Branch Universal Object -- + + let branchUniversalObject = BranchUniversalObject.init() + branchUniversalObject.canonicalIdentifier = "item/12345" + branchUniversalObject.canonicalUrl = "https://branch.io/deepviews" + branchUniversalObject.title = "My Content Title" + branchUniversalObject.contentDescription = "my_product_description1" + branchUniversalObject.imageUrl = "https://test_img_url" + branchUniversalObject.keywords = [ "My_Keyword1", "My_Keyword2" ] + branchUniversalObject.creationDate = Date.init(timeIntervalSince1970:1501869445321.0/1000.0) + branchUniversalObject.expirationDate = Date.init(timeIntervalSince1970:212123232544.0/1000.0) + branchUniversalObject.locallyIndex = true + branchUniversalObject.publiclyIndex = false + + branchUniversalObject.contentMetadata.contentSchema = .commerceProduct + branchUniversalObject.contentMetadata.quantity = 2 + branchUniversalObject.contentMetadata.price = 23.20 + branchUniversalObject.contentMetadata.currency = .USD + branchUniversalObject.contentMetadata.sku = "1994320302" + branchUniversalObject.contentMetadata.productName = "my_product_name1" + branchUniversalObject.contentMetadata.productBrand = "my_prod_Brand1" + branchUniversalObject.contentMetadata.productCategory = .babyToddler + branchUniversalObject.contentMetadata.productVariant = "3T" + branchUniversalObject.contentMetadata.condition = .fair + + branchUniversalObject.contentMetadata.ratingAverage = 5; + branchUniversalObject.contentMetadata.ratingCount = 5; + branchUniversalObject.contentMetadata.ratingMax = 7; + branchUniversalObject.contentMetadata.rating = 6; + branchUniversalObject.contentMetadata.addressStreet = "Street_name1" + branchUniversalObject.contentMetadata.addressCity = "city1" + branchUniversalObject.contentMetadata.addressRegion = "Region1" + branchUniversalObject.contentMetadata.addressCountry = "Country1" + branchUniversalObject.contentMetadata.addressPostalCode = "postal_code" + branchUniversalObject.contentMetadata.latitude = 12.07 + branchUniversalObject.contentMetadata.longitude = -97.5 + branchUniversalObject.contentMetadata.imageCaptions = [ + "my_img_caption1", + "my_img_caption_2" + ] + branchUniversalObject.contentMetadata.customMetadata = [ + "Custom_Content_metadata_key1": "Custom_Content_metadata_val1", + "Custom_Content_metadata_key2": "Custom_Content_metadata_val2" + ] + + // Set up the event properties -- + + let event = BranchEvent.standardEvent(.purchase) + event.transactionID = "12344555" + event.currency = .USD; + event.revenue = 1.5 + event.shipping = 10.2 + event.tax = 12.3 + event.coupon = "test_coupon"; + event.affiliation = "test_affiliation"; + event.eventDescription = "Event _description"; + event.searchQuery = "Query" + event.customData = [ + "Custom_Event_Property_Key1": "Custom_Event_Property_val1", + "Custom_Event_Property_Key2": "Custom_Event_Property_val2" + ] + + var testDictionary = event.dictionary() + var dictionary = self.mutableDictionaryFromBundleJSON(withKey: "V2EventProperties") + XCTAssert((dictionary?.isEqual(to: testDictionary))!) + + testDictionary = branchUniversalObject.dictionary() as! [AnyHashable : Any] + dictionary = self.mutableDictionaryFromBundleJSON(withKey: "BranchUniversalObjectJSON") + dictionary!["$publicly_indexable"] = nil // Remove this value since we don't add false values. + XCTAssert((dictionary?.isEqual(to: testDictionary))!) + + event.contentItems = [ branchUniversalObject ] + event.logEvent() + } + + func testExampleSyntaxSwift() throws { + let contentItem = BranchUniversalObject.init() + contentItem.canonicalIdentifier = "item/123" + contentItem.canonicalUrl = "https://branch.io/item/123" + contentItem.contentMetadata.ratingAverage = 5.0; + + var event = BranchEvent.standardEvent(.spendCredits) + event.transactionID = "tx1234" + event.eventDescription = "Product Search" + event.searchQuery = "user search query terms for product xyz" + event.customData["Custom_Event_Property_Key1"] = "Custom_Event_Property_val1" + event.contentItems = [ contentItem ] + event.logEvent() + + event = BranchEvent.standardEvent(.viewItem) + event.logEvent(); + + // Quickly log an event: + BranchEvent.standardEvent(.viewItem).logEvent() + + // Quickly log an event with content: + let branchUniversalObject = BranchUniversalObject.init() + branchUniversalObject.canonicalIdentifier = "item/12345" + branchUniversalObject.canonicalUrl = "https://branch.io/deepviews" + branchUniversalObject.title = "My Content Title" + BranchEvent.standardEvent(.viewItem, withContentItem: branchUniversalObject).logEvent() + } +} +*/ diff --git a/BranchSDKTests/BranchLastAttributedTouchDataTests.m b/BranchSDKTests/BranchLastAttributedTouchDataTests.m new file mode 100644 index 000000000..908711125 --- /dev/null +++ b/BranchSDKTests/BranchLastAttributedTouchDataTests.m @@ -0,0 +1,63 @@ +// +// BranchLastAttributedTouchDataTests.m +// Branch-SDK-Tests +// +// Created by Ernest Cho on 9/18/19. +// Copyright © 2019 Branch, Inc. All rights reserved. +// + +#import +#import "BNCJsonLoader.h" +#import "BranchLastAttributedTouchData.h" + +@interface BranchLastAttributedTouchDataTests : XCTestCase + +@end + +@implementation BranchLastAttributedTouchDataTests + +- (void)setUp { + // Put setup code here. This method is called before the invocation of each test method in the class. +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. +} + +- (void)testBuildFromJSON { + NSDictionary *json = [BNCJsonLoader dictionaryFromJSONFileNamed:@"latd"]; + XCTAssertNotNil(json); + + BranchLastAttributedTouchData *latd = [BranchLastAttributedTouchData buildFromJSON:json]; + XCTAssertNotNil(latd); + XCTAssertNotNil(latd.lastAttributedTouchJSON); + XCTAssertNotNil(latd.attributionWindow); +} + +- (void)testBuildFromJSON_EmptyData { + NSDictionary *json = [BNCJsonLoader dictionaryFromJSONFileNamed:@"latd_empty_data"]; + XCTAssertNotNil(json); + + BranchLastAttributedTouchData *latd = [BranchLastAttributedTouchData buildFromJSON:json]; + XCTAssertNotNil(latd); + XCTAssertTrue(latd.lastAttributedTouchJSON.count == 0); +} + +- (void)testBuildFromJSON_MissingData { + NSDictionary *json = [BNCJsonLoader dictionaryFromJSONFileNamed:@"latd_missing_data"]; + XCTAssertNotNil(json); + + BranchLastAttributedTouchData *latd = [BranchLastAttributedTouchData buildFromJSON:json]; + XCTAssertNil(latd); +} + +- (void)testBuildFromJSON_MissingWindow { + NSDictionary *json = [BNCJsonLoader dictionaryFromJSONFileNamed:@"latd_missing_window"]; + XCTAssertNotNil(json); + + BranchLastAttributedTouchData *latd = [BranchLastAttributedTouchData buildFromJSON:json]; + XCTAssertNotNil(latd); + XCTAssertNil(latd.attributionWindow); +} + +@end diff --git a/BranchSDKTests/BranchLoggerTests.m b/BranchSDKTests/BranchLoggerTests.m new file mode 100644 index 000000000..1a4be3490 --- /dev/null +++ b/BranchSDKTests/BranchLoggerTests.m @@ -0,0 +1,261 @@ +// +// BranchLoggerTests.m +// Branch-SDK-Tests +// +// Created by Nipun Singh on 2/5/24. +// Copyright © 2024 Branch, Inc. All rights reserved. +// + +#import +#import "BranchLogger.h" +#import "Branch.h" + +@interface BranchLoggerTests : XCTestCase + +@end + +@implementation BranchLoggerTests + +// public API test +- (void)testEnableLoggingSetsCorrectDefaultLevel { + [[Branch getInstance] enableLogging]; + XCTAssertEqual([BranchLogger shared].logLevelThreshold, BranchLogLevelDebug, "Default log level should be Debug."); +} + +- (void)testLoggingEnabled_NOByDefault { + BranchLogger *logger = [BranchLogger new]; + + __block int count = 0; + logger.logCallback = ^(NSString * _Nonnull message, BranchLogLevel logLevel, NSError * _Nullable error) { + count = count + 1; + }; + [logger logError:@"msg" error:nil]; + + XCTAssertTrue(count == 0); +} + +- (void)testLoggingEnabled_Yes { + BranchLogger *logger = [BranchLogger new]; + logger.loggingEnabled = YES; + + __block int count = 0; + logger.logCallback = ^(NSString * _Nonnull message, BranchLogLevel logLevel, NSError * _Nullable error) { + count = count + 1; + }; + + [logger logError:@"msg" error:nil]; + XCTAssertTrue(count == 1); + + [logger logError:@"msg" error:nil]; + XCTAssertTrue(count == 2); +} + +- (void)testLoggingIgnoresNil { + BranchLogger *logger = [BranchLogger new]; + logger.loggingEnabled = YES; + + __block int count = 0; + logger.logCallback = ^(NSString * _Nonnull message, BranchLogLevel logLevel, NSError * _Nullable error) { + count = count + 1; + }; + + [logger logError:nil error:nil]; + XCTAssertTrue(count == 0); +} + +- (void)testLoggingIgnoresEmptyString { + BranchLogger *logger = [BranchLogger new]; + logger.loggingEnabled = YES; + + __block int count = 0; + logger.logCallback = ^(NSString * _Nonnull message, BranchLogLevel logLevel, NSError * _Nullable error) { + count = count + 1; + }; + + [logger logError:@"" error:nil]; + XCTAssertTrue(count == 0); +} + +- (void)testLoggingEnabled_YesThenNo { + BranchLogger *logger = [BranchLogger new]; + logger.loggingEnabled = YES; + + __block int count = 0; + logger.logCallback = ^(NSString * _Nonnull message, BranchLogLevel logLevel, NSError * _Nullable error) { + count = count + 1; + }; + + // one call + [logger logError:@"msg" error:nil]; + XCTAssertTrue(count == 1); + + // disable, second call is ignored + logger.loggingEnabled = NO; + [logger logError:@"msg" error:nil]; + XCTAssertTrue(count == 1); +} + +- (void)testLogLevel_DebugByDefault { + BranchLogger *logger = [BranchLogger new]; + logger.loggingEnabled = YES; + + __block int count = 0; + logger.logCallback = ^(NSString * _Nonnull message, BranchLogLevel logLevel, NSError * _Nullable error) { + count = count + 1; + }; + + [logger logError:@"msg" error:nil]; + XCTAssertTrue(count == 1); + [logger logWarning:@"msg" error:nil]; + XCTAssertTrue(count == 2); + [logger logDebug:@"msg" error:nil]; + XCTAssertTrue(count == 3); + + // this should be ignored and the counter not incremented + [logger logVerbose:@"msg" error:nil]; + XCTAssertTrue(count == 3); +} + +- (void)testLogLevel_Error { + BranchLogger *logger = [BranchLogger new]; + logger.loggingEnabled = YES; + logger.logLevelThreshold = BranchLogLevelError; + + + __block int count = 0; + logger.logCallback = ^(NSString * _Nonnull message, BranchLogLevel logLevel, NSError * _Nullable error) { + count = count + 1; + }; + + [logger logError:@"msg" error:nil]; + XCTAssertTrue(count == 1); + + // these should be ignored and the counter not incremented + [logger logWarning:@"msg" error:nil]; + XCTAssertTrue(count == 1); + [logger logDebug:@"msg" error:nil]; + XCTAssertTrue(count == 1); + [logger logVerbose:@"msg" error:nil]; + XCTAssertTrue(count == 1); +} + +- (void)testLogLevel_Warning { + BranchLogger *logger = [BranchLogger new]; + logger.loggingEnabled = YES; + logger.logLevelThreshold = BranchLogLevelWarning; + + + __block int count = 0; + logger.logCallback = ^(NSString * _Nonnull message, BranchLogLevel logLevel, NSError * _Nullable error) { + count = count + 1; + }; + + [logger logError:@"msg" error:nil]; + XCTAssertTrue(count == 1); + [logger logWarning:@"msg" error:nil]; + XCTAssertTrue(count == 2); + + // this should be ignored and the counter not incremented + [logger logDebug:@"msg" error:nil]; + XCTAssertTrue(count == 2); + [logger logVerbose:@"msg" error:nil]; + XCTAssertTrue(count == 2); +} + +- (void)testLogLevel_Verbose { + BranchLogger *logger = [BranchLogger new]; + logger.loggingEnabled = YES; + logger.logLevelThreshold = BranchLogLevelVerbose; + + + __block int count = 0; + logger.logCallback = ^(NSString * _Nonnull message, BranchLogLevel logLevel, NSError * _Nullable error) { + count = count + 1; + }; + + [logger logError:@"msg" error:nil]; + XCTAssertTrue(count == 1); + [logger logWarning:@"msg" error:nil]; + XCTAssertTrue(count == 2); + [logger logDebug:@"msg" error:nil]; + XCTAssertTrue(count == 3); + [logger logVerbose:@"msg" error:nil]; + XCTAssertTrue(count == 4); +} + +- (void)testLogFormat_Default { + BranchLogger *logger = [BranchLogger new]; + logger.loggingEnabled = YES; + + logger.logCallback = ^(NSString * _Nonnull message, BranchLogLevel logLevel, NSError * _Nullable error) { + NSString *expectedMessage = @"[BranchLoggerTests testLogFormat_Default] msg"; + + XCTAssertTrue([expectedMessage isEqualToString:message]); + XCTAssertTrue(logLevel == BranchLogLevelError); + XCTAssertNil(error); + }; + + [logger logError:@"msg" error:nil]; +} + +- (void)testLogFormat_NSError { + __block NSError *originalError = [NSError errorWithDomain:@"com.domain.test" code:200 userInfo:@{@"Error Message": @"Test Error"}]; + + BranchLogger *logger = [BranchLogger new]; + logger.loggingEnabled = YES; + + logger.logCallback = ^(NSString * _Nonnull message, BranchLogLevel logLevel, NSError * _Nullable error) { + NSString *expectedMessage = @"[BranchLoggerTests testLogFormat_NSError] msg"; + + XCTAssertTrue([expectedMessage isEqualToString:message]); + XCTAssertTrue(logLevel == BranchLogLevelError); + XCTAssertTrue(originalError == error); + }; + + [logger logError:@"msg" error:originalError]; +} + +- (void)testLogFormat_includeCallerDetailsNO { + BranchLogger *logger = [BranchLogger new]; + logger.loggingEnabled = YES; + logger.includeCallerDetails = NO; + + logger.logCallback = ^(NSString * _Nonnull message, BranchLogLevel logLevel, NSError * _Nullable error) { + NSString *expectedMessage = @"msg"; + + XCTAssertTrue([expectedMessage isEqualToString:message]); + XCTAssertTrue(logLevel == BranchLogLevelError); + XCTAssertNil(error); + }; + + [logger logError:@"msg" error:nil]; +} + +- (void)testLogFormat_includeCallerDetailsNO_NSError { + __block NSError *originalError = [NSError errorWithDomain:@"com.domain.test" code:200 userInfo:@{@"Error Message": @"Test Error"}]; + + BranchLogger *logger = [BranchLogger new]; + logger.loggingEnabled = YES; + logger.includeCallerDetails = NO; + + logger.logCallback = ^(NSString * _Nonnull message, BranchLogLevel logLevel, NSError * _Nullable error) { + NSString *expectedMessage = @"msg"; + + XCTAssertTrue([expectedMessage isEqualToString:message]); + XCTAssertTrue(logLevel == BranchLogLevelError); + XCTAssertTrue(originalError == error); + }; + + [logger logError:@"msg" error:originalError]; +} + +- (void)testDefaultBranchLogFormat { + NSError *error = [NSError errorWithDomain:@"com.domain.test" code:200 userInfo:@{@"Error Message": @"Test Error"}]; + + NSString *expectedMessage = @"[BranchSDK][Error]msg NSError: Error Domain=com.domain.test Code=200 \"(null)\" UserInfo={Error Message=Test Error}"; + NSString *formattedMessage = [BranchLogger formatMessage:@"msg" logLevel:BranchLogLevelError error:error]; + + XCTAssertTrue([expectedMessage isEqualToString:formattedMessage]); +} + +@end diff --git a/BranchSDKTests/BranchPluginSupportTests.m b/BranchSDKTests/BranchPluginSupportTests.m new file mode 100644 index 000000000..d46b620fc --- /dev/null +++ b/BranchSDKTests/BranchPluginSupportTests.m @@ -0,0 +1,91 @@ +// +// BranchPluginSupportTests.m +// Branch-SDK-Tests +// +// Created by Nipun Singh on 1/25/22. +// Copyright © 2022 Branch, Inc. All rights reserved. +// + +#import +#import "BranchPluginSupport.h" + +@interface BranchPluginSupportTests : XCTestCase +@property (nonatomic, strong, readwrite) NSDictionary *deviceDescription; +@end + +@implementation BranchPluginSupportTests + +- (void)setUp { + self.deviceDescription = [[BranchPluginSupport new] deviceDescription]; +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. +} + +- (void)testAppVersion { + // checks test app version + XCTAssert([@"1.0" isEqualToString:_deviceDescription[@"app_version"]]); +} + +- (void)testBrandName { + XCTAssert([@"Apple" isEqualToString:_deviceDescription[@"brand"]]); +} + +- (void)testModelName_Simulator { + // intel processor + bool x86_64 = [@"x86_64" isEqualToString:_deviceDescription[@"model"]]; + + // apple processor + bool arm64 = [@"arm64" isEqualToString:_deviceDescription[@"model"]]; + + XCTAssert(x86_64 || arm64); +} + +- (void)testOSName { + XCTAssertNotNil(_deviceDescription[@"os"]); + XCTAssert([_deviceDescription[@"os"] isEqualToString:[UIDevice currentDevice].systemName]); +} + +- (void)testOSVersion { + XCTAssertNotNil(_deviceDescription[@"os_version"]); + XCTAssert([_deviceDescription[@"os_version"] isEqualToString:[UIDevice currentDevice].systemVersion]); +} + +- (void)testEnvironment { + XCTAssert([@"FULL_APP" isEqualToString:_deviceDescription[@"environment"]]); +} + +- (void)testScreenWidth { + XCTAssert(_deviceDescription[@"screen_width"].intValue > 320); +} + +- (void)testScreenHeight { + XCTAssert(_deviceDescription[@"screen_height"].intValue > 320); +} + +- (void)testScreenScale { + XCTAssert(_deviceDescription[@"screen_dpi"].intValue > 0); +} + +- (void)testCountry { + NSString *locale = [NSLocale currentLocale].localeIdentifier; + XCTAssertNotNil(locale); + XCTAssert([locale containsString:_deviceDescription[@"country"]]); +} + +- (void)testLanguage { + NSString *locale = [NSLocale currentLocale].localeIdentifier; + XCTAssertNotNil(locale); + XCTAssert([locale containsString:_deviceDescription[@"language"]]); +} + +- (void)testLocalIPAddress { + NSString *address = _deviceDescription[@"local_ip"]; + XCTAssertNotNil(address); + + // shortest ipv4 is 7 + XCTAssert(address.length >= 7); +} + +@end diff --git a/BranchSDKTests/BranchQRCodeTests.m b/BranchSDKTests/BranchQRCodeTests.m new file mode 100644 index 000000000..3d1e1ffc6 --- /dev/null +++ b/BranchSDKTests/BranchQRCodeTests.m @@ -0,0 +1,154 @@ +// +// BranchQRCodeTests.m +// Branch-SDK-Tests +// +// Created by Nipun Singh on 4/14/22. +// Copyright © 2022 Branch, Inc. All rights reserved. +// + +#import +#import "Branch.h" +#import "BranchQRCode.h" +#import "BNCQRCodeCache.h" + +@interface BranchQRCodeTests : XCTestCase + +@end + +@implementation BranchQRCodeTests + +- (void)testNormalQRCodeDataWithAllSettings { + XCTestExpectation *expectation = [self expectationWithDescription:@"Fetching QR Code"]; + + BranchQRCode *qrCode = [BranchQRCode new]; + qrCode.width = @(1000); + qrCode.margin = @(1); + qrCode.codeColor = [UIColor blueColor]; + qrCode.backgroundColor = [UIColor whiteColor]; + qrCode.centerLogo = @"https://upload.wikimedia.org/wikipedia/en/a/a9/Example.jpg"; + qrCode.imageFormat = BranchQRCodeImageFormatPNG; + + BranchUniversalObject *buo = [BranchUniversalObject new]; + BranchLinkProperties *lp = [BranchLinkProperties new]; + + [qrCode getQRCodeAsData:buo linkProperties:lp completion:^(NSData * _Nonnull qrCode, NSError * _Nonnull error) { + XCTAssertNil(error); + XCTAssertNotNil(qrCode); + [expectation fulfill]; + }]; + + [self waitForExpectationsWithTimeout:10 handler:^(NSError *error) { + if (error) { + NSLog(@"Error Testing QR Code Cache: %@", error); + XCTFail(); + } + }]; +} + +- (void)testNormalQRCodeAsDataWithNoSettings { + XCTestExpectation *expectation = [self expectationWithDescription:@"Fetching QR Code"]; + + BranchQRCode *qrCode = [BranchQRCode new]; + + BranchUniversalObject *buo = [BranchUniversalObject new]; + BranchLinkProperties *lp = [BranchLinkProperties new]; + + [qrCode getQRCodeAsData:buo linkProperties:lp completion:^(NSData * _Nonnull qrCode, NSError * _Nonnull error) { + XCTAssertNil(error); + XCTAssertNotNil(qrCode); + [expectation fulfill]; + }]; + + [self waitForExpectationsWithTimeout:10 handler:^(NSError *error) { + if (error) { + NSLog(@"Error Testing QR Code Cache: %@", error); + XCTFail(); + } + }]; +} + +- (void)testNormalQRCodeWithInvalidLogoURL { + XCTestExpectation *expectation = [self expectationWithDescription:@"Fetching QR Code"]; + + BranchQRCode *qrCode = [BranchQRCode new]; + qrCode.centerLogo = @"https://branch.branch/notARealImageURL.jpg"; + + BranchUniversalObject *buo = [BranchUniversalObject new]; + BranchLinkProperties *lp = [BranchLinkProperties new]; + + [qrCode getQRCodeAsData:buo linkProperties:lp completion:^(NSData * _Nonnull qrCode, NSError * _Nonnull error) { + XCTAssertNil(error); + XCTAssertNotNil(qrCode); + [expectation fulfill]; + }]; + + [self waitForExpectationsWithTimeout:10 handler:^(NSError *error) { + if (error) { + NSLog(@"Error Testing QR Code Cache: %@", error); + XCTFail(); + } + }]; +} + +- (void)testNormalQRCodeAsImage { + XCTestExpectation *expectation = [self expectationWithDescription:@"Fetching QR Code"]; + + BranchQRCode *qrCode = [BranchQRCode new]; + + BranchUniversalObject *buo = [BranchUniversalObject new]; + BranchLinkProperties *lp = [BranchLinkProperties new]; + + [qrCode getQRCodeAsImage:buo linkProperties:lp completion:^(UIImage * _Nonnull qrCode, NSError * _Nonnull error) { + XCTAssertNil(error); + XCTAssertNotNil(qrCode); + [expectation fulfill]; + }]; + + [self waitForExpectationsWithTimeout:10 handler:^(NSError *error) { + if (error) { + NSLog(@"Error Testing QR Code Cache: %@", error); + XCTFail(); + } + }]; +} + +- (void)testQRCodeCache { + XCTestExpectation *expectation = [self expectationWithDescription:@"Fetching QR Code"]; + + BranchQRCode *myQRCode = [BranchQRCode new]; + BranchUniversalObject *buo = [BranchUniversalObject new]; + BranchLinkProperties *lp = [BranchLinkProperties new]; + + [myQRCode getQRCodeAsData:buo linkProperties:lp completion:^(NSData * _Nonnull qrCode, NSError * _Nonnull error) { + + XCTAssertNil(error); + XCTAssertNotNil(qrCode); + + NSMutableDictionary *parameters = [NSMutableDictionary new]; + NSMutableDictionary *settings = [NSMutableDictionary new]; + + settings[@"image_format"] = @"PNG"; + settings[@"width"] = @(300); + settings[@"margin"] = @(1); + + parameters[@"qr_code_settings"] = settings; + parameters[@"data"] = [NSMutableDictionary new]; + parameters[@"branch_key"] = [Branch branchKey]; + + + NSData *cachedQRCode = [[BNCQRCodeCache sharedInstance] checkQRCodeCache:parameters]; + + XCTAssertEqual(cachedQRCode, qrCode); + [expectation fulfill]; + }]; + + [self waitForExpectationsWithTimeout:10 handler:^(NSError *error) { + if (error) { + NSLog(@"Error Testing QR Code Cache: %@", error); + XCTFail(); + } + }]; +} + + +@end diff --git a/BranchSDKTests/BranchSDKTests.m b/BranchSDKTests/BranchSDKTests.m new file mode 100644 index 000000000..7a37169d8 --- /dev/null +++ b/BranchSDKTests/BranchSDKTests.m @@ -0,0 +1,36 @@ +// +// BranchSDKTests.m +// BranchSDKTests +// +// Created by Nidhi Dixit on 7/6/25. +// + +#import + +@interface BranchSDKTests : XCTestCase + +@end + +@implementation BranchSDKTests + +- (void)setUp { + // Put setup code here. This method is called before the invocation of each test method in the class. +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. +} + +- (void)testExample { + // This is an example of a functional test case. + // Use XCTAssert and related functions to verify your tests produce the correct results. +} + +- (void)testPerformanceExample { + // This is an example of a performance test case. + [self measureBlock:^{ + // Put the code you want to measure the time of here. + }]; +} + +@end diff --git a/BranchSDKTests/BranchSDKTests.xctestplan b/BranchSDKTests/BranchSDKTests.xctestplan new file mode 100644 index 000000000..d72383a21 --- /dev/null +++ b/BranchSDKTests/BranchSDKTests.xctestplan @@ -0,0 +1,33 @@ +{ + "configurations" : [ + { + "id" : "9EAB663B-7807-43EE-AD4E-658E8734932A", + "name" : "Test Scheme Action", + "options" : { + + } + } + ], + "defaultOptions" : { + "targetForVariableExpansion" : { + "containerPath" : "container:BranchSDK.xcodeproj", + "identifier" : "E7CA755E2E1B59F5002EFB40", + "name" : "BranchSDKTestsHostApp" + } + }, + "testTargets" : [ + { + "parallelizable" : false, + "skippedTests" : [ + "BNCDisableAdNetworkCalloutsTests", + "BranchActivityItemTests" + ], + "target" : { + "containerPath" : "container:BranchSDK.xcodeproj", + "identifier" : "E7CA74EA2E1B4F75002EFB40", + "name" : "BranchSDKTests" + } + } + ], + "version" : 1 +} diff --git a/BranchSDKTests/BranchShareLinkTests.m b/BranchSDKTests/BranchShareLinkTests.m new file mode 100644 index 000000000..c41fdb618 --- /dev/null +++ b/BranchSDKTests/BranchShareLinkTests.m @@ -0,0 +1,38 @@ +// +// BranchShareLinkTests.m +// Branch-SDK-Tests +// +// Created by Nipun Singh on 5/5/22. +// Copyright © 2022 Branch, Inc. All rights reserved. +// + +#import +#import "BranchShareLink.h" +#import "BranchLinkProperties.h" +#import "Branch.h" + +@interface BranchShareLinkTests : XCTestCase + +@end + +@implementation BranchShareLinkTests + +- (void)testAddLPLinkMetadata { + BranchUniversalObject *buo = [[BranchUniversalObject alloc] initWithCanonicalIdentifier:@"test/001"]; + BranchLinkProperties *lp = [[BranchLinkProperties alloc] init]; + + BranchShareLink *bsl = [[BranchShareLink alloc] initWithUniversalObject:buo linkProperties:lp]; + + if (@available(iOS 13.0, macCatalyst 13.1, *)) { + NSURL *imageURL = [NSURL URLWithString:@"https://cdn.branch.io/branch-assets/1598575682753-og_image.png"]; + NSData *imageData = [NSData dataWithContentsOfURL:imageURL]; + UIImage *iconImage = [UIImage imageWithData:imageData]; + + [bsl addLPLinkMetadata:@"Test Preview Title" icon:iconImage]; + XCTAssertNotNil([bsl lpMetaData]); + } else { + XCTAssertTrue(true); + } +} + +@end diff --git a/BranchSDKTests/BranchUniversalObjectTests.m b/BranchSDKTests/BranchUniversalObjectTests.m new file mode 100644 index 000000000..9a7112e31 --- /dev/null +++ b/BranchSDKTests/BranchUniversalObjectTests.m @@ -0,0 +1,446 @@ +// +// BranchUniversalObjectTests.m +// Branch-TestBed +// +// Created by Edward Smith on 8/15/17. +// Copyright © 2017 Branch Metrics. All rights reserved. +// + +#import +#import "BranchUniversalObject.h" + +@interface BranchUniversalObjectTests : XCTestCase +@end + +@implementation BranchUniversalObjectTests + +- (void)setUp { + // Put setup code here. This method is called before the invocation of each test method in the class. +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. +} + +#pragma mark BranchContentMetadata tests + +- (BranchContentMetadata *)branchContentMetadataWithAllPropertiesSet { + BranchContentMetadata *metadata = [BranchContentMetadata new]; + metadata.contentSchema = BranchContentSchemaOther; + metadata.quantity = 10; + metadata.price = [[NSDecimalNumber alloc] initWithDouble:5.5]; + metadata.currency = BNCCurrencyUSD; + metadata.sku = @"testSKU"; + metadata.productName = @"testProductName"; + metadata.productBrand = @"testProductBrand"; + metadata.productCategory = BNCProductCategoryApparel; + metadata.productVariant = @"testProductVariant"; + metadata.condition = BranchConditionNew; + metadata.ratingAverage = 3.5; + metadata.ratingCount = 2; + metadata.ratingMax = 4; + metadata.rating = 3; + metadata.addressStreet = @"195 Page Mill Road"; + metadata.addressCity = @"Palo Alto"; + metadata.addressRegion = @"CA"; + metadata.addressCountry = @"USA"; + metadata.addressPostalCode = @"94306"; + metadata.latitude = 37.426; + metadata.longitude = -122.138; + + metadata.imageCaptions = @[ + @"Hello World", + @"Goodbye World" + ].mutableCopy; + + metadata.customMetadata = @{ + @"custom0": @"custom data 0" + }.mutableCopy; + + return metadata; +} + +- (void)verifyBranchContentMetadataWithAllProperties:(BranchContentMetadata *)metadata { + XCTAssertNotNil(metadata); + + XCTAssertEqual(BranchContentSchemaOther, metadata.contentSchema); + XCTAssertTrue([@(10) isEqualToNumber:@(metadata.quantity)]); + XCTAssertTrue([[[NSDecimalNumber alloc] initWithDouble:5.5] isEqualToNumber:metadata.price]); + + XCTAssertEqual(BNCCurrencyUSD, metadata.currency); + XCTAssertTrue([@"testSKU" isEqualToString:metadata.sku]); + XCTAssertTrue([@"testProductName" isEqualToString:metadata.productName]); + XCTAssertTrue([@"testProductBrand" isEqualToString:metadata.productBrand]); + XCTAssertEqual(BNCProductCategoryApparel, metadata.productCategory); + XCTAssertTrue([@"testProductVariant" isEqualToString:metadata.productVariant]); + XCTAssertEqual(BranchConditionNew, metadata.condition); + XCTAssertTrue([@(3.5) isEqualToNumber:@(metadata.ratingAverage)]); + XCTAssertTrue([@(2) isEqualToNumber:@(metadata.ratingCount)]); + XCTAssertTrue([@(4) isEqualToNumber:@(metadata.ratingMax)]); + XCTAssertTrue([@(3) isEqualToNumber:@(metadata.rating)]); + + XCTAssertTrue([@"195 Page Mill Road" isEqualToString:metadata.addressStreet]); + XCTAssertTrue([@"Palo Alto" isEqualToString:metadata.addressCity]); + XCTAssertTrue([@"CA" isEqualToString:metadata.addressRegion]); + XCTAssertTrue([@"USA" isEqualToString:metadata.addressCountry]); + XCTAssertTrue([@"94306" isEqualToString:metadata.addressPostalCode]); + + XCTAssertTrue([@(37.426) isEqualToNumber:@(metadata.latitude)]); + XCTAssertTrue([@(-122.138) isEqualToNumber:@(metadata.longitude)]); + + XCTAssertNotNil(metadata.imageCaptions); + XCTAssertTrue(metadata.imageCaptions.count == 2); + XCTAssertTrue([metadata.imageCaptions[0] isEqualToString:@"Hello World"]); + XCTAssertTrue([metadata.imageCaptions[1] isEqualToString:@"Goodbye World"]); + + XCTAssertNotNil(metadata.customMetadata); + XCTAssertTrue(metadata.customMetadata.allKeys.count == 1); +} + +- (void)verifyBranchContentMetadataDictionaryWithAllPropertiesSet:(NSDictionary *)dict { + XCTAssertTrue([@"OTHER" isEqualToString:dict[@"$content_schema"]]); + XCTAssertTrue([@(10) isEqualToNumber:dict[@"$quantity"]]); + XCTAssertTrue([[[NSDecimalNumber alloc] initWithDouble:5.5] isEqualToNumber:dict[@"$price"]]); + XCTAssertTrue([@"USD" isEqualToString:dict[@"$currency"]]); + XCTAssertTrue([@"testSKU" isEqualToString:dict[@"$sku"]]); + XCTAssertTrue([@"testProductName" isEqualToString:dict[@"$product_name"]]); + XCTAssertTrue([@"testProductBrand" isEqualToString:dict[@"$product_brand"]]); + XCTAssertTrue([@"Apparel & Accessories" isEqualToString:dict[@"$product_category"]]); + XCTAssertTrue([@"testProductVariant" isEqualToString:dict[@"$product_variant"]]); + XCTAssertTrue([@"NEW" isEqualToString:dict[@"$condition"]]); + + XCTAssertTrue([@(3.5) isEqualToNumber:dict[@"$rating_average"]]); + XCTAssertTrue([@(2) isEqualToNumber:dict[@"$rating_count"]]); + XCTAssertTrue([@(4) isEqualToNumber:dict[@"$rating_max"]]); + XCTAssertTrue([@(3) isEqualToNumber:dict[@"$rating"]]); + + XCTAssertTrue([@"195 Page Mill Road" isEqualToString:dict[@"$address_street"]]); + XCTAssertTrue([@"Palo Alto" isEqualToString:dict[@"$address_city"]]); + XCTAssertTrue([@"CA" isEqualToString:dict[@"$address_region"]]); + XCTAssertTrue([@"USA" isEqualToString:dict[@"$address_country"]]); + XCTAssertTrue([@"94306" isEqualToString:dict[@"$address_postal_code"]]); + + XCTAssertTrue([@(37.426) isEqualToNumber:dict[@"$latitude"]]); + XCTAssertTrue([@(-122.138) isEqualToNumber:dict[@"$longitude"]]); + + XCTAssertTrue([dict[@"$image_captions"] isKindOfClass:NSArray.class]); + NSArray *tmp = dict[@"$image_captions"]; + XCTAssertTrue(tmp.count == 2); + XCTAssertTrue([tmp[0] isEqualToString:@"Hello World"]); + XCTAssertTrue([tmp[1] isEqualToString:@"Goodbye World"]); + + XCTAssertTrue([@"custom data 0" isEqualToString:dict[@"custom0"]]); +} + +- (void)testBranchContentMetadataCreation_NoPropertiesSet { + BranchContentMetadata *metadata = [BranchContentMetadata new]; + + // most properties default to nil. primitives default to 0 + XCTAssertNil(metadata.contentSchema); + XCTAssertEqual(0, metadata.quantity); + XCTAssertNil(metadata.price); + XCTAssertNil(metadata.currency); + XCTAssertNil(metadata.sku); + XCTAssertNil(metadata.productName); + XCTAssertNil(metadata.productBrand); + XCTAssertNil(metadata.productCategory); + XCTAssertNil(metadata.productVariant); + XCTAssertNil(metadata.condition); + XCTAssertEqual(0, metadata.ratingAverage); + XCTAssertEqual(0, metadata.ratingCount); + XCTAssertEqual(0, metadata.ratingMax); + XCTAssertEqual(0, metadata.rating); + XCTAssertNil(metadata.addressStreet); + XCTAssertNil(metadata.addressCity); + XCTAssertNil(metadata.addressRegion); + XCTAssertNil(metadata.addressCountry); + XCTAssertNil(metadata.addressPostalCode); + XCTAssertEqual(0, metadata.latitude); + XCTAssertEqual(0, metadata.longitude); + + // defaults to an empty array + XCTAssertNotNil(metadata.imageCaptions); + XCTAssertTrue(metadata.imageCaptions.count == 0); + + // defaults to an empty dictionary + XCTAssertNotNil(metadata.customMetadata); + XCTAssertTrue(metadata.customMetadata.allKeys.count == 0); +} + +- (void)testBranchContentMetadataCreation_AllPropertiesSet { + BranchContentMetadata *metadata = [self branchContentMetadataWithAllPropertiesSet]; + [self verifyBranchContentMetadataWithAllProperties:metadata]; +} + +- (void)testBranchContentMetadataDictionary_NoPropertiesSet { + BranchContentMetadata *metadata = [BranchContentMetadata new]; + NSDictionary *dict = metadata.dictionary; + + XCTAssertNotNil(dict); + XCTAssertTrue(dict.allKeys.count == 0); +} + +- (void)testBranchContentMetadataDictionary_AllPropertiesSet { + BranchContentMetadata *metadata = [self branchContentMetadataWithAllPropertiesSet]; + NSDictionary *dict = metadata.dictionary; + + XCTAssertNotNil(dict); + XCTAssertTrue(dict.allKeys.count == 23); + [self verifyBranchContentMetadataDictionaryWithAllPropertiesSet:dict]; +} + +- (void)testBranchContentMetadata_contentMetadataWithDictionary { + BranchContentMetadata *original = [self branchContentMetadataWithAllPropertiesSet]; + NSDictionary *dict = [original dictionary]; + + BranchContentMetadata *metadata = [BranchContentMetadata contentMetadataWithDictionary:dict]; + [self verifyBranchContentMetadataWithAllProperties:metadata]; +} + +- (void)testBranchContentMetadataDescription_NoPropertiesSet { + BranchContentMetadata *metadata = [BranchContentMetadata new]; + NSString *desc = [metadata description]; + XCTAssertTrue([desc containsString:@"BranchContentMetadata"]); + XCTAssertTrue([desc containsString:@"schema: (null) userData: 0 items"]); +} + +- (void)testBranchContentMetadataDescription_AllPropertiesSet { + BranchContentMetadata *metadata = [self branchContentMetadataWithAllPropertiesSet]; + NSString *desc = [metadata description]; + XCTAssertTrue([desc containsString:@"BranchContentMetadata"]); + XCTAssertTrue([desc containsString:@"schema: OTHER userData: 1 items"]); +} + +#pragma mark BranchUniversalObject tests + +- (BranchUniversalObject *)branchUniversalObjectWithAllPropertiesSet { + BranchUniversalObject *buo = [[BranchUniversalObject alloc] initWithCanonicalIdentifier:@"io.branch.testObject"]; + buo.canonicalUrl = @"https://branch.io"; + buo.title = @"Test Title"; + buo.contentDescription = @"the quick brown fox jumps over the lazy dog"; + buo.imageUrl = @"https://branch.io"; + buo.keywords = @[@"keyword1", @"keyword2"]; + buo.expirationDate = [NSDate dateWithTimeIntervalSinceNow:1]; + buo.locallyIndex = YES; + buo.publiclyIndex = YES; + + buo.contentMetadata = [self branchContentMetadataWithAllPropertiesSet]; + return buo; +} + +- (void)verifyBranchUniversalObjectWithAllPropertiesSet:(BranchUniversalObject *)buo { + XCTAssertNotNil(buo); + XCTAssertTrue([@"https://branch.io" isEqualToString:buo.canonicalUrl]); + XCTAssertTrue([@"Test Title" isEqualToString:buo.title]); + XCTAssertTrue([@"the quick brown fox jumps over the lazy dog" isEqualToString:buo.contentDescription]); + XCTAssertTrue([@"https://branch.io" isEqualToString:buo.imageUrl]); + + XCTAssertTrue(buo.keywords.count == 2); + XCTAssertTrue([buo.keywords[0] isEqualToString:@"keyword1"]); + XCTAssertTrue([buo.keywords[1] isEqualToString:@"keyword2"]); + + XCTAssertTrue([buo.creationDate compare:buo.expirationDate] == NSOrderedAscending); + + XCTAssertTrue(buo.locallyIndex); + XCTAssertTrue(buo.publiclyIndex); + + [self verifyBranchContentMetadataWithAllProperties:buo.contentMetadata]; +} + +- (void)verifyBranchUniversalObjectDictionaryWithAllPropertiesSet:(NSDictionary *)dict { + XCTAssertTrue([@"io.branch.testObject" isEqualToString:dict[@"$canonical_identifier"]]); + XCTAssertTrue([@"https://branch.io" isEqualToString:dict[@"$canonical_url"]]); + XCTAssertTrue([@"Test Title" isEqualToString:dict[@"$og_title"]]); + XCTAssertTrue([@"the quick brown fox jumps over the lazy dog" isEqualToString:dict[@"$og_description"]]); + XCTAssertTrue([@"https://branch.io" isEqualToString:dict[@"$og_image_url"]]); + + XCTAssertTrue(dict[@"$locally_indexable"]); + XCTAssertTrue(dict[@"$publicly_indexable"]); + + XCTAssertTrue([dict[@"$creation_timestamp"] isKindOfClass:NSNumber.class]); + XCTAssertTrue([dict[@"$exp_date"] isKindOfClass:NSNumber.class]); + NSNumber *creationDate = dict[@"$creation_timestamp"]; + NSNumber *expirationDate = dict[@"$exp_date"]; + XCTAssertTrue([creationDate compare:expirationDate] == NSOrderedAscending); + + XCTAssertTrue([dict[@"$keywords"] isKindOfClass:NSArray.class]); + NSArray *tmp = dict[@"$keywords"]; + XCTAssertTrue(tmp.count == 2); + XCTAssertTrue([tmp[0] isEqualToString:@"keyword1"]); + XCTAssertTrue([tmp[1] isEqualToString:@"keyword2"]); + + // the BranchContentMetadata dictionary is NOT in a sub dictionary, it is merged in at the top level + [self verifyBranchContentMetadataDictionaryWithAllPropertiesSet:dict]; +} + +- (void)testBranchUniversalObjectCreation { + BranchUniversalObject *buo = [BranchUniversalObject new]; + XCTAssertNotNil(buo); + + XCTAssertNil(buo.canonicalIdentifier); + XCTAssertNil(buo.canonicalUrl); + XCTAssertNil(buo.title); + XCTAssertNil(buo.contentDescription); + XCTAssertNil(buo.imageUrl); + XCTAssertNil(buo.keywords); + XCTAssertNil(buo.creationDate); + XCTAssertNil(buo.expirationDate); + XCTAssertFalse(buo.locallyIndex); + XCTAssertFalse(buo.publiclyIndex); + + XCTAssertNotNil(buo.contentMetadata); +} + +- (void)testBranchUniversalObjectCreation_initWithCanonicalIdentifier { + BranchUniversalObject *buo = [[BranchUniversalObject alloc] initWithCanonicalIdentifier:@"io.branch.testObject"]; + XCTAssertNotNil(buo); + + XCTAssertTrue([@"io.branch.testObject" isEqualToString:buo.canonicalIdentifier]); + XCTAssertNil(buo.canonicalUrl); + XCTAssertNil(buo.title); + XCTAssertNil(buo.contentDescription); + XCTAssertNil(buo.imageUrl); + XCTAssertNil(buo.keywords); + XCTAssertNotNil(buo.creationDate); + XCTAssertNil(buo.expirationDate); + XCTAssertFalse(buo.locallyIndex); + XCTAssertFalse(buo.publiclyIndex); + + XCTAssertNotNil(buo.contentMetadata); +} + +- (void)testBranchUniversalObjectCreation_initWithTitle { + BranchUniversalObject *buo = [[BranchUniversalObject alloc] initWithTitle:@"Test Title"]; + XCTAssertNotNil(buo); + + XCTAssertNil(buo.canonicalIdentifier); + XCTAssertNil(buo.canonicalUrl); + XCTAssertTrue([@"Test Title" isEqualToString:buo.title]); + XCTAssertNil(buo.contentDescription); + XCTAssertNil(buo.imageUrl); + XCTAssertNil(buo.keywords); + XCTAssertNotNil(buo.creationDate); + XCTAssertNil(buo.expirationDate); + XCTAssertFalse(buo.locallyIndex); + XCTAssertFalse(buo.publiclyIndex); + + XCTAssertNotNil(buo.contentMetadata); +} + +- (void)testBranchUniversalObject_AllPropertiesSet { + BranchUniversalObject *buo = [self branchUniversalObjectWithAllPropertiesSet]; + [self verifyBranchUniversalObjectWithAllPropertiesSet:buo]; +} + +- (void)testBranchUniversalObjectDescription_AllPropertiesSet { + BranchUniversalObject *buo = [self branchUniversalObjectWithAllPropertiesSet]; + NSString *desc = buo.description; + + // Verifies a few properties used to generate the description string + XCTAssertTrue([desc containsString:@"BranchUniversalObject"]); + XCTAssertTrue([desc containsString:@"canonicalIdentifier: io.branch.testObject"]); + XCTAssertTrue([desc containsString:@"title: Test Title"]); + XCTAssertTrue([desc containsString:@"contentDescription: the quick brown fox jumps over the lazy dog"]); +} + +- (void)testBranchUniversalObjectDictionary_AllPropertiesSet { + BranchUniversalObject *buo = [self branchUniversalObjectWithAllPropertiesSet]; + NSDictionary *dict = buo.dictionary; + + XCTAssertNotNil(dict); + XCTAssertTrue(dict.allKeys.count == 33); + [self verifyBranchUniversalObjectDictionaryWithAllPropertiesSet:dict]; +} + +- (void)testBranchUniversalObject_objectWithDictionary { + BranchUniversalObject *original = [self branchUniversalObjectWithAllPropertiesSet]; + NSDictionary *dict = [original dictionary]; + + BranchUniversalObject *buo = [BranchUniversalObject objectWithDictionary:dict]; + [self verifyBranchUniversalObjectWithAllPropertiesSet:buo]; +} + +- (void)testBranchUniversalObject_getDictionaryWithCompleteLinkProperties_NoLinkPropertiesSet { + BranchUniversalObject *original = [self branchUniversalObjectWithAllPropertiesSet]; + BranchLinkProperties *linkProperties = [BranchLinkProperties new]; + NSDictionary *dict = [original getDictionaryWithCompleteLinkProperties:linkProperties]; + + XCTAssertNotNil(dict); + XCTAssertTrue([@(0) isEqualToNumber:dict[@"~duration"]]); +} + +- (void)testBranchUniversalObject_getDictionaryWithCompleteLinkProperties_AllLinkPropertiesSet { + BranchUniversalObject *original = [self branchUniversalObjectWithAllPropertiesSet]; + BranchLinkProperties *linkProperties = [BranchLinkProperties new]; + + linkProperties.tags = @[@"tag1", @"tag2"]; + linkProperties.feature = @"test feature"; + linkProperties.alias = @"test alias"; + linkProperties.channel = @"test channel"; + linkProperties.matchDuration = 10; + + // BranchUniversalObject.controlParams overwrites BranchContentMetadata.customMetadata + linkProperties.controlParams = @{ + @"testControlParam": @"test control param", + //@"custom0": @"test control param" + }; + + NSDictionary *dict = [original getDictionaryWithCompleteLinkProperties:linkProperties]; + XCTAssertNotNil(dict); + XCTAssertTrue(dict.allKeys.count == 39); + + XCTAssertTrue([@(10) isEqualToNumber:dict[@"~duration"]]); + XCTAssertTrue([@"test alias" isEqualToString:dict[@"~alias"]]); + XCTAssertTrue([@"test channel" isEqualToString:dict[@"~channel"]]); + XCTAssertTrue([@"test feature" isEqualToString:dict[@"~feature"]]); + + XCTAssertTrue([@"test control param" isEqualToString:dict[@"testControlParam"]]); + + // BranchUniversalObject fields are at the top level of the dictionary + [self verifyBranchUniversalObjectDictionaryWithAllPropertiesSet:dict]; +} + +- (void)testBranchUniversalObject_getParamsForServerRequestWithAddedLinkProperties_NoLinkPropertiesSet { + BranchUniversalObject *original = [self branchUniversalObjectWithAllPropertiesSet]; + BranchLinkProperties *linkProperties = [BranchLinkProperties new]; + + // Nothing is added with this call + NSDictionary *dict = [original getParamsForServerRequestWithAddedLinkProperties:linkProperties]; + + XCTAssertNotNil(dict); + + // BranchUniversalObject fields are at the top level of the dictionary + [self verifyBranchUniversalObjectDictionaryWithAllPropertiesSet:dict]; +} + +- (void)testBranchUniversalObject_getParamsForServerRequestWithAddedLinkProperties_AllLinkPropertiesSet { + BranchUniversalObject *original = [self branchUniversalObjectWithAllPropertiesSet]; + BranchLinkProperties *linkProperties = [BranchLinkProperties new]; + linkProperties.tags = @[@"tag1", @"tag2"]; + linkProperties.feature = @"test feature"; + linkProperties.alias = @"test alias"; + linkProperties.channel = @"test channel"; + linkProperties.matchDuration = 10; + + // BranchUniversalObject.controlParams overwrites BranchContentMetadata.customMetadata + linkProperties.controlParams = @{ + @"testControlParam": @"test control param", + //@"custom0": @"test control param" + }; + + NSDictionary *dict = [original getParamsForServerRequestWithAddedLinkProperties:linkProperties]; + XCTAssertNotNil(dict); + XCTAssertTrue(dict.allKeys.count == 34); + + // only the control parameters are in the dictionary + XCTAssertTrue([@"test control param" isEqualToString:dict[@"testControlParam"]]); + XCTAssertNil(dict[@"~duration"]); + XCTAssertNil(dict[@"~alias"]); + XCTAssertNil(dict[@"~channel"]); + XCTAssertNil(dict[@"~feature"]); + + // BranchUniversalObject fields are at the top level of the dictionary + [self verifyBranchUniversalObjectDictionaryWithAllPropertiesSet:dict]; +} + +@end diff --git a/BranchSDKTests/DispatchToIsolationQueueTests.m b/BranchSDKTests/DispatchToIsolationQueueTests.m new file mode 100644 index 000000000..89043aa94 --- /dev/null +++ b/BranchSDKTests/DispatchToIsolationQueueTests.m @@ -0,0 +1,76 @@ +// +// BNCPreInitBlockTests.m +// Branch-SDK-Tests +// +// Created by Benas Klastaitis on 12/9/19. +// Copyright © 2019 Branch, Inc. All rights reserved. +// + +#import +// #import "Branch.h" + +@interface DispatchToIsolationQueueTests : XCTestCase +// @property (nonatomic, strong, readwrite) Branch *branch; +// @property (nonatomic, strong, readwrite) BNCPreferenceHelper *prefHelper; +@end + +// this is an integration test, needs to be moved to a new target +@implementation DispatchToIsolationQueueTests + +- (void)setUp { + // self.branch = [Branch getInstance]; + // self.prefHelper = [[BNCPreferenceHelper alloc] init]; +} + +- (void)tearDown { + // [self.prefHelper setRequestMetadataKey:@"$marketing_cloud_visitor_id" value:@"dummy"]; +} + +- (void)testPreInitBlock { + // __block XCTestExpectation *expectation = [self expectationWithDescription:@""]; + + // [self.branch dispatchToIsolationQueue:^{ + // dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); + // dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + // [self.branch setRequestMetadataKey:@"$marketing_cloud_visitor_id" value:@"adobeID123"]; + // dispatch_semaphore_signal(semaphore); + // }); + // dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); + // }]; + + // [self.branch initSessionWithLaunchOptions:nil andRegisterDeepLinkHandlerUsingBranchUniversalObject: + // ^ (BranchUniversalObject * _Nullable universalObject, + // BranchLinkProperties * _Nullable linkProperties, + // NSError * _Nullable error) { + // [expectation fulfill]; + // }]; + + // // test that session initialization blocking works + // dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + // id initializationStatus = [self.branch valueForKey:@"initializationStatus"]; + // XCTAssertTrue([self enumIntValueFromId:initializationStatus] == 0);// uninitialized + // XCTAssertNil([[self.prefHelper requestMetadataDictionary] objectForKey:@"$marketing_cloud_visitor_id"]); + // }); + + // // test that initialization does happen afterwards and that pre init block was executed + // dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + // id initializationStatus = [self.branch valueForKey:@"initializationStatus"]; + // XCTAssertTrue([self enumIntValueFromId:initializationStatus] == 2);// initialized + + // XCTAssertTrue([[[self.prefHelper requestMetadataDictionary] objectForKey:@"$marketing_cloud_visitor_id"] isEqualToString:@"adobeID123"]); + // }); + + + // [self waitForExpectationsWithTimeout:6 handler:^(NSError * _Nullable error) { + // NSLog(@"%@", error); + // }]; +} + +// -(int)enumIntValueFromId:(id)enumValueId { +// if (![enumValueId respondsToSelector:@selector(intValue)]) +// return -1; + +// return [enumValueId intValue]; +// } + +@end diff --git a/TestDeepLinking/TestDeepLinkingUITestsWithHostApp/Info.plist b/BranchSDKTests/Info.plist similarity index 86% rename from TestDeepLinking/TestDeepLinkingUITestsWithHostApp/Info.plist rename to BranchSDKTests/Info.plist index 64d65ca49..ba72822e8 100644 --- a/TestDeepLinking/TestDeepLinkingUITestsWithHostApp/Info.plist +++ b/BranchSDKTests/Info.plist @@ -3,7 +3,7 @@ CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) + en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier @@ -13,9 +13,11 @@ CFBundleName $(PRODUCT_NAME) CFBundlePackageType - $(PRODUCT_BUNDLE_PACKAGE_TYPE) + BNDL CFBundleShortVersionString 1.0 + CFBundleSignature + ???? CFBundleVersion 1 diff --git a/BranchSDKTests/NSErrorBranchTests.m b/BranchSDKTests/NSErrorBranchTests.m new file mode 100644 index 000000000..4399b7484 --- /dev/null +++ b/BranchSDKTests/NSErrorBranchTests.m @@ -0,0 +1,54 @@ +/** + @file NSErrorBranchCategoryTests.m + @package Branch-SDK + @brief Branch error tests. + + @author Edward Smith + @date August 2017 + @copyright Copyright © 2017 Branch. All rights reserved. +*/ + +#import +#import "NSError+Branch.h" + +@interface NSErrorBranchTests : XCTestCase +@end + +@implementation NSErrorBranchTests + +- (void)testErrorDomain { + XCTAssertTrue([@"io.branch.sdk.error" isEqualToString:[NSError bncErrorDomain]]); +} + +- (void)testError { + NSError *error = [NSError branchErrorWithCode:BNCInitError]; + XCTAssert(error.domain == [NSError bncErrorDomain]); + XCTAssert(error.code == BNCInitError); + XCTAssert([error.localizedDescription isEqualToString: + @"The Branch user session has not been initialized."] + ); +} + +- (void)testErrorWithUnderlyingError { + NSError *underlyingError = [NSError errorWithDomain:NSCocoaErrorDomain code:NSFileNoSuchFileError userInfo:nil]; + NSError *error = [NSError branchErrorWithCode:BNCServerProblemError error:underlyingError]; + + XCTAssert(error.domain == [NSError bncErrorDomain]); + XCTAssert(error.code == BNCServerProblemError); + XCTAssert([error.localizedDescription isEqualToString: @"Trouble reaching the Branch servers, please try again shortly."]); + + XCTAssert(error.userInfo[NSUnderlyingErrorKey] == underlyingError); + XCTAssert([error.localizedFailureReason isEqualToString:@"The file doesn’t exist."]); +} + +- (void)testErrorWithMessage { + NSString *message = [NSString stringWithFormat:@"Network operation of class '%@' does not conform to the BNCNetworkOperationProtocol.", NSStringFromClass([self class])]; + NSError *error = [NSError branchErrorWithCode:BNCNetworkServiceInterfaceError localizedMessage:message]; + + XCTAssert(error.domain == [NSError bncErrorDomain]); + XCTAssert(error.code == BNCNetworkServiceInterfaceError); + XCTAssert([error.localizedDescription isEqualToString: @"The underlying network service does not conform to the BNCNetworkOperationProtocol."]); + XCTAssert([error.localizedFailureReason isEqualToString: @"Network operation of class 'NSErrorBranchTests' does not conform to the BNCNetworkOperationProtocol."]); +} + +@end diff --git a/BranchSDKTests/NSMutableDictionaryBranchTests.m b/BranchSDKTests/NSMutableDictionaryBranchTests.m new file mode 100644 index 000000000..9fadbefb2 --- /dev/null +++ b/BranchSDKTests/NSMutableDictionaryBranchTests.m @@ -0,0 +1,389 @@ +// +// NSMutableDictionaryBranchTests.m +// Branch-SDK-Tests +// +// Created by Ernest Cho on 2/9/24. +// Copyright © 2024 Branch, Inc. All rights reserved. +// + +#import +#import "NSMutableDictionary+Branch.h" + +@interface NSMutableDictionaryBranchTests : XCTestCase + +@end + +@implementation NSMutableDictionaryBranchTests + +- (void)setUp { + // Put setup code here. This method is called before the invocation of each test method in the class. +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. +} + +- (void)testSafeSetObject_StringString { + NSMutableDictionary *dict = [NSMutableDictionary new]; + + [dict bnc_safeSetObject:@"foo" forKey:@"bar"]; + XCTAssertTrue(dict.count == 1); + XCTAssertTrue([@"foo" isEqualToString:dict[@"bar"]]); +} + +- (void)testSafeSetObject_NilString { + NSMutableDictionary *dict = [NSMutableDictionary new]; + + [dict bnc_safeSetObject:nil forKey:@"bar"]; + XCTAssertTrue(dict.count == 0); +} + +- (void)testSafeSetObject_StringNil { + NSMutableDictionary *dict = [NSMutableDictionary new]; + + [dict bnc_safeSetObject:@"foo" forKey:nil]; + XCTAssertTrue(dict.count == 0); +} + +- (void)testSafeAddEntriesFromDictionary { + + // NSStrings are never copied, so use NSMutableStrings + NSMutableDictionary *other = [NSMutableDictionary new]; + other[@"foo"] = [[NSMutableString alloc] initWithString:@"bar"]; + other[@"hello"] = [[NSMutableString alloc] initWithString:@"world"]; + + NSMutableDictionary *dict = [NSMutableDictionary new]; + [dict bnc_safeAddEntriesFromDictionary:other]; + + NSArray *keyset = [other allKeys]; + for (id key in keyset) { + id original = other[key]; + id copy = dict[key]; + + // same object value + XCTAssertTrue([original isEqual:copy]); + + // different object instance + XCTAssertTrue(original != copy); + } +} + +- (void)testSafeAddEntriesFromDictionary_NestedArray { + + // NSStrings are never copied, so use NSMutableStrings + NSMutableDictionary *other = [NSMutableDictionary new]; + other[@"foo"] = [[NSMutableString alloc] initWithString:@"bar"]; + other[@"hello"] = [[NSMutableString alloc] initWithString:@"world"]; + + NSMutableArray *array = [NSMutableArray new]; + [array addObject:[[NSMutableString alloc] initWithString:@"dog"]]; + [array addObject:[[NSMutableString alloc] initWithString:@"cat"]]; + [array addObject:[[NSMutableString alloc] initWithString:@"child"]]; + + other[@"good"] = array; + + NSMutableDictionary *dict = [NSMutableDictionary new]; + [dict bnc_safeAddEntriesFromDictionary:other]; + + NSArray *keyset = [other allKeys]; + for (id key in keyset) { + id original = other[key]; + id copy = dict[key]; + + // same object value + XCTAssertTrue([original isEqual:copy]); + + // different object instance + XCTAssertTrue(original != copy); + } + + // confirm that copyItems is a one layer deep copy + NSArray *arrayCopy = dict[@"good"]; + XCTAssertTrue(array.count == arrayCopy.count); + XCTAssertTrue(array != arrayCopy); + + for (int i=0; i +#import "NSString+Branch.h" + +#define _countof(array) (sizeof(array)/sizeof(array[0])) + +@interface NSStringBranchTests : XCTestCase +@end + +@implementation NSStringBranchTests + +- (void)testMaskEqual { + XCTAssertTrue([@"0123" bnc_isEqualToMaskedString:@"0123"]); + XCTAssertFalse([@"0123" bnc_isEqualToMaskedString:@"012"]); + XCTAssertFalse([@"0123" bnc_isEqualToMaskedString:@"01234"]); + XCTAssertTrue([@"0123" bnc_isEqualToMaskedString:@"01*3"]); + XCTAssertFalse([@"0123" bnc_isEqualToMaskedString:@"01*4"]); + XCTAssertTrue([@"0123" bnc_isEqualToMaskedString:@"*123"]); + XCTAssertTrue([@"0123" bnc_isEqualToMaskedString:@"012*"]); + XCTAssertTrue([@"日本語123日本語" bnc_isEqualToMaskedString:@"日本語123日本語"]); + XCTAssertFalse([@"日本語123日本語" bnc_isEqualToMaskedString:@"日本語1234本語"]); + XCTAssertTrue([@"日本語123日本語" bnc_isEqualToMaskedString:@"日本語***日本語"]); + XCTAssertTrue([@"日本語123日本語" bnc_isEqualToMaskedString:@"***123日本語"]); +} + +@end diff --git a/BranchSDKTestsHostApp/AppDelegate.h b/BranchSDKTestsHostApp/AppDelegate.h new file mode 100644 index 000000000..ba35f21cd --- /dev/null +++ b/BranchSDKTestsHostApp/AppDelegate.h @@ -0,0 +1,14 @@ +// +// AppDelegate.h +// BranchSDKTestsHostApp +// +// Created by Nidhi Dixit on 7/6/25. +// + +#import + +@interface AppDelegate : UIResponder + + +@end + diff --git a/BranchSDKTestsHostApp/AppDelegate.m b/BranchSDKTestsHostApp/AppDelegate.m new file mode 100644 index 000000000..3c267c2e5 --- /dev/null +++ b/BranchSDKTestsHostApp/AppDelegate.m @@ -0,0 +1,40 @@ +// +// AppDelegate.m +// BranchSDKTestsHostApp +// +// Created by Nidhi Dixit on 7/6/25. +// + +#import "AppDelegate.h" + +@interface AppDelegate () + +@end + +@implementation AppDelegate + + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Override point for customization after application launch. + return YES; +} + + +#pragma mark - UISceneSession lifecycle + + +- (UISceneConfiguration *)application:(UIApplication *)application configurationForConnectingSceneSession:(UISceneSession *)connectingSceneSession options:(UISceneConnectionOptions *)options { + // Called when a new scene session is being created. + // Use this method to select a configuration to create the new scene with. + return [[UISceneConfiguration alloc] initWithName:@"Default Configuration" sessionRole:connectingSceneSession.role]; +} + + +- (void)application:(UIApplication *)application didDiscardSceneSessions:(NSSet *)sceneSessions { + // Called when the user discards a scene session. + // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions. + // Use this method to release any resources that were specific to the discarded scenes, as they will not return. +} + + +@end diff --git a/DeepLinkDemo/DeepLinkDemo/Assets.xcassets/AccentColor.colorset/Contents.json b/BranchSDKTestsHostApp/Assets.xcassets/AccentColor.colorset/Contents.json similarity index 100% rename from DeepLinkDemo/DeepLinkDemo/Assets.xcassets/AccentColor.colorset/Contents.json rename to BranchSDKTestsHostApp/Assets.xcassets/AccentColor.colorset/Contents.json diff --git a/BranchSDKTestsHostApp/Assets.xcassets/AppIcon.appiconset/Contents.json b/BranchSDKTestsHostApp/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 000000000..230588010 --- /dev/null +++ b/BranchSDKTestsHostApp/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,35 @@ +{ + "images" : [ + { + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "tinted" + } + ], + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/DeepLinkDemo/DeepLinkDemo/Assets.xcassets/Contents.json b/BranchSDKTestsHostApp/Assets.xcassets/Contents.json similarity index 100% rename from DeepLinkDemo/DeepLinkDemo/Assets.xcassets/Contents.json rename to BranchSDKTestsHostApp/Assets.xcassets/Contents.json diff --git a/DeepLinkDemo/DeepLinkDemo/Base.lproj/LaunchScreen.storyboard b/BranchSDKTestsHostApp/Base.lproj/LaunchScreen.storyboard similarity index 100% rename from DeepLinkDemo/DeepLinkDemo/Base.lproj/LaunchScreen.storyboard rename to BranchSDKTestsHostApp/Base.lproj/LaunchScreen.storyboard diff --git a/TestHost/Base.lproj/Main.storyboard b/BranchSDKTestsHostApp/Base.lproj/Main.storyboard similarity index 95% rename from TestHost/Base.lproj/Main.storyboard rename to BranchSDKTestsHostApp/Base.lproj/Main.storyboard index 25a763858..808a21ce7 100644 --- a/TestHost/Base.lproj/Main.storyboard +++ b/BranchSDKTestsHostApp/Base.lproj/Main.storyboard @@ -9,7 +9,7 @@ - + diff --git a/DeepLinkDemo/DeepLinkDemo/DeepLinkDemo.entitlements b/BranchSDKTestsHostApp/BranchSDKTestsHostAppRelease.entitlements similarity index 50% rename from DeepLinkDemo/DeepLinkDemo/DeepLinkDemo.entitlements rename to BranchSDKTestsHostApp/BranchSDKTestsHostAppRelease.entitlements index 51c38f856..9ad5d115f 100644 --- a/DeepLinkDemo/DeepLinkDemo/DeepLinkDemo.entitlements +++ b/BranchSDKTestsHostApp/BranchSDKTestsHostAppRelease.entitlements @@ -4,9 +4,11 @@ com.apple.developer.associated-domains - applinks:timber.test-app.link - applinks:timber.test-app.link - applinks:timber.test-app.link + applinks:bnc.lt + applinks:bnctestbed.app.link + applinks:bnctestbed.test-app.link + applinks:bnctestbed-alternate.app.link + applinks:bnctestbed-alternate.test-app.link diff --git a/TestHost/Info.plist b/BranchSDKTestsHostApp/Info.plist similarity index 59% rename from TestHost/Info.plist rename to BranchSDKTestsHostApp/Info.plist index dd3c9afda..f0cb4d34f 100644 --- a/TestHost/Info.plist +++ b/BranchSDKTestsHostApp/Info.plist @@ -2,6 +2,17 @@ + CFBundleURLTypes + + + CFBundleTypeRole + Editor + CFBundleURLSchemes + + branchtest + + + UIApplicationSceneManifest UIApplicationSupportsMultipleScenes @@ -14,12 +25,19 @@ UISceneConfigurationName Default Configuration UISceneDelegateClassName - $(PRODUCT_MODULE_NAME).SceneDelegate + SceneDelegate UISceneStoryboardFile Main + branch_key + + live + key_live_hcnegAumkH7Kv18M8AOHhfgiohpXq5tB + test + key_test_hdcBLUy1xZ1JD0tKg7qrLcgirFmPPVJc + diff --git a/BranchSDKTestsHostApp/SceneDelegate.h b/BranchSDKTestsHostApp/SceneDelegate.h new file mode 100644 index 000000000..ae4e37f24 --- /dev/null +++ b/BranchSDKTestsHostApp/SceneDelegate.h @@ -0,0 +1,15 @@ +// +// SceneDelegate.h +// BranchSDKTestsHostApp +// +// Created by Nidhi Dixit on 7/6/25. +// + +#import + +@interface SceneDelegate : UIResponder + +@property (strong, nonatomic) UIWindow * window; + +@end + diff --git a/BranchSDKTestsHostApp/SceneDelegate.m b/BranchSDKTestsHostApp/SceneDelegate.m new file mode 100644 index 000000000..be25ed27f --- /dev/null +++ b/BranchSDKTestsHostApp/SceneDelegate.m @@ -0,0 +1,57 @@ +// +// SceneDelegate.m +// BranchSDKTestsHostApp +// +// Created by Nidhi Dixit on 7/6/25. +// + +#import "SceneDelegate.h" + +@interface SceneDelegate () + +@end + +@implementation SceneDelegate + + +- (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions { + // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`. + // If using a storyboard, the `window` property will automatically be initialized and attached to the scene. + // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead). +} + + +- (void)sceneDidDisconnect:(UIScene *)scene { + // Called as the scene is being released by the system. + // This occurs shortly after the scene enters the background, or when its session is discarded. + // Release any resources associated with this scene that can be re-created the next time the scene connects. + // The scene may re-connect later, as its session was not necessarily discarded (see `application:didDiscardSceneSessions` instead). +} + + +- (void)sceneDidBecomeActive:(UIScene *)scene { + // Called when the scene has moved from an inactive state to an active state. + // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive. +} + + +- (void)sceneWillResignActive:(UIScene *)scene { + // Called when the scene will move from an active state to an inactive state. + // This may occur due to temporary interruptions (ex. an incoming phone call). +} + + +- (void)sceneWillEnterForeground:(UIScene *)scene { + // Called as the scene transitions from the background to the foreground. + // Use this method to undo the changes made on entering the background. +} + + +- (void)sceneDidEnterBackground:(UIScene *)scene { + // Called as the scene transitions from the foreground to the background. + // Use this method to save data, release shared resources, and store enough scene-specific state information + // to restore the scene back to its current state. +} + + +@end diff --git a/BranchSDKTestsHostApp/ViewController.h b/BranchSDKTestsHostApp/ViewController.h new file mode 100644 index 000000000..83b3d1118 --- /dev/null +++ b/BranchSDKTestsHostApp/ViewController.h @@ -0,0 +1,14 @@ +// +// ViewController.h +// BranchSDKTestsHostApp +// +// Created by Nidhi Dixit on 7/6/25. +// + +#import + +@interface ViewController : UIViewController + + +@end + diff --git a/BranchSDKTestsHostApp/ViewController.m b/BranchSDKTestsHostApp/ViewController.m new file mode 100644 index 000000000..0a3c38aa1 --- /dev/null +++ b/BranchSDKTestsHostApp/ViewController.m @@ -0,0 +1,22 @@ +// +// ViewController.m +// BranchSDKTestsHostApp +// +// Created by Nidhi Dixit on 7/6/25. +// + +#import "ViewController.h" + +@interface ViewController () + +@end + +@implementation ViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + // Do any additional setup after loading the view. +} + + +@end diff --git a/BranchSDKTestsHostApp/cannedData/example.json b/BranchSDKTestsHostApp/cannedData/example.json new file mode 100644 index 000000000..d3be9b233 --- /dev/null +++ b/BranchSDKTestsHostApp/cannedData/example.json @@ -0,0 +1,31 @@ +{ + "user_string": "test user", + "user_number": 3.14, + "user_dict": { + "id": "273e4c5da13b978ee2f78f8997abd972959c184aaffb8cad716721a00a08d32b", + "name": "hello@branch.io" + }, + "user_dict_mixed": { + "id": 123, + "name": "hello@branch.io" + }, + "user_dict_numbers": { + "id": 123, + "name": 42 + }, + "user_array": [ + "123", + "abc", + "xyz" + ], + "user_array_mixed": [ + "abc", + 123, + "xyz" + ], + "user_array_numbers": [ + 1, + 2, + 3 + ] +} diff --git a/BranchSDKTestsHostApp/cannedData/latd.json b/BranchSDKTestsHostApp/cannedData/latd.json new file mode 100644 index 000000000..cc8d42631 --- /dev/null +++ b/BranchSDKTestsHostApp/cannedData/latd.json @@ -0,0 +1,7 @@ +{ + "last_attributed_touch_data": { + "$3p": "hello", + "~campaign": "world" + }, + "attribution_window": 30 +} diff --git a/BranchSDKTestsHostApp/cannedData/latd_empty_data.json b/BranchSDKTestsHostApp/cannedData/latd_empty_data.json new file mode 100644 index 000000000..5561c6a3c --- /dev/null +++ b/BranchSDKTestsHostApp/cannedData/latd_empty_data.json @@ -0,0 +1,4 @@ +{ + "last_attributed_touch_data": { }, + "attribution_window": 30 +} diff --git a/BranchSDKTestsHostApp/cannedData/latd_missing_data.json b/BranchSDKTestsHostApp/cannedData/latd_missing_data.json new file mode 100644 index 000000000..5dfcf058b --- /dev/null +++ b/BranchSDKTestsHostApp/cannedData/latd_missing_data.json @@ -0,0 +1,3 @@ +{ + "attribution_window": 30 +} diff --git a/BranchSDKTestsHostApp/cannedData/latd_missing_window.json b/BranchSDKTestsHostApp/cannedData/latd_missing_window.json new file mode 100644 index 000000000..7e4649891 --- /dev/null +++ b/BranchSDKTestsHostApp/cannedData/latd_missing_window.json @@ -0,0 +1,6 @@ +{ + "last_attributed_touch_data": { + "$3p": "hello", + "~campaign": "world" + } +} diff --git a/BranchSDKTestsHostApp/main.m b/BranchSDKTestsHostApp/main.m new file mode 100644 index 000000000..abfb64588 --- /dev/null +++ b/BranchSDKTestsHostApp/main.m @@ -0,0 +1,18 @@ +// +// main.m +// BranchSDKTestsHostApp +// +// Created by Nidhi Dixit on 7/6/25. +// + +#import +#import "AppDelegate.h" + +int main(int argc, char * argv[]) { + NSString * appDelegateClassName; + @autoreleasepool { + // Setup code that might create autoreleased objects goes here. + appDelegateClassName = NSStringFromClass([AppDelegate class]); + } + return UIApplicationMain(argc, argv, nil, appDelegateClassName); +} diff --git a/DeepLinkDemo/DeepLinkDemo.xcodeproj/project.pbxproj b/DeepLinkDemo/DeepLinkDemo.xcodeproj/project.pbxproj deleted file mode 100644 index 6117713fe..000000000 --- a/DeepLinkDemo/DeepLinkDemo.xcodeproj/project.pbxproj +++ /dev/null @@ -1,586 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 55; - objects = { - -/* Begin PBXBuildFile section */ - 180748E82833A914006DB0FA /* ReadLogViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 180748E72833A914006DB0FA /* ReadLogViewController.swift */; }; - 180748EA2833CC85006DB0FA /* ParentViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 180748E92833CC85006DB0FA /* ParentViewController.swift */; }; - 182B1F43282E0ECE00EA8C70 /* AddMetaDataVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 182B1F42282E0ECE00EA8C70 /* AddMetaDataVC.swift */; }; - 182B1F45282E210B00EA8C70 /* MetaDataTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 182B1F44282E210B00EA8C70 /* MetaDataTableViewCell.swift */; }; - 183F6FA2282D109800E293F6 /* TrackContentVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 183F6FA1282D109800E293F6 /* TrackContentVC.swift */; }; - 1877918A283C8D2400229CD5 /* Utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18779189283C8D2400229CD5 /* Utils.swift */; }; - 1889ACED283BE1C9009E3601 /* NSURLSessionBranch.m in Sources */ = {isa = PBXBuildFile; fileRef = 1889ACEC283BE1C9009E3601 /* NSURLSessionBranch.m */; }; - 18AC5ADE283F61430098736E /* LogFileListViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18AC5ADD283F61430098736E /* LogFileListViewController.swift */; }; - 2A2347C154C6746FA55C3649 /* Pods_DeepLinkDemo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DDBB5A837B0C008CA5BEC1EF /* Pods_DeepLinkDemo.framework */; }; - 7E1A39D42818289B002B302D /* DispalyVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7E1A39D32818289B002B302D /* DispalyVC.swift */; }; - 7E2AE639280ED92800142446 /* CreateObjectReferenceObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7E2AE638280ED92800142446 /* CreateObjectReferenceObject.swift */; }; - 7E2AE63B280EE1F700142446 /* GenerateURLVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7E2AE63A280EE1F700142446 /* GenerateURLVC.swift */; }; - 7E2AE63F280EE23500142446 /* NavigateContentVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7E2AE63E280EE23500142446 /* NavigateContentVC.swift */; }; - 7E37E69B280CF9D1003E42DB /* CommonMethod.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7E37E69A280CF9D1003E42DB /* CommonMethod.swift */; }; - 7E37E69D280D061E003E42DB /* SIAlertView in Resources */ = {isa = PBXBuildFile; fileRef = 7E37E69C280D061E003E42DB /* SIAlertView */; }; - 7E37E6A1280D12E2003E42DB /* img.png in Resources */ = {isa = PBXBuildFile; fileRef = 7E37E6A0280D12E2003E42DB /* img.png */; }; - 7E6505F6281B003C006179FF /* ReadVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7E6505F5281B003C006179FF /* ReadVC.swift */; }; - 7E7477CA2809C46C0088A7D3 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7E7477C92809C46C0088A7D3 /* AppDelegate.swift */; }; - 7E7477CE2809C46C0088A7D3 /* HomeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7E7477CD2809C46C0088A7D3 /* HomeViewController.swift */; }; - 7E7477D12809C46C0088A7D3 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7E7477CF2809C46C0088A7D3 /* Main.storyboard */; }; - 7E7477D32809C46D0088A7D3 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 7E7477D22809C46D0088A7D3 /* Assets.xcassets */; }; - 7E7477D62809C46D0088A7D3 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7E7477D42809C46D0088A7D3 /* LaunchScreen.storyboard */; }; - 7ED8BFED2835EFA90080C0CB /* Reachability.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7ED8BFEC2835EFA90080C0CB /* Reachability.swift */; }; - 7ED8BFEF2835EFB40080C0CB /* CommonAlert.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7ED8BFEE2835EFB40080C0CB /* CommonAlert.swift */; }; - 7EE84374281CDFAE00A1561C /* StartupOptionsData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7EE84373281CDFAE00A1561C /* StartupOptionsData.swift */; }; - 7EF58D5B2812CF2300BA92D5 /* WebViewVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7EF58D5A2812CF2300BA92D5 /* WebViewVC.swift */; }; - B7B7DC2A2859974E00D45FC5 /* TextViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B7B7DC292859974E00D45FC5 /* TextViewController.swift */; }; -/* End PBXBuildFile section */ - -/* Begin PBXFileReference section */ - 180748E72833A914006DB0FA /* ReadLogViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReadLogViewController.swift; sourceTree = ""; }; - 180748E92833CC85006DB0FA /* ParentViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParentViewController.swift; sourceTree = ""; }; - 182B1F42282E0ECE00EA8C70 /* AddMetaDataVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddMetaDataVC.swift; sourceTree = ""; }; - 182B1F44282E210B00EA8C70 /* MetaDataTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MetaDataTableViewCell.swift; sourceTree = ""; }; - 183F6FA1282D109800E293F6 /* TrackContentVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrackContentVC.swift; sourceTree = ""; }; - 18779189283C8D2400229CD5 /* Utils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Utils.swift; sourceTree = ""; }; - 1889ACEB283BE1C9009E3601 /* NSURLSessionBranch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NSURLSessionBranch.h; sourceTree = ""; }; - 1889ACEC283BE1C9009E3601 /* NSURLSessionBranch.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NSURLSessionBranch.m; sourceTree = ""; }; - 18AC5ADD283F61430098736E /* LogFileListViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogFileListViewController.swift; sourceTree = ""; }; - 7E1A39D32818289B002B302D /* DispalyVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DispalyVC.swift; sourceTree = ""; }; - 7E2AE638280ED92800142446 /* CreateObjectReferenceObject.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateObjectReferenceObject.swift; sourceTree = ""; }; - 7E2AE63A280EE1F700142446 /* GenerateURLVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GenerateURLVC.swift; sourceTree = ""; }; - 7E2AE63E280EE23500142446 /* NavigateContentVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigateContentVC.swift; sourceTree = ""; }; - 7E37E69A280CF9D1003E42DB /* CommonMethod.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommonMethod.swift; sourceTree = ""; }; - 7E37E69C280D061E003E42DB /* SIAlertView */ = {isa = PBXFileReference; lastKnownFileType = folder; path = SIAlertView; sourceTree = ""; }; - 7E37E69E280D0676003E42DB /* Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Header.h; sourceTree = ""; }; - 7E37E69F280D06FF003E42DB /* DeepLinkDemo-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "DeepLinkDemo-Bridging-Header.h"; sourceTree = ""; }; - 7E37E6A0280D12E2003E42DB /* img.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = img.png; sourceTree = ""; }; - 7E6505F5281B003C006179FF /* ReadVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReadVC.swift; sourceTree = ""; }; - 7E7477C62809C46C0088A7D3 /* DeepLinkDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = DeepLinkDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 7E7477C92809C46C0088A7D3 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - 7E7477CD2809C46C0088A7D3 /* HomeViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeViewController.swift; sourceTree = ""; }; - 7E7477D02809C46C0088A7D3 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - 7E7477D22809C46D0088A7D3 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; - 7E7477D52809C46D0088A7D3 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; - 7E7477D72809C46D0088A7D3 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 7ED8BFEB2835EFA90080C0CB /* Reachability.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Reachability.h; sourceTree = ""; }; - 7ED8BFEC2835EFA90080C0CB /* Reachability.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Reachability.swift; sourceTree = ""; }; - 7ED8BFEE2835EFB40080C0CB /* CommonAlert.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CommonAlert.swift; sourceTree = ""; }; - 7EE84373281CDFAE00A1561C /* StartupOptionsData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StartupOptionsData.swift; sourceTree = ""; }; - 7EF58D5A2812CF2300BA92D5 /* WebViewVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebViewVC.swift; sourceTree = ""; }; - 7EF58D5C2816D14700BA92D5 /* DeepLinkDemo.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DeepLinkDemo.entitlements; sourceTree = ""; }; - 88EDCA13B444CE5565DC92FA /* Pods-DeepLinkDemo.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-DeepLinkDemo.release.xcconfig"; path = "Target Support Files/Pods-DeepLinkDemo/Pods-DeepLinkDemo.release.xcconfig"; sourceTree = ""; }; - B7B7DC292859974E00D45FC5 /* TextViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextViewController.swift; sourceTree = ""; }; - C06885D21868B25319262FC1 /* Pods-DeepLinkDemo.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-DeepLinkDemo.debug.xcconfig"; path = "Target Support Files/Pods-DeepLinkDemo/Pods-DeepLinkDemo.debug.xcconfig"; sourceTree = ""; }; - DDBB5A837B0C008CA5BEC1EF /* Pods_DeepLinkDemo.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_DeepLinkDemo.framework; sourceTree = BUILT_PRODUCTS_DIR; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 7E7477C32809C46C0088A7D3 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 2A2347C154C6746FA55C3649 /* Pods_DeepLinkDemo.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 0D26D1E3284DFA33003FAB18 /* Constants */ = { - isa = PBXGroup; - children = ( - 18779189283C8D2400229CD5 /* Utils.swift */, - 7ED8BFEE2835EFB40080C0CB /* CommonAlert.swift */, - 7E37E69A280CF9D1003E42DB /* CommonMethod.swift */, - ); - path = Constants; - sourceTree = ""; - }; - 29D53CAAE9E9EF2F96296086 /* Frameworks */ = { - isa = PBXGroup; - children = ( - DDBB5A837B0C008CA5BEC1EF /* Pods_DeepLinkDemo.framework */, - ); - name = Frameworks; - sourceTree = ""; - }; - 7E2AE642280EFF1200142446 /* Controllers */ = { - isa = PBXGroup; - children = ( - 7E7477CD2809C46C0088A7D3 /* HomeViewController.swift */, - B7B7DC292859974E00D45FC5 /* TextViewController.swift */, - 7E2AE638280ED92800142446 /* CreateObjectReferenceObject.swift */, - 7E2AE63A280EE1F700142446 /* GenerateURLVC.swift */, - 7E2AE63E280EE23500142446 /* NavigateContentVC.swift */, - 7E1A39D32818289B002B302D /* DispalyVC.swift */, - 7EF58D5A2812CF2300BA92D5 /* WebViewVC.swift */, - 7E6505F5281B003C006179FF /* ReadVC.swift */, - 183F6FA1282D109800E293F6 /* TrackContentVC.swift */, - 182B1F42282E0ECE00EA8C70 /* AddMetaDataVC.swift */, - 182B1F44282E210B00EA8C70 /* MetaDataTableViewCell.swift */, - 180748E72833A914006DB0FA /* ReadLogViewController.swift */, - 18AC5ADD283F61430098736E /* LogFileListViewController.swift */, - 180748E92833CC85006DB0FA /* ParentViewController.swift */, - ); - path = Controllers; - sourceTree = ""; - }; - 7E7477BD2809C46C0088A7D3 = { - isa = PBXGroup; - children = ( - 7E7477C82809C46C0088A7D3 /* DeepLinkDemo */, - 7E7477C72809C46C0088A7D3 /* Products */, - DB9F65A595474F5DA261D89A /* Pods */, - 29D53CAAE9E9EF2F96296086 /* Frameworks */, - ); - sourceTree = ""; - }; - 7E7477C72809C46C0088A7D3 /* Products */ = { - isa = PBXGroup; - children = ( - 7E7477C62809C46C0088A7D3 /* DeepLinkDemo.app */, - ); - name = Products; - sourceTree = ""; - }; - 7E7477C82809C46C0088A7D3 /* DeepLinkDemo */ = { - isa = PBXGroup; - children = ( - 7E2AE642280EFF1200142446 /* Controllers */, - 1889ACEB283BE1C9009E3601 /* NSURLSessionBranch.h */, - 1889ACEC283BE1C9009E3601 /* NSURLSessionBranch.m */, - 7ED8BFEA2835EF9E0080C0CB /* Reachability */, - 7EF58D5C2816D14700BA92D5 /* DeepLinkDemo.entitlements */, - 7E37E69C280D061E003E42DB /* SIAlertView */, - 7E7477C92809C46C0088A7D3 /* AppDelegate.swift */, - 7EE84373281CDFAE00A1561C /* StartupOptionsData.swift */, - 0D26D1E3284DFA33003FAB18 /* Constants */, - 7E7477CF2809C46C0088A7D3 /* Main.storyboard */, - 7E37E6A0280D12E2003E42DB /* img.png */, - 7E7477D22809C46D0088A7D3 /* Assets.xcassets */, - 7E7477D42809C46D0088A7D3 /* LaunchScreen.storyboard */, - 7E7477D72809C46D0088A7D3 /* Info.plist */, - 7E37E69E280D0676003E42DB /* Header.h */, - 7E37E69F280D06FF003E42DB /* DeepLinkDemo-Bridging-Header.h */, - ); - path = DeepLinkDemo; - sourceTree = ""; - }; - 7ED8BFEA2835EF9E0080C0CB /* Reachability */ = { - isa = PBXGroup; - children = ( - 7ED8BFEB2835EFA90080C0CB /* Reachability.h */, - 7ED8BFEC2835EFA90080C0CB /* Reachability.swift */, - ); - path = Reachability; - sourceTree = ""; - }; - DB9F65A595474F5DA261D89A /* Pods */ = { - isa = PBXGroup; - children = ( - C06885D21868B25319262FC1 /* Pods-DeepLinkDemo.debug.xcconfig */, - 88EDCA13B444CE5565DC92FA /* Pods-DeepLinkDemo.release.xcconfig */, - ); - path = Pods; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 7E7477C52809C46C0088A7D3 /* DeepLinkDemo */ = { - isa = PBXNativeTarget; - buildConfigurationList = 7E7477DA2809C46D0088A7D3 /* Build configuration list for PBXNativeTarget "DeepLinkDemo" */; - buildPhases = ( - 8C8C5B24F34C07814525F311 /* [CP] Check Pods Manifest.lock */, - 7E7477C22809C46C0088A7D3 /* Sources */, - 7E7477C32809C46C0088A7D3 /* Frameworks */, - 7E7477C42809C46C0088A7D3 /* Resources */, - 9086714B33BB3D176E3DED70 /* [CP] Embed Pods Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = DeepLinkDemo; - productName = DeepLinkDemo; - productReference = 7E7477C62809C46C0088A7D3 /* DeepLinkDemo.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 7E7477BE2809C46C0088A7D3 /* Project object */ = { - isa = PBXProject; - attributes = { - BuildIndependentTargetsInParallel = 1; - LastSwiftUpdateCheck = 1330; - LastUpgradeCheck = 1330; - TargetAttributes = { - 7E7477C52809C46C0088A7D3 = { - CreatedOnToolsVersion = 13.3.1; - LastSwiftMigration = 1340; - }; - }; - }; - buildConfigurationList = 7E7477C12809C46C0088A7D3 /* Build configuration list for PBXProject "DeepLinkDemo" */; - compatibilityVersion = "Xcode 13.0"; - developmentRegion = en; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 7E7477BD2809C46C0088A7D3; - productRefGroup = 7E7477C72809C46C0088A7D3 /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 7E7477C52809C46C0088A7D3 /* DeepLinkDemo */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 7E7477C42809C46C0088A7D3 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 7E37E6A1280D12E2003E42DB /* img.png in Resources */, - 7E7477D62809C46D0088A7D3 /* LaunchScreen.storyboard in Resources */, - 7E7477D32809C46D0088A7D3 /* Assets.xcassets in Resources */, - 7E37E69D280D061E003E42DB /* SIAlertView in Resources */, - 7E7477D12809C46C0088A7D3 /* Main.storyboard in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXShellScriptBuildPhase section */ - 8C8C5B24F34C07814525F311 /* [CP] Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-DeepLinkDemo-checkManifestLockResult.txt", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; - }; - 9086714B33BB3D176E3DED70 /* [CP] Embed Pods Frameworks */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-DeepLinkDemo/Pods-DeepLinkDemo-frameworks-${CONFIGURATION}-input-files.xcfilelist", - ); - name = "[CP] Embed Pods Frameworks"; - outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-DeepLinkDemo/Pods-DeepLinkDemo-frameworks-${CONFIGURATION}-output-files.xcfilelist", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-DeepLinkDemo/Pods-DeepLinkDemo-frameworks.sh\"\n"; - showEnvVarsInLog = 0; - }; -/* End PBXShellScriptBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 7E7477C22809C46C0088A7D3 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 182B1F43282E0ECE00EA8C70 /* AddMetaDataVC.swift in Sources */, - 7E6505F6281B003C006179FF /* ReadVC.swift in Sources */, - 7ED8BFED2835EFA90080C0CB /* Reachability.swift in Sources */, - 7E7477CE2809C46C0088A7D3 /* HomeViewController.swift in Sources */, - 180748E82833A914006DB0FA /* ReadLogViewController.swift in Sources */, - 7E7477CA2809C46C0088A7D3 /* AppDelegate.swift in Sources */, - 7EF58D5B2812CF2300BA92D5 /* WebViewVC.swift in Sources */, - 1877918A283C8D2400229CD5 /* Utils.swift in Sources */, - 1889ACED283BE1C9009E3601 /* NSURLSessionBranch.m in Sources */, - 7E37E69B280CF9D1003E42DB /* CommonMethod.swift in Sources */, - 183F6FA2282D109800E293F6 /* TrackContentVC.swift in Sources */, - 180748EA2833CC85006DB0FA /* ParentViewController.swift in Sources */, - 7E2AE63B280EE1F700142446 /* GenerateURLVC.swift in Sources */, - 7E1A39D42818289B002B302D /* DispalyVC.swift in Sources */, - 182B1F45282E210B00EA8C70 /* MetaDataTableViewCell.swift in Sources */, - 7ED8BFEF2835EFB40080C0CB /* CommonAlert.swift in Sources */, - 7EE84374281CDFAE00A1561C /* StartupOptionsData.swift in Sources */, - 7E2AE639280ED92800142446 /* CreateObjectReferenceObject.swift in Sources */, - 18AC5ADE283F61430098736E /* LogFileListViewController.swift in Sources */, - 7E2AE63F280EE23500142446 /* NavigateContentVC.swift in Sources */, - B7B7DC2A2859974E00D45FC5 /* TextViewController.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXVariantGroup section */ - 7E7477CF2809C46C0088A7D3 /* Main.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 7E7477D02809C46C0088A7D3 /* Base */, - ); - name = Main.storyboard; - sourceTree = ""; - }; - 7E7477D42809C46D0088A7D3 /* LaunchScreen.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 7E7477D52809C46D0088A7D3 /* Base */, - ); - name = LaunchScreen.storyboard; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 7E7477D82809C46D0088A7D3 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 14.0; - MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; - MTL_FAST_MATH = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - }; - name = Debug; - }; - 7E7477D92809C46D0088A7D3 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 14.0; - MTL_ENABLE_DEBUG_INFO = NO; - MTL_FAST_MATH = YES; - SDKROOT = iphoneos; - SWIFT_COMPILATION_MODE = wholemodule; - SWIFT_OPTIMIZATION_LEVEL = "-O"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 7E7477DB2809C46D0088A7D3 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = C06885D21868B25319262FC1 /* Pods-DeepLinkDemo.debug.xcconfig */; - buildSettings = { - ARCHS = "$(ARCHS_STANDARD)"; - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; - CLANG_ENABLE_MODULES = YES; - CODE_SIGN_IDENTITY = "Apple Development"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 2; - DEVELOPMENT_TEAM = ""; - "DEVELOPMENT_TEAM[sdk=iphoneos*]" = R63EM248DP; - GENERATE_INFOPLIST_FILE = YES; - INFOPLIST_FILE = DeepLinkDemo/Info.plist; - INFOPLIST_KEY_CFBundleDisplayName = SaaS_SDK_TestBed_iOS; - INFOPLIST_KEY_LSApplicationCategoryType = ""; - INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; - INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; - INFOPLIST_KEY_UIMainStoryboardFile = Main; - INFOPLIST_KEY_UISupportedInterfaceOrientations = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UIInterfaceOrientationPortraitUpsideDown"; - INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; - INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = UIInterfaceOrientationPortrait; - INFOPLIST_OUTPUT_FORMAT = "same-as-input"; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Framework", - ); - MARKETING_VERSION = 1.1; - PLIST_FILE_OUTPUT_FORMAT = "same-as-input"; - PRODUCT_BUNDLE_IDENTIFIER = io.branch.saas.sdk.testbed; - PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE_SPECIFIER = ""; - "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "iOS Saas SDK - Dev"; - STRINGS_FILE_OUTPUT_ENCODING = "UTF-8"; - SWIFT_EMIT_LOC_STRINGS = YES; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = 1; - }; - name = Debug; - }; - 7E7477DC2809C46D0088A7D3 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 88EDCA13B444CE5565DC92FA /* Pods-DeepLinkDemo.release.xcconfig */; - buildSettings = { - ARCHS = "$(ARCHS_STANDARD)"; - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; - CLANG_ENABLE_MODULES = YES; - CODE_SIGN_IDENTITY = "Apple Development"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 2; - DEVELOPMENT_TEAM = ""; - "DEVELOPMENT_TEAM[sdk=iphoneos*]" = R63EM248DP; - GENERATE_INFOPLIST_FILE = YES; - INFOPLIST_FILE = DeepLinkDemo/Info.plist; - INFOPLIST_KEY_CFBundleDisplayName = SaaS_SDK_TestBed_iOS; - INFOPLIST_KEY_LSApplicationCategoryType = ""; - INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; - INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; - INFOPLIST_KEY_UIMainStoryboardFile = Main; - INFOPLIST_KEY_UISupportedInterfaceOrientations = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UIInterfaceOrientationPortraitUpsideDown"; - INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; - INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = UIInterfaceOrientationPortrait; - INFOPLIST_OUTPUT_FORMAT = "same-as-input"; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Framework", - ); - MARKETING_VERSION = 1.1; - ONLY_ACTIVE_ARCH = YES; - PLIST_FILE_OUTPUT_FORMAT = "same-as-input"; - PRODUCT_BUNDLE_IDENTIFIER = io.branch.saas.sdk.testbed; - PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE_SPECIFIER = ""; - "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "iOS Saas SDK - Dev"; - STRINGS_FILE_OUTPUT_ENCODING = "UTF-8"; - SWIFT_EMIT_LOC_STRINGS = YES; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = 1; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 7E7477C12809C46C0088A7D3 /* Build configuration list for PBXProject "DeepLinkDemo" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 7E7477D82809C46D0088A7D3 /* Debug */, - 7E7477D92809C46D0088A7D3 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 7E7477DA2809C46D0088A7D3 /* Build configuration list for PBXNativeTarget "DeepLinkDemo" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 7E7477DB2809C46D0088A7D3 /* Debug */, - 7E7477DC2809C46D0088A7D3 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 7E7477BE2809C46C0088A7D3 /* Project object */; -} diff --git a/DeepLinkDemo/DeepLinkDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/DeepLinkDemo/DeepLinkDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index 919434a62..000000000 --- a/DeepLinkDemo/DeepLinkDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/DeepLinkDemo/DeepLinkDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/DeepLinkDemo/DeepLinkDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist deleted file mode 100644 index 18d981003..000000000 --- a/DeepLinkDemo/DeepLinkDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEDidComputeMac32BitWarning - - - diff --git a/DeepLinkDemo/DeepLinkDemo.xcodeproj/xcshareddata/xcschemes/DeepLinkDemo.xcscheme b/DeepLinkDemo/DeepLinkDemo.xcodeproj/xcshareddata/xcschemes/DeepLinkDemo.xcscheme deleted file mode 100644 index a2671aeb8..000000000 --- a/DeepLinkDemo/DeepLinkDemo.xcodeproj/xcshareddata/xcschemes/DeepLinkDemo.xcscheme +++ /dev/null @@ -1,78 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/DeepLinkDemo/DeepLinkDemo.xcworkspace/contents.xcworkspacedata b/DeepLinkDemo/DeepLinkDemo.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index dbfeee663..000000000 --- a/DeepLinkDemo/DeepLinkDemo.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - diff --git a/DeepLinkDemo/DeepLinkDemo.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/DeepLinkDemo/DeepLinkDemo.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist deleted file mode 100644 index 18d981003..000000000 --- a/DeepLinkDemo/DeepLinkDemo.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEDidComputeMac32BitWarning - - - diff --git a/DeepLinkDemo/DeepLinkDemo/AppDelegate.swift b/DeepLinkDemo/DeepLinkDemo/AppDelegate.swift deleted file mode 100644 index bebb005e5..000000000 --- a/DeepLinkDemo/DeepLinkDemo/AppDelegate.swift +++ /dev/null @@ -1,268 +0,0 @@ -// -// AppDelegate.swift -// DeepLinkDemo -// -// Created by Rakesh kumar on 4/15/22. -// - -import UIKit -import BranchSDK -import IQKeyboardManager -@main -class AppDelegate: UIResponder, UIApplicationDelegate { - var window: UIWindow? - static var shared: AppDelegate { - return (UIApplication.shared.delegate as? AppDelegate)! - - } - var launchOption = [UIApplication.LaunchOptionsKey : Any]() - var delegate: AppDelegate! - - - func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool { - print("didFinishLaunchingWithOptions") - if #available(iOS 10.0, *) { - let center = UNUserNotificationCenter.current() - UNUserNotificationCenter.current().delegate = self - center.requestAuthorization(options: [.alert, .badge, .sound]) { (granted, error) in - if granted { - print("Allowed to send Notification") - } else { - print("Not allowed to send Notification") - } - } - }else{ - let notificationSettings = UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil) - UIApplication.shared.registerUserNotificationSettings(notificationSettings) - _ = application.beginBackgroundTask(withName: "showNotification", expirationHandler: nil) - } - - Utils.shared.clearAllLogFiles() - Utils.shared.setLogFile("AppLaunch") - IQKeyboardManager.shared().isEnabled = true - StartupOptionsData.setActiveSetDebugEnabled(true) - StartupOptionsData.setPendingSetDebugEnabled(true) - Utils.shared.setLogFile("AppDelegate") - return true - } - - - func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool { - - //check for link_click_id - if url.absoluteString.contains("link_click_id") == true{ - return Branch.getInstance().application(app, open: url, options: options) - } - return true - } - - - func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool { - // handler for Universal Links - return Branch.getInstance().continue(userActivity) - } - - func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) { - // handler for Push Notifications - Branch.getInstance().handlePushNotification(userInfo) - } - - - - func application(_ application: UIApplication, didReceiveRemoteNotification launchOptions: [AnyHashable: Any]) -> Void { - Branch.getInstance().handlePushNotification(launchOptions) - } - - func application(_ application: UIApplication, didReceive notification: UILocalNotification){ - print(#function) - } - - func application(_ application: UIApplication, handleActionWithIdentifier identifier: String?, for notification: UILocalNotification, completionHandler: @escaping () -> Void){ - print(#function) - } - - - // Respond to URL scheme links - func application(_ application: UIApplication, - open url: URL, - sourceApplication: String?, - annotation: Any) -> Bool { - - let branchHandled = Branch.getInstance().application(application, - open: url, - sourceApplication: sourceApplication, - annotation: annotation - ) - if(!branchHandled) { - // If not handled by Branch, do other deep link routing for the Facebook SDK, Pinterest SDK, etc - - } - return true - } - - // Respond to Universal Links - func application(_ - application: UIApplication, - continue userActivity: NSUserActivity, - restorationHandler: @escaping ([Any]?) -> Void - ) -> Bool { - let branchHandled = Branch.getInstance().continue(userActivity) - if (userActivity.activityType == NSUserActivityTypeBrowsingWeb) { - if let url = userActivity.webpageURL, - !branchHandled { - - } - } - - // Apply your logic to determine the return value of this method - return true - } - - - func pushNewView() { - if let controller = NavigateContentVC() as? NavigateContentVC { - if let window = self.window, let rootViewController = window.rootViewController { - var currentController = rootViewController - while let presentedController = currentController.presentedViewController { - currentController = presentedController - } - currentController.present(controller, animated: true, completion: nil) - } - } - } - func handleDeepLinkObject(object: BranchUniversalObject, linkProperties:BranchLinkProperties, error:NSError) { - - NSLog("Deep linked with object: %@.", object); - let deeplinkText = object.contentMetadata.customMetadata.value(forKey: "deeplink_text") - let textDetail = "Successfully Deeplinked:\n\n%@\nSession Details:\n\n%@, \(String(describing: deeplinkText)) \(String(describing: Branch.getInstance().getLatestReferringParams()?.description))" - NSLog(textDetail) - self.pushNewView() - } - - - - - func getBranchData(_ launchOptions: [UIApplication.LaunchOptionsKey : Any]?) { - - Branch.getInstance().initSession( - launchOptions: launchOptions, - automaticallyDisplayDeepLinkController: false, - deepLinkHandler: { params, error in - - defer { - let notificationName = Notification.Name("BranchCallbackCompleted") - NotificationCenter.default.post(name: notificationName, object: nil) - } - - guard error == nil else { - NSLog("Branch TestBed: Initialization failed: " + error!.localizedDescription) - return - } - - guard let paramsDictionary = (params as? Dictionary) else { - NSLog("No Branch parameters returned") - return - } - - let clickedBranchLink = params?[BRANCH_INIT_KEY_CLICKED_BRANCH_LINK] as! Bool? - if let referringLink = paramsDictionary["~referring_link"] as! String?, - let trackerId = paramsDictionary["ios_tracker_id"] as! String?, - let clickedBranchLink = clickedBranchLink, - clickedBranchLink { - var adjustUrl = URLComponents(string: referringLink) - var adjust_tracker:URLQueryItem - if referringLink.starts(with: "https://") || referringLink.starts(with: "http://") { - adjust_tracker = URLQueryItem(name: "adjust_t", value: trackerId) - } else { - adjust_tracker = URLQueryItem(name: "adjust_tracker", value: trackerId) - } - let adjust_campaign = URLQueryItem(name: "adjust_campaign", value: paramsDictionary[BRANCH_INIT_KEY_CAMPAIGN] as? String) - let adjust_adgroup = URLQueryItem(name: "adjust_adgroup", value: paramsDictionary[BRANCH_INIT_KEY_CHANNEL] as? String) - let adjust_creative = URLQueryItem(name: "adjust_creative", value: paramsDictionary[BRANCH_INIT_KEY_FEATURE] as? String) - let queryItems = [adjust_tracker,adjust_campaign,adjust_adgroup,adjust_creative] - adjustUrl?.queryItems = queryItems -// if let url = adjustUrl?.url { -// //Adjust.appWillOpen(url) -// } - } - // Deeplinking logic for use when automaticallyDisplayDeepLinkController = false - if let clickedBranchLink = clickedBranchLink, - clickedBranchLink { - let nc = self.window!.rootViewController as! UINavigationController - let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil) - if let vc = storyBoard.instantiateViewController(withIdentifier: "DispalyVC") as? DispalyVC { - let linkurl = UserDefaults.standard.value(forKey: "link") as? String ?? "" - //let referringLink = paramsDictionary["~referring_link"] as! String - let content = String(format:"\nReferring link: %@ \n\nSession Details:\n %@", linkurl, paramsDictionary.jsonStringRepresentation!) - vc.textDescription = content - vc.appData = paramsDictionary - vc.linkURL = linkurl - nc.pushViewController(vc, animated: true) - } - } else { - NSLog("Branch TestBed: Finished init with params\n%@", paramsDictionary.description) - } - }) - } - - - func handleURL(_ url: URL) { - guard url.pathComponents.count >= 3 else { return } - - let section = url.pathComponents[1] - let detail = url.pathComponents[2] - - switch section { - case "post": - guard let id = Int(detail) else { break } - // navigateToItem(id) - case "settings": - //navigateToSettings(detail) - break - default: break - } - } - -} - - -@available(iOS 10.0, *) -extension AppDelegate: UNUserNotificationCenterDelegate{ - - func getApprovalForSendingNotification(){ - if #available(iOS 11.0, *) { - let center = UNUserNotificationCenter.current() - UNUserNotificationCenter.current().delegate = self - center.requestAuthorization(options: [.alert, .badge, .sound]) { (granted, error) in - if granted { - print("Allowed to send Notification") - } else { - print("Not allowed to send Notification") - } - } - }else{ - let notificationSettings = UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil) - UIApplication.shared.registerUserNotificationSettings(notificationSettings) - } - } - func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) { - completionHandler([.alert, .badge, .sound]) - } - func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) { - print(response) - let content = response.notification.request.content - print(content.userInfo) - Branch.getInstance().handlePushNotification(content.userInfo) - } - -} -extension Dictionary { - var jsonStringRepresentation: String? { - guard let theJSONData = try? JSONSerialization.data(withJSONObject: self, - options: [.prettyPrinted]) else { - return nil - } - - return String(data: theJSONData, encoding: .ascii) - } -} diff --git a/DeepLinkDemo/DeepLinkDemo/Assets.xcassets/AppIcon.appiconset/Contents.json b/DeepLinkDemo/DeepLinkDemo/Assets.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index 9221b9bb1..000000000 --- a/DeepLinkDemo/DeepLinkDemo/Assets.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,98 +0,0 @@ -{ - "images" : [ - { - "idiom" : "iphone", - "scale" : "2x", - "size" : "20x20" - }, - { - "idiom" : "iphone", - "scale" : "3x", - "size" : "20x20" - }, - { - "idiom" : "iphone", - "scale" : "2x", - "size" : "29x29" - }, - { - "idiom" : "iphone", - "scale" : "3x", - "size" : "29x29" - }, - { - "idiom" : "iphone", - "scale" : "2x", - "size" : "40x40" - }, - { - "idiom" : "iphone", - "scale" : "3x", - "size" : "40x40" - }, - { - "idiom" : "iphone", - "scale" : "2x", - "size" : "60x60" - }, - { - "idiom" : "iphone", - "scale" : "3x", - "size" : "60x60" - }, - { - "idiom" : "ipad", - "scale" : "1x", - "size" : "20x20" - }, - { - "idiom" : "ipad", - "scale" : "2x", - "size" : "20x20" - }, - { - "idiom" : "ipad", - "scale" : "1x", - "size" : "29x29" - }, - { - "idiom" : "ipad", - "scale" : "2x", - "size" : "29x29" - }, - { - "idiom" : "ipad", - "scale" : "1x", - "size" : "40x40" - }, - { - "idiom" : "ipad", - "scale" : "2x", - "size" : "40x40" - }, - { - "idiom" : "ipad", - "scale" : "1x", - "size" : "76x76" - }, - { - "idiom" : "ipad", - "scale" : "2x", - "size" : "76x76" - }, - { - "idiom" : "ipad", - "scale" : "2x", - "size" : "83.5x83.5" - }, - { - "idiom" : "ios-marketing", - "scale" : "1x", - "size" : "1024x1024" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/DeepLinkDemo/DeepLinkDemo/Assets.xcassets/back_img.imageset/Contents.json b/DeepLinkDemo/DeepLinkDemo/Assets.xcassets/back_img.imageset/Contents.json deleted file mode 100644 index d18ba8435..000000000 --- a/DeepLinkDemo/DeepLinkDemo/Assets.xcassets/back_img.imageset/Contents.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "scale" : "1x" - }, - { - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "icons8-left-100.png", - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - }, - "properties" : { - "template-rendering-intent" : "template" - } -} diff --git a/DeepLinkDemo/DeepLinkDemo/Assets.xcassets/back_img.imageset/icons8-left-100.png b/DeepLinkDemo/DeepLinkDemo/Assets.xcassets/back_img.imageset/icons8-left-100.png deleted file mode 100644 index b1952be8a..000000000 Binary files a/DeepLinkDemo/DeepLinkDemo/Assets.xcassets/back_img.imageset/icons8-left-100.png and /dev/null differ diff --git a/DeepLinkDemo/DeepLinkDemo/Assets.xcassets/qentelli_logo.imageset/Contents.json b/DeepLinkDemo/DeepLinkDemo/Assets.xcassets/qentelli_logo.imageset/Contents.json deleted file mode 100644 index aca8f0cf5..000000000 --- a/DeepLinkDemo/DeepLinkDemo/Assets.xcassets/qentelli_logo.imageset/Contents.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "images" : [ - { - "filename" : "img.png", - "idiom" : "universal", - "scale" : "1x" - }, - { - "idiom" : "universal", - "scale" : "2x" - }, - { - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/DeepLinkDemo/DeepLinkDemo/Assets.xcassets/qentelli_logo.imageset/img.png b/DeepLinkDemo/DeepLinkDemo/Assets.xcassets/qentelli_logo.imageset/img.png deleted file mode 100644 index 95f2e9562..000000000 Binary files a/DeepLinkDemo/DeepLinkDemo/Assets.xcassets/qentelli_logo.imageset/img.png and /dev/null differ diff --git a/DeepLinkDemo/DeepLinkDemo/Base.lproj/Main.storyboard b/DeepLinkDemo/DeepLinkDemo/Base.lproj/Main.storyboard deleted file mode 100644 index 7c5844536..000000000 --- a/DeepLinkDemo/DeepLinkDemo/Base.lproj/Main.storyboard +++ /dev/null @@ -1,2685 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/DeepLinkDemo/DeepLinkDemo/Constants/CommonAlert.swift b/DeepLinkDemo/DeepLinkDemo/Constants/CommonAlert.swift deleted file mode 100644 index feb4c06e4..000000000 --- a/DeepLinkDemo/DeepLinkDemo/Constants/CommonAlert.swift +++ /dev/null @@ -1,22 +0,0 @@ - -import UIKit - -class CommonAlert { - - static let shared = CommonAlert() - - func showActionAlertView(title:String,message:String,actions:[UIAlertAction],preferredStyle:UIAlertController.Style = .alert,viewController:UIViewController?) -> Void { - let alertController = UIAlertController(title: title, message:message, preferredStyle: preferredStyle) - if actions.isEmpty { - alertController.addAction(UIAlertAction(title: "OK", style: .default, handler: { (action: UIAlertAction!) in - viewController?.dismiss(animated: true, completion: nil) - })) - }else{ - for action in actions { - alertController.addAction(action) - } - } - - viewController?.present(alertController, animated: true, completion: nil) - } -} diff --git a/DeepLinkDemo/DeepLinkDemo/Constants/CommonMethod.swift b/DeepLinkDemo/DeepLinkDemo/Constants/CommonMethod.swift deleted file mode 100644 index de52c755b..000000000 --- a/DeepLinkDemo/DeepLinkDemo/Constants/CommonMethod.swift +++ /dev/null @@ -1,59 +0,0 @@ -// CommonMethod.swift -// DeepLinkDemo -// Created by Rakesh kumar on 4/18/22. - - -import Foundation -import UIKit -import BranchSDK -import SystemConfiguration - - -class CommonMethod { - - static let sharedInstance = CommonMethod() - var branchUniversalObject = BranchUniversalObject() - var linkProperties = BranchLinkProperties() - var contentMetaData : BranchContentMetadata? = nil - - var branchData = [String: AnyObject]() - - func navigatetoContent(onCompletion:@escaping (NSDictionary?) -> Void) -> Void { - guard let data = branchData as? [String: AnyObject] else { return } - onCompletion(data as NSDictionary) - } - - func showActionAlertView(title:String,message:String,actions:[UIAlertAction],preferredStyle:UIAlertController.Style = .alert,viewController:UIViewController?) -> Void { - let alertController = UIAlertController(title: title, message:message, preferredStyle: preferredStyle) - if actions.isEmpty { - alertController.addAction(UIAlertAction(title: "OK", style: .default, handler: { (action: UIAlertAction!) in - viewController?.dismiss(animated: true, completion: nil) - - })) - } else { - for action in actions { - alertController.addAction(action) - } - } - } - - func isInternetAvailable() -> Bool { - var zeroAddress = sockaddr_in() - zeroAddress.sin_len = UInt8(MemoryLayout.size(ofValue: zeroAddress)) - zeroAddress.sin_family = sa_family_t(AF_INET) - let defaultRouteReachability = withUnsafePointer(to: &zeroAddress) { - $0.withMemoryRebound(to: sockaddr.self, capacity: 1) {zeroSockAddress in - SCNetworkReachabilityCreateWithAddress(nil, zeroSockAddress) - } - } - - var flags = SCNetworkReachabilityFlags() - - if !SCNetworkReachabilityGetFlags(defaultRouteReachability!, &flags) { - return false - } - let isReachable = flags.contains(.reachable) - let needsConnection = flags.contains(.connectionRequired) - return (isReachable && !needsConnection) - } -} diff --git a/DeepLinkDemo/DeepLinkDemo/Constants/Utils.swift b/DeepLinkDemo/DeepLinkDemo/Constants/Utils.swift deleted file mode 100644 index b0182457b..000000000 --- a/DeepLinkDemo/DeepLinkDemo/Constants/Utils.swift +++ /dev/null @@ -1,87 +0,0 @@ -// -// Utils.swift -// DeepLinkDemo -// -// Created by Apple on 24/05/22. -// - -import Foundation -import UIKit - -class Utils: NSObject { - - static let shared = Utils() - var logFileName: String? - var prevCommandLogFileName: String? - - func clearAllLogFiles(){ - - let documentsUrl = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first! - - do { - let fileURLs = try FileManager.default.contentsOfDirectory(at: documentsUrl, - includingPropertiesForKeys: nil, - options: .skipsHiddenFiles) - for fileURL in fileURLs { - try FileManager.default.removeItem(at: fileURL) - } - } catch { - NSLog("Failed to delete the file %@", error.localizedDescription) - } - - } - - - func removeItem(_ relativeFilePath: String) { - guard let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else { return } - let absoluteFilePath = documentsDirectory.appendingPathComponent(relativeFilePath) - try? FileManager.default.removeItem(at: absoluteFilePath) - } - - func setLogFile(_ fileName: String?) { - if fileName == nil { - logFileName = nil - return - } - let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).map(\.path)[0] - let pathForLog = "\(documentsDirectory)/\(fileName ?? "app").log" - self.removeItem(pathForLog) - if (logFileName == nil) { - logFileName = pathForLog - prevCommandLogFileName = logFileName - } else { - prevCommandLogFileName = logFileName - logFileName = pathForLog - } - let cstr = (pathForLog as NSString).utf8String - freopen(cstr, "a+", stderr) - - } - - func printLogMessage(_ message: String) { - objc_sync_enter(self) - do { - print(message) // print to console - - if !FileManager.default.fileExists(atPath: logFileName!) { // does it exits? - FileManager.default.createFile(atPath: logFileName!, contents: nil) - } - - if let data = message.data(using: .utf8) { - let fileHandle = try FileHandle(forWritingTo: URL(fileURLWithPath: logFileName!)) - if #available(iOS 13.4, *) { - print(" ============= ********** Writing in file " + logFileName!) - try fileHandle.seekToEnd() - try fileHandle.write(contentsOf: data) - try fileHandle.close() - } else { - print("Unable to write log: iOS Version not supported") - } - } - } catch let error as NSError { // something wrong - print("Unable to write log: \(error.debugDescription)") // debug printout - } - objc_sync_exit(self) - } -} - diff --git a/DeepLinkDemo/DeepLinkDemo/Controllers/AddMetaDataVC.swift b/DeepLinkDemo/DeepLinkDemo/Controllers/AddMetaDataVC.swift deleted file mode 100644 index 76884a790..000000000 --- a/DeepLinkDemo/DeepLinkDemo/Controllers/AddMetaDataVC.swift +++ /dev/null @@ -1,117 +0,0 @@ -// -// AddMetaDataVC.swift -// DeepLinkDemo -// -// Created by Apple on 13/05/22. -// - -import UIKit -import BranchSDK - -class AddMetaDataVC: ParentViewController { - - @IBOutlet weak var metaDataTblVw: UITableView! - private var reachability:Reachability? - override func viewDidLoad() { - super.viewDidLoad() - - self.metaDataTblVw.keyboardDismissMode = .onDrag - reachabilityCheck() - } - - override func viewWillAppear(_ animated: Bool) { - super.viewWillAppear(animated) - Utils.shared.setLogFile("AddMetadata") - } - - - @IBAction func backBtnAction(){ - self.navigationController?.popToRootViewController(animated: true) - } - - @objc func submitBtnAction(){ - if let cell = metaDataTblVw.cellForRow(at: IndexPath(row: 0, section: 0)) as? MetaDataTableViewCell{ - -// let branchUniversalObject = CommonMethod.sharedInstance.branchUniversalObject -// branchUniversalObject.canonicalIdentifier = branchUniversalObject.canonicalIdentifier -// branchUniversalObject.canonicalUrl = "https://branch.io/item/12345" -// branchUniversalObject.title = branchUniversalObject.title - let contentMetadata = BranchContentMetadata() - let contentSchemaSelected : BranchContentSchema = BranchContentSchema(rawValue: cell.contentSchema.text!) - contentMetadata.contentSchema = contentSchemaSelected - let quantityEntered = Double(cell.quantity.text ?? "0") - contentMetadata.quantity = quantityEntered ?? 0 - let formattedPrice = NSDecimalNumber(string: cell.price.text ?? "0.0") - if cell.price.text != "" { - contentMetadata.price = formattedPrice - let currencySelected: BNCCurrency = BNCCurrency(rawValue: cell.currencyName.text!) - contentMetadata.currency = currencySelected - } - contentMetadata.sku = cell.sku.text - contentMetadata.productName = cell.productName.text - contentMetadata.productBrand = cell.productBrand.text - let productCategorySelected: BNCProductCategory = BNCProductCategory(rawValue: cell.productCategory.text!) - contentMetadata.productCategory = productCategorySelected - contentMetadata.productVariant = cell.productVariant.text - let conditionSelected: BranchCondition = BranchCondition(rawValue: cell.productCondition.text!) - contentMetadata.condition = conditionSelected - contentMetadata.customMetadata = [ - "custom_key1": cell.customMetadata.text!, - ] - contentMetadata.addressStreet = cell.street.text - contentMetadata.addressCity = cell.city.text - contentMetadata.addressRegion = cell.region.text - contentMetadata.addressCountry = cell.country.text - contentMetadata.addressPostalCode = cell.postalCode.text - - contentMetadata.latitude = Double(cell.latitude.text ?? "0.0") ?? 0.0 - contentMetadata.longitude = Double(cell.longitude.text ?? "0.0") ?? 0.0 - - contentMetadata.ratingAverage = Double(cell.averageRating.text ?? "0.0") ?? 0.0 - contentMetadata.ratingMax = Double(cell.maximumRating.text ?? "0.0") ?? 0.0 - contentMetadata.ratingCount = Int(cell.ratingCount.text ?? "0") ?? 0 - contentMetadata.rating = Double(cell.rating.text ?? "0.0") ?? 0.0 - - contentMetadata.imageCaptions = [cell.imageCaption.text ?? ""] - CommonMethod.sharedInstance.contentMetaData = contentMetadata - print("ContentMetaData:", contentMetadata) - - let metadataDetail = String(format: "%@", contentMetadata) - NSLog("Metadata", metadataDetail); - Utils.shared.setLogFile("AddMetadata") - - self.navigationController?.popViewController(animated: true) - } - } - -} - -extension AddMetaDataVC: UITableViewDataSource, UITableViewDelegate{ - func numberOfSections(in tableView: UITableView) -> Int { - return 1 - } - - func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - return 1 - } - - func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - if let cell = tableView.dequeueReusableCell(withIdentifier: "MetaDataTableViewCell", for: indexPath) as? MetaDataTableViewCell{ - cell.submitBtn.addTarget(self, action: #selector(submitBtnAction), for: UIControl.Event.touchUpInside) - cell.pickerDelegate = self - return cell - } - return UITableViewCell() - } - - func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { - return UITableView.automaticDimension - } -} - - -extension AddMetaDataVC: PickerViewDelegate{ - func removePickerView() { - self.view.endEditing(true) - } -} diff --git a/DeepLinkDemo/DeepLinkDemo/Controllers/CreateObjectReferenceObject.swift b/DeepLinkDemo/DeepLinkDemo/Controllers/CreateObjectReferenceObject.swift deleted file mode 100644 index 061f256d1..000000000 --- a/DeepLinkDemo/DeepLinkDemo/Controllers/CreateObjectReferenceObject.swift +++ /dev/null @@ -1,268 +0,0 @@ -// CreateObjectReferenceObject.swift -// DeepLinkDemo -// Created by Rakesh kumar on 4/19/22. - -import UIKit -import BranchSDK - - -class CreateObjectReferenceObject: ParentViewController { - @IBOutlet weak var txtFldContentTitle: UITextField! - @IBOutlet weak var txtFldCanonicalIdentifier: UITextField! - @IBOutlet weak var txtFldDescription: UITextField! - @IBOutlet weak var txtFldImageUrl: UITextField! - @IBOutlet weak var scrollViewMain: UIScrollView! - - var screenMode = 0 - var txtFldValue = "" - var responseStatus = "" - - enum ScreenMode { - static let createBUO = 0 - static let readdeeplink = 1 - static let sharedeeplink = 2 - static let navigatetoContent = 3 - static let handlLinkinWebview = 4 - static let createdeeplink = 5 - static let sendnotification = 6 - static let trackContent = 7 - static let displayContent = 8 - } - - override func viewDidLoad() { - super.viewDidLoad() - - uiSetUp() - - super.reachabilityCheck() - } - - override func viewWillAppear(_ animated: Bool) { - super.viewWillAppear(animated) - if self.screenMode == ScreenMode.trackContent { - Utils.shared.setLogFile("TrackContent") - } - else { - Utils.shared.setLogFile("CreateBUO") - } - } - - override func viewDidLayoutSubviews() { - super.viewDidLayoutSubviews() - scrollViewMain.contentSize.height = scrollViewMain.subviews.sorted(by: { $0.frame.maxY < $1.frame.maxY }).last?.frame.maxY ?? scrollViewMain.contentSize.height - } - - @IBAction func backAction(_ sender: Any) { - self.navigationController?.popToRootViewController(animated: true) - } - - @objc func addMetaDataAction(sender: UIButton) { - let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil) - if let vc = storyBoard.instantiateViewController(withIdentifier: "AddMetaDataVC") as? AddMetaDataVC { - self.navigationController?.pushViewController(vc, animated: true) - } - } - fileprivate func handleOkBtnAction(dict : [String:Any], alertMessage: String) { - Utils.shared.setLogFile("CreateBUO") - if self.screenMode == ScreenMode.displayContent { - launchGenerateURLVC(dict: dict, displayContent: true) - }else if self.screenMode == ScreenMode.trackContent { - NSLog("screenMode:", self.screenMode) - launchGenerateURLVC(dict: dict, message: alertMessage, TrackContent: true) - }else if self.screenMode == ScreenMode.sendnotification { - NSLog("screenMode:", self.screenMode) - launchGenerateURLVC(dict: dict, forNotification: true) - }else if self.screenMode == ScreenMode.createdeeplink { - NSLog("screenMode:", self.screenMode) - launchGenerateURLVC(dict: dict, CreateDeepLink: true) - }else if self.screenMode == ScreenMode.sharedeeplink { - NSLog("screenMode:", self.screenMode) - launchGenerateURLVC(dict: dict, ShareDeepLink: true) - }else if self.screenMode == ScreenMode.readdeeplink { - NSLog("screenMode:", self.screenMode) - launchGenerateURLVC(dict: dict) - }else if self.screenMode == ScreenMode.navigatetoContent { - NSLog("screenMode:", self.screenMode) - launchGenerateURLVC(dict: dict, NavigateToContent: true) - }else if self.screenMode == ScreenMode.handlLinkinWebview { - NSLog("screenMode:", self.screenMode) - launchGenerateURLVC(dict: dict, handleLinkInWebview: true) - }else { - self.navigationController?.popToRootViewController(animated: true) - } - } - - func launchGenerateURLVC(dict: [String:Any], message: String? = "", ShareDeepLink: Bool? = false, displayContent: Bool? = false, NavigateToContent: Bool? = false, TrackContent: Bool? = false, handleLinkInWebview: Bool? = false, CreateDeepLink: Bool? = false, forNotification: Bool? = false) { - if self.screenMode == ScreenMode.trackContent { - let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil) - if let vc = storyBoard.instantiateViewController(withIdentifier: "TextViewController") as? TextViewController { - vc.isTrackContent = TrackContent! - vc.forNotification = forNotification! - vc.isCreateDeepLink = CreateDeepLink! - vc.isShareDeepLink = ShareDeepLink! - vc.isNavigateToContent = NavigateToContent! - vc.handleLinkInWebview = handleLinkInWebview! - vc.isDisplayContent = displayContent! - vc.dictData = dict - vc.textViewText = message! - vc.responseStatus = self.responseStatus - self.navigationController?.pushViewController(vc, animated: true) - } - } else { - let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil) - if let vc = storyBoard.instantiateViewController(withIdentifier: "GenerateURLVC") as? GenerateURLVC { - vc.isTrackContent = TrackContent! - vc.forNotification = forNotification! - vc.isCreateDeepLink = CreateDeepLink! - vc.isShareDeepLink = ShareDeepLink! - vc.isNavigateToContent = NavigateToContent! - vc.handleLinkInWebview = handleLinkInWebview! - vc.isDisplayContent = displayContent! - vc.dictData = dict - self.navigationController?.pushViewController(vc, animated: true) - } - } - } - - @objc func submitAction(sender : UIButton) { - - self.view.endEditing(true) - CommonMethod.sharedInstance.branchUniversalObject = BranchUniversalObject(canonicalIdentifier: txtFldCanonicalIdentifier.text!) - CommonMethod.sharedInstance.branchUniversalObject.title = txtFldContentTitle.text! - CommonMethod.sharedInstance.branchUniversalObject.contentDescription = txtFldDescription.text! - CommonMethod.sharedInstance.branchUniversalObject.imageUrl = txtFldImageUrl.text! - let linkProperties = BranchLinkProperties() - - - var dict = [String:Any]() - dict["$canonicalIdentifier"] = txtFldCanonicalIdentifier.text! - dict["title"] = txtFldContentTitle.text! - dict["description"] = txtFldDescription.text! - dict["imgurl"] = txtFldImageUrl.text! - - CommonMethod.sharedInstance.branchUniversalObject.locallyIndex = true - CommonMethod.sharedInstance.branchUniversalObject.publiclyIndex = true - if CommonMethod.sharedInstance.contentMetaData != nil { - CommonMethod.sharedInstance.branchUniversalObject.contentMetadata = CommonMethod.sharedInstance.contentMetaData! - } - print("universalObject:", CommonMethod.sharedInstance.branchUniversalObject) - NSLog("CommonMethod.sharedInstance.branchUniversalObject:",CommonMethod.sharedInstance.branchUniversalObject) - - if self.screenMode == ScreenMode.trackContent { - let selectedEvent: BranchStandardEvent = BranchStandardEvent(rawValue: txtFldValue) - BranchEvent.standardEvent(selectedEvent, withContentItem: CommonMethod.sharedInstance.branchUniversalObject).logEvent {[weak self] isLogged, loggingErr in - if isLogged { - self?.responseStatus = "Success" - NSLog("BranchEvent Logged") - Utils.shared.setLogFile("TrackContent") - - DispatchQueue.main.asyncAfter(deadline: .now() + 0.7) { - //AJAY - let alertMessage = self?.getAPIDetailFromLogFile(fileName: "TrackContent.log") - - self?.handleOkBtnAction(dict: dict, alertMessage: alertMessage ?? "") - } - }else{ - NSLog("BranchEvent failed to log \(loggingErr?.localizedDescription ?? "NA")") - } - } - - } - else { - CommonMethod.sharedInstance.branchUniversalObject.listOnSpotlight(with: linkProperties) { (url, error) in - if (error == nil) { - NSLog("Successfully indexed on spotlight \(url)") - } - } - let alert = UIAlertController(title: "Alert", message: "BranchUniversalObject reference created", preferredStyle: .alert) - alert.addAction(UIAlertAction(title: "OK", style: .default, handler: { action in - UserDefaults.standard.set("buo", forKey: "isStatus") - UserDefaults.standard.set(true, forKey: "isCreatedBUO") - self.handleOkBtnAction(dict: dict, alertMessage: "") - })) - self.present(alert, animated: true, completion: nil) - } - } - - private func loadTextWithFileName(_ fileName: String) -> String? { - if let dir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first { - let fileURL = dir.appendingPathComponent(fileName) - guard let text = try? String(contentsOf: fileURL, encoding: .utf8) else { - return nil - } - return text - } - return nil - } - - fileprivate func getAPIDetailFromLogFile(fileName: String) -> String{ - var alertMessage = "LogFilePath : \(self.getLogFilepath(fileName)!) \n\n" - alertMessage = alertMessage + "\n\n" - if let fileContent = self.loadTextWithFileName(fileName), !fileContent.isEmpty { - - if let startlocation = fileContent.range(of: "BranchSDK API LOG START OF FILE"),let endlocation = fileContent.range(of: "BranchSDK API LOG END OF FILE"){ - let apiResponse = fileContent[startlocation.lowerBound.. String? { - let dir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first - let fileURL = dir?.appendingPathComponent(fileName) - let fileURLStr = fileURL?.path - return fileURLStr - } -} - -extension CreateObjectReferenceObject { - func uiSetUp() { - - let addMetaDataBtn = UIButton(frame: CGRect(x: self.view.frame.width/2-90, y: txtFldImageUrl.frame.maxY+30, width: 180, height: 55)) - addMetaDataBtn.setTitle("Add Metadata", for: .normal) - addMetaDataBtn.backgroundColor = UIColor(red: 89.0/255.0, green: 12.0/255.0, blue: 228.0/255.0, alpha: 1.0) - addMetaDataBtn.layer.cornerRadius = 8 - addMetaDataBtn.setTitleColor(UIColor.white, for: .normal) - addMetaDataBtn.titleLabel?.font = UIFont.boldSystemFont(ofSize: 22.0) - addMetaDataBtn.addTarget(self, action: #selector(addMetaDataAction), for: .touchUpInside) - scrollViewMain.addSubview(addMetaDataBtn) - - let submitBtn = UIButton(frame: CGRect(x: self.view.frame.width/2-60, y: addMetaDataBtn.frame.maxY+30, width: 120, height: 55)) - submitBtn.setTitle("Submit", for: .normal) - submitBtn.backgroundColor = UIColor(red: 89.0/255.0, green: 12.0/255.0, blue: 228.0/255.0, alpha: 1.0) - submitBtn.layer.cornerRadius = 8 - submitBtn.setTitleColor(UIColor.white, for: .normal) - submitBtn.titleLabel?.font = UIFont.boldSystemFont(ofSize: 22.0) - submitBtn.addTarget(self, action: #selector(self.submitAction), for: .touchUpInside) - scrollViewMain.addSubview(submitBtn) - - - txtFldContentTitle.setLeftPaddingPoints(10) - txtFldDescription.setLeftPaddingPoints(10) - txtFldImageUrl.setLeftPaddingPoints(10) - txtFldCanonicalIdentifier.setLeftPaddingPoints(10) - txtFldCanonicalIdentifier.attributedPlaceholder = NSAttributedString( - string: "Canonical Identifier", - attributes: [NSAttributedString.Key.foregroundColor: UIColor.darkGray] - ) - - txtFldContentTitle.attributedPlaceholder = NSAttributedString( - string: "Content Title", - attributes: [NSAttributedString.Key.foregroundColor: UIColor.darkGray] - ) - - txtFldDescription.attributedPlaceholder = NSAttributedString( - string: "Content Description", - attributes: [NSAttributedString.Key.foregroundColor: UIColor.darkGray] - ) - txtFldImageUrl.attributedPlaceholder = NSAttributedString( - string: "Image URL", - attributes: [NSAttributedString.Key.foregroundColor: UIColor.darkGray] - ) - } -} diff --git a/DeepLinkDemo/DeepLinkDemo/Controllers/DispalyVC.swift b/DeepLinkDemo/DeepLinkDemo/Controllers/DispalyVC.swift deleted file mode 100644 index b98f2ccab..000000000 --- a/DeepLinkDemo/DeepLinkDemo/Controllers/DispalyVC.swift +++ /dev/null @@ -1,60 +0,0 @@ -// -// DispalyVC.swift -// DeepLinkDemo -// -// Created by Rakesh kumar on 4/26/22. -// - -import UIKit -import BranchSDK - -class DispalyVC: ParentViewController { - - @IBOutlet weak var pageTitle: UILabel! - - @IBOutlet weak var textViewDescription: UITextView! - - var textDescription = "" - var linkURL = "" - var appData : Dictionary = Dictionary() - private var reachability:Reachability? - override func viewDidLoad() { - super.viewDidLoad() - - debugPrint("textDescription", textDescription) - - if appData["nav_to"] is String { - self.pageTitle.text = "Navigate To Content" - let content = String(format:"\nReferring link: %@ \n\nSession Details:\n %@", linkURL, appData.jsonStringRepresentation!) - self.textViewDescription.text = content - } else if appData["display_Cont"] is String { - self.pageTitle.text = "Display Content" - let content = String(format:"\nReferring link: %@ \n\nSession Details:\n %@", linkURL, appData.jsonStringRepresentation!) - self.textViewDescription.text = content - } - else{ - self.pageTitle.text = "Read Deep Linking" - self.textViewDescription.text = String(format:"%@", textDescription) - } - - reachabilityCheck() - } - - override func viewWillAppear(_ animated: Bool) { - super.viewWillAppear(animated) - if appData["nav_to"] is String { - Utils.shared.setLogFile("NavigateContentDetail") - } else if appData["display_Cont"] is String { - Utils.shared.setLogFile("DisplayContentDetail") - } else { - Utils.shared.setLogFile("ReadDeepLinkingDetail") - } - } - - - - @IBAction func backAction(_ sender: Any) { - self.navigationController?.popToRootViewController(animated: true) - } - -} diff --git a/DeepLinkDemo/DeepLinkDemo/Controllers/GenerateURLVC.swift b/DeepLinkDemo/DeepLinkDemo/Controllers/GenerateURLVC.swift deleted file mode 100644 index a1db4f8f6..000000000 --- a/DeepLinkDemo/DeepLinkDemo/Controllers/GenerateURLVC.swift +++ /dev/null @@ -1,257 +0,0 @@ -// -// GenerateURLVC.swift -// DeepLinkDemo -// Created by Rakesh kumar on 4/19/22. - -import UIKit -import BranchSDK -class GenerateURLVC: ParentViewController { - @IBOutlet weak var txtFldCChannel: UITextField! - @IBOutlet weak var txtFldFeature: UITextField! - @IBOutlet weak var txtFldChampaignName: UITextField! - @IBOutlet weak var txtFldStage: UITextField! - @IBOutlet weak var txtFldDeskTopUrl: UITextField! - @IBOutlet weak var txtFldAndroidUrl: UITextField! - @IBOutlet weak var txtFldiOSTopUrl: UITextField! - @IBOutlet weak var txtFldAdditionalData: UITextField! - @IBOutlet weak var scrollViewMain: UIScrollView! - - var responseStatus = "" - var screenMode = 0 - - var dictData = [String:Any]() - - var isShareDeepLink = false - - var isDisplayContent = false - - var isNavigateToContent = false - - var isTrackContent = false - - var handleLinkInWebview = false - - var isCreateDeepLink = false - - var forNotification = false - - override func viewDidLoad() { - super.viewDidLoad() - uiSetUp() - - NSLog("dictData", dictData) - super.reachabilityCheck() - } - - override func viewDidLayoutSubviews() { - super.viewDidLayoutSubviews() - scrollViewMain.contentSize.height = scrollViewMain.subviews.sorted(by: { $0.frame.maxY < $1.frame.maxY }).last?.frame.maxY ?? scrollViewMain.contentSize.height - } - - override func viewWillAppear(_ animated: Bool) { - super.viewWillAppear(animated) - Utils.shared.setLogFile("CreateDeeplink") - } - - - @IBAction func backAction(_ sender: Any) { - self.navigationController?.popToRootViewController(animated: true) - } - - func fireLocalNotification(linkurl: String){ - let dict = [ - "aps": [ - "alert":[ - "title":"Hi", - "body":"Hi, How Are You Dear" - ] - ], - "mutable-content" : false, - "branch": "\(linkurl)" - ] as [String : Any] - let notification = UILocalNotification() - notification.fireDate = Date(timeIntervalSinceNow: 1) - notification.alertBody = "Notification for handling deeplink" - notification.alertAction = "TestBed App" - notification.soundName = UILocalNotificationDefaultSoundName - notification.userInfo = dict - UIApplication.shared.scheduleLocalNotification(notification) - // sleep(2) - // self.navigationController?.popToRootViewController(animated: true) - } - - fileprivate func processShortURLGenerated(_ url: String?) { - NSLog("Check out my ShortUrl!! \(url ?? "")") - Utils.shared.setLogFile("CreateDeeplink") - let alertMessage = self.getAPIDetailFromLogFile("CreateDeeplink.log") - DispatchQueue.main.asyncAfter(deadline: .now() + 0.7) { - UserDefaults.standard.set("createdeeplinking", forKey: "isStatus") - UserDefaults.standard.set(true, forKey: "isCreatedDeepLink") - UserDefaults.standard.set("\(url ?? "")", forKey: "link") - if self.forNotification == true { - self.fireLocalNotification(linkurl: "\(url ?? "")") - self.launchTextViewController(url: "\(url ?? "")", message: alertMessage, forNotification: true) - }else if self.isShareDeepLink == true { - let bsl = BranchShareLink(universalObject: CommonMethod.sharedInstance.branchUniversalObject, linkProperties: CommonMethod.sharedInstance.linkProperties) - if #available(iOS 13.0, *) { - let metaData: LPLinkMetadata = LPLinkMetadata() - let iconImage = UIImage(named: "qentelli_logo") - metaData.iconProvider = NSItemProvider(object: iconImage!) - metaData.title = "Share Deeplink from the app" - metaData.url = URL(string: "\(url ?? "")") - bsl.lpMetaData = metaData - } - bsl.presentActivityViewController(from: self, anchor: nil) - } else if self.isTrackContent == true { - self.launchTextViewController(url: "\(url ?? "")", message: alertMessage, TrackContentWeb: true) - } else if self.isNavigateToContent == true { - self.launchTextViewController(url: "\(url ?? "")", message: alertMessage, NavigateToContent: true) - } else if self.isDisplayContent == true { - self.launchTextViewController(url: "\(url ?? "")", message: alertMessage, displayContent: true) - } else if self.handleLinkInWebview == true { - self.launchTextViewController(url: "\(url ?? "")", message: alertMessage, handleLinkInWebview: true) - } else if self.isCreateDeepLink == true{ - self.launchTextViewController(url: "\(url ?? "")", message: alertMessage, CreateDeepLink: true) - } else { - self.launchTextViewController(url: "\(url ?? "")", message: alertMessage) - } - } - } - - func launchTextViewController(url: String? = "",message: String? = "", ShareDeepLink: Bool? = false, displayContent: Bool? = false, NavigateToContent: Bool? = false, TrackContent: Bool? = false, TrackContentWeb: Bool? = false, handleLinkInWebview: Bool? = false, CreateDeepLink: Bool? = false, forNotification: Bool? = false) { - let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil) - if let vc = storyBoard.instantiateViewController(withIdentifier: "TextViewController") as? TextViewController { - vc.isTrackContent = TrackContent! - vc.forNotification = forNotification! - vc.isCreateDeepLink = CreateDeepLink! - vc.isShareDeepLink = ShareDeepLink! - vc.isNavigateToContent = NavigateToContent! - vc.handleLinkInWebview = handleLinkInWebview! - vc.isDisplayContent = displayContent! - vc.isTrackContenttoWeb = TrackContentWeb! - vc.textViewText = message ?? "" - vc.responseStatus = self.responseStatus - vc.url = url ?? "" - self.navigationController?.pushViewController(vc, animated: true) - } - } - - private func loadTextWithFileName(_ fileName: String) -> String? { - if let dir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first { - let fileURL = dir.appendingPathComponent(fileName) - guard let text = try? String(contentsOf: fileURL, encoding: .utf8) else { - return nil - } - return text - } - return nil - } - - fileprivate func getAPIDetailFromLogFile(_ fileName: String) -> String{ - var alertMessage = "LogFilePath : \(self.getLogFilepath(fileName)!) \n\n" - alertMessage = alertMessage + "\n\n" - if let fileContent = self.loadTextWithFileName(fileName), !fileContent.isEmpty { - let startlocation = fileContent.range(of: "BranchSDK API LOG START OF FILE") - let endlocation = fileContent.range(of: "BranchSDK API LOG END OF FILE") - if ((startlocation?.lowerBound != startlocation?.upperBound) && (endlocation?.lowerBound != endlocation?.upperBound)){ - let apiResponse = fileContent[startlocation!.lowerBound.. String? { - let dir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first - let fileURL = dir?.appendingPathComponent(fileName) - let fileURLStr = fileURL?.path - return fileURLStr - } - - @IBAction func submitAction(sender : UIButton) { - self.view.endEditing(true) - let linkProperties = BranchLinkProperties() - linkProperties.feature = txtFldFeature.text - linkProperties.channel = txtFldCChannel.text - linkProperties.campaign = txtFldChampaignName.text - linkProperties.stage = txtFldStage.text - linkProperties.addControlParam("$desktop_url", withValue: txtFldDeskTopUrl.text) - linkProperties.addControlParam("$ios_url", withValue: txtFldiOSTopUrl.text) - linkProperties.addControlParam("$android_url", withValue: txtFldAndroidUrl.text) - linkProperties.addControlParam("custom", withValue: txtFldAdditionalData.text) - if isNavigateToContent == true { - linkProperties.addControlParam("nav_to", withValue: "landing_page") - } else if isDisplayContent == true { - linkProperties.addControlParam("display_Cont", withValue: "landing_page") - } - - - CommonMethod.sharedInstance.branchUniversalObject.getShortUrl(with: linkProperties, andCallback: {[weak self] url, error in - - if error == nil { - self?.responseStatus = "Success" - self?.processShortURLGenerated(url) - } else { - self?.responseStatus = "Failure" - } - }) - - - } - -} - -extension GenerateURLVC { - func uiSetUp() { - let submitBtn = UIButton(frame: CGRect(x: self.view.frame.width/2-60, y: txtFldAdditionalData.frame.maxY+15, width: 120, height: 55)) - submitBtn.setTitle("Submit", for: .normal) - submitBtn.backgroundColor = UIColor(red: 89.0/255.0, green: 12.0/255.0, blue: 228.0/255.0, alpha: 1.0) - submitBtn.layer.cornerRadius = 8 - submitBtn.setTitleColor(UIColor.white, for: .normal) - submitBtn.titleLabel?.font = UIFont.boldSystemFont(ofSize: 22.0) - submitBtn.addTarget(self, action: #selector(self.submitAction), for: .touchUpInside) - scrollViewMain.addSubview(submitBtn) - - txtFldCChannel.setLeftPaddingPoints(10) - txtFldFeature.setLeftPaddingPoints(10) - txtFldChampaignName.setLeftPaddingPoints(10) - txtFldStage.setLeftPaddingPoints(10) - txtFldDeskTopUrl.setLeftPaddingPoints(10) - txtFldAdditionalData.setLeftPaddingPoints(10) - txtFldAndroidUrl.setLeftPaddingPoints(10) - txtFldiOSTopUrl.setLeftPaddingPoints(10) - - txtFldCChannel.attributedPlaceholder = NSAttributedString( - string: "Channel name like Facebook", - attributes: [NSAttributedString.Key.foregroundColor: UIColor.darkGray] - ) - txtFldFeature.attributedPlaceholder = NSAttributedString( - string: "Feature eg: Sharing", - attributes: [NSAttributedString.Key.foregroundColor: UIColor.darkGray] - ) - txtFldChampaignName.attributedPlaceholder = NSAttributedString( - string: "Campaign name", - attributes: [NSAttributedString.Key.foregroundColor: UIColor.darkGray] - ) - txtFldStage.attributedPlaceholder = NSAttributedString( - string: "Stage", - attributes: [NSAttributedString.Key.foregroundColor: UIColor.darkGray] - ) - txtFldDeskTopUrl.attributedPlaceholder = NSAttributedString( - string: "Desktop URL", - attributes: [NSAttributedString.Key.foregroundColor: UIColor.darkGray] - ) - txtFldAndroidUrl.attributedPlaceholder = NSAttributedString( - string: "Android URL", - attributes: [NSAttributedString.Key.foregroundColor: UIColor.darkGray] - ) - txtFldiOSTopUrl.attributedPlaceholder = NSAttributedString( - string: "iOS URL", - attributes: [NSAttributedString.Key.foregroundColor: UIColor.darkGray] - ) - txtFldAdditionalData.attributedPlaceholder = NSAttributedString( - string: "Additional Data", - attributes: [NSAttributedString.Key.foregroundColor: UIColor.darkGray] - ) - } -} diff --git a/DeepLinkDemo/DeepLinkDemo/Controllers/HomeViewController.swift b/DeepLinkDemo/DeepLinkDemo/Controllers/HomeViewController.swift deleted file mode 100644 index b4880dce9..000000000 --- a/DeepLinkDemo/DeepLinkDemo/Controllers/HomeViewController.swift +++ /dev/null @@ -1,452 +0,0 @@ -// ViewController.swift -// DeepLinkDemo -// Created by Rakesh kumar on 4/15/22 - -import UIKit -import BranchSDK -class HomeViewController: UITableViewController { - private var reachability:Reachability? - - @IBOutlet weak var btnCreatBUO: UIButton! - @IBOutlet weak var btnTrackingEnabled: UIButton! - @IBOutlet weak var btnCreateDeepLinking: UIButton! - @IBOutlet weak var btnShareLink: UIButton! - @IBOutlet weak var btnSendNotification: UIButton! - @IBOutlet weak var btnTrackUser: UIButton! - @IBOutlet weak var btnLoadWebView: UIButton! - @IBOutlet weak var btReadDeeplink: UIButton! - @IBOutlet weak var btnTrackContent: UIButton! - @IBOutlet weak var btnNavigateToContent: UIButton! - @IBOutlet weak var btnDisplayContent: UIButton! - @IBOutlet weak var btnReadLog: UIButton! - @IBOutlet weak var btnSetDMAParams: UIButton! - @IBOutlet weak var btnSendV2Event: UIButton! - @IBOutlet weak var btnSetAttributionLevel: UIButton! - - @IBOutlet weak var switchControl: UISwitch! - - @IBOutlet weak var labelStatus: UILabel! - - let branchObj:Branch! = nil - var logData: String! = "" - var branchSDKInitialized = false; - - override func viewDidLoad() { - super.viewDidLoad() - - btnTrackingEnabled.layer.cornerRadius = 8.0 - btnCreatBUO.layer.cornerRadius = 8.0 - btnCreateDeepLinking.layer.cornerRadius = 8.0 - btnShareLink.layer.cornerRadius = 8.0 - btnShareLink.layer.cornerRadius = 8.0 - btnTrackUser.layer.cornerRadius = 8.0 - btnSendNotification.layer.cornerRadius = 8.0 - btReadDeeplink.layer.cornerRadius = 8.0 - btnTrackContent.layer.cornerRadius = 8.0 - btnNavigateToContent.layer.cornerRadius = 8.0 - btnReadLog.layer.cornerRadius = 8.0 - btnLoadWebView.layer.cornerRadius = 8.0 - btnSetDMAParams.layer.cornerRadius = 8.0 - btnSendV2Event.layer.cornerRadius = 8.0 - btnSetAttributionLevel.layer.cornerRadius = 8.0 - - NotificationCenter.default.addObserver(self, selector: #selector(self.methodOfReceivedNotification(notification:)), name: Notification.Name("NotificationIdentifier"), object: nil) - - reachabilityCheck(textValue:"") - - if Branch.trackingDisabled(){ - switchControl.isOn = false - }else{ - switchControl.isOn = true - } - - btnReadLog.isHidden = true - - } - - override func viewWillAppear(_ animated: Bool) { - super.viewWillAppear(animated) - Utils.shared.setLogFile("Homepage") - } - - func reachabilityCheck(textValue:String?) { - CommonMethod.sharedInstance.contentMetaData = nil - reachability = Reachability()! - reachability!.whenReachable = { reachability in - Branch.setBranchKey("key_test_om2EWe1WBeBYmpz9Z1mdpopouDmoN72T") - DispatchQueue.main.async { - if textValue == "displayContent" { - self.initBranch() - self.launchBUOVC(mode: 8) - } else if textValue == "navigatetoContent" { - self.initBranch() - self.launchBUOVC(mode: 3) - } else if textValue == "sendNotification" { - self.initBranch() - self.launchBUOVC(mode: 6) - } else if textValue == "loadUrlInWeb" { - self.initBranch() - self.launchBUOVC(mode: 4) - } else if textValue == "createDeep" { - self.initBranch() - self.launchBUOVC(mode: 5) - } else if textValue == "shareDeeplinking" { - self.initBranch() - self.launchBUOVC(mode: 2) - } else if textValue == "readDeeplinking" { - self.initBranch() - self.launchBUOVC(mode: 1) - } else if textValue == "trackContent" { - self.initBranch() - let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil) - if let vc = storyBoard.instantiateViewController(withIdentifier: "TrackContentVC") as? TrackContentVC { - self.navigationController?.pushViewController(vc, animated: true) - } - } else if textValue == "trackUser" { - self.initBranch() - Branch.getInstance().setIdentity("qentelli_test_user") { params, error in - - if let referringParams = params as? [String :AnyObject] { - let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil) - if let vc = storyBoard.instantiateViewController(withIdentifier: "TextViewController") as? TextViewController { - vc.isTrackUser = true - vc.textViewText = "Result \(referringParams)" - vc.responseStatus = "Success" - self.navigationController?.pushViewController(vc, animated: true) - } - }else{ - NSLog("track user error--> \(error!.localizedDescription)") - } - } - } else if textValue == "swichAction" { - - } else if textValue == "createObject" { - self.initBranch() - self.launchBUOVC(mode: 0) - } else if textValue == "readSystemLog" { - self.initBranch() - let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil) - if let vc = storyBoard.instantiateViewController(withIdentifier: "LogFileListViewController") as? LogFileListViewController { - self.navigationController?.pushViewController(vc, animated: true) - } - } else if textValue == "setDMAParams" { - self.setDMAParamsWrapper() - } else if textValue == "sendV2Event" { - self.sendV2EventWrapper() - } else if textValue == "setAttributionLevel" { - self.setAttributionLevelWrapper() - } - } - } - - reachability?.whenUnreachable = { reachability in - DispatchQueue.main.asyncAfter(deadline: .now() + 0.6) { - self.networkError() - } - } - do { - try reachability?.startNotifier() - } catch { - NSLog("Unable to start notifier") - } - } - func launchBUOVC(mode: Int) { - let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil) - if let vc = storyBoard.instantiateViewController(withIdentifier: "CreateObjectReferenceObject") as? CreateObjectReferenceObject { - vc.screenMode = mode - self.navigationController?.pushViewController(vc, animated: true) - } - } - - func networkError() { - CommonAlert.shared.showActionAlertView(title: "Failure", message: "Your internet/network connection appears to be offline. Please check your internet/network connection.", actions: [], preferredStyle: .alert, viewController: self) - } - - func enableBranchLogging(callback: @escaping BranchLogCallback){ - Branch.enableLogging(at: .verbose, withCallback: callback) - } - - func initBranch(){ - if branchSDKInitialized { - return - } - self.enableBranchLogging(){(message:String, loglevel:BranchLogLevel, error:Error?)->() in - if (message.contains("BranchSDK")){ - self.logData = self.logData + message + "\n" - Utils.shared.printLogMessage(message + "\n") - } - } - AppDelegate.shared.getBranchData(AppDelegate.shared.launchOption) - branchSDKInitialized = true - } - - func logEvent(){ - let event = BranchEvent.standardEvent(.purchase) - // Add a populated `BranchUniversalObject` to the event - let buo = BranchUniversalObject(canonicalIdentifier: "item/12345") - event.contentItems = [ buo ] - // Add additional event data - event.alias = "my custom alias" - event.transactionID = "12344555" - event.eventDescription = "event_description" - event.searchQuery = "item 123" - event.customData = [ - "Custom_Event_Property_Key1": "Custom_Event_Property_val1", - "Custom_Event_Property_Key2": "Custom_Event_Property_val2" - ] - // Log the event - event.logEvent() - } - - func setAttributionLevelWrapper() { - self.logData = "Error: Missing testData.\n" - - let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil) - let vc = storyBoard.instantiateViewController(withIdentifier: "TextViewController") as? TextViewController - vc?.isSetAttributionLevel = true - - do { - let argCount = ProcessInfo.processInfo.arguments.count - if argCount >= 2 { - - for i in (1 ..< argCount) { - let data = ProcessInfo.processInfo.arguments[i].data(using: .utf8)! - - if let jsonObject = try JSONSerialization.jsonObject(with: data, options : .allowFragments) as? [String:AnyObject] - { - if jsonObject["consumer_protection_attribution_level"] != nil { - let attribution_level = jsonObject["consumer_protection_attribution_level"] as! String - self.logData = "" - self.enableBranchLogging(){(msg:String,msg2:BranchLogLevel,msg3:Error?)->() in - if (msg.contains("BranchSDK")){ - self.logData = self.logData + msg + "\n" - } - vc?.updateText(msg: self.logData) - } - if(self.branchSDKInitialized){ - Branch.getInstance().resetUserSession() - } - - switch attribution_level { - case "0": - Branch.getInstance().setConsumerProtectionAttributionLevel(.full) - case "1": - Branch.getInstance().setConsumerProtectionAttributionLevel(.reduced) - case "2": - Branch.getInstance().setConsumerProtectionAttributionLevel(.minimal) - case "3": - Branch.getInstance().setConsumerProtectionAttributionLevel(.none) - default: - Branch.getInstance().setConsumerProtectionAttributionLevel(.full) - } - - AppDelegate.shared.getBranchData(AppDelegate.shared.launchOption) - self.branchSDKInitialized = true - } else { - self.logData = "Missing params from JSON Object: \n" + jsonObject.description - } - } else { - self.logData = "Bad JSON : \n" + ProcessInfo.processInfo.arguments[i] - } - } - - - } - } catch let error as NSError { - print(error) - self.logData += error.localizedDescription - } - vc?.updateText(msg: self.logData) - self.navigationController?.pushViewController(vc!, animated: true) - } - - func setDMAParamsWrapper() { - self.logData = "Error: Missing testData.\n" - - let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil) - let vc = storyBoard.instantiateViewController(withIdentifier: "TextViewController") as? TextViewController - vc?.isSetDMAParams = true - - do { - let argCount = ProcessInfo.processInfo.arguments.count - if argCount >= 2 { - - for i in (1 ..< argCount) { - let data = ProcessInfo.processInfo.arguments[i].data(using: .utf8)! - - if let jsonObject = try JSONSerialization.jsonObject(with: data, options : .allowFragments) as? [String:AnyObject] - { - if ((jsonObject["dma_eea"] != nil) && (jsonObject["dma_eea"] != nil) && (jsonObject["dma_eea"] != nil)) { - let dma_eea = jsonObject["dma_eea"] as! Bool - let dma_ad_personalization = jsonObject["dma_ad_personalization"] as! Bool - let dma_ad_user_data = jsonObject["dma_ad_user_data"] as! Bool - self.logData = "" - self.enableBranchLogging(){(msg:String,msg2:BranchLogLevel,msg3:Error?)->() in - if (msg.contains("BranchSDK")){ - self.logData = self.logData + msg + "\n" - } - vc?.updateText(msg: self.logData) - } - if(self.branchSDKInitialized){ - Branch.getInstance().resetUserSession() - } - - Branch.setDMAParamsForEEA(dma_eea, adPersonalizationConsent: dma_ad_personalization, adUserDataUsageConsent: dma_ad_user_data) - AppDelegate.shared.getBranchData(AppDelegate.shared.launchOption) - self.branchSDKInitialized = true - } else { - self.logData = "Missing params from JSON Object: \n" + jsonObject.description - } - } else { - self.logData = "Bad JSON : \n" + ProcessInfo.processInfo.arguments[i] - } - } - - - } - } catch let error as NSError { - print(error) - self.logData += error.localizedDescription - } - vc?.updateText(msg: self.logData) - self.navigationController?.pushViewController(vc!, animated: true) - } - - func sendV2EventWrapper(){ - self.logData = "" - - let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil) - let vc = storyBoard.instantiateViewController(withIdentifier: "TextViewController") as? TextViewController - - self.enableBranchLogging(){(msg:String,msg2:BranchLogLevel,msg3:Error?)->() in - if (msg.contains("BranchSDK")){ - self.logData = self.logData + msg + "\n" - vc?.updateText(msg: self.logData) - } - } - self.logEvent() - self.navigationController?.pushViewController(vc!, animated: true) - vc?.isSendV2Event = true - vc?.updateText(msg: self.logData) - self.branchSDKInitialized = true - } - - @IBAction func sendNotificationAction(_ sender: Any) { - reachabilityCheck(textValue: "sendNotification") - } - - @objc func methodOfReceivedNotification(notification: Notification) { - - Branch.getInstance().initSession( launchOptions: AppDelegate.shared.launchOption, - andRegisterDeepLinkHandlerUsingBranchUniversalObject: { [self] universalObject, linkProperties, error in - if universalObject != nil { - NSLog("UniversalObject", universalObject ?? "NA") - NSLog("LinkProperties", linkProperties ?? "NA") - NSLog("UniversalObject Metadata:", universalObject?.contentMetadata.customMetadata ?? "NA") - if let isRead = UserDefaults.standard.value(forKey: "isRead") as? Bool, isRead == true { - if let dictData = universalObject?.contentMetadata.customMetadata as? NSDictionary { - let referedlink = dictData.value(forKey: "~referring_link") as? String ?? "" - // let linkurl = UserDefaults.standard.value(forKey: "link") as? String ?? "" - NSLog("referedlink:", referedlink) - UserDefaults.standard.set(referedlink, forKey: "link") - NSLog("Deep linked with object: %@.", universalObject ?? BranchUniversalObject()); - let deeplinkText = universalObject?.contentMetadata.customMetadata.value(forKey: "deeplink_text") - let textDetail = "Successfully Deeplinked:\n\n%@\nSession Details:\n\n%@, \(String(describing: deeplinkText)) \(String(describing: Branch.getInstance().getLatestReferringParams()?.description))" - UserDefaults.standard.setValue(textDetail, forKey: "textDetail") - let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil) - if let vc = storyBoard.instantiateViewController(withIdentifier: "DispalyVC") as? DispalyVC { - vc.textDescription = textDetail - self.navigationController?.pushViewController(vc, animated: true) - } - } - } else { - NSLog("No Deep linked object"); - } - } - }) - } - - @IBAction func displayContentBtnAction(_ sender: Any) { - reachabilityCheck(textValue: "displayContent") - } - - @IBAction func navigatetoContentBtnAction(_ sender: Any) { - reachabilityCheck(textValue: "navigatetoContent") - } - - @IBAction func loadUrlInWebViewAction(_ sender: Any) { - reachabilityCheck(textValue: "loadUrlInWeb") - } - - @IBAction func createDeeplinking(_ sender: Any) { - reachabilityCheck(textValue: "createDeep") - } - - @IBAction func shareDeeplinking(_ sender: Any) { - reachabilityCheck(textValue: "shareDeeplinking") - } - - @IBAction func readDeeplinking(_ sender: Any) { - reachabilityCheck(textValue: "readDeeplinking") - } - - @IBAction func trackContentAction(_ sender: Any) { - reachabilityCheck(textValue: "trackContent") - } - - @IBAction func trackUserAction(_ sender: Any) { - reachabilityCheck(textValue: "trackUser") - } - - @IBAction func swichAction(_ sender: UISwitch) { - reachabilityCheck(textValue: "swichAction") - if sender.isOn == true { - NSLog("is OFF", "ison") - btnTrackingEnabled.setTitle("Tracking Enabled", for: .normal) - btnTrackingEnabled.titleLabel?.font = UIFont.boldSystemFont(ofSize: 36) - Branch.setTrackingDisabled(true) - - } else { - NSLog("is ON", "isOFF") - Branch.setTrackingDisabled(false) - btnTrackingEnabled.setTitle("Tracking Disabled", for: .normal) - btnTrackingEnabled.titleLabel?.font = UIFont(name: "Helvetica", size:36) - } - } - - @IBAction func createObject(_ sender: Any) { - reachabilityCheck(textValue: "createObject") - - } - - @IBAction func readSystemLog(){ - reachabilityCheck(textValue: "readSystemLog") - - - } - - @IBAction func setDMAParams(){ - reachabilityCheck(textValue: "setDMAParams") - } - - @IBAction func sendV2Event(){ - reachabilityCheck(textValue: "sendV2Event") - } - - @IBAction func setAttributionLevel(){ - reachabilityCheck(textValue: "setAttributionLevel") - } -} - -extension UITextField { - func setLeftPaddingPoints(_ amount:CGFloat){ - let paddingView = UIView(frame: CGRect(x: 0, y: 0, width: amount, height: self.frame.size.height)) - self.leftView = paddingView - self.leftViewMode = .always - } - func setRightPaddingPoints(_ amount:CGFloat) { - let paddingView = UIView(frame: CGRect(x: 0, y: 0, width: amount, height: self.frame.size.height)) - self.rightView = paddingView - self.rightViewMode = .always - } -} diff --git a/DeepLinkDemo/DeepLinkDemo/Controllers/LogFileListViewController.swift b/DeepLinkDemo/DeepLinkDemo/Controllers/LogFileListViewController.swift deleted file mode 100644 index 844af618d..000000000 --- a/DeepLinkDemo/DeepLinkDemo/Controllers/LogFileListViewController.swift +++ /dev/null @@ -1,84 +0,0 @@ -// -// LogFileListViewController.swift -// DeepLinkDemo -// -// Created by Apple on 26/05/22. -// - -import UIKit - -class LogFileListViewController: UIViewController { - - var fileNames = [String]() - - @IBOutlet weak var logFileListTblView: UITableView! - - override func viewDidLoad() { - super.viewDidLoad() - - fileNames = getAllLogFileNames() - } - - func getAllLogFileNames() -> [String]{ - let documentsUrl = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first! - - do { - var fileName = [String]() - let fileURLs = try FileManager.default.contentsOfDirectory(at: documentsUrl, - includingPropertiesForKeys: nil, - options: .skipsHiddenFiles) - for fileURL in fileURLs { - fileName.append(fileURL.lastPathComponent) - } - - return fileName - } catch { - NSLog("Failed to delete/read the file in document directory %@", error.localizedDescription) - } - return [""] - } - @IBAction func backAction(_ sender: Any) { - self.navigationController?.popToRootViewController(animated: true) - } - - -} - - -extension LogFileListViewController: UITableViewDataSource, UITableViewDelegate{ - func numberOfSections(in tableView: UITableView) -> Int { - return 1 - } - - func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - return fileNames.count - } - - func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - if let cell = tableView.dequeueReusableCell(withIdentifier: "LogTableViewCell", for: indexPath) as? LogTableViewCell{ - cell.nameLbl.text = fileNames[indexPath.row] - return cell - } - return UITableViewCell() - } - - func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { - return 60 - } - - func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - let selectedFile = fileNames[indexPath.row] - let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil) - if let vc = storyBoard.instantiateViewController(withIdentifier: "ReadLogViewController") as? ReadLogViewController { - vc.selectedFileName = selectedFile - self.navigationController?.pushViewController(vc, animated: true) - } - - } -} - - -class LogTableViewCell: UITableViewCell{ - - @IBOutlet weak var nameLbl: UILabel! -} diff --git a/DeepLinkDemo/DeepLinkDemo/Controllers/MetaDataTableViewCell.swift b/DeepLinkDemo/DeepLinkDemo/Controllers/MetaDataTableViewCell.swift deleted file mode 100644 index bc5170c63..000000000 --- a/DeepLinkDemo/DeepLinkDemo/Controllers/MetaDataTableViewCell.swift +++ /dev/null @@ -1,224 +0,0 @@ -// -// MetaDataTableViewCell.swift -// DeepLinkDemo -// -// Created by Apple on 13/05/22. -// - -import UIKit -import BranchSDK - -protocol PickerViewDelegate{ - func removePickerView() -} -class MetaDataTableViewCell: UITableViewCell { - - var pickerDelegate: PickerViewDelegate! - - private let contentSchemaNames = ["COMMERCE_AUCTION", "COMMERCE_BUSINESS", "COMMERCE_OTHER", - "COMMERCE_PRODUCT", "COMMERCE_RESTAURANT", "COMMERCE_SERVICE", - "COMMERCE_TRAVEL_FLIGHT", "COMMERCE_TRAVEL_HOTEL", "COMMERCE_TRAVEL_OTHER", - "GAME_STATE", "MEDIA_IMAGE", "MEDIA_MIXED", "MEDIA_MUSIC", "MEDIA_OTHER", - "MEDIA_VIDEO", "OTHER", "TEXT_ARTICLE", "TEXT_BLOG", "TEXT_OTHER", - "TEXT_RECIPE", "TEXT_REVIEW", "TEXT_SEARCH_RESULTS", "TEXT_STORY", - "TEXT_TECHNICAL_DOC"] - - private let productCategories = ["Animals & Pet Supplies", "Apparel & Accessories", "Arts & Entertainment", - "Baby & Toddler", "Business & Industrial", "Cameras & Optics", - "Electronics", "Food, Beverages & Tobacco", "Furniture", "Hardware", - "Health & Beauty", "Home & Garden", "Luggage & Bags", "Mature", - "Media", "Media", "Office Supplies", "Religious & Ceremonial", - "Software", "Sporting Goods", "Toys & Games", "Vehicles & Parts"] - - - private let productConditions = ["EXCELLENT", "NEW", "GOOD", "FAIR", "POOR", "USED", "REFURBISHED", "OTHER"] - - - private let currencyNames = ["USD", "AFN", "ALL", "AMD", "ANG", "AOA", "ARS", "AUD", "AWG", "AZN", "BAM", "BBD", "BDT", "BGN", "BHD", "BIF", "BMD", "BND", "BOB", "BOV", "BRL", "BSD", "BTN", "BWP", "BYN", "BYR", "CAD", "CDF", "CHE", "CHF", "CHW", "CLF", "CLP", "CNY", "COP", "COU", "CRC", "CUC", "CUP", "CVE", "CZK", "DJF", "DKK", "DOP", "DZD", "EGP", "ERN", "ETB", "EUR", "FJD", "FKP", "GBP", "GEL", "GHS", "GIP", "GMD", "GNF", "GTQ", "GYD", "HKD", "HNL", "HRK", "HTG", "HUF", "IDR", "ILS", "INR", "IQD", "IRR", "ISK", "JMD", "JOD", "JPY", "KES", "KGS", "KHR", "KMF", "KPW", "KRW", "KWD", "KYD", "KZT", "LAK", "LBP", "LKR", "LRD", "LSL", "LYD", "MAD", "MDL", "MGA", "MKD", "MMK", "MNT", "MOP", "MRO", "MUR", "MVR", "MWK", "MXN", "MXV", "MYR", "MZN", "NAD", "NGN", "NIO", "NOK", "NPR", "NZD", "OMR", "PAB", "PEN", "PGK", "PHP", "PKR", "PLN", "PYG", "QAR", "RON", "RSD", "RUB", "RWF", "SAR", "SBD", "SCR", "SDG", "SEK", "SGD", "SHP", "SLL", "SOS", "SRD", "SSP", "STD", "SYP", "SZL", "THB", "TJS", "TMT", "TND", "TOP", "TRY", "TTD", "TWD", "TZS", "UAH", "UGX", "USN", "UYI", "UYU", "UZS", "VEF", "VND", "VUV", "WST", "XAF", "XAG", "XAU", "XBA", "XBB", "XBC", "XBD", "XCD", "XDR", "XFU", "XOF", "XPD", "XPF", "XPT", "XSU", "XTS", "XUA", "XXX", "YER", "ZAR", "ZMW"] - - private var pickerView = UIPickerView() - - @IBOutlet weak var contentSchema: UITextField! - @IBOutlet weak var productName: UITextField! - @IBOutlet weak var productBrand: UITextField! - @IBOutlet weak var productVariant: UITextField! - @IBOutlet weak var productCategory: UITextField! - @IBOutlet weak var productCondition: UITextField! - @IBOutlet weak var street: UITextField! - @IBOutlet weak var city: UITextField! - @IBOutlet weak var region: UITextField! - @IBOutlet weak var country: UITextField! - @IBOutlet weak var postalCode: UITextField! - @IBOutlet weak var latitude: UITextField! - @IBOutlet weak var longitude: UITextField! - @IBOutlet weak var sku: UITextField! - @IBOutlet weak var rating: UITextField! - @IBOutlet weak var averageRating: UITextField! - @IBOutlet weak var maximumRating: UITextField! - @IBOutlet weak var ratingCount: UITextField! - @IBOutlet weak var imageCaption: UITextField! - @IBOutlet weak var quantity: UITextField! - @IBOutlet weak var price: UITextField! - @IBOutlet weak var currencyName: UITextField! - @IBOutlet weak var customMetadata: UITextField! - - @IBOutlet weak var submitBtn: UIButton! - - fileprivate func setAtrributePlaceHolder(targetField: UITextField, placeholderTxt: String){ - targetField.setLeftPaddingPoints(10) - targetField.attributedPlaceholder = NSAttributedString( - string: placeholderTxt, - attributes: [NSAttributedString.Key.foregroundColor: UIColor.darkGray] - ) - - } - - fileprivate func prepareUI(){ - self.setAtrributePlaceHolder(targetField: self.productName, placeholderTxt: "Product Name") - self.setAtrributePlaceHolder(targetField: self.productBrand, placeholderTxt: "Product Brand") - self.setAtrributePlaceHolder(targetField: self.productVariant, placeholderTxt: "Product Variant") - self.setAtrributePlaceHolder(targetField: self.street, placeholderTxt: "Street") - self.setAtrributePlaceHolder(targetField: self.city, placeholderTxt: "City") - self.setAtrributePlaceHolder(targetField: self.region, placeholderTxt: "Region") - self.setAtrributePlaceHolder(targetField: self.country, placeholderTxt: "Country") - self.setAtrributePlaceHolder(targetField: self.postalCode, placeholderTxt: "Postal Code") - self.setAtrributePlaceHolder(targetField: self.latitude, placeholderTxt: "Latitude") - self.setAtrributePlaceHolder(targetField: self.longitude, placeholderTxt: "Longitude") - self.setAtrributePlaceHolder(targetField: self.sku, placeholderTxt: "SKU") - self.setAtrributePlaceHolder(targetField: self.rating, placeholderTxt: "Rating") - self.setAtrributePlaceHolder(targetField: self.averageRating, placeholderTxt: "Average Rating") - self.setAtrributePlaceHolder(targetField: self.maximumRating, placeholderTxt: "Maximum Rating") - self.setAtrributePlaceHolder(targetField: self.ratingCount, placeholderTxt: "Rating Count") - self.setAtrributePlaceHolder(targetField: self.imageCaption, placeholderTxt: "Image Caption") - self.setAtrributePlaceHolder(targetField: self.quantity, placeholderTxt: "Quantity") - self.setAtrributePlaceHolder(targetField: self.price, placeholderTxt: "Price") - self.setAtrributePlaceHolder(targetField: self.customMetadata, placeholderTxt: "Custom Metadata") - - } - - fileprivate func setupPickerViewDataSource() { - pickerView.dataSource = self - pickerView.delegate = self - - let toolBar = UIToolbar(frame: CGRect(x: 0.0, y: 0.0, width: UIScreen.main.bounds.size.width,height: 44.0)) - let flexibleSpace = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil) - let doneButton = UIBarButtonItem(title: "Done", style: .plain, target: self, action: #selector(tapDone)) - let cancelButton = UIBarButtonItem(title: "Cancel", style: .plain, target: self, action: #selector(tapCancel)) - toolBar.setItems([cancelButton, flexibleSpace, doneButton], animated: false) - - contentSchema.inputView = pickerView - contentSchema.inputAccessoryView = toolBar - contentSchema.text = contentSchemaNames.first - - currencyName.inputView = pickerView - currencyName.inputAccessoryView = toolBar - currencyName.text = currencyNames.first - - productCondition.inputView = pickerView - productCondition.inputAccessoryView = toolBar - productCondition.text = productConditions.first - - productCategory.inputView = pickerView - productCategory.inputAccessoryView = toolBar - productCategory.text = productCategories.first - - productCategory.setLeftPaddingPoints(10) - productCondition.setLeftPaddingPoints(10) - currencyName.setLeftPaddingPoints(10) - contentSchema.setLeftPaddingPoints(10) - - - - } - - override func awakeFromNib() { - super.awakeFromNib() - - prepareUI() - - setupPickerViewDataSource() - - self.selectionStyle = .none - } - - @objc func tapDone() { - if contentSchema.isFirstResponder{ - let selectedRow = pickerView.selectedRow(inComponent: 0) - if contentSchemaNames.indices.contains(selectedRow){ - contentSchema.text = contentSchemaNames[selectedRow] - } - contentSchema.resignFirstResponder() - } else if currencyName.isFirstResponder{ - let selectedRow = pickerView.selectedRow(inComponent: 0) - if currencyNames.indices.contains(selectedRow){ - currencyName.text = currencyNames[selectedRow] - } - currencyName.resignFirstResponder() - } else if productCondition.isFirstResponder{ - let selectedRow = pickerView.selectedRow(inComponent: 0) - if productConditions.indices.contains(selectedRow){ - productCondition.text = productConditions[selectedRow] - } - productCondition.resignFirstResponder() - } else if productCategory.isFirstResponder{ - let selectedRow = pickerView.selectedRow(inComponent: 0) - if productCategories.indices.contains(selectedRow){ - productCategory.text = productCategories[selectedRow] - } - productCategory.resignFirstResponder() - } - self.endEditing(true) - } - - @objc func tapCancel() { - self.endEditing(true) - } - - -} - - -extension MetaDataTableViewCell: UIPickerViewDataSource, UIPickerViewDelegate{ - - func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int { - if contentSchema.isFirstResponder{ - return contentSchemaNames.count - } else if currencyName.isFirstResponder{ - return currencyNames.count - } else if productCondition.isFirstResponder{ - return productConditions.count - } else if productCategory.isFirstResponder{ - return productCategories.count - } - return 0 - } - - func numberOfComponents(in pickerView: UIPickerView) -> Int { - return 1 - } - - func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? { - if contentSchema.isFirstResponder{ - return contentSchemaNames[row] - } else if currencyName.isFirstResponder{ - return currencyNames[row] - } else if productCondition.isFirstResponder{ - return productConditions[row] - } else if productCategory.isFirstResponder{ - return productCategories[row] - } - return nil - } - - func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) { - if contentSchema.isFirstResponder{ - contentSchema.text = contentSchemaNames[row] - } else if currencyName.isFirstResponder{ - currencyName.text = currencyNames[row] - } else if productCondition.isFirstResponder{ - productCondition.text = productConditions[row] - } else if productCategory.isFirstResponder{ - productCategory.text = productCategories[row] - } - } -} diff --git a/DeepLinkDemo/DeepLinkDemo/Controllers/NavigateContentVC.swift b/DeepLinkDemo/DeepLinkDemo/Controllers/NavigateContentVC.swift deleted file mode 100644 index 225b64e8c..000000000 --- a/DeepLinkDemo/DeepLinkDemo/Controllers/NavigateContentVC.swift +++ /dev/null @@ -1,108 +0,0 @@ -// -// NavigateContentVC.swift -// DeepLinkDemo -// -// Created by Rakesh kumar on 4/19/22. -// - -import UIKit - -class NavigateContentVC: ParentViewController { - @IBOutlet weak var txtFldCChannel: UITextField! - @IBOutlet weak var txtFldFeature: UITextField! - @IBOutlet weak var txtFldChampaignName: UITextField! - @IBOutlet weak var txtFldStage: UITextField! - @IBOutlet weak var txtFldDeskTopUrl: UITextField! - @IBOutlet weak var txtFldAdditionalData: UITextField! - @IBOutlet weak var scrollViewMain: UIScrollView! - private var reachability:Reachability? - - override func viewDidLoad() { - super.viewDidLoad() - uiSetUp() - reachabilityCheck() - } - - override func viewWillAppear(_ animated: Bool) { - super.viewWillAppear(animated) - Utils.shared.setLogFile("NavigateContent") - } - - - override func viewDidLayoutSubviews() { - super.viewDidLayoutSubviews() - scrollViewMain.contentSize.height = scrollViewMain.subviews.sorted(by: { $0.frame.maxY < $1.frame.maxY }).last?.frame.maxY ?? scrollViewMain.contentSize.height - } - - @IBAction func backAction(_ sender: Any) { - self.navigationController?.popToRootViewController(animated: true) - } - - @objc func submitAction(sender : UIButton) { - self.view.endEditing(true) - CommonMethod.sharedInstance.branchUniversalObject.publiclyIndex = true - CommonMethod.sharedInstance.branchUniversalObject.locallyIndex = true - CommonMethod.sharedInstance.branchUniversalObject.contentMetadata.customMetadata["key1"] = txtFldDeskTopUrl.text! - CommonMethod.sharedInstance.linkProperties.channel = txtFldCChannel.text! - CommonMethod.sharedInstance.linkProperties.feature = txtFldFeature.text! - CommonMethod.sharedInstance.linkProperties.campaign = txtFldChampaignName.text! - CommonMethod.sharedInstance.linkProperties.stage = txtFldStage.text! - CommonMethod.sharedInstance.linkProperties.addControlParam("$desktop_url", withValue: txtFldDeskTopUrl.text!) - CommonMethod.sharedInstance.linkProperties.addControlParam("custom_data", withValue: "yes") - CommonMethod.sharedInstance.branchUniversalObject.getShortUrl(with:CommonMethod.sharedInstance.linkProperties, andCallback: { (optUrl: String?, error: Error?) in - if error == nil, let url = optUrl { - NSLog("got my Branch link to share: %@", url) - Utils.shared.setLogFile("NavigateContent") - DispatchQueue.main.async { - UserDefaults.standard.set(true, forKey: "isCreatedDeepLink") - UserDefaults.standard.set(url, forKey: "link") - self.navigationController?.popToRootViewController(animated: true) - } - } - }) - } -} - -extension NavigateContentVC { - - func uiSetUp() { - let submitBtn = UIButton(frame: CGRect(x: self.view.frame.width/2-60, y: txtFldAdditionalData.frame.maxY+30, width: 120, height: 55)) - submitBtn.setTitle("Submit", for: .normal) - submitBtn.backgroundColor = UIColor(red: 89.0/255.0, green: 12.0/255.0, blue: 228.0/255.0, alpha: 1.0) - submitBtn.layer.cornerRadius = 8 - submitBtn.setTitleColor(UIColor.white, for: .normal) - submitBtn.titleLabel?.font = UIFont.boldSystemFont(ofSize: 22.0) - submitBtn.addTarget(self, action: #selector(self.submitAction), for: .touchUpInside) - scrollViewMain.addSubview(submitBtn) - txtFldCChannel.setLeftPaddingPoints(10) - txtFldFeature.setLeftPaddingPoints(10) - txtFldChampaignName.setLeftPaddingPoints(10) - txtFldStage.setLeftPaddingPoints(10) - txtFldDeskTopUrl.setLeftPaddingPoints(10) - txtFldAdditionalData.setLeftPaddingPoints(10) - txtFldCChannel.attributedPlaceholder = NSAttributedString( - string: "Channel name like Facebook", - attributes: [NSAttributedString.Key.foregroundColor: UIColor.darkGray] - ) - txtFldFeature.attributedPlaceholder = NSAttributedString( - string: "Feature eg: Sharing", - attributes: [NSAttributedString.Key.foregroundColor: UIColor.darkGray] - ) - txtFldChampaignName.attributedPlaceholder = NSAttributedString( - string: "Champaign name", - attributes: [NSAttributedString.Key.foregroundColor: UIColor.darkGray] - ) - txtFldStage.attributedPlaceholder = NSAttributedString( - string: "Stage", - attributes: [NSAttributedString.Key.foregroundColor: UIColor.darkGray] - ) - txtFldDeskTopUrl.attributedPlaceholder = NSAttributedString( - string: "Desktop URL", - attributes: [NSAttributedString.Key.foregroundColor: UIColor.darkGray] - ) - txtFldAdditionalData.attributedPlaceholder = NSAttributedString( - string: "Additional Data", - attributes: [NSAttributedString.Key.foregroundColor: UIColor.darkGray] - ) - } -} diff --git a/DeepLinkDemo/DeepLinkDemo/Controllers/ParentViewController.swift b/DeepLinkDemo/DeepLinkDemo/Controllers/ParentViewController.swift deleted file mode 100644 index 241dd72e9..000000000 --- a/DeepLinkDemo/DeepLinkDemo/Controllers/ParentViewController.swift +++ /dev/null @@ -1,39 +0,0 @@ -// ParentViewController.swift -// DeepLinkDemo -// Created by Apple on 17/05/22. - -import UIKit -class ParentViewController: UIViewController { - private var reachability:Reachability? - - override func viewDidLoad() { - super.viewDidLoad() - reachabilityCheck() - } - - override var preferredStatusBarStyle: UIStatusBarStyle { - return .lightContent - } - - - func reachabilityCheck() { - reachability = Reachability()! - reachability!.whenReachable = { reachability in - } - reachability?.whenUnreachable = { reachability in - DispatchQueue.main.asyncAfter(deadline: .now() + 1.5) { - self.networkError() - } - } - do { - try reachability?.startNotifier() - } catch { - NSLog("Unable to start notifier") - } - } - - func networkError() { - CommonAlert.shared.showActionAlertView(title: "Failure", message: "Your internet/network connection appears to be offline. Please check your internet/network connection.", actions: [], preferredStyle: .alert, viewController: self) - } - -} diff --git a/DeepLinkDemo/DeepLinkDemo/Controllers/ReadDeeplinkingVC.swift b/DeepLinkDemo/DeepLinkDemo/Controllers/ReadDeeplinkingVC.swift deleted file mode 100644 index 6d72dfa49..000000000 --- a/DeepLinkDemo/DeepLinkDemo/Controllers/ReadDeeplinkingVC.swift +++ /dev/null @@ -1,108 +0,0 @@ -// -// ReadDeeplinkingVC.swift -// DeepLinkDemo -// -// Created by Rakesh kumar on 4/19/22. - -import UIKit -import Branch - -class ReadDeeplinkingVC: ParentViewController { - @IBOutlet weak var txtFldCChannel: UITextField! - @IBOutlet weak var txtFldFeature: UITextField! - @IBOutlet weak var txtFldChampaignName: UITextField! - @IBOutlet weak var txtFldStage: UITextField! - @IBOutlet weak var txtFldDeskTopUrl: UITextField! - @IBOutlet weak var txtFldAdditionalData: UITextField! - @IBOutlet weak var scrollViewMain: UIScrollView! - private var reachability:Reachability? - override func viewDidLoad() { - super.viewDidLoad() - uiSetUp() - reachabilityCheck() - } - - override func viewWillAppear(_ animated: Bool) { - super.viewWillAppear(animated) - Utils.shared.setLogFile("ReadDeeplinking") - } - - - override func viewDidLayoutSubviews() { - super.viewDidLayoutSubviews() - scrollViewMain.contentSize.height = scrollViewMain.subviews.sorted(by: { $0.frame.maxY < $1.frame.maxY }).last?.frame.maxY ?? scrollViewMain.contentSize.height - } - - @IBAction func backAction(_ sender: Any) { - self.navigationController?.popToRootViewController(animated: true) - } - - @objc func submitAction(sender : UIButton) { - self.view.endEditing(true) - - CommonMethod.sharedInstance.branchUniversalObject.publiclyIndex = true - CommonMethod.sharedInstance.branchUniversalObject.locallyIndex = true - CommonMethod.sharedInstance.branchUniversalObject.contentMetadata.customMetadata["key1"] = txtFldDeskTopUrl.text! - - CommonMethod.sharedInstance.linkProperties.channel = txtFldCChannel.text! - CommonMethod.sharedInstance.linkProperties.feature = txtFldFeature.text! - CommonMethod.sharedInstance.linkProperties.campaign = txtFldChampaignName.text! - CommonMethod.sharedInstance.linkProperties.stage = txtFldStage.text! - CommonMethod.sharedInstance.linkProperties.addControlParam("$desktop_url", withValue: txtFldDeskTopUrl.text!) - CommonMethod.sharedInstance.linkProperties.addControlParam("custom_data", withValue: "yes") - CommonMethod.sharedInstance.branchUniversalObject.getShortUrl(with:CommonMethod.sharedInstance.linkProperties, andCallback: { (optUrl: String?, error: Error?) in - if error == nil, let url = optUrl { - NSLog("got my Branch link to share: %@", url) - DispatchQueue.main.async { - UserDefaults.standard.set(true, forKey: "isCreatedDeepLink") - UserDefaults.standard.set(url, forKey: "link") - self.navigationController?.popToRootViewController(animated: true) - } - } - }) - } -} - -extension ReadDeeplinkingVC { - - func uiSetUp() { - let submitBtn = UIButton(frame: CGRect(x: self.view.frame.width/2-60, y: txtFldAdditionalData.frame.maxY+30, width: 120, height: 55)) - submitBtn.setTitle("Submit", for: .normal) - submitBtn.backgroundColor = UIColor(red: 89.0/255.0, green: 12.0/255.0, blue: 228.0/255.0, alpha: 1.0) - submitBtn.layer.cornerRadius = 8 - submitBtn.setTitleColor(UIColor.white, for: .normal) - submitBtn.titleLabel?.font = UIFont.boldSystemFont(ofSize: 22.0) - submitBtn.addTarget(self, action: #selector(self.submitAction), for: .touchUpInside) - scrollViewMain.addSubview(submitBtn) - txtFldCChannel.setLeftPaddingPoints(10) - txtFldFeature.setLeftPaddingPoints(10) - txtFldChampaignName.setLeftPaddingPoints(10) - txtFldStage.setLeftPaddingPoints(10) - txtFldDeskTopUrl.setLeftPaddingPoints(10) - txtFldAdditionalData.setLeftPaddingPoints(10) - txtFldCChannel.attributedPlaceholder = NSAttributedString( - string: "Channel name like Facebook", - attributes: [NSAttributedString.Key.foregroundColor: UIColor.darkGray] - ) - txtFldFeature.attributedPlaceholder = NSAttributedString( - string: "Feature eg: Sharing", - attributes: [NSAttributedString.Key.foregroundColor: UIColor.darkGray] - ) - txtFldChampaignName.attributedPlaceholder = NSAttributedString( - string: "Campaign name", - attributes: [NSAttributedString.Key.foregroundColor: UIColor.darkGray] - ) - txtFldStage.attributedPlaceholder = NSAttributedString( - string: "Stage", - attributes: [NSAttributedString.Key.foregroundColor: UIColor.darkGray] - ) - txtFldDeskTopUrl.attributedPlaceholder = NSAttributedString( - string: "Desktop URL", - attributes: [NSAttributedString.Key.foregroundColor: UIColor.darkGray] - ) - txtFldAdditionalData.attributedPlaceholder = NSAttributedString( - string: "Additional Data", - attributes: [NSAttributedString.Key.foregroundColor: UIColor.darkGray] - ) - } -} diff --git a/DeepLinkDemo/DeepLinkDemo/Controllers/ReadLogViewController.swift b/DeepLinkDemo/DeepLinkDemo/Controllers/ReadLogViewController.swift deleted file mode 100644 index d88749390..000000000 --- a/DeepLinkDemo/DeepLinkDemo/Controllers/ReadLogViewController.swift +++ /dev/null @@ -1,41 +0,0 @@ -// -// ReadLogViewController.swift -// DeepLinkDemo -// -// Created by Apple on 17/05/22. -// - -import UIKit - -class ReadLogViewController: ParentViewController { - - @IBOutlet weak var textViewDescription: UITextView! - - var selectedFileName = "" - - override func viewDidLoad() { - super.viewDidLoad() - - self.textViewDescription.text = loadTextWithFileName(selectedFileName) - reachabilityCheck() - } - - - @IBAction func backAction(_ sender: Any) { - self.navigationController?.popToRootViewController(animated: true) - } - - private func loadTextWithFileName(_ fileName: String) -> String? { - if let dir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first { - let fileURL = dir.appendingPathComponent(fileName) - guard let text = try? String(contentsOf: fileURL, encoding: .utf8) else { - return nil - } - return text - } - return nil - } - -} - - diff --git a/DeepLinkDemo/DeepLinkDemo/Controllers/ReadVC.swift b/DeepLinkDemo/DeepLinkDemo/Controllers/ReadVC.swift deleted file mode 100644 index 08fe32021..000000000 --- a/DeepLinkDemo/DeepLinkDemo/Controllers/ReadVC.swift +++ /dev/null @@ -1,50 +0,0 @@ -// -// ReadVC.swift -// DeepLinkDemo -// -// Created by Rakesh kumar on 4/28/22. -// - -import UIKit -import BranchSDK -class ReadVC: ParentViewController { - - @IBOutlet weak var btnback: UIButton! - @IBOutlet weak var labelTxt: UILabel! - @IBOutlet weak var btnShare: UIButton! - var strTxt = "" - private var reachability:Reachability? - override func viewDidLoad() { - super.viewDidLoad() - labelTxt.text = "Success\nUrl is generated.\nHere is the Short URL\(strTxt)" - btnShare.layer.cornerRadius = 8.0 - let tap = UITapGestureRecognizer(target: self, action: #selector(self.onClicLabel(sender:))) - labelTxt.isUserInteractionEnabled = true - labelTxt.addGestureRecognizer(tap) - reachabilityCheck() - } - - override func viewWillAppear(_ animated: Bool) { - super.viewWillAppear(animated) - } - - - // And that's the function :) - @objc func onClicLabel(sender:UITapGestureRecognizer) { - - UserDefaults.standard.set(true, forKey: "isRead") - let anURL = URL(string: strTxt) - Branch.getInstance().handleDeepLink(anURL) - } - - @IBAction func backAction(_ sender: Any) { - self.navigationController?.popToRootViewController(animated: true) - } - - @IBAction func btnrReadDeeplink(_ sender: Any) { - UserDefaults.standard.set(true, forKey: "isRead") - let anURL = URL(string: strTxt) - Branch.getInstance().handleDeepLink(anURL) - } - -} diff --git a/DeepLinkDemo/DeepLinkDemo/Controllers/ShareDynamicallyVC.swift b/DeepLinkDemo/DeepLinkDemo/Controllers/ShareDynamicallyVC.swift deleted file mode 100644 index cb71f1bed..000000000 --- a/DeepLinkDemo/DeepLinkDemo/Controllers/ShareDynamicallyVC.swift +++ /dev/null @@ -1,10 +0,0 @@ -// -// ShareDynamicallyVC.swift -// DeepLinkDemo -// -// Created by Rakesh kumar on 4/19/22. -// - -import UIKit -class ShareDynamicallyVC: ParentViewController { -} diff --git a/DeepLinkDemo/DeepLinkDemo/Controllers/TextViewController.swift b/DeepLinkDemo/DeepLinkDemo/Controllers/TextViewController.swift deleted file mode 100644 index b55b15c90..000000000 --- a/DeepLinkDemo/DeepLinkDemo/Controllers/TextViewController.swift +++ /dev/null @@ -1,101 +0,0 @@ -// -// TextViewController.swift -// DeepLinkDemo -// -// Created by ajaykumar on 15/06/22. -// - -import Foundation -import UIKit -import CoreSpotlight; -import MobileCoreServices; - -class TextViewController: UIViewController { - - var isShareDeepLink = false - var isNavigateToContent = false - var isDisplayContent = false - var isTrackContent = false - var isTrackContenttoWeb = false - var handleLinkInWebview = false - var isCreateDeepLink = false - var forNotification = false - var isTrackUser = false - var isSetDMAParams = false - var isSendV2Event = false - var isSetAttributionLevel = false - - var url = "" - var responseStatus = "" - var dictData = [String:Any]() - var textViewText = "" - - @IBOutlet weak var statusLabel: UILabel! - - @IBOutlet weak var logDataTextView: UITextView! - - - override func viewDidLoad() { - super.viewDidLoad() - logDataTextView.text = textViewText - statusLabel.text = responseStatus - logDataTextView.isEditable = false - } - - @IBAction func BackButtonAction(_ sender: Any) { - self.navigationController?.popToRootViewController(animated: true) - } - @IBAction func nextButtonAction(_ sender: Any) { - if self.isTrackContent == true { - let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil) - if let vc = storyBoard.instantiateViewController(withIdentifier: "GenerateURLVC") as? GenerateURLVC { - vc.isTrackContent = true - vc.forNotification = false - vc.isCreateDeepLink = false - vc.isShareDeepLink = false - vc.isNavigateToContent = false - vc.dictData = dictData - self.navigationController?.pushViewController(vc, animated: true) - } - } else if self.isTrackUser == true { - self.navigationController?.popToRootViewController(animated: true) - } else if self.forNotification == true { - self.navigationController?.popToRootViewController(animated: true) - } else if self.isTrackContenttoWeb || self.isCreateDeepLink { - launchWebView() - } else if self.isNavigateToContent || self.isDisplayContent || self.handleLinkInWebview { - launchReadVC() - } else if self.isSetDMAParams == true { - self.navigationController?.popToRootViewController(animated: true) - } else if self.isSendV2Event == true { - self.navigationController?.popToRootViewController(animated: true) - } else if self.isSetAttributionLevel == true { - self.navigationController?.popToRootViewController(animated: true) - } - else { - launchReadVC() - } - } - - func launchReadVC(){ - let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil) - if let vc = storyBoard.instantiateViewController(withIdentifier: "ReadVC") as? ReadVC { - vc.strTxt = url - self.navigationController?.pushViewController(vc, animated: true) - } - } - - func launchWebView(){ - //Fixed - let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil) - if let vc = storyBoard.instantiateViewController(withIdentifier: "WebViewVC") as? WebViewVC { - self.navigationController?.pushViewController(vc, animated: true) - } - } - - func updateText(msg: String) -> () { - DispatchQueue.main.async() { - self.logDataTextView?.text = msg - } - } -} diff --git a/DeepLinkDemo/DeepLinkDemo/Controllers/TrackContentVC.swift b/DeepLinkDemo/DeepLinkDemo/Controllers/TrackContentVC.swift deleted file mode 100644 index 9efe7653d..000000000 --- a/DeepLinkDemo/DeepLinkDemo/Controllers/TrackContentVC.swift +++ /dev/null @@ -1,88 +0,0 @@ -// -// TrackContentVC.swift -// DeepLinkDemo -// -// Created by Apple on 12/05/22. -// - -import UIKit -import BranchSDK - -class TrackContentVC: ParentViewController { - - @IBOutlet weak var txtFldOptions: UITextField! - - var pickerView = UIPickerView() - - var trackContenOptions = [String]() - private var reachability:Reachability? - override func viewDidLoad() { - super.viewDidLoad() - - trackContenOptions = ["ADD_TO_CART", "ADD_TO_WISHLIST", "VIEW_CART", "INITIATE_PURCHASE", "ADD_PAYMENT_INFO", "PURCHASE", "SPEND_CREDITS", "SUBSCRIBE", "START_TRIAL", "CLICK_AD", "VIEW_AD", "SEARCH", "VIEW_ITEM", "VIEW_ITEMS", "RATE", "SHARE", "START_TRIAL", "CLICK_AD", "COMPLETE_REGISTRATION", "COMPLETE_TUTORIAL", "ACHIEVE_LEVEL", "UNLOCK_ACHIEVEMENT", "INVITE", "LOGIN", "RESERVE", "OPT_IN", "OPT_OUT"] - - pickerView.dataSource = self - pickerView.delegate = self - - txtFldOptions.inputView = pickerView - let toolBar = UIToolbar(frame: CGRect(x: 0.0, y: 0.0, width: UIScreen.main.bounds.size.width,height: 44.0)) - let flexibleSpace = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil) - let doneButton = UIBarButtonItem(title: "Done", style: .plain, target: target, action: #selector(tapDone)) - let cancelButton = UIBarButtonItem(title: "Cancel", style: .plain, target: target, action: #selector(tapCancel)) - toolBar.setItems([cancelButton, flexibleSpace, doneButton], animated: false) - txtFldOptions.inputAccessoryView = toolBar - - txtFldOptions.text = trackContenOptions.first - reachabilityCheck() - } - - override func viewWillAppear(_ animated: Bool) { - super.viewWillAppear(animated) - } - - - @objc func tapDone() { - let selectedRow = pickerView.selectedRow(inComponent: 0) - if trackContenOptions.indices.contains(selectedRow){ - txtFldOptions.text = trackContenOptions[selectedRow] - } - txtFldOptions.resignFirstResponder() - self.view.endEditing(true) - } - @objc func tapCancel() { - self.view.endEditing(true) - } - - @IBAction func backBtnAction(){ - self.navigationController?.popToRootViewController(animated: true) - } - - @IBAction func nextBtnAction(){ - let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil) - if let vc = storyBoard.instantiateViewController(withIdentifier: "CreateObjectReferenceObject") as? CreateObjectReferenceObject { - vc.screenMode = 7 - vc.txtFldValue = String(txtFldOptions.text ?? "") - self.navigationController?.pushViewController(vc, animated: true) - } - } - -} - -extension TrackContentVC: UIPickerViewDataSource, UIPickerViewDelegate{ - - func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int { - return trackContenOptions.count - } - - func numberOfComponents(in pickerView: UIPickerView) -> Int { - return 1 - } - - func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? { - return trackContenOptions[row] - } - - func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) { - txtFldOptions.text = trackContenOptions[row] - } -} diff --git a/DeepLinkDemo/DeepLinkDemo/Controllers/ViewController.swift b/DeepLinkDemo/DeepLinkDemo/Controllers/ViewController.swift deleted file mode 100644 index 359d647da..000000000 --- a/DeepLinkDemo/DeepLinkDemo/Controllers/ViewController.swift +++ /dev/null @@ -1,20 +0,0 @@ -// ViewController.swift -// DeepLinkDemo -// Created by Apple on 17/05/22 -import UIKit - -class ViewController: ParentViewController { - - override func viewDidLoad() { - super.viewDidLoad() - super.reachabilityCheck() - } - - - - override var preferredStatusBarStyle: UIStatusBarStyle { - return .lightContent - } - - -} diff --git a/DeepLinkDemo/DeepLinkDemo/Controllers/WebViewVC.swift b/DeepLinkDemo/DeepLinkDemo/Controllers/WebViewVC.swift deleted file mode 100644 index b244ac66a..000000000 --- a/DeepLinkDemo/DeepLinkDemo/Controllers/WebViewVC.swift +++ /dev/null @@ -1,59 +0,0 @@ -// -// WebViewVC.swift -// DeepLinkDemo -// -// Created by Rakesh kumar on 4/22/22. -// - -import UIKit -import WebKit -import SafariServices - -class WebViewVC: ParentViewController, WKNavigationDelegate { - - @IBOutlet weak var webViewContainer: UIView! - - var webViewDetail: WKWebView = WKWebView() - private var reachability:Reachability? - - override func viewDidLoad() { - super.viewDidLoad() - - loadWKWebview() - reachabilityCheck() - } - - override func viewWillAppear(_ animated: Bool) { - super.viewWillAppear(animated) - Utils.shared.setLogFile("HandleLinksInapp") - } - - fileprivate func loadWKWebview(){ - let webConfiguration = WKWebViewConfiguration() - let customFrame = CGRect.init(origin: CGPoint.zero, size: CGSize.init(width: self.webViewContainer.frame.size.width, height: self.webViewContainer.frame.size.height)) - self.webViewDetail = WKWebView (frame: customFrame , configuration: webConfiguration) - webViewDetail.translatesAutoresizingMaskIntoConstraints = false - self.webViewContainer.addSubview(webViewDetail) - self.view.addConstraint(NSLayoutConstraint(item: webViewDetail, attribute: .trailing, relatedBy: .equal, toItem: self.webViewContainer, attribute: .trailing, multiplier: 1, constant: 0)) - self.view.addConstraint(NSLayoutConstraint(item: webViewDetail, attribute: .leading, relatedBy: .equal, toItem: self.webViewContainer, attribute: .leading, multiplier: 1, constant: 0)) - self.view.addConstraint(NSLayoutConstraint(item: webViewDetail, attribute: .top, relatedBy: .equal, toItem: self.webViewContainer, attribute: .top, multiplier: 1, constant: 0)) - self.view.addConstraint(NSLayoutConstraint(item: webViewDetail, attribute: .bottom, relatedBy: .equal, toItem: self.webViewContainer, attribute: .bottom, multiplier: 1, constant: 0)) - - webViewDetail.navigationDelegate = self - if let deeplinkurl: String = UserDefaults.standard.string(forKey: "link"){ - webViewDetail.load(URLRequest(url: URL(string: deeplinkurl)!)) - } - } - - @IBAction func backBtnTapped(){ - self.navigationController?.popToRootViewController(animated: true) - } - -} - -extension WebViewVC: SFSafariViewControllerDelegate{ - func safariViewControllerDidFinish(_ controller: SFSafariViewController) { - self.dismiss(animated: true) - self.navigationController?.popViewController(animated: true) - } -} diff --git a/DeepLinkDemo/DeepLinkDemo/DeepLinkDemo-Bridging-Header.h b/DeepLinkDemo/DeepLinkDemo/DeepLinkDemo-Bridging-Header.h deleted file mode 100644 index 28c03fdc2..000000000 --- a/DeepLinkDemo/DeepLinkDemo/DeepLinkDemo-Bridging-Header.h +++ /dev/null @@ -1,12 +0,0 @@ -// -// DeepLinkDemo-Bridging-Header.h -// DeepLinkDemo -// -// Created by Rakesh kumar on 4/18/22. -// - -#ifndef DeepLinkDemo_Bridging_Header_h -#define DeepLinkDemo_Bridging_Header_h -#import "SIAlertView.h" - -#endif /* DeepLinkDemo_Bridging_Header_h */ diff --git a/DeepLinkDemo/DeepLinkDemo/Header.h b/DeepLinkDemo/DeepLinkDemo/Header.h deleted file mode 100644 index d3e5fefff..000000000 --- a/DeepLinkDemo/DeepLinkDemo/Header.h +++ /dev/null @@ -1,12 +0,0 @@ -// -// Header.h -// DeepLinkDemo -// -// Created by Rakesh kumar on 4/18/22. -// - -#ifndef Header_h -#define Header_h -#import "SIAlertView.h" - -#endif /* Header_h */ diff --git a/DeepLinkDemo/DeepLinkDemo/Info.plist b/DeepLinkDemo/DeepLinkDemo/Info.plist deleted file mode 100644 index 6ce93adf7..000000000 --- a/DeepLinkDemo/DeepLinkDemo/Info.plist +++ /dev/null @@ -1,54 +0,0 @@ - - - - - CFBundleSignature - ???? - CFBundleURLTypes - - - CFBundleURLSchemes - - Timber - - - - NSAppTransportSecurity - - NSAllowsArbitraryLoads - - - UIBackgroundModes - - fetch - processing - remote-notification - - UIStatusBarStyle - UIStatusBarStyleLightContent - adjust_app_token - x66ziay2jtvk - amplitude_api_key - 3dc11880800fe99b829ca66886abf9e5 - appboy_api_key - d781dccf-9f96-46a8-878a-a1bef7bb6968 - appmetrica_api_key - 4805cb1a-2e2c-4a03-af63-4c712939817b - appsflyer_api_key - 84qHoE3ZXh7SetmHU6boi5 - branch_key - - live - key_live_nf8w3l1WBpzWdlC00KsLNdmbuEccK6Yr - test - key_test_om2EWe1WBeBYmpz9Z1mdpopouDmoN72T - - branch_universal_link_domains - - timber.app.link - timber-alternate.app.link - timber.test.app.link - timber-alternate.test.app.link - - - diff --git a/DeepLinkDemo/DeepLinkDemo/NSURLSessionBranch.h b/DeepLinkDemo/DeepLinkDemo/NSURLSessionBranch.h deleted file mode 100644 index 125b19377..000000000 --- a/DeepLinkDemo/DeepLinkDemo/NSURLSessionBranch.h +++ /dev/null @@ -1,16 +0,0 @@ -// -// NSURLSession+Branch.h -// -// Created by Ernest Cho on 10/11/18. -// Copyright © 2018 Branch Metrics, Inc. All rights reserved. -// - -#import - -NS_ASSUME_NONNULL_BEGIN - -@interface NSURLSession (Branch) - -@end - -NS_ASSUME_NONNULL_END diff --git a/DeepLinkDemo/DeepLinkDemo/NSURLSessionBranch.m b/DeepLinkDemo/DeepLinkDemo/NSURLSessionBranch.m deleted file mode 100644 index 379c8e752..000000000 --- a/DeepLinkDemo/DeepLinkDemo/NSURLSessionBranch.m +++ /dev/null @@ -1,94 +0,0 @@ -// -// NSURLSession+Branch.m -// -// Created by Ernest Cho on 10/11/18. -// Copyright © 2018 Branch Metrics, Inc. All rights reserved. -// - -#import "NSURLSessionBranch.h" -#import -#import "BranchLogger.h" - -@implementation NSURLSession (Branch) - -+ (void)load { - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - [self swizzleSelector:@selector(dataTaskWithRequest:completionHandler:) - withSelector:@selector(xxx_dataTaskWithRequest:completionHandler:)]; - }); -} - -// swaps originalSelector with swizzledSelector -+ (void)swizzleSelector:(SEL)originalSelector withSelector:(SEL)swizzledSelector { - Class class = [self class]; - - Method originalMethod = class_getInstanceMethod(class, originalSelector); - Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector); - - method_exchangeImplementations(originalMethod, swizzledMethod); -} - -- (void)logNetworkTrafficRequest:(NSURLRequest *)request data:(NSData *)data response:(NSURLResponse *)response { - [[BranchLogger shared] logDebug: @"BranchSDK API LOG START OF FILE" error:nil]; - - [[BranchLogger shared] logDebug:(@"[LogEntryStart]\n\n") error:nil]; - [[BranchLogger shared] logDebug:(@"---------------------------------------------------------------------BranchSDK LOG START ---------------------------------------------------------------------" ) error:nil]; - [[BranchLogger shared] logDebug:(@"[LogEntryStart]\n\n") error:nil]; - [[BranchLogger shared] logDebug:([NSString stringWithFormat: @"BranchSDK Request log: %@", request]) error:nil]; - - NSData *body = [request HTTPBody]; - if (body) { - [[BranchLogger shared] logDebug:(@"[LogEntryStart]\n\n") error:nil]; - [[BranchLogger shared] logDebug:[NSString stringWithFormat:@"BranchSDK Request Body: %@", [NSString stringWithUTF8String:body.bytes]] error:nil]; - } - - [[BranchLogger shared] logDebug:(@"[LogEntryStart]\n\n") error:nil]; - [[BranchLogger shared] logDebug:[NSString stringWithFormat:@"BranchSDK Response: %@", response] error:nil]; - - if (data.bytes) { - [[BranchLogger shared] logDebug:(@"\n\n") error:nil]; - [[BranchLogger shared] logDebug:[NSString stringWithFormat:@"BranchSDK Response Data: %@", [NSString stringWithUTF8String:data.bytes]] error:nil]; - } - [[BranchLogger shared] logDebug:(@"[LogEntryStart]\n\n") error:nil]; - [[BranchLogger shared] logDebug:(@"---------------------------------------------------------------------BranchSDK LOG END ---------------------------------------------------------------------" ) error:nil]; - [[BranchLogger shared] logDebug:(@"[LogEntryStart]\n\n") error:nil]; - [[BranchLogger shared] logDebug:(@"BranchSDK API LOG END OF FILE") error:nil]; - -} - -// replacement method for dataTaskWithRequest -- (NSURLSessionDataTask *)xxx_dataTaskWithRequest:(NSURLRequest *)request - completionHandler:(void (^)(NSData *data, NSURLResponse *response, NSError *error))completionHandler { - - // create a new block that just calls the original block after logging the request - void (^completionHandlerWithLogging)(NSData *, NSURLResponse *, NSError *) = ^(NSData *data, NSURLResponse *response, NSError *error) { - if (completionHandler) { - - [self logNetworkTrafficRequest:request data:data response:response]; - completionHandler(data, response, error); - } - }; - - return [self xxx_dataTaskWithRequest:request completionHandler:completionHandlerWithLogging]; -} - -- (NSData *)dataFromJSONFileNamed:(NSString *)fileName { - // If this class is part of the Test target, [self class] returns the Test Bundle - // NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:fileName ofType:@"json"]; - - NSString *path = [[NSBundle mainBundle] pathForResource:fileName ofType:@"json"]; - NSString *jsonString = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:NULL]; - return [jsonString dataUsingEncoding:NSUTF8StringEncoding]; -} - -- (NSDictionary *)dictionaryFromJSONFileNamed:(NSString *)fileName { - NSData *jsonData = [self dataFromJSONFileNamed:fileName]; - id dict = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:nil]; - if ([dict isKindOfClass:NSDictionary.class]) { - return dict; - } - return nil; -} - -@end diff --git a/DeepLinkDemo/DeepLinkDemo/Reachability/Reachability.h b/DeepLinkDemo/DeepLinkDemo/Reachability/Reachability.h deleted file mode 100644 index ad32df88d..000000000 --- a/DeepLinkDemo/DeepLinkDemo/Reachability/Reachability.h +++ /dev/null @@ -1,19 +0,0 @@ -// -// Reachability.h -// Reachability -// -// Created by Yuki Nagai on 11/2/15. -// Copyright © 2015 Ashley Mills. All rights reserved. -// - -#import - -//! Project version number for Reachability. -FOUNDATION_EXPORT double ReachabilityVersionNumber; - -//! Project version string for Reachability. -FOUNDATION_EXPORT const unsigned char ReachabilityVersionString[]; - -// In this header, you should import all the public headers of your framework using statements like #import - - diff --git a/DeepLinkDemo/DeepLinkDemo/Reachability/Reachability.swift b/DeepLinkDemo/DeepLinkDemo/Reachability/Reachability.swift deleted file mode 100644 index 9f5f4d7ae..000000000 --- a/DeepLinkDemo/DeepLinkDemo/Reachability/Reachability.swift +++ /dev/null @@ -1,270 +0,0 @@ -/* - Copyright (c) 2014, Ashley Mills - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. - */ - -import SystemConfiguration -import Foundation - -public enum ReachabilityError: Error { - case FailedToCreateWithAddress(sockaddr_in) - case FailedToCreateWithHostname(String) - case UnableToSetCallback - case UnableToSetDispatchQueue -} - -public let ReachabilityChangedNotification = NSNotification.Name("ReachabilityChangedNotification") - -func callback(reachability:SCNetworkReachability, flags: SCNetworkReachabilityFlags, info: UnsafeMutableRawPointer?) { - - guard let info = info else { return } - - let reachability = Unmanaged.fromOpaque(info).takeUnretainedValue() - - DispatchQueue.main.async { - reachability.reachabilityChanged() - } -} - -public class Reachability { - - public typealias NetworkReachable = (Reachability) -> () - public typealias NetworkUnreachable = (Reachability) -> () - - public enum NetworkStatus: CustomStringConvertible { - - case notReachable, reachableViaWiFi, reachableViaWWAN - - public var description: String { - switch self { - case .reachableViaWWAN: return "Cellular" - case .reachableViaWiFi: return "WiFi" - case .notReachable: return "No Connection" - } - } - } - - public var whenReachable: NetworkReachable? - public var whenUnreachable: NetworkUnreachable? - public var reachableOnWWAN: Bool - - // The notification center on which "reachability changed" events are being posted - public var notificationCenter: NotificationCenter = NotificationCenter.default - public var currentReachabilityString: String { - return "\(currentReachabilityStatus)" - } - - public var currentReachabilityStatus: NetworkStatus { - guard isReachable else { return .notReachable } - if isReachableViaWiFi { - return .reachableViaWiFi - } - if isRunningOnDevice { - return .reachableViaWWAN - } - return .notReachable - } - - fileprivate var previousFlags: SCNetworkReachabilityFlags? - fileprivate var isRunningOnDevice: Bool = { - #if (arch(i386) || arch(x86_64)) && os(iOS) - return false - #else - return true - #endif - }() - fileprivate var notifierRunning = false - fileprivate var reachabilityRef: SCNetworkReachability? - fileprivate let reachabilitySerialQueue = DispatchQueue(label: "uk.co.ashleymills.reachability") - required public init(reachabilityRef: SCNetworkReachability) { - reachableOnWWAN = true - self.reachabilityRef = reachabilityRef - } - - public convenience init?(hostname: String) { - guard let ref = SCNetworkReachabilityCreateWithName(nil, hostname) else { return nil } - self.init(reachabilityRef: ref) - } - - public convenience init?() { - var zeroAddress = sockaddr() - zeroAddress.sa_len = UInt8(MemoryLayout.size) - zeroAddress.sa_family = sa_family_t(AF_INET) - guard let ref: SCNetworkReachability = withUnsafePointer(to: &zeroAddress, { - SCNetworkReachabilityCreateWithAddress(nil, UnsafePointer($0)) - }) else { return nil } - self.init(reachabilityRef: ref) - } - - deinit { - stopNotifier() - reachabilityRef = nil - whenReachable = nil - whenUnreachable = nil - } -} - -public extension Reachability { - - // MARK: - *** Notifier methods *** - func startNotifier() throws { - guard let reachabilityRef = reachabilityRef, !notifierRunning else { return } - var context = SCNetworkReachabilityContext(version: 0, info: nil, retain: nil, release: nil, copyDescription: nil) - context.info = UnsafeMutableRawPointer(Unmanaged.passUnretained(self).toOpaque()) - if !SCNetworkReachabilitySetCallback(reachabilityRef, callback, &context) { - stopNotifier() - throw ReachabilityError.UnableToSetCallback - } - if !SCNetworkReachabilitySetDispatchQueue(reachabilityRef, reachabilitySerialQueue) { - stopNotifier() - throw ReachabilityError.UnableToSetDispatchQueue - } - // Perform an intial check - reachabilitySerialQueue.async { - self.reachabilityChanged() - } - notifierRunning = true - } - - func stopNotifier() { - defer { notifierRunning = false } - guard let reachabilityRef = reachabilityRef else { return } - SCNetworkReachabilitySetCallback(reachabilityRef, nil, nil) - SCNetworkReachabilitySetDispatchQueue(reachabilityRef, nil) - } - - // MARK: - *** Connection test methods *** - var isReachable: Bool { - - guard isReachableFlagSet else { return false } - - if isConnectionRequiredAndTransientFlagSet { - return false - } - if isRunningOnDevice { - if isOnWWANFlagSet && !reachableOnWWAN { - // We don't want to connect when on 3G. - return false - } - } - return true - } - - var isReachableViaWWAN: Bool { - // Check we're not on the simulator, we're REACHABLE and check we're on WWAN - return isRunningOnDevice && isReachableFlagSet && isOnWWANFlagSet - } - - var isReachableViaWiFi: Bool { - // Check we're reachable - guard isReachableFlagSet else { return false } - // If reachable we're reachable, but not on an iOS device (i.e. simulator), we must be on WiFi - guard isRunningOnDevice else { return true } - // Check we're NOT on WWAN - return !isOnWWANFlagSet - } - - var description: String { - - let W = isRunningOnDevice ? (isOnWWANFlagSet ? "W" : "-") : "X" - let R = isReachableFlagSet ? "R" : "-" - let c = isConnectionRequiredFlagSet ? "c" : "-" - let t = isTransientConnectionFlagSet ? "t" : "-" - let i = isInterventionRequiredFlagSet ? "i" : "-" - let C = isConnectionOnTrafficFlagSet ? "C" : "-" - let D = isConnectionOnDemandFlagSet ? "D" : "-" - let l = isLocalAddressFlagSet ? "l" : "-" - let d = isDirectFlagSet ? "d" : "-" - return "\(W)\(R) \(c)\(t)\(i)\(C)\(D)\(l)\(d)" - } -} - -fileprivate extension Reachability { - - func reachabilityChanged() { - let flags = reachabilityFlags - guard previousFlags != flags else { return } - let block = isReachable ? whenReachable : whenUnreachable - block?(self) - if ReachabilityChangedNotification.rawValue != "" { - self.notificationCenter.post(name: ReachabilityChangedNotification, object:self) - } - previousFlags = flags - } - - var isOnWWANFlagSet: Bool { - #if os(iOS) - return reachabilityFlags.contains(.isWWAN) - #else - return false - #endif - } - var isReachableFlagSet: Bool { - return reachabilityFlags.contains(.reachable) - } - var isConnectionRequiredFlagSet: Bool { - return reachabilityFlags.contains(.connectionRequired) - } - var isInterventionRequiredFlagSet: Bool { - return reachabilityFlags.contains(.interventionRequired) - } - var isConnectionOnTrafficFlagSet: Bool { - return reachabilityFlags.contains(.connectionOnTraffic) - } - var isConnectionOnDemandFlagSet: Bool { - return reachabilityFlags.contains(.connectionOnDemand) - } - var isConnectionOnTrafficOrDemandFlagSet: Bool { - return !reachabilityFlags.intersection([.connectionOnTraffic, .connectionOnDemand]).isEmpty - } - var isTransientConnectionFlagSet: Bool { - return reachabilityFlags.contains(.transientConnection) - } - var isLocalAddressFlagSet: Bool { - return reachabilityFlags.contains(.isLocalAddress) - } - var isDirectFlagSet: Bool { - return reachabilityFlags.contains(.isDirect) - } - var isConnectionRequiredAndTransientFlagSet: Bool { - return reachabilityFlags.intersection([.connectionRequired, .transientConnection]) == [.connectionRequired, .transientConnection] - } - - var reachabilityFlags: SCNetworkReachabilityFlags { - - guard let reachabilityRef = reachabilityRef else { return SCNetworkReachabilityFlags() } - - var flags = SCNetworkReachabilityFlags() - let gotFlags = withUnsafeMutablePointer(to: &flags) { - SCNetworkReachabilityGetFlags(reachabilityRef, UnsafeMutablePointer($0)) - } - - if gotFlags { - return flags - } else { - return SCNetworkReachabilityFlags() - } - } -} diff --git a/DeepLinkDemo/DeepLinkDemo/SIAlertView/SIAlertView.bundle/button-cancel-d.png b/DeepLinkDemo/DeepLinkDemo/SIAlertView/SIAlertView.bundle/button-cancel-d.png deleted file mode 100644 index fa432a55d..000000000 Binary files a/DeepLinkDemo/DeepLinkDemo/SIAlertView/SIAlertView.bundle/button-cancel-d.png and /dev/null differ diff --git a/DeepLinkDemo/DeepLinkDemo/SIAlertView/SIAlertView.bundle/button-cancel-d@2x.png b/DeepLinkDemo/DeepLinkDemo/SIAlertView/SIAlertView.bundle/button-cancel-d@2x.png deleted file mode 100644 index 8f359b8a5..000000000 Binary files a/DeepLinkDemo/DeepLinkDemo/SIAlertView/SIAlertView.bundle/button-cancel-d@2x.png and /dev/null differ diff --git a/DeepLinkDemo/DeepLinkDemo/SIAlertView/SIAlertView.bundle/button-cancel.png b/DeepLinkDemo/DeepLinkDemo/SIAlertView/SIAlertView.bundle/button-cancel.png deleted file mode 100644 index 88d1564f9..000000000 Binary files a/DeepLinkDemo/DeepLinkDemo/SIAlertView/SIAlertView.bundle/button-cancel.png and /dev/null differ diff --git a/DeepLinkDemo/DeepLinkDemo/SIAlertView/SIAlertView.bundle/button-cancel@2x.png b/DeepLinkDemo/DeepLinkDemo/SIAlertView/SIAlertView.bundle/button-cancel@2x.png deleted file mode 100644 index 0ac483b72..000000000 Binary files a/DeepLinkDemo/DeepLinkDemo/SIAlertView/SIAlertView.bundle/button-cancel@2x.png and /dev/null differ diff --git a/DeepLinkDemo/DeepLinkDemo/SIAlertView/SIAlertView.bundle/button-default-d.png b/DeepLinkDemo/DeepLinkDemo/SIAlertView/SIAlertView.bundle/button-default-d.png deleted file mode 100644 index 47f5163cc..000000000 Binary files a/DeepLinkDemo/DeepLinkDemo/SIAlertView/SIAlertView.bundle/button-default-d.png and /dev/null differ diff --git a/DeepLinkDemo/DeepLinkDemo/SIAlertView/SIAlertView.bundle/button-default-d@2x.png b/DeepLinkDemo/DeepLinkDemo/SIAlertView/SIAlertView.bundle/button-default-d@2x.png deleted file mode 100644 index 6d21603e1..000000000 Binary files a/DeepLinkDemo/DeepLinkDemo/SIAlertView/SIAlertView.bundle/button-default-d@2x.png and /dev/null differ diff --git a/DeepLinkDemo/DeepLinkDemo/SIAlertView/SIAlertView.bundle/button-default.png b/DeepLinkDemo/DeepLinkDemo/SIAlertView/SIAlertView.bundle/button-default.png deleted file mode 100644 index 17eab5920..000000000 Binary files a/DeepLinkDemo/DeepLinkDemo/SIAlertView/SIAlertView.bundle/button-default.png and /dev/null differ diff --git a/DeepLinkDemo/DeepLinkDemo/SIAlertView/SIAlertView.bundle/button-default@2x.png b/DeepLinkDemo/DeepLinkDemo/SIAlertView/SIAlertView.bundle/button-default@2x.png deleted file mode 100644 index d5f08e6c0..000000000 Binary files a/DeepLinkDemo/DeepLinkDemo/SIAlertView/SIAlertView.bundle/button-default@2x.png and /dev/null differ diff --git a/DeepLinkDemo/DeepLinkDemo/SIAlertView/SIAlertView.bundle/button-destructive-d.png b/DeepLinkDemo/DeepLinkDemo/SIAlertView/SIAlertView.bundle/button-destructive-d.png deleted file mode 100644 index 0a531501e..000000000 Binary files a/DeepLinkDemo/DeepLinkDemo/SIAlertView/SIAlertView.bundle/button-destructive-d.png and /dev/null differ diff --git a/DeepLinkDemo/DeepLinkDemo/SIAlertView/SIAlertView.bundle/button-destructive-d@2x.png b/DeepLinkDemo/DeepLinkDemo/SIAlertView/SIAlertView.bundle/button-destructive-d@2x.png deleted file mode 100644 index e614fafec..000000000 Binary files a/DeepLinkDemo/DeepLinkDemo/SIAlertView/SIAlertView.bundle/button-destructive-d@2x.png and /dev/null differ diff --git a/DeepLinkDemo/DeepLinkDemo/SIAlertView/SIAlertView.bundle/button-destructive.png b/DeepLinkDemo/DeepLinkDemo/SIAlertView/SIAlertView.bundle/button-destructive.png deleted file mode 100644 index 28f3264e5..000000000 Binary files a/DeepLinkDemo/DeepLinkDemo/SIAlertView/SIAlertView.bundle/button-destructive.png and /dev/null differ diff --git a/DeepLinkDemo/DeepLinkDemo/SIAlertView/SIAlertView.bundle/button-destructive@2x.png b/DeepLinkDemo/DeepLinkDemo/SIAlertView/SIAlertView.bundle/button-destructive@2x.png deleted file mode 100644 index 1a82328a0..000000000 Binary files a/DeepLinkDemo/DeepLinkDemo/SIAlertView/SIAlertView.bundle/button-destructive@2x.png and /dev/null differ diff --git a/DeepLinkDemo/DeepLinkDemo/SIAlertView/SIAlertView.h b/DeepLinkDemo/DeepLinkDemo/SIAlertView/SIAlertView.h deleted file mode 100644 index 49eaae22f..000000000 --- a/DeepLinkDemo/DeepLinkDemo/SIAlertView/SIAlertView.h +++ /dev/null @@ -1,69 +0,0 @@ -// SIAlertView.h -// SIAlertView -// Created by Kevin Cao on 13-4-29. -// Copyright (c) 2013年 Sumi Interactive. All rights reserved. - -#import -extern NSString *const SIAlertViewWillShowNotification; -extern NSString *const SIAlertViewDidShowNotification; -extern NSString *const SIAlertViewWillDismissNotification; -extern NSString *const SIAlertViewDidDismissNotification; -typedef NS_ENUM(NSInteger, SIAlertViewButtonType) { - SIAlertViewButtonTypeDefault = 0, - SIAlertViewButtonTypeDestructive, - SIAlertViewButtonTypeCancel -}; -typedef NS_ENUM(NSInteger, SIAlertViewBackgroundStyle) { - SIAlertViewBackgroundStyleGradient = 0, - SIAlertViewBackgroundStyleSolid, -}; -typedef NS_ENUM(NSInteger, SIAlertViewButtonsListStyle) { - SIAlertViewButtonsListStyleNormal = 0, - SIAlertViewButtonsListStyleRows -}; -typedef NS_ENUM(NSInteger, SIAlertViewTransitionStyle) { - SIAlertViewTransitionStyleSlideFromBottom = 0, - SIAlertViewTransitionStyleSlideFromTop, - SIAlertViewTransitionStyleFade, - SIAlertViewTransitionStyleBounce, - SIAlertViewTransitionStyleDropDown -}; -@class SIAlertView; -typedef void(^SIAlertViewHandler)(SIAlertView *alertView); -@interface SIAlertView : UIView -@property (nonatomic, copy) NSString *title; -@property (nonatomic, copy) NSString *message; -@property (nonatomic, assign) SIAlertViewTransitionStyle transitionStyle; // default is SIAlertViewTransitionStyleSlideFromBottom -@property (nonatomic, assign) SIAlertViewBackgroundStyle backgroundStyle; // default is SIAlertViewBackgroundStyleGradient -@property (nonatomic, assign) SIAlertViewButtonsListStyle buttonsListStyle; // default is SIAlertViewButtonsListStyleNormal -@property (nonatomic, copy) SIAlertViewHandler willShowHandler; -@property (nonatomic, copy) SIAlertViewHandler didShowHandler; -@property (nonatomic, copy) SIAlertViewHandler willDismissHandler; -@property (nonatomic, copy) SIAlertViewHandler didDismissHandler; -@property (nonatomic, readonly, getter = isVisible) BOOL visible; -@property (nonatomic, readonly, getter = isParallaxEffectEnabled) BOOL enabledParallaxEffect; -@property (nonatomic, strong) UIColor *viewBackgroundColor NS_AVAILABLE_IOS(5_0) UI_APPEARANCE_SELECTOR; -@property (nonatomic, strong) UIColor *titleColor NS_AVAILABLE_IOS(5_0) UI_APPEARANCE_SELECTOR; -@property (nonatomic, strong) UIColor *messageColor NS_AVAILABLE_IOS(5_0) UI_APPEARANCE_SELECTOR; -@property (nonatomic, strong) UIFont *titleFont NS_AVAILABLE_IOS(5_0) UI_APPEARANCE_SELECTOR; -@property (nonatomic, strong) UIFont *messageFont NS_AVAILABLE_IOS(5_0) UI_APPEARANCE_SELECTOR; -@property (nonatomic, strong) UIFont *buttonFont NS_AVAILABLE_IOS(5_0) UI_APPEARANCE_SELECTOR; -@property (nonatomic, strong) UIColor *buttonColor NS_AVAILABLE_IOS(5_0) UI_APPEARANCE_SELECTOR; -@property (nonatomic, strong) UIColor *cancelButtonColor NS_AVAILABLE_IOS(5_0) UI_APPEARANCE_SELECTOR; -@property (nonatomic, strong) UIColor *destructiveButtonColor NS_AVAILABLE_IOS(5_0) UI_APPEARANCE_SELECTOR; -@property (nonatomic, assign) CGFloat cornerRadius NS_AVAILABLE_IOS(5_0) UI_APPEARANCE_SELECTOR; // default is 2.0 -@property (nonatomic, assign) CGFloat shadowRadius NS_AVAILABLE_IOS(5_0) UI_APPEARANCE_SELECTOR; // default is 8.0 - -@property (nonatomic) BOOL shouldRemoveAfterTouch; - -- (void)setDefaultButtonImage:(UIImage *)defaultButtonImage forState:(UIControlState)state NS_AVAILABLE_IOS(5_0) UI_APPEARANCE_SELECTOR; -- (void)setCancelButtonImage:(UIImage *)cancelButtonImage forState:(UIControlState)state NS_AVAILABLE_IOS(5_0) UI_APPEARANCE_SELECTOR; -- (void)setDestructiveButtonImage:(UIImage *)destructiveButtonImage forState:(UIControlState)state NS_AVAILABLE_IOS(5_0) UI_APPEARANCE_SELECTOR; - -- (instancetype)initWithTitle:(NSString *)title andMessage:(NSString *)message NS_DESIGNATED_INITIALIZER; -- (void)addButtonWithTitle:(NSString *)title type:(SIAlertViewButtonType)type handler:(SIAlertViewHandler)handler; - -- (void)show; -- (void)dismissAnimated:(BOOL)animated; - -@end diff --git a/DeepLinkDemo/DeepLinkDemo/SIAlertView/SIAlertView.m b/DeepLinkDemo/DeepLinkDemo/SIAlertView/SIAlertView.m deleted file mode 100644 index e2f988e2d..000000000 --- a/DeepLinkDemo/DeepLinkDemo/SIAlertView/SIAlertView.m +++ /dev/null @@ -1,1253 +0,0 @@ -// SIAlertView.m -// SIAlertView -// Created by Kevin Cao on 13-4-29. -// Copyright (c) 2013年 Sumi Interactive. All rights reserved. - -#import "SIAlertView.h" -#import "UIWindow+SIUtils.h" -#import -NSString *const SIAlertViewWillShowNotification = @"SIAlertViewWillShowNotification"; -NSString *const SIAlertViewDidShowNotification = @"SIAlertViewDidShowNotification"; -NSString *const SIAlertViewWillDismissNotification = @"SIAlertViewWillDismissNotification"; -NSString *const SIAlertViewDidDismissNotification = @"SIAlertViewDidDismissNotification"; -#define DEBUG_LAYOUT 0 -#define MESSAGE_MIN_LINE_COUNT 3 -#define MESSAGE_MAX_LINE_COUNT 15 -#define GAP 10 -#define CANCEL_BUTTON_PADDING_TOP 5 -#define CONTENT_PADDING_LEFT 10 -#define CONTENT_PADDING_TOP 12 -#define CONTENT_PADDING_BOTTOM 10 -#define BUTTON_HEIGHT 45.0//([[UIScreen mainScreen] bounds].size.height/(2208.0/147.0))//47 -#define CONTAINER_WIDTH 300 - -const UIWindowLevel UIWindowLevelSIAlert = 1996.0; // don't overlap system's alert -const UIWindowLevel UIWindowLevelSIAlertBackground = 1985.0; // below the alert window - -@class SIAlertBackgroundWindow; -static NSMutableArray *__si_alert_queue; -static BOOL __si_alert_animating; -static SIAlertBackgroundWindow *__si_alert_background_window; -static SIAlertView *__si_alert_current_view; - -@interface SIAlertView () - -@property (nonatomic, strong) NSMutableArray *items; -@property (nonatomic, weak) UIWindow *oldKeyWindow; -@property (nonatomic, strong) UIWindow *alertWindow; -#ifdef __IPHONE_7_0 -@property (nonatomic, assign) UIViewTintAdjustmentMode oldTintAdjustmentMode; -#endif -@property (nonatomic, assign, getter = isVisible) BOOL visible; - -@property (nonatomic, strong) UILabel *titleLabel; -@property (nonatomic, strong) UILabel *messageLabel; -@property (nonatomic, strong) UIView *containerView; -@property (nonatomic, strong) NSMutableArray *buttons; - -@property (nonatomic, assign, getter = isLayoutDirty) BOOL layoutDirty; - -+ (NSMutableArray *)sharedQueue; -+ (SIAlertView *)currentAlertView; - -+ (BOOL)isAnimating; -+ (void)setAnimating:(BOOL)animating; - -+ (void)showBackground; -+ (void)hideBackgroundAnimated:(BOOL)animated; - -- (void)setup; -- (void)invalidateLayout; -- (void)resetTransition; - -@end - -#pragma mark - SIBackgroundWindow - -@interface SIAlertBackgroundWindow : UIWindow - -@end - -@interface SIAlertBackgroundWindow () - -@property (nonatomic, assign) SIAlertViewBackgroundStyle style; - -@end - -@implementation SIAlertBackgroundWindow - -- (instancetype)initWithFrame:(CGRect)frame andStyle:(SIAlertViewBackgroundStyle)style -{ - self = [super initWithFrame:frame]; - if (self) { - self.style = style; - self.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; - self.opaque = NO; - self.windowLevel = UIWindowLevelSIAlertBackground; - } - return self; -} - -- (void)drawRect:(CGRect)rect -{ - CGContextRef context = UIGraphicsGetCurrentContext(); - switch (self.style) { - case SIAlertViewBackgroundStyleGradient: - { - size_t locationsCount = 2; - CGFloat locations[2] = {0.0f, 1.0f}; - CGFloat colors[8] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.75f}; - CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); - CGGradientRef gradient = CGGradientCreateWithColorComponents(colorSpace, colors, locations, locationsCount); - CGColorSpaceRelease(colorSpace); - - CGPoint center = CGPointMake(self.bounds.size.width / 2, self.bounds.size.height / 2); - CGFloat radius = MIN(self.bounds.size.width, self.bounds.size.height) ; - CGContextDrawRadialGradient (context, gradient, center, 0, center, radius, kCGGradientDrawsAfterEndLocation); - CGGradientRelease(gradient); - break; - } - case SIAlertViewBackgroundStyleSolid: - { - [[UIColor colorWithWhite:0 alpha:0.5] set]; - CGContextFillRect(context, self.bounds); - break; - } - } -} - -@end - -#pragma mark - SIAlertItem -@interface SIAlertItem : NSObject -@property (nonatomic, copy) NSString *title; -@property (nonatomic, assign) SIAlertViewButtonType type; -@property (nonatomic, copy) SIAlertViewHandler action; -@end -@implementation SIAlertItem -@end - -#pragma mark - SIAlertViewController -@interface SIAlertViewController : UIViewController -@property (nonatomic, strong) SIAlertView *alertView; -@end - -@implementation SIAlertViewController - -#pragma mark - View life cycle - -- (void)loadView -{ - self.view = self.alertView; -} - -- (void)viewDidLoad -{ - [super viewDidLoad]; - [self.alertView setup]; -} - -- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration -{ - [self.alertView resetTransition]; - [self.alertView invalidateLayout]; -} - -#ifdef __IPHONE_7_0 -- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration -{ - if ([self respondsToSelector:@selector(setNeedsStatusBarAppearanceUpdate)]) { - [self setNeedsStatusBarAppearanceUpdate]; - } -} -#endif - -- (UIInterfaceOrientationMask)supportedInterfaceOrientations -{ - UIViewController *viewController = [self.alertView.oldKeyWindow currentViewController]; - if (viewController) { - return [viewController supportedInterfaceOrientations]; - } - return UIInterfaceOrientationMaskAll; -} - -- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation -{ - UIViewController *viewController = [self.alertView.oldKeyWindow currentViewController]; - if (viewController) { - return [viewController shouldAutorotateToInterfaceOrientation:toInterfaceOrientation]; - } - return YES; -} - -- (BOOL)shouldAutorotate -{ - UIViewController *viewController = [self.alertView.oldKeyWindow currentViewController]; - if (viewController) { - return [viewController shouldAutorotate]; - } - return YES; -} - -#ifdef __IPHONE_7_0 -- (UIStatusBarStyle)preferredStatusBarStyle -{ - UIWindow *window = self.alertView.oldKeyWindow; - if (!window) { - window = [UIApplication sharedApplication].windows[0]; - } - return [[window viewControllerForStatusBarStyle] preferredStatusBarStyle]; -} - -- (BOOL)prefersStatusBarHidden -{ - UIWindow *window = self.alertView.oldKeyWindow; - if (!window) { - window = [UIApplication sharedApplication].windows[0]; - } - return [[window viewControllerForStatusBarHidden] prefersStatusBarHidden]; -} -#endif - -@end - -#pragma mark - SIAlert - -@implementation SIAlertView - -+ (void)initialize { - if (self != [SIAlertView class]) - return; - SIAlertView *appearance = [self appearance]; - appearance.viewBackgroundColor = [UIColor whiteColor]; - appearance.titleColor = [UIColor blackColor]; - appearance.messageColor = [UIColor darkGrayColor]; - appearance.titleFont = [UIFont fontWithName:@"SegoeUI" size:20.0]; // FONT_MAVEN_REGULAR - appearance.messageFont = [UIFont fontWithName:@"SegoeUI-Light" size:18.0];// FONT_MAVEN_LIGHT_300 - appearance.buttonFont = [UIFont fontWithName:@"SegoeUI" size:20.0];// FONT_MAVEN_REGULAR - appearance.buttonColor = [UIColor whiteColor];//[UIColor colorWithRed:39.0/255.0 green:75.0/255.0 blue:160.0/255.0 alpha:1.0]; - appearance.cancelButtonColor = [UIColor whiteColor]; - appearance.destructiveButtonColor = [UIColor whiteColor];//[UIColor colorWithRed:77.0/255.0 green:184.0/255.0 blue:49.0/255.0 alpha:1.0]; - appearance.destructiveButtonColor = [UIColor whiteColor]; - appearance.cornerRadius = 5.0; - appearance.shadowRadius = 5.0; -} -/* -- (instancetype)init -{ - return [self initWithTitle:nil andMessage:nil]; -}*/ - -- (instancetype)initWithTitle:(NSString *)title andMessage:(NSString *)message { - self = [super initWithFrame:CGRectZero]; - if (self) { - - if (title.length > 0) { // Check Added because nill could not be passed (from swift) - _title = title; - } else { - _title = nil; - } - _message = message; - _enabledParallaxEffect = YES; - self.items = [[NSMutableArray alloc] init]; - } - return self; -} - -#pragma mark - Class methods - -+ (NSMutableArray *)sharedQueue -{ - if (!__si_alert_queue) { - __si_alert_queue = [NSMutableArray array]; - } - return __si_alert_queue; -} - -+ (SIAlertView *)currentAlertView -{ - return __si_alert_current_view; -} - -+ (void)setCurrentAlertView:(SIAlertView *)alertView -{ - __si_alert_current_view = alertView; -} - -+ (BOOL)isAnimating -{ - return __si_alert_animating; -} - -+ (void)setAnimating:(BOOL)animating { - __si_alert_animating = animating; -} - -+ (void)showBackground { - if (!__si_alert_background_window) { - CGRect frame = [UIScreen mainScreen].bounds; - if([[UIScreen mainScreen] respondsToSelector:@selector(fixedCoordinateSpace)]) - { - frame = [[UIScreen mainScreen].fixedCoordinateSpace convertRect:frame fromCoordinateSpace:[UIScreen mainScreen].coordinateSpace]; - } - - __si_alert_background_window = [[SIAlertBackgroundWindow alloc] initWithFrame:frame - andStyle:[SIAlertView currentAlertView].backgroundStyle]; - [__si_alert_background_window makeKeyAndVisible]; - __si_alert_background_window.alpha = 0; - [UIView animateWithDuration:0.3 - animations:^{ - __si_alert_background_window.alpha = 1; - }]; - } -} - -- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { - UITouch *touch = [touches anyObject]; - CGPoint location = [touch locationInView:self]; -// NSLog(@"%@",self.containerView); - if (self.shouldRemoveAfterTouch && self.containerView) { - if (!(((location.y > CGRectGetMinY(self.containerView.frame)) && (location.y < CGRectGetMaxY(self.containerView.frame))) && ((location.x > CGRectGetMinX(self.containerView.frame)) && (location.x < CGRectGetMaxX(self.containerView.frame))))) { - self.shouldRemoveAfterTouch = NO; - [self dismissAnimated:YES]; - } - } -} - -+ (void)hideBackgroundAnimated:(BOOL)animated -{ - if (!animated) { - [__si_alert_background_window removeFromSuperview]; - __si_alert_background_window = nil; - return; - } - [UIView animateWithDuration:0.3 - animations:^{ - __si_alert_background_window.alpha = 0; - } - completion:^(BOOL finished) { - [__si_alert_background_window removeFromSuperview]; - __si_alert_background_window = nil; - }]; -} - -#pragma mark - Setters - -- (void)setTitle:(NSString *)title -{ - _title = title; - [self invalidateLayout]; -} - -- (void)setMessage:(NSString *)message -{ - _message = message; - [self invalidateLayout]; -} - -#pragma mark - Public - -- (void)addButtonWithTitle:(NSString *)title type:(SIAlertViewButtonType)type handler:(SIAlertViewHandler)handler -{ - SIAlertItem *item = [[SIAlertItem alloc] init]; - item.title = title; - item.type = type; - item.action = handler; - [self.items addObject:item]; -} - -- (void)show -{ - if (self.isVisible) { - return; - } - - self.oldKeyWindow = [UIApplication sharedApplication].keyWindow; -#ifdef __IPHONE_7_0 - if ([self.oldKeyWindow respondsToSelector:@selector(setTintAdjustmentMode:)]) { // for iOS 7 - self.oldTintAdjustmentMode = self.oldKeyWindow.tintAdjustmentMode; - self.oldKeyWindow.tintAdjustmentMode = UIViewTintAdjustmentModeDimmed; - } -#endif - - if (![[SIAlertView sharedQueue] containsObject:self]) { - [[SIAlertView sharedQueue] addObject:self]; - } - - if ([SIAlertView isAnimating]) { - return; // wait for next turn - } - - if ([SIAlertView currentAlertView].isVisible) { - SIAlertView *alert = [SIAlertView currentAlertView]; - [alert dismissAnimated:YES cleanup:NO]; - return; - } - - if (self.willShowHandler) { - self.willShowHandler(self); - } - - [[NSNotificationCenter defaultCenter] postNotificationName:SIAlertViewWillShowNotification object:self userInfo:nil]; - - self.visible = YES; - - [SIAlertView setAnimating:YES]; - [SIAlertView setCurrentAlertView:self]; - - // transition background - [SIAlertView showBackground]; - - SIAlertViewController *viewController = [[SIAlertViewController alloc] initWithNibName:nil bundle:nil]; - viewController.alertView = self; - - if (!self.alertWindow) { - UIWindow *window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; - window.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; - window.opaque = NO; - window.windowLevel = UIWindowLevelSIAlert; - window.rootViewController = viewController; - self.alertWindow = window; - } - [self.alertWindow makeKeyAndVisible]; - - [self validateLayout]; - [self.containerView setClipsToBounds:YES]; - - CGFloat yAxisOfBackgroundLayer = self.containerView.frame.size.height - BUTTON_HEIGHT - 0.5; - UIView *backgroundLayerOfButtons = [[UIView alloc] init]; - backgroundLayerOfButtons.frame = CGRectMake(0, yAxisOfBackgroundLayer, self.containerView.frame.size.width, self.containerView.frame.size.height - yAxisOfBackgroundLayer); - backgroundLayerOfButtons.backgroundColor = [UIColor colorWithRed:04.0/255.0 green:202.0/255.0 blue:169.0/255.0 alpha:1.0]; - [self.containerView insertSubview:backgroundLayerOfButtons atIndex:0]; - - [self transitionInCompletion:^{ - if (self.didShowHandler) { - self.didShowHandler(self); - } - [[NSNotificationCenter defaultCenter] postNotificationName:SIAlertViewDidShowNotification object:self userInfo:nil]; - #ifdef __IPHONE_7_0 - [self addParallaxEffect]; - #endif - - [SIAlertView setAnimating:NO]; - - NSInteger index = [[SIAlertView sharedQueue] indexOfObject:self]; - if (index < [SIAlertView sharedQueue].count - 1) { - [self dismissAnimated:YES cleanup:NO]; // dismiss to show next alert view - } - }]; -} - -- (void)dismissAnimated:(BOOL)animated -{ - [self dismissAnimated:animated cleanup:YES]; -} - -- (void)dismissAnimated:(BOOL)animated cleanup:(BOOL)cleanup -{ - BOOL isVisible = self.isVisible; - - if (isVisible) { - if (self.willDismissHandler) { - self.willDismissHandler(self); - } - [[NSNotificationCenter defaultCenter] postNotificationName:SIAlertViewWillDismissNotification object:self userInfo:nil]; - #ifdef __IPHONE_7_0 - [self removeParallaxEffect]; - #endif - } - - void (^dismissComplete)(void) = ^{ - self.visible = NO; - - [self teardown]; - - [SIAlertView setCurrentAlertView:nil]; - - SIAlertView *nextAlertView; - NSInteger index = [[SIAlertView sharedQueue] indexOfObject:self]; - if (index != NSNotFound && index < [SIAlertView sharedQueue].count - 1) { - nextAlertView = [SIAlertView sharedQueue][index + 1]; - } - - if (cleanup) { - [[SIAlertView sharedQueue] removeObject:self]; - } - - [SIAlertView setAnimating:NO]; - - if (isVisible) { - if (self.didDismissHandler) { - self.didDismissHandler(self); - } - [[NSNotificationCenter defaultCenter] postNotificationName:SIAlertViewDidDismissNotification object:self userInfo:nil]; - } - - // check if we should show next alert - if (!isVisible) { - return; - } - - if (nextAlertView) { - [nextAlertView show]; - } else { - // show last alert view - if ([SIAlertView sharedQueue].count > 0) { - SIAlertView *alert = [SIAlertView sharedQueue].lastObject; - [alert show]; - } - } - }; - - if (animated && isVisible) { - [SIAlertView setAnimating:YES]; - [self transitionOutCompletion:dismissComplete]; - - if ([SIAlertView sharedQueue].count == 1) { - [SIAlertView hideBackgroundAnimated:YES]; - } - - } else { - dismissComplete(); - - if ([SIAlertView sharedQueue].count == 0) { - [SIAlertView hideBackgroundAnimated:YES]; - } - } - - UIWindow *window = self.oldKeyWindow; -#ifdef __IPHONE_7_0 - if ([window respondsToSelector:@selector(setTintAdjustmentMode:)]) { - window.tintAdjustmentMode = self.oldTintAdjustmentMode; - } -#endif - if (!window) { - window = [UIApplication sharedApplication].windows[0]; - } - [window makeKeyWindow]; - window.hidden = NO; -} - -#pragma mark - Transitions - -- (void)transitionInCompletion:(void(^)(void))completion -{ - switch (self.transitionStyle) { - case SIAlertViewTransitionStyleSlideFromBottom: - { - CGRect rect = self.containerView.frame; - CGRect originalRect = rect; - rect.origin.y = self.bounds.size.height; - self.containerView.frame = rect; - [UIView animateWithDuration:0.3 - animations:^{ - self.containerView.frame = originalRect; - } - completion:^(BOOL finished) { - if (completion) { - completion(); - } - }]; - } - break; - case SIAlertViewTransitionStyleSlideFromTop: - { - CGRect rect = self.containerView.frame; - CGRect originalRect = rect; - rect.origin.y = -rect.size.height; - self.containerView.frame = rect; - [UIView animateWithDuration:0.3 - animations:^{ - self.containerView.frame = originalRect; - } - completion:^(BOOL finished) { - if (completion) { - completion(); - } - }]; - } - break; - case SIAlertViewTransitionStyleFade: - { - self.containerView.alpha = 0; - [UIView animateWithDuration:0.3 - animations:^{ - self.containerView.alpha = 1; - } - completion:^(BOOL finished) { - if (completion) { - completion(); - } - }]; - } - break; - case SIAlertViewTransitionStyleBounce: - { - CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"transform.scale"]; - animation.values = @[@(0.01), @(1.2), @(0.9), @(1)]; - animation.keyTimes = @[@(0), @(0.4), @(0.6), @(1)]; - animation.timingFunctions = @[[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear], [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear], [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]]; - animation.duration = 0.5; - animation.delegate = self; - [animation setValue:completion forKey:@"handler"]; - [self.containerView.layer addAnimation:animation forKey:@"bouce"]; - } - break; - case SIAlertViewTransitionStyleDropDown: - { - CGFloat y = self.containerView.center.y; - CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"position.y"]; - animation.values = @[@(y - self.bounds.size.height), @(y + 20), @(y - 10), @(y)]; - animation.keyTimes = @[@(0), @(0.5), @(0.75), @(1)]; - animation.timingFunctions = @[[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut], [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear], [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]]; - animation.duration = 0.4; - animation.delegate = self; - [animation setValue:completion forKey:@"handler"]; - [self.containerView.layer addAnimation:animation forKey:@"dropdown"]; - } - break; - default: - break; - } -} - -- (void)transitionOutCompletion:(void(^)(void))completion -{ - switch (self.transitionStyle) { - case SIAlertViewTransitionStyleSlideFromBottom: - { - CGRect rect = self.containerView.frame; - rect.origin.y = self.bounds.size.height; - [UIView animateWithDuration:0.3 - delay:0 - options:UIViewAnimationOptionCurveEaseIn - animations:^{ - self.containerView.frame = rect; - } - completion:^(BOOL finished) { - if (completion) { - completion(); - } - }]; - } - break; - case SIAlertViewTransitionStyleSlideFromTop: - { - CGRect rect = self.containerView.frame; - rect.origin.y = -rect.size.height; - [UIView animateWithDuration:0.3 - delay:0 - options:UIViewAnimationOptionCurveEaseIn - animations:^{ - self.containerView.frame = rect; - } - completion:^(BOOL finished) { - if (completion) { - completion(); - } - }]; - } - break; - case SIAlertViewTransitionStyleFade: - { - [UIView animateWithDuration:0.25 - animations:^{ - self.containerView.alpha = 0; - } - completion:^(BOOL finished) { - if (completion) { - completion(); - } - }]; - } - break; - case SIAlertViewTransitionStyleBounce: - { - CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"transform.scale"]; - animation.values = @[@(1), @(1.2), @(0.01)]; - animation.keyTimes = @[@(0), @(0.4), @(1)]; - animation.timingFunctions = @[[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut], [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]]; - animation.duration = 0.35; - animation.delegate = self; - [animation setValue:completion forKey:@"handler"]; - [self.containerView.layer addAnimation:animation forKey:@"bounce"]; - self.containerView.transform = CGAffineTransformMakeScale(0.01, 0.01); - } - break; - case SIAlertViewTransitionStyleDropDown: - { - CGPoint point = self.containerView.center; - point.y += self.bounds.size.height; - [UIView animateWithDuration:0.3 - delay:0 - options:UIViewAnimationOptionCurveEaseIn - animations:^{ - self.containerView.center = point; - CGFloat angle = ((CGFloat)arc4random_uniform(100) - 50.f) / 100.f; - self.containerView.transform = CGAffineTransformMakeRotation(angle); - } - completion:^(BOOL finished) { - if (completion) { - completion(); - } - }]; - } - break; - default: - break; - } -} - -- (void)resetTransition -{ - [self.containerView.layer removeAllAnimations]; -} - -#pragma mark - Layout - -- (void)layoutSubviews -{ - [super layoutSubviews]; - [self validateLayout]; -} - -- (void)invalidateLayout -{ - self.layoutDirty = YES; - [self setNeedsLayout]; -} - -- (void)validateLayout -{ - if (!self.isLayoutDirty) { - return; - } - self.layoutDirty = NO; -#if DEBUG_LAYOUT -// NSLog(@"%@, %@", self, NSStringFromSelector(_cmd)); -#endif - - CGFloat height = [self preferredHeight]; - CGFloat left = (self.bounds.size.width - CONTAINER_WIDTH) * 0.5; - CGFloat top = (self.bounds.size.height - height) * 0.5; - self.containerView.transform = CGAffineTransformIdentity; - self.containerView.frame = CGRectMake(left, top, CONTAINER_WIDTH, height); - self.containerView.layer.shadowPath = [UIBezierPath bezierPathWithRoundedRect:self.containerView.bounds cornerRadius:self.containerView.layer.cornerRadius].CGPath; - - CGFloat y = CONTENT_PADDING_TOP; - if (self.titleLabel) { - self.titleLabel.text = self.title; - CGFloat height = [self heightForTitleLabel]; - self.titleLabel.frame = CGRectMake(CONTENT_PADDING_LEFT, y, self.containerView.bounds.size.width - CONTENT_PADDING_LEFT * 2, height); - y += height; - } - if (self.messageLabel) { - if (y > CONTENT_PADDING_TOP) { - y += GAP; - } - self.messageLabel.text = self.message; - CGFloat height = [self heightForMessageLabel]; - self.messageLabel.frame = CGRectMake(CONTENT_PADDING_LEFT, y, self.containerView.bounds.size.width - CONTENT_PADDING_LEFT * 2, height); - y += height; - } - if (self.items.count > 0) { - if (y > CONTENT_PADDING_TOP) { - y += GAP; - } - // y = self.containerView.bounds.size.height - BUTTON_HEIGHT; - if (self.items.count == 2 && self.buttonsListStyle == SIAlertViewButtonsListStyleNormal) { - //CGFloat width = (self.containerView.bounds.size.width - CONTENT_PADDING_LEFT * 2 - GAP) * 0.5; - CGFloat width = (self.containerView.bounds.size.width - 0.5) * 0.5; - UIButton *button = self.buttons[0]; -// button.frame = CGRectMake(CONTENT_PADDING_LEFT, y, width, BUTTON_HEIGHT); - button.frame = CGRectMake(0, y, width, BUTTON_HEIGHT); - button = self.buttons[1]; -// button.frame = CGRectMake(CONTENT_PADDING_LEFT + width + GAP, y, width, BUTTON_HEIGHT); - button.frame = CGRectMake(width + 0.5, y, width, BUTTON_HEIGHT); - } else { - for (NSUInteger i = 0; i < self.buttons.count; i++) { - UIButton *button = self.buttons[i]; -// button.frame = CGRectMake(CONTENT_PADDING_LEFT, y, self.containerView.bounds.size.width - CONTENT_PADDING_LEFT * 2, BUTTON_HEIGHT); - button.frame = CGRectMake(0, y, self.containerView.bounds.size.width, BUTTON_HEIGHT); - if (self.buttons.count > 1) { - if (i == self.buttons.count - 1 && ((SIAlertItem *)self.items[i]).type == SIAlertViewButtonTypeCancel) { - CGRect rect = button.frame; - rect.origin.y += CANCEL_BUTTON_PADDING_TOP; - button.frame = rect; - } - //y += BUTTON_HEIGHT + GAP; - y += BUTTON_HEIGHT + 0.5; - } - } - } - } -} - -- (CGFloat)preferredHeight -{ - CGFloat height = CONTENT_PADDING_TOP; - if (self.title) { - height += [self heightForTitleLabel]; - } - if (self.message) { - if (height > CONTENT_PADDING_TOP) { - height += GAP; - } - height += [self heightForMessageLabel]; - } - if (self.items.count > 0) { - if (height > CONTENT_PADDING_TOP) { - height += GAP; - } - if (self.items.count <= 2 && self.buttonsListStyle == SIAlertViewButtonsListStyleNormal) { - height += BUTTON_HEIGHT; - } else { -// height += (BUTTON_HEIGHT + GAP) * self.items.count - GAP; - height += (BUTTON_HEIGHT + 1.5) * self.items.count - 1.5; - if (self.buttons.count > 2 && ((SIAlertItem *)(self.items).lastObject).type == SIAlertViewButtonTypeCancel) { - height += CANCEL_BUTTON_PADDING_TOP; - } - } - } - //height += CONTENT_PADDING_BOTTOM; - return height; -} - -- (CGFloat)heightForTitleLabel { - if (self.titleLabel) { - float maxHeightOfTitleLabel = 2 * self.titleLabel.font.lineHeight; - (self.titleLabel).numberOfLines = 2; - (self.titleLabel).lineBreakMode = NSLineBreakByWordWrapping; - - #ifdef __IPHONE_7_0 - NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init]; - paragraphStyle.lineBreakMode = self.titleLabel.lineBreakMode; - - NSDictionary *attributes = @{NSFontAttributeName:self.titleLabel.font, - NSParagraphStyleAttributeName: paragraphStyle.copy}; - - // NSString class method: boundingRectWithSize:options:attributes:context is - // available only on ios7.0 sdk. - CGRect rect = [self.titleLabel.text boundingRectWithSize:CGSizeMake(CONTAINER_WIDTH - CONTENT_PADDING_LEFT * 2, maxHeightOfTitleLabel) - options:NSStringDrawingUsesLineFragmentOrigin - attributes:attributes - context:nil]; - return ceil(rect.size.height); - #else - CGSize size = [self.title sizeWithFont:self.titleLabel.font - minFontSize: - #if __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_6_0 - self.titleLabel.font.pointSize * self.titleLabel.minimumScaleFactor - #else - self.titleLabel.minimumFontSize - #endif - actualFontSize:nil - forWidth:CONTAINER_WIDTH - CONTENT_PADDING_LEFT * 2 - lineBreakMode:self.titleLabel.lineBreakMode]; - return size.height; - #endif - } - - return 0; -} - -- (CGFloat)heightForMessageLabel -{ - CGFloat minHeight = MESSAGE_MIN_LINE_COUNT * self.messageLabel.font.lineHeight; - if (self.messageLabel) { - CGFloat maxHeight = MESSAGE_MAX_LINE_COUNT * self.messageLabel.font.lineHeight; - - #ifdef __IPHONE_7_0 - NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init]; - paragraphStyle.lineBreakMode = self.messageLabel.lineBreakMode; - - NSDictionary *attributes = @{NSFontAttributeName:self.messageLabel.font, - NSParagraphStyleAttributeName: paragraphStyle.copy}; - - // NSString class method: boundingRectWithSize:options:attributes:context is - // available only on ios7.0 sdk. - //NSLog(@"Text of Message=>%@",self.messageLabel.text); - // NSLog(@"Widthof Expected label =>%d \n and height expected =>%f",(CONTAINER_WIDTH - CONTENT_PADDING_LEFT * 2), maxHeight); - CGRect rect = [self.messageLabel.text boundingRectWithSize:CGSizeMake(CONTAINER_WIDTH - CONTENT_PADDING_LEFT * 2, maxHeight) - options:NSStringDrawingUsesLineFragmentOrigin - attributes:attributes - context:nil]; - // NSLog(@"estimated height of Message label =>%f \n exact height of Message label=>%f",rect.size.height,MAX(minHeight, ceil(rect.size.height))); - return MAX(minHeight, ceil(rect.size.height)); - #else - CGSize size = [self.message sizeWithFont:self.messageLabel.font - constrainedToSize:CGSizeMake(CONTAINER_WIDTH - CONTENT_PADDING_LEFT * 2, maxHeight) - lineBreakMode:self.messageLabel.lineBreakMode]; - - return MAX(minHeight, size.height); - #endif - } - - return minHeight; -} - -#pragma mark - Setup - -- (void)setup -{ - [self setupContainerView]; - [self updateTitleLabel]; - [self updateMessageLabel]; - [self setupButtons]; - [self invalidateLayout]; -} - -- (void)teardown -{ - [self.containerView removeFromSuperview]; - self.containerView = nil; - self.titleLabel = nil; - self.messageLabel = nil; - [self.buttons removeAllObjects]; - [self.alertWindow removeFromSuperview]; - self.alertWindow = nil; - self.layoutDirty = NO; -} - -- (void)setupContainerView -{ - self.containerView = [[UIView alloc] initWithFrame:self.bounds]; - self.containerView.backgroundColor = _viewBackgroundColor ? _viewBackgroundColor : [UIColor whiteColor]; - self.containerView.layer.cornerRadius = self.cornerRadius; - self.containerView.layer.shadowOffset = CGSizeZero; - self.containerView.layer.shadowRadius = self.shadowRadius; - self.containerView.layer.shadowOpacity = 0.5; - [self addSubview:self.containerView]; -} - -- (void)updateTitleLabel -{ - if (self.title) { - if (!self.titleLabel) { - self.titleLabel = [[UILabel alloc] initWithFrame:self.bounds]; - self.titleLabel.textAlignment = NSTextAlignmentCenter; - self.titleLabel.backgroundColor = [UIColor clearColor]; - self.titleLabel.font = self.titleFont; - self.titleLabel.textColor = self.titleColor; - self.titleLabel.adjustsFontSizeToFitWidth = YES; -#if __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_6_0 - self.titleLabel.minimumScaleFactor = 0.75; -#else - self.titleLabel.minimumFontSize = self.titleLabel.font.pointSize * 0.75; -#endif - [self.containerView addSubview:self.titleLabel]; -#if DEBUG_LAYOUT - self.titleLabel.backgroundColor = [UIColor redColor]; -#endif - } - self.titleLabel.text = self.title; - } else { - [self.titleLabel removeFromSuperview]; - self.titleLabel = nil; - } - [self invalidateLayout]; -} - -- (void)updateMessageLabel -{ - if (self.message) { - if (!self.messageLabel) { - self.messageLabel = [[UILabel alloc] initWithFrame:self.bounds]; - self.messageLabel.textAlignment = NSTextAlignmentCenter; - self.messageLabel.backgroundColor = [UIColor clearColor]; - self.messageLabel.font = self.messageFont; - self.messageLabel.textColor = self.messageColor; - self.messageLabel.numberOfLines = MESSAGE_MAX_LINE_COUNT; - (self.messageLabel).lineBreakMode = NSLineBreakByWordWrapping; - [self.containerView addSubview:self.messageLabel]; -#if DEBUG_LAYOUT - self.messageLabel.backgroundColor = [UIColor redColor]; -#endif - } - self.messageLabel.text = self.message; - } else { - [self.messageLabel removeFromSuperview]; - self.messageLabel = nil; - } - [self invalidateLayout]; -} - -- (void)setupButtons -{ - self.buttons = [[NSMutableArray alloc] initWithCapacity:self.items.count]; - for (NSUInteger i = 0; i < self.items.count; i++) { - UIButton *button = [self buttonForItemIndex:i]; - [self.buttons addObject:button]; - [self.containerView addSubview:button]; - } -} - -- (UIButton *)buttonForItemIndex:(NSUInteger)index -{ - //CGFloat heightOfButton = [[CommonFunctions shareCommonMethods] targetYOrHeightSize:150.0]; - - SIAlertItem *item = self.items[index]; - UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom]; - button.tag = index; - button.autoresizingMask = UIViewAutoresizingFlexibleWidth; - button.titleLabel.font = self.buttonFont; - [button setTitle:item.title forState:UIControlStateNormal]; - UIImage *normalImage = nil; - UIImage *highlightedImage = [self imageWithColor:[UIColor clearColor] andFrame:CGRectMake(0, 0, 400, BUTTON_HEIGHT)]; - switch (item.type) { - case SIAlertViewButtonTypeCancel: - //normalImage = [UIImage imageNamed:@"SIAlertView.bundle/button-cancel"]; - //highlightedImage = [UIImage imageNamed:@"SIAlertView.bundle/button-cancel-d"]; - normalImage = [self imageWithColor:[UIColor colorWithRed:04.0/255.0 green:202.0/255.0 blue:169.0/255.0 alpha:1.0] andFrame:CGRectMake(0, 0, 400, BUTTON_HEIGHT)]; - - [button setTitleColor:self.cancelButtonColor forState:UIControlStateNormal]; - //[button setTitleColor:[UIColor whiteColor] forState:UIControlStateHighlighted]; - //[button.layer setBorderColor:[COLOR_JUGNOO_MEALS_THEME CGColor]]; - //[button.layer setBorderWidth:2.0]; - break; - case SIAlertViewButtonTypeDestructive: - normalImage = [self imageWithColor:[UIColor colorWithRed:04.0/255.0 green:202.0/255.0 blue:169.0/255.0 alpha:1.0] andFrame:CGRectMake(0, 0, 400, BUTTON_HEIGHT)]; - //highlightedImage = [UIImage imageNamed:@"SIAlertView.bundle/button-destructive-d"]; - [button setTitleColor:self.destructiveButtonColor forState:UIControlStateNormal]; - //[button setTitleColor:[UIColor whiteColor] forState:UIControlStateHighlighted]; - //[button.layer setBorderColor:[[UIColor whiteColor] CGColor]]; - //[button.layer setBorderWidth:2.0]; - break; - case SIAlertViewButtonTypeDefault: - default: - //normalImage = [UIImage imageNamed:@"SIAlertView.bundle/button-default"]; - //highlightedImage = [UIImage imageNamed:@"SIAlertView.bundle/button-default-d"]; - normalImage = [self imageWithColor:[UIColor colorWithRed:04.0/255.0 green:202.0/255.0 blue:169.0/255.0 alpha:1.0] andFrame:CGRectMake(0, 0, 400, BUTTON_HEIGHT)]; - [button setTitleColor:self.buttonColor forState:UIControlStateNormal]; - //[button setTitleColor:[UIColor whiteColor] forState:UIControlStateHighlighted]; - //[button.layer setBorderColor:[[UIColor whiteColor] CGColor]]; - //[button.layer setBorderWidth:2.0]; - break; - } - /*CGFloat hInset = floorf(normalImage.size.width / 2); - CGFloat vInset = floorf(normalImage.size.height / 2); - UIEdgeInsets insets = UIEdgeInsetsMake(vInset, hInset, vInset, hInset); - normalImage = [normalImage resizableImageWithCapInsets:insets]; - highlightedImage = [highlightedImage resizableImageWithCapInsets:insets];*/ - [button setClipsToBounds:YES]; - //[button.layer setCornerRadius:4.0]; - [button setBackgroundImage:normalImage forState:UIControlStateNormal]; - [button setBackgroundImage:highlightedImage forState:UIControlStateHighlighted]; - // [button setTitleColor:[UIColor whiteColor] forState:UIControlStateHighlighted]; - [button addTarget:self action:@selector(buttonAction:) forControlEvents:UIControlEventTouchUpInside]; - - return button; -} - -- (UIImage *)imageWithColor:(UIColor *)color andFrame:(CGRect)customFrame { - UIGraphicsBeginImageContext(customFrame.size); - CGContextRef context = UIGraphicsGetCurrentContext(); - CGContextSetFillColorWithColor(context, [color CGColor]); - CGContextFillRect(context, customFrame); - UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); - UIGraphicsEndImageContext(); - return image; -} - -#pragma mark - Actions - -- (void)buttonAction:(UIButton *)button -{ - [SIAlertView setAnimating:YES]; // set this flag to YES in order to prevent showing another alert in action block - SIAlertItem *item = self.items[button.tag]; - if (item.action) { - item.action(self); - } - [self dismissAnimated:YES]; -} - -#pragma mark - CAAnimation delegate - -- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag -{ - void(^completion)(void) = [anim valueForKey:@"handler"]; - if (completion) { - completion(); - } -} - -#pragma mark - UIAppearance setters - -- (void)setViewBackgroundColor:(UIColor *)viewBackgroundColor -{ - if (_viewBackgroundColor == viewBackgroundColor) { - return; - } - _viewBackgroundColor = viewBackgroundColor; - self.containerView.backgroundColor = viewBackgroundColor; -} - -- (void)setTitleFont:(UIFont *)titleFont -{ - if (_titleFont == titleFont) { - return; - } - _titleFont = titleFont; - self.titleLabel.font = titleFont; - [self invalidateLayout]; -} - -- (void)setMessageFont:(UIFont *)messageFont -{ - if (_messageFont == messageFont) { - return; - } - _messageFont = messageFont; - self.messageLabel.font = messageFont; - [self invalidateLayout]; -} - -- (void)setTitleColor:(UIColor *)titleColor -{ - if (_titleColor == titleColor) { - return; - } - _titleColor = titleColor; - self.titleLabel.textColor = titleColor; -} - -- (void)setMessageColor:(UIColor *)messageColor -{ - if (_messageColor == messageColor) { - return; - } - _messageColor = messageColor; - self.messageLabel.textColor = messageColor; -} - -- (void)setButtonFont:(UIFont *)buttonFont -{ - if (_buttonFont == buttonFont) { - return; - } - _buttonFont = buttonFont; - for (UIButton *button in self.buttons) { - button.titleLabel.font = buttonFont; - } -} - -- (void)setCornerRadius:(CGFloat)cornerRadius -{ - if (_cornerRadius == cornerRadius) { - return; - } - _cornerRadius = cornerRadius; - self.containerView.layer.cornerRadius = cornerRadius; -} - -- (void)setShadowRadius:(CGFloat)shadowRadius -{ - if (_shadowRadius == shadowRadius) { - return; - } - _shadowRadius = shadowRadius; - self.containerView.layer.shadowRadius = shadowRadius; -} - -- (void)setButtonColor:(UIColor *)buttonColor -{ - if (_buttonColor == buttonColor) { - return; - } - _buttonColor = buttonColor; - [self setColor:buttonColor toButtonsOfType:SIAlertViewButtonTypeDefault]; -} - -- (void)setCancelButtonColor:(UIColor *)buttonColor -{ - if (_cancelButtonColor == buttonColor) { - return; - } - _cancelButtonColor = buttonColor; - [self setColor:buttonColor toButtonsOfType:SIAlertViewButtonTypeCancel]; -} - -- (void)setDestructiveButtonColor:(UIColor *)buttonColor -{ - if (_destructiveButtonColor == buttonColor) { - return; - } - _destructiveButtonColor = buttonColor; - [self setColor:buttonColor toButtonsOfType:SIAlertViewButtonTypeDestructive]; -} - - -- (void)setDefaultButtonImage:(UIImage *)defaultButtonImage forState:(UIControlState)state -{ - [self setButtonImage:defaultButtonImage forState:state andButtonType:SIAlertViewButtonTypeDefault]; -} - - -- (void)setCancelButtonImage:(UIImage *)cancelButtonImage forState:(UIControlState)state -{ - [self setButtonImage:cancelButtonImage forState:state andButtonType:SIAlertViewButtonTypeCancel]; -} - - -- (void)setDestructiveButtonImage:(UIImage *)destructiveButtonImage forState:(UIControlState)state -{ - [self setButtonImage:destructiveButtonImage forState:state andButtonType:SIAlertViewButtonTypeDestructive]; -} - - -- (void)setButtonImage:(UIImage *)image forState:(UIControlState)state andButtonType:(SIAlertViewButtonType)type -{ - for (NSUInteger i = 0; i < self.items.count; i++) - { - SIAlertItem *item = self.items[i]; - if(item.type == type) - { - UIButton *button = self.buttons[i]; - [button setBackgroundImage:image forState:state]; - } - } -} - - --(void)setColor:(UIColor *)color toButtonsOfType:(SIAlertViewButtonType)type { - for (NSUInteger i = 0; i < self.items.count; i++) { - SIAlertItem *item = self.items[i]; - if(item.type == type) { - UIButton *button = self.buttons[i]; - [button setTitleColor:color forState:UIControlStateNormal]; - //[button setTitleColor:[UIColor whiteColor] forState:UIControlStateHighlighted]; - } - } -} - -# pragma mark - -# pragma mark Enable parallax effect (iOS7 only) - -#ifdef __IPHONE_7_0 -- (void)addParallaxEffect -{ - if (_enabledParallaxEffect && NSClassFromString(@"UIInterpolatingMotionEffect")) - { - UIInterpolatingMotionEffect *effectHorizontal = [[UIInterpolatingMotionEffect alloc] initWithKeyPath:@"position.x" type:UIInterpolatingMotionEffectTypeTiltAlongHorizontalAxis]; - UIInterpolatingMotionEffect *effectVertical = [[UIInterpolatingMotionEffect alloc] initWithKeyPath:@"position.y" type:UIInterpolatingMotionEffectTypeTiltAlongVerticalAxis]; - effectHorizontal.maximumRelativeValue = @(20.0f); - effectHorizontal.minimumRelativeValue = @(-20.0f); - effectVertical.maximumRelativeValue = @(50.0f); - effectVertical.minimumRelativeValue = @(-50.0f); - [self.containerView addMotionEffect:effectHorizontal]; - [self.containerView addMotionEffect:effectVertical]; - } -} - -- (void)removeParallaxEffect -{ - if (_enabledParallaxEffect && NSClassFromString(@"UIInterpolatingMotionEffect")) - { - [self.containerView.motionEffects enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { - [self.containerView removeMotionEffect:obj]; - }]; - } -} -#endif - -@end diff --git a/DeepLinkDemo/DeepLinkDemo/SIAlertView/UIWindow+SIUtils.h b/DeepLinkDemo/DeepLinkDemo/SIAlertView/UIWindow+SIUtils.h deleted file mode 100644 index 3d5abf36f..000000000 --- a/DeepLinkDemo/DeepLinkDemo/SIAlertView/UIWindow+SIUtils.h +++ /dev/null @@ -1,20 +0,0 @@ -// -// UIWindow+SIUtils.h -// SIAlertView -// -// Created by Kevin Cao on 13-11-1. -// Copyright (c) 2013年 Sumi Interactive. All rights reserved. -// - -#import - -@interface UIWindow (SIUtils) - -- (UIViewController *)currentViewController; - -#ifdef __IPHONE_7_0 -- (UIViewController *)viewControllerForStatusBarStyle; -- (UIViewController *)viewControllerForStatusBarHidden; -#endif - -@end diff --git a/DeepLinkDemo/DeepLinkDemo/SIAlertView/UIWindow+SIUtils.m b/DeepLinkDemo/DeepLinkDemo/SIAlertView/UIWindow+SIUtils.m deleted file mode 100644 index 2967def19..000000000 --- a/DeepLinkDemo/DeepLinkDemo/SIAlertView/UIWindow+SIUtils.m +++ /dev/null @@ -1,42 +0,0 @@ -// UIWindow+SIUtils.m -// SIAlertView -// Created by Kevin Cao on 13-11-1. -// Copyright (c) 2013年 Sumi Interactive. All rights reserved. - -#import "UIWindow+SIUtils.h" - -@implementation UIWindow (SIUtils) - -- (UIViewController *)currentViewController -{ - UIViewController *viewController = self.rootViewController; - while (viewController.presentedViewController) { - viewController = viewController.presentedViewController; - } - return viewController; -} - -#ifdef __IPHONE_7_0 - -- (UIViewController *)viewControllerForStatusBarStyle { - UIViewController *currentViewController = [self currentViewController]; - - while ([currentViewController childViewControllerForStatusBarStyle]) { - currentViewController = [currentViewController childViewControllerForStatusBarStyle]; - } - return currentViewController; -} - -- (UIViewController *)viewControllerForStatusBarHidden -{ - UIViewController *currentViewController = [self currentViewController]; - - while ([currentViewController childViewControllerForStatusBarHidden]) { - currentViewController = [currentViewController childViewControllerForStatusBarHidden]; - } - return currentViewController; -} - -#endif - -@end diff --git a/DeepLinkDemo/DeepLinkDemo/StartupOptionsData.swift b/DeepLinkDemo/DeepLinkDemo/StartupOptionsData.swift deleted file mode 100644 index f0a6697b4..000000000 --- a/DeepLinkDemo/DeepLinkDemo/StartupOptionsData.swift +++ /dev/null @@ -1,59 +0,0 @@ -// -// StartupOptionsData.swift -// TestBed-Swift -// -// Created by David Westgate on 9/17/17. -// Copyright © 2017 Branch Metrics. All rights reserved. -// - -import Foundation - -struct StartupOptionsData { - - static let userDefaults = UserDefaults.standard - - static func getActiveBranchKey() -> String? { - if let value = userDefaults.string(forKey: "activeBranchKey") { - return value - } else { - let value = "" - userDefaults.setValue(value, forKey: "activeBranchKey") - return value - } - } - - static func setActiveBranchKey(_ value: String) { - userDefaults.setValue(value, forKey: "activeBranchKey") - } - - static func getPendingBranchKey() -> String? { - if let value = userDefaults.string(forKey: "pendingBranchKey") { - return value - } else { - let value = "" - userDefaults.setValue(value, forKey: "pendingBranchKey") - return value - } - } - - static func setPendingBranchKey(_ value: String) { - userDefaults.setValue(value, forKey: "pendingBranchKey") - } - - static func getActiveSetDebugEnabled() -> Bool? { - return userDefaults.bool(forKey: "activeSetDebug") - } - - static func setActiveSetDebugEnabled(_ value: Bool) { - userDefaults.setValue(value, forKey: "activeSetDebug") - } - - static func getPendingSetDebugEnabled() -> Bool? { - return userDefaults.bool(forKey: "pendingSetDebug") - } - - static func setPendingSetDebugEnabled(_ value: Bool) { - userDefaults.setValue(value, forKey: "pendingSetDebug") - } - -} diff --git a/DeepLinkDemo/DeepLinkDemo/img.png b/DeepLinkDemo/DeepLinkDemo/img.png deleted file mode 100644 index 95f2e9562..000000000 Binary files a/DeepLinkDemo/DeepLinkDemo/img.png and /dev/null differ diff --git a/DeepLinkDemo/IPA/Info.plist b/DeepLinkDemo/IPA/Info.plist deleted file mode 100644 index 42890b144..000000000 --- a/DeepLinkDemo/IPA/Info.plist +++ /dev/null @@ -1,27 +0,0 @@ - - - - - compileBitcode - - destination - export - method - development - provisioningProfiles - - io.branch.saas.sdk.testbed - iOS Saas SDK - Dev - - signingCertificate - Apple Development - signingStyle - manual - stripSwiftSymbols - - teamID - R63EM248DP - thinning - <none> - - diff --git a/DeepLinkDemo/Podfile b/DeepLinkDemo/Podfile deleted file mode 100644 index b7266ceb5..000000000 --- a/DeepLinkDemo/Podfile +++ /dev/null @@ -1,12 +0,0 @@ -# Uncomment the next line to define a global platform for your project - platform :ios, '12.0' - -target 'DeepLinkDemo' do - # Comment the next line if you don't want to use dynamic frameworks - use_frameworks! - pod 'IQKeyboardManager' - pod 'BranchSDK', :path => './../' - - # Pods for DeepLinkDemo - -end diff --git a/DeepLinkDemo/Podfile.lock b/DeepLinkDemo/Podfile.lock deleted file mode 100644 index e5b283e13..000000000 --- a/DeepLinkDemo/Podfile.lock +++ /dev/null @@ -1,23 +0,0 @@ -PODS: - - BranchSDK (3.4.4) - - IQKeyboardManager (6.5.19) - -DEPENDENCIES: - - BranchSDK (from `./../`) - - IQKeyboardManager - -SPEC REPOS: - trunk: - - IQKeyboardManager - -EXTERNAL SOURCES: - BranchSDK: - :path: "./../" - -SPEC CHECKSUMS: - BranchSDK: 28bec34fb99c53ab8e86b7bf69cc55a4505fe0b3 - IQKeyboardManager: c8665b3396bd0b79402b4c573eac345a31c7d485 - -PODFILE CHECKSUM: 8c4b32f5c4a14defd62bc8a2d1e49cee9e7c2173 - -COCOAPODS: 1.15.2 diff --git a/DeepLinkDemo/README.md b/DeepLinkDemo/README.md deleted file mode 100644 index e95c403f6..000000000 --- a/DeepLinkDemo/README.md +++ /dev/null @@ -1,2 +0,0 @@ -# Branch SaaS SDK IOS TestApp - diff --git a/Gemfile b/Gemfile deleted file mode 100644 index 2e36ecb83..000000000 --- a/Gemfile +++ /dev/null @@ -1,10 +0,0 @@ -source 'https://rubygems.org' - -gem 'cocoapods', '~> 1.9' -gem 'activesupport', '~> 7.0', '<= 7.0.8' -gem 'fastlane', '~> 2.69' -gem 'pattern_patch', '~> 0.5' -gem 'slather' - -plugins_path = File.join(File.dirname(__FILE__), 'fastlane', 'Pluginfile') -eval_gemfile(plugins_path) if File.exist?(plugins_path) diff --git a/TestDeepLinking/Podfile b/TestDeepLinking/Podfile deleted file mode 100644 index 1a6061452..000000000 --- a/TestDeepLinking/Podfile +++ /dev/null @@ -1,8 +0,0 @@ -platform :ios, '9.0' - -target 'TestDeepLinking' do - # if swift - use_frameworks! - - pod 'Branch' -end diff --git a/TestDeepLinking/TestDeepLinking.xcodeproj/project.pbxproj b/TestDeepLinking/TestDeepLinking.xcodeproj/project.pbxproj deleted file mode 100644 index 31dd25628..000000000 --- a/TestDeepLinking/TestDeepLinking.xcodeproj/project.pbxproj +++ /dev/null @@ -1,733 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 51; - objects = { - -/* Begin PBXBuildFile section */ - 032DAEE82607431D00891641 /* TestDeepLinkWithoutApp.m in Sources */ = {isa = PBXBuildFile; fileRef = 032DAED2260742D100891641 /* TestDeepLinkWithoutApp.m */; }; - 032DAEFE2607491B00891641 /* TestDeepLinkingUITestsWithHostApp.m in Sources */ = {isa = PBXBuildFile; fileRef = 032DAEFD2607491B00891641 /* TestDeepLinkingUITestsWithHostApp.m */; }; - 033608162605E2110032A5DC /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 033608152605E2110032A5DC /* AppDelegate.swift */; }; - 033608182605E2110032A5DC /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 033608172605E2110032A5DC /* SceneDelegate.swift */; }; - 0336081A2605E2110032A5DC /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 033608192605E2110032A5DC /* ViewController.swift */; }; - 0336081D2605E2110032A5DC /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0336081B2605E2110032A5DC /* Main.storyboard */; }; - 0336081F2605E2150032A5DC /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0336081E2605E2150032A5DC /* Assets.xcassets */; }; - 033608222605E2150032A5DC /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 033608202605E2150032A5DC /* LaunchScreen.storyboard */; }; - 033608302605F1E30032A5DC /* CoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0336082F2605F1E30032A5DC /* CoreServices.framework */; }; - 033608322605F1F10032A5DC /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 033608312605F1F10032A5DC /* SystemConfiguration.framework */; }; - 033608342605F20C0032A5DC /* CoreTelephony.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 033608332605F20C0032A5DC /* CoreTelephony.framework */; }; - 033608362605F2130032A5DC /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 033608352605F2130032A5DC /* WebKit.framework */; }; - 033608382605F21B0032A5DC /* CoreSpotlight.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 033608372605F21B0032A5DC /* CoreSpotlight.framework */; }; - 0336083B2605F2370032A5DC /* AdSupport.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 033608392605F2370032A5DC /* AdSupport.framework */; }; - 0336083C2605F2370032A5DC /* iAd.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0336083A2605F2370032A5DC /* iAd.framework */; }; - 0336083E2605F2880032A5DC /* AdSupport.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 033608392605F2370032A5DC /* AdSupport.framework */; }; - 033608402605F4470032A5DC /* AdSupport.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 033608392605F2370032A5DC /* AdSupport.framework */; }; - 03DE13B32606A1B4006D18F5 /* TestDeepLinking.entitlements in Resources */ = {isa = PBXBuildFile; fileRef = 03DE13B22606A0C4006D18F5 /* TestDeepLinking.entitlements */; }; - 03DE13BA2606BFC4006D18F5 /* AdServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 03DE13B92606BFC4006D18F5 /* AdServices.framework */; }; - 69BEC330F5B8AF8CE3C32174 /* Pods_TestDeepLinking.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 815FC6A40AFE1F218C25C738 /* Pods_TestDeepLinking.framework */; }; -/* End PBXBuildFile section */ - -/* Begin PBXContainerItemProxy section */ - 032DAEDF2607430600891641 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 0336080A2605E2100032A5DC /* Project object */; - proxyType = 1; - remoteGlobalIDString = 033608112605E2110032A5DC; - remoteInfo = TestDeepLinking; - }; - 032DAF002607491B00891641 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 0336080A2605E2100032A5DC /* Project object */; - proxyType = 1; - remoteGlobalIDString = 033608112605E2110032A5DC; - remoteInfo = TestDeepLinking; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXFileReference section */ - 032DAED2260742D100891641 /* TestDeepLinkWithoutApp.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TestDeepLinkWithoutApp.m; sourceTree = ""; }; - 032DAEDA2607430600891641 /* TestDeepLinkingUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = TestDeepLinkingUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 032DAEDE2607430600891641 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 032DAEFB2607491B00891641 /* TestDeepLinkingUITestsWithHostApp.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = TestDeepLinkingUITestsWithHostApp.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 032DAEFD2607491B00891641 /* TestDeepLinkingUITestsWithHostApp.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TestDeepLinkingUITestsWithHostApp.m; sourceTree = ""; }; - 032DAEFF2607491B00891641 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 032DAF122607504000891641 /* TestDeepLinking.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = TestDeepLinking.xctestplan; sourceTree = ""; }; - 033608122605E2110032A5DC /* TestDeepLinking.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TestDeepLinking.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 033608152605E2110032A5DC /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - 033608172605E2110032A5DC /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; - 033608192605E2110032A5DC /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; - 0336081C2605E2110032A5DC /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - 0336081E2605E2150032A5DC /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; - 033608212605E2150032A5DC /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; - 033608232605E2150032A5DC /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 0336082F2605F1E30032A5DC /* CoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreServices.framework; path = System/Library/Frameworks/CoreServices.framework; sourceTree = SDKROOT; }; - 033608312605F1F10032A5DC /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; - 033608332605F20C0032A5DC /* CoreTelephony.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreTelephony.framework; path = System/Library/Frameworks/CoreTelephony.framework; sourceTree = SDKROOT; }; - 033608352605F2130032A5DC /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = System/Library/Frameworks/WebKit.framework; sourceTree = SDKROOT; }; - 033608372605F21B0032A5DC /* CoreSpotlight.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreSpotlight.framework; path = System/Library/Frameworks/CoreSpotlight.framework; sourceTree = SDKROOT; }; - 033608392605F2370032A5DC /* AdSupport.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AdSupport.framework; path = System/Library/Frameworks/AdSupport.framework; sourceTree = SDKROOT; }; - 0336083A2605F2370032A5DC /* iAd.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = iAd.framework; path = System/Library/Frameworks/iAd.framework; sourceTree = SDKROOT; }; - 03DE13B22606A0C4006D18F5 /* TestDeepLinking.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = TestDeepLinking.entitlements; sourceTree = ""; }; - 03DE13B92606BFC4006D18F5 /* AdServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AdServices.framework; path = ../../AdServices.framework; sourceTree = ""; }; - 0EE470FCEAEA1ECC99DC0A89 /* Pods-TestDeepLinking.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-TestDeepLinking.release.xcconfig"; path = "Target Support Files/Pods-TestDeepLinking/Pods-TestDeepLinking.release.xcconfig"; sourceTree = ""; }; - 815FC6A40AFE1F218C25C738 /* Pods_TestDeepLinking.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_TestDeepLinking.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 86113F63A46AE44E1E8B1648 /* Pods-TestDeepLinking.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-TestDeepLinking.debug.xcconfig"; path = "Target Support Files/Pods-TestDeepLinking/Pods-TestDeepLinking.debug.xcconfig"; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 032DAED72607430600891641 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 032DAEF82607491B00891641 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 0336080F2605E2110032A5DC /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 033608362605F2130032A5DC /* WebKit.framework in Frameworks */, - 033608402605F4470032A5DC /* AdSupport.framework in Frameworks */, - 033608342605F20C0032A5DC /* CoreTelephony.framework in Frameworks */, - 03DE13BA2606BFC4006D18F5 /* AdServices.framework in Frameworks */, - 0336083E2605F2880032A5DC /* AdSupport.framework in Frameworks */, - 033608382605F21B0032A5DC /* CoreSpotlight.framework in Frameworks */, - 033608322605F1F10032A5DC /* SystemConfiguration.framework in Frameworks */, - 033608302605F1E30032A5DC /* CoreServices.framework in Frameworks */, - 0336083B2605F2370032A5DC /* AdSupport.framework in Frameworks */, - 0336083C2605F2370032A5DC /* iAd.framework in Frameworks */, - 69BEC330F5B8AF8CE3C32174 /* Pods_TestDeepLinking.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 032DAEDB2607430600891641 /* TestDeepLinkingUITests */ = { - isa = PBXGroup; - children = ( - 032DAED2260742D100891641 /* TestDeepLinkWithoutApp.m */, - 032DAEDE2607430600891641 /* Info.plist */, - ); - path = TestDeepLinkingUITests; - sourceTree = ""; - }; - 032DAEFC2607491B00891641 /* TestDeepLinkingUITestsWithHostApp */ = { - isa = PBXGroup; - children = ( - 032DAEFD2607491B00891641 /* TestDeepLinkingUITestsWithHostApp.m */, - 032DAEFF2607491B00891641 /* Info.plist */, - ); - path = TestDeepLinkingUITestsWithHostApp; - sourceTree = ""; - }; - 033608092605E2100032A5DC = { - isa = PBXGroup; - children = ( - 033608142605E2110032A5DC /* TestDeepLinking */, - 032DAEDB2607430600891641 /* TestDeepLinkingUITests */, - 032DAEFC2607491B00891641 /* TestDeepLinkingUITestsWithHostApp */, - 033608132605E2110032A5DC /* Products */, - 0336082E2605F1E30032A5DC /* Frameworks */, - FBA3F883B3850B5894EAA121 /* Pods */, - ); - sourceTree = ""; - }; - 033608132605E2110032A5DC /* Products */ = { - isa = PBXGroup; - children = ( - 033608122605E2110032A5DC /* TestDeepLinking.app */, - 032DAEDA2607430600891641 /* TestDeepLinkingUITests.xctest */, - 032DAEFB2607491B00891641 /* TestDeepLinkingUITestsWithHostApp.xctest */, - ); - name = Products; - sourceTree = ""; - }; - 033608142605E2110032A5DC /* TestDeepLinking */ = { - isa = PBXGroup; - children = ( - 03DE13B22606A0C4006D18F5 /* TestDeepLinking.entitlements */, - 033608152605E2110032A5DC /* AppDelegate.swift */, - 032DAF122607504000891641 /* TestDeepLinking.xctestplan */, - 033608172605E2110032A5DC /* SceneDelegate.swift */, - 033608192605E2110032A5DC /* ViewController.swift */, - 0336081B2605E2110032A5DC /* Main.storyboard */, - 0336081E2605E2150032A5DC /* Assets.xcassets */, - 033608202605E2150032A5DC /* LaunchScreen.storyboard */, - 033608232605E2150032A5DC /* Info.plist */, - ); - path = TestDeepLinking; - sourceTree = ""; - }; - 0336082E2605F1E30032A5DC /* Frameworks */ = { - isa = PBXGroup; - children = ( - 03DE13B92606BFC4006D18F5 /* AdServices.framework */, - 033608392605F2370032A5DC /* AdSupport.framework */, - 0336083A2605F2370032A5DC /* iAd.framework */, - 033608372605F21B0032A5DC /* CoreSpotlight.framework */, - 033608352605F2130032A5DC /* WebKit.framework */, - 033608332605F20C0032A5DC /* CoreTelephony.framework */, - 033608312605F1F10032A5DC /* SystemConfiguration.framework */, - 0336082F2605F1E30032A5DC /* CoreServices.framework */, - 815FC6A40AFE1F218C25C738 /* Pods_TestDeepLinking.framework */, - ); - name = Frameworks; - sourceTree = ""; - }; - FBA3F883B3850B5894EAA121 /* Pods */ = { - isa = PBXGroup; - children = ( - 86113F63A46AE44E1E8B1648 /* Pods-TestDeepLinking.debug.xcconfig */, - 0EE470FCEAEA1ECC99DC0A89 /* Pods-TestDeepLinking.release.xcconfig */, - ); - path = Pods; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 032DAED92607430600891641 /* TestDeepLinkingUITests */ = { - isa = PBXNativeTarget; - buildConfigurationList = 032DAEE12607430600891641 /* Build configuration list for PBXNativeTarget "TestDeepLinkingUITests" */; - buildPhases = ( - 032DAED62607430600891641 /* Sources */, - 032DAED72607430600891641 /* Frameworks */, - 032DAED82607430600891641 /* Resources */, - 032DAF0826074B6A00891641 /* ShellScript */, - ); - buildRules = ( - ); - dependencies = ( - 032DAEE02607430600891641 /* PBXTargetDependency */, - ); - name = TestDeepLinkingUITests; - productName = TestDeepLinkingUITests; - productReference = 032DAEDA2607430600891641 /* TestDeepLinkingUITests.xctest */; - productType = "com.apple.product-type.bundle.ui-testing"; - }; - 032DAEFA2607491B00891641 /* TestDeepLinkingUITestsWithHostApp */ = { - isa = PBXNativeTarget; - buildConfigurationList = 032DAF022607491B00891641 /* Build configuration list for PBXNativeTarget "TestDeepLinkingUITestsWithHostApp" */; - buildPhases = ( - 032DAEF72607491B00891641 /* Sources */, - 032DAEF82607491B00891641 /* Frameworks */, - 032DAEF92607491B00891641 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - 032DAF012607491B00891641 /* PBXTargetDependency */, - ); - name = TestDeepLinkingUITestsWithHostApp; - productName = TestDeepLinkingUITestsWithHostApp; - productReference = 032DAEFB2607491B00891641 /* TestDeepLinkingUITestsWithHostApp.xctest */; - productType = "com.apple.product-type.bundle.ui-testing"; - }; - 033608112605E2110032A5DC /* TestDeepLinking */ = { - isa = PBXNativeTarget; - buildConfigurationList = 033608262605E2150032A5DC /* Build configuration list for PBXNativeTarget "TestDeepLinking" */; - buildPhases = ( - A6E708B8F29A1D55D1D76DE9 /* [CP] Check Pods Manifest.lock */, - 0336080E2605E2110032A5DC /* Sources */, - 0336080F2605E2110032A5DC /* Frameworks */, - 033608102605E2110032A5DC /* Resources */, - 249508BA477D5282ACF2EE9E /* [CP] Embed Pods Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = TestDeepLinking; - productName = TestDeepLinking; - productReference = 033608122605E2110032A5DC /* TestDeepLinking.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 0336080A2605E2100032A5DC /* Project object */ = { - isa = PBXProject; - attributes = { - LastSwiftUpdateCheck = 1200; - LastUpgradeCheck = 1200; - TargetAttributes = { - 032DAED92607430600891641 = { - CreatedOnToolsVersion = 12.3; - }; - 032DAEFA2607491B00891641 = { - CreatedOnToolsVersion = 12.3; - TestTargetID = 033608112605E2110032A5DC; - }; - 033608112605E2110032A5DC = { - CreatedOnToolsVersion = 12.0.1; - LastSwiftMigration = 1230; - }; - }; - }; - buildConfigurationList = 0336080D2605E2100032A5DC /* Build configuration list for PBXProject "TestDeepLinking" */; - compatibilityVersion = "Xcode 9.3"; - developmentRegion = en; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 033608092605E2100032A5DC; - productRefGroup = 033608132605E2110032A5DC /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 033608112605E2110032A5DC /* TestDeepLinking */, - 032DAED92607430600891641 /* TestDeepLinkingUITests */, - 032DAEFA2607491B00891641 /* TestDeepLinkingUITestsWithHostApp */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 032DAED82607430600891641 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 032DAEF92607491B00891641 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 033608102605E2110032A5DC /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 03DE13B32606A1B4006D18F5 /* TestDeepLinking.entitlements in Resources */, - 033608222605E2150032A5DC /* LaunchScreen.storyboard in Resources */, - 0336081F2605E2150032A5DC /* Assets.xcassets in Resources */, - 0336081D2605E2110032A5DC /* Main.storyboard in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXShellScriptBuildPhase section */ - 032DAF0826074B6A00891641 /* ShellScript */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - ); - outputFileListPaths = ( - ); - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "xcrun simctl terminate booted io.branch.TestiOSDeepLink\nxcrun simctl uninstall booted io.branch.TestiOSDeepLink\n\n"; - }; - 249508BA477D5282ACF2EE9E /* [CP] Embed Pods Frameworks */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-TestDeepLinking/Pods-TestDeepLinking-frameworks-${CONFIGURATION}-input-files.xcfilelist", - ); - name = "[CP] Embed Pods Frameworks"; - outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-TestDeepLinking/Pods-TestDeepLinking-frameworks-${CONFIGURATION}-output-files.xcfilelist", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-TestDeepLinking/Pods-TestDeepLinking-frameworks.sh\"\n"; - showEnvVarsInLog = 0; - }; - A6E708B8F29A1D55D1D76DE9 /* [CP] Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-TestDeepLinking-checkManifestLockResult.txt", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; - }; -/* End PBXShellScriptBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 032DAED62607430600891641 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 032DAEE82607431D00891641 /* TestDeepLinkWithoutApp.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 032DAEF72607491B00891641 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 032DAEFE2607491B00891641 /* TestDeepLinkingUITestsWithHostApp.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 0336080E2605E2110032A5DC /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 0336081A2605E2110032A5DC /* ViewController.swift in Sources */, - 033608162605E2110032A5DC /* AppDelegate.swift in Sources */, - 033608182605E2110032A5DC /* SceneDelegate.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXTargetDependency section */ - 032DAEE02607430600891641 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 033608112605E2110032A5DC /* TestDeepLinking */; - targetProxy = 032DAEDF2607430600891641 /* PBXContainerItemProxy */; - }; - 032DAF012607491B00891641 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 033608112605E2110032A5DC /* TestDeepLinking */; - targetProxy = 032DAF002607491B00891641 /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - -/* Begin PBXVariantGroup section */ - 0336081B2605E2110032A5DC /* Main.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 0336081C2605E2110032A5DC /* Base */, - ); - name = Main.storyboard; - sourceTree = ""; - }; - 033608202605E2150032A5DC /* LaunchScreen.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 033608212605E2150032A5DC /* Base */, - ); - name = LaunchScreen.storyboard; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 032DAEE22607430600891641 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; - CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = XHGU2TWQZE; - INFOPLIST_FILE = TestDeepLinkingUITests/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 14.3; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@loader_path/Frameworks", - ); - PRODUCT_BUNDLE_IDENTIFIER = com.trusona.TestDeepLinkingUITests; - PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE = ""; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 032DAEE32607430600891641 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; - CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = XHGU2TWQZE; - INFOPLIST_FILE = TestDeepLinkingUITests/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 14.3; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@loader_path/Frameworks", - ); - PRODUCT_BUNDLE_IDENTIFIER = com.trusona.TestDeepLinkingUITests; - PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE = ""; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Release; - }; - 032DAF032607491B00891641 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; - CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = XHGU2TWQZE; - INFOPLIST_FILE = TestDeepLinkingUITestsWithHostApp/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 14.3; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@loader_path/Frameworks", - ); - PRODUCT_BUNDLE_IDENTIFIER = com.trusona.TestDeepLinkingUITestsWithHostApp; - PRODUCT_NAME = "$(TARGET_NAME)"; - TARGETED_DEVICE_FAMILY = "1,2"; - TEST_TARGET_NAME = TestDeepLinking; - }; - name = Debug; - }; - 032DAF042607491B00891641 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; - CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = XHGU2TWQZE; - INFOPLIST_FILE = TestDeepLinkingUITestsWithHostApp/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 14.3; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@loader_path/Frameworks", - ); - PRODUCT_BUNDLE_IDENTIFIER = com.trusona.TestDeepLinkingUITestsWithHostApp; - PRODUCT_NAME = "$(TARGET_NAME)"; - TARGETED_DEVICE_FAMILY = "1,2"; - TEST_TARGET_NAME = TestDeepLinking; - }; - name = Release; - }; - 033608242605E2150032A5DC /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 14.0; - MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; - MTL_FAST_MATH = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - }; - name = Debug; - }; - 033608252605E2150032A5DC /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 14.0; - MTL_ENABLE_DEBUG_INFO = NO; - MTL_FAST_MATH = YES; - SDKROOT = iphoneos; - SWIFT_COMPILATION_MODE = wholemodule; - SWIFT_OPTIMIZATION_LEVEL = "-O"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 033608272605E2150032A5DC /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 86113F63A46AE44E1E8B1648 /* Pods-TestDeepLinking.debug.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; - CLANG_ENABLE_MODULES = YES; - CODE_SIGN_ENTITLEMENTS = TestDeepLinking/TestDeepLinking.entitlements; - CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = R63EM248DP; - EXCLUDED_ARCHS = arm64; - INFOPLIST_FILE = TestDeepLinking/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 14.0; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - PRODUCT_BUNDLE_IDENTIFIER = io.branch.TestiOSDeepLink; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = 1; - }; - name = Debug; - }; - 033608282605E2150032A5DC /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 0EE470FCEAEA1ECC99DC0A89 /* Pods-TestDeepLinking.release.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; - CLANG_ENABLE_MODULES = YES; - CODE_SIGN_ENTITLEMENTS = TestDeepLinking/TestDeepLinking.entitlements; - CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = R63EM248DP; - EXCLUDED_ARCHS = arm64; - INFOPLIST_FILE = TestDeepLinking/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 14.0; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - PRODUCT_BUNDLE_IDENTIFIER = io.branch.TestiOSDeepLink; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = 1; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 032DAEE12607430600891641 /* Build configuration list for PBXNativeTarget "TestDeepLinkingUITests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 032DAEE22607430600891641 /* Debug */, - 032DAEE32607430600891641 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 032DAF022607491B00891641 /* Build configuration list for PBXNativeTarget "TestDeepLinkingUITestsWithHostApp" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 032DAF032607491B00891641 /* Debug */, - 032DAF042607491B00891641 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 0336080D2605E2100032A5DC /* Build configuration list for PBXProject "TestDeepLinking" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 033608242605E2150032A5DC /* Debug */, - 033608252605E2150032A5DC /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 033608262605E2150032A5DC /* Build configuration list for PBXNativeTarget "TestDeepLinking" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 033608272605E2150032A5DC /* Debug */, - 033608282605E2150032A5DC /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 0336080A2605E2100032A5DC /* Project object */; -} diff --git a/TestDeepLinking/TestDeepLinking.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/TestDeepLinking/TestDeepLinking.xcodeproj/project.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index 919434a62..000000000 --- a/TestDeepLinking/TestDeepLinking.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/TestDeepLinking/TestDeepLinking.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/TestDeepLinking/TestDeepLinking.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist deleted file mode 100644 index 18d981003..000000000 --- a/TestDeepLinking/TestDeepLinking.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEDidComputeMac32BitWarning - - - diff --git a/TestDeepLinking/TestDeepLinking.xcworkspace/contents.xcworkspacedata b/TestDeepLinking/TestDeepLinking.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index ba8e3820e..000000000 --- a/TestDeepLinking/TestDeepLinking.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - diff --git a/TestDeepLinking/TestDeepLinking.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/TestDeepLinking/TestDeepLinking.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist deleted file mode 100644 index 18d981003..000000000 --- a/TestDeepLinking/TestDeepLinking.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEDidComputeMac32BitWarning - - - diff --git a/TestDeepLinking/TestDeepLinking/AppDelegate.swift b/TestDeepLinking/TestDeepLinking/AppDelegate.swift deleted file mode 100644 index 8f1e6984d..000000000 --- a/TestDeepLinking/TestDeepLinking/AppDelegate.swift +++ /dev/null @@ -1,45 +0,0 @@ -// -// AppDelegate.swift -// TestDeepLinking -// -// Created by Nidhi on 3/20/21. -// - -import UIKit -import Branch - -@main -class AppDelegate: UIResponder, UIApplicationDelegate { - - - - func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { - - BranchScene.shared().initSession(launchOptions: launchOptions, registerDeepLinkHandler: { (params, error, scene) in - let presentedVC : ViewController = UIApplication.shared.keyWindow?.rootViewController as! ViewController - let jsonData = try! JSONSerialization.data(withJSONObject:params, options: JSONSerialization.WritingOptions.prettyPrinted) - - let jsonString = NSString(data: jsonData, encoding: String.Encoding.utf8.rawValue)! as String - - presentedVC.addText(jsonString) - }) - return true - } - - // MARK: UISceneSession Lifecycle - - func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { - // Called when a new scene session is being created. - // Use this method to select a configuration to create the new scene with. - return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) - } - - func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) { - // Called when the user discards a scene session. - // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions. - // Use this method to release any resources that were specific to the discarded scenes, as they will not return. - } - - -} - diff --git a/TestDeepLinking/TestDeepLinking/Assets.xcassets/AccentColor.colorset/Contents.json b/TestDeepLinking/TestDeepLinking/Assets.xcassets/AccentColor.colorset/Contents.json deleted file mode 100644 index eb8789700..000000000 --- a/TestDeepLinking/TestDeepLinking/Assets.xcassets/AccentColor.colorset/Contents.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "colors" : [ - { - "idiom" : "universal" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/TestDeepLinking/TestDeepLinking/Assets.xcassets/AppIcon.appiconset/Contents.json b/TestDeepLinking/TestDeepLinking/Assets.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index 9221b9bb1..000000000 --- a/TestDeepLinking/TestDeepLinking/Assets.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,98 +0,0 @@ -{ - "images" : [ - { - "idiom" : "iphone", - "scale" : "2x", - "size" : "20x20" - }, - { - "idiom" : "iphone", - "scale" : "3x", - "size" : "20x20" - }, - { - "idiom" : "iphone", - "scale" : "2x", - "size" : "29x29" - }, - { - "idiom" : "iphone", - "scale" : "3x", - "size" : "29x29" - }, - { - "idiom" : "iphone", - "scale" : "2x", - "size" : "40x40" - }, - { - "idiom" : "iphone", - "scale" : "3x", - "size" : "40x40" - }, - { - "idiom" : "iphone", - "scale" : "2x", - "size" : "60x60" - }, - { - "idiom" : "iphone", - "scale" : "3x", - "size" : "60x60" - }, - { - "idiom" : "ipad", - "scale" : "1x", - "size" : "20x20" - }, - { - "idiom" : "ipad", - "scale" : "2x", - "size" : "20x20" - }, - { - "idiom" : "ipad", - "scale" : "1x", - "size" : "29x29" - }, - { - "idiom" : "ipad", - "scale" : "2x", - "size" : "29x29" - }, - { - "idiom" : "ipad", - "scale" : "1x", - "size" : "40x40" - }, - { - "idiom" : "ipad", - "scale" : "2x", - "size" : "40x40" - }, - { - "idiom" : "ipad", - "scale" : "1x", - "size" : "76x76" - }, - { - "idiom" : "ipad", - "scale" : "2x", - "size" : "76x76" - }, - { - "idiom" : "ipad", - "scale" : "2x", - "size" : "83.5x83.5" - }, - { - "idiom" : "ios-marketing", - "scale" : "1x", - "size" : "1024x1024" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/TestDeepLinking/TestDeepLinking/Assets.xcassets/Contents.json b/TestDeepLinking/TestDeepLinking/Assets.xcassets/Contents.json deleted file mode 100644 index 73c00596a..000000000 --- a/TestDeepLinking/TestDeepLinking/Assets.xcassets/Contents.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/TestDeepLinking/TestDeepLinking/Base.lproj/LaunchScreen.storyboard b/TestDeepLinking/TestDeepLinking/Base.lproj/LaunchScreen.storyboard deleted file mode 100644 index 865e9329f..000000000 --- a/TestDeepLinking/TestDeepLinking/Base.lproj/LaunchScreen.storyboard +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/TestDeepLinking/TestDeepLinking/Base.lproj/Main.storyboard b/TestDeepLinking/TestDeepLinking/Base.lproj/Main.storyboard deleted file mode 100644 index 99cb43c0a..000000000 --- a/TestDeepLinking/TestDeepLinking/Base.lproj/Main.storyboard +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/TestDeepLinking/TestDeepLinking/Info.plist b/TestDeepLinking/TestDeepLinking/Info.plist deleted file mode 100644 index 74d99de4a..000000000 --- a/TestDeepLinking/TestDeepLinking/Info.plist +++ /dev/null @@ -1,79 +0,0 @@ - - - - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - $(PRODUCT_BUNDLE_PACKAGE_TYPE) - CFBundleShortVersionString - 1.0 - CFBundleURLTypes - - - CFBundleTypeRole - Editor - CFBundleURLSchemes - - testiOSDeepLink - - - - CFBundleVersion - 1 - LSRequiresIPhoneOS - - UIApplicationSceneManifest - - UIApplicationSupportsMultipleScenes - - UISceneConfigurations - - UIWindowSceneSessionRoleApplication - - - UISceneConfigurationName - Default Configuration - UISceneDelegateClassName - $(PRODUCT_MODULE_NAME).SceneDelegate - UISceneStoryboardFile - Main - - - - - UIApplicationSupportsIndirectInputEvents - - UILaunchStoryboardName - LaunchScreen - UIMainStoryboardFile - Main - UIRequiredDeviceCapabilities - - armv7 - - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - branch_key - key_live_fk7pNcsmBjFPVS2VGlvrZaiazxkxxZ7r - - diff --git a/TestDeepLinking/TestDeepLinking/SceneDelegate.swift b/TestDeepLinking/TestDeepLinking/SceneDelegate.swift deleted file mode 100644 index dfeac44f1..000000000 --- a/TestDeepLinking/TestDeepLinking/SceneDelegate.swift +++ /dev/null @@ -1,64 +0,0 @@ -// -// SceneDelegate.swift -// TestDeepLinking -// -// Created by Nidhi on 3/20/21. -// - -import UIKit -import Branch - -class SceneDelegate: UIResponder, UIWindowSceneDelegate { - - var window: UIWindow? - - - func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { - // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`. - // If using a storyboard, the `window` property will automatically be initialized and attached to the scene. - // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead). - guard let _ = (scene as? UIWindowScene) else { return } - if let userActivity = connectionOptions.userActivities.first { - - BranchScene.shared().scene(scene, continue: userActivity) - } - } - - func sceneDidDisconnect(_ scene: UIScene) { - // Called as the scene is being released by the system. - // This occurs shortly after the scene enters the background, or when its session is discarded. - // Release any resources associated with this scene that can be re-created the next time the scene connects. - // The scene may re-connect later, as its session was not necessarily discarded (see `application:didDiscardSceneSessions` instead). - } - - func sceneDidBecomeActive(_ scene: UIScene) { - // Called when the scene has moved from an inactive state to an active state. - // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive. - } - - func sceneWillResignActive(_ scene: UIScene) { - // Called when the scene will move from an active state to an inactive state. - // This may occur due to temporary interruptions (ex. an incoming phone call). - } - - func sceneWillEnterForeground(_ scene: UIScene) { - // Called as the scene transitions from the background to the foreground. - // Use this method to undo the changes made on entering the background. - } - - func sceneDidEnterBackground(_ scene: UIScene) { - // Called as the scene transitions from the foreground to the background. - // Use this method to save data, release shared resources, and store enough scene-specific state information - // to restore the scene back to its current state. - } - - func scene(_ scene: UIScene, continue userActivity: NSUserActivity) { - BranchScene.shared().scene(scene, continue: userActivity) - } - func scene(_ scene: UIScene, openURLContexts URLContexts: Set) { - BranchScene.shared().scene(scene, openURLContexts: URLContexts) - } - - -} - diff --git a/TestDeepLinking/TestDeepLinking/TestDeepLinking.entitlements b/TestDeepLinking/TestDeepLinking/TestDeepLinking.entitlements deleted file mode 100644 index 343898fc9..000000000 --- a/TestDeepLinking/TestDeepLinking/TestDeepLinking.entitlements +++ /dev/null @@ -1,13 +0,0 @@ - - - - - com.apple.developer.associated-domains - - mnl7s.app.link - mnl7s-alternate.app.link - mnl7s.test-app.link - mnl7s-alternate.test-app.link - - - diff --git a/TestDeepLinking/TestDeepLinking/TestDeepLinking.xctestplan b/TestDeepLinking/TestDeepLinking/TestDeepLinking.xctestplan deleted file mode 100644 index 90b72d85e..000000000 --- a/TestDeepLinking/TestDeepLinking/TestDeepLinking.xctestplan +++ /dev/null @@ -1,36 +0,0 @@ -{ - "configurations" : [ - { - "id" : "21B9F7C4-BF2C-40DB-B313-9320AC57EB78", - "name" : "Configuration 1", - "options" : { - - } - } - ], - "defaultOptions" : { - "codeCoverage" : false, - "targetForVariableExpansion" : { - "containerPath" : "container:TestDeepLinking.xcodeproj", - "identifier" : "033608112605E2110032A5DC", - "name" : "TestDeepLinking" - } - }, - "testTargets" : [ - { - "target" : { - "containerPath" : "container:TestDeepLinking.xcodeproj", - "identifier" : "032DAED92607430600891641", - "name" : "TestDeepLinkingUITests" - } - }, - { - "target" : { - "containerPath" : "container:TestDeepLinking.xcodeproj", - "identifier" : "032DAEFA2607491B00891641", - "name" : "TestDeepLinkingUITestsWithHostApp" - } - } - ], - "version" : 1 -} diff --git a/TestDeepLinking/TestDeepLinking/ViewController.swift b/TestDeepLinking/TestDeepLinking/ViewController.swift deleted file mode 100644 index 0f5a341aa..000000000 --- a/TestDeepLinking/TestDeepLinking/ViewController.swift +++ /dev/null @@ -1,22 +0,0 @@ -// -// ViewController.swift -// TestDeepLinking -// -// Created by Nidhi on 3/20/21. -// - -import UIKit - -class ViewController: UIViewController { - - @IBOutlet var textView: UITextView! - override func viewDidLoad() { - super.viewDidLoad() - } - - func addText(_ text: String) { - textView.text = "" - textView.insertText(text) - } -} - diff --git a/TestDeepLinking/TestDeepLinkingUITests/Info.plist b/TestDeepLinking/TestDeepLinkingUITests/Info.plist deleted file mode 100644 index 64d65ca49..000000000 --- a/TestDeepLinking/TestDeepLinkingUITests/Info.plist +++ /dev/null @@ -1,22 +0,0 @@ - - - - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - $(PRODUCT_BUNDLE_PACKAGE_TYPE) - CFBundleShortVersionString - 1.0 - CFBundleVersion - 1 - - diff --git a/TestDeepLinking/TestDeepLinkingUITests/TestDeepLinkWithoutApp.m b/TestDeepLinking/TestDeepLinkingUITests/TestDeepLinkWithoutApp.m deleted file mode 100644 index 22a741930..000000000 --- a/TestDeepLinking/TestDeepLinkingUITests/TestDeepLinkWithoutApp.m +++ /dev/null @@ -1,64 +0,0 @@ -// -// TestDeepLinkWithoutApp.m -// TestDeepLinking -// -// Created by Nidhi on 3/21/21. -// - -#import - -@interface TestDeepLinkWithoutApp : XCTestCase - -@end - -@implementation TestDeepLinkWithoutApp - -- (void)setUp { - self.continueAfterFailure = YES; - [self addUIInterruptionMonitorWithDescription:@"Open App" handler:^BOOL(XCUIElement * _Nonnull interruptingElement) { - [interruptingElement description]; - XCUIElement *button = interruptingElement.buttons[@"Open"]; - if ([button exists]) { - [button tap]; - return YES; - } - return NO; - }]; - -} - -- (void)tearDown { - // Put teardown code here. This method is called after the invocation of each test method in the class. -} - -- (void)test0OpenLinkWithoutApp { - - XCUIApplication *safariApp = [[XCUIApplication alloc] initWithBundleIdentifier:@"com.apple.mobilesafari"]; - //[safariApp setLaunchArguments: @[@"-u",@"https://ndixit-branch.github.io/TestWebPage.html"]]; - [safariApp launch]; - - sleep(1.0); - [safariApp.buttons[@"URL"] tap]; - //[safariApp.otherElements[@"URL"] tap]; - [safariApp.textFields[@"Search or enter website name"] tap]; - [safariApp typeText:@"https://mnl7s.app.link/CwOJ5aTaNeb"]; - [safariApp.buttons[@"Go"] tap]; - XCUIElement *testBedLink = [[safariApp.webViews descendantsMatchingType:XCUIElementTypeLink] elementBoundByIndex:0]; - - [testBedLink tap]; - - sleep(10); - [safariApp terminate]; - -// XCUIApplication *app = [[XCUIApplication alloc] initWithBundleIdentifier:@"io.branch.TestiOSDeepLink"]; -// -// if ([ app waitForExistenceWithTimeout:5] != NO) { -// NSString *deepLinkData = app.textViews[@"DeepLinkData"].value; -// XCTAssertTrue([deepLinkData containsString:self.deeplinkDataToCheck]); -// } else { -// XCTFail("Application not launched"); -// } -// -} - -@end diff --git a/TestDeepLinking/TestDeepLinkingUITestsWithHostApp/TestDeepLinkingUITestsWithHostApp.m b/TestDeepLinking/TestDeepLinkingUITestsWithHostApp/TestDeepLinkingUITestsWithHostApp.m deleted file mode 100644 index 7e40b4ba8..000000000 --- a/TestDeepLinking/TestDeepLinkingUITestsWithHostApp/TestDeepLinkingUITestsWithHostApp.m +++ /dev/null @@ -1,38 +0,0 @@ -// -// TestDeepLinkingUITestsWithHostApp.m -// TestDeepLinkingUITestsWithHostApp -// -// Created by Nidhi on 3/21/21. -// - -#import - -@interface TestDeepLinkingUITestsWithHostApp : XCTestCase - -@end - -@implementation TestDeepLinkingUITestsWithHostApp - -- (void)setUp { - self.continueAfterFailure = YES; -} - -- (void)tearDown { -} - -- (void)test1OpenApp { - XCUIApplication *app = [[XCUIApplication alloc] init]; - [app launch]; - - sleep(3); - if ([ app waitForExistenceWithTimeout:15] != NO) { - NSString *deepLinkData = app.textViews[@"tvID"].value; - NSLog(@"==== %@" , deepLinkData); - XCTAssertTrue([deepLinkData containsString:@"https:\\/\\/mnl7s.app.link\\/CwOJ5aTaNeb"]); - } else { - XCTFail("Application not launched"); - } -} - - -@end diff --git a/TestHost/AppDelegate.swift b/TestHost/AppDelegate.swift deleted file mode 100644 index c77614d85..000000000 --- a/TestHost/AppDelegate.swift +++ /dev/null @@ -1,37 +0,0 @@ -// -// AppDelegate.swift -// TestHost -// -// Created by Ernest Cho on 7/29/22. -// - -import UIKit -import BranchSDK - -@main -class AppDelegate: UIResponder, UIApplicationDelegate { - - - - func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { - // Override point for customization after application launch. - return true - } - - // MARK: UISceneSession Lifecycle - - func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { - // Called when a new scene session is being created. - // Use this method to select a configuration to create the new scene with. - return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) - } - - func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) { - // Called when the user discards a scene session. - // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions. - // Use this method to release any resources that were specific to the discarded scenes, as they will not return. - } - - -} - diff --git a/TestHost/Assets.xcassets/AccentColor.colorset/Contents.json b/TestHost/Assets.xcassets/AccentColor.colorset/Contents.json deleted file mode 100644 index eb8789700..000000000 --- a/TestHost/Assets.xcassets/AccentColor.colorset/Contents.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "colors" : [ - { - "idiom" : "universal" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/TestHost/Assets.xcassets/AppIcon.appiconset/Contents.json b/TestHost/Assets.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index 9221b9bb1..000000000 --- a/TestHost/Assets.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,98 +0,0 @@ -{ - "images" : [ - { - "idiom" : "iphone", - "scale" : "2x", - "size" : "20x20" - }, - { - "idiom" : "iphone", - "scale" : "3x", - "size" : "20x20" - }, - { - "idiom" : "iphone", - "scale" : "2x", - "size" : "29x29" - }, - { - "idiom" : "iphone", - "scale" : "3x", - "size" : "29x29" - }, - { - "idiom" : "iphone", - "scale" : "2x", - "size" : "40x40" - }, - { - "idiom" : "iphone", - "scale" : "3x", - "size" : "40x40" - }, - { - "idiom" : "iphone", - "scale" : "2x", - "size" : "60x60" - }, - { - "idiom" : "iphone", - "scale" : "3x", - "size" : "60x60" - }, - { - "idiom" : "ipad", - "scale" : "1x", - "size" : "20x20" - }, - { - "idiom" : "ipad", - "scale" : "2x", - "size" : "20x20" - }, - { - "idiom" : "ipad", - "scale" : "1x", - "size" : "29x29" - }, - { - "idiom" : "ipad", - "scale" : "2x", - "size" : "29x29" - }, - { - "idiom" : "ipad", - "scale" : "1x", - "size" : "40x40" - }, - { - "idiom" : "ipad", - "scale" : "2x", - "size" : "40x40" - }, - { - "idiom" : "ipad", - "scale" : "1x", - "size" : "76x76" - }, - { - "idiom" : "ipad", - "scale" : "2x", - "size" : "76x76" - }, - { - "idiom" : "ipad", - "scale" : "2x", - "size" : "83.5x83.5" - }, - { - "idiom" : "ios-marketing", - "scale" : "1x", - "size" : "1024x1024" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/TestHost/Assets.xcassets/Contents.json b/TestHost/Assets.xcassets/Contents.json deleted file mode 100644 index 73c00596a..000000000 --- a/TestHost/Assets.xcassets/Contents.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/TestHost/Base.lproj/LaunchScreen.storyboard b/TestHost/Base.lproj/LaunchScreen.storyboard deleted file mode 100644 index 865e9329f..000000000 --- a/TestHost/Base.lproj/LaunchScreen.storyboard +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/TestHost/NSURLSession+Branch.h b/TestHost/NSURLSession+Branch.h deleted file mode 100644 index 28073f0a1..000000000 --- a/TestHost/NSURLSession+Branch.h +++ /dev/null @@ -1,17 +0,0 @@ -// -// NSURLSession+Branch.h -// BranchSearchDemo -// -// Created by Ernest Cho on 10/11/18. -// Copyright © 2018 Branch Metrics, Inc. All rights reserved. -// - -#import - -NS_ASSUME_NONNULL_BEGIN - -@interface NSURLSession (Branch) - -@end - -NS_ASSUME_NONNULL_END diff --git a/TestHost/NSURLSession+Branch.m b/TestHost/NSURLSession+Branch.m deleted file mode 100644 index 594fc6b11..000000000 --- a/TestHost/NSURLSession+Branch.m +++ /dev/null @@ -1,64 +0,0 @@ -// -// NSURLSession+Branch.m -// BranchSearchDemo -// -// Created by Ernest Cho on 8/19/20. -// Copyright © 2020 Branch Metrics, Inc. All rights reserved. -// - -#import "NSURLSession+Branch.h" -#import - -@implementation NSURLSession (Branch) - -+ (void)load { - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - [self swizzleSelector:@selector(dataTaskWithRequest:completionHandler:) - withSelector:@selector(xxx_dataTaskWithRequest:completionHandler:)]; - }); -} - -// swaps originalSelector with swizzledSelector -+ (void)swizzleSelector:(SEL)originalSelector withSelector:(SEL)swizzledSelector { - Class class = [self class]; - - Method originalMethod = class_getInstanceMethod(class, originalSelector); - Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector); - - method_exchangeImplementations(originalMethod, swizzledMethod); -} - -- (void)logNetworkTrafficRequest:(NSURLRequest *)request data:(NSData *)data response:(NSURLResponse *)response { - NSLog(@"NSURLSessionDataTask Request: %@", request); - - NSData *body = [request HTTPBody]; - if (body) { - NSLog(@"NSURLSessionDataTask Request Body: %@", [NSString stringWithUTF8String:body.bytes]); - } - - NSLog(@"NSURLSessionDataTask Response: %@", response); - - if (data.bytes) { - NSLog(@"NSURLSessionDataTask Response Data: %@", [NSString stringWithUTF8String:data.bytes]); - } -} - -// replacement method for dataTaskWithRequest -- (NSURLSessionDataTask *)xxx_dataTaskWithRequest:(NSURLRequest *)request - completionHandler:(void (^)(NSData *data, NSURLResponse *response, NSError *error))completionHandler { - - // create a new block that just calls the original block after logging the request - void (^completionHandlerWithLogging)(NSData *, NSURLResponse *, NSError *) = ^(NSData *data, NSURLResponse *response, NSError *error) { - if (completionHandler) { - - [self logNetworkTrafficRequest:request data:data response:response]; - - completionHandler(data, response, error); - } - }; - - return [self xxx_dataTaskWithRequest:request completionHandler:completionHandlerWithLogging]; -} - -@end diff --git a/TestHost/SceneDelegate.swift b/TestHost/SceneDelegate.swift deleted file mode 100644 index ee2ca8f1b..000000000 --- a/TestHost/SceneDelegate.swift +++ /dev/null @@ -1,57 +0,0 @@ -// -// SceneDelegate.swift -// TestHost -// -// Created by Ernest Cho on 7/29/22. -// - -import UIKit -import BranchSDK - -class SceneDelegate: UIResponder, UIWindowSceneDelegate { - - var window: UIWindow? - - - func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { - // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`. - // If using a storyboard, the `window` property will automatically be initialized and attached to the scene. - // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead). - guard let _ = (scene as? UIWindowScene) else { return } - - if let userActivity = connectionOptions.userActivities.first { - BranchScene.shared().scene(scene, continue: userActivity) - } - } - - func sceneDidDisconnect(_ scene: UIScene) { - // Called as the scene is being released by the system. - // This occurs shortly after the scene enters the background, or when its session is discarded. - // Release any resources associated with this scene that can be re-created the next time the scene connects. - // The scene may re-connect later, as its session was not necessarily discarded (see `application:didDiscardSceneSessions` instead). - } - - func sceneDidBecomeActive(_ scene: UIScene) { - // Called when the scene has moved from an inactive state to an active state. - // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive. - } - - func sceneWillResignActive(_ scene: UIScene) { - // Called when the scene will move from an active state to an inactive state. - // This may occur due to temporary interruptions (ex. an incoming phone call). - } - - func sceneWillEnterForeground(_ scene: UIScene) { - // Called as the scene transitions from the background to the foreground. - // Use this method to undo the changes made on entering the background. - } - - func sceneDidEnterBackground(_ scene: UIScene) { - // Called as the scene transitions from the foreground to the background. - // Use this method to save data, release shared resources, and store enough scene-specific state information - // to restore the scene back to its current state. - } - - -} - diff --git a/TestHost/TestHost-Bridging-Header.h b/TestHost/TestHost-Bridging-Header.h deleted file mode 100644 index 1b2cb5d6d..000000000 --- a/TestHost/TestHost-Bridging-Header.h +++ /dev/null @@ -1,4 +0,0 @@ -// -// Use this file to import your target's public headers that you would like to expose to Swift. -// - diff --git a/TestHost/ViewController.swift b/TestHost/ViewController.swift deleted file mode 100644 index ab76ab909..000000000 --- a/TestHost/ViewController.swift +++ /dev/null @@ -1,19 +0,0 @@ -// -// ViewController.swift -// TestHost -// -// Created by Ernest Cho on 7/29/22. -// - -import UIKit - -class ViewController: UIViewController { - - override func viewDidLoad() { - super.viewDidLoad() - // Do any additional setup after loading the view. - } - - -} - diff --git a/TestHostTests/TestHostTests.swift b/TestHostTests/TestHostTests.swift deleted file mode 100644 index 231b61ed4..000000000 --- a/TestHostTests/TestHostTests.swift +++ /dev/null @@ -1,36 +0,0 @@ -// -// TestHostTests.swift -// TestHostTests -// -// Created by Ernest Cho on 7/29/22. -// - -import XCTest -@testable import TestHost - -class TestHostTests: XCTestCase { - - override func setUpWithError() throws { - // Put setup code here. This method is called before the invocation of each test method in the class. - } - - override func tearDownWithError() throws { - // Put teardown code here. This method is called after the invocation of each test method in the class. - } - - func testExample() throws { - // This is an example of a functional test case. - // Use XCTAssert and related functions to verify your tests produce the correct results. - // Any test you write for XCTest can be annotated as throws and async. - // Mark your test throws to produce an unexpected failure when your test encounters an uncaught error. - // Mark your test async to allow awaiting for asynchronous code to complete. Check the results with assertions afterwards. - } - - func testPerformanceExample() throws { - // This is an example of a performance test case. - self.measure { - // Put the code you want to measure the time of here. - } - } - -} diff --git a/TestHostUITests/TestHostUITests.swift b/TestHostUITests/TestHostUITests.swift deleted file mode 100644 index 2f5a1af58..000000000 --- a/TestHostUITests/TestHostUITests.swift +++ /dev/null @@ -1,41 +0,0 @@ -// -// TestHostUITests.swift -// TestHostUITests -// -// Created by Ernest Cho on 7/29/22. -// - -import XCTest - -class TestHostUITests: XCTestCase { - - override func setUpWithError() throws { - // Put setup code here. This method is called before the invocation of each test method in the class. - - // In UI tests it is usually best to stop immediately when a failure occurs. - continueAfterFailure = false - - // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. - } - - override func tearDownWithError() throws { - // Put teardown code here. This method is called after the invocation of each test method in the class. - } - - func testExample() throws { - // UI tests must launch the application that they test. - let app = XCUIApplication() - app.launch() - - // Use XCTAssert and related functions to verify your tests produce the correct results. - } - - func testLaunchPerformance() throws { - if #available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 7.0, *) { - // This measures how long it takes to launch your application. - measure(metrics: [XCTApplicationLaunchMetric()]) { - XCUIApplication().launch() - } - } - } -} diff --git a/TestHostUITests/TestHostUITestsLaunchTests.swift b/TestHostUITests/TestHostUITestsLaunchTests.swift deleted file mode 100644 index a49cc5663..000000000 --- a/TestHostUITests/TestHostUITestsLaunchTests.swift +++ /dev/null @@ -1,32 +0,0 @@ -// -// TestHostUITestsLaunchTests.swift -// TestHostUITests -// -// Created by Ernest Cho on 7/29/22. -// - -import XCTest - -class TestHostUITestsLaunchTests: XCTestCase { - - override class var runsForEachTargetApplicationUIConfiguration: Bool { - true - } - - override func setUpWithError() throws { - continueAfterFailure = false - } - - func testLaunch() throws { - let app = XCUIApplication() - app.launch() - - // Insert steps here to perform after app launch but before taking a screenshot, - // such as logging into a test account or navigating somewhere in the app - - let attachment = XCTAttachment(screenshot: app.screenshot()) - attachment.name = "Launch Screen" - attachment.lifetime = .keepAlways - add(attachment) - } -} diff --git a/fastlane/.gitignore b/fastlane/.gitignore deleted file mode 100644 index 23d325c5e..000000000 --- a/fastlane/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -report.* -test_output -README.md -.version diff --git a/fastlane/Appfile b/fastlane/Appfile deleted file mode 100644 index 180306309..000000000 --- a/fastlane/Appfile +++ /dev/null @@ -1,6 +0,0 @@ -# app_identifier("[[APP_IDENTIFIER]]") # The bundle identifier of your app -# apple_id("[[APPLE_ID]]") # Your Apple email address - - -# For more information about the Appfile, see: -# https://docs.fastlane.tools/advanced/#appfile diff --git a/fastlane/Fastfile b/fastlane/Fastfile deleted file mode 100644 index 6b9f7fda6..000000000 --- a/fastlane/Fastfile +++ /dev/null @@ -1,48 +0,0 @@ -require_relative 'lib/helper/cocoapods_helper' -require_relative 'lib/helper/version_helper' - -fastlane_version "2.69.0" - -lane :prepare_pods do - # This helps optimize CI with caching by testing whether a pod install is necessary - # from cocoapods_helper - # pod_install_if_required '../Branch-TestBed' - # Can also turn on verbose output and disable repo update - # pod_install_if_required '../Branch-TestBed', verbose: true, repo_update: false -end - -lane :unit_tests do - prepare_pods - # This testplan only runs unit tests for PR verification. - scan scheme: 'Branch-TestBed-CI' - slather( - cobertura_xml: true, - output_directory: "./fastlane/test_output", - proj: "./Branch-TestBed/Branch-TestBed.xcodeproj", - #workspace: "./Branch-TestBed/Branch-TestBed.xcworkspace", - scheme: "Branch-TestBed-CI" - ) -end - -lane :integration_tests do - prepare_pods - # This testplan includes unit tests as well as integration tests. - scan scheme: 'Branch-TestBed' -end - -# bundle exec fastlane version_bump version:patch # default -# bundle exec fastlane version_bump version:minor -# bundle exec fastlane version_bump version:major -# bundle exec fastlane version_bump version:1.41.0 -lane :version_bump do |opts| - # from version_helper - next_version = update_sdk_version opts - sh 'git', 'commit', '-a', '-m', "[release] #{next_version}" -end - -lane :current_version do - UI.message 'Generating fastlane/.version with podspec version' - File.open('.version', 'w') do |f| - f.puts current_pod_version - end -end diff --git a/fastlane/Matchfile b/fastlane/Matchfile deleted file mode 100644 index e8fc3631e..000000000 --- a/fastlane/Matchfile +++ /dev/null @@ -1,14 +0,0 @@ -# branch private repo for fastlane match -git_url("git@github.com:BranchMetrics/ios-signing-certificates.git") - -storage_mode("git") - -type("development") # The default type, can be: appstore, adhoc, enterprise or development - -app_identifier(["io.branch.sdk.Branch-TestBed"]) -username("sdk-team@branch.io") - -# For all available options run `fastlane match --help` -# Remove the # in the beginning of the line to enable the other options - -# The docs are available on https://docs.fastlane.tools/actions/match diff --git a/fastlane/Pluginfile b/fastlane/Pluginfile deleted file mode 100644 index e69de29bb..000000000 diff --git a/fastlane/Scanfile b/fastlane/Scanfile deleted file mode 100644 index 11cd4873f..000000000 --- a/fastlane/Scanfile +++ /dev/null @@ -1,6 +0,0 @@ -project 'Branch-TestBed/Branch-TestBed.xcodeproj' -device 'iPhone 12' -output_types 'junit,html' -code_coverage true -clean true -output_directory 'fastlane/test_output/' \ No newline at end of file diff --git a/fastlane/lib/helper/cocoapods_helper.rb b/fastlane/lib/helper/cocoapods_helper.rb deleted file mode 100644 index fe71d4dee..000000000 --- a/fastlane/lib/helper/cocoapods_helper.rb +++ /dev/null @@ -1,86 +0,0 @@ -require 'cocoapods' -require 'pathname' - -module CocoapodsHelper - UI = FastlaneCore::UI - - class CocoapodsHelperException < RuntimeError; end - - # Following the lead of npm ci (https://docs.npmjs.com/cli/v7/commands/npm-ci): - # The Podfile.lock must exist. - # The Podfile and Podfile.lock must be in sync. - # A pod install may be required, but it is an error to generate a change to - # the Podfile.lock, including when it's missing. If pod install is run, it - # may regenerate Pods/Manifest.lock or the entire Pods folder if the cache - # is out of sync. - def pod_install_required?(podfile_folder) - podfile_folder = File.expand_path podfile_folder - podfile_path = File.join podfile_folder, 'Podfile' - raise ArgumentError, "No Podfile at #{podfile_folder}" unless File.readable?(podfile_path) - - # Podfile must be evalled in its current directory in order to resolve - # the require_relative at the top. - podfile = Dir.chdir(podfile_folder) { Pod::Podfile.from_file podfile_path } - - # From here on we expect pod install to succeed. We just check whether it's - # necessary. The Podfile.from_file call above can raise if the Podfile - # contains errors. In that case, pod install will also fail, so we allow - # the exception to be raised instead of returning true. - - lockfile_path = File.join podfile_folder, 'Podfile.lock' - manifest_path = File.join podfile_folder, 'Pods', 'Manifest.lock' - - # Don't regenerate the lockfile - raise CocoapodsHelperException, "#{lockfile_path} missing or not readable." unless File.readable?(lockfile_path) - - return true unless File.readable?(manifest_path) - - # This validates the Podfile.lock for yaml formatting at least and makes - # the lockfile hash available to check the Podfile checksum later. - lockfile = Pod::Lockfile.from_file Pathname.new lockfile_path - lockfile_contents = File.read lockfile_path - - begin - # diff the contents of Podfile.lock and Pods/Manifest.lock - # This is just what is done in the "[CP] Check Pods Manifest.lock" script - # build phase in a project using CocoaPods. This is a stricter requirement - # than semantic comparison of the two lockfile hashes. - return true unless lockfile_contents == File.read(manifest_path) - - # compare checksum of Podfile with checksum in Podfile.lock in case Podfile - # updated since last pod install/update. - return false if lockfile.to_hash["PODFILE CHECKSUM"] == podfile.checksum - rescue StandardError, Pod::PlainInformative => e - # Any error from Pod::Lockfile.from_file or File.read after verifying a - # file exists and is readable. pod install will regenerate these files. - UI.error e.message - return true - end - - # Don't regenerate the lockfile. - raise CocoapodsHelperException, "Podfile checksum #{podfile.checksum} does not match PODFILE CHECKSUM in Podfile.lock." - end - - def pod_install_if_required(podfile_folder, verbose: false, repo_update: true) - podfile_folder = File.expand_path podfile_folder - install_required = pod_install_required? podfile_folder - UI.message "pod install #{install_required ? '' : 'not '}required in #{podfile_folder}" - return unless install_required - - command = %w[pod install] - command << '--silent' unless verbose - command << '--repo-update' if repo_update - - Dir.chdir(podfile_folder) { Fastlane::Action.sh(*command) } - end - - def current_pod_version - # Get current version from podspec - podspec = File.open('../BranchSDK.podspec', 'r') do |f| - eval f.read - end - podspec.version - end -end - -include CocoapodsHelper diff --git a/fastlane/lib/helper/version_helper.rb b/fastlane/lib/helper/version_helper.rb deleted file mode 100644 index 5bde29d52..000000000 --- a/fastlane/lib/helper/version_helper.rb +++ /dev/null @@ -1,89 +0,0 @@ -require 'CFPropertyList' -require 'pattern_patch' -require 'xcodeproj' - -module VersionHelper - # Updates the SDK version from the Fastfile lane opts - def update_sdk_version(opts) - # Shell out to agvtool to increment the build number - Dir.chdir('../carthage-files') { Fastlane::Action.sh(%w[agvtool bump]) } - # Update the MARKETING_VERSION using patch, minor, major or an actual version number - next_version = update_project_marketing_version '../carthage-files/BranchSDK.xcodeproj', opts[:version] - - # Update BNCConfig.m - PatternPatch::Patch.new( - regexp: /(BNC_SDK_VERSION.*@")(.*)(";)/, - text: "\\1#{next_version}\\3", - mode: :replace - ).apply '../Branch-SDK/BNCConfig.m' - - # Update Branch.podspec - PatternPatch::Patch.new( - regexp: /(s.version.*=\s*")(.*)(")/, - text: "\\1#{next_version}\\3", - mode: :replace - ).apply '../Branch.podspec' - - update_testbed_framework_info_plist next_version - - next_version - end - - # agvtool doesn't do this for the marketing version - # Pass an actual version or major, minor or patch for an automatic bump - # If the version includes a suffix like -beta.1, that will be removed in - # the automatic bump. - def new_version(version, next_version) - # Remove any suffix beginning with a hyphen, e.g. 1.2.3-beta.1 -> 1.2.3 - components = version.sub(/-.*$/, '').split '.' - - case next_version - when 'patch', nil - components[2] = components[2].to_i + 1 - when 'minor' - components[1] = components[1].to_i + 1 - when 'major' - components[0] = components[0].to_i + 1 - else - return next_version - end - - components.join '.' - end - - # Update MARKETING_VERSION to the specified version in the specified project - # at project_path. - def update_project_marketing_version(project_path, version) - # raises - project = Xcodeproj::Project.open project_path - framework_targets = project.native_targets.reject &:test_target_type? - current_marketing_version = framework_targets.first.resolved_build_setting('MARKETING_VERSION')['Release'] - - next_version = new_version current_marketing_version, version - - # TODO: Isn't this a project-level setting? - framework_targets.reject(&:test_target_type?).each do |target| - target.build_configuration_list.set_setting 'MARKETING_VERSION', next_version - end - - # raises - project.save - - next_version - end - - def update_testbed_framework_info_plist(marketing_version) - plist = CFPropertyList::List.new file: '../Branch-TestBed/Framework-Info.plist' - data = CFPropertyList.native_types(plist.value) - - data['CFBundleShortVersionString'] = marketing_version - # Ordinarily CFBundleVersion is the project version (build number), not the marketing version - # Following the lead of the existing script here. - data['CFBundleVersion'] = marketing_version - - plist.value = CFPropertyList.guess data - plist.save '../Branch-TestBed/Framework-Info.plist', CFPropertyList::List::FORMAT_BINARY - end -end - -include VersionHelper