mirror of
https://github.com/zhigang1992/facebook-ios-sdk.git
synced 2026-01-12 17:22:28 +08:00
Backfill Unit Tests EventManager
Summary: Backfills some unit tests for event manager and introduces a protocol `FBSDKSwizzling` to be able to examine what is being swizzled by the type without actually doing any swizzling. Reviewed By: KylinChang Differential Revision: D26855106 fbshipit-source-id: f57a7dc8a4a00a0a0a16ae4355644f4e9d492583
This commit is contained in:
committed by
Facebook GitHub Bot
parent
9bf746529b
commit
99786670d6
@@ -703,7 +703,7 @@
|
||||
C4FC99F1202CD56D0038C5ED /* FBSDKHybridAppEventsScriptMessageHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = C4FC99D7202CD5590038C5ED /* FBSDKHybridAppEventsScriptMessageHandler.h */; };
|
||||
C4FC99F2202CD56D0038C5ED /* FBSDKHybridAppEventsScriptMessageHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = C4FC99D8202CD5590038C5ED /* FBSDKHybridAppEventsScriptMessageHandler.m */; };
|
||||
C51121CB20A27EF50041DC94 /* FBSDKEventBindingTests.m in Sources */ = {isa = PBXBuildFile; fileRef = C51121C920A27EF50041DC94 /* FBSDKEventBindingTests.m */; };
|
||||
C51121CC20A27EF50041DC94 /* FBSDKSampleEventBinding.swift in Sources */ = {isa = PBXBuildFile; fileRef = C51121CA20A27EF50041DC94 /* FBSDKSampleEventBinding.swift */; };
|
||||
C51121CC20A27EF50041DC94 /* SampleRawRemoteEventBindings.swift in Sources */ = {isa = PBXBuildFile; fileRef = C51121CA20A27EF50041DC94 /* SampleRawRemoteEventBindings.swift */; };
|
||||
C51122A020A4BCEB0041DC94 /* FBSDKApplicationDelegateTests.m in Sources */ = {isa = PBXBuildFile; fileRef = C511229F20A4BCEB0041DC94 /* FBSDKApplicationDelegateTests.m */; };
|
||||
C5188DF9222F388400F4D8BC /* FBSDKApplicationObserving.h in Headers */ = {isa = PBXBuildFile; fileRef = C5188DF8222F388400F4D8BC /* FBSDKApplicationObserving.h */; };
|
||||
C5188DFA222F388400F4D8BC /* FBSDKApplicationObserving.h in Headers */ = {isa = PBXBuildFile; fileRef = C5188DF8222F388400F4D8BC /* FBSDKApplicationObserving.h */; };
|
||||
@@ -1047,6 +1047,9 @@
|
||||
F4A033C525F13E1300D19DE9 /* UrlSessionTaskTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4A033C425F13E1300D19DE9 /* UrlSessionTaskTests.swift */; };
|
||||
F4A033D425F13FD700D19DE9 /* SampleUrl.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4A033D325F13FD700D19DE9 /* SampleUrl.swift */; };
|
||||
F4A033E325F1545B00D19DE9 /* GraphRequestPiggyBackManagerProviderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4A033E225F1545B00D19DE9 /* GraphRequestPiggyBackManagerProviderTests.swift */; };
|
||||
F4A0341925F15D9500D19DE9 /* EventBindingManagerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4A0341825F15D9500D19DE9 /* EventBindingManagerTests.swift */; };
|
||||
F4A0346E25F1985300D19DE9 /* TestSwizzler.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4A0346D25F1985200D19DE9 /* TestSwizzler.swift */; };
|
||||
F4A035C225F2C6F800D19DE9 /* SampleEventBindings.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4A035C125F2C6F800D19DE9 /* SampleEventBindings.swift */; };
|
||||
F4A2B1A525E56BF400DE13D9 /* FBSDKDeviceButton.h in Headers */ = {isa = PBXBuildFile; fileRef = 9D9E16AA1CB46C7D00C8B68F /* FBSDKDeviceButton.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
F4A2B1BA25E56BF500DE13D9 /* FBSDKDeviceButton.h in Headers */ = {isa = PBXBuildFile; fileRef = 9D9E16AA1CB46C7D00C8B68F /* FBSDKDeviceButton.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
F4A2B1D525E56C3200DE13D9 /* FBSDKDeviceViewControllerBase.h in Headers */ = {isa = PBXBuildFile; fileRef = 9D10A68B1CB38D5D00F42AC1 /* FBSDKDeviceViewControllerBase.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
@@ -1295,6 +1298,13 @@
|
||||
remoteGlobalIDString = 81B71CFC1D19C87400933E93;
|
||||
remoteInfo = "FBSDKCoreKit-Dynamic";
|
||||
};
|
||||
F46873E425F7D0D500ABD912 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = F4A4069C25F4522500F0E578 /* TestTools.xcodeproj */;
|
||||
proxyType = 2;
|
||||
remoteGlobalIDString = F4E5F09025F4354900D67852;
|
||||
remoteInfo = TestTools;
|
||||
};
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
@@ -1581,7 +1591,7 @@
|
||||
C4FC99D7202CD5590038C5ED /* FBSDKHybridAppEventsScriptMessageHandler.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FBSDKHybridAppEventsScriptMessageHandler.h; sourceTree = "<group>"; };
|
||||
C4FC99D8202CD5590038C5ED /* FBSDKHybridAppEventsScriptMessageHandler.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBSDKHybridAppEventsScriptMessageHandler.m; sourceTree = "<group>"; };
|
||||
C51121C920A27EF50041DC94 /* FBSDKEventBindingTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBSDKEventBindingTests.m; sourceTree = "<group>"; };
|
||||
C51121CA20A27EF50041DC94 /* FBSDKSampleEventBinding.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FBSDKSampleEventBinding.swift; sourceTree = "<group>"; };
|
||||
C51121CA20A27EF50041DC94 /* SampleRawRemoteEventBindings.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SampleRawRemoteEventBindings.swift; sourceTree = "<group>"; };
|
||||
C511229F20A4BCEB0041DC94 /* FBSDKApplicationDelegateTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBSDKApplicationDelegateTests.m; sourceTree = "<group>"; };
|
||||
C5188DF8222F388400F4D8BC /* FBSDKApplicationObserving.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FBSDKApplicationObserving.h; sourceTree = "<group>"; };
|
||||
C5188E312231C4B500F4D8BC /* FBSDKBridgeAPI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBSDKBridgeAPI.h; sourceTree = "<group>"; };
|
||||
@@ -1708,6 +1718,11 @@
|
||||
F4A033C425F13E1300D19DE9 /* UrlSessionTaskTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UrlSessionTaskTests.swift; sourceTree = "<group>"; };
|
||||
F4A033D325F13FD700D19DE9 /* SampleUrl.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SampleUrl.swift; sourceTree = "<group>"; };
|
||||
F4A033E225F1545B00D19DE9 /* GraphRequestPiggyBackManagerProviderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GraphRequestPiggyBackManagerProviderTests.swift; sourceTree = "<group>"; };
|
||||
F4A0341825F15D9500D19DE9 /* EventBindingManagerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventBindingManagerTests.swift; sourceTree = "<group>"; };
|
||||
F4A0342725F164EF00D19DE9 /* FBSDKSwizzling.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FBSDKSwizzling.h; sourceTree = "<group>"; };
|
||||
F4A0342825F1650900D19DE9 /* FBSDKSwizzler+Swizzling.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "FBSDKSwizzler+Swizzling.h"; sourceTree = "<group>"; };
|
||||
F4A0346D25F1985200D19DE9 /* TestSwizzler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestSwizzler.swift; sourceTree = "<group>"; };
|
||||
F4A035C125F2C6F800D19DE9 /* SampleEventBindings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SampleEventBindings.swift; sourceTree = "<group>"; };
|
||||
F4A11B4824E36E5200D4C010 /* FBSDKTypeUtility.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FBSDKTypeUtility.h; sourceTree = "<group>"; };
|
||||
F4A11B4924E36E5200D4C010 /* FBSDKURLSessionTask.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FBSDKURLSessionTask.h; sourceTree = "<group>"; };
|
||||
F4A11B4A24E36E5200D4C010 /* FBSDKSafeCast.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FBSDKSafeCast.h; sourceTree = "<group>"; };
|
||||
@@ -2111,6 +2126,7 @@
|
||||
9D195CC61B9FE2E000BD6BEC /* FBSDKContainerViewController.h */,
|
||||
9D195CC71B9FE2E000BD6BEC /* FBSDKContainerViewController.m */,
|
||||
890414731A647D2E00617215 /* FBSDKCoreKit+Internal.h */,
|
||||
F4A02F8C25EEAF6600D19DE9 /* FBSDKDataPersisting.h */,
|
||||
520223F51D83C8D200CE0AB5 /* FBSDKDeviceRequestsHelper.h */,
|
||||
520223F61D83C8D200CE0AB5 /* FBSDKDeviceRequestsHelper.m */,
|
||||
81C969301C114723002FC037 /* FBSDKDynamicFrameworkLoader.h */,
|
||||
@@ -2141,15 +2157,16 @@
|
||||
F4EC338525E6A86B0003C0CF /* FBSDKSettingsProtocol.h */,
|
||||
C5696FA1209CCEB3009C931F /* FBSDKSwizzler.h */,
|
||||
C5696FA2209CCEB4009C931F /* FBSDKSwizzler.m */,
|
||||
F4A0342825F1650900D19DE9 /* FBSDKSwizzler+Swizzling.h */,
|
||||
F4A0342725F164EF00D19DE9 /* FBSDKSwizzling.h */,
|
||||
52963A9D215993C100C7B252 /* FBSDKURL_Internal.h */,
|
||||
5DB7ADCA22EA59E60012E8CB /* Instrument */,
|
||||
89FB8C3D1A84237A003CAE60 /* Network */,
|
||||
F4A02F9425EEB09500D19DE9 /* NSUserDefaults+FBSDKDataPersisting.h */,
|
||||
89830F251A7805A900226ABB /* ServerConfiguration */,
|
||||
9D32A8381A69941A000A936D /* TokenCaching */,
|
||||
89FB8C3E1A842393003CAE60 /* UI */,
|
||||
89FB8C431A842644003CAE60 /* WebDialog */,
|
||||
F4A02F9425EEB09500D19DE9 /* NSUserDefaults+FBSDKDataPersisting.h */,
|
||||
F4A02F8C25EEAF6600D19DE9 /* FBSDKDataPersisting.h */,
|
||||
);
|
||||
path = Internal;
|
||||
sourceTree = "<group>";
|
||||
@@ -2633,7 +2650,7 @@
|
||||
C51121C720A27EF50041DC94 /* Codeless */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C51121CA20A27EF50041DC94 /* FBSDKSampleEventBinding.swift */,
|
||||
F4A0341825F15D9500D19DE9 /* EventBindingManagerTests.swift */,
|
||||
C51121C920A27EF50041DC94 /* FBSDKEventBindingTests.m */,
|
||||
);
|
||||
path = Codeless;
|
||||
@@ -2762,6 +2779,14 @@
|
||||
path = ML;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
F46873DA25F7D0D500ABD912 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
F46873E525F7D0D500ABD912 /* TestTools.framework */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
F487DBCA231EBD8B008416A9 /* Swift */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -2830,8 +2855,10 @@
|
||||
F496E58E24E49DBC006231A2 /* SampleAppEvents.swift */,
|
||||
F48AD347257700B80052C056 /* SampleAuthenticationToken.swift */,
|
||||
F4A0308E25EEE42300D19DE9 /* SampleError.swift */,
|
||||
F4A035C125F2C6F800D19DE9 /* SampleEventBindings.swift */,
|
||||
F4EB31BA2540A1B800736B67 /* SampleGraphRequestConnection.swift */,
|
||||
F4EB31D22540A35800736B67 /* SampleGraphRequests.swift */,
|
||||
C51121CA20A27EF50041DC94 /* SampleRawRemoteEventBindings.swift */,
|
||||
F4A02FF625EEC1CB00D19DE9 /* SampleRawRemoteGateKeeper.swift */,
|
||||
F4A0304825EECC6800D19DE9 /* SampleRawRemoteGateKeeperList.swift */,
|
||||
F4EB33CD2542323500736B67 /* SampleRawRemotePermissions.swift */,
|
||||
@@ -2852,6 +2879,7 @@
|
||||
F40D25F225E41C71004681FC /* TestOperationQueue.swift */,
|
||||
F494285C25829C72008FE009 /* TestSessionProvider.swift */,
|
||||
F4EC339425E6ABE60003C0CF /* TestSettings.swift */,
|
||||
F4A0346D25F1985200D19DE9 /* TestSwizzler.swift */,
|
||||
F496E5FD24E5D0D5006231A2 /* TestTokenCache.swift */,
|
||||
F43F397C25D48C4B0046027A /* TestURLSessionProxy.swift */,
|
||||
F4F6036F25D5D3A30053D3E7 /* TestURLSessionProxyFactory.swift */,
|
||||
@@ -3779,6 +3807,10 @@
|
||||
ProductGroup = 9D9947101A9531B5003375EC /* Products */;
|
||||
ProjectRef = 9D99470F1A9531B5003375EC /* OCMock.xcodeproj */;
|
||||
},
|
||||
{
|
||||
ProductGroup = F46873DA25F7D0D500ABD912 /* Products */;
|
||||
ProjectRef = F4A4069C25F4522500F0E578 /* TestTools.xcodeproj */;
|
||||
},
|
||||
);
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
@@ -3849,6 +3881,13 @@
|
||||
remoteRef = 9D9947281A9531B5003375EC /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
F46873E525F7D0D500ABD912 /* TestTools.framework */ = {
|
||||
isa = PBXReferenceProxy;
|
||||
fileType = wrapper.framework;
|
||||
path = TestTools.framework;
|
||||
remoteRef = F46873E425F7D0D500ABD912 /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
/* End PBXReferenceProxy section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
@@ -4403,6 +4442,7 @@
|
||||
C77C07A62486BAC600345460 /* FBSDKRestrictiveDataFilterTests.m in Sources */,
|
||||
F4E50155243648A100C99262 /* FBSDKServerConfigurationFixtures.m in Sources */,
|
||||
894C0B4A1A70524F009137EF /* FBSDKBase64Tests.swift in Sources */,
|
||||
F4A0346E25F1985300D19DE9 /* TestSwizzler.swift in Sources */,
|
||||
894C0B3A1A702EBE009137EF /* FBSDKBridgeAPIProtocolNativeV1Tests.m in Sources */,
|
||||
F4E50156243648A100C99262 /* FBSDKServerConfigurationTests.m in Sources */,
|
||||
F48AD3252576FEB20052C056 /* FBSDKAuthenticationTokenTests.m in Sources */,
|
||||
@@ -4436,7 +4476,7 @@
|
||||
89C8B19C1A8D7A27009B07F5 /* FBSDKUtilityTests.swift in Sources */,
|
||||
F441DDE725DDDB670092C8F6 /* GraphRequestConnectionFactoryTests.swift in Sources */,
|
||||
F41979282475A20E003007CC /* FBSDKTypeUtilityTests.m in Sources */,
|
||||
C51121CC20A27EF50041DC94 /* FBSDKSampleEventBinding.swift in Sources */,
|
||||
C51121CC20A27EF50041DC94 /* SampleRawRemoteEventBindings.swift in Sources */,
|
||||
F916581524F6BAB200BB759A /* FBSDKSKAdNetworkConversionConfigurationTests.m in Sources */,
|
||||
F4A826B724EC6FAD00EB2CD4 /* FBSDKProfileTests.m in Sources */,
|
||||
F4CCDC8825E958320057FE5F /* GateKeeperManagerTests.swift in Sources */,
|
||||
@@ -4449,8 +4489,10 @@
|
||||
C6E3622625E03FD0007D555D /* FBSDKAuthenticationTokenHeaderTests.m in Sources */,
|
||||
C6C5CBDC2581875600AA3BB3 /* FBSDKAuthenticationStatusUtilityTests.m in Sources */,
|
||||
F4EB31D32540A35800736B67 /* SampleGraphRequests.swift in Sources */,
|
||||
F4A0341925F15D9500D19DE9 /* EventBindingManagerTests.swift in Sources */,
|
||||
F402B062255C645600473083 /* FakeLoginManager.m in Sources */,
|
||||
F441DC3E25DC97E60092C8F6 /* TestGraphRequestConnection.swift in Sources */,
|
||||
F4A035C225F2C6F800D19DE9 /* SampleEventBindings.swift in Sources */,
|
||||
F4D80B582565D6B3008CCAF0 /* FBSDKRestrictiveDataTests.m in Sources */,
|
||||
F4EB33CE2542323500736B67 /* SampleRawRemotePermissions.swift in Sources */,
|
||||
5DBB0447227FEF700009E0A6 /* FBSDKBasicUtilityTests.m in Sources */,
|
||||
|
||||
@@ -22,13 +22,17 @@
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
NS_SWIFT_NAME(EventBindingManager)
|
||||
@interface FBSDKEventBindingManager : NSObject
|
||||
|
||||
- (FBSDKEventBindingManager*)initWithJSON:(NSDictionary*)dict;
|
||||
- (instancetype)initWithJSON:(NSDictionary*)dict;
|
||||
- (void)updateBindings:(NSArray *)bindings;
|
||||
+ (NSArray *)parseArray:(NSArray *)array;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
#endif
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
#import "FBSDKCodelessPathComponent.h"
|
||||
#import "FBSDKEventBinding.h"
|
||||
#import "FBSDKInternalUtility.h"
|
||||
#import "FBSDKSwizzler.h"
|
||||
#import "FBSDKSwizzler+Swizzling.h"
|
||||
#import "FBSDKViewHierarchy.h"
|
||||
#import "FBSDKViewHierarchyMacros.h"
|
||||
|
||||
@@ -37,29 +37,36 @@
|
||||
#define ReactNativeTouchEndEventName @"touchEnd"
|
||||
|
||||
#define ReactNativeClassRCTTextView "RCTTextView"
|
||||
#define ReactNativeClassRCTImageView "RCTImageVIew"
|
||||
#define ReactNativeClassRCTImageView "RCTImageView"
|
||||
#define ReactNativeClassRCTTouchEvent "RCTTouchEvent"
|
||||
#define ReactNativeClassRCTTouchHandler "RCTTouchHandler"
|
||||
|
||||
@interface FBSDKEventBindingManager ()
|
||||
{
|
||||
BOOL isStarted;
|
||||
NSMutableDictionary *reactBindings;
|
||||
NSSet *validClasses;
|
||||
BOOL hasReactNative;
|
||||
NSArray *eventBindings;
|
||||
BOOL _isStarted;
|
||||
NSMutableDictionary *_reactBindings;
|
||||
NSSet *_validClasses;
|
||||
BOOL _hasReactNative;
|
||||
NSArray *_eventBindings;
|
||||
Class<FBSDKSwizzling> _swizzler;
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation FBSDKEventBindingManager
|
||||
|
||||
- (id)init
|
||||
- (instancetype)init
|
||||
{
|
||||
return [self initWithSwizzler:FBSDKSwizzler.class];
|
||||
}
|
||||
|
||||
- (instancetype)initWithSwizzler:(Class<FBSDKSwizzling>)swizzling;
|
||||
{
|
||||
self = [super init];
|
||||
if (self) {
|
||||
isStarted = NO;
|
||||
hasReactNative = NO;
|
||||
reactBindings = [NSMutableDictionary dictionary];
|
||||
_swizzler = swizzling;
|
||||
_isStarted = NO;
|
||||
_hasReactNative = NO;
|
||||
_reactBindings = [NSMutableDictionary dictionary];
|
||||
|
||||
NSMutableSet *classes = [NSMutableSet set];
|
||||
[classes addObject:[UIControl class]];
|
||||
@@ -68,7 +75,7 @@
|
||||
// ReactNative
|
||||
Class classRCTRootView = objc_lookUpClass(ReactNativeClassRCTRootView);
|
||||
if (classRCTRootView != nil) {
|
||||
hasReactNative = YES;
|
||||
_hasReactNative = YES;
|
||||
Class classRCTView = objc_lookUpClass(ReactNativeClassRCTView);
|
||||
Class classRCTTextView = objc_lookUpClass(ReactNativeClassRCTTextView);
|
||||
Class classRCTImageView = objc_lookUpClass(ReactNativeClassRCTImageView);
|
||||
@@ -82,7 +89,28 @@
|
||||
[classes addObject:classRCTImageView];
|
||||
}
|
||||
}
|
||||
validClasses = [NSSet setWithSet:classes];
|
||||
_validClasses = [NSSet setWithSet:classes];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)initWithJSON:(NSDictionary *)dict
|
||||
{
|
||||
return [self initWithSwizzler:FBSDKSwizzler.class json:dict];
|
||||
}
|
||||
|
||||
- (instancetype)initWithSwizzler:(Class<FBSDKSwizzling>)swizzling
|
||||
json:(NSDictionary *)dict
|
||||
{
|
||||
if ((self = [super init])) {
|
||||
_swizzler = swizzling;
|
||||
NSArray *eventBindingsDict = [FBSDKTypeUtility arrayValue:dict[@"event_bindings"]];
|
||||
NSMutableArray *bindings = [NSMutableArray array];
|
||||
for (NSDictionary *d in eventBindingsDict) {
|
||||
FBSDKEventBinding *e = [[FBSDKEventBinding alloc] initWithJSON:d];
|
||||
[FBSDKTypeUtility array:bindings addObject:e];
|
||||
}
|
||||
_eventBindings = [bindings copy];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
@@ -99,65 +127,52 @@
|
||||
return [result copy];
|
||||
}
|
||||
|
||||
- (FBSDKEventBindingManager *)initWithJSON:(NSDictionary *)dict
|
||||
{
|
||||
if ((self = [super init])) {
|
||||
NSArray *eventBindingsDict = [FBSDKTypeUtility arrayValue:dict[@"event_bindings"]];
|
||||
NSMutableArray *bindings = [NSMutableArray array];
|
||||
for (NSDictionary *d in eventBindingsDict) {
|
||||
FBSDKEventBinding *e = [[FBSDKEventBinding alloc] initWithJSON:d];
|
||||
[FBSDKTypeUtility array:bindings addObject:e];
|
||||
}
|
||||
eventBindings = [bindings copy];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wundeclared-selector"
|
||||
- (void)start
|
||||
{
|
||||
if (isStarted) {
|
||||
if (self.isStarted) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (0 == eventBindings.count) {
|
||||
if (0 == self.eventBindings.count) {
|
||||
return;
|
||||
}
|
||||
|
||||
isStarted = YES;
|
||||
self.isStarted = YES;
|
||||
|
||||
void (^blockToWindow)(id view) = ^(id view) {
|
||||
[self matchView:view delegate:nil];
|
||||
};
|
||||
|
||||
[FBSDKSwizzler swizzleSelector:@selector(didMoveToWindow)
|
||||
[self.swizzler swizzleSelector:@selector(didMoveToWindow)
|
||||
onClass:[UIControl class]
|
||||
withBlock:blockToWindow named:@"map_control"];
|
||||
withBlock:blockToWindow
|
||||
named:@"map_control"];
|
||||
|
||||
// ReactNative
|
||||
if (hasReactNative) { // If app is built via ReactNative
|
||||
if (self.hasReactNative) { // If app is built via ReactNative
|
||||
Class classRCTView = objc_lookUpClass(ReactNativeClassRCTView);
|
||||
Class classRCTTextView = objc_lookUpClass(ReactNativeClassRCTTextView);
|
||||
Class classRCTImageView = objc_lookUpClass(ReactNativeClassRCTImageView);
|
||||
Class classRCTTouchHandler = objc_lookUpClass(ReactNativeClassRCTTouchHandler);
|
||||
|
||||
// All react-native views would be added tp RCTRootView, so no need to check didMoveToWindow
|
||||
[FBSDKSwizzler swizzleSelector:@selector(didMoveToWindow)
|
||||
[self.swizzler swizzleSelector:@selector(didMoveToWindow)
|
||||
onClass:classRCTView
|
||||
withBlock:blockToWindow
|
||||
named:@"match_react_native"];
|
||||
[FBSDKSwizzler swizzleSelector:@selector(didMoveToWindow)
|
||||
[self.swizzler swizzleSelector:@selector(didMoveToWindow)
|
||||
onClass:classRCTTextView
|
||||
withBlock:blockToWindow
|
||||
named:@"match_react_native"];
|
||||
[FBSDKSwizzler swizzleSelector:@selector(didMoveToWindow)
|
||||
[self.swizzler swizzleSelector:@selector(didMoveToWindow)
|
||||
onClass:classRCTImageView
|
||||
withBlock:blockToWindow
|
||||
named:@"match_react_native"];
|
||||
|
||||
// RCTTouchHandler handles with touch events, like touchEnd and uses RCTEventDispather to dispatch events, so we can check _updateAndDispatchTouches to fire events
|
||||
[FBSDKSwizzler swizzleSelector:@selector(_updateAndDispatchTouches:eventName:) onClass:classRCTTouchHandler withBlock:^(id touchHandler, SEL command, id touches, id eventName) {
|
||||
[self.swizzler swizzleSelector:@selector(_updateAndDispatchTouches:eventName:) onClass:classRCTTouchHandler withBlock:^(id touchHandler, SEL command, id touches, id eventName) {
|
||||
if ([touches isKindOfClass:[NSSet class]] && [eventName isKindOfClass:[NSString class]]) {
|
||||
@try {
|
||||
NSString *reactEventName = (NSString *)eventName;
|
||||
@@ -174,7 +189,7 @@
|
||||
}
|
||||
targetView = targetView.superview;
|
||||
}
|
||||
FBSDKEventBinding *eventBinding = self->reactBindings[reactTag];
|
||||
FBSDKEventBinding *eventBinding = self->_reactBindings[reactTag];
|
||||
if (reactTag != nil && eventBinding != nil) {
|
||||
[eventBinding trackEvent:nil];
|
||||
}
|
||||
@@ -198,7 +213,7 @@
|
||||
|
||||
[self matchView:tableView delegate:delegate];
|
||||
};
|
||||
[FBSDKSwizzler swizzleSelector:@selector(setDelegate:)
|
||||
[self.swizzler swizzleSelector:@selector(setDelegate:)
|
||||
onClass:[UITableView class]
|
||||
withBlock:tableViewBlock
|
||||
named:@"match_table_view"];
|
||||
@@ -213,7 +228,7 @@
|
||||
|
||||
[self matchView:collectionView delegate:delegate];
|
||||
};
|
||||
[FBSDKSwizzler swizzleSelector:@selector(setDelegate:)
|
||||
[self.swizzler swizzleSelector:@selector(setDelegate:)
|
||||
onClass:[UICollectionView class]
|
||||
withBlock:collectionViewBlock
|
||||
named:@"handle_collection_view"];
|
||||
@@ -221,7 +236,7 @@
|
||||
|
||||
- (void)rematchBindings
|
||||
{
|
||||
if (0 == eventBindings.count) {
|
||||
if (0 == self.eventBindings.count) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -239,7 +254,7 @@
|
||||
|
||||
for (UIView *subview in view.subviews) {
|
||||
BOOL isValidClass = NO;
|
||||
for (Class cls in validClasses) {
|
||||
for (Class cls in self.validClasses) {
|
||||
if ([subview isKindOfClass:cls]) {
|
||||
isValidClass = YES;
|
||||
break;
|
||||
@@ -271,10 +286,12 @@
|
||||
// check if the view is matched to any event
|
||||
- (void)matchView:(UIView *)view delegate:(id)delegate
|
||||
{
|
||||
if (0 == eventBindings.count) {
|
||||
if (0 == self.eventBindings.count) {
|
||||
return;
|
||||
}
|
||||
|
||||
__weak Class<FBSDKSwizzling> weakSwizzler = self.swizzler;
|
||||
__block BOOL hasReactNative = self.hasReactNative;
|
||||
fb_dispatch_on_main_thread(^{
|
||||
if (![view window]) {
|
||||
return;
|
||||
@@ -285,7 +302,7 @@
|
||||
fb_dispatch_on_default_thread(^{
|
||||
if ([view isKindOfClass:[UIControl class]]) {
|
||||
UIControl *control = (UIControl *)view;
|
||||
for (FBSDKEventBinding *binding in self->eventBindings) {
|
||||
for (FBSDKEventBinding *binding in self->_eventBindings) {
|
||||
if ([FBSDKEventBinding isPath:binding.path matchViewPath:path]) {
|
||||
fb_dispatch_on_main_thread(^{
|
||||
[control addTarget:binding
|
||||
@@ -295,15 +312,15 @@
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (self->hasReactNative
|
||||
} else if (hasReactNative
|
||||
&& [view respondsToSelector:@selector(reactTag)]) {
|
||||
for (FBSDKEventBinding *binding in self->eventBindings) {
|
||||
for (FBSDKEventBinding *binding in self->_eventBindings) {
|
||||
if ([FBSDKEventBinding isPath:binding.path matchViewPath:path]) {
|
||||
fb_dispatch_on_main_thread(^{
|
||||
if (view) {
|
||||
NSNumber *reactTag = [FBSDKViewHierarchy getViewReactTag:view];
|
||||
if (reactTag != nil) {
|
||||
[FBSDKTypeUtility dictionary:self->reactBindings setObject:binding forKey:reactTag];
|
||||
[FBSDKTypeUtility dictionary:self->_reactBindings setObject:binding forKey:reactTag];
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -314,7 +331,7 @@
|
||||
&& [delegate conformsToProtocol:@protocol(UITableViewDelegate)]) {
|
||||
fb_dispatch_on_default_thread(^{
|
||||
NSMutableSet *matchedBindings = [NSMutableSet set];
|
||||
for (FBSDKEventBinding *binding in self->eventBindings) {
|
||||
for (FBSDKEventBinding *binding in self->_eventBindings) {
|
||||
if (binding.path.count > 1) {
|
||||
NSArray *shortPath = [binding.path
|
||||
subarrayWithRange:NSMakeRange(0, binding.path.count - 1)];
|
||||
@@ -338,17 +355,17 @@
|
||||
}
|
||||
});
|
||||
};
|
||||
[FBSDKSwizzler swizzleSelector:@selector(tableView:didSelectRowAtIndexPath:)
|
||||
onClass:[delegate class]
|
||||
withBlock:block
|
||||
named:@"handle_table_view"];
|
||||
[weakSwizzler swizzleSelector:@selector(tableView:didSelectRowAtIndexPath:)
|
||||
onClass:[delegate class]
|
||||
withBlock:block
|
||||
named:@"handle_table_view"];
|
||||
}
|
||||
});
|
||||
} else if ([view isKindOfClass:[UICollectionView class]]
|
||||
&& [delegate conformsToProtocol:@protocol(UICollectionViewDelegate)]) {
|
||||
fb_dispatch_on_default_thread(^{
|
||||
NSMutableSet *matchedBindings = [NSMutableSet set];
|
||||
for (FBSDKEventBinding *binding in self->eventBindings) {
|
||||
for (FBSDKEventBinding *binding in self->_eventBindings) {
|
||||
if (binding.path.count > 1) {
|
||||
NSArray *shortPath = [binding.path
|
||||
subarrayWithRange:NSMakeRange(0, binding.path.count - 1)];
|
||||
@@ -372,10 +389,10 @@
|
||||
}
|
||||
});
|
||||
};
|
||||
[FBSDKSwizzler swizzleSelector:@selector(collectionView:didSelectItemAtIndexPath:)
|
||||
onClass:[delegate class]
|
||||
withBlock:block
|
||||
named:@"handle_collection_view"];
|
||||
[weakSwizzler swizzleSelector:@selector(collectionView:didSelectItemAtIndexPath:)
|
||||
onClass:[delegate class]
|
||||
withBlock:block
|
||||
named:@"handle_collection_view"];
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -386,11 +403,11 @@
|
||||
#pragma clang diagnostic pop
|
||||
- (void)updateBindings:(NSArray *)bindings
|
||||
{
|
||||
if (eventBindings.count > 0 && eventBindings.count == bindings.count) {
|
||||
if (self.eventBindings.count > 0 && self.eventBindings.count == bindings.count) {
|
||||
// Check whether event bindings are the same
|
||||
BOOL isSame = YES;
|
||||
for (int i = 0; i < eventBindings.count; i++) {
|
||||
if (![[FBSDKTypeUtility array:eventBindings objectAtIndex:i] isEqualToBinding:[FBSDKTypeUtility array:bindings objectAtIndex:i]]) {
|
||||
for (int i = 0; i < self.eventBindings.count; i++) {
|
||||
if (![[FBSDKTypeUtility array:self.eventBindings objectAtIndex:i] isEqualToBinding:[FBSDKTypeUtility array:bindings objectAtIndex:i]]) {
|
||||
isSame = NO;
|
||||
break;
|
||||
}
|
||||
@@ -401,9 +418,9 @@
|
||||
}
|
||||
}
|
||||
|
||||
eventBindings = bindings;
|
||||
[reactBindings removeAllObjects];
|
||||
if (!isStarted) {
|
||||
self.eventBindings = bindings;
|
||||
[self.reactBindings removeAllObjects];
|
||||
if (!self.isStarted) {
|
||||
[self start];
|
||||
}
|
||||
|
||||
@@ -412,6 +429,57 @@
|
||||
});
|
||||
}
|
||||
|
||||
- (BOOL)isStarted
|
||||
{
|
||||
return _isStarted;
|
||||
}
|
||||
|
||||
- (void)setIsStarted:(BOOL)isStarted
|
||||
{
|
||||
_isStarted = isStarted;
|
||||
}
|
||||
|
||||
- (Class<FBSDKSwizzling>)swizzler
|
||||
{
|
||||
return _swizzler;
|
||||
}
|
||||
|
||||
- (BOOL)hasReactNative
|
||||
{
|
||||
return _hasReactNative;
|
||||
}
|
||||
|
||||
- (NSSet *)validClasses
|
||||
{
|
||||
return _validClasses;
|
||||
}
|
||||
|
||||
- (NSArray<FBSDKEventBinding *> *)eventBindings
|
||||
{
|
||||
return _eventBindings;
|
||||
}
|
||||
|
||||
- (NSMutableDictionary *)reactBindings
|
||||
{
|
||||
return _reactBindings;
|
||||
}
|
||||
|
||||
- (void)setEventBindings:(NSArray<FBSDKEventBinding *> *)bindings
|
||||
{
|
||||
_eventBindings = bindings;
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
#if FBSDKTEST
|
||||
|
||||
- (void)setReactBindings:(NSMutableDictionary *)bindings
|
||||
{
|
||||
_reactBindings = bindings;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
|
||||
29
FBSDKCoreKit/FBSDKCoreKit/Internal/FBSDKSwizzler+Swizzling.h
Normal file
29
FBSDKCoreKit/FBSDKCoreKit/Internal/FBSDKSwizzler+Swizzling.h
Normal file
@@ -0,0 +1,29 @@
|
||||
// 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 <Foundation/Foundation.h>
|
||||
|
||||
#import "FBSDKSwizzling.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
// Default conformance to the Swizzling interface
|
||||
@interface FBSDKSwizzler (Swizzling) <FBSDKSwizzling>
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
30
FBSDKCoreKit/FBSDKCoreKit/Internal/FBSDKSwizzling.h
Normal file
30
FBSDKCoreKit/FBSDKCoreKit/Internal/FBSDKSwizzling.h
Normal file
@@ -0,0 +1,30 @@
|
||||
// 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 <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
NS_SWIFT_NAME(Swizzling)
|
||||
@protocol FBSDKSwizzling
|
||||
|
||||
+ (void)swizzleSelector:(SEL)aSelector onClass:(Class)aClass withBlock:(swizzleBlock)block named:(NSString *)aName;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -22,6 +22,8 @@
|
||||
#import "FBSDKBridgeAPI+Testing.h"
|
||||
#import "FBSDKCloseIcon.h"
|
||||
#import "FBSDKEventDeactivationManager.h"
|
||||
#import "FBSDKEventBinding.h"
|
||||
#import "FBSDKEventBindingManager.h"
|
||||
#import "FBSDKMath.h"
|
||||
#import "FBSDKSKAdNetworkEvent.h"
|
||||
#import "FBSDKSKAdNetworkRule.h"
|
||||
@@ -52,6 +54,8 @@
|
||||
// Data Persistance
|
||||
#import "FBSDKDataPersisting.h"
|
||||
#import "NSUserDefaults+FBSDKDataPersisting.h"
|
||||
// Swizzling
|
||||
#import "FBSDKSwizzling.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@@ -142,4 +146,20 @@ NS_SWIFT_NAME(parse(result:error:));
|
||||
|
||||
@end
|
||||
|
||||
@interface FBSDKEventBindingManager (Testing)
|
||||
|
||||
@property (nonatomic) BOOL isStarted;
|
||||
@property (nonatomic, nullable) NSMutableDictionary *reactBindings;
|
||||
@property (nonatomic, readonly) NSSet *validClasses;
|
||||
@property (nonatomic) BOOL hasReactNative;
|
||||
@property (nonatomic, nullable) NSArray<FBSDKEventBinding *> *eventBindings;
|
||||
@property (nonatomic, nullable, readonly) Class<FBSDKSwizzling> swizzler;
|
||||
|
||||
- (instancetype)initWithSwizzler:(Class<FBSDKSwizzling>)swizzling;
|
||||
- (instancetype)initWithSwizzler:(Class<FBSDKSwizzling>)swizzling
|
||||
json:(NSDictionary *)dict;
|
||||
- (void)start;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
@@ -0,0 +1,300 @@
|
||||
// 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
|
||||
|
||||
@objc
|
||||
protocol WindowMoving {
|
||||
func didMoveToWindow()
|
||||
}
|
||||
|
||||
class EventBindingManagerTests: XCTestCase {
|
||||
|
||||
var manager: EventBindingManager! // swiftlint:disable:this implicitly_unwrapped_optional
|
||||
var bindings = SampleEventBindingList.valid
|
||||
|
||||
let expectedEvidenceWithoutReactNative = [
|
||||
SwizzleEvidence(selector: #selector(UIControl.didMoveToWindow), class: UIControl.self),
|
||||
SwizzleEvidence(selector: #selector(setter: UITableView.delegate), class: UITableView.self),
|
||||
SwizzleEvidence(selector: #selector(setter: UICollectionView.delegate), class: UICollectionView.self)
|
||||
]
|
||||
|
||||
override func setUp() {
|
||||
super.setUp()
|
||||
|
||||
registerReactNativeClasses()
|
||||
TestSwizzler.reset()
|
||||
|
||||
manager = EventBindingManager(
|
||||
swizzler: TestSwizzler.self,
|
||||
json: SampleRawRemoteEventBindings.sampleDictionary
|
||||
)
|
||||
}
|
||||
|
||||
// MARK: - Dependencies
|
||||
|
||||
func testCreatingDefault() {
|
||||
XCTAssertTrue(
|
||||
EventBindingManager().swizzler is Swizzler.Type,
|
||||
"Should be created with the expected concrete swizzling type by default"
|
||||
)
|
||||
}
|
||||
|
||||
func testCreatingDefaultWithJson() {
|
||||
manager = EventBindingManager(json: ["some": "stuff"])
|
||||
XCTAssertTrue(
|
||||
manager.swizzler is Swizzler.Type,
|
||||
"Should be created with the expected concrete swizzling type by default"
|
||||
)
|
||||
}
|
||||
|
||||
func testCreatingCustom() {
|
||||
manager = EventBindingManager(swizzler: TestSwizzler.self)
|
||||
XCTAssertTrue(
|
||||
manager.swizzler is TestSwizzler.Type,
|
||||
"Should be created with the provided swizzling type"
|
||||
)
|
||||
}
|
||||
|
||||
func testCreatingCustomWithJson() {
|
||||
manager = EventBindingManager(
|
||||
swizzler: TestSwizzler.self,
|
||||
json: ["some": "stuff"]
|
||||
)
|
||||
XCTAssertTrue(
|
||||
manager.swizzler is TestSwizzler.Type,
|
||||
"Should be created with the provided swizzling type"
|
||||
)
|
||||
}
|
||||
|
||||
func testCreatingWithReactNativeUnavailable() {
|
||||
deregisterReactNativeClasses()
|
||||
manager = EventBindingManager(swizzler: TestSwizzler.self)
|
||||
XCTAssertFalse(
|
||||
manager.hasReactNative,
|
||||
"Should detect if react native is in the runtime"
|
||||
)
|
||||
manager.validClasses.forEach { item in
|
||||
switch item.base {
|
||||
case is UIControl.Type: break
|
||||
case is UICollectionView.Type: break
|
||||
case is UITableView.Type: break
|
||||
default: XCTFail("\(item.description) should not be considered valid")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func testCreatingWithReactNativeAvailable() {
|
||||
manager = EventBindingManager(swizzler: TestSwizzler.self)
|
||||
XCTAssertTrue(
|
||||
manager.hasReactNative,
|
||||
"Should detect if react native is in the runtime"
|
||||
)
|
||||
let classNames = Set(manager.validClasses.map { $0.description })
|
||||
let expected = Set([
|
||||
"RCTTextView",
|
||||
"RCTImageView",
|
||||
"UITableView",
|
||||
"UIControl",
|
||||
"UICollectionView",
|
||||
"RCTView"
|
||||
])
|
||||
XCTAssertEqual(
|
||||
classNames,
|
||||
expected,
|
||||
"Should have a known set of valid classes"
|
||||
)
|
||||
}
|
||||
|
||||
// MARK: - Starting
|
||||
|
||||
func testStartingWithEventsWhenStarted() {
|
||||
manager.isStarted = true
|
||||
manager.start()
|
||||
|
||||
XCTAssertTrue(TestSwizzler.evidence.isEmpty)
|
||||
}
|
||||
|
||||
func testStartingWithEventsWhenNotStarted() {
|
||||
manager.isStarted = false
|
||||
manager.start()
|
||||
|
||||
XCTAssertEqual(
|
||||
TestSwizzler.evidence,
|
||||
expectedEvidenceWithoutReactNative
|
||||
)
|
||||
}
|
||||
|
||||
func testStartingWithoutEventsWhenStarted() {
|
||||
manager.eventBindings = []
|
||||
manager.isStarted = true
|
||||
manager.start()
|
||||
|
||||
XCTAssertTrue(TestSwizzler.evidence.isEmpty)
|
||||
}
|
||||
|
||||
func testStartingWithoutEventsWhenNotStarted() {
|
||||
manager.eventBindings = []
|
||||
manager.isStarted = false
|
||||
manager.start()
|
||||
|
||||
XCTAssertTrue(TestSwizzler.evidence.isEmpty)
|
||||
}
|
||||
|
||||
func testStartingWithReactNativeClasses() {
|
||||
manager = EventBindingManager(swizzler: TestSwizzler.self)
|
||||
|
||||
// Updating bindings will actually call start if it is not in a started state
|
||||
manager.isStarted = true
|
||||
manager.updateBindings(bindings)
|
||||
|
||||
manager.isStarted = false
|
||||
manager.start()
|
||||
|
||||
// This is ugly but there is no good way to do this in Swift.
|
||||
// swiftlint:disable line_length
|
||||
let expected = "["
|
||||
.appending(
|
||||
[
|
||||
"FBSDKCoreKitTests.SwizzleEvidence(selector: didMoveToWindow, class: UIControl, block: Optional((Function)))",
|
||||
"FBSDKCoreKitTests.SwizzleEvidence(selector: didMoveToWindow, class: RCTView, block: Optional((Function)))",
|
||||
"FBSDKCoreKitTests.SwizzleEvidence(selector: didMoveToWindow, class: RCTTextView, block: Optional((Function)))",
|
||||
"FBSDKCoreKitTests.SwizzleEvidence(selector: didMoveToWindow, class: RCTImageView, block: Optional((Function)))"
|
||||
]
|
||||
.joined(separator: ", ")
|
||||
)
|
||||
.appending("]")
|
||||
// swiftlint:enable line_length
|
||||
|
||||
XCTAssertEqual(
|
||||
TestSwizzler.evidence.description,
|
||||
expected
|
||||
)
|
||||
}
|
||||
|
||||
// MARK: - Updating Bindings
|
||||
|
||||
func testUpdatingEventBindings() {
|
||||
manager = EventBindingManager(swizzler: TestSwizzler.self)
|
||||
manager.reactBindings = ["foo": EventBinding()]
|
||||
manager.updateBindings(bindings)
|
||||
|
||||
XCTAssertEqual(
|
||||
manager.eventBindings,
|
||||
bindings,
|
||||
"Should persist updated event bindings"
|
||||
)
|
||||
XCTAssertEqual(
|
||||
manager.reactBindings?.count,
|
||||
0,
|
||||
"Should clear react bindings when updating bindings"
|
||||
)
|
||||
}
|
||||
|
||||
func testUpdatingEventBindingsWithIdenticalBindings() {
|
||||
manager = EventBindingManager(swizzler: TestSwizzler.self)
|
||||
manager.updateBindings(bindings)
|
||||
manager.updateBindings(bindings)
|
||||
|
||||
XCTAssertEqual(
|
||||
manager.eventBindings,
|
||||
bindings,
|
||||
"Should not add duplicate event bindings"
|
||||
)
|
||||
}
|
||||
|
||||
func testUpdatingEventBindingsWithRecreatedBindings() {
|
||||
manager.updateBindings(bindings)
|
||||
|
||||
guard let eventBindings = manager.eventBindings else {
|
||||
return XCTFail("There should be event bindings on the manager")
|
||||
}
|
||||
|
||||
eventBindings.enumerated().forEach { pair in
|
||||
let (index, element) = pair
|
||||
XCTAssertTrue(
|
||||
element.isEqual(to: bindings[index]),
|
||||
"Bindings with the same information should be considered equal"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func testUpdatingEventBindingsWithDifferentBindingsDifferentNumberOfBindings() {
|
||||
bindings.append(EventBinding())
|
||||
manager.updateBindings(bindings)
|
||||
|
||||
XCTAssertEqual(
|
||||
manager.eventBindings,
|
||||
bindings,
|
||||
"Setting a different number of bindings from the number of stored bindings should overwrite the stored bindings"
|
||||
)
|
||||
}
|
||||
|
||||
func testUpdatingEventBindingsWithDifferentBindingsSameNumberOfBindings() {
|
||||
let binding = SampleEventBinding.valid(withName: "foo")
|
||||
let binding2 = SampleEventBinding.valid(withName: "bar")
|
||||
let binding3 = SampleEventBinding.valid(withName: "baz")
|
||||
|
||||
manager.updateBindings([binding, binding2])
|
||||
manager.updateBindings([binding2, binding3])
|
||||
|
||||
XCTAssertEqual(
|
||||
manager.eventBindings,
|
||||
[binding2, binding3],
|
||||
"Setting different bindings from the stored bindings should overwrite the stored bindings"
|
||||
)
|
||||
}
|
||||
|
||||
func testUpdatingBindingsStarts() {
|
||||
manager.isStarted = false
|
||||
manager = EventBindingManager(swizzler: TestSwizzler.self)
|
||||
manager.updateBindings(bindings)
|
||||
|
||||
XCTAssertTrue(
|
||||
manager.isStarted,
|
||||
"Updating bindings should start the manager if it is not started"
|
||||
)
|
||||
}
|
||||
|
||||
// MARK: - Helpers
|
||||
|
||||
func registerReactNativeClasses() {
|
||||
if objc_lookUpClass("RCTRootView") == nil,
|
||||
let reactRootView: AnyClass = objc_allocateClassPair(NSObject.self, "RCTRootView", 0),
|
||||
let imageView: AnyClass = objc_allocateClassPair(NSObject.self, "RCTImageView", 0),
|
||||
let textView: AnyClass = objc_allocateClassPair(NSObject.self, "RCTTextView", 0),
|
||||
let view: AnyClass = objc_allocateClassPair(NSObject.self, "RCTView", 0) {
|
||||
objc_registerClassPair(reactRootView)
|
||||
objc_registerClassPair(imageView)
|
||||
objc_registerClassPair(textView)
|
||||
objc_registerClassPair(view)
|
||||
}
|
||||
}
|
||||
|
||||
func deregisterReactNativeClasses() {
|
||||
if let rootViewClass = objc_lookUpClass("RCTRootView"),
|
||||
let imageView = objc_lookUpClass("RCTImageView"),
|
||||
let textView = objc_lookUpClass("RCTTextView"),
|
||||
let view = objc_lookUpClass("RCTView") {
|
||||
objc_disposeClassPair(rootViewClass)
|
||||
objc_disposeClassPair(imageView)
|
||||
objc_disposeClassPair(textView)
|
||||
objc_disposeClassPair(view)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -50,7 +50,7 @@
|
||||
[super setUp];
|
||||
|
||||
eventBindingManager = [[FBSDKEventBindingManager alloc]
|
||||
initWithJSON:[FBSDKSampleEventBinding getSampleDictionary]];
|
||||
initWithJSON:[SampleRawRemoteEventBindings sampleDictionary]];
|
||||
window = [[UIWindow alloc] init];
|
||||
UIViewController *vc = [[UIViewController alloc] init];
|
||||
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:vc];
|
||||
@@ -94,7 +94,7 @@
|
||||
|
||||
- (void)testMatching
|
||||
{
|
||||
NSArray *bindings = [FBSDKEventBindingManager parseArray:[FBSDKSampleEventBinding getSampleDictionary][@"event_bindings"]];
|
||||
NSArray *bindings = [FBSDKEventBindingManager parseArray:[SampleRawRemoteEventBindings sampleDictionary][@"event_bindings"]];
|
||||
FBSDKEventBinding *binding = bindings[0];
|
||||
XCTAssertTrue([FBSDKEventBinding isViewMatchPath:stepper path:binding.path]);
|
||||
|
||||
@@ -116,7 +116,7 @@
|
||||
|
||||
- (void)testEventBindingEquation
|
||||
{
|
||||
NSArray *bindings = [FBSDKEventBindingManager parseArray:[FBSDKSampleEventBinding getSampleDictionary][@"event_bindings"]];
|
||||
NSArray *bindings = [FBSDKEventBindingManager parseArray:[SampleRawRemoteEventBindings sampleDictionary][@"event_bindings"]];
|
||||
XCTAssertTrue([bindings[0] isEqualToBinding:bindings[0]]);
|
||||
XCTAssertFalse([bindings[0] isEqualToBinding:bindings[1]]);
|
||||
}
|
||||
@@ -124,7 +124,7 @@
|
||||
- (void)testParsing
|
||||
{
|
||||
for (int i = 0; i < 100; i++) {
|
||||
NSDictionary *sampleData = [FBSDKSampleEventBinding getSampleDictionary];
|
||||
NSDictionary *sampleData = [SampleRawRemoteEventBindings sampleDictionary];
|
||||
[FBSDKEventBindingManager parseArray:@[[Fuzzer randomizeWithJson:sampleData]]];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,140 +0,0 @@
|
||||
// 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.
|
||||
|
||||
@objcMembers
|
||||
class FBSDKSampleEventBinding: NSObject {
|
||||
class func getSampleDictionary() -> [String: Any] { // swiftlint:disable:this function_body_length
|
||||
return [
|
||||
"event_bindings": [
|
||||
[
|
||||
"event_name": "Quantity Changed",
|
||||
"event_type": "click",
|
||||
"app_version": "1.2",
|
||||
"path": [
|
||||
[
|
||||
"class_name": "UIWindow"
|
||||
],
|
||||
[
|
||||
"class_name": "UITabBarController"
|
||||
],
|
||||
[
|
||||
"class_name": "UINavigationController"
|
||||
],
|
||||
[
|
||||
"class_name": "UIViewController"
|
||||
],
|
||||
[
|
||||
"class_name": "UIStackView"
|
||||
],
|
||||
[
|
||||
"class_name": "UIStackView"
|
||||
],
|
||||
[
|
||||
"class_name": "UIStepper"
|
||||
],
|
||||
],
|
||||
],
|
||||
[
|
||||
"event_name": "Add To Cart",
|
||||
"event_type": "click",
|
||||
"app_version": "1.2",
|
||||
"path": [
|
||||
[
|
||||
"class_name": "UIViewController"
|
||||
],
|
||||
[
|
||||
"class_name": "UIStackView"
|
||||
],
|
||||
[
|
||||
"class_name": "UIButton",
|
||||
"text": "Buy",
|
||||
],
|
||||
],
|
||||
"parameters": [
|
||||
[
|
||||
"parameter_name": "price",
|
||||
"path_type": "relative",
|
||||
"path": [
|
||||
[
|
||||
"class_name": ".."
|
||||
],
|
||||
[
|
||||
"class_name": "UILabel",
|
||||
"index": 2,
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"event_name": "Purchase",
|
||||
"event_type": "click",
|
||||
"app_version": "1.2",
|
||||
"path": [
|
||||
[
|
||||
"class_name": "UIWindow"
|
||||
],
|
||||
[
|
||||
"class_name": "UITabBarController"
|
||||
],
|
||||
[
|
||||
"class_name": "UINavigationController"
|
||||
],
|
||||
[
|
||||
"class_name": "UIViewController"
|
||||
],
|
||||
[
|
||||
"class_name": "UIStackView"
|
||||
],
|
||||
[
|
||||
"class_name": "UIButton",
|
||||
"text": "Confirm",
|
||||
],
|
||||
],
|
||||
"parameters": [
|
||||
[
|
||||
"parameter_name": "price",
|
||||
"path_type": "relative",
|
||||
"path": [
|
||||
[
|
||||
"class_name": ".."
|
||||
],
|
||||
[
|
||||
"class_name": "UIStackView"
|
||||
],
|
||||
[
|
||||
"class_name": "UILabel",
|
||||
"index": 0,
|
||||
],
|
||||
],
|
||||
],
|
||||
[
|
||||
"parameter_name": "action",
|
||||
"path_type": "relative",
|
||||
"path": [
|
||||
[
|
||||
"class_name": "."
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
// 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.
|
||||
|
||||
@objcMembers
|
||||
class SampleEventBinding: NSObject {
|
||||
|
||||
static func valid(withName name: String) -> EventBinding {
|
||||
// swiftlint:disable:next force_unwrapping
|
||||
return EventBinding(json: SampleRawRemoteEventBindings.rawBinding(name: name))!
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@objcMembers
|
||||
class SampleEventBindingList: NSObject {
|
||||
|
||||
static var valid: [EventBinding] {
|
||||
return SampleRawRemoteEventBindings.bindings.compactMap { EventBinding(json: $0) }
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
// 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.
|
||||
|
||||
@objcMembers
|
||||
class SampleRawRemoteEventBindings: NSObject {
|
||||
|
||||
static var sampleDictionary: [String: Any] {
|
||||
return [
|
||||
"event_bindings": bindings
|
||||
]
|
||||
}
|
||||
|
||||
static var bindings: [[String: Any]] {
|
||||
return [
|
||||
[
|
||||
"event_name": "Quantity Changed",
|
||||
"event_type": "click",
|
||||
"app_version": "1.2",
|
||||
"path": [
|
||||
[
|
||||
"class_name": "UIWindow"
|
||||
],
|
||||
[
|
||||
"class_name": "UITabBarController"
|
||||
],
|
||||
[
|
||||
"class_name": "UINavigationController"
|
||||
],
|
||||
[
|
||||
"class_name": "UIViewController"
|
||||
],
|
||||
[
|
||||
"class_name": "UIStackView"
|
||||
],
|
||||
[
|
||||
"class_name": "UIStackView"
|
||||
],
|
||||
[
|
||||
"class_name": "UIStepper"
|
||||
],
|
||||
],
|
||||
],
|
||||
[
|
||||
"event_name": "Add To Cart",
|
||||
"event_type": "click",
|
||||
"app_version": "1.2",
|
||||
"path": [
|
||||
[
|
||||
"class_name": "UIViewController"
|
||||
],
|
||||
[
|
||||
"class_name": "UIStackView"
|
||||
],
|
||||
[
|
||||
"class_name": "UIButton",
|
||||
"text": "Buy",
|
||||
],
|
||||
],
|
||||
"parameters": [
|
||||
[
|
||||
"parameter_name": "price",
|
||||
"path_type": "relative",
|
||||
"path": [
|
||||
[
|
||||
"class_name": ".."
|
||||
],
|
||||
[
|
||||
"class_name": "UILabel",
|
||||
"index": 2,
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
"event_name": "Purchase",
|
||||
"event_type": "click",
|
||||
"app_version": "1.2",
|
||||
"path": [
|
||||
[
|
||||
"class_name": "UIWindow"
|
||||
],
|
||||
[
|
||||
"class_name": "UITabBarController"
|
||||
],
|
||||
[
|
||||
"class_name": "UINavigationController"
|
||||
],
|
||||
[
|
||||
"class_name": "UIViewController"
|
||||
],
|
||||
[
|
||||
"class_name": "UIStackView"
|
||||
],
|
||||
[
|
||||
"class_name": "UIButton",
|
||||
"text": "Confirm",
|
||||
],
|
||||
],
|
||||
"parameters": [
|
||||
[
|
||||
"parameter_name": "price",
|
||||
"path_type": "relative",
|
||||
"path": [
|
||||
[
|
||||
"class_name": ".."
|
||||
],
|
||||
[
|
||||
"class_name": "UIStackView"
|
||||
],
|
||||
[
|
||||
"class_name": "UILabel",
|
||||
"index": 0,
|
||||
],
|
||||
],
|
||||
],
|
||||
[
|
||||
"parameter_name": "action",
|
||||
"path_type": "relative",
|
||||
"path": [
|
||||
[
|
||||
"class_name": "."
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
}
|
||||
|
||||
static func rawBinding(name: String) -> [String: Any] {
|
||||
return [
|
||||
"event_name": name,
|
||||
"event_type": "click",
|
||||
"app_version": "1.2",
|
||||
"path": [
|
||||
[
|
||||
"class_name": "UIWindow"
|
||||
]
|
||||
]
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
// 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.
|
||||
|
||||
struct SwizzleEvidence: Equatable {
|
||||
let selector: Selector
|
||||
let `class`: AnyClass
|
||||
let block: swizzleBlock?
|
||||
|
||||
init(
|
||||
selector: Selector,
|
||||
`class`: AnyClass,
|
||||
block: swizzleBlock? = nil
|
||||
) {
|
||||
self.selector = selector
|
||||
self.`class` = `class`
|
||||
self.block = block
|
||||
}
|
||||
|
||||
static func == (lhs: SwizzleEvidence, rhs: SwizzleEvidence) -> Bool {
|
||||
return lhs.selector == rhs.selector && lhs.class == rhs.class
|
||||
}
|
||||
}
|
||||
|
||||
class TestSwizzler: Swizzling {
|
||||
static var evidence = [SwizzleEvidence]()
|
||||
|
||||
static func swizzleSelector(
|
||||
_ aSelector: Selector,
|
||||
on aClass: AnyClass,
|
||||
with block: @escaping swizzleBlock,
|
||||
named aName: String
|
||||
) {
|
||||
evidence.append(.init(selector: aSelector, class: aClass, block: block))
|
||||
}
|
||||
|
||||
static func reset() {
|
||||
evidence = []
|
||||
}
|
||||
}
|
||||
@@ -16,8 +16,8 @@
|
||||
// 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 TestTools
|
||||
import FBSDKCoreKit
|
||||
import TestTools
|
||||
import XCTest
|
||||
|
||||
class ProfilePictureViewTests: XCTestCase {
|
||||
|
||||
@@ -153,7 +153,6 @@
|
||||
C6E1332C259173B000B611C6 /* FBSDKPermission.h in Headers */ = {isa = PBXBuildFile; fileRef = C6E1332B259173AF00B611C6 /* FBSDKPermission.h */; };
|
||||
C6E1333F259174A500B611C6 /* FBSDKPermission.m in Sources */ = {isa = PBXBuildFile; fileRef = C6E1333E259174A500B611C6 /* FBSDKPermission.m */; };
|
||||
C6E63D2D24F822620015FC7C /* FBSDKReferralManagerLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = C6E63D2C24F822620015FC7C /* FBSDKReferralManagerLogger.m */; };
|
||||
F401866525F45BD100C57ADE /* TestTools.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F401866425F45BD100C57ADE /* TestTools.framework */; };
|
||||
F40BFD56257852E5007B85AC /* LoginButtonTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F40BFD55257852E5007B85AC /* LoginButtonTests.swift */; };
|
||||
F462DC0E23B958E000FFCECA /* FBSDKLoginKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 9D9DB8DE1A114E500086167B /* FBSDKLoginKit.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
F462DC0F23B958E100FFCECA /* FBSDKLoginKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 9D9DB8DE1A114E500086167B /* FBSDKLoginKit.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
@@ -309,6 +308,20 @@
|
||||
remoteGlobalIDString = 818EB4211D1A283100252851;
|
||||
remoteInfo = "FBSDKLoginKit-Dynamic";
|
||||
};
|
||||
F468741F25F7D39A00ABD912 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = F468741B25F7D39A00ABD912 /* TestTools.xcodeproj */;
|
||||
proxyType = 2;
|
||||
remoteGlobalIDString = F4E5F09025F4354900D67852;
|
||||
remoteInfo = TestTools;
|
||||
};
|
||||
F468742825F7D3AF00ABD912 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = F468741B25F7D39A00ABD912 /* TestTools.xcodeproj */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = F4E5F08F25F4354900D67852;
|
||||
remoteInfo = TestTools;
|
||||
};
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
@@ -410,7 +423,6 @@
|
||||
C6E63D2224F8219A0015FC7C /* FBSDKReferralManagerLogger.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FBSDKReferralManagerLogger.h; sourceTree = "<group>"; };
|
||||
C6E63D2C24F822620015FC7C /* FBSDKReferralManagerLogger.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBSDKReferralManagerLogger.m; sourceTree = "<group>"; };
|
||||
F401864D25F45B8100C57ADE /* TestTools.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = TestTools.xcodeproj; path = ../../../TestTools/TestTools.xcodeproj; sourceTree = "<group>"; };
|
||||
F401866425F45BD100C57ADE /* TestTools.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = TestTools.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
F40BFD55257852E5007B85AC /* LoginButtonTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginButtonTests.swift; sourceTree = "<group>"; };
|
||||
F4647451256AD09000502449 /* FBSDKLoginKitTests-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "FBSDKLoginKitTests-Bridging-Header.h"; sourceTree = "<group>"; };
|
||||
F4647478256AEF8E00502449 /* NonceTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NonceTests.swift; sourceTree = "<group>"; };
|
||||
@@ -419,6 +431,7 @@
|
||||
F464749B256B048500502449 /* LoginConfigurationTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LoginConfigurationTests.swift; sourceTree = "<group>"; };
|
||||
F4665CC0258D684300981FDE /* Fuzzer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Fuzzer.swift; sourceTree = "<group>"; };
|
||||
F4665CD2258D687500981FDE /* FakeGraphRequestConnectionProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FakeGraphRequestConnectionProvider.swift; sourceTree = "<group>"; };
|
||||
F468741B25F7D39A00ABD912 /* TestTools.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = TestTools.xcodeproj; path = ../TestTools/TestTools.xcodeproj; sourceTree = "<group>"; };
|
||||
F46FA659245347570060C902 /* FBLoginButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FBLoginButton.swift; sourceTree = "<group>"; };
|
||||
F46FA65C245347820060C902 /* LoginManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LoginManager.swift; sourceTree = "<group>"; };
|
||||
F47FB44E25805E7900922543 /* FBSDKLoginManagerLoggerTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBSDKLoginManagerLoggerTests.m; sourceTree = "<group>"; };
|
||||
@@ -467,7 +480,6 @@
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
F401866525F45BD100C57ADE /* TestTools.framework in Frameworks */,
|
||||
6B4453551A8AF2B9004C4437 /* Accounts.framework in Frameworks */,
|
||||
9DCDEC9E1A82ECA1002A2A66 /* libOCMock.a in Frameworks */,
|
||||
9DEE5C941A671B5500D750E1 /* XCTest.framework in Frameworks */,
|
||||
@@ -566,7 +578,7 @@
|
||||
893774AF1A3B815D00BE2807 /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
F401866425F45BD100C57ADE /* TestTools.framework */,
|
||||
F468741B25F7D39A00ABD912 /* TestTools.xcodeproj */,
|
||||
0BD1F3512093A1A3005109EC /* UIKit.framework */,
|
||||
0BD1F34C2093A1A0005109EC /* CoreGraphics.framework */,
|
||||
8118B6781D0A5B9400962084 /* FBSDKCoreKit.xcodeproj */,
|
||||
@@ -729,6 +741,14 @@
|
||||
path = Helpers;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
F468741C25F7D39A00ABD912 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
F468742025F7D39A00ABD912 /* TestTools.framework */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
F46FA66E24535E3F0060C902 /* Swift */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -932,7 +952,7 @@
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
F45045AE25F425FF0032CC7E /* PBXTargetDependency */,
|
||||
F468742925F7D3AF00ABD912 /* PBXTargetDependency */,
|
||||
F410D0552370CD0F005B9318 /* PBXTargetDependency */,
|
||||
F410D0532370CD0B005B9318 /* PBXTargetDependency */,
|
||||
);
|
||||
@@ -985,6 +1005,10 @@
|
||||
ProductGroup = 8118B6791D0A5B9400962084 /* Products */;
|
||||
ProjectRef = 8118B6781D0A5B9400962084 /* FBSDKCoreKit.xcodeproj */;
|
||||
},
|
||||
{
|
||||
ProductGroup = F468741C25F7D39A00ABD912 /* Products */;
|
||||
ProjectRef = F468741B25F7D39A00ABD912 /* TestTools.xcodeproj */;
|
||||
},
|
||||
);
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
@@ -1063,6 +1087,13 @@
|
||||
remoteRef = 817490FE1D1C6C11006E09DF /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
F468742025F7D39A00ABD912 /* TestTools.framework */ = {
|
||||
isa = PBXReferenceProxy;
|
||||
fileType = wrapper.framework;
|
||||
path = TestTools.framework;
|
||||
remoteRef = F468741F25F7D39A00ABD912 /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
/* End PBXReferenceProxy section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
@@ -1299,9 +1330,10 @@
|
||||
target = 818EB4211D1A283100252851 /* FBSDKLoginKit-Dynamic */;
|
||||
targetProxy = F410D0542370CD0F005B9318 /* PBXContainerItemProxy */;
|
||||
};
|
||||
F45045AE25F425FF0032CC7E /* PBXTargetDependency */ = {
|
||||
F468742925F7D3AF00ABD912 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
productRef = F45045AD25F425FF0032CC7E /* TestTools */;
|
||||
name = TestTools;
|
||||
targetProxy = F468742825F7D3AF00ABD912 /* PBXContainerItemProxy */;
|
||||
};
|
||||
/* End PBXTargetDependency section */
|
||||
|
||||
@@ -1521,13 +1553,6 @@
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
|
||||
/* Begin XCSwiftPackageProductDependency section */
|
||||
F45045AD25F425FF0032CC7E /* TestTools */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
productName = TestTools;
|
||||
};
|
||||
/* End XCSwiftPackageProductDependency section */
|
||||
};
|
||||
rootObject = 9D9DB8D01A114E500086167B /* Project object */;
|
||||
}
|
||||
|
||||
@@ -434,6 +434,7 @@
|
||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
DYLIB_CURRENT_VERSION = 1;
|
||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
INFOPLIST_FILE = "$(SRCROOT)/TestTools/Info.plist";
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
@@ -457,6 +458,7 @@
|
||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
DYLIB_CURRENT_VERSION = 1;
|
||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
INFOPLIST_FILE = "$(SRCROOT)/TestTools/Info.plist";
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
|
||||
26
TestTools/TestTools/Info.plist
Normal file
26
TestTools/TestTools/Info.plist
Normal file
@@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>$(CURRENT_PROJECT_VERSION)</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string></string>
|
||||
</dict>
|
||||
</plist>
|
||||
Reference in New Issue
Block a user