diff --git a/IntegrationTests/AppDelegate.h b/IntegrationTests/AppDelegate.h new file mode 100644 index 000000000..f0ec66bdb --- /dev/null +++ b/IntegrationTests/AppDelegate.h @@ -0,0 +1,10 @@ +// Copyright 2004-present Facebook. All Rights Reserved. + +#import + +@interface AppDelegate : UIResponder + +@property (nonatomic, strong) UIWindow *window; + +@end + diff --git a/IntegrationTests/AppDelegate.m b/IntegrationTests/AppDelegate.m new file mode 100644 index 000000000..db988faf8 --- /dev/null +++ b/IntegrationTests/AppDelegate.m @@ -0,0 +1,44 @@ +// Copyright 2004-present Facebook. All Rights Reserved. + +#import "AppDelegate.h" + +#import "RCTRootView.h" + +@implementation AppDelegate + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions +{ + NSURL *jsCodeLocation; + RCTRootView *rootView = [[RCTRootView alloc] init]; + + // Loading JavaScript code - uncomment the one you want. + + // OPTION 1 + // Load from development server. Start the server from the repository root: + // + // $ npm start + // + // To run on device, change `localhost` to the IP address of your computer, and make sure your computer and + // iOS device are on the same Wi-Fi network. + jsCodeLocation = [NSURL URLWithString:@"http://localhost:8081/IntegrationTests/IntegrationTestsApp.includeRequire.runModule.bundle?dev=true"]; + + // OPTION 2 + // Load from pre-bundled file on disk. To re-generate the static bundle, run + // + // $ curl http://localhost:8081/IntegrationTests/IntegrationTestsApp.includeRequire.runModule.bundle -o main.jsbundle + // + // and uncomment the next following line + // jsCodeLocation = [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"]; + + rootView.scriptURL = jsCodeLocation; + rootView.moduleName = @"IntegrationTestsApp"; + + self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; + UIViewController *rootViewController = [[UIViewController alloc] init]; + rootViewController.view = rootView; + self.window.rootViewController = rootViewController; + [self.window makeKeyAndVisible]; + return YES; +} + +@end diff --git a/IntegrationTests/Base.lproj/LaunchScreen.xib b/IntegrationTests/Base.lproj/LaunchScreen.xib new file mode 100644 index 000000000..52cc0828d --- /dev/null +++ b/IntegrationTests/Base.lproj/LaunchScreen.xib @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/IntegrationTests/Images.xcassets/AppIcon.appiconset/Contents.json b/IntegrationTests/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 000000000..413d60e76 --- /dev/null +++ b/IntegrationTests/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,44 @@ +{ + "images" : [ + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "uie_icon@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "uie_icon@2x-1.png", + "scale" : "3x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "uie_icon@2x-2.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "uie_icon@2x-3.png", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "uie_icon@2x-5.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "uie_icon@2x-4.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/IntegrationTests/Images.xcassets/AppIcon.appiconset/uie_icon@2x-1.png b/IntegrationTests/Images.xcassets/AppIcon.appiconset/uie_icon@2x-1.png new file mode 100644 index 000000000..08a42699d Binary files /dev/null and b/IntegrationTests/Images.xcassets/AppIcon.appiconset/uie_icon@2x-1.png differ diff --git a/IntegrationTests/Images.xcassets/AppIcon.appiconset/uie_icon@2x-2.png b/IntegrationTests/Images.xcassets/AppIcon.appiconset/uie_icon@2x-2.png new file mode 100644 index 000000000..08a42699d Binary files /dev/null and b/IntegrationTests/Images.xcassets/AppIcon.appiconset/uie_icon@2x-2.png differ diff --git a/IntegrationTests/Images.xcassets/AppIcon.appiconset/uie_icon@2x-3.png b/IntegrationTests/Images.xcassets/AppIcon.appiconset/uie_icon@2x-3.png new file mode 100644 index 000000000..08a42699d Binary files /dev/null and b/IntegrationTests/Images.xcassets/AppIcon.appiconset/uie_icon@2x-3.png differ diff --git a/IntegrationTests/Images.xcassets/AppIcon.appiconset/uie_icon@2x-4.png b/IntegrationTests/Images.xcassets/AppIcon.appiconset/uie_icon@2x-4.png new file mode 100644 index 000000000..08a42699d Binary files /dev/null and b/IntegrationTests/Images.xcassets/AppIcon.appiconset/uie_icon@2x-4.png differ diff --git a/IntegrationTests/Images.xcassets/AppIcon.appiconset/uie_icon@2x-5.png b/IntegrationTests/Images.xcassets/AppIcon.appiconset/uie_icon@2x-5.png new file mode 100644 index 000000000..08a42699d Binary files /dev/null and b/IntegrationTests/Images.xcassets/AppIcon.appiconset/uie_icon@2x-5.png differ diff --git a/IntegrationTests/Images.xcassets/AppIcon.appiconset/uie_icon@2x.png b/IntegrationTests/Images.xcassets/AppIcon.appiconset/uie_icon@2x.png new file mode 100644 index 000000000..08a42699d Binary files /dev/null and b/IntegrationTests/Images.xcassets/AppIcon.appiconset/uie_icon@2x.png differ diff --git a/IntegrationTests/Info.plist b/IntegrationTests/Info.plist new file mode 100644 index 000000000..245054621 --- /dev/null +++ b/IntegrationTests/Info.plist @@ -0,0 +1,42 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + com.facebook.$(PRODUCT_NAME:rfc1034identifier) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + NSLocationWhenInUseUsageDescription + You need to add NSLocationWhenInUseUsageDescription key in Info.plist to enable geolocation, otherwise it is going to *fail silently*! + UIViewControllerBasedStatusBarAppearance + + + diff --git a/IntegrationTests/IntegrationTestHarnessTest.js b/IntegrationTests/IntegrationTestHarnessTest.js new file mode 100644 index 000000000..5b6e78838 --- /dev/null +++ b/IntegrationTests/IntegrationTestHarnessTest.js @@ -0,0 +1,57 @@ +/** + * Copyright 2004-present Facebook. All Rights Reserved. + */ +'use strict'; + +var RCTTestModule = require('NativeModules').RCTTestModule; +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 ( + + + {this.constructor.displayName + ': '} + {this.state.done ? 'Done' : 'Testing...'} + + + ); + } +}); + +module.exports = IntegrationTestHarnessTest; diff --git a/IntegrationTests/IntegrationTests.xcodeproj/project.pbxproj b/IntegrationTests/IntegrationTests.xcodeproj/project.pbxproj new file mode 100644 index 000000000..c850360b1 --- /dev/null +++ b/IntegrationTests/IntegrationTests.xcodeproj/project.pbxproj @@ -0,0 +1,651 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 004D28A31AAF61C70097A701 /* IntegrationTestsTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 004D28A21AAF61C70097A701 /* IntegrationTestsTests.m */; }; + 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 */; }; + 580C37601AB0F6180015E709 /* libReactKit.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 580C37461AB0F5320015E709 /* libReactKit.a */; }; + 580C37611AB0F61E0015E709 /* libRCTAdSupport.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 580C374B1AB0F54A0015E709 /* libRCTAdSupport.a */; }; + 580C37621AB0F6260015E709 /* libRCTGeolocation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 580C37501AB0F55C0015E709 /* libRCTGeolocation.a */; }; + 580C37631AB0F62C0015E709 /* libRCTImage.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 580C37551AB0F56E0015E709 /* libRCTImage.a */; }; + 580C37641AB0F6350015E709 /* libRCTNetwork.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 580C375A1AB0F5970015E709 /* libRCTNetwork.a */; }; + 580C37651AB0F63E0015E709 /* libRCTText.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 580C375F1AB0F5D10015E709 /* libRCTText.a */; }; + 580C37921AB1090B0015E709 /* libRCTTest.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 580C378F1AB104B00015E709 /* libRCTTest.a */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 004D28A41AAF61C70097A701 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 83CBB9F71A601CBA00E9B192 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 13B07F861A680F5B00A75B9A; + remoteInfo = IntegrationTests; + }; + 580C37451AB0F5320015E709 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 13417FFA1AA91531003F314A /* ReactKit.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 83CBBA2E1A601D0E00E9B192; + remoteInfo = ReactKit; + }; + 580C374A1AB0F54A0015E709 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 134454551AAFCAAE003F0779 /* RCTAdSupport.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 832C81801AAF6DEF007FA2F7; + remoteInfo = RCTAdSupport; + }; + 580C374F1AB0F55C0015E709 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 134A8A201AACED6A00945AAE /* RCTGeolocation.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 134814201AA4EA6300B7C361; + remoteInfo = RCTGeolocation; + }; + 580C37541AB0F56E0015E709 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 13417FE31AA91428003F314A /* RCTImage.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 58B5115D1A9E6B3D00147676; + remoteInfo = RCTImage; + }; + 580C37591AB0F5970015E709 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 134180261AA91779003F314A /* RCTNetwork.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 58B511DB1A9E6C8500147676; + remoteInfo = RCTNetwork; + }; + 580C375E1AB0F5D10015E709 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 13417FEA1AA914B8003F314A /* RCTText.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 58B5119B1A9E6C1200147676; + remoteInfo = RCTText; + }; + 580C378E1AB104B00015E709 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 580C37891AB104AF0015E709 /* RCTTest.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 580C376F1AB104AF0015E709; + remoteInfo = RCTTest; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 004D289E1AAF61C70097A701 /* IntegrationTestsTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = IntegrationTestsTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 004D28A11AAF61C70097A701 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 004D28A21AAF61C70097A701 /* IntegrationTestsTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = IntegrationTestsTests.m; sourceTree = ""; }; + 13417FE31AA91428003F314A /* RCTImage.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTImage.xcodeproj; path = ../Libraries/Image/RCTImage.xcodeproj; sourceTree = ""; }; + 13417FEA1AA914B8003F314A /* RCTText.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTText.xcodeproj; path = ../Libraries/Text/RCTText.xcodeproj; sourceTree = ""; }; + 13417FFA1AA91531003F314A /* ReactKit.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = ReactKit.xcodeproj; path = ../ReactKit/ReactKit.xcodeproj; sourceTree = ""; }; + 134180261AA91779003F314A /* RCTNetwork.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTNetwork.xcodeproj; path = ../Libraries/Network/RCTNetwork.xcodeproj; sourceTree = ""; }; + 134454551AAFCAAE003F0779 /* RCTAdSupport.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTAdSupport.xcodeproj; path = ../Libraries/AdSupport/RCTAdSupport.xcodeproj; sourceTree = ""; }; + 134A8A201AACED6A00945AAE /* RCTGeolocation.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTGeolocation.xcodeproj; path = ../Libraries/GeoLocation/RCTGeolocation.xcodeproj; sourceTree = ""; }; + 13B07F961A680F5B00A75B9A /* IntegrationTests.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = IntegrationTests.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 13B07FB01A68108700A75B9A /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 13B07FB21A68108700A75B9A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; + 13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; + 13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 580C37891AB104AF0015E709 /* RCTTest.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTTest.xcodeproj; path = ../Libraries/RCTTest/RCTTest.xcodeproj; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 004D289B1AAF61C70097A701 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 13B07F8C1A680F5B00A75B9A /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 580C37601AB0F6180015E709 /* libReactKit.a in Frameworks */, + 580C37611AB0F61E0015E709 /* libRCTAdSupport.a in Frameworks */, + 580C37621AB0F6260015E709 /* libRCTGeolocation.a in Frameworks */, + 580C37631AB0F62C0015E709 /* libRCTImage.a in Frameworks */, + 580C37641AB0F6350015E709 /* libRCTNetwork.a in Frameworks */, + 580C37651AB0F63E0015E709 /* libRCTText.a in Frameworks */, + 580C37921AB1090B0015E709 /* libRCTTest.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 004D289F1AAF61C70097A701 /* IntegrationTestsTests */ = { + isa = PBXGroup; + children = ( + 004D28A21AAF61C70097A701 /* IntegrationTestsTests.m */, + 004D28A01AAF61C70097A701 /* Supporting Files */, + ); + path = IntegrationTestsTests; + sourceTree = ""; + }; + 004D28A01AAF61C70097A701 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 004D28A11AAF61C70097A701 /* Info.plist */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 1316A21D1AA397F400C0188E /* Libraries */ = { + isa = PBXGroup; + children = ( + 13417FFA1AA91531003F314A /* ReactKit.xcodeproj */, + 134454551AAFCAAE003F0779 /* RCTAdSupport.xcodeproj */, + 134A8A201AACED6A00945AAE /* RCTGeolocation.xcodeproj */, + 13417FE31AA91428003F314A /* RCTImage.xcodeproj */, + 134180261AA91779003F314A /* RCTNetwork.xcodeproj */, + 13417FEA1AA914B8003F314A /* RCTText.xcodeproj */, + 580C37891AB104AF0015E709 /* RCTTest.xcodeproj */, + ); + name = Libraries; + sourceTree = ""; + }; + 13B07FAE1A68108700A75B9A /* IntegrationTests */ = { + isa = PBXGroup; + children = ( + 13B07FAF1A68108700A75B9A /* AppDelegate.h */, + 13B07FB01A68108700A75B9A /* AppDelegate.m */, + 13B07FB51A68108700A75B9A /* Images.xcassets */, + 13B07FB61A68108700A75B9A /* Info.plist */, + 13B07FB11A68108700A75B9A /* LaunchScreen.xib */, + 13B07FB71A68108700A75B9A /* main.m */, + ); + name = IntegrationTests; + sourceTree = ""; + }; + 580C37421AB0F5320015E709 /* Products */ = { + isa = PBXGroup; + children = ( + 580C37461AB0F5320015E709 /* libReactKit.a */, + ); + name = Products; + sourceTree = ""; + }; + 580C37471AB0F54A0015E709 /* Products */ = { + isa = PBXGroup; + children = ( + 580C374B1AB0F54A0015E709 /* libRCTAdSupport.a */, + ); + name = Products; + sourceTree = ""; + }; + 580C374C1AB0F55C0015E709 /* Products */ = { + isa = PBXGroup; + children = ( + 580C37501AB0F55C0015E709 /* libRCTGeolocation.a */, + ); + name = Products; + sourceTree = ""; + }; + 580C37511AB0F56E0015E709 /* Products */ = { + isa = PBXGroup; + children = ( + 580C37551AB0F56E0015E709 /* libRCTImage.a */, + ); + name = Products; + sourceTree = ""; + }; + 580C37561AB0F5970015E709 /* Products */ = { + isa = PBXGroup; + children = ( + 580C375A1AB0F5970015E709 /* libRCTNetwork.a */, + ); + name = Products; + sourceTree = ""; + }; + 580C375B1AB0F5D10015E709 /* Products */ = { + isa = PBXGroup; + children = ( + 580C375F1AB0F5D10015E709 /* libRCTText.a */, + ); + name = Products; + sourceTree = ""; + }; + 580C378A1AB104AF0015E709 /* Products */ = { + isa = PBXGroup; + children = ( + 580C378F1AB104B00015E709 /* libRCTTest.a */, + ); + name = Products; + sourceTree = ""; + }; + 83CBB9F61A601CBA00E9B192 = { + isa = PBXGroup; + children = ( + 13B07FAE1A68108700A75B9A /* IntegrationTests */, + 1316A21D1AA397F400C0188E /* Libraries */, + 004D289F1AAF61C70097A701 /* IntegrationTestsTests */, + 83CBBA001A601CBA00E9B192 /* Products */, + ); + sourceTree = ""; + }; + 83CBBA001A601CBA00E9B192 /* Products */ = { + isa = PBXGroup; + children = ( + 13B07F961A680F5B00A75B9A /* IntegrationTests.app */, + 004D289E1AAF61C70097A701 /* IntegrationTestsTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 004D289D1AAF61C70097A701 /* IntegrationTestsTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 004D28AD1AAF61C70097A701 /* Build configuration list for PBXNativeTarget "IntegrationTestsTests" */; + buildPhases = ( + 004D289A1AAF61C70097A701 /* Sources */, + 004D289B1AAF61C70097A701 /* Frameworks */, + 004D289C1AAF61C70097A701 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 004D28A51AAF61C70097A701 /* PBXTargetDependency */, + ); + name = IntegrationTestsTests; + productName = IntegrationTestsTests; + productReference = 004D289E1AAF61C70097A701 /* IntegrationTestsTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 13B07F861A680F5B00A75B9A /* IntegrationTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "IntegrationTests" */; + buildPhases = ( + 13B07F871A680F5B00A75B9A /* Sources */, + 13B07F8C1A680F5B00A75B9A /* Frameworks */, + 13B07F8E1A680F5B00A75B9A /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = IntegrationTests; + productName = "Hello World"; + productReference = 13B07F961A680F5B00A75B9A /* IntegrationTests.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 83CBB9F71A601CBA00E9B192 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0610; + ORGANIZATIONNAME = Facebook; + TargetAttributes = { + 004D289D1AAF61C70097A701 = { + CreatedOnToolsVersion = 6.1.1; + TestTargetID = 13B07F861A680F5B00A75B9A; + }; + }; + }; + buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "IntegrationTests" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 83CBB9F61A601CBA00E9B192; + productRefGroup = 83CBBA001A601CBA00E9B192 /* Products */; + projectDirPath = ""; + projectReferences = ( + { + ProductGroup = 580C37471AB0F54A0015E709 /* Products */; + ProjectRef = 134454551AAFCAAE003F0779 /* RCTAdSupport.xcodeproj */; + }, + { + ProductGroup = 580C374C1AB0F55C0015E709 /* Products */; + ProjectRef = 134A8A201AACED6A00945AAE /* RCTGeolocation.xcodeproj */; + }, + { + ProductGroup = 580C37511AB0F56E0015E709 /* Products */; + ProjectRef = 13417FE31AA91428003F314A /* RCTImage.xcodeproj */; + }, + { + ProductGroup = 580C37561AB0F5970015E709 /* Products */; + ProjectRef = 134180261AA91779003F314A /* RCTNetwork.xcodeproj */; + }, + { + ProductGroup = 580C378A1AB104AF0015E709 /* Products */; + ProjectRef = 580C37891AB104AF0015E709 /* RCTTest.xcodeproj */; + }, + { + ProductGroup = 580C375B1AB0F5D10015E709 /* Products */; + ProjectRef = 13417FEA1AA914B8003F314A /* RCTText.xcodeproj */; + }, + { + ProductGroup = 580C37421AB0F5320015E709 /* Products */; + ProjectRef = 13417FFA1AA91531003F314A /* ReactKit.xcodeproj */; + }, + ); + projectRoot = ""; + targets = ( + 13B07F861A680F5B00A75B9A /* IntegrationTests */, + 004D289D1AAF61C70097A701 /* IntegrationTestsTests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXReferenceProxy section */ + 580C37461AB0F5320015E709 /* libReactKit.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libReactKit.a; + remoteRef = 580C37451AB0F5320015E709 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 580C374B1AB0F54A0015E709 /* libRCTAdSupport.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libRCTAdSupport.a; + remoteRef = 580C374A1AB0F54A0015E709 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 580C37501AB0F55C0015E709 /* libRCTGeolocation.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libRCTGeolocation.a; + remoteRef = 580C374F1AB0F55C0015E709 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 580C37551AB0F56E0015E709 /* libRCTImage.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libRCTImage.a; + remoteRef = 580C37541AB0F56E0015E709 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 580C375A1AB0F5970015E709 /* libRCTNetwork.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libRCTNetwork.a; + remoteRef = 580C37591AB0F5970015E709 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 580C375F1AB0F5D10015E709 /* libRCTText.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libRCTText.a; + remoteRef = 580C375E1AB0F5D10015E709 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 580C378F1AB104B00015E709 /* libRCTTest.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libRCTTest.a; + remoteRef = 580C378E1AB104B00015E709 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; +/* End PBXReferenceProxy section */ + +/* Begin PBXResourcesBuildPhase section */ + 004D289C1AAF61C70097A701 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 13B07F8E1A680F5B00A75B9A /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */, + 13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 004D289A1AAF61C70097A701 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 004D28A31AAF61C70097A701 /* IntegrationTestsTests.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 13B07F871A680F5B00A75B9A /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */, + 13B07FC11A68108700A75B9A /* main.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 004D28A51AAF61C70097A701 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 13B07F861A680F5B00A75B9A /* IntegrationTests */; + targetProxy = 004D28A41AAF61C70097A701 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 13B07FB11A68108700A75B9A /* LaunchScreen.xib */ = { + isa = PBXVariantGroup; + children = ( + 13B07FB21A68108700A75B9A /* Base */, + ); + name = LaunchScreen.xib; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 004D28A61AAF61C70097A701 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(SDKROOT)/Developer/Library/Frameworks", + "$(DEVELOPER_FRAMEWORKS_DIR)", + ); + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + INFOPLIST_FILE = IntegrationTestsTests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 8.1; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/IntegrationTests.app/IntegrationTests"; + }; + name = Debug; + }; + 004D28A71AAF61C70097A701 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(SDKROOT)/Developer/Library/Frameworks", + "$(DEVELOPER_FRAMEWORKS_DIR)", + ); + INFOPLIST_FILE = IntegrationTestsTests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 8.1; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/IntegrationTests.app/IntegrationTests"; + }; + name = Release; + }; + 13B07F941A680F5B00A75B9A /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, + "$(SRCROOT)/../../ReactKit/**", + ); + INFOPLIST_FILE = "$(SRCROOT)/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LIBRARY_SEARCH_PATHS = "$(inherited)"; + OTHER_LDFLAGS = "-ObjC"; + PRODUCT_NAME = IntegrationTests; + }; + name = Debug; + }; + 13B07F951A680F5B00A75B9A /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, + "$(SRCROOT)/../../ReactKit/**", + ); + INFOPLIST_FILE = "$(SRCROOT)/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LIBRARY_SEARCH_PATHS = "$(inherited)"; + OTHER_LDFLAGS = "-ObjC"; + PRODUCT_NAME = IntegrationTests; + }; + name = Release; + }; + 83CBBA201A601CBA00E9B192 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, + "$(SRCROOT)/../ReactKit/**", + ); + IPHONEOS_DEPLOYMENT_TARGET = 7.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + }; + name = Debug; + }; + 83CBBA211A601CBA00E9B192 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = YES; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, + "$(SRCROOT)/../ReactKit/**", + ); + IPHONEOS_DEPLOYMENT_TARGET = 7.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 004D28AD1AAF61C70097A701 /* Build configuration list for PBXNativeTarget "IntegrationTestsTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 004D28A61AAF61C70097A701 /* Debug */, + 004D28A71AAF61C70097A701 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "IntegrationTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 13B07F941A680F5B00A75B9A /* Debug */, + 13B07F951A680F5B00A75B9A /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "IntegrationTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 83CBBA201A601CBA00E9B192 /* Debug */, + 83CBBA211A601CBA00E9B192 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 83CBB9F71A601CBA00E9B192 /* Project object */; +} diff --git a/IntegrationTests/IntegrationTestsApp.js b/IntegrationTests/IntegrationTestsApp.js new file mode 100644 index 000000000..ee60aa388 --- /dev/null +++ b/IntegrationTests/IntegrationTestsApp.js @@ -0,0 +1,84 @@ +/** + * Copyright 2004-present Facebook. All Rights Reserved. + * + * @providesModule IntegrationTestsApp + */ +'use strict'; + +var React = require('react-native'); + +var { + AppRegistry, + ScrollView, + StyleSheet, + Text, + TouchableOpacity, + View, +} = React; + +var TESTS = [ + require('./IntegrationTestHarnessTest'), +]; + +TESTS.forEach( + (test) => AppRegistry.registerComponent(test.displayName, () => test) +); + +var IntegrationTestsApp = React.createClass({ + getInitialState: function() { + return { + test: null, + }; + }, + render: function() { + if (this.state.test) { + return ( + + + + ); + } + return ( + + + 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. + + + + {TESTS.map((test) => [ + this.setState({test})}> + + + {test.displayName} + + + , + + ])} + + + ); + } +}); + +var styles = StyleSheet.create({ + container: { + backgroundColor: 'white', + marginTop: 40, + margin: 15, + }, + row: { + padding: 10, + }, + testName: { + fontWeight: 'bold', + }, + separator: { + height: 1, + backgroundColor: '#bbbbbb', + }, +}); + +AppRegistry.registerComponent('IntegrationTestsApp', () => IntegrationTestsApp); diff --git a/IntegrationTests/IntegrationTestsTests/Info.plist b/IntegrationTests/IntegrationTestsTests/Info.plist new file mode 100644 index 000000000..87e3a6175 --- /dev/null +++ b/IntegrationTests/IntegrationTestsTests/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + com.facebook.$(PRODUCT_NAME:rfc1034identifier) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + diff --git a/IntegrationTests/IntegrationTestsTests/IntegrationTestsTests.m b/IntegrationTests/IntegrationTestsTests/IntegrationTestsTests.m new file mode 100644 index 000000000..9d9020f7d --- /dev/null +++ b/IntegrationTests/IntegrationTestsTests/IntegrationTestsTests.m @@ -0,0 +1,40 @@ +// Copyright 2004-present Facebook. All Rights Reserved. + +#import +#import + +#import + +#import "RCTAssert.h" + +@interface IntegrationTestsTests : XCTestCase + +@end + +@implementation IntegrationTestsTests { + RCTTestRunner *_runner; +} + +- (void)setUp +{ + _runner = [[RCTTestRunner alloc] initWithApp:@"IntegrationTests/IntegrationTestsApp"]; +} + +- (void)testTheTester +{ + [_runner runTest:@"IntegrationTestHarnessTest"]; +} + +- (void)testTheTester_waitOneFrame +{ + [_runner runTest:@"IntegrationTestHarnessTest" initialProps:@{@"waitOneFrame": @YES} expectErrorBlock:nil]; +} + +- (void)testTheTester_ExpectError +{ + [_runner runTest:@"IntegrationTestHarnessTest" + initialProps:@{@"shouldThrow": @YES} + expectErrorRegex:[NSRegularExpression regularExpressionWithPattern:@"because shouldThrow" options:0 error:nil]]; +} + +@end diff --git a/IntegrationTests/main.m b/IntegrationTests/main.m new file mode 100644 index 000000000..357a233b1 --- /dev/null +++ b/IntegrationTests/main.m @@ -0,0 +1,10 @@ +// Copyright 2004-present Facebook. All Rights Reserved. + +#import +#import "AppDelegate.h" + +int main(int argc, char * argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} diff --git a/Libraries/RCTTest/RCTTest.xcodeproj/project.pbxproj b/Libraries/RCTTest/RCTTest.xcodeproj/project.pbxproj new file mode 100644 index 000000000..f377b4c98 --- /dev/null +++ b/Libraries/RCTTest/RCTTest.xcodeproj/project.pbxproj @@ -0,0 +1,264 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 585135371AB3C56F00882537 /* RCTTestModule.m in Sources */ = {isa = PBXBuildFile; fileRef = 585135341AB3C56F00882537 /* RCTTestModule.m */; }; + 585135381AB3C57000882537 /* RCTTestRunner.m in Sources */ = {isa = PBXBuildFile; fileRef = 585135361AB3C56F00882537 /* RCTTestRunner.m */; }; + 585135391AB3C59A00882537 /* RCTTestRunner.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 585135351AB3C56F00882537 /* RCTTestRunner.h */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 580C376D1AB104AF0015E709 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "include/$(PRODUCT_NAME)"; + dstSubfolderSpec = 16; + files = ( + 585135391AB3C59A00882537 /* RCTTestRunner.h in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 580C376F1AB104AF0015E709 /* libRCTTest.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRCTTest.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 585135331AB3C56F00882537 /* RCTTestModule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTTestModule.h; sourceTree = ""; }; + 585135341AB3C56F00882537 /* RCTTestModule.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTTestModule.m; sourceTree = ""; }; + 585135351AB3C56F00882537 /* RCTTestRunner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTTestRunner.h; sourceTree = ""; }; + 585135361AB3C56F00882537 /* RCTTestRunner.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTTestRunner.m; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 580C376C1AB104AF0015E709 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 580C37661AB104AF0015E709 = { + isa = PBXGroup; + children = ( + 585135331AB3C56F00882537 /* RCTTestModule.h */, + 585135341AB3C56F00882537 /* RCTTestModule.m */, + 585135351AB3C56F00882537 /* RCTTestRunner.h */, + 585135361AB3C56F00882537 /* RCTTestRunner.m */, + 580C37701AB104AF0015E709 /* Products */, + ); + sourceTree = ""; + }; + 580C37701AB104AF0015E709 /* Products */ = { + isa = PBXGroup; + children = ( + 580C376F1AB104AF0015E709 /* libRCTTest.a */, + ); + name = Products; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 580C376E1AB104AF0015E709 /* RCTTest */ = { + isa = PBXNativeTarget; + buildConfigurationList = 580C37831AB104AF0015E709 /* Build configuration list for PBXNativeTarget "RCTTest" */; + buildPhases = ( + 580C376B1AB104AF0015E709 /* Sources */, + 580C376C1AB104AF0015E709 /* Frameworks */, + 580C376D1AB104AF0015E709 /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = RCTTest; + productName = RCTTest; + productReference = 580C376F1AB104AF0015E709 /* libRCTTest.a */; + productType = "com.apple.product-type.library.static"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 580C37671AB104AF0015E709 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0610; + ORGANIZATIONNAME = Facebook; + TargetAttributes = { + 580C376E1AB104AF0015E709 = { + CreatedOnToolsVersion = 6.1.1; + }; + }; + }; + buildConfigurationList = 580C376A1AB104AF0015E709 /* Build configuration list for PBXProject "RCTTest" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 580C37661AB104AF0015E709; + productRefGroup = 580C37701AB104AF0015E709 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 580C376E1AB104AF0015E709 /* RCTTest */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXSourcesBuildPhase section */ + 580C376B1AB104AF0015E709 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 585135371AB3C56F00882537 /* RCTTestModule.m in Sources */, + 585135381AB3C57000882537 /* RCTTestRunner.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 580C37811AB104AF0015E709 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, + "$(SRCROOT)/../../ReactKit/**", + ); + IPHONEOS_DEPLOYMENT_TARGET = 8.1; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + }; + name = Debug; + }; + 580C37821AB104AF0015E709 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = YES; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, + "$(SRCROOT)/../../ReactKit/**", + ); + IPHONEOS_DEPLOYMENT_TARGET = 8.1; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 580C37841AB104AF0015E709 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + OTHER_LDFLAGS = ( + "-ObjC", + "-framework", + XCTest, + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + }; + name = Debug; + }; + 580C37851AB104AF0015E709 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + OTHER_LDFLAGS = ( + "-ObjC", + "-framework", + XCTest, + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 580C376A1AB104AF0015E709 /* Build configuration list for PBXProject "RCTTest" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 580C37811AB104AF0015E709 /* Debug */, + 580C37821AB104AF0015E709 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 580C37831AB104AF0015E709 /* Build configuration list for PBXNativeTarget "RCTTest" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 580C37841AB104AF0015E709 /* Debug */, + 580C37851AB104AF0015E709 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 580C37671AB104AF0015E709 /* Project object */; +} diff --git a/Libraries/RCTTest/RCTTestModule.h b/Libraries/RCTTest/RCTTestModule.h new file mode 100644 index 000000000..f439df7b2 --- /dev/null +++ b/Libraries/RCTTest/RCTTestModule.h @@ -0,0 +1,9 @@ +// Copyright 2004-present Facebook. All Rights Reserved. + +#import "RCTBridgeModule.h" + +@interface RCTTestModule : NSObject + +@property (nonatomic, readonly, getter=isDone) BOOL done; + +@end diff --git a/Libraries/RCTTest/RCTTestModule.m b/Libraries/RCTTest/RCTTestModule.m new file mode 100644 index 000000000..eeb73734c --- /dev/null +++ b/Libraries/RCTTest/RCTTestModule.m @@ -0,0 +1,14 @@ +// Copyright 2004-present Facebook. All Rights Reserved. + +#import "RCTTestModule.h" + +@implementation RCTTestModule + +- (void)markTestCompleted +{ + RCT_EXPORT(); + + _done = YES; +} + +@end diff --git a/Libraries/RCTTest/RCTTestRunner.h b/Libraries/RCTTest/RCTTestRunner.h new file mode 100644 index 000000000..a774088dc --- /dev/null +++ b/Libraries/RCTTest/RCTTestRunner.h @@ -0,0 +1,14 @@ +// Copyright 2004-present Facebook. All Rights Reserved. + +#import + +@interface RCTTestRunner : NSObject + +@property (nonatomic, copy) NSString *script; + +- (instancetype)initWithApp:(NSString *)app; +- (void)runTest:(NSString *)moduleName; +- (void)runTest:(NSString *)moduleName initialProps:(NSDictionary *)initialProps expectErrorRegex:(NSRegularExpression *)expectErrorRegex; +- (void)runTest:(NSString *)moduleName initialProps:(NSDictionary *)initialProps expectErrorBlock:(BOOL(^)(NSString *error))expectErrorBlock; + +@end diff --git a/Libraries/RCTTest/RCTTestRunner.m b/Libraries/RCTTest/RCTTestRunner.m new file mode 100644 index 000000000..3fec65b9e --- /dev/null +++ b/Libraries/RCTTest/RCTTestRunner.m @@ -0,0 +1,64 @@ +// Copyright 2004-present Facebook. All Rights Reserved. + +#import "RCTTestRunner.h" + +#import "RCTRedBox.h" +#import "RCTRootView.h" +#import "RCTTestModule.h" +#import "RCTUtils.h" + +#define TIMEOUT_SECONDS 30 + +@implementation RCTTestRunner + +- (instancetype)initWithApp:(NSString *)app +{ + if (self = [super init]) { + _script = [NSString stringWithFormat:@"http://localhost:8081/%@.includeRequire.runModule.bundle?dev=true", app]; + } + return self; +} + +- (void)runTest:(NSString *)moduleName +{ + [self runTest:moduleName initialProps:nil expectErrorBlock:nil]; +} + +- (void)runTest:(NSString *)moduleName initialProps:(NSDictionary *)initialProps expectErrorRegex:(NSRegularExpression *)errorRegex +{ + [self runTest:moduleName initialProps:initialProps expectErrorBlock:^BOOL(NSString *error){ + return [errorRegex numberOfMatchesInString:error options:0 range:NSMakeRange(0, [error length])] > 0; + }]; +} + +- (void)runTest:(NSString *)moduleName initialProps:(NSDictionary *)initialProps expectErrorBlock:(BOOL(^)(NSString *error))expectErrorBlock +{ + RCTTestModule *testModule = [[RCTTestModule alloc] init]; + RCTRootView *rootView = [[RCTRootView alloc] init]; + UIViewController *vc = [[[[UIApplication sharedApplication] delegate] window] rootViewController]; + vc.view = rootView; + rootView.moduleProvider = ^(void){ + return @[testModule]; + }; + rootView.moduleName = moduleName; + rootView.initialProperties = initialProps; + rootView.scriptURL = [NSURL URLWithString:_script]; + + NSDate *date = [NSDate dateWithTimeIntervalSinceNow:TIMEOUT_SECONDS]; + NSString *error = [[RCTRedBox sharedInstance] currentErrorMessage]; + while ([date timeIntervalSinceNow] > 0 && ![testModule isDone] && error == nil) { + [[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:date]; + [[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:date]; + error = [[RCTRedBox sharedInstance] currentErrorMessage]; + } + [[RCTRedBox sharedInstance] dismiss]; + if (expectErrorBlock) { + RCTAssert(expectErrorBlock(error), @"Expected an error but got none."); + } else if (error) { + RCTAssert(error == nil, @"RedBox error: %@", error); + } else { + RCTAssert([testModule isDone], @"Test didn't finish within %d seconds", TIMEOUT_SECONDS); + } +} + +@end diff --git a/ReactKit/Base/RCTRedBox.h b/ReactKit/Base/RCTRedBox.h index 82137eb06..c13ac729b 100644 --- a/ReactKit/Base/RCTRedBox.h +++ b/ReactKit/Base/RCTRedBox.h @@ -11,6 +11,8 @@ - (void)showErrorMessage:(NSString *)message withStack:(NSArray *)stack; - (void)updateErrorMessage:(NSString *)message withStack:(NSArray *)stack; +- (NSString *)currentErrorMessage; + - (void)dismiss; @end diff --git a/ReactKit/Base/RCTRedBox.m b/ReactKit/Base/RCTRedBox.m index 93a73087e..1d037cd4f 100644 --- a/ReactKit/Base/RCTRedBox.m +++ b/ReactKit/Base/RCTRedBox.m @@ -6,6 +6,8 @@ @interface RCTRedBoxWindow : UIWindow +@property (nonatomic, copy) NSString *lastErrorMessage; + @end @implementation RCTRedBoxWindow @@ -13,7 +15,6 @@ UIView *_rootView; UITableView *_stackTraceTableView; - NSString *_lastErrorMessage; NSArray *_lastStackTrace; UITableViewCell *_cachedMessageCell; @@ -289,6 +290,15 @@ } +- (NSString *)currentErrorMessage +{ + if (_window && !_window.hidden) { + return _window.lastErrorMessage; + } else { + return nil; + } +} + - (void)dismiss { [_window dismiss]; diff --git a/ReactKit/Base/RCTRootView.h b/ReactKit/Base/RCTRootView.h index 240c000c3..3fc0be165 100644 --- a/ReactKit/Base/RCTRootView.h +++ b/ReactKit/Base/RCTRootView.h @@ -2,6 +2,8 @@ #import +#import "RCTBridge.h" + @interface RCTRootView : UIView /** @@ -19,13 +21,20 @@ */ @property (nonatomic, copy) NSString *moduleName; +/** + * A block that returns an array of pre-allocated modules. These + * modules will take precedence over any automatically registered + * modules of the same name. + */ +@property (nonatomic, copy) RCTBridgeModuleProviderBlock moduleProvider; + /** * The default properties to apply to the view when the script bundle * is first loaded. Defaults to nil/empty. */ @property (nonatomic, copy) NSDictionary *initialProperties; -/** +/** * The class of the RCTJavaScriptExecutor to use with this view. * If not specified, it will default to using RCTContextExecutor. * Changes will take effect next time the bundle is reloaded. diff --git a/ReactKit/Base/RCTRootView.m b/ReactKit/Base/RCTRootView.m index 5f0698e32..c62793d50 100644 --- a/ReactKit/Base/RCTRootView.m +++ b/ReactKit/Base/RCTRootView.m @@ -142,7 +142,7 @@ static Class _globalExecutorClass; // Choose local executor if specified, followed by global, followed by default _executor = [[_executorClass ?: _globalExecutorClass ?: [RCTContextExecutor class] alloc] init]; - _bridge = [[RCTBridge alloc] initWithExecutor:_executor moduleProvider:nil]; + _bridge = [[RCTBridge alloc] initWithExecutor:_executor moduleProvider:_moduleProvider]; _touchHandler = [[RCTTouchHandler alloc] initWithBridge:_bridge]; [self addGestureRecognizer:_touchHandler];