Files
RestKit/Tests/Logic/ObjectMapping/RKObjectManagerTest.m

1279 lines
76 KiB
Objective-C

//
// RKObjectManagerTest.m
// RestKit
//
// Created by Blake Watters on 1/14/10.
// Copyright (c) 2009-2012 RestKit. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#import "RKTestEnvironment.h"
#import "RKObjectManager.h"
#import "RKManagedObjectStore.h"
#import "RKEntityMapping.h"
#import "RKHuman.h"
#import "RKCat.h"
#import "RKTestUser.h"
#import "RKObjectMapperTestModel.h"
#import "RKDynamicMapping.h"
#import "RKTestAddress.h"
#import "RKPost.h"
@interface RKSubclassedTestModel : RKObjectMapperTestModel
@end
@implementation RKSubclassedTestModel
@end
@interface RKTestAFHTTPClient : AFHTTPClient
@end
@implementation RKTestAFHTTPClient
- (NSMutableURLRequest *)requestWithMethod:(NSString *)method
path:(NSString *)path
parameters:(NSDictionary *)parameters
{
NSMutableURLRequest *request = [super requestWithMethod:method path:path parameters:parameters];
[request setAllHTTPHeaderFields:@{@"test": @"value", @"Accept": @"text/html"}];
return request;
}
@end
@interface RKTestHTTPRequestOperation : RKHTTPRequestOperation
@end
@implementation RKTestHTTPRequestOperation : RKHTTPRequestOperation
@end
@interface RKTestObjectRequestOperation : RKObjectRequestOperation
@end
@implementation RKTestObjectRequestOperation
+ (BOOL)canProcessRequest:(NSURLRequest *)request
{
return [[request.URL relativePath] isEqualToString:@"/match"];
}
@end
@interface RKTestManagedObjectRequestOperation : RKManagedObjectRequestOperation
@end
@implementation RKTestManagedObjectRequestOperation
+ (BOOL)canProcessRequest:(NSURLRequest *)request
{
return [[request.URL relativePath] isEqualToString:@"/match"];
}
@end
@interface RKObjectManagerTest : RKTestCase
@property (nonatomic, strong) RKObjectManager *objectManager;
@property (nonatomic, strong) RKRoute *humanGETRoute;
@property (nonatomic, strong) RKRoute *humanPOSTRoute;
@property (nonatomic, strong) RKRoute *humanDELETERoute;
@property (nonatomic, strong) RKRoute *humanCatsRoute;
@property (nonatomic, strong) RKRoute *humansCollectionRoute;
@end
@implementation RKObjectManagerTest
- (void)setUp
{
[RKTestFactory setUp];
self.objectManager = [RKTestFactory objectManager];
self.objectManager.managedObjectStore = [RKTestFactory managedObjectStore];
[RKObjectManager setSharedManager:self.objectManager];
NSError *error;
[self.objectManager.managedObjectStore resetPersistentStores:&error];
RKEntityMapping *humanMapping = [RKEntityMapping mappingForEntityForName:@"Human" inManagedObjectStore:_objectManager.managedObjectStore];
[humanMapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"name" toKeyPath:@"name"]];
[humanMapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"nick-name" toKeyPath:@"nickName"]];
[humanMapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"birthday" toKeyPath:@"birthday"]];
[humanMapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"sex" toKeyPath:@"sex"]];
[humanMapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"age" toKeyPath:@"age"]];
[humanMapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"created-at" toKeyPath:@"createdAt"]];
[humanMapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"updated-at" toKeyPath:@"updatedAt"]];
[humanMapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"id" toKeyPath:@"railsID"]];
RKEntityMapping *catMapping = [RKEntityMapping mappingForEntityForName:@"Cat" inManagedObjectStore:_objectManager.managedObjectStore];
[catMapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"name" toKeyPath:@"name"]];
[catMapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"nick-name" toKeyPath:@"nickName"]];
[catMapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"birthday" toKeyPath:@"birthday"]];
[catMapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"sex" toKeyPath:@"sex"]];
[catMapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"age" toKeyPath:@"age"]];
[catMapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"created-at" toKeyPath:@"createdAt"]];
[catMapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"updated-at" toKeyPath:@"updatedAt"]];
[catMapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"id" toKeyPath:@"railsID"]];
[catMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"cats" toKeyPath:@"cats" withMapping:catMapping]];
[self.objectManager addResponseDescriptorsFromArray:@[
[RKResponseDescriptor responseDescriptorWithMapping:humanMapping pathPattern:nil keyPath:@"human" statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)],
[RKResponseDescriptor responseDescriptorWithMapping:humanMapping pathPattern:nil keyPath:@"humans" statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)]
]];
RKObjectMapping *humanSerialization = [RKObjectMapping requestMapping];
[humanSerialization addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"name" toKeyPath:@"name"]];
[self.objectManager addRequestDescriptor:[RKRequestDescriptor requestDescriptorWithMapping:humanSerialization objectClass:[RKHuman class] rootKeyPath:@"human"]];
self.humanPOSTRoute = [RKRoute routeWithClass:[RKHuman class] pathPattern:@"/humans" method:RKRequestMethodPOST];
self.humanGETRoute = [RKRoute routeWithClass:[RKHuman class] pathPattern:@"/humans/:railsID" method:RKRequestMethodGET];
self.humanDELETERoute = [RKRoute routeWithClass:[RKHuman class] pathPattern:@"/humans/:railsID" method:RKRequestMethodDELETE];
self.humanCatsRoute = [RKRoute routeWithRelationshipName:@"cats" objectClass:[RKHuman class] pathPattern:@"/humans/:railsID/cats" method:RKRequestMethodGET];
self.humansCollectionRoute = [RKRoute routeWithName:@"humans" pathPattern:@"/humans" method:RKRequestMethodGET];
[self.objectManager.router.routeSet addRoute:self.humanPOSTRoute];
[self.objectManager.router.routeSet addRoute:self.humanGETRoute];
[self.objectManager.router.routeSet addRoute:self.humanDELETERoute];
[self.objectManager.router.routeSet addRoute:self.humanCatsRoute];
[self.objectManager.router.routeSet addRoute:self.humansCollectionRoute];
}
- (void)tearDown
{
[RKTestFactory tearDown];
}
- (void)testInitializationWithBaseURLSetsDefaultAcceptHeaderValueToJSON
{
RKObjectManager *manager = [RKObjectManager managerWithBaseURL:[NSURL URLWithString:@"http://restkit.org"]];
expect([manager defaultHeaders][@"Accept"]).to.equal(RKMIMETypeJSON);
}
- (void)testInitializationWithBaseURLSetsRequestSerializationMIMETypeToFormURLEncoded
{
RKObjectManager *manager = [RKObjectManager managerWithBaseURL:[NSURL URLWithString:@"http://restkit.org"]];
expect(manager.requestSerializationMIMEType).to.equal(RKMIMETypeFormURLEncoded);
}
- (void)testInitializationWithAFHTTPClientSetsNilAcceptHeaderValue
{
AFHTTPClient *client = [AFHTTPClient clientWithBaseURL:[NSURL URLWithString:@"http://restkit.org"]];
[client setDefaultHeader:@"Accept" value:@"this/that"];
RKObjectManager *manager = [[RKObjectManager alloc] initWithHTTPClient:client];
expect([manager defaultHeaders][@"Accept"]).to.equal(@"this/that");
}
- (void)testDefersToAFHTTPClientParameterEncodingWhenInitializedWithAFHTTPClient
{
AFHTTPClient *client = [AFHTTPClient clientWithBaseURL:[NSURL URLWithString:@"http://restkit.org"]];
client.parameterEncoding = AFJSONParameterEncoding;
RKObjectManager *manager = [[RKObjectManager alloc] initWithHTTPClient:client];
expect([manager requestSerializationMIMEType]).to.equal(RKMIMETypeJSON);
}
- (void)testDefaultsToFormURLEncodingForUnsupportedParameterEncodings
{
AFHTTPClient *client = [AFHTTPClient clientWithBaseURL:[NSURL URLWithString:@"http://restkit.org"]];
client.parameterEncoding = AFPropertyListParameterEncoding;
RKObjectManager *manager = [[RKObjectManager alloc] initWithHTTPClient:client];
expect([manager requestSerializationMIMEType]).to.equal(RKMIMETypeFormURLEncoded);
}
- (void)testShouldUpdateACoreDataBackedTargetObject
{
NSManagedObjectContext *managedObjectContext = [[RKTestFactory managedObjectStore] persistentStoreManagedObjectContext];
RKHuman *temporaryHuman = [RKTestFactory insertManagedObjectForEntityForName:@"Human" inManagedObjectContext:managedObjectContext withProperties:nil];
temporaryHuman.name = @"My Name";
RKManagedObjectRequestOperation *operation = [_objectManager appropriateObjectRequestOperationWithObject:temporaryHuman method:RKRequestMethodPOST path:nil parameters:nil];
[operation start];
[operation waitUntilFinished];
expect(operation.mappingResult).notTo.beNil();
expect([operation.mappingResult array]).notTo.beEmpty();
RKHuman *human = (RKHuman *)[[operation.mappingResult array] objectAtIndex:0];
expect(human.objectID).to.equal(temporaryHuman.objectID);
expect(human.railsID).to.equal(1);
}
- (void)testShouldNotPersistTemporaryEntityToPersistentStoreOnError
{
NSManagedObjectContext *managedObjectContext = [[RKTestFactory managedObjectStore] persistentStoreManagedObjectContext];
RKHuman *temporaryHuman = [RKTestFactory insertManagedObjectForEntityForName:@"Human" inManagedObjectContext:managedObjectContext withProperties:nil];
temporaryHuman.name = @"My Name";
RKObjectMapping *mapping = [RKObjectMapping mappingForClass:[NSMutableDictionary class]];
[mapping addAttributeMappingsFromArray:@[@"name"]];
RKManagedObjectRequestOperation *operation = [_objectManager appropriateObjectRequestOperationWithObject:temporaryHuman method:RKRequestMethodPOST path:@"/humans/fail" parameters:nil];
[operation start];
[operation waitUntilFinished];
expect([temporaryHuman isNew]).to.equal(YES);
}
- (void)testThatFailedObjectRequestOperationDoesNotSaveObjectToPersistentStore
{
NSManagedObjectContext *managedObjectContext = [[RKTestFactory managedObjectStore] persistentStoreManagedObjectContext];
RKHuman *temporaryHuman = [RKTestFactory insertManagedObjectForEntityForName:@"Human" inManagedObjectContext:managedObjectContext withProperties:nil];
temporaryHuman.name = @"My Name";
RKObjectMapping *mapping = [RKObjectMapping mappingForClass:[NSMutableDictionary class]];
[mapping addAttributeMappingsFromArray:@[@"name"]];
expect([temporaryHuman isNew]).to.equal(YES);
RKManagedObjectRequestOperation *operation = [self.objectManager appropriateObjectRequestOperationWithObject:temporaryHuman method:RKRequestMethodPOST path:@"/humans/fail" parameters:nil];
[operation start];
[operation waitUntilFinished];
expect([temporaryHuman isNew]).to.equal(YES);
}
- (void)testShouldDeleteACoreDataBackedTargetObjectOnSuccessfulDeleteReturning200
{
NSManagedObjectContext *managedObjectContext = [[RKTestFactory managedObjectStore] persistentStoreManagedObjectContext];
RKHuman *temporaryHuman = [RKTestFactory insertManagedObjectForEntityForName:@"Human" inManagedObjectContext:managedObjectContext withProperties:nil];
temporaryHuman.name = @"My Name";
temporaryHuman.railsID = @1;
RKObjectMapping *mapping = [RKObjectMapping mappingForClass:[NSMutableDictionary class]];
[mapping addAttributeMappingsFromArray:@[@"name"]];
// Save it to ensure the object is persisted before we delete it
[self.objectManager.managedObjectStore.persistentStoreManagedObjectContext save:nil];
RKManagedObjectRequestOperation *operation = [self.objectManager appropriateObjectRequestOperationWithObject:temporaryHuman method:RKRequestMethodDELETE path:nil parameters:nil];
[operation start];
[operation waitUntilFinished];
NSError *error = nil;
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"Human"];
NSArray *humans = [_objectManager.managedObjectStore.persistentStoreManagedObjectContext executeFetchRequest:fetchRequest error:&error];
expect(error).to.beNil();
expect(humans).to.haveCountOf(0);
}
- (void)testShouldDeleteACoreDataBackedTargetObjectOnSuccessfulDeleteReturning204
{
NSManagedObjectContext *managedObjectContext = [[RKTestFactory managedObjectStore] persistentStoreManagedObjectContext];
RKHuman *temporaryHuman = [RKTestFactory insertManagedObjectForEntityForName:@"Human" inManagedObjectContext:managedObjectContext withProperties:nil];
temporaryHuman.name = @"My Name";
temporaryHuman.railsID = @204;
RKObjectMapping *mapping = [RKObjectMapping mappingForClass:[NSMutableDictionary class]];
[mapping addAttributeMappingsFromArray:@[@"name"]];
// Save it to ensure the object is persisted before we delete it
[self.objectManager.managedObjectStore.persistentStoreManagedObjectContext save:nil];
RKManagedObjectRequestOperation *operation = [self.objectManager appropriateObjectRequestOperationWithObject:temporaryHuman method:RKRequestMethodDELETE path:nil parameters:nil];
[operation start];
[operation waitUntilFinished];
NSError *error = nil;
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"Human"];
NSArray *humans = [_objectManager.managedObjectStore.persistentStoreManagedObjectContext executeFetchRequest:fetchRequest error:&error];
expect(error).to.beNil();
expect(humans).to.haveCountOf(0);
}
- (void)testCancellationByExactMethodAndPath
{
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"/object_manager/cancel" relativeToURL:self.objectManager.HTTPClient.baseURL]];
RKObjectRequestOperation *operation = [[RKObjectRequestOperation alloc] initWithRequest:request responseDescriptors:self.objectManager.responseDescriptors];
[_objectManager enqueueObjectRequestOperation:operation];
[_objectManager cancelAllObjectRequestOperationsWithMethod:RKRequestMethodGET matchingPathPattern:@"/object_manager/cancel"];
expect([operation isCancelled]).to.equal(YES);
}
- (void)testCancellationByPathMatch
{
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"/object_manager/1234/cancel" relativeToURL:self.objectManager.HTTPClient.baseURL]];
RKObjectRequestOperation *operation = [[RKObjectRequestOperation alloc] initWithRequest:request responseDescriptors:self.objectManager.responseDescriptors];
[_objectManager enqueueObjectRequestOperation:operation];
[_objectManager cancelAllObjectRequestOperationsWithMethod:RKRequestMethodGET matchingPathPattern:@"/object_manager/:objectID/cancel"];
expect([operation isCancelled]).to.equal(YES);
}
- (void)testCancellationFailsForMismatchedMethod
{
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"/object_manager/cancel" relativeToURL:self.objectManager.HTTPClient.baseURL]];
RKObjectRequestOperation *operation = [[RKObjectRequestOperation alloc] initWithRequest:request responseDescriptors:self.objectManager.responseDescriptors];
[_objectManager enqueueObjectRequestOperation:operation];
[_objectManager cancelAllObjectRequestOperationsWithMethod:RKRequestMethodPOST matchingPathPattern:@"/object_manager/cancel"];
expect([operation isCancelled]).to.equal(NO);
}
- (void)testCancellationFailsForMismatchedPath
{
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"/object_manager/cancel" relativeToURL:self.objectManager.HTTPClient.baseURL]];
RKObjectRequestOperation *operation = [[RKObjectRequestOperation alloc] initWithRequest:request responseDescriptors:self.objectManager.responseDescriptors];
[_objectManager enqueueObjectRequestOperation:operation];
[_objectManager cancelAllObjectRequestOperationsWithMethod:RKRequestMethodGET matchingPathPattern:@"/wrong"];
expect([operation isCancelled]).to.equal(NO);
}
- (void)testCancellationByPathMatchForBaseURLWithPath
{
self.objectManager = [RKObjectManager managerWithBaseURL:[NSURL URLWithString:@"http://localhost:4567/object_manager/"]];
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://localhost:4567/object_manager/1234/cancel"]];
RKObjectRequestOperation *operation = [[RKObjectRequestOperation alloc] initWithRequest:request responseDescriptors:self.objectManager.responseDescriptors];
[_objectManager enqueueObjectRequestOperation:operation];
[_objectManager cancelAllObjectRequestOperationsWithMethod:RKRequestMethodGET matchingPathPattern:@":objectID/cancel"];
expect([operation isCancelled]).to.equal(YES);
}
- (void)testShouldProperlyFireABatchOfOperations
{
NSManagedObjectContext *managedObjectContext = [[RKTestFactory managedObjectStore] persistentStoreManagedObjectContext];
RKHuman *temporaryHuman = [RKTestFactory insertManagedObjectForEntityForName:@"Human" inManagedObjectContext:managedObjectContext withProperties:nil];
temporaryHuman.name = @"My Name";
RKManagedObjectRequestOperation *successfulGETOperation = [_objectManager appropriateObjectRequestOperationWithObject:temporaryHuman method:RKRequestMethodGET path:nil parameters:nil];
RKManagedObjectRequestOperation *successfulPOSTOperation = [_objectManager appropriateObjectRequestOperationWithObject:temporaryHuman method:RKRequestMethodPOST path:nil parameters:nil];
RKManagedObjectRequestOperation *failedPOSTOperation = [_objectManager appropriateObjectRequestOperationWithObject:temporaryHuman method:RKRequestMethodPOST path:@"/humans/fail" parameters:nil];
__block NSUInteger progressCallbackCount = 0;
__block NSUInteger completionBlockOperationCount = 0;
[_objectManager enqueueBatchOfObjectRequestOperations:@[successfulGETOperation, successfulPOSTOperation, failedPOSTOperation] progress:^(NSUInteger numberOfFinishedOperations, NSUInteger totalNumberOfOperations) {
progressCallbackCount++;
} completion:^(NSArray *operations) {
completionBlockOperationCount = operations.count;
}];
expect(_objectManager.operationQueue).notTo.beNil();
[_objectManager.operationQueue waitUntilAllOperationsAreFinished];
dispatch_async(dispatch_get_main_queue(), ^{
expect(progressCallbackCount).to.equal(3);
expect(completionBlockOperationCount).to.equal(3);
});
}
- (void)testShouldProperlyFireABatchOfOperationsFromRoute
{
NSManagedObjectContext *managedObjectContext = [[RKTestFactory managedObjectStore] persistentStoreManagedObjectContext];
RKHuman *dan = [RKTestFactory insertManagedObjectForEntityForName:@"Human" inManagedObjectContext:managedObjectContext withProperties:nil];
dan.name = @"Dan";
RKHuman *blake = [RKTestFactory insertManagedObjectForEntityForName:@"Human" inManagedObjectContext:managedObjectContext withProperties:nil];
blake.name = @"Blake";
RKHuman *jeff = [RKTestFactory insertManagedObjectForEntityForName:@"Human" inManagedObjectContext:managedObjectContext withProperties:nil];
jeff.name = @"Jeff";
__block NSUInteger progressCallbackCount = 0;
__block NSUInteger completionBlockOperationCount = 0;
[_objectManager enqueueBatchOfObjectRequestOperationsWithRoute:self.humanPOSTRoute objects:@[dan, blake, jeff] progress:^(NSUInteger numberOfFinishedOperations, NSUInteger totalNumberOfOperations) {
progressCallbackCount++;
} completion:^(NSArray *operations) {
completionBlockOperationCount = operations.count;
}];
expect(_objectManager.operationQueue).notTo.beNil();
[_objectManager.operationQueue waitUntilAllOperationsAreFinished];
dispatch_async(dispatch_get_main_queue(), ^{
expect(progressCallbackCount).to.equal(3);
expect(completionBlockOperationCount).to.equal(3);
});
}
- (void)testThatObjectParametersAreNotSentDuringGetObject
{
RKHuman *temporaryHuman = [RKTestFactory insertManagedObjectForEntityForName:@"Human" inManagedObjectContext:nil withProperties:nil];
temporaryHuman.name = @"My Name";
temporaryHuman.railsID = @204;
RKManagedObjectRequestOperation *operation = [_objectManager appropriateObjectRequestOperationWithObject:temporaryHuman method:RKRequestMethodGET path:nil parameters:@{@"this": @"that"}];
expect([operation.HTTPRequestOperation.request.URL absoluteString]).to.equal(@"http://127.0.0.1:4567/humans/204?this=that");
}
- (void)testThatObjectParametersAreNotSentDuringDeleteObject
{
RKHuman *temporaryHuman = [RKTestFactory insertManagedObjectForEntityForName:@"Human" inManagedObjectContext:nil withProperties:nil];
temporaryHuman.name = @"My Name";
temporaryHuman.railsID = @204;
RKManagedObjectRequestOperation *operation = [_objectManager appropriateObjectRequestOperationWithObject:temporaryHuman method:RKRequestMethodDELETE path:nil parameters:@{@"this": @"that"}];
expect([operation.HTTPRequestOperation.request.URL absoluteString]).to.equal(@"http://127.0.0.1:4567/humans/204?this=that");
}
- (void)testInitializationOfObjectRequestOperationProducesCorrectURLRequest
{
RKHuman *temporaryHuman = [RKTestFactory insertManagedObjectForEntityForName:@"Human" inManagedObjectContext:nil withProperties:nil];
NSURLRequest *request = [_objectManager requestWithObject:temporaryHuman method:RKRequestMethodPATCH path:@"/the/path" parameters:@{@"key": @"value"}];
expect([request.URL absoluteString]).to.equal(@"http://127.0.0.1:4567/the/path");
expect(request.HTTPMethod).to.equal(@"PATCH");
expect(request.HTTPBody).notTo.beNil();
NSString *string = [[NSString alloc] initWithData:request.HTTPBody encoding:NSUTF8StringEncoding];
expect(string).to.equal(@"key=value");
}
- (void)testAFHTTPClientCanModifyRequestsBuiltByObjectManager
{
RKTestAFHTTPClient *testClient = [[RKTestAFHTTPClient alloc] initWithBaseURL:[NSURL URLWithString:@"http://test.com"]];
RKObjectManager *manager = [[RKObjectManager alloc] initWithHTTPClient:testClient];
RKHuman *temporaryHuman = [RKTestFactory insertManagedObjectForEntityForName:@"Human" inManagedObjectContext:nil withProperties:nil];
NSURLRequest *request = [manager requestWithObject:temporaryHuman method:RKRequestMethodPATCH path:@"/the/path" parameters:@{@"key": @"value"}];
expect([request.URL absoluteString]).to.equal(@"http://test.com/the/path");
expect(request.HTTPMethod).to.equal(@"PATCH");
expect([request allHTTPHeaderFields][@"test"]).to.equal(@"value");
expect([request allHTTPHeaderFields][@"Accept"]).to.equal(@"text/html");
}
- (void)testRegistrationOfHTTPRequestOperationClass
{
RKObjectManager *manager = [RKObjectManager managerWithBaseURL:[NSURL URLWithString:@"http://restkit.org"]];
[manager registerRequestOperationClass:[RKTestHTTPRequestOperation class]];
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"/test" relativeToURL:manager.baseURL]];
RKObjectRequestOperation *operation = [manager objectRequestOperationWithRequest:request success:nil failure:nil];
expect(operation.HTTPRequestOperation).to.beKindOf([RKTestHTTPRequestOperation class]);
}
- (void)testSettingNilHTTPRequestOperationClassRestoresDefaultHTTPOperationClass
{
RKObjectManager *manager = [RKObjectManager managerWithBaseURL:[NSURL URLWithString:@"http://restkit.org"]];
[manager registerRequestOperationClass:[RKTestHTTPRequestOperation class]];
[manager unregisterRequestOperationClass:[RKTestHTTPRequestOperation class]];
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"/test" relativeToURL:manager.baseURL]];
RKObjectRequestOperation *operation = [manager objectRequestOperationWithRequest:request success:nil failure:nil];
expect(operation.HTTPRequestOperation).to.beKindOf([RKHTTPRequestOperation class]);
}
- (void)testThatManagedObjectRequestOperationsDefaultToSavingToPersistentStore
{
RKObjectManager *manager = [RKObjectManager managerWithBaseURL:[NSURL URLWithString:@"http://restkit.org"]];
NSManagedObjectContext *managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"/whatever" relativeToURL:manager.baseURL]];
RKManagedObjectRequestOperation *operation = [manager managedObjectRequestOperationWithRequest:request managedObjectContext:managedObjectContext success:nil failure:nil];
expect(operation.savesToPersistentStore).to.equal(YES);
}
- (void)testShouldLoadAHuman
{
__block RKObjectRequestOperation *requestOperation = nil;
[self.objectManager getObjectsAtPath:@"/JSON/humans/1.json" parameters:nil success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
requestOperation = operation;
} failure:nil];
dispatch_async(dispatch_get_main_queue(), ^{
expect(requestOperation.error).to.beNil();
expect([requestOperation.mappingResult array]).notTo.beEmpty();
RKHuman *blake = (RKHuman *)[requestOperation.mappingResult array][0];
expect(blake.name).to.equal(@"Blake Watters");
});
}
- (void)testShouldLoadAllHumans
{
__block RKObjectRequestOperation *requestOperation = nil;
[_objectManager getObjectsAtPath:@"/JSON/humans/all.json" parameters:nil success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
requestOperation = operation;
} failure:nil];
dispatch_async(dispatch_get_main_queue(), ^{
NSArray *humans = [requestOperation.mappingResult array];
expect(humans).to.haveCountOf(2);
expect(humans[0]).to.beInstanceOf([RKHuman class]);
});
}
- (void)testThatAttemptingToAddARequestDescriptorThatOverlapsAnExistingEntryGeneratesAnError
{
RKObjectMapping *mapping = [RKObjectMapping requestMapping];
RKRequestDescriptor *requestDesriptor1 = [RKRequestDescriptor requestDescriptorWithMapping:mapping objectClass:[RKCat class] rootKeyPath:nil];
RKRequestDescriptor *requestDesriptor2 = [RKRequestDescriptor requestDescriptorWithMapping:mapping objectClass:[RKCat class] rootKeyPath:@"cat"];
RKObjectManager *objectManager = [RKTestFactory objectManager];
[objectManager addRequestDescriptor:requestDesriptor1];
NSException *caughtException = nil;
@try {
[objectManager addRequestDescriptor:requestDesriptor2];
}
@catch (NSException *exception) {
caughtException = exception;
}
@finally {
expect(caughtException).notTo.beNil();
}
}
- (void)testThatRegisteringARequestDescriptorForASubclassSecondWillMatchAppropriately
{
RKObjectMapping *mapping1 = [RKObjectMapping requestMapping];
[mapping1 addAttributeMappingsFromArray:@[ @"name" ]];
RKObjectMapping *mapping2 = [RKObjectMapping requestMapping];
[mapping2 addAttributeMappingsFromArray:@[ @"age" ]];
RKRequestDescriptor *requestDesriptor1 = [RKRequestDescriptor requestDescriptorWithMapping:mapping1 objectClass:[RKObjectMapperTestModel class] rootKeyPath:nil];
RKRequestDescriptor *requestDesriptor2 = [RKRequestDescriptor requestDescriptorWithMapping:mapping2 objectClass:[RKSubclassedTestModel class] rootKeyPath:@"subclassed"];
RKObjectManager *objectManager = [RKTestFactory objectManager];
objectManager.requestSerializationMIMEType = RKMIMETypeJSON;
[objectManager addRequestDescriptor:requestDesriptor1];
[objectManager addRequestDescriptor:requestDesriptor2];
RKSubclassedTestModel *model = [RKSubclassedTestModel new];
model.name = @"Blake";
model.age = @30;
NSURLRequest *request = [objectManager requestWithObject:model method:RKRequestMethodPOST path:@"/path" parameters:nil];
NSDictionary *dictionary = [NSJSONSerialization JSONObjectWithData:request.HTTPBody options:0 error:nil];
expect(dictionary).to.equal(@{ @"subclassed": @{ @"age": @(30) } });
}
- (void)testThatResponseDescriptorWithUnmanagedMappingTriggersCreationOfObjectRequestOperation
{
RKObjectMapping *vanillaMapping = [RKObjectMapping requestMapping];
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:vanillaMapping pathPattern:nil keyPath:nil statusCodes:nil];
RKObjectManager *manager = [RKObjectManager managerWithBaseURL:[NSURL URLWithString:@"http://restkit.org"]];
manager.managedObjectStore = [RKTestFactory managedObjectStore];
[manager addResponseDescriptor:responseDescriptor];
RKObjectRequestOperation *objectRequestOperation = [manager appropriateObjectRequestOperationWithObject:nil method:RKRequestMethodGET path:@"/something" parameters:nil];
expect(objectRequestOperation).to.beInstanceOf([RKObjectRequestOperation class]);
}
- (void)testThatResponseDescriptorWithDynamicMappingContainingEntityMappingsTriggersCreationOfManagedObjectRequestOperation
{
RKEntityMapping *humanMapping = [RKEntityMapping mappingForEntityForName:@"Human" inManagedObjectStore:_objectManager.managedObjectStore];
RKDynamicMapping *dynamicMapping = [RKDynamicMapping new];
[dynamicMapping addMatcher:[RKObjectMappingMatcher matcherWithKeyPath:@"whatever" expectedValue:@"whatever" objectMapping:humanMapping]];
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:dynamicMapping pathPattern:nil keyPath:nil statusCodes:nil];
RKObjectManager *manager = [RKObjectManager managerWithBaseURL:[NSURL URLWithString:@"http://restkit.org"]];
manager.managedObjectStore = [RKTestFactory managedObjectStore];
[manager addResponseDescriptor:responseDescriptor];
RKObjectRequestOperation *objectRequestOperation = [manager appropriateObjectRequestOperationWithObject:nil method:RKRequestMethodGET path:@"/something" parameters:nil];
expect(objectRequestOperation).to.beInstanceOf([RKManagedObjectRequestOperation class]);
}
- (void)testThatResponseDescriptorWithDynamicMappingUsingABlockTriggersCreationOfManagedObjectRequestOperation
{
RKEntityMapping *humanMapping = [RKEntityMapping mappingForEntityForName:@"Human" inManagedObjectStore:_objectManager.managedObjectStore];
RKDynamicMapping *dynamicMapping = [RKDynamicMapping new];
[dynamicMapping setObjectMappingForRepresentationBlock:^RKObjectMapping *(id representation) {
return humanMapping;
}];
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:dynamicMapping pathPattern:nil keyPath:nil statusCodes:nil];
RKObjectManager *manager = [RKObjectManager managerWithBaseURL:[NSURL URLWithString:@"http://restkit.org"]];
manager.managedObjectStore = [RKTestFactory managedObjectStore];
[manager addResponseDescriptor:responseDescriptor];
RKObjectRequestOperation *objectRequestOperation = [manager appropriateObjectRequestOperationWithObject:nil method:RKRequestMethodGET path:@"/something" parameters:nil];
expect(objectRequestOperation).to.beInstanceOf([RKManagedObjectRequestOperation class]);
}
- (void)testThatResponseDescriptorWithUnmanagedMappingContainingRelationshipMappingWithEntityMappingsTriggersCreationOfManagedObjectRequestOperation
{
RKEntityMapping *humanMapping = [RKEntityMapping mappingForEntityForName:@"Human" inManagedObjectStore:_objectManager.managedObjectStore];
RKObjectMapping *objectMapping = [RKObjectMapping mappingForClass:[NSMutableDictionary class]];
[objectMapping addRelationshipMappingWithSourceKeyPath:@"relationship" mapping:humanMapping];
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:objectMapping pathPattern:nil keyPath:nil statusCodes:nil];
RKObjectManager *manager = [RKObjectManager managerWithBaseURL:[NSURL URLWithString:@"http://restkit.org"]];
manager.managedObjectStore = [RKTestFactory managedObjectStore];
[manager addResponseDescriptor:responseDescriptor];
RKObjectRequestOperation *objectRequestOperation = [manager appropriateObjectRequestOperationWithObject:nil method:RKRequestMethodGET path:@"/something" parameters:nil];
expect(objectRequestOperation).to.beInstanceOf([RKManagedObjectRequestOperation class]);
}
- (void)testThatResponseDescriptorWithUnmanagedMappingContainingRelationshipMappingWithEntityMappingsDeepWithinObjectGraphTriggersCreationOfManagedObjectRequestOperation
{
RKEntityMapping *humanMapping = [RKEntityMapping mappingForEntityForName:@"Human" inManagedObjectStore:_objectManager.managedObjectStore];
RKObjectMapping *objectMapping = [RKObjectMapping mappingForClass:[NSMutableDictionary class]];
[objectMapping addRelationshipMappingWithSourceKeyPath:@"relationship" mapping:humanMapping];
RKObjectMapping *objectMapping2 = [RKObjectMapping mappingForClass:[NSMutableDictionary class]];
[objectMapping2 addRelationshipMappingWithSourceKeyPath:@"relationship" mapping:objectMapping];
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:objectMapping2 pathPattern:nil keyPath:nil statusCodes:nil];
RKObjectManager *manager = [RKObjectManager managerWithBaseURL:[NSURL URLWithString:@"http://restkit.org"]];
manager.managedObjectStore = [RKTestFactory managedObjectStore];
[manager addResponseDescriptor:responseDescriptor];
RKObjectRequestOperation *objectRequestOperation = [manager appropriateObjectRequestOperationWithObject:nil method:RKRequestMethodGET path:@"/something" parameters:nil];
expect(objectRequestOperation).to.beInstanceOf([RKManagedObjectRequestOperation class]);
}
- (void)testChangingHTTPClient
{
RKObjectManager *manager = [RKObjectManager managerWithBaseURL:[NSURL URLWithString:@"http://restkit.org"]];
manager.HTTPClient = [AFHTTPClient clientWithBaseURL:[NSURL URLWithString:@"http://google.com/"]];
expect([manager.baseURL absoluteString]).to.equal(@"http://google.com/");
}
- (void)testPostingOneObjectAndGettingResponseMatchingAnotherClass
{
RKObjectManager *manager = [RKObjectManager managerWithBaseURL:[RKTestFactory baseURL]];
RKObjectMapping *userMapping = [RKObjectMapping mappingForClass:[RKTestUser class]];
[userMapping addAttributeMappingsFromDictionary:@{ @"fullname": @"name" }];
RKObjectMapping *metaMapping = [RKObjectMapping mappingForClass:[NSMutableDictionary class]];
[metaMapping addAttributeMappingsFromArray:@[ @"status", @"version" ]];
RKResponseDescriptor *metaResponseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:metaMapping pathPattern:nil keyPath:@"meta" statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
[manager addResponseDescriptorsFromArray:@[ metaResponseDescriptor ]];
RKTestUser *user = [RKTestUser new];
RKObjectRequestOperation *requestOperation = [manager appropriateObjectRequestOperationWithObject:user method:RKRequestMethodPOST path:@"/ComplexUser" parameters:nil];
[requestOperation start];
[requestOperation waitUntilFinished];
expect(requestOperation.error).to.beNil();
expect(requestOperation.mappingResult).notTo.beNil();
expect([requestOperation.mappingResult array]).to.haveCountOf(1);
NSDictionary *expectedObject = @{ @"status": @"ok", @"version": @"0.3" };
expect([requestOperation.mappingResult firstObject]).to.equal(expectedObject);
}
- (void)testPostingOneObjectAndGettingResponseMatchingMultipleDescriptors
{
RKObjectManager *manager = [RKObjectManager managerWithBaseURL:[RKTestFactory baseURL]];
RKObjectMapping *userMapping = [RKObjectMapping mappingForClass:[RKTestUser class]];
[userMapping addAttributeMappingsFromDictionary:@{ @"fullname": @"name" }];
RKResponseDescriptor *userResponseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:userMapping pathPattern:nil keyPath:@"data.STUser" statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
RKObjectMapping *metaMapping = [RKObjectMapping mappingForClass:[NSMutableDictionary class]];
[metaMapping addAttributeMappingsFromArray:@[ @"status", @"version" ]];
RKResponseDescriptor *metaResponseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:metaMapping pathPattern:nil keyPath:@"meta" statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
[manager addResponseDescriptorsFromArray:@[ userResponseDescriptor, metaResponseDescriptor ]];
RKTestUser *user = [RKTestUser new];
RKObjectRequestOperation *requestOperation = [manager appropriateObjectRequestOperationWithObject:user method:RKRequestMethodPOST path:@"/ComplexUser" parameters:nil];
[requestOperation start];
[requestOperation waitUntilFinished];
expect(requestOperation.mappingResult).notTo.beNil();
expect([requestOperation.mappingResult array]).to.haveCountOf(2);
}
- (void)testThatAppropriateObjectRequestOperationReturnsManagedObjectRequestOperationForManagedObjectWithNoResponseDescriptors
{
RKObjectManager *manager = [RKObjectManager managerWithBaseURL:[NSURL URLWithString:@"http://restkit.org"]];
manager.managedObjectStore = [RKTestFactory managedObjectStore];
NSManagedObject *managedObject = [NSEntityDescription insertNewObjectForEntityForName:@"Human" inManagedObjectContext:manager.managedObjectStore.mainQueueManagedObjectContext];
RKObjectRequestOperation *objectRequestOperation = [manager appropriateObjectRequestOperationWithObject:managedObject method:RKRequestMethodPOST path:@"/something" parameters:nil];
expect(objectRequestOperation).to.beInstanceOf([RKManagedObjectRequestOperation class]);
}
- (void)testCreatingAnObjectRequestWithoutARequestDescriptorButWithParametersSetsTheRequestBody
{
RKTestUser *user = [RKTestUser new];
user.name = @"Blake";
user.emailAddress = @"blake@restkit.org";
RKObjectManager *objectManager = [RKTestFactory objectManager];
objectManager.requestSerializationMIMEType = RKMIMETypeJSON;
NSURLRequest *request = [objectManager requestWithObject:user method:RKRequestMethodPOST path:@"/path" parameters:@{ @"this": @"that" }];
id body = [NSJSONSerialization JSONObjectWithData:request.HTTPBody options:0 error:nil];
NSDictionary *expected = @{ @"this": @"that" };
expect(body).to.equal(expected);
}
- (void)testPostingAnArrayOfObjectsWhereNoneHaveARootKeyPath
{
RKObjectMapping *firstRequestMapping = [RKObjectMapping requestMapping];
[firstRequestMapping addAttributeMappingsFromArray:@[ @"name", @"emailAddress" ]];
RKObjectMapping *secondRequestMapping = [RKObjectMapping requestMapping];
[secondRequestMapping addAttributeMappingsFromArray:@[ @"city", @"state" ]];
RKRequestDescriptor *firstRequestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:firstRequestMapping objectClass:[RKTestUser class] rootKeyPath:nil];
RKRequestDescriptor *secondRequestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:secondRequestMapping objectClass:[RKTestAddress class] rootKeyPath:nil];
RKTestUser *user = [RKTestUser new];
user.name = @"Blake";
user.emailAddress = @"blake@restkit.org";
RKTestAddress *address = [RKTestAddress new];
address.city = @"New York City";
address.state = @"New York";
RKObjectManager *objectManager = [RKTestFactory objectManager];
objectManager.requestSerializationMIMEType = RKMIMETypeJSON;
[objectManager addRequestDescriptor:firstRequestDescriptor];
[objectManager addRequestDescriptor:secondRequestDescriptor];
NSArray *arrayOfObjects = @[ user, address ];
NSURLRequest *request = [objectManager requestWithObject:arrayOfObjects method:RKRequestMethodPOST path:@"/path" parameters:nil];
NSArray *array = [NSJSONSerialization JSONObjectWithData:request.HTTPBody options:0 error:nil];
NSArray *expected = @[ @{ @"name": @"Blake", @"emailAddress": @"blake@restkit.org" }, @{ @"city": @"New York City", @"state": @"New York" } ];
expect(array).to.equal(expected);
}
- (void)testPostingAnArrayOfObjectsWhereAllObjectsHaveAnOverlappingRootKeyPath
{
RKObjectMapping *firstRequestMapping = [RKObjectMapping requestMapping];
[firstRequestMapping addAttributeMappingsFromArray:@[ @"name", @"emailAddress" ]];
RKObjectMapping *secondRequestMapping = [RKObjectMapping requestMapping];
[secondRequestMapping addAttributeMappingsFromArray:@[ @"city", @"state" ]];
RKRequestDescriptor *firstRequestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:firstRequestMapping objectClass:[RKTestUser class] rootKeyPath:@"whatever"];
RKRequestDescriptor *secondRequestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:secondRequestMapping objectClass:[RKTestAddress class] rootKeyPath:@"whatever"];
RKTestUser *user = [RKTestUser new];
user.name = @"Blake";
user.emailAddress = @"blake@restkit.org";
RKTestAddress *address = [RKTestAddress new];
address.city = @"New York City";
address.state = @"New York";
RKObjectManager *objectManager = [RKTestFactory objectManager];
objectManager.requestSerializationMIMEType = RKMIMETypeJSON;
[objectManager addRequestDescriptor:firstRequestDescriptor];
[objectManager addRequestDescriptor:secondRequestDescriptor];
NSArray *arrayOfObjects = @[ user, address ];
NSURLRequest *request = [objectManager requestWithObject:arrayOfObjects method:RKRequestMethodPOST path:@"/path" parameters:nil];
NSArray *array = [NSJSONSerialization JSONObjectWithData:request.HTTPBody options:0 error:nil];
NSDictionary *expected = @{ @"whatever": @[ @{ @"name": @"Blake", @"emailAddress": @"blake@restkit.org" }, @{ @"city": @"New York City", @"state": @"New York" } ] };
expect(array).to.equal(expected);
}
- (void)testPostingAnArrayOfObjectsWithMixedRootKeyPath
{
RKObjectMapping *firstRequestMapping = [RKObjectMapping requestMapping];
[firstRequestMapping addAttributeMappingsFromArray:@[ @"name", @"emailAddress" ]];
RKObjectMapping *secondRequestMapping = [RKObjectMapping requestMapping];
[secondRequestMapping addAttributeMappingsFromArray:@[ @"city", @"state" ]];
RKRequestDescriptor *firstRequestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:firstRequestMapping objectClass:[RKTestUser class] rootKeyPath:@"this"];
RKRequestDescriptor *secondRequestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:secondRequestMapping objectClass:[RKTestAddress class] rootKeyPath:@"that"];
RKTestUser *user = [RKTestUser new];
user.name = @"Blake";
user.emailAddress = @"blake@restkit.org";
RKTestAddress *address = [RKTestAddress new];
address.city = @"New York City";
address.state = @"New York";
RKObjectManager *objectManager = [RKTestFactory objectManager];
objectManager.requestSerializationMIMEType = RKMIMETypeJSON;
[objectManager addRequestDescriptor:firstRequestDescriptor];
[objectManager addRequestDescriptor:secondRequestDescriptor];
NSArray *arrayOfObjects = @[ user, address ];
NSURLRequest *request = [objectManager requestWithObject:arrayOfObjects method:RKRequestMethodPOST path:@"/path" parameters:nil];
NSArray *array = [NSJSONSerialization JSONObjectWithData:request.HTTPBody options:0 error:nil];
NSDictionary *expected = @{ @"this": @{ @"name": @"Blake", @"emailAddress": @"blake@restkit.org" }, @"that": @{ @"city": @"New York City", @"state": @"New York" } };
expect(array).to.equal(expected);
}
- (void)testPostingAnArrayOfObjectsWithNonNilRootKeyPathAndExtraParameters
{
RKObjectMapping *firstRequestMapping = [RKObjectMapping requestMapping];
[firstRequestMapping addAttributeMappingsFromArray:@[ @"name", @"emailAddress" ]];
RKObjectMapping *secondRequestMapping = [RKObjectMapping requestMapping];
[secondRequestMapping addAttributeMappingsFromArray:@[ @"city", @"state" ]];
RKRequestDescriptor *firstRequestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:firstRequestMapping objectClass:[RKTestUser class] rootKeyPath:@"this"];
RKRequestDescriptor *secondRequestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:secondRequestMapping objectClass:[RKTestAddress class] rootKeyPath:@"that"];
RKTestUser *user = [RKTestUser new];
user.name = @"Blake";
user.emailAddress = @"blake@restkit.org";
RKTestAddress *address = [RKTestAddress new];
address.city = @"New York City";
address.state = @"New York";
RKObjectManager *objectManager = [RKTestFactory objectManager];
objectManager.requestSerializationMIMEType = RKMIMETypeJSON;
[objectManager addRequestDescriptor:firstRequestDescriptor];
[objectManager addRequestDescriptor:secondRequestDescriptor];
NSArray *arrayOfObjects = @[ user, address ];
NSURLRequest *request = [objectManager requestWithObject:arrayOfObjects method:RKRequestMethodPOST path:@"/path" parameters:@{ @"extra": @"info" }];
NSArray *array = [NSJSONSerialization JSONObjectWithData:request.HTTPBody options:0 error:nil];
NSDictionary *expected = @{ @"this": @{ @"name": @"Blake", @"emailAddress": @"blake@restkit.org" }, @"that": @{ @"city": @"New York City", @"state": @"New York" }, @"extra": @"info" };
expect(array).to.equal(expected);
}
- (void)testPostingNilObjectWithExtraParameters
{
RKObjectMapping *firstRequestMapping = [RKObjectMapping requestMapping];
[firstRequestMapping addAttributeMappingsFromArray:@[ @"name", @"emailAddress" ]];
RKObjectMapping *secondRequestMapping = [RKObjectMapping requestMapping];
[secondRequestMapping addAttributeMappingsFromArray:@[ @"city", @"state" ]];
RKRequestDescriptor *firstRequestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:firstRequestMapping objectClass:[RKTestUser class] rootKeyPath:@"this"];
RKRequestDescriptor *secondRequestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:secondRequestMapping objectClass:[RKTestAddress class] rootKeyPath:@"that"];
RKObjectManager *objectManager = [RKTestFactory objectManager];
objectManager.requestSerializationMIMEType = RKMIMETypeJSON;
[objectManager addRequestDescriptor:firstRequestDescriptor];
[objectManager addRequestDescriptor:secondRequestDescriptor];
NSDictionary *parameters = @{ @"this": @"that" };
NSURLRequest *request = [objectManager requestWithObject:nil method:RKRequestMethodPOST path:@"/path" parameters:parameters];
NSArray *array = [NSJSONSerialization JSONObjectWithData:request.HTTPBody options:0 error:nil];
expect(array).to.equal(parameters);
}
- (void)testAttemptingToPostAnArrayOfObjectsWithMixtureOfNilAndNonNilRootKeyPathsRaisesError
{
RKObjectMapping *firstRequestMapping = [RKObjectMapping requestMapping];
[firstRequestMapping addAttributeMappingsFromArray:@[ @"name", @"emailAddress" ]];
RKObjectMapping *secondRequestMapping = [RKObjectMapping requestMapping];
[secondRequestMapping addAttributeMappingsFromArray:@[ @"city", @"state" ]];
RKRequestDescriptor *firstRequestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:firstRequestMapping objectClass:[RKTestUser class] rootKeyPath:nil];
RKRequestDescriptor *secondRequestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:secondRequestMapping objectClass:[RKTestAddress class] rootKeyPath:nil];
RKTestUser *user = [RKTestUser new];
user.name = @"Blake";
user.emailAddress = @"blake@restkit.org";
RKTestAddress *address = [RKTestAddress new];
address.city = @"New York City";
address.state = @"New York";
RKObjectManager *objectManager = [RKTestFactory objectManager];
objectManager.requestSerializationMIMEType = RKMIMETypeJSON;
[objectManager addRequestDescriptor:firstRequestDescriptor];
[objectManager addRequestDescriptor:secondRequestDescriptor];
NSArray *arrayOfObjects = @[ user, address ];
NSException *caughtException = nil;
@try {
NSURLRequest __unused *request = [objectManager requestWithObject:arrayOfObjects method:RKRequestMethodPOST path:@"/path" parameters:@{ @"name": @"Foo" }];
}
@catch (NSException *exception) {
caughtException = exception;
expect([exception name]).to.equal(NSInvalidArgumentException);
expect([exception reason]).to.equal(@"Cannot merge parameters with array of object representations serialized with a nil root key path.");
}
expect(caughtException).notTo.beNil();
}
- (void)testThatAttemptingToPostObjectsWithAMixtureOfNilAndNonNilRootKeyPathsRaisesError
{
RKObjectMapping *firstRequestMapping = [RKObjectMapping requestMapping];
[firstRequestMapping addAttributeMappingsFromArray:@[ @"name", @"emailAddress" ]];
RKObjectMapping *secondRequestMapping = [RKObjectMapping requestMapping];
[secondRequestMapping addAttributeMappingsFromArray:@[ @"city", @"state" ]];
RKRequestDescriptor *firstRequestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:firstRequestMapping objectClass:[RKTestUser class] rootKeyPath:@"bang"];
RKRequestDescriptor *secondRequestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:secondRequestMapping objectClass:[RKTestAddress class] rootKeyPath:nil];
RKTestUser *user = [RKTestUser new];
user.name = @"Blake";
user.emailAddress = @"blake@restkit.org";
RKTestAddress *address = [RKTestAddress new];
address.city = @"New York City";
address.state = @"New York";
RKObjectManager *objectManager = [RKTestFactory objectManager];
objectManager.requestSerializationMIMEType = RKMIMETypeJSON;
[objectManager addRequestDescriptor:firstRequestDescriptor];
[objectManager addRequestDescriptor:secondRequestDescriptor];
NSArray *arrayOfObjects = @[ user, address ];
NSException *caughtException = nil;
@try {
NSURLRequest __unused *request = [objectManager requestWithObject:arrayOfObjects method:RKRequestMethodPOST path:@"/path" parameters:nil];
}
@catch (NSException *exception) {
caughtException = exception;
expect([exception name]).to.equal(NSInvalidArgumentException);
expect([exception reason]).to.equal(@"Invalid request descriptor configuration: The request descriptors specify that multiple objects be serialized at incompatible key paths. Cannot serialize objects at the `nil` root key path in the same request as objects with a non-nil root key path. Please check your request descriptors and try again.");
}
expect(caughtException).notTo.beNil();
}
#pragma mark - Object Request Operation Registration
- (void)testRegistrationOfObjectRequestOperationClass
{
RKObjectManager *manager = [RKObjectManager managerWithBaseURL:[NSURL URLWithString:@"http://restkit.org"]];
[manager registerRequestOperationClass:[RKTestObjectRequestOperation class]];
NSURL *URL = [NSURL URLWithString:@"/match" relativeToURL:manager.baseURL];
NSURLRequest *request = [NSURLRequest requestWithURL:URL];
RKObjectRequestOperation *operation = [manager objectRequestOperationWithRequest:request success:nil failure:nil];
expect(operation).to.beInstanceOf([RKTestObjectRequestOperation class]);
}
- (void)testRegistrationOfObjectRequestOperationClassRespectsSubclassDecisionToProcessRequest
{
RKObjectManager *manager = [RKObjectManager managerWithBaseURL:[NSURL URLWithString:@"http://restkit.org"]];
[manager registerRequestOperationClass:[RKTestObjectRequestOperation class]];
NSURL *URL = [NSURL URLWithString:@"/mismatch" relativeToURL:manager.baseURL];
NSURLRequest *request = [NSURLRequest requestWithURL:URL];
RKObjectRequestOperation *operation = [manager objectRequestOperationWithRequest:request success:nil failure:nil];
expect(operation).notTo.beInstanceOf([RKTestObjectRequestOperation class]);
expect(operation).to.beInstanceOf([RKObjectRequestOperation class]);
}
- (void)testRegistrationOfManagedObjectRequestOperationClass
{
RKManagedObjectStore *managedObjectStore = [RKTestFactory managedObjectStore];
RKObjectManager *manager = [RKObjectManager managerWithBaseURL:[NSURL URLWithString:@"http://restkit.org"]];
[manager registerRequestOperationClass:[RKTestManagedObjectRequestOperation class]];
NSURL *URL = [NSURL URLWithString:@"/match" relativeToURL:manager.baseURL];
NSURLRequest *request = [NSURLRequest requestWithURL:URL];
RKObjectRequestOperation *operation = [manager managedObjectRequestOperationWithRequest:request managedObjectContext:managedObjectStore.mainQueueManagedObjectContext success:nil failure:nil];
expect(operation).to.beInstanceOf([RKTestManagedObjectRequestOperation class]);
}
- (void)testRegistrationOfManagedObjectRequestOperationClassRespectsSubclassDecisionToProcessRequest
{
RKManagedObjectStore *managedObjectStore = [RKTestFactory managedObjectStore];
RKObjectManager *manager = [RKObjectManager managerWithBaseURL:[NSURL URLWithString:@"http://restkit.org"]];
[manager registerRequestOperationClass:[RKTestManagedObjectRequestOperation class]];
NSURL *URL = [NSURL URLWithString:@"/mismatch" relativeToURL:manager.baseURL];
NSURLRequest *request = [NSURLRequest requestWithURL:URL];
RKObjectRequestOperation *operation = [manager managedObjectRequestOperationWithRequest:request managedObjectContext:managedObjectStore.mainQueueManagedObjectContext success:nil failure:nil];
expect(operation).notTo.beInstanceOf([RKTestManagedObjectRequestOperation class]);
expect(operation).to.beInstanceOf([RKManagedObjectRequestOperation class]);
}
- (void)testThatPostingUnsavedObjectWithUnsavedChildrenDoesNotCrash
{
RKManagedObjectStore *managedObjectStore = [RKTestFactory managedObjectStore];
NSManagedObject *developmentTag = [NSEntityDescription insertNewObjectForEntityForName:@"Tag" inManagedObjectContext:managedObjectStore.mainQueueManagedObjectContext];
[developmentTag setValue:@"development" forKey:@"name"];
NSManagedObject *restkitTag = [NSEntityDescription insertNewObjectForEntityForName:@"Tag" inManagedObjectContext:managedObjectStore.mainQueueManagedObjectContext];
[restkitTag setValue:@"restkit" forKey:@"name"];
NSManagedObject *post = [NSEntityDescription insertNewObjectForEntityForName:@"Post" inManagedObjectContext:managedObjectStore.mainQueueManagedObjectContext];
[post setValue:@"Post Title" forKey:@"title"];
[post setValue:[NSSet setWithObjects:developmentTag, restkitTag, nil] forKey:@"tags"];
RKEntityMapping *postMapping = [RKEntityMapping mappingForEntityForName:@"Post" inManagedObjectStore:managedObjectStore];
postMapping.identificationAttributes = @[ @"title" ];
[postMapping addAttributeMappingsFromArray:@[ @"title", @"body" ]];
RKEntityMapping *tagMapping = [RKEntityMapping mappingForEntityForName:@"Tag" inManagedObjectStore:managedObjectStore];
tagMapping.identificationAttributes = @[ @"name" ];
[tagMapping addAttributeMappingsFromArray:@[ @"name" ]];
[postMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"tags" toKeyPath:@"tags" withMapping:tagMapping]];
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:postMapping pathPattern:nil keyPath:@"post" statusCodes:[NSIndexSet indexSetWithIndex:200]];
RKObjectMapping *tagRequestMapping = [RKObjectMapping requestMapping];
[tagRequestMapping addAttributeMappingsFromArray:@[ @"name" ]];
RKObjectMapping *postRequestMapping = [RKObjectMapping requestMapping];
[postRequestMapping addAttributeMappingsFromArray:@[ @"title", @"body" ]];
[postRequestMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"tags" toKeyPath:@"tags" withMapping:tagRequestMapping]];
RKRequestDescriptor *requestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:postRequestMapping objectClass:[NSManagedObject class] rootKeyPath:nil];
RKObjectManager *objectManager = [RKTestFactory objectManager];
objectManager.managedObjectStore = managedObjectStore;
[objectManager addResponseDescriptor:responseDescriptor];
[objectManager addRequestDescriptor:requestDescriptor];
expect([post isNew]).to.equal(YES);
expect([post.objectID isTemporaryID]).to.equal(YES);
expect([developmentTag isNew]).to.equal(YES);
expect([developmentTag.objectID isTemporaryID]).to.equal(YES);
expect([restkitTag isNew]).to.equal(YES);
expect([restkitTag.objectID isTemporaryID]).to.equal(YES);
__block RKMappingResult *postMappingResult = nil;
RKManagedObjectRequestOperation *operation = [objectManager appropriateObjectRequestOperationWithObject:post method:RKRequestMethodPOST path:@"/posts.json" parameters:nil];
operation.savesToPersistentStore = NO;
[operation setCompletionBlockWithSuccess:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
postMappingResult = mappingResult;
} failure:nil];
[objectManager enqueueObjectRequestOperation:operation];
expect(postMappingResult).willNot.beNil();
expect([post.objectID isTemporaryID]).will.equal(NO);
expect([developmentTag.objectID isTemporaryID]).will.equal(NO);
expect([restkitTag.objectID isTemporaryID]).will.equal(NO);
}
- (void)testPathMatchingForMultipartRequest
{
RKObjectManager *objectManager = [RKTestFactory objectManager];
NSString *path = @"/api/upload/";
NSData *blakePng = [RKTestFixture dataWithContentsOfFixture:@"blake.png"];
NSMutableURLRequest *request = [objectManager multipartFormRequestWithObject:nil method:RKRequestMethodPOST path:path parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
[formData appendPartWithFileData:blakePng
name:@"file"
fileName:@"blake.png"
mimeType:@"image/png"];
}];
RKObjectMapping *mapping = [RKObjectMapping mappingForClass:[RKTestUser class]];
[mapping addAttributeMappingsFromArray:@[ @"name" ]];
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:mapping pathPattern:path keyPath:nil statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
[objectManager addResponseDescriptor:responseDescriptor];
RKObjectRequestOperation * operation = [[RKObjectRequestOperation alloc] initWithRequest:request responseDescriptors:@[ responseDescriptor ]];
[[RKObjectManager sharedManager] enqueueObjectRequestOperation:operation];
expect([operation isFinished]).will.equal(YES);
expect(operation.error).to.beNil();
RKTestUser *user = [operation.mappingResult firstObject];
expect(user.name).to.equal(@"Blake");
}
- (void)testPostingTemporaryObjectThatDoesNotExistInCacheDoesNotCreateDuplicatesWithFetchRequestCache
{
RKManagedObjectStore *managedObjectStore = [RKTestFactory managedObjectStore];
RKFetchRequestManagedObjectCache *managedObjectCache = [RKFetchRequestManagedObjectCache new];
managedObjectStore.managedObjectCache = managedObjectCache;
NSEntityDescription *entity = [managedObjectStore.managedObjectModel entitiesByName][@"Human"];
RKEntityMapping *entityMapping = [RKEntityMapping mappingForEntityForName:@"Human" inManagedObjectStore:managedObjectStore];
entityMapping.identificationAttributes = @[ @"railsID" ];
[entityMapping addAttributeMappingsFromDictionary:@{ @"id": @"railsID", @"name": @"name" }];
NSManagedObjectContext *childContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
[childContext setParentContext:managedObjectStore.mainQueueManagedObjectContext];
RKHuman *human = [NSEntityDescription insertNewObjectForEntityForName:@"Human" inManagedObjectContext:childContext];
RKObjectManager *objectManager = [RKObjectManager managerWithBaseURL:[RKTestFactory baseURL]];
objectManager.managedObjectStore = managedObjectStore;
[objectManager addResponseDescriptor:[RKResponseDescriptor responseDescriptorWithMapping:entityMapping pathPattern:@"/humans" keyPath:@"human" statusCodes:[NSIndexSet indexSetWithIndex:201]]];
__block RKMappingResult *mappingResult = nil;
[objectManager postObject:human path:@"/humans" parameters:nil success:^(RKObjectRequestOperation *operation, RKMappingResult *blockMappingResult) {
mappingResult = blockMappingResult;
} failure:nil];
expect(mappingResult).willNot.beNil();
expect([[human objectID] isTemporaryID]).to.beFalsy();
NSSet *managedObjects = [managedObjectCache managedObjectsWithEntity:entity attributeValues:@{ @"railsID": @(1) } inManagedObjectContext:childContext];
expect(managedObjects).to.haveCountOf(1);
[objectManager postObject:human path:@"/humans" parameters:nil success:^(RKObjectRequestOperation *operation, RKMappingResult *blockMappingResult) {
mappingResult = blockMappingResult;
} failure:nil];
expect(mappingResult).willNot.beNil();
managedObjects = [managedObjectCache managedObjectsWithEntity:entity attributeValues:@{ @"railsID": @(1) } inManagedObjectContext:childContext];
expect(managedObjects).to.haveCountOf(1);
}
- (void)testPostingTemporaryObjectWithChildObjectsThatDoesNotExistInCacheDoesNotCreateDuplicatesWithFetchRequestCache
{
RKManagedObjectStore *managedObjectStore = [RKTestFactory managedObjectStore];
RKFetchRequestManagedObjectCache *managedObjectCache = [RKFetchRequestManagedObjectCache new];
managedObjectStore.managedObjectCache = managedObjectCache;
NSManagedObject *developmentTag = [NSEntityDescription insertNewObjectForEntityForName:@"Tag" inManagedObjectContext:managedObjectStore.mainQueueManagedObjectContext];
[developmentTag setValue:@"development" forKey:@"name"];
NSManagedObject *restkitTag = [NSEntityDescription insertNewObjectForEntityForName:@"Tag" inManagedObjectContext:managedObjectStore.mainQueueManagedObjectContext];
[restkitTag setValue:@"restkit" forKey:@"name"];
NSManagedObject *post = [NSEntityDescription insertNewObjectForEntityForName:@"Post" inManagedObjectContext:managedObjectStore.mainQueueManagedObjectContext];
[post setValue:@"Post Title" forKey:@"title"];
[post setValue:[NSSet setWithObjects:developmentTag, restkitTag, nil] forKey:@"tags"];
RKEntityMapping *postMapping = [RKEntityMapping mappingForEntityForName:@"Post" inManagedObjectStore:managedObjectStore];
postMapping.identificationAttributes = @[ @"title" ];
[postMapping addAttributeMappingsFromArray:@[ @"title", @"body" ]];
RKEntityMapping *tagMapping = [RKEntityMapping mappingForEntityForName:@"Tag" inManagedObjectStore:managedObjectStore];
[tagMapping addAttributeMappingsFromArray:@[ @"name" ]];
RKRelationshipMapping *relationshipMapping = [RKRelationshipMapping relationshipMappingFromKeyPath:@"tags" toKeyPath:@"tags" withMapping:tagMapping];
[postMapping addPropertyMapping:relationshipMapping];
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:postMapping pathPattern:nil keyPath:@"post" statusCodes:[NSIndexSet indexSetWithIndex:200]];
RKObjectMapping *tagRequestMapping = [RKObjectMapping requestMapping];
[tagRequestMapping addAttributeMappingsFromArray:@[ @"name" ]];
RKObjectMapping *postRequestMapping = [RKObjectMapping requestMapping];
[postRequestMapping addAttributeMappingsFromArray:@[ @"title", @"body" ]];
[postRequestMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"tags" toKeyPath:@"tags" withMapping:tagRequestMapping]];
RKRequestDescriptor *requestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:postRequestMapping objectClass:[NSManagedObject class] rootKeyPath:nil];
RKObjectManager *objectManager = [RKTestFactory objectManager];
objectManager.managedObjectStore = managedObjectStore;
[objectManager addResponseDescriptor:responseDescriptor];
[objectManager addRequestDescriptor:requestDescriptor];
expect([post isNew]).to.equal(YES);
expect([post.objectID isTemporaryID]).to.equal(YES);
expect([developmentTag isNew]).to.equal(YES);
expect([developmentTag.objectID isTemporaryID]).to.equal(YES);
expect([restkitTag isNew]).to.equal(YES);
expect([restkitTag.objectID isTemporaryID]).to.equal(YES);
__block RKMappingResult *postMappingResult = nil;
RKManagedObjectRequestOperation *operation = [objectManager appropriateObjectRequestOperationWithObject:post method:RKRequestMethodPOST path:@"/posts.json" parameters:nil];
operation.savesToPersistentStore = NO;
[operation setCompletionBlockWithSuccess:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
postMappingResult = mappingResult;
} failure:nil];
[objectManager enqueueObjectRequestOperation:operation];
expect(postMappingResult).willNot.beNil();
expect([post.objectID isTemporaryID]).will.equal(NO);
expect([developmentTag.objectID isTemporaryID]).will.equal(NO);
expect([restkitTag.objectID isTemporaryID]).will.equal(NO);
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"Tag"];
NSUInteger tagsCount = [objectManager.managedObjectStore.mainQueueManagedObjectContext countForFetchRequest:fetchRequest error:nil];
expect(tagsCount).to.equal(2);
}
- (void)testThatMappingAToManyRelationshipOnAnExistingSetOfObjectsDoesNotReuseTheFirstObjectInTheCollection
{
RKManagedObjectStore *managedObjectStore = [RKTestFactory managedObjectStore];
RKEntityMapping *postMapping = [RKEntityMapping mappingForEntityForName:@"Post" inManagedObjectStore:managedObjectStore];
[postMapping addAttributeMappingsFromDictionary:@{ @"title": @"title" }];
RKEntityMapping *tagMapping = [RKEntityMapping mappingForEntityForName:@"Tag" inManagedObjectStore:managedObjectStore];
[tagMapping addAttributeMappingsFromDictionary:@{ @"name": @"name" }];
[postMapping addRelationshipMappingWithSourceKeyPath:@"tags" mapping:tagMapping];
NSDictionary *representation = @{ @"title": @"The Post", @"tags": @[ @{ @"name": @"first" }, @{ @"name": @"second" } ] };
RKFetchRequestManagedObjectCache *fetchRequestCache = [RKFetchRequestManagedObjectCache new];
RKManagedObjectMappingOperationDataSource *dataSource = [[RKManagedObjectMappingOperationDataSource alloc] initWithManagedObjectContext:managedObjectStore.mainQueueManagedObjectContext cache:fetchRequestCache];
RKMapperOperation *mapperOperation = [[RKMapperOperation alloc] initWithRepresentation:representation mappingsDictionary:@{ [NSNull null]: postMapping }];
mapperOperation.mappingOperationDataSource = dataSource;
NSError *error = nil;
BOOL success = [mapperOperation execute:&error];
expect(success).to.beTruthy();
RKPost *post = [mapperOperation.mappingResult firstObject];
expect(post.tags).to.haveCountOf(2);
mapperOperation = [[RKMapperOperation alloc] initWithRepresentation:representation mappingsDictionary:@{ [NSNull null]: postMapping }];
mapperOperation.mappingOperationDataSource = dataSource;
success = [mapperOperation execute:&error];
expect(success).to.beTruthy();
post = [mapperOperation.mappingResult firstObject];
expect(post.tags).to.haveCountOf(2);
}
- (void)testMappingErrorsFromFiveHundredStatusCodeRange
{
RKObjectManager *objectManager = [RKObjectManager managerWithBaseURL:[RKTestFactory baseURL]];
NSIndexSet *statusCodes = RKStatusCodeIndexSetForClass(RKStatusCodeClassServerError);
RKObjectMapping *errorResponseMapping = [RKObjectMapping mappingForClass:[RKErrorMessage class]];
[errorResponseMapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:nil toKeyPath:@"errorMessage"]];
[objectManager addResponseDescriptor:[RKResponseDescriptor responseDescriptorWithMapping:errorResponseMapping pathPattern:nil keyPath:@"errors" statusCodes:statusCodes]];
__block NSError *error = nil;
[objectManager getObjectsAtPath:@"/fail" parameters:nil success:nil failure:^(RKObjectRequestOperation *operation, NSError *blockError) {
error = blockError;
}];
expect(error).willNot.beNil();
expect([error localizedDescription]).to.equal(@"error1, error2");
}
- (void)testPostingATemporaryObjectThatHasJustBeenSaved
{
NSManagedObjectContext *managedObjectContext = [[RKTestFactory managedObjectStore] mainQueueManagedObjectContext];
RKHuman *temporaryHuman = [NSEntityDescription insertNewObjectForEntityForName:@"Human" inManagedObjectContext:managedObjectContext];
temporaryHuman.name = @"My Name";
expect([temporaryHuman.objectID isTemporaryID]).to.equal(YES);
NSError *error = nil;
BOOL success = [temporaryHuman.managedObjectContext saveToPersistentStore:&error];
expect(success).to.equal(YES);
expect([temporaryHuman.objectID isTemporaryID]).to.equal(YES); // Still temporary because the permanent ID has not yet been merged
RKManagedObjectRequestOperation *operation = [_objectManager appropriateObjectRequestOperationWithObject:temporaryHuman method:RKRequestMethodPOST path:nil parameters:nil];
[_objectManager enqueueObjectRequestOperation:operation];
expect([operation isFinished]).will.equal(YES);
expect(operation.mappingResult).notTo.beNil();
expect([operation.mappingResult array]).notTo.beEmpty();
RKHuman *human = (RKHuman *)[[operation.mappingResult array] objectAtIndex:0];
expect(human.objectID).to.equal(temporaryHuman.objectID);
expect(human.railsID).to.equal(1);
}
- (void)testConnectingARelationshipToAnObjectUsingRoutingMetadata
{
RKManagedObjectStore *managedObjectStore = [RKTestFactory managedObjectStore];
RKFetchRequestManagedObjectCache *managedObjectCache = [RKFetchRequestManagedObjectCache new];
managedObjectStore.managedObjectCache = managedObjectCache;
NSManagedObject *post = [NSEntityDescription insertNewObjectForEntityForName:@"Post" inManagedObjectContext:managedObjectStore.mainQueueManagedObjectContext];
[post setValue:@"The Post" forKey:@"title"];
[post setValue:@(1234) forKey:@"postID"];
RKEntityMapping *tagMapping = [RKEntityMapping mappingForEntityForName:@"Tag" inManagedObjectStore:managedObjectStore];
[tagMapping addAttributeMappingsFromDictionary:@{ @"@metadata.routing.parameters.postID": @"postID", @"name": @"name" }];
[tagMapping addConnectionForRelationship:@"posts" connectedBy:@{ @"postID": @"postID" }];
RKObjectManager *objectManager = [RKTestFactory objectManager];
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:tagMapping pathPattern:@"/posts/:postID/tags" keyPath:nil statusCodes:[NSIndexSet indexSetWithIndex:200]];
[objectManager addResponseDescriptor:responseDescriptor];
[objectManager.router.routeSet addRoute:[RKRoute routeWithRelationshipName:@"tags" objectClass:[RKPost class] pathPattern:@"/posts/:postID/tags" method:RKRequestMethodGET]];
__block RKMappingResult *mappingResult = nil;
[objectManager getObjectsAtPathForRelationship:@"tags" ofObject:post parameters:nil success:^(RKObjectRequestOperation *operation, RKMappingResult *blockMappingResult) {
mappingResult = blockMappingResult;
} failure:nil];
expect(mappingResult).willNot.beNil();
NSArray *tags = [mappingResult array];
expect(tags).notTo.beNil();
NSArray *tagNames = @[@"development", @"restkit"];
expect([tags valueForKey:@"name"]).to.equal(tagNames);
NSSet *connectedTags = [post valueForKey:@"tags"];
expect(connectedTags).notTo.beEmpty();
}
- (void)testMappingMetadataParameterForNamedRoute
{
RKObjectManager *objectManager = [RKObjectManager managerWithBaseURL:[RKTestFactory baseURL]];
RKObjectMapping *userMapping = [RKObjectMapping mappingForClass:[RKTestUser class]];
[userMapping addAttributeMappingsFromDictionary:@{ @"name": @"name", @"@metadata.routing.parameters.userID": @"position" }];
[objectManager.router.routeSet addRoute:[RKRoute routeWithName:@"load_human" pathPattern:@"/JSON/humans/:userID\\.json" method:RKRequestMethodGET]];
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:userMapping pathPattern:@"/JSON/humans/:userID\\.json" keyPath:@"human" statusCodes:[NSIndexSet indexSetWithIndex:200]];
[objectManager addResponseDescriptor:responseDescriptor];
RKTestUser *user = [RKTestUser new];
user.userID = @1;
__block RKMappingResult *mappingResult = nil;
[objectManager getObjectsAtPathForRouteNamed:@"load_human" object:user parameters:nil success:^(RKObjectRequestOperation *operation, RKMappingResult *blockMappingResult) {
mappingResult = blockMappingResult;
} failure:nil];
expect(mappingResult).willNot.beNil();
RKTestUser *anotherUser = [mappingResult firstObject];
expect(anotherUser.name).to.equal(@"Blake Watters");
expect(anotherUser.position).to.equal(@1);
}
- (void)testRoutingMetadataWithAppropriateObjectRequestOperation
{
NSManagedObjectContext *managedObjectContext = [[RKTestFactory managedObjectStore] persistentStoreManagedObjectContext];
RKHuman *temporaryHuman = [RKTestFactory insertManagedObjectForEntityForName:@"Human" inManagedObjectContext:managedObjectContext withProperties:nil];
temporaryHuman.name = @"My Name";
temporaryHuman.railsID = @(12345);
RKManagedObjectRequestOperation *operation = [_objectManager appropriateObjectRequestOperationWithObject:temporaryHuman method:RKRequestMethodDELETE path:nil parameters:nil];
expect([operation.mappingMetadata valueForKeyPath:@"routing.parameters.railsID"]).to.equal(@"12345");
}
- (void)testThatNoCrashOccursWhenLoadingNamedRouteWithNilObject
{
RKObjectManager *objectManager = [RKObjectManager managerWithBaseURL:[RKTestFactory baseURL]];
RKObjectMapping *userMapping = [RKObjectMapping mappingForClass:[RKTestUser class]];
[objectManager.router.routeSet addRoute:[RKRoute routeWithName:@"named_route" pathPattern:@"/JSON/humans/1.json" method:RKRequestMethodGET]];
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:userMapping pathPattern:nil keyPath:@"human" statusCodes:[NSIndexSet indexSetWithIndex:200]];
[objectManager addResponseDescriptor:responseDescriptor];
__block RKMappingResult *mappingResult = nil;
[objectManager getObjectsAtPathForRouteNamed:@"named_route" object:nil parameters:nil success:^(RKObjectRequestOperation *operation, RKMappingResult *blockMappingResult) {
mappingResult = blockMappingResult;
} failure:nil];
expect(mappingResult).willNot.beNil();
}
- (void)testUseOfMetadataMappingAsIdentificationAttribute
{
RKObjectManager *objectManager = [RKObjectManager managerWithBaseURL:[RKTestFactory baseURL]];
objectManager.managedObjectStore = [RKTestFactory managedObjectStore];
RKEntityMapping *humanMapping = [RKEntityMapping mappingForEntityForName:@"Human" inManagedObjectStore:objectManager.managedObjectStore];
[humanMapping addAttributeMappingsFromDictionary:@{ @"name": @"name", @"@metadata.routing.parameters.railsID": @"favoriteCatID" }];
[humanMapping setIdentificationAttributes:@[ @"favoriteCatID" ]];
[objectManager.router.routeSet addRoute:[RKRoute routeWithName:@"load_human" pathPattern:@"/JSON/humans/:railsID\\.json" method:RKRequestMethodGET]];
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:humanMapping pathPattern:@"/JSON/humans/:railsID\\.json" keyPath:@"human" statusCodes:[NSIndexSet indexSetWithIndex:200]];
[objectManager addResponseDescriptor:responseDescriptor];
RKHuman *human = [NSEntityDescription insertNewObjectForEntityForName:@"Human" inManagedObjectContext:objectManager.managedObjectStore.mainQueueManagedObjectContext];
human.railsID = @1;
__block RKMappingResult *mappingResult = nil;
[objectManager getObjectsAtPathForRouteNamed:@"load_human" object:human parameters:nil success:^(RKObjectRequestOperation *operation, RKMappingResult *blockMappingResult) {
mappingResult = blockMappingResult;
} failure:nil];
expect(mappingResult).willNot.beNil();
RKHuman *anotherHuman = [mappingResult firstObject];
expect(anotherHuman.name).to.equal(@"Blake Watters");
expect(anotherHuman.favoriteCatID).to.equal(@1);
expect([anotherHuman isEqual:human]).to.beFalsy();
}
@end