diff --git a/Parse/Internal/PFInternalUtils.m b/Parse/Internal/PFInternalUtils.m index 8648df1e2..ed8775dfb 100644 --- a/Parse/Internal/PFInternalUtils.m +++ b/Parse/Internal/PFInternalUtils.m @@ -34,6 +34,7 @@ #import "PFMultiProcessFileLockController.h" #import "PFHash.h" #import "Parse_Private.h" +#import "ParseClientConfiguration_Private.h" #if TARGET_OS_IOS #import "PFProduct.h" diff --git a/Parse/Internal/ParseClientConfiguration_Private.h b/Parse/Internal/ParseClientConfiguration_Private.h index 6e075d10d..11a0d1874 100644 --- a/Parse/Internal/ParseClientConfiguration_Private.h +++ b/Parse/Internal/ParseClientConfiguration_Private.h @@ -11,11 +11,15 @@ NS_ASSUME_NONNULL_BEGIN +extern NSString *const _ParseDefaultServerURLString; + @interface ParseClientConfiguration () @property (nullable, nonatomic, copy, readwrite) NSString *applicationId; @property (nullable, nonatomic, copy, readwrite) NSString *clientKey; +@property (nonatomic, copy, readwrite) NSString *server; + @property (nonatomic, assign, readwrite, getter=isLocalDatastoreEnabled) BOOL localDatastoreEnabled; @property (nullable, nonatomic, copy, readwrite) NSString *applicationGroupIdentifier; diff --git a/Parse/Internal/Parse_Private.h b/Parse/Internal/Parse_Private.h index fc7cd3f12..176dd1f14 100644 --- a/Parse/Internal/Parse_Private.h +++ b/Parse/Internal/Parse_Private.h @@ -13,8 +13,6 @@ #import "ParseManager.h" -extern NSString *const _ParseDefaultServerURLString; - @class PFEventuallyQueue; @interface Parse () diff --git a/Parse/Parse.m b/Parse/Parse.m index 12e4457dc..c677a0d24 100644 --- a/Parse/Parse.m +++ b/Parse/Parse.m @@ -33,8 +33,6 @@ #import "PFCategoryLoader.h" -NSString *const _ParseDefaultServerURLString = @"https://api.parse.com/1"; - @implementation Parse static ParseManager *currentParseManager_; @@ -58,6 +56,7 @@ + (void)initialize { + (void)setApplicationId:(NSString *)applicationId clientKey:(NSString *)clientKey { currentParseConfiguration_.applicationId = applicationId; currentParseConfiguration_.clientKey = clientKey; + currentParseConfiguration_.server = [PFInternalUtils parseServerURLString]; // TODO: (nlutsenko) Clean this up after tests are updated. [self initializeWithConfiguration:currentParseConfiguration_]; @@ -77,7 +76,7 @@ + (void)initializeWithConfiguration:(ParseClientConfiguration *)configuration { @"'containingApplicationBundleIdentifier' must be non-nil in extension environment"); ParseManager *manager = [[ParseManager alloc] initWithConfiguration:configuration - serverURL:[NSURL URLWithString:[PFInternalUtils parseServerURLString]]]; + serverURL:[NSURL URLWithString:configuration.server]]; [manager startManaging]; currentParseManager_ = manager; diff --git a/Parse/ParseClientConfiguration.h b/Parse/ParseClientConfiguration.h index 40ff511ed..51a9d888a 100644 --- a/Parse/ParseClientConfiguration.h +++ b/Parse/ParseClientConfiguration.h @@ -41,6 +41,14 @@ NS_ASSUME_NONNULL_BEGIN */ @property (nullable, nonatomic, copy) NSString *clientKey; +/** + The URL of the server that is being used by the SDK. + Defaults to `https://api.parse.com/1`. + + @note Setting this property to a non-valid URL or `nil` will throw an `NSInvalidArgumentException`. + */ +@property (nonatomic, copy) NSString *server; + ///-------------------------------------- #pragma mark - Enabling Local Datastore ///-------------------------------------- @@ -106,6 +114,12 @@ NS_ASSUME_NONNULL_BEGIN */ @property (nullable, nonatomic, copy, readonly) NSString *clientKey; +/** + The URL of the server that is being used by the SDK. + Defaults to `https://api.parse.com/1` + */ +@property (nonatomic, copy, readonly) NSString *server; + ///-------------------------------------- #pragma mark - Enabling Local Datastore ///-------------------------------------- diff --git a/Parse/ParseClientConfiguration.m b/Parse/ParseClientConfiguration.m index 0a219754d..7a2d09d1e 100644 --- a/Parse/ParseClientConfiguration.m +++ b/Parse/ParseClientConfiguration.m @@ -17,6 +17,8 @@ #import "PFHash.h" #import "PFObjectUtilities.h" +NSString *const _ParseDefaultServerURLString = @"https://api.parse.com/1"; + @implementation ParseClientConfiguration ///-------------------------------------- @@ -32,6 +34,7 @@ - (instancetype)initEmpty { if (!self) return nil; _networkRetryAttempts = PFCommandRunningDefaultMaxAttemptsCount; + _server = [_ParseDefaultServerURLString copy]; return self; } @@ -57,28 +60,34 @@ + (instancetype)configurationWithBlock:(void (^)(id_applicationId = [self->_applicationId copy]; configuration->_clientKey = [self->_clientKey copy]; + configuration->_server = [self.server copy]; configuration->_localDatastoreEnabled = self->_localDatastoreEnabled; configuration->_applicationGroupIdentifier = [self->_applicationGroupIdentifier copy]; configuration->_containingApplicationBundleIdentifier = [self->_containingApplicationBundleIdentifier copy]; diff --git a/Tests/Unit/CommandUnitTests.m b/Tests/Unit/CommandUnitTests.m index 353001328..2acbbce29 100644 --- a/Tests/Unit/CommandUnitTests.m +++ b/Tests/Unit/CommandUnitTests.m @@ -15,6 +15,7 @@ #import "PFURLSessionCommandRunner.h" #import "PFUnitTestCase.h" #import "Parse_Private.h" +#import "ParseClientConfiguration_Private.h" @interface CommandUnitTests : PFUnitTestCase diff --git a/Tests/Unit/ParseClientConfigurationTests.m b/Tests/Unit/ParseClientConfigurationTests.m index 835e7290b..fe9263bd8 100644 --- a/Tests/Unit/ParseClientConfigurationTests.m +++ b/Tests/Unit/ParseClientConfigurationTests.m @@ -37,19 +37,21 @@ - (void)testConfigurationWithBlock { ParseClientConfiguration *configuration = [ParseClientConfiguration configurationWithBlock:^(id configuration) { configuration.applicationId = @"foo"; configuration.clientKey = @"bar"; + configuration.server = @"http://localhost"; configuration.localDatastoreEnabled = YES; configuration.networkRetryAttempts = 1337; }]; XCTAssertEqualObjects(configuration.applicationId, @"foo"); XCTAssertEqualObjects(configuration.clientKey, @"bar"); + XCTAssertEqualObjects(configuration.server, @"http://localhost"); XCTAssertTrue(configuration.localDatastoreEnabled); XCTAssertEqual(configuration.networkRetryAttempts, 1337); } - (void)testEqual { - ParseClientConfiguration *configurationA = [(id)[ParseClientConfiguration alloc] init]; - ParseClientConfiguration *configurationB = [(id)[ParseClientConfiguration alloc] init]; + ParseClientConfiguration *configurationA = [ParseClientConfiguration emptyConfiguration]; + ParseClientConfiguration *configurationB = [ParseClientConfiguration emptyConfiguration]; XCTAssertEqualObjects(configurationA, configurationB); XCTAssertEqual(configurationA.hash, configurationB.hash); @@ -67,6 +69,13 @@ - (void)testEqual { XCTAssertNotEqualObjects(configurationA, configurationB); configurationB.clientKey = configurationA.clientKey; + configurationA.server = configurationB.server = @"http://localhost"; + XCTAssertEqualObjects(configurationA, configurationB); + XCTAssertEqual(configurationA.hash, configurationB.hash); + configurationB.server = @"http://api.parse.com"; + XCTAssertNotEqualObjects(configurationA, configurationB); + configurationB.server = configurationA.server; + configurationA.localDatastoreEnabled = configurationB.localDatastoreEnabled = YES; XCTAssertEqualObjects(configurationA, configurationB); XCTAssertEqual(configurationA.hash, configurationB.hash); @@ -85,6 +94,7 @@ - (void)testCopy { ParseClientConfiguration *configurationA = [ParseClientConfiguration configurationWithBlock:^(id configuration) { configuration.applicationId = @"foo"; configuration.clientKey = @"bar"; + configuration.server = @"http://localhost"; configuration.localDatastoreEnabled = YES; configuration.networkRetryAttempts = 1337; }]; @@ -100,6 +110,7 @@ - (void)testCopy { XCTAssertEqualObjects(configurationB.applicationId, @"foo"); XCTAssertEqualObjects(configurationB.clientKey, @"bar"); + XCTAssertEqualObjects(configurationB.server, @"http://localhost"); XCTAssertTrue(configurationB.localDatastoreEnabled); XCTAssertEqual(configurationB.networkRetryAttempts, 1337); } @@ -125,4 +136,14 @@ - (void)testExtensionDataSharing { XCTAssertNoThrow(configuration.containingApplicationBundleIdentifier = @"someContainer"); } +- (void)testServerValidation { + [ParseClientConfiguration configurationWithBlock:^(id _Nonnull configuration) { + configuration.applicationId = @"a"; + configuration.clientKey = @"b"; + + PFAssertThrowsInvalidArgumentException(configuration.server = @""); + PFAssertThrowsInvalidArgumentException(configuration.server = @"Yolo Yarr"); + }]; +} + @end diff --git a/Tests/Unit/ParseSetupUnitTests.m b/Tests/Unit/ParseSetupUnitTests.m index 0b7032b79..d7f60c2c1 100644 --- a/Tests/Unit/ParseSetupUnitTests.m +++ b/Tests/Unit/ParseSetupUnitTests.m @@ -48,9 +48,9 @@ - (void)testInitializeWithLDSAfterInitializeShouldThrowException { - (void)testInitializeWithNilApplicationIdNilClientKeyShouldThrowException { NSString *yolo = nil; - PFAssertThrowsInconsistencyException([Parse setApplicationId:yolo clientKey:yolo]); - PFAssertThrowsInconsistencyException([Parse setApplicationId:yolo clientKey:@"a"]); - PFAssertThrowsInconsistencyException([Parse setApplicationId:@"a" clientKey:yolo]); + PFAssertThrowsInvalidArgumentException([Parse setApplicationId:yolo clientKey:yolo]); + PFAssertThrowsInvalidArgumentException([Parse setApplicationId:yolo clientKey:@"a"]); + PFAssertThrowsInvalidArgumentException([Parse setApplicationId:@"a" clientKey:yolo]); } @end