IGListKit/Tests/IGListWorkingRangeHandlerTests.m
Tim Oliver f92b9339ee Standarize the copyright notice in all source files
Summary:
The standardized Meta copyright notice is "Copyright (c) Meta Platforms, Inc. and affiliates." and not "Copyright (c) Meta Platforms, Inc. and its affiliates." (Dropping the "its")

This diff updates the copyright notice in each source file to the correct this.

Reviewed By: willbailey

Differential Revision: D44737667

fbshipit-source-id: 643bf36df76723e70d9d826c53cf8f29b8a0c8cc
2023-04-06 02:44:16 -07:00

504 lines
30 KiB
Objective-C

/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#import <XCTest/XCTest.h>
#import <OCMock/OCMock.h>
#import <IGListKit/IGListReloadDataUpdater.h>
#import <IGListKit/IGListWorkingRangeDelegate.h>
#import "IGListAdapterInternal.h"
#import "IGListTestAdapterDataSource.h"
#import "IGListTestSection.h"
#import "IGListWorkingRangeHandler.h"
@interface _IGTestWorkingRangeAdapterDataSource : NSObject <IGListAdapterDataSource>
- (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 {
NSArray *_objects;
NSDictionary *_map;
}
- (instancetype)initWithObjects:(NSArray *)objects
objectToControllerMap:(NSDictionary<id,IGListSectionController *> *)map {
if (self = [super init]) {
_objects = objects;
_map = map;
}
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;
}
- (NSArray<id<IGListDiffable>> *)objectsForListAdapter:(IGListAdapter *)listAdapter {
return _objects;
}
- (IGListSectionController *)listAdapter:(IGListAdapter *)listAdapter
sectionControllerForObject:(id)object {
return [_map objectForKey:object];
}
@end
@interface IGListWorkingRangeHandlerTests : XCTestCase
@end
@implementation IGListWorkingRangeHandlerTests
- (void)test_whenDisplayingItemAtPath_withWorkingRangeSizeZero_thatItemEntersWorkingRange {
// Arrange 1: Set up a simple collection view and adapter with a single element.
IGListTestSection *controller = [[IGListTestSection alloc] init];
NSString *object = @"obj";
_IGTestWorkingRangeAdapterDataSource *ds = [[_IGTestWorkingRangeAdapterDataSource alloc] initWithObjects:@[object]
objectToControllerMap:@{object: controller}];
IGListReloadDataUpdater *updater = [[IGListReloadDataUpdater alloc] init];
IGListAdapter *adapter = [[IGListAdapter alloc] initWithUpdater:updater viewController:nil];
id collectionView = [OCMockObject niceMockForClass:[UICollectionView class]];
adapter.collectionView = collectionView;
id mockWorkingRangeDelegate = [OCMockObject mockForProtocol:@protocol(IGListWorkingRangeDelegate)];
adapter.dataSource = ds;
controller.workingRangeDelegate = mockWorkingRangeDelegate;
// 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 first, and only item in the list will be displayed.
[[mockWorkingRangeDelegate expect] listAdapter:adapter sectionControllerWillEnterWorkingRange:controller];
[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];
NSString *object = @"obj";
_IGTestWorkingRangeAdapterDataSource *ds = [[_IGTestWorkingRangeAdapterDataSource alloc] initWithObjects:@[object]
objectToControllerMap:@{object: controller}];
IGListReloadDataUpdater *updater = [[IGListReloadDataUpdater alloc] init];
IGListAdapter *adapter = [[IGListAdapter alloc] initWithUpdater:updater viewController:nil];
id collectionView = [OCMockObject niceMockForClass:[UICollectionView class]];
adapter.collectionView = collectionView;
id mockWorkingRangeDelegate = [OCMockObject mockForProtocol:@protocol(IGListWorkingRangeDelegate)];
adapter.dataSource = ds;
controller.workingRangeDelegate = mockWorkingRangeDelegate;
// 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, and only item in the list will be displayed.
[[mockWorkingRangeDelegate expect] listAdapter:adapter sectionControllerWillEnterWorkingRange:controller];
[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 indexPathForItem:0 inSection:0] forListAdapter:adapter];
[mockWorkingRangeDelegate verifyWithDelay:5];
}
- (void)test_whenDisplayingItemAtPath_withWorkingRangeSizeOne_thatNextItemEntersWorkingRange {
// Arrange 1: Set up a simple collection view and adapter with two elements.
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 mockWorkingRangeDelegate = [OCMockObject mockForProtocol:@protocol(IGListWorkingRangeDelegate)];
adapter.dataSource = ds;
controller2.workingRangeDelegate = mockWorkingRangeDelegate;
// 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 first, and only item in the list will be displayed.
[[mockWorkingRangeDelegate expect] listAdapter:adapter sectionControllerWillEnterWorkingRange:controller2];
[adapter.workingRangeHandler willDisplayItemAtIndexPath:[NSIndexPath indexPathForItem:0 inSection:0] forListAdapter:adapter];
[mockWorkingRangeDelegate verifyWithDelay:5];
}
- (void)test_whenDisplayingItemAtPath_withWorkingRangeSizeOne_thatThirdItemDoesNotEnterWorkingRange {
// 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 mockWorkingRangeDelegate2 = [OCMockObject mockForProtocol:@protocol(IGListWorkingRangeDelegate)];
id mockWorkingRangeDelegate3 = [OCMockObject mockForProtocol:@protocol(IGListWorkingRangeDelegate)];
adapter.dataSource = ds;
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 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 indexPathForItem:0 inSection:0] forListAdapter:adapter];
[mockWorkingRangeDelegate2 verifyWithDelay:5];
[mockWorkingRangeDelegate3 verify];
}
- (void)test_whenDisplayingItemAtPath_withWorkingRangeSizeOne_thenEndDisplayingThatItem_thatNextItemLeavesWorkingRange {
// Arrange 1: Set up a simple collection view and adapter with two elements.
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 mockWorkingRangeDelegate = [OCMockObject mockForProtocol:@protocol(IGListWorkingRangeDelegate)];
adapter.dataSource = ds;
controller2.workingRangeDelegate = mockWorkingRangeDelegate;
// 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, and only item in the list will be displayed.
[[mockWorkingRangeDelegate expect] listAdapter:adapter sectionControllerWillEnterWorkingRange:controller2];
[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 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)DISABLED_test_whenDisplayingItemsAtPaths_withWorkingRangeSizeZero_thenRemovingFirstItem_thenInsertingItemAtLastPosition_thatItemEntersWorkingRange {
// 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)DISABLED_test_whenDisplayingItemAtPath_withWorkingRangeSizeZero_thenInsertingNewItem_thatVisibleItemsRemainInWorkingRange {
// 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