[ReactNative] Move unit tests to UIExplorer
This commit is contained in:
parent
40579181d3
commit
c2b0e72771
|
@ -17,11 +17,31 @@
|
|||
13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB11A68108700A75B9A /* LaunchScreen.xib */; };
|
||||
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
|
||||
13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
|
||||
143BC5881B21E18100462512 /* ClippingTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 143BC57D1B21E18100462512 /* ClippingTests.m */; };
|
||||
143BC5891B21E18100462512 /* Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 143BC57E1B21E18100462512 /* Info.plist */; };
|
||||
143BC5A11B21E45C00462512 /* UIExplorerIntegrationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 143BC5A01B21E45C00462512 /* UIExplorerIntegrationTests.m */; };
|
||||
144D21241B2204C5006DB32B /* RCTClippingTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 144D21231B2204C5006DB32B /* RCTClippingTests.m */; };
|
||||
147CED4C1AB3532B00DA3E4C /* libRCTActionSheet.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 147CED4B1AB34F8C00DA3E4C /* libRCTActionSheet.a */; };
|
||||
1497CFAC1B21F5E400C1F8F2 /* RCTAllocationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 1497CFA41B21F5E400C1F8F2 /* RCTAllocationTests.m */; };
|
||||
1497CFAD1B21F5E400C1F8F2 /* RCTBridgeTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 1497CFA51B21F5E400C1F8F2 /* RCTBridgeTests.m */; };
|
||||
1497CFAE1B21F5E400C1F8F2 /* RCTContextExecutorTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 1497CFA61B21F5E400C1F8F2 /* RCTContextExecutorTests.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
|
||||
1497CFAF1B21F5E400C1F8F2 /* RCTConvert_NSURLTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 1497CFA71B21F5E400C1F8F2 /* RCTConvert_NSURLTests.m */; };
|
||||
1497CFB01B21F5E400C1F8F2 /* RCTConvert_UIFontTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 1497CFA81B21F5E400C1F8F2 /* RCTConvert_UIFontTests.m */; };
|
||||
1497CFB11B21F5E400C1F8F2 /* RCTEventDispatcherTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 1497CFA91B21F5E400C1F8F2 /* RCTEventDispatcherTests.m */; };
|
||||
1497CFB21B21F5E400C1F8F2 /* RCTSparseArrayTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 1497CFAA1B21F5E400C1F8F2 /* RCTSparseArrayTests.m */; };
|
||||
1497CFB31B21F5E400C1F8F2 /* RCTUIManagerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 1497CFAB1B21F5E400C1F8F2 /* RCTUIManagerTests.m */; };
|
||||
14AADF051AC3DBB1002390C9 /* libReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 14AADF041AC3DB95002390C9 /* libReact.a */; };
|
||||
14D6D7111B220EB3001FB087 /* libOCMock.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 14D6D7101B220EB3001FB087 /* libOCMock.a */; };
|
||||
14D6D71E1B2222EF001FB087 /* libRCTActionSheet.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 147CED4B1AB34F8C00DA3E4C /* libRCTActionSheet.a */; };
|
||||
14D6D71F1B2222EF001FB087 /* libRCTAdSupport.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1344545A1AAFCAAE003F0779 /* libRCTAdSupport.a */; };
|
||||
14D6D7201B2222EF001FB087 /* libRCTGeolocation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 134A8A251AACED6A00945AAE /* libRCTGeolocation.a */; };
|
||||
14D6D7211B2222EF001FB087 /* libRCTImage.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 13417FE81AA91428003F314A /* libRCTImage.a */; };
|
||||
14D6D7221B2222EF001FB087 /* libRCTNetwork.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1341802B1AA91779003F314A /* libRCTNetwork.a */; };
|
||||
14D6D7231B2222EF001FB087 /* libRCTPushNotification.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 14DC67F11AB71876001358AB /* libRCTPushNotification.a */; };
|
||||
14D6D7241B2222EF001FB087 /* libRCTSettings.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 834C36D21AF8DA610019C93C /* libRCTSettings.a */; };
|
||||
14D6D7251B2222EF001FB087 /* libRCTTest.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 58005BEE1ABA80530062E044 /* libRCTTest.a */; };
|
||||
14D6D7261B2222EF001FB087 /* libRCTText.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 13417FEF1AA914B8003F314A /* libRCTText.a */; };
|
||||
14D6D7271B2222EF001FB087 /* libRCTVibration.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D85B829C1AB6D5CE003F4FE2 /* libRCTVibration.a */; };
|
||||
14D6D7281B2222EF001FB087 /* libRCTWebSocket.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 139FDED91B0651EA00C62182 /* libRCTWebSocket.a */; };
|
||||
14D6D7291B2222EF001FB087 /* libReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 14AADF041AC3DB95002390C9 /* libReact.a */; };
|
||||
14DC67F41AB71881001358AB /* libRCTPushNotification.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 14DC67F11AB71876001358AB /* libRCTPushNotification.a */; };
|
||||
58005BF21ABA80A60062E044 /* libRCTTest.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 58005BEE1ABA80530062E044 /* libRCTTest.a */; };
|
||||
834C36EC1AF8DED70019C93C /* libRCTSettings.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 834C36D21AF8DA610019C93C /* libRCTSettings.a */; };
|
||||
|
@ -29,13 +49,6 @@
|
|||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
004D28A41AAF61C70097A701 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 83CBB9F71A601CBA00E9B192 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = 13B07F861A680F5B00A75B9A;
|
||||
remoteInfo = UIExplorer;
|
||||
};
|
||||
13417FE71AA91428003F314A /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 13417FE31AA91428003F314A /* RCTImage.xcodeproj */;
|
||||
|
@ -145,7 +158,6 @@
|
|||
13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = UIExplorer/Info.plist; sourceTree = "<group>"; };
|
||||
13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = UIExplorer/main.m; sourceTree = "<group>"; };
|
||||
13CC9D481AEED2B90020D1C2 /* RCTSettings.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTSettings.xcodeproj; path = ../../Libraries/Settings/RCTSettings.xcodeproj; sourceTree = "<group>"; };
|
||||
143BC57D1B21E18100462512 /* ClippingTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ClippingTests.m; sourceTree = "<group>"; };
|
||||
143BC57E1B21E18100462512 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
143BC5811B21E18100462512 /* testLayoutExampleSnapshot_1@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "testLayoutExampleSnapshot_1@2x.png"; sourceTree = "<group>"; };
|
||||
143BC5821B21E18100462512 /* testSliderExampleSnapshot_1@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "testSliderExampleSnapshot_1@2x.png"; sourceTree = "<group>"; };
|
||||
|
@ -156,7 +168,26 @@
|
|||
143BC5951B21E3E100462512 /* UIExplorerIntegrationTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = UIExplorerIntegrationTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
143BC5981B21E3E100462512 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
143BC5A01B21E45C00462512 /* UIExplorerIntegrationTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UIExplorerIntegrationTests.m; sourceTree = "<group>"; };
|
||||
144D21231B2204C5006DB32B /* RCTClippingTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTClippingTests.m; sourceTree = "<group>"; };
|
||||
1497CFA41B21F5E400C1F8F2 /* RCTAllocationTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTAllocationTests.m; sourceTree = "<group>"; };
|
||||
1497CFA51B21F5E400C1F8F2 /* RCTBridgeTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTBridgeTests.m; sourceTree = "<group>"; };
|
||||
1497CFA61B21F5E400C1F8F2 /* RCTContextExecutorTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTContextExecutorTests.m; sourceTree = "<group>"; };
|
||||
1497CFA71B21F5E400C1F8F2 /* RCTConvert_NSURLTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTConvert_NSURLTests.m; sourceTree = "<group>"; };
|
||||
1497CFA81B21F5E400C1F8F2 /* RCTConvert_UIFontTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTConvert_UIFontTests.m; sourceTree = "<group>"; };
|
||||
1497CFA91B21F5E400C1F8F2 /* RCTEventDispatcherTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTEventDispatcherTests.m; sourceTree = "<group>"; };
|
||||
1497CFAA1B21F5E400C1F8F2 /* RCTSparseArrayTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTSparseArrayTests.m; sourceTree = "<group>"; };
|
||||
1497CFAB1B21F5E400C1F8F2 /* RCTUIManagerTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTUIManagerTests.m; sourceTree = "<group>"; };
|
||||
14AADEFF1AC3DB95002390C9 /* React.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = React.xcodeproj; path = ../../React/React.xcodeproj; sourceTree = "<group>"; };
|
||||
14D6D7021B220AE3001FB087 /* NSNotificationCenter+OCMAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSNotificationCenter+OCMAdditions.h"; sourceTree = "<group>"; };
|
||||
14D6D7031B220AE3001FB087 /* OCMArg.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OCMArg.h; sourceTree = "<group>"; };
|
||||
14D6D7041B220AE3001FB087 /* OCMConstraint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OCMConstraint.h; sourceTree = "<group>"; };
|
||||
14D6D7051B220AE3001FB087 /* OCMLocation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OCMLocation.h; sourceTree = "<group>"; };
|
||||
14D6D7061B220AE3001FB087 /* OCMMacroState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OCMMacroState.h; sourceTree = "<group>"; };
|
||||
14D6D7071B220AE3001FB087 /* OCMock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OCMock.h; sourceTree = "<group>"; };
|
||||
14D6D7081B220AE3001FB087 /* OCMockObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OCMockObject.h; sourceTree = "<group>"; };
|
||||
14D6D7091B220AE3001FB087 /* OCMRecorder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OCMRecorder.h; sourceTree = "<group>"; };
|
||||
14D6D70A1B220AE3001FB087 /* OCMStubRecorder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OCMStubRecorder.h; sourceTree = "<group>"; };
|
||||
14D6D7101B220EB3001FB087 /* libOCMock.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libOCMock.a; sourceTree = "<group>"; };
|
||||
14DC67E71AB71876001358AB /* RCTPushNotification.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTPushNotification.xcodeproj; path = ../../Libraries/PushNotificationIOS/RCTPushNotification.xcodeproj; sourceTree = "<group>"; };
|
||||
14E0EEC81AB118F7000DECC3 /* RCTActionSheet.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTActionSheet.xcodeproj; path = ../../Libraries/ActionSheetIOS/RCTActionSheet.xcodeproj; sourceTree = "<group>"; };
|
||||
58005BE41ABA80530062E044 /* RCTTest.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTTest.xcodeproj; path = ../../Libraries/RCTTest/RCTTest.xcodeproj; sourceTree = "<group>"; };
|
||||
|
@ -168,6 +199,19 @@
|
|||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
14D6D71E1B2222EF001FB087 /* libRCTActionSheet.a in Frameworks */,
|
||||
14D6D71F1B2222EF001FB087 /* libRCTAdSupport.a in Frameworks */,
|
||||
14D6D7201B2222EF001FB087 /* libRCTGeolocation.a in Frameworks */,
|
||||
14D6D7211B2222EF001FB087 /* libRCTImage.a in Frameworks */,
|
||||
14D6D7221B2222EF001FB087 /* libRCTNetwork.a in Frameworks */,
|
||||
14D6D7231B2222EF001FB087 /* libRCTPushNotification.a in Frameworks */,
|
||||
14D6D7241B2222EF001FB087 /* libRCTSettings.a in Frameworks */,
|
||||
14D6D7251B2222EF001FB087 /* libRCTTest.a in Frameworks */,
|
||||
14D6D7261B2222EF001FB087 /* libRCTText.a in Frameworks */,
|
||||
14D6D7271B2222EF001FB087 /* libRCTVibration.a in Frameworks */,
|
||||
14D6D7281B2222EF001FB087 /* libRCTWebSocket.a in Frameworks */,
|
||||
14D6D7291B2222EF001FB087 /* libReact.a in Frameworks */,
|
||||
14D6D7111B220EB3001FB087 /* libOCMock.a in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -283,8 +327,18 @@
|
|||
143BC57C1B21E18100462512 /* UIExplorerUnitTests */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
143BC57D1B21E18100462512 /* ClippingTests.m */,
|
||||
1497CFA41B21F5E400C1F8F2 /* RCTAllocationTests.m */,
|
||||
1497CFA51B21F5E400C1F8F2 /* RCTBridgeTests.m */,
|
||||
144D21231B2204C5006DB32B /* RCTClippingTests.m */,
|
||||
1497CFA61B21F5E400C1F8F2 /* RCTContextExecutorTests.m */,
|
||||
1497CFA71B21F5E400C1F8F2 /* RCTConvert_NSURLTests.m */,
|
||||
1497CFA81B21F5E400C1F8F2 /* RCTConvert_UIFontTests.m */,
|
||||
1497CFA91B21F5E400C1F8F2 /* RCTEventDispatcherTests.m */,
|
||||
1497CFAA1B21F5E400C1F8F2 /* RCTSparseArrayTests.m */,
|
||||
1497CFAB1B21F5E400C1F8F2 /* RCTUIManagerTests.m */,
|
||||
143BC57E1B21E18100462512 /* Info.plist */,
|
||||
14D6D7101B220EB3001FB087 /* libOCMock.a */,
|
||||
14D6D7011B220AE3001FB087 /* OCMock */,
|
||||
143BC57F1B21E18100462512 /* ReferenceImages */,
|
||||
);
|
||||
path = UIExplorerUnitTests;
|
||||
|
@ -344,6 +398,29 @@
|
|||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
14D6D6EA1B2205C0001FB087 /* OCMock */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
);
|
||||
path = OCMock;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
14D6D7011B220AE3001FB087 /* OCMock */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
14D6D7021B220AE3001FB087 /* NSNotificationCenter+OCMAdditions.h */,
|
||||
14D6D7031B220AE3001FB087 /* OCMArg.h */,
|
||||
14D6D7041B220AE3001FB087 /* OCMConstraint.h */,
|
||||
14D6D7051B220AE3001FB087 /* OCMLocation.h */,
|
||||
14D6D7061B220AE3001FB087 /* OCMMacroState.h */,
|
||||
14D6D7071B220AE3001FB087 /* OCMock.h */,
|
||||
14D6D7081B220AE3001FB087 /* OCMockObject.h */,
|
||||
14D6D7091B220AE3001FB087 /* OCMRecorder.h */,
|
||||
14D6D70A1B220AE3001FB087 /* OCMStubRecorder.h */,
|
||||
);
|
||||
path = OCMock;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
14DC67E81AB71876001358AB /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
@ -375,6 +452,7 @@
|
|||
1316A21D1AA397F400C0188E /* Libraries */,
|
||||
143BC57C1B21E18100462512 /* UIExplorerUnitTests */,
|
||||
143BC5961B21E3E100462512 /* UIExplorerIntegrationTests */,
|
||||
14D6D6EA1B2205C0001FB087 /* OCMock */,
|
||||
83CBBA001A601CBA00E9B192 /* Products */,
|
||||
);
|
||||
indentWidth = 2;
|
||||
|
@ -413,7 +491,6 @@
|
|||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
004D28A51AAF61C70097A701 /* PBXTargetDependency */,
|
||||
);
|
||||
name = UIExplorerUnitTests;
|
||||
productName = UIExplorerTests;
|
||||
|
@ -466,7 +543,6 @@
|
|||
TargetAttributes = {
|
||||
004D289D1AAF61C70097A701 = {
|
||||
CreatedOnToolsVersion = 6.1.1;
|
||||
TestTargetID = 13B07F861A680F5B00A75B9A;
|
||||
};
|
||||
143BC5941B21E3E100462512 = {
|
||||
CreatedOnToolsVersion = 6.3.2;
|
||||
|
@ -636,7 +712,6 @@
|
|||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
143BC5891B21E18100462512 /* Info.plist in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -663,7 +738,15 @@
|
|||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
143BC5881B21E18100462512 /* ClippingTests.m in Sources */,
|
||||
1497CFB01B21F5E400C1F8F2 /* RCTConvert_UIFontTests.m in Sources */,
|
||||
144D21241B2204C5006DB32B /* RCTClippingTests.m in Sources */,
|
||||
1497CFB21B21F5E400C1F8F2 /* RCTSparseArrayTests.m in Sources */,
|
||||
1497CFAF1B21F5E400C1F8F2 /* RCTConvert_NSURLTests.m in Sources */,
|
||||
1497CFAE1B21F5E400C1F8F2 /* RCTContextExecutorTests.m in Sources */,
|
||||
1497CFAD1B21F5E400C1F8F2 /* RCTBridgeTests.m in Sources */,
|
||||
1497CFB11B21F5E400C1F8F2 /* RCTEventDispatcherTests.m in Sources */,
|
||||
1497CFB31B21F5E400C1F8F2 /* RCTUIManagerTests.m in Sources */,
|
||||
1497CFAC1B21F5E400C1F8F2 /* RCTAllocationTests.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -687,11 +770,6 @@
|
|||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXTargetDependency section */
|
||||
004D28A51AAF61C70097A701 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = 13B07F861A680F5B00A75B9A /* UIExplorer */;
|
||||
targetProxy = 004D28A41AAF61C70097A701 /* PBXContainerItemProxy */;
|
||||
};
|
||||
143BC59C1B21E3E100462512 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = 13B07F861A680F5B00A75B9A /* UIExplorer */;
|
||||
|
@ -715,7 +793,6 @@
|
|||
004D28A61AAF61C70097A701 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(SDKROOT)/Developer/Library/Frameworks",
|
||||
"$(inherited)",
|
||||
|
@ -723,35 +800,52 @@
|
|||
GCC_PREPROCESSOR_DEFINITIONS = "$(inherited)";
|
||||
HEADER_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
|
||||
"$(SRCROOT)/../../React/**",
|
||||
"$(SRCROOT)/UIExplorerUnitTests/**",
|
||||
);
|
||||
INFOPLIST_FILE = UIExplorerUnitTests/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.3;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
LIBRARY_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/UIExplorerUnitTests",
|
||||
);
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
"-framework",
|
||||
XCTest,
|
||||
"-ObjC",
|
||||
);
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/UIExplorer.app/UIExplorer";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
004D28A71AAF61C70097A701 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(SDKROOT)/Developer/Library/Frameworks",
|
||||
"$(inherited)",
|
||||
);
|
||||
HEADER_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
|
||||
"$(SRCROOT)/../../React/**",
|
||||
"$(SRCROOT)/UIExplorerUnitTests/**",
|
||||
);
|
||||
INFOPLIST_FILE = UIExplorerUnitTests/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.3;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
LIBRARY_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/UIExplorerUnitTests",
|
||||
);
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
"-framework",
|
||||
XCTest,
|
||||
"-ObjC",
|
||||
);
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/UIExplorer.app/UIExplorer";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
|
@ -947,6 +1041,7 @@
|
|||
143BC59F1B21E3E100462512 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "UIExplorer" */ = {
|
||||
isa = XCConfigurationList;
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import <XCTest/XCTest.h>
|
||||
|
||||
#import <OCMock/OCMock.h>
|
||||
|
||||
@interface LayoutSubviewsOrderingTest : XCTestCase
|
||||
|
||||
@end
|
||||
|
||||
@implementation LayoutSubviewsOrderingTest
|
||||
|
||||
/**
|
||||
* This test exists to insure that didLayoutSubviews is always called immediately after layoutSubviews for a VC:View
|
||||
* pair. In Catalyst we have multiple levels of ViewController containment, and we rely on this ordering
|
||||
* to insure that layoutGuides are set on RKViewControllers before Views further down in the heirarchy have
|
||||
* their layoutSubviews called (and need to use the aforementioned layoutGuides)
|
||||
*/
|
||||
- (void)testLayoutSubviewsOrdering
|
||||
{
|
||||
// create some Views and ViewControllers
|
||||
UIViewController *parentVC = [[UIViewController alloc] init];
|
||||
UIView *parentView = [[UIView alloc] init];
|
||||
UIViewController *childVC = [[UIViewController alloc] init];
|
||||
UIView *childView = [[UIView alloc] init];
|
||||
|
||||
// The ordering we expect is:
|
||||
// parentView::layoutSubviews
|
||||
// parentVC::didLayoutSubviews
|
||||
// childView::layoutSubviews
|
||||
// childVC::didLayoutSubviews
|
||||
|
||||
id parentViewMock = [OCMockObject partialMockForObject:parentView];
|
||||
id parentVCMock = [OCMockObject partialMockForObject:parentVC];
|
||||
id childViewMock = [OCMockObject partialMockForObject:childView];
|
||||
id childVCMock = [OCMockObject partialMockForObject:childVC];
|
||||
|
||||
__block int layoutOrderCount = 0;
|
||||
[[[parentViewMock stub] andDo:^(NSInvocation *inv) {
|
||||
if (layoutOrderCount < 4) {
|
||||
layoutOrderCount++;
|
||||
XCTAssertEqual(layoutOrderCount, 1, @"Expect parentView::layoutSubviews to be called first");
|
||||
}
|
||||
}] layoutSubviews];
|
||||
[[[parentVCMock stub] andDo:^(NSInvocation *inv) {
|
||||
if (layoutOrderCount < 4) {
|
||||
layoutOrderCount++;
|
||||
XCTAssertEqual(layoutOrderCount, 2, @"Expect parentVC::viewDidLayoutSubviews to be called 2nd");
|
||||
}
|
||||
}] viewDidLayoutSubviews];
|
||||
[[[childViewMock stub] andDo:^(NSInvocation *inv) {
|
||||
if (layoutOrderCount < 4) {
|
||||
layoutOrderCount++;
|
||||
XCTAssertEqual(layoutOrderCount, 3, @"Expect childView::layoutSubviews to be called 3rd");
|
||||
}
|
||||
}] layoutSubviews];
|
||||
[[[childVCMock stub] andDo:^(NSInvocation *inv) {
|
||||
if (layoutOrderCount < 4) {
|
||||
layoutOrderCount++;
|
||||
XCTAssertEqual(layoutOrderCount, 4, @"Expect childVC::viewDidLayoutSubviews to be called last");
|
||||
[childVCMock stopMocking];
|
||||
}
|
||||
}] viewDidLayoutSubviews];
|
||||
|
||||
// setup View heirarchy and force layout
|
||||
parentVC.view = parentView;
|
||||
childVC.view = childView;
|
||||
[parentVC addChildViewController:childVC];
|
||||
[childVC didMoveToParentViewController:parentVC];
|
||||
[parentView addSubview:childView];
|
||||
|
||||
[childViewMock setNeedsLayout];
|
||||
[parentViewMock layoutIfNeeded];
|
||||
|
||||
XCTAssertEqual(layoutOrderCount, 4, @"Expect layoutSubviews/viewDidLayoutSubviews to be called");
|
||||
}
|
||||
|
||||
@end
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* Copyright (c) 2009-2014 Erik Doernenburg and contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use these files except in compliance with the License. You may obtain
|
||||
* a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@class OCObserverMockObject;
|
||||
|
||||
|
||||
@interface NSNotificationCenter(OCMAdditions)
|
||||
|
||||
- (void)addMockObserver:(OCObserverMockObject *)notificationObserver name:(NSString *)notificationName object:(id)notificationSender;
|
||||
|
||||
@end
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* Copyright (c) 2009-2014 Erik Doernenburg and contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use these files except in compliance with the License. You may obtain
|
||||
* a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@interface OCMArg : NSObject
|
||||
|
||||
// constraining arguments
|
||||
|
||||
+ (id)any;
|
||||
+ (SEL)anySelector;
|
||||
+ (void *)anyPointer;
|
||||
+ (id __autoreleasing *)anyObjectRef;
|
||||
+ (id)isNil;
|
||||
+ (id)isNotNil;
|
||||
+ (id)isEqual:(id)value;
|
||||
+ (id)isNotEqual:(id)value;
|
||||
+ (id)isKindOfClass:(Class)cls;
|
||||
+ (id)checkWithSelector:(SEL)selector onObject:(id)anObject;
|
||||
+ (id)checkWithBlock:(BOOL (^)(id obj))block;
|
||||
|
||||
// manipulating arguments
|
||||
|
||||
+ (id *)setTo:(id)value;
|
||||
+ (void *)setToValue:(NSValue *)value;
|
||||
|
||||
// internal use only
|
||||
|
||||
+ (id)resolveSpecialValues:(NSValue *)value;
|
||||
|
||||
@end
|
||||
|
||||
#define OCMOCK_ANY [OCMArg any]
|
||||
|
||||
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
|
||||
#define OCMOCK_VALUE(variable) \
|
||||
({ __typeof__(variable) __v = (variable); [NSValue value:&__v withObjCType:@encode(__typeof__(__v))]; })
|
||||
#else
|
||||
#define OCMOCK_VALUE(variable) [NSValue value:&variable withObjCType:@encode(__typeof__(variable))]
|
||||
#endif
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* Copyright (c) 2007-2014 Erik Doernenburg and contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use these files except in compliance with the License. You may obtain
|
||||
* a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
|
||||
@interface OCMConstraint : NSObject
|
||||
|
||||
+ (instancetype)constraint;
|
||||
- (BOOL)evaluate:(id)value;
|
||||
|
||||
// if you are looking for any, isNil, etc, they have moved to OCMArg
|
||||
|
||||
// try to use [OCMArg checkWith...] instead of the constraintWith... methods below
|
||||
|
||||
+ (instancetype)constraintWithSelector:(SEL)aSelector onObject:(id)anObject;
|
||||
+ (instancetype)constraintWithSelector:(SEL)aSelector onObject:(id)anObject withValue:(id)aValue;
|
||||
|
||||
|
||||
@end
|
||||
|
||||
@interface OCMAnyConstraint : OCMConstraint
|
||||
@end
|
||||
|
||||
@interface OCMIsNilConstraint : OCMConstraint
|
||||
@end
|
||||
|
||||
@interface OCMIsNotNilConstraint : OCMConstraint
|
||||
@end
|
||||
|
||||
@interface OCMIsNotEqualConstraint : OCMConstraint
|
||||
{
|
||||
@public
|
||||
id testValue;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@interface OCMInvocationConstraint : OCMConstraint
|
||||
{
|
||||
@public
|
||||
NSInvocation *invocation;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@interface OCMBlockConstraint : OCMConstraint
|
||||
{
|
||||
BOOL (^block)(id);
|
||||
}
|
||||
|
||||
- (instancetype)initWithConstraintBlock:(BOOL (^)(id))block;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
#define CONSTRAINT(aSelector) [OCMConstraint constraintWithSelector:aSelector onObject:self]
|
||||
#define CONSTRAINTV(aSelector, aValue) [OCMConstraint constraintWithSelector:aSelector onObject:self withValue:(aValue)]
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Copyright (c) 2014 Erik Doernenburg and contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use these files except in compliance with the License. You may obtain
|
||||
* a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@interface OCMLocation : NSObject
|
||||
{
|
||||
id testCase;
|
||||
NSString *file;
|
||||
NSUInteger line;
|
||||
}
|
||||
|
||||
+ (instancetype)locationWithTestCase:(id)aTestCase file:(NSString *)aFile line:(NSUInteger)aLine;
|
||||
|
||||
- (instancetype)initWithTestCase:(id)aTestCase file:(NSString *)aFile line:(NSUInteger)aLine;
|
||||
|
||||
- (id)testCase;
|
||||
- (NSString *)file;
|
||||
- (NSUInteger)line;
|
||||
|
||||
@end
|
||||
|
||||
extern OCMLocation *OCMMakeLocation(id testCase, const char *file, int line);
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Copyright (c) 2014 Erik Doernenburg and contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use these files except in compliance with the License. You may obtain
|
||||
* a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@class OCMLocation;
|
||||
@class OCMRecorder;
|
||||
@class OCMStubRecorder;
|
||||
@class OCMockObject;
|
||||
|
||||
|
||||
@interface OCMMacroState : NSObject
|
||||
{
|
||||
OCMRecorder *recorder;
|
||||
}
|
||||
|
||||
+ (void)beginStubMacro;
|
||||
+ (OCMStubRecorder *)endStubMacro;
|
||||
|
||||
+ (void)beginExpectMacro;
|
||||
+ (OCMStubRecorder *)endExpectMacro;
|
||||
|
||||
+ (void)beginVerifyMacroAtLocation:(OCMLocation *)aLocation;
|
||||
+ (void)endVerifyMacro;
|
||||
|
||||
+ (OCMMacroState *)globalState;
|
||||
|
||||
- (OCMRecorder *)recorder;
|
||||
|
||||
- (void)switchToClassMethod;
|
||||
|
||||
@end
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Copyright (c) 2014 Erik Doernenburg and contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use these files except in compliance with the License. You may obtain
|
||||
* a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@class OCMockObject;
|
||||
@class OCMInvocationMatcher;
|
||||
|
||||
|
||||
@interface OCMRecorder : NSProxy
|
||||
{
|
||||
OCMockObject *mockObject;
|
||||
OCMInvocationMatcher *invocationMatcher;
|
||||
}
|
||||
|
||||
- (instancetype)init;
|
||||
- (instancetype)initWithMockObject:(OCMockObject *)aMockObject;
|
||||
|
||||
- (void)setMockObject:(OCMockObject *)aMockObject;
|
||||
|
||||
- (OCMInvocationMatcher *)invocationMatcher;
|
||||
|
||||
- (id)classMethod;
|
||||
- (id)ignoringNonObjectArgs;
|
||||
|
||||
@end
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* Copyright (c) 2004-2014 Erik Doernenburg and contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use these files except in compliance with the License. You may obtain
|
||||
* a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#import "OCMRecorder.h"
|
||||
|
||||
|
||||
@interface OCMStubRecorder : OCMRecorder
|
||||
|
||||
- (id)andReturn:(id)anObject;
|
||||
- (id)andReturnValue:(NSValue *)aValue;
|
||||
- (id)andThrow:(NSException *)anException;
|
||||
- (id)andPost:(NSNotification *)aNotification;
|
||||
- (id)andCall:(SEL)selector onObject:(id)anObject;
|
||||
- (id)andDo:(void (^)(NSInvocation *invocation))block;
|
||||
- (id)andForwardToRealObject;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@interface OCMStubRecorder (Properties)
|
||||
|
||||
#define andReturn(aValue) _andReturn(({ __typeof__(aValue) _v = (aValue); [NSValue value:&_v withObjCType:@encode(__typeof__(_v))]; }))
|
||||
@property (nonatomic, readonly) OCMStubRecorder *(^ _andReturn)(NSValue *);
|
||||
|
||||
#define andThrow(anException) _andThrow(anException)
|
||||
@property (nonatomic, readonly) OCMStubRecorder *(^ _andThrow)(NSException *);
|
||||
|
||||
#define andPost(aNotification) _andPost(aNotification)
|
||||
@property (nonatomic, readonly) OCMStubRecorder *(^ _andPost)(NSNotification *);
|
||||
|
||||
#define andCall(anObject, aSelector) _andCall(anObject, aSelector)
|
||||
@property (nonatomic, readonly) OCMStubRecorder *(^ _andCall)(id, SEL);
|
||||
|
||||
#define andDo(aBlock) _andDo(aBlock)
|
||||
@property (nonatomic, readonly) OCMStubRecorder *(^ _andDo)(void (^)(NSInvocation *));
|
||||
|
||||
#define andForwardToRealObject() _andForwardToRealObject()
|
||||
@property (nonatomic, readonly) OCMStubRecorder *(^ _andForwardToRealObject)(void);
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* Copyright (c) 2004-2014 Erik Doernenburg and contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use these files except in compliance with the License. You may obtain
|
||||
* a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#import <OCMock/OCMockObject.h>
|
||||
#import <OCMock/OCMRecorder.h>
|
||||
#import <OCMock/OCMStubRecorder.h>
|
||||
#import <OCMock/OCMConstraint.h>
|
||||
#import <OCMock/OCMArg.h>
|
||||
#import <OCMock/OCMLocation.h>
|
||||
#import <OCMock/OCMMacroState.h>
|
||||
#import <OCMock/NSNotificationCenter+OCMAdditions.h>
|
||||
|
||||
|
||||
#define OCMClassMock(cls) [OCMockObject niceMockForClass:cls]
|
||||
|
||||
#define OCMStrictClassMock(cls) [OCMockObject mockForClass:cls]
|
||||
|
||||
#define OCMProtocolMock(protocol) [OCMockObject niceMockForProtocol:protocol]
|
||||
|
||||
#define OCMStrictProtocolMock(protocol) [OCMockObject mockForProtocol:protocol]
|
||||
|
||||
#define OCMPartialMock(obj) [OCMockObject partialMockForObject:obj]
|
||||
|
||||
#define OCMObserverMock() [OCMockObject observerMock]
|
||||
|
||||
|
||||
#define OCMStub(invocation) \
|
||||
({ \
|
||||
_OCMSilenceWarnings( \
|
||||
[OCMMacroState beginStubMacro]; \
|
||||
invocation; \
|
||||
[OCMMacroState endStubMacro]; \
|
||||
); \
|
||||
})
|
||||
|
||||
#define OCMExpect(invocation) \
|
||||
({ \
|
||||
_OCMSilenceWarnings( \
|
||||
[OCMMacroState beginExpectMacro]; \
|
||||
invocation; \
|
||||
[OCMMacroState endExpectMacro]; \
|
||||
); \
|
||||
})
|
||||
|
||||
#define ClassMethod(invocation) \
|
||||
_OCMSilenceWarnings( \
|
||||
[[OCMMacroState globalState] switchToClassMethod]; \
|
||||
invocation; \
|
||||
);
|
||||
|
||||
|
||||
#define OCMVerifyAll(mock) [mock verifyAtLocation:OCMMakeLocation(self, __FILE__, __LINE__)]
|
||||
|
||||
#define OCMVerifyAllWithDelay(mock, delay) [mock verifyWithDelay:delay atLocation:OCMMakeLocation(self, __FILE__, __LINE__)]
|
||||
|
||||
#define OCMVerify(invocation) \
|
||||
({ \
|
||||
_OCMSilenceWarnings( \
|
||||
[OCMMacroState beginVerifyMacroAtLocation:OCMMakeLocation(self, __FILE__, __LINE__)]; \
|
||||
invocation; \
|
||||
[OCMMacroState endVerifyMacro]; \
|
||||
); \
|
||||
})
|
||||
|
||||
#define _OCMSilenceWarnings(macro) \
|
||||
({ \
|
||||
_Pragma("clang diagnostic push") \
|
||||
_Pragma("clang diagnostic ignored \"-Wunused-value\"") \
|
||||
macro \
|
||||
_Pragma("clang diagnostic pop") \
|
||||
})
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* Copyright (c) 2004-2014 Erik Doernenburg and contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use these files except in compliance with the License. You may obtain
|
||||
* a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@class OCMLocation;
|
||||
@class OCMInvocationStub;
|
||||
@class OCMStubRecorder;
|
||||
@class OCMInvocationMatcher;
|
||||
@class OCMInvocationExpectation;
|
||||
|
||||
|
||||
@interface OCMockObject : NSProxy
|
||||
{
|
||||
BOOL isNice;
|
||||
BOOL expectationOrderMatters;
|
||||
NSMutableArray *stubs;
|
||||
NSMutableArray *expectations;
|
||||
NSMutableArray *exceptions;
|
||||
NSMutableArray *invocations;
|
||||
}
|
||||
|
||||
+ (id)mockForClass:(Class)aClass;
|
||||
+ (id)mockForProtocol:(Protocol *)aProtocol;
|
||||
+ (id)partialMockForObject:(NSObject *)anObject;
|
||||
|
||||
+ (id)niceMockForClass:(Class)aClass;
|
||||
+ (id)niceMockForProtocol:(Protocol *)aProtocol;
|
||||
|
||||
+ (id)observerMock;
|
||||
|
||||
- (instancetype)init;
|
||||
|
||||
- (void)setExpectationOrderMatters:(BOOL)flag;
|
||||
|
||||
- (id)stub;
|
||||
- (id)expect;
|
||||
- (id)reject;
|
||||
|
||||
- (id)verify;
|
||||
- (id)verifyAtLocation:(OCMLocation *)location;
|
||||
|
||||
- (void)verifyWithDelay:(NSTimeInterval)delay;
|
||||
- (void)verifyWithDelay:(NSTimeInterval)delay atLocation:(OCMLocation *)location;
|
||||
|
||||
- (void)stopMocking;
|
||||
|
||||
// internal use only
|
||||
|
||||
- (void)addStub:(OCMInvocationStub *)aStub;
|
||||
- (void)addExpectation:(OCMInvocationExpectation *)anExpectation;
|
||||
|
||||
- (BOOL)handleInvocation:(NSInvocation *)anInvocation;
|
||||
- (void)handleUnRecordedInvocation:(NSInvocation *)anInvocation;
|
||||
- (BOOL)handleSelector:(SEL)sel;
|
||||
|
||||
- (void)verifyInvocation:(OCMInvocationMatcher *)matcher;
|
||||
- (void)verifyInvocation:(OCMInvocationMatcher *)matcher atLocation:(OCMLocation *)location;
|
||||
|
||||
@end
|
||||
|
|
@ -0,0 +1,191 @@
|
|||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <XCTest/XCTest.h>
|
||||
|
||||
#import "RCTBridge.h"
|
||||
#import "RCTContextExecutor.h"
|
||||
#import "RCTRootView.h"
|
||||
|
||||
#define RUN_RUNLOOP_WHILE(CONDITION, TIMEOUT) \
|
||||
_Pragma("clang diagnostic push") \
|
||||
_Pragma("clang diagnostic ignored \"-Wshadow\"") \
|
||||
NSDate *timeout = [[NSDate date] dateByAddingTimeInterval:TIMEOUT]; \
|
||||
while ((CONDITION) && [timeout timeIntervalSinceNow] > 0) { \
|
||||
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:timeout]; \
|
||||
} \
|
||||
_Pragma("clang diagnostic pop")
|
||||
|
||||
#define DEFAULT_TIMEOUT 2
|
||||
|
||||
@interface RCTBridge (RCTAllocationTests)
|
||||
|
||||
@property (nonatomic, weak) RCTBridge *batchedBridge;
|
||||
|
||||
@end
|
||||
|
||||
@interface RCTJavaScriptContext : NSObject
|
||||
|
||||
@property (nonatomic, assign, readonly) JSGlobalContextRef ctx;
|
||||
|
||||
@end
|
||||
|
||||
@interface AllocationTestModule : NSObject<RCTBridgeModule, RCTInvalidating>
|
||||
@end
|
||||
|
||||
@implementation AllocationTestModule
|
||||
|
||||
RCT_EXPORT_MODULE();
|
||||
|
||||
@synthesize valid = _valid;
|
||||
|
||||
- (id)init
|
||||
{
|
||||
if ((self = [super init])) {
|
||||
_valid = YES;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)invalidate
|
||||
{
|
||||
_valid = NO;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@interface RCTAllocationTests : XCTestCase
|
||||
@end
|
||||
|
||||
@implementation RCTAllocationTests
|
||||
|
||||
- (void)testBridgeIsDeallocated
|
||||
{
|
||||
__weak RCTBridge *weakBridge;
|
||||
@autoreleasepool {
|
||||
RCTRootView *view = [[RCTRootView alloc] initWithBundleURL:nil
|
||||
moduleName:@""
|
||||
launchOptions:nil];
|
||||
weakBridge = view.bridge;
|
||||
XCTAssertNotNil(weakBridge, @"RCTBridge should have been created");
|
||||
(void)view;
|
||||
}
|
||||
|
||||
sleep(DEFAULT_TIMEOUT);
|
||||
XCTAssertNil(weakBridge, @"RCTBridge should have been deallocated");
|
||||
}
|
||||
|
||||
- (void)testModulesAreInvalidated
|
||||
{
|
||||
AllocationTestModule *module = [[AllocationTestModule alloc] init];
|
||||
@autoreleasepool {
|
||||
RCTBridge *bridge = [[RCTBridge alloc] initWithBundleURL:nil
|
||||
moduleProvider:^{
|
||||
return @[module];
|
||||
}
|
||||
launchOptions:nil];
|
||||
XCTAssertTrue(module.isValid, @"AllocationTestModule should be valid");
|
||||
(void)bridge;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sleep on the main thread to allow js thread deallocations then run the runloop
|
||||
* to allow the module to be deallocated on the main thread
|
||||
*/
|
||||
sleep(1);
|
||||
RUN_RUNLOOP_WHILE(module.isValid, 1)
|
||||
XCTAssertFalse(module.isValid, @"AllocationTestModule should have been invalidated by the bridge");
|
||||
}
|
||||
|
||||
- (void)testModulesAreDeallocated
|
||||
{
|
||||
__weak AllocationTestModule *weakModule;
|
||||
@autoreleasepool {
|
||||
AllocationTestModule *module = [[AllocationTestModule alloc] init];
|
||||
RCTBridge *bridge = [[RCTBridge alloc] initWithBundleURL:nil
|
||||
moduleProvider:^{
|
||||
return @[module];
|
||||
}
|
||||
launchOptions:nil];
|
||||
weakModule = module;
|
||||
XCTAssertNotNil(weakModule, @"AllocationTestModule should have been created");
|
||||
(void)bridge;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sleep on the main thread to allow js thread deallocations then run the runloop
|
||||
* to allow the module to be deallocated on the main thread
|
||||
*/
|
||||
sleep(1);
|
||||
RUN_RUNLOOP_WHILE(weakModule, 1)
|
||||
XCTAssertNil(weakModule, @"AllocationTestModule should have been deallocated");
|
||||
}
|
||||
|
||||
- (void)testJavaScriptExecutorIsDeallocated
|
||||
{
|
||||
__weak id<RCTJavaScriptExecutor> weakExecutor;
|
||||
@autoreleasepool {
|
||||
RCTBridge *bridge = [[RCTBridge alloc] initWithBundleURL:nil
|
||||
moduleProvider:nil
|
||||
launchOptions:nil];
|
||||
weakExecutor = [bridge.batchedBridge valueForKey:@"javaScriptExecutor"];
|
||||
XCTAssertNotNil(weakExecutor, @"JavaScriptExecutor should have been created");
|
||||
(void)bridge;
|
||||
}
|
||||
|
||||
// Sleep on the main thread so the deallocation can happen on the JS thread.
|
||||
sleep(DEFAULT_TIMEOUT);
|
||||
XCTAssertNil(weakExecutor, @"JavaScriptExecutor should have been released");
|
||||
}
|
||||
|
||||
- (void)testJavaScriptContextIsDeallocated
|
||||
{
|
||||
__weak id weakContext;
|
||||
@autoreleasepool {
|
||||
RCTBridge *bridge = [[RCTBridge alloc] initWithBundleURL:nil
|
||||
moduleProvider:nil
|
||||
launchOptions:nil];
|
||||
id executor = [bridge.batchedBridge valueForKey:@"javaScriptExecutor"];
|
||||
RUN_RUNLOOP_WHILE(!(weakContext = [executor valueForKey:@"context"]), DEFAULT_TIMEOUT);
|
||||
XCTAssertNotNil(weakContext, @"RCTJavaScriptContext should have been created");
|
||||
(void)bridge;
|
||||
}
|
||||
|
||||
sleep(DEFAULT_TIMEOUT);
|
||||
XCTAssertNil(weakContext, @"RCTJavaScriptContext should have been deallocated");
|
||||
}
|
||||
|
||||
- (void)testContentViewIsInvalidated
|
||||
{
|
||||
RCTBridge *bridge = [[RCTBridge alloc] initWithBundleURL:nil moduleProvider:nil launchOptions:nil];
|
||||
__weak id rootContentView;
|
||||
@autoreleasepool {
|
||||
RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge moduleName:@""];
|
||||
RUN_RUNLOOP_WHILE(!(rootContentView = [rootView valueForKey:@"contentView"]), DEFAULT_TIMEOUT)
|
||||
XCTAssertTrue([rootContentView isValid], @"RCTContentView should be valid");
|
||||
(void)rootView;
|
||||
}
|
||||
|
||||
sleep(DEFAULT_TIMEOUT);
|
||||
XCTAssertFalse([rootContentView isValid], @"RCTContentView should have been invalidated");
|
||||
}
|
||||
|
||||
- (void)testUnderlyingBridgeIsDeallocated
|
||||
{
|
||||
RCTBridge *bridge;
|
||||
__weak id batchedBridge;
|
||||
@autoreleasepool {
|
||||
bridge = [[RCTBridge alloc] initWithBundleURL:nil moduleProvider:nil launchOptions:nil];
|
||||
batchedBridge = bridge.batchedBridge;
|
||||
XCTAssertTrue([batchedBridge isValid], @"RCTBatchedBridge should be valid");
|
||||
[bridge reload];
|
||||
}
|
||||
|
||||
// Use RUN_RUNLOOP_WHILE because `batchedBridge` deallocates on the main thread.
|
||||
RUN_RUNLOOP_WHILE(batchedBridge != nil, DEFAULT_TIMEOUT)
|
||||
|
||||
XCTAssertNotNil(bridge, @"RCTBridge should not have been deallocated");
|
||||
XCTAssertNil(batchedBridge, @"RCTBatchedBridge should have been deallocated");
|
||||
}
|
||||
|
||||
@end
|
|
@ -0,0 +1,183 @@
|
|||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <XCTest/XCTest.h>
|
||||
|
||||
#import "RCTBridge.h"
|
||||
#import "RCTBridgeModule.h"
|
||||
#import "RCTJavaScriptExecutor.h"
|
||||
#import "RCTUtils.h"
|
||||
|
||||
@interface RCTBridge (Testing)
|
||||
|
||||
@property (nonatomic, strong, readonly) RCTBridge *batchedBridge;
|
||||
|
||||
- (void)_handleBuffer:(id)buffer context:(NSNumber *)context;
|
||||
- (void)setUp;
|
||||
|
||||
@end
|
||||
|
||||
@interface TestExecutor : NSObject <RCTJavaScriptExecutor>
|
||||
|
||||
@property (nonatomic, readonly, copy) NSMutableDictionary *injectedStuff;
|
||||
|
||||
@end
|
||||
|
||||
@implementation TestExecutor
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
if (self = [super init]) {
|
||||
_injectedStuff = [NSMutableDictionary dictionary];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (BOOL)isValid
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)executeJSCall:(NSString *)name
|
||||
method:(NSString *)method
|
||||
arguments:(NSArray *)arguments
|
||||
context:(NSNumber *)executorID
|
||||
callback:(RCTJavaScriptCallback)onComplete
|
||||
{
|
||||
onComplete(nil, nil);
|
||||
}
|
||||
|
||||
- (void)executeApplicationScript:(NSString *)script
|
||||
sourceURL:(NSURL *)url
|
||||
onComplete:(RCTJavaScriptCompleteBlock)onComplete
|
||||
{
|
||||
onComplete(nil);
|
||||
}
|
||||
|
||||
- (void)executeBlockOnJavaScriptQueue:(dispatch_block_t)block
|
||||
{
|
||||
block();
|
||||
}
|
||||
|
||||
- (void)injectJSONText:(NSString *)script
|
||||
asGlobalObjectNamed:(NSString *)objectName
|
||||
callback:(RCTJavaScriptCompleteBlock)onComplete
|
||||
{
|
||||
_injectedStuff[objectName] = script;
|
||||
onComplete(nil);
|
||||
}
|
||||
|
||||
- (void)invalidate {}
|
||||
|
||||
@end
|
||||
|
||||
@interface RCTBridgeTests : XCTestCase <RCTBridgeModule>
|
||||
{
|
||||
RCTBridge *_bridge;
|
||||
BOOL _testMethodCalled;
|
||||
dispatch_queue_t _queue;
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation RCTBridgeTests
|
||||
|
||||
RCT_EXPORT_MODULE(TestModule)
|
||||
|
||||
- (dispatch_queue_t)methodQueue
|
||||
{
|
||||
return _queue;
|
||||
}
|
||||
|
||||
- (void)setUp
|
||||
{
|
||||
[super setUp];
|
||||
|
||||
_queue = dispatch_queue_create("com.facebook.React.TestQueue", DISPATCH_QUEUE_SERIAL);
|
||||
|
||||
_bridge = [[RCTBridge alloc] initWithBundleURL:nil
|
||||
moduleProvider:^{ return @[self]; }
|
||||
launchOptions:nil];
|
||||
|
||||
_bridge.executorClass = [TestExecutor class];
|
||||
// Force to recreate the executor with the new class
|
||||
// - reload: doesn't work here since bridge hasn't loaded yet.
|
||||
[_bridge invalidate];
|
||||
[_bridge setUp];
|
||||
}
|
||||
|
||||
- (void)tearDown
|
||||
{
|
||||
[super tearDown];
|
||||
[_bridge invalidate];
|
||||
}
|
||||
|
||||
- (void)testHookRegistration
|
||||
{
|
||||
TestExecutor *executor = [_bridge.batchedBridge valueForKey:@"_javaScriptExecutor"];
|
||||
NSString *injectedStuff = executor.injectedStuff[@"__fbBatchedBridgeConfig"];
|
||||
NSDictionary *moduleConfig = RCTJSONParse(injectedStuff, NULL);
|
||||
NSDictionary *remoteModuleConfig = moduleConfig[@"remoteModuleConfig"];
|
||||
NSDictionary *testModuleConfig = remoteModuleConfig[@"TestModule"];
|
||||
NSDictionary *constants = testModuleConfig[@"constants"];
|
||||
NSDictionary *methods = testModuleConfig[@"methods"];
|
||||
|
||||
XCTAssertNotNil(moduleConfig);
|
||||
XCTAssertNotNil(remoteModuleConfig);
|
||||
XCTAssertNotNil(testModuleConfig);
|
||||
XCTAssertNotNil(constants);
|
||||
XCTAssertEqualObjects(constants[@"eleventyMillion"], @42);
|
||||
XCTAssertNotNil(methods);
|
||||
XCTAssertNotNil(methods[@"testMethod"]);
|
||||
}
|
||||
|
||||
- (void)testCallNativeMethod
|
||||
{
|
||||
TestExecutor *executor = [_bridge.batchedBridge valueForKey:@"_javaScriptExecutor"];
|
||||
NSString *injectedStuff = executor.injectedStuff[@"__fbBatchedBridgeConfig"];
|
||||
NSDictionary *moduleConfig = RCTJSONParse(injectedStuff, NULL);
|
||||
NSDictionary *remoteModuleConfig = moduleConfig[@"remoteModuleConfig"];
|
||||
NSDictionary *testModuleConfig = remoteModuleConfig[@"TestModule"];
|
||||
NSNumber *testModuleID = testModuleConfig[@"moduleID"];
|
||||
NSDictionary *methods = testModuleConfig[@"methods"];
|
||||
NSDictionary *testMethod = methods[@"testMethod"];
|
||||
NSNumber *testMethodID = testMethod[@"methodID"];
|
||||
|
||||
NSArray *args = @[@1234, @5678, @"stringy", @{@"a": @1}, @42];
|
||||
NSArray *buffer = @[@[testModuleID], @[testMethodID], @[args], @[], @1234567];
|
||||
|
||||
[_bridge.batchedBridge _handleBuffer:buffer context:RCTGetExecutorID(executor)];
|
||||
|
||||
dispatch_sync(_queue, ^{
|
||||
// clear the queue
|
||||
XCTAssertTrue(_testMethodCalled);
|
||||
});
|
||||
}
|
||||
|
||||
- (void)DISABLED_testBadArgumentsCount
|
||||
{
|
||||
//NSArray *bufferWithMissingArgument = @[@[@1], @[@0], @[@[@1234, @5678, @"stringy", @{@"a": @1}/*, @42*/]], @[], @1234567];
|
||||
//[_bridge _handleBuffer:bufferWithMissingArgument];
|
||||
NSLog(@"WARNING: testBadArgumentsCount is temporarily disabled until we have a better way to test cases that we expect to trigger redbox errors");
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(testMethod:(NSInteger)integer
|
||||
number:(NSNumber *)number
|
||||
string:(NSString *)string
|
||||
dictionary:(NSDictionary *)dict
|
||||
callback:(RCTResponseSenderBlock)callback)
|
||||
{
|
||||
_testMethodCalled = YES;
|
||||
|
||||
XCTAssertTrue(integer == 1234);
|
||||
XCTAssertEqualObjects(number, @5678);
|
||||
XCTAssertEqualObjects(string, @"stringy");
|
||||
XCTAssertEqualObjects(dict, @{@"a": @1});
|
||||
XCTAssertNotNil(callback);
|
||||
}
|
||||
|
||||
- (NSDictionary *)constantsToExport
|
||||
{
|
||||
return @{@"eleventyMillion": @42};
|
||||
}
|
||||
|
||||
@end
|
|
@ -0,0 +1,184 @@
|
|||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
|
||||
#import <mach/mach_time.h>
|
||||
|
||||
#import <XCTest/XCTest.h>
|
||||
|
||||
#import "RCTContextExecutor.h"
|
||||
#import "RCTUtils.h"
|
||||
|
||||
|
||||
@interface RCTContextExecutorTests : XCTestCase
|
||||
|
||||
@end
|
||||
|
||||
@implementation RCTContextExecutorTests
|
||||
|
||||
- (void)testNativeLoggingHookExceptionBehavior
|
||||
{
|
||||
RCTContextExecutor *executor = [[RCTContextExecutor alloc] init];
|
||||
dispatch_semaphore_t doneSem = dispatch_semaphore_create(0);
|
||||
[executor executeApplicationScript:@"var x = {toString: function() { throw 1; }}; nativeLoggingHook(x);"
|
||||
sourceURL:[NSURL URLWithString:@"file://"]
|
||||
onComplete:^(id error){
|
||||
dispatch_semaphore_signal(doneSem);
|
||||
}];
|
||||
dispatch_semaphore_wait(doneSem, DISPATCH_TIME_FOREVER);
|
||||
[executor invalidate];
|
||||
}
|
||||
|
||||
static uint64_t _get_time_nanoseconds(void)
|
||||
{
|
||||
static struct mach_timebase_info tb_info = {0};
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
int ret = mach_timebase_info(&tb_info);
|
||||
assert(0 == ret);
|
||||
});
|
||||
|
||||
return (mach_absolute_time() * tb_info.numer) / tb_info.denom;
|
||||
}
|
||||
|
||||
- (void)testDeserializationPerf
|
||||
{
|
||||
// This test case checks the assumption that deserializing objects from JavaScript
|
||||
// values one-by-one via ObjC JSC API is slower than using JSON string
|
||||
// You might want to switch your tests schema to "Release" build configuration
|
||||
|
||||
JSContextGroupRef group = JSContextGroupCreate();
|
||||
JSGlobalContextRef context = JSGlobalContextCreateInGroup(group, NULL);
|
||||
id message = @[@[@1, @2, @3, @4], @[@{@"a": @1}, @{@"b": @2}], [NSNull null]];
|
||||
NSString *code = RCTJSONStringify(message, NULL);
|
||||
JSStringRef script = JSStringCreateWithCFString((__bridge CFStringRef)code);
|
||||
JSValueRef error = NULL;
|
||||
JSValueRef value = JSEvaluateScript(context, script, NULL, NULL, 0, &error);
|
||||
XCTAssertTrue(error == NULL);
|
||||
|
||||
id obj;
|
||||
uint64_t start = _get_time_nanoseconds();
|
||||
for (int i = 0; i < 10000; i++) {
|
||||
JSStringRef jsonJSString = JSValueCreateJSONString(context, value, 0, nil);
|
||||
NSString *jsonString = (__bridge NSString *)JSStringCopyCFString(kCFAllocatorDefault, jsonJSString);
|
||||
JSStringRelease(jsonJSString);
|
||||
|
||||
obj = RCTJSONParse(jsonString, NULL);
|
||||
}
|
||||
NSLog(@"JSON Parse time: %.2fms", (_get_time_nanoseconds() - start) / 1000000.0);
|
||||
|
||||
JSStringRelease(script);
|
||||
JSGlobalContextRelease(context);
|
||||
JSContextGroupRelease(group);
|
||||
}
|
||||
|
||||
- (void)MANUALLY_testJavaScriptCallSpeed
|
||||
{
|
||||
/**
|
||||
* Since we almost don't change the RCTContextExecutor logic, and this test is
|
||||
* very likely to become flaky (specially accross different devices) leave it
|
||||
* to be run manually
|
||||
*
|
||||
* Previous Values: If you change the executor code, you should update this values
|
||||
*/
|
||||
|
||||
int const runs = 4e5;
|
||||
int const frequency = 10;
|
||||
double const threshold = 0.1;
|
||||
static double const expectedTimes[] = {
|
||||
0x1.6199943826cf1p+13,
|
||||
0x1.a3bc0a81551c3p+13,
|
||||
0x1.d49fbb8602fe3p+13,
|
||||
0x1.d1f64085ecb7bp+13,
|
||||
};
|
||||
|
||||
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
|
||||
RCTContextExecutor *executor = RCTCreateExecutor([RCTContextExecutor class]);
|
||||
NSString *script = @" \
|
||||
var modules = { \
|
||||
module: { \
|
||||
method: function () { \
|
||||
return true; \
|
||||
} \
|
||||
} \
|
||||
}; \
|
||||
function require(module) { \
|
||||
return modules[module]; \
|
||||
} \
|
||||
";
|
||||
|
||||
[executor executeApplicationScript:script sourceURL:[NSURL URLWithString:@"http://localhost:8081/"] onComplete:^(NSError *error) {
|
||||
NSMutableArray *params = [[NSMutableArray alloc] init];
|
||||
id data = @1;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
double samples[runs / frequency];
|
||||
int size = runs / frequency;
|
||||
double total = 0;
|
||||
for (int j = 0; j < runs; j++) {
|
||||
@autoreleasepool {
|
||||
double start = _get_time_nanoseconds();
|
||||
[executor executeJSCall:@"module"
|
||||
method:@"method"
|
||||
arguments:params
|
||||
context:RCTGetExecutorID(executor)
|
||||
callback:^(id json, NSError *__error) {
|
||||
RCTAssert([json isEqual:@YES], @"Invalid return");
|
||||
}];
|
||||
double run = _get_time_nanoseconds() - start;
|
||||
if ((j % frequency) == frequency - 1) { // Warmup
|
||||
total += run;
|
||||
samples[j/frequency] = run;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
double mean = total / size;
|
||||
double variance = 0;
|
||||
|
||||
for (int j = 0; j < size; j++) {
|
||||
variance += pow(samples[j] - mean, 2);
|
||||
}
|
||||
variance /= size;
|
||||
|
||||
double standardDeviation = sqrt(variance);
|
||||
double marginOfError = standardDeviation * 1.645;
|
||||
|
||||
double lower = mean - marginOfError;
|
||||
double upper = mean + marginOfError;
|
||||
|
||||
int s = 0;
|
||||
total = 0;
|
||||
for (int j = 0; j < size; j++) {
|
||||
double v = samples[j];
|
||||
if (v >= lower && v <= upper) {
|
||||
samples[s++] = v;
|
||||
total += v;
|
||||
}
|
||||
}
|
||||
mean = total / s;
|
||||
|
||||
lower = mean * (1.0 - threshold);
|
||||
upper = mean * (1.0 + threshold);
|
||||
|
||||
double expected = expectedTimes[i];
|
||||
|
||||
NSLog(@"Previous: %lf, New: %f -> %a", expected, mean, mean);
|
||||
if (upper < expected) {
|
||||
NSLog(@"You made JS calls with %d argument(s) %.2lf%% faster :) - Remember to update the tests with the new value: %a",
|
||||
i, (1 - (double)mean / expected) * 100, mean);
|
||||
}
|
||||
|
||||
|
||||
XCTAssertTrue(lower < expected, @"You made JS calls with %d argument(s) %.2lf%% slower :( - If that's *really* necessary, update the tests with the new value: %a",
|
||||
i, ((double)mean / expected - 1) * 100, mean);
|
||||
|
||||
[params addObject:data];
|
||||
}
|
||||
dispatch_semaphore_signal(semaphore);
|
||||
}];
|
||||
|
||||
while (dispatch_semaphore_wait(semaphore, DISPATCH_TIME_NOW)) {
|
||||
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode
|
||||
beforeDate:[NSDate dateWithTimeIntervalSinceNow:10]];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
|
@ -0,0 +1,48 @@
|
|||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
|
||||
#import <XCTest/XCTest.h>
|
||||
|
||||
#import "RCTConvert.h"
|
||||
|
||||
@interface RCTConvert_NSURLTests : XCTestCase
|
||||
|
||||
@end
|
||||
|
||||
@implementation RCTConvert_NSURLTests
|
||||
|
||||
#define TEST_URL(name, _input, _expectedURL) \
|
||||
- (void)test_##name { \
|
||||
NSURL *result = [RCTConvert NSURL:_input]; \
|
||||
NSURL *expected = [NSURL URLWithString:_expectedURL]; \
|
||||
XCTAssertEqualObjects(result.absoluteURL, expected); \
|
||||
} \
|
||||
|
||||
#define TEST_PATH(name, _input, _expectedPath) \
|
||||
- (void)test_##name { \
|
||||
NSURL *result = [RCTConvert NSURL:_input]; \
|
||||
XCTAssertEqualObjects(result.path, _expectedPath); \
|
||||
} \
|
||||
|
||||
#define TEST_BUNDLE_PATH(name, _input, _expectedPath) \
|
||||
TEST_PATH(name, _input, [[[NSBundle mainBundle] bundlePath] stringByAppendingPathComponent:_expectedPath])
|
||||
|
||||
// Basic tests
|
||||
TEST_URL(basic, @"http://example.com", @"http://example.com")
|
||||
TEST_URL(null, [NSNull null], nil)
|
||||
|
||||
// Local files
|
||||
TEST_PATH(fileURL, @"file:///blah/hello.jsbundle", @"/blah/hello.jsbundle")
|
||||
TEST_BUNDLE_PATH(filePath, @"blah/hello.jsbundle", @"blah/hello.jsbundle")
|
||||
TEST_BUNDLE_PATH(filePathWithSpaces, @"blah blah/hello.jsbundle", @"blah blah/hello.jsbundle")
|
||||
TEST_BUNDLE_PATH(filePathWithEncodedSpaces, @"blah%20blah/hello.jsbundle", @"blah blah/hello.jsbundle")
|
||||
TEST_BUNDLE_PATH(imageAt2XPath, @"images/foo@2x.jpg", @"images/foo@2x.jpg")
|
||||
TEST_BUNDLE_PATH(imageFile, @"foo.jpg", @"foo.jpg")
|
||||
|
||||
// Remote files
|
||||
TEST_URL(fullURL, @"http://example.com/blah/hello.jsbundle", @"http://example.com/blah/hello.jsbundle")
|
||||
TEST_URL(urlWithSpaces, @"http://example.com/blah blah/foo", @"http://example.com/blah%20blah/foo")
|
||||
TEST_URL(urlWithEncodedSpaces, @"http://example.com/blah%20blah/foo", @"http://example.com/blah%20blah/foo")
|
||||
TEST_URL(imageURL, @"http://example.com/foo@2x.jpg", @"http://example.com/foo@2x.jpg")
|
||||
TEST_URL(imageURLWithSpaces, @"http://example.com/blah foo@2x.jpg", @"http://example.com/blah%20foo@2x.jpg")
|
||||
|
||||
@end
|
|
@ -0,0 +1,159 @@
|
|||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
|
||||
#import <XCTest/XCTest.h>
|
||||
|
||||
#import "RCTConvert.h"
|
||||
|
||||
@interface RCTConvert_UIFontTests : XCTestCase
|
||||
|
||||
@end
|
||||
|
||||
@implementation RCTConvert_UIFontTests
|
||||
|
||||
#define RCTAssertEqualFonts(font1, font2) { \
|
||||
XCTAssertEqualObjects(font1, font2); \
|
||||
}
|
||||
|
||||
- (void)DISABLED_testWeight // task #7118691
|
||||
{
|
||||
{
|
||||
UIFont *expected = [UIFont fontWithName:@"HelveticaNeue-Bold" size:14];
|
||||
UIFont *result = [RCTConvert UIFont:@{@"fontWeight": @"bold"}];
|
||||
RCTAssertEqualFonts(expected, result);
|
||||
}
|
||||
{
|
||||
UIFont *expected = [UIFont fontWithName:@"HelveticaNeue-Medium" size:14];
|
||||
UIFont *result = [RCTConvert UIFont:@{@"fontWeight": @"500"}];
|
||||
RCTAssertEqualFonts(expected, result);
|
||||
}
|
||||
{
|
||||
UIFont *expected = [UIFont fontWithName:@"HelveticaNeue-UltraLight" size:14];
|
||||
UIFont *result = [RCTConvert UIFont:@{@"fontWeight": @"100"}];
|
||||
RCTAssertEqualFonts(expected, result);
|
||||
}
|
||||
{
|
||||
UIFont *expected = [UIFont fontWithName:@"HelveticaNeue" size:14];
|
||||
UIFont *result = [RCTConvert UIFont:@{@"fontWeight": @"normal"}];
|
||||
RCTAssertEqualFonts(expected, result);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)testSize
|
||||
{
|
||||
{
|
||||
UIFont *expected = [UIFont fontWithName:@"HelveticaNeue" size:18.5];
|
||||
UIFont *result = [RCTConvert UIFont:@{@"fontSize": @18.5}];
|
||||
RCTAssertEqualFonts(expected, result);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)testFamily
|
||||
{
|
||||
{
|
||||
UIFont *expected = [UIFont fontWithName:@"Cochin" size:14];
|
||||
UIFont *result = [RCTConvert UIFont:@{@"fontFamily": @"Cochin"}];
|
||||
RCTAssertEqualFonts(expected, result);
|
||||
}
|
||||
{
|
||||
UIFont *expected = [UIFont fontWithName:@"HelveticaNeue" size:14];
|
||||
UIFont *result = [RCTConvert UIFont:@{@"fontFamily": @"Helvetica Neue"}];
|
||||
RCTAssertEqualFonts(expected, result);
|
||||
}
|
||||
{
|
||||
UIFont *expected = [UIFont fontWithName:@"HelveticaNeue-Italic" size:14];
|
||||
UIFont *result = [RCTConvert UIFont:@{@"fontFamily": @"HelveticaNeue-Italic"}];
|
||||
RCTAssertEqualFonts(expected, result);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)testStyle
|
||||
{
|
||||
{
|
||||
UIFont *expected = [UIFont fontWithName:@"HelveticaNeue-Italic" size:14];
|
||||
UIFont *result = [RCTConvert UIFont:@{@"fontStyle": @"italic"}];
|
||||
RCTAssertEqualFonts(expected, result);
|
||||
}
|
||||
{
|
||||
UIFont *expected = [UIFont fontWithName:@"HelveticaNeue" size:14];
|
||||
UIFont *result = [RCTConvert UIFont:@{@"fontStyle": @"normal"}];
|
||||
RCTAssertEqualFonts(expected, result);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)DISABLED_testStyleAndWeight // task #7118691
|
||||
{
|
||||
{
|
||||
UIFont *expected = [UIFont fontWithName:@"HelveticaNeue-UltraLightItalic" size:14];
|
||||
UIFont *result = [RCTConvert UIFont:@{@"fontStyle": @"italic", @"fontWeight": @"100"}];
|
||||
RCTAssertEqualFonts(expected, result);
|
||||
}
|
||||
{
|
||||
UIFont *expected = [UIFont fontWithName:@"HelveticaNeue-BoldItalic" size:14];
|
||||
UIFont *result = [RCTConvert UIFont:@{@"fontStyle": @"italic", @"fontWeight": @"bold"}];
|
||||
RCTAssertEqualFonts(expected, result);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)DISABLED_testFamilyAndWeight // task #7118691
|
||||
{
|
||||
{
|
||||
UIFont *expected = [UIFont fontWithName:@"HelveticaNeue-Bold" size:14];
|
||||
UIFont *result = [RCTConvert UIFont:@{@"fontFamily": @"Helvetica Neue", @"fontWeight": @"bold"}];
|
||||
RCTAssertEqualFonts(expected, result);
|
||||
}
|
||||
{
|
||||
UIFont *expected = [UIFont fontWithName:@"HelveticaNeue" size:14];
|
||||
UIFont *result = [RCTConvert UIFont:@{@"fontFamily": @"HelveticaNeue-Bold", @"fontWeight": @"normal"}];
|
||||
RCTAssertEqualFonts(expected, result);
|
||||
}
|
||||
{
|
||||
UIFont *expected = [UIFont fontWithName:@"Cochin-Bold" size:14];
|
||||
UIFont *result = [RCTConvert UIFont:@{@"fontFamily": @"Cochin", @"fontWeight": @"700"}];
|
||||
RCTAssertEqualFonts(expected, result);
|
||||
}
|
||||
{
|
||||
UIFont *expected = [UIFont fontWithName:@"Cochin" size:14];
|
||||
UIFont *result = [RCTConvert UIFont:@{@"fontFamily": @"Cochin", @"fontWeight": @"500"}]; // regular Cochin is actually medium bold
|
||||
RCTAssertEqualFonts(expected, result);
|
||||
}
|
||||
{
|
||||
UIFont *expected = [UIFont fontWithName:@"Cochin" size:14];
|
||||
UIFont *result = [RCTConvert UIFont:@{@"fontFamily": @"Cochin", @"fontWeight": @"100"}];
|
||||
RCTAssertEqualFonts(expected, result);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)testFamilyAndStyle
|
||||
{
|
||||
{
|
||||
UIFont *expected = [UIFont fontWithName:@"HelveticaNeue-Italic" size:14];
|
||||
UIFont *result = [RCTConvert UIFont:@{@"fontFamily": @"Helvetica Neue", @"fontStyle": @"italic"}];
|
||||
RCTAssertEqualFonts(expected, result);
|
||||
}
|
||||
{
|
||||
UIFont *expected = [UIFont fontWithName:@"HelveticaNeue" size:14];
|
||||
UIFont *result = [RCTConvert UIFont:@{@"fontFamily": @"HelveticaNeue-Italic", @"fontStyle": @"normal"}];
|
||||
RCTAssertEqualFonts(expected, result);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)DISABLED_testFamilyStyleAndWeight // task #7118691
|
||||
{
|
||||
{
|
||||
UIFont *expected = [UIFont fontWithName:@"HelveticaNeue-UltraLightItalic" size:14];
|
||||
UIFont *result = [RCTConvert UIFont:@{@"fontFamily": @"Helvetica Neue", @"fontStyle": @"italic", @"fontWeight": @"100"}];
|
||||
RCTAssertEqualFonts(expected, result);
|
||||
}
|
||||
{
|
||||
UIFont *expected = [UIFont fontWithName:@"HelveticaNeue-Bold" size:14];
|
||||
UIFont *result = [RCTConvert UIFont:@{@"fontFamily": @"HelveticaNeue-Italic", @"fontStyle": @"normal", @"fontWeight": @"bold"}];
|
||||
RCTAssertEqualFonts(expected, result);
|
||||
}
|
||||
{
|
||||
UIFont *expected = [UIFont fontWithName:@"HelveticaNeue" size:14];
|
||||
UIFont *result = [RCTConvert UIFont:@{@"fontFamily": @"HelveticaNeue-Italic", @"fontStyle": @"normal", @"fontWeight": @"normal"}];
|
||||
RCTAssertEqualFonts(expected, result);
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
|
@ -0,0 +1,144 @@
|
|||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import <XCTest/XCTest.h>
|
||||
|
||||
#import <OCMock/OCMock.h>
|
||||
#import "RCTEventDispatcher.h"
|
||||
|
||||
@interface RCTTestEvent : RCTBaseEvent
|
||||
|
||||
@property (nonatomic, assign) BOOL canCoalesce;
|
||||
|
||||
@end
|
||||
|
||||
@implementation RCTTestEvent
|
||||
|
||||
- (instancetype)initWithViewTag:(NSNumber *)viewTag eventName:(NSString *)eventName body:(NSDictionary *)body
|
||||
{
|
||||
if (self = [super initWithViewTag:viewTag eventName:eventName body:body]) {
|
||||
self.canCoalesce = YES;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (NSString *)moduleDotMethod
|
||||
{
|
||||
return @"RCTDeviceEventEmitter.emit";
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@interface RCTEventDispatcherTests : XCTestCase
|
||||
@end
|
||||
|
||||
@implementation RCTEventDispatcherTests
|
||||
{
|
||||
id _bridge;
|
||||
RCTEventDispatcher *_eventDispatcher;
|
||||
|
||||
NSString *_eventName;
|
||||
NSDictionary *_body;
|
||||
RCTTestEvent *_testEvent;
|
||||
NSString *_JSMethod;
|
||||
}
|
||||
|
||||
|
||||
- (void)setUp
|
||||
{
|
||||
[super setUp];
|
||||
|
||||
_bridge = [OCMockObject mockForClass:[RCTBridge class]];
|
||||
_eventDispatcher = [[RCTEventDispatcher alloc] init];
|
||||
((id<RCTBridgeModule>)_eventDispatcher).bridge = _bridge;
|
||||
|
||||
_eventName = @"sampleEvent";
|
||||
_body = @{ @"foo": @"bar" };
|
||||
_testEvent = [[RCTTestEvent alloc] initWithViewTag:nil
|
||||
eventName:_eventName
|
||||
body:_body];
|
||||
|
||||
_JSMethod = [[_testEvent class] moduleDotMethod];
|
||||
}
|
||||
|
||||
- (void)testLegacyEventsAreImmediatelyDispatched
|
||||
{
|
||||
[[_bridge expect] enqueueJSCall:_JSMethod
|
||||
args:@[_eventName, _body]];
|
||||
|
||||
[_eventDispatcher sendDeviceEventWithName:_eventName body:_body];
|
||||
|
||||
[_bridge verify];
|
||||
}
|
||||
|
||||
- (void)testNonCoalescingEventsAreImmediatelyDispatched
|
||||
{
|
||||
_testEvent.canCoalesce = NO;
|
||||
[[_bridge expect] enqueueJSCall:_JSMethod
|
||||
args:@[_eventName, _body]];
|
||||
|
||||
[_eventDispatcher sendEvent:_testEvent];
|
||||
|
||||
[_bridge verify];
|
||||
}
|
||||
|
||||
- (void)testCoalescedEventShouldBeDispatchedOnFrameUpdate
|
||||
{
|
||||
[_eventDispatcher sendEvent:_testEvent];
|
||||
|
||||
[[_bridge expect] enqueueJSCall:@"RCTDeviceEventEmitter.emit"
|
||||
args:@[_eventName, _body]];
|
||||
|
||||
[(id<RCTFrameUpdateObserver>)_eventDispatcher didUpdateFrame:nil];
|
||||
|
||||
[_bridge verify];
|
||||
}
|
||||
|
||||
- (void)testBasicCoalescingReturnsLastEvent
|
||||
{
|
||||
RCTTestEvent *ignoredEvent = [[RCTTestEvent alloc] initWithViewTag:nil
|
||||
eventName:_eventName
|
||||
body:@{ @"other": @"body" }];
|
||||
|
||||
[_eventDispatcher sendEvent:ignoredEvent];
|
||||
[_eventDispatcher sendEvent:_testEvent];
|
||||
|
||||
[[_bridge expect] enqueueJSCall:@"RCTDeviceEventEmitter.emit"
|
||||
args:@[_eventName, _body]];
|
||||
|
||||
[(id<RCTFrameUpdateObserver>)_eventDispatcher didUpdateFrame:nil];
|
||||
|
||||
[_bridge verify];
|
||||
}
|
||||
|
||||
- (void)testDifferentEventTypesDontCoalesce
|
||||
{
|
||||
NSString *firstEventName = @"firstEvent";
|
||||
RCTTestEvent *firstEvent = [[RCTTestEvent alloc] initWithViewTag:nil
|
||||
eventName:firstEventName
|
||||
body:_body];
|
||||
|
||||
[_eventDispatcher sendEvent:firstEvent];
|
||||
[_eventDispatcher sendEvent:_testEvent];
|
||||
|
||||
[[_bridge expect] enqueueJSCall:@"RCTDeviceEventEmitter.emit"
|
||||
args:@[firstEventName, _body]];
|
||||
|
||||
[[_bridge expect] enqueueJSCall:@"RCTDeviceEventEmitter.emit"
|
||||
args:@[_eventName, _body]];
|
||||
|
||||
[(id<RCTFrameUpdateObserver>)_eventDispatcher didUpdateFrame:nil];
|
||||
|
||||
[_bridge verify];
|
||||
}
|
||||
|
||||
@end
|
|
@ -0,0 +1,43 @@
|
|||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
|
||||
#import <XCTest/XCTest.h>
|
||||
|
||||
#import "RCTSparseArray.h"
|
||||
#import "UIView+React.h"
|
||||
|
||||
@interface RCTSparseArrayTests : XCTestCase
|
||||
|
||||
@end
|
||||
|
||||
@implementation RCTSparseArrayTests
|
||||
|
||||
- (void)testDictionary
|
||||
{
|
||||
NSObject<RCTViewNodeProtocol> *myView = [[UIView alloc] init];
|
||||
myView.reactTag = @4;
|
||||
|
||||
NSObject<RCTViewNodeProtocol> *myOtherView = [[UIView alloc] init];
|
||||
myOtherView.reactTag = @5;
|
||||
|
||||
RCTSparseArray *registry = [[RCTSparseArray alloc] init];
|
||||
XCTAssertNil(registry[@4], @"how did you have a view when none are registered?");
|
||||
XCTAssertNil(registry[@5], @"how did you have a view when none are registered?");
|
||||
|
||||
registry[myView.reactTag] = myView;
|
||||
XCTAssertEqual(registry[@4], myView);
|
||||
XCTAssertNil(registry[@5], @"didn't register other view yet");
|
||||
|
||||
registry[myOtherView.reactTag] = myOtherView;
|
||||
XCTAssertEqual(registry[@4], myView);
|
||||
XCTAssertEqual(registry[@5], myOtherView);
|
||||
|
||||
registry[myView.reactTag] = nil;
|
||||
XCTAssertNil(registry[@4]);
|
||||
XCTAssertEqual(registry[@5], myOtherView);
|
||||
|
||||
registry[myOtherView.reactTag] = nil;
|
||||
XCTAssertNil(registry[@4], @"how did you have a view when none are registered?");
|
||||
XCTAssertNil(registry[@5], @"how did you have a view when none are registered?");
|
||||
}
|
||||
|
||||
@end
|
|
@ -0,0 +1,179 @@
|
|||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
|
||||
#import <XCTest/XCTest.h>
|
||||
|
||||
#import "RCTSparseArray.h"
|
||||
#import "RCTUIManager.h"
|
||||
#import "UIView+React.h"
|
||||
|
||||
@interface RCTUIManager (Testing)
|
||||
|
||||
- (void)_manageChildren:(NSNumber *)containerReactTag
|
||||
moveFromIndices:(NSArray *)moveFromIndices
|
||||
moveToIndices:(NSArray *)moveToIndices
|
||||
addChildReactTags:(NSArray *)addChildReactTags
|
||||
addAtIndices:(NSArray *)addAtIndices
|
||||
removeAtIndices:(NSArray *)removeAtIndices
|
||||
registry:(RCTSparseArray *)registry;
|
||||
|
||||
@property (nonatomic, readonly) RCTSparseArray *viewRegistry;
|
||||
|
||||
@end
|
||||
|
||||
@interface RCTUIManagerTests : XCTestCase
|
||||
|
||||
@property (nonatomic, readwrite, strong) RCTUIManager *uiManager;
|
||||
|
||||
@end
|
||||
|
||||
@implementation RCTUIManagerTests
|
||||
|
||||
- (void)setUp
|
||||
{
|
||||
[super setUp];
|
||||
|
||||
_uiManager = [[RCTUIManager alloc] init];
|
||||
|
||||
// Register 20 views to use in the tests
|
||||
for (NSInteger i = 1; i <= 20; i++) {
|
||||
UIView *registeredView = [[UIView alloc] init];
|
||||
[registeredView setReactTag:@(i)];
|
||||
_uiManager.viewRegistry[i] = registeredView;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)testManagingChildrenToAddViews
|
||||
{
|
||||
UIView *containerView = _uiManager.viewRegistry[20];
|
||||
NSMutableArray *addedViews = [NSMutableArray array];
|
||||
|
||||
NSArray *tagsToAdd = @[@1, @2, @3, @4, @5];
|
||||
NSArray *addAtIndices = @[@0, @1, @2, @3, @4];
|
||||
for (NSNumber *tag in tagsToAdd) {
|
||||
[addedViews addObject:_uiManager.viewRegistry[tag]];
|
||||
}
|
||||
|
||||
// Add views 1-5 to view 20
|
||||
[_uiManager _manageChildren:@20
|
||||
moveFromIndices:nil
|
||||
moveToIndices:nil
|
||||
addChildReactTags:tagsToAdd
|
||||
addAtIndices:addAtIndices
|
||||
removeAtIndices:nil
|
||||
registry:_uiManager.viewRegistry];
|
||||
|
||||
XCTAssertTrue([[containerView reactSubviews] count] == 5,
|
||||
@"Expect to have 5 react subviews after calling manage children \
|
||||
with 5 tags to add, instead have %lu", (unsigned long)[[containerView reactSubviews] count]);
|
||||
for (UIView *view in addedViews) {
|
||||
XCTAssertTrue([view superview] == containerView,
|
||||
@"Expected to have manage children successfully add children");
|
||||
[view removeFromSuperview];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)testManagingChildrenToRemoveViews
|
||||
{
|
||||
UIView *containerView = _uiManager.viewRegistry[20];
|
||||
NSMutableArray *removedViews = [NSMutableArray array];
|
||||
|
||||
NSArray *removeAtIndices = @[@0, @4, @8, @12, @16];
|
||||
for (NSNumber *index in removeAtIndices) {
|
||||
NSNumber *reactTag = @([index integerValue] + 2);
|
||||
[removedViews addObject:_uiManager.viewRegistry[reactTag]];
|
||||
}
|
||||
for (NSInteger i = 2; i < 20; i++) {
|
||||
UIView *view = _uiManager.viewRegistry[i];
|
||||
[containerView addSubview:view];
|
||||
}
|
||||
|
||||
// Remove views 1-5 from view 20
|
||||
[_uiManager _manageChildren:@20
|
||||
moveFromIndices:nil
|
||||
moveToIndices:nil
|
||||
addChildReactTags:nil
|
||||
addAtIndices:nil
|
||||
removeAtIndices:removeAtIndices
|
||||
registry:_uiManager.viewRegistry];
|
||||
|
||||
XCTAssertEqual(containerView.reactSubviews.count, (NSUInteger)13,
|
||||
@"Expect to have 13 react subviews after calling manage children\
|
||||
with 5 tags to remove and 18 prior children, instead have %zd",
|
||||
containerView.reactSubviews.count);
|
||||
for (UIView *view in removedViews) {
|
||||
XCTAssertTrue([view superview] == nil,
|
||||
@"Expected to have manage children successfully remove children");
|
||||
// After removing views are unregistered - we need to reregister
|
||||
_uiManager.viewRegistry[view.reactTag] = view;
|
||||
}
|
||||
for (NSInteger i = 2; i < 20; i++) {
|
||||
UIView *view = _uiManager.viewRegistry[i];
|
||||
if (![removedViews containsObject:view]) {
|
||||
XCTAssertTrue([view superview] == containerView,
|
||||
@"Should not have removed view with react tag %ld during delete but did", (long)i);
|
||||
[view removeFromSuperview];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We want to start with views 1-10 added at indices 0-9
|
||||
// Then we'll remove indices 2, 3, 5 and 8
|
||||
// Add views 11 and 12 to indices 0 and 6
|
||||
// And move indices 4 and 9 to 1 and 7
|
||||
// So in total it goes from:
|
||||
// [1,2,3,4,5,6,7,8,9,10]
|
||||
// to
|
||||
// [11,5,1,2,7,8,12,10]
|
||||
- (void)testManagingChildrenToAddRemoveAndMove
|
||||
{
|
||||
UIView *containerView = _uiManager.viewRegistry[20];
|
||||
|
||||
NSArray *removeAtIndices = @[@2, @3, @5, @8];
|
||||
NSArray *addAtIndices = @[@0, @6];
|
||||
NSArray *tagsToAdd = @[@11, @12];
|
||||
NSArray *moveFromIndices = @[@4, @9];
|
||||
NSArray *moveToIndices = @[@1, @7];
|
||||
|
||||
// We need to keep these in array to keep them around
|
||||
NSMutableArray *viewsToRemove = [NSMutableArray array];
|
||||
for (NSInteger i = 0; i < removeAtIndices.count; i++) {
|
||||
NSNumber *reactTagToRemove = @([removeAtIndices[i] integerValue] + 1);
|
||||
UIView *viewToRemove = _uiManager.viewRegistry[reactTagToRemove];
|
||||
[viewsToRemove addObject:viewToRemove];
|
||||
}
|
||||
|
||||
for (NSInteger i = 1; i < 11; i++) {
|
||||
UIView *view = _uiManager.viewRegistry[i];
|
||||
[containerView addSubview:view];
|
||||
}
|
||||
|
||||
[_uiManager _manageChildren:@20
|
||||
moveFromIndices:moveFromIndices
|
||||
moveToIndices:moveToIndices
|
||||
addChildReactTags:tagsToAdd
|
||||
addAtIndices:addAtIndices
|
||||
removeAtIndices:removeAtIndices
|
||||
registry:_uiManager.viewRegistry];
|
||||
|
||||
XCTAssertTrue([[containerView reactSubviews] count] == 8,
|
||||
@"Expect to have 8 react subviews after calling manage children,\
|
||||
instead have the following subviews %@", [containerView reactSubviews]);
|
||||
|
||||
NSArray *expectedReactTags = @[@11, @5, @1, @2, @7, @8, @12, @10];
|
||||
for (NSInteger i = 0; i < [[containerView subviews] count]; i++) {
|
||||
XCTAssertEqualObjects([[containerView reactSubviews][i] reactTag], expectedReactTags[i],
|
||||
@"Expected subview at index %ld to have react tag #%@ but has tag #%@",
|
||||
(long)i, expectedReactTags[i], [[containerView reactSubviews][i] reactTag]);
|
||||
}
|
||||
|
||||
// Clean up after ourselves
|
||||
for (NSInteger i = 1; i < 13; i++) {
|
||||
UIView *view = _uiManager.viewRegistry[i];
|
||||
[view removeFromSuperview];
|
||||
}
|
||||
for (UIView *view in viewsToRemove) {
|
||||
_uiManager.viewRegistry[view.reactTag] = view;
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
Binary file not shown.
Loading…
Reference in New Issue