diff --git a/Tests/IGListWorkingRangeHandlerTests.m b/Tests/IGListWorkingRangeHandlerTests.m index e0e2bcdb..b06f1ee6 100644 --- a/Tests/IGListWorkingRangeHandlerTests.m +++ b/Tests/IGListWorkingRangeHandlerTests.m @@ -21,6 +21,10 @@ - (instancetype)initWithObjects:(NSArray *)objects objectToControllerMap:(NSDictionary *)map; +- (void)insertObject:(id)object withController:(IGListSectionController *)controller atIndex:(NSInteger)index; + +- (void)removeObjectAtIndex:(NSInteger)index; + @end @implementation _IGTestWorkingRangeAdapterDataSource { @@ -37,6 +41,24 @@ return self; } +- (void)insertObject:(id)object withController:(IGListSectionController *)controller atIndex:(NSInteger)index { + NSMutableArray *const objects = [_objects mutableCopy]; + NSMutableDictionary *const map = [_map mutableCopy]; + [objects insertObject:object atIndex:index]; + map[object] = controller; + _objects = [objects copy]; + _map = [map copy]; +} + +- (void)removeObjectAtIndex:(NSInteger)index { + NSMutableArray *const objects = [_objects mutableCopy]; + NSMutableDictionary *const map = [_map mutableCopy]; + [map removeObjectForKey:[objects objectAtIndex:index]]; + [objects removeObjectAtIndex:index]; + _objects = [objects copy]; + _map = [map copy]; +} + - (UIView *)emptyViewForListAdapter:(IGListAdapter *)listAdapter { return nil; } @@ -78,11 +100,145 @@ // Act: Tell the working range handler that the first, and only item in the list will be displayed. [[mockWorkingRangeDelegate expect] listAdapter:adapter sectionControllerWillEnterWorkingRange:controller]; - [adapter.workingRangeHandler willDisplayItemAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] forListAdapter:adapter]; + [adapter.workingRangeHandler willDisplayItemAtIndexPath:[NSIndexPath indexPathForItem:0 inSection:0] forListAdapter:adapter]; [mockWorkingRangeDelegate verifyWithDelay:5]; } +- (void)test_whenDisplayingItemAtPath_withWorkingRangeSizeZero_thatAdjacentItemsDoNotEnterWorkingRange { + // Arrange 1: Set up a simple collection view and adapter with three elements. + IGListTestSection *controller1 = [[IGListTestSection alloc] init]; + NSString *object1 = @"obj1"; + IGListTestSection *controller2 = [[IGListTestSection alloc] init]; + NSString *object2 = @"obj2"; + IGListTestSection *controller3 = [[IGListTestSection alloc] init]; + NSString *object3 = @"obj3"; + _IGTestWorkingRangeAdapterDataSource *ds = [[_IGTestWorkingRangeAdapterDataSource alloc] initWithObjects:@[object1, object2, object3] + objectToControllerMap:@{object1: controller1, + object2: controller2, + object3: controller3}]; + IGListReloadDataUpdater *updater = [[IGListReloadDataUpdater alloc] init]; + IGListAdapter *adapter = [[IGListAdapter alloc] initWithUpdater:updater viewController:nil]; + id collectionView = [OCMockObject niceMockForClass:[UICollectionView class]]; + adapter.collectionView = collectionView; + + id mockWorkingRangeDelegate1 = [OCMockObject mockForProtocol:@protocol(IGListWorkingRangeDelegate)]; + id mockWorkingRangeDelegate2 = [OCMockObject mockForProtocol:@protocol(IGListWorkingRangeDelegate)]; + id mockWorkingRangeDelegate3 = [OCMockObject mockForProtocol:@protocol(IGListWorkingRangeDelegate)]; + + adapter.dataSource = ds; + controller1.workingRangeDelegate = mockWorkingRangeDelegate1; + controller2.workingRangeDelegate = mockWorkingRangeDelegate2; + controller3.workingRangeDelegate = mockWorkingRangeDelegate3; + + // Arrange 2: Force an update so we get the objects we configured through the system. + [adapter performUpdatesAnimated:NO completion:nil]; + + // Act: Tell the working range handler that the center item will be displayed. + [[mockWorkingRangeDelegate1 reject] listAdapter:[OCMArg any] sectionControllerWillEnterWorkingRange:[OCMArg any]]; + [[mockWorkingRangeDelegate2 expect] listAdapter:adapter sectionControllerWillEnterWorkingRange:controller2]; + [[mockWorkingRangeDelegate3 reject] listAdapter:[OCMArg any] sectionControllerWillEnterWorkingRange:[OCMArg any]]; + [adapter.workingRangeHandler willDisplayItemAtIndexPath:[NSIndexPath indexPathForItem:0 inSection:1] forListAdapter:adapter]; + + [mockWorkingRangeDelegate1 verifyWithDelay:5]; + [mockWorkingRangeDelegate2 verifyWithDelay:5]; + [mockWorkingRangeDelegate3 verifyWithDelay:5]; +} + +- (void)test_whenDisplayingItemAtPath_withWorkingRangeSizeOne_thatAdjacentItemsEnterWorkingRange { + // Arrange 1: Set up a simple collection view and adapter with three elements. + IGListTestSection *controller1 = [[IGListTestSection alloc] init]; + NSString *object1 = @"obj1"; + IGListTestSection *controller2 = [[IGListTestSection alloc] init]; + NSString *object2 = @"obj2"; + IGListTestSection *controller3 = [[IGListTestSection alloc] init]; + NSString *object3 = @"obj3"; + _IGTestWorkingRangeAdapterDataSource *ds = [[_IGTestWorkingRangeAdapterDataSource alloc] initWithObjects:@[object1, object2, object3] + objectToControllerMap:@{object1: controller1, + object2: controller2, + object3: controller3}]; + IGListReloadDataUpdater *updater = [[IGListReloadDataUpdater alloc] init]; + IGListAdapter *adapter = [[IGListAdapter alloc] initWithUpdater:updater viewController:nil workingRangeSize:1]; + id collectionView = [OCMockObject niceMockForClass:[UICollectionView class]]; + adapter.collectionView = collectionView; + + id mockWorkingRangeDelegate1 = [OCMockObject mockForProtocol:@protocol(IGListWorkingRangeDelegate)]; + id mockWorkingRangeDelegate2 = [OCMockObject mockForProtocol:@protocol(IGListWorkingRangeDelegate)]; + id mockWorkingRangeDelegate3 = [OCMockObject mockForProtocol:@protocol(IGListWorkingRangeDelegate)]; + + adapter.dataSource = ds; + controller1.workingRangeDelegate = mockWorkingRangeDelegate1; + controller2.workingRangeDelegate = mockWorkingRangeDelegate2; + controller3.workingRangeDelegate = mockWorkingRangeDelegate3; + + // Arrange 2: Force an update so we get the objects we configured through the system. + [adapter performUpdatesAnimated:NO completion:nil]; + + // Act: Tell the working range handler that the center item will be displayed. + [[mockWorkingRangeDelegate1 expect] listAdapter:adapter sectionControllerWillEnterWorkingRange:controller1]; + [[mockWorkingRangeDelegate2 expect] listAdapter:adapter sectionControllerWillEnterWorkingRange:controller2]; + [[mockWorkingRangeDelegate3 expect] listAdapter:adapter sectionControllerWillEnterWorkingRange:controller3]; + [adapter.workingRangeHandler willDisplayItemAtIndexPath:[NSIndexPath indexPathForItem:0 inSection:1] forListAdapter:adapter]; + + [mockWorkingRangeDelegate1 verifyWithDelay:5]; + [mockWorkingRangeDelegate2 verifyWithDelay:5]; + [mockWorkingRangeDelegate3 verifyWithDelay:5]; +} + +- (void)test_whenDisplayingItemAtPath_withWorkingRangeSizeOne_thatOnlyAdjacentAndVisibleItemsEnterWorkingRange { + // Arrange 1: Set up a simple collection view and adapter with five elements. + IGListTestSection *controller1 = [[IGListTestSection alloc] init]; + NSString *object1 = @"obj1"; + IGListTestSection *controller2 = [[IGListTestSection alloc] init]; + NSString *object2 = @"obj2"; + IGListTestSection *controller3 = [[IGListTestSection alloc] init]; + NSString *object3 = @"obj3"; + IGListTestSection *controller4 = [[IGListTestSection alloc] init]; + NSString *object4 = @"obj4"; + IGListTestSection *controller5 = [[IGListTestSection alloc] init]; + NSString *object5 = @"obj5"; + _IGTestWorkingRangeAdapterDataSource *ds = [[_IGTestWorkingRangeAdapterDataSource alloc] initWithObjects:@[object1, object2, object3, object4, object5] + objectToControllerMap:@{object1: controller1, + object2: controller2, + object3: controller3, + object4: controller4, + object5: controller5}]; + IGListReloadDataUpdater *updater = [[IGListReloadDataUpdater alloc] init]; + IGListAdapter *adapter = [[IGListAdapter alloc] initWithUpdater:updater viewController:nil workingRangeSize:1]; + id collectionView = [OCMockObject niceMockForClass:[UICollectionView class]]; + adapter.collectionView = collectionView; + + id mockWorkingRangeDelegate1 = [OCMockObject mockForProtocol:@protocol(IGListWorkingRangeDelegate)]; + id mockWorkingRangeDelegate2 = [OCMockObject mockForProtocol:@protocol(IGListWorkingRangeDelegate)]; + id mockWorkingRangeDelegate3 = [OCMockObject mockForProtocol:@protocol(IGListWorkingRangeDelegate)]; + id mockWorkingRangeDelegate4 = [OCMockObject mockForProtocol:@protocol(IGListWorkingRangeDelegate)]; + id mockWorkingRangeDelegate5 = [OCMockObject mockForProtocol:@protocol(IGListWorkingRangeDelegate)]; + + adapter.dataSource = ds; + controller1.workingRangeDelegate = mockWorkingRangeDelegate1; + controller2.workingRangeDelegate = mockWorkingRangeDelegate2; + controller3.workingRangeDelegate = mockWorkingRangeDelegate3; + controller4.workingRangeDelegate = mockWorkingRangeDelegate4; + controller5.workingRangeDelegate = mockWorkingRangeDelegate5; + + // Arrange 2: Force an update so we get the objects we configured through the system. + [adapter performUpdatesAnimated:NO completion:nil]; + + // Act: Tell the working range handler that the center item will be displayed. + [[mockWorkingRangeDelegate1 reject] listAdapter:[OCMArg any] sectionControllerWillEnterWorkingRange:[OCMArg any]]; + [[mockWorkingRangeDelegate2 expect] listAdapter:adapter sectionControllerWillEnterWorkingRange:controller2]; + [[mockWorkingRangeDelegate3 expect] listAdapter:adapter sectionControllerWillEnterWorkingRange:controller3]; + [[mockWorkingRangeDelegate4 expect] listAdapter:adapter sectionControllerWillEnterWorkingRange:controller4]; + [[mockWorkingRangeDelegate5 reject] listAdapter:[OCMArg any] sectionControllerWillEnterWorkingRange:[OCMArg any]]; + [adapter.workingRangeHandler willDisplayItemAtIndexPath:[NSIndexPath indexPathForItem:0 inSection:2] forListAdapter:adapter]; + + [mockWorkingRangeDelegate1 verifyWithDelay:5]; + [mockWorkingRangeDelegate2 verifyWithDelay:5]; + [mockWorkingRangeDelegate3 verifyWithDelay:5]; + [mockWorkingRangeDelegate4 verifyWithDelay:5]; + [mockWorkingRangeDelegate5 verifyWithDelay:5]; +} + - (void)test_whenDisplayingItemAtPath_withWorkingRangeSizeZero_thenHidingThatItem_thatItemLeavesWorkingRange { // Arrange 1: Set up a simple collection view and adapter with a single element. IGListTestSection *controller = [[IGListTestSection alloc] init]; @@ -103,14 +259,14 @@ // Arrange 3: Tell the working range handler that the first, and only item in the list will be displayed. [[mockWorkingRangeDelegate expect] listAdapter:adapter sectionControllerWillEnterWorkingRange:controller]; - [adapter.workingRangeHandler willDisplayItemAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] forListAdapter:adapter]; + [adapter.workingRangeHandler willDisplayItemAtIndexPath:[NSIndexPath indexPathForItem:0 inSection:0] forListAdapter:adapter]; // Arrange 4: Wait for the item to move in-range [mockWorkingRangeDelegate verifyWithDelay:5]; // Act: Tell the working range handler that the first item is now hidden. [[mockWorkingRangeDelegate expect] listAdapter:adapter sectionControllerDidExitWorkingRange:controller]; - [adapter.workingRangeHandler didEndDisplayingItemAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] forListAdapter:adapter]; + [adapter.workingRangeHandler didEndDisplayingItemAtIndexPath:[NSIndexPath indexPathForItem:0 inSection:0] forListAdapter:adapter]; [mockWorkingRangeDelegate verifyWithDelay:5]; } @@ -138,7 +294,7 @@ // Act: Tell the working range handler that the first, and only item in the list will be displayed. [[mockWorkingRangeDelegate expect] listAdapter:adapter sectionControllerWillEnterWorkingRange:controller2]; - [adapter.workingRangeHandler willDisplayItemAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] forListAdapter:adapter]; + [adapter.workingRangeHandler willDisplayItemAtIndexPath:[NSIndexPath indexPathForItem:0 inSection:0] forListAdapter:adapter]; [mockWorkingRangeDelegate verifyWithDelay:5]; } @@ -172,7 +328,7 @@ // Act: Tell the working range handler that the first, and only item in the list will be displayed. [[mockWorkingRangeDelegate2 expect] listAdapter:adapter sectionControllerWillEnterWorkingRange:controller2]; [[mockWorkingRangeDelegate3 reject] listAdapter:[OCMArg any] sectionControllerWillEnterWorkingRange:[OCMArg any]]; - [adapter.workingRangeHandler willDisplayItemAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] forListAdapter:adapter]; + [adapter.workingRangeHandler willDisplayItemAtIndexPath:[NSIndexPath indexPathForItem:0 inSection:0] forListAdapter:adapter]; [mockWorkingRangeDelegate2 verifyWithDelay:5]; [mockWorkingRangeDelegate3 verify]; @@ -201,16 +357,151 @@ // Arrange 3: Tell the working range handler that the first, and only item in the list will be displayed. [[mockWorkingRangeDelegate expect] listAdapter:adapter sectionControllerWillEnterWorkingRange:controller2]; - [adapter.workingRangeHandler willDisplayItemAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] forListAdapter:adapter]; + [adapter.workingRangeHandler willDisplayItemAtIndexPath:[NSIndexPath indexPathForItem:0 inSection:0] forListAdapter:adapter]; // Arrange 4: Wait for the item to move in-range. [mockWorkingRangeDelegate verifyWithDelay:5]; // Act: Hide the first item, and watch for the second item to leave the working range. [[mockWorkingRangeDelegate expect] listAdapter:adapter sectionControllerDidExitWorkingRange:controller2]; - [adapter.workingRangeHandler didEndDisplayingItemAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] forListAdapter:adapter]; + [adapter.workingRangeHandler didEndDisplayingItemAtIndexPath:[NSIndexPath indexPathForItem:0 inSection:0] forListAdapter:adapter]; [mockWorkingRangeDelegate verifyWithDelay:5]; } +- (void)test_whenDisplayingItemsAtPaths_withWorkingRangeSizeOne_thatSpuriousWorkingRangeCallsAreNotMade { + // Arrange 1: Set up a simple collection view and adapter with a single element. + IGListTestSection *controller1 = [[IGListTestSection alloc] init]; + NSString *object1 = @"obj1"; + IGListTestSection *controller2 = [[IGListTestSection alloc] init]; + NSString *object2 = @"obj2"; + _IGTestWorkingRangeAdapterDataSource *ds = [[_IGTestWorkingRangeAdapterDataSource alloc] initWithObjects:@[object1, object2] + objectToControllerMap:@{object1: controller1, + object2: controller2}]; + IGListReloadDataUpdater *updater = [[IGListReloadDataUpdater alloc] init]; + IGListAdapter *adapter = [[IGListAdapter alloc] initWithUpdater:updater viewController:nil workingRangeSize:1]; + id collectionView = [OCMockObject niceMockForClass:[UICollectionView class]]; + adapter.collectionView = collectionView; + + id mockWorkingRangeDelegate1 = [OCMockObject mockForProtocol:@protocol(IGListWorkingRangeDelegate)]; + id mockWorkingRangeDelegate2 = [OCMockObject mockForProtocol:@protocol(IGListWorkingRangeDelegate)]; + + adapter.dataSource = ds; + controller1.workingRangeDelegate = mockWorkingRangeDelegate1; + controller2.workingRangeDelegate = mockWorkingRangeDelegate2; + + // Arrange 2: Force an update so we get the objects we configured through the system. + [adapter performUpdatesAnimated:NO completion:nil]; + + // Arrange 3: Tell the working range handler that the first item in the list will be displayed. + [[mockWorkingRangeDelegate1 expect] listAdapter:adapter sectionControllerWillEnterWorkingRange:controller1]; + [[mockWorkingRangeDelegate2 expect] listAdapter:adapter sectionControllerWillEnterWorkingRange:controller2]; + [adapter.workingRangeHandler willDisplayItemAtIndexPath:[NSIndexPath indexPathForItem:0 inSection:0] forListAdapter:adapter]; + + [mockWorkingRangeDelegate1 verifyWithDelay:5]; + [mockWorkingRangeDelegate2 verifyWithDelay:5]; + + // Act: Tell the working range handler that the second item in the list will be displayed. + [[mockWorkingRangeDelegate1 reject] listAdapter:[OCMArg any] sectionControllerWillEnterWorkingRange:[OCMArg any]]; + [[mockWorkingRangeDelegate2 reject] listAdapter:[OCMArg any] sectionControllerWillEnterWorkingRange:[OCMArg any]]; + [adapter.workingRangeHandler willDisplayItemAtIndexPath:[NSIndexPath indexPathForItem:0 inSection:1] forListAdapter:adapter]; + + [mockWorkingRangeDelegate1 verifyWithDelay:5]; + [mockWorkingRangeDelegate2 verifyWithDelay:5]; +} + +- (void)test_whenDisplayingItemsAtPaths_withWorkingRangeSizeZero_thenRemovingFirstItem_thenInsertingItemAtLastPosition_thatItemEntersWorkingRange { + return; // This test currently fails; working range calculations do not take inserts + deletes into account. + + // Arrange 1: Set up a simple collection view and adapter with a single element. + IGListTestSection *controller1 = [[IGListTestSection alloc] init]; + NSString *object1 = @"obj1"; + IGListTestSection *controller2 = [[IGListTestSection alloc] init]; + NSString *object2 = @"obj2"; + _IGTestWorkingRangeAdapterDataSource *ds = [[_IGTestWorkingRangeAdapterDataSource alloc] initWithObjects:@[object1, object2] + objectToControllerMap:@{object1: controller1, + object2: controller2}]; + IGListReloadDataUpdater *updater = [[IGListReloadDataUpdater alloc] init]; + IGListAdapter *adapter = [[IGListAdapter alloc] initWithUpdater:updater viewController:nil]; + id collectionView = [OCMockObject niceMockForClass:[UICollectionView class]]; + adapter.collectionView = collectionView; + + id mockWorkingRangeDelegate1 = [OCMockObject mockForProtocol:@protocol(IGListWorkingRangeDelegate)]; + id mockWorkingRangeDelegate2 = [OCMockObject mockForProtocol:@protocol(IGListWorkingRangeDelegate)]; + + adapter.dataSource = ds; + controller1.workingRangeDelegate = mockWorkingRangeDelegate1; + controller2.workingRangeDelegate = mockWorkingRangeDelegate2; + + // Arrange 2: Force an update so we get the objects we configured through the system. + [adapter performUpdatesAnimated:NO completion:nil]; + + // Arrange 3: Tell the working range handler that the first two items in the list will be displayed. + [[mockWorkingRangeDelegate1 expect] listAdapter:adapter sectionControllerWillEnterWorkingRange:controller1]; + [[mockWorkingRangeDelegate2 expect] listAdapter:adapter sectionControllerWillEnterWorkingRange:controller2]; + [adapter.workingRangeHandler willDisplayItemAtIndexPath:[NSIndexPath indexPathForItem:0 inSection:0] forListAdapter:adapter]; + [adapter.workingRangeHandler willDisplayItemAtIndexPath:[NSIndexPath indexPathForItem:0 inSection:1] forListAdapter:adapter]; + [mockWorkingRangeDelegate1 verifyWithDelay:5]; + [mockWorkingRangeDelegate2 verifyWithDelay:5]; + + // Arrange 4: Remove the object at the first index, and update the working range handler. + [ds removeObjectAtIndex:0]; + [[mockWorkingRangeDelegate1 expect] listAdapter:adapter sectionControllerDidExitWorkingRange:controller1]; + [adapter.workingRangeHandler didEndDisplayingItemAtIndexPath:[NSIndexPath indexPathForItem:0 inSection:0] forListAdapter:adapter]; + [mockWorkingRangeDelegate1 verifyWithDelay:5]; + + // Act: Insert a new object at index one, and update the working range handler. + [ds insertObject:object1 withController:controller1 atIndex:1]; + [[mockWorkingRangeDelegate1 expect] listAdapter:adapter sectionControllerWillEnterWorkingRange:controller1]; + [[mockWorkingRangeDelegate2 reject] listAdapter:[OCMArg any] sectionControllerWillEnterWorkingRange:[OCMArg any]]; + [[mockWorkingRangeDelegate2 reject] listAdapter:[OCMArg any] sectionControllerDidExitWorkingRange:[OCMArg any]]; + [adapter.workingRangeHandler willDisplayItemAtIndexPath:[NSIndexPath indexPathForItem:0 inSection:1] forListAdapter:adapter]; + [mockWorkingRangeDelegate1 verifyWithDelay:5]; + [mockWorkingRangeDelegate2 verifyWithDelay:5]; +} + +- (void)test_whenDisplayingItemAtPath_withWorkingRangeSizeZero_thenInsertingNewItem_thatVisibleItemsRemainInWorkingRange { + return; // This test currently fails; working range calculations do not take inserts + deletes into account. + + // Arrange 1: Set up a simple collection view and adapter with a single element. + IGListTestSection *controller1 = [[IGListTestSection alloc] init]; + NSString *object1 = @"obj1"; + IGListTestSection *controller2 = [[IGListTestSection alloc] init]; + NSString *object2 = @"obj2"; + _IGTestWorkingRangeAdapterDataSource *ds = [[_IGTestWorkingRangeAdapterDataSource alloc] initWithObjects:@[object1] + objectToControllerMap:@{object1: controller1}]; + IGListReloadDataUpdater *updater = [[IGListReloadDataUpdater alloc] init]; + IGListAdapter *adapter = [[IGListAdapter alloc] initWithUpdater:updater viewController:nil]; + id collectionView = [OCMockObject niceMockForClass:[UICollectionView class]]; + adapter.collectionView = collectionView; + + id mockWorkingRangeDelegate1 = [OCMockObject mockForProtocol:@protocol(IGListWorkingRangeDelegate)]; + id mockWorkingRangeDelegate2 = [OCMockObject mockForProtocol:@protocol(IGListWorkingRangeDelegate)]; + + adapter.dataSource = ds; + controller1.workingRangeDelegate = mockWorkingRangeDelegate1; + controller2.workingRangeDelegate = mockWorkingRangeDelegate2; + + // Arrange 2: Force an update so we get the objects we configured through the system. + [adapter performUpdatesAnimated:NO completion:nil]; + + // Arrange 3: Tell the working range handler that the first item in the list will be displayed. + [[mockWorkingRangeDelegate1 expect] listAdapter:adapter sectionControllerWillEnterWorkingRange:controller1]; + [adapter.workingRangeHandler willDisplayItemAtIndexPath:[NSIndexPath indexPathForItem:0 inSection:0] forListAdapter:adapter]; + [mockWorkingRangeDelegate1 verifyWithDelay:5]; + + // Arrange 4: Insert a second object in the first index. + [ds insertObject:object2 withController:controller2 atIndex:0]; + + // Act: Tell the working range handler that the new item will become visible. + [[mockWorkingRangeDelegate1 reject] listAdapter:[OCMArg any] sectionControllerWillEnterWorkingRange:[OCMArg any]]; + [[mockWorkingRangeDelegate1 reject] listAdapter:[OCMArg any] sectionControllerDidExitWorkingRange:[OCMArg any]]; + [[mockWorkingRangeDelegate2 expect] listAdapter:adapter sectionControllerWillEnterWorkingRange:controller2]; + [[mockWorkingRangeDelegate2 reject] listAdapter:[OCMArg any] sectionControllerDidExitWorkingRange:[OCMArg any]]; + [adapter.workingRangeHandler willDisplayItemAtIndexPath:[NSIndexPath indexPathForItem:0 inSection:0] forListAdapter:adapter]; + + [mockWorkingRangeDelegate1 verifyWithDelay:5]; + [mockWorkingRangeDelegate2 verifyWithDelay:5]; +} + @end