Add edge-case unit tests

Summary:
- Removed dead code in batch data and updater
- Tested updating with empty index sets
- Tested updating with not-found section controller
- Tested reloading when collection view or data source are not set
- Tested `-[IGListAdapter sectionForObject:]`
- Tested index path return for not-found section controller
- Tested pointer comparison with `NSObject+IGListDiffable` category

Fixes #190, #189

- [x] All tests pass. Demo project builds and runs.
- [x] I added tests, an experiment, or detailed why my change isn't tested.
- [x] I have reviewed the [contributing guide](https://github.com/Instagram/IGListKit/blob/master/CONTRIBUTING.md)
Closes https://github.com/Instagram/IGListKit/pull/191

Differential Revision: D4172781

Pulled By: rnystrom

fbshipit-source-id: c25cc917e9a1ebc5fc94fa022e01f99c80c2466c
This commit is contained in:
Ryan Nystrom 2016-11-12 09:48:23 -08:00 committed by Facebook Github Bot
parent 715773476e
commit 8ea5e08880
5 changed files with 111 additions and 38 deletions

View file

@ -221,17 +221,6 @@ static NSArray *objectsWithDuplicateIdentifiersRemoved(NSArray<id<IGListDiffable
}
}
- (NSSet *)filterIndexPaths:(NSSet<NSIndexPath *> *)indexPaths removingSections:(NSIndexSet *)sections {
NSMutableSet *filteredIndexPaths = [indexPaths mutableCopy];
for (NSIndexPath *indexPath in indexPaths) {
const NSUInteger section = indexPath.section;
if ([sections containsIndex:section]) {
[filteredIndexPaths removeObject:indexPath];
}
}
return filteredIndexPaths;
}
void convertReloadToDeleteInsert(NSMutableIndexSet *reloads,
NSMutableIndexSet *deletes,
NSMutableIndexSet *inserts,
@ -300,16 +289,6 @@ void convertReloadToDeleteInsert(NSMutableIndexSet *reloads,
self.batchUpdateOrReloadInProgress = NO;
}
- (NSArray *)trimmedIndexPaths:(NSArray <NSIndexPath *> *)indexPaths inSections:(NSIndexSet *)sections {
NSMutableArray *paths = [indexPaths mutableCopy];
for (NSInteger i = 0; i < paths.count; i++) {
if ([sections containsIndex:[paths[i] section]]) {
[paths removeObjectAtIndex:i];
}
}
return paths;
}
- (void)cleanupState {
self.queuedUpdateIsAnimated = YES;

View file

@ -40,21 +40,6 @@ static void convertMoveToDeleteAndInsert(NSMutableSet<IGListMoveIndex *> *moves,
@implementation IGListBatchUpdateData
// Converts all moves that have section operations into a section delete + insert.
+ (void)cleanIndexSetWithMap:(const std::unordered_map<NSUInteger, IGListMoveIndex*> &)map
moves:(NSMutableSet<IGListMoveIndex *> *)moves
sections:(NSMutableIndexSet *)sections
deletes:(NSMutableIndexSet *)deletes
inserts:(NSMutableIndexSet *)inserts {
for(const auto &i : map) {
const NSUInteger index = i.first;
if ([sections containsIndex:index]) {
[sections removeIndex:index];
convertMoveToDeleteAndInsert(moves, i.second, deletes, inserts);
}
}
}
// Converts all section moves that have index path operations into a section delete + insert.
+ (void)cleanIndexPathsWithMap:(const std::unordered_map<NSUInteger, IGListMoveIndex*> &)map
moves:(NSMutableSet<IGListMoveIndex *> *)moves

View file

@ -32,7 +32,8 @@ IGListCollectionContext
__weak UICollectionView *_collectionView;
}
@property (nonatomic, strong, readonly) id <IGListUpdatingDelegate> updatingDelegate;
@property (nonatomic, strong) id <IGListUpdatingDelegate> updatingDelegate;
@property (nonatomic, strong, readonly) IGListSectionMap *sectionMap;
@property (nonatomic, strong, readonly) IGListDisplayHandler *displayHandler;
@property (nonatomic, strong, readonly) IGListWorkingRangeHandler *workingRangeHandler;
@ -61,6 +62,7 @@ IGListCollectionContext
- (NSArray *)indexPathsFromSectionController:(IGListSectionController <IGListSectionType> *)sectionController
indexes:(NSIndexSet *)indexes
adjustForUpdateBlock:(BOOL)adjustForUpdateBlock;
- (NSIndexPath *)indexPathForSectionController:(IGListSectionController *)controller index:(NSInteger)index;
@end

View file

@ -13,7 +13,6 @@
#import <OCMock/OCMock.h>
#import <IGListKit/IGListKit.h>
#import <IGListKit/IGListReloadDataUpdater.h>
#import "IGListAdapterInternal.h"
#import "IGListTestAdapterDataSource.h"
@ -626,4 +625,107 @@ XCTAssertEqual(CGPointEqualToPoint(point, p), YES); \
IGAssertEqualPoint([self.collectionView contentOffset], 0, 10);
}
- (void)test_whenQueryingIndexPath_withOOBSectionController_thatNilReturned {
self.dataSource.objects = @[@0, @1, @2];
[self.adapter reloadDataWithCompletion:nil];
id randomSectionController = [IGListSectionController new];
XCTAssertNil([self.adapter indexPathForSectionController:randomSectionController index:0]);
}
- (void)test_whenQueryingSectionForObject_thatSectionReturned {
self.dataSource.objects = @[@0, @1, @2];
[self.adapter reloadDataWithCompletion:nil];
XCTAssertEqual([self.adapter sectionForObject:@0], 0);
XCTAssertEqual([self.adapter sectionForObject:@1], 1);
XCTAssertEqual([self.adapter sectionForObject:@2], 2);
XCTAssertEqual([self.adapter sectionForObject:@3], NSNotFound);
}
- (void)test_whenReloadingData_withNoDataSource_thatCompletionCalledWithNO {
self.dataSource.objects = @[@1];
IGListAdapter *adapter = [[IGListAdapter alloc] initWithUpdater:[IGListReloadDataUpdater new]
viewController:nil
workingRangeSize:0];
adapter.collectionView = self.collectionView;
__block BOOL executed = NO;
[adapter reloadDataWithCompletion:^(BOOL finished) {
executed = YES;
XCTAssertFalse(finished);
}];
XCTAssertTrue(executed);
}
- (void)test_whenReloadingData_withNoCollectionView_thatCompletionCalledWithNO {
self.dataSource.objects = @[@1];
IGListAdapter *adapter = [[IGListAdapter alloc] initWithUpdater:[IGListReloadDataUpdater new]
viewController:nil
workingRangeSize:0];
adapter.dataSource = self.dataSource;
__block BOOL executed = NO;
[adapter reloadDataWithCompletion:^(BOOL finished) {
executed = YES;
XCTAssertFalse(finished);
}];
XCTAssertTrue(executed);
}
- (void)test_whenSectionControllerReloading_withEmptyIndexes_thatNoUpdatesHappen {
self.dataSource.objects = @[@0, @1, @2];
[self.adapter reloadDataWithCompletion:nil];
id mockDelegate = [OCMockObject mockForProtocol:@protocol(IGListUpdatingDelegate)];
[[mockDelegate reject] reloadItemsInCollectionView:[OCMArg any] indexPaths:[OCMArg any]];
self.adapter.updatingDelegate = mockDelegate;
id sectionController = [self.adapter sectionControllerForObject:@1];
[self.adapter reloadInSectionController:sectionController atIndexes:[NSIndexSet new]];
[mockDelegate verify];
}
- (void)test_whenSectionControllerDeleting_withEmptyIndexes_thatNoUpdatesHappen {
self.dataSource.objects = @[@0, @1, @2];
[self.adapter reloadDataWithCompletion:nil];
id mockDelegate = [OCMockObject mockForProtocol:@protocol(IGListUpdatingDelegate)];
[[mockDelegate reject] deleteItemsFromCollectionView:[OCMArg any] indexPaths:[OCMArg any]];
self.adapter.updatingDelegate = mockDelegate;
id sectionController = [self.adapter sectionControllerForObject:@1];
[self.adapter deleteInSectionController:sectionController atIndexes:[NSIndexSet new]];
[mockDelegate verify];
}
- (void)test_whenSectionControllerInserting_withEmptyIndexes_thatNoUpdatesHappen {
self.dataSource.objects = @[@0, @1, @2];
[self.adapter reloadDataWithCompletion:nil];
id mockDelegate = [OCMockObject mockForProtocol:@protocol(IGListUpdatingDelegate)];
[[mockDelegate reject] insertItemsIntoCollectionView:[OCMArg any] indexPaths:[OCMArg any]];
self.adapter.updatingDelegate = mockDelegate;
id sectionController = [self.adapter sectionControllerForObject:@1];
[self.adapter insertInSectionController:sectionController atIndexes:[NSIndexSet new]];
[mockDelegate verify];
}
- (void)test_whenReloading_withSectionControllerNotFound_thatNoUpdatesHappen {
self.dataSource.objects = @[@0, @1, @2];
[self.adapter reloadDataWithCompletion:nil];
id mockDelegate = [OCMockObject mockForProtocol:@protocol(IGListUpdatingDelegate)];
[[mockDelegate reject] reloadCollectionView:[OCMArg any] sections:[OCMArg any]];
self.adapter.updatingDelegate = mockDelegate;
id sectionController = [IGListSectionController new];
[self.adapter reloadSectionController:sectionController];
[mockDelegate verify];
}
@end

View file

@ -428,4 +428,9 @@ static NSArray *sorted(NSArray *arr) {
XCTAssertEqualObjects(sorted(result.inserts), expectedInserts);
}
- (void)test_whenComparingDiffableObjects_withDefaultCategory_thatPointersAreAlwaysEqual {
NSObject *object = [NSObject new];
XCTAssertTrue([object isEqualToDiffableObject:object]);
}
@end