diff --git a/HybridMobileDeploy.android.js b/CodePush.android.js similarity index 77% rename from HybridMobileDeploy.android.js rename to CodePush.android.js index 5536c57..c89e202 100644 --- a/HybridMobileDeploy.android.js +++ b/CodePush.android.js @@ -8,10 +8,10 @@ var warning = require('warning'); -var HybridMobileDeploy = { +var CodePush = { test: function() { warning("Not yet implemented for Android."); } }; -module.exports = HybridMobileDeploy; +module.exports = CodePush; diff --git a/HybridMobileDeploy.h b/CodePush.h similarity index 82% rename from HybridMobileDeploy.h rename to CodePush.h index 82792cb..e1f92c2 100644 --- a/HybridMobileDeploy.h +++ b/CodePush.h @@ -1,12 +1,12 @@ #import "RCTBridgeModule.h" -@interface HybridMobileDeploy : NSObject +@interface CodePush : NSObject + (NSURL *) getBundleUrl; @end -@interface HybridMobileDeployConfig : NSObject +@interface CodePushConfig : NSObject + (void)setDeploymentKey:(NSString *)deploymentKey; + (NSString *)getDeploymentKey; diff --git a/HybridMobileDeploy.ios.js b/CodePush.ios.js similarity index 67% rename from HybridMobileDeploy.ios.js rename to CodePush.ios.js index 49723b0..154d06c 100644 --- a/HybridMobileDeploy.ios.js +++ b/CodePush.ios.js @@ -1,24 +1,31 @@ /** - * @providesModule HybridMobileDeploy + * @providesModule CodePush * @flow */ 'use strict'; -var NativeHybridMobileDeploy = require('react-native').NativeModules.HybridMobileDeploy; +var NativeCodePush = require('react-native').NativeModules.CodePush; var requestFetchAdapter = require("./request-fetch-adapter.js"); var semver = require('semver'); var Sdk = require("code-push/script/acquisition-sdk").AcquisitionManager; var sdk; var config; +// This function is only used for tests. Replaces the default SDK, configuration and native bridge +function setUpTestDependencies(testSdk, testConfiguration, testNativeBridge){ + if (testSdk) sdk = testSdk; + if (testConfiguration) config = testConfiguration; + if (testNativeBridge) NativeCodePush = testNativeBridge; +} + function getConfiguration(callback) { if (config) { setImmediate(function() { callback(/*error=*/ null, config); }); } else { - NativeHybridMobileDeploy.getConfiguration(function(err, configuration) { + NativeCodePush.getConfiguration(function(err, configuration) { if (err) callback(err); config = configuration; callback(/*error=*/ null, config); @@ -44,7 +51,7 @@ function queryUpdate(callback) { if (err) callback(err); getSdk(function(err, sdk) { if (err) callback(err); - NativeHybridMobileDeploy.getLocalPackage(function(err, localPackage) { + NativeCodePush.getLocalPackage(function(err, localPackage) { var queryPackage = {appVersion: configuration.appVersion}; if (!err && localPackage && localPackage.appVersion === configuration.appVersion) { queryPackage = localPackage; @@ -61,13 +68,14 @@ function queryUpdate(callback) { function installUpdate(update) { // Use the downloaded package info. Native code will save the package info // so that the client knows what the current package version is. - NativeHybridMobileDeploy.installUpdate(update, JSON.stringify(update), (err) => console.log(err)); + NativeCodePush.installUpdate(update, JSON.stringify(update), (err) => console.log(err)); } -var HybridMobileDeploy = { +var CodePush = { getConfiguration: getConfiguration, queryUpdate: queryUpdate, - installUpdate: installUpdate + installUpdate: installUpdate, + setUpTestDependencies: setUpTestDependencies }; -module.exports = HybridMobileDeploy; +module.exports = CodePush; diff --git a/HybridMobileDeploy.m b/CodePush.m similarity index 66% rename from HybridMobileDeploy.m rename to CodePush.m index 792b881..01ce716 100644 --- a/HybridMobileDeploy.m +++ b/CodePush.m @@ -1,21 +1,24 @@ -#import "HybridMobileDeploy.h" +#import "CodePush.h" #import "RCTBridgeModule.h" #import "RCTRootView.h" #import "RCTUtils.h" -@implementation HybridMobileDeploy + +@implementation CodePush RCT_EXPORT_MODULE() RCTBridge * _bridge; +BOOL usingTestFolder = NO; @synthesize bridge = _bridge; + (NSString *) getBundleFolderPath { NSString* home = NSHomeDirectory(); - NSString* bundleFolder = [home stringByAppendingPathComponent:@"HybridMobileDeploy/bundle"]; + NSString* pathExtension = [[@"CodePush/" stringByAppendingString: (usingTestFolder ? @"test/" : @"")] stringByAppendingString: @"bundle"]; + NSString* bundleFolder = [home stringByAppendingPathComponent:pathExtension]; return bundleFolder; } @@ -29,7 +32,8 @@ RCTBridge * _bridge; + (NSString *) getPackageFolderPath { NSString* home = NSHomeDirectory(); - NSString* packageFolder = [home stringByAppendingPathComponent:@"HybridMobileDeploy/package"]; + NSString* pathExtension = [[@"CodePush/" stringByAppendingString: (usingTestFolder ? @"test/" : @"")] stringByAppendingString: @"package"]; + NSString* packageFolder = [home stringByAppendingPathComponent:pathExtension]; return packageFolder; } @@ -71,9 +75,14 @@ RCTBridge * _bridge; }); } +RCT_EXPORT_METHOD(setUsingTestFolder:(BOOL) shouldUseTestFolder) +{ + usingTestFolder = shouldUseTestFolder; +} + RCT_EXPORT_METHOD(getConfiguration:(RCTResponseSenderBlock)callback) { - callback(@[[NSNull null], [HybridMobileDeployConfig getConfiguration]]); + callback(@[[NSNull null], [CodePushConfig getConfiguration]]); } RCT_EXPORT_METHOD(installUpdate:(NSDictionary*)updatePackage @@ -93,34 +102,34 @@ RCT_EXPORT_METHOD(installUpdate:(NSDictionary*)updatePackage } else { dispatch_async(dispatch_get_main_queue(), ^{ NSError *saveError; - NSString *bundleFolderPath = [HybridMobileDeploy getBundleFolderPath]; + NSString *bundleFolderPath = [CodePush getBundleFolderPath]; if (![[NSFileManager defaultManager] fileExistsAtPath:bundleFolderPath]) { [[NSFileManager defaultManager] createDirectoryAtPath:bundleFolderPath withIntermediateDirectories:YES attributes:nil error:&saveError]; } - [updateContents writeToFile:[HybridMobileDeploy getBundlePath] + [updateContents writeToFile:[CodePush getBundlePath] atomically:YES encoding:NSUTF8StringEncoding error:&saveError]; if (saveError) { // TODO send file path - callback(@[RCTMakeError(@"Error saving file", err, [[NSDictionary alloc] initWithObjectsAndKeys:[HybridMobileDeploy getBundlePath],@"bundlePath", nil])]); + callback(@[RCTMakeError(@"Error saving file", saveError, [[NSDictionary alloc] initWithObjectsAndKeys:[CodePush getBundlePath],@"bundlePath", nil])]); } else { // Save the package info too. - NSString *packageFolderPath = [HybridMobileDeploy getPackageFolderPath]; + NSString *packageFolderPath = [CodePush getPackageFolderPath]; if (![[NSFileManager defaultManager] fileExistsAtPath:packageFolderPath]) { [[NSFileManager defaultManager] createDirectoryAtPath:packageFolderPath withIntermediateDirectories:YES attributes:nil error:&saveError]; } - [packageJsonString writeToFile:[HybridMobileDeploy getPackagePath] + [packageJsonString writeToFile:[CodePush getPackagePath] atomically:YES encoding:NSUTF8StringEncoding error:&saveError]; if (saveError) { - callback(@[RCTMakeError(@"Error saving file", err, [[NSDictionary alloc] initWithObjectsAndKeys:[HybridMobileDeploy getPackagePath],@"packagePath", nil])]); + callback(@[RCTMakeError(@"Error saving file", saveError, [[NSDictionary alloc] initWithObjectsAndKeys:[CodePush getPackagePath],@"packagePath", nil])]); } else { - [HybridMobileDeploy loadBundle:[HybridMobileDeployConfig getRootComponent]]; + [CodePush loadBundle:[CodePushConfig getRootComponent]]; callback(@[[NSNull null]]); } } @@ -129,12 +138,52 @@ RCT_EXPORT_METHOD(installUpdate:(NSDictionary*)updatePackage }); } +RCT_EXPORT_METHOD(writeToLocalPackage:(NSString*)packageJsonString + callback:(RCTResponseSenderBlock)callback) +{ + NSError *saveError; + + // Save the package info too. + NSString *packageFolderPath = [CodePush getPackageFolderPath]; + if (![[NSFileManager defaultManager] fileExistsAtPath:packageFolderPath]) { + [[NSFileManager defaultManager] createDirectoryAtPath:packageFolderPath withIntermediateDirectories:YES attributes:nil error:&saveError]; + } + + [packageJsonString writeToFile:[CodePush getPackagePath] + atomically:YES + encoding:NSUTF8StringEncoding + error:&saveError]; + + if (saveError) { + callback(@[RCTMakeError(@"Error saving file", saveError, [[NSDictionary alloc] initWithObjectsAndKeys:[CodePush getPackagePath],@"packagePath", nil])]); + } else { + callback(@[[NSNull null]]); + } + +} + +RCT_EXPORT_METHOD(removeLocalPackage: (RCTResponseSenderBlock)callback) +{ + NSError *error; + + // Save the package info too. + NSString *packagePath = [CodePush getPackagePath]; + if ([[NSFileManager defaultManager] fileExistsAtPath:packagePath]) { + [[NSFileManager defaultManager] removeItemAtPath:packagePath error: &error]; + } + + if (error) { + callback(@[RCTMakeError(@"Error saving file", error, [[NSDictionary alloc] initWithObjectsAndKeys:[CodePush getPackagePath],@"packagePath", nil])]); + } else { + callback(@[[NSNull null]]); + } +} RCT_EXPORT_METHOD(getLocalPackage: (RCTResponseSenderBlock)callback) { - NSString *path = [HybridMobileDeploy getPackagePath]; + NSString *path = [CodePush getPackagePath]; dispatch_async(dispatch_get_main_queue(), ^{ diff --git a/HybridMobileDeploy.xcodeproj/project.pbxproj b/CodePush.xcodeproj/project.pbxproj similarity index 77% rename from HybridMobileDeploy.xcodeproj/project.pbxproj rename to CodePush.xcodeproj/project.pbxproj index fa8c150..ab476b4 100644 --- a/HybridMobileDeploy.xcodeproj/project.pbxproj +++ b/CodePush.xcodeproj/project.pbxproj @@ -7,8 +7,8 @@ objects = { /* Begin PBXBuildFile section */ - 13BE3DEE1AC21097009241FE /* HybridMobileDeploy.m in Sources */ = {isa = PBXBuildFile; fileRef = 13BE3DED1AC21097009241FE /* HybridMobileDeploy.m */; }; - 81D51F3A1B6181C2000DA084 /* HybridMobileDeployConfig.m in Sources */ = {isa = PBXBuildFile; fileRef = 81D51F391B6181C2000DA084 /* HybridMobileDeployConfig.m */; }; + 13BE3DEE1AC21097009241FE /* CodePush.m in Sources */ = {isa = PBXBuildFile; fileRef = 13BE3DED1AC21097009241FE /* CodePush.m */; }; + 81D51F3A1B6181C2000DA084 /* CodePushConfig.m in Sources */ = {isa = PBXBuildFile; fileRef = 81D51F391B6181C2000DA084 /* CodePushConfig.m */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -24,10 +24,10 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ - 134814201AA4EA6300B7C361 /* libHybridMobileDeploy.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libHybridMobileDeploy.a; sourceTree = BUILT_PRODUCTS_DIR; }; - 13BE3DEC1AC21097009241FE /* HybridMobileDeploy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HybridMobileDeploy.h; sourceTree = ""; }; - 13BE3DED1AC21097009241FE /* HybridMobileDeploy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HybridMobileDeploy.m; sourceTree = ""; }; - 81D51F391B6181C2000DA084 /* HybridMobileDeployConfig.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HybridMobileDeployConfig.m; sourceTree = ""; }; + 134814201AA4EA6300B7C361 /* libCodePush.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libCodePush.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 13BE3DEC1AC21097009241FE /* CodePush.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CodePush.h; sourceTree = ""; }; + 13BE3DED1AC21097009241FE /* CodePush.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CodePush.m; sourceTree = ""; }; + 81D51F391B6181C2000DA084 /* CodePushConfig.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CodePushConfig.m; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -44,7 +44,7 @@ 134814211AA4EA7D00B7C361 /* Products */ = { isa = PBXGroup; children = ( - 134814201AA4EA6300B7C361 /* libHybridMobileDeploy.a */, + 134814201AA4EA6300B7C361 /* libCodePush.a */, ); name = Products; sourceTree = ""; @@ -52,9 +52,9 @@ 58B511D21A9E6C8500147676 = { isa = PBXGroup; children = ( - 81D51F391B6181C2000DA084 /* HybridMobileDeployConfig.m */, - 13BE3DEC1AC21097009241FE /* HybridMobileDeploy.h */, - 13BE3DED1AC21097009241FE /* HybridMobileDeploy.m */, + 81D51F391B6181C2000DA084 /* CodePushConfig.m */, + 13BE3DEC1AC21097009241FE /* CodePush.h */, + 13BE3DED1AC21097009241FE /* CodePush.m */, 134814211AA4EA7D00B7C361 /* Products */, ); sourceTree = ""; @@ -62,9 +62,9 @@ /* End PBXGroup section */ /* Begin PBXNativeTarget section */ - 58B511DA1A9E6C8500147676 /* HybridMobileDeploy */ = { + 58B511DA1A9E6C8500147676 /* CodePush */ = { isa = PBXNativeTarget; - buildConfigurationList = 58B511EF1A9E6C8500147676 /* Build configuration list for PBXNativeTarget "HybridMobileDeploy" */; + buildConfigurationList = 58B511EF1A9E6C8500147676 /* Build configuration list for PBXNativeTarget "CodePush" */; buildPhases = ( 58B511D71A9E6C8500147676 /* Sources */, 58B511D81A9E6C8500147676 /* Frameworks */, @@ -74,9 +74,9 @@ ); dependencies = ( ); - name = HybridMobileDeploy; + name = CodePush; productName = RCTDataManager; - productReference = 134814201AA4EA6300B7C361 /* libHybridMobileDeploy.a */; + productReference = 134814201AA4EA6300B7C361 /* libCodePush.a */; productType = "com.apple.product-type.library.static"; }; /* End PBXNativeTarget section */ @@ -93,7 +93,7 @@ }; }; }; - buildConfigurationList = 58B511D61A9E6C8500147676 /* Build configuration list for PBXProject "HybridMobileDeploy" */; + buildConfigurationList = 58B511D61A9E6C8500147676 /* Build configuration list for PBXProject "CodePush" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; @@ -105,7 +105,7 @@ projectDirPath = ""; projectRoot = ""; targets = ( - 58B511DA1A9E6C8500147676 /* HybridMobileDeploy */, + 58B511DA1A9E6C8500147676 /* CodePush */, ); }; /* End PBXProject section */ @@ -115,8 +115,8 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 81D51F3A1B6181C2000DA084 /* HybridMobileDeployConfig.m in Sources */, - 13BE3DEE1AC21097009241FE /* HybridMobileDeploy.m in Sources */, + 81D51F3A1B6181C2000DA084 /* CodePushConfig.m in Sources */, + 13BE3DEE1AC21097009241FE /* CodePush.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -209,7 +209,7 @@ ); LIBRARY_SEARCH_PATHS = "$(inherited)"; OTHER_LDFLAGS = "-ObjC"; - PRODUCT_NAME = HybridMobileDeploy; + PRODUCT_NAME = CodePush; SKIP_INSTALL = YES; }; name = Debug; @@ -224,7 +224,7 @@ ); LIBRARY_SEARCH_PATHS = "$(inherited)"; OTHER_LDFLAGS = "-ObjC"; - PRODUCT_NAME = HybridMobileDeploy; + PRODUCT_NAME = CodePush; SKIP_INSTALL = YES; }; name = Release; @@ -232,7 +232,7 @@ /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ - 58B511D61A9E6C8500147676 /* Build configuration list for PBXProject "HybridMobileDeploy" */ = { + 58B511D61A9E6C8500147676 /* Build configuration list for PBXProject "CodePush" */ = { isa = XCConfigurationList; buildConfigurations = ( 58B511ED1A9E6C8500147676 /* Debug */, @@ -241,7 +241,7 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 58B511EF1A9E6C8500147676 /* Build configuration list for PBXNativeTarget "HybridMobileDeploy" */ = { + 58B511EF1A9E6C8500147676 /* Build configuration list for PBXNativeTarget "CodePush" */ = { isa = XCConfigurationList; buildConfigurations = ( 58B511F01A9E6C8500147676 /* Debug */, diff --git a/Examples/HybridMobileDeployCompanion/HybridMobileDeployCompanion.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/CodePush.xcodeproj/project.xcworkspace/contents.xcworkspacedata similarity index 100% rename from Examples/HybridMobileDeployCompanion/HybridMobileDeployCompanion.xcodeproj/project.xcworkspace/contents.xcworkspacedata rename to CodePush.xcodeproj/project.xcworkspace/contents.xcworkspacedata diff --git a/HybridMobileDeployConfig.m b/CodePushConfig.m similarity index 96% rename from HybridMobileDeployConfig.m rename to CodePushConfig.m index de601a4..f4c3c6c 100644 --- a/HybridMobileDeployConfig.m +++ b/CodePushConfig.m @@ -1,8 +1,8 @@ -#import "HybridMobileDeploy.h" +#import "CodePush.h" NSMutableDictionary *configuration; -@implementation HybridMobileDeployConfig +@implementation CodePushConfig + (void)initialize { diff --git a/Examples/HybridMobileDeployCompanion/.flowconfig b/Examples/CodePushDemoApp/.flowconfig similarity index 100% rename from Examples/HybridMobileDeployCompanion/.flowconfig rename to Examples/CodePushDemoApp/.flowconfig diff --git a/Examples/HybridMobileDeployCompanion/.gitignore b/Examples/CodePushDemoApp/.gitignore similarity index 100% rename from Examples/HybridMobileDeployCompanion/.gitignore rename to Examples/CodePushDemoApp/.gitignore diff --git a/Examples/HybridMobileDeployCompanion/HybridMobileDeployCompanion.xcodeproj/project.pbxproj b/Examples/CodePushDemoApp/CodePushDemoApp.xcodeproj/project.pbxproj similarity index 84% rename from Examples/HybridMobileDeployCompanion/HybridMobileDeployCompanion.xcodeproj/project.pbxproj rename to Examples/CodePushDemoApp/CodePushDemoApp.xcodeproj/project.pbxproj index 6acd3c6..0d3a903 100644 --- a/Examples/HybridMobileDeployCompanion/HybridMobileDeployCompanion.xcodeproj/project.pbxproj +++ b/Examples/CodePushDemoApp/CodePushDemoApp.xcodeproj/project.pbxproj @@ -7,14 +7,12 @@ objects = { /* Begin PBXBuildFile section */ - 008F07F31AC5B25A0029DE68 /* main.jsbundle in Resources */ = {isa = PBXBuildFile; fileRef = 008F07F21AC5B25A0029DE68 /* main.jsbundle */; }; 00C302E51ABCBA2D00DB3ED1 /* libRCTActionSheet.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302AC1ABCB8CE00DB3ED1 /* libRCTActionSheet.a */; }; 00C302E61ABCBA2D00DB3ED1 /* libRCTAdSupport.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302B41ABCB8E700DB3ED1 /* libRCTAdSupport.a */; }; 00C302E71ABCBA2D00DB3ED1 /* libRCTGeolocation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302BA1ABCB90400DB3ED1 /* libRCTGeolocation.a */; }; 00C302E81ABCBA2D00DB3ED1 /* libRCTImage.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302C01ABCB91800DB3ED1 /* libRCTImage.a */; }; 00C302E91ABCBA2D00DB3ED1 /* libRCTNetwork.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302DC1ABCB9D200DB3ED1 /* libRCTNetwork.a */; }; 00C302EA1ABCBA2D00DB3ED1 /* libRCTVibration.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302E41ABCB9EE00DB3ED1 /* libRCTVibration.a */; }; - 00E356F31AD99517003FC87E /* HybridMobileDeployCompanionTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 00E356F21AD99517003FC87E /* HybridMobileDeployCompanionTests.m */; }; 133E29F31AD74F7200F7D852 /* libRCTLinking.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 78C398B91ACF4ADC00677621 /* libRCTLinking.a */; }; 139105C61AF99C1200B5F7CC /* libRCTSettings.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 139105C11AF99BAD00B5F7CC /* libRCTSettings.a */; }; 139FDEF61B0652A700C62182 /* libRCTWebSocket.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 139FDEF41B06529B00C62182 /* libRCTWebSocket.a */; }; @@ -23,8 +21,11 @@ 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; }; 13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; }; 146834051AC3E58100842450 /* libReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 146834041AC3E56700842450 /* libReact.a */; }; - 81551E1B1B3B428000F5B9F1 /* libHybridMobileDeploy.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 81551E0F1B3B427200F5B9F1 /* libHybridMobileDeploy.a */; }; - 832341BD1AAA6AB300B99B32 /* libRCTText.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 832341B51AAA6A8300B99B32 /* libRCTText.a */; }; + 544161591B8BCA81000D9E25 /* libRCTText.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 832341B51AAA6A8300B99B32 /* libRCTText.a */; }; + 5451ACBA1B86A5B600E2A7DF /* QueryUpdateTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 5451ACB81B86A5B600E2A7DF /* QueryUpdateTests.m */; }; + 5451ACEC1B86E40A00E2A7DF /* libRCTTest.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5451ACEB1B86E34300E2A7DF /* libRCTTest.a */; }; + 54D774BA1B87DAF800F2ABF8 /* ApplyUpdateTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 54D774B91B87DAF800F2ABF8 /* ApplyUpdateTests.m */; }; + 81551E1B1B3B428000F5B9F1 /* libCodePush.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 81551E0F1B3B427200F5B9F1 /* libCodePush.a */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -75,7 +76,7 @@ containerPortal = 83CBB9F71A601CBA00E9B192 /* Project object */; proxyType = 1; remoteGlobalIDString = 13B07F861A680F5B00A75B9A; - remoteInfo = HybridMobileDeployCompanion; + remoteInfo = CodePushDemoApp; }; 139105C01AF99BAD00B5F7CC /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; @@ -98,6 +99,13 @@ remoteGlobalIDString = 83CBBA2E1A601D0E00E9B192; remoteInfo = React; }; + 5451ACEA1B86E34300E2A7DF /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 5451ACE61B86E34300E2A7DF /* RCTTest.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 580C376F1AB104AF0015E709; + remoteInfo = RCTTest; + }; 78C398B81ACF4ADC00677621 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */; @@ -107,10 +115,10 @@ }; 81551E0E1B3B427200F5B9F1 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 81551E0A1B3B427200F5B9F1 /* HybridMobileDeploy.xcodeproj */; + containerPortal = 81551E0A1B3B427200F5B9F1 /* CodePush.xcodeproj */; proxyType = 2; remoteGlobalIDString = 134814201AA4EA6300B7C361; - remoteInfo = HybridMobileDeploy; + remoteInfo = CodePush; }; 832341B41AAA6A8300B99B32 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; @@ -122,19 +130,17 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ - 008F07F21AC5B25A0029DE68 /* main.jsbundle */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = main.jsbundle; path = iOS/main.jsbundle; sourceTree = ""; }; 00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTActionSheet.xcodeproj; path = "node_modules/react-native/Libraries/ActionSheetIOS/RCTActionSheet.xcodeproj"; sourceTree = ""; }; 00C302AF1ABCB8E700DB3ED1 /* RCTAdSupport.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTAdSupport.xcodeproj; path = "node_modules/react-native/Libraries/AdSupport/RCTAdSupport.xcodeproj"; sourceTree = ""; }; 00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTGeolocation.xcodeproj; path = "node_modules/react-native/Libraries/Geolocation/RCTGeolocation.xcodeproj"; sourceTree = ""; }; 00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTImage.xcodeproj; path = "node_modules/react-native/Libraries/Image/RCTImage.xcodeproj"; sourceTree = ""; }; 00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTNetwork.xcodeproj; path = "node_modules/react-native/Libraries/Network/RCTNetwork.xcodeproj"; sourceTree = ""; }; 00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTVibration.xcodeproj; path = "node_modules/react-native/Libraries/Vibration/RCTVibration.xcodeproj"; sourceTree = ""; }; - 00E356EE1AD99517003FC87E /* HybridMobileDeployCompanionTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = HybridMobileDeployCompanionTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 00E356EE1AD99517003FC87E /* CodePushDemoAppTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CodePushDemoAppTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 00E356F11AD99517003FC87E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 00E356F21AD99517003FC87E /* HybridMobileDeployCompanionTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HybridMobileDeployCompanionTests.m; sourceTree = ""; }; 139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTSettings.xcodeproj; path = "node_modules/react-native/Libraries/Settings/RCTSettings.xcodeproj"; sourceTree = ""; }; 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTWebSocket.xcodeproj; path = "node_modules/react-native/Libraries/WebSocket/RCTWebSocket.xcodeproj"; sourceTree = ""; }; - 13B07F961A680F5B00A75B9A /* HybridMobileDeployCompanion.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = HybridMobileDeployCompanion.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 13B07F961A680F5B00A75B9A /* CodePushDemoApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = CodePushDemoApp.app; sourceTree = BUILT_PRODUCTS_DIR; }; 13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = iOS/AppDelegate.h; sourceTree = ""; }; 13B07FB01A68108700A75B9A /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = iOS/AppDelegate.m; sourceTree = ""; }; 13B07FB21A68108700A75B9A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; @@ -142,8 +148,11 @@ 13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = iOS/Info.plist; sourceTree = ""; }; 13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = iOS/main.m; sourceTree = ""; }; 146833FF1AC3E56700842450 /* React.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = React.xcodeproj; path = "node_modules/react-native/React/React.xcodeproj"; sourceTree = ""; }; + 5451ACB81B86A5B600E2A7DF /* QueryUpdateTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = QueryUpdateTests.m; sourceTree = ""; }; + 5451ACE61B86E34300E2A7DF /* RCTTest.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTTest.xcodeproj; path = "node_modules/react-native/Libraries/RCTTest/RCTTest.xcodeproj"; sourceTree = ""; }; + 54D774B91B87DAF800F2ABF8 /* ApplyUpdateTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ApplyUpdateTests.m; sourceTree = ""; }; 78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTLinking.xcodeproj; path = "node_modules/react-native/Libraries/LinkingIOS/RCTLinking.xcodeproj"; sourceTree = ""; }; - 81551E0A1B3B427200F5B9F1 /* HybridMobileDeploy.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = HybridMobileDeploy.xcodeproj; path = ../../HybridMobileDeploy.xcodeproj; sourceTree = ""; }; + 81551E0A1B3B427200F5B9F1 /* CodePush.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = CodePush.xcodeproj; path = ../../CodePush.xcodeproj; sourceTree = ""; }; 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTText.xcodeproj; path = "node_modules/react-native/Libraries/Text/RCTText.xcodeproj"; sourceTree = ""; }; /* End PBXFileReference section */ @@ -159,6 +168,8 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 544161591B8BCA81000D9E25 /* libRCTText.a in Frameworks */, + 5451ACEC1B86E40A00E2A7DF /* libRCTTest.a in Frameworks */, 146834051AC3E58100842450 /* libReact.a in Frameworks */, 00C302E51ABCBA2D00DB3ED1 /* libRCTActionSheet.a in Frameworks */, 00C302E61ABCBA2D00DB3ED1 /* libRCTAdSupport.a in Frameworks */, @@ -167,10 +178,9 @@ 133E29F31AD74F7200F7D852 /* libRCTLinking.a in Frameworks */, 00C302E91ABCBA2D00DB3ED1 /* libRCTNetwork.a in Frameworks */, 139105C61AF99C1200B5F7CC /* libRCTSettings.a in Frameworks */, - 832341BD1AAA6AB300B99B32 /* libRCTText.a in Frameworks */, 00C302EA1ABCBA2D00DB3ED1 /* libRCTVibration.a in Frameworks */, 139FDEF61B0652A700C62182 /* libRCTWebSocket.a in Frameworks */, - 81551E1B1B3B428000F5B9F1 /* libHybridMobileDeploy.a in Frameworks */, + 81551E1B1B3B428000F5B9F1 /* libCodePush.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -225,13 +235,14 @@ name = Products; sourceTree = ""; }; - 00E356EF1AD99517003FC87E /* HybridMobileDeployCompanionTests */ = { + 00E356EF1AD99517003FC87E /* CodePushDemoAppTests */ = { isa = PBXGroup; children = ( - 00E356F21AD99517003FC87E /* HybridMobileDeployCompanionTests.m */, + 5451ACB81B86A5B600E2A7DF /* QueryUpdateTests.m */, + 54D774B91B87DAF800F2ABF8 /* ApplyUpdateTests.m */, 00E356F01AD99517003FC87E /* Supporting Files */, ); - path = HybridMobileDeployCompanionTests; + path = CodePushDemoAppTests; sourceTree = ""; }; 00E356F01AD99517003FC87E /* Supporting Files */ = { @@ -258,10 +269,9 @@ name = Products; sourceTree = ""; }; - 13B07FAE1A68108700A75B9A /* HybridMobileDeployCompanion */ = { + 13B07FAE1A68108700A75B9A /* CodePushDemoApp */ = { isa = PBXGroup; children = ( - 008F07F21AC5B25A0029DE68 /* main.jsbundle */, 13B07FAF1A68108700A75B9A /* AppDelegate.h */, 13B07FB01A68108700A75B9A /* AppDelegate.m */, 13B07FB51A68108700A75B9A /* Images.xcassets */, @@ -269,7 +279,7 @@ 13B07FB11A68108700A75B9A /* LaunchScreen.xib */, 13B07FB71A68108700A75B9A /* main.m */, ); - name = HybridMobileDeployCompanion; + name = CodePushDemoApp; sourceTree = ""; }; 146834001AC3E56700842450 /* Products */ = { @@ -280,6 +290,14 @@ name = Products; sourceTree = ""; }; + 5451ACE71B86E34300E2A7DF /* Products */ = { + isa = PBXGroup; + children = ( + 5451ACEB1B86E34300E2A7DF /* libRCTTest.a */, + ); + name = Products; + sourceTree = ""; + }; 78C398B11ACF4ADC00677621 /* Products */ = { isa = PBXGroup; children = ( @@ -291,7 +309,7 @@ 81551E0B1B3B427200F5B9F1 /* Products */ = { isa = PBXGroup; children = ( - 81551E0F1B3B427200F5B9F1 /* libHybridMobileDeploy.a */, + 81551E0F1B3B427200F5B9F1 /* libCodePush.a */, ); name = Products; sourceTree = ""; @@ -299,7 +317,8 @@ 832341AE1AAA6A7D00B99B32 /* Libraries */ = { isa = PBXGroup; children = ( - 81551E0A1B3B427200F5B9F1 /* HybridMobileDeploy.xcodeproj */, + 5451ACE61B86E34300E2A7DF /* RCTTest.xcodeproj */, + 81551E0A1B3B427200F5B9F1 /* CodePush.xcodeproj */, 146833FF1AC3E56700842450 /* React.xcodeproj */, 00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */, 00C302AF1ABCB8E700DB3ED1 /* RCTAdSupport.xcodeproj */, @@ -326,9 +345,9 @@ 83CBB9F61A601CBA00E9B192 = { isa = PBXGroup; children = ( - 13B07FAE1A68108700A75B9A /* HybridMobileDeployCompanion */, + 13B07FAE1A68108700A75B9A /* CodePushDemoApp */, 832341AE1AAA6A7D00B99B32 /* Libraries */, - 00E356EF1AD99517003FC87E /* HybridMobileDeployCompanionTests */, + 00E356EF1AD99517003FC87E /* CodePushDemoAppTests */, 83CBBA001A601CBA00E9B192 /* Products */, ); indentWidth = 2; @@ -338,8 +357,8 @@ 83CBBA001A601CBA00E9B192 /* Products */ = { isa = PBXGroup; children = ( - 13B07F961A680F5B00A75B9A /* HybridMobileDeployCompanion.app */, - 00E356EE1AD99517003FC87E /* HybridMobileDeployCompanionTests.xctest */, + 13B07F961A680F5B00A75B9A /* CodePushDemoApp.app */, + 00E356EE1AD99517003FC87E /* CodePushDemoAppTests.xctest */, ); name = Products; sourceTree = ""; @@ -347,9 +366,9 @@ /* End PBXGroup section */ /* Begin PBXNativeTarget section */ - 00E356ED1AD99517003FC87E /* HybridMobileDeployCompanionTests */ = { + 00E356ED1AD99517003FC87E /* CodePushDemoAppTests */ = { isa = PBXNativeTarget; - buildConfigurationList = 00E357021AD99517003FC87E /* Build configuration list for PBXNativeTarget "HybridMobileDeployCompanionTests" */; + buildConfigurationList = 00E357021AD99517003FC87E /* Build configuration list for PBXNativeTarget "CodePushDemoAppTests" */; buildPhases = ( 00E356EA1AD99517003FC87E /* Sources */, 00E356EB1AD99517003FC87E /* Frameworks */, @@ -360,14 +379,14 @@ dependencies = ( 00E356F51AD99517003FC87E /* PBXTargetDependency */, ); - name = HybridMobileDeployCompanionTests; - productName = HybridMobileDeployCompanionTests; - productReference = 00E356EE1AD99517003FC87E /* HybridMobileDeployCompanionTests.xctest */; + name = CodePushDemoAppTests; + productName = CodePushDemoAppTests; + productReference = 00E356EE1AD99517003FC87E /* CodePushDemoAppTests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; - 13B07F861A680F5B00A75B9A /* HybridMobileDeployCompanion */ = { + 13B07F861A680F5B00A75B9A /* CodePushDemoApp */ = { isa = PBXNativeTarget; - buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "HybridMobileDeployCompanion" */; + buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "CodePushDemoApp" */; buildPhases = ( 13B07F871A680F5B00A75B9A /* Sources */, 13B07F8C1A680F5B00A75B9A /* Frameworks */, @@ -377,9 +396,9 @@ ); dependencies = ( ); - name = HybridMobileDeployCompanion; + name = CodePushDemoApp; productName = "Hello World"; - productReference = 13B07F961A680F5B00A75B9A /* HybridMobileDeployCompanion.app */; + productReference = 13B07F961A680F5B00A75B9A /* CodePushDemoApp.app */; productType = "com.apple.product-type.application"; }; /* End PBXNativeTarget section */ @@ -389,7 +408,7 @@ isa = PBXProject; attributes = { LastUpgradeCheck = 0610; - ORGANIZATIONNAME = Facebook; + ORGANIZATIONNAME = Microsoft; TargetAttributes = { 00E356ED1AD99517003FC87E = { CreatedOnToolsVersion = 6.2; @@ -397,7 +416,7 @@ }; }; }; - buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "HybridMobileDeployCompanion" */; + buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "CodePushDemoApp" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; @@ -411,7 +430,7 @@ projectReferences = ( { ProductGroup = 81551E0B1B3B427200F5B9F1 /* Products */; - ProjectRef = 81551E0A1B3B427200F5B9F1 /* HybridMobileDeploy.xcodeproj */; + ProjectRef = 81551E0A1B3B427200F5B9F1 /* CodePush.xcodeproj */; }, { ProductGroup = 00C302A81ABCB8CE00DB3ED1 /* Products */; @@ -441,6 +460,10 @@ ProductGroup = 139105B71AF99BAD00B5F7CC /* Products */; ProjectRef = 139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */; }, + { + ProductGroup = 5451ACE71B86E34300E2A7DF /* Products */; + ProjectRef = 5451ACE61B86E34300E2A7DF /* RCTTest.xcodeproj */; + }, { ProductGroup = 832341B11AAA6A8300B99B32 /* Products */; ProjectRef = 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */; @@ -460,8 +483,8 @@ ); projectRoot = ""; targets = ( - 13B07F861A680F5B00A75B9A /* HybridMobileDeployCompanion */, - 00E356ED1AD99517003FC87E /* HybridMobileDeployCompanionTests */, + 13B07F861A680F5B00A75B9A /* CodePushDemoApp */, + 00E356ED1AD99517003FC87E /* CodePushDemoAppTests */, ); }; /* End PBXProject section */ @@ -530,6 +553,13 @@ remoteRef = 146834031AC3E56700842450 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; + 5451ACEB1B86E34300E2A7DF /* libRCTTest.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libRCTTest.a; + remoteRef = 5451ACEA1B86E34300E2A7DF /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; 78C398B91ACF4ADC00677621 /* libRCTLinking.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; @@ -537,10 +567,10 @@ remoteRef = 78C398B81ACF4ADC00677621 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; - 81551E0F1B3B427200F5B9F1 /* libHybridMobileDeploy.a */ = { + 81551E0F1B3B427200F5B9F1 /* libCodePush.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; - path = libHybridMobileDeploy.a; + path = libCodePush.a; remoteRef = 81551E0E1B3B427200F5B9F1 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -565,7 +595,6 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - 008F07F31AC5B25A0029DE68 /* main.jsbundle in Resources */, 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */, 13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */, ); @@ -578,7 +607,8 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 00E356F31AD99517003FC87E /* HybridMobileDeployCompanionTests.m in Sources */, + 5451ACBA1B86A5B600E2A7DF /* QueryUpdateTests.m in Sources */, + 54D774BA1B87DAF800F2ABF8 /* ApplyUpdateTests.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -596,7 +626,7 @@ /* Begin PBXTargetDependency section */ 00E356F51AD99517003FC87E /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = 13B07F861A680F5B00A75B9A /* HybridMobileDeployCompanion */; + target = 13B07F861A680F5B00A75B9A /* CodePushDemoApp */; targetProxy = 00E356F41AD99517003FC87E /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ @@ -626,11 +656,11 @@ "DEBUG=1", "$(inherited)", ); - INFOPLIST_FILE = HybridMobileDeployCompanionTests/Info.plist; + INFOPLIST_FILE = CodePushDemoAppTests/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 8.2; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_NAME = "$(TARGET_NAME)"; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/HybridMobileDeployCompanion.app/HybridMobileDeployCompanion"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/CodePushDemoApp.app/CodePushDemoApp"; }; name = Debug; }; @@ -643,11 +673,11 @@ "$(SDKROOT)/Developer/Library/Frameworks", "$(inherited)", ); - INFOPLIST_FILE = HybridMobileDeployCompanionTests/Info.plist; + INFOPLIST_FILE = CodePushDemoAppTests/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 8.2; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_NAME = "$(TARGET_NAME)"; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/HybridMobileDeployCompanion.app/HybridMobileDeployCompanion"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/CodePushDemoApp.app/CodePushDemoApp"; }; name = Release; }; @@ -664,7 +694,7 @@ INFOPLIST_FILE = "$(SRCROOT)/iOS/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; OTHER_LDFLAGS = "-ObjC"; - PRODUCT_NAME = HybridMobileDeployCompanion; + PRODUCT_NAME = CodePushDemoApp; }; name = Debug; }; @@ -681,7 +711,7 @@ INFOPLIST_FILE = "$(SRCROOT)/iOS/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; OTHER_LDFLAGS = "-ObjC"; - PRODUCT_NAME = HybridMobileDeployCompanion; + PRODUCT_NAME = CodePushDemoApp; }; name = Release; }; @@ -774,7 +804,7 @@ /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ - 00E357021AD99517003FC87E /* Build configuration list for PBXNativeTarget "HybridMobileDeployCompanionTests" */ = { + 00E357021AD99517003FC87E /* Build configuration list for PBXNativeTarget "CodePushDemoAppTests" */ = { isa = XCConfigurationList; buildConfigurations = ( 00E356F61AD99517003FC87E /* Debug */, @@ -783,7 +813,7 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "HybridMobileDeployCompanion" */ = { + 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "CodePushDemoApp" */ = { isa = XCConfigurationList; buildConfigurations = ( 13B07F941A680F5B00A75B9A /* Debug */, @@ -792,7 +822,7 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "HybridMobileDeployCompanion" */ = { + 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "CodePushDemoApp" */ = { isa = XCConfigurationList; buildConfigurations = ( 83CBBA201A601CBA00E9B192 /* Debug */, diff --git a/HybridMobileDeploy.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Examples/CodePushDemoApp/CodePushDemoApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata similarity index 100% rename from HybridMobileDeploy.xcodeproj/project.xcworkspace/contents.xcworkspacedata rename to Examples/CodePushDemoApp/CodePushDemoApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata diff --git a/Examples/HybridMobileDeployCompanion/HybridMobileDeployCompanion.xcodeproj/xcshareddata/xcschemes/HybridMobileDeployCompanion.xcscheme b/Examples/CodePushDemoApp/CodePushDemoApp.xcodeproj/xcshareddata/xcschemes/CodePushDemoApp.xcscheme similarity index 72% rename from Examples/HybridMobileDeployCompanion/HybridMobileDeployCompanion.xcodeproj/xcshareddata/xcschemes/HybridMobileDeployCompanion.xcscheme rename to Examples/CodePushDemoApp/CodePushDemoApp.xcodeproj/xcshareddata/xcschemes/CodePushDemoApp.xcscheme index d162955..a61b64b 100644 --- a/Examples/HybridMobileDeployCompanion/HybridMobileDeployCompanion.xcodeproj/xcshareddata/xcschemes/HybridMobileDeployCompanion.xcscheme +++ b/Examples/CodePushDemoApp/CodePushDemoApp.xcodeproj/xcshareddata/xcschemes/CodePushDemoApp.xcscheme @@ -15,9 +15,9 @@ + BuildableName = "CodePushDemoApp.app" + BlueprintName = "CodePushDemoApp" + ReferencedContainer = "container:CodePushDemoApp.xcodeproj"> + BuildableName = "CodePushDemoAppTests.xctest" + BlueprintName = "CodePushDemoAppTests" + ReferencedContainer = "container:CodePushDemoApp.xcodeproj"> @@ -47,19 +47,24 @@ + BuildableName = "CodePushDemoAppTests.xctest" + BlueprintName = "CodePushDemoAppTests" + ReferencedContainer = "container:CodePushDemoApp.xcodeproj"> + + + + + BuildableName = "CodePushDemoApp.app" + BlueprintName = "CodePushDemoApp" + ReferencedContainer = "container:CodePushDemoApp.xcodeproj"> @@ -77,9 +82,9 @@ + BuildableName = "CodePushDemoApp.app" + BlueprintName = "CodePushDemoApp" + ReferencedContainer = "container:CodePushDemoApp.xcodeproj"> @@ -96,9 +101,9 @@ + BuildableName = "CodePushDemoApp.app" + BlueprintName = "CodePushDemoApp" + ReferencedContainer = "container:CodePushDemoApp.xcodeproj"> diff --git a/Examples/CodePushDemoApp/CodePushDemoAppTests/ApplyUpdateTests.m b/Examples/CodePushDemoApp/CodePushDemoAppTests/ApplyUpdateTests.m new file mode 100644 index 0000000..acaeda8 --- /dev/null +++ b/Examples/CodePushDemoApp/CodePushDemoAppTests/ApplyUpdateTests.m @@ -0,0 +1,98 @@ +#import +#import +#import + +#import "RCTBridge.h" +#import "RCTBridgeModule.h" +#import "RCTDefines.h" +#import "RCTRootView.h" +#import "RCTRedBox.h" +#import "RCTAssert.h" + +#define FB_REFERENCE_IMAGE_DIR "\"$(SOURCE_ROOT)/$(PROJECT_NAME)Tests/ReferenceImages\"" + +#define TIMEOUT_SECONDS 60 +#define TEXT_TO_LOOK_FOR @"If you see this, you have successfully installed an update!" + +@interface ApplyUpdateTests : XCTestCase + +@end + +@implementation ApplyUpdateTests +{ + RCTTestRunner *_runner; + NSString* app; +} + +- (void)setUp +{ + app = @"CodePushDemoAppTests/ApplyUpdateTests/ApplyUpdateTestApp"; +#if __LP64__ + RCTAssert(false, @"Tests should be run on 32-bit device simulators (e.g. iPhone 5)"); +#endif + + NSOperatingSystemVersion version = [[NSProcessInfo processInfo] operatingSystemVersion]; + RCTAssert(version.majorVersion == 8 || version.minorVersion == 3, @"Tests should be run on iOS 8.3, found %zd.%zd.%zd", version.majorVersion, version.minorVersion, version.patchVersion); +} + + +- (BOOL)findSubviewInView:(UIView *)view matching:(BOOL(^)(UIView *view))test +{ + if (test(view)) { + return YES; + } + for (UIView *subview in [view subviews]) { + if ([self findSubviewInView:subview matching:test]) { + return YES; + } + } + return NO; +} + +#pragma mark Logic Tests +- (void)testDownloadAndApplyUpdate +{ + NSString *sanitizedAppName = [app stringByReplacingOccurrencesOfString:@"/" withString:@"-"]; + sanitizedAppName = [sanitizedAppName stringByReplacingOccurrencesOfString:@"\\" withString:@"-"]; + NSURL* scriptURL; + +#if RUNNING_ON_CI + scriptURL = [[NSBundle bundleForClass:[RCTBridge class]] URLForResource:@"main" withExtension:@"jsbundle"]; + RCTAssert(_scriptURL != nil, @"Could not locate main.jsBundle"); +#else + scriptURL = [NSURL URLWithString:[NSString stringWithFormat:@"http://localhost:8081/%@.includeRequire.runModule.bundle?dev=true", app]]; +#endif + + RCTBridge *bridge = [[RCTBridge alloc] initWithBundleURL:scriptURL + moduleProvider:nil + launchOptions:nil]; + RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge moduleName:@"DownloadAndApplyUpdateTest"]; + + NSDate *date = [NSDate dateWithTimeIntervalSinceNow:TIMEOUT_SECONDS]; + BOOL foundElement = NO; + NSString *redboxError = nil; + + while ([date timeIntervalSinceNow] > 0 && !foundElement && !redboxError) { + [[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; + [[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; + redboxError = [[RCTRedBox sharedInstance] currentErrorMessage]; + UIViewController *vc = [UIApplication sharedApplication].delegate.window.rootViewController; + foundElement = [self findSubviewInView:vc.view matching:^BOOL(UIView *view) { + if ([NSStringFromClass([view class]) isEqualToString:@"RCTText"]){ + NSString *text = [(id)view textStorage].string; + if ([text isEqualToString:TEXT_TO_LOOK_FOR]) { + return YES; + } + } + + return NO; + }]; + } + + XCTAssertNil(redboxError, @"RedBox error: %@", redboxError); + XCTAssertTrue(foundElement, @"Cound't find element with text '%@' in %d seconds", TEXT_TO_LOOK_FOR, TIMEOUT_SECONDS); + +} + + +@end diff --git a/Examples/CodePushDemoApp/CodePushDemoAppTests/ApplyUpdateTests/ApplyUpdateTestApp.js b/Examples/CodePushDemoApp/CodePushDemoAppTests/ApplyUpdateTests/ApplyUpdateTestApp.js new file mode 100644 index 0000000..37cbb33 --- /dev/null +++ b/Examples/CodePushDemoApp/CodePushDemoAppTests/ApplyUpdateTests/ApplyUpdateTestApp.js @@ -0,0 +1,82 @@ +/** + * @providesModule QueryUpdateTestApp + */ +'use strict'; + +var React = require('react-native'); + +var { + AppRegistry, + ScrollView, + StyleSheet, + Text, + TouchableOpacity, + View, +} = React; + +var TESTS = [ + require('./DownloadAndApplyUpdateTest') +]; + +TESTS.forEach( + (test) => AppRegistry.registerComponent(test.displayName, () => test) +); + +var ApplyUpdateTestApp = 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 environment with cmd+U in + Xcode. + + + + {TESTS.map((test) => [ + this.setState({test})} + style={styles.row}> + + {test.displayName} + + , + + ])} + + + ); + } +}); + +var styles = StyleSheet.create({ + container: { + backgroundColor: 'white', + marginTop: 40, + margin: 15, + }, + row: { + padding: 10, + }, + testName: { + fontWeight: '500', + }, + separator: { + height: 1, + backgroundColor: '#bbbbbb', + } +}); + +AppRegistry.registerComponent('ApplyUpdateTestApp', () => ApplyUpdateTestApp); \ No newline at end of file diff --git a/Examples/CodePushDemoApp/CodePushDemoAppTests/ApplyUpdateTests/CodePushDemoApp.ios.js b/Examples/CodePushDemoApp/CodePushDemoAppTests/ApplyUpdateTests/CodePushDemoApp.ios.js new file mode 100644 index 0000000..dd8fef1 --- /dev/null +++ b/Examples/CodePushDemoApp/CodePushDemoAppTests/ApplyUpdateTests/CodePushDemoApp.ios.js @@ -0,0 +1,60 @@ +/** + * Sample React Native App + * https://github.com/facebook/react-native + */ +'use strict'; + +var React = require('react-native'); +var { + AppRegistry, + StyleSheet, + Text, + TouchableOpacity, + View, +} = React; + +var RCTTestModule = require('NativeModules').TestModule; +var NativeCodePush = require('react-native').NativeModules.CodePush; + +var CodePushDemoApp = React.createClass({ + componentDidMount: function() { + NativeCodePush.setUsingTestFolder(true); + NativeCodePush.getLocalPackage(function(err, savedPackage) { + if (err || !savedPackage) { + throw new Error("The updated package was not saved"); + } else { + var testPackage = require("./TestPackage"); + for (var key in testPackage) { + if (savedPackage[key] !== testPackage[key]) { + throw new Error("The local package is still different from the updated package after installation"); + } + } + } + }); + }, + render: function() { + return ( + + + If you see this, you have successfully installed an update! + + + ); + } +}); + +var styles = StyleSheet.create({ + container: { + flex: 1, + justifyContent: 'center', + alignItems: 'center', + backgroundColor: '#F5FCFF', + }, + welcome: { + fontSize: 20, + textAlign: 'center', + margin: 10, + } +}); + +AppRegistry.registerComponent('CodePushDemoApp', () => CodePushDemoApp); diff --git a/Examples/CodePushDemoApp/CodePushDemoAppTests/ApplyUpdateTests/DownloadAndApplyUpdateTest.js b/Examples/CodePushDemoApp/CodePushDemoAppTests/ApplyUpdateTests/DownloadAndApplyUpdateTest.js new file mode 100644 index 0000000..5b6b510 --- /dev/null +++ b/Examples/CodePushDemoApp/CodePushDemoAppTests/ApplyUpdateTests/DownloadAndApplyUpdateTest.js @@ -0,0 +1,58 @@ +'use strict'; + +var React = require('react-native'); +var CodePushSdk = require('react-native-code-push'); +var NativeBridge = require('react-native').NativeModules.CodePush; + +var { + Text, + View, +} = React; + +var DownloadAndApplyUpdateTest = 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.setUp(); + this.runTest(); + } + }, + + setUp(callWhenDone) { + var mockConfiguration = { appVersion : "1.5.0" }; + NativeBridge.setUsingTestFolder(true); + CodePushSdk.setUpTestDependencies(null, mockConfiguration, NativeBridge); + }, + + runTest() { + var update = require("./TestPackage"); + CodePushSdk.installUpdate(update); + }, + + render() { + return ( + + + {this.constructor.displayName + ': '} + {this.state.done ? 'Done' : 'Testing...'} + + + ); + } +}); + +DownloadAndApplyUpdateTest.displayName = 'DownloadAndApplyUpdateTest'; + +module.exports = DownloadAndApplyUpdateTest; \ No newline at end of file diff --git a/Examples/CodePushDemoApp/CodePushDemoAppTests/ApplyUpdateTests/TestPackage.js b/Examples/CodePushDemoApp/CodePushDemoAppTests/ApplyUpdateTests/TestPackage.js new file mode 100644 index 0000000..7d7308f --- /dev/null +++ b/Examples/CodePushDemoApp/CodePushDemoAppTests/ApplyUpdateTests/TestPackage.js @@ -0,0 +1,13 @@ +var testPackage = { + downloadUrl: "http://localhost:8081/CodePushDemoAppTests/ApplyUpdateTests/CodePushDemoApp.ios.includeRequire.runModule.bundle?dev=true", + description: "Angry flappy birds", + appVersion: "1.5.0", + label: "2.4.0", + isMandatory: false, + isAvailable: true, + updateAppVersion: false, + packageHash: "hash240", + packageSize: 1024 +}; + +module.exports = testPackage; \ No newline at end of file diff --git a/Examples/HybridMobileDeployCompanion/HybridMobileDeployCompanionTests/Info.plist b/Examples/CodePushDemoApp/CodePushDemoAppTests/Info.plist similarity index 100% rename from Examples/HybridMobileDeployCompanion/HybridMobileDeployCompanionTests/Info.plist rename to Examples/CodePushDemoApp/CodePushDemoAppTests/Info.plist diff --git a/Examples/CodePushDemoApp/CodePushDemoAppTests/QueryUpdateTests.m b/Examples/CodePushDemoApp/CodePushDemoAppTests/QueryUpdateTests.m new file mode 100644 index 0000000..1e99ea0 --- /dev/null +++ b/Examples/CodePushDemoApp/CodePushDemoAppTests/QueryUpdateTests.m @@ -0,0 +1,61 @@ +#import +#import +#import + +#import "RCTAssert.h" + +#define FB_REFERENCE_IMAGE_DIR "\"$(SOURCE_ROOT)/$(PROJECT_NAME)Tests/ReferenceImages\"" + +@interface QueryUpdateTests : XCTestCase + +@end + +@implementation QueryUpdateTests +{ + RCTTestRunner *_runner; +} + +- (void)setUp +{ +#if __LP64__ + RCTAssert(false, @"Tests should be run on 32-bit device simulators (e.g. iPhone 5)"); +#endif + + NSOperatingSystemVersion version = [[NSProcessInfo processInfo] operatingSystemVersion]; + RCTAssert(version.majorVersion == 8 || version.minorVersion == 3, @"Tests should be run on iOS 8.3, found %zd.%zd.%zd", version.majorVersion, version.minorVersion, version.patchVersion); + _runner = RCTInitRunnerForApp(@"CodePushDemoAppTests/QueryUpdateTests/QueryUpdateTestApp", nil); +} + +#pragma mark Logic Tests +- (void)testNoRemotePackage +{ + + [_runner runTest:_cmd module:@"NoRemotePackageTest"]; +} + +- (void)testNoRemotePackageWithSameAppVersion +{ + [_runner runTest:_cmd + module:@"NoRemotePackageWithSameAppVersionTest"]; +} + +- (void)testFirstUpdate +{ + [_runner runTest:_cmd + module:@"FirstUpdateTest"]; +} + +- (void)testNewUpdate +{ + [_runner runTest:_cmd + module:@"NewUpdateTest"]; +} + +- (void)testSamePackage +{ + [_runner runTest:_cmd + module:@"SamePackageTest"]; +} + + +@end diff --git a/Examples/CodePushDemoApp/CodePushDemoAppTests/QueryUpdateTests/FirstUpdateTest.js b/Examples/CodePushDemoApp/CodePushDemoAppTests/QueryUpdateTests/FirstUpdateTest.js new file mode 100644 index 0000000..a93b89e --- /dev/null +++ b/Examples/CodePushDemoApp/CodePushDemoAppTests/QueryUpdateTests/FirstUpdateTest.js @@ -0,0 +1,95 @@ +'use strict'; + +var RCTTestModule = require('NativeModules').TestModule; +var React = require('react-native'); +var CodePushSdk = require('react-native-code-push'); +var NativeBridge = require('react-native').NativeModules.CodePush; + +var { + Text, + View, +} = React; + +var FirstUpdateTest = 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.setUp(this.runTest); + } + }, + + setUp(callWhenDone) { + var mockAcquisitionSdk = { + latestPackage: { + downloadUrl: "http://www.windowsazure.com/blobs/awperoiuqpweru", + description: "Angry flappy birds", + appVersion: "1.5.0", + label: "2.4.0", + isMandatory: false, + isAvailable: true, + updateAppVersion: false, + packageHash: "hash240", + packageSize: 1024 + }, + queryUpdateWithCurrentPackage: function(queryPackage, callback){ + if (!this.latestPackage || queryPackage.appVersion !== this.latestPackage.appVersion || + queryPackage.packageHash == this.latestPackage.packageHash) { + callback(/*err:*/ null, false); + } else { + callback(/*err:*/ null, this.latestPackage); + } + } + }; + + var mockConfiguration = { appVersion : "1.5.0" }; + NativeBridge.setUsingTestFolder(true); + CodePushSdk.setUpTestDependencies(mockAcquisitionSdk, mockConfiguration, NativeBridge); + + NativeBridge.removeLocalPackage(function(err){ + if (err) { + throw new Error('Setup: Error removing local package'); + } else { + callWhenDone(); + } + }); + }, + + runTest() { + CodePushSdk.queryUpdate((err, update) => { + if (update) { + this.setState({done: true}, RCTTestModule.markTestCompleted); + } else if (err) { + throw new Error(err.message); + } else { + throw new Error('SDK should return a package when there is an update'); + } + }); + }, + + render() { + return ( + + + {this.constructor.displayName + ': '} + {this.state.done ? 'Done' : 'Testing...'} + + + ); + } +}); + +FirstUpdateTest.displayName = 'FirstUpdateTest'; + +module.exports = FirstUpdateTest; \ No newline at end of file diff --git a/Examples/CodePushDemoApp/CodePushDemoAppTests/QueryUpdateTests/NewUpdateTest.js b/Examples/CodePushDemoApp/CodePushDemoAppTests/QueryUpdateTests/NewUpdateTest.js new file mode 100644 index 0000000..36d27a9 --- /dev/null +++ b/Examples/CodePushDemoApp/CodePushDemoAppTests/QueryUpdateTests/NewUpdateTest.js @@ -0,0 +1,107 @@ +'use strict'; + +var RCTTestModule = require('NativeModules').TestModule; +var React = require('react-native'); +var CodePushSdk = require('react-native-code-push'); +var NativeBridge = require('react-native').NativeModules.CodePush; + +var { + Text, + View, +} = React; + +var NewUpdateTest = 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.setUp(this.runTest); + } + }, + + setUp(callWhenDone) { + var mockAcquisitionSdk = { + latestPackage: { + downloadUrl: "http://www.windowsazure.com/blobs/awperoiuqpweru", + description: "Angry flappy birds", + appVersion: "1.5.0", + label: "2.4.0", + isMandatory: false, + isAvailable: true, + updateAppVersion: false, + packageHash: "hash240", + packageSize: 1024 + }, + queryUpdateWithCurrentPackage: function(queryPackage, callback){ + if (!this.latestPackage || queryPackage.appVersion !== this.latestPackage.appVersion || + queryPackage.packageHash == this.latestPackage.packageHash) { + callback(/*err:*/ null, false); + } else { + callback(/*err:*/ null, this.latestPackage); + } + } + }; + + var localPackage = JSON.stringify({ + downloadURL: "http://www.windowsazure.com/blobs/awperoiuqpweru", + description: "Angry flappy birds", + appVersion: "1.5.0", + label: "2.4.0", + isMandatory: false, + isAvailable: true, + updateAppVersion: false, + packageHash: "hash123", + packageSize: 1024 + }); + + var mockConfiguration = { appVersion : "1.5.0" }; + NativeBridge.setUsingTestFolder(true); + CodePushSdk.setUpTestDependencies(mockAcquisitionSdk, mockConfiguration, NativeBridge); + + NativeBridge.writeToLocalPackage(localPackage, function(err){ + if (err) { + throw new Error('Setup: Error removing local package'); + } else { + callWhenDone(); + } + }); + }, + + runTest() { + CodePushSdk.queryUpdate((err, update) => { + if (update) { + this.setState({done: true}, RCTTestModule.markTestCompleted); + } else if (err) { + throw new Error(err.message); + } else { + throw new Error('SDK should return a package when there is a new update'); + } + }); + }, + + render() { + return ( + + + {this.constructor.displayName + ': '} + {this.state.done ? 'Done' : 'Testing...'} + + + ); + } +}); + +NewUpdateTest.displayName = 'NewUpdateTest'; + +module.exports = NewUpdateTest; \ No newline at end of file diff --git a/Examples/CodePushDemoApp/CodePushDemoAppTests/QueryUpdateTests/NoRemotePackageTest.js b/Examples/CodePushDemoApp/CodePushDemoAppTests/QueryUpdateTests/NoRemotePackageTest.js new file mode 100644 index 0000000..10c8424 --- /dev/null +++ b/Examples/CodePushDemoApp/CodePushDemoAppTests/QueryUpdateTests/NoRemotePackageTest.js @@ -0,0 +1,78 @@ +'use strict'; + +var React = require('react-native'); +var CodePushSdk = require('react-native-code-push'); +var NativeBridge = require('react-native').NativeModules.CodePush; +var RCTTestModule = require('NativeModules').TestModule; + +var { + Text, + View, +} = React; + +var NoRemotePackageTest = 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.setUp(); + this.runTest(); + } + }, + + setUp() { + var mockAcquisitionSdk = { + latestPackage: null, + queryUpdateWithCurrentPackage: function(queryPackage, callback){ + if (!this.latestPackage || queryPackage.appVersion !== this.latestPackage.appVersion || + queryPackage.packageHash == this.latestPackage.packageHash) { + callback(/*err:*/ null, false); + } else { + callback(/*err:*/ null, latestPackage); + } + } + }; + + var mockConfiguration = { appVersion : "1.5.0" }; + NativeBridge.setUsingTestFolder(true); + CodePushSdk.setUpTestDependencies(mockAcquisitionSdk, mockConfiguration, NativeBridge); + }, + + runTest() { + CodePushSdk.queryUpdate((err, update) => { + if (update) { + throw new Error('SDK should not return a package if remote does not contain a package'); + } else if (err) { + throw new Error(err.message); + } else { + this.setState({done: true}, RCTTestModule.markTestCompleted); + } + }); + }, + + render() { + return ( + + + {this.constructor.displayName + ': '} + {this.state.done ? 'Done' : 'Testing...'} + + + ); + } +}); + +NoRemotePackageTest.displayName = 'NoRemotePackageTest'; + +module.exports = NoRemotePackageTest; \ No newline at end of file diff --git a/Examples/CodePushDemoApp/CodePushDemoAppTests/QueryUpdateTests/NoRemotePackageWithSameAppVersionTest.js b/Examples/CodePushDemoApp/CodePushDemoAppTests/QueryUpdateTests/NoRemotePackageWithSameAppVersionTest.js new file mode 100644 index 0000000..1d7c5ec --- /dev/null +++ b/Examples/CodePushDemoApp/CodePushDemoAppTests/QueryUpdateTests/NoRemotePackageWithSameAppVersionTest.js @@ -0,0 +1,106 @@ +'use strict'; + +var React = require('react-native'); +var RCTTestModule = React.NativeModules.TestModule; +var CodePushSdk = require('react-native-code-push'); +var NativeBridge = require('react-native').NativeModules.CodePush; + +var { + Text, + View, +} = React; + +var NoRemotePackageWithSameAppVersionTest = 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.setUp(this.runTest); + } + }, + + setUp(callWhenDone) { + var mockAcquisitionSdk = { + latestPackage: { + downloadUrl: "http://www.windowsazure.com/blobs/awperoiuqpweru", + description: "Angry flappy birds", + appVersion: "1.5.0", + label: "2.4.0", + isMandatory: false, + isAvailable: true, + updateAppVersion: false, + packageHash: "hash240", + packageSize: 1024 + }, + queryUpdateWithCurrentPackage: function(queryPackage, callback){ + if (!this.latestPackage || queryPackage.appVersion !== this.latestPackage.appVersion || + queryPackage.packageHash == this.latestPackage.packageHash) { + callback(/*err:*/ null, false); + } else { + callback(/*err:*/ null, latestPackage); + } + } + }; + + NativeBridge.setUsingTestFolder(true); + var localPackage = JSON.stringify({ + downloadURL: "http://www.windowsazure.com/blobs/awperoiuqpweru", + description: "Angry flappy birds", + appVersion: "1.0.0", + label: "2.4.0", + isMandatory: false, + isAvailable: true, + updateAppVersion: false, + packageHash: "hash123", + packageSize: 1024 + }); + + var mockConfiguration = { appVersion : "1.0.0" }; + CodePushSdk.setUpTestDependencies(mockAcquisitionSdk, mockConfiguration, NativeBridge); + NativeBridge.writeToLocalPackage(localPackage, function(err){ + if (err) { + throw new Error('Setup: Error removing local package'); + } else { + callWhenDone(); + } + }); + }, + + runTest() { + CodePushSdk.queryUpdate((err, update) => { + if (update) { + throw new Error('SDK should not return a package if remote package is of a different version'); + } else if (err) { + throw new Error(err.message); + } else { + this.setState({done: true}, RCTTestModule.markTestCompleted); + } + }); + }, + + render() { + return ( + + + {this.constructor.displayName + ': '} + {this.state.done ? 'Done' : 'Testing...'} + + + ); + } +}); + +NoRemotePackageWithSameAppVersionTest.displayName = 'NoRemotePackageWithSameAppVersionTest'; + +module.exports = NoRemotePackageWithSameAppVersionTest; \ No newline at end of file diff --git a/Examples/CodePushDemoApp/CodePushDemoAppTests/QueryUpdateTests/QueryUpdateTestApp.js b/Examples/CodePushDemoApp/CodePushDemoAppTests/QueryUpdateTests/QueryUpdateTestApp.js new file mode 100644 index 0000000..f55c484 --- /dev/null +++ b/Examples/CodePushDemoApp/CodePushDemoAppTests/QueryUpdateTests/QueryUpdateTestApp.js @@ -0,0 +1,86 @@ +/** + * @providesModule QueryUpdateTestApp + */ +'use strict'; + +var React = require('react-native'); + +var { + AppRegistry, + ScrollView, + StyleSheet, + Text, + TouchableOpacity, + View, +} = React; + +var TESTS = [ + require('./NoRemotePackageTest'), + require('./NoRemotePackageWithSameAppVersionTest'), + require('./FirstUpdateTest'), + require('./NewUpdateTest'), + require('./SamePackageTest') +]; + +TESTS.forEach( + (test) => AppRegistry.registerComponent(test.displayName, () => test) +); + +var QueryUpdateTestApp = 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 environment with cmd+U in + Xcode. + + + + {TESTS.map((test) => [ + this.setState({test})} + style={styles.row}> + + {test.displayName} + + , + + ])} + + + ); + } +}); + +var styles = StyleSheet.create({ + container: { + backgroundColor: 'white', + marginTop: 40, + margin: 15, + }, + row: { + padding: 10, + }, + testName: { + fontWeight: '500', + }, + separator: { + height: 1, + backgroundColor: '#bbbbbb', + } +}); + +AppRegistry.registerComponent('QueryUpdateTestApp', () => QueryUpdateTestApp); \ No newline at end of file diff --git a/Examples/CodePushDemoApp/CodePushDemoAppTests/QueryUpdateTests/SamePackageTest.js b/Examples/CodePushDemoApp/CodePushDemoAppTests/QueryUpdateTests/SamePackageTest.js new file mode 100644 index 0000000..a96a1a9 --- /dev/null +++ b/Examples/CodePushDemoApp/CodePushDemoAppTests/QueryUpdateTests/SamePackageTest.js @@ -0,0 +1,107 @@ +'use strict'; + +var RCTTestModule = require('NativeModules').TestModule; +var React = require('react-native'); +var CodePushSdk = require('react-native-code-push'); +var NativeBridge = require('react-native').NativeModules.CodePush; + +var { + Text, + View, +} = React; + +var SamePackageTest = 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.setUp(this.runTest); + } + }, + + setUp(callWhenDone) { + var mockAcquisitionSdk = { + latestPackage: { + downloadUrl: "http://www.windowsazure.com/blobs/awperoiuqpweru", + description: "Angry flappy birds", + appVersion: "1.5.0", + label: "2.4.0", + isMandatory: false, + isAvailable: true, + updateAppVersion: false, + packageHash: "hash240", + packageSize: 1024 + }, + queryUpdateWithCurrentPackage: function(queryPackage, callback){ + if (!this.latestPackage || queryPackage.appVersion !== this.latestPackage.appVersion || + queryPackage.packageHash == this.latestPackage.packageHash) { + callback(/*err:*/ null, false); + } else { + callback(/*err:*/ null, this.latestPackage); + } + } + }; + + var localPackage = JSON.stringify({ + downloadURL: "http://www.windowsazure.com/blobs/awperoiuqpweru", + description: "Angry flappy birds", + appVersion: "1.5.0", + label: "2.4.0", + isMandatory: false, + isAvailable: true, + updateAppVersion: false, + packageHash: "hash240", + packageSize: 1024 + }); + + var mockConfiguration = { appVersion : "1.5.0" }; + NativeBridge.setUsingTestFolder(true); + CodePushSdk.setUpTestDependencies(mockAcquisitionSdk, mockConfiguration, NativeBridge); + + NativeBridge.writeToLocalPackage(localPackage, function(err){ + if (err) { + throw new Error('Setup: Error removing local package'); + } else { + callWhenDone(); + } + }); + }, + + runTest() { + CodePushSdk.queryUpdate((err, update) => { + if (update) { + throw new Error('SDK should not return a package when local package is identical'); + } else if (err) { + throw new Error(err.message); + } else { + this.setState({done: true}, RCTTestModule.markTestCompleted); + } + }); + }, + + render() { + return ( + + + {this.constructor.displayName + ': '} + {this.state.done ? 'Done' : 'Testing...'} + + + ); + } +}); + +SamePackageTest.displayName = 'SamePackageTest'; + +module.exports = SamePackageTest; \ No newline at end of file diff --git a/Examples/CodePushDemoApp/CodePushDemoAppTests/README.md b/Examples/CodePushDemoApp/CodePushDemoAppTests/README.md new file mode 100644 index 0000000..f31ecb9 --- /dev/null +++ b/Examples/CodePushDemoApp/CodePushDemoAppTests/README.md @@ -0,0 +1,12 @@ + +Test Cases +--- +* QueryUpdateTests - Tests the functionality of querying for new app updates via the SDK + * testNoRemotePackage - Checks that when the remote server has no update packages available, CodePushSdk.queryUpdate does not return a new package nor throw an error. + * testNoRemotePackageWithSameAppVersion - Checks that when the remote server has an update with a different appVersion, the CodePushSdk.queryUpdate does not return a new package nor throw an error. + * testFirstUpdate - Checks that when there is no current package (for example, the current build is a fresh install from the app store) and the remote server has a new package, CodePushSdk.queryUpdate returns that new package without throwing an error. + * testNewUpdate - Checks that when the remote server has a new package with a different package hash and same version as the current package, CodePushSdk.queryUpdate returns that new package without throwing an error. + * testSamePackage - Checks that when the remote server has a package that is identical to the current package, CodePushSdk.queryUpdate does not return a new package nor throw an error. + +* ApplyUpdateTests - Tests the functionality of installing new app updates downloaded from the server via the SDK + * testDownloadAndApplyUpdate - Queries for a new update, downloads it and then verifies that from the UI that the new update has been installed. \ No newline at end of file diff --git a/Examples/CodePushDemoApp/bundle.sh b/Examples/CodePushDemoApp/bundle.sh new file mode 100644 index 0000000..1b41e14 --- /dev/null +++ b/Examples/CodePushDemoApp/bundle.sh @@ -0,0 +1,3 @@ +-pushd Examples/CodePushDemoApp +-react-native bundle +-popd \ No newline at end of file diff --git a/Examples/HybridMobileDeployCompanion/iOS/AppDelegate.h b/Examples/CodePushDemoApp/iOS/AppDelegate.h similarity index 100% rename from Examples/HybridMobileDeployCompanion/iOS/AppDelegate.h rename to Examples/CodePushDemoApp/iOS/AppDelegate.h diff --git a/Examples/HybridMobileDeployCompanion/iOS/AppDelegate.m b/Examples/CodePushDemoApp/iOS/AppDelegate.m similarity index 92% rename from Examples/HybridMobileDeployCompanion/iOS/AppDelegate.m rename to Examples/CodePushDemoApp/iOS/AppDelegate.m index a39a908..0182a28 100644 --- a/Examples/HybridMobileDeployCompanion/iOS/AppDelegate.m +++ b/Examples/CodePushDemoApp/iOS/AppDelegate.m @@ -11,7 +11,7 @@ #import "RCTRootView.h" -#import "HybridMobileDeploy.h" +#import "CodePush.h" @implementation AppDelegate @@ -33,7 +33,7 @@ * on the same Wi-Fi network. */ - //jsCodeLocation = [NSURL URLWithString:@"http://localhost:8081/index.ios.bundle"]; + //jsCodeLocation = [NSURL URLWithString:@"http://localhost:8081/index.ios.includeRequire.runModule.bundle?dev=true"]; /** * OPTION 2 @@ -45,10 +45,10 @@ * see http://facebook.github.io/react-native/docs/runningondevice.html */ - jsCodeLocation = [HybridMobileDeploy getBundleUrl]; + jsCodeLocation = [CodePush getBundleUrl]; RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation - moduleName:@"HybridMobileDeployCompanion" + moduleName:@"CodePushDemoApp" launchOptions:launchOptions]; self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; diff --git a/Examples/HybridMobileDeployCompanion/iOS/Base.lproj/LaunchScreen.xib b/Examples/CodePushDemoApp/iOS/Base.lproj/LaunchScreen.xib similarity index 93% rename from Examples/HybridMobileDeployCompanion/iOS/Base.lproj/LaunchScreen.xib rename to Examples/CodePushDemoApp/iOS/Base.lproj/LaunchScreen.xib index bb058f0..78681d3 100644 --- a/Examples/HybridMobileDeployCompanion/iOS/Base.lproj/LaunchScreen.xib +++ b/Examples/CodePushDemoApp/iOS/Base.lproj/LaunchScreen.xib @@ -18,7 +18,7 @@ -