Updates from Tue 9 Jun
@@ -45,7 +45,7 @@ var NavigatorIOSColors = React.createClass({
|
||||
|
||||
render: function() {
|
||||
// Set StatusBar with light contents to get better contrast
|
||||
StatusBarIOS.setStyle(StatusBarIOS.Style.lightContent);
|
||||
StatusBarIOS.setStyle('light-content');
|
||||
|
||||
return (
|
||||
<NavigatorIOS
|
||||
@@ -55,7 +55,7 @@ var NavigatorIOSColors = React.createClass({
|
||||
title: '<NavigatorIOS>',
|
||||
rightButtonTitle: 'Done',
|
||||
onRightButtonPress: () => {
|
||||
StatusBarIOS.setStyle(StatusBarIOS.Style['default']);
|
||||
StatusBarIOS.setStyle('default');
|
||||
this.props.onExampleExit();
|
||||
},
|
||||
passProps: {
|
||||
|
||||
@@ -7,20 +7,42 @@
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
004D28A31AAF61C70097A701 /* UIExplorerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 004D28A21AAF61C70097A701 /* UIExplorerTests.m */; };
|
||||
13417FE91AA91432003F314A /* libRCTImage.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 13417FE81AA91428003F314A /* libRCTImage.a */; };
|
||||
134180011AA9153C003F314A /* libRCTText.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 13417FEF1AA914B8003F314A /* libRCTText.a */; };
|
||||
1341802C1AA9178B003F314A /* libRCTNetwork.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1341802B1AA91779003F314A /* libRCTNetwork.a */; };
|
||||
134454601AAFCABD003F0779 /* libRCTAdSupport.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1344545A1AAFCAAE003F0779 /* libRCTAdSupport.a */; };
|
||||
134A8A2A1AACED7A00945AAE /* libRCTGeolocation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 134A8A251AACED6A00945AAE /* libRCTGeolocation.a */; };
|
||||
1353F5461B0E64F9009B4FAC /* ClippingTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 1353F5451B0E64F9009B4FAC /* ClippingTests.m */; };
|
||||
139FDEDB1B0651FB00C62182 /* libRCTWebSocket.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 139FDED91B0651EA00C62182 /* libRCTWebSocket.a */; };
|
||||
13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.m */; };
|
||||
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 */; };
|
||||
141FC1211B222EBB004D5FFB /* IntegrationTestsTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 141FC1201B222EBB004D5FFB /* IntegrationTestsTests.m */; };
|
||||
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 */; };
|
||||
@@ -28,13 +50,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 */;
|
||||
@@ -77,6 +92,13 @@
|
||||
remoteGlobalIDString = 3C86DF461ADF2C930047B81A;
|
||||
remoteInfo = RCTWebSocket;
|
||||
};
|
||||
143BC59B1B21E3E100462512 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 83CBB9F71A601CBA00E9B192 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = 13B07F861A680F5B00A75B9A;
|
||||
remoteInfo = UIExplorer;
|
||||
};
|
||||
147CED4A1AB34F8C00DA3E4C /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 14E0EEC81AB118F7000DECC3 /* RCTActionSheet.xcodeproj */;
|
||||
@@ -122,15 +144,12 @@
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
004D289E1AAF61C70097A701 /* UIExplorerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = UIExplorerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
004D28A11AAF61C70097A701 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
004D28A21AAF61C70097A701 /* UIExplorerTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = UIExplorerTests.m; sourceTree = "<group>"; };
|
||||
004D289E1AAF61C70097A701 /* UIExplorerUnitTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = UIExplorerUnitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
13417FE31AA91428003F314A /* RCTImage.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTImage.xcodeproj; path = ../../Libraries/Image/RCTImage.xcodeproj; sourceTree = "<group>"; };
|
||||
13417FEA1AA914B8003F314A /* RCTText.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTText.xcodeproj; path = ../../Libraries/Text/RCTText.xcodeproj; sourceTree = "<group>"; };
|
||||
134180261AA91779003F314A /* RCTNetwork.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTNetwork.xcodeproj; path = ../../Libraries/Network/RCTNetwork.xcodeproj; sourceTree = "<group>"; };
|
||||
134454551AAFCAAE003F0779 /* RCTAdSupport.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTAdSupport.xcodeproj; path = ../../Libraries/AdSupport/RCTAdSupport.xcodeproj; sourceTree = "<group>"; };
|
||||
134A8A201AACED6A00945AAE /* RCTGeolocation.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTGeolocation.xcodeproj; path = ../../Libraries/Geolocation/RCTGeolocation.xcodeproj; sourceTree = "<group>"; };
|
||||
1353F5451B0E64F9009B4FAC /* ClippingTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ClippingTests.m; sourceTree = "<group>"; };
|
||||
139FDECA1B0651EA00C62182 /* RCTWebSocket.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTWebSocket.xcodeproj; path = ../../Libraries/WebSocket/RCTWebSocket.xcodeproj; sourceTree = "<group>"; };
|
||||
13B07F961A680F5B00A75B9A /* UIExplorer.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = UIExplorer.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = UIExplorer/AppDelegate.h; sourceTree = "<group>"; };
|
||||
@@ -140,7 +159,37 @@
|
||||
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>"; };
|
||||
141FC1201B222EBB004D5FFB /* IntegrationTestsTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IntegrationTestsTests.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>"; };
|
||||
143BC5831B21E18100462512 /* testSwitchExampleSnapshot_1@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "testSwitchExampleSnapshot_1@2x.png"; sourceTree = "<group>"; };
|
||||
143BC5841B21E18100462512 /* testTabBarExampleSnapshot_1@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "testTabBarExampleSnapshot_1@2x.png"; sourceTree = "<group>"; };
|
||||
143BC5851B21E18100462512 /* testTextExampleSnapshot_1@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "testTextExampleSnapshot_1@2x.png"; sourceTree = "<group>"; };
|
||||
143BC5861B21E18100462512 /* testViewExampleSnapshot_1@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "testViewExampleSnapshot_1@2x.png"; sourceTree = "<group>"; };
|
||||
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>"; };
|
||||
@@ -152,6 +201,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;
|
||||
};
|
||||
@@ -174,27 +236,16 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
143BC5921B21E3E100462512 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
004D289F1AAF61C70097A701 /* UIExplorerTests */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
004D28A21AAF61C70097A701 /* UIExplorerTests.m */,
|
||||
1353F5451B0E64F9009B4FAC /* ClippingTests.m */,
|
||||
004D28A01AAF61C70097A701 /* Supporting Files */,
|
||||
);
|
||||
path = UIExplorerTests;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
004D28A01AAF61C70097A701 /* Supporting Files */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
004D28A11AAF61C70097A701 /* Info.plist */,
|
||||
);
|
||||
name = "Supporting Files";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
1316A21D1AA397F400C0188E /* Libraries */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -275,6 +326,65 @@
|
||||
name = UIExplorer;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
143BC57C1B21E18100462512 /* UIExplorerUnitTests */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
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;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
143BC57F1B21E18100462512 /* ReferenceImages */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
143BC5801B21E18100462512 /* Examples-UIExplorer-UIExplorerApp */,
|
||||
);
|
||||
path = ReferenceImages;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
143BC5801B21E18100462512 /* Examples-UIExplorer-UIExplorerApp */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
143BC5811B21E18100462512 /* testLayoutExampleSnapshot_1@2x.png */,
|
||||
143BC5821B21E18100462512 /* testSliderExampleSnapshot_1@2x.png */,
|
||||
143BC5831B21E18100462512 /* testSwitchExampleSnapshot_1@2x.png */,
|
||||
143BC5841B21E18100462512 /* testTabBarExampleSnapshot_1@2x.png */,
|
||||
143BC5851B21E18100462512 /* testTextExampleSnapshot_1@2x.png */,
|
||||
143BC5861B21E18100462512 /* testViewExampleSnapshot_1@2x.png */,
|
||||
);
|
||||
path = "Examples-UIExplorer-UIExplorerApp";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
143BC5961B21E3E100462512 /* UIExplorerIntegrationTests */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
141FC1201B222EBB004D5FFB /* IntegrationTestsTests.m */,
|
||||
143BC5A01B21E45C00462512 /* UIExplorerIntegrationTests.m */,
|
||||
143BC5971B21E3E100462512 /* Supporting Files */,
|
||||
);
|
||||
path = UIExplorerIntegrationTests;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
143BC5971B21E3E100462512 /* Supporting Files */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
143BC5981B21E3E100462512 /* Info.plist */,
|
||||
);
|
||||
name = "Supporting Files";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
147CED471AB34F8C00DA3E4C /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -291,6 +401,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 = (
|
||||
@@ -320,7 +453,9 @@
|
||||
children = (
|
||||
13B07FAE1A68108700A75B9A /* UIExplorer */,
|
||||
1316A21D1AA397F400C0188E /* Libraries */,
|
||||
004D289F1AAF61C70097A701 /* UIExplorerTests */,
|
||||
143BC57C1B21E18100462512 /* UIExplorerUnitTests */,
|
||||
143BC5961B21E3E100462512 /* UIExplorerIntegrationTests */,
|
||||
14D6D6EA1B2205C0001FB087 /* OCMock */,
|
||||
83CBBA001A601CBA00E9B192 /* Products */,
|
||||
);
|
||||
indentWidth = 2;
|
||||
@@ -331,7 +466,8 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
13B07F961A680F5B00A75B9A /* UIExplorer.app */,
|
||||
004D289E1AAF61C70097A701 /* UIExplorerTests.xctest */,
|
||||
004D289E1AAF61C70097A701 /* UIExplorerUnitTests.xctest */,
|
||||
143BC5951B21E3E100462512 /* UIExplorerIntegrationTests.xctest */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
@@ -347,9 +483,9 @@
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
004D289D1AAF61C70097A701 /* UIExplorerTests */ = {
|
||||
004D289D1AAF61C70097A701 /* UIExplorerUnitTests */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 004D28AD1AAF61C70097A701 /* Build configuration list for PBXNativeTarget "UIExplorerTests" */;
|
||||
buildConfigurationList = 004D28AD1AAF61C70097A701 /* Build configuration list for PBXNativeTarget "UIExplorerUnitTests" */;
|
||||
buildPhases = (
|
||||
004D289A1AAF61C70097A701 /* Sources */,
|
||||
004D289B1AAF61C70097A701 /* Frameworks */,
|
||||
@@ -358,11 +494,10 @@
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
004D28A51AAF61C70097A701 /* PBXTargetDependency */,
|
||||
);
|
||||
name = UIExplorerTests;
|
||||
name = UIExplorerUnitTests;
|
||||
productName = UIExplorerTests;
|
||||
productReference = 004D289E1AAF61C70097A701 /* UIExplorerTests.xctest */;
|
||||
productReference = 004D289E1AAF61C70097A701 /* UIExplorerUnitTests.xctest */;
|
||||
productType = "com.apple.product-type.bundle.unit-test";
|
||||
};
|
||||
13B07F861A680F5B00A75B9A /* UIExplorer */ = {
|
||||
@@ -382,6 +517,24 @@
|
||||
productReference = 13B07F961A680F5B00A75B9A /* UIExplorer.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
143BC5941B21E3E100462512 /* UIExplorerIntegrationTests */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 143BC59D1B21E3E100462512 /* Build configuration list for PBXNativeTarget "UIExplorerIntegrationTests" */;
|
||||
buildPhases = (
|
||||
143BC5911B21E3E100462512 /* Sources */,
|
||||
143BC5921B21E3E100462512 /* Frameworks */,
|
||||
143BC5931B21E3E100462512 /* Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
143BC59C1B21E3E100462512 /* PBXTargetDependency */,
|
||||
);
|
||||
name = UIExplorerIntegrationTests;
|
||||
productName = UIExplorerIntegrationTests;
|
||||
productReference = 143BC5951B21E3E100462512 /* UIExplorerIntegrationTests.xctest */;
|
||||
productType = "com.apple.product-type.bundle.unit-test";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
@@ -393,6 +546,9 @@
|
||||
TargetAttributes = {
|
||||
004D289D1AAF61C70097A701 = {
|
||||
CreatedOnToolsVersion = 6.1.1;
|
||||
};
|
||||
143BC5941B21E3E100462512 = {
|
||||
CreatedOnToolsVersion = 6.3.2;
|
||||
TestTargetID = 13B07F861A680F5B00A75B9A;
|
||||
};
|
||||
};
|
||||
@@ -461,7 +617,8 @@
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
13B07F861A680F5B00A75B9A /* UIExplorer */,
|
||||
004D289D1AAF61C70097A701 /* UIExplorerTests */,
|
||||
004D289D1AAF61C70097A701 /* UIExplorerUnitTests */,
|
||||
143BC5941B21E3E100462512 /* UIExplorerIntegrationTests */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
@@ -570,6 +727,13 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
143BC5931B21E3E100462512 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
@@ -577,8 +741,15 @@
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
004D28A31AAF61C70097A701 /* UIExplorerTests.m in Sources */,
|
||||
1353F5461B0E64F9009B4FAC /* 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;
|
||||
};
|
||||
@@ -591,13 +762,22 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
143BC5911B21E3E100462512 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
141FC1211B222EBB004D5FFB /* IntegrationTestsTests.m in Sources */,
|
||||
143BC5A11B21E45C00462512 /* UIExplorerIntegrationTests.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXTargetDependency section */
|
||||
004D28A51AAF61C70097A701 /* PBXTargetDependency */ = {
|
||||
143BC59C1B21E3E100462512 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = 13B07F861A680F5B00A75B9A /* UIExplorer */;
|
||||
targetProxy = 004D28A41AAF61C70097A701 /* PBXContainerItemProxy */;
|
||||
targetProxy = 143BC59B1B21E3E100462512 /* PBXContainerItemProxy */;
|
||||
};
|
||||
/* End PBXTargetDependency section */
|
||||
|
||||
@@ -617,47 +797,59 @@
|
||||
004D28A61AAF61C70097A701 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(SDKROOT)/Developer/Library/Frameworks",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"FB_REFERENCE_IMAGE_DIR=\"\\\"$(SOURCE_ROOT)/$(PROJECT_NAME)Tests/ReferenceImages\\\"\"",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_PREPROCESSOR_DEFINITIONS = "$(inherited)";
|
||||
HEADER_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
|
||||
"$(SRCROOT)/../../React/**",
|
||||
"$(SRCROOT)/UIExplorerUnitTests/**",
|
||||
);
|
||||
INFOPLIST_FILE = UIExplorerTests/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.1;
|
||||
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 = UIExplorerTests/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.1;
|
||||
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;
|
||||
};
|
||||
@@ -698,6 +890,47 @@
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
143BC59E1B21E3E100462512 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(SDKROOT)/Developer/Library/Frameworks",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"$(inherited)",
|
||||
"FB_REFERENCE_IMAGE_DIR=\"\\\"$(SOURCE_ROOT)/$(PROJECT_NAME)IntegrationTests/ReferenceImages\\\"\"",
|
||||
);
|
||||
INFOPLIST_FILE = UIExplorerIntegrationTests/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.3;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/UIExplorer.app/UIExplorer";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
143BC59F1B21E3E100462512 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(SDKROOT)/Developer/Library/Frameworks",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
INFOPLIST_FILE = UIExplorerIntegrationTests/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.3;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/UIExplorer.app/UIExplorer";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
83CBBA201A601CBA00E9B192 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
@@ -787,7 +1020,7 @@
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
004D28AD1AAF61C70097A701 /* Build configuration list for PBXNativeTarget "UIExplorerTests" */ = {
|
||||
004D28AD1AAF61C70097A701 /* Build configuration list for PBXNativeTarget "UIExplorerUnitTests" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
004D28A61AAF61C70097A701 /* Debug */,
|
||||
@@ -805,6 +1038,15 @@
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
143BC59D1B21E3E100462512 /* Build configuration list for PBXNativeTarget "UIExplorerIntegrationTests" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
143BC59E1B21E3E100462512 /* Debug */,
|
||||
143BC59F1B21E3E100462512 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "UIExplorer" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
|
||||
@@ -29,8 +29,22 @@
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "004D289D1AAF61C70097A701"
|
||||
BuildableName = "UIExplorerTests.xctest"
|
||||
BlueprintName = "UIExplorerTests"
|
||||
BuildableName = "UIExplorerUnitTests.xctest"
|
||||
BlueprintName = "UIExplorerUnitTests"
|
||||
ReferencedContainer = "container:UIExplorer.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "NO"
|
||||
buildForArchiving = "NO"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "143BC5941B21E3E100462512"
|
||||
BuildableName = "UIExplorerIntegrationTests.xctest"
|
||||
BlueprintName = "UIExplorerIntegrationTests"
|
||||
ReferencedContainer = "container:UIExplorer.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
@@ -47,8 +61,18 @@
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "004D289D1AAF61C70097A701"
|
||||
BuildableName = "UIExplorerTests.xctest"
|
||||
BlueprintName = "UIExplorerTests"
|
||||
BuildableName = "UIExplorerUnitTests.xctest"
|
||||
BlueprintName = "UIExplorerUnitTests"
|
||||
ReferencedContainer = "container:UIExplorer.xcodeproj">
|
||||
</BuildableReference>
|
||||
</TestableReference>
|
||||
<TestableReference
|
||||
skipped = "NO">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "143BC5941B21E3E100462512"
|
||||
BuildableName = "UIExplorerIntegrationTests.xctest"
|
||||
BlueprintName = "UIExplorerIntegrationTests"
|
||||
ReferencedContainer = "container:UIExplorer.xcodeproj">
|
||||
</BuildableReference>
|
||||
</TestableReference>
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
* on the same Wi-Fi network.
|
||||
*/
|
||||
|
||||
jsCodeLocation = [NSURL URLWithString:@"http://localhost:8081/Examples/UIExplorer/UIExplorerApp.includeRequire.runModule.bundle?dev=true"];
|
||||
jsCodeLocation = [NSURL URLWithString:@"http://localhost:8081/Examples/UIExplorer/UIExplorerApp.ios.includeRequire.runModule.bundle?dev=true"];
|
||||
|
||||
/**
|
||||
* OPTION 2
|
||||
|
||||
125
Examples/UIExplorer/UIExplorerApp.android.js
Normal file
@@ -0,0 +1,125 @@
|
||||
/**
|
||||
* The examples provided by Facebook are for non-commercial testing and
|
||||
* evaluation purposes only.
|
||||
*
|
||||
* Facebook reserves all rights not expressly granted.
|
||||
*
|
||||
* 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 NON INFRINGEMENT. IN NO EVENT SHALL
|
||||
* FACEBOOK 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.
|
||||
*
|
||||
* @providesModule UIExplorerApp
|
||||
* @flow
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var React = require('react-native');
|
||||
var Dimensions = require('Dimensions');
|
||||
var DrawerLayoutAndroid = require('DrawerLayoutAndroid');
|
||||
var ToolbarAndroid = require('ToolbarAndroid');
|
||||
var UIExplorerList = require('./UIExplorerList');
|
||||
var {
|
||||
StyleSheet,
|
||||
View,
|
||||
} = React;
|
||||
|
||||
var DRAWER_WIDTH_LEFT = 56;
|
||||
|
||||
var UIExplorerApp = React.createClass({
|
||||
|
||||
getInitialState: function() {
|
||||
return {
|
||||
example: {
|
||||
title: 'UIExplorer',
|
||||
component: this._renderHome(),
|
||||
},
|
||||
};
|
||||
},
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
<DrawerLayoutAndroid
|
||||
drawerPosition={DrawerLayoutAndroid.positions.Left}
|
||||
drawerWidth={Dimensions.get('window').width - DRAWER_WIDTH_LEFT}
|
||||
ref={(drawer) => { this.drawer = drawer; }}
|
||||
renderNavigationView={this._renderNavigationView}>
|
||||
{this._renderNavigation()}
|
||||
</DrawerLayoutAndroid>
|
||||
);
|
||||
},
|
||||
|
||||
_renderNavigationView: function() {
|
||||
return (
|
||||
<UIExplorerList
|
||||
onSelectExample={this.onSelectExample}
|
||||
isInDrawer={true}
|
||||
/>
|
||||
);
|
||||
},
|
||||
|
||||
onSelectExample: function(example) {
|
||||
this.drawer.closeDrawer();
|
||||
if (example.title === 'UIExplorer') {
|
||||
example.component = this._renderHome();
|
||||
}
|
||||
this.setState({
|
||||
example: {
|
||||
title: example.title,
|
||||
component: example.component,
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
_renderHome: function() {
|
||||
var onSelectExample = this.onSelectExample;
|
||||
return React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
<UIExplorerList
|
||||
onSelectExample={onSelectExample}
|
||||
isInDrawer={false}
|
||||
/>
|
||||
);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
_renderNavigation: function() {
|
||||
var Component = this.state.example.component;
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<ToolbarAndroid
|
||||
logo={require('image!launcher_icon')}
|
||||
navIcon={require('image!ic_menu_black_24dp')}
|
||||
onIconClicked={() => this.drawer.openDrawer()}
|
||||
style={styles.toolbar}
|
||||
title={this.state.example.title}
|
||||
/>
|
||||
<Component />
|
||||
</View>
|
||||
);
|
||||
},
|
||||
|
||||
});
|
||||
|
||||
var styles = StyleSheet.create({
|
||||
messageText: {
|
||||
fontSize: 17,
|
||||
fontWeight: '500',
|
||||
padding: 15,
|
||||
marginTop: 50,
|
||||
marginLeft: 15,
|
||||
},
|
||||
container: {
|
||||
flex: 1,
|
||||
},
|
||||
toolbar: {
|
||||
backgroundColor: '#E9EAED',
|
||||
height: 56,
|
||||
},
|
||||
});
|
||||
|
||||
module.exports = UIExplorerApp;
|
||||
@@ -43,22 +43,22 @@ var UIExplorerApp = React.createClass({
|
||||
/>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<NavigatorIOS
|
||||
style={styles.container}
|
||||
initialRoute={{
|
||||
title: 'UIExplorer',
|
||||
component: UIExplorerList,
|
||||
passProps: {
|
||||
onExternalExampleRequested: (example) => {
|
||||
this.setState({ openExternalExample: example, });
|
||||
},
|
||||
}
|
||||
}}
|
||||
itemWrapperStyle={styles.itemWrapper}
|
||||
tintColor='#008888'
|
||||
/>
|
||||
);
|
||||
return (
|
||||
<NavigatorIOS
|
||||
style={styles.container}
|
||||
initialRoute={{
|
||||
title: 'UIExplorer',
|
||||
component: UIExplorerList,
|
||||
passProps: {
|
||||
onExternalExampleRequested: (example) => {
|
||||
this.setState({ openExternalExample: example, });
|
||||
},
|
||||
}
|
||||
}}
|
||||
itemWrapperStyle={styles.itemWrapper}
|
||||
tintColor="#008888"
|
||||
/>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
24
Examples/UIExplorer/UIExplorerIntegrationTests/Info.plist
Normal file
@@ -0,0 +1,24 @@
|
||||
<?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>com.facebook.React.$(PRODUCT_NAME:rfc1034identifier)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>BNDL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -0,0 +1,101 @@
|
||||
/**
|
||||
* 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 <RCTTest/RCTTestRunner.h>
|
||||
|
||||
#import "RCTAssert.h"
|
||||
|
||||
@interface IntegrationTestsTests : XCTestCase
|
||||
|
||||
@end
|
||||
|
||||
@implementation IntegrationTestsTests
|
||||
{
|
||||
RCTTestRunner *_runner;
|
||||
}
|
||||
|
||||
- (void)setUp
|
||||
{
|
||||
#ifdef __LP64__
|
||||
RCTAssert(!__LP64__, @"Tests should be run on 32-bit device simulators (e.g. iPhone 5)");
|
||||
#endif
|
||||
NSString *version = [[UIDevice currentDevice] systemVersion];
|
||||
RCTAssert([version integerValue] == 8, @"Tests should be run on iOS 8.x, found %@", version);
|
||||
_runner = RCTInitRunnerForApp(@"Examples/UIExplorer/UIExplorerIntegrationTests/js/IntegrationTestsApp");
|
||||
|
||||
// If tests have changes, set recordMode = YES below and run the affected
|
||||
// tests on an iPhone5, iOS 8.3 simulator.
|
||||
_runner.recordMode = NO;
|
||||
}
|
||||
|
||||
#pragma mark Logic Tests
|
||||
|
||||
- (void)testTheTester
|
||||
{
|
||||
[_runner runTest:_cmd module:@"IntegrationTestHarnessTest"];
|
||||
}
|
||||
|
||||
- (void)testTheTester_waitOneFrame
|
||||
{
|
||||
[_runner runTest:_cmd
|
||||
module:@"IntegrationTestHarnessTest"
|
||||
initialProps:@{@"waitOneFrame": @YES}
|
||||
expectErrorBlock:nil];
|
||||
}
|
||||
|
||||
// TODO: this seems to stall forever - figure out why
|
||||
- (void)DISABLED_testTheTester_ExpectError
|
||||
{
|
||||
[_runner runTest:_cmd
|
||||
module:@"IntegrationTestHarnessTest"
|
||||
initialProps:@{@"shouldThrow": @YES}
|
||||
expectErrorRegex:@"because shouldThrow"];
|
||||
}
|
||||
|
||||
- (void)testTimers
|
||||
{
|
||||
[_runner runTest:_cmd module:@"TimersTest"];
|
||||
}
|
||||
|
||||
- (void)testAsyncStorage
|
||||
{
|
||||
[_runner runTest:_cmd module:@"AsyncStorageTest"];
|
||||
}
|
||||
|
||||
- (void)DISABLED_testLayoutEvents // #7149037
|
||||
{
|
||||
[_runner runTest:_cmd module:@"LayoutEventsTest"];
|
||||
}
|
||||
|
||||
- (void)testAppEvents
|
||||
{
|
||||
[_runner runTest:_cmd module:@"AppEventsTest"];
|
||||
}
|
||||
|
||||
- (void)testPromises
|
||||
{
|
||||
[_runner runTest:_cmd module:@"PromiseTest"];
|
||||
}
|
||||
|
||||
#pragma mark Snapshot Tests
|
||||
|
||||
- (void)testSimpleSnapshot
|
||||
{
|
||||
[_runner runTest:_cmd module:@"SimpleSnapshotTest"];
|
||||
}
|
||||
|
||||
- (void)testZZZ_NotInRecordMode
|
||||
{
|
||||
RCTAssert(_runner.recordMode == NO, @"Don't forget to turn record mode back to NO before commit.");
|
||||
}
|
||||
|
||||
@end
|
||||
|
Before Width: | Height: | Size: 72 KiB After Width: | Height: | Size: 72 KiB |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 87 KiB After Width: | Height: | Size: 87 KiB |
|
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 269 KiB After Width: | Height: | Size: 269 KiB |
|
Before Width: | Height: | Size: 86 KiB After Width: | Height: | Size: 86 KiB |
|
After Width: | Height: | Size: 56 KiB |
@@ -39,7 +39,7 @@
|
||||
#endif
|
||||
NSString *version = [[UIDevice currentDevice] systemVersion];
|
||||
RCTAssert([version isEqualToString:@"8.3"], @"Snapshot tests should be run on iOS 8.3, found %@", version);
|
||||
_runner = RCTInitRunnerForApp(@"Examples/UIExplorer/UIExplorerApp");
|
||||
_runner = RCTInitRunnerForApp(@"Examples/UIExplorer/UIExplorerApp.ios");
|
||||
|
||||
// If tests have changes, set recordMode = YES below and run the affected
|
||||
// tests on an iPhone5, iOS 8.1 simulator.
|
||||
@@ -0,0 +1,62 @@
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @providesModule AppEventsTest
|
||||
* @flow
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var React = require('react-native');
|
||||
var {
|
||||
NativeAppEventEmitter,
|
||||
NativeModules,
|
||||
StyleSheet,
|
||||
Text,
|
||||
View,
|
||||
} = React;
|
||||
var TestModule = NativeModules.TestModule || NativeModules.SnapshotTestManager;
|
||||
|
||||
var deepDiffer = require('deepDiffer');
|
||||
|
||||
var TEST_PAYLOAD = {foo: 'bar'};
|
||||
|
||||
var AppEventsTest = React.createClass({
|
||||
getInitialState: function() {
|
||||
return {sent: 'none', received: 'none'};
|
||||
},
|
||||
componentDidMount: function() {
|
||||
NativeAppEventEmitter.addListener('testEvent', this.receiveEvent);
|
||||
var event = {data: TEST_PAYLOAD, ts: Date.now()};
|
||||
TestModule.sendAppEvent('testEvent', event);
|
||||
this.setState({sent: event});
|
||||
},
|
||||
receiveEvent: function(event: any) {
|
||||
if (deepDiffer(event.data, TEST_PAYLOAD)) {
|
||||
throw new Error('Received wrong event: ' + JSON.stringify(event));
|
||||
}
|
||||
var elapsed = (Date.now() - event.ts) + 'ms';
|
||||
this.setState({received: event, elapsed}, TestModule.markTestCompleted);
|
||||
},
|
||||
render: function() {
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<Text>
|
||||
{JSON.stringify(this.state, null, ' ')}
|
||||
</Text>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var styles = StyleSheet.create({
|
||||
container: {
|
||||
margin: 40,
|
||||
},
|
||||
});
|
||||
|
||||
module.exports = AppEventsTest;
|
||||
@@ -0,0 +1,176 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var RCTTestModule = require('NativeModules').TestModule;
|
||||
var React = require('react-native');
|
||||
var {
|
||||
AsyncStorage,
|
||||
Text,
|
||||
View,
|
||||
} = React;
|
||||
|
||||
var deepDiffer = require('deepDiffer');
|
||||
|
||||
var DEBUG = false;
|
||||
|
||||
var KEY_1 = 'key_1';
|
||||
var VAL_1 = 'val_1';
|
||||
var KEY_2 = 'key_2';
|
||||
var VAL_2 = 'val_2';
|
||||
var KEY_MERGE = 'key_merge';
|
||||
var VAL_MERGE_1 = {'foo': 1, 'bar': {'hoo': 1, 'boo': 1}, 'moo': {'a': 3}};
|
||||
var VAL_MERGE_2 = {'bar': {'hoo': 2}, 'baz': 2, 'moo': {'a': 3}};
|
||||
var VAL_MERGE_EXPECT =
|
||||
{'foo': 1, 'bar': {'hoo': 2, 'boo': 1}, 'baz': 2, 'moo': {'a': 3}};
|
||||
|
||||
// setup in componentDidMount
|
||||
var done;
|
||||
var updateMessage;
|
||||
|
||||
function runTestCase(description, fn) {
|
||||
updateMessage(description);
|
||||
fn();
|
||||
}
|
||||
|
||||
function expectTrue(condition, message) {
|
||||
if (!condition) {
|
||||
throw new Error(message);
|
||||
}
|
||||
}
|
||||
|
||||
function expectEqual(lhs, rhs, testname) {
|
||||
expectTrue(
|
||||
!deepDiffer(lhs, rhs),
|
||||
'Error in test ' + testname + ': expected\n' + JSON.stringify(rhs) +
|
||||
'\ngot\n' + JSON.stringify(lhs)
|
||||
);
|
||||
}
|
||||
|
||||
function expectAsyncNoError(err) {
|
||||
expectTrue(err === null, 'Unexpected Async error: ' + JSON.stringify(err));
|
||||
}
|
||||
|
||||
function testSetAndGet() {
|
||||
AsyncStorage.setItem(KEY_1, VAL_1, (err1) => {
|
||||
expectAsyncNoError(err1);
|
||||
AsyncStorage.getItem(KEY_1, (err2, result) => {
|
||||
expectAsyncNoError(err2);
|
||||
expectEqual(result, VAL_1, 'testSetAndGet setItem');
|
||||
updateMessage('get(key_1) correctly returned ' + result);
|
||||
runTestCase('should get null for missing key', testMissingGet);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function testMissingGet() {
|
||||
AsyncStorage.getItem(KEY_2, (err, result) => {
|
||||
expectAsyncNoError(err);
|
||||
expectEqual(result, null, 'testMissingGet');
|
||||
updateMessage('missing get(key_2) correctly returned ' + result);
|
||||
runTestCase('check set twice results in a single key', testSetTwice);
|
||||
});
|
||||
}
|
||||
|
||||
function testSetTwice() {
|
||||
AsyncStorage.setItem(KEY_1, VAL_1, ()=>{
|
||||
AsyncStorage.setItem(KEY_1, VAL_1, ()=>{
|
||||
AsyncStorage.getItem(KEY_1, (err, result) => {
|
||||
expectAsyncNoError(err);
|
||||
expectEqual(result, VAL_1, 'testSetTwice');
|
||||
updateMessage('setTwice worked as expected');
|
||||
runTestCase('test removeItem', testRemoveItem);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function testRemoveItem() {
|
||||
AsyncStorage.setItem(KEY_1, VAL_1, ()=>{
|
||||
AsyncStorage.setItem(KEY_2, VAL_2, ()=>{
|
||||
AsyncStorage.getAllKeys((err, result) => {
|
||||
expectAsyncNoError(err);
|
||||
expectTrue(
|
||||
result.indexOf(KEY_1) >= 0 && result.indexOf(KEY_2) >= 0,
|
||||
'Missing KEY_1 or KEY_2 in ' + '(' + result + ')'
|
||||
);
|
||||
updateMessage('testRemoveItem - add two items');
|
||||
AsyncStorage.removeItem(KEY_1, (err2) => {
|
||||
expectAsyncNoError(err2);
|
||||
updateMessage('delete successful ');
|
||||
AsyncStorage.getItem(KEY_1, (err3, result2) => {
|
||||
expectAsyncNoError(err3);
|
||||
expectEqual(
|
||||
result2,
|
||||
null,
|
||||
'testRemoveItem: key_1 present after delete'
|
||||
);
|
||||
updateMessage('key properly removed ');
|
||||
AsyncStorage.getAllKeys((err4, result3) => {
|
||||
expectAsyncNoError(err4);
|
||||
expectTrue(
|
||||
result3.indexOf(KEY_1) === -1,
|
||||
'Unexpected: KEY_1 present in ' + result3
|
||||
);
|
||||
updateMessage('proper length returned.');
|
||||
runTestCase('should merge values', testMerge);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function testMerge() {
|
||||
AsyncStorage.setItem(KEY_MERGE, JSON.stringify(VAL_MERGE_1), (err1) => {
|
||||
expectAsyncNoError(err1);
|
||||
AsyncStorage.mergeItem(KEY_MERGE, JSON.stringify(VAL_MERGE_2), (err2) => {
|
||||
expectAsyncNoError(err2);
|
||||
AsyncStorage.getItem(KEY_MERGE, (err3, result) => {
|
||||
expectAsyncNoError(err3);
|
||||
expectEqual(JSON.parse(result), VAL_MERGE_EXPECT, 'testMerge');
|
||||
updateMessage('objects deeply merged\nDone!');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
var AsyncStorageTest = React.createClass({
|
||||
getInitialState() {
|
||||
return {
|
||||
messages: 'Initializing...',
|
||||
done: false,
|
||||
};
|
||||
},
|
||||
|
||||
componentDidMount() {
|
||||
done = () => this.setState({done: true}, RCTTestModule.markTestCompleted);
|
||||
updateMessage = (msg) => {
|
||||
this.setState({messages: this.state.messages.concat('\n' + msg)});
|
||||
DEBUG && console.log(msg);
|
||||
};
|
||||
AsyncStorage.clear(testSetAndGet);
|
||||
},
|
||||
|
||||
render() {
|
||||
return (
|
||||
<View style={{backgroundColor: 'white', padding: 40}}>
|
||||
<Text>
|
||||
{this.constructor.displayName + ': '}
|
||||
{this.state.done ? 'Done' : 'Testing...'}
|
||||
{'\n\n' + this.state.messages}
|
||||
</Text>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = AsyncStorageTest;
|
||||
@@ -0,0 +1,62 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var RCTTestModule = require('NativeModules').TestModule;
|
||||
var React = require('react-native');
|
||||
var {
|
||||
Text,
|
||||
View,
|
||||
} = React;
|
||||
|
||||
var IntegrationTestHarnessTest = React.createClass({
|
||||
propTypes: {
|
||||
shouldThrow: React.PropTypes.bool,
|
||||
waitOneFrame: React.PropTypes.bool,
|
||||
},
|
||||
|
||||
getInitialState() {
|
||||
return {
|
||||
done: false,
|
||||
};
|
||||
},
|
||||
|
||||
componentDidMount() {
|
||||
if (this.props.waitOneFrame) {
|
||||
requestAnimationFrame(this.runTest);
|
||||
} else {
|
||||
this.runTest();
|
||||
}
|
||||
},
|
||||
|
||||
runTest() {
|
||||
if (this.props.shouldThrow) {
|
||||
throw new Error('Throwing error because shouldThrow');
|
||||
}
|
||||
if (!RCTTestModule) {
|
||||
throw new Error('RCTTestModule is not registered.');
|
||||
} else if (!RCTTestModule.markTestCompleted) {
|
||||
throw new Error('RCTTestModule.markTestCompleted not defined.');
|
||||
}
|
||||
this.setState({done: true}, RCTTestModule.markTestCompleted);
|
||||
},
|
||||
|
||||
render() {
|
||||
return (
|
||||
<View style={{backgroundColor: 'white', padding: 40}}>
|
||||
<Text>
|
||||
{this.constructor.displayName + ': '}
|
||||
{this.state.done ? 'Done' : 'Testing...'}
|
||||
</Text>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = IntegrationTestHarnessTest;
|
||||
@@ -0,0 +1,95 @@
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @providesModule IntegrationTestsApp
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var React = require('react-native');
|
||||
|
||||
var {
|
||||
AppRegistry,
|
||||
ScrollView,
|
||||
StyleSheet,
|
||||
Text,
|
||||
TouchableOpacity,
|
||||
View,
|
||||
} = React;
|
||||
|
||||
var TESTS = [
|
||||
require('./IntegrationTestHarnessTest'),
|
||||
require('./TimersTest'),
|
||||
require('./AsyncStorageTest'),
|
||||
require('./LayoutEventsTest'),
|
||||
require('./AppEventsTest'),
|
||||
require('./SimpleSnapshotTest'),
|
||||
require('./PromiseTest'),
|
||||
];
|
||||
|
||||
TESTS.forEach(
|
||||
(test) => AppRegistry.registerComponent(test.displayName, () => test)
|
||||
);
|
||||
|
||||
var IntegrationTestsApp = React.createClass({
|
||||
getInitialState: function() {
|
||||
return {
|
||||
test: null,
|
||||
};
|
||||
},
|
||||
render: function() {
|
||||
if (this.state.test) {
|
||||
return (
|
||||
<ScrollView>
|
||||
<this.state.test />
|
||||
</ScrollView>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<Text style={styles.row}>
|
||||
Click on a test to run it in this shell for easier debugging and
|
||||
development. Run all tests in the testing envirnment with cmd+U in
|
||||
Xcode.
|
||||
</Text>
|
||||
<View style={styles.separator} />
|
||||
<ScrollView>
|
||||
{TESTS.map((test) => [
|
||||
<TouchableOpacity onPress={() => this.setState({test})}>
|
||||
<View style={styles.row}>
|
||||
<Text style={styles.testName}>
|
||||
{test.displayName}
|
||||
</Text>
|
||||
</View>
|
||||
</TouchableOpacity>,
|
||||
<View style={styles.separator} />
|
||||
])}
|
||||
</ScrollView>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var styles = StyleSheet.create({
|
||||
container: {
|
||||
backgroundColor: 'white',
|
||||
marginTop: 40,
|
||||
margin: 15,
|
||||
},
|
||||
row: {
|
||||
padding: 10,
|
||||
},
|
||||
testName: {
|
||||
fontWeight: '500',
|
||||
},
|
||||
separator: {
|
||||
height: 1,
|
||||
backgroundColor: '#bbbbbb',
|
||||
},
|
||||
});
|
||||
|
||||
AppRegistry.registerComponent('IntegrationTestsApp', () => IntegrationTestsApp);
|
||||
@@ -0,0 +1,167 @@
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @providesModule LayoutEventsTest
|
||||
* @flow
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var React = require('react-native');
|
||||
var {
|
||||
Image,
|
||||
LayoutAnimation,
|
||||
NativeModules,
|
||||
StyleSheet,
|
||||
Text,
|
||||
View,
|
||||
} = React;
|
||||
var TestModule = NativeModules.TestModule || NativeModules.SnapshotTestManager;
|
||||
|
||||
var deepDiffer = require('deepDiffer');
|
||||
|
||||
function debug() {
|
||||
//console.log.apply(null, arguments);
|
||||
}
|
||||
|
||||
type LayoutEvent = {
|
||||
nativeEvent: {
|
||||
layout: {
|
||||
x: number;
|
||||
y: number;
|
||||
width: number;
|
||||
height: number;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
var LayoutEventsTest = React.createClass({
|
||||
getInitialState: function() {
|
||||
return {
|
||||
didAnimation: false,
|
||||
};
|
||||
},
|
||||
animateViewLayout: function() {
|
||||
LayoutAnimation.configureNext(
|
||||
LayoutAnimation.Presets.spring,
|
||||
() => {
|
||||
debug('layout animation done.');
|
||||
this.checkLayout(this.addWrapText);
|
||||
},
|
||||
(error) => { throw new Error(JSON.stringify(error)); }
|
||||
);
|
||||
this.setState({viewStyle: {margin: 60}});
|
||||
},
|
||||
addWrapText: function() {
|
||||
this.setState(
|
||||
{extraText: ' And a bunch more text to wrap around a few lines.'},
|
||||
() => this.checkLayout(this.changeContainer)
|
||||
);
|
||||
},
|
||||
changeContainer: function() {
|
||||
this.setState(
|
||||
{containerStyle: {width: 280}},
|
||||
() => this.checkLayout(TestModule.markTestCompleted)
|
||||
);
|
||||
},
|
||||
checkLayout: function(next?: ?Function) {
|
||||
if (!this.isMounted()) {
|
||||
return;
|
||||
}
|
||||
this.refs.view.measure((x, y, width, height) => {
|
||||
this.compare('view', {x, y, width, height}, this.state.viewLayout);
|
||||
if (typeof next === 'function') {
|
||||
next();
|
||||
} else if (!this.state.didAnimation) {
|
||||
// Trigger first state change after onLayout fires
|
||||
this.animateViewLayout();
|
||||
this.state.didAnimation = true;
|
||||
}
|
||||
});
|
||||
this.refs.txt.measure((x, y, width, height) => {
|
||||
this.compare('txt', {x, y, width, height}, this.state.textLayout);
|
||||
});
|
||||
this.refs.img.measure((x, y, width, height) => {
|
||||
this.compare('img', {x, y, width, height}, this.state.imageLayout);
|
||||
});
|
||||
},
|
||||
compare: function(node: string, measured: any, onLayout: any): void {
|
||||
if (deepDiffer(measured, onLayout)) {
|
||||
var data = {measured, onLayout};
|
||||
throw new Error(
|
||||
node + ' onLayout mismatch with measure ' +
|
||||
JSON.stringify(data, null, ' ')
|
||||
);
|
||||
}
|
||||
},
|
||||
onViewLayout: function(e: LayoutEvent) {
|
||||
debug('received view layout event\n', e.nativeEvent);
|
||||
this.setState({viewLayout: e.nativeEvent.layout}, this.checkLayout);
|
||||
},
|
||||
onTextLayout: function(e: LayoutEvent) {
|
||||
debug('received text layout event\n', e.nativeEvent);
|
||||
this.setState({textLayout: e.nativeEvent.layout}, this.checkLayout);
|
||||
},
|
||||
onImageLayout: function(e: LayoutEvent) {
|
||||
debug('received image layout event\n', e.nativeEvent);
|
||||
this.setState({imageLayout: e.nativeEvent.layout}, this.checkLayout);
|
||||
},
|
||||
render: function() {
|
||||
var viewStyle = [styles.view, this.state.viewStyle];
|
||||
var textLayout = this.state.textLayout || {width: '?', height: '?'};
|
||||
var imageLayout = this.state.imageLayout || {x: '?', y: '?'};
|
||||
return (
|
||||
<View style={[styles.container, this.state.containerStyle]}>
|
||||
<View ref="view" onLayout={this.onViewLayout} style={viewStyle}>
|
||||
<Image
|
||||
ref="img"
|
||||
onLayout={this.onImageLayout}
|
||||
style={styles.image}
|
||||
source={{uri: 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851561_767334496626293_1958532586_n.png'}}
|
||||
/>
|
||||
<Text>
|
||||
ViewLayout: {JSON.stringify(this.state.viewLayout, null, ' ') + '\n\n'}
|
||||
</Text>
|
||||
<Text ref="txt" onLayout={this.onTextLayout} style={styles.text}>
|
||||
A simple piece of text.{this.state.extraText}
|
||||
</Text>
|
||||
<Text>
|
||||
{'\n'}
|
||||
Text w/h: {textLayout.width}/{textLayout.height + '\n'}
|
||||
Image x/y: {imageLayout.x}/{imageLayout.y}
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var styles = StyleSheet.create({
|
||||
container: {
|
||||
margin: 40,
|
||||
},
|
||||
view: {
|
||||
margin: 20,
|
||||
padding: 12,
|
||||
borderColor: 'black',
|
||||
borderWidth: 0.5,
|
||||
backgroundColor: 'transparent',
|
||||
},
|
||||
text: {
|
||||
alignSelf: 'flex-start',
|
||||
borderColor: 'rgba(0, 0, 255, 0.2)',
|
||||
borderWidth: 0.5,
|
||||
},
|
||||
image: {
|
||||
width: 50,
|
||||
height: 50,
|
||||
marginBottom: 10,
|
||||
alignSelf: 'center',
|
||||
},
|
||||
});
|
||||
|
||||
module.exports = LayoutEventsTest;
|
||||
@@ -0,0 +1,50 @@
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @providesModule PromiseTest
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var RCTTestModule = require('NativeModules').TestModule;
|
||||
var React = require('react-native');
|
||||
|
||||
var PromiseTest = React.createClass({
|
||||
|
||||
shouldResolve: false,
|
||||
shouldReject: false,
|
||||
|
||||
componentDidMount() {
|
||||
Promise.all([
|
||||
this.testShouldResolve(),
|
||||
this.testShouldReject(),
|
||||
]).then(() => RCTTestModule.finish(
|
||||
this.shouldResolve && this.shouldReject
|
||||
));
|
||||
},
|
||||
|
||||
testShouldResolve() {
|
||||
return RCTTestModule
|
||||
.shouldResolve()
|
||||
.then(() => this.shouldResolve = true)
|
||||
.catch(() => this.shouldResolve = false);
|
||||
},
|
||||
|
||||
testShouldReject() {
|
||||
return RCTTestModule
|
||||
.shouldReject()
|
||||
.then(() => this.shouldReject = false)
|
||||
.catch(() => this.shouldReject = true);
|
||||
},
|
||||
|
||||
render() {
|
||||
return <React.View />;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
module.exports = PromiseTest;
|
||||
@@ -0,0 +1,56 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var React = require('react-native');
|
||||
var {
|
||||
StyleSheet,
|
||||
View,
|
||||
} = React;
|
||||
|
||||
var { TestModule } = React.addons;
|
||||
|
||||
var SimpleSnapshotTest = React.createClass({
|
||||
componentDidMount() {
|
||||
if (!TestModule.verifySnapshot) {
|
||||
throw new Error('TestModule.verifySnapshot not defined.');
|
||||
}
|
||||
requestAnimationFrame(() => TestModule.verifySnapshot(this.done));
|
||||
},
|
||||
|
||||
done() {
|
||||
TestModule.markTestCompleted();
|
||||
},
|
||||
|
||||
render() {
|
||||
return (
|
||||
<View style={{backgroundColor: 'white', padding: 100}}>
|
||||
<View style={styles.box1} />
|
||||
<View style={styles.box2} />
|
||||
</View>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var styles = StyleSheet.create({
|
||||
box1: {
|
||||
width: 80,
|
||||
height: 50,
|
||||
backgroundColor: 'red',
|
||||
},
|
||||
box2: {
|
||||
top: -10,
|
||||
left: 20,
|
||||
width: 70,
|
||||
height: 90,
|
||||
backgroundColor: 'blue',
|
||||
},
|
||||
});
|
||||
|
||||
module.exports = SimpleSnapshotTest;
|
||||
155
Examples/UIExplorer/UIExplorerIntegrationTests/js/TimersTest.js
Normal file
@@ -0,0 +1,155 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var RCTTestModule = require('NativeModules').TestModule;
|
||||
var React = require('react-native');
|
||||
var {
|
||||
StyleSheet,
|
||||
Text,
|
||||
View,
|
||||
} = React;
|
||||
var TimerMixin = require('react-timer-mixin');
|
||||
|
||||
var TimersTest = React.createClass({
|
||||
mixins: [TimerMixin],
|
||||
|
||||
getInitialState() {
|
||||
return {
|
||||
count: 0,
|
||||
done: false,
|
||||
};
|
||||
},
|
||||
|
||||
componentDidMount() {
|
||||
this.testSetTimeout0();
|
||||
},
|
||||
|
||||
testSetTimeout0() {
|
||||
this.setTimeout(this.testSetTimeout1, 0);
|
||||
},
|
||||
|
||||
testSetTimeout1() {
|
||||
this.setTimeout(this.testSetTimeout50, 1);
|
||||
},
|
||||
|
||||
testSetTimeout50() {
|
||||
this.setTimeout(this.testRequestAnimationFrame, 50);
|
||||
},
|
||||
|
||||
testRequestAnimationFrame() {
|
||||
this.requestAnimationFrame(this.testSetInterval0);
|
||||
},
|
||||
|
||||
testSetInterval0() {
|
||||
this._nextTest = this.testSetInterval20;
|
||||
this._interval = this.setInterval(this._incrementInterval, 0);
|
||||
},
|
||||
|
||||
testSetInterval20() {
|
||||
this._nextTest = this.testSetImmediate;
|
||||
this._interval = this.setInterval(this._incrementInterval, 20);
|
||||
},
|
||||
|
||||
testSetImmediate() {
|
||||
this.setImmediate(this.testClearTimeout0);
|
||||
},
|
||||
|
||||
testClearTimeout0() {
|
||||
var timeout = this.setTimeout(() => this._fail('testClearTimeout0'), 0);
|
||||
this.clearTimeout(timeout);
|
||||
this.testClearTimeout30();
|
||||
},
|
||||
|
||||
testClearTimeout30() {
|
||||
var timeout = this.setTimeout(() => this._fail('testClearTimeout30'), 30);
|
||||
this.clearTimeout(timeout);
|
||||
this.setTimeout(this.testClearMulti, 50);
|
||||
},
|
||||
|
||||
testClearMulti() {
|
||||
var fails = [this.setTimeout(() => this._fail('testClearMulti-1'), 20)];
|
||||
fails.push(this.setTimeout(() => this._fail('testClearMulti-2'), 50));
|
||||
var delayClear = this.setTimeout(() => this._fail('testClearMulti-3'), 50);
|
||||
fails.push(this.setTimeout(() => this._fail('testClearMulti-4'), 0));
|
||||
|
||||
this.setTimeout(this.testOrdering, 100); // Next test interleaved
|
||||
|
||||
fails.push(this.setTimeout(() => this._fail('testClearMulti-5'), 10));
|
||||
|
||||
fails.forEach((timeout) => this.clearTimeout(timeout));
|
||||
this.setTimeout(() => this.clearTimeout(delayClear), 20);
|
||||
},
|
||||
|
||||
testOrdering() {
|
||||
// Clear timers are set first because it's more likely to uncover bugs.
|
||||
var fail0;
|
||||
this.setImmediate(() => this.clearTimeout(fail0));
|
||||
fail0 = this.setTimeout(
|
||||
() => this._fail('testOrdering-t0, setImmediate should happen before ' +
|
||||
'setTimeout 0'),
|
||||
0
|
||||
);
|
||||
var failAnim; // This should fail without the t=0 fastpath feature.
|
||||
this.setTimeout(() => this.cancelAnimationFrame(failAnim), 0);
|
||||
failAnim = this.requestAnimationFrame(
|
||||
() => this._fail('testOrdering-Anim, setTimeout 0 should happen before ' +
|
||||
'requestAnimationFrame')
|
||||
);
|
||||
var fail50;
|
||||
this.setTimeout(() => this.clearTimeout(fail50), 20);
|
||||
fail50 = this.setTimeout(
|
||||
() => this._fail('testOrdering-t50, setTimeout 20 should happen before ' +
|
||||
'setTimeout 50'),
|
||||
50
|
||||
);
|
||||
this.setTimeout(this.done, 75);
|
||||
},
|
||||
|
||||
done() {
|
||||
this.setState({done: true}, RCTTestModule.markTestCompleted);
|
||||
},
|
||||
|
||||
render() {
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<Text>
|
||||
{this.constructor.displayName + ': \n'}
|
||||
Intervals: {this.state.count + '\n'}
|
||||
{this.state.done ? 'Done' : 'Testing...'}
|
||||
</Text>
|
||||
</View>
|
||||
);
|
||||
},
|
||||
|
||||
_incrementInterval() {
|
||||
if (this.state.count > 3) {
|
||||
throw new Error('interval incremented past end.');
|
||||
}
|
||||
if (this.state.count === 3) {
|
||||
this.clearInterval(this._interval);
|
||||
this.setState({count: 0}, this._nextTest);
|
||||
return;
|
||||
}
|
||||
this.setState({count: this.state.count + 1});
|
||||
},
|
||||
|
||||
_fail(caller) {
|
||||
throw new Error('_fail called by ' + caller);
|
||||
},
|
||||
});
|
||||
|
||||
var styles = StyleSheet.create({
|
||||
container: {
|
||||
backgroundColor: 'white',
|
||||
padding: 40,
|
||||
},
|
||||
});
|
||||
|
||||
module.exports = TimersTest;
|
||||
@@ -20,6 +20,7 @@ var {
|
||||
AppRegistry,
|
||||
ListView,
|
||||
PixelRatio,
|
||||
Platform,
|
||||
StyleSheet,
|
||||
Text,
|
||||
TextInput,
|
||||
@@ -34,51 +35,67 @@ import type { ExampleModule } from 'ExampleTypes';
|
||||
|
||||
var createExamplePage = require('./createExamplePage');
|
||||
|
||||
var COMPONENTS = [
|
||||
require('./ActivityIndicatorIOSExample'),
|
||||
require('./DatePickerIOSExample'),
|
||||
require('./ImageExample'),
|
||||
require('./ListViewExample'),
|
||||
require('./ListViewPagingExample'),
|
||||
require('./MapViewExample'),
|
||||
require('./Navigator/NavigatorExample'),
|
||||
require('./NavigatorIOSColorsExample'),
|
||||
require('./NavigatorIOSExample'),
|
||||
require('./PickerIOSExample'),
|
||||
require('./ProgressViewIOSExample'),
|
||||
require('./ScrollViewExample'),
|
||||
require('./SegmentedControlIOSExample'),
|
||||
require('./SliderIOSExample'),
|
||||
require('./SwitchIOSExample'),
|
||||
require('./TabBarIOSExample'),
|
||||
require('./TextExample.ios'),
|
||||
require('./TextInputExample'),
|
||||
require('./TouchableExample'),
|
||||
var COMMON_COMPONENTS = [
|
||||
require('./ViewExample'),
|
||||
require('./WebViewExample'),
|
||||
];
|
||||
|
||||
var APIS = [
|
||||
require('./AccessibilityIOSExample'),
|
||||
require('./ActionSheetIOSExample'),
|
||||
require('./AdSupportIOSExample'),
|
||||
require('./AlertIOSExample'),
|
||||
require('./AppStateIOSExample'),
|
||||
require('./AsyncStorageExample'),
|
||||
require('./BorderExample'),
|
||||
require('./CameraRollExample.ios'),
|
||||
var COMMON_APIS = [
|
||||
require('./GeolocationExample'),
|
||||
require('./LayoutEventsExample'),
|
||||
require('./LayoutExample'),
|
||||
require('./NetInfoExample'),
|
||||
require('./PanResponderExample'),
|
||||
require('./PointerEventsExample'),
|
||||
require('./PushNotificationIOSExample'),
|
||||
require('./StatusBarIOSExample'),
|
||||
require('./TimerExample'),
|
||||
require('./VibrationIOSExample'),
|
||||
];
|
||||
|
||||
if (Platform.OS === 'ios') {
|
||||
var COMPONENTS = COMMON_COMPONENTS.concat([
|
||||
require('./ActivityIndicatorIOSExample'),
|
||||
require('./DatePickerIOSExample'),
|
||||
require('./ImageExample'),
|
||||
require('./ListViewExample'),
|
||||
require('./ListViewPagingExample'),
|
||||
require('./MapViewExample'),
|
||||
require('./Navigator/NavigatorExample'),
|
||||
require('./NavigatorIOSColorsExample'),
|
||||
require('./NavigatorIOSExample'),
|
||||
require('./PickerIOSExample'),
|
||||
require('./ProgressViewIOSExample'),
|
||||
require('./ScrollViewExample'),
|
||||
require('./SegmentedControlIOSExample'),
|
||||
require('./SliderIOSExample'),
|
||||
require('./SwitchIOSExample'),
|
||||
require('./TabBarIOSExample'),
|
||||
require('./TextExample.ios'),
|
||||
require('./TextInputExample'),
|
||||
require('./TouchableExample'),
|
||||
]);
|
||||
|
||||
var APIS = COMMON_APIS.concat([
|
||||
require('./AccessibilityIOSExample'),
|
||||
require('./ActionSheetIOSExample'),
|
||||
require('./AdSupportIOSExample'),
|
||||
require('./AlertIOSExample'),
|
||||
require('./AppStateIOSExample'),
|
||||
require('./AsyncStorageExample'),
|
||||
require('./BorderExample'),
|
||||
require('./CameraRollExample.ios'),
|
||||
require('./LayoutEventsExample'),
|
||||
require('./NetInfoExample'),
|
||||
require('./PointerEventsExample'),
|
||||
require('./PushNotificationIOSExample'),
|
||||
require('./StatusBarIOSExample'),
|
||||
require('./TimerExample'),
|
||||
require('./VibrationIOSExample'),
|
||||
require('./XHRExample'),
|
||||
]);
|
||||
|
||||
} else if (Platform.OS === 'android') {
|
||||
var COMPONENTS = COMMON_COMPONENTS.concat([
|
||||
]);
|
||||
|
||||
var APIS = COMMON_APIS.concat([
|
||||
]);
|
||||
}
|
||||
|
||||
var ds = new ListView.DataSource({
|
||||
rowHasChanged: (r1, r2) => r1 !== r2,
|
||||
sectionHeaderHasChanged: (h1, h2) => h1 !== h2,
|
||||
@@ -114,10 +131,10 @@ COMPONENTS.concat(APIS).forEach((Example) => {
|
||||
type Props = {
|
||||
navigator: Array<{title: string, component: ReactClass<any,any,any>}>,
|
||||
onExternalExampleRequested: Function,
|
||||
onSelectExample: Function,
|
||||
isInDrawer: bool,
|
||||
};
|
||||
|
||||
|
||||
|
||||
class UIExplorerList extends React.Component {
|
||||
props: Props;
|
||||
|
||||
@@ -128,7 +145,7 @@ class UIExplorerList extends React.Component {
|
||||
components: COMPONENTS,
|
||||
apis: APIS,
|
||||
}),
|
||||
searchText: Settings.get('searchText'),
|
||||
searchText: Platform.OS === 'ios' ? Settings.get('searchText') : '',
|
||||
};
|
||||
}
|
||||
|
||||
@@ -137,8 +154,12 @@ class UIExplorerList extends React.Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<View style={styles.listContainer}>
|
||||
if (Platform.OS === 'ios' ||
|
||||
(Platform.OS === 'android' && !this.props.isInDrawer)) {
|
||||
var platformTextInputStyle =
|
||||
Platform.OS === 'ios' ? styles.searchTextInputIOS :
|
||||
Platform.OS === 'android' ? styles.searchTextInputAndroid : {};
|
||||
var textInput = (
|
||||
<View style={styles.searchRow}>
|
||||
<TextInput
|
||||
autoCapitalize="none"
|
||||
@@ -146,10 +167,24 @@ class UIExplorerList extends React.Component {
|
||||
clearButtonMode="always"
|
||||
onChangeText={this._search.bind(this)}
|
||||
placeholder="Search..."
|
||||
style={styles.searchTextInput}
|
||||
style={[styles.searchTextInput, platformTextInputStyle]}
|
||||
value={this.state.searchText}
|
||||
/>
|
||||
</View>
|
||||
</View>);
|
||||
}
|
||||
|
||||
var homePage;
|
||||
if (Platform.OS === 'android' && this.props.isInDrawer) {
|
||||
homePage = this._renderRow({
|
||||
title: 'UIExplorer',
|
||||
description: 'List of examples',
|
||||
}, -1);
|
||||
}
|
||||
|
||||
return (
|
||||
<View style={styles.listContainer}>
|
||||
{textInput}
|
||||
{homePage}
|
||||
<ListView
|
||||
style={styles.list}
|
||||
dataSource={this.state.dataSource}
|
||||
@@ -173,7 +208,7 @@ class UIExplorerList extends React.Component {
|
||||
);
|
||||
}
|
||||
|
||||
_renderRow(example: ExampleModule, i: number) {
|
||||
_renderRow(example: any, i: number) {
|
||||
return (
|
||||
<View key={i}>
|
||||
<TouchableHighlight onPress={() => this._onPressRow(example)}>
|
||||
@@ -205,16 +240,23 @@ class UIExplorerList extends React.Component {
|
||||
Settings.set({searchText: text});
|
||||
}
|
||||
|
||||
_onPressRow(example: ExampleModule) {
|
||||
_onPressRow(example: any) {
|
||||
if (example.external) {
|
||||
this.props.onExternalExampleRequested(example);
|
||||
return;
|
||||
}
|
||||
var Component = makeRenderable(example);
|
||||
this.props.navigator.push({
|
||||
title: Component.title,
|
||||
component: Component,
|
||||
});
|
||||
if (Platform.OS === 'ios') {
|
||||
this.props.navigator.push({
|
||||
title: Component.title,
|
||||
component: Component,
|
||||
});
|
||||
} else if (Platform.OS === 'android') {
|
||||
this.props.onSelectExample({
|
||||
title: Component.title,
|
||||
component: Component,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -267,9 +309,14 @@ var styles = StyleSheet.create({
|
||||
borderColor: '#cccccc',
|
||||
borderRadius: 3,
|
||||
borderWidth: 1,
|
||||
height: 30,
|
||||
paddingLeft: 8,
|
||||
},
|
||||
searchTextInputIOS: {
|
||||
height: 30,
|
||||
},
|
||||
searchTextInputAndroid: {
|
||||
padding: 2,
|
||||
},
|
||||
});
|
||||
|
||||
module.exports = UIExplorerList;
|
||||
|
||||
@@ -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
|
||||
53
Examples/UIExplorer/UIExplorerUnitTests/OCMock/OCMArg.h
Normal file
@@ -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)]
|
||||
36
Examples/UIExplorer/UIExplorerUnitTests/OCMock/OCMLocation.h
Normal file
@@ -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
|
||||
39
Examples/UIExplorer/UIExplorerUnitTests/OCMock/OCMRecorder.h
Normal file
@@ -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
|
||||
|
||||
|
||||
|
||||
84
Examples/UIExplorer/UIExplorerUnitTests/OCMock/OCMock.h
Normal file
@@ -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
|
||||
|
||||
192
Examples/UIExplorer/UIExplorerUnitTests/RCTAllocationTests.m
Normal file
@@ -0,0 +1,192 @@
|
||||
// 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;
|
||||
}
|
||||
|
||||
RUN_RUNLOOP_WHILE(weakExecutor, 1);
|
||||
sleep(1);
|
||||
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;
|
||||
}
|
||||
|
||||
RUN_RUNLOOP_WHILE(weakContext, 1);
|
||||
sleep(1);
|
||||
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
|
||||
187
Examples/UIExplorer/UIExplorerUnitTests/RCTBridgeTests.m
Normal file
@@ -0,0 +1,187 @@
|
||||
// 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
|
||||
|
||||
RCT_EXPORT_MODULE()
|
||||
|
||||
- (void)setUp {}
|
||||
|
||||
- (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,193 @@
|
||||
// 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
|
||||
{
|
||||
RCTContextExecutor *_executor;
|
||||
}
|
||||
|
||||
- (void)setUp
|
||||
{
|
||||
[super setUp];
|
||||
_executor = [[RCTContextExecutor alloc] init];
|
||||
RCTSetExecutorID(_executor);
|
||||
[_executor setUp];
|
||||
}
|
||||
|
||||
- (void)testNativeLoggingHookExceptionBehavior
|
||||
{
|
||||
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);
|
||||
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
|
||||
159
Examples/UIExplorer/UIExplorerUnitTests/RCTConvert_UIFontTests.m
Normal file
@@ -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
|
||||
179
Examples/UIExplorer/UIExplorerUnitTests/RCTUIManagerTests.m
Normal file
@@ -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
|
||||
BIN
Examples/UIExplorer/UIExplorerUnitTests/libOCMock.a
Normal file
131
Examples/UIExplorer/XHRExample.js
Normal file
@@ -0,0 +1,131 @@
|
||||
/**
|
||||
* The examples provided by Facebook are for non-commercial testing and
|
||||
* evaluation purposes only.
|
||||
*
|
||||
* Facebook reserves all rights not expressly granted.
|
||||
*
|
||||
* 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 NON INFRINGEMENT. IN NO EVENT SHALL
|
||||
* FACEBOOK 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.
|
||||
*
|
||||
* @flow
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var React = require('react-native');
|
||||
var {
|
||||
ProgressViewIOS,
|
||||
StyleSheet,
|
||||
View,
|
||||
Text,
|
||||
TouchableHighlight,
|
||||
} = React;
|
||||
|
||||
class Downloader extends React.Component {
|
||||
|
||||
xhr: XMLHttpRequest;
|
||||
cancelled: boolean;
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.cancelled = false;
|
||||
this.state = {
|
||||
downloading: false,
|
||||
contentSize: 1,
|
||||
downloaded: 0,
|
||||
};
|
||||
}
|
||||
|
||||
download() {
|
||||
this.xhr && this.xhr.abort();
|
||||
|
||||
var xhr = this.xhr || new XMLHttpRequest();
|
||||
xhr.onreadystatechange = () => {
|
||||
if (xhr.readyState === xhr.HEADERS_RECEIVED) {
|
||||
var contentSize = parseInt(xhr.getResponseHeader('Content-Length'), 10);
|
||||
this.setState({
|
||||
contentSize: contentSize,
|
||||
downloaded: 0,
|
||||
});
|
||||
} else if (xhr.readyState === xhr.LOADING) {
|
||||
this.setState({
|
||||
downloaded: xhr.responseText.length,
|
||||
});
|
||||
} else if (xhr.readyState === xhr.DONE) {
|
||||
this.setState({
|
||||
downloading: false,
|
||||
});
|
||||
if (this.cancelled) {
|
||||
this.cancelled = false;
|
||||
return;
|
||||
}
|
||||
if (xhr.status === 200) {
|
||||
alert('Download complete!');
|
||||
} else if (xhr.status !== 0) {
|
||||
alert('Error: Server returned HTTP status of ' + xhr.status + ' ' + xhr.responseText);
|
||||
} else {
|
||||
alert('Error: ' + xhr.responseText);
|
||||
}
|
||||
}
|
||||
};
|
||||
xhr.open('GET', 'http://www.gutenberg.org/cache/epub/100/pg100.txt');
|
||||
xhr.send();
|
||||
this.xhr = xhr;
|
||||
|
||||
this.setState({downloading: true});
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.cancelled = true;
|
||||
this.xhr && this.xhr.abort();
|
||||
}
|
||||
|
||||
render() {
|
||||
var button = this.state.downloading ? (
|
||||
<View style={styles.wrapper}>
|
||||
<View style={styles.button}>
|
||||
<Text>Downloading...</Text>
|
||||
</View>
|
||||
</View>
|
||||
) : (
|
||||
<TouchableHighlight
|
||||
style={styles.wrapper}
|
||||
onPress={this.download.bind(this)}>
|
||||
<View style={styles.button}>
|
||||
<Text>Download 5MB Text File</Text>
|
||||
</View>
|
||||
</TouchableHighlight>
|
||||
);
|
||||
|
||||
return (
|
||||
<View>
|
||||
{button}
|
||||
<ProgressViewIOS progress={(this.state.downloaded / this.state.contentSize)}/>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
exports.framework = 'React';
|
||||
exports.title = 'XMLHttpRequest';
|
||||
exports.description = 'XMLHttpRequest';
|
||||
exports.examples = [{
|
||||
title: 'File Download',
|
||||
render() {
|
||||
return <Downloader/>;
|
||||
}
|
||||
}];
|
||||
|
||||
var styles = StyleSheet.create({
|
||||
wrapper: {
|
||||
borderRadius: 5,
|
||||
marginBottom: 5,
|
||||
},
|
||||
button: {
|
||||
backgroundColor: '#eeeeee',
|
||||
padding: 10,
|
||||
},
|
||||
});
|
||||