├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── RMErrors.podspec ├── RMErrors.xcworkspace └── contents.xcworkspacedata ├── RMErrors ├── RMErrorCodeBoundary.h ├── RMErrorCodeDefinition.h ├── RMErrorCodeDefinition.m ├── RMErrorCodeRangeBoundary.h ├── RMErrorCodeRangeBoundary.m ├── RMErrorCodes.h ├── RMErrorCodes.m ├── RMErrorDescription.h ├── RMErrorDescription.m ├── RMErrorDomainDefinition.h ├── RMErrorDomainDefinition.m ├── RMErrorDomains.h ├── RMErrorDomains.m ├── RMErrorTransformation.h ├── RMErrorTransformations.h ├── RMErrorTransformations.m ├── RMErrors.h └── RMErrors.m └── Tests ├── .gitignore ├── Podfile ├── RMErrorsIOSTests ├── Info.plist └── RMErrorsIOSTests.m ├── RMErrorsOSXTests ├── Info.plist └── RMErrorsOSXTests.m ├── RMErrorsTests.xcodeproj ├── project.pbxproj └── xcshareddata │ └── xcschemes │ ├── RMErrorsIOSTests.xcscheme │ └── RMErrorsOSXTests.xcscheme └── Tests ├── Fixtures └── RMErrors.plist ├── RMErrorCodeDefinitionTest.m ├── RMErrorCodeRangeBoundaryTest.m ├── RMErrorCodesTest.m ├── RMErrorDomainDefinitionTest.m ├── RMErrorDomainsTest.m ├── RMErrorsTest.m └── RMErrorsTransformationTest.m /.gitignore: -------------------------------------------------------------------------------- 1 | xcuserdata 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: objective-c 2 | osx_image: xcode7.1 3 | sudo: false 4 | env: 5 | global: 6 | - LC_CTYPE=en_US.UTF-8 7 | - LANG=en_US.UTF-8 8 | matrix: 9 | - DESTINATION="OS=9.1,name=iPhone 6s" TEST_SCHEME="RMErrorsIOSTests" EXAMPLE_SCHEME="RMErrors iOS Example" SDK=iphonesimulator9.1 RUN_TESTS="YES" BUILD_EXAMPLE="YES" POD_LINT="NO" 10 | - DESTINATION="OS=9.0,name=iPhone 6 Plus" TEST_SCHEME="RMErrorsIOSTests" EXAMPLE_SCHEME="RMErrors iOS Example" SDK=iphonesimulator9.1 RUN_TESTS="YES" BUILD_EXAMPLE="YES" POD_LINT="NO" 11 | - DESTINATION="OS=8.4,name=iPhone 6" TEST_SCHEME="RMErrorsIOSTests" EXAMPLE_SCHEME="RMErrors iOS Example" SDK=iphonesimulator9.1 RUN_TESTS="YES" BUILD_EXAMPLE="NO" POD_LINT="NO" 12 | - DESTINATION="OS=8.3,name=iPhone 5S" TEST_SCHEME="RMErrorsIOSTests" EXAMPLE_SCHEME="RMErrors iOS Example" SDK=iphonesimulator9.1 RUN_TESTS="YES" BUILD_EXAMPLE="NO" POD_LINT="NO" 13 | - DESTINATION="OS=8.2,name=iPhone 5" TEST_SCHEME="RMErrorsIOSTests" EXAMPLE_SCHEME="RMErrors iOS Example" SDK=iphonesimulator9.1 RUN_TESTS="YES" BUILD_EXAMPLE="NO" POD_LINT="NO" 14 | - DESTINATION="OS=8.1,name=iPhone 4S" TEST_SCHEME="RMErrorsIOSTests" EXAMPLE_SCHEME="RMErrors iOS Example" SDK=iphonesimulator9.1 RUN_TESTS="YES" BUILD_EXAMPLE="NO" POD_LINT="YES" 15 | - DESTINATION="arch=x86_64" TEST_SCHEME="RMErrorsOSXTests" SDK=macosx10.11 EXAMPLE_SCHEME="RMErrors Example" RUN_TESTS="NO" BUILD_EXAMPLE="YES" POD_LINT="NO" 16 | before_install: 17 | - gem install cocoapods --no-rdoc --no-ri --no-document --quiet 18 | - gem install xcpretty --no-rdoc --no-ri --no-document --quiet 19 | - cd Tests && pod install && cd $TRAVIS_BUILD_DIR 20 | script: 21 | - set -o pipefail 22 | - xcodebuild -version 23 | - xcodebuild -showsdks 24 | - if [ $RUN_TESTS == "YES" ]; then 25 | xcodebuild -workspace RMErrors.xcworkspace -scheme "$TEST_SCHEME" -sdk "$SDK" -destination "$DESTINATION" -configuration Debug ONLY_ACTIVE_ARCH=NO test | xcpretty -c; 26 | fi 27 | - if [ $POD_LINT == "YES" ]; then 28 | pod lib lint --quick; 29 | fi 30 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Ride Group Inc (http://ride.com/) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # RMErrors 2 | [![Build Status](https://travis-ci.org/ride/RMErrors.svg?branch=master)](https://travis-ci.org/ride/RMErrors) 3 | 4 | > Powerful Error Handling for **iOS** and **OSX** apps 5 | 6 | RMErrors describes instances `NSError` and returns friendly messages following rules set in a simple property list. 7 | 8 | ## How it Works 9 | 10 | The following example RMErrors.plist will setup RMErrors to: 11 | 12 | * NSError with domain `NSURLErrorDomain` and code between `-1003` and `-1009` will be described with friendly message `the connection failed because the device is not connected to the internet`. 13 | * NSError with domain `NSURLErrorDomain` and code `-1001` will be described with friendly message `The connection timed out, please make sure you're connected to the internet and try again`. 14 | * NSError with domain `NSURLErrorDomain` and other codes not included by any of the previous rules will be described with friendly message `Network issue` 15 | * NSError with domain other than `NSURLErrorDomain` will be described with friendly message `Oopss, something went wrong`. 16 | 17 | 18 | ```plist 19 | 20 | 21 | 22 | 23 | (default) 24 | 25 | code 26 | -1 27 | friendlyMessage 28 | Oopss, something went wrong 29 | 30 | domains 31 | 32 | NSURLErrorDomain 33 | 34 | (default) 35 | 36 | transient 37 | 38 | friendlyMessage 39 | Network issue 40 | 41 | codes 42 | 43 | -1009..-1003 44 | 45 | transient 46 | 47 | friendlyMessage 48 | the connection failed because the device is not connected to the internet 49 | 50 | -1001 51 | 52 | transient 53 | 54 | friendlyMessage 55 | The connection timed out, please make sure you're connected to the internet and try again 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | ``` 64 | 65 | 66 | ## Usage 67 | 68 | ### Install from Cocoapods 69 | 70 | ```rb 71 | pod 'RMErrors' 72 | ``` 73 | 74 | ```bash 75 | $ pod install 76 | ``` 77 | 78 | ### Prepare configuration file 79 | 80 | Create a new property list file in your project and make sure it's included in all the Xcode targets you intent to use from. 81 | 82 | ### Initialize 83 | 84 | ```obj-c 85 | RMErrors *errors = [[RMErrors alloc] init]; 86 | [errors loadPropertyList]; //loads from RMErrors.plist in main bundle. 87 | ``` 88 | 89 | ### Describing Errors 90 | 91 | ```obj-c 92 | RMErrorDescription *description = [errors describe:[NSError errorWithDomain:@"com.foo.bar.oopsie" code:500 userInfo:nil]]; 93 | NSLog(@"Friendly Message: %@", description.friendlyMessage); 94 | ``` 95 | 96 | Outputs: 97 | 98 | "Oopss, something went wrong" 99 | 100 | ## Test & Enhance 101 | 102 | ```bash 103 | $ cd Tests && pod install 104 | $ open RMErrors.xcworkspace 105 | ``` 106 | -------------------------------------------------------------------------------- /RMErrors.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = 'RMErrors' 3 | s.version = '1.0.1' 4 | s.license = 'MIT' 5 | s.summary = 'Powerful error handling for iOS and OSX' 6 | s.homepage = 'https://github.com/ride/RMErrors' 7 | s.authors = { 'Bithavoc' => 'im@bithavoc.io' } 8 | s.source = { :git => 'https://github.com/ride/RMErrors.git', :tag=>s.version } 9 | 10 | s.requires_arc = true 11 | 12 | s.public_header_files = 'RMErrors/*.{h}' 13 | s.source_files = 'RMErrors/*.{h,m}' 14 | 15 | s.ios.deployment_target = '8.0' 16 | s.osx.deployment_target = '10.9' 17 | s.watchos.deployment_target = '2.0' 18 | end 19 | -------------------------------------------------------------------------------- /RMErrors.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 9 | 10 | 12 | 13 | 15 | 16 | 17 | 20 | 22 | 23 | 25 | 26 | 28 | 29 | 31 | 32 | 34 | 35 | 37 | 38 | 40 | 41 | 43 | 44 | 46 | 47 | 49 | 50 | 52 | 53 | 55 | 56 | 58 | 59 | 61 | 62 | 64 | 65 | 67 | 68 | 70 | 71 | 73 | 74 | 75 | 77 | 78 | 80 | 81 | 82 | -------------------------------------------------------------------------------- /RMErrors/RMErrorCodeBoundary.h: -------------------------------------------------------------------------------- 1 | // 2 | // RMErrorCodeBoundary.h 3 | // RideMarketplace 4 | // 5 | // Created by Johan Ride on 8/24/15. 6 | // Copyright (c) 2015 Ride. All rights reserved. 7 | // 8 | 9 | @import Foundation; 10 | 11 | @protocol RMErrorCodeBoundary 12 | 13 | /** 14 | Evaluates the error code and return YES if it fits the boundary 15 | */ 16 | - (BOOL)matches:(NSInteger)code; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /RMErrors/RMErrorCodeDefinition.h: -------------------------------------------------------------------------------- 1 | // 2 | // RMErrorCodeDefinition.h 3 | // RideMarketplace 4 | // 5 | // Created by Johan Ride on 8/24/15. 6 | // Copyright (c) 2015 Ride. All rights reserved. 7 | // 8 | 9 | @import Foundation; 10 | #import "RMErrorCodeBoundary.h" 11 | #import "RMErrorDescription.h" 12 | 13 | /** 14 | Describes how the app sees error code for a Domain. 15 | */ 16 | @interface RMErrorCodeDefinition : NSObject 17 | 18 | /** 19 | Initializes the Error Code definition with a boundary, friendly message and transient indicator 20 | @param boundary Boundary to Match the error code 21 | @param friendlyMessage (optional) a text message to show in UI when error is matched 22 | @param transient indicates whether the error is transient or not 23 | */ 24 | - (instancetype)initWithBoundary:(id)boundary 25 | friendlyMessage:(NSString *)friendlyMessage transient:(BOOL)transient NS_DESIGNATED_INITIALIZER; 26 | 27 | /** 28 | Initializes the Error Code definition with boundary and attributes dictionary(RMErrors.plist) 29 | @param boundary Boundary to Match the error code 30 | @param attributes NSDictionary with attributes (See RMErrors.plist) 31 | */ 32 | - (instancetype)initWithBoundary:(id)boundary andAttributes:(NSDictionary *)attributes; 33 | 34 | /** 35 | Boundary of this error code. 36 | See RMErrorCodeRangeBoundary. 37 | */ 38 | @property (nonatomic, readonly) id boundary; 39 | 40 | /** 41 | User-Friendly message associated with the matched code boundary. 42 | */ 43 | @property (nonatomic, readonly) NSString *friendlyMessage; 44 | 45 | /** 46 | Indicates whether the matched error code is transient. Transient errors should be retried with our without user intervention after a certain amount of time. 47 | */ 48 | @property (nonatomic, readonly) BOOL transient; 49 | 50 | /** 51 | Indicates whether it can describe the error or not 52 | */ 53 | - (BOOL)canDescribe:(NSInteger)code; 54 | 55 | /** 56 | Describes the given error code with a default message 57 | @param code error code to describe 58 | @param defaultMessage default known message for the error code 59 | */ 60 | - (RMErrorDescription *)describe:(NSInteger)code withDefaultMessage:(NSString *)defaultMessage; 61 | 62 | @end 63 | -------------------------------------------------------------------------------- /RMErrors/RMErrorCodeDefinition.m: -------------------------------------------------------------------------------- 1 | // 2 | // RMErrorCodeDefinition.m 3 | // RideMarketplace 4 | // 5 | // Created by Johan Ride on 8/24/15. 6 | // Copyright (c) 2015 Ride. All rights reserved. 7 | // 8 | 9 | #import "RMErrorCodeDefinition.h" 10 | #import "RMErrorCodeRangeBoundary.h" 11 | 12 | static NSString *const RMErrorCodeDefinitionAttributeFriendlyMessageName= @"friendlyMessage"; 13 | static NSString *const RMErrorCodeDefinitionAttributeTransientName= @"transient"; 14 | 15 | @implementation RMErrorCodeDefinition 16 | @synthesize boundary = _boundary; 17 | @synthesize friendlyMessage = _friendlyMessage; 18 | @synthesize transient = _transient; 19 | 20 | - (instancetype)init { 21 | return [self initWithBoundary:nil friendlyMessage:nil transient:NO]; 22 | } 23 | 24 | - (instancetype)initWithBoundary:(id)boundary 25 | friendlyMessage:(NSString *)friendlyMessage transient:(BOOL)transient { 26 | if((self = [super init])) { 27 | NSParameterAssert(boundary); 28 | _boundary = boundary; 29 | _friendlyMessage = friendlyMessage; 30 | _transient = transient; 31 | } 32 | return self; 33 | } 34 | 35 | - (instancetype)initWithBoundary:(id)boundary andAttributes:(NSDictionary *)attributes { 36 | NSString *friendlyMessage = attributes[RMErrorCodeDefinitionAttributeFriendlyMessageName]; 37 | NSNumber *transient = attributes[RMErrorCodeDefinitionAttributeTransientName]; 38 | return [self initWithBoundary:boundary friendlyMessage:friendlyMessage transient:transient.boolValue]; 39 | } 40 | 41 | - (BOOL)canDescribe:(NSInteger)code { 42 | return [self.boundary matches:code]; 43 | } 44 | 45 | - (RMErrorDescription *)describe:(NSInteger)code withDefaultMessage:(NSString *)defaultMessage { 46 | NSString *msg = self.friendlyMessage; 47 | if(!msg) { 48 | msg = defaultMessage; 49 | } 50 | return [[RMErrorDescription alloc] initWithFriendlyMessage:msg transient:self.transient code:code]; 51 | } 52 | 53 | @end 54 | -------------------------------------------------------------------------------- /RMErrors/RMErrorCodeRangeBoundary.h: -------------------------------------------------------------------------------- 1 | // 2 | // RMErrorCodeRangeBoundary.h 3 | // RideMarketplace 4 | // 5 | // Created by Johan Ride on 8/24/15. 6 | // Copyright (c) 2015 Ride. All rights reserved. 7 | // 8 | 9 | @import Foundation; 10 | #import "RMErrorCodeBoundary.h" 11 | 12 | extern NSInteger const RMErrorCodeRangeBoundaryDefaultLimit; 13 | 14 | /** 15 | Boundary of error codes based on upper and lower inclusive limits 16 | */ 17 | @interface RMErrorCodeRangeBoundary : NSObject 18 | 19 | /** 20 | Initializes the Boundary Ranges with lower and upper limits. 21 | */ 22 | - (instancetype)initWithLower:(NSInteger)lower andUpper:(NSInteger)upper NS_DESIGNATED_INITIALIZER; 23 | 24 | /** 25 | Upper limit of the error code (inclusive). 26 | */ 27 | @property (nonatomic, readonly) NSInteger upperLimit; 28 | 29 | /** 30 | Lower limit of the error codes (inclusive). 31 | */ 32 | @property (nonatomic, readonly) NSInteger lowerLimit; 33 | 34 | /** 35 | Creates a range boundary using the given pattern. 36 | A pattern is an string as "500..599" or just "500" which is the same as "500..500". 37 | */ 38 | + (instancetype)boundaryWithPattern:(NSString *)pattern; 39 | 40 | /** 41 | Returns a range boundary that matches all the error codes 42 | */ 43 | + (instancetype)wildcard; 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /RMErrors/RMErrorCodeRangeBoundary.m: -------------------------------------------------------------------------------- 1 | // 2 | // RMErrorCodeRangeBoundary.m 3 | // RideMarketplace 4 | // 5 | // Created by Johan Ride on 8/24/15. 6 | // Copyright (c) 2015 Ride. All rights reserved. 7 | // 8 | 9 | #import "RMErrorCodeRangeBoundary.h" 10 | 11 | NSInteger const RMErrorCodeRangeBoundaryDefaultLimit = -1; 12 | 13 | static NSString *const RMErrorCodeRangeBoundaryPatternSeparator = @".."; 14 | 15 | @implementation RMErrorCodeRangeBoundary 16 | @synthesize upperLimit = _upperLimit; 17 | @synthesize lowerLimit = _lowerLimit; 18 | 19 | - (instancetype)init { 20 | return [self initWithLower:RMErrorCodeRangeBoundaryDefaultLimit andUpper:RMErrorCodeRangeBoundaryDefaultLimit]; 21 | } 22 | 23 | - (instancetype)initWithLower:(NSInteger)lower andUpper:(NSInteger)upper { 24 | if((self = [super init])) { 25 | _lowerLimit = lower; 26 | _upperLimit = upper; 27 | } 28 | return self; 29 | } 30 | 31 | - (BOOL)matches:(NSInteger)code { 32 | return code >= self.lowerLimit && code <= self.upperLimit; 33 | } 34 | 35 | + (instancetype)boundaryWithPattern:(NSString *)pattern { 36 | NSParameterAssert(pattern); 37 | NSArray *limits = [pattern componentsSeparatedByString:RMErrorCodeRangeBoundaryPatternSeparator]; 38 | NSString *lowerText = limits.firstObject; 39 | NSInteger lower = RMErrorCodeRangeBoundaryDefaultLimit; 40 | if(lowerText.length != 0) { 41 | lower = lowerText.integerValue; 42 | } 43 | NSInteger upper = lower; 44 | NSString *upperText = limits.lastObject; 45 | if(upperText.length != 0) { 46 | upper = upperText.integerValue; 47 | } 48 | return [[RMErrorCodeRangeBoundary alloc] initWithLower:lower andUpper:upper]; 49 | } 50 | 51 | + (instancetype)wildcard { 52 | static RMErrorCodeRangeBoundary *_wildcard; 53 | static dispatch_once_t onceToken; 54 | dispatch_once(&onceToken, ^{ 55 | _wildcard = [[RMErrorCodeRangeBoundary alloc]initWithLower:NSIntegerMin andUpper:NSIntegerMax]; 56 | }); 57 | return _wildcard; 58 | } 59 | 60 | @end 61 | -------------------------------------------------------------------------------- /RMErrors/RMErrorCodes.h: -------------------------------------------------------------------------------- 1 | // 2 | // RMErrorCodes.h 3 | // RideMarketplace 4 | // 5 | // Created by Johan Ride on 8/25/15. 6 | // Copyright (c) 2015 Ride. All rights reserved. 7 | // 8 | 9 | @import Foundation; 10 | #import "RMErrorCodeDefinition.h" 11 | #import "RMErrorDescription.h" 12 | 13 | /** 14 | Collection of error codes known from an error domain 15 | */ 16 | @interface RMErrorCodes : NSObject 17 | 18 | /** 19 | Adds definitions from Content Dictionary (RMErrors.plist) to the collection 20 | */ 21 | - (void)addFromContent:(NSDictionary *)content; 22 | 23 | /** 24 | Adds an error code definition to the collection 25 | */ 26 | - (void)add:(RMErrorCodeDefinition *)definition; 27 | 28 | /** 29 | Returns all the available error definitions 30 | */ 31 | @property (nonatomic, readonly) NSArray *definitions; 32 | 33 | /** 34 | Describes the given error code with default message. Nil will be returned if none of the code definition can describe the error. 35 | */ 36 | - (RMErrorDescription *)describe:(NSInteger)code withDefaultMessage:(NSString *)defaultMessage; 37 | 38 | @end 39 | -------------------------------------------------------------------------------- /RMErrors/RMErrorCodes.m: -------------------------------------------------------------------------------- 1 | // 2 | // RMErrorCodes.m 3 | // RideMarketplace 4 | // 5 | // Created by Johan Ride on 8/25/15. 6 | // Copyright (c) 2015 Ride. All rights reserved. 7 | // 8 | 9 | #import "RMErrorCodes.h" 10 | #import "RMErrorCodeRangeBoundary.h" 11 | 12 | @interface RMErrorCodes() 13 | 14 | @property (nonatomic) NSMutableArray *codes; 15 | 16 | @end 17 | 18 | @implementation RMErrorCodes 19 | @dynamic definitions; 20 | @synthesize codes; 21 | 22 | - (instancetype)init { 23 | return [self initWithDictionary:nil]; 24 | } 25 | 26 | - (instancetype)initWithDictionary:(NSDictionary *)domains { 27 | if((self = [super init])) { 28 | self.codes = [NSMutableArray array]; 29 | } 30 | return self; 31 | } 32 | 33 | - (void)addFromContent:(NSDictionary *)content { 34 | for (NSString *pattern in content.allKeys) { 35 | NSDictionary *codeAttributes = content[pattern]; 36 | id boundary = [RMErrorCodeRangeBoundary boundaryWithPattern:pattern]; 37 | RMErrorCodeDefinition *definition = [[RMErrorCodeDefinition alloc] initWithBoundary:boundary andAttributes:codeAttributes]; 38 | [self add:definition]; 39 | } 40 | } 41 | 42 | - (void)add:(RMErrorCodeDefinition *)definition { 43 | NSParameterAssert([definition isKindOfClass:[RMErrorCodeDefinition class]]); 44 | [self.codes addObject:definition]; 45 | } 46 | 47 | - (NSArray *)definitions { 48 | return [self.codes copy]; 49 | } 50 | 51 | - (RMErrorDescription *)describe:(NSInteger)code withDefaultMessage:(NSString *)defaultMessage { 52 | for (RMErrorCodeDefinition *definition in self.codes) { 53 | if([definition canDescribe:code]) { 54 | return [definition describe:code withDefaultMessage:defaultMessage]; 55 | } 56 | } 57 | return nil; 58 | } 59 | 60 | @end 61 | -------------------------------------------------------------------------------- /RMErrors/RMErrorDescription.h: -------------------------------------------------------------------------------- 1 | // 2 | // RMErrorDescription.h 3 | // RideMarketplace 4 | // 5 | // Created by Johan Ride on 8/25/15. 6 | // Copyright (c) 2015 Ride. All rights reserved. 7 | // 8 | 9 | @import Foundation; 10 | 11 | extern NSString *const RMErrorDescriptionContentFriendlyMessageKey; 12 | extern NSString *const RMErrorDescriptionContentTransientKey; 13 | extern NSString *const RMErrorDescriptionContentCodeKey; 14 | 15 | /** 16 | Description of an error that occurred in the application 17 | */ 18 | @interface RMErrorDescription : NSObject 19 | 20 | /** 21 | Initializes the error description with the given message and transient indicator 22 | */ 23 | - (instancetype)initWithFriendlyMessage:(NSString *)friendlyMessage transient:(BOOL)transient code:(NSInteger)code NS_DESIGNATED_INITIALIZER; 24 | 25 | - (instancetype)initWithContent:(NSDictionary *)content; 26 | 27 | /** 28 | Indicates whether the error is transient or not 29 | */ 30 | @property (nonatomic, readonly) BOOL transient; 31 | 32 | /** 33 | A user friendly message to be shown to the user 34 | */ 35 | @property (nonatomic, readonly) NSString *friendlyMessage; 36 | 37 | /** 38 | Error code 39 | */ 40 | @property (nonatomic, readonly) NSInteger code; 41 | 42 | @end 43 | -------------------------------------------------------------------------------- /RMErrors/RMErrorDescription.m: -------------------------------------------------------------------------------- 1 | // 2 | // RMErrorDescription.m 3 | // RideMarketplace 4 | // 5 | // Created by Johan Ride on 8/25/15. 6 | // Copyright (c) 2015 Ride. All rights reserved. 7 | // 8 | 9 | #import "RMErrorDescription.h" 10 | 11 | NSString *const RMErrorDescriptionContentFriendlyMessageKey = @"friendlyMessage"; 12 | NSString *const RMErrorDescriptionContentTransientKey = @"transient"; 13 | NSString *const RMErrorDescriptionContentCodeKey = @"code"; 14 | 15 | @implementation RMErrorDescription 16 | @synthesize transient = _transient; 17 | @synthesize friendlyMessage = _friendlyMessage; 18 | @synthesize code = _code; 19 | 20 | - (instancetype)init { 21 | return [self initWithFriendlyMessage:nil transient:NO code:-1]; 22 | } 23 | 24 | - (instancetype)initWithFriendlyMessage:(NSString *)friendlyMessage transient:(BOOL)transient code:(NSInteger)code { 25 | if((self = [super init])) { 26 | _friendlyMessage = friendlyMessage; 27 | _transient = transient; 28 | _code = code; 29 | } 30 | return self; 31 | } 32 | 33 | - (instancetype)initWithContent:(NSDictionary *)content { 34 | NSString *friendlyMessage = content[RMErrorDescriptionContentFriendlyMessageKey]; 35 | NSNumber *transient = content[RMErrorDescriptionContentTransientKey]; 36 | NSNumber *code = content[RMErrorDescriptionContentCodeKey]; 37 | return [self initWithFriendlyMessage:friendlyMessage transient:transient.boolValue code:code.integerValue]; 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /RMErrors/RMErrorDomainDefinition.h: -------------------------------------------------------------------------------- 1 | // 2 | // RMErrorDomainDefinition.h 3 | // RideMarketplace 4 | // 5 | // Created by Johan Ride on 8/24/15. 6 | // Copyright (c) 2015 Ride. All rights reserved. 7 | // 8 | 9 | @import Foundation; 10 | #import "RMErrorCodes.h" 11 | #import "RMErrorCodeDefinition.h" 12 | 13 | /** 14 | Describes how the app sees an Error Domain. 15 | */ 16 | @interface RMErrorDomainDefinition : NSObject 17 | 18 | /** 19 | Initializes an error domain definition with the given domain name 20 | */ 21 | - (instancetype)initWithName:(NSString *)name NS_DESIGNATED_INITIALIZER; 22 | 23 | /** 24 | Name of Error Domain 25 | */ 26 | @property (nonatomic, readonly) NSString *name; 27 | 28 | /** 29 | Error codes definitions under this domain 30 | */ 31 | @property (nonatomic, readonly) RMErrorCodes *codes; 32 | 33 | /** 34 | Loads content of this domain definition RMErrors.plist content 35 | */ 36 | - (void)loadFromContent:(NSDictionary *)content; 37 | 38 | /** 39 | Indicates whether the error can be described by this domain 40 | */ 41 | - (BOOL)canDescribe:(NSError *)error; 42 | 43 | /** 44 | Process the given error and returns a description of it 45 | */ 46 | - (RMErrorDescription *)describe:(NSError *)error; 47 | 48 | /** 49 | Default code used when none of the codes are matched 50 | */ 51 | @property (nonatomic) RMErrorCodeDefinition *defaultCode; 52 | 53 | @end 54 | -------------------------------------------------------------------------------- /RMErrors/RMErrorDomainDefinition.m: -------------------------------------------------------------------------------- 1 | // 2 | // RMErrorDomainDefinition.m 3 | // RideMarketplace 4 | // 5 | // Created by Johan Ride on 8/24/15. 6 | // Copyright (c) 2015 Ride. All rights reserved. 7 | // 8 | 9 | #import "RMErrorDomainDefinition.h" 10 | #import "RMErrorCodes.h" 11 | #import "RMErrorCodeRangeBoundary.h" 12 | 13 | static NSString *const RMErrorDomainDefinitionContentCodesKey = @"codes"; 14 | static NSString *const RMErrorDomainDefinitionContentDefaultCodeKey = @"(default)"; 15 | 16 | @implementation RMErrorDomainDefinition 17 | @synthesize name = _name; 18 | @synthesize codes = _codes; 19 | @synthesize defaultCode = _defaultCode; 20 | 21 | - (instancetype)init { 22 | return [self initWithName:nil]; 23 | } 24 | 25 | - (instancetype)initWithName:(NSString *)name { 26 | if((self = [super init])) { 27 | NSParameterAssert(name); 28 | _name = name; 29 | _codes = [[RMErrorCodes alloc] init]; 30 | } 31 | return self; 32 | } 33 | 34 | - (void)loadFromContent:(NSDictionary *)content { 35 | [self.codes addFromContent:content[RMErrorDomainDefinitionContentCodesKey]]; 36 | NSDictionary *defaultCodeContent = content[RMErrorDomainDefinitionContentDefaultCodeKey]; 37 | if(defaultCodeContent) { 38 | self.defaultCode = [[RMErrorCodeDefinition alloc] initWithBoundary:[RMErrorCodeRangeBoundary wildcard] andAttributes:defaultCodeContent]; 39 | } 40 | } 41 | 42 | - (BOOL)canDescribe:(NSError *)error { 43 | return [error.domain isEqualToString:self.name]; 44 | } 45 | 46 | - (RMErrorDescription *)describe:(NSError *)error { 47 | NSInteger code = error.code; 48 | NSString *originalMessage = error.userInfo[NSLocalizedDescriptionKey]; 49 | RMErrorDescription *description = [self.codes describe:code withDefaultMessage:originalMessage]; 50 | if(description) { 51 | return description; 52 | } 53 | return [self.defaultCode describe:code withDefaultMessage:originalMessage]; 54 | } 55 | 56 | @end 57 | -------------------------------------------------------------------------------- /RMErrors/RMErrorDomains.h: -------------------------------------------------------------------------------- 1 | // 2 | // RMErrorDomains.h 3 | // RideMarketplace 4 | // 5 | // Created by Johan Ride on 8/24/15. 6 | // Copyright (c) 2015 Ride. All rights reserved. 7 | // 8 | 9 | @import Foundation; 10 | #import "RMErrorDomainDefinition.h" 11 | #import "RMErrorDescription.h" 12 | 13 | /** 14 | Collection of Error domains known by the app 15 | */ 16 | @interface RMErrorDomains : NSObject 17 | 18 | /** 19 | Adds definitions from Content Dictionary (RMErrors.plist) to the collection 20 | */ 21 | - (void)addFromContent:(NSDictionary *)content; 22 | 23 | /** 24 | Adds an error domain definition to the collection 25 | */ 26 | - (void)add:(RMErrorDomainDefinition *)definition; 27 | 28 | /** 29 | Returns all the available domain definitions 30 | */ 31 | @property (nonatomic, readonly) NSArray *definitions; 32 | 33 | /** 34 | Describes an error 35 | */ 36 | - (RMErrorDescription *)describe:(NSError *)error; 37 | 38 | @end 39 | -------------------------------------------------------------------------------- /RMErrors/RMErrorDomains.m: -------------------------------------------------------------------------------- 1 | // 2 | // RMErrorDomains.m 3 | // RideMarketplace 4 | // 5 | // Created by Johan Ride on 8/24/15. 6 | // Copyright (c) 2015 Ride. All rights reserved. 7 | // 8 | 9 | #import "RMErrorDomains.h" 10 | #import "RMErrorDomainDefinition.h" 11 | 12 | @interface RMErrorDomains() 13 | 14 | @property (nonatomic) NSMutableArray *domains; 15 | 16 | @end 17 | 18 | @implementation RMErrorDomains 19 | @dynamic definitions; 20 | @synthesize domains; 21 | 22 | - (instancetype)init { 23 | return [self initWithDictionary:nil]; 24 | } 25 | 26 | - (instancetype)initWithDictionary:(NSDictionary *)domains { 27 | if((self = [super init])) { 28 | self.domains = [NSMutableArray array]; 29 | } 30 | return self; 31 | } 32 | 33 | - (void)addFromContent:(NSDictionary *)content { 34 | for (NSString *domain in content.allKeys) { 35 | NSDictionary *domainContent = content[domain]; 36 | RMErrorDomainDefinition *definition = [[RMErrorDomainDefinition alloc] initWithName:domain]; 37 | [definition loadFromContent:domainContent]; 38 | [self add:definition]; 39 | } 40 | } 41 | 42 | - (void)add:(RMErrorDomainDefinition *)definition { 43 | NSParameterAssert([definition isKindOfClass:[RMErrorDomainDefinition class]]); 44 | [self.domains addObject:definition]; 45 | } 46 | 47 | - (NSArray *)definitions { 48 | return [self.domains copy]; 49 | } 50 | 51 | - (RMErrorDescription *)describe:(NSError *)error { 52 | for (RMErrorDomainDefinition *domain in self.domains) { 53 | if([domain canDescribe:error]) { 54 | return [domain describe:error]; 55 | } 56 | } 57 | return nil; 58 | } 59 | 60 | @end 61 | -------------------------------------------------------------------------------- /RMErrors/RMErrorTransformation.h: -------------------------------------------------------------------------------- 1 | // 2 | // RMErrorTransformation.h 3 | // RideMarketplace 4 | // 5 | // Created by Johan Ride on 8/25/15. 6 | // Copyright (c) 2015 Ride. All rights reserved. 7 | // 8 | 9 | @import Foundation; 10 | 11 | /** 12 | Implemented by error transformations 13 | */ 14 | @protocol RMErrorTransformation 15 | 16 | /* 17 | Transforms one NSError into another. Depending on the implementation, either a new NSerror or the original could be returned. 18 | */ 19 | - (NSError *)transform:(NSError *)original; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /RMErrors/RMErrorTransformations.h: -------------------------------------------------------------------------------- 1 | // 2 | // RMErrorTransformations.h 3 | // RideMarketplace 4 | // 5 | // Created by Johan Ride on 8/25/15. 6 | // Copyright (c) 2015 Ride. All rights reserved. 7 | // 8 | 9 | @import Foundation; 10 | #import "RMErrorTransformation.h" 11 | 12 | /** 13 | Collection of Transformations 14 | */ 15 | @interface RMErrorTransformations : NSObject 16 | 17 | /** 18 | Adds a Transformation to the collection. 19 | */ 20 | - (void)add:(id)transformation; 21 | 22 | /** 23 | Transforms an error into a new instance, depending on the implementation the original could be returned. 24 | */ 25 | - (NSError *)transform:(NSError *)original; 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /RMErrors/RMErrorTransformations.m: -------------------------------------------------------------------------------- 1 | // 2 | // RMErrorTransformations.m 3 | // RideMarketplace 4 | // 5 | // Created by Johan Ride on 8/25/15. 6 | // Copyright (c) 2015 Ride. All rights reserved. 7 | // 8 | 9 | #import "RMErrorTransformations.h" 10 | 11 | @interface RMErrorTransformations() 12 | 13 | @property (nonatomic) NSMutableArray *list; 14 | 15 | @end 16 | 17 | @implementation RMErrorTransformations 18 | @synthesize list; 19 | 20 | - (instancetype)init { 21 | if((self = [super init])) { 22 | self.list = [NSMutableArray array]; 23 | } 24 | return self; 25 | } 26 | 27 | - (void)add:(id)transformation { 28 | NSParameterAssert(transformation); 29 | [self.list addObject:transformation]; 30 | } 31 | 32 | - (NSError *)transform:(NSError *)original { 33 | NSError *last = original; 34 | for (id transformation in self.list) { 35 | last = [transformation transform:last]; 36 | } 37 | return last; 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /RMErrors/RMErrors.h: -------------------------------------------------------------------------------- 1 | // 2 | // RMErrors.h 3 | // RideMarketplace 4 | // 5 | // Created by Johan Ride on 8/24/15. 6 | // Copyright (c) 2015 Ride. All rights reserved. 7 | // 8 | 9 | @import Foundation; 10 | #import "RMErrorDomains.h" 11 | #import "RMErrorDescription.h" 12 | #import "RMErrorTransformations.h" 13 | #import "RMErrorCodes.h" 14 | 15 | extern NSString *__nonnull const RMErrorsContentDomainsKey; 16 | extern NSString *__nonnull const RMErrorsContentDefaultKey; 17 | extern NSString *__nonnull const RMErrorsDefaultFileName; 18 | 19 | @interface RMErrors : NSObject 20 | 21 | /** 22 | Error Domain definitions 23 | */ 24 | @property (nonatomic, nonnull, readonly) RMErrorDomains* domains; 25 | 26 | /** 27 | A collection of transformation to run prior describing the original error. 28 | */ 29 | @property (nonatomic, nonnull, readonly) RMErrorTransformations *transformations; 30 | 31 | /** 32 | Default error description in case is not found in domains and errors. 33 | */ 34 | @property (nonatomic, nullable) RMErrorDescription *defaultDescription; 35 | 36 | /** 37 | Load from parsed RMErrors.plist 38 | */ 39 | - (void)load:(nonnull NSDictionary *)content; 40 | 41 | /* 42 | Loads from property list in the main bundle 43 | */ 44 | - (void)loadPropertyList; 45 | 46 | /* 47 | Load the content of RMErrors with Property List 48 | @param name Name of the property list in the bundle. Can not be nil. 49 | @param bundle Bundle to load the property list from. Can not be nil. 50 | */ 51 | - (void)loadPropertyList:(nonnull NSString *)name bundle:(nonnull NSBundle *)bundle; 52 | 53 | /** 54 | Process an error and returns a description 55 | */ 56 | - (nullable RMErrorDescription *)describe:(nonnull NSError *)error; 57 | 58 | @end 59 | -------------------------------------------------------------------------------- /RMErrors/RMErrors.m: -------------------------------------------------------------------------------- 1 | // 2 | // RMErrors.m 3 | // RideMarketplace 4 | // 5 | // Created by Johan Ride on 8/24/15. 6 | // Copyright (c) 2015 Ride. All rights reserved. 7 | // 8 | 9 | #import "RMErrors.h" 10 | 11 | NSString *const RMErrorsContentDomainsKey = @"domains"; 12 | NSString *const RMErrorsContentDefaultKey = @"(default)"; 13 | NSString *const RMErrorsDefaultFileName = @"RMErrors"; 14 | 15 | @implementation RMErrors 16 | @synthesize domains = _domains; 17 | @synthesize transformations = _transformations; 18 | @synthesize defaultDescription = _defaultDescription; 19 | 20 | - (instancetype)init { 21 | if((self = [super init])) { 22 | _domains = [[RMErrorDomains alloc] init]; 23 | _transformations = [[RMErrorTransformations alloc] init]; 24 | } 25 | return self; 26 | } 27 | 28 | - (void)load:(NSDictionary *)content { 29 | [self.domains addFromContent:content[RMErrorsContentDomainsKey]]; 30 | NSDictionary *defaultContent = content[RMErrorsContentDefaultKey]; 31 | if(defaultContent) { 32 | self.defaultDescription = [[RMErrorDescription alloc] initWithContent:defaultContent]; 33 | } 34 | } 35 | 36 | - (nullable RMErrorDescription *)describe:(NSError *)error { 37 | NSError *transformed = [self.transformations transform:error]; 38 | RMErrorDescription *description = [self.domains describe:transformed]; 39 | if(description) { 40 | return description; 41 | } 42 | return self.defaultDescription; 43 | } 44 | 45 | - (void)loadPropertyList { 46 | [self loadPropertyList:RMErrorsDefaultFileName bundle:[NSBundle mainBundle]]; 47 | } 48 | 49 | - (void)loadPropertyList:(NSString *)name bundle:(NSBundle *)bundle { 50 | NSString *path = [bundle pathForResource:name ofType:@"plist"]; 51 | NSDictionary *content = [NSDictionary dictionaryWithContentsOfFile:path]; 52 | if(!content) { 53 | NSString *reason = [NSString stringWithFormat:@"Unable to load %@.plist", name]; 54 | [[NSException exceptionWithName:@"RMErrorsConfigFileException" reason:reason userInfo:nil] raise]; 55 | } 56 | [self load:content]; 57 | } 58 | 59 | @end 60 | -------------------------------------------------------------------------------- /Tests/.gitignore: -------------------------------------------------------------------------------- 1 | /Pods 2 | /Podfile.lock 3 | -------------------------------------------------------------------------------- /Tests/Podfile: -------------------------------------------------------------------------------- 1 | xcodeproj 'RMErrorsTests' 2 | workspace '../RMErrors' 3 | use_frameworks! 4 | 5 | def common_pods 6 | pod 'RMErrors', :path => '../' 7 | end 8 | 9 | target :ios do 10 | platform :ios, '8.0' 11 | link_with 'RMErrorsIOSTests' 12 | common_pods 13 | end 14 | 15 | target :osx do 16 | platform :osx, '10.9' 17 | link_with 'RMErrorsOSXTests' 18 | common_pods 19 | end 20 | 21 | -------------------------------------------------------------------------------- /Tests/RMErrorsIOSTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /Tests/RMErrorsIOSTests/RMErrorsIOSTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // RMErrorsIOSTests.m 3 | // RMErrorsIOSTests 4 | // 5 | // Created by Johan Ride on 11/10/15. 6 | // 7 | // 8 | 9 | #import 10 | 11 | @interface RMErrorsIOSTests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation RMErrorsIOSTests 16 | 17 | - (void)setUp { 18 | [super setUp]; 19 | // Put setup code here. This method is called before the invocation of each test method in the class. 20 | } 21 | 22 | - (void)tearDown { 23 | // Put teardown code here. This method is called after the invocation of each test method in the class. 24 | [super tearDown]; 25 | } 26 | 27 | - (void)testExample { 28 | // This is an example of a functional test case. 29 | // Use XCTAssert and related functions to verify your tests produce the correct results. 30 | } 31 | 32 | - (void)testPerformanceExample { 33 | // This is an example of a performance test case. 34 | [self measureBlock:^{ 35 | // Put the code you want to measure the time of here. 36 | }]; 37 | } 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /Tests/RMErrorsOSXTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /Tests/RMErrorsOSXTests/RMErrorsOSXTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // RMErrorsOSXTests.m 3 | // RMErrorsOSXTests 4 | // 5 | // Created by Johan Ride on 11/10/15. 6 | // 7 | // 8 | 9 | #import 10 | 11 | @interface RMErrorsOSXTests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation RMErrorsOSXTests 16 | 17 | - (void)setUp { 18 | [super setUp]; 19 | // Put setup code here. This method is called before the invocation of each test method in the class. 20 | } 21 | 22 | - (void)tearDown { 23 | // Put teardown code here. This method is called after the invocation of each test method in the class. 24 | [super tearDown]; 25 | } 26 | 27 | - (void)testExample { 28 | // This is an example of a functional test case. 29 | // Use XCTAssert and related functions to verify your tests produce the correct results. 30 | } 31 | 32 | - (void)testPerformanceExample { 33 | // This is an example of a performance test case. 34 | [self measureBlock:^{ 35 | // Put the code you want to measure the time of here. 36 | }]; 37 | } 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /Tests/RMErrorsTests.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 1E84A7DA1BF29C3D00D1532C /* RMErrorsIOSTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E84A7D91BF29C3D00D1532C /* RMErrorsIOSTests.m */; }; 11 | 1E84A7E01BF29E1300D1532C /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1E84A7DF1BF29E1300D1532C /* Foundation.framework */; }; 12 | 1E84A7EB1BF29F2000D1532C /* RMErrorCodeDefinitionTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E84A7E31BF29F2000D1532C /* RMErrorCodeDefinitionTest.m */; }; 13 | 1E84A7EC1BF29F2000D1532C /* RMErrorCodeRangeBoundaryTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E84A7E41BF29F2000D1532C /* RMErrorCodeRangeBoundaryTest.m */; }; 14 | 1E84A7ED1BF29F2000D1532C /* RMErrorCodesTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E84A7E51BF29F2000D1532C /* RMErrorCodesTest.m */; }; 15 | 1E84A7EE1BF29F2000D1532C /* RMErrorDomainDefinitionTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E84A7E61BF29F2000D1532C /* RMErrorDomainDefinitionTest.m */; }; 16 | 1E84A7EF1BF29F2000D1532C /* RMErrorDomainsTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E84A7E71BF29F2000D1532C /* RMErrorDomainsTest.m */; }; 17 | 1E84A7F11BF29F2000D1532C /* RMErrorsTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E84A7E91BF29F2000D1532C /* RMErrorsTest.m */; }; 18 | 1E84A7F21BF29F2000D1532C /* RMErrorsTransformationTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E84A7EA1BF29F2000D1532C /* RMErrorsTransformationTest.m */; }; 19 | 1E9597CA1BF2FAEA004C4851 /* RMErrorsOSXTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E9597C91BF2FAEA004C4851 /* RMErrorsOSXTests.m */; }; 20 | 1E9597CF1BF2FAFC004C4851 /* RMErrorCodeDefinitionTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E84A7E31BF29F2000D1532C /* RMErrorCodeDefinitionTest.m */; }; 21 | 1E9597D01BF2FAFC004C4851 /* RMErrorCodeRangeBoundaryTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E84A7E41BF29F2000D1532C /* RMErrorCodeRangeBoundaryTest.m */; }; 22 | 1E9597D11BF2FAFC004C4851 /* RMErrorCodesTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E84A7E51BF29F2000D1532C /* RMErrorCodesTest.m */; }; 23 | 1E9597D21BF2FAFC004C4851 /* RMErrorDomainDefinitionTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E84A7E61BF29F2000D1532C /* RMErrorDomainDefinitionTest.m */; }; 24 | 1E9597D31BF2FAFC004C4851 /* RMErrorDomainsTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E84A7E71BF29F2000D1532C /* RMErrorDomainsTest.m */; }; 25 | 1E9597D41BF2FAFC004C4851 /* RMErrorsTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E84A7E91BF29F2000D1532C /* RMErrorsTest.m */; }; 26 | 1E9597D51BF2FAFC004C4851 /* RMErrorsTransformationTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E84A7EA1BF29F2000D1532C /* RMErrorsTransformationTest.m */; }; 27 | 1EFF20BB1BF63963002A65C1 /* RMErrors.plist in Resources */ = {isa = PBXBuildFile; fileRef = 1EFF20BA1BF63963002A65C1 /* RMErrors.plist */; }; 28 | 1EFF20BC1BF63966002A65C1 /* RMErrors.plist in Resources */ = {isa = PBXBuildFile; fileRef = 1EFF20BA1BF63963002A65C1 /* RMErrors.plist */; }; 29 | 4C57D94F189E98E8470F6437 /* Pods_osx.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8764C77DB944C27DB9414DF2 /* Pods_osx.framework */; }; 30 | 6150E705DB159ECDB2520F37 /* Pods_ios.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2BBC31B3CBFB36F4316ECC00 /* Pods_ios.framework */; }; 31 | /* End PBXBuildFile section */ 32 | 33 | /* Begin PBXFileReference section */ 34 | 1E84A7D61BF29C3D00D1532C /* RMErrorsIOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RMErrorsIOSTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 35 | 1E84A7D91BF29C3D00D1532C /* RMErrorsIOSTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RMErrorsIOSTests.m; sourceTree = ""; }; 36 | 1E84A7DB1BF29C3D00D1532C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 37 | 1E84A7DF1BF29E1300D1532C /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS9.1.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; 38 | 1E84A7E31BF29F2000D1532C /* RMErrorCodeDefinitionTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RMErrorCodeDefinitionTest.m; sourceTree = ""; }; 39 | 1E84A7E41BF29F2000D1532C /* RMErrorCodeRangeBoundaryTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RMErrorCodeRangeBoundaryTest.m; sourceTree = ""; }; 40 | 1E84A7E51BF29F2000D1532C /* RMErrorCodesTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RMErrorCodesTest.m; sourceTree = ""; }; 41 | 1E84A7E61BF29F2000D1532C /* RMErrorDomainDefinitionTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RMErrorDomainDefinitionTest.m; sourceTree = ""; }; 42 | 1E84A7E71BF29F2000D1532C /* RMErrorDomainsTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RMErrorDomainsTest.m; sourceTree = ""; }; 43 | 1E84A7E91BF29F2000D1532C /* RMErrorsTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RMErrorsTest.m; sourceTree = ""; }; 44 | 1E84A7EA1BF29F2000D1532C /* RMErrorsTransformationTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RMErrorsTransformationTest.m; sourceTree = ""; }; 45 | 1E9597C71BF2FAEA004C4851 /* RMErrorsOSXTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RMErrorsOSXTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 46 | 1E9597C91BF2FAEA004C4851 /* RMErrorsOSXTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RMErrorsOSXTests.m; sourceTree = ""; }; 47 | 1E9597CB1BF2FAEA004C4851 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 48 | 1EFF20BA1BF63963002A65C1 /* RMErrors.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = RMErrors.plist; sourceTree = ""; }; 49 | 2BBC31B3CBFB36F4316ECC00 /* Pods_ios.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_ios.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 50 | 35578B838AB067E90CF97C5D /* Pods-osx.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-osx.release.xcconfig"; path = "Pods/Target Support Files/Pods-osx/Pods-osx.release.xcconfig"; sourceTree = ""; }; 51 | 7767EB1B31CE7690808120B9 /* Pods-ios.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ios.debug.xcconfig"; path = "Pods/Target Support Files/Pods-ios/Pods-ios.debug.xcconfig"; sourceTree = ""; }; 52 | 8764C77DB944C27DB9414DF2 /* Pods_osx.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_osx.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 53 | D96A260D7F7B8FD3663122A1 /* Pods-osx.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-osx.debug.xcconfig"; path = "Pods/Target Support Files/Pods-osx/Pods-osx.debug.xcconfig"; sourceTree = ""; }; 54 | FDC8FB2FD40BCD8294ADF04E /* Pods-ios.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ios.release.xcconfig"; path = "Pods/Target Support Files/Pods-ios/Pods-ios.release.xcconfig"; sourceTree = ""; }; 55 | /* End PBXFileReference section */ 56 | 57 | /* Begin PBXFrameworksBuildPhase section */ 58 | 1E84A7D31BF29C3D00D1532C /* Frameworks */ = { 59 | isa = PBXFrameworksBuildPhase; 60 | buildActionMask = 2147483647; 61 | files = ( 62 | 1E84A7E01BF29E1300D1532C /* Foundation.framework in Frameworks */, 63 | 6150E705DB159ECDB2520F37 /* Pods_ios.framework in Frameworks */, 64 | ); 65 | runOnlyForDeploymentPostprocessing = 0; 66 | }; 67 | 1E9597C41BF2FAEA004C4851 /* Frameworks */ = { 68 | isa = PBXFrameworksBuildPhase; 69 | buildActionMask = 2147483647; 70 | files = ( 71 | 4C57D94F189E98E8470F6437 /* Pods_osx.framework in Frameworks */, 72 | ); 73 | runOnlyForDeploymentPostprocessing = 0; 74 | }; 75 | /* End PBXFrameworksBuildPhase section */ 76 | 77 | /* Begin PBXGroup section */ 78 | 1E84A7CB1BF29BE000D1532C = { 79 | isa = PBXGroup; 80 | children = ( 81 | 1E84A7E21BF29ECD00D1532C /* Tests */, 82 | 1E9597C81BF2FAEA004C4851 /* RMErrorsOSXTests */, 83 | 1E84A7E11BF29E1900D1532C /* Frameworks */, 84 | 1E84A7D81BF29C3D00D1532C /* RMErrorsIOSTests */, 85 | 1E84A7D71BF29C3D00D1532C /* Products */, 86 | AFDD49766CA6D337187962F0 /* Pods */, 87 | ); 88 | sourceTree = ""; 89 | }; 90 | 1E84A7D71BF29C3D00D1532C /* Products */ = { 91 | isa = PBXGroup; 92 | children = ( 93 | 1E84A7D61BF29C3D00D1532C /* RMErrorsIOSTests.xctest */, 94 | 1E9597C71BF2FAEA004C4851 /* RMErrorsOSXTests.xctest */, 95 | ); 96 | name = Products; 97 | sourceTree = ""; 98 | }; 99 | 1E84A7D81BF29C3D00D1532C /* RMErrorsIOSTests */ = { 100 | isa = PBXGroup; 101 | children = ( 102 | 1E84A7D91BF29C3D00D1532C /* RMErrorsIOSTests.m */, 103 | 1E84A7DB1BF29C3D00D1532C /* Info.plist */, 104 | ); 105 | path = RMErrorsIOSTests; 106 | sourceTree = ""; 107 | }; 108 | 1E84A7E11BF29E1900D1532C /* Frameworks */ = { 109 | isa = PBXGroup; 110 | children = ( 111 | 1E84A7DF1BF29E1300D1532C /* Foundation.framework */, 112 | 2BBC31B3CBFB36F4316ECC00 /* Pods_ios.framework */, 113 | 8764C77DB944C27DB9414DF2 /* Pods_osx.framework */, 114 | ); 115 | name = Frameworks; 116 | sourceTree = ""; 117 | }; 118 | 1E84A7E21BF29ECD00D1532C /* Tests */ = { 119 | isa = PBXGroup; 120 | children = ( 121 | 1EFF20B91BF63908002A65C1 /* Fixtures */, 122 | 1E84A7E31BF29F2000D1532C /* RMErrorCodeDefinitionTest.m */, 123 | 1E84A7E41BF29F2000D1532C /* RMErrorCodeRangeBoundaryTest.m */, 124 | 1E84A7E51BF29F2000D1532C /* RMErrorCodesTest.m */, 125 | 1E84A7E61BF29F2000D1532C /* RMErrorDomainDefinitionTest.m */, 126 | 1E84A7E71BF29F2000D1532C /* RMErrorDomainsTest.m */, 127 | 1E84A7E91BF29F2000D1532C /* RMErrorsTest.m */, 128 | 1E84A7EA1BF29F2000D1532C /* RMErrorsTransformationTest.m */, 129 | ); 130 | path = Tests; 131 | sourceTree = ""; 132 | }; 133 | 1E9597C81BF2FAEA004C4851 /* RMErrorsOSXTests */ = { 134 | isa = PBXGroup; 135 | children = ( 136 | 1E9597C91BF2FAEA004C4851 /* RMErrorsOSXTests.m */, 137 | 1E9597CB1BF2FAEA004C4851 /* Info.plist */, 138 | ); 139 | path = RMErrorsOSXTests; 140 | sourceTree = ""; 141 | }; 142 | 1EFF20B91BF63908002A65C1 /* Fixtures */ = { 143 | isa = PBXGroup; 144 | children = ( 145 | 1EFF20BA1BF63963002A65C1 /* RMErrors.plist */, 146 | ); 147 | path = Fixtures; 148 | sourceTree = ""; 149 | }; 150 | AFDD49766CA6D337187962F0 /* Pods */ = { 151 | isa = PBXGroup; 152 | children = ( 153 | 7767EB1B31CE7690808120B9 /* Pods-ios.debug.xcconfig */, 154 | FDC8FB2FD40BCD8294ADF04E /* Pods-ios.release.xcconfig */, 155 | D96A260D7F7B8FD3663122A1 /* Pods-osx.debug.xcconfig */, 156 | 35578B838AB067E90CF97C5D /* Pods-osx.release.xcconfig */, 157 | ); 158 | name = Pods; 159 | sourceTree = ""; 160 | }; 161 | /* End PBXGroup section */ 162 | 163 | /* Begin PBXNativeTarget section */ 164 | 1E84A7D51BF29C3D00D1532C /* RMErrorsIOSTests */ = { 165 | isa = PBXNativeTarget; 166 | buildConfigurationList = 1E84A7DC1BF29C3D00D1532C /* Build configuration list for PBXNativeTarget "RMErrorsIOSTests" */; 167 | buildPhases = ( 168 | 33DC975854BB9C9B7CBE00E4 /* Check Pods Manifest.lock */, 169 | 1E84A7D21BF29C3D00D1532C /* Sources */, 170 | 1E84A7D31BF29C3D00D1532C /* Frameworks */, 171 | 1E84A7D41BF29C3D00D1532C /* Resources */, 172 | 326D9A1631CD824DE4AC9585 /* Embed Pods Frameworks */, 173 | F5FD045F7CB9868EF0E410D7 /* Copy Pods Resources */, 174 | ); 175 | buildRules = ( 176 | ); 177 | dependencies = ( 178 | ); 179 | name = RMErrorsIOSTests; 180 | productName = RMErrorsIOSTests; 181 | productReference = 1E84A7D61BF29C3D00D1532C /* RMErrorsIOSTests.xctest */; 182 | productType = "com.apple.product-type.bundle.unit-test"; 183 | }; 184 | 1E9597C61BF2FAEA004C4851 /* RMErrorsOSXTests */ = { 185 | isa = PBXNativeTarget; 186 | buildConfigurationList = 1E9597CE1BF2FAEA004C4851 /* Build configuration list for PBXNativeTarget "RMErrorsOSXTests" */; 187 | buildPhases = ( 188 | 23D7C20CFC8C5B07052DDFAF /* Check Pods Manifest.lock */, 189 | 1E9597C31BF2FAEA004C4851 /* Sources */, 190 | 1E9597C41BF2FAEA004C4851 /* Frameworks */, 191 | 1E9597C51BF2FAEA004C4851 /* Resources */, 192 | 6A0C4EB7DA69FA2C584D4BE8 /* Embed Pods Frameworks */, 193 | BC83CFC9B336B4261E577ABD /* Copy Pods Resources */, 194 | ); 195 | buildRules = ( 196 | ); 197 | dependencies = ( 198 | ); 199 | name = RMErrorsOSXTests; 200 | productName = RMErrorsOSXTests; 201 | productReference = 1E9597C71BF2FAEA004C4851 /* RMErrorsOSXTests.xctest */; 202 | productType = "com.apple.product-type.bundle.unit-test"; 203 | }; 204 | /* End PBXNativeTarget section */ 205 | 206 | /* Begin PBXProject section */ 207 | 1E84A7CC1BF29BE000D1532C /* Project object */ = { 208 | isa = PBXProject; 209 | attributes = { 210 | LastUpgradeCheck = 0710; 211 | TargetAttributes = { 212 | 1E84A7D51BF29C3D00D1532C = { 213 | CreatedOnToolsVersion = 7.1; 214 | }; 215 | 1E9597C61BF2FAEA004C4851 = { 216 | CreatedOnToolsVersion = 7.1; 217 | }; 218 | }; 219 | }; 220 | buildConfigurationList = 1E84A7CF1BF29BE000D1532C /* Build configuration list for PBXProject "RMErrorsTests" */; 221 | compatibilityVersion = "Xcode 3.2"; 222 | developmentRegion = English; 223 | hasScannedForEncodings = 0; 224 | knownRegions = ( 225 | en, 226 | ); 227 | mainGroup = 1E84A7CB1BF29BE000D1532C; 228 | productRefGroup = 1E84A7D71BF29C3D00D1532C /* Products */; 229 | projectDirPath = ""; 230 | projectRoot = ""; 231 | targets = ( 232 | 1E84A7D51BF29C3D00D1532C /* RMErrorsIOSTests */, 233 | 1E9597C61BF2FAEA004C4851 /* RMErrorsOSXTests */, 234 | ); 235 | }; 236 | /* End PBXProject section */ 237 | 238 | /* Begin PBXResourcesBuildPhase section */ 239 | 1E84A7D41BF29C3D00D1532C /* Resources */ = { 240 | isa = PBXResourcesBuildPhase; 241 | buildActionMask = 2147483647; 242 | files = ( 243 | 1EFF20BB1BF63963002A65C1 /* RMErrors.plist in Resources */, 244 | ); 245 | runOnlyForDeploymentPostprocessing = 0; 246 | }; 247 | 1E9597C51BF2FAEA004C4851 /* Resources */ = { 248 | isa = PBXResourcesBuildPhase; 249 | buildActionMask = 2147483647; 250 | files = ( 251 | 1EFF20BC1BF63966002A65C1 /* RMErrors.plist in Resources */, 252 | ); 253 | runOnlyForDeploymentPostprocessing = 0; 254 | }; 255 | /* End PBXResourcesBuildPhase section */ 256 | 257 | /* Begin PBXShellScriptBuildPhase section */ 258 | 23D7C20CFC8C5B07052DDFAF /* Check Pods Manifest.lock */ = { 259 | isa = PBXShellScriptBuildPhase; 260 | buildActionMask = 2147483647; 261 | files = ( 262 | ); 263 | inputPaths = ( 264 | ); 265 | name = "Check Pods Manifest.lock"; 266 | outputPaths = ( 267 | ); 268 | runOnlyForDeploymentPostprocessing = 0; 269 | shellPath = /bin/sh; 270 | shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; 271 | showEnvVarsInLog = 0; 272 | }; 273 | 326D9A1631CD824DE4AC9585 /* Embed Pods Frameworks */ = { 274 | isa = PBXShellScriptBuildPhase; 275 | buildActionMask = 2147483647; 276 | files = ( 277 | ); 278 | inputPaths = ( 279 | ); 280 | name = "Embed Pods Frameworks"; 281 | outputPaths = ( 282 | ); 283 | runOnlyForDeploymentPostprocessing = 0; 284 | shellPath = /bin/sh; 285 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-ios/Pods-ios-frameworks.sh\"\n"; 286 | showEnvVarsInLog = 0; 287 | }; 288 | 33DC975854BB9C9B7CBE00E4 /* Check Pods Manifest.lock */ = { 289 | isa = PBXShellScriptBuildPhase; 290 | buildActionMask = 2147483647; 291 | files = ( 292 | ); 293 | inputPaths = ( 294 | ); 295 | name = "Check Pods Manifest.lock"; 296 | outputPaths = ( 297 | ); 298 | runOnlyForDeploymentPostprocessing = 0; 299 | shellPath = /bin/sh; 300 | shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; 301 | showEnvVarsInLog = 0; 302 | }; 303 | 6A0C4EB7DA69FA2C584D4BE8 /* Embed Pods Frameworks */ = { 304 | isa = PBXShellScriptBuildPhase; 305 | buildActionMask = 2147483647; 306 | files = ( 307 | ); 308 | inputPaths = ( 309 | ); 310 | name = "Embed Pods Frameworks"; 311 | outputPaths = ( 312 | ); 313 | runOnlyForDeploymentPostprocessing = 0; 314 | shellPath = /bin/sh; 315 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-osx/Pods-osx-frameworks.sh\"\n"; 316 | showEnvVarsInLog = 0; 317 | }; 318 | BC83CFC9B336B4261E577ABD /* Copy Pods Resources */ = { 319 | isa = PBXShellScriptBuildPhase; 320 | buildActionMask = 2147483647; 321 | files = ( 322 | ); 323 | inputPaths = ( 324 | ); 325 | name = "Copy Pods Resources"; 326 | outputPaths = ( 327 | ); 328 | runOnlyForDeploymentPostprocessing = 0; 329 | shellPath = /bin/sh; 330 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-osx/Pods-osx-resources.sh\"\n"; 331 | showEnvVarsInLog = 0; 332 | }; 333 | F5FD045F7CB9868EF0E410D7 /* Copy Pods Resources */ = { 334 | isa = PBXShellScriptBuildPhase; 335 | buildActionMask = 2147483647; 336 | files = ( 337 | ); 338 | inputPaths = ( 339 | ); 340 | name = "Copy Pods Resources"; 341 | outputPaths = ( 342 | ); 343 | runOnlyForDeploymentPostprocessing = 0; 344 | shellPath = /bin/sh; 345 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-ios/Pods-ios-resources.sh\"\n"; 346 | showEnvVarsInLog = 0; 347 | }; 348 | /* End PBXShellScriptBuildPhase section */ 349 | 350 | /* Begin PBXSourcesBuildPhase section */ 351 | 1E84A7D21BF29C3D00D1532C /* Sources */ = { 352 | isa = PBXSourcesBuildPhase; 353 | buildActionMask = 2147483647; 354 | files = ( 355 | 1E84A7ED1BF29F2000D1532C /* RMErrorCodesTest.m in Sources */, 356 | 1E84A7EF1BF29F2000D1532C /* RMErrorDomainsTest.m in Sources */, 357 | 1E84A7F21BF29F2000D1532C /* RMErrorsTransformationTest.m in Sources */, 358 | 1E84A7DA1BF29C3D00D1532C /* RMErrorsIOSTests.m in Sources */, 359 | 1E84A7EE1BF29F2000D1532C /* RMErrorDomainDefinitionTest.m in Sources */, 360 | 1E84A7F11BF29F2000D1532C /* RMErrorsTest.m in Sources */, 361 | 1E84A7EB1BF29F2000D1532C /* RMErrorCodeDefinitionTest.m in Sources */, 362 | 1E84A7EC1BF29F2000D1532C /* RMErrorCodeRangeBoundaryTest.m in Sources */, 363 | ); 364 | runOnlyForDeploymentPostprocessing = 0; 365 | }; 366 | 1E9597C31BF2FAEA004C4851 /* Sources */ = { 367 | isa = PBXSourcesBuildPhase; 368 | buildActionMask = 2147483647; 369 | files = ( 370 | 1E9597CF1BF2FAFC004C4851 /* RMErrorCodeDefinitionTest.m in Sources */, 371 | 1E9597D01BF2FAFC004C4851 /* RMErrorCodeRangeBoundaryTest.m in Sources */, 372 | 1E9597D11BF2FAFC004C4851 /* RMErrorCodesTest.m in Sources */, 373 | 1E9597D21BF2FAFC004C4851 /* RMErrorDomainDefinitionTest.m in Sources */, 374 | 1E9597D31BF2FAFC004C4851 /* RMErrorDomainsTest.m in Sources */, 375 | 1E9597D41BF2FAFC004C4851 /* RMErrorsTest.m in Sources */, 376 | 1E9597D51BF2FAFC004C4851 /* RMErrorsTransformationTest.m in Sources */, 377 | 1E9597CA1BF2FAEA004C4851 /* RMErrorsOSXTests.m in Sources */, 378 | ); 379 | runOnlyForDeploymentPostprocessing = 0; 380 | }; 381 | /* End PBXSourcesBuildPhase section */ 382 | 383 | /* Begin XCBuildConfiguration section */ 384 | 1E84A7D01BF29BE000D1532C /* Debug */ = { 385 | isa = XCBuildConfiguration; 386 | buildSettings = { 387 | CLANG_ENABLE_MODULES = YES; 388 | CLANG_WARN_NULLABLE_TO_NONNULL_CONVERSION = YES; 389 | IPHONEOS_DEPLOYMENT_TARGET = 8.1; 390 | }; 391 | name = Debug; 392 | }; 393 | 1E84A7D11BF29BE000D1532C /* Release */ = { 394 | isa = XCBuildConfiguration; 395 | buildSettings = { 396 | CLANG_ENABLE_MODULES = YES; 397 | CLANG_WARN_NULLABLE_TO_NONNULL_CONVERSION = YES; 398 | IPHONEOS_DEPLOYMENT_TARGET = 8.1; 399 | }; 400 | name = Release; 401 | }; 402 | 1E84A7DD1BF29C3D00D1532C /* Debug */ = { 403 | isa = XCBuildConfiguration; 404 | baseConfigurationReference = 7767EB1B31CE7690808120B9 /* Pods-ios.debug.xcconfig */; 405 | buildSettings = { 406 | ALWAYS_SEARCH_USER_PATHS = NO; 407 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 408 | CLANG_CXX_LIBRARY = "libc++"; 409 | CLANG_ENABLE_MODULES = YES; 410 | CLANG_ENABLE_OBJC_ARC = YES; 411 | CLANG_WARN_BOOL_CONVERSION = YES; 412 | CLANG_WARN_CONSTANT_CONVERSION = YES; 413 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 414 | CLANG_WARN_EMPTY_BODY = YES; 415 | CLANG_WARN_ENUM_CONVERSION = YES; 416 | CLANG_WARN_INT_CONVERSION = YES; 417 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 418 | CLANG_WARN_UNREACHABLE_CODE = YES; 419 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 420 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 421 | COPY_PHASE_STRIP = NO; 422 | DEBUG_INFORMATION_FORMAT = dwarf; 423 | ENABLE_STRICT_OBJC_MSGSEND = YES; 424 | ENABLE_TESTABILITY = YES; 425 | GCC_C_LANGUAGE_STANDARD = gnu99; 426 | GCC_DYNAMIC_NO_PIC = NO; 427 | GCC_NO_COMMON_BLOCKS = YES; 428 | GCC_OPTIMIZATION_LEVEL = 0; 429 | GCC_PREPROCESSOR_DEFINITIONS = ( 430 | "DEBUG=1", 431 | "$(inherited)", 432 | ); 433 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 434 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 435 | GCC_WARN_UNDECLARED_SELECTOR = YES; 436 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 437 | GCC_WARN_UNUSED_FUNCTION = YES; 438 | GCC_WARN_UNUSED_VARIABLE = YES; 439 | INFOPLIST_FILE = RMErrorsIOSTests/Info.plist; 440 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 441 | MTL_ENABLE_DEBUG_INFO = YES; 442 | ONLY_ACTIVE_ARCH = YES; 443 | PRODUCT_BUNDLE_IDENTIFIER = com.ride.RMErrorsIOSTests; 444 | PRODUCT_NAME = "$(TARGET_NAME)"; 445 | SDKROOT = iphoneos; 446 | }; 447 | name = Debug; 448 | }; 449 | 1E84A7DE1BF29C3D00D1532C /* Release */ = { 450 | isa = XCBuildConfiguration; 451 | baseConfigurationReference = FDC8FB2FD40BCD8294ADF04E /* Pods-ios.release.xcconfig */; 452 | buildSettings = { 453 | ALWAYS_SEARCH_USER_PATHS = NO; 454 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 455 | CLANG_CXX_LIBRARY = "libc++"; 456 | CLANG_ENABLE_MODULES = YES; 457 | CLANG_ENABLE_OBJC_ARC = YES; 458 | CLANG_WARN_BOOL_CONVERSION = YES; 459 | CLANG_WARN_CONSTANT_CONVERSION = YES; 460 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 461 | CLANG_WARN_EMPTY_BODY = YES; 462 | CLANG_WARN_ENUM_CONVERSION = YES; 463 | CLANG_WARN_INT_CONVERSION = YES; 464 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 465 | CLANG_WARN_UNREACHABLE_CODE = YES; 466 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 467 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 468 | COPY_PHASE_STRIP = NO; 469 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 470 | ENABLE_NS_ASSERTIONS = NO; 471 | ENABLE_STRICT_OBJC_MSGSEND = YES; 472 | GCC_C_LANGUAGE_STANDARD = gnu99; 473 | GCC_NO_COMMON_BLOCKS = YES; 474 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 475 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 476 | GCC_WARN_UNDECLARED_SELECTOR = YES; 477 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 478 | GCC_WARN_UNUSED_FUNCTION = YES; 479 | GCC_WARN_UNUSED_VARIABLE = YES; 480 | INFOPLIST_FILE = RMErrorsIOSTests/Info.plist; 481 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 482 | MTL_ENABLE_DEBUG_INFO = NO; 483 | PRODUCT_BUNDLE_IDENTIFIER = com.ride.RMErrorsIOSTests; 484 | PRODUCT_NAME = "$(TARGET_NAME)"; 485 | SDKROOT = iphoneos; 486 | VALIDATE_PRODUCT = YES; 487 | }; 488 | name = Release; 489 | }; 490 | 1E9597CC1BF2FAEA004C4851 /* Debug */ = { 491 | isa = XCBuildConfiguration; 492 | baseConfigurationReference = D96A260D7F7B8FD3663122A1 /* Pods-osx.debug.xcconfig */; 493 | buildSettings = { 494 | ALWAYS_SEARCH_USER_PATHS = NO; 495 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 496 | CLANG_CXX_LIBRARY = "libc++"; 497 | CLANG_ENABLE_MODULES = YES; 498 | CLANG_ENABLE_OBJC_ARC = YES; 499 | CLANG_WARN_BOOL_CONVERSION = YES; 500 | CLANG_WARN_CONSTANT_CONVERSION = YES; 501 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 502 | CLANG_WARN_EMPTY_BODY = YES; 503 | CLANG_WARN_ENUM_CONVERSION = YES; 504 | CLANG_WARN_INT_CONVERSION = YES; 505 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 506 | CLANG_WARN_UNREACHABLE_CODE = YES; 507 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 508 | CODE_SIGN_IDENTITY = "-"; 509 | COMBINE_HIDPI_IMAGES = YES; 510 | COPY_PHASE_STRIP = NO; 511 | DEBUG_INFORMATION_FORMAT = dwarf; 512 | ENABLE_STRICT_OBJC_MSGSEND = YES; 513 | ENABLE_TESTABILITY = YES; 514 | GCC_C_LANGUAGE_STANDARD = gnu99; 515 | GCC_DYNAMIC_NO_PIC = NO; 516 | GCC_NO_COMMON_BLOCKS = YES; 517 | GCC_OPTIMIZATION_LEVEL = 0; 518 | GCC_PREPROCESSOR_DEFINITIONS = ( 519 | "DEBUG=1", 520 | "$(inherited)", 521 | ); 522 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 523 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 524 | GCC_WARN_UNDECLARED_SELECTOR = YES; 525 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 526 | GCC_WARN_UNUSED_FUNCTION = YES; 527 | GCC_WARN_UNUSED_VARIABLE = YES; 528 | INFOPLIST_FILE = RMErrorsOSXTests/Info.plist; 529 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; 530 | MACOSX_DEPLOYMENT_TARGET = 10.11; 531 | MTL_ENABLE_DEBUG_INFO = YES; 532 | ONLY_ACTIVE_ARCH = YES; 533 | PRODUCT_BUNDLE_IDENTIFIER = com.ride.RMErrorsOSXTests; 534 | PRODUCT_NAME = "$(TARGET_NAME)"; 535 | SDKROOT = macosx; 536 | }; 537 | name = Debug; 538 | }; 539 | 1E9597CD1BF2FAEA004C4851 /* Release */ = { 540 | isa = XCBuildConfiguration; 541 | baseConfigurationReference = 35578B838AB067E90CF97C5D /* Pods-osx.release.xcconfig */; 542 | buildSettings = { 543 | ALWAYS_SEARCH_USER_PATHS = NO; 544 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 545 | CLANG_CXX_LIBRARY = "libc++"; 546 | CLANG_ENABLE_MODULES = YES; 547 | CLANG_ENABLE_OBJC_ARC = YES; 548 | CLANG_WARN_BOOL_CONVERSION = YES; 549 | CLANG_WARN_CONSTANT_CONVERSION = YES; 550 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 551 | CLANG_WARN_EMPTY_BODY = YES; 552 | CLANG_WARN_ENUM_CONVERSION = YES; 553 | CLANG_WARN_INT_CONVERSION = YES; 554 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 555 | CLANG_WARN_UNREACHABLE_CODE = YES; 556 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 557 | CODE_SIGN_IDENTITY = "-"; 558 | COMBINE_HIDPI_IMAGES = YES; 559 | COPY_PHASE_STRIP = NO; 560 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 561 | ENABLE_NS_ASSERTIONS = NO; 562 | ENABLE_STRICT_OBJC_MSGSEND = YES; 563 | GCC_C_LANGUAGE_STANDARD = gnu99; 564 | GCC_NO_COMMON_BLOCKS = YES; 565 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 566 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 567 | GCC_WARN_UNDECLARED_SELECTOR = YES; 568 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 569 | GCC_WARN_UNUSED_FUNCTION = YES; 570 | GCC_WARN_UNUSED_VARIABLE = YES; 571 | INFOPLIST_FILE = RMErrorsOSXTests/Info.plist; 572 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; 573 | MACOSX_DEPLOYMENT_TARGET = 10.11; 574 | MTL_ENABLE_DEBUG_INFO = NO; 575 | PRODUCT_BUNDLE_IDENTIFIER = com.ride.RMErrorsOSXTests; 576 | PRODUCT_NAME = "$(TARGET_NAME)"; 577 | SDKROOT = macosx; 578 | }; 579 | name = Release; 580 | }; 581 | /* End XCBuildConfiguration section */ 582 | 583 | /* Begin XCConfigurationList section */ 584 | 1E84A7CF1BF29BE000D1532C /* Build configuration list for PBXProject "RMErrorsTests" */ = { 585 | isa = XCConfigurationList; 586 | buildConfigurations = ( 587 | 1E84A7D01BF29BE000D1532C /* Debug */, 588 | 1E84A7D11BF29BE000D1532C /* Release */, 589 | ); 590 | defaultConfigurationIsVisible = 0; 591 | defaultConfigurationName = Release; 592 | }; 593 | 1E84A7DC1BF29C3D00D1532C /* Build configuration list for PBXNativeTarget "RMErrorsIOSTests" */ = { 594 | isa = XCConfigurationList; 595 | buildConfigurations = ( 596 | 1E84A7DD1BF29C3D00D1532C /* Debug */, 597 | 1E84A7DE1BF29C3D00D1532C /* Release */, 598 | ); 599 | defaultConfigurationIsVisible = 0; 600 | defaultConfigurationName = Release; 601 | }; 602 | 1E9597CE1BF2FAEA004C4851 /* Build configuration list for PBXNativeTarget "RMErrorsOSXTests" */ = { 603 | isa = XCConfigurationList; 604 | buildConfigurations = ( 605 | 1E9597CC1BF2FAEA004C4851 /* Debug */, 606 | 1E9597CD1BF2FAEA004C4851 /* Release */, 607 | ); 608 | defaultConfigurationIsVisible = 0; 609 | defaultConfigurationName = Release; 610 | }; 611 | /* End XCConfigurationList section */ 612 | }; 613 | rootObject = 1E84A7CC1BF29BE000D1532C /* Project object */; 614 | } 615 | -------------------------------------------------------------------------------- /Tests/RMErrorsTests.xcodeproj/xcshareddata/xcschemes/RMErrorsIOSTests.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 14 | 15 | 17 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 39 | 40 | 41 | 42 | 48 | 49 | 51 | 52 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /Tests/RMErrorsTests.xcodeproj/xcshareddata/xcschemes/RMErrorsOSXTests.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 14 | 15 | 17 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 39 | 40 | 41 | 42 | 48 | 49 | 51 | 52 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /Tests/Tests/Fixtures/RMErrors.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | (default) 6 | 7 | code 8 | -1 9 | friendlyMessage 10 | Oopss, something went wrong 11 | 12 | domains 13 | 14 | NSURLErrorDomain 15 | 16 | (default) 17 | 18 | transient 19 | 20 | 21 | codes 22 | 23 | -1003..-1009 24 | 25 | transient 26 | 27 | friendlyMessage 28 | the connection failed because the device is not connected to the internet 29 | 30 | -1001 31 | 32 | transient 33 | 34 | friendlyMessage 35 | The connection timed out, please make sure you're connected to the internet and try again 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /Tests/Tests/RMErrorCodeDefinitionTest.m: -------------------------------------------------------------------------------- 1 | // 2 | // RMErrorCodeDefinitionTest.m 3 | // RideMarketplace 4 | // 5 | // Created by Johan Ride on 8/25/15. 6 | // Copyright (c) 2015 Ride. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "RMErrorCodeDefinition.h" 11 | 12 | @interface RMErrorCodeDefinitionTest : XCTestCase 13 | 14 | @end 15 | 16 | @implementation RMErrorCodeDefinitionTest 17 | 18 | - (BOOL)matches:(NSInteger)code { 19 | if(code <= 200) { 20 | return NO; 21 | } 22 | return YES; 23 | } 24 | 25 | - (void)testDefaultInitializer { 26 | RMErrorCodeDefinition *definition = [[RMErrorCodeDefinition alloc] initWithBoundary:self friendlyMessage:@"oops!" transient:YES]; 27 | XCTAssertEqualObjects(definition.friendlyMessage, @"oops!"); 28 | XCTAssertTrue(definition.transient); 29 | XCTAssertEqualObjects(definition.boundary, self, @"boundary should have been the same passed in initializer"); 30 | } 31 | 32 | - (void)testDefaultWithAttributes { 33 | NSDictionary *attributes = @{ 34 | @"friendlyMessage": @"oops!", 35 | @"transient": @(YES) 36 | }; 37 | RMErrorCodeDefinition *definition = [[RMErrorCodeDefinition alloc] initWithBoundary:self andAttributes:attributes]; 38 | XCTAssertEqualObjects(definition.friendlyMessage, @"oops!"); 39 | XCTAssertTrue(definition.transient); 40 | XCTAssertEqualObjects(definition.boundary, self, @"boundary should have been the same passed in initializer"); 41 | } 42 | 43 | - (void)testDescribeWithoutFriendlyMessage { 44 | NSDictionary *attributes = @{ 45 | @"transient": @(YES) 46 | }; 47 | RMErrorCodeDefinition *definition = [[RMErrorCodeDefinition alloc] initWithBoundary:self andAttributes:attributes]; 48 | RMErrorDescription *errorDescription = [definition describe:300 withDefaultMessage:@"original error message"]; 49 | XCTAssertEqualObjects(errorDescription.friendlyMessage, @"original error message", @"should have described with the original error message since no friendlyMessage was provided"); 50 | } 51 | 52 | - (void)testDescribeWithFriendlyMessage { 53 | NSDictionary *attributes = @{ 54 | @"friendlyMessage": @"Oops, sorry", 55 | @"transient": @(YES) 56 | }; 57 | RMErrorCodeDefinition *definition = [[RMErrorCodeDefinition alloc] initWithBoundary:self andAttributes:attributes]; 58 | RMErrorDescription *errorDescription = [definition describe:300 withDefaultMessage:@"original error message"]; 59 | XCTAssertEqualObjects(errorDescription.friendlyMessage, @"Oops, sorry", @"should have described with the friendly message since it was included in the error definition"); 60 | } 61 | 62 | @end 63 | -------------------------------------------------------------------------------- /Tests/Tests/RMErrorCodeRangeBoundaryTest.m: -------------------------------------------------------------------------------- 1 | // 2 | // RMErrorCodeRangeBoundaryTest.m 3 | // RideMarketplace 4 | // 5 | // Created by Johan Ride on 8/25/15. 6 | // Copyright (c) 2015 Ride. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "RMErrorCodeRangeBoundary.h" 11 | 12 | @interface RMErrorCodeRangeBoundaryTest : XCTestCase 13 | 14 | @end 15 | 16 | @implementation RMErrorCodeRangeBoundaryTest 17 | 18 | - (void)testDefaultInitializer { 19 | RMErrorCodeRangeBoundary *boundary = [[RMErrorCodeRangeBoundary alloc] init]; 20 | XCTAssertEqual(boundary.lowerLimit, RMErrorCodeRangeBoundaryDefaultLimit); 21 | XCTAssertEqual(boundary.upperLimit, RMErrorCodeRangeBoundaryDefaultLimit); 22 | } 23 | 24 | - (void)testDesignatedInitializer { 25 | RMErrorCodeRangeBoundary *boundary = [[RMErrorCodeRangeBoundary alloc] initWithLower:500 andUpper:599]; 26 | XCTAssertEqual(boundary.lowerLimit, 500); 27 | XCTAssertEqual(boundary.upperLimit, 599); 28 | } 29 | 30 | - (void)testEmptyPattern { 31 | RMErrorCodeRangeBoundary *boundary = [RMErrorCodeRangeBoundary boundaryWithPattern:@""]; 32 | XCTAssertEqual(boundary.lowerLimit, RMErrorCodeRangeBoundaryDefaultLimit); 33 | XCTAssertEqual(boundary.upperLimit, RMErrorCodeRangeBoundaryDefaultLimit); 34 | } 35 | 36 | - (void)testInvalidPattern { 37 | RMErrorCodeRangeBoundary *boundary = [RMErrorCodeRangeBoundary boundaryWithPattern:@".."]; 38 | XCTAssertEqual(boundary.lowerLimit, RMErrorCodeRangeBoundaryDefaultLimit); 39 | XCTAssertEqual(boundary.upperLimit, RMErrorCodeRangeBoundaryDefaultLimit); 40 | } 41 | 42 | - (void)testImplicitPattern { 43 | RMErrorCodeRangeBoundary *boundary = [RMErrorCodeRangeBoundary boundaryWithPattern:@"404"]; 44 | XCTAssertNotNil(boundary); 45 | 46 | XCTAssertEqual(boundary.lowerLimit, 404); 47 | XCTAssertEqual(boundary.upperLimit, 404); 48 | } 49 | 50 | - (void)testExplicitPattern { 51 | RMErrorCodeRangeBoundary *boundary = [RMErrorCodeRangeBoundary boundaryWithPattern:@"403..404"]; 52 | XCTAssertNotNil(boundary); 53 | 54 | XCTAssertEqual(boundary.lowerLimit, 403); 55 | XCTAssertEqual(boundary.upperLimit, 404); 56 | } 57 | 58 | - (void)testLowerInclusiveMatching { 59 | RMErrorCodeRangeBoundary *boundary = [[RMErrorCodeRangeBoundary alloc] initWithLower:200 andUpper:200]; 60 | XCTAssertTrue([boundary matches:200]); 61 | XCTAssertFalse([boundary matches:199]); 62 | } 63 | 64 | - (void)testUpperInclusiveMatching { 65 | RMErrorCodeRangeBoundary *boundary = [[RMErrorCodeRangeBoundary alloc] initWithLower:200 andUpper:299]; 66 | XCTAssertTrue([boundary matches:200]); 67 | XCTAssertTrue([boundary matches:299]); 68 | XCTAssertFalse([boundary matches:300]); 69 | } 70 | 71 | - (void)testWildcard { 72 | RMErrorCodeRangeBoundary *boundary = [RMErrorCodeRangeBoundary wildcard]; 73 | XCTAssertTrue([boundary matches:NSIntegerMin]); 74 | XCTAssertTrue([boundary matches:NSIntegerMax]); 75 | } 76 | 77 | @end 78 | -------------------------------------------------------------------------------- /Tests/Tests/RMErrorCodesTest.m: -------------------------------------------------------------------------------- 1 | // 2 | // RMErrorCodesTest.m 3 | // RideMarketplace 4 | // 5 | // Created by Johan Ride on 8/25/15. 6 | // Copyright (c) 2015 Ride. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import 12 | 13 | @interface RMErrorCodesTest : XCTestCase { 14 | NSDictionary *_content; 15 | } 16 | 17 | @end 18 | 19 | @implementation RMErrorCodesTest 20 | 21 | - (void)setUp { 22 | [super setUp]; 23 | _content = @{ 24 | @"500-599": @{ 25 | @"friendlyMessage": @"server down, try again later", 26 | @"transient": @(YES) 27 | } 28 | }; 29 | } 30 | 31 | - (void)testAddFromContent { 32 | RMErrorCodes *codes = [[RMErrorCodes alloc] init]; 33 | [codes addFromContent:_content]; 34 | XCTAssertEqual(codes.definitions.count, 1); 35 | 36 | RMErrorCodeDefinition* definition = codes.definitions.firstObject; 37 | XCTAssertEqualObjects([definition class], [RMErrorCodeDefinition class]); 38 | XCTAssertEqualObjects(definition.boundary.class, [RMErrorCodeRangeBoundary class]); 39 | XCTAssertTrue(definition.transient); 40 | XCTAssertEqual(definition.friendlyMessage, @"server down, try again later"); 41 | } 42 | 43 | @end 44 | -------------------------------------------------------------------------------- /Tests/Tests/RMErrorDomainDefinitionTest.m: -------------------------------------------------------------------------------- 1 | // 2 | // RMErrorDomainDefinitionTest.m 3 | // RideMarketplace 4 | // 5 | // Created by Johan Ride on 8/25/15. 6 | // Copyright (c) 2015 Ride. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "RMErrorDomainDefinition.h" 11 | 12 | @interface RMErrorDomainDefinitionTest : XCTestCase 13 | 14 | @end 15 | 16 | @implementation RMErrorDomainDefinitionTest 17 | 18 | - (void)testDesignatedInitializer { 19 | RMErrorDomainDefinition *definition = [[RMErrorDomainDefinition alloc]initWithName:@"NSURLErrorDomain"]; 20 | XCTAssertEqualObjects(definition.name, @"NSURLErrorDomain"); 21 | XCTAssertNotNil(definition.codes); 22 | } 23 | 24 | - (void)testAttributesInitializer { 25 | NSDictionary *attributes = @{ 26 | @"codes": @{ 27 | @"500": @{} 28 | } 29 | }; 30 | RMErrorDomainDefinition *definition = [[RMErrorDomainDefinition alloc]initWithName:@"NSURLErrorDomain"]; 31 | [definition loadFromContent:attributes]; 32 | XCTAssertEqualObjects(definition.name, @"NSURLErrorDomain"); 33 | XCTAssertNotNil(definition.codes); 34 | XCTAssertEqual(definition.codes.definitions.count, 1); 35 | } 36 | 37 | - (void)testMatchNoDefaultCode { 38 | NSDictionary *content = @{ 39 | @"codes": @{ 40 | @"500": @{} 41 | } 42 | }; 43 | RMErrorDomainDefinition *definition = [[RMErrorDomainDefinition alloc]initWithName:@"NSURLErrorDomain"]; 44 | [definition loadFromContent:content]; 45 | RMErrorDescription *description =[definition describe:[NSError errorWithDomain:@"NSURLErrorDomain" code:20 userInfo:nil]]; 46 | XCTAssertNil(description, @"should have been nil since there is no default code at this error domain level"); 47 | } 48 | 49 | - (void)testMatchWithDefaultCode { 50 | NSDictionary *content = @{ 51 | @"(default)": @{ 52 | @"transient": @(YES), 53 | }, 54 | @"codes": @{ 55 | @"500": @{} 56 | } 57 | }; 58 | RMErrorDomainDefinition *definition = [[RMErrorDomainDefinition alloc]initWithName:@"NSURLErrorDomain"]; 59 | [definition loadFromContent:content]; 60 | RMErrorDescription *description =[definition describe:[NSError errorWithDomain:@"NSURLErrorDomain" code:20 userInfo:@{ 61 | NSLocalizedDescriptionKey: @"original error message", 62 | }]]; 63 | XCTAssertNotNil(description, @"should have been an error description instance since there is a default code at this error domain level"); 64 | XCTAssertTrue(description.transient); 65 | XCTAssertEqualObjects(description.friendlyMessage, @"original error message", @"should have included the original NSError message since friendlyMessage was not specified in default code for the domain"); 66 | } 67 | 68 | - (void)testMatchWithDefaultCodeAndFriendlyMessageOverride { 69 | NSDictionary *content = @{ 70 | @"(default)": @{ 71 | @"transient": @(YES), 72 | @"friendlyMessage": @"Default error message for all codes in this domain", 73 | }, 74 | @"codes": @{ 75 | @"500": @{} 76 | } 77 | }; 78 | RMErrorDomainDefinition *definition = [[RMErrorDomainDefinition alloc]initWithName:@"NSURLErrorDomain"]; 79 | [definition loadFromContent:content]; 80 | RMErrorDescription *description =[definition describe:[NSError errorWithDomain:@"NSURLErrorDomain" code:20 userInfo:@{ 81 | NSLocalizedDescriptionKey: @"original error message", 82 | }]]; 83 | XCTAssertNotNil(description, @"should have been an error description instance since there is a default code at this error domain level"); 84 | XCTAssertTrue(description.transient); 85 | XCTAssertEqualObjects(description.friendlyMessage, @"Default error message for all codes in this domain", @"should have included the overriden default message for the domain"); 86 | } 87 | @end 88 | -------------------------------------------------------------------------------- /Tests/Tests/RMErrorDomainsTest.m: -------------------------------------------------------------------------------- 1 | // 2 | // RMErrorDomainsTest.m 3 | // RideMarketplace 4 | // 5 | // Created by Johan Ride on 8/25/15. 6 | // Copyright (c) 2015 Ride. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface RMErrorDomainsTest : XCTestCase { 13 | NSDictionary *_content; 14 | } 15 | 16 | @end 17 | 18 | @implementation RMErrorDomainsTest 19 | 20 | - (void)setUp { 21 | [super setUp]; 22 | _content = @{ 23 | @"NSURLErrorDomain": @{ 24 | @"codes": @{ 25 | @"500-599": @{} 26 | } 27 | } 28 | }; 29 | } 30 | 31 | - (void)testAddFromContent { 32 | RMErrorDomains *domains = [[RMErrorDomains alloc] init]; 33 | [domains addFromContent:_content]; 34 | XCTAssertEqual(domains.definitions.count, 1); 35 | 36 | RMErrorDomainDefinition* definition = domains.definitions.firstObject; 37 | XCTAssertEqualObjects([definition class], [RMErrorDomainDefinition class]); 38 | XCTAssertEqualObjects(definition.name, @"NSURLErrorDomain"); 39 | XCTAssertEqual(definition.codes.definitions.count, 1); 40 | } 41 | 42 | @end 43 | -------------------------------------------------------------------------------- /Tests/Tests/RMErrorsTest.m: -------------------------------------------------------------------------------- 1 | // 2 | // RMErrorsTest.m 3 | // RideMarketplace 4 | // 5 | // Created by Johan Ride on 8/25/15. 6 | // Copyright (c) 2015 Ride. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "RMErrors.h" 11 | #import "RMErrorCodeRangeBoundary.h" 12 | 13 | @interface RMErrorsTest : XCTestCase 14 | 15 | @end 16 | 17 | @implementation RMErrorsTest 18 | 19 | - (void)testLoadContent { 20 | RMErrors *errors = [[RMErrors alloc] init]; 21 | [errors load:@{ 22 | @"domains": @{ 23 | @"NSURLErrorDomain": @{} 24 | } 25 | }]; 26 | XCTAssertEqual(errors.domains.definitions.count, 1); 27 | } 28 | 29 | - (void)testLoadPropertyList { 30 | RMErrors *errors = [[RMErrors alloc] init]; 31 | [errors loadPropertyList:RMErrorsDefaultFileName bundle:[NSBundle bundleForClass:self.class]]; 32 | XCTAssertEqual(errors.domains.definitions.count, 1); 33 | } 34 | 35 | - (void)testDescribe { 36 | RMErrors *errors = [[RMErrors alloc] init]; 37 | RMErrorDomainDefinition *errorDomain = [[RMErrorDomainDefinition alloc] initWithName:@"com.foo.bar.oopsie"]; 38 | [errorDomain.codes add:[[RMErrorCodeDefinition alloc] initWithBoundary:[RMErrorCodeRangeBoundary boundaryWithPattern:@"500..503"] friendlyMessage:@"server error" transient:YES]]; 39 | 40 | [errors.domains add:errorDomain]; 41 | 42 | [errorDomain.codes add:[[RMErrorCodeDefinition alloc] initWithBoundary:[RMErrorCodeRangeBoundary boundaryWithPattern:@"504..510"] friendlyMessage:@"server is gone forever" transient:NO]]; 43 | 44 | [errors.domains add:errorDomain]; 45 | 46 | RMErrorDescription *description = [errors describe:[NSError errorWithDomain:@"com.foo.bar.oopsie" code:500 userInfo:nil]]; 47 | XCTAssertNotNil(description); 48 | XCTAssertEqualObjects(description.friendlyMessage, @"server error"); 49 | XCTAssertTrue(description.transient); 50 | 51 | 52 | description = [errors describe:[NSError errorWithDomain:@"com.foo.bar.oopsie" code:507 userInfo:nil]]; 53 | XCTAssertNotNil(description); 54 | XCTAssertEqualObjects(description.friendlyMessage, @"server is gone forever"); 55 | XCTAssertFalse(description.transient); 56 | } 57 | 58 | @end 59 | -------------------------------------------------------------------------------- /Tests/Tests/RMErrorsTransformationTest.m: -------------------------------------------------------------------------------- 1 | // 2 | // RMErrorsTransformationTest.m 3 | // RideMarketplace 4 | // 5 | // Created by Johan Ride on 8/25/15. 6 | // Copyright (c) 2015 Ride. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface RMTestHelloErrorTransformation : NSObject 13 | 14 | @end 15 | 16 | @implementation RMTestHelloErrorTransformation 17 | 18 | - (NSError *)transform:(nonnull NSError *)original { 19 | NSString *msg = original.userInfo[@"msg"]; 20 | if([@"hello" isEqualToString:msg]) { 21 | NSMutableDictionary *userInfo = [NSMutableDictionary dictionaryWithDictionary:original.userInfo]; 22 | userInfo[@"msg"] = [original.userInfo[@"msg"] stringByAppendingString:@" world"]; 23 | return [NSError errorWithDomain:original.domain code:original.code userInfo:userInfo]; 24 | } 25 | return original; 26 | } 27 | 28 | @end 29 | 30 | @interface RMTestWorldErrorTransformation : NSObject 31 | 32 | @end 33 | 34 | @implementation RMTestWorldErrorTransformation 35 | 36 | - (NSError *)transform:(NSError *)original { 37 | if(original.userInfo[@"msg"]) { 38 | NSMutableDictionary *userInfo = [NSMutableDictionary dictionaryWithDictionary:original.userInfo]; 39 | userInfo[NSLocalizedDescriptionKey] = userInfo[@"msg"]; 40 | return [NSError errorWithDomain:original.domain code:original.code userInfo:userInfo]; 41 | } 42 | return original; 43 | } 44 | 45 | @end 46 | 47 | @interface RMErrorsTransformationTest : XCTestCase 48 | 49 | @end 50 | 51 | @implementation RMErrorsTransformationTest 52 | 53 | - (void)testTransformationOriginal { 54 | RMErrorTransformations *transformations = [[RMErrorTransformations alloc] init]; 55 | [transformations add:[[RMTestHelloErrorTransformation alloc] init]]; 56 | [transformations add:[[RMTestWorldErrorTransformation alloc] init]]; 57 | 58 | NSError *original = [NSError errorWithDomain:@"com.foo.test" code:1 userInfo:@{NSLocalizedDescriptionKey: @"this is not a greeting, should be kept original"}]; 59 | NSError *transformed = [transformations transform:original]; 60 | XCTAssertEqualObjects(transformed.userInfo[NSLocalizedDescriptionKey], @"this is not a greeting, should be kept original"); 61 | } 62 | 63 | - (void)testTransformationChain { 64 | RMErrorTransformations *transformations = [[RMErrorTransformations alloc] init]; 65 | [transformations add:[[RMTestHelloErrorTransformation alloc] init]]; 66 | [transformations add:[[RMTestWorldErrorTransformation alloc] init]]; 67 | 68 | NSError *original = [NSError errorWithDomain:@"com.foo.test" code:1 userInfo:@{@"msg": @"hello"}]; 69 | NSError *transformed = [transformations transform:original]; 70 | XCTAssertEqualObjects(transformed.userInfo[NSLocalizedDescriptionKey], @"hello world"); 71 | } 72 | 73 | @end 74 | --------------------------------------------------------------------------------