PageRenderTime 171ms CodeModel.GetById 2ms app.highlight 161ms RepoModel.GetById 1ms app.codeStats 0ms

/Tests/Logic/ObjectMapping/RKObjectParameterizationTest.m

http://github.com/RestKit/RestKit
Objective C | 786 lines | 621 code | 136 blank | 29 comment | 0 complexity | 1f84cd23b77273435856a86718bf2463 MD5 | raw file
  1//
  2//  RKObjectParameterizationTest.m
  3//  RestKit
  4//
  5//  Created by Jeremy Ellison on 5/9/11.
  6//  Copyright (c) 2009-2012 RestKit. All rights reserved.
  7//
  8//  Licensed under the Apache License, Version 2.0 (the "License");
  9//  you may not use this file except in compliance with the License.
 10//  You may obtain a copy of the License at
 11//
 12//  http://www.apache.org/licenses/LICENSE-2.0
 13//
 14//  Unless required by applicable law or agreed to in writing, software
 15//  distributed under the License is distributed on an "AS IS" BASIS,
 16//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 17//  See the License for the specific language governing permissions and
 18//  limitations under the License.
 19//
 20
 21#import <CoreLocation/CoreLocation.h>
 22#import "RKTestEnvironment.h"
 23#import "RKObjectParameterization.h"
 24#import "RKMIMETypeSerialization.h"
 25#import "RKMappableObject.h"
 26#import "RKDynamicMapping.h"
 27#import "RKMappingErrors.h"
 28#import "RKHuman.h"
 29#import "RKTestUser.h"
 30#import "RKCat.h"
 31#import "RKCLLocationValueTransformer.h"
 32
 33@interface RKMIMETypeSerialization ()
 34@property (nonatomic, strong) NSMutableArray *registrations;
 35
 36+ (RKMIMETypeSerialization *)sharedSerialization;
 37- (void)addRegistrationsForKnownSerializations;
 38@end
 39
 40@interface RKObjectParameterizationTest : RKTestCase
 41@end
 42
 43@implementation RKObjectParameterizationTest
 44
 45- (void)setUp
 46{
 47    [RKTestFactory setUp];
 48    
 49    [RKMIMETypeSerialization sharedSerialization].registrations = [NSMutableArray array];
 50    [[RKMIMETypeSerialization sharedSerialization] addRegistrationsForKnownSerializations];
 51
 52    // Reset the default transformer
 53    [RKValueTransformer setDefaultValueTransformer:nil];
 54}
 55
 56- (void)tearDown
 57{
 58    [RKTestFactory tearDown];
 59}
 60
 61- (void)testShouldSerializeToFormEncodedData
 62{
 63    NSDictionary *object = @{@"key1": @"value1", @"key2": @"value2"};
 64    RKObjectMapping *mapping = [RKObjectMapping requestMapping];
 65    [mapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"key1" toKeyPath:@"key1-form-name"]];
 66    [mapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"key2" toKeyPath:@"key2-form-name"]];
 67    NSError *error = nil;
 68    RKRequestDescriptor *requestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:mapping objectClass:[NSDictionary class] rootKeyPath:nil method:RKRequestMethodAny];
 69    
 70    // URL Encode
 71    NSDictionary *parameters = [RKObjectParameterization parametersWithObject:object requestDescriptor:requestDescriptor error:&error];
 72    NSData *data = [RKMIMETypeSerialization dataFromObject:parameters MIMEType:RKMIMETypeFormURLEncoded error:&error];
 73    NSString *string = [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
 74    expect(error).to.beNil();
 75    expect(string).to.equal(@"key1-form-name=value1&key2-form-name=value2");
 76}
 77
 78- (void)testShouldSerializeADate
 79{
 80    NSDictionary *object = @{@"key1": @"value1", @"date": [NSDate dateWithTimeIntervalSince1970:0]};
 81    RKObjectMapping *mapping = [RKObjectMapping requestMapping];
 82    [mapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"key1" toKeyPath:@"key1-form-name"]];
 83    [mapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"date" toKeyPath:@"date-form-name"]];
 84    
 85    NSError *error = nil;
 86    RKRequestDescriptor *requestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:mapping objectClass:[NSDictionary class] rootKeyPath:nil method:RKRequestMethodAny];
 87    NSDictionary *parameters = [RKObjectParameterization parametersWithObject:object requestDescriptor:requestDescriptor error:&error];
 88    expect(error).to.beNil();
 89    expect(parameters[@"date-form-name"]).to.equal(@"1970-01-01T00:00:00.000Z");
 90}
 91
 92#pragma clang diagnostic push
 93#pragma clang diagnostic ignored "-Wdeprecated-declarations"
 94
 95- (void)testShouldSerializeADateToAStringUsingThePreferredDateFormatter
 96{
 97    NSDictionary *object = @{@"key1": @"value1", @"date": [NSDate dateWithTimeIntervalSince1970:0]};
 98    RKObjectMapping *mapping = [RKObjectMapping requestMapping];
 99    NSDateFormatter *dateFormatter = [NSDateFormatter new];
100    dateFormatter.dateFormat = @"MM/dd/yyyy";
101    dateFormatter.timeZone = [NSTimeZone timeZoneForSecondsFromGMT:0];
102    mapping.preferredDateFormatter = dateFormatter;
103    [mapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"key1" toKeyPath:@"key1-form-name"]];
104    [mapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"date" toKeyPath:@"date-form-name"]];
105    
106    NSError *error = nil;
107    RKRequestDescriptor *requestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:mapping objectClass:[NSDictionary class] rootKeyPath:nil method:RKRequestMethodAny];
108    NSDictionary *parameters = [RKObjectParameterization parametersWithObject:object requestDescriptor:requestDescriptor error:&error];
109    
110    NSData *data = [RKMIMETypeSerialization dataFromObject:parameters MIMEType:RKMIMETypeFormURLEncoded error:&error];
111    NSString *string = [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
112    expect(error).to.beNil();
113    expect(string).to.equal(@"date-form-name=01/01/1970&key1-form-name=value1");
114}
115
116#pragma clang diagnostic pop
117
118- (void)testShouldSerializeADateToAStringUsingTheAttributeMappingValueTransformer
119{
120    NSDictionary *object = @{@"key1": @"value1", @"date": [NSDate dateWithTimeIntervalSince1970:0]};
121    RKObjectMapping *mapping = [RKObjectMapping requestMapping];
122    NSDateFormatter *dateFormatter = [NSDateFormatter new];
123    dateFormatter.dateFormat = @"MM/dd/yyyy";
124    dateFormatter.timeZone = [NSTimeZone timeZoneForSecondsFromGMT:0];
125    RKAttributeMapping *propertyMapping = [RKAttributeMapping attributeMappingFromKeyPath:@"date" toKeyPath:@"date-form-name"];
126
127    propertyMapping.valueTransformer = dateFormatter;
128
129    [mapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"key1" toKeyPath:@"key1-form-name"]];
130    [mapping addPropertyMapping: propertyMapping];
131
132    NSError *error = nil;
133    RKRequestDescriptor *requestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:mapping objectClass:[NSDictionary class] rootKeyPath:nil method:RKRequestMethodAny];
134    NSDictionary *parameters = [RKObjectParameterization parametersWithObject:object requestDescriptor:requestDescriptor error:&error];
135
136    NSData *data = [RKMIMETypeSerialization dataFromObject:parameters MIMEType:RKMIMETypeFormURLEncoded error:&error];
137    NSString *string = [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
138    expect(error).to.beNil();
139    expect(string).to.equal(@"date-form-name=01/01/1970&key1-form-name=value1");
140}
141
142- (void)testShouldSerializeADateToJSON
143{
144    NSDictionary *object = @{@"key1": @"value1", @"date": [NSDate dateWithTimeIntervalSince1970:0]};
145    RKObjectMapping *mapping = [RKObjectMapping requestMapping];
146    [mapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"key1" toKeyPath:@"key1-form-name"]];
147    [mapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"date" toKeyPath:@"date-form-name"]];
148
149    NSError *error = nil;
150    RKRequestDescriptor *requestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:mapping objectClass:[NSDictionary class] rootKeyPath:nil method:RKRequestMethodAny];
151    NSDictionary *parameters = [RKObjectParameterization parametersWithObject:object requestDescriptor:requestDescriptor error:&error];
152    
153    NSData *data = [RKMIMETypeSerialization dataFromObject:parameters MIMEType:RKMIMETypeJSON error:&error];
154    NSString *string = [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
155
156    expect(error).to.beNil();
157    expect(string).to.equal(@"{\"key1-form-name\":\"value1\",\"date-form-name\":\"1970-01-01T00:00:00.000Z\"}");
158}
159
160- (void)testShouldSerializeNSDecimalNumberAttributesToJSON
161{
162    NSDictionary *object = @{@"key1": @"value1", @"number": [NSDecimalNumber decimalNumberWithString:@"18274191731731.4557723623"]};
163    RKObjectMapping *mapping = [RKObjectMapping requestMapping];
164    [mapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"key1" toKeyPath:@"key1-form-name"]];
165    [mapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"number" toKeyPath:@"number-form-name"]];
166        
167    NSError *error = nil;
168    RKRequestDescriptor *requestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:mapping objectClass:[NSDictionary class] rootKeyPath:nil method:RKRequestMethodAny];
169    NSDictionary *parameters = [RKObjectParameterization parametersWithObject:object requestDescriptor:requestDescriptor error:&error];
170    
171    NSData *data = [RKMIMETypeSerialization dataFromObject:parameters MIMEType:RKMIMETypeJSON error:&error];
172    NSString *string = [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
173
174    expect(error).to.beNil();
175    expect(string).to.equal(@"{\"key1-form-name\":\"value1\",\"number-form-name\":\"18274191731731.4557723623\"}");
176}
177
178- (void)testShouldSerializeRelationshipsToo
179{
180    NSDictionary *object = @{@"key1": @"value1", @"key2": @"value2",
181                            @"relationship1": @[@{@"relatioship1Key1": @"relationship1Value1"},
182                             @{@"relatioship1Key1": @"relationship1Value2"}],
183                            @"relationship2": @{@"subKey1": @"subValue1"}};
184
185    RKObjectMapping *mapping = [RKObjectMapping requestMapping];
186    [mapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"key1" toKeyPath:@"key1-form-name"]];
187    [mapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"key2" toKeyPath:@"key2-form-name"]];
188    [mapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"relationship1.relatioship1Key1" toKeyPath:@"relationship1-form-name[r1k1]"]];
189    [mapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"relationship2.subKey1" toKeyPath:@"relationship2-form-name[subKey1]"]];
190
191    NSError *error = nil;
192    RKRequestDescriptor *requestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:mapping objectClass:[NSDictionary class] rootKeyPath:nil method:RKRequestMethodAny];
193    NSDictionary *parameters = [RKObjectParameterization parametersWithObject:object requestDescriptor:requestDescriptor error:&error];
194    
195    NSData *data = [RKMIMETypeSerialization dataFromObject:parameters MIMEType:RKMIMETypeFormURLEncoded error:&error];
196    NSString *string = [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
197
198    expect(error).to.beNil();
199    expect(string).to.equal(@"key1-form-name=value1&key2-form-name=value2&relationship1-form-name[r1k1][]=relationship1Value1&relationship1-form-name[r1k1][]=relationship1Value2&relationship2-form-name[subKey1]=subValue1");
200}
201
202- (void)testShouldSerializeToJSON
203{
204    NSDictionary *object = @{@"key1": @"value1", @"key2": @"value2"};
205    RKObjectMapping *mapping = [RKObjectMapping requestMapping];
206    [mapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"key1" toKeyPath:@"key1-form-name"]];
207    [mapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"key2" toKeyPath:@"key2-form-name"]];
208    
209    NSError *error = nil;
210    RKRequestDescriptor *requestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:mapping objectClass:[NSDictionary class] rootKeyPath:nil method:RKRequestMethodAny];
211    NSDictionary *parameters = [RKObjectParameterization parametersWithObject:object requestDescriptor:requestDescriptor error:&error];
212    
213    NSData *data = [RKMIMETypeSerialization dataFromObject:parameters MIMEType:RKMIMETypeJSON error:&error];
214    NSString *string = [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
215
216    expect(error).to.beNil();
217    expect(string).to.equal(@"{\"key2-form-name\":\"value2\",\"key1-form-name\":\"value1\"}");
218}
219
220- (void)testShouldSetReturnEmptyDictionaryIfItDoesNotFindAnythingToSerialize
221{
222    NSDictionary *object = @{@"key1": @"value1", @"key2": @"value2"};
223    RKObjectMapping *mapping = [RKObjectMapping requestMapping];
224    [mapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"key12123" toKeyPath:@"key1-form-name"]];
225    
226    NSError *error = nil;
227    RKRequestDescriptor *requestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:mapping objectClass:[NSDictionary class] rootKeyPath:nil method:RKRequestMethodAny];
228    NSDictionary *parameters = [RKObjectParameterization parametersWithObject:object requestDescriptor:requestDescriptor error:&error];
229    expect(error).to.beNil();
230    expect(parameters).to.equal(@{ @"key1-form-name": [NSNull null] });
231}
232
233- (void)testEmptyParameterizationRespectsRootKeyPath
234{
235    NSDictionary *object = @{@"key1": @"value1", @"key2": @"value2"};
236    RKObjectMapping *mapping = [RKObjectMapping requestMapping];
237    [mapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"key12123" toKeyPath:@"key1-form-name"]];
238    
239    NSError *error = nil;
240    RKRequestDescriptor *requestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:mapping objectClass:[NSDictionary class] rootKeyPath:@"root" method:RKRequestMethodAny];
241    NSDictionary *parameters = [RKObjectParameterization parametersWithObject:object requestDescriptor:requestDescriptor error:&error];
242    expect(error).to.beNil();
243    expect(parameters).to.equal(@{ @"root":@{ @"key1-form-name": [NSNull null] } });
244}
245
246- (void)testShouldSerializeNestedObjectsContainingDatesToJSON
247{
248    RKMappableObject *object = [RKMappableObject new];
249    object.stringTest = @"The string";
250    RKMappableAssociation *association = [RKMappableAssociation new];
251    association.date = [NSDate dateWithTimeIntervalSince1970:0];
252    object.hasOne = association;
253
254    // Setup object mappings
255    RKObjectMapping *objectMapping = [RKObjectMapping requestMapping];
256    [objectMapping addAttributeMappingsFromArray:@[ @"stringTest" ]];
257    RKObjectMapping *relationshipMapping = [RKObjectMapping mappingForClass:[NSMutableDictionary class]];
258    [relationshipMapping addAttributeMappingsFromArray:@[ @"date" ]];
259    [objectMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"hasOne" toKeyPath:@"hasOne" withMapping:relationshipMapping]];
260    
261    NSError *error = nil;
262    RKRequestDescriptor *requestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:objectMapping objectClass:[NSDictionary class] rootKeyPath:nil method:RKRequestMethodAny];
263    NSDictionary *parameters = [RKObjectParameterization parametersWithObject:object requestDescriptor:requestDescriptor error:&error];
264    
265    NSData *data = [RKMIMETypeSerialization dataFromObject:parameters MIMEType:RKMIMETypeJSON error:&error];
266    NSString *string = [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
267
268    expect((@[@"{\"stringTest\":\"The string\",\"hasOne\":{\"date\":\"1970-01-01T00:00:00.000Z\"}}", @"{\"hasOne\":{\"date\":\"1970-01-01T00:00:00.000Z\"},\"stringTest\":\"The string\"}"])).to.contain(string);
269}
270
271- (void)testShouldEncloseTheSerializationInAContainerIfRequested
272{
273    NSDictionary *object = @{@"key1": @"value1", @"key2": @"value2"};
274    RKObjectMapping *mapping = [RKObjectMapping requestMapping];
275    [mapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"key1" toKeyPath:@"key1-form-name"]];
276    [mapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"key2" toKeyPath:@"key2-form-name"]];
277    
278    NSError *error = nil;
279    RKRequestDescriptor *requestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:mapping objectClass:[NSDictionary class] rootKeyPath:@"stuff" method:RKRequestMethodAny];
280    NSDictionary *parameters = [RKObjectParameterization parametersWithObject:object requestDescriptor:requestDescriptor error:&error];
281    
282    expect(parameters[@"stuff"][@"key2-form-name"]).to.equal(@"value2");
283    expect(parameters[@"stuff"][@"key1-form-name"]).to.equal(@"value1");
284}
285
286- (void)testShouldSerializeToManyRelationships
287{
288    RKMappableObject *object = [RKMappableObject new];
289    object.stringTest = @"The string";
290    RKMappableAssociation *association = [RKMappableAssociation new];
291    association.date = [NSDate dateWithTimeIntervalSince1970:0];
292    object.hasMany = [NSSet setWithObject:association];
293
294    // Setup object mappings
295    RKObjectMapping *objectMapping = [RKObjectMapping mappingForClass:[NSMutableDictionary class]];
296    [objectMapping addAttributeMappingsFromArray:@[@"stringTest"]];
297    RKObjectMapping *relationshipMapping = [RKObjectMapping mappingForClass:[NSMutableDictionary class]];
298    [relationshipMapping addAttributeMappingsFromArray:@[@"date"]];
299    [objectMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"hasMany" toKeyPath:@"hasMany" withMapping:relationshipMapping]];
300
301    // Serialize
302    NSError *error = nil;
303    RKRequestDescriptor *requestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:objectMapping objectClass:[NSDictionary class] rootKeyPath:nil method:RKRequestMethodAny];
304    NSDictionary *parameters = [RKObjectParameterization parametersWithObject:object requestDescriptor:requestDescriptor error:&error];
305    
306    NSData *data = [RKMIMETypeSerialization dataFromObject:parameters MIMEType:RKMIMETypeJSON error:&error];
307    NSString *string = [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
308    expect(string).to.equal(@"{\"hasMany\":[{\"date\":\"1970-01-01T00:00:00.000Z\"}],\"stringTest\":\"The string\"}");
309}
310
311- (void)testShouldSerializeAnNSNumberContainingABooleanToTrueFalseIfRequested
312{
313    NSDictionary *object = @{@"key1": @"value1", @"boolean": @YES};
314    RKObjectMapping *mapping = [RKObjectMapping requestMapping];
315    RKAttributeMapping *attributeMapping = [RKAttributeMapping attributeMappingFromKeyPath:@"boolean" toKeyPath:@"boolean-value"];
316    [mapping addPropertyMapping:attributeMapping];    
317    
318    NSError *error = nil;
319    RKRequestDescriptor *requestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:mapping objectClass:[NSDictionary class] rootKeyPath:nil method:RKRequestMethodAny];
320    NSDictionary *parameters = [RKObjectParameterization parametersWithObject:object requestDescriptor:requestDescriptor error:&error];
321    NSData *data = [RKMIMETypeSerialization dataFromObject:parameters MIMEType:RKMIMETypeJSON error:&error];
322    NSString *string = [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
323
324    expect(error).to.beNil();
325    expect(string).to.equal(@"{\"boolean-value\":true}");
326}
327
328- (void)testShouldSerializeANSOrderedSetToJSON
329{
330    NSDictionary *object = @{@"key1": @"value1",
331                            @"set": [NSOrderedSet orderedSetWithObjects:@"setElementOne", @"setElementTwo", @"setElementThree", nil]};
332    RKObjectMapping *mapping = [RKObjectMapping requestMapping];
333    [mapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"key1" toKeyPath:@"key1-form-name"]];
334    [mapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"set" toKeyPath:@"set-form-name"]];
335    
336    NSError *error = nil;
337    RKRequestDescriptor *requestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:mapping objectClass:[NSDictionary class] rootKeyPath:nil method:RKRequestMethodAny];
338    NSDictionary *parameters = [RKObjectParameterization parametersWithObject:object requestDescriptor:requestDescriptor error:&error];
339    NSData *data = [RKMIMETypeSerialization dataFromObject:parameters MIMEType:RKMIMETypeJSON error:&error];
340    NSString *string = [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
341
342    expect(error).to.beNil();
343    expect(string).to.equal(@"{\"key1-form-name\":\"value1\",\"set-form-name\":[\"setElementOne\",\"setElementTwo\",\"setElementThree\"]}");
344}
345
346- (void)testShouldSerializeAnNSSetToJSON
347{
348    NSDictionary *object = @{@"key1": @"value1",
349                            @"set": [NSSet setWithObjects:@"setElementOne", nil]};
350    RKObjectMapping *mapping = [RKObjectMapping requestMapping];
351    [mapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"key1" toKeyPath:@"key1-form-name"]];
352    [mapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"set" toKeyPath:@"set-form-name"]];
353    
354    NSError *error = nil;
355    RKRequestDescriptor *requestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:mapping objectClass:[NSDictionary class] rootKeyPath:nil method:RKRequestMethodAny];
356    NSDictionary *parameters = [RKObjectParameterization parametersWithObject:object requestDescriptor:requestDescriptor error:&error];
357    NSData *data = [RKMIMETypeSerialization dataFromObject:parameters MIMEType:RKMIMETypeJSON error:&error];
358    NSString *string = [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
359    
360    expect(error).to.beNil();
361    expect(string).to.equal(@"{\"key1-form-name\":\"value1\",\"set-form-name\":[\"setElementOne\"]}");
362}
363
364- (void)testParameterizationOfAttributesNestedByKeyPath
365{
366    NSDictionary *object = @{ @"name" : @"Blake Watters", @"occupation" : @"Hacker" };
367    RKObjectMapping *mapping = [RKObjectMapping requestMapping];
368    [mapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"name" toKeyPath:@"user.name"]];
369    [mapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"occupation" toKeyPath:@"user.job"]];
370    
371    NSError *error = nil;
372    RKRequestDescriptor *requestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:mapping objectClass:[NSDictionary class] rootKeyPath:nil method:RKRequestMethodAny];
373    NSDictionary *parameters = [RKObjectParameterization parametersWithObject:object requestDescriptor:requestDescriptor error:&error];
374    NSDictionary *expected = @{@"user": @{@"name": @"Blake Watters", @"job": @"Hacker"}};
375    expect(parameters).to.equal(expected);
376}
377
378- (void)testParameterizationOfAttributesDeeplyNestedByKeyPathToFormEncoded
379{
380    NSDictionary *object = @{ @"name" : @"Blake Watters", @"occupation" : @"Hacker" };
381    RKObjectMapping *mapping = [RKObjectMapping requestMapping];
382    [mapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"name" toKeyPath:@"user.anotherKeyPath.name"]];
383    [mapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"occupation" toKeyPath:@"user.anotherKeyPath.another.job"]];
384    
385    NSError *error = nil;
386    RKRequestDescriptor *requestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:mapping objectClass:[NSDictionary class] rootKeyPath:nil method:RKRequestMethodAny];
387    NSDictionary *parameters = [RKObjectParameterization parametersWithObject:object requestDescriptor:requestDescriptor error:&error];
388    NSDictionary *expected = @{@"user": @{@"anotherKeyPath": @{@"name": @"Blake Watters", @"another": @{ @"job": @"Hacker"}}}};
389    expect(parameters).to.equal(expected);
390}
391
392- (void)testParameterizationOfPrimitiveBooleansToJSONBooleans
393{
394    NSDictionary *object = @{ @"name" : @"Blake Watters", @"isHacker" : @YES };
395    RKObjectMapping *mapping = [RKObjectMapping requestMapping];
396    [mapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"name" toKeyPath:@"name"]];
397    [mapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"isHacker" toKeyPath:@"isHacker"]];
398    
399    NSError *error = nil;
400    RKRequestDescriptor *requestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:mapping objectClass:[NSDictionary class] rootKeyPath:nil method:RKRequestMethodAny];
401    NSDictionary *parameters = [RKObjectParameterization parametersWithObject:object requestDescriptor:requestDescriptor error:&error];
402    NSDictionary *expected = @ {@"name": @"Blake Watters", @"isHacker": @YES };
403    expect(parameters).to.equal(expected);
404    
405    NSData *data = [RKMIMETypeSerialization dataFromObject:parameters MIMEType:RKMIMETypeJSON error:&error];
406    NSString *string = [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
407    
408    expect(error).to.beNil();
409    expect(string).to.equal(@"{\"name\":\"Blake Watters\",\"isHacker\":true}");
410}
411
412- (void)testParameterizationOfBooleanPropertiesToJSONBooleansFromObjectProperties
413{
414    RKMappableObject *object = [RKMappableObject new];
415    object.stringTest = @"Whatever";
416    object.isValid = NO;
417    object.numberTest = @YES;
418    RKObjectMapping *mapping = [RKObjectMapping requestMapping];
419    [mapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"stringTest" toKeyPath:@"name"]];
420    [mapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"isValid" toKeyPath:@"is_valid"]];
421    [mapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"numberTest" toKeyPath:@"is_boolean"]];
422    
423    NSError *error = nil;
424    RKRequestDescriptor *requestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:mapping objectClass:[NSDictionary class] rootKeyPath:nil method:RKRequestMethodAny];
425    NSDictionary *parameters = [RKObjectParameterization parametersWithObject:object requestDescriptor:requestDescriptor error:&error];
426    
427    NSData *data = [RKMIMETypeSerialization dataFromObject:parameters MIMEType:RKMIMETypeJSON error:&error];
428    NSString *string = [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
429    
430    expect(error).to.beNil();
431    // Unordered dictionary handling
432    NSArray *serializations = @[ @"{\"is_valid\":0,\"name\":\"Whatever\",\"is_boolean\":true}", @"{\"name\":\"Whatever\",\"is_valid\":0,\"is_boolean\":true}", @"{\"name\":\"Whatever\",\"is_valid\":false,\"is_boolean\":true}"];
433    expect(serializations).to.contain(string);
434}
435
436- (void)testParameterizationofBooleanPropertiesFromManagedObjectProperty
437{
438    RKHuman *human = [RKTestFactory insertManagedObjectForEntityForName:@"Human" inManagedObjectContext:nil withProperties:nil];
439    human.isHappy = @YES;
440    human.name = @"Blake Watters";
441    RKObjectMapping *mapping = [RKObjectMapping requestMapping];
442    [mapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"name" toKeyPath:@"name"]];
443    [mapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"isHappy" toKeyPath:@"happy"]];
444    
445    NSError *error = nil;
446    RKRequestDescriptor *requestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:mapping objectClass:[NSDictionary class] rootKeyPath:nil method:RKRequestMethodAny];
447    NSDictionary *parameters = [RKObjectParameterization parametersWithObject:human requestDescriptor:requestDescriptor error:&error];
448    
449    NSData *data = [RKMIMETypeSerialization dataFromObject:parameters MIMEType:RKMIMETypeJSON error:&error];
450    NSString *string = [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
451    
452    expect(error).to.beNil();
453    expect(string).to.equal(@"{\"name\":\"Blake Watters\",\"happy\":true}");
454}
455
456- (void)testParameterizationofBooleanPropertiesFromManagedObjectPropertyWithFalseValue
457{
458    RKHuman *human = [RKTestFactory insertManagedObjectForEntityForName:@"Human" inManagedObjectContext:nil withProperties:nil];
459    human.isHappy = @NO;
460    human.name = @"Blake Watters";
461    RKObjectMapping *mapping = [RKObjectMapping requestMapping];
462    [mapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"name" toKeyPath:@"name"]];
463    [mapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"isHappy" toKeyPath:@"happy"]];
464    
465    NSError *error = nil;
466    RKRequestDescriptor *requestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:mapping objectClass:[NSDictionary class] rootKeyPath:nil method:RKRequestMethodAny];
467    NSDictionary *parameters = [RKObjectParameterization parametersWithObject:human requestDescriptor:requestDescriptor error:&error];
468    
469    NSData *data = [RKMIMETypeSerialization dataFromObject:parameters MIMEType:RKMIMETypeJSON error:&error];
470    NSString *string = [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
471    
472    expect(error).to.beNil();
473    expect(string).to.equal(@"{\"name\":\"Blake Watters\",\"happy\":false}");
474}
475
476- (void)testSerializingWithDynamicNestingAttributeWithBraces
477{
478    NSDictionary *object = @{ @"name" : @"blake", @"occupation" : @"Hacker" };
479    RKObjectMapping *mapping = [RKObjectMapping requestMapping];
480    [mapping addAttributeMappingToKeyOfRepresentationFromAttribute:@"name"];
481    [mapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"name" toKeyPath:@"{name}.name"]];
482    [mapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"occupation" toKeyPath:@"{name}.job"]];
483
484    NSError *error = nil;
485    RKRequestDescriptor *requestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:mapping objectClass:[NSDictionary class] rootKeyPath:nil method:RKRequestMethodAny];
486    NSDictionary *parameters = [RKObjectParameterization parametersWithObject:object requestDescriptor:requestDescriptor error:&error];
487    NSDictionary *expected = @{@"blake": @{@"name": @"blake", @"job": @"Hacker"}};
488    expect(parameters).to.equal(expected);
489}
490
491- (void)testSerializingWithDynamicNestingAttributeWithParentheses
492{
493    NSDictionary *object = @{ @"name" : @"blake", @"occupation" : @"Hacker" };
494    RKObjectMapping *mapping = [RKObjectMapping requestMapping];
495    [mapping addAttributeMappingToKeyOfRepresentationFromAttribute:@"name"];
496    [mapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"name" toKeyPath:@"(name).name"]];
497    [mapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"occupation" toKeyPath:@"(name).job"]];
498    
499    NSError *error = nil;
500    RKRequestDescriptor *requestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:mapping objectClass:[NSDictionary class] rootKeyPath:nil method:RKRequestMethodAny];
501    NSDictionary *parameters = [RKObjectParameterization parametersWithObject:object requestDescriptor:requestDescriptor error:&error];
502    NSDictionary *expected = @{@"blake": @{@"name": @"blake", @"job": @"Hacker"}};
503    expect(parameters).to.equal(expected);
504}
505
506- (void)testParameterizationOfCoreDataEntityWithDateToNestedKeypath
507{
508    RKHuman *human = [RKTestFactory insertManagedObjectForEntityForName:@"Human" inManagedObjectContext:nil withProperties:nil];
509    human.birthday = [NSDate dateWithTimeIntervalSince1970:0];
510    RKObjectMapping *mapping = [RKObjectMapping requestMapping];
511    [mapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"birthday" toKeyPath:@"nestedPath.birthday"]];
512    
513    NSError *error = nil;
514    RKRequestDescriptor *requestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:mapping objectClass:[NSDictionary class] rootKeyPath:nil method:RKRequestMethodAny];
515    NSDictionary *parameters = [RKObjectParameterization parametersWithObject:human requestDescriptor:requestDescriptor error:&error];
516    
517    NSData *data = [RKMIMETypeSerialization dataFromObject:parameters MIMEType:RKMIMETypeJSON error:&error];
518    NSString *string = [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
519    
520    expect(error).to.beNil();
521    expect(string).to.equal(@"{\"nestedPath\":{\"birthday\":\"1970-01-01T00:00:00.000Z\"}}");
522}
523
524- (void)testParameterizationFromLocationToNestedDictionaryUsingValueTransformer
525{
526    RKTestUser *user = [RKTestUser new];
527    user.name = @"Blake";
528    user.location = [[CLLocation alloc] initWithLatitude:125.55 longitude:200.5];
529    RKObjectMapping *userMapping = [RKObjectMapping requestMapping];
530    [userMapping addAttributeMappingsFromArray:@[ @"name" ]];
531    RKAttributeMapping *attributeMapping = [RKAttributeMapping attributeMappingFromKeyPath:@"location" toKeyPath:@"location"];
532    attributeMapping.propertyValueClass = [NSDictionary class];
533    attributeMapping.valueTransformer = [RKCLLocationValueTransformer locationValueTransformerWithLatitudeKey:@"latitude" longitudeKey:@"longitude"];
534    [userMapping addPropertyMapping:attributeMapping];
535
536    NSError *error = nil;
537    RKRequestDescriptor *requestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:userMapping objectClass:[RKTestUser class] rootKeyPath:nil method:RKRequestMethodAny];
538    NSDictionary *parameters = [RKObjectParameterization parametersWithObject:user requestDescriptor:requestDescriptor error:&error];
539
540    expect(parameters).notTo.beNil();
541    expect(error).to.beNil();
542    expect(parameters[@"location"]).notTo.beNil();
543    expect(parameters[@"location"][@"latitude"]).to.equal(125.55);
544    expect(parameters[@"location"][@"longitude"]).to.equal(200.5);
545}
546
547- (void)testSerializingToNull
548{
549    RKTestUser *blake = [RKTestUser new];
550    blake.name = @"Blake Watters";
551    blake.website = nil;
552
553    RKObjectMapping *mapping = [RKObjectMapping requestMapping];
554    [mapping addAttributeMappingsFromArray:@[ @"name", @"website" ]];
555
556    NSError *error = nil;
557    RKRequestDescriptor *requestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:mapping objectClass:[RKTestUser class] rootKeyPath:nil method:RKRequestMethodAny];
558    NSDictionary *parameters = [RKObjectParameterization parametersWithObject:blake requestDescriptor:requestDescriptor error:&error];
559    expect(error).to.beNil();
560    expect(parameters).to.equal((@{ @"name": @"Blake Watters", @"website": [NSNull null] }));
561}
562
563- (void)testSerializingOmitsNullAttributesWhenAssignsDefaultValueForMissingAttributesIsFalse
564{
565    RKTestUser *blake = [RKTestUser new];
566    blake.name = @"Blake Watters";
567    blake.website = nil;
568
569    RKObjectMapping *mapping = [RKObjectMapping requestMapping];
570    [mapping addAttributeMappingsFromArray:@[@"name", @"website"]];
571    mapping.assignsDefaultValueForMissingAttributes = NO;
572
573    NSError *error = nil;
574    RKRequestDescriptor *requestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:mapping objectClass:[RKTestUser class] rootKeyPath:nil method:RKRequestMethodAny];
575    NSDictionary *parameters = [RKObjectParameterization parametersWithObject:blake requestDescriptor:requestDescriptor error:&error];
576    expect(error).to.beNil();
577    expect(parameters).to.equal((@{@"name" : @"Blake Watters"}));
578}
579
580@end
581
582#pragma mark - Dynamic Request Paramterization
583
584typedef NS_ENUM(NSInteger, RKFlightSearchMode) {
585    RKSearchByFlightNumberMode = 1,
586    RKSearchByRouteMode = 2,
587    RKSearcyByOtherMode
588} ;
589
590@interface RKDynamicParameterizationFlightSearch : NSObject
591@property (nonatomic, assign) RKFlightSearchMode mode;
592@property (nonatomic, copy) NSNumber *airlineID;
593@property (nonatomic, copy) NSNumber *flightNumber;
594@property (nonatomic, copy) NSNumber *departureAirportID;
595@property (nonatomic, copy) NSNumber *arrivalAirportID;
596@property (nonatomic, copy) NSDate *departureDate;
597@end
598
599@implementation RKDynamicParameterizationFlightSearch
600@end
601
602@interface RKDynamicParameterizationTest : RKTestCase
603@end
604
605@implementation RKDynamicParameterizationTest
606
607- (void)testParameterizationUsingDynamicMapping
608{
609    NSDictionary *expectedFlightNumberParameters = @{ @"flight_search": @{ @"flight_number": @1234, @"airline_id": @5678 } };
610    NSDictionary *expectedRouteParameters = @{ @"flight_search": @{ @"departure_airport_id": @25, @"arrival_airport_id": @66, @"airline_id": @5678 } };
611    
612    RKObjectMapping *flightNumberMapping = [RKObjectMapping requestMapping];
613    [flightNumberMapping addAttributeMappingsFromDictionary:@{ @"flightNumber": @"flight_number", @"airlineID": @"airline_id" }];
614    RKObjectMapping *routeMapping = [RKObjectMapping requestMapping];
615    [routeMapping addAttributeMappingsFromDictionary:@{ @"airlineID": @"airline_id", @"departureAirportID": @"departure_airport_id", @"arrivalAirportID": @"arrival_airport_id" }];
616    
617    RKDynamicMapping *flightSearchMapping = [RKDynamicMapping new];
618    [flightSearchMapping addMatcher:[RKObjectMappingMatcher matcherWithKeyPath:@"mode" expectedValue:@(RKSearchByFlightNumberMode) objectMapping:flightNumberMapping]];
619    [flightSearchMapping addMatcher:[RKObjectMappingMatcher matcherWithKeyPath:@"mode" expectedValue:@(RKSearchByRouteMode) objectMapping:routeMapping]];
620    
621    RKDynamicParameterizationFlightSearch *flightSearch = [RKDynamicParameterizationFlightSearch new];
622    flightSearch.airlineID = @5678;
623    flightSearch.flightNumber = @1234;
624    flightSearch.departureAirportID = @25;
625    flightSearch.arrivalAirportID = @66;
626    
627    RKRequestDescriptor *requestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:flightSearchMapping
628                                                                                   objectClass:[RKDynamicParameterizationFlightSearch class]
629                                                                                   rootKeyPath:@"flight_search"
630                                                                                        method:RKRequestMethodAny];
631    NSError *error = nil;
632    NSDictionary *parameters = nil;
633    
634    // Test generation of Flight Number parameters
635    flightSearch.mode = RKSearchByFlightNumberMode;
636    parameters = [RKObjectParameterization parametersWithObject:flightSearch requestDescriptor:requestDescriptor error:&error];
637    expect(parameters).to.equal(expectedFlightNumberParameters);
638    
639    // Test generation of Route paramters
640    flightSearch.mode = RKSearchByRouteMode;
641    parameters = [RKObjectParameterization parametersWithObject:flightSearch requestDescriptor:requestDescriptor error:&error];
642    expect(parameters).to.equal(expectedRouteParameters);
643    
644    // Test non-match
645    flightSearch.mode = RKSearcyByOtherMode;
646    parameters = [RKObjectParameterization parametersWithObject:flightSearch requestDescriptor:requestDescriptor error:&error];
647    expect(parameters).to.beNil();
648    expect(error).notTo.beNil();
649    expect(error.code).to.equal(RKMappingErrorUnableToDetermineMapping);
650}
651
652- (void)testDynamicParameterizationIncludingADate
653{
654    RKObjectMapping *concreteMapping = [RKObjectMapping requestMapping];
655    [concreteMapping addAttributeMappingsFromDictionary:@{ @"departureDate": @"departure_date" }];
656    
657    RKDynamicMapping *flightSearchMapping = [RKDynamicMapping new];
658    [flightSearchMapping addMatcher:[RKObjectMappingMatcher matcherWithKeyPath:@"mode" expectedValue:@(RKSearchByFlightNumberMode) objectMapping:concreteMapping]];
659    
660    RKDynamicParameterizationFlightSearch *flightSearch = [RKDynamicParameterizationFlightSearch new];
661    flightSearch.airlineID = @5678;
662    flightSearch.flightNumber = @1234;
663    flightSearch.departureAirportID = @25;
664    flightSearch.arrivalAirportID = @66;
665    flightSearch.mode = RKSearchByFlightNumberMode;
666    flightSearch.departureDate = [NSDate dateWithTimeIntervalSince1970:0];
667    RKRequestDescriptor *requestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:flightSearchMapping
668                                                                                   objectClass:[RKDynamicParameterizationFlightSearch class]
669                                                                                   rootKeyPath:@"flight_search"
670                                                                                        method:RKRequestMethodAny];
671    NSError *error = nil;
672    NSDictionary *parameters = nil;
673    
674    // Test generation of Flight Number parameters    
675    parameters = [RKObjectParameterization parametersWithObject:flightSearch requestDescriptor:requestDescriptor error:&error];
676    NSDictionary *expectedParameters = @{ @"flight_search": @{ @"departure_date": @"1970-01-01T00:00:00Z" }};
677    expect(parameters).to.equal(expectedParameters);
678}
679
680- (void)testShouldSerializeHasOneRelatioshipsToJSON
681{
682    RKObjectMapping *userMapping = [RKObjectMapping mappingForClass:[RKTestUser class]];
683    [userMapping addAttributeMappingsFromArray:@[@"name"]];
684    RKObjectMapping *addressMapping = [RKObjectMapping mappingForClass:[RKTestAddress class]];
685    [addressMapping addAttributeMappingsFromArray:@[@"city", @"state"]];
686    [userMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"address" toKeyPath:@"address" withMapping:addressMapping]];
687
688    RKTestUser *user = [RKTestUser new];
689    user.name = @"Blake Watters";
690    RKTestAddress *address = [RKTestAddress new];
691    address.state = @"North Carolina";
692    user.address = address;
693
694    RKObjectMapping *serializationMapping = [userMapping inverseMapping];
695    NSDictionary *params = [RKObjectParameterization parametersWithObject:user requestDescriptor:[RKRequestDescriptor requestDescriptorWithMapping:serializationMapping objectClass:[RKTestUser class] rootKeyPath:nil method:RKRequestMethodAny] error:nil];
696    NSError *error = nil;
697    NSData *JSON = [RKMIMETypeSerialization dataFromObject:params MIMEType:RKMIMETypeJSON error:nil];
698    NSDictionary *jsonDictionary = [NSJSONSerialization JSONObjectWithData:JSON options:0 error:nil];
699    assertThat(error, is(nilValue()));
700    assertThat(jsonDictionary, is(equalTo(params)));
701}
702
703- (void)testShouldSerializeHasManyRelationshipsToJSON
704{
705    RKObjectMapping *userMapping = [RKObjectMapping mappingForClass:[RKTestUser class]];
706    [userMapping addAttributeMappingsFromArray:@[@"name"]];
707    RKObjectMapping *addressMapping = [RKObjectMapping mappingForClass:[RKTestAddress class]];
708    [addressMapping addAttributeMappingsFromArray:@[@"city", @"state"]];
709    [userMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"friends" toKeyPath:@"friends" withMapping:addressMapping]];
710
711    RKTestUser *user = [RKTestUser new];
712    user.name = @"Blake Watters";
713    RKTestAddress *address1 = [RKTestAddress new];
714    address1.city = @"Carrboro";
715    RKTestAddress *address2 = [RKTestAddress new];
716    address2.city = @"New York City";
717    user.friends = @[address1, address2];
718
719    RKObjectMapping *serializationMapping = [userMapping inverseMapping];
720    NSDictionary *params = [RKObjectParameterization parametersWithObject:user requestDescriptor:[RKRequestDescriptor requestDescriptorWithMapping:serializationMapping objectClass:[RKTestUser class] rootKeyPath:nil method:RKRequestMethodAny] error:nil];
721    NSError *error = nil;
722    NSData *JSON = [RKMIMETypeSerialization dataFromObject:params MIMEType:RKMIMETypeJSON error:nil];
723    NSDictionary *jsonDictionary = [NSJSONSerialization JSONObjectWithData:JSON options:0 error:nil];
724    assertThat(error, is(nilValue()));
725    assertThat(jsonDictionary, is(equalTo(params)));
726}
727
728- (void)testShouldSerializeManagedHasManyRelationshipsToJSON
729{
730    RKManagedObjectStore *managedObjectStore = [RKTestFactory managedObjectStore];
731    RKObjectMapping *humanMapping = [RKObjectMapping mappingForClass:[RKHuman class]];
732    [humanMapping addAttributeMappingsFromArray:@[@"name"]];
733    RKObjectMapping *catMapping = [RKObjectMapping mappingForClass:[RKCat class]];
734    [catMapping addAttributeMappingsFromArray:@[@"name"]];
735    [humanMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"cats" toKeyPath:@"cats" withMapping:catMapping]];
736
737    RKHuman *blake = [NSEntityDescription insertNewObjectForEntityForName:@"Human" inManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext];
738    blake.name = @"Blake Watters";
739    RKCat *asia = [NSEntityDescription insertNewObjectForEntityForName:@"Cat" inManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext];
740    asia.name = @"Asia";
741    RKCat *roy = [NSEntityDescription insertNewObjectForEntityForName:@"Cat" inManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext];
742    roy.name = @"Roy";
743    blake.cats = [NSSet setWithObjects:asia, roy, nil];
744
745    RKObjectMapping *serializationMapping = [humanMapping inverseMapping];
746
747    NSDictionary *params = [RKObjectParameterization parametersWithObject:blake requestDescriptor:[RKRequestDescriptor requestDescriptorWithMapping:serializationMapping objectClass:[RKHuman class] rootKeyPath:nil method:RKRequestMethodAny] error:nil];
748    NSError *error = nil;
749    NSDictionary *parsedJSON = [NSJSONSerialization JSONObjectWithData:[RKMIMETypeSerialization dataFromObject:params MIMEType:RKMIMETypeJSON error:nil] options:0 error:nil];
750    assertThat(error, is(nilValue()));
751    assertThat([parsedJSON valueForKey:@"name"], is(equalTo(@"Blake Watters")));
752    NSArray *catNames = [[parsedJSON valueForKeyPath:@"cats.name"] sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)];
753    assertThat(catNames, is(equalTo(@[@"Asia", @"Roy"])));
754}
755
756- (void)testParameterizingHasManyRelationshipToNestedKeyPath
757{
758    RKObjectMapping *userMapping = [RKObjectMapping mappingForClass:[RKTestUser class]];
759    [userMapping addAttributeMappingsFromArray:@[@"name"]];
760    RKObjectMapping *addressMapping = [RKObjectMapping mappingForClass:[RKTestAddress class]];
761    [addressMapping addAttributeMappingsFromArray:@[@"city", @"state"]];
762    [userMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"friends" toKeyPath:@"friends" withMapping:addressMapping]];
763    
764    RKTestUser *user = [RKTestUser new];
765    user.name = @"Blake Watters";
766    RKTestAddress *address1 = [RKTestAddress new];
767    address1.city = @"Carrboro";
768    RKTestAddress *address2 = [RKTestAddress new];
769    address2.city = @"New York City";
770    user.friends = @[address1, address2];
771    
772    
773    RKObjectMapping *requestMapping = [RKObjectMapping requestMapping];
774    [requestMapping addAttributeMappingsFromArray:@[ @"name" ]];
775    RKObjectMapping *cityMapping = [RKObjectMapping requestMapping];
776    [cityMapping addAttributeMappingsFromArray:@[ @"city" ]];
777    [requestMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"friends" toKeyPath:@"cities.eastCoast" withMapping:cityMapping]];;
778    NSDictionary *params = [RKObjectParameterization parametersWithObject:user requestDescriptor:[RKRequestDescriptor requestDescriptorWithMapping:requestMapping objectClass:[RKTestUser class] rootKeyPath:nil method:RKRequestMethodAny] error:nil];
779    NSError *error = nil;
780    NSDictionary *parsedJSON = [NSJSONSerialization JSONObjectWithData:[RKMIMETypeSerialization dataFromObject:params MIMEType:RKMIMETypeJSON error:nil] options:0 error:nil];
781    assertThat(error, is(nilValue()));
782    assertThat(parsedJSON[@"name"], is(equalTo(@"Blake Watters")));
783    assertThat([parsedJSON valueForKeyPath:@"cities.eastCoast.city"], hasItems(@"Carrboro", @"New York City", nil));
784}
785
786@end