mirror of
https://github.com/tappollo/IGListKit.git
synced 2026-01-12 22:45:13 +08:00
Summary: Quick rename before releasing 3.0 to get this API in parity w/ `isFirstSection` and `isLastSection`. My b I should have caught this in review. Closes #720 Reviewed By: jessesquires, amonshiz Differential Revision: D5031184 fbshipit-source-id: 1cd7b00c8b32084fecd861e78808eea0d0056337
906 lines
46 KiB
Objective-C
906 lines
46 KiB
Objective-C
/**
|
|
* Copyright (c) 2016-present, Facebook, Inc.
|
|
* All rights reserved.
|
|
*
|
|
* This source code is licensed under the BSD-style license found in the
|
|
* LICENSE file in the root directory of this source tree. An additional grant
|
|
* of patent rights can be found in the PATENTS file in the same directory.
|
|
*/
|
|
|
|
#import <XCTest/XCTest.h>
|
|
#import <OCMock/OCMock.h>
|
|
|
|
#import <IGListKit/IGListKit.h>
|
|
#import <IGListKit/IGListReloadDataUpdater.h>
|
|
|
|
#import "IGListAdapterInternal.h"
|
|
#import "IGListDisplayHandler.h"
|
|
#import "IGListStackedSectionControllerInternal.h"
|
|
#import "IGListTestSection.h"
|
|
#import "IGListTestContainerSizeSection.h"
|
|
#import "IGTestCell.h"
|
|
#import "IGTestStackedDataSource.h"
|
|
#import "IGTestStoryboardCell.h"
|
|
#import "IGTestStoryboardViewController.h"
|
|
#import "IGTestSupplementarySource.h"
|
|
#import "IGTestSupplementarySource.h"
|
|
#import "IGTestStoryboardSupplementarySource.h"
|
|
#import "IGListTestHelpers.h"
|
|
|
|
static const CGRect kStackTestFrame = (CGRect){{0.0, 0.0}, {100.0, 100.0}};
|
|
|
|
@interface IGListStackSectionControllerTests : XCTestCase
|
|
|
|
@property (nonatomic, strong) UIWindow *window;
|
|
@property (nonatomic, strong) UICollectionView *collectionView;
|
|
@property (nonatomic, strong) IGListAdapter *adapter;
|
|
@property (nonatomic, strong) IGTestStackedDataSource *dataSource;
|
|
|
|
@end
|
|
|
|
@implementation IGListStackSectionControllerTests
|
|
|
|
- (void)setUp {
|
|
[super setUp];
|
|
|
|
self.window = [[UIWindow alloc] initWithFrame:kStackTestFrame];
|
|
|
|
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"IGTestStoryboard" bundle:[NSBundle bundleForClass:self.class]];
|
|
IGTestStoryboardViewController *vc = [storyboard instantiateViewControllerWithIdentifier:@"testVC"];
|
|
self.window.rootViewController = vc;
|
|
[self.window addSubview:vc.view];
|
|
[vc performSelectorOnMainThread:@selector(loadView) withObject:nil waitUntilDone:YES];
|
|
self.collectionView = vc.collectionView;
|
|
|
|
vc.view.frame = kStackTestFrame;
|
|
self.collectionView.frame = kStackTestFrame;
|
|
|
|
self.dataSource = [[IGTestStackedDataSource alloc] init];
|
|
self.adapter = [[IGListAdapter alloc] initWithUpdater:[IGListAdapterUpdater new] viewController:nil workingRangeSize:1];
|
|
}
|
|
|
|
- (void)tearDown {
|
|
[super tearDown];
|
|
|
|
self.adapter = nil;
|
|
self.collectionView = nil;
|
|
self.dataSource = nil;
|
|
}
|
|
|
|
- (void)setupWithObjects:(NSArray *)objects {
|
|
self.dataSource.objects = objects;
|
|
self.adapter.collectionView = self.collectionView;
|
|
self.adapter.dataSource = self.dataSource;
|
|
[self.collectionView layoutIfNeeded];
|
|
}
|
|
|
|
#pragma mark - Base
|
|
|
|
- (void)test_whenInitializingStack_thatNumberOfItemsMatches {
|
|
IGListTestSection *section1 = [[IGListTestSection alloc] init];
|
|
section1.items = 2;
|
|
IGListTestSection *section2 = [[IGListTestSection alloc] init];
|
|
section2.items = 3;
|
|
IGListTestSection *section3 = [[IGListTestSection alloc] init];
|
|
section3.items = 0;
|
|
IGListTestSection *section4 = [[IGListTestSection alloc] init];
|
|
section4.items = 1;
|
|
|
|
IGListStackedSectionController *stack = [[IGListStackedSectionController alloc] initWithSectionControllers:@[section1, section2, section3, section4]];
|
|
[stack reloadData];
|
|
|
|
XCTAssertEqual([stack numberOfItems], 6);
|
|
}
|
|
|
|
- (void)test_whenInitializingStack_thatSectionControllerIndexesMatch {
|
|
IGListTestSection *section1 = [[IGListTestSection alloc] init];
|
|
section1.items = 2;
|
|
IGListTestSection *section2 = [[IGListTestSection alloc] init];
|
|
section2.items = 3;
|
|
IGListTestSection *section3 = [[IGListTestSection alloc] init];
|
|
section3.items = 0;
|
|
IGListTestSection *section4 = [[IGListTestSection alloc] init];
|
|
section4.items = 1;
|
|
|
|
IGListStackedSectionController *stack = [[IGListStackedSectionController alloc] initWithSectionControllers:@[section1, section2, section3, section4]];
|
|
[stack reloadData];
|
|
|
|
XCTAssertEqualObjects([stack sectionControllerForObjectIndex:0], section1);
|
|
XCTAssertEqualObjects([stack sectionControllerForObjectIndex:1], section1);
|
|
XCTAssertEqualObjects([stack sectionControllerForObjectIndex:2], section2);
|
|
XCTAssertEqualObjects([stack sectionControllerForObjectIndex:3], section2);
|
|
XCTAssertEqualObjects([stack sectionControllerForObjectIndex:4], section2);
|
|
XCTAssertEqualObjects([stack sectionControllerForObjectIndex:5], section4);
|
|
}
|
|
|
|
- (void)test_whenInitializingStack_thatSectionControllerOffsetsMatch {
|
|
IGListTestSection *section1 = [[IGListTestSection alloc] init];
|
|
section1.items = 2;
|
|
IGListTestSection *section2 = [[IGListTestSection alloc] init];
|
|
section2.items = 3;
|
|
IGListTestSection *section3 = [[IGListTestSection alloc] init];
|
|
section3.items = 0;
|
|
IGListTestSection *section4 = [[IGListTestSection alloc] init];
|
|
section4.items = 1;
|
|
|
|
IGListStackedSectionController *stack = [[IGListStackedSectionController alloc] initWithSectionControllers:@[section1, section2, section3, section4]];
|
|
[stack reloadData];
|
|
|
|
XCTAssertEqual([stack offsetForSectionController:section1], 0);
|
|
XCTAssertEqual([stack offsetForSectionController:section2], 2);
|
|
XCTAssertEqual([stack offsetForSectionController:section3], 5);
|
|
XCTAssertEqual([stack offsetForSectionController:section4], 5);
|
|
}
|
|
|
|
|
|
#pragma mark - IGListCollectionContext
|
|
|
|
- (void)test_whenReloadingStack_thatSectionControllerContainerMatchesCollectionView {
|
|
[self setupWithObjects:@[
|
|
[[IGTestObject alloc] initWithKey:@0 value:@[@1]]
|
|
]];
|
|
IGListStackedSectionController *stack = [self.adapter sectionControllerForObject:self.dataSource.objects[0]];
|
|
IGListTestSection *section1 = stack.sectionControllers[0];
|
|
XCTAssertTrue(CGSizeEqualToSize([section1.collectionContext containerSize], kStackTestFrame.size));
|
|
}
|
|
|
|
- (void)test_whenSectionEdgeInsetIsNotZero {
|
|
[self setupWithObjects:@[
|
|
[[IGTestObject alloc] initWithKey:@0 value:@[@42]]
|
|
]];
|
|
IGListStackedSectionController *stack = [self.adapter sectionControllerForObject:self.dataSource.objects[0]];
|
|
IGListTestContainerSizeSection *section1 = stack.sectionControllers[0];
|
|
IGAssertEqualSize([stack containerSizeForSectionController:section1], 98, 98);
|
|
}
|
|
|
|
- (void)test_whenQueryingContainerInset_thatMatchesCollectionView {
|
|
self.collectionView.contentInset = UIEdgeInsetsMake(1, 2, 3, 4);
|
|
[self setupWithObjects:@[
|
|
[[IGTestObject alloc] initWithKey:@0 value:@[@42]]
|
|
]];
|
|
IGListStackedSectionController *stack = [self.adapter sectionControllerForObject:self.dataSource.objects[0]];
|
|
IGListTestContainerSizeSection *section1 = stack.sectionControllers[0];
|
|
const UIEdgeInsets inset = [section1.collectionContext containerInset];
|
|
XCTAssertEqual(inset.top, 1);
|
|
XCTAssertEqual(inset.left, 2);
|
|
XCTAssertEqual(inset.bottom, 3);
|
|
XCTAssertEqual(inset.right, 4);
|
|
}
|
|
|
|
- (void)test_whenQueryingInsetContainerSize_thatBoundsInsetByContent {
|
|
self.collectionView.contentInset = UIEdgeInsetsMake(1, 2, 3, 4);
|
|
[self setupWithObjects:@[
|
|
[[IGTestObject alloc] initWithKey:@0 value:@[@42]]
|
|
]];
|
|
IGListStackedSectionController *stack = [self.adapter sectionControllerForObject:self.dataSource.objects[0]];
|
|
IGListTestContainerSizeSection *section1 = stack.sectionControllers[0];
|
|
const CGSize size = [section1.collectionContext insetContainerSize];
|
|
XCTAssertEqual(size.width, 94);
|
|
XCTAssertEqual(size.height, 96);
|
|
}
|
|
|
|
- (void)test_whenQueryingCellIndex_thatIndexIsRelativeToSectionController {
|
|
[self setupWithObjects:@[
|
|
[[IGTestObject alloc] initWithKey:@0 value:@[@1, @1, @2]]
|
|
]];
|
|
|
|
IGListStackedSectionController *stack = [self.adapter sectionControllerForObject:self.dataSource.objects[0]];
|
|
|
|
IGListTestSection *section1 = stack.sectionControllers[0];
|
|
UICollectionViewCell *cell1 = [self.collectionView cellForItemAtIndexPath:[NSIndexPath indexPathForItem:0 inSection:0]];
|
|
|
|
IGListTestSection *section2 = stack.sectionControllers[1];
|
|
UICollectionViewCell *cell2 = [self.collectionView cellForItemAtIndexPath:[NSIndexPath indexPathForItem:1 inSection:0]];
|
|
|
|
IGListTestSection *section3 = stack.sectionControllers[2];
|
|
UICollectionViewCell *cell30 = [self.collectionView cellForItemAtIndexPath:[NSIndexPath indexPathForItem:2 inSection:0]];
|
|
UICollectionViewCell *cell31 = [self.collectionView cellForItemAtIndexPath:[NSIndexPath indexPathForItem:3 inSection:0]];
|
|
|
|
// each controller in the stack has one cell, even though the item indexes are 0, 1, 2, 3
|
|
XCTAssertEqual([section1.collectionContext indexForCell:cell1 sectionController:section1], 0);
|
|
XCTAssertEqual([section2.collectionContext indexForCell:cell2 sectionController:section2], 0);
|
|
XCTAssertEqual([section3.collectionContext indexForCell:cell30 sectionController:section3], 0);
|
|
XCTAssertEqual([section3.collectionContext indexForCell:cell31 sectionController:section3], 1);
|
|
}
|
|
|
|
- (void)test_whenQueryingCells_thatCellIsRelativeToSectionController {
|
|
[self setupWithObjects:@[
|
|
[[IGTestObject alloc] initWithKey:@0 value:@[@1, @1, @2]]
|
|
]];
|
|
|
|
IGListStackedSectionController *stack = [self.adapter sectionControllerForObject:self.dataSource.objects[0]];
|
|
|
|
IGListTestSection *section1 = stack.sectionControllers[0];
|
|
UICollectionViewCell *cell1 = [self.collectionView cellForItemAtIndexPath:[NSIndexPath indexPathForItem:0 inSection:0]];
|
|
|
|
IGListTestSection *section2 = stack.sectionControllers[1];
|
|
UICollectionViewCell *cell2 = [self.collectionView cellForItemAtIndexPath:[NSIndexPath indexPathForItem:1 inSection:0]];
|
|
|
|
IGListTestSection *section3 = stack.sectionControllers[2];
|
|
UICollectionViewCell *cell30 = [self.collectionView cellForItemAtIndexPath:[NSIndexPath indexPathForItem:2 inSection:0]];
|
|
UICollectionViewCell *cell31 = [self.collectionView cellForItemAtIndexPath:[NSIndexPath indexPathForItem:3 inSection:0]];
|
|
|
|
// each controller in the stack has one cell, even though the item indexes are 0, 1, 2, 3
|
|
XCTAssertEqualObjects([section1.collectionContext cellForItemAtIndex:0 sectionController:section1], cell1);
|
|
XCTAssertEqualObjects([section2.collectionContext cellForItemAtIndex:0 sectionController:section2], cell2);
|
|
XCTAssertEqualObjects([section3.collectionContext cellForItemAtIndex:0 sectionController:section3], cell30);
|
|
XCTAssertEqualObjects([section3.collectionContext cellForItemAtIndex:1 sectionController:section3], cell31);
|
|
}
|
|
|
|
- (void)test_whenQueryingSectionControllerSection_thatSectionMatchesStackSection {
|
|
[self setupWithObjects:@[
|
|
[[IGTestObject alloc] initWithKey:@0 value:@[@1, @1]],
|
|
[[IGTestObject alloc] initWithKey:@1 value:@[@1, @1]]
|
|
]];
|
|
|
|
IGListStackedSectionController *stack1 = [self.adapter sectionControllerForObject:self.dataSource.objects[0]];
|
|
IGListStackedSectionController *stack2 = [self.adapter sectionControllerForObject:self.dataSource.objects[1]];
|
|
|
|
IGListTestSection *section11 = stack1.sectionControllers[0];
|
|
IGListTestSection *section12 = stack1.sectionControllers[1];
|
|
IGListTestSection *section21 = stack2.sectionControllers[0];
|
|
IGListTestSection *section22 = stack2.sectionControllers[1];
|
|
|
|
XCTAssertEqual(stack1.section, 0);
|
|
XCTAssertEqual(stack2.section, 1);
|
|
XCTAssertEqual(section11.section, 0);
|
|
XCTAssertEqual(section12.section, 0);
|
|
XCTAssertEqual(section21.section, 1);
|
|
XCTAssertEqual(section22.section, 1);
|
|
}
|
|
|
|
- (void)test_whenReloadingItems_thatCollectionViewReloadsRelativeIndexPaths {
|
|
[self setupWithObjects:@[
|
|
[[IGTestObject alloc] initWithKey:@0 value:@[@2, @2]]
|
|
]];
|
|
|
|
id mockCollectionView = [OCMockObject niceMockForClass:[UICollectionView class]];
|
|
self.adapter.collectionView = mockCollectionView;
|
|
|
|
IGListStackedSectionController *stack = [self.adapter sectionControllerForObject:self.dataSource.objects[0]];
|
|
|
|
id mockBatchContext = [OCMockObject mockForProtocol:@protocol(IGListBatchContext)];
|
|
stack.forwardingBatchContext = mockBatchContext;
|
|
|
|
IGListTestSection *section2 = stack.sectionControllers[1];
|
|
|
|
[[mockBatchContext expect] reloadInSectionController:stack atIndexes:[NSIndexSet indexSetWithIndex:3]];
|
|
[stack reloadInSectionController:section2 atIndexes:[NSIndexSet indexSetWithIndex:1]];
|
|
[mockBatchContext verify];
|
|
}
|
|
|
|
- (void)test_whenInsertingItems_thatCollectionViewReloadsRelativeIndexPaths {
|
|
[self setupWithObjects:@[
|
|
[[IGTestObject alloc] initWithKey:@0 value:@[@2, @2]]
|
|
]];
|
|
|
|
id mockCollectionView = [OCMockObject niceMockForClass:[UICollectionView class]];
|
|
self.adapter.collectionView = mockCollectionView;
|
|
|
|
IGListStackedSectionController *stack = [self.adapter sectionControllerForObject:self.dataSource.objects[0]];
|
|
|
|
id mockBatchContext = [OCMockObject mockForProtocol:@protocol(IGListBatchContext)];
|
|
stack.forwardingBatchContext = mockBatchContext;
|
|
|
|
IGListTestSection *section2 = stack.sectionControllers[1];
|
|
section2.items = 3;
|
|
|
|
[[mockBatchContext expect] insertInSectionController:stack atIndexes:[NSIndexSet indexSetWithIndex:4]];
|
|
[stack insertInSectionController:section2 atIndexes:[NSIndexSet indexSetWithIndex:2]];
|
|
[mockBatchContext verify];
|
|
|
|
XCTAssertEqual([stack numberOfItems], 5);
|
|
}
|
|
|
|
- (void)test_whenDeletingItems_thatCollectionViewReloadsRelativeIndexPaths {
|
|
[self setupWithObjects:@[
|
|
[[IGTestObject alloc] initWithKey:@0 value:@[@2, @2]]
|
|
]];
|
|
|
|
id mockCollectionView = [OCMockObject niceMockForClass:[UICollectionView class]];
|
|
self.adapter.collectionView = mockCollectionView;
|
|
|
|
IGListStackedSectionController *stack = [self.adapter sectionControllerForObject:self.dataSource.objects[0]];
|
|
|
|
id mockBatchContext = [OCMockObject mockForProtocol:@protocol(IGListBatchContext)];
|
|
stack.forwardingBatchContext = mockBatchContext;
|
|
|
|
IGListTestSection *section2 = stack.sectionControllers[1];
|
|
section2.items = 1;
|
|
|
|
[[mockBatchContext expect] deleteInSectionController:stack atIndexes:[NSIndexSet indexSetWithIndex:3]];
|
|
[stack deleteInSectionController:section2 atIndexes:[NSIndexSet indexSetWithIndex:1]];
|
|
[mockBatchContext verify];
|
|
|
|
XCTAssertEqual([stack numberOfItems], 3);
|
|
}
|
|
|
|
- (void)test_whenReloadingSectionController_thatCollectionViewReloadsStack {
|
|
[self setupWithObjects:@[
|
|
[[IGTestObject alloc] initWithKey:@0 value:@[@2, @2]]
|
|
]];
|
|
|
|
id mockCollectionView = [OCMockObject niceMockForClass:[UICollectionView class]];
|
|
self.adapter.collectionView = mockCollectionView;
|
|
|
|
IGListStackedSectionController *stack = [self.adapter sectionControllerForObject:self.dataSource.objects[0]];
|
|
|
|
id mockBatchContext = [OCMockObject mockForProtocol:@protocol(IGListBatchContext)];
|
|
stack.forwardingBatchContext = mockBatchContext;
|
|
|
|
IGListTestSection *section2 = stack.sectionControllers[1];
|
|
section2.items = 3;
|
|
|
|
// section 0 b/c any controller doing a full reload will queue reload of the entire stack
|
|
[[mockBatchContext expect] reloadSectionController:stack];
|
|
[stack reloadSectionController:section2];
|
|
[mockBatchContext verify];
|
|
|
|
XCTAssertEqual([stack numberOfItems], 5);
|
|
}
|
|
|
|
- (void)test_whenDisplayingCell_thatEventsForwardedToSectionControllers {
|
|
id mock1Delegate = [OCMockObject mockForProtocol:@protocol(IGListDisplayDelegate)];
|
|
id mock2Delegate = [OCMockObject mockForProtocol:@protocol(IGListDisplayDelegate)];
|
|
IGListTestSection *section1 = [[IGListTestSection alloc] init];
|
|
section1.items = 2;
|
|
section1.displayDelegate = mock1Delegate;
|
|
IGListTestSection *section2 = [[IGListTestSection alloc] init];
|
|
section2.displayDelegate = mock2Delegate;
|
|
section2.items = 2;
|
|
UICollectionViewCell *cell1 = [UICollectionViewCell new];
|
|
UICollectionViewCell *cell2 = [UICollectionViewCell new];
|
|
|
|
[[mock1Delegate expect] listAdapter:self.adapter willDisplaySectionController:section1];
|
|
[[mock1Delegate expect] listAdapter:self.adapter willDisplaySectionController:section1 cell:cell1 atIndex:0];
|
|
[[mock1Delegate expect] listAdapter:self.adapter willDisplaySectionController:section1 cell:cell2 atIndex:1];
|
|
[[mock2Delegate reject] listAdapter:self.adapter willDisplaySectionController:section2];
|
|
|
|
IGListDisplayHandler *display = [[IGListDisplayHandler alloc] init];
|
|
IGListStackedSectionController *stack = [[IGListStackedSectionController alloc] initWithSectionControllers:@[section1, section2]];
|
|
[stack reloadData];
|
|
|
|
[display willDisplayCell:cell1 forListAdapter:self.adapter sectionController:stack object:@"a" indexPath:[NSIndexPath indexPathForItem:0 inSection:0]];
|
|
[display willDisplayCell:cell2 forListAdapter:self.adapter sectionController:stack object:@"a" indexPath:[NSIndexPath indexPathForItem:1 inSection:0]];
|
|
|
|
[mock1Delegate verify];
|
|
[mock2Delegate verify];
|
|
}
|
|
|
|
- (void)test_whenEndDisplayingCell_thatEventsForwardedToSectionControllers {
|
|
id mock1Delegate = [OCMockObject mockForProtocol:@protocol(IGListDisplayDelegate)];
|
|
id mock2Delegate = [OCMockObject mockForProtocol:@protocol(IGListDisplayDelegate)];
|
|
IGListTestSection *section1 = [[IGListTestSection alloc] init];
|
|
section1.items = 2;
|
|
IGListTestSection *section2 = [[IGListTestSection alloc] init];
|
|
section2.items = 2;
|
|
UICollectionViewCell *cell1 = [UICollectionViewCell new];
|
|
UICollectionViewCell *cell2 = [UICollectionViewCell new];
|
|
UICollectionViewCell *cell3 = [UICollectionViewCell new];
|
|
UICollectionViewCell *cell4 = [UICollectionViewCell new];
|
|
|
|
IGListDisplayHandler *display = [[IGListDisplayHandler alloc] init];
|
|
IGListStackedSectionController *stack = [[IGListStackedSectionController alloc] initWithSectionControllers:@[section1, section2]];
|
|
[stack reloadData];
|
|
|
|
// display all 4 cells (2 per child section controller)
|
|
[display willDisplayCell:cell1 forListAdapter:self.adapter sectionController:stack object:@"a" indexPath:[NSIndexPath indexPathForItem:0 inSection:0]];
|
|
[display willDisplayCell:cell2 forListAdapter:self.adapter sectionController:stack object:@"a" indexPath:[NSIndexPath indexPathForItem:1 inSection:0]];
|
|
[display willDisplayCell:cell3 forListAdapter:self.adapter sectionController:stack object:@"a" indexPath:[NSIndexPath indexPathForItem:2 inSection:0]];
|
|
[display willDisplayCell:cell4 forListAdapter:self.adapter sectionController:stack object:@"a" indexPath:[NSIndexPath indexPathForItem:3 inSection:0]];
|
|
|
|
section1.displayDelegate = mock1Delegate;
|
|
section2.displayDelegate = mock2Delegate;
|
|
|
|
[[mock1Delegate expect] listAdapter:self.adapter didEndDisplayingSectionController:section1];
|
|
[[mock1Delegate expect] listAdapter:self.adapter didEndDisplayingSectionController:section1 cell:cell1 atIndex:0];
|
|
[[mock1Delegate expect] listAdapter:self.adapter didEndDisplayingSectionController:section1 cell:cell2 atIndex:1];
|
|
[[mock2Delegate reject] listAdapter:self.adapter didEndDisplayingSectionController:section2];
|
|
|
|
[display didEndDisplayingCell:cell1 forListAdapter:self.adapter sectionController:stack indexPath:[NSIndexPath indexPathForItem:0 inSection:0]];
|
|
[display didEndDisplayingCell:cell2 forListAdapter:self.adapter sectionController:stack indexPath:[NSIndexPath indexPathForItem:1 inSection:0]];
|
|
|
|
[mock1Delegate verify];
|
|
[mock2Delegate verify];
|
|
}
|
|
|
|
- (void)test_whenRemovingCell_thatEventsForwardedToSectionControllers {
|
|
[self setupWithObjects:@[
|
|
[[IGTestObject alloc] initWithKey:@0 value:@[@1, @2]],
|
|
[[IGTestObject alloc] initWithKey:@1 value:@[@1, @2]]
|
|
]];
|
|
|
|
IGTestObject *obj1 = self.dataSource.objects[0];
|
|
IGTestObject *obj2 = self.dataSource.objects[1];
|
|
|
|
self.dataSource.objects = @[obj1];
|
|
|
|
id mockDelegate = [OCMockObject mockForProtocol:@protocol(IGListDisplayDelegate)];
|
|
|
|
IGListStackedSectionController *stack = [self.adapter sectionControllerForObject:obj2];
|
|
|
|
IGListTestSection *section1 = stack.sectionControllers[0];
|
|
IGListTestSection *section2 = stack.sectionControllers[1];
|
|
|
|
section1.displayDelegate = mockDelegate;
|
|
section2.displayDelegate = mockDelegate;
|
|
|
|
UICollectionViewCell *cell1 = [self.adapter.collectionView cellForItemAtIndexPath:[NSIndexPath indexPathForItem:0 inSection:1]];
|
|
UICollectionViewCell *cell2 = [self.adapter.collectionView cellForItemAtIndexPath:[NSIndexPath indexPathForItem:1 inSection:1]];
|
|
UICollectionViewCell *cell3 = [self.adapter.collectionView cellForItemAtIndexPath:[NSIndexPath indexPathForItem:2 inSection:1]];
|
|
|
|
[[mockDelegate expect] listAdapter:self.adapter didEndDisplayingSectionController:section1];
|
|
[[mockDelegate expect] listAdapter:self.adapter didEndDisplayingSectionController:section2];
|
|
[[mockDelegate expect] listAdapter:self.adapter didEndDisplayingSectionController:section1 cell:cell1 atIndex:0];
|
|
[[mockDelegate expect] listAdapter:self.adapter didEndDisplayingSectionController:section2 cell:cell2 atIndex:0];
|
|
[[mockDelegate expect] listAdapter:self.adapter didEndDisplayingSectionController:section2 cell:cell3 atIndex:1];
|
|
|
|
XCTestExpectation *expectation = [self expectationWithDescription:NSStringFromSelector(_cmd)];
|
|
[self.adapter reloadDataWithCompletion:^(BOOL finished) {
|
|
[mockDelegate verify];
|
|
[expectation fulfill];
|
|
}];
|
|
[self waitForExpectationsWithTimeout:30 handler:nil];
|
|
}
|
|
|
|
- (void)test_whenQueryingVisibleSectionControllers_withCellsOffscreen_thatOnlyVisibleReturned {
|
|
[self setupWithObjects:@[
|
|
[[IGTestObject alloc] initWithKey:@0 value:@[@3, @4, @0, @5, @6]]
|
|
]];
|
|
IGListStackedSectionController *stack = [self.adapter sectionControllerForObject:self.dataSource.objects[0]];
|
|
|
|
IGListTestSection *section1 = stack.sectionControllers[0];
|
|
IGListTestSection *section2 = stack.sectionControllers[1];
|
|
IGListTestSection *section3 = stack.sectionControllers[2];
|
|
IGListTestSection *section4 = stack.sectionControllers[3];
|
|
IGListTestSection *section5 = stack.sectionControllers[4];
|
|
|
|
XCTAssertEqual([self.adapter visibleCellsForSectionController:stack].count, 10);
|
|
XCTAssertEqual([stack visibleCellsForSectionController:section1].count, 3);
|
|
XCTAssertEqual([stack visibleCellsForSectionController:section2].count, 4);
|
|
XCTAssertEqual([stack visibleCellsForSectionController:section3].count, 0);
|
|
XCTAssertEqual([stack visibleCellsForSectionController:section4].count, 3);
|
|
XCTAssertEqual([stack visibleCellsForSectionController:section5].count, 0);
|
|
}
|
|
|
|
- (void)test_whenQueryingVisibleSectionControllers_withIndexPathsOffscreen_thatOnlyVisibleReturned {
|
|
[self setupWithObjects:@[
|
|
[[IGTestObject alloc] initWithKey:@0 value:@[@3, @4, @0, @5, @6]]
|
|
]];
|
|
IGListStackedSectionController *stack = [self.adapter sectionControllerForObject:self.dataSource.objects[0]];
|
|
|
|
IGListTestSection *section1 = stack.sectionControllers[0];
|
|
IGListTestSection *section2 = stack.sectionControllers[1];
|
|
IGListTestSection *section3 = stack.sectionControllers[2];
|
|
IGListTestSection *section4 = stack.sectionControllers[3];
|
|
IGListTestSection *section5 = stack.sectionControllers[4];
|
|
|
|
NSSet *visible1 = [NSSet setWithArray:[stack visibleIndexPathsForSectionController:section1]];
|
|
NSSet *expected1 = [NSSet setWithArray:@[
|
|
[NSIndexPath indexPathForItem:0 inSection:0],
|
|
[NSIndexPath indexPathForItem:1 inSection:0],
|
|
[NSIndexPath indexPathForItem:2 inSection:0],
|
|
]];
|
|
XCTAssertEqualObjects(visible1, expected1);
|
|
|
|
NSSet *visible2 = [NSSet setWithArray:[stack visibleIndexPathsForSectionController:section2]];
|
|
NSSet *expected2 = [NSSet setWithArray:@[
|
|
[NSIndexPath indexPathForItem:3 inSection:0],
|
|
[NSIndexPath indexPathForItem:4 inSection:0],
|
|
[NSIndexPath indexPathForItem:5 inSection:0],
|
|
[NSIndexPath indexPathForItem:6 inSection:0],
|
|
]];
|
|
XCTAssertEqualObjects(visible2, expected2);
|
|
|
|
NSSet *visible3 = [NSSet setWithArray:[stack visibleIndexPathsForSectionController:section3]];
|
|
NSSet *expected3 = [NSSet setWithArray:@[]];
|
|
XCTAssertEqualObjects(visible3, expected3);
|
|
|
|
NSSet *visible4 = [NSSet setWithArray:[stack visibleIndexPathsForSectionController:section4]];
|
|
NSSet *expected4 = [NSSet setWithArray:@[
|
|
[NSIndexPath indexPathForItem:7 inSection:0],
|
|
[NSIndexPath indexPathForItem:8 inSection:0],
|
|
[NSIndexPath indexPathForItem:9 inSection:0],
|
|
]];
|
|
XCTAssertEqualObjects(visible4, expected4);
|
|
|
|
NSSet *visible5 = [NSSet setWithArray:[stack visibleIndexPathsForSectionController:section5]];
|
|
NSSet *expected5 = [NSSet setWithArray:@[]];
|
|
XCTAssertEqualObjects(visible5, expected5);
|
|
}
|
|
|
|
- (void)test_whenPerformingItemUpdates_thatMutationsMapToSectionControllers {
|
|
[self setupWithObjects:@[
|
|
[[IGTestObject alloc] initWithKey:@0 value:@[@1, @2, @3]],
|
|
[[IGTestObject alloc] initWithKey:@1 value:@[@1, @2, @3]],
|
|
[[IGTestObject alloc] initWithKey:@2 value:@[@1, @1]]
|
|
]];
|
|
|
|
IGTestObject *object = self.dataSource.objects[1];
|
|
|
|
IGListStackedSectionController *stack = [self.adapter sectionControllerForObject:object];
|
|
IGListTestSection *section1 = stack.sectionControllers[0];
|
|
IGListTestSection *section2 = stack.sectionControllers[1];
|
|
|
|
XCTestExpectation *expectation = [self expectationWithDescription:NSStringFromSelector(_cmd)];
|
|
[section1.collectionContext performBatchAnimated:YES updates:^(id<IGListBatchContext> batchContext) {
|
|
section1.items = 3;
|
|
[batchContext insertInSectionController:section1 atIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(1, 2)]];
|
|
} completion:^(BOOL finished2) {
|
|
XCTAssertEqual([self.collectionView numberOfSections], 3);
|
|
XCTAssertEqual([self.collectionView numberOfItemsInSection:0], 6);
|
|
XCTAssertEqual([self.collectionView numberOfItemsInSection:1], 7);
|
|
XCTAssertEqual([self.collectionView numberOfItemsInSection:2], 2);
|
|
[expectation fulfill];
|
|
}];
|
|
|
|
[section2.collectionContext performBatchAnimated:YES updates:^(id<IGListBatchContext> batchContext) {
|
|
section2.items = 1;
|
|
[batchContext deleteInSectionController:section2 atIndexes:[NSIndexSet indexSetWithIndex:0]];
|
|
} completion:nil];
|
|
|
|
[self waitForExpectationsWithTimeout:30 handler:nil];
|
|
}
|
|
|
|
- (void)test_whenSelectingItems_thatChildSectionControllersSelected {
|
|
[self setupWithObjects:@[
|
|
[[IGTestObject alloc] initWithKey:@0 value:@[@1, @2, @3]],
|
|
[[IGTestObject alloc] initWithKey:@1 value:@[@1, @2, @3]],
|
|
[[IGTestObject alloc] initWithKey:@2 value:@[@1, @1]]
|
|
]];
|
|
|
|
[self.adapter collectionView:self.collectionView didSelectItemAtIndexPath:[NSIndexPath indexPathForItem:0 inSection:0]];
|
|
[self.adapter collectionView:self.collectionView didSelectItemAtIndexPath:[NSIndexPath indexPathForItem:2 inSection:1]];
|
|
[self.adapter collectionView:self.collectionView didSelectItemAtIndexPath:[NSIndexPath indexPathForItem:1 inSection:2]];
|
|
|
|
IGListStackedSectionController *stack0 = [self.adapter sectionControllerForObject:self.dataSource.objects[0]];
|
|
IGListStackedSectionController *stack1 = [self.adapter sectionControllerForObject:self.dataSource.objects[1]];
|
|
IGListStackedSectionController *stack2 = [self.adapter sectionControllerForObject:self.dataSource.objects[2]];
|
|
|
|
XCTAssertTrue([stack0.sectionControllers[0] wasSelected]);
|
|
XCTAssertFalse([stack0.sectionControllers[1] wasSelected]);
|
|
XCTAssertFalse([stack0.sectionControllers[2] wasSelected]);
|
|
XCTAssertFalse([stack1.sectionControllers[0] wasSelected]);
|
|
XCTAssertTrue([stack1.sectionControllers[1] wasSelected]);
|
|
XCTAssertFalse([stack1.sectionControllers[2] wasSelected]);
|
|
XCTAssertFalse([stack2.sectionControllers[0] wasSelected]);
|
|
XCTAssertTrue([stack2.sectionControllers[1] wasSelected]);
|
|
}
|
|
|
|
- (void)test_whenUsingNibs_withStoryboards_thatCellsAreConfigured {
|
|
[self setupWithObjects:@[
|
|
[[IGTestObject alloc] initWithKey:@0 value:@[@1, @"nib", @"storyboard"]],
|
|
]];
|
|
|
|
UICollectionViewCell *cell0 = [self.collectionView cellForItemAtIndexPath:[NSIndexPath indexPathForItem:0 inSection:0]];
|
|
IGTestCell *cell1 = (IGTestCell *)[self.collectionView cellForItemAtIndexPath:[NSIndexPath indexPathForItem:1 inSection:0]];
|
|
IGTestStoryboardCell *cell2 = (IGTestStoryboardCell *)[self.collectionView cellForItemAtIndexPath:[NSIndexPath indexPathForItem:2 inSection:0]];
|
|
|
|
XCTAssertEqualObjects(cell0.class, [UICollectionViewCell class]);
|
|
XCTAssertEqualObjects(cell1.class, [IGTestCell class]);
|
|
XCTAssertEqualObjects(cell2.class, [IGTestStoryboardCell class]);
|
|
|
|
XCTAssertEqualObjects(cell1.label.text, @"nib");
|
|
XCTAssertEqualObjects(cell2.label.text, @"storyboard");
|
|
}
|
|
|
|
- (void)test_whenForwardingDidScrollEvent_thatChildSectionControllersReceiveEvent {
|
|
[self setupWithObjects:@[
|
|
[[IGTestObject alloc] initWithKey:@0 value:@[@1, @2, @3]],
|
|
[[IGTestObject alloc] initWithKey:@2 value:@[@1, @1]]
|
|
]];
|
|
|
|
id mockScrollDelegate = [OCMockObject mockForProtocol:@protocol(IGListScrollDelegate)];
|
|
|
|
IGListStackedSectionController *stack0 = [self.adapter sectionControllerForObject:self.dataSource.objects[0]];
|
|
IGListStackedSectionController *stack1 = [self.adapter sectionControllerForObject:self.dataSource.objects[1]];
|
|
|
|
[stack0.sectionControllers[0] setScrollDelegate:mockScrollDelegate];
|
|
[stack0.sectionControllers[1] setScrollDelegate:mockScrollDelegate];
|
|
[stack0.sectionControllers[2] setScrollDelegate:mockScrollDelegate];
|
|
[stack1.sectionControllers[0] setScrollDelegate:mockScrollDelegate];
|
|
[stack1.sectionControllers[1] setScrollDelegate:mockScrollDelegate];
|
|
|
|
[[mockScrollDelegate expect] listAdapter:self.adapter didScrollSectionController:stack0.sectionControllers[0]];
|
|
[[mockScrollDelegate expect] listAdapter:self.adapter didScrollSectionController:stack0.sectionControllers[1]];
|
|
[[mockScrollDelegate expect] listAdapter:self.adapter didScrollSectionController:stack0.sectionControllers[2]];
|
|
[[mockScrollDelegate expect] listAdapter:self.adapter didScrollSectionController:stack1.sectionControllers[0]];
|
|
[[mockScrollDelegate expect] listAdapter:self.adapter didScrollSectionController:stack1.sectionControllers[1]];
|
|
|
|
[self.adapter scrollViewDidScroll:self.collectionView];
|
|
|
|
[mockScrollDelegate verify];
|
|
}
|
|
|
|
- (void)test_whenForwardingWillBeginDraggingEvent_thatChildSectionControllersReceiveEvent {
|
|
[self setupWithObjects:@[
|
|
[[IGTestObject alloc] initWithKey:@0 value:@[@1, @2, @3]],
|
|
[[IGTestObject alloc] initWithKey:@2 value:@[@1, @1]]
|
|
]];
|
|
|
|
id mockScrollDelegate = [OCMockObject mockForProtocol:@protocol(IGListScrollDelegate)];
|
|
|
|
IGListStackedSectionController *stack0 = [self.adapter sectionControllerForObject:self.dataSource.objects[0]];
|
|
IGListStackedSectionController *stack1 = [self.adapter sectionControllerForObject:self.dataSource.objects[1]];
|
|
|
|
[stack0.sectionControllers[0] setScrollDelegate:mockScrollDelegate];
|
|
[stack0.sectionControllers[1] setScrollDelegate:mockScrollDelegate];
|
|
[stack0.sectionControllers[2] setScrollDelegate:mockScrollDelegate];
|
|
[stack1.sectionControllers[0] setScrollDelegate:mockScrollDelegate];
|
|
[stack1.sectionControllers[1] setScrollDelegate:mockScrollDelegate];
|
|
|
|
[[mockScrollDelegate expect] listAdapter:self.adapter willBeginDraggingSectionController:stack0.sectionControllers[0]];
|
|
[[mockScrollDelegate expect] listAdapter:self.adapter willBeginDraggingSectionController:stack0.sectionControllers[1]];
|
|
[[mockScrollDelegate expect] listAdapter:self.adapter willBeginDraggingSectionController:stack0.sectionControllers[2]];
|
|
[[mockScrollDelegate expect] listAdapter:self.adapter willBeginDraggingSectionController:stack1.sectionControllers[0]];
|
|
[[mockScrollDelegate expect] listAdapter:self.adapter willBeginDraggingSectionController:stack1.sectionControllers[1]];
|
|
|
|
[self.adapter scrollViewWillBeginDragging:self.collectionView];
|
|
|
|
[mockScrollDelegate verify];
|
|
}
|
|
|
|
- (void)test_whenForwardingDidEndDraggingEvent_thatChildSectionControllersReceiveEvent {
|
|
[self setupWithObjects:@[
|
|
[[IGTestObject alloc] initWithKey:@0 value:@[@1, @2, @3]],
|
|
[[IGTestObject alloc] initWithKey:@2 value:@[@1, @1]]
|
|
]];
|
|
|
|
id mockScrollDelegate = [OCMockObject mockForProtocol:@protocol(IGListScrollDelegate)];
|
|
|
|
IGListStackedSectionController *stack0 = [self.adapter sectionControllerForObject:self.dataSource.objects[0]];
|
|
IGListStackedSectionController *stack1 = [self.adapter sectionControllerForObject:self.dataSource.objects[1]];
|
|
|
|
[stack0.sectionControllers[0] setScrollDelegate:mockScrollDelegate];
|
|
[stack0.sectionControllers[1] setScrollDelegate:mockScrollDelegate];
|
|
[stack0.sectionControllers[2] setScrollDelegate:mockScrollDelegate];
|
|
[stack1.sectionControllers[0] setScrollDelegate:mockScrollDelegate];
|
|
[stack1.sectionControllers[1] setScrollDelegate:mockScrollDelegate];
|
|
|
|
[[mockScrollDelegate expect] listAdapter:self.adapter didEndDraggingSectionController:stack0.sectionControllers[0] willDecelerate:NO];
|
|
[[mockScrollDelegate expect] listAdapter:self.adapter didEndDraggingSectionController:stack0.sectionControllers[1] willDecelerate:NO];
|
|
[[mockScrollDelegate expect] listAdapter:self.adapter didEndDraggingSectionController:stack0.sectionControllers[2] willDecelerate:NO];
|
|
[[mockScrollDelegate expect] listAdapter:self.adapter didEndDraggingSectionController:stack1.sectionControllers[0] willDecelerate:NO];
|
|
[[mockScrollDelegate expect] listAdapter:self.adapter didEndDraggingSectionController:stack1.sectionControllers[1] willDecelerate:NO];
|
|
|
|
[self.adapter scrollViewDidEndDragging:self.collectionView willDecelerate:NO];
|
|
|
|
[mockScrollDelegate verify];
|
|
}
|
|
|
|
- (void)test_whenUsingSupplementary_withCode_thatSupplementaryViewExists {
|
|
// updater that uses reloadData so we can rebuild all views/sizes
|
|
IGListAdapter *adapter = [[IGListAdapter alloc] initWithUpdater:[IGListReloadDataUpdater new] viewController:nil];
|
|
|
|
self.dataSource.objects = @[
|
|
[[IGTestObject alloc] initWithKey:@0 value:@[@1, @2, @3]],
|
|
[[IGTestObject alloc] initWithKey:@2 value:@[@1, @1]]
|
|
];
|
|
|
|
adapter.collectionView = self.collectionView;
|
|
adapter.dataSource = self.dataSource;
|
|
[self.collectionView layoutIfNeeded];
|
|
|
|
IGListStackedSectionController *stack = [adapter sectionControllerForObject:self.dataSource.objects[1]];
|
|
IGListTestSection *section = stack.sectionControllers.lastObject;
|
|
|
|
IGTestSupplementarySource *supplementarySource = [IGTestSupplementarySource new];
|
|
// the stack acts as the collection context. manually assign it.
|
|
supplementarySource.collectionContext = stack;
|
|
// however the actual section controller the supplementary serves is a child of the stack
|
|
supplementarySource.sectionController = section;
|
|
supplementarySource.supportedElementKinds = @[UICollectionElementKindSectionFooter];
|
|
|
|
section.supplementaryViewSource = supplementarySource;
|
|
|
|
[adapter performUpdatesAnimated:NO completion:nil];
|
|
|
|
XCTAssertNotNil([self.collectionView supplementaryViewForElementKind:UICollectionElementKindSectionFooter
|
|
atIndexPath:[NSIndexPath indexPathForItem:0 inSection:1]]);
|
|
XCTAssertNotNil(supplementarySource);
|
|
}
|
|
|
|
- (void)test_whenUsingSupplementary_withNib_thatSupplementaryViewExists {
|
|
// updater that uses reloadData so we can rebuild all views/sizes
|
|
IGListAdapter *adapter = [[IGListAdapter alloc] initWithUpdater:[IGListReloadDataUpdater new] viewController:nil];
|
|
|
|
self.dataSource.objects = @[
|
|
[[IGTestObject alloc] initWithKey:@0 value:@[@1, @2, @3]],
|
|
[[IGTestObject alloc] initWithKey:@2 value:@[@1, @1]]
|
|
];
|
|
|
|
adapter.collectionView = self.collectionView;
|
|
adapter.dataSource = self.dataSource;
|
|
[self.collectionView layoutIfNeeded];
|
|
|
|
IGListStackedSectionController *stack = [adapter sectionControllerForObject:self.dataSource.objects[1]];
|
|
IGListTestSection *section = stack.sectionControllers.lastObject;
|
|
|
|
IGTestSupplementarySource *supplementarySource = [IGTestSupplementarySource new];
|
|
// the stack acts as the collection context. manually assign it.
|
|
supplementarySource.collectionContext = stack;
|
|
// however the actual section controller the supplementary serves is a child of the stack
|
|
supplementarySource.sectionController = section;
|
|
supplementarySource.supportedElementKinds = @[UICollectionElementKindSectionFooter];
|
|
supplementarySource.dequeueFromNib = YES;
|
|
|
|
section.supplementaryViewSource = supplementarySource;
|
|
|
|
[adapter performUpdatesAnimated:NO completion:nil];
|
|
|
|
XCTAssertNotNil([self.collectionView supplementaryViewForElementKind:UICollectionElementKindSectionFooter
|
|
atIndexPath:[NSIndexPath indexPathForItem:0 inSection:1]]);
|
|
XCTAssertNotNil(supplementarySource);
|
|
}
|
|
|
|
- (void)test_whenUsingSupplementary_withStoryboard_thatSupplementaryViewExists {
|
|
// updater that uses reloadData so we can rebuild all views/sizes
|
|
IGListAdapter *adapter = [[IGListAdapter alloc] initWithUpdater:[IGListReloadDataUpdater new] viewController:nil];
|
|
|
|
self.dataSource.objects = @[
|
|
[[IGTestObject alloc] initWithKey:@0 value:@[@1, @2, @3]],
|
|
[[IGTestObject alloc] initWithKey:@2 value:@[@1, @1]]
|
|
];
|
|
|
|
adapter.collectionView = self.collectionView;
|
|
adapter.dataSource = self.dataSource;
|
|
[self.collectionView layoutIfNeeded];
|
|
|
|
IGListStackedSectionController *stack = [adapter sectionControllerForObject:self.dataSource.objects[1]];
|
|
IGListTestSection *section = stack.sectionControllers.lastObject;
|
|
|
|
IGTestStoryboardSupplementarySource *supplementarySource = [IGTestStoryboardSupplementarySource new];
|
|
// the stack acts as the collection context. manually assign it.
|
|
supplementarySource.collectionContext = stack;
|
|
// however the actual section controller the supplementary serves is a child of the stack
|
|
supplementarySource.sectionController = section;
|
|
|
|
// the "section header" property of the parent collection view must be checked
|
|
supplementarySource.supportedElementKinds = @[UICollectionElementKindSectionHeader];
|
|
|
|
section.supplementaryViewSource = supplementarySource;
|
|
|
|
[adapter performUpdatesAnimated:NO completion:nil];
|
|
|
|
XCTAssertNotNil([self.collectionView supplementaryViewForElementKind:UICollectionElementKindSectionHeader
|
|
atIndexPath:[NSIndexPath indexPathForItem:0 inSection:1]]);
|
|
XCTAssertNotNil(supplementarySource);
|
|
}
|
|
|
|
- (void)test_whenScrollingFromChildSectionController_thatScrollsToCorrectPosition {
|
|
// pad with enough items that we can freely scroll to the middle without accounting for content size
|
|
[self setupWithObjects:@[
|
|
[[IGTestObject alloc] initWithKey:@0 value:@[@4, @5, @6]],
|
|
[[IGTestObject alloc] initWithKey:@1 value:@[@1, @2, @3]],
|
|
[[IGTestObject alloc] initWithKey:@2 value:@[@4, @5, @6]]
|
|
]];
|
|
|
|
IGListStackedSectionController *stack = [self.adapter sectionControllerForObject:self.dataSource.objects[1]];
|
|
IGListTestSection *section = stack.sectionControllers[1];
|
|
|
|
[section.collectionContext scrollToSectionController:section atIndex:1 scrollPosition:UICollectionViewScrollPositionTop animated:NO];
|
|
|
|
// IGListTestSection cells are 100x10
|
|
XCTAssertEqual(self.collectionView.contentOffset.x, 0);
|
|
XCTAssertEqual(self.collectionView.contentOffset.y, 170);
|
|
}
|
|
|
|
- (void)test_whenDeselectingChildSectionControllerIndex_thatCorrectCellDeselected {
|
|
[self setupWithObjects:@[
|
|
[[IGTestObject alloc] initWithKey:@0 value:@[@1, @2, @3]],
|
|
[[IGTestObject alloc] initWithKey:@1 value:@[@1, @1]]
|
|
]];
|
|
|
|
NSIndexPath *path = [NSIndexPath indexPathForItem:1 inSection:1];
|
|
[self.collectionView selectItemAtIndexPath:path animated:NO scrollPosition:UICollectionViewScrollPositionTop];
|
|
XCTAssertTrue([[self.collectionView cellForItemAtIndexPath:path] isSelected]);
|
|
|
|
IGListStackedSectionController *stack = [self.adapter sectionControllerForObject:self.dataSource.objects.lastObject];
|
|
IGListSectionController *section = stack.sectionControllers.lastObject;
|
|
[section.collectionContext deselectItemAtIndex:0 sectionController:section animated:NO];
|
|
XCTAssertFalse([[self.collectionView cellForItemAtIndexPath:path] isSelected]);
|
|
}
|
|
|
|
- (void)test_whenRemovingSection_withWorkingRange_thatChildSectionControllersReceiveEvents {
|
|
[self setupWithObjects:@[
|
|
[[IGTestObject alloc] initWithKey:@0 value:@[@1, @2, @3]],
|
|
[[IGTestObject alloc] initWithKey:@1 value:@[@1, @1]]
|
|
]];
|
|
|
|
IGListStackedSectionController *stack = [self.adapter sectionControllerForObject:self.dataSource.objects.firstObject];
|
|
IGListTestSection *section = stack.sectionControllers.firstObject;
|
|
|
|
id mockDelegate = [OCMockObject mockForProtocol:@protocol(IGListWorkingRangeDelegate)];
|
|
[[mockDelegate expect] listAdapter:self.adapter sectionControllerDidExitWorkingRange:section];
|
|
|
|
section.workingRangeDelegate = mockDelegate;
|
|
|
|
self.dataSource.objects = @[
|
|
[[IGTestObject alloc] initWithKey:@1 value:@[@1, @1]],
|
|
];
|
|
|
|
XCTestExpectation *expectation = [self expectationWithDescription:NSStringFromSelector(_cmd)];
|
|
|
|
[self.adapter performUpdatesAnimated:YES completion:^(BOOL finished) {
|
|
[mockDelegate verify];
|
|
[expectation fulfill];
|
|
}];
|
|
|
|
[self waitForExpectationsWithTimeout:30 handler:nil];
|
|
}
|
|
|
|
- (void)test_whenScrolling_withWorkingRange_thatChildSectionControllersReceiveEvents {
|
|
[self setupWithObjects:@[
|
|
[[IGTestObject alloc] initWithKey:@0 value:@[@1, @2, @3]],
|
|
[[IGTestObject alloc] initWithKey:@1 value:@[@1, @2, @3]],
|
|
[[IGTestObject alloc] initWithKey:@2 value:@[@1, @2, @3]],
|
|
[[IGTestObject alloc] initWithKey:@3 value:@[@1, @2, @3]],
|
|
[[IGTestObject alloc] initWithKey:@4 value:@[@1, @1]]
|
|
]];
|
|
|
|
IGListStackedSectionController *stack = [self.adapter sectionControllerForObject:self.dataSource.objects.lastObject];
|
|
IGListTestSection *section = stack.sectionControllers.firstObject;
|
|
|
|
id mockDelegate = [OCMockObject mockForProtocol:@protocol(IGListWorkingRangeDelegate)];
|
|
[[mockDelegate expect] listAdapter:self.adapter sectionControllerWillEnterWorkingRange:section];
|
|
|
|
section.workingRangeDelegate = mockDelegate;
|
|
|
|
[self.collectionView scrollToItemAtIndexPath:[NSIndexPath indexPathForItem:0 inSection:4] atScrollPosition:UICollectionViewScrollPositionTop animated:NO];
|
|
[self.collectionView layoutIfNeeded];
|
|
|
|
[mockDelegate verify];
|
|
}
|
|
|
|
- (void)test_whenRemovingCellsFromChild_thatStackSendsDisplayEventsCorrectly {
|
|
IGTestObject *object = [[IGTestObject alloc] initWithKey:@0 value:@[@1, @2]];
|
|
[self setupWithObjects:@[object]];
|
|
|
|
IGListStackedSectionController *stack = [self.adapter sectionControllerForObject:object];
|
|
IGListTestSection *section = stack.sectionControllers.lastObject;
|
|
|
|
XCTAssertEqual([self.collectionView numberOfSections], 1);
|
|
XCTAssertEqual([self.collectionView numberOfItemsInSection:0], 3);
|
|
|
|
XCTestExpectation *expectation = [self expectationWithDescription:NSStringFromSelector(_cmd)];
|
|
[section.collectionContext performBatchAnimated:YES updates:^(id<IGListBatchContext> batchContext) {
|
|
section.items = 1;
|
|
[batchContext deleteInSectionController:section atIndexes:[NSIndexSet indexSetWithIndex:1]];
|
|
} completion:^(BOOL finished) {
|
|
XCTAssertEqual([self.collectionView numberOfSections], 1);
|
|
XCTAssertEqual([self.collectionView numberOfItemsInSection:0], 2);
|
|
[expectation fulfill];
|
|
}];
|
|
|
|
[self waitForExpectationsWithTimeout:30 handler:nil];
|
|
}
|
|
|
|
- (void)test_whenMovingItemsInChild_thatCorrectCellsAreMoved {
|
|
[self setupWithObjects:@[
|
|
[[IGTestObject alloc] initWithKey:@0 value:@[@1, @2, @3]],
|
|
[[IGTestObject alloc] initWithKey:@1 value:@[@1, @2, @3]],
|
|
[[IGTestObject alloc] initWithKey:@2 value:@[@1, @2, @3]],
|
|
]];
|
|
|
|
UICollectionViewCell *cell = [self.collectionView cellForItemAtIndexPath:[NSIndexPath indexPathForItem:2 inSection:1]];
|
|
cell.tag = 42;
|
|
|
|
IGListStackedSectionController *stack = [self.adapter sectionControllerForObject:self.dataSource.objects[1]];
|
|
IGListTestSection *section = stack.sectionControllers[1];
|
|
|
|
XCTestExpectation *expectation = [self expectationWithDescription:NSStringFromSelector(_cmd)];
|
|
[section.collectionContext performBatchAnimated:YES updates:^(id<IGListBatchContext> batchContext) {
|
|
[batchContext moveInSectionController:section fromIndex:1 toIndex:0];
|
|
} completion:^(BOOL finished) {
|
|
XCTAssertEqual([self.collectionView cellForItemAtIndexPath:[NSIndexPath indexPathForItem:0 inSection:1]].tag, 0);
|
|
XCTAssertEqual([self.collectionView cellForItemAtIndexPath:[NSIndexPath indexPathForItem:1 inSection:1]].tag, 42);
|
|
XCTAssertEqual([self.collectionView cellForItemAtIndexPath:[NSIndexPath indexPathForItem:2 inSection:1]].tag, 0);
|
|
|
|
[expectation fulfill];
|
|
}];
|
|
|
|
[self waitForExpectationsWithTimeout:30 handler:nil];
|
|
}
|
|
|
|
@end
|