Improve IGListWorkingRangeHandler Test Coverage

Summary:
Added working range handler tests. This will allow changes/experiments to be made to the working range handler with improved confidence.

Two of the added tests are currently disabled; working range updates don't currently take inserts and deletes into account and so these tests fail.

Reviewed By: rnystrom

Differential Revision: D13717357

fbshipit-source-id: dd4523d3162cfe13ee03e9d10ffa22b58514ca5f
This commit is contained in:
Jordan Smith 2019-02-19 08:07:11 -08:00 committed by Facebook Github Bot
parent 035808e750
commit 3f5047dd9a

View file

@ -21,6 +21,10 @@
- (instancetype)initWithObjects:(NSArray *)objects
objectToControllerMap:(NSDictionary<id, IGListSectionController *> *)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