diff --git a/VENCore.xcodeproj/project.pbxproj b/VENCore.xcodeproj/project.pbxproj index 07f1f99..31ad190 100644 --- a/VENCore.xcodeproj/project.pbxproj +++ b/VENCore.xcodeproj/project.pbxproj @@ -16,6 +16,7 @@ 47BD36E018FDBA4500DE4554 /* fetchChrisUser.json in Resources */ = {isa = PBXBuildFile; fileRef = 47BD36DF18FDBA4500DE4554 /* fetchChrisUser.json */; }; 9B2C2D06196ED75400D1B241 /* NSArray+VENCore.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B2C2D05196ED75400D1B241 /* NSArray+VENCore.m */; }; 9B2C2D09196EDC3000D1B241 /* NSArray+VENCoreSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B2C2D08196EDC3000D1B241 /* NSArray+VENCoreSpec.m */; }; + 9B6220EB1982DFB8001E4E3E /* searchUsers.json in Resources */ = {isa = PBXBuildFile; fileRef = 9B6220EA1982DFB8001E4E3E /* searchUsers.json */; }; C24E595918F84C67009670F7 /* VENTransaction.m in Sources */ = {isa = PBXBuildFile; fileRef = C24E595418F84C67009670F7 /* VENTransaction.m */; }; C24E595A18F84C67009670F7 /* VENUser.m in Sources */ = {isa = PBXBuildFile; fileRef = C24E595718F84C67009670F7 /* VENUser.m */; }; E84803CCC64F49DB9C88AD75 /* libPods-VENCoreIntegrationTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 25B6CD691E644507A1045E0D /* libPods-VENCoreIntegrationTests.a */; }; @@ -104,6 +105,7 @@ 9B2C2D04196ED75400D1B241 /* NSArray+VENCore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSArray+VENCore.h"; path = "Categories/NSArray+VENCore.h"; sourceTree = ""; }; 9B2C2D05196ED75400D1B241 /* NSArray+VENCore.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSArray+VENCore.m"; path = "Categories/NSArray+VENCore.m"; sourceTree = ""; }; 9B2C2D08196EDC3000D1B241 /* NSArray+VENCoreSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSArray+VENCoreSpec.m"; path = "Categories/NSArray+VENCoreSpec.m"; sourceTree = ""; }; + 9B6220EA1982DFB8001E4E3E /* searchUsers.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = searchUsers.json; sourceTree = ""; }; A1AE1BF8A82F4124AD872FD8 /* Pods-VENCore.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-VENCore.xcconfig"; path = "Pods/Pods-VENCore.xcconfig"; sourceTree = ""; }; B5284720DE944039BF66DD7A /* Pods-VENCoreUnitTests.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-VENCoreUnitTests.xcconfig"; path = "Pods/Pods-VENCoreUnitTests.xcconfig"; sourceTree = ""; }; BB802D1BBF75489EBAC57A1E /* libPods.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPods.a; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -235,6 +237,7 @@ children = ( 4796A38618FDD4C6005CABA6 /* fetchInvalidUser.json */, 47BD36DF18FDBA4500DE4554 /* fetchChrisUser.json */, + 9B6220EA1982DFB8001E4E3E /* searchUsers.json */, ); name = users; path = API/users; @@ -551,6 +554,9 @@ EB00DB331906E647001836A8 = { TestTargetID = EBCB247318E9FBAF00807472; }; + EBCB248318E9FBAF00807472 = { + TestTargetID = EBCB247318E9FBAF00807472; + }; }; }; buildConfigurationList = EBCB246F18E9FBAF00807472 /* Build configuration list for PBXProject "VENCore" */; @@ -588,6 +594,7 @@ EBA57C5418FC362000D39D0F /* invalidAmountError.json in Resources */, EBA57C5318FC362000D39D0F /* invalidAccessTokenError.json in Resources */, EB34431319071EA200B7791E /* paymentToUser.json in Resources */, + 9B6220EB1982DFB8001E4E3E /* searchUsers.json in Resources */, 4796A38718FDD4C6005CABA6 /* fetchInvalidUser.json in Resources */, EB427E5318F844910070EDD9 /* paymentToEmail.json in Resources */, EBCB249218E9FBAF00807472 /* InfoPlist.strings in Resources */, diff --git a/VENCore.xcodeproj/xcshareddata/xcschemes/VENCore.xcscheme b/VENCore.xcodeproj/xcshareddata/xcschemes/VENCore.xcscheme index f431b74..c18386c 100644 --- a/VENCore.xcodeproj/xcshareddata/xcschemes/VENCore.xcscheme +++ b/VENCore.xcodeproj/xcshareddata/xcschemes/VENCore.xcscheme @@ -29,7 +29,7 @@ buildConfiguration = "Debug"> + skipped = "YES"> + skipped = "NO"> \ No newline at end of file + + + + + + + diff --git a/VENCore/Models/Users/VENUser.h b/VENCore/Models/Users/VENUser.h index 934d79d..ff67bf4 100644 --- a/VENCore/Models/Users/VENUser.h +++ b/VENCore/Models/Users/VENUser.h @@ -6,6 +6,9 @@ typedef void(^VENUserFetchSuccessBlock)(VENUser *user); typedef void(^VENUserFetchFailureBlock)(NSError *error); +typedef void(^VENSearchUsersSuccessBlock)(NSArray *users); +typedef void(^VENSearchUsersFailureBlock)(NSError *error); + /** * @note Users are considered equal if and only if their external IDs are the same */ @@ -63,4 +66,16 @@ typedef void(^VENUserFetchFailureBlock)(NSError *error); failure:(VENUserFetchFailureBlock)failureBlock; +/** + * Asynchronously search for users with a query string + * @param searchString An NSString of the query + * @param successBlock A block to be executed with the array of searched users + * @param failureBlock A block to be executed in case of failure / error + * @note This may return from a cache or pull from the network + */ ++ (void) searchUsersWithQuery:(NSString *)searchString + success:(VENSearchUsersSuccessBlock)successBlock + failure:(VENSearchUsersFailureBlock)failureBlock; + + @end \ No newline at end of file diff --git a/VENCore/Models/Users/VENUser.m b/VENCore/Models/Users/VENUser.m index e4bcc01..acec145 100644 --- a/VENCore/Models/Users/VENUser.m +++ b/VENCore/Models/Users/VENUser.m @@ -174,4 +174,38 @@ + (void)fetchUserWithExternalId:(NSString *)externalId }]; } ++ (void)searchUsersWithQuery:(NSString *)searchString + success:(VENSearchUsersSuccessBlock)successBlock + failure:(VENSearchUsersFailureBlock)failureBlock +{ + NSString *urlString = @"users"; + NSMutableDictionary *getParameters = [NSMutableDictionary dictionaryWithDictionary:@{@"query" : searchString}]; + + [[[VENCore defaultCore] httpClient] GET:urlString + parameters:getParameters + success:^(VENHTTPResponse *response) { + NSArray *usersPayload = [NSArray arrayWithArray:response.object[@"data"]]; + NSMutableArray *usersArray = [[NSMutableArray alloc] init]; + for (id object in usersPayload) { + if ([object isKindOfClass:[NSDictionary class]]) { + NSDictionary *userDictionary = (NSDictionary *)object; + if([VENUser canInitWithDictionary:userDictionary]) { + VENUser *user = [[VENUser alloc] initWithDictionary:userDictionary]; + [usersArray addObject:user]; + } + } + } + successBlock(usersArray); + } + failure:^(VENHTTPResponse *response, NSError *error) { + if ([response error]) { + error = [response error]; + } + if (failureBlock) { + failureBlock(error); + } + }]; + +} + @end diff --git a/VENCoreIntegrationTests/VENUserIntegrationSpec.m b/VENCoreIntegrationTests/VENUserIntegrationSpec.m index a834c88..d70a665 100644 --- a/VENCoreIntegrationTests/VENUserIntegrationSpec.m +++ b/VENCoreIntegrationTests/VENUserIntegrationSpec.m @@ -26,4 +26,24 @@ }); }); +describe(@"Searching for a user", ^{ + it(@"should retrieve an arary of users with a search query", ^AsyncBlock{ + NSString *query = @"Leah"; + [VENUser searchUsersWithQuery:query success:^(NSArray *users) { + if ([users count]) { + for (VENUser *user in users){ + expect(user.displayName).notTo.beNil(); + expect(user.externalId).notTo.beNil(); + expect(user.firstName).notTo.beNil(); + expect(user.lastName).notTo.beNil(); + } + } + done(); + } failure:^(NSError *error) { + XCTFail(); + done(); + }]; + }); +}); + SpecEnd diff --git a/VENCoreUnitTests/API/users/searchUsers.json b/VENCoreUnitTests/API/users/searchUsers.json new file mode 100644 index 0000000..f5717d9 --- /dev/null +++ b/VENCoreUnitTests/API/users/searchUsers.json @@ -0,0 +1 @@ +{"data": [{"username": "johnjohnny", "first_name": "John", "last_name": "Johnny", "display_name": "John Johnny", "about": "Super cool", "profile_picture_url": "https://s3.amazonaws.com/venmo/no-image.gif", "id": "357916301328384538", "date_joined": "2010-05-09T19:55:48"}, {"username": "ian-john", "first_name": "Ian", "last_name": "John", "display_name": "Ian John", "about": "No Short Bio", "profile_picture_url": "https://venmopics.appspot.com/u/v1/s/7472351c-5048-43d2-b355-783cc8ddccc3", "id": "1119050902011904420", "date_joined": "2013-03-24T23:54:23"}, {"username": "fred-iwan", "first_name": "Fred", "last_name": "Iwan", "display_name": "Fred Iwan", "about": "No Short Bio", "profile_picture_url": "https://venmopics.appspot.com/u/v1/f/0061894e-ae49-432f-b71c-5d2c8a90af8c", "id": "1181135426027520752", "date_joined": "2013-06-18T15:45:15"}, {"username": "wojtek-iwan", "first_name": "Wojtek", "last_name": "Iwan", "display_name": "Wojtek Iwan", "about": "No Short Bio", "profile_picture_url": "https://s3.amazonaws.com/venmo/no-image.gif", "id": "1424746868637696006", "date_joined": "2014-05-20T18:37:42"}, {"username": "iwan-dodd", "first_name": "Iwan", "last_name": "Dodd", "display_name": "Iwan Dodd", "about": "No Short Bio", "profile_picture_url": "https://s3.amazonaws.com/venmo/no-image.gif", "id": "1321719184752640008", "date_joined": "2013-12-29T15:00:05"}, {"username": "iwan-vandervinne", "first_name": "Iwan", "last_name": "Vandervinne", "display_name": "Iwan Vandervinne", "about": "No Short Bio", "profile_picture_url": "https://s3.amazonaws.com/venmo/no-image.gif", "id": "1401122828845056083", "date_joined": "2014-04-18T04:20:57"}, {"username": "iwan-nyotowidjojo", "first_name": "Iwan", "last_name": "Nyotowidjojo", "display_name": "Iwan Nyotowidjojo", "about": "No Short Bio", "profile_picture_url": "https://venmopics.appspot.com/u/v1/s/82ed1fe4-1370-4af8-a50e-8c07b4ee639f", "id": "1412014085767168711", "date_joined": "2014-05-03T04:59:56"}, {"username": "iain-macneill", "first_name": "Iain", "last_name": "Macneill", "display_name": "Iain Macneill", "about": "No Short Bio", "profile_picture_url": "https://s3.amazonaws.com/venmo/no-image.gif", "id": "584921714262016599", "date_joined": "2011-03-19T00:55:02"}, {"username": "iain-edminster", "first_name": "Iain", "last_name": "Edminster", "display_name": "Iain Edminster", "about": "No Short Bio", "profile_picture_url": "https://venmopics.appspot.com/u/v1/s/e8d56419-dc3b-4507-901a-2b13f0a00878", "id": "952159050924033016", "date_joined": "2012-08-06T17:30:04"}, {"username": "iain-christenson", "first_name": "Iain", "last_name": "Christenson", "display_name": "Iain Christenson", "about": "No Short Bio", "profile_picture_url": "https://graph.facebook.com/760153964/picture?type=square", "id": "1337762254946305010", "date_joined": "2014-01-20T18:14:48"}, {"username": "iain-cockshott", "first_name": "Iain", "last_name": "Cockshott", "display_name": "Iain Cockshott", "about": "No Short Bio", "profile_picture_url": "https://s3.amazonaws.com/venmo/no-image.gif", "id": "1317372979838976810", "date_joined": "2013-12-23T15:04:57"}, {"username": "iain-griffiths", "first_name": "Iain", "last_name": "Griffiths", "display_name": "Iain Griffiths", "about": "No Short Bio", "profile_picture_url": "https://s3.amazonaws.com/venmo/no-image.gif", "id": "1204272582623232024", "date_joined": "2013-07-20T13:54:39"}, {"username": "iain-saunderson", "first_name": "Iain", "last_name": "Saunderson", "display_name": "Iain Saunderson", "about": " ", "profile_picture_url": "https://graph.facebook.com/602218352/picture?type=square", "id": "1437851124236288685", "date_joined": "2014-06-07T20:33:31"}, {"username": "iain-marrs", "first_name": "Iain ", "last_name": "Marrs", "display_name": "Iain Marrs", "about": "No Short Bio", "profile_picture_url": "https://s3.amazonaws.com/venmo/no-image.gif", "id": "1442080744275968454", "date_joined": "2014-06-13T16:37:01"}, {"username": "iain-zautner", "first_name": "Iain", "last_name": "Zautner", "display_name": "Iain Zautner", "about": "No Short Bio", "profile_picture_url": "https://venmopics.appspot.com/u/v1/s/4ff3c610-a54c-4af6-9ecc-a0f05170bd3d", "id": "1262519477862400113", "date_joined": "2013-10-08T22:40:50"}, {"username": "iain-starr", "first_name": "Iain", "last_name": "Starr", "display_name": "Iain Starr", "about": "No Short Bio", "profile_picture_url": "https://s3.amazonaws.com/venmo/no-image.gif", "id": "1246383579332608233", "date_joined": "2013-09-16T16:21:41"}, {"username": "iain-macdonald", "first_name": "Iain", "last_name": "Macdonald", "display_name": "Iain Macdonald", "about": "No Short Bio", "profile_picture_url": "https://s3.amazonaws.com/venmo/no-image.gif", "id": "1465680054452224192", "date_joined": "2014-07-16T06:04:38"}, {"username": "iain-denham", "first_name": "Iain", "last_name": "Denham", "display_name": "Iain Denham", "about": "No Short Bio", "profile_picture_url": "https://graph.facebook.com/10703485/picture?type=square", "id": "1366773509128192389", "date_joined": "2014-03-01T18:54:59"}, {"username": "iain-mcdonald", "first_name": "Iain", "last_name": "Mcdonald", "display_name": "Iain Mcdonald", "about": "No Short Bio", "profile_picture_url": "https://s3.amazonaws.com/venmo/no-image.gif", "id": "1369164547620864354", "date_joined": "2014-03-05T02:05:33"}, {"username": "iain-proctor", "first_name": "Iain", "last_name": "Proctor", "display_name": "Iain Proctor", "about": "No Short Bio", "profile_picture_url": "https://s3.amazonaws.com/venmo/no-image.gif", "id": "1408403142344704509", "date_joined": "2014-04-28T05:25:38"}]} \ No newline at end of file diff --git a/VENCoreUnitTests/Models/Users/VENUserSpec.m b/VENCoreUnitTests/Models/Users/VENUserSpec.m index 340d274..0606058 100644 --- a/VENCoreUnitTests/Models/Users/VENUserSpec.m +++ b/VENCoreUnitTests/Models/Users/VENUserSpec.m @@ -252,4 +252,37 @@ }); + +describe(@"SearchUsersWithSearchQuery", ^{ + it(@"should fetch users with search string 'john'", ^AsyncBlock{ + NSString *query = @"john"; + NSString *baseURLString = [VENTestUtilities baseURLStringForCore:[VENCore defaultCore]]; + NSString *urlToStub = [NSString stringWithFormat:@"%@/users?query=%@", baseURLString, query]; + [VENTestUtilities stubNetworkGET:urlToStub withStatusCode:200 andResponseFilePath:@"searchUsers"]; + [VENUser searchUsersWithQuery:query success:^(NSArray *users) { + expect([users count]).to.equal(@(20)); + done(); + + }failure:^(NSError *error) { + XCTFail(); + done(); + }]; + }); + + it(@"should return 20 users when given an empy string search query", ^AsyncBlock{ + NSString *query = @""; + NSString *baseURLString = [VENTestUtilities baseURLStringForCore:[VENCore defaultCore]]; + NSString *urlToStub = [NSString stringWithFormat:@"%@/users?query=%@", baseURLString, query]; + [VENTestUtilities stubNetworkGET:urlToStub withStatusCode:200 andResponseFilePath:@"searchUsers"]; + [VENUser searchUsersWithQuery:query success:^(NSArray *users) { + expect([users count]).to.equal(@(20)); + done(); + }failure:^(NSError *error) { + XCTFail(); + done(); + }]; + }); +}); + + SpecEnd \ No newline at end of file