// // RKTableControllerTest.m // RestKit // // Created by Blake Watters on 8/3/11. // Copyright (c) 2009-2012 RestKit. All rights reserved. // #import "RKTestEnvironment.h" #import "RKTableController.h" #import "RKTableSection.h" #import "RKTestUser.h" #import "RKMappableObject.h" #import "RKAbstractTableController_Internals.h" #import "RKTableControllerTestDelegate.h" // Expose the object loader delegate for testing purposes... @interface RKTableController () - (void)animationDidStopAddingSwipeView:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context; @end @interface RKTableControllerTestTableViewController : UITableViewController @end @implementation RKTableControllerTestTableViewController @end @interface RKTableControllerTestViewController : UIViewController @end @implementation RKTableControllerTestViewController @end @interface RKTestUserTableViewCell : UITableViewCell @end @implementation RKTestUserTableViewCell @end //////////////////////////////////////////////////////////////////////////////////////////////////////////////// @interface RKTableControllerTest : RKTestCase @end @implementation RKTableControllerTest - (void)setUp { [RKTestFactory setUp]; } - (void)tearDown { [RKTestFactory tearDown]; } - (void)testInitializeWithATableViewController { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; assertThat(viewController.tableView, is(notNilValue())); RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; assertThat(tableController.viewController, is(equalTo(viewController))); assertThat(tableController.tableView, is(equalTo(viewController.tableView))); } - (void)testInitializeWithATableViewAndViewController { UITableView *tableView = [UITableView new]; RKTableControllerTestViewController *viewController = [RKTableControllerTestViewController new]; RKTableController *tableController = [RKTableController tableControllerWithTableView:tableView forViewController:viewController]; assertThat(tableController.viewController, is(equalTo(viewController))); assertThat(tableController.tableView, is(equalTo(tableView))); } - (void)testInitializesToUnloadedState { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; assertThatBool([tableController isLoaded], is(equalToBool(NO))); } - (void)testAlwaysHaveAtLeastOneSection { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; assertThat(viewController.tableView, is(notNilValue())); RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; assertThatInt(tableController.sectionCount, is(equalToInt(1))); } - (void)testDisconnectFromTheTableViewOnDealloc { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; assertThatInt(tableController.sectionCount, is(equalToInt(1))); [pool drain]; assertThat(viewController.tableView.delegate, is(nilValue())); assertThat(viewController.tableView.dataSource, is(nilValue())); } - (void)testNotDisconnectFromTheTableViewIfDelegateOrDataSourceAreNotSelf { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [[RKTableController alloc] initWithTableView:viewController.tableView viewController:viewController]; viewController.tableView.delegate = viewController; viewController.tableView.dataSource = viewController; assertThatInt(tableController.sectionCount, is(equalToInt(1))); [tableController release]; assertThat(viewController.tableView.delegate, isNot(nilValue())); assertThat(viewController.tableView.dataSource, isNot(nilValue())); } #pragma mark - Section Management - (void)testAddASection { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; RKTableSection *section = [RKTableSection section]; [tableController addSection:section]; assertThatInt([tableController.sections count], is(equalToInt(2))); } - (void)testConnectTheSectionToTheTableModelOnAdd { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; RKTableSection *section = [RKTableSection section]; [tableController addSection:section]; assertThat(section.tableController, is(equalTo(tableController))); } - (void)testConnectTheSectionToTheCellMappingsOfTheTableModelWhenNil { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; RKTableSection *section = [RKTableSection section]; assertThat(section.cellMappings, is(nilValue())); [tableController addSection:section]; assertThat(section.cellMappings, is(equalTo(tableController.cellMappings))); } - (void)testNotConnectTheSectionToTheCellMappingsOfTheTableModelWhenNonNil { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; RKTableSection *section = [RKTableSection section]; section.cellMappings = [NSMutableDictionary dictionary]; [tableController addSection:section]; assertThatBool(section.cellMappings == tableController.cellMappings, is(equalToBool(NO))); } - (void)testCountTheSections { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; RKTableSection *section = [RKTableSection section]; [tableController addSection:section]; assertThatInt(tableController.sectionCount, is(equalToInt(2))); } - (void)testRemoveASection { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; RKTableSection *section = [RKTableSection section]; [tableController addSection:section]; assertThatInt(tableController.sectionCount, is(equalToInt(2))); [tableController removeSection:section]; assertThatInt(tableController.sectionCount, is(equalToInt(1))); } - (void)testNotLetRemoveTheLastSection { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; RKTableSection *section = [RKTableSection section]; [tableController addSection:section]; assertThatInt(tableController.sectionCount, is(equalToInt(2))); [tableController removeSection:section]; } - (void)testInsertASectionAtATestificIndex { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; RKTableSection *referenceSection = [RKTableSection section]; [tableController addSection:[RKTableSection section]]; [tableController addSection:[RKTableSection section]]; [tableController addSection:[RKTableSection section]]; [tableController addSection:[RKTableSection section]]; [tableController insertSection:referenceSection atIndex:2]; assertThatInt(tableController.sectionCount, is(equalToInt(6))); assertThat([tableController.sections objectAtIndex:2], is(equalTo(referenceSection))); } - (void)testRemoveASectionByIndex { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; RKTableSection *section = [RKTableSection section]; [tableController addSection:section]; assertThatInt(tableController.sectionCount, is(equalToInt(2))); [tableController removeSectionAtIndex:1]; assertThatInt(tableController.sectionCount, is(equalToInt(1))); } - (void)testRaiseAnExceptionWhenAttemptingToRemoveTheLastSection { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; NSException *exception = nil; @try { [tableController removeSectionAtIndex:0]; } @catch (NSException *e) { exception = e; } @finally { assertThat(exception, isNot(nilValue())); } } - (void)testReturnTheSectionAtAGivenIndex { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; RKTableSection *referenceSection = [RKTableSection section]; [tableController addSection:[RKTableSection section]]; [tableController addSection:[RKTableSection section]]; [tableController addSection:[RKTableSection section]]; [tableController addSection:[RKTableSection section]]; [tableController insertSection:referenceSection atIndex:2]; assertThatInt(tableController.sectionCount, is(equalToInt(6))); assertThat([tableController sectionAtIndex:2], is(equalTo(referenceSection))); } - (void)testRemoveAllSections { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; [tableController addSection:[RKTableSection section]]; [tableController addSection:[RKTableSection section]]; [tableController addSection:[RKTableSection section]]; [tableController addSection:[RKTableSection section]]; assertThatInt(tableController.sectionCount, is(equalToInt(5))); [tableController removeAllSections]; assertThatInt(tableController.sectionCount, is(equalToInt(1))); } - (void)testReturnASectionByHeaderTitle { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; [tableController addSection:[RKTableSection section]]; [tableController addSection:[RKTableSection section]]; RKTableSection *titledSection = [RKTableSection section]; titledSection.headerTitle = @"Testing"; [tableController addSection:titledSection]; [tableController addSection:[RKTableSection section]]; assertThat([tableController sectionWithHeaderTitle:@"Testing"], is(equalTo(titledSection))); } - (void)testNotifyTheTableViewOnSectionInsertion { RKTableControllerTestViewController *viewController = [RKTableControllerTestViewController new]; id mockTableView = [OCMockObject niceMockForClass:[UITableView class]]; RKTableController *tableController = [RKTableController tableControllerWithTableView:mockTableView forViewController:viewController]; [[mockTableView expect] insertSections:[NSIndexSet indexSetWithIndex:1] withRowAnimation:tableController.defaultRowAnimation]; [tableController addSection:[RKTableSection section]]; [mockTableView verify]; } - (void)testNotifyTheTableViewOnSectionRemoval { RKTableControllerTestViewController *viewController = [RKTableControllerTestViewController new]; id mockTableView = [OCMockObject niceMockForClass:[UITableView class]]; RKTableController *tableController = [RKTableController tableControllerWithTableView:mockTableView forViewController:viewController]; [[mockTableView expect] insertSections:[NSIndexSet indexSetWithIndex:1] withRowAnimation:tableController.defaultRowAnimation]; [[mockTableView expect] deleteSections:[NSIndexSet indexSetWithIndex:1] withRowAnimation:tableController.defaultRowAnimation]; RKTableSection *section = [RKTableSection section]; [tableController addSection:section]; [tableController removeSection:section]; [mockTableView verify]; } - (void)testNotifyTheTableOfSectionRemovalAndReaddWhenRemovingAllSections { RKTableControllerTestViewController *viewController = [RKTableControllerTestViewController new]; id mockTableView = [OCMockObject niceMockForClass:[UITableView class]]; RKTableController *tableController = [RKTableController tableControllerWithTableView:mockTableView forViewController:viewController]; [[mockTableView expect] deleteSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:tableController.defaultRowAnimation]; [[mockTableView expect] deleteSections:[NSIndexSet indexSetWithIndex:1] withRowAnimation:tableController.defaultRowAnimation]; [[mockTableView expect] insertSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:tableController.defaultRowAnimation]; RKTableSection *section = [RKTableSection section]; [tableController addSection:section]; [tableController removeAllSections]; [mockTableView verify]; } #pragma mark - UITableViewDataSource Tests - (void)testRaiseAnExceptionIfSentAMessageWithATableViewItIsNotBoundTo { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; NSException *exception = nil; @try { [tableController numberOfSectionsInTableView:[UITableView new]]; } @catch (NSException *e) { exception = e; } @finally { assertThat(exception, is(notNilValue())); } } - (void)testReturnTheNumberOfSectionsInTableView { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; assertThatInt([tableController numberOfSectionsInTableView:viewController.tableView], is(equalToInt(1))); [tableController addSection:[RKTableSection section]]; assertThatInt([tableController numberOfSectionsInTableView:viewController.tableView], is(equalToInt(2))); } - (void)testReturnTheNumberOfRowsInSectionInTableView { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; assertThatInt([tableController tableView:viewController.tableView numberOfRowsInSection:0], is(equalToInt(0))); NSArray *objects = [NSArray arrayWithObject:@"one"]; [tableController loadObjects:objects]; assertThatInt([tableController tableView:viewController.tableView numberOfRowsInSection:0], is(equalToInt(1))); } - (void)testReturnTheHeaderTitleForSection { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; RKTableSection *section = [RKTableSection section]; [tableController addSection:section]; assertThat([tableController tableView:viewController.tableView titleForHeaderInSection:1], is(nilValue())); section.headerTitle = @"RestKit!"; assertThat([tableController tableView:viewController.tableView titleForHeaderInSection:1], is(equalTo(@"RestKit!"))); } - (void)testReturnTheTitleForFooterInSection { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; RKTableSection *section = [RKTableSection section]; [tableController addSection:section]; assertThat([tableController tableView:viewController.tableView titleForFooterInSection:1], is(nilValue())); section.footerTitle = @"RestKit!"; assertThat([tableController tableView:viewController.tableView titleForFooterInSection:1], is(equalTo(@"RestKit!"))); } - (void)testReturnTheNumberOfRowsAcrossAllSections { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; RKTableSection *section = [RKTableSection section]; id sectionMock = [OCMockObject partialMockForObject:section]; NSUInteger rowCount = 5; [[[sectionMock stub] andReturnValue:OCMOCK_VALUE(rowCount)] rowCount]; [tableController addSection:section]; assertThatInt(tableController.rowCount, is(equalToInt(5))); } - (void)testReturnTheTableViewCellForRowAtIndexPath { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; RKTableItem *item = [RKTableItem tableItemWithText:@"Test!" detailText:@"Details!" image:nil]; [tableController loadTableItems:[NSArray arrayWithObject:item] inSection:0 withMapping:[RKTableViewCellMapping cellMappingUsingBlock:^(RKTableViewCellMapping *cellMapping) { // Detail text label won't appear with default style... cellMapping.style = UITableViewCellStyleValue1; [cellMapping addDefaultMappings]; }]]; UITableViewCell *cell = [tableController tableView:tableController.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]]; assertThat(cell.textLabel.text, is(equalTo(@"Test!"))); assertThat(cell.detailTextLabel.text, is(equalTo(@"Details!"))); } #pragma mark - Table Cell Mapping - (void)testInitializeCellMappings { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; assertThat(tableController.cellMappings, is(notNilValue())); } - (void)testRegisterMappingsForObjectsToTableViewCell { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; assertThat([tableController.cellMappings cellMappingForClass:[RKTestUser class]], is(nilValue())); [tableController mapObjectsWithClass:[RKTestUser class] toTableCellsWithMapping:[RKTableViewCellMapping cellMapping]]; RKObjectMapping *mapping = [tableController.cellMappings cellMappingForClass:[RKTestUser class]]; assertThat(mapping, isNot(nilValue())); assertThatBool([mapping.objectClass isSubclassOfClass:[UITableViewCell class]], is(equalToBool(YES))); } - (void)testDefaultTheReuseIdentifierToTheNameOfTheObjectClass { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; assertThat([tableController.cellMappings cellMappingForClass:[RKTestUser class]], is(nilValue())); RKTableViewCellMapping *cellMapping = [RKTableViewCellMapping cellMapping]; [tableController mapObjectsWithClass:[RKTestUser class] toTableCellsWithMapping:cellMapping]; assertThat(cellMapping.reuseIdentifier, is(equalTo(@"UITableViewCell"))); } - (void)testDefaultTheReuseIdentifierToTheNameOfTheObjectClassWhenCreatingMappingWithBlockSyntax { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; assertThat([tableController.cellMappings cellMappingForClass:[RKTestUser class]], is(nilValue())); RKTableViewCellMapping *cellMapping = [RKTableViewCellMapping cellMappingUsingBlock:^(RKTableViewCellMapping *cellMapping) { cellMapping.cellClass = [RKTestUserTableViewCell class]; }]; [tableController mapObjectsWithClass:[RKTestUser class] toTableCellsWithMapping:cellMapping]; assertThat(cellMapping.reuseIdentifier, is(equalTo(@"RKTestUserTableViewCell"))); } - (void)testReturnTheObjectForARowAtIndexPath { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; RKTestUser *user = [RKTestUser user]; [tableController loadObjects:[NSArray arrayWithObject:user]]; NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0]; assertThatBool(user == [tableController objectForRowAtIndexPath:indexPath], is(equalToBool(YES))); } - (void)testReturnTheCellMappingForTheRowAtIndexPath { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; RKTableViewCellMapping *cellMapping = [RKTableViewCellMapping cellMapping]; [tableController mapObjectsWithClass:[RKTestUser class] toTableCellsWithMapping:cellMapping]; [tableController loadObjects:[NSArray arrayWithObject:[RKTestUser user]]]; NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0]; assertThat([tableController cellMappingForObjectAtIndexPath:indexPath], is(equalTo(cellMapping))); } - (void)testChangeTheReuseIdentifierWhenMutatedWithinTheBlockInitializer { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; assertThat([tableController.cellMappings cellMappingForClass:[RKTestUser class]], is(nilValue())); [tableController mapObjectsWithClass:[RKTestUser class] toTableCellsWithMapping:[RKTableViewCellMapping cellMappingUsingBlock:^(RKTableViewCellMapping *cellMapping) { cellMapping.cellClass = [RKTestUserTableViewCell class]; cellMapping.reuseIdentifier = @"RKTestUserOverride"; }]]; RKTableViewCellMapping *userCellMapping = [tableController.cellMappings cellMappingForClass:[RKTestUser class]]; assertThat(userCellMapping, isNot(nilValue())); assertThat(userCellMapping.reuseIdentifier, is(equalTo(@"RKTestUserOverride"))); } #pragma mark - Static Object Loading - (void)testLoadAnArrayOfObjects { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; NSArray *objects = [NSArray arrayWithObject:@"one"]; assertThat([tableController sectionAtIndex:0].objects, is(empty())); [tableController loadObjects:objects]; assertThat([tableController sectionAtIndex:0].objects, is(equalTo(objects))); } - (void)testLoadAnArrayOfObjectsToTheTestifiedSection { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; [tableController addSection:[RKTableSection section]]; NSArray *objects = [NSArray arrayWithObject:@"one"]; assertThat([tableController sectionAtIndex:1].objects, is(empty())); [tableController loadObjects:objects inSection:1]; assertThat([tableController sectionAtIndex:1].objects, is(equalTo(objects))); } - (void)testLoadAnArrayOfTableItems { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; NSArray *tableItems = [RKTableItem tableItemsFromStrings:@"One", @"Two", @"Three", nil]; [tableController loadTableItems:tableItems]; assertThatBool([tableController isLoaded], is(equalToBool(YES))); assertThatInt(tableController.rowCount, is(equalToInt(3))); UITableViewCell *cellOne = [tableController tableView:tableController.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]]; UITableViewCell *cellTwo = [tableController tableView:tableController.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:1 inSection:0]]; UITableViewCell *cellThree = [tableController tableView:tableController.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:2 inSection:0]]; assertThat(cellOne.textLabel.text, is(equalTo(@"One"))); assertThat(cellTwo.textLabel.text, is(equalTo(@"Two"))); assertThat(cellThree.textLabel.text, is(equalTo(@"Three"))); } - (void)testAllowYouToTriggerAnEmptyLoad { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; assertThatBool([tableController isLoaded], is(equalToBool(NO))); [tableController loadEmpty]; assertThatBool([tableController isLoaded], is(equalToBool(YES))); assertThatBool([tableController isEmpty], is(equalToBool(YES))); } #pragma mark - Network Load - (void)testLoadCollectionOfObjectsAndMapThemIntoTableViewCells { RKObjectManager *objectManager = [RKTestFactory objectManager]; objectManager.client.cachePolicy = RKRequestCachePolicyNone; RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; tableController.objectManager = objectManager; [tableController mapObjectsWithClass:[RKTestUser class] toTableCellsWithMapping:[RKTableViewCellMapping cellMappingUsingBlock:^(RKTableViewCellMapping *mapping) { mapping.cellClass = [RKTestUserTableViewCell class]; [mapping mapKeyPath:@"name" toAttribute:@"textLabel.text"]; [mapping mapKeyPath:@"nickName" toAttribute:@"detailTextLabel.text"]; }]]; RKTableControllerTestDelegate *delegate = [RKTableControllerTestDelegate tableControllerDelegate]; delegate.timeout = 10; tableController.delegate = delegate; [tableController loadTableFromResourcePath:@"/JSON/users.json" usingBlock:^(RKObjectLoader *objectLoader) { objectLoader.objectMapping = [RKObjectMapping mappingForClass:[RKTestUser class] usingBlock:^(RKObjectMapping *mapping) { [mapping mapAttributes:@"name", nil]; }]; }]; [delegate waitForLoad]; assertThatBool([tableController isLoaded], is(equalToBool(YES))); assertThatInt(tableController.rowCount, is(equalToInt(3))); } - (void)testSetTheModelToTheLoadedStateIfObjectsAreLoadedSuccessfully { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; assertThatBool([tableController isLoaded], is(equalToBool(NO))); NSArray *objects = [NSArray arrayWithObject:[RKTestUser new]]; id mockLoader = [OCMockObject mockForClass:[RKObjectLoader class]]; [tableController objectLoader:mockLoader didLoadObjects:objects]; assertThatBool([tableController isLoading], is(equalToBool(NO))); assertThatBool([tableController isLoaded], is(equalToBool(YES))); } - (void)testSetTheModelToErrorStateIfTheObjectLoaderFailsWithAnError { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; id mockObjectLoader = [OCMockObject niceMockForClass:[RKObjectLoader class]]; NSError *error = [NSError errorWithDomain:@"Test" code:0 userInfo:nil]; [tableController objectLoader:mockObjectLoader didFailWithError:error]; assertThatBool([tableController isLoading], is(equalToBool(NO))); assertThatBool([tableController isLoaded], is(equalToBool(YES))); assertThatBool([tableController isError], is(equalToBool(YES))); assertThatBool([tableController isEmpty], is(equalToBool(YES))); } - (void)testErrorIsClearedAfterSubsequentLoad { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; id mockObjectLoader = [OCMockObject niceMockForClass:[RKObjectLoader class]]; NSError *error = [NSError errorWithDomain:@"Test" code:0 userInfo:nil]; [tableController objectLoader:mockObjectLoader didFailWithError:error]; assertThatBool([tableController isLoading], is(equalToBool(NO))); assertThatBool([tableController isLoaded], is(equalToBool(YES))); assertThatBool([tableController isError], is(equalToBool(YES))); assertThatBool([tableController isEmpty], is(equalToBool(YES))); [tableController objectLoader:mockObjectLoader didLoadObjects:[NSArray array]]; assertThatBool([tableController isError], is(equalToBool(NO))); assertThat(tableController.error, is(nilValue())); } - (void)testDisplayOfErrorImageTakesPresendenceOverEmpty { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; UIImage *imageForEmpty = [RKTestFixture imageWithContentsOfFixture:@"blake.png"]; UIImage *imageForError = [imageForEmpty copy]; tableController.imageForEmpty = imageForEmpty; tableController.imageForError = imageForError; id mockObjectLoader = [OCMockObject niceMockForClass:[RKObjectLoader class]]; NSError *error = [NSError errorWithDomain:@"Test" code:0 userInfo:nil]; [tableController objectLoader:mockObjectLoader didFailWithError:error]; assertThatBool([tableController isLoading], is(equalToBool(NO))); assertThatBool([tableController isLoaded], is(equalToBool(YES))); assertThatBool([tableController isError], is(equalToBool(YES))); assertThatBool([tableController isEmpty], is(equalToBool(YES))); UIImage *overlayImage = [tableController overlayImage]; assertThat(overlayImage, isNot(nilValue())); assertThat(overlayImage, is(equalTo(imageForError))); } - (void)testBitwiseLoadingTransition { RKTableControllerState oldState = RKTableControllerStateNotYetLoaded; RKTableControllerState newState = RKTableControllerStateLoading; BOOL loadingTransitioned = ((oldState ^ newState) & RKTableControllerStateLoading); assertThatBool(loadingTransitioned, is(equalToBool(YES))); oldState = RKTableControllerStateOffline | RKTableControllerStateEmpty; newState = RKTableControllerStateOffline | RKTableControllerStateEmpty | RKTableControllerStateLoading; loadingTransitioned = ((oldState ^ newState) & RKTableControllerStateLoading); assertThatBool(loadingTransitioned, is(equalToBool(YES))); oldState = RKTableControllerStateNormal; newState = RKTableControllerStateLoading; loadingTransitioned = ((oldState ^ newState) & RKTableControllerStateLoading); assertThatBool(loadingTransitioned, is(equalToBool(YES))); oldState = RKTableControllerStateOffline | RKTableControllerStateEmpty | RKTableControllerStateLoading; newState = RKTableControllerStateOffline | RKTableControllerStateLoading; loadingTransitioned = ((oldState ^ newState) & RKTableControllerStateLoading); assertThatBool(loadingTransitioned, is(equalToBool(NO))); oldState = RKTableControllerStateNotYetLoaded; newState = RKTableControllerStateOffline; loadingTransitioned = ((oldState ^ newState) & RKTableControllerStateLoading); assertThatBool(loadingTransitioned, is(equalToBool(NO))); } - (void)testSetTheModelToAnEmptyStateIfTheObjectLoaderReturnsAnEmptyCollection { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; assertThatBool([tableController isLoaded], is(equalToBool(NO))); NSArray *objects = [NSArray array]; id mockLoader = [OCMockObject mockForClass:[RKObjectLoader class]]; [tableController objectLoader:mockLoader didLoadObjects:objects]; assertThatBool([tableController isLoading], is(equalToBool(NO))); assertThatBool([tableController isEmpty], is(equalToBool(YES))); } - (void)testSetTheModelToALoadedStateEvenIfTheObjectLoaderReturnsAnEmptyCollection { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; assertThatBool([tableController isLoaded], is(equalToBool(NO))); NSArray *objects = [NSArray array]; id mockLoader = [OCMockObject mockForClass:[RKObjectLoader class]]; [tableController objectLoader:mockLoader didLoadObjects:objects]; assertThatBool([tableController isLoading], is(equalToBool(NO))); assertThatBool([tableController isEmpty], is(equalToBool(YES))); assertThatBool([tableController isLoaded], is(equalToBool(YES))); } - (void)testEnterTheLoadingStateWhenTheRequestStartsLoading { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; assertThatBool([tableController isLoaded], is(equalToBool(NO))); assertThatBool([tableController isLoading], is(equalToBool(NO))); id mockLoader = [OCMockObject mockForClass:[RKObjectLoader class]]; [tableController requestDidStartLoad:mockLoader]; assertThatBool([tableController isLoading], is(equalToBool(YES))); } - (void)testExitTheLoadingStateWhenTheRequestFinishesLoading { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; assertThatBool([tableController isLoaded], is(equalToBool(NO))); assertThatBool([tableController isLoading], is(equalToBool(NO))); id mockLoader = [OCMockObject niceMockForClass:[RKObjectLoader class]]; [tableController requestDidStartLoad:mockLoader]; assertThatBool([tableController isLoading], is(equalToBool(YES))); [tableController objectLoaderDidFinishLoading:mockLoader]; assertThatBool([tableController isLoading], is(equalToBool(NO))); } - (void)testClearTheLoadingStateWhenARequestIsCancelled { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; assertThatBool([tableController isLoaded], is(equalToBool(NO))); assertThatBool([tableController isLoading], is(equalToBool(NO))); id mockLoader = [OCMockObject mockForClass:[RKObjectLoader class]]; [tableController requestDidStartLoad:mockLoader]; assertThatBool([tableController isLoading], is(equalToBool(YES))); [tableController requestDidCancelLoad:mockLoader]; assertThatBool([tableController isLoading], is(equalToBool(NO))); } - (void)testClearTheLoadingStateWhenARequestTimesOut { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; assertThatBool([tableController isLoaded], is(equalToBool(NO))); assertThatBool([tableController isLoading], is(equalToBool(NO))); id mockLoader = [OCMockObject mockForClass:[RKObjectLoader class]]; [tableController requestDidStartLoad:mockLoader]; assertThatBool([tableController isLoading], is(equalToBool(YES))); [tableController requestDidTimeout:mockLoader]; assertThatBool([tableController isLoading], is(equalToBool(NO))); } - (void)testDoSomethingWhenTheRequestLoadsAnUnexpectedResponse { RKLogCritical(@"PENDING - Undefined Behavior!!!"); } - (void)testLoadCollectionOfObjectsAndMapThemIntoSections { RKObjectManager *objectManager = [RKTestFactory objectManager]; objectManager.client.cachePolicy = RKRequestCachePolicyNone; RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; tableController.objectManager = objectManager; [tableController mapObjectsWithClass:[RKTestUser class] toTableCellsWithMapping:[RKTableViewCellMapping cellMappingUsingBlock:^(RKTableViewCellMapping *mapping) { mapping.cellClass = [RKTestUserTableViewCell class]; [mapping mapKeyPath:@"name" toAttribute:@"textLabel.text"]; [mapping mapKeyPath:@"nickName" toAttribute:@"detailTextLabel.text"]; }]]; tableController.sectionNameKeyPath = @"name"; RKTableControllerTestDelegate *delegate = [RKTableControllerTestDelegate tableControllerDelegate]; delegate.timeout = 10; tableController.delegate = delegate; [tableController loadTableFromResourcePath:@"/JSON/users.json" usingBlock:^(RKObjectLoader *objectLoader) { objectLoader.objectMapping = [RKObjectMapping mappingForClass:[RKTestUser class] usingBlock:^(RKObjectMapping *mapping) { [mapping mapAttributes:@"name", nil]; }]; }]; [delegate waitForLoad]; assertThatBool([tableController isLoaded], is(equalToBool(YES))); assertThatInt(tableController.sectionCount, is(equalToInt(3))); assertThatInt(tableController.rowCount, is(equalToInt(3))); } - (void)testLoadingACollectionOfObjectsIntoSectionsAndThenLoadingAnEmptyCollectionChangesTableToEmpty { RKObjectManager *objectManager = [RKTestFactory objectManager]; objectManager.client.cachePolicy = RKRequestCachePolicyNone; RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; tableController.objectManager = objectManager; [tableController mapObjectsWithClass:[RKTestUser class] toTableCellsWithMapping:[RKTableViewCellMapping cellMappingUsingBlock:^(RKTableViewCellMapping *mapping) { mapping.cellClass = [RKTestUserTableViewCell class]; [mapping mapKeyPath:@"name" toAttribute:@"textLabel.text"]; [mapping mapKeyPath:@"nickName" toAttribute:@"detailTextLabel.text"]; }]]; tableController.sectionNameKeyPath = @"name"; RKTableControllerTestDelegate *delegate = [RKTableControllerTestDelegate tableControllerDelegate]; delegate.timeout = 10; tableController.delegate = delegate; [tableController loadTableFromResourcePath:@"/JSON/users.json" usingBlock:^(RKObjectLoader *objectLoader) { objectLoader.objectMapping = [RKObjectMapping mappingForClass:[RKTestUser class] usingBlock:^(RKObjectMapping *mapping) { [mapping mapAttributes:@"name", nil]; }]; }]; [delegate waitForLoad]; assertThatBool([tableController isLoaded], is(equalToBool(YES))); assertThatInt(tableController.sectionCount, is(equalToInt(3))); assertThatInt(tableController.rowCount, is(equalToInt(3))); delegate = [RKTableControllerTestDelegate tableControllerDelegate]; delegate.timeout = 10; tableController.delegate = delegate; [tableController loadTableFromResourcePath:@"/204" usingBlock:^(RKObjectLoader *objectLoader) { objectLoader.objectMapping = [RKObjectMapping mappingForClass:[RKTestUser class] usingBlock:^(RKObjectMapping *mapping) { [mapping mapAttributes:@"name", nil]; }]; }]; [delegate waitForLoad]; assertThatBool([tableController isLoaded], is(equalToBool(YES))); assertThatBool([tableController isEmpty], is(equalToBool(YES))); } #pragma mark - RKTableViewDelegate Tests - (void)testNotifyTheDelegateWhenLoadingStarts { RKObjectManager *objectManager = [RKTestFactory objectManager]; RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; tableController.objectManager = objectManager; [tableController mapObjectsWithClass:[RKTestUser class] toTableCellsWithMapping:[RKTableViewCellMapping cellMappingUsingBlock:^(RKTableViewCellMapping *mapping) { mapping.cellClass = [RKTestUserTableViewCell class]; [mapping mapKeyPath:@"name" toAttribute:@"textLabel.text"]; [mapping mapKeyPath:@"nickName" toAttribute:@"detailTextLabel.text"]; }]]; id mockDelegate = [OCMockObject partialMockForObject:[RKTableControllerTestDelegate new]]; [[[mockDelegate expect] andForwardToRealObject] tableControllerDidStartLoad:tableController]; tableController.delegate = mockDelegate; [tableController loadTableFromResourcePath:@"/JSON/users.json" usingBlock:^(RKObjectLoader *objectLoader) { objectLoader.objectMapping = [RKObjectMapping mappingForClass:[RKTestUser class] usingBlock:^(RKObjectMapping *mapping) { [mapping mapAttributes:@"name", nil]; }]; }]; [mockDelegate waitForLoad]; STAssertNoThrow([mockDelegate verify], nil); } - (void)testNotifyTheDelegateWhenLoadingFinishes { RKObjectManager *objectManager = [RKTestFactory objectManager]; RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; tableController.objectManager = objectManager; [tableController mapObjectsWithClass:[RKTestUser class] toTableCellsWithMapping:[RKTableViewCellMapping cellMappingUsingBlock:^(RKTableViewCellMapping *mapping) { mapping.cellClass = [RKTestUserTableViewCell class]; [mapping mapKeyPath:@"name" toAttribute:@"textLabel.text"]; [mapping mapKeyPath:@"nickName" toAttribute:@"detailTextLabel.text"]; }]]; RKTableControllerTestDelegate *delegate = [RKTableControllerTestDelegate new]; id mockDelegate = [OCMockObject partialMockForObject:delegate]; [[[mockDelegate expect] andForwardToRealObject] tableControllerDidFinishLoad:tableController]; tableController.delegate = mockDelegate; [tableController loadTableFromResourcePath:@"/JSON/users.json" usingBlock:^(RKObjectLoader *objectLoader) { objectLoader.objectMapping = [RKObjectMapping mappingForClass:[RKTestUser class] usingBlock:^(RKObjectMapping *mapping) { [mapping mapAttributes:@"name", nil]; }]; }]; [mockDelegate waitForLoad]; STAssertNoThrow([mockDelegate verify], nil); } - (void)testNotifyTheDelegateOnDidFinalizeLoad { RKObjectManager *objectManager = [RKTestFactory objectManager]; RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; tableController.objectManager = objectManager; [tableController mapObjectsWithClass:[RKTestUser class] toTableCellsWithMapping:[RKTableViewCellMapping cellMappingUsingBlock:^(RKTableViewCellMapping *mapping) { mapping.cellClass = [RKTestUserTableViewCell class]; [mapping mapKeyPath:@"name" toAttribute:@"textLabel.text"]; [mapping mapKeyPath:@"nickName" toAttribute:@"detailTextLabel.text"]; }]]; RKTableControllerTestDelegate *delegate = [RKTableControllerTestDelegate new]; id mockDelegate = [OCMockObject partialMockForObject:delegate]; [[mockDelegate expect] tableControllerDidFinalizeLoad:tableController]; tableController.delegate = mockDelegate; [tableController loadTableFromResourcePath:@"/JSON/users.json" usingBlock:^(RKObjectLoader *objectLoader) { objectLoader.objectMapping = [RKObjectMapping mappingForClass:[RKTestUser class] usingBlock:^(RKObjectMapping *mapping) { [mapping mapAttributes:@"name", nil]; }]; }]; [mockDelegate waitForLoad]; STAssertNoThrow([mockDelegate verify], nil); } - (void)testNotifyTheDelegateWhenAnErrorOccurs { RKObjectManager *objectManager = [RKTestFactory objectManager]; RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; tableController.objectManager = objectManager; [tableController mapObjectsWithClass:[RKTestUser class] toTableCellsWithMapping:[RKTableViewCellMapping cellMappingUsingBlock:^(RKTableViewCellMapping *mapping) { mapping.cellClass = [RKTestUserTableViewCell class]; [mapping mapKeyPath:@"name" toAttribute:@"textLabel.text"]; [mapping mapKeyPath:@"nickName" toAttribute:@"detailTextLabel.text"]; }]]; RKTableControllerTestDelegate *delegate = [RKTableControllerTestDelegate new]; id mockDelegate = [OCMockObject partialMockForObject:delegate]; [[[mockDelegate expect] andForwardToRealObject] tableController:tableController didFailLoadWithError:OCMOCK_ANY]; tableController.delegate = mockDelegate; [tableController loadTableFromResourcePath:@"/fail" usingBlock:^(RKObjectLoader *objectLoader) { objectLoader.objectMapping = [RKObjectMapping mappingForClass:[RKTestUser class] usingBlock:^(RKObjectMapping *mapping) { [mapping mapAttributes:@"name", nil]; }]; }]; [mockDelegate waitForLoad]; STAssertNoThrow([mockDelegate verify], nil); } - (void)testNotifyTheDelegateWhenAnEmptyCollectionIsLoaded { RKObjectManager *objectManager = [RKTestFactory objectManager]; objectManager.client.cachePolicy = RKRequestCachePolicyNone; RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; tableController.objectManager = objectManager; [tableController mapObjectsWithClass:[RKTestUser class] toTableCellsWithMapping:[RKTableViewCellMapping cellMappingUsingBlock:^(RKTableViewCellMapping *mapping) { mapping.cellClass = [RKTestUserTableViewCell class]; [mapping mapKeyPath:@"name" toAttribute:@"textLabel.text"]; [mapping mapKeyPath:@"nickName" toAttribute:@"detailTextLabel.text"]; }]]; RKTableControllerTestDelegate *delegate = [RKTableControllerTestDelegate new]; delegate.timeout = 5; id mockDelegate = [OCMockObject partialMockForObject:delegate]; [[[mockDelegate expect] andForwardToRealObject] tableControllerDidBecomeEmpty:tableController]; tableController.delegate = mockDelegate; [tableController loadTableFromResourcePath:@"/empty/array" usingBlock:^(RKObjectLoader *objectLoader) { objectLoader.objectMapping = [RKObjectMapping mappingForClass:[RKTestUser class] usingBlock:^(RKObjectMapping *mapping) { [mapping mapAttributes:@"name", nil]; }]; }]; [mockDelegate waitForLoad]; STAssertNoThrow([mockDelegate verify], nil); } - (void)testNotifyTheDelegateWhenModelWillLoadWithObjectLoader { RKObjectManager *objectManager = [RKTestFactory objectManager]; RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; tableController.objectManager = objectManager; [tableController mapObjectsWithClass:[RKTestUser class] toTableCellsWithMapping:[RKTableViewCellMapping cellMappingUsingBlock:^(RKTableViewCellMapping *mapping) { mapping.cellClass = [RKTestUserTableViewCell class]; [mapping mapKeyPath:@"name" toAttribute:@"textLabel.text"]; [mapping mapKeyPath:@"nickName" toAttribute:@"detailTextLabel.text"]; }]]; RKTableControllerTestDelegate *delegate = [RKTableControllerTestDelegate new]; id mockDelegate = [OCMockObject partialMockForObject:delegate]; [[[mockDelegate expect] andForwardToRealObject] tableController:tableController willLoadTableWithObjectLoader:OCMOCK_ANY]; tableController.delegate = mockDelegate; [tableController loadTableFromResourcePath:@"/empty/array" usingBlock:^(RKObjectLoader *objectLoader) { objectLoader.objectMapping = [RKObjectMapping mappingForClass:[RKTestUser class] usingBlock:^(RKObjectMapping *mapping) { [mapping mapAttributes:@"name", nil]; }]; }]; [mockDelegate waitForLoad]; STAssertNoThrow([mockDelegate verify], nil); } - (void)testNotifyTheDelegateWhenModelDidLoadWithObjectLoader { RKObjectManager *objectManager = [RKTestFactory objectManager]; RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; tableController.objectManager = objectManager; [tableController mapObjectsWithClass:[RKTestUser class] toTableCellsWithMapping:[RKTableViewCellMapping cellMappingUsingBlock:^(RKTableViewCellMapping *mapping) { mapping.cellClass = [RKTestUserTableViewCell class]; [mapping mapKeyPath:@"name" toAttribute:@"textLabel.text"]; [mapping mapKeyPath:@"nickName" toAttribute:@"detailTextLabel.text"]; }]]; RKTableControllerTestDelegate *delegate = [RKTableControllerTestDelegate new]; id mockDelegate = [OCMockObject partialMockForObject:delegate]; [[[mockDelegate expect] andForwardToRealObject] tableController:tableController didLoadTableWithObjectLoader:OCMOCK_ANY]; tableController.delegate = mockDelegate; [tableController loadTableFromResourcePath:@"/empty/array" usingBlock:^(RKObjectLoader *objectLoader) { objectLoader.objectMapping = [RKObjectMapping mappingForClass:[RKTestUser class] usingBlock:^(RKObjectMapping *mapping) { [mapping mapAttributes:@"name", nil]; }]; }]; [mockDelegate waitForLoad]; STAssertNoThrow([mockDelegate verify], nil); } - (void)testNotifyTheDelegateWhenModelDidCancelLoad { RKObjectManager *objectManager = [RKTestFactory objectManager]; RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; tableController.objectManager = objectManager; [tableController mapObjectsWithClass:[RKTestUser class] toTableCellsWithMapping:[RKTableViewCellMapping cellMappingUsingBlock:^(RKTableViewCellMapping *mapping) { mapping.cellClass = [RKTestUserTableViewCell class]; [mapping mapKeyPath:@"name" toAttribute:@"textLabel.text"]; [mapping mapKeyPath:@"nickName" toAttribute:@"detailTextLabel.text"]; }]]; RKTableControllerTestDelegate *delegate = [RKTableControllerTestDelegate new]; id mockDelegate = [OCMockObject partialMockForObject:delegate]; [[[mockDelegate expect] andForwardToRealObject] tableControllerDidCancelLoad:tableController]; tableController.delegate = mockDelegate; [tableController loadTableFromResourcePath:@"/empty/array" usingBlock:^(RKObjectLoader *objectLoader) { objectLoader.objectMapping = [RKObjectMapping mappingForClass:[RKTestUser class] usingBlock:^(RKObjectMapping *mapping) { [mapping mapAttributes:@"name", nil]; }]; }]; [tableController cancelLoad]; STAssertNoThrow([mockDelegate verify], nil); } - (void)testNotifyTheDelegateWhenDidEndEditingARow { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; RKTableItem *tableItem = [RKTableItem tableItem]; RKTableControllerTestDelegate *delegate = [RKTableControllerTestDelegate new]; id mockDelegate = [OCMockObject partialMockForObject:delegate]; [[[mockDelegate expect] andForwardToRealObject] tableController:tableController didEndEditing:OCMOCK_ANY atIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]]; tableController.delegate = mockDelegate; [tableController loadTableItems:[NSArray arrayWithObject:tableItem]]; [tableController tableView:tableController.tableView didEndEditingRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]]; STAssertNoThrow([mockDelegate verify], nil); } - (void)testNotifyTheDelegateWhenWillBeginEditingARow { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; RKTableItem *tableItem = [RKTableItem tableItem]; RKTableControllerTestDelegate *delegate = [RKTableControllerTestDelegate new]; id mockDelegate = [OCMockObject partialMockForObject:delegate]; [[[mockDelegate expect] andForwardToRealObject] tableController:tableController willBeginEditing:OCMOCK_ANY atIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]]; tableController.delegate = mockDelegate; [tableController loadTableItems:[NSArray arrayWithObject:tableItem]]; [tableController tableView:tableController.tableView willBeginEditingRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]]; STAssertNoThrow([mockDelegate verify], nil); } - (void)testNotifyTheDelegateWhenAnObjectIsInserted { NSArray *objects = [NSArray arrayWithObject:@"first object"]; RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; RKTableControllerTestDelegate *delegate = [RKTableControllerTestDelegate new]; id mockDelegate = [OCMockObject partialMockForObject:delegate]; [[[mockDelegate expect] andForwardToRealObject] tableController:tableController didInsertObject:@"first object" atIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]]; [[[mockDelegate expect] andForwardToRealObject] tableController:tableController didInsertObject:@"new object" atIndexPath:[NSIndexPath indexPathForRow:1 inSection:0]]; tableController.delegate = mockDelegate; [tableController loadObjects:objects]; assertThat([tableController objectForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]], is(equalTo(@"first object"))); [[tableController.sections objectAtIndex:0] insertObject:@"new object" atIndex:1]; assertThat([[tableController.sections objectAtIndex:0] objectAtIndex:0], is(equalTo(@"first object"))); assertThat([[tableController.sections objectAtIndex:0] objectAtIndex:1], is(equalTo(@"new object"))); STAssertNoThrow([mockDelegate verify], nil); } - (void)testNotifyTheDelegateWhenAnObjectIsUpdated { NSArray *objects = [NSArray arrayWithObjects:@"first object", @"second object", nil]; RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; RKTableControllerTestDelegate *delegate = [RKTableControllerTestDelegate new]; id mockDelegate = [OCMockObject partialMockForObject:delegate]; [[[mockDelegate expect] andForwardToRealObject] tableController:tableController didInsertObject:@"first object" atIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]]; [[[mockDelegate expect] andForwardToRealObject] tableController:tableController didInsertObject:@"second object" atIndexPath:[NSIndexPath indexPathForRow:1 inSection:0]]; [[[mockDelegate expect] andForwardToRealObject] tableController:tableController didUpdateObject:@"new second object" atIndexPath:[NSIndexPath indexPathForRow:1 inSection:0]]; tableController.delegate = mockDelegate; [tableController loadObjects:objects]; assertThat([[tableController.sections objectAtIndex:0] objectAtIndex:0], is(equalTo(@"first object"))); assertThat([[tableController.sections objectAtIndex:0] objectAtIndex:1], is(equalTo(@"second object"))); [[tableController.sections objectAtIndex:0] replaceObjectAtIndex:1 withObject:@"new second object"]; assertThat([[tableController.sections objectAtIndex:0] objectAtIndex:1], is(equalTo(@"new second object"))); STAssertNoThrow([mockDelegate verify], nil); } - (void)testNotifyTheDelegateWhenAnObjectIsDeleted { NSArray *objects = [NSArray arrayWithObjects:@"first object", @"second object", nil]; RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; RKTableControllerTestDelegate *delegate = [RKTableControllerTestDelegate new]; id mockDelegate = [OCMockObject partialMockForObject:delegate]; [[[mockDelegate expect] andForwardToRealObject] tableController:tableController didInsertObject:@"first object" atIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]]; [[[mockDelegate expect] andForwardToRealObject] tableController:tableController didInsertObject:@"second object" atIndexPath:[NSIndexPath indexPathForRow:1 inSection:0]]; [[[mockDelegate expect] andForwardToRealObject] tableController:tableController didDeleteObject:@"second object" atIndexPath:[NSIndexPath indexPathForRow:1 inSection:0]]; tableController.delegate = mockDelegate; [tableController loadObjects:objects]; assertThat([[tableController.sections objectAtIndex:0] objectAtIndex:0], is(equalTo(@"first object"))); assertThat([[tableController.sections objectAtIndex:0] objectAtIndex:1], is(equalTo(@"second object"))); [[tableController.sections objectAtIndex:0] removeObjectAtIndex:1]; assertThat([[tableController.sections objectAtIndex:0] objectAtIndex:0], is(equalTo(@"first object"))); STAssertNoThrow([mockDelegate verify], nil); } - (void)testNotifyTheDelegateWhenObjectsAreLoadedInASection { RKObjectManager *objectManager = [RKTestFactory objectManager]; RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; tableController.objectManager = objectManager; [tableController mapObjectsWithClass:[RKTestUser class] toTableCellsWithMapping:[RKTableViewCellMapping cellMappingUsingBlock:^(RKTableViewCellMapping *mapping) { mapping.cellClass = [RKTestUserTableViewCell class]; [mapping mapKeyPath:@"name" toAttribute:@"textLabel.text"]; [mapping mapKeyPath:@"nickName" toAttribute:@"detailTextLabel.text"]; }]]; RKTableControllerTestDelegate *delegate = [RKTableControllerTestDelegate new]; id mockDelegate = [OCMockObject partialMockForObject:delegate]; [[mockDelegate expect] tableController:tableController didLoadObjects:OCMOCK_ANY inSection:OCMOCK_ANY]; tableController.delegate = mockDelegate; [tableController loadTableFromResourcePath:@"/JSON/users.json" usingBlock:^(RKObjectLoader *objectLoader) { objectLoader.objectMapping = [RKObjectMapping mappingForClass:[RKTestUser class] usingBlock:^(RKObjectMapping *mapping) { [mapping mapAttributes:@"name", nil]; }]; }]; [mockDelegate waitForLoad]; STAssertNoThrow([mockDelegate verify], nil); } - (void)testDelegateIsNotifiedOfWillDisplayCellForObjectAtIndexPath { RKObjectManager *objectManager = [RKTestFactory objectManager]; RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; tableController.objectManager = objectManager; [tableController mapObjectsWithClass:[RKTestUser class] toTableCellsWithMapping:[RKTableViewCellMapping cellMappingUsingBlock:^(RKTableViewCellMapping *mapping) { mapping.cellClass = [RKTestUserTableViewCell class]; [mapping mapKeyPath:@"name" toAttribute:@"textLabel.text"]; }]]; RKTableControllerTestDelegate *delegate = [RKTableControllerTestDelegate new]; id mockDelegate = [OCMockObject partialMockForObject:delegate]; [[[mockDelegate expect] andForwardToRealObject] tableController:tableController willLoadTableWithObjectLoader:OCMOCK_ANY]; tableController.delegate = mockDelegate; [tableController loadTableFromResourcePath:@"/JSON/users.json" usingBlock:^(RKObjectLoader *objectLoader) { objectLoader.objectMapping = [RKObjectMapping mappingForClass:[RKTestUser class] usingBlock:^(RKObjectMapping *mapping) { [mapping mapAttributes:@"name", nil]; }]; }]; [[mockDelegate expect] tableController:tableController willDisplayCell:OCMOCK_ANY forObject:OCMOCK_ANY atIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]]; [[mockDelegate expect] tableController:tableController willDisplayCell:OCMOCK_ANY forObject:OCMOCK_ANY atIndexPath:[NSIndexPath indexPathForRow:1 inSection:0]]; [[mockDelegate expect] tableController:tableController willDisplayCell:OCMOCK_ANY forObject:OCMOCK_ANY atIndexPath:[NSIndexPath indexPathForRow:2 inSection:0]]; [[[UIApplication sharedApplication].windows objectAtIndex:0] setRootViewController:viewController]; [mockDelegate waitForLoad]; STAssertNoThrow([mockDelegate verify], nil); } - (void)testDelegateIsNotifiedOfDidSelectRowForObjectAtIndexPath { RKObjectManager *objectManager = [RKTestFactory objectManager]; RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; tableController.objectManager = objectManager; [tableController mapObjectsWithClass:[RKTestUser class] toTableCellsWithMapping:[RKTableViewCellMapping cellMappingUsingBlock:^(RKTableViewCellMapping *mapping) { mapping.cellClass = [RKTestUserTableViewCell class]; [mapping mapKeyPath:@"name" toAttribute:@"textLabel.text"]; }]]; RKTableControllerTestDelegate *delegate = [RKTableControllerTestDelegate new]; id mockDelegate = [OCMockObject partialMockForObject:delegate]; [[[mockDelegate expect] andForwardToRealObject] tableController:tableController willLoadTableWithObjectLoader:OCMOCK_ANY]; tableController.delegate = mockDelegate; [tableController loadTableFromResourcePath:@"/JSON/users.json" usingBlock:^(RKObjectLoader *objectLoader) { objectLoader.objectMapping = [RKObjectMapping mappingForClass:[RKTestUser class] usingBlock:^(RKObjectMapping *mapping) { [mapping mapAttributes:@"name", nil]; }]; }]; [[mockDelegate expect] tableController:tableController didSelectCell:OCMOCK_ANY forObject:OCMOCK_ANY atIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]]; [[[UIApplication sharedApplication].windows objectAtIndex:0] setRootViewController:viewController]; [mockDelegate waitForLoad]; [tableController tableView:tableController.tableView didSelectRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]]; STAssertNoThrow([mockDelegate verify], nil); } #pragma mark - Notifications - (void)testPostANotificationWhenLoadingStarts { RKObjectManager *objectManager = [RKTestFactory objectManager]; RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; tableController.objectManager = objectManager; [tableController mapObjectsWithClass:[RKTestUser class] toTableCellsWithMapping:[RKTableViewCellMapping cellMappingUsingBlock:^(RKTableViewCellMapping *mapping) { mapping.cellClass = [RKTestUserTableViewCell class]; [mapping mapKeyPath:@"name" toAttribute:@"textLabel.text"]; [mapping mapKeyPath:@"nickName" toAttribute:@"detailTextLabel.text"]; }]]; id observerMock = [OCMockObject observerMock]; [[NSNotificationCenter defaultCenter] addMockObserver:observerMock name:RKTableControllerDidStartLoadNotification object:tableController]; [[observerMock expect] notificationWithName:RKTableControllerDidStartLoadNotification object:tableController]; RKTableControllerTestDelegate *delegate = [RKTableControllerTestDelegate new]; tableController.delegate = delegate; [tableController loadTableFromResourcePath:@"/JSON/users.json" usingBlock:^(RKObjectLoader *objectLoader) { objectLoader.objectMapping = [RKObjectMapping mappingForClass:[RKTestUser class] usingBlock:^(RKObjectMapping *mapping) { [mapping mapAttributes:@"name", nil]; }]; }]; [delegate waitForLoad]; [observerMock verify]; } - (void)testPostANotificationWhenLoadingFinishes { RKObjectManager *objectManager = [RKTestFactory objectManager]; RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; tableController.objectManager = objectManager; [tableController mapObjectsWithClass:[RKTestUser class] toTableCellsWithMapping:[RKTableViewCellMapping cellMappingUsingBlock:^(RKTableViewCellMapping *mapping) { mapping.cellClass = [RKTestUserTableViewCell class]; [mapping mapKeyPath:@"name" toAttribute:@"textLabel.text"]; [mapping mapKeyPath:@"nickName" toAttribute:@"detailTextLabel.text"]; }]]; id observerMock = [OCMockObject observerMock]; [[NSNotificationCenter defaultCenter] addMockObserver:observerMock name:RKTableControllerDidFinishLoadNotification object:tableController]; [[observerMock expect] notificationWithName:RKTableControllerDidFinishLoadNotification object:tableController]; RKTableControllerTestDelegate *delegate = [RKTableControllerTestDelegate new]; tableController.delegate = delegate; [tableController loadTableFromResourcePath:@"/JSON/users.json" usingBlock:^(RKObjectLoader *objectLoader) { objectLoader.objectMapping = [RKObjectMapping mappingForClass:[RKTestUser class] usingBlock:^(RKObjectMapping *mapping) { [mapping mapAttributes:@"name", nil]; }]; }]; [delegate waitForLoad]; [observerMock verify]; } - (void)testPostANotificationWhenObjectsAreLoaded { RKObjectManager *objectManager = [RKTestFactory objectManager]; RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; tableController.objectManager = objectManager; [tableController mapObjectsWithClass:[RKTestUser class] toTableCellsWithMapping:[RKTableViewCellMapping cellMappingUsingBlock:^(RKTableViewCellMapping *mapping) { mapping.cellClass = [RKTestUserTableViewCell class]; [mapping mapKeyPath:@"name" toAttribute:@"textLabel.text"]; [mapping mapKeyPath:@"nickName" toAttribute:@"detailTextLabel.text"]; }]]; id observerMock = [OCMockObject observerMock]; [[NSNotificationCenter defaultCenter] addMockObserver:observerMock name:RKTableControllerDidLoadObjectsNotification object:tableController]; [[observerMock expect] notificationWithName:RKTableControllerDidLoadObjectsNotification object:tableController]; RKTableControllerTestDelegate *delegate = [RKTableControllerTestDelegate new]; tableController.delegate = delegate; [tableController loadTableFromResourcePath:@"/JSON/users.json" usingBlock:^(RKObjectLoader *objectLoader) { objectLoader.objectMapping = [RKObjectMapping mappingForClass:[RKTestUser class] usingBlock:^(RKObjectMapping *mapping) { [mapping mapAttributes:@"name", nil]; }]; }]; [delegate waitForLoad]; [observerMock verify]; } - (void)testPostANotificationWhenAnErrorOccurs { RKObjectManager *objectManager = [RKTestFactory objectManager]; RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; tableController.objectManager = objectManager; [tableController mapObjectsWithClass:[RKTestUser class] toTableCellsWithMapping:[RKTableViewCellMapping cellMappingUsingBlock:^(RKTableViewCellMapping *mapping) { mapping.cellClass = [RKTestUserTableViewCell class]; [mapping mapKeyPath:@"name" toAttribute:@"textLabel.text"]; [mapping mapKeyPath:@"nickName" toAttribute:@"detailTextLabel.text"]; }]]; id observerMock = [OCMockObject observerMock]; [[NSNotificationCenter defaultCenter] addMockObserver:observerMock name:RKTableControllerDidLoadErrorNotification object:tableController]; [[observerMock expect] notificationWithName:RKTableControllerDidLoadErrorNotification object:tableController userInfo:OCMOCK_ANY]; RKTableControllerTestDelegate *delegate = [RKTableControllerTestDelegate new]; tableController.delegate = delegate; [tableController loadTableFromResourcePath:@"/fail" usingBlock:^(RKObjectLoader *objectLoader) { objectLoader.objectMapping = [RKObjectMapping mappingForClass:[RKTestUser class] usingBlock:^(RKObjectMapping *mapping) { [mapping mapAttributes:@"name", nil]; }]; }]; [delegate waitForLoad]; [observerMock verify]; } - (void)testPostANotificationWhenAnEmptyCollectionIsLoaded { RKObjectManager *objectManager = [RKTestFactory objectManager]; objectManager.client.cachePolicy = RKRequestCachePolicyNone; RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; tableController.objectManager = objectManager; [tableController mapObjectsWithClass:[RKTestUser class] toTableCellsWithMapping:[RKTableViewCellMapping cellMappingUsingBlock:^(RKTableViewCellMapping *mapping) { mapping.cellClass = [RKTestUserTableViewCell class]; [mapping mapKeyPath:@"name" toAttribute:@"textLabel.text"]; [mapping mapKeyPath:@"nickName" toAttribute:@"detailTextLabel.text"]; }]]; id observerMock = [OCMockObject observerMock]; [[NSNotificationCenter defaultCenter] addMockObserver:observerMock name:RKTableControllerDidLoadEmptyNotification object:tableController]; [[observerMock expect] notificationWithName:RKTableControllerDidLoadEmptyNotification object:tableController]; RKTableControllerTestDelegate *delegate = [RKTableControllerTestDelegate new]; tableController.delegate = delegate; [tableController loadTableFromResourcePath:@"/empty/array" usingBlock:^(RKObjectLoader *objectLoader) { objectLoader.objectMapping = [RKObjectMapping mappingForClass:[RKTestUser class] usingBlock:^(RKObjectMapping *mapping) { [mapping mapAttributes:@"name", nil]; }]; }]; [delegate waitForLoad]; [observerMock verify]; } #pragma mark - State Transitions - (void)testInitializesToNotYetLoadedState { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; assertThatBool(tableController.state == RKTableControllerStateNotYetLoaded, is(equalToBool(YES))); } - (void)testInitialLoadSetsStateToLoading { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; assertThatBool([tableController isLoaded], is(equalToBool(NO))); assertThatBool([tableController isLoading], is(equalToBool(NO))); id mockLoader = [OCMockObject mockForClass:[RKObjectLoader class]]; [tableController requestDidStartLoad:mockLoader]; assertThatBool([tableController isLoading], is(equalToBool(YES))); assertThatBool([tableController isLoaded], is(equalToBool(NO))); } - (void)testSuccessfulLoadSetsStateToNormal { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; assertThatBool([tableController isLoaded], is(equalToBool(NO))); assertThatBool([tableController isLoading], is(equalToBool(NO))); id mockLoader = [OCMockObject mockForClass:[RKObjectLoader class]]; [tableController objectLoader:mockLoader didLoadObjects:[NSArray arrayWithObject:@"test"]]; assertThatBool([tableController isLoading], is(equalToBool(NO))); assertThatBool([tableController isLoaded], is(equalToBool(YES))); assertThatInteger(tableController.state, is(equalToInteger(RKTableControllerStateNormal))); } - (void)testErrorLoadsSetsStateToError { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; assertThatBool([tableController isLoaded], is(equalToBool(NO))); assertThatBool([tableController isLoading], is(equalToBool(NO))); id mockLoader = [OCMockObject mockForClass:[RKObjectLoader class]]; NSError *error = [NSError errorWithDomain:@"Test" code:1234 userInfo:nil]; [tableController objectLoader:mockLoader didFailWithError:error]; assertThatBool([tableController isLoaded], is(equalToBool(YES))); assertThatBool([tableController isError], is(equalToBool(YES))); assertThatBool([tableController isEmpty], is(equalToBool(YES))); } - (void)testSecondaryLoadAfterErrorSetsStateToErrorAndLoading { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; assertThatBool([tableController isLoaded], is(equalToBool(NO))); assertThatBool([tableController isLoading], is(equalToBool(NO))); id mockLoader = [OCMockObject mockForClass:[RKObjectLoader class]]; NSError *error = [NSError errorWithDomain:@"Test" code:1234 userInfo:nil]; [tableController objectLoader:mockLoader didFailWithError:error]; assertThatBool([tableController isLoaded], is(equalToBool(YES))); assertThatBool([tableController isError], is(equalToBool(YES))); assertThatBool([tableController isEmpty], is(equalToBool(YES))); [tableController requestDidStartLoad:mockLoader]; assertThatBool([tableController isLoading], is(equalToBool(YES))); assertThatBool([tableController isError], is(equalToBool(YES))); } - (void)testEmptyLoadSetsStateToEmpty { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; [tableController loadEmpty]; assertThatBool([tableController isEmpty], is(equalToBool(YES))); } - (void)testSecondaryLoadAfterEmptySetsStateToEmptyAndLoading { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; [tableController loadEmpty]; assertThatBool([tableController isEmpty], is(equalToBool(YES))); assertThatBool([tableController isLoading], is(equalToBool(NO))); id mockLoader = [OCMockObject mockForClass:[RKObjectLoader class]]; [tableController requestDidStartLoad:mockLoader]; assertThatBool([tableController isLoading], is(equalToBool(YES))); assertThatBool([tableController isEmpty], is(equalToBool(YES))); } - (void)testTransitionToOfflineAfterLoadSetsStateToOfflineAndLoaded { RKObjectManager *objectManager = [RKTestFactory objectManager]; id mockManager = [OCMockObject partialMockForObject:objectManager]; BOOL isOnline = YES; [[[mockManager stub] andReturnValue:OCMOCK_VALUE(isOnline)] isOnline]; RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; tableController.objectManager = mockManager; [tableController loadEmpty]; assertThatBool([tableController isEmpty], is(equalToBool(YES))); assertThatBool([tableController isLoading], is(equalToBool(NO))); assertThatBool([tableController isOffline], is(equalToBool(NO))); id mockLoader = [OCMockObject mockForClass:[RKObjectLoader class]]; [tableController requestDidStartLoad:mockLoader]; assertThatBool([tableController isLoading], is(equalToBool(YES))); assertThatBool([tableController isEmpty], is(equalToBool(YES))); isOnline = NO; id mockManager2 = [OCMockObject partialMockForObject:objectManager]; [[[mockManager2 stub] andReturnValue:OCMOCK_VALUE(isOnline)] isOnline]; tableController.objectManager = mockManager2; [[NSNotificationCenter defaultCenter] postNotificationName:RKObjectManagerDidBecomeOfflineNotification object:tableController.objectManager]; assertThatBool(tableController.isOffline, is(equalToBool(YES))); } #pragma mark - State Views - (void)testPermitYouToOverlayAnImageOnTheTable { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; UIImage *image = [RKTestFixture imageWithContentsOfFixture:@"blake.png"]; [tableController showImageInOverlay:image]; UIImageView *imageView = tableController.stateOverlayImageView; assertThat(imageView, isNot(nilValue())); assertThat(imageView.image, is(equalTo(image))); } - (void)testPermitYouToRemoveAnImageOverlayFromTheTable { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; UIImage *image = [RKTestFixture imageWithContentsOfFixture:@"blake.png"]; [tableController showImageInOverlay:image]; assertThat([tableController.tableView.superview subviews], isNot(empty())); [tableController removeImageOverlay]; assertThat([tableController.tableView.superview subviews], is(nilValue())); } - (void)testTriggerDisplayOfTheErrorViewOnTransitionToErrorState { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; UIImage *image = [RKTestFixture imageWithContentsOfFixture:@"blake.png"]; tableController.imageForError = image; id mockError = [OCMockObject mockForClass:[NSError class]]; [tableController objectLoader:nil didFailWithError:mockError]; assertThatBool([tableController isError], is(equalToBool(YES))); UIImageView *imageView = tableController.stateOverlayImageView; assertThat(imageView, isNot(nilValue())); assertThat(imageView.image, is(equalTo(image))); } - (void)testTriggerHidingOfTheErrorViewOnTransitionOutOfTheErrorState { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; UIImage *image = [RKTestFixture imageWithContentsOfFixture:@"blake.png"]; tableController.imageForError = image; id mockError = [OCMockObject niceMockForClass:[NSError class]]; [tableController objectLoader:nil didFailWithError:mockError]; assertThatBool([tableController isError], is(equalToBool(YES))); UIImageView *imageView = tableController.stateOverlayImageView; assertThat(imageView, isNot(nilValue())); assertThat(imageView.image, is(equalTo(image))); [tableController loadTableItems:[NSArray arrayWithObject:[RKTableItem tableItem]]]; assertThat(tableController.error, is(nilValue())); assertThat(tableController.stateOverlayImageView.image, is(nilValue())); } - (void)testTriggerDisplayOfTheEmptyViewOnTransitionToEmptyState { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; UIImage *image = [RKTestFixture imageWithContentsOfFixture:@"blake.png"]; tableController.imageForEmpty = image; [tableController loadEmpty]; assertThatBool([tableController isEmpty], is(equalToBool(YES))); UIImageView *imageView = tableController.stateOverlayImageView; assertThat(imageView, isNot(nilValue())); assertThat(imageView.image, is(equalTo(image))); } - (void)testTriggerHidingOfTheEmptyViewOnTransitionOutOfTheEmptyState { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; UIImage *image = [RKTestFixture imageWithContentsOfFixture:@"blake.png"]; tableController.imageForEmpty = image; [tableController loadEmpty]; assertThatBool([tableController isEmpty], is(equalToBool(YES))); UIImageView *imageView = tableController.stateOverlayImageView; assertThat(imageView, isNot(nilValue())); assertThat(imageView.image, is(equalTo(image))); [tableController loadTableItems:[NSArray arrayWithObject:[RKTableItem tableItem]]]; assertThat(tableController.stateOverlayImageView.image, is(nilValue())); } - (void)testTriggerDisplayOfTheLoadingViewOnTransitionToTheLoadingState { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; UIActivityIndicatorView *spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray]; tableController.loadingView = spinner; [tableController setValue:[NSNumber numberWithBool:YES] forKey:@"loading"]; UIView *view = [tableController.tableOverlayView.subviews lastObject]; assertThatBool(view == spinner, is(equalToBool(YES))); } - (void)testTriggerHidingOfTheLoadingViewOnTransitionOutOfTheLoadingState { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; UIActivityIndicatorView *spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray]; tableController.loadingView = spinner; [tableController setValue:[NSNumber numberWithBool:YES] forKey:@"loading"]; UIView *loadingView = [tableController.tableOverlayView.subviews lastObject]; assertThatBool(loadingView == spinner, is(equalToBool(YES))); [tableController setValue:[NSNumber numberWithBool:NO] forKey:@"loading"]; loadingView = [tableController.tableOverlayView.subviews lastObject]; assertThat(loadingView, is(nilValue())); } #pragma mark - Header, Footer, and Empty Rows - (void)testShowHeaderRows { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; [tableController addHeaderRowForItem:[RKTableItem tableItemUsingBlock:^(RKTableItem *tableItem) { tableItem.text = @"Header"; tableItem.cellMapping = [RKTableViewCellMapping cellMappingUsingBlock:^(RKTableViewCellMapping *cellMapping) { [cellMapping addDefaultMappings]; }]; }]]; NSArray *tableItems = [RKTableItem tableItemsFromStrings:@"One", @"Two", @"Three", nil]; [tableController loadTableItems:tableItems]; assertThatBool([tableController isLoaded], is(equalToBool(YES))); assertThatInt(tableController.rowCount, is(equalToInt(4))); UITableViewCell *cellOne = [tableController tableView:tableController.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]]; UITableViewCell *cellTwo = [tableController tableView:tableController.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:1 inSection:0]]; UITableViewCell *cellThree = [tableController tableView:tableController.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:2 inSection:0]]; UITableViewCell *cellFour = [tableController tableView:tableController.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:3 inSection:0]]; assertThat(cellOne.textLabel.text, is(equalTo(@"Header"))); assertThat(cellTwo.textLabel.text, is(equalTo(@"One"))); assertThat(cellThree.textLabel.text, is(equalTo(@"Two"))); assertThat(cellFour.textLabel.text, is(equalTo(@"Three"))); [tableController tableView:tableController.tableView willDisplayCell:cellOne forRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]]; [tableController tableView:tableController.tableView willDisplayCell:cellTwo forRowAtIndexPath:[NSIndexPath indexPathForRow:1 inSection:0]]; [tableController tableView:tableController.tableView willDisplayCell:cellThree forRowAtIndexPath:[NSIndexPath indexPathForRow:2 inSection:0]]; [tableController tableView:tableController.tableView willDisplayCell:cellFour forRowAtIndexPath:[NSIndexPath indexPathForRow:3 inSection:0]]; assertThatBool(cellOne.hidden, is(equalToBool(NO))); assertThatBool(cellTwo.hidden, is(equalToBool(NO))); assertThatBool(cellThree.hidden, is(equalToBool(NO))); assertThatBool(cellFour.hidden, is(equalToBool(NO))); } - (void)testShowFooterRows { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; [tableController addFooterRowForItem:[RKTableItem tableItemUsingBlock:^(RKTableItem *tableItem) { tableItem.text = @"Footer"; tableItem.cellMapping = [RKTableViewCellMapping cellMappingUsingBlock:^(RKTableViewCellMapping *cellMapping) { [cellMapping addDefaultMappings]; }]; }]]; NSArray *tableItems = [RKTableItem tableItemsFromStrings:@"One", @"Two", @"Three", nil]; [tableController loadTableItems:tableItems]; assertThatBool([tableController isLoaded], is(equalToBool(YES))); assertThatInt(tableController.rowCount, is(equalToInt(4))); UITableViewCell *cellOne = [tableController tableView:tableController.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]]; UITableViewCell *cellTwo = [tableController tableView:tableController.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:1 inSection:0]]; UITableViewCell *cellThree = [tableController tableView:tableController.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:2 inSection:0]]; UITableViewCell *cellFour = [tableController tableView:tableController.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:3 inSection:0]]; assertThat(cellOne.textLabel.text, is(equalTo(@"One"))); assertThat(cellTwo.textLabel.text, is(equalTo(@"Two"))); assertThat(cellThree.textLabel.text, is(equalTo(@"Three"))); assertThat(cellFour.textLabel.text, is(equalTo(@"Footer"))); [tableController tableView:tableController.tableView willDisplayCell:cellOne forRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]]; [tableController tableView:tableController.tableView willDisplayCell:cellTwo forRowAtIndexPath:[NSIndexPath indexPathForRow:1 inSection:0]]; [tableController tableView:tableController.tableView willDisplayCell:cellThree forRowAtIndexPath:[NSIndexPath indexPathForRow:2 inSection:0]]; [tableController tableView:tableController.tableView willDisplayCell:cellFour forRowAtIndexPath:[NSIndexPath indexPathForRow:3 inSection:0]]; assertThatBool(cellOne.hidden, is(equalToBool(NO))); assertThatBool(cellTwo.hidden, is(equalToBool(NO))); assertThatBool(cellThree.hidden, is(equalToBool(NO))); assertThatBool(cellFour.hidden, is(equalToBool(NO))); } - (void)testHideHeaderRowsWhenEmptyWhenPropertyIsNotSet { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; [tableController addHeaderRowForItem:[RKTableItem tableItemUsingBlock:^(RKTableItem *tableItem) { tableItem.text = @"Header"; tableItem.cellMapping = [RKTableViewCellMapping cellMappingUsingBlock:^(RKTableViewCellMapping *cellMapping) { [cellMapping addDefaultMappings]; }]; }]]; tableController.showsHeaderRowsWhenEmpty = NO; [tableController loadEmpty]; assertThatBool([tableController isLoaded], is(equalToBool(YES))); assertThatInt(tableController.rowCount, is(equalToInt(1))); assertThatBool([tableController isEmpty], is(equalToBool(YES))); UITableViewCell *cellOne = [tableController tableView:tableController.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]]; assertThat(cellOne.textLabel.text, is(equalTo(@"Header"))); [tableController tableView:tableController.tableView willDisplayCell:cellOne forRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]]; assertThatBool(cellOne.hidden, is(equalToBool(YES))); } - (void)testHideFooterRowsWhenEmptyWhenPropertyIsNotSet { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; [tableController addFooterRowForItem:[RKTableItem tableItemUsingBlock:^(RKTableItem *tableItem) { tableItem.text = @"Footer"; tableItem.cellMapping = [RKTableViewCellMapping cellMappingUsingBlock:^(RKTableViewCellMapping *cellMapping) { [cellMapping addDefaultMappings]; }]; }]]; tableController.showsFooterRowsWhenEmpty = NO; [tableController loadEmpty]; assertThatBool([tableController isLoaded], is(equalToBool(YES))); assertThatInt(tableController.rowCount, is(equalToInt(1))); assertThatBool([tableController isEmpty], is(equalToBool(YES))); UITableViewCell *cellOne = [tableController tableView:tableController.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]]; assertThat(cellOne.textLabel.text, is(equalTo(@"Footer"))); [tableController tableView:tableController.tableView willDisplayCell:cellOne forRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]]; assertThatBool(cellOne.hidden, is(equalToBool(YES))); } - (void)testRemoveHeaderAndFooterCountsWhenDeterminingIsEmpty { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; [tableController addHeaderRowForItem:[RKTableItem tableItemUsingBlock:^(RKTableItem *tableItem) { tableItem.text = @"Header"; tableItem.cellMapping = [RKTableViewCellMapping cellMappingUsingBlock:^(RKTableViewCellMapping *cellMapping) { [cellMapping addDefaultMappings]; }]; }]]; [tableController addFooterRowForItem:[RKTableItem tableItemUsingBlock:^(RKTableItem *tableItem) { tableItem.text = @"Footer"; tableItem.cellMapping = [RKTableViewCellMapping cellMappingUsingBlock:^(RKTableViewCellMapping *cellMapping) { [cellMapping addDefaultMappings]; }]; }]]; [tableController setEmptyItem:[RKTableItem tableItemUsingBlock:^(RKTableItem *tableItem) { tableItem.text = @"Empty"; tableItem.cellMapping = [RKTableViewCellMapping cellMappingUsingBlock:^(RKTableViewCellMapping *cellMapping) { [cellMapping addDefaultMappings]; }]; }]]; tableController.showsFooterRowsWhenEmpty = NO; tableController.showsHeaderRowsWhenEmpty = NO; [tableController loadEmpty]; assertThatBool([tableController isLoaded], is(equalToBool(YES))); assertThatInt(tableController.rowCount, is(equalToInt(3))); assertThatBool([tableController isEmpty], is(equalToBool(YES))); } - (void)testNotShowTheEmptyItemWhenTheTableIsNotEmpty { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; [tableController addHeaderRowForItem:[RKTableItem tableItemUsingBlock:^(RKTableItem *tableItem) { tableItem.text = @"Header"; tableItem.cellMapping = [RKTableViewCellMapping cellMappingUsingBlock:^(RKTableViewCellMapping *cellMapping) { [cellMapping addDefaultMappings]; }]; }]]; [tableController addFooterRowForItem:[RKTableItem tableItemUsingBlock:^(RKTableItem *tableItem) { tableItem.text = @"Footer"; tableItem.cellMapping = [RKTableViewCellMapping cellMappingUsingBlock:^(RKTableViewCellMapping *cellMapping) { [cellMapping addDefaultMappings]; }]; }]]; [tableController setEmptyItem:[RKTableItem tableItemUsingBlock:^(RKTableItem *tableItem) { tableItem.text = @"Empty"; tableItem.cellMapping = [RKTableViewCellMapping cellMappingUsingBlock:^(RKTableViewCellMapping *cellMapping) { [cellMapping addDefaultMappings]; }]; }]]; NSArray *tableItems = [RKTableItem tableItemsFromStrings:@"One", @"Two", @"Three", nil]; [tableController loadTableItems:tableItems]; assertThatBool([tableController isLoaded], is(equalToBool(YES))); assertThatInt(tableController.rowCount, is(equalToInt(6))); UITableViewCell *cellOne = [tableController tableView:tableController.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]]; UITableViewCell *cellTwo = [tableController tableView:tableController.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:1 inSection:0]]; UITableViewCell *cellThree = [tableController tableView:tableController.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:2 inSection:0]]; UITableViewCell *cellFour = [tableController tableView:tableController.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:3 inSection:0]]; UITableViewCell *cellFive = [tableController tableView:tableController.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:4 inSection:0]]; UITableViewCell *cellSix = [tableController tableView:tableController.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:5 inSection:0]]; assertThat(cellOne.textLabel.text, is(equalTo(@"Empty"))); assertThat(cellTwo.textLabel.text, is(equalTo(@"Header"))); assertThat(cellThree.textLabel.text, is(equalTo(@"One"))); assertThat(cellFour.textLabel.text, is(equalTo(@"Two"))); assertThat(cellFive.textLabel.text, is(equalTo(@"Three"))); assertThat(cellSix.textLabel.text, is(equalTo(@"Footer"))); [tableController tableView:tableController.tableView willDisplayCell:cellOne forRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]]; [tableController tableView:tableController.tableView willDisplayCell:cellTwo forRowAtIndexPath:[NSIndexPath indexPathForRow:1 inSection:0]]; [tableController tableView:tableController.tableView willDisplayCell:cellThree forRowAtIndexPath:[NSIndexPath indexPathForRow:2 inSection:0]]; [tableController tableView:tableController.tableView willDisplayCell:cellFour forRowAtIndexPath:[NSIndexPath indexPathForRow:3 inSection:0]]; [tableController tableView:tableController.tableView willDisplayCell:cellFive forRowAtIndexPath:[NSIndexPath indexPathForRow:4 inSection:0]]; [tableController tableView:tableController.tableView willDisplayCell:cellSix forRowAtIndexPath:[NSIndexPath indexPathForRow:5 inSection:0]]; assertThatBool(cellOne.hidden, is(equalToBool(YES))); assertThatBool(cellTwo.hidden, is(equalToBool(NO))); assertThatBool(cellThree.hidden, is(equalToBool(NO))); assertThatBool(cellFour.hidden, is(equalToBool(NO))); assertThatBool(cellFive.hidden, is(equalToBool(NO))); assertThatBool(cellSix.hidden, is(equalToBool(NO))); } - (void)testShowTheEmptyItemWhenTheTableIsEmpty { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; [tableController addHeaderRowForItem:[RKTableItem tableItemUsingBlock:^(RKTableItem *tableItem) { tableItem.text = @"Header"; tableItem.cellMapping = [RKTableViewCellMapping cellMappingUsingBlock:^(RKTableViewCellMapping *cellMapping) { [cellMapping addDefaultMappings]; }]; }]]; [tableController addFooterRowForItem:[RKTableItem tableItemUsingBlock:^(RKTableItem *tableItem) { tableItem.text = @"Footer"; tableItem.cellMapping = [RKTableViewCellMapping cellMappingUsingBlock:^(RKTableViewCellMapping *cellMapping) { [cellMapping addDefaultMappings]; }]; }]]; [tableController setEmptyItem:[RKTableItem tableItemUsingBlock:^(RKTableItem *tableItem) { tableItem.text = @"Empty"; tableItem.cellMapping = [RKTableViewCellMapping cellMappingUsingBlock:^(RKTableViewCellMapping *cellMapping) { [cellMapping addDefaultMappings]; }]; }]]; tableController.showsHeaderRowsWhenEmpty = NO; tableController.showsFooterRowsWhenEmpty = NO; [tableController loadEmpty]; assertThatBool([tableController isLoaded], is(equalToBool(YES))); assertThatInt(tableController.rowCount, is(equalToInt(3))); assertThatBool([tableController isEmpty], is(equalToBool(YES))); UITableViewCell *cellOne = [tableController tableView:tableController.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]]; UITableViewCell *cellTwo = [tableController tableView:tableController.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:1 inSection:0]]; UITableViewCell *cellThree = [tableController tableView:tableController.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:2 inSection:0]]; assertThat(cellOne.textLabel.text, is(equalTo(@"Empty"))); assertThat(cellTwo.textLabel.text, is(equalTo(@"Header"))); assertThat(cellThree.textLabel.text, is(equalTo(@"Footer"))); [tableController tableView:tableController.tableView willDisplayCell:cellOne forRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]]; [tableController tableView:tableController.tableView willDisplayCell:cellTwo forRowAtIndexPath:[NSIndexPath indexPathForRow:1 inSection:0]]; [tableController tableView:tableController.tableView willDisplayCell:cellThree forRowAtIndexPath:[NSIndexPath indexPathForRow:2 inSection:0]]; assertThatBool(cellOne.hidden, is(equalToBool(NO))); assertThatBool(cellTwo.hidden, is(equalToBool(YES))); assertThatBool(cellThree.hidden, is(equalToBool(YES))); } - (void)testShowTheEmptyItemPlusHeadersAndFootersWhenTheTableIsEmpty { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; [tableController addHeaderRowForItem:[RKTableItem tableItemUsingBlock:^(RKTableItem *tableItem) { tableItem.text = @"Header"; tableItem.cellMapping = [RKTableViewCellMapping cellMappingUsingBlock:^(RKTableViewCellMapping *cellMapping) { [cellMapping addDefaultMappings]; }]; }]]; [tableController addFooterRowForItem:[RKTableItem tableItemUsingBlock:^(RKTableItem *tableItem) { tableItem.text = @"Footer"; tableItem.cellMapping = [RKTableViewCellMapping cellMappingUsingBlock:^(RKTableViewCellMapping *cellMapping) { [cellMapping addDefaultMappings]; }]; }]]; [tableController setEmptyItem:[RKTableItem tableItemUsingBlock:^(RKTableItem *tableItem) { tableItem.text = @"Empty"; tableItem.cellMapping = [RKTableViewCellMapping cellMappingUsingBlock:^(RKTableViewCellMapping *cellMapping) { [cellMapping addDefaultMappings]; }]; }]]; tableController.showsHeaderRowsWhenEmpty = YES; tableController.showsFooterRowsWhenEmpty = YES; [tableController loadEmpty]; assertThatBool([tableController isLoaded], is(equalToBool(YES))); assertThatInt(tableController.rowCount, is(equalToInt(3))); assertThatBool([tableController isEmpty], is(equalToBool(YES))); UITableViewCell *cellOne = [tableController tableView:tableController.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]]; UITableViewCell *cellTwo = [tableController tableView:tableController.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:1 inSection:0]]; UITableViewCell *cellThree = [tableController tableView:tableController.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:2 inSection:0]]; assertThat(cellOne.textLabel.text, is(equalTo(@"Empty"))); assertThat(cellTwo.textLabel.text, is(equalTo(@"Header"))); assertThat(cellThree.textLabel.text, is(equalTo(@"Footer"))); [tableController tableView:tableController.tableView willDisplayCell:cellOne forRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]]; [tableController tableView:tableController.tableView willDisplayCell:cellTwo forRowAtIndexPath:[NSIndexPath indexPathForRow:1 inSection:0]]; [tableController tableView:tableController.tableView willDisplayCell:cellThree forRowAtIndexPath:[NSIndexPath indexPathForRow:2 inSection:0]]; assertThatBool(cellOne.hidden, is(equalToBool(NO))); assertThatBool(cellTwo.hidden, is(equalToBool(NO))); assertThatBool(cellThree.hidden, is(equalToBool(NO))); } #pragma mark - UITableViewDelegate Tests - (void)testInvokeTheOnSelectCellForObjectAtIndexPathBlockHandler { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; RKTableItem *tableItem = [RKTableItem tableItem]; __block BOOL dispatched = NO; [tableController loadTableItems:[NSArray arrayWithObject:tableItem] withMapping:[RKTableViewCellMapping cellMappingUsingBlock:^(RKTableViewCellMapping *cellMapping) { cellMapping.onSelectCellForObjectAtIndexPath = ^(UITableViewCell *cell, id object, NSIndexPath *indexPath) { dispatched = YES; }; }]]; [tableController tableView:tableController.tableView didSelectRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]]; assertThatBool(dispatched, is(equalToBool(YES))); } - (void)testInvokeTheOnCellWillAppearForObjectAtIndexPathBlockHandler { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; RKTableItem *tableItem = [RKTableItem tableItem]; __block BOOL dispatched = NO; [tableController loadTableItems:[NSArray arrayWithObject:tableItem] withMapping:[RKTableViewCellMapping cellMappingUsingBlock:^(RKTableViewCellMapping *cellMapping) { cellMapping.onCellWillAppearForObjectAtIndexPath = ^(UITableViewCell *cell, id object, NSIndexPath *indexPath) { dispatched = YES; }; }]]; id mockCell = [OCMockObject niceMockForClass:[UITableViewCell class]]; [tableController tableView:tableController.tableView willDisplayCell:mockCell forRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]]; assertThatBool(dispatched, is(equalToBool(YES))); } - (void)testOptionallyHideHeaderRowsWhenTheyAppearAndTheTableIsEmpty { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; tableController.showsHeaderRowsWhenEmpty = NO; RKTableItem *tableItem = [RKTableItem tableItem]; [tableController addHeaderRowForItem:tableItem]; [tableController loadEmpty]; id mockCell = [OCMockObject niceMockForClass:[UITableViewCell class]]; [[mockCell expect] setHidden:YES]; [tableController tableView:tableController.tableView willDisplayCell:mockCell forRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]]; [mockCell verify]; } - (void)testOptionallyHideFooterRowsWhenTheyAppearAndTheTableIsEmpty { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; tableController.showsFooterRowsWhenEmpty = NO; RKTableItem *tableItem = [RKTableItem tableItem]; [tableController addFooterRowForItem:tableItem]; [tableController loadEmpty]; id mockCell = [OCMockObject niceMockForClass:[UITableViewCell class]]; [[mockCell expect] setHidden:YES]; [tableController tableView:tableController.tableView willDisplayCell:mockCell forRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]]; [mockCell verify]; } - (void)testInvokeABlockCallbackWhenTheCellAccessoryButtonIsTapped { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; RKTableItem *tableItem = [RKTableItem tableItem]; __block BOOL dispatched = NO; RKTableViewCellMapping *mapping = [RKTableViewCellMapping cellMappingUsingBlock:^(RKTableViewCellMapping *cellMapping) { cellMapping.onTapAccessoryButtonForObjectAtIndexPath = ^(UITableViewCell *cell, id object, NSIndexPath *indexPath) { dispatched = YES; }; }]; [tableController loadTableItems:[NSArray arrayWithObject:tableItem] withMapping:mapping]; [tableController tableView:tableController.tableView accessoryButtonTappedForRowWithIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]]; assertThatBool(dispatched, is(equalToBool(YES))); } - (void)testInvokeABlockCallbackWhenTheDeleteConfirmationButtonTitleIsDetermined { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; RKTableItem *tableItem = [RKTableItem tableItem]; NSString *deleteTitle = @"Delete Me"; RKTableViewCellMapping *mapping = [RKTableViewCellMapping cellMappingUsingBlock:^(RKTableViewCellMapping *cellMapping) { cellMapping.titleForDeleteButtonForObjectAtIndexPath = ^ NSString*(UITableViewCell *cell, id object, NSIndexPath *indexPath) { return deleteTitle; }; }]; [tableController loadTableItems:[NSArray arrayWithObject:tableItem] withMapping:mapping]; NSString *delegateTitle = [tableController tableView:tableController.tableView titleForDeleteConfirmationButtonForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]]; assertThat(delegateTitle, is(equalTo(deleteTitle))); } - (void)testInvokeABlockCallbackWhenCellEditingStyleIsDetermined { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; tableController.canEditRows = YES; RKTableItem *tableItem = [RKTableItem tableItem]; RKTableViewCellMapping *mapping = [RKTableViewCellMapping cellMappingUsingBlock:^(RKTableViewCellMapping *cellMapping) { cellMapping.editingStyleForObjectAtIndexPath = ^ UITableViewCellEditingStyle(UITableViewCell *cell, id object, NSIndexPath *indexPath) { return UITableViewCellEditingStyleInsert; }; }]; [tableController loadTableItems:[NSArray arrayWithObject:tableItem] withMapping:mapping]; UITableViewCellEditingStyle delegateStyle = [tableController tableView:tableController.tableView editingStyleForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]]; assertThatInt(delegateStyle, is(equalToInt(UITableViewCellEditingStyleInsert))); } - (void)testInvokeABlockCallbackWhenACellIsMoved { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; tableController.canMoveRows = YES; RKTableItem *tableItem = [RKTableItem tableItem]; NSIndexPath *moveToIndexPath = [NSIndexPath indexPathForRow:2 inSection:0]; [tableController loadTableItems:[NSArray arrayWithObject:tableItem] withMapping:[RKTableViewCellMapping cellMappingUsingBlock:^(RKTableViewCellMapping *cellMapping) { cellMapping.targetIndexPathForMove = ^ NSIndexPath*(UITableViewCell *cell, id object, NSIndexPath *sourceIndexPath, NSIndexPath *destinationIndexPath) { return moveToIndexPath; }; }]]; NSIndexPath *delegateIndexPath = [tableController tableView:tableController.tableView targetIndexPathForMoveFromRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] toProposedIndexPath:[NSIndexPath indexPathForRow:1 inSection:0]]; assertThat(delegateIndexPath, is(equalTo(moveToIndexPath))); } #pragma mark Variable Height Rows - (void)testReturnTheRowHeightConfiguredOnTheTableViewWhenVariableHeightRowsIsDisabled { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; tableController.variableHeightRows = NO; tableController.tableView.rowHeight = 55; RKTableItem *tableItem = [RKTableItem tableItem]; [tableController loadTableItems:[NSArray arrayWithObject:tableItem] withMapping:[RKTableViewCellMapping cellMappingUsingBlock:^(RKTableViewCellMapping *cellMapping) { cellMapping.rowHeight = 200; }]]; CGFloat height = [tableController tableView:tableController.tableView heightForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]]; assertThatFloat(height, is(equalToFloat(55))); } - (void)testReturnTheHeightFromTheTableCellMappingWhenVariableHeightRowsAreEnabled { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; tableController.variableHeightRows = YES; tableController.tableView.rowHeight = 55; RKTableItem *tableItem = [RKTableItem tableItem]; [tableController loadTableItems:[NSArray arrayWithObject:tableItem] withMapping:[RKTableViewCellMapping cellMappingUsingBlock:^(RKTableViewCellMapping *cellMapping) { cellMapping.rowHeight = 200; }]]; CGFloat height = [tableController tableView:tableController.tableView heightForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]]; assertThatFloat(height, is(equalToFloat(200))); } - (void)testInvokeAnBlockCallbackToDetermineTheCellHeightWhenVariableHeightRowsAreEnabled { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; tableController.variableHeightRows = YES; tableController.tableView.rowHeight = 55; RKTableItem *tableItem = [RKTableItem tableItem]; [tableController loadTableItems:[NSArray arrayWithObject:tableItem] withMapping:[RKTableViewCellMapping cellMappingUsingBlock:^(RKTableViewCellMapping *cellMapping) { cellMapping.rowHeight = 200; cellMapping.heightOfCellForObjectAtIndexPath = ^ CGFloat(id object, NSIndexPath *indexPath) { return 150; }; }]]; CGFloat height = [tableController tableView:tableController.tableView heightForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]]; assertThatFloat(height, is(equalToFloat(150))); } #pragma mark - Editing - (void)testAllowEditingWhenTheCanEditRowsPropertyIsSet { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; tableController.canEditRows = YES; RKTableItem *tableItem = [RKTableItem tableItem]; [tableController loadTableItems:[NSArray arrayWithObject:tableItem]]; BOOL delegateCanEdit = [tableController tableView:tableController.tableView canEditRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]]; assertThatBool(delegateCanEdit, is(equalToBool(YES))); } - (void)testCommitADeletionWhenTheCanEditRowsPropertyIsSet { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; tableController.canEditRows = YES; [tableController loadObjects:[NSArray arrayWithObjects:@"First Object", @"Second Object", nil]]; assertThatInt([tableController rowCount], is(equalToInt(2))); BOOL delegateCanEdit = [tableController tableView:tableController.tableView canEditRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]]; assertThatBool(delegateCanEdit, is(equalToBool(YES))); [tableController tableView:tableController.tableView commitEditingStyle:UITableViewCellEditingStyleDelete forRowAtIndexPath:[NSIndexPath indexPathForRow:1 inSection:0]]; assertThatInt([tableController rowCount], is(equalToInt(1))); assertThat([tableController objectForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]], is(equalTo(@"First Object"))); } - (void)testNotCommitADeletionWhenTheCanEditRowsPropertyIsNotSet { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; [tableController loadObjects:[NSArray arrayWithObjects:@"First Object", @"Second Object", nil]]; assertThatInt([tableController rowCount], is(equalToInt(2))); BOOL delegateCanEdit = [tableController tableView:tableController.tableView canEditRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]]; assertThatBool(delegateCanEdit, is(equalToBool(NO))); [tableController tableView:tableController.tableView commitEditingStyle:UITableViewCellEditingStyleDelete forRowAtIndexPath:[NSIndexPath indexPathForRow:1 inSection:0]]; assertThatInt([tableController rowCount], is(equalToInt(2))); assertThat([tableController objectForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]], is(equalTo(@"First Object"))); assertThat([tableController objectForRowAtIndexPath:[NSIndexPath indexPathForRow:1 inSection:0]], is(equalTo(@"Second Object"))); } - (void)testDoNothingToCommitAnInsertionWhenTheCanEditRowsPropertyIsSet { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; tableController.canEditRows = YES; [tableController loadObjects:[NSArray arrayWithObjects:@"First Object", @"Second Object", nil]]; assertThatInt([tableController rowCount], is(equalToInt(2))); BOOL delegateCanEdit = [tableController tableView:tableController.tableView canEditRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]]; assertThatBool(delegateCanEdit, is(equalToBool(YES))); [tableController tableView:tableController.tableView commitEditingStyle:UITableViewCellEditingStyleInsert forRowAtIndexPath:[NSIndexPath indexPathForRow:2 inSection:0]]; assertThatInt([tableController rowCount], is(equalToInt(2))); assertThat([tableController objectForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]], is(equalTo(@"First Object"))); assertThat([tableController objectForRowAtIndexPath:[NSIndexPath indexPathForRow:1 inSection:0]], is(equalTo(@"Second Object"))); } - (void)testAllowMovingWhenTheCanMoveRowsPropertyIsSet { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; tableController.canMoveRows = YES; RKTableItem *tableItem = [RKTableItem tableItem]; [tableController loadTableItems:[NSArray arrayWithObject:tableItem]]; BOOL delegateCanMove = [tableController tableView:tableController.tableView canMoveRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]]; assertThatBool(delegateCanMove, is(equalToBool(YES))); } - (void)testMoveARowWithinASectionWhenTheCanMoveRowsPropertyIsSet { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; tableController.canMoveRows = YES; [tableController loadObjects:[NSArray arrayWithObjects:@"First Object", @"Second Object", nil]]; assertThatInt([tableController rowCount], is(equalToInt(2))); BOOL delegateCanMove = [tableController tableView:tableController.tableView canMoveRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]]; assertThatBool(delegateCanMove, is(equalToBool(YES))); [tableController tableView:tableController.tableView moveRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] toIndexPath:[NSIndexPath indexPathForRow:1 inSection:0]]; assertThatInt([tableController rowCount], is(equalToInt(2))); assertThat([tableController objectForRowAtIndexPath:[NSIndexPath indexPathForRow:1 inSection:0]], is(equalTo(@"First Object"))); assertThat([tableController objectForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]], is(equalTo(@"Second Object"))); } - (void)testMoveARowAcrossSectionsWhenTheCanMoveRowsPropertyIsSet { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; tableController.canMoveRows = YES; [tableController loadObjects:[NSArray arrayWithObjects:@"First Object", @"Second Object", nil]]; assertThatInt([tableController rowCount], is(equalToInt(2))); assertThatInt([tableController sectionCount], is(equalToInt(1))); BOOL delegateCanMove = [tableController tableView:tableController.tableView canMoveRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]]; assertThatBool(delegateCanMove, is(equalToBool(YES))); [tableController tableView:tableController.tableView moveRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] toIndexPath:[NSIndexPath indexPathForRow:0 inSection:1]]; assertThatInt([tableController rowCount], is(equalToInt(2))); assertThatInt([tableController sectionCount], is(equalToInt(2))); assertThat([tableController objectForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:1]], is(equalTo(@"First Object"))); assertThat([tableController objectForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]], is(equalTo(@"Second Object"))); } - (void)testNotMoveARowWhenTheCanMoveRowsPropertyIsNotSet { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; [tableController loadObjects:[NSArray arrayWithObjects:@"First Object", @"Second Object", nil]]; assertThatInt([tableController rowCount], is(equalToInt(2))); BOOL delegateCanMove = [tableController tableView:tableController.tableView canMoveRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]]; assertThatBool(delegateCanMove, is(equalToBool(NO))); [tableController tableView:tableController.tableView moveRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] toIndexPath:[NSIndexPath indexPathForRow:1 inSection:0]]; assertThatInt([tableController rowCount], is(equalToInt(2))); assertThat([tableController objectForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]], is(equalTo(@"First Object"))); assertThat([tableController objectForRowAtIndexPath:[NSIndexPath indexPathForRow:1 inSection:0]], is(equalTo(@"Second Object"))); } #pragma mark - Reachability Integration - (void)testTransitionToTheOnlineStateWhenAReachabilityNoticeIsReceived { RKObjectManager *objectManager = [RKTestFactory objectManager]; id mockManager = [OCMockObject partialMockForObject:objectManager]; BOOL online = YES; [[[mockManager stub] andReturnValue:OCMOCK_VALUE(online)] isOnline]; RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; tableController.objectManager = objectManager; [[NSNotificationCenter defaultCenter] postNotificationName:RKObjectManagerDidBecomeOnlineNotification object:objectManager]; assertThatBool(tableController.isOnline, is(equalToBool(YES))); } - (void)testTransitionToTheOfflineStateWhenAReachabilityNoticeIsReceived { RKObjectManager *objectManager = [RKTestFactory objectManager]; id mockManager = [OCMockObject partialMockForObject:objectManager]; BOOL online = NO; [[[mockManager stub] andReturnValue:OCMOCK_VALUE(online)] isOnline]; RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; tableController.objectManager = objectManager; [[NSNotificationCenter defaultCenter] postNotificationName:RKObjectManagerDidBecomeOfflineNotification object:objectManager]; assertThatBool(tableController.isOnline, is(equalToBool(NO))); } - (void)testNotifyTheDelegateOnTransitionToOffline { RKObjectManager *objectManager = [RKTestFactory objectManager]; id mockManager = [OCMockObject partialMockForObject:objectManager]; [mockManager setExpectationOrderMatters:YES]; RKObjectManagerNetworkStatus networkStatus = RKObjectManagerNetworkStatusOnline; [[[mockManager stub] andReturnValue:OCMOCK_VALUE(networkStatus)] networkStatus]; BOOL online = YES; // Initial online state for table [[[mockManager expect] andReturnValue:OCMOCK_VALUE(online)] isOnline]; online = NO; // After the notification is posted [[[mockManager expect] andReturnValue:OCMOCK_VALUE(online)] isOnline]; RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; id mockDelegate = [OCMockObject mockForProtocol:@protocol(RKTableControllerDelegate)]; [[mockDelegate expect] tableControllerDidBecomeOffline:tableController]; tableController.delegate = mockDelegate; [[NSNotificationCenter defaultCenter] postNotificationName:RKObjectManagerDidBecomeOfflineNotification object:objectManager]; STAssertNoThrow([mockDelegate verify], nil); } - (void)testPostANotificationOnTransitionToOffline { RKObjectManager *objectManager = [RKTestFactory objectManager]; id mockManager = [OCMockObject partialMockForObject:objectManager]; [mockManager setExpectationOrderMatters:YES]; RKObjectManagerNetworkStatus networkStatus = RKObjectManagerNetworkStatusOnline; [[[mockManager stub] andReturnValue:OCMOCK_VALUE(networkStatus)] networkStatus]; BOOL online = YES; // Initial online state for table [[[mockManager expect] andReturnValue:OCMOCK_VALUE(online)] isOnline]; online = NO; // After the notification is posted [[[mockManager expect] andReturnValue:OCMOCK_VALUE(online)] isOnline]; RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; id observerMock = [OCMockObject observerMock]; [[NSNotificationCenter defaultCenter] addMockObserver:observerMock name:RKTableControllerDidBecomeOffline object:tableController]; [[observerMock expect] notificationWithName:RKTableControllerDidBecomeOffline object:tableController]; [[NSNotificationCenter defaultCenter] postNotificationName:RKObjectManagerDidBecomeOfflineNotification object:objectManager]; [observerMock verify]; } - (void)testNotifyTheDelegateOnTransitionToOnline { RKObjectManager *objectManager = [RKTestFactory objectManager]; id mockManager = [OCMockObject partialMockForObject:objectManager]; BOOL online = NO; [[[mockManager expect] andReturnValue:OCMOCK_VALUE(online)] isOnline]; online = YES; [[[mockManager stub] andReturnValue:OCMOCK_VALUE(online)] isOnline]; RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; [RKObjectManager setSharedManager:nil]; // Don't want the controller to initialize with the sharedManager... RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; tableController.objectManager = objectManager; id mockDelegate = [OCMockObject mockForProtocol:@protocol(RKTableControllerDelegate)]; [[mockDelegate expect] tableControllerDidBecomeOnline:tableController]; tableController.delegate = mockDelegate; [[NSNotificationCenter defaultCenter] postNotificationName:RKObjectManagerDidBecomeOnlineNotification object:objectManager]; [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.3]]; STAssertNoThrow([mockDelegate verify], nil); } - (void)testPostANotificationOnTransitionToOnline { RKObjectManager *objectManager = [RKTestFactory objectManager]; id mockManager = [OCMockObject partialMockForObject:objectManager]; BOOL online = NO; [[[mockManager expect] andReturnValue:OCMOCK_VALUE(online)] isOnline]; online = YES; [[[mockManager stub] andReturnValue:OCMOCK_VALUE(online)] isOnline]; RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; [RKObjectManager setSharedManager:nil]; // Don't want the controller to initialize with the sharedManager... RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; tableController.objectManager = objectManager; id observerMock = [OCMockObject observerMock]; [[NSNotificationCenter defaultCenter] addMockObserver:observerMock name:RKTableControllerDidBecomeOnline object:tableController]; [[observerMock expect] notificationWithName:RKTableControllerDidBecomeOnline object:tableController]; [[NSNotificationCenter defaultCenter] postNotificationName:RKObjectManagerDidBecomeOnlineNotification object:objectManager]; [observerMock verify]; } - (void)testShowTheOfflineImageOnTransitionToOffline { RKObjectManager *objectManager = [RKTestFactory objectManager]; id mockManager = [OCMockObject partialMockForObject:objectManager]; [mockManager setExpectationOrderMatters:YES]; RKObjectManagerNetworkStatus networkStatus = RKObjectManagerNetworkStatusOnline; [[[mockManager stub] andReturnValue:OCMOCK_VALUE(networkStatus)] networkStatus]; BOOL online = YES; // Initial online state for table [[[mockManager expect] andReturnValue:OCMOCK_VALUE(online)] isOnline]; online = NO; // After the notification is posted [[[mockManager expect] andReturnValue:OCMOCK_VALUE(online)] isOnline]; RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; UIImage *image = [RKTestFixture imageWithContentsOfFixture:@"blake.png"]; tableController.imageForOffline = image; [[NSNotificationCenter defaultCenter] postNotificationName:RKObjectManagerDidBecomeOfflineNotification object:objectManager]; assertThatBool(tableController.isOnline, is(equalToBool(NO))); UIImageView *imageView = tableController.stateOverlayImageView; assertThat(imageView, isNot(nilValue())); assertThat(imageView.image, is(equalTo(image))); } - (void)testRemoveTheOfflineImageOnTransitionToOnlineFromOffline { RKObjectManager *objectManager = [RKTestFactory objectManager]; id mockManager = [OCMockObject partialMockForObject:objectManager]; [mockManager setExpectationOrderMatters:YES]; RKObjectManagerNetworkStatus networkStatus = RKObjectManagerNetworkStatusOnline; [[[mockManager stub] andReturnValue:OCMOCK_VALUE(networkStatus)] networkStatus]; BOOL online = YES; // Initial online state for table [[[mockManager expect] andReturnValue:OCMOCK_VALUE(online)] isOnline]; online = NO; // After the notification is posted [[[mockManager expect] andReturnValue:OCMOCK_VALUE(online)] isOnline]; RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; [tableController loadEmpty]; // Load to change the isLoaded state UIImage *image = [RKTestFixture imageWithContentsOfFixture:@"blake.png"]; tableController.imageForOffline = image; [[NSNotificationCenter defaultCenter] postNotificationName:RKObjectManagerDidBecomeOfflineNotification object:objectManager]; assertThatBool(tableController.isOnline, is(equalToBool(NO))); UIImageView *imageView = tableController.stateOverlayImageView; assertThat(imageView, isNot(nilValue())); assertThat(imageView.image, is(equalTo(image))); online = YES; [[[mockManager expect] andReturnValue:OCMOCK_VALUE(online)] isOnline]; [[NSNotificationCenter defaultCenter] postNotificationName:RKObjectManagerDidBecomeOnlineNotification object:objectManager]; assertThatBool(tableController.isOnline, is(equalToBool(YES))); imageView = tableController.stateOverlayImageView; assertThat(imageView.image, is(nilValue())); } #pragma mark - Swipe Menus - (void)testAllowSwipeMenusWhenTheSwipeViewsEnabledPropertyIsSet { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; tableController.cellSwipeViewsEnabled = YES; RKTableItem *tableItem = [RKTableItem tableItem]; [tableController loadTableItems:[NSArray arrayWithObject:tableItem]]; assertThatBool(tableController.canEditRows, is(equalToBool(NO))); assertThatBool(tableController.cellSwipeViewsEnabled, is(equalToBool(YES))); } - (void)testNotAllowEditingWhenTheSwipeViewsEnabledPropertyIsSet { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; tableController.cellSwipeViewsEnabled = YES; RKTableItem *tableItem = [RKTableItem tableItem]; [tableController loadTableItems:[NSArray arrayWithObject:tableItem]]; BOOL delegateCanEdit = [tableController tableView:tableController.tableView canEditRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]]; assertThatBool(delegateCanEdit, is(equalToBool(NO))); } - (void)testRaiseAnExceptionWhenEnablingSwipeViewsWhenTheCanEditRowsPropertyIsSet { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; tableController.canEditRows = YES; NSException *exception = nil; @try { tableController.cellSwipeViewsEnabled = YES; } @catch (NSException *e) { exception = e; } @finally { assertThat(exception, isNot(nilValue())); } } - (void)testCallTheDelegateBeforeShowingTheSwipeView { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; tableController.cellSwipeViewsEnabled = YES; RKTableItem *tableItem = [RKTableItem tableItem]; RKTableControllerTestDelegate *delegate = [RKTableControllerTestDelegate new]; id mockDelegate = [OCMockObject partialMockForObject:delegate]; [[[mockDelegate expect] andForwardToRealObject] tableController:tableController willAddSwipeView:OCMOCK_ANY toCell:OCMOCK_ANY forObject:OCMOCK_ANY]; tableController.delegate = mockDelegate; [tableController loadTableItems:[NSArray arrayWithObject:tableItem]]; [tableController addSwipeViewTo:[RKTestUserTableViewCell new] withObject:@"object" direction:UISwipeGestureRecognizerDirectionRight]; STAssertNoThrow([mockDelegate verify], nil); } - (void)testCallTheDelegateBeforeHidingTheSwipeView { RKTableControllerTestTableViewController *viewController = [RKTableControllerTestTableViewController new]; RKTableController *tableController = [RKTableController tableControllerForTableViewController:viewController]; tableController.cellSwipeViewsEnabled = YES; RKTableItem *tableItem = [RKTableItem tableItem]; RKTableControllerTestDelegate *delegate = [RKTableControllerTestDelegate new]; id mockDelegate = [OCMockObject partialMockForObject:delegate]; [[[mockDelegate expect] andForwardToRealObject] tableController:tableController willAddSwipeView:OCMOCK_ANY toCell:OCMOCK_ANY forObject:OCMOCK_ANY]; [[[mockDelegate expect] andForwardToRealObject] tableController:tableController willRemoveSwipeView:OCMOCK_ANY fromCell:OCMOCK_ANY forObject:OCMOCK_ANY]; tableController.delegate = mockDelegate; [tableController loadTableItems:[NSArray arrayWithObject:tableItem]]; [tableController addSwipeViewTo:[RKTestUserTableViewCell new] withObject:@"object" direction:UISwipeGestureRecognizerDirectionRight]; [tableController animationDidStopAddingSwipeView:nil finished:nil context:nil]; [tableController removeSwipeView:YES]; STAssertNoThrow([mockDelegate verify], nil); } @end