Skip to content

Commit

Permalink
Merge pull request #18 from johankool/master
Browse files Browse the repository at this point in the history
Pretty print errors
  • Loading branch information
johankool committed Jun 1, 2014
2 parents db6dea5 + 50a9f98 commit 3a86c0f
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 29 deletions.
2 changes: 1 addition & 1 deletion EFDataMappingKit.podspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = "EFDataMappingKit"
s.version = "0.1.2"
s.version = "0.1.3"
s.summary = "EFDataMappingKit maps data such as those coming from JSON onto an instance using mappings"
s.description = "EFDataMappingKit maps data such as those coming from JSON onto an instance using mappings. The mappings are also used to simplify implementing the NSCoding protocol for a class, and to create a dictionary representation of an instance."
s.homepage = "https://github.com/Egeniq/EFDataMappingKit"
Expand Down
10 changes: 5 additions & 5 deletions EFMapping/EFMapper.m
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ - (BOOL)validateValues:(NSDictionary *)values forClass:(Class)aClass onObject:(i
}

if ([errorsInArray count] > 0) {
NSString *description = [NSString stringWithFormat:@"Encountered %lu validation error(s) in array for key %@", (unsigned long)[errorsInArray count], mapping.internalKey];
NSString *description = [NSString stringWithFormat:@"Encountered %lu validation error%@ in array for key %@", (unsigned long)[errorsInArray count], [errorsInArray count] == 1 ? @"" : @"s", mapping.internalKey];
NSError *validationError = [NSError errorWithDomain:EFMappingErrorDomain code:EFMappingUnexpectedClass userInfo:@{NSLocalizedDescriptionKey: description, EFMappingErrorValidationErrorsKey: errorsInArray}];
errors[mapping.internalKey] = validationError;
} else {
Expand Down Expand Up @@ -218,7 +218,7 @@ - (BOOL)validateValues:(NSDictionary *)values forClass:(Class)aClass onObject:(i
}];

