mirror of
https://github.com/zhigang1992/facebook-ios-sdk.git
synced 2026-04-30 02:16:16 +08:00
Unit Test Hardening (FBSDKAppLinkResolver)
Summary: The main goal of this diff is to remove OHHTPStubs from the FBSDKAppLinkResolver test code. The easiest way to do that has been to extract the request building part from FBSDKAppLinkResolver to it own class. These allows us to: - Assert correctness over some parts of the request independently - Inject a builder mock in FBSDKAppLinkResolver so we can control the FBSDKGraphRequest and inject the response we want, without having to mock the http layer at all. Reviewed By: joesus Differential Revision: D24077192 fbshipit-source-id: 54141fe1a0533bc97503e7a241387c0d0c4da5e3
This commit is contained in:
committed by
Facebook GitHub Bot
parent
6538b2700b
commit
6771546b8e
@@ -62,6 +62,7 @@ Pod::Spec.new do |s|
|
||||
'FBSDKCoreKit/FBSDKCoreKit/*.h',
|
||||
'FBSDKCoreKit/FBSDKCoreKit/AppEvents/*.h',
|
||||
'FBSDKCoreKit/FBSDKCoreKit/AppLink/*.h',
|
||||
'FBSDKCoreKit/FBSDKCoreKit/AppLink/Resolver/*.h',
|
||||
'FBSDKCoreKit/FBSDKCoreKit/GraphAPI/*.h'
|
||||
ss.private_header_files = 'FBSDKCoreKit/FBSDKCoreKit/Internal/**/*.h',
|
||||
'FBSDKCoreKit/FBSDKCoreKit/AppEvents/Internal/**/*.h'
|
||||
|
||||
@@ -68,6 +68,11 @@
|
||||
0384CED1208E606B0013D404 /* FBSDKAccessTokenExpirer.m in Sources */ = {isa = PBXBuildFile; fileRef = 033429B120894D4700C94913 /* FBSDKAccessTokenExpirer.m */; };
|
||||
2A3DA4161CB4C0F600339BD4 /* FBSDKAppLinkUtilityTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 2A3DA4151CB4C0F600339BD4 /* FBSDKAppLinkUtilityTests.m */; };
|
||||
40853B9424C8C43300A7CB16 /* FBSDKJSONValueTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 40853B9324C8C43300A7CB16 /* FBSDKJSONValueTests.m */; };
|
||||
45540D9125271A4B008E853E /* FBSDKAppLinkResolverRequestBuilder.h in Headers */ = {isa = PBXBuildFile; fileRef = 45540D8F25271A4B008E853E /* FBSDKAppLinkResolverRequestBuilder.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
45540D9225271A4B008E853E /* FBSDKAppLinkResolverRequestBuilder.h in Headers */ = {isa = PBXBuildFile; fileRef = 45540D8F25271A4B008E853E /* FBSDKAppLinkResolverRequestBuilder.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
45540D9325271A4B008E853E /* FBSDKAppLinkResolverRequestBuilder.m in Sources */ = {isa = PBXBuildFile; fileRef = 45540D9025271A4B008E853E /* FBSDKAppLinkResolverRequestBuilder.m */; };
|
||||
45540D9425271A4B008E853E /* FBSDKAppLinkResolverRequestBuilder.m in Sources */ = {isa = PBXBuildFile; fileRef = 45540D9025271A4B008E853E /* FBSDKAppLinkResolverRequestBuilder.m */; };
|
||||
45540DB125271A88008E853E /* FBSDKAppLinkResolverRequestBuilderTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 45540DB025271A88008E853E /* FBSDKAppLinkResolverRequestBuilderTests.m */; };
|
||||
4AF47CF31F42468E00A57A67 /* FBSDKDeviceUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = 4AF47CF11F42468D00A57A67 /* FBSDKDeviceUtilities.m */; };
|
||||
4AF47CF41F42468E00A57A67 /* FBSDKDeviceUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = 4AF47CF11F42468D00A57A67 /* FBSDKDeviceUtilities.m */; };
|
||||
4AF47CF51F42468E00A57A67 /* FBSDKDeviceUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = 4AF47CF21F42468D00A57A67 /* FBSDKDeviceUtilities.h */; };
|
||||
@@ -1207,6 +1212,9 @@
|
||||
033429B120894D4700C94913 /* FBSDKAccessTokenExpirer.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBSDKAccessTokenExpirer.m; sourceTree = "<group>"; };
|
||||
2A3DA4151CB4C0F600339BD4 /* FBSDKAppLinkUtilityTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBSDKAppLinkUtilityTests.m; sourceTree = "<group>"; };
|
||||
40853B9324C8C43300A7CB16 /* FBSDKJSONValueTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBSDKJSONValueTests.m; sourceTree = "<group>"; };
|
||||
45540D8F25271A4B008E853E /* FBSDKAppLinkResolverRequestBuilder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBSDKAppLinkResolverRequestBuilder.h; sourceTree = "<group>"; };
|
||||
45540D9025271A4B008E853E /* FBSDKAppLinkResolverRequestBuilder.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBSDKAppLinkResolverRequestBuilder.m; sourceTree = "<group>"; };
|
||||
45540DB025271A88008E853E /* FBSDKAppLinkResolverRequestBuilderTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = FBSDKAppLinkResolverRequestBuilderTests.m; path = AppLinks/FBSDKAppLinkResolverRequestBuilderTests.m; sourceTree = "<group>"; };
|
||||
4AF47CF11F42468D00A57A67 /* FBSDKDeviceUtilities.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBSDKDeviceUtilities.m; sourceTree = "<group>"; };
|
||||
4AF47CF21F42468D00A57A67 /* FBSDKDeviceUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBSDKDeviceUtilities.h; sourceTree = "<group>"; };
|
||||
4AF47CFE1F424A8700A57A67 /* CoreImage.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreImage.framework; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS11.0.sdk/System/Library/Frameworks/CoreImage.framework; sourceTree = DEVELOPER_DIR; };
|
||||
@@ -1755,6 +1763,8 @@
|
||||
7E5557361A8D833100344F86 /* FBSDKAppLinkResolver.h */,
|
||||
7E5557351A8D833100344F86 /* FBSDKAppLinkResolver.m */,
|
||||
52963A69215992F100C7B252 /* FBSDKAppLinkResolving.h */,
|
||||
45540D8F25271A4B008E853E /* FBSDKAppLinkResolverRequestBuilder.h */,
|
||||
45540D9025271A4B008E853E /* FBSDKAppLinkResolverRequestBuilder.m */,
|
||||
);
|
||||
path = Resolver;
|
||||
sourceTree = "<group>";
|
||||
@@ -1860,6 +1870,7 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
7E55573A1A8D834B00344F86 /* FBSDKAppLinkResolverTests.m */,
|
||||
45540DB025271A88008E853E /* FBSDKAppLinkResolverRequestBuilderTests.m */,
|
||||
);
|
||||
name = AppLinks;
|
||||
sourceTree = "<group>";
|
||||
@@ -2955,6 +2966,7 @@
|
||||
81B71D6F1D19C87400933E93 /* FBSDKInternalUtility.h in Headers */,
|
||||
81B71D701D19C87400933E93 /* FBSDKConstants.h in Headers */,
|
||||
BFC0244A237B6B0E00A596EE /* FBSDKSuggestedEventsIndexer.h in Headers */,
|
||||
45540D9225271A4B008E853E /* FBSDKAppLinkResolverRequestBuilder.h in Headers */,
|
||||
81B71D711D19C87400933E93 /* FBSDKWebDialog.h in Headers */,
|
||||
52963A95215992F400C7B252 /* FBSDKWebViewAppLinkResolver.h in Headers */,
|
||||
81B71D721D19C87400933E93 /* FBSDKMonotonicTime.h in Headers */,
|
||||
@@ -3039,6 +3051,7 @@
|
||||
52963AAC2159A16E00C7B252 /* FBSDKMeasurementEvent.h in Headers */,
|
||||
899C3CF81A8BF73A00EA8658 /* FBSDKProfilePictureView.h in Headers */,
|
||||
891687EE1AB38C7C00F55364 /* FBSDKButton.h in Headers */,
|
||||
45540D9125271A4B008E853E /* FBSDKAppLinkResolverRequestBuilder.h in Headers */,
|
||||
F94310F424F8D608002441F1 /* FBSDKSKAdNetworkRule.h in Headers */,
|
||||
52963A7E215992F400C7B252 /* FBSDKAppLinkResolving.h in Headers */,
|
||||
894C0AF31A6F21A1009137EF /* FBSDKBridgeAPIProtocol.h in Headers */,
|
||||
@@ -3868,6 +3881,7 @@
|
||||
5D81B424238739E600B02B2E /* FBSDKIntegrityManager.m in Sources */,
|
||||
81B71D011D19C87400933E93 /* FBSDKGraphRequestPiggybackManager.m in Sources */,
|
||||
81B71D021D19C87400933E93 /* FBSDKAppEventsStateManager.m in Sources */,
|
||||
45540D9425271A4B008E853E /* FBSDKAppLinkResolverRequestBuilder.m in Sources */,
|
||||
81B71D031D19C87400933E93 /* FBSDKServerConfigurationManager.m in Sources */,
|
||||
81B71D041D19C87400933E93 /* FBSDKGraphRequest.m in Sources */,
|
||||
F9CBE51424E090590097B442 /* FBSDKSKAdNetworkReporter.m in Sources */,
|
||||
@@ -3997,6 +4011,7 @@
|
||||
5D81B423238739E600B02B2E /* FBSDKIntegrityManager.m in Sources */,
|
||||
9DA81B2A1AA65FA200B9FE0B /* FBSDKGraphRequestPiggybackManager.m in Sources */,
|
||||
9D0BC1601A8D428700BE8BA4 /* FBSDKAppEventsStateManager.m in Sources */,
|
||||
45540D9325271A4B008E853E /* FBSDKAppLinkResolverRequestBuilder.m in Sources */,
|
||||
89830F2C1A7805D100226ABB /* FBSDKServerConfigurationManager.m in Sources */,
|
||||
9DC658961A6EE5C500B85AAF /* FBSDKGraphRequest.m in Sources */,
|
||||
F9CBE51224E085CD0097B442 /* FBSDKSKAdNetworkReporter.m in Sources */,
|
||||
@@ -4165,6 +4180,7 @@
|
||||
F428430B246B427700CD4393 /* FBSDKServerConfigurationManagerTests.m in Sources */,
|
||||
F9CEF1EB24F769F900EB0C3D /* FBSDKSKAdNetworkReporterTests.m in Sources */,
|
||||
F98D1D73251297A900276B68 /* FBSDKAppEventsConfigurationManagerTests.m in Sources */,
|
||||
45540DB125271A88008E853E /* FBSDKAppLinkResolverRequestBuilderTests.m in Sources */,
|
||||
5DAB01F123A1831A005495FB /* FBSDKCrashObserverTests.m in Sources */,
|
||||
F40B24C224732DD90059351C /* Fuzzer.swift in Sources */,
|
||||
40853B9424C8C43300A7CB16 /* FBSDKJSONValueTests.m in Sources */,
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
|
||||
#import "FBSDKAccessToken.h"
|
||||
#import "FBSDKAppLink.h"
|
||||
#import "FBSDKAppLinkResolverRequestBuilder.h"
|
||||
#import "FBSDKAppLinkTarget.h"
|
||||
#import "FBSDKGraphRequest+Internal.h"
|
||||
#import "FBSDKGraphRequestConnection.h"
|
||||
@@ -48,6 +49,7 @@ static NSString *const kAppLinksKey = @"app_links";
|
||||
|
||||
@property (nonatomic, strong) NSMutableDictionary<NSURL *, FBSDKAppLink *> *cachedFBSDKAppLinks;
|
||||
@property (nonatomic, assign) UIUserInterfaceIdiom userInterfaceIdiom;
|
||||
@property (nonatomic, strong) FBSDKAppLinkResolverRequestBuilder *requestBuilder;
|
||||
@end
|
||||
|
||||
@implementation FBSDKAppLinkResolver
|
||||
@@ -62,6 +64,27 @@ static NSString *const kAppLinksKey = @"app_links";
|
||||
if (self = [super init]) {
|
||||
self.cachedFBSDKAppLinks = [NSMutableDictionary dictionary];
|
||||
self.userInterfaceIdiom = userInterfaceIdiom;
|
||||
self.requestBuilder = [FBSDKAppLinkResolverRequestBuilder new];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)initWithUserInterfaceIdiom:(UIUserInterfaceIdiom)userInterfaceIdiom andRequestBuilder:(FBSDKAppLinkResolverRequestBuilder *)builder
|
||||
{
|
||||
if (self = [super init]) {
|
||||
self.cachedFBSDKAppLinks = [NSMutableDictionary dictionary];
|
||||
self.userInterfaceIdiom = userInterfaceIdiom;
|
||||
self.requestBuilder = builder;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)initWithRequestBuilder:(FBSDKAppLinkResolverRequestBuilder *)builder
|
||||
{
|
||||
if (self = [super init]) {
|
||||
self.cachedFBSDKAppLinks = [NSMutableDictionary dictionary];
|
||||
self.userInterfaceIdiom = UI_USER_INTERFACE_IDIOM();
|
||||
self.requestBuilder = builder;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
@@ -79,9 +102,9 @@ static NSString *const kAppLinksKey = @"app_links";
|
||||
[FBSDKLogger singleShotLogEntry:FBSDKLoggingBehaviorDeveloperErrors
|
||||
logEntry:@"A user access token or clientToken is required to use FBAppLinkResolver"];
|
||||
}
|
||||
|
||||
NSMutableDictionary<NSURL *, FBSDKAppLink *> *appLinks = [NSMutableDictionary dictionary];
|
||||
NSMutableArray<NSURL *> *toFind = [NSMutableArray array];
|
||||
NSMutableArray<NSString *> *toFindStrings = [NSMutableArray array];
|
||||
|
||||
@synchronized(self.cachedFBSDKAppLinks) {
|
||||
for (NSURL *url in urls) {
|
||||
@@ -89,86 +112,68 @@ static NSString *const kAppLinksKey = @"app_links";
|
||||
[FBSDKTypeUtility dictionary:appLinks setObject:self.cachedFBSDKAppLinks[url] forKey:url];
|
||||
} else {
|
||||
[FBSDKTypeUtility array:toFind addObject:url];
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
NSString *toFindString = [url.absoluteString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
|
||||
#pragma clang diagnostic pop
|
||||
if (toFindString) {
|
||||
[FBSDKTypeUtility array:toFindStrings addObject:toFindString];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (toFind.count == 0) {
|
||||
// All of the URLs have already been found.
|
||||
handler(_cachedFBSDKAppLinks, nil);
|
||||
handler(appLinks, nil);
|
||||
return;
|
||||
}
|
||||
NSMutableArray<NSString *> *fields = [NSMutableArray arrayWithObject:kIOSKey];
|
||||
|
||||
NSString *idiomSpecificField = nil;
|
||||
|
||||
switch (self.userInterfaceIdiom) {
|
||||
case UIUserInterfaceIdiomPad:
|
||||
idiomSpecificField = kIPadKey;
|
||||
break;
|
||||
case UIUserInterfaceIdiomPhone:
|
||||
idiomSpecificField = kIPhoneKey;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (idiomSpecificField) {
|
||||
[FBSDKTypeUtility array:fields addObject:idiomSpecificField];
|
||||
}
|
||||
NSString *path = [NSString stringWithFormat:@"?fields=%@.fields(%@)&ids=%@",
|
||||
kAppLinksKey,
|
||||
[fields componentsJoinedByString:@","],
|
||||
[toFindStrings componentsJoinedByString:@","]];
|
||||
FBSDKGraphRequest *request = [[FBSDKGraphRequest alloc] initWithGraphPath:path
|
||||
parameters:nil
|
||||
flags:FBSDKGraphRequestFlagDoNotInvalidateTokenOnError | FBSDKGraphRequestFlagDisableErrorRecovery];
|
||||
FBSDKGraphRequest *request = [self.requestBuilder requestForURLs:urls];
|
||||
|
||||
[request startWithCompletionHandler:^(FBSDKGraphRequestConnection *connection, id result, NSError *error) {
|
||||
if (error) {
|
||||
handler(@{}, error);
|
||||
return;
|
||||
}
|
||||
|
||||
for (NSURL *url in toFind) {
|
||||
id nestedObject = result[url.absoluteString][kAppLinksKey];
|
||||
NSMutableArray *rawTargets = [NSMutableArray array];
|
||||
if (idiomSpecificField) {
|
||||
[rawTargets addObjectsFromArray:nestedObject[idiomSpecificField]];
|
||||
}
|
||||
[rawTargets addObjectsFromArray:nestedObject[kIOSKey]];
|
||||
FBSDKAppLink *link = [self buildAppLinkForURL:url inResults:result];
|
||||
|
||||
NSMutableArray<FBSDKAppLinkTarget *> *targets = [NSMutableArray arrayWithCapacity:rawTargets.count];
|
||||
for (id rawTarget in rawTargets) {
|
||||
[FBSDKTypeUtility array:targets addObject:[FBSDKAppLinkTarget appLinkTargetWithURL:[NSURL URLWithString:rawTarget[kURLKey]]
|
||||
appStoreId:rawTarget[kIOSAppStoreIdKey]
|
||||
appName:rawTarget[kIOSAppNameKey]]];
|
||||
}
|
||||
|
||||
id webTarget = nestedObject[kWebKey];
|
||||
NSString *webFallbackString = webTarget[kURLKey];
|
||||
NSURL *fallbackUrl = webFallbackString ? [NSURL URLWithString:webFallbackString] : url;
|
||||
|
||||
NSNumber *shouldFallback = webTarget[kShouldFallbackKey];
|
||||
if (shouldFallback != nil && !shouldFallback.boolValue) {
|
||||
fallbackUrl = nil;
|
||||
}
|
||||
|
||||
FBSDKAppLink *link = [FBSDKAppLink appLinkWithSourceURL:url
|
||||
targets:targets
|
||||
webURL:fallbackUrl];
|
||||
@synchronized(self.cachedFBSDKAppLinks) {
|
||||
[FBSDKTypeUtility dictionary:self.cachedFBSDKAppLinks setObject:link forKey:url];
|
||||
}
|
||||
|
||||
[FBSDKTypeUtility dictionary:appLinks setObject:link forKey:url];
|
||||
}
|
||||
handler(appLinks, nil);
|
||||
}];
|
||||
}
|
||||
|
||||
- (FBSDKAppLink *)buildAppLinkForURL:(NSURL *)url inResults:(id)result
|
||||
{
|
||||
NSString *idiomSpecificField = [self.requestBuilder getIdiomSpecificField];
|
||||
|
||||
id nestedObject = result[url.absoluteString][kAppLinksKey];
|
||||
NSMutableArray *rawTargets = [NSMutableArray array];
|
||||
if (idiomSpecificField) {
|
||||
[rawTargets addObjectsFromArray:nestedObject[idiomSpecificField]];
|
||||
}
|
||||
[rawTargets addObjectsFromArray:nestedObject[kIOSKey]];
|
||||
|
||||
NSMutableArray<FBSDKAppLinkTarget *> *targets = [NSMutableArray arrayWithCapacity:rawTargets.count];
|
||||
for (id rawTarget in rawTargets) {
|
||||
[FBSDKTypeUtility array:targets addObject:[FBSDKAppLinkTarget appLinkTargetWithURL:[NSURL URLWithString:rawTarget[kURLKey]]
|
||||
appStoreId:rawTarget[kIOSAppStoreIdKey]
|
||||
appName:rawTarget[kIOSAppNameKey]]];
|
||||
}
|
||||
|
||||
id webTarget = nestedObject[kWebKey];
|
||||
NSString *webFallbackString = webTarget[kURLKey];
|
||||
NSURL *fallbackUrl = webFallbackString ? [NSURL URLWithString:webFallbackString] : url;
|
||||
|
||||
NSNumber *shouldFallback = webTarget[kShouldFallbackKey];
|
||||
if (shouldFallback != nil && !shouldFallback.boolValue) {
|
||||
fallbackUrl = nil;
|
||||
}
|
||||
|
||||
return [FBSDKAppLink appLinkWithSourceURL:url
|
||||
targets:targets
|
||||
webURL:fallbackUrl];
|
||||
}
|
||||
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
+ (instancetype)resolver
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import "TargetConditionals.h"
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "FBSDKAppLinkResolving.h"
|
||||
#import "FBSDKGraphRequest.h"
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
Class responsible for generating the appropriate FBSDKGraphRequest for a given set of urls
|
||||
*/
|
||||
NS_SWIFT_NAME(AppLinkResolverRequestBuilder)
|
||||
@interface FBSDKAppLinkResolverRequestBuilder : NSObject
|
||||
|
||||
/**
|
||||
Generates the FBSDKGraphRequest
|
||||
|
||||
@param urls The URLs to build the requests for
|
||||
*/
|
||||
- (FBSDKGraphRequest* _Nonnull)requestForURLs:(NSArray<NSURL *> * _Nonnull)urls
|
||||
NS_EXTENSION_UNAVAILABLE_IOS("Not available in app extension");
|
||||
|
||||
- (NSString* _Nullable)getIdiomSpecificField
|
||||
NS_EXTENSION_UNAVAILABLE_IOS("Not available in app extension");
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,125 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to
|
||||
// use, copy, modify, and distribute this software in source code or binary form
|
||||
// for use in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#import "TargetConditionals.h"
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
|
||||
#import "FBSDKAppLinkResolverRequestBuilder.h"
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#import "FBSDKCoreKit+Internal.h"
|
||||
#import "FBSDKGraphRequest+Internal.h"
|
||||
|
||||
static NSString *const kIOSKey = @"ios";
|
||||
static NSString *const kIPhoneKey = @"iphone";
|
||||
static NSString *const kIPadKey = @"ipad";
|
||||
static NSString *const kAppLinksKey = @"app_links";
|
||||
|
||||
@interface FBSDKAppLinkResolverRequestBuilder ()
|
||||
@property (nonatomic, assign) UIUserInterfaceIdiom userInterfaceIdiom;
|
||||
@end
|
||||
|
||||
@implementation FBSDKAppLinkResolverRequestBuilder
|
||||
|
||||
- (instancetype)initWithUserInterfaceIdiom:(UIUserInterfaceIdiom)userInterfaceIdiom
|
||||
{
|
||||
if (self = [super init]) {
|
||||
self.userInterfaceIdiom = userInterfaceIdiom;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
if ((self = [super init])) {
|
||||
_userInterfaceIdiom = UI_USER_INTERFACE_IDIOM();
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (FBSDKGraphRequest *)requestForURLs:(NSArray<NSURL *> *)urls
|
||||
{
|
||||
NSArray<NSString *> *fields = [self getUISpecificFields];
|
||||
NSArray<NSString *> *encodedURLs = [self getEncodedURLs:urls];
|
||||
|
||||
NSString *path =
|
||||
[NSString stringWithFormat:@"?fields=%@.fields(%@)&ids=%@",
|
||||
kAppLinksKey,
|
||||
[fields componentsJoinedByString:@","],
|
||||
[encodedURLs componentsJoinedByString:@","]];
|
||||
return [[FBSDKGraphRequest alloc]
|
||||
initWithGraphPath:path
|
||||
parameters:nil
|
||||
flags:FBSDKGraphRequestFlagDoNotInvalidateTokenOnError
|
||||
| FBSDKGraphRequestFlagDisableErrorRecovery];
|
||||
}
|
||||
|
||||
- (NSString *_Nullable)getIdiomSpecificField
|
||||
{
|
||||
NSString *idiomSpecificField = nil;
|
||||
|
||||
switch (self.userInterfaceIdiom) {
|
||||
case UIUserInterfaceIdiomPad:
|
||||
idiomSpecificField = kIPadKey;
|
||||
break;
|
||||
case UIUserInterfaceIdiomPhone:
|
||||
idiomSpecificField = kIPhoneKey;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return idiomSpecificField;
|
||||
}
|
||||
|
||||
- (NSArray<NSString *> *)getUISpecificFields
|
||||
{
|
||||
NSMutableArray<NSString *> *fields = [NSMutableArray arrayWithObject:kIOSKey];
|
||||
NSString *idiomSpecificField = [self getIdiomSpecificField];
|
||||
|
||||
if (idiomSpecificField) {
|
||||
[FBSDKTypeUtility array:fields addObject:idiomSpecificField];
|
||||
}
|
||||
|
||||
return fields;
|
||||
}
|
||||
|
||||
- (NSArray<NSString *> *)getEncodedURLs:(NSArray<NSURL *> *)urls
|
||||
{
|
||||
NSMutableArray<NSString *> *encodedURLs = [NSMutableArray array];
|
||||
|
||||
for (NSURL *url in urls) {
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
NSString *encodedURL = [url.absoluteString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
|
||||
#pragma clang diagnostic pop
|
||||
if (encodedURL) {
|
||||
[FBSDKTypeUtility array:encodedURLs addObject:encodedURL];
|
||||
}
|
||||
}
|
||||
|
||||
return encodedURLs;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
@@ -43,6 +43,7 @@
|
||||
#import <FBSDKCoreKit/FBSDKAppLink.h>
|
||||
#import <FBSDKCoreKit/FBSDKAppLinkNavigation.h>
|
||||
#import <FBSDKCoreKit/FBSDKAppLinkResolver.h>
|
||||
#import <FBSDKCoreKit/FBSDKAppLinkResolverRequestBuilder.h>
|
||||
#import <FBSDKCoreKit/FBSDKAppLinkResolving.h>
|
||||
#import <FBSDKCoreKit/FBSDKAppLinkReturnToRefererController.h>
|
||||
#import <FBSDKCoreKit/FBSDKAppLinkReturnToRefererView.h>
|
||||
@@ -79,6 +80,7 @@
|
||||
#import "FBSDKAppLink.h"
|
||||
#import "FBSDKAppLinkNavigation.h"
|
||||
#import "FBSDKAppLinkResolver.h"
|
||||
#import "FBSDKAppLinkResolverRequestBuilder.h"
|
||||
#import "FBSDKAppLinkResolving.h"
|
||||
#import "FBSDKAppLinkReturnToRefererController.h"
|
||||
#import "FBSDKAppLinkReturnToRefererView.h"
|
||||
|
||||
@@ -1 +1 @@
|
||||
../AppLink/FBSDKAppLinkResolver.h
|
||||
../AppLink/Resolver/FBSDKAppLinkResolver.h
|
||||
@@ -0,0 +1 @@
|
||||
../AppLink/Resolver/FBSDKAppLinkResolverRequestBuilder.h
|
||||
@@ -1 +1 @@
|
||||
../AppLink/FBSDKAppLinkResolving.h
|
||||
../AppLink/Resolver/FBSDKAppLinkResolving.h
|
||||
@@ -0,0 +1,58 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import <XCTest/XCTest.h>
|
||||
|
||||
#import <FBSDKCoreKit/FBSDKCoreKit.h>
|
||||
|
||||
#import "FBSDKAppLinkResolverRequestBuilder.h"
|
||||
#import "FBSDKTestCase.h"
|
||||
|
||||
@interface FBSDKAppLinkResolverRequestBuilder (FBSDKAppLinkResolverTests)
|
||||
|
||||
- (instancetype)initWithUserInterfaceIdiom:(UIUserInterfaceIdiom)userInterfaceIdiom;
|
||||
|
||||
@end
|
||||
|
||||
@interface FBSDKAppLinkResolverRequestBuilderTests : FBSDKTestCase
|
||||
@end
|
||||
|
||||
@implementation FBSDKAppLinkResolverRequestBuilderTests
|
||||
#pragma mark - test cases
|
||||
|
||||
- (void)testAsksForPhoneDataOnPhone
|
||||
{
|
||||
FBSDKAppLinkResolverRequestBuilder *builder = [[FBSDKAppLinkResolverRequestBuilder alloc] initWithUserInterfaceIdiom:UIUserInterfaceIdiomPhone];
|
||||
|
||||
FBSDKGraphRequest *request = [builder requestForURLs:@[]];
|
||||
BOOL askedForPhone = [request.parameters[@"fields"] rangeOfString:@"iphone"].location != NSNotFound;
|
||||
|
||||
XCTAssertTrue(askedForPhone);
|
||||
}
|
||||
|
||||
- (void)testAsksForPadDataOnPad
|
||||
{
|
||||
FBSDKAppLinkResolverRequestBuilder *builder = [[FBSDKAppLinkResolverRequestBuilder alloc] initWithUserInterfaceIdiom:UIUserInterfaceIdiomPad];
|
||||
|
||||
FBSDKGraphRequest *request = [builder requestForURLs:@[]];
|
||||
BOOL askedForPad = [request.parameters[@"fields"] rangeOfString:@"iphone"].location != NSNotFound;
|
||||
|
||||
XCTAssertTrue(askedForPad);
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -20,19 +20,15 @@
|
||||
#import <XCTest/XCTest.h>
|
||||
|
||||
#import <FBSDKCoreKit/FBSDKCoreKit.h>
|
||||
#import <OHHTTPStubs/OHHTTPStubs.h>
|
||||
|
||||
#import "FBSDKAppLinkResolver.h"
|
||||
#import "FBSDKCoreKitTestUtility.h"
|
||||
#import "FBSDKInternalUtility.h"
|
||||
#import "FBSDKSettings.h"
|
||||
#import "FBSDKTestCase.h"
|
||||
|
||||
static NSString *const kAppLinkURLString = @"http://example.com/1234567890";
|
||||
static NSString *const kAppLinkURL2String = @"http://example.com/0987654321";
|
||||
static NSString *const kAppLinksKey = @"app_links";
|
||||
|
||||
typedef void (^HTTPStubCallback)(NSURLRequest *request);
|
||||
typedef _Nullable id (^StringURLBlock)(NSString *urlString);
|
||||
static NSString *const kIphoneKey = @"iphone";
|
||||
static NSString *const kIpadKey = @"ipad";
|
||||
|
||||
@interface NSURL (FBSDKAppLinkResolverTests)
|
||||
|
||||
@@ -43,147 +39,87 @@ typedef _Nullable id (^StringURLBlock)(NSString *urlString);
|
||||
@interface FBSDKAppLinkResolver (FBSDKAppLinkResolverTests)
|
||||
|
||||
- (instancetype)initWithUserInterfaceIdiom:(UIUserInterfaceIdiom)userInterfaceIdiom;
|
||||
- (instancetype)initWithRequestBuilder:(FBSDKAppLinkResolverRequestBuilder *)builder;
|
||||
- (instancetype)initWithUserInterfaceIdiom:(UIUserInterfaceIdiom)userInterfaceIdiom andRequestBuilder:(FBSDKAppLinkResolverRequestBuilder *)builder;
|
||||
|
||||
@end
|
||||
|
||||
@interface FBSDKAppLinkResolverTests : XCTestCase
|
||||
@interface FBSDKAppLinkResolverTests : FBSDKTestCase
|
||||
@end
|
||||
|
||||
@implementation FBSDKAppLinkResolverTests
|
||||
|
||||
#pragma mark - Mock requests
|
||||
|
||||
- (void)mockAppLinkRequestWithResult:(id)result
|
||||
{
|
||||
id _mockNSBundle;
|
||||
[self mockAppLinkRequestWithResult:result error:nil idiomSpecificField:kIphoneKey];
|
||||
}
|
||||
|
||||
#pragma mark - HTTP stubbing helpers
|
||||
|
||||
- (void)stubAllResponsesWithResult:(id)result
|
||||
- (void)mockAppLinkRequestWithError
|
||||
{
|
||||
[self stubAllResponsesWithResult:result statusCode:200];
|
||||
[self mockAppLinkRequestWithResult:@{@"error" : @{}}
|
||||
error:[[NSError alloc]
|
||||
initWithDomain:FBSDKErrorDomain
|
||||
code:-1
|
||||
userInfo:nil]
|
||||
idiomSpecificField:kIphoneKey];
|
||||
}
|
||||
|
||||
- (void)stubAllResponsesWithResult:(id)result
|
||||
statusCode:(int)statusCode
|
||||
- (void)mockAppLinkRequestWithResult:(id)result idiomSpecificField:(NSString *)field
|
||||
{
|
||||
[self stubAllResponsesWithResult:result statusCode:statusCode callback:nil];
|
||||
[self mockAppLinkRequestWithResult:result error:nil idiomSpecificField:field];
|
||||
}
|
||||
|
||||
- (void)stubAllResponsesWithResult:(id)result
|
||||
statusCode:(int)statusCode
|
||||
callback:(HTTPStubCallback)callback
|
||||
- (void)mockAppLinkRequestWithResult:(id)result error:(NSError *)error idiomSpecificField:(NSString *)field
|
||||
{
|
||||
return [self stubMatchingRequestsWithResponses:@{@"" : result}
|
||||
statusCode:statusCode
|
||||
callback:callback];
|
||||
[self mockAppLinkRequestWithResult:result error:error idiomSpecificField:field andDo:nil];
|
||||
}
|
||||
|
||||
- (void)stubMatchingRequestsWithResponses:(NSDictionary<NSString *, id> *)requestsAndResponses
|
||||
statusCode:(int)statusCode
|
||||
callback:(HTTPStubCallback)callback
|
||||
- (void)mockAppLinkRequestWithResult:(id)result error:(NSError *)error idiomSpecificField:(NSString *)field andDo:(void (^_Nullable)(NSInvocation *))block
|
||||
{
|
||||
StringURLBlock matchingKey = ^id (NSString *urlString) {
|
||||
for (NSString *substring in requestsAndResponses.allKeys) {
|
||||
// The first @"" always matches
|
||||
if (substring.length == 0
|
||||
|| [urlString rangeOfString:substring].location != NSNotFound) {
|
||||
return substring;
|
||||
}
|
||||
}
|
||||
return nil;
|
||||
};
|
||||
[self stubGraphRequestWithResult:result error:error connection:nil];
|
||||
[self stubAppLinkResolverRequestBuilderWithIdiomSpecificField:field];
|
||||
|
||||
[OHHTTPStubs stubRequestsPassingTest:^BOOL (NSURLRequest *request) {
|
||||
if (callback) {
|
||||
callback(request);
|
||||
}
|
||||
|
||||
return matchingKey(request.URL.absoluteString) != nil;
|
||||
} withStubResponse:^OHHTTPStubsResponse *(NSURLRequest *request) {
|
||||
id result = requestsAndResponses[matchingKey(request.URL.absoluteString)];
|
||||
NSData *data = [[FBSDKBasicUtility JSONStringForObject:result
|
||||
error:NULL
|
||||
invalidObjectHandler:NULL] dataUsingEncoding:NSUTF8StringEncoding];
|
||||
|
||||
return [OHHTTPStubsResponse responseWithData:data
|
||||
statusCode:statusCode
|
||||
headers:nil];
|
||||
}];
|
||||
OCMStub([self.appLinkResolverRequestBuilderMock requestForURLs:[OCMArg any]]).andReturn(self.graphRequestMock).andDo(block);
|
||||
}
|
||||
|
||||
#pragma mark - test cases
|
||||
|
||||
- (void)setUp
|
||||
{
|
||||
_mockNSBundle = [FBSDKCoreKitTestUtility mainBundleMock];
|
||||
}
|
||||
|
||||
/*
|
||||
- (void)testAsksForPhoneDataOnPhone
|
||||
{
|
||||
XCTestExpectation *expectation = [self expectationWithDescription:@"asksForPhoneDataOnPhone"];
|
||||
[FBSDKAccessToken setCurrentAccessToken:nil];
|
||||
[FBSDKSettings setClientToken:@"clienttoken"];
|
||||
|
||||
__block BOOL askedForPhone = NO;
|
||||
[OHHTTPStubs stubRequestsPassingTest:^BOOL(NSURLRequest *request) {
|
||||
NSDictionary<NSString *, NSString *> *queryParameters =
|
||||
[FBSDKInternalUtility dictionaryFromFBURL:request.URL];
|
||||
askedForPhone = [queryParameters[@"fields"] rangeOfString:@"iphone"].location != NSNotFound;
|
||||
return YES;
|
||||
} withStubResponse:^OHHTTPStubsResponse *(NSURLRequest *request) {
|
||||
return [OHHTTPStubsResponse responseWithData:[NSData data]
|
||||
statusCode:200
|
||||
headers:nil];
|
||||
}];
|
||||
|
||||
FBSDKAppLinkResolver *resolver = [[FBSDKAppLinkResolver alloc] initWithUserInterfaceIdiom:UIUserInterfaceIdiomPhone];
|
||||
[resolver
|
||||
appLinkFromURL:[NSURL URLWithString:kAppLinkURLString]
|
||||
handler:^(FBSDKAppLink * _Nullable appLink, NSError * _Nullable error) {
|
||||
XCTAssertTrue(askedForPhone);
|
||||
[expectation fulfill];
|
||||
}];
|
||||
|
||||
[self waitForExpectationsWithTimeout:2 handler:^(NSError * _Nullable error) {
|
||||
XCTAssertNil(error);
|
||||
}];
|
||||
[FBSDKSettings setClientToken:nil];
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
- (void)testUsesPhoneDataOnPhone
|
||||
{
|
||||
XCTestExpectation *expectation = [self expectationWithDescription:@"usesPhoneDataOnPhone"];
|
||||
[FBSDKAccessToken setCurrentAccessToken:nil];
|
||||
[FBSDKSettings setClientToken:@"clienttoken"];
|
||||
[self stubClientTokenWith:@"clienttoken"];
|
||||
|
||||
[self stubAllResponsesWithResult:@{
|
||||
kAppLinkURLString : @{
|
||||
kAppLinksKey: @{
|
||||
@"iphone": @[
|
||||
@{
|
||||
@"app_name": @"Example",
|
||||
@"app_store_id": @"456",
|
||||
@"url": @"example://things/1234567890"
|
||||
}
|
||||
],
|
||||
@"ios": @[
|
||||
@{
|
||||
@"app_name": @"Example",
|
||||
@"app_store_id": @"123",
|
||||
@"url": @"example://things/1234567890"
|
||||
}
|
||||
],
|
||||
},
|
||||
@"id": kAppLinkURLString
|
||||
}
|
||||
}];
|
||||
id result = @{
|
||||
kAppLinkURLString : @{
|
||||
kAppLinksKey : @{
|
||||
kIphoneKey : @[
|
||||
@{
|
||||
@"app_name" : @"Example",
|
||||
@"app_store_id" : @"456",
|
||||
@"url" : @"example://things/1234567890"
|
||||
}
|
||||
],
|
||||
@"ios" : @[
|
||||
@{
|
||||
@"app_name" : @"Example",
|
||||
@"app_store_id" : @"123",
|
||||
@"url" : @"example://things/1234567890"
|
||||
}
|
||||
],
|
||||
},
|
||||
@"id" : kAppLinkURLString
|
||||
}
|
||||
};
|
||||
|
||||
[self mockAppLinkRequestWithResult:result idiomSpecificField:kIphoneKey];
|
||||
|
||||
FBSDKAppLinkResolver *resolver = [[FBSDKAppLinkResolver alloc] initWithUserInterfaceIdiom:UIUserInterfaceIdiomPhone andRequestBuilder:self.appLinkResolverRequestBuilderMock];
|
||||
|
||||
FBSDKAppLinkResolver *resolver = [[FBSDKAppLinkResolver alloc] initWithUserInterfaceIdiom:UIUserInterfaceIdiomPhone];
|
||||
[resolver
|
||||
appLinkFromURL:[NSURL URLWithString:kAppLinkURLString]
|
||||
handler:^(FBSDKAppLink * _Nullable link, NSError * _Nullable error) {
|
||||
|
||||
handler:^(FBSDKAppLink *_Nullable link, NSError *_Nullable error) {
|
||||
XCTAssertNotNil(link);
|
||||
XCTAssertEqual(link.sourceURL.absoluteString, kAppLinkURLString);
|
||||
XCTAssertEqualObjects([link.targets[0] appStoreId], @"456");
|
||||
@@ -192,82 +128,45 @@ typedef _Nullable id (^StringURLBlock)(NSString *urlString);
|
||||
[expectation fulfill];
|
||||
}];
|
||||
|
||||
[self waitForExpectationsWithTimeout:2 handler:^(NSError * _Nullable error) {
|
||||
[self waitForExpectationsWithTimeout:2 handler:^(NSError *_Nullable error) {
|
||||
XCTAssertNil(error);
|
||||
}];
|
||||
[FBSDKSettings setClientToken:nil];
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
- (void)testAsksForPadDataOnPad
|
||||
{
|
||||
XCTestExpectation *expectation = [self expectationWithDescription:@"asksForPadDataOnPad"];
|
||||
[FBSDKAccessToken setCurrentAccessToken:nil];
|
||||
[FBSDKSettings setClientToken:@"clienttoken"];
|
||||
|
||||
__block BOOL askedForPad = NO;
|
||||
[OHHTTPStubs stubRequestsPassingTest:^BOOL(NSURLRequest *request) {
|
||||
NSDictionary<NSString *, NSString *> *queryParameters =
|
||||
[FBSDKInternalUtility dictionaryFromFBURL:request.URL];
|
||||
// do an "OR" because we only need to verify we asked for it once (in cases where unrelated network requests
|
||||
// were resetting the flag incorrectly back to NO).
|
||||
askedForPad |= [queryParameters[@"fields"] rangeOfString:@"ipad"].location != NSNotFound;
|
||||
return YES;
|
||||
} withStubResponse:^OHHTTPStubsResponse *(NSURLRequest *request) {
|
||||
return [OHHTTPStubsResponse responseWithData:[NSData data]
|
||||
statusCode:200
|
||||
headers:nil];
|
||||
}];
|
||||
|
||||
FBSDKAppLinkResolver *resolver = [[FBSDKAppLinkResolver alloc] initWithUserInterfaceIdiom:UIUserInterfaceIdiomPad];
|
||||
[resolver
|
||||
appLinkFromURL:[NSURL URLWithString:kAppLinkURLString]
|
||||
handler:^(FBSDKAppLink * _Nullable link, NSError * _Nullable error) {
|
||||
XCTAssertTrue(askedForPad);
|
||||
[expectation fulfill];
|
||||
}];
|
||||
|
||||
[self waitForExpectationsWithTimeout:2 handler:^(NSError * _Nullable error) {
|
||||
XCTAssertNil(error);
|
||||
}];
|
||||
[FBSDKSettings setClientToken:nil];
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
- (void)testUsesPadDataOnPad
|
||||
{
|
||||
XCTestExpectation *expectation = [self expectationWithDescription:@"usesPadDataOnPad"];
|
||||
[FBSDKAccessToken setCurrentAccessToken:nil];
|
||||
[FBSDKSettings setClientToken:@"clienttoken"];
|
||||
[self stubClientTokenWith:@"clienttoken"];
|
||||
|
||||
[self stubAllResponsesWithResult:@{
|
||||
kAppLinkURLString : @{
|
||||
kAppLinksKey: @{
|
||||
@"ipad": @[
|
||||
@{
|
||||
@"app_name": @"Example",
|
||||
@"app_store_id": @"456",
|
||||
@"url": @"example://things/1234567890"
|
||||
}
|
||||
],
|
||||
@"ios": @[
|
||||
@{
|
||||
@"app_name": @"Example",
|
||||
@"app_store_id": @"123",
|
||||
@"url": @"example://things/1234567890"
|
||||
}
|
||||
],
|
||||
},
|
||||
@"id": kAppLinkURLString
|
||||
}
|
||||
}];
|
||||
id result = @{
|
||||
kAppLinkURLString : @{
|
||||
kAppLinksKey : @{
|
||||
@"ipad" : @[
|
||||
@{
|
||||
@"app_name" : @"Example",
|
||||
@"app_store_id" : @"456",
|
||||
@"url" : @"example://things/1234567890"
|
||||
}
|
||||
],
|
||||
@"ios" : @[
|
||||
@{
|
||||
@"app_name" : @"Example",
|
||||
@"app_store_id" : @"123",
|
||||
@"url" : @"example://things/1234567890"
|
||||
}
|
||||
],
|
||||
},
|
||||
@"id" : kAppLinkURLString
|
||||
}
|
||||
};
|
||||
|
||||
[self mockAppLinkRequestWithResult:result idiomSpecificField:kIpadKey];
|
||||
|
||||
FBSDKAppLinkResolver *resolver = [[FBSDKAppLinkResolver alloc] initWithUserInterfaceIdiom:UIUserInterfaceIdiomPad andRequestBuilder:self.appLinkResolverRequestBuilderMock];
|
||||
|
||||
FBSDKAppLinkResolver *resolver = [[FBSDKAppLinkResolver alloc] initWithUserInterfaceIdiom:UIUserInterfaceIdiomPad];
|
||||
[resolver
|
||||
appLinkFromURL:[NSURL URLWithString:kAppLinkURLString]
|
||||
handler:^(FBSDKAppLink * _Nullable link, NSError * _Nullable error) {
|
||||
handler:^(FBSDKAppLink *_Nullable link, NSError *_Nullable error) {
|
||||
XCTAssertNotNil(link);
|
||||
XCTAssertEqual(link.sourceURL.absoluteString, kAppLinkURLString);
|
||||
XCTAssertEqualObjects([link.targets[0] appStoreId], @"456");
|
||||
@@ -276,76 +175,73 @@ typedef _Nullable id (^StringURLBlock)(NSString *urlString);
|
||||
[expectation fulfill];
|
||||
}];
|
||||
|
||||
[self waitForExpectationsWithTimeout:2 handler:^(NSError * _Nullable error) {
|
||||
[self waitForExpectationsWithTimeout:2 handler:^(NSError *_Nullable error) {
|
||||
XCTAssertNil(error);
|
||||
}];
|
||||
[FBSDKSettings setClientToken:nil];
|
||||
}
|
||||
|
||||
|
||||
- (void)testIgnoresAndroidData
|
||||
{
|
||||
XCTestExpectation *expectation = [self expectationWithDescription:@"ignoresAndroidData"];
|
||||
[FBSDKAccessToken setCurrentAccessToken:nil];
|
||||
[FBSDKSettings setClientToken:@"clienttoken"];
|
||||
[self stubClientTokenWith:@"clienttoken"];
|
||||
|
||||
// We are not asking for it, but just make sure we ignore any non-iOS-platform data we get, to be safe.
|
||||
[self stubAllResponsesWithResult:@{
|
||||
kAppLinkURLString : @{
|
||||
kAppLinksKey: @{
|
||||
@"android": @[
|
||||
@{
|
||||
@"app_name": @"Example",
|
||||
@"package": @"com.example.app",
|
||||
@"url": @"example://things/1234567890"
|
||||
}
|
||||
],
|
||||
@"ios": @[
|
||||
@{
|
||||
@"app_name": @"Example",
|
||||
@"app_store_id": @"123",
|
||||
@"url": @"example://things/1234567890"
|
||||
}
|
||||
],
|
||||
},
|
||||
@"id": kAppLinkURLString
|
||||
}
|
||||
}];
|
||||
id result = @{
|
||||
kAppLinkURLString : @{
|
||||
kAppLinksKey : @{
|
||||
@"android" : @[
|
||||
@{
|
||||
@"app_name" : @"Example",
|
||||
@"package" : @"com.example.app",
|
||||
@"url" : @"example://things/1234567890"
|
||||
}
|
||||
],
|
||||
@"ios" : @[
|
||||
@{
|
||||
@"app_name" : @"Example",
|
||||
@"app_store_id" : @"123",
|
||||
@"url" : @"example://things/1234567890"
|
||||
}
|
||||
],
|
||||
},
|
||||
@"id" : kAppLinkURLString
|
||||
}
|
||||
};
|
||||
|
||||
[self mockAppLinkRequestWithResult:result];
|
||||
FBSDKAppLinkResolver *resolver = [[FBSDKAppLinkResolver alloc] initWithRequestBuilder:self.appLinkResolverRequestBuilderMock];
|
||||
|
||||
FBSDKAppLinkResolver *resolver = [FBSDKAppLinkResolver resolver];
|
||||
[resolver
|
||||
appLinkFromURL:[NSURL URLWithString:kAppLinkURLString]
|
||||
handler:^(FBSDKAppLink * _Nullable link, NSError * _Nullable error) {
|
||||
handler:^(FBSDKAppLink *_Nullable link, NSError *_Nullable error) {
|
||||
XCTAssertNotNil(link);
|
||||
XCTAssertEqualObjects([link.targets[0] appStoreId], @"123");
|
||||
|
||||
[expectation fulfill];
|
||||
}];
|
||||
|
||||
[self waitForExpectationsWithTimeout:2 handler:^(NSError * _Nullable error) {
|
||||
[self waitForExpectationsWithTimeout:2 handler:^(NSError *_Nullable error) {
|
||||
XCTAssertNil(error);
|
||||
}];
|
||||
[FBSDKSettings setClientToken:nil];
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
- (void)testHandlesNoTargets
|
||||
{
|
||||
XCTestExpectation *expectation = [self expectationWithDescription:@"handlesNoTargets"];
|
||||
[FBSDKAccessToken setCurrentAccessToken:nil];
|
||||
[FBSDKSettings setClientToken:@"clienttoken"];
|
||||
[self stubClientTokenWith:@"clienttoken"];
|
||||
|
||||
[self stubAllResponsesWithResult:@{
|
||||
kAppLinkURLString : @{
|
||||
@"id": kAppLinkURLString
|
||||
}
|
||||
}];
|
||||
id result = @{
|
||||
kAppLinkURLString : @{
|
||||
@"id" : kAppLinkURLString
|
||||
}
|
||||
};
|
||||
|
||||
[self mockAppLinkRequestWithResult:result];
|
||||
FBSDKAppLinkResolver *resolver = [[FBSDKAppLinkResolver alloc] initWithRequestBuilder:self.appLinkResolverRequestBuilderMock];
|
||||
|
||||
FBSDKAppLinkResolver *resolver = [FBSDKAppLinkResolver resolver];
|
||||
[resolver
|
||||
appLinkFromURL:[NSURL URLWithString:kAppLinkURLString]
|
||||
handler:^(FBSDKAppLink * _Nullable link, NSError * _Nullable error) {
|
||||
handler:^(FBSDKAppLink *_Nullable link, NSError *_Nullable error) {
|
||||
XCTAssertNotNil(link);
|
||||
XCTAssertEqual(link.sourceURL.absoluteString, kAppLinkURLString);
|
||||
XCTAssertEqual(link.targets.count, 0);
|
||||
@@ -353,33 +249,31 @@ typedef _Nullable id (^StringURLBlock)(NSString *urlString);
|
||||
[expectation fulfill];
|
||||
}];
|
||||
|
||||
[self waitForExpectationsWithTimeout:2 handler:^(NSError * _Nullable error) {
|
||||
[self waitForExpectationsWithTimeout:2 handler:^(NSError *_Nullable error) {
|
||||
XCTAssertNil(error);
|
||||
}];
|
||||
[FBSDKSettings setClientToken:nil];
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
- (void)testHandlesMultipleURLs
|
||||
{
|
||||
XCTestExpectation *expectation = [self expectationWithDescription:@"handlesMultipleURLs"];
|
||||
[FBSDKAccessToken setCurrentAccessToken:nil];
|
||||
[FBSDKSettings setClientToken:@"clienttoken"];
|
||||
[self stubClientTokenWith:@"clienttoken"];
|
||||
|
||||
[self stubAllResponsesWithResult:@{
|
||||
kAppLinkURLString : @{
|
||||
@"id": kAppLinkURLString
|
||||
},
|
||||
kAppLinkURL2String : @{
|
||||
@"id": kAppLinkURL2String
|
||||
}
|
||||
}];
|
||||
id result = @{
|
||||
kAppLinkURLString : @{
|
||||
@"id" : kAppLinkURLString
|
||||
},
|
||||
kAppLinkURL2String : @{
|
||||
@"id" : kAppLinkURL2String
|
||||
}
|
||||
};
|
||||
|
||||
[self mockAppLinkRequestWithResult:result];
|
||||
FBSDKAppLinkResolver *resolver = [[FBSDKAppLinkResolver alloc] initWithRequestBuilder:self.appLinkResolverRequestBuilderMock];
|
||||
|
||||
FBSDKAppLinkResolver *resolver = [FBSDKAppLinkResolver resolver];
|
||||
[resolver
|
||||
appLinksFromURLs:@[[NSURL URLWithString:kAppLinkURLString], [NSURL URLWithString:kAppLinkURL2String]]
|
||||
handler:^(NSDictionary<NSURL *,FBSDKAppLink *> * _Nonnull links, NSError * _Nullable error) {
|
||||
handler:^(NSDictionary<NSURL *, FBSDKAppLink *> *_Nonnull links, NSError *_Nullable error) {
|
||||
XCTAssertNotNil(links);
|
||||
XCTAssertEqual(links.count, 2);
|
||||
XCTAssertEqual([links[[NSURL URLWithString:kAppLinkURLString]] sourceURL].absoluteString, kAppLinkURLString);
|
||||
@@ -388,311 +282,204 @@ typedef _Nullable id (^StringURLBlock)(NSString *urlString);
|
||||
[expectation fulfill];
|
||||
}];
|
||||
|
||||
[self waitForExpectationsWithTimeout:2 handler:^(NSError * _Nullable error) {
|
||||
[self waitForExpectationsWithTimeout:2 handler:^(NSError *_Nullable error) {
|
||||
XCTAssertNil(error);
|
||||
}];
|
||||
[FBSDKSettings setClientToken:nil];
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
- (void)testSetsFallbackIfNotSpecified
|
||||
{
|
||||
XCTestExpectation *expectation = [self expectationWithDescription:@"setsFallbackIfNotSpecified"];
|
||||
[FBSDKAccessToken setCurrentAccessToken:nil];
|
||||
[FBSDKSettings setClientToken:@"clienttoken"];
|
||||
[self stubClientTokenWith:@"clienttoken"];
|
||||
|
||||
[self stubAllResponsesWithResult:@{
|
||||
kAppLinkURLString : @{
|
||||
@"id": kAppLinkURLString
|
||||
}
|
||||
}];
|
||||
id result = @{
|
||||
kAppLinkURLString : @{
|
||||
@"id" : kAppLinkURLString
|
||||
}
|
||||
};
|
||||
|
||||
[self mockAppLinkRequestWithResult:result];
|
||||
FBSDKAppLinkResolver *resolver = [[FBSDKAppLinkResolver alloc] initWithRequestBuilder:self.appLinkResolverRequestBuilderMock];
|
||||
|
||||
FBSDKAppLinkResolver *resolver = [FBSDKAppLinkResolver resolver];
|
||||
[resolver
|
||||
appLinkFromURL:[NSURL URLWithString:kAppLinkURLString]
|
||||
handler:^(FBSDKAppLink * _Nullable link, NSError * _Nullable error) {
|
||||
handler:^(FBSDKAppLink *_Nullable link, NSError *_Nullable error) {
|
||||
XCTAssertNotNil(link);
|
||||
XCTAssertEqual(link.webURL.absoluteString, kAppLinkURLString);
|
||||
|
||||
[expectation fulfill];
|
||||
}];
|
||||
|
||||
[self waitForExpectationsWithTimeout:2 handler:^(NSError * _Nullable error) {
|
||||
[self waitForExpectationsWithTimeout:2 handler:^(NSError *_Nullable error) {
|
||||
XCTAssertNil(error);
|
||||
}];
|
||||
[FBSDKSettings setClientToken:nil];
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
- (void)testSetsFallbackIfSpecified
|
||||
{
|
||||
XCTestExpectation *expectation = [self expectationWithDescription:@"setsFallbackIfSpecified"];
|
||||
[self stubClientTokenWith:@"clienttoken"];
|
||||
|
||||
[FBSDKAccessToken setCurrentAccessToken:nil];
|
||||
[FBSDKSettings setClientToken:@"clienttoken"];
|
||||
id result = @{
|
||||
kAppLinkURLString : @{
|
||||
kAppLinksKey : @{
|
||||
@"web" : @{
|
||||
@"url" : @"http://www.example.com/somethingelse",
|
||||
@"should_fallback" : @"true"
|
||||
}
|
||||
},
|
||||
@"id" : kAppLinkURLString
|
||||
}
|
||||
};
|
||||
|
||||
[self stubAllResponsesWithResult:@{
|
||||
kAppLinkURLString : @{
|
||||
kAppLinksKey : @{
|
||||
@"web": @{
|
||||
@"url" : @"http://www.example.com/somethingelse",
|
||||
@"should_fallback": @"true"
|
||||
}
|
||||
},
|
||||
@"id": kAppLinkURLString
|
||||
}
|
||||
}];
|
||||
[self mockAppLinkRequestWithResult:result];
|
||||
FBSDKAppLinkResolver *resolver = [[FBSDKAppLinkResolver alloc] initWithRequestBuilder:self.appLinkResolverRequestBuilderMock];
|
||||
|
||||
FBSDKAppLinkResolver *resolver = [FBSDKAppLinkResolver resolver];
|
||||
[resolver
|
||||
appLinkFromURL:[NSURL URLWithString:kAppLinkURLString]
|
||||
handler:^(FBSDKAppLink * _Nullable link, NSError * _Nullable error) {
|
||||
handler:^(FBSDKAppLink *_Nullable link, NSError *_Nullable error) {
|
||||
XCTAssertNotNil(link);
|
||||
XCTAssertEqualObjects(link.webURL.absoluteString, @"http://www.example.com/somethingelse");
|
||||
|
||||
[expectation fulfill];
|
||||
}];
|
||||
|
||||
[self waitForExpectationsWithTimeout:2 handler:^(NSError * _Nullable error) {
|
||||
[self waitForExpectationsWithTimeout:2 handler:^(NSError *_Nullable error) {
|
||||
XCTAssertNil(error);
|
||||
}];
|
||||
[FBSDKSettings setClientToken:nil];
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
- (void)testUsesSourceAsFallbackIfSpecified
|
||||
{
|
||||
XCTestExpectation *expectation = [self expectationWithDescription:@"usesSourceAsFallbackIfSpecified"];
|
||||
[self stubClientTokenWith:@"clienttoken"];
|
||||
|
||||
[FBSDKAccessToken setCurrentAccessToken:nil];
|
||||
[FBSDKSettings setClientToken:@"clienttoken"];
|
||||
id result = @{
|
||||
kAppLinkURLString : @{
|
||||
kAppLinksKey : @{
|
||||
@"web" : @{
|
||||
@"should_fallback" : @"true"
|
||||
}
|
||||
},
|
||||
@"id" : kAppLinkURLString,
|
||||
}
|
||||
};
|
||||
|
||||
[self stubAllResponsesWithResult:@{
|
||||
kAppLinkURLString : @{
|
||||
kAppLinksKey: @{
|
||||
@"web": @{
|
||||
@"should_fallback": @"true"
|
||||
}
|
||||
},
|
||||
@"id": kAppLinkURLString,
|
||||
}
|
||||
}];
|
||||
[self mockAppLinkRequestWithResult:result];
|
||||
FBSDKAppLinkResolver *resolver = [[FBSDKAppLinkResolver alloc] initWithRequestBuilder:self.appLinkResolverRequestBuilderMock];
|
||||
|
||||
FBSDKAppLinkResolver *resolver = [FBSDKAppLinkResolver resolver];
|
||||
[resolver
|
||||
appLinkFromURL:[NSURL URLWithString:kAppLinkURLString]
|
||||
handler:^(FBSDKAppLink * _Nullable link, NSError * _Nullable error) {
|
||||
handler:^(FBSDKAppLink *_Nullable link, NSError *_Nullable error) {
|
||||
XCTAssertNotNil(link);
|
||||
XCTAssertEqual(link.webURL.absoluteString, kAppLinkURLString);
|
||||
|
||||
[expectation fulfill];
|
||||
}];
|
||||
|
||||
[self waitForExpectationsWithTimeout:2 handler:^(NSError * _Nullable error) {
|
||||
[self waitForExpectationsWithTimeout:2 handler:^(NSError *_Nullable error) {
|
||||
XCTAssertNil(error);
|
||||
}];
|
||||
[FBSDKSettings setClientToken:nil];
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
- (void)testSetsNoFallbackIfSpecified
|
||||
{
|
||||
XCTestExpectation *expectation = [self expectationWithDescription:@"setsNoFallbackIfSpecified"];
|
||||
[self stubClientTokenWith:@"clienttoken"];
|
||||
|
||||
[FBSDKAccessToken setCurrentAccessToken:nil];
|
||||
[FBSDKSettings setClientToken:@"clienttoken"];
|
||||
id result = @{
|
||||
kAppLinkURLString : @{
|
||||
kAppLinksKey : @{
|
||||
@"web" : @{
|
||||
@"url" : @"http://www.example.com/somethingelse",
|
||||
@"should_fallback" : @"false"
|
||||
}
|
||||
},
|
||||
@"id" : kAppLinkURLString
|
||||
}
|
||||
};
|
||||
|
||||
[self stubAllResponsesWithResult:@{
|
||||
kAppLinkURLString : @{
|
||||
kAppLinksKey : @{
|
||||
@"web": @{
|
||||
@"url" : @"http://www.example.com/somethingelse",
|
||||
@"should_fallback": @"false"
|
||||
}
|
||||
},
|
||||
@"id": kAppLinkURLString
|
||||
}
|
||||
}];
|
||||
[self mockAppLinkRequestWithResult:result];
|
||||
FBSDKAppLinkResolver *resolver = [[FBSDKAppLinkResolver alloc] initWithRequestBuilder:self.appLinkResolverRequestBuilderMock];
|
||||
|
||||
FBSDKAppLinkResolver *resolver = [FBSDKAppLinkResolver resolver];
|
||||
[resolver
|
||||
appLinkFromURL:[NSURL URLWithString:kAppLinkURLString]
|
||||
handler:^(FBSDKAppLink * _Nullable link, NSError * _Nullable error) {
|
||||
handler:^(FBSDKAppLink *_Nullable link, NSError *_Nullable error) {
|
||||
XCTAssertNotNil(link);
|
||||
XCTAssertNil(link.webURL.absoluteString);
|
||||
|
||||
[expectation fulfill];
|
||||
}];
|
||||
|
||||
[self waitForExpectationsWithTimeout:2 handler:^(NSError * _Nullable error) {
|
||||
[self waitForExpectationsWithTimeout:2 handler:^(NSError *_Nullable error) {
|
||||
XCTAssertNil(error);
|
||||
}];
|
||||
[FBSDKSettings setClientToken:nil];
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
- (void)testHandlesError
|
||||
{
|
||||
XCTestExpectation *expectation = [self expectationWithDescription:@"handlesError"];
|
||||
[self stubClientTokenWith:@"clienttoken"];
|
||||
|
||||
[FBSDKAccessToken setCurrentAccessToken:nil];
|
||||
[FBSDKSettings setClientToken:@"clienttoken"];
|
||||
[self mockAppLinkRequestWithError];
|
||||
FBSDKAppLinkResolver *resolver = [[FBSDKAppLinkResolver alloc] initWithRequestBuilder:self.appLinkResolverRequestBuilderMock];
|
||||
|
||||
// We are not asking for it, but just make sure we ignore any non-iOS-platform data we get, to be safe.
|
||||
[self stubAllResponsesWithResult:@{
|
||||
@"error" : @{}
|
||||
}
|
||||
statusCode:404];
|
||||
|
||||
FBSDKAppLinkResolver *resolver = [FBSDKAppLinkResolver resolver];
|
||||
[resolver
|
||||
appLinkFromURL:[NSURL URLWithString:kAppLinkURLString]
|
||||
handler:^(FBSDKAppLink * _Nullable link, NSError * _Nullable error) {
|
||||
handler:^(FBSDKAppLink *_Nullable link, NSError *_Nullable error) {
|
||||
XCTAssertNil(link);
|
||||
XCTAssertNotNil(error);
|
||||
[expectation fulfill];
|
||||
}];
|
||||
|
||||
[self waitForExpectationsWithTimeout:2 handler:^(NSError * _Nullable error) {
|
||||
[self waitForExpectationsWithTimeout:2 handler:^(NSError *_Nullable error) {
|
||||
XCTAssertNil(error);
|
||||
}];
|
||||
[FBSDKSettings setClientToken:nil];
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
- (void)testResultsAreCachedAndCacheIsUsed
|
||||
{
|
||||
XCTestExpectation *expectation = [self expectationWithDescription:@"handlesCache"];
|
||||
[self stubClientTokenWith:@"clienttoken"];
|
||||
|
||||
[FBSDKAccessToken setCurrentAccessToken:nil];
|
||||
[FBSDKSettings setClientToken:@"clienttoken"];
|
||||
id result = @{
|
||||
kAppLinkURLString : @{
|
||||
kAppLinksKey : @{
|
||||
@"iphone" : @[
|
||||
@{
|
||||
@"app_name" : @"Example",
|
||||
@"app_store_id" : @"456",
|
||||
@"url" : @"example://things/1234567890"
|
||||
}
|
||||
],
|
||||
},
|
||||
@"id" : kAppLinkURLString
|
||||
}
|
||||
};
|
||||
|
||||
__block NSUInteger callCount = 0;
|
||||
// We can change the approach and do OCMVerify(exactly(1), [_mockRequestBuilder requestForURLs]);
|
||||
// in the inner block of the double call instead of using this counter.
|
||||
__block int callCount = 0;
|
||||
[self mockAppLinkRequestWithResult:result error:nil idiomSpecificField:kIphoneKey andDo:^(NSInvocation *invocation) {
|
||||
callCount++;
|
||||
}];
|
||||
|
||||
[self stubAllResponsesWithResult:@{
|
||||
kAppLinkURLString : @{
|
||||
kAppLinksKey : @{
|
||||
@"iphone": @[
|
||||
@{
|
||||
@"app_name": @"Example",
|
||||
@"app_store_id": @"456",
|
||||
@"url": @"example://things/1234567890"
|
||||
}
|
||||
],
|
||||
},
|
||||
@"id": kAppLinkURLString
|
||||
}
|
||||
}
|
||||
statusCode:200
|
||||
callback:^(NSURLRequest *request) {
|
||||
++callCount;
|
||||
}];
|
||||
FBSDKAppLinkResolver *resolver = [[FBSDKAppLinkResolver alloc] initWithRequestBuilder:self.appLinkResolverRequestBuilderMock];
|
||||
|
||||
FBSDKAppLinkResolver *resolver = [FBSDKAppLinkResolver resolver];
|
||||
[resolver
|
||||
appLinkFromURL:[NSURL URLWithString:kAppLinkURLString]
|
||||
handler:^(FBSDKAppLink * _Nullable link1, NSError * _Nullable error1) {
|
||||
// Note: callCount is not necessarily 1, as the callback may be called multiple times during processing of the request.
|
||||
NSUInteger expectedCallCount = callCount;
|
||||
|
||||
handler:^(FBSDKAppLink *_Nullable link1, NSError *_Nullable error1) {
|
||||
[resolver
|
||||
appLinkFromURL:[NSURL URLWithString:kAppLinkURLString]
|
||||
handler:^(FBSDKAppLink * _Nullable link2, NSError * _Nullable error2) {
|
||||
XCTAssertEqual(callCount, expectedCallCount);
|
||||
handler:^(FBSDKAppLink *_Nullable link2, NSError *_Nullable error2) {
|
||||
XCTAssertEqual(callCount, 1);
|
||||
[expectation fulfill];
|
||||
}];
|
||||
}];
|
||||
|
||||
[self waitForExpectationsWithTimeout:2 handler:^(NSError * _Nullable error) {
|
||||
[self waitForExpectationsWithTimeout:2 handler:^(NSError *_Nullable error) {
|
||||
XCTAssertNil(error);
|
||||
}];
|
||||
[FBSDKSettings setClientToken:nil];
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
- (void)testMixOfCachedAndUncached
|
||||
{
|
||||
XCTestExpectation *expectation = [self expectationWithDescription:@"mixOfCachedAndUncached"];
|
||||
|
||||
[FBSDKAccessToken setCurrentAccessToken:nil];
|
||||
[FBSDKSettings setClientToken:@"clienttoken"];
|
||||
|
||||
__block NSMutableDictionary<NSString *, NSNumber *> *callCounts =
|
||||
[NSMutableDictionary dictionary];
|
||||
|
||||
[self stubMatchingRequestsWithResponses:@{
|
||||
@"1234567890" : @{
|
||||
kAppLinkURLString : @{
|
||||
kAppLinksKey : @{
|
||||
@"iphone": @[
|
||||
@{
|
||||
@"app_name": @"Example",
|
||||
@"app_store_id": @"456",
|
||||
@"url": @"example://things/1234567890"
|
||||
}
|
||||
],
|
||||
},
|
||||
@"id": kAppLinkURLString
|
||||
}
|
||||
},
|
||||
@"0987654321" : @{
|
||||
kAppLinkURL2String : @{
|
||||
kAppLinksKey : @{
|
||||
@"iphone": @[
|
||||
@{
|
||||
@"app_name": @"Example",
|
||||
@"app_store_id": @"456",
|
||||
@"url": @"example://things/1234567890"
|
||||
}
|
||||
],
|
||||
},
|
||||
@"id": kAppLinkURL2String
|
||||
}
|
||||
}
|
||||
}
|
||||
statusCode:200
|
||||
callback:^(NSURLRequest *request) {
|
||||
NSUInteger callCount = callCounts[request.URL.absoluteString].unsignedIntegerValue;
|
||||
++callCount;
|
||||
callCounts[request.URL.absoluteString] = @(callCount);
|
||||
}];
|
||||
|
||||
FBSDKAppLinkResolver *resolver = [FBSDKAppLinkResolver resolver];
|
||||
|
||||
// Prime the cache with kAppLinkURL
|
||||
[resolver
|
||||
appLinkFromURL:[NSURL URLWithString:kAppLinkURLString]
|
||||
handler:^(FBSDKAppLink * _Nullable appLink, NSError * _Nullable error1) {
|
||||
XCTAssertEqual(callCounts.count, 1);
|
||||
|
||||
// Note: callCount is not necessarily 1, as the callback may be called multiple times during processing of the request.
|
||||
NSString *firstCallKey = callCounts.allKeys[0];
|
||||
NSUInteger expectedCallCount = callCounts[firstCallKey].unsignedIntegerValue;
|
||||
|
||||
// Now request them both; we expect the call count for kAppLinkURL to be unchanged.
|
||||
[resolver
|
||||
appLinksFromURLs:@[[NSURL URLWithString:kAppLinkURLString], [NSURL URLWithString:kAppLinkURL2String]]
|
||||
handler:^(NSDictionary<NSURL *,FBSDKAppLink *> * _Nonnull links, NSError * _Nullable error2) {
|
||||
XCTAssertEqual(callCounts.count, 2);
|
||||
XCTAssertEqual([callCounts[firstCallKey] unsignedIntegerValue], expectedCallCount);
|
||||
|
||||
XCTAssertEqual(links.count, 2);
|
||||
[expectation fulfill];
|
||||
}];
|
||||
}];
|
||||
|
||||
[self waitForExpectationsWithTimeout:2 handler:^(NSError * _Nullable error) {
|
||||
XCTAssertNil(error);
|
||||
}];
|
||||
[FBSDKSettings setClientToken:nil];
|
||||
}
|
||||
*/
|
||||
|
||||
@end
|
||||
|
||||
@@ -67,6 +67,9 @@ Also, to get a better understanding of mocking, please read the documentation at
|
||||
/// Used for sharing a `FBSDKAppEventsUtility` class mock between tests
|
||||
@property (nullable, nonatomic, assign) id appEventsUtilityClassMock;
|
||||
|
||||
/// Used for sharing an `FBSDKAppLinkResolverRequestBuilder` class mock between tests
|
||||
@property (nullable, assign) id appLinkResolverRequestBuilderMock;
|
||||
|
||||
/// Used for sharing an `FBSDKApplicationDelegate` class mock between tests
|
||||
@property (nullable, assign) id fbApplicationDelegateClassMock;
|
||||
|
||||
@@ -76,6 +79,9 @@ Also, to get a better understanding of mocking, please read the documentation at
|
||||
/// Used for sharing an `FBSDKGatekeeperManager` class mock between tests
|
||||
@property (nullable, assign) id gatekeeperManagerClassMock;
|
||||
|
||||
/// Used for sharing an `FBSDKGraphRequest` class mock between tests
|
||||
@property (nullable, assign) id graphRequestMock;
|
||||
|
||||
/// Used for sharing an `NSBundle` class mock between tests
|
||||
@property (nullable, assign) id nsBundleClassMock;
|
||||
|
||||
@@ -199,6 +205,12 @@ Also, to get a better understanding of mocking, please read the documentation at
|
||||
/// Stubs `FBSDKAppEventsUtility.tokenStringToUseFor:` and returns the provided string
|
||||
- (void)stubAppEventsUtilityTokenStringToUseForTokenWith:(NSString *)tokenString;
|
||||
|
||||
/// Stubs `FBSDKGraphRequest.startWithCompletionHandler:` and returns the provided result, error and connection
|
||||
- (void)stubGraphRequestWithResult:(id)result error:(nullable NSError *)error connection:(nullable FBSDKGraphRequestConnection *)connection;
|
||||
|
||||
/// Stubs `FBSDKGraphRequest.startWithCompletionHandler:` and returns the provided result, error and connection
|
||||
- (void)stubAppLinkResolverRequestBuilderWithIdiomSpecificField:(nullable NSString *)field;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
@@ -73,6 +73,8 @@ typedef void (^FBSDKSKAdNetworkReporterBlock)(void);
|
||||
[self setUpTimeSpendDataMock];
|
||||
[self setUpInternalUtilityMock];
|
||||
[self setUpAdNetworkReporterMock];
|
||||
[self setUpAppLinkResolverRequestBuilderMock];
|
||||
[self setUpGraphRequestMock];
|
||||
}
|
||||
|
||||
- (void)tearDown
|
||||
@@ -132,6 +134,12 @@ typedef void (^FBSDKSKAdNetworkReporterBlock)(void);
|
||||
|
||||
[_adNetworkReporterClassMock stopMocking];
|
||||
_adNetworkReporterClassMock = nil;
|
||||
|
||||
[_appLinkResolverRequestBuilderMock stopMocking];
|
||||
_appLinkResolverRequestBuilderMock = nil;
|
||||
|
||||
[_graphRequestMock stopMocking];
|
||||
_graphRequestMock = nil;
|
||||
}
|
||||
|
||||
- (void)setUpSettingsMock
|
||||
@@ -225,6 +233,16 @@ typedef void (^FBSDKSKAdNetworkReporterBlock)(void);
|
||||
self.adNetworkReporterClassMock = OCMClassMock(FBSDKSKAdNetworkReporter.class);
|
||||
}
|
||||
|
||||
- (void)setUpAppLinkResolverRequestBuilderMock
|
||||
{
|
||||
_appLinkResolverRequestBuilderMock = OCMStrictClassMock(FBSDKAppLinkResolverRequestBuilder.class);
|
||||
}
|
||||
|
||||
- (void)setUpGraphRequestMock
|
||||
{
|
||||
_graphRequestMock = OCMStrictClassMock(FBSDKGraphRequest.class);
|
||||
}
|
||||
|
||||
#pragma mark - Public Methods
|
||||
|
||||
- (void)stubAppID:(NSString *)appID
|
||||
@@ -383,4 +401,23 @@ typedef void (^FBSDKSKAdNetworkReporterBlock)(void);
|
||||
OCMStub(ClassMethod([_serverConfigurationManagerClassMock loadServerConfigurationWithCompletionBlock:OCMArg.isNil]));
|
||||
}
|
||||
|
||||
- (void)stubGraphRequestWithResult:(id)result error:(nullable NSError *)error connection:(nullable FBSDKGraphRequestConnection *)connection
|
||||
{
|
||||
OCMStub([_graphRequestMock startWithCompletionHandler:([OCMArg invokeBlockWithArgs:[self nsNullIfNil:connection], [self nsNullIfNil:result], [self nsNullIfNil:error], nil])]);
|
||||
}
|
||||
|
||||
- (void)stubAppLinkResolverRequestBuilderWithIdiomSpecificField:(nullable NSString *)field
|
||||
{
|
||||
OCMStub([_appLinkResolverRequestBuilderMock getIdiomSpecificField]).andReturn(field);
|
||||
}
|
||||
|
||||
- (id)nsNullIfNil:(id)nilValue
|
||||
{
|
||||
id converted = nilValue;
|
||||
if (!nilValue) {
|
||||
converted = [NSNull null];
|
||||
}
|
||||
return converted;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
Reference in New Issue
Block a user