mirror of
https://github.com/zhigang1992/RestKit.git
synced 2026-04-23 20:31:13 +08:00
Rework path based response descriptor matching and expand test coverage. Eliminate path normalization. fixes #987
This commit is contained in:
@@ -36,11 +36,10 @@
|
||||
Creates and returns a new `RKResponseDescriptor` object.
|
||||
|
||||
@param mapping The mapping for the response descriptor.
|
||||
@param pathPattern A path pattern that matches against URLs for which the mapping should be used. The path pattern will be normalized on input via `RKPathNormalize`.
|
||||
@param pathPattern A path pattern that matches against URLs for which the mapping should be used.
|
||||
@param keyPath A key path specifying the subset of the parsed response for which the mapping is to be used.
|
||||
@param statusCodes A set of HTTP status codes for which the mapping is to be used.
|
||||
@return A new `RKResponseDescriptor` object.
|
||||
@see `RKPathNormalize`
|
||||
*/
|
||||
+ (RKResponseDescriptor *)responseDescriptorWithMapping:(RKMapping *)mapping
|
||||
pathPattern:(NSString *)pathPattern
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
#import "RKPathMatcher.h"
|
||||
#import "RKResponseDescriptor.h"
|
||||
#import "RKPathUtilities.h"
|
||||
#import "RKHTTPUtilities.h"
|
||||
|
||||
// Cloned from AFStringFromIndexSet -- method should be non-static for reuse
|
||||
static NSString *RKStringFromIndexSet(NSIndexSet *indexSet) {
|
||||
@@ -53,23 +53,6 @@ static NSString *RKStringFromIndexSet(NSIndexSet *indexSet) {
|
||||
return string;
|
||||
}
|
||||
|
||||
// Assumes that URL is relative to baseURL
|
||||
static NSString *RKPathAndQueryStringFromURLRelativeToURL(NSURL *URL, NSURL *baseURL)
|
||||
{
|
||||
if (baseURL) {
|
||||
NSString *pathAndQuery = [[URL absoluteString] substringFromIndex:[[baseURL absoluteString] length]];
|
||||
return ([pathAndQuery characterAtIndex:0] != '/') ? [NSString stringWithFormat:@"/%@", pathAndQuery] : pathAndQuery;
|
||||
} else {
|
||||
NSString *query = [URL query];
|
||||
return (query && [query length]) ? [NSString stringWithFormat:@"%@?%@", [URL path], query] : [URL path];
|
||||
}
|
||||
}
|
||||
|
||||
static BOOL RKURLIsRelativeToURL(NSURL *sourceURL, NSURL *baseURL)
|
||||
{
|
||||
return [[sourceURL absoluteString] hasPrefix:[baseURL absoluteString]];
|
||||
}
|
||||
|
||||
@interface RKResponseDescriptor ()
|
||||
@property (nonatomic, strong, readwrite) RKMapping *mapping;
|
||||
@property (nonatomic, copy, readwrite) NSString *pathPattern;
|
||||
@@ -87,7 +70,7 @@ static BOOL RKURLIsRelativeToURL(NSURL *sourceURL, NSURL *baseURL)
|
||||
NSParameterAssert(mapping);
|
||||
RKResponseDescriptor *mappingDescriptor = [self new];
|
||||
mappingDescriptor.mapping = mapping;
|
||||
mappingDescriptor.pathPattern = pathPattern ? RKPathNormalize(pathPattern) : nil;
|
||||
mappingDescriptor.pathPattern = pathPattern;
|
||||
mappingDescriptor.keyPath = keyPath;
|
||||
mappingDescriptor.statusCodes = statusCodes;
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@
|
||||
*/
|
||||
- (id)initWithResponse:(NSHTTPURLResponse *)response
|
||||
data:(NSData *)data
|
||||
responseDescriptors:(NSArray *)responseDescriptors;
|
||||
responseDescriptors:(NSArray *)responseDescriptors;
|
||||
|
||||
///------------------------------
|
||||
/// @name Accessing Response Data
|
||||
|
||||
@@ -95,3 +95,25 @@ NSDate *RKDateFromHTTPDateString(NSString *);
|
||||
@return The expiration date as specified by the cache headers or `nil` if none was found.
|
||||
*/
|
||||
NSDate *RKHTTPCacheExpirationDateFromHeadersWithStatusCode(NSDictionary *headers, NSInteger statusCode);
|
||||
|
||||
/**
|
||||
Returns a Boolean value that indicates if a given URL is relative to another URL.
|
||||
|
||||
This method does not rely on the `baseURL` method of `NSURL` as it only indicates a relationship between the initialization of two URL objects. The relativity of the given URL is assessed by evaluating a prefix match of the URL's absolute string value with the absolute string value of the potential base URL.
|
||||
|
||||
@param URL The URL to assess the relativity of.
|
||||
@param baseURL The base URL to determine if the given URL is relative to.
|
||||
@return `YES` is URL is relative to the base URL, else `NO`.
|
||||
*/
|
||||
BOOL RKURLIsRelativeToURL(NSURL *URL, NSURL *baseURL);
|
||||
|
||||
/**
|
||||
Returns a string object containing the relative path and query string of a given URL object and a base URL that the given URL is relative to.
|
||||
|
||||
If the given URL is found not to be relative to the baseURL, `nil` is returned.
|
||||
|
||||
@param URL The URL to retrieve the relative path and query string of.
|
||||
@param baseURL The base URL to be omitted from the returned path and query string.
|
||||
@return A string containing the relative path and query parameters.
|
||||
*/
|
||||
NSString *RKPathAndQueryStringFromURLRelativeToURL(NSURL *URL, NSURL *baseURL);
|
||||
|
||||
@@ -404,3 +404,20 @@ NSDate * RKHTTPCacheExpirationDateFromHeadersWithStatusCode(NSDictionary *header
|
||||
// If nothing permitted to define the cache expiration delay nor to restrict its cacheability, use a default cache expiration delay
|
||||
return [[NSDate alloc] initWithTimeInterval:kRKURLCacheDefault sinceDate:now];
|
||||
}
|
||||
|
||||
BOOL RKURLIsRelativeToURL(NSURL *URL, NSURL *baseURL)
|
||||
{
|
||||
return [[URL absoluteString] hasPrefix:[baseURL absoluteString]];
|
||||
}
|
||||
|
||||
NSString *RKPathAndQueryStringFromURLRelativeToURL(NSURL *URL, NSURL *baseURL)
|
||||
{
|
||||
if (baseURL) {
|
||||
if (! RKURLIsRelativeToURL(URL, baseURL)) return nil;
|
||||
return [[URL absoluteString] substringFromIndex:[[baseURL absoluteString] length]];
|
||||
} else {
|
||||
// NOTE: [URL relativeString] would return the same value as `absoluteString` if URL is not relative to a baseURL
|
||||
NSString *query = [URL query];
|
||||
return (query && [query length]) ? [NSString stringWithFormat:@"%@?%@", [URL path], query] : [URL path];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
#import "SOCKit.h"
|
||||
#import "RKLog.h"
|
||||
#import "RKDictionaryUtilities.h"
|
||||
#import "RKPathUtilities.h"
|
||||
|
||||
static NSString *RKEncodeURLString(NSString *unencodedString);
|
||||
extern NSDictionary *RKQueryParametersFromStringWithEncoding(NSString *string, NSStringEncoding stringEncoding);
|
||||
@@ -77,12 +76,6 @@ static NSString *RKEncodeURLString(NSString *unencodedString)
|
||||
return matcher;
|
||||
}
|
||||
|
||||
// Normalize our root path for matching cleanly with SOCKit
|
||||
- (void)setRootPath:(NSString *)rootPath
|
||||
{
|
||||
_rootPath = RKPathNormalize(rootPath);
|
||||
}
|
||||
|
||||
- (BOOL)matches
|
||||
{
|
||||
NSAssert((self.socPattern != NULL && self.rootPath != NULL), @"Matcher is insufficiently configured. Before attempting pattern matching, you must provide a path string and a pattern to match it against.");
|
||||
@@ -145,10 +138,11 @@ static NSString *RKEncodeURLString(NSString *unencodedString)
|
||||
NSAssert(self.socPattern != NULL, @"Matcher has no established pattern. Instantiate it using pathMatcherWithPattern: before calling pathFromObject:");
|
||||
NSAssert(object != NULL, @"Object provided is invalid; cannot create a path from a NULL object");
|
||||
NSString *(^encoderBlock)(NSString *interpolatedString) = nil;
|
||||
if (addEscapes)
|
||||
if (addEscapes) {
|
||||
encoderBlock = ^NSString *(NSString *interpolatedString) {
|
||||
return RKEncodeURLString(interpolatedString);
|
||||
};
|
||||
}
|
||||
NSString *path = [self.socPattern stringFromObject:object withBlock:encoderBlock];
|
||||
return path;
|
||||
}
|
||||
|
||||
@@ -55,11 +55,3 @@ NSString *RKPathFromPatternWithObject(NSString *pathPattern, id object);
|
||||
@return The expected MIME Type of the resource identified by the path or nil if unknown.
|
||||
*/
|
||||
NSString *RKMIMETypeFromPathExtension(NSString *path);
|
||||
|
||||
/**
|
||||
Normalizes a given string into a path by ensuring that it includes a leading slash and does not include a trailing slash.
|
||||
|
||||
@param path The path to be normalized.
|
||||
@return The given path, normalized with a leading slash and without a trailing sla
|
||||
*/
|
||||
NSString *RKPathNormalize(NSString *path);
|
||||
|
||||
@@ -119,12 +119,3 @@ NSString *RKMIMETypeFromPathExtension(NSString *path)
|
||||
// Consult our internal dictionary of mappings if not found
|
||||
return [RKDictionaryOfFileExtensionsToMIMETypes() valueForKey:pathExtension];
|
||||
}
|
||||
|
||||
NSString *RKPathNormalize(NSString *path)
|
||||
{
|
||||
path = [path stringByReplacingOccurrencesOfString:@"//" withString:@"/"];
|
||||
NSUInteger length = [path length];
|
||||
if ([path characterAtIndex:length - 1] == '/') path = [path substringToIndex:length - 1];
|
||||
if ([path characterAtIndex:0] != '/') path = [NSString stringWithFormat:@"/%@", path];
|
||||
return path;
|
||||
}
|
||||
|
||||
@@ -12,16 +12,6 @@
|
||||
|
||||
SPEC_BEGIN(RKResponseDescriptorSpec)
|
||||
|
||||
describe(@"init", ^{
|
||||
context(@"when given a relative path pattern", ^{
|
||||
it(@"normalizes the path pattern", ^{
|
||||
RKObjectMapping *mapping = [RKObjectMapping mappingForClass:[RKTestUser class]];
|
||||
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:mapping pathPattern:@"monkeys" keyPath:nil statusCodes:[NSIndexSet indexSetWithIndex:200]];
|
||||
[[responseDescriptor.pathPattern should] equal:@"/monkeys"];
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe(@"matchesURL:", ^{
|
||||
__block NSURL *baseURL;
|
||||
__block RKResponseDescriptor *responseDescriptor;
|
||||
@@ -139,10 +129,10 @@ describe(@"matchesURL:", ^{
|
||||
baseURL = [NSURL URLWithString:@"http://0.0.0.0:5000"];
|
||||
});
|
||||
|
||||
context(@"and the path pattern is '/api/v1/organizations'", ^{
|
||||
context(@"and the path pattern is '/api/v1/organizations/'", ^{
|
||||
beforeEach(^{
|
||||
RKObjectMapping *mapping = [RKObjectMapping mappingForClass:[RKTestUser class]];
|
||||
responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:mapping pathPattern:@"/api/v1/organizations" keyPath:nil statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
|
||||
responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:mapping pathPattern:@"/api/v1/organizations/" keyPath:nil statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
|
||||
responseDescriptor.baseURL = baseURL;
|
||||
});
|
||||
|
||||
@@ -199,7 +189,7 @@ describe(@"matchesURL:", ^{
|
||||
context(@"and the path pattern is '/monkeys/:monkeyID\\.json'", ^{
|
||||
beforeEach(^{
|
||||
RKObjectMapping *mapping = [RKObjectMapping mappingForClass:[RKTestUser class]];
|
||||
responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:mapping pathPattern:@"/monkeys/:monkeyID\\.json" keyPath:nil statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
|
||||
responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:mapping pathPattern:@"monkeys/:monkeyID\\.json" keyPath:nil statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
|
||||
responseDescriptor.baseURL = baseURL;
|
||||
});
|
||||
|
||||
@@ -244,11 +234,11 @@ describe(@"matchesResponse:", ^{
|
||||
__block RKResponseDescriptor *responseDescriptor;
|
||||
|
||||
context(@"when the baseURL is 'http://0.0.0.0:5000", ^{
|
||||
context(@"and the path pattern is '/api/v1/organizations'", ^{
|
||||
context(@"and the path pattern is '/api/v1/organizations/'", ^{
|
||||
context(@"and given the URL 'http://0.0.0.0:5000/api/v1/organizations/?client_search=t'", ^{
|
||||
beforeEach(^{
|
||||
RKObjectMapping *mapping = [RKObjectMapping mappingForClass:[RKTestUser class]];
|
||||
responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:mapping pathPattern:@"/api/v1/organizations" keyPath:nil statusCodes:[NSIndexSet indexSetWithIndex:200]];
|
||||
responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:mapping pathPattern:@"/api/v1/organizations/" keyPath:nil statusCodes:[NSIndexSet indexSetWithIndex:200]];
|
||||
responseDescriptor.baseURL = [NSURL URLWithString:@"http://0.0.0.0:5000"];
|
||||
});
|
||||
|
||||
@@ -270,10 +260,10 @@ describe(@"matchesResponse:", ^{
|
||||
responseDescriptor.baseURL = [NSURL URLWithString:@"http://domain.com/domain/api/v1/"];
|
||||
});
|
||||
|
||||
it(@"returns YES", ^{
|
||||
it(@"returns NO", ^{
|
||||
NSURL *URL = [NSURL URLWithString:@"http://domain.com/domain/api/v1/recommendation/"];
|
||||
NSHTTPURLResponse *response = [[NSHTTPURLResponse alloc] initWithURL:URL statusCode:200 HTTPVersion:@"1.1" headerFields:nil];
|
||||
[[@([responseDescriptor matchesResponse:response]) should] beYes];
|
||||
[[@([responseDescriptor matchesResponse:response]) should] beNo];
|
||||
});
|
||||
});
|
||||
|
||||
@@ -284,10 +274,10 @@ describe(@"matchesResponse:", ^{
|
||||
responseDescriptor.baseURL = [NSURL URLWithString:@"http://domain.com/domain/api/v1/"];
|
||||
});
|
||||
|
||||
it(@"returns YES", ^{
|
||||
it(@"returns NO", ^{
|
||||
NSURL *URL = [NSURL URLWithString:@"http://domain.com/domain/api/v1/recommendation?action=search&type=whatever"];
|
||||
NSHTTPURLResponse *response = [[NSHTTPURLResponse alloc] initWithURL:URL statusCode:200 HTTPVersion:@"1.1" headerFields:nil];
|
||||
[[@([responseDescriptor matchesResponse:response]) should] beYes];
|
||||
[[@([responseDescriptor matchesResponse:response]) should] beNo];
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
#import "RKErrorMessage.h"
|
||||
#import "RKMappingErrors.h"
|
||||
|
||||
NSString *RKPathAndQueryStringFromURLRelativeToURL(NSURL *URL, NSURL *baseURL);
|
||||
|
||||
@interface RKObjectResponseMapperOperationTest : RKTestCase
|
||||
|
||||
@end
|
||||
@@ -106,4 +108,96 @@
|
||||
expect([mapper.error localizedDescription]).to.equal(@"Loaded an unprocessable client error response (422)");
|
||||
}
|
||||
|
||||
#pragma mark - Response Descriptor Matching
|
||||
|
||||
- (void)testThatResponseMapperMatchesBaseURLWithoutPathAppropriately
|
||||
{
|
||||
NSURL *baseURL = [NSURL URLWithString:@"http://restkit.org"];
|
||||
NSURL *responseURL = [NSURL URLWithString:@"http://restkit.org/api/v1/organizations/"];
|
||||
NSHTTPURLResponse *response = [[NSHTTPURLResponse alloc] initWithURL:responseURL statusCode:200 HTTPVersion:@"1.1" headerFields:@{@"Content-Type": @"application/json"}];
|
||||
NSData *data = [@"{}" dataUsingEncoding:NSUTF8StringEncoding];
|
||||
|
||||
RKObjectMapping *mapping = [RKObjectMapping mappingForClass:[NSMutableDictionary class]];
|
||||
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:mapping pathPattern:@"/api/v1/organizations/" keyPath:nil statusCodes:[NSIndexSet indexSetWithIndex:200]];
|
||||
responseDescriptor.baseURL = baseURL;
|
||||
RKObjectResponseMapperOperation *mapper = [[RKObjectResponseMapperOperation alloc] initWithResponse:response data:data responseDescriptors:@[responseDescriptor]];
|
||||
[mapper start];
|
||||
expect(mapper.error).to.beNil();
|
||||
|
||||
NSDictionary *expectedMappingsDictionary = @{ [NSNull null] : mapping };
|
||||
expect(mapper.responseMappingsDictionary).to.equal(expectedMappingsDictionary);
|
||||
}
|
||||
|
||||
- (void)testThatResponseMapperMatchesBaseURLWithJustASingleSlashAsThePathAppropriately
|
||||
{
|
||||
NSURL *baseURL = [NSURL URLWithString:@"http://restkit.org/"];
|
||||
NSURL *responseURL = [NSURL URLWithString:@"http://restkit.org/api/v1/organizations/"];
|
||||
NSHTTPURLResponse *response = [[NSHTTPURLResponse alloc] initWithURL:responseURL statusCode:200 HTTPVersion:@"1.1" headerFields:@{@"Content-Type": @"application/json"}];
|
||||
NSData *data = [@"{}" dataUsingEncoding:NSUTF8StringEncoding];
|
||||
|
||||
RKObjectMapping *mapping = [RKObjectMapping mappingForClass:[NSMutableDictionary class]];
|
||||
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:mapping pathPattern:@"api/v1/organizations/" keyPath:nil statusCodes:[NSIndexSet indexSetWithIndex:200]];
|
||||
responseDescriptor.baseURL = baseURL;
|
||||
RKObjectResponseMapperOperation *mapper = [[RKObjectResponseMapperOperation alloc] initWithResponse:response data:data responseDescriptors:@[responseDescriptor]];
|
||||
[mapper start];
|
||||
expect(mapper.error).to.beNil();
|
||||
|
||||
NSDictionary *expectedMappingsDictionary = @{ [NSNull null] : mapping };
|
||||
expect(mapper.responseMappingsDictionary).to.equal(expectedMappingsDictionary);
|
||||
}
|
||||
|
||||
- (void)testThatResponseMapperMatchesBaseURLWithPathWithoutATrailingSlashAppropriately
|
||||
{
|
||||
NSURL *baseURL = [NSURL URLWithString:@"http://restkit.org/api/v1"];
|
||||
NSURL *responseURL = [NSURL URLWithString:@"http://restkit.org/api/v1/organizations/"];
|
||||
NSHTTPURLResponse *response = [[NSHTTPURLResponse alloc] initWithURL:responseURL statusCode:200 HTTPVersion:@"1.1" headerFields:@{@"Content-Type": @"application/json"}];
|
||||
NSData *data = [@"{}" dataUsingEncoding:NSUTF8StringEncoding];
|
||||
|
||||
RKObjectMapping *mapping = [RKObjectMapping mappingForClass:[NSMutableDictionary class]];
|
||||
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:mapping pathPattern:@"/organizations/" keyPath:nil statusCodes:[NSIndexSet indexSetWithIndex:200]];
|
||||
responseDescriptor.baseURL = baseURL;
|
||||
RKObjectResponseMapperOperation *mapper = [[RKObjectResponseMapperOperation alloc] initWithResponse:response data:data responseDescriptors:@[responseDescriptor]];
|
||||
[mapper start];
|
||||
expect(mapper.error).to.beNil();
|
||||
|
||||
NSDictionary *expectedMappingsDictionary = @{ [NSNull null] : mapping };
|
||||
expect(mapper.responseMappingsDictionary).to.equal(expectedMappingsDictionary);
|
||||
}
|
||||
|
||||
- (void)testThatResponseMapperMatchesBaseURLWithPathWithATrailingSlashAppropriately
|
||||
{
|
||||
NSURL *baseURL = [NSURL URLWithString:@"http://restkit.org/api/v1/"];
|
||||
NSURL *responseURL = [NSURL URLWithString:@"http://restkit.org/api/v1/organizations/"];
|
||||
NSHTTPURLResponse *response = [[NSHTTPURLResponse alloc] initWithURL:responseURL statusCode:200 HTTPVersion:@"1.1" headerFields:@{@"Content-Type": @"application/json"}];
|
||||
NSData *data = [@"{}" dataUsingEncoding:NSUTF8StringEncoding];
|
||||
|
||||
RKObjectMapping *mapping = [RKObjectMapping mappingForClass:[NSMutableDictionary class]];
|
||||
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:mapping pathPattern:@"organizations/" keyPath:nil statusCodes:[NSIndexSet indexSetWithIndex:200]];
|
||||
responseDescriptor.baseURL = baseURL;
|
||||
RKObjectResponseMapperOperation *mapper = [[RKObjectResponseMapperOperation alloc] initWithResponse:response data:data responseDescriptors:@[responseDescriptor]];
|
||||
[mapper start];
|
||||
expect(mapper.error).to.beNil();
|
||||
|
||||
NSDictionary *expectedMappingsDictionary = @{ [NSNull null] : mapping };
|
||||
expect(mapper.responseMappingsDictionary).to.equal(expectedMappingsDictionary);
|
||||
}
|
||||
|
||||
- (void)testThatResponseMapperMatchesBaseURLWithPathAndQueryParametersAppropriately
|
||||
{
|
||||
NSURL *baseURL = [NSURL URLWithString:@"http://restkit.org/api/v1/"];
|
||||
NSURL *responseURL = [NSURL URLWithString:@"http://restkit.org/api/v1/organizations/?client_search=s"];
|
||||
NSHTTPURLResponse *response = [[NSHTTPURLResponse alloc] initWithURL:responseURL statusCode:200 HTTPVersion:@"1.1" headerFields:@{@"Content-Type": @"application/json"}];
|
||||
NSData *data = [@"{}" dataUsingEncoding:NSUTF8StringEncoding];
|
||||
|
||||
RKObjectMapping *mapping = [RKObjectMapping mappingForClass:[NSMutableDictionary class]];
|
||||
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:mapping pathPattern:@"organizations/" keyPath:nil statusCodes:[NSIndexSet indexSetWithIndex:200]];
|
||||
responseDescriptor.baseURL = baseURL;
|
||||
RKObjectResponseMapperOperation *mapper = [[RKObjectResponseMapperOperation alloc] initWithResponse:response data:data responseDescriptors:@[responseDescriptor]];
|
||||
[mapper start];
|
||||
expect(mapper.error).to.beNil();
|
||||
|
||||
NSDictionary *expectedMappingsDictionary = @{ [NSNull null] : mapping };
|
||||
expect(mapper.responseMappingsDictionary).to.equal(expectedMappingsDictionary);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
108
Tests/Logic/Support/RKHTTPUtilitiesTest.m
Normal file
108
Tests/Logic/Support/RKHTTPUtilitiesTest.m
Normal file
@@ -0,0 +1,108 @@
|
||||
//
|
||||
// RKHTTPUtilitiesTest.m
|
||||
// RestKit
|
||||
//
|
||||
// Created by Blake Watters on 10/14/12.
|
||||
// Copyright (c) 2012 RestKit. All rights reserved.
|
||||
//
|
||||
|
||||
#import "RKTestEnvironment.h"
|
||||
#import "RKHTTPUtilities.h"
|
||||
|
||||
@interface RKHTTPUtilitiesTest : RKTestCase
|
||||
|
||||
@end
|
||||
|
||||
@implementation RKHTTPUtilitiesTest
|
||||
|
||||
#pragma mark - RKPathAndQueryStringFromURLRelativeToURL
|
||||
|
||||
- (void)testThatNilIsReturnedWhenTheGivenURLIsNotRelativeToTheBaseURL
|
||||
{
|
||||
NSURL *baseURL = [NSURL URLWithString:@"http://google.com/path"];
|
||||
NSURL *testURL = [NSURL URLWithString:@"http://restkit.org/path"];
|
||||
NSString *pathAndQueryString = RKPathAndQueryStringFromURLRelativeToURL(testURL, baseURL);
|
||||
expect(pathAndQueryString).to.beNil();
|
||||
}
|
||||
|
||||
- (void)testReturningThePathAndQueryParametersWithANilBaseURLForURLWithNoPath
|
||||
{
|
||||
NSURL *baseURL = nil;
|
||||
NSURL *testURL = [NSURL URLWithString:@"http://restkit.org"];
|
||||
NSString *pathAndQueryString = RKPathAndQueryStringFromURLRelativeToURL(testURL, baseURL);
|
||||
expect(pathAndQueryString).to.equal(@"");
|
||||
}
|
||||
|
||||
- (void)testReturningThePathAndQueryParametersWithANilBaseURLForURLWithASingleSlashAsThePath
|
||||
{
|
||||
NSURL *baseURL = nil;
|
||||
NSURL *testURL = [NSURL URLWithString:@"http://restkit.org/"];
|
||||
NSString *pathAndQueryString = RKPathAndQueryStringFromURLRelativeToURL(testURL, baseURL);
|
||||
expect(pathAndQueryString).to.equal(@"/");
|
||||
}
|
||||
|
||||
- (void)testReturningThePathAndQueryParametersWithANilBaseURLForURLWithAPath
|
||||
{
|
||||
NSURL *baseURL = nil;
|
||||
NSURL *testURL = [NSURL URLWithString:@"http://restkit.org/the/path"];
|
||||
NSString *pathAndQueryString = RKPathAndQueryStringFromURLRelativeToURL(testURL, baseURL);
|
||||
expect(pathAndQueryString).to.equal(@"/the/path");
|
||||
}
|
||||
|
||||
- (void)testReturningThePathAndQueryParametersWithANilBaseURLForURLWithAPathAndQueryString
|
||||
{
|
||||
NSURL *baseURL = nil;
|
||||
NSURL *testURL = [NSURL URLWithString:@"http://restkit.org/search?this=that&type=search"];
|
||||
NSString *pathAndQueryString = RKPathAndQueryStringFromURLRelativeToURL(testURL, baseURL);
|
||||
expect(pathAndQueryString).to.equal(@"/search?this=that&type=search");
|
||||
}
|
||||
|
||||
- (void)testShouldReturnAnEmptyStringGivenAURLEqualToTheBaseURLWithNoPath
|
||||
{
|
||||
NSURL *baseURL = [NSURL URLWithString:@"http://restkit.org"];
|
||||
NSURL *testURL = [NSURL URLWithString:@"http://restkit.org"];
|
||||
NSString *pathAndQueryString = RKPathAndQueryStringFromURLRelativeToURL(testURL, baseURL);
|
||||
expect(pathAndQueryString).to.equal(@"");
|
||||
}
|
||||
|
||||
- (void)testShouldReturnAnEmptyStringGivenAURLEqualToTheBaseURLWithASingleSlashAsThePath
|
||||
{
|
||||
NSURL *baseURL = [NSURL URLWithString:@"http://restkit.org/"];
|
||||
NSURL *testURL = [NSURL URLWithString:@"http://restkit.org/"];
|
||||
NSString *pathAndQueryString = RKPathAndQueryStringFromURLRelativeToURL(testURL, baseURL);
|
||||
expect(pathAndQueryString).to.equal(@"");
|
||||
}
|
||||
|
||||
- (void)testShouldReturnTheCompletePathAndQueryStringGivenABaseURLWithNoPath
|
||||
{
|
||||
NSURL *baseURL = [NSURL URLWithString:@"http://restkit.org"];
|
||||
NSURL *testURL = [NSURL URLWithString:@"http://restkit.org/search?this=that&type=search"];
|
||||
NSString *pathAndQueryString = RKPathAndQueryStringFromURLRelativeToURL(testURL, baseURL);
|
||||
expect(pathAndQueryString).to.equal(@"/search?this=that&type=search");
|
||||
}
|
||||
|
||||
- (void)testShouldReturnJustTheRelativePathGivenABaseURLWithASingleTrailingSlash
|
||||
{
|
||||
NSURL *baseURL = [NSURL URLWithString:@"http://restkit.org/"];
|
||||
NSURL *testURL = [NSURL URLWithString:@"http://restkit.org/search?this=that&type=search"];
|
||||
NSString *pathAndQueryString = RKPathAndQueryStringFromURLRelativeToURL(testURL, baseURL);
|
||||
expect(pathAndQueryString).to.equal(@"search?this=that&type=search");
|
||||
}
|
||||
|
||||
- (void)testShouldReturnTheCompletePathAndQueryStringGivenABaseURLWithAComplexPathWithNoTrailingSlash
|
||||
{
|
||||
NSURL *baseURL = [NSURL URLWithString:@"http://restkit.org/api/v1"];
|
||||
NSURL *testURL = [NSURL URLWithString:@"http://restkit.org/api/v1/search?this=that&type=search"];
|
||||
NSString *pathAndQueryString = RKPathAndQueryStringFromURLRelativeToURL(testURL, baseURL);
|
||||
expect(pathAndQueryString).to.equal(@"/search?this=that&type=search");
|
||||
}
|
||||
|
||||
- (void)testShouldReturnTheCompletePathAndQueryStringGivenABaseURLWithAComplexPathWithATrailingSlash
|
||||
{
|
||||
NSURL *baseURL = [NSURL URLWithString:@"http://restkit.org/api/v1/"];
|
||||
NSURL *testURL = [NSURL URLWithString:@"http://restkit.org/api/v1/search?this=that&type=search"];
|
||||
NSString *pathAndQueryString = RKPathAndQueryStringFromURLRelativeToURL(testURL, baseURL);
|
||||
expect(pathAndQueryString).to.equal(@"search?this=that&type=search");
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -32,10 +32,10 @@
|
||||
NSDictionary *arguments = nil;
|
||||
RKPathMatcher *pathMatcher = [RKPathMatcher pathMatcherWithPath:@"/this/is/my/backend?foo=bar&this=that"];
|
||||
BOOL isMatchingPattern = [pathMatcher matchesPattern:@"/this/is/:controllerName/:entityName" tokenizeQueryStrings:YES parsedArguments:&arguments];
|
||||
assertThatBool(isMatchingPattern, is(equalToBool(YES)));
|
||||
assertThat(arguments, isNot(empty()));
|
||||
assertThat(arguments, hasEntries(@"controllerName", @"my", @"entityName", @"backend", @"foo", @"bar", @"this", @"that", nil));
|
||||
|
||||
expect(isMatchingPattern).to.equal(YES);
|
||||
expect(arguments).notTo.beEmpty();
|
||||
NSDictionary *expectedArguments = @{ @"controllerName": @"my", @"entityName": @"backend", @"foo": @"bar", @"this": @"that" };
|
||||
expect(arguments).to.equal(expectedArguments);
|
||||
}
|
||||
|
||||
- (void)testShouldMatchPathsWithEscapedArguments
|
||||
@@ -43,9 +43,10 @@
|
||||
NSDictionary *arguments = nil;
|
||||
RKPathMatcher *pathMatcher = [RKPathMatcher pathMatcherWithPath:@"/bills/tx/82/SB%2014?apikey=GC12d0c6af"];
|
||||
BOOL isMatchingPattern = [pathMatcher matchesPattern:@"/bills/:stateID/:session/:billID" tokenizeQueryStrings:YES parsedArguments:&arguments];
|
||||
assertThatBool(isMatchingPattern, is(equalToBool(YES)));
|
||||
assertThat(arguments, isNot(empty()));
|
||||
assertThat(arguments, hasEntries(@"stateID", @"tx", @"session", @"82", @"billID", @"SB 14", @"apikey", @"GC12d0c6af", nil));
|
||||
expect(isMatchingPattern).to.equal(YES);
|
||||
expect(arguments).notTo.beEmpty();
|
||||
NSDictionary *expectedArguments = @{ @"stateID": @"tx", @"session": @"82", @"billID": @"SB 14", @"apikey": @"GC12d0c6af" };
|
||||
expect(arguments).to.equal(expectedArguments);
|
||||
|
||||
}
|
||||
|
||||
@@ -54,9 +55,10 @@
|
||||
NSDictionary *arguments = nil;
|
||||
RKPathMatcher *patternMatcher = [RKPathMatcher pathMatcherWithPattern:@"github.com/:username"];
|
||||
BOOL isMatchingPattern = [patternMatcher matchesPath:@"github.com/jverkoey" tokenizeQueryStrings:NO parsedArguments:&arguments];
|
||||
assertThatBool(isMatchingPattern, is(equalToBool(YES)));
|
||||
assertThat(arguments, isNot(empty()));
|
||||
assertThat(arguments, hasEntry(@"username", @"jverkoey"));
|
||||
expect(isMatchingPattern).to.equal(YES);
|
||||
expect(arguments).notTo.beEmpty();
|
||||
NSDictionary *params = @{ @"username": @"jverkoey" };
|
||||
expect(arguments).to.equal(params);
|
||||
}
|
||||
|
||||
- (void)testShouldMatchPathsWithoutAnyArguments
|
||||
@@ -64,8 +66,8 @@
|
||||
NSDictionary *arguments = nil;
|
||||
RKPathMatcher *patternMatcher = [RKPathMatcher pathMatcherWithPattern:@"/metadata"];
|
||||
BOOL isMatchingPattern = [patternMatcher matchesPath:@"/metadata" tokenizeQueryStrings:NO parsedArguments:&arguments];
|
||||
assertThatBool(isMatchingPattern, is(equalToBool(YES)));
|
||||
assertThat(arguments, is(empty()));
|
||||
expect(isMatchingPattern).to.equal(YES);
|
||||
expect(arguments).to.beEmpty();
|
||||
}
|
||||
|
||||
- (void)testShouldPerformTwoMatchesInARow
|
||||
@@ -73,11 +75,11 @@
|
||||
NSDictionary *arguments = nil;
|
||||
RKPathMatcher *pathMatcher = [RKPathMatcher pathMatcherWithPath:@"/metadata?apikey=GC12d0c6af"];
|
||||
BOOL isMatchingPattern1 = [pathMatcher matchesPattern:@"/metadata/:stateID" tokenizeQueryStrings:YES parsedArguments:&arguments];
|
||||
assertThatBool(isMatchingPattern1, is(equalToBool(NO)));
|
||||
expect(isMatchingPattern1).to.equal(NO);
|
||||
BOOL isMatchingPattern2 = [pathMatcher matchesPattern:@"/metadata" tokenizeQueryStrings:YES parsedArguments:&arguments];
|
||||
assertThatBool(isMatchingPattern2, is(equalToBool(YES)));
|
||||
assertThat(arguments, isNot(empty()));
|
||||
assertThat(arguments, hasEntry(@"apikey", @"GC12d0c6af"));
|
||||
expect(isMatchingPattern2).to.equal(YES);
|
||||
expect(arguments).notTo.beNil();
|
||||
expect(arguments).to.equal(@{ @"apikey": @"GC12d0c6af" });
|
||||
}
|
||||
|
||||
- (void)testShouldCreatePathsFromInterpolatedObjects
|
||||
@@ -86,9 +88,9 @@
|
||||
@"CuddleGuts", @"name", [NSNumber numberWithInt:6], @"age", nil];
|
||||
RKPathMatcher *matcher = [RKPathMatcher pathMatcherWithPattern:@"/people/:name/:age"];
|
||||
NSString *interpolatedPath = [matcher pathFromObject:person addingEscapes:YES];
|
||||
assertThat(interpolatedPath, isNot(equalTo(nil)));
|
||||
expect(interpolatedPath).notTo.beNil();
|
||||
NSString *expectedPath = @"/people/CuddleGuts/6";
|
||||
assertThat(interpolatedPath, is(equalTo(expectedPath)));
|
||||
expect(interpolatedPath).to.equal(expectedPath);
|
||||
}
|
||||
|
||||
- (void)testShouldCreatePathsFromInterpolatedObjectsWithAddedEscapes
|
||||
@@ -97,9 +99,9 @@
|
||||
@"JUICE|BOX&121", @"password", @"Joe Bob Briggs", @"name", [NSNumber numberWithInt:15], @"group", nil];
|
||||
RKPathMatcher *matcher = [RKPathMatcher pathMatcherWithPattern:@"/people/:group/:name?password=:password"];
|
||||
NSString *interpolatedPath = [matcher pathFromObject:person addingEscapes:YES];
|
||||
assertThat(interpolatedPath, isNot(equalTo(nil)));
|
||||
expect(interpolatedPath).notTo.beNil();
|
||||
NSString *expectedPath = @"/people/15/Joe%20Bob%20Briggs?password=JUICE%7CBOX%26121";
|
||||
assertThat(interpolatedPath, is(equalTo(expectedPath)));
|
||||
expect(interpolatedPath).to.equal(expectedPath);
|
||||
}
|
||||
|
||||
- (void)testShouldCreatePathsFromInterpolatedObjectsWithoutAddedEscapes
|
||||
@@ -108,9 +110,9 @@
|
||||
@"JUICE|BOX&121", @"password", @"Joe Bob Briggs", @"name", [NSNumber numberWithInt:15], @"group", nil];
|
||||
RKPathMatcher *matcher = [RKPathMatcher pathMatcherWithPattern:@"/people/:group/:name?password=:password"];
|
||||
NSString *interpolatedPath = [matcher pathFromObject:person addingEscapes:NO];
|
||||
assertThat(interpolatedPath, isNot(equalTo(nil)));
|
||||
expect(interpolatedPath).notTo.beNil();
|
||||
NSString *expectedPath = @"/people/15/Joe Bob Briggs?password=JUICE|BOX&121";
|
||||
assertThat(interpolatedPath, is(equalTo(expectedPath)));
|
||||
expect(interpolatedPath).to.equal(expectedPath);
|
||||
}
|
||||
|
||||
- (void)testShouldCreatePathsThatIncludePatternArgumentsFollowedByEscapedNonPatternDots
|
||||
@@ -118,14 +120,14 @@
|
||||
NSDictionary *arguments = [NSDictionary dictionaryWithObjectsAndKeys:@"Resources", @"filename", nil];
|
||||
RKPathMatcher *matcher = [RKPathMatcher pathMatcherWithPattern:@"/directory/:filename\\.json"];
|
||||
NSString *interpolatedPath = [matcher pathFromObject:arguments addingEscapes:YES];
|
||||
assertThat(interpolatedPath, isNot(equalTo(nil)));
|
||||
expect(interpolatedPath).notTo.beNil();
|
||||
NSString *expectedPath = @"/directory/Resources.json";
|
||||
assertThat(interpolatedPath, is(equalTo(expectedPath)));
|
||||
expect(interpolatedPath).to.equal(expectedPath);
|
||||
}
|
||||
|
||||
- (void)testMatchingPathWithTrailingSlashAndQuery
|
||||
{
|
||||
RKPathMatcher *pathMatcher = [RKPathMatcher pathMatcherWithPattern:@"/api/v1/organizations"];
|
||||
RKPathMatcher *pathMatcher = [RKPathMatcher pathMatcherWithPattern:@"/api/v1/organizations/"];
|
||||
BOOL matches = [pathMatcher matchesPath:@"/api/v1/organizations/?client_search=t" tokenizeQueryStrings:NO parsedArguments:nil];
|
||||
expect(matches).to.equal(YES);
|
||||
}
|
||||
@@ -141,11 +143,27 @@
|
||||
expect(matches).to.equal(NO);
|
||||
|
||||
matches = [pathMatcher matchesPath:@"/api/v1/organizations/" tokenizeQueryStrings:NO parsedArguments:nil];
|
||||
expect(matches).to.equal(YES);
|
||||
expect(matches).to.equal(NO);
|
||||
|
||||
pathMatcher = [RKPathMatcher pathMatcherWithPattern:@"/api/:version/organizations/:organizationID"];
|
||||
matches = [pathMatcher matchesPath:@"/api/v1/organizations/1234/" tokenizeQueryStrings:NO parsedArguments:nil];
|
||||
expect(matches).to.equal(YES);
|
||||
}
|
||||
|
||||
- (void)testMatchingPathPatternWithTrailingSlash
|
||||
{
|
||||
NSDictionary *argsDictionary = nil;
|
||||
RKPathMatcher *pathMatcher = [RKPathMatcher pathMatcherWithPattern:@"/api/v1/organizations/:identifier/"];
|
||||
BOOL match = [pathMatcher matchesPath:@"/api/v1/organizations/1/" tokenizeQueryStrings:YES parsedArguments:&argsDictionary];
|
||||
expect(match).to.beTruthy();
|
||||
}
|
||||
|
||||
- (void)testMatchingPathPatternWithTrailingSlashAndQueryParameters
|
||||
{
|
||||
NSDictionary *argsDictionary = nil;
|
||||
RKPathMatcher *pathMatcher = [RKPathMatcher pathMatcherWithPattern:@"/api/v1/organizations/"];
|
||||
BOOL match = [pathMatcher matchesPath:@"/api/v1/organizations/?client_search=s" tokenizeQueryStrings:YES parsedArguments:&argsDictionary];
|
||||
expect(match).to.beTruthy();
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -15,22 +15,5 @@
|
||||
|
||||
@implementation RKPathUtilitiesTest
|
||||
|
||||
- (void)testPathNormalizationRemovesTrailingSlash
|
||||
{
|
||||
NSString *normalizedPath = RKPathNormalize(@"/api/v1/organizations/");
|
||||
expect(normalizedPath).to.equal(@"/api/v1/organizations");
|
||||
}
|
||||
|
||||
- (void)testPathNormalizationAddsLeadingSlash
|
||||
{
|
||||
NSString *normalizedPath = RKPathNormalize(@"api/v1/organizations/");
|
||||
expect(normalizedPath).to.equal(@"/api/v1/organizations");
|
||||
}
|
||||
|
||||
- (void)testPathNormalizationRemovesDuplicateSlashes
|
||||
{
|
||||
NSString *normalizedPath = RKPathNormalize(@"api//v1/organizations//");
|
||||
expect(normalizedPath).to.equal(@"/api/v1/organizations");
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
Reference in New Issue
Block a user