if ([errorsInDictionary count] > 0) {
NSString *description = [NSString stringWithFormat:@"Encountered %lu validation error(s) in dictionary for key %@", (unsigned long)[errorsInDictionary count], mapping.internalKey];
NSString *description = [NSString stringWithFormat:@"Encountered %lu validation error%@ in dictionary for key %@", (unsigned long)[errorsInDictionary count], [errorsInDictionary count] == 1 ? @"" : @"s", mapping.internalKey];
NSError *validationError = [NSError errorWithDomain:EFMappingErrorDomain code:EFMappingUnexpectedClass userInfo:@{NSLocalizedDescriptionKey: description, EFMappingErrorValidationErrorsKey: errorsInDictionary}];
errors[mapping.internalKey] = validationError;
} else {
Expand Down Expand Up @@ -265,7 +265,7 @@ - (BOOL)validateValues:(NSDictionary *)values forClass:(Class)aClass onObject:(i

if ([errors count] > 0) {
if (error != NULL) {
NSString *description = [NSString stringWithFormat:NSLocalizedString(@"Encountered %d validation error(s) in %@", @""), [errors count], NSStringFromClass(aClass)];
NSString *description = [NSString stringWithFormat:NSLocalizedString(@"Encountered %d validation error%@ in %@", @""), [errors count], [errors count] == 1 ? @"" : @"s", NSStringFromClass(aClass)];
*error = [NSError errorWithDomain:EFMappingErrorDomain code:EFMappingInvalidValues userInfo:@{NSLocalizedDescriptionKey: description, EFMappingErrorValidationErrorsKey: errors}];
}
return NO;
Expand Down Expand Up @@ -409,7 +409,7 @@ - (BOOL)validateValue:(id)value isCollection:(BOOL)isCollection mapping:(EFMappi
if (isCollection) {
if (value && ![value isKindOfClass:mapping.collectionClass]) {
if (error != NULL) {
NSString *description = [NSString stringWithFormat:@"Did not expect value (%@) of class %@ for key %@ but %@ instance", value, NSStringFromClass([value class]), mapping.internalKey, NSStringFromClass(mapping.collectionClass)];
NSString *description = [NSString stringWithFormat:@"Did not expect value (%@) of class %@ for key %@ but a %@ instance", value, NSStringFromClass([value class]), mapping.internalKey, NSStringFromClass(mapping.collectionClass)];
*error = [NSError errorWithDomain:EFMappingErrorDomain code:EFMappingUnexpectedClass userInfo:@{NSLocalizedDescriptionKey: description}];
}
return NO;
Expand All @@ -424,7 +424,7 @@ - (BOOL)validateValue:(id)value isCollection:(BOOL)isCollection mapping:(EFMappi
}
} else {
if (error != NULL) {
NSString *description = [NSString stringWithFormat:@"Did not expect value (%@) of class %@ for key %@ but %@ instance%@", value, NSStringFromClass([value class]), mapping.internalKey, NSStringFromClass(mapping.internalClass), [self mappingsForClass:mapping.internalClass] ? @" or NSDictionary" : @""];
NSString *description = [NSString stringWithFormat:@"Did not expect value (%@) of class %@ for key %@ but a %@ instance%@", value, NSStringFromClass([value class]), mapping.internalKey, NSStringFromClass(mapping.internalClass), [self mappingsForClass:mapping.internalClass] ? @" or NSDictionary" : @""];
*error = [NSError errorWithDomain:EFMappingErrorDomain code:EFMappingUnexpectedClass userInfo:@{NSLocalizedDescriptionKey: description}];
}
return NO;
Expand Down
34 changes: 18 additions & 16 deletions EFMapping/EFMappingError.m
Original file line number Diff line number Diff line change
Expand Up @@ -11,27 +11,29 @@
NSString * const EFMappingErrorDomain = @"EFMappingErrorDomain";
NSString * const EFMappingErrorValidationErrorsKey = @"validationErrors";

NSString* EFPrettyMappingError(NSError *error) {
NSString* EFPrettyMappingErrorWithIndentation(NSError *error, NSUInteger indentationLevel) {
if ([error.domain isEqualToString:EFMappingErrorDomain]) {
NSMutableString *string = [NSMutableString string];
if (error.code == EFMappingInvalidValues) {
[string appendFormat:@"%@:", error.userInfo[NSLocalizedDescriptionKey]];
id errors = error.userInfo[EFMappingErrorValidationErrorsKey];
if ([errors isKindOfClass:[NSArray class]]) {
[errors enumerateObjectsUsingBlock:^(NSError *subError, NSUInteger idx, BOOL *stop) {
[string appendFormat:@"\n\t- %lu: %@", (unsigned long)idx, subError.userInfo[NSLocalizedDescriptionKey]];
}];
} else if ([errors isKindOfClass:[NSDictionary class]]) {
[errors enumerateKeysAndObjectsUsingBlock:^(NSString *key, NSError *subError, BOOL *stop) {
[string appendFormat:@"\n\t- %@: %@", key, subError.userInfo[NSLocalizedDescriptionKey]];
}];
}
} else {
// Do some recursive stuff here!
[string appendString:error.userInfo[NSLocalizedDescriptionKey]];
id errors = error.userInfo[EFMappingErrorValidationErrorsKey];
NSString *tabs = [@"\n" stringByPaddingToLength:indentationLevel + 2 withString:@"\t" startingAtIndex:0];
if ([errors isKindOfClass:[NSArray class]]) {
[string appendString:@":"];
[errors enumerateObjectsUsingBlock:^(NSError *subError, NSUInteger idx, BOOL *stop) {
[string appendFormat:@"%@%lu: %@", tabs, (unsigned long)idx, EFPrettyMappingErrorWithIndentation(subError, indentationLevel + 1)];
}];
} else if ([errors isKindOfClass:[NSDictionary class]]) {
[string appendString:@":"];
[errors enumerateKeysAndObjectsUsingBlock:^(NSString *key, NSError *subError, BOOL *stop) {
[string appendFormat:@"%@%@: %@", tabs, key, EFPrettyMappingErrorWithIndentation(subError, indentationLevel + 1)];
}];
}
[string appendString:@"\n"];
return string;
} else {
return [error description];
}
}

NSString* EFPrettyMappingError(NSError *error) {
return EFPrettyMappingErrorWithIndentation(error, 0);
}
24 changes: 17 additions & 7 deletions EFMappingTests/EFMappingTest.m
Original file line number Diff line number Diff line change
Expand Up @@ -82,13 +82,6 @@ - (void)testSettingValues {
m.externalKey = @"id";
m.internalKey = @"guid";
m.requires = [EFRequires exists];
m.transformationBlock = ^id(id value, BOOL reverse) {
if (reverse) {
return [(NSURL *)value absoluteString];
} else {
return [NSURL URLWithString:(NSString *)value];
}
};
}]] forClass:[EFSample class]];

NSError *error;
Expand Down Expand Up @@ -201,4 +194,21 @@ - (void)testRequirements {
XCTAssertFalse([[EFRequires either:array or:[EFRequires equalTo:@10]] evaluateForValue:@1], @"Value or");
}

- (void)testPrettyErrors {
EFMapper *mapper = [[EFMapper alloc] init];
[mapper registerMappings:@[[EFMapping mapping:^(EFMapping *m){m.internalClass = [NSString class]; m.externalKey = @"id"; m.internalKey = @"guid"; m.requires = [EFRequires exists];}],
[EFMapping mappingForArrayOfClass:[EFSample class] externalKey:@"children" internalKey:@"relatedSamples"]] forClass:[EFSample class]];

NSError *error;
EFSample *sample = [mapper objectOfClass:[EFSample class] withValues:@{@"id": @"1", @"children": @[@{@"id": @"2"}, @{@"id": @3, @"children": @[@{@"id": @"4"}, @{@"id": @5}]}]} error:&error];
NSString *expectedErrorMsg = @"Encountered 1 validation error in EFSample:\n\
\trelatedSamples: Encountered 1 validation error in array for key relatedSamples:\n\
\t\t0: Encountered 2 validation errors in EFSample:\n\
\t\t\tguid: Did not expect value (3) of class __NSCFNumber for key guid but a NSString instance\n\
\t\t\trelatedSamples: Encountered 1 validation error in array for key relatedSamples:\n\
\t\t\t\t0: Encountered 1 validation error in EFSample:\n\
\t\t\t\t\tguid: Did not expect value (5) of class __NSCFNumber for key guid but a NSString instance";
XCTAssertEqualObjects(EFPrettyMappingError(error), expectedErrorMsg, @"Pretty print error differs");
}

@end

0 comments on commit 3a86c0f

Please sign in to comment.