IGListKit/Tests/IGListCollectionViewLayoutTests.m
Tim Oliver 1c73ecb4e7 Add coverage for minium invalidated section in IGListCollectionViewLayout
Summary: Added a test to properly cover the `if (lastValidSection >= 0 && lastValidSection < sectionCount)` check in the `_calculateLayoutIfNeeded` pass inside `IGListCollectionViewLayout`.

Reviewed By: fabiomassimo

Differential Revision: D50000785

fbshipit-source-id: fe6b99f9592a1ae08299c599dadb03d7b8a958dc
2023-10-11 22:30:36 -07:00

1305 lines
72 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 <IGListKit/IGListCollectionViewLayout.h>
#import "IGLayoutTestDataSource.h"
#import "IGLayoutTestItem.h"
#import "IGLayoutTestSection.h"
#import "IGListAdapter.h"
#import "IGListAdapterProxy.h"
#import "IGListAdapterUpdater.h"
#import "IGListCollectionViewLayoutInternal.h"
#import "IGListTestHelpers.h"
@interface IGListCollectionViewLayout (Tests)
- (NSString *)_classNameForDelegate:(id<UICollectionViewDelegateFlowLayout>)delegate sectionIndex:(NSInteger)section;
@end
@interface IGListCollectionViewLayoutTests : XCTestCase
@property (nonatomic, strong) IGListCollectionViewLayout *layout;
@property (nonatomic, strong) UICollectionView *collectionView;
@property (nonatomic, strong) IGLayoutTestDataSource *dataSource;
@end
static const CGRect kTestFrame = (CGRect){{0, 0}, {100, 100}};
@implementation IGListCollectionViewLayoutTests
- (UICollectionViewCell *)cellForSection:(NSInteger)section item:(NSInteger)item {
return [self.collectionView cellForItemAtIndexPath:genIndexPath(section, item)];
}
- (UICollectionReusableView *)headerForSection:(NSInteger)section {
return [self.collectionView supplementaryViewForElementKind:UICollectionElementKindSectionHeader atIndexPath:genIndexPath(section, 0)];
}
- (UICollectionReusableView *)footerForSection:(NSInteger)section {
return [self.collectionView supplementaryViewForElementKind:UICollectionElementKindSectionFooter atIndexPath:genIndexPath(section, 0)];
}
- (void)setUpWithStickyHeaders:(BOOL)sticky showHeaderWhenEmpty:(BOOL)showHeaderWhenEmpty {
self.layout = [[IGListCollectionViewLayout alloc] initWithStickyHeaders:YES topContentInset:0 stretchToEdge:NO];
self.layout.showHeaderWhenEmpty = showHeaderWhenEmpty;
[self setUpCollectionViewAndDataSource:kTestFrame];
}
- (void)setUpWithStickyHeaders:(BOOL)sticky topInset:(CGFloat)inset {
[self setUpWithStickyHeaders:sticky topInset:inset stretchToEdge:NO];
}
- (void)setUpWithStickyHeaders:(BOOL)sticky topInset:(CGFloat)inset testFrame:(CGRect)testFrame {
[self setUpWithStickyHeaders:sticky scrollDirection:UICollectionViewScrollDirectionVertical topInset:inset stretchToEdge:NO testFrame:testFrame];
}
- (void)setUpWithStickyHeaders:(BOOL)sticky topInset:(CGFloat)inset stretchToEdge:(BOOL)stretchToEdge {
[self setUpWithStickyHeaders:sticky scrollDirection:UICollectionViewScrollDirectionVertical topInset:inset stretchToEdge:stretchToEdge testFrame:kTestFrame];
}
- (void)setUpWithStickyHeaders:(BOOL)sticky scrollDirection:(UICollectionViewScrollDirection)scrollDirection topInset:(CGFloat)inset stretchToEdge:(BOOL)stretchToEdge testFrame:(CGRect)testFrame {
self.layout = [[IGListCollectionViewLayout alloc] initWithStickyHeaders:sticky scrollDirection:scrollDirection topContentInset:inset stretchToEdge:stretchToEdge];
[self setUpCollectionViewAndDataSource:testFrame];
}
- (void)setUpCollectionViewAndDataSource:(CGRect)testFrame {
self.dataSource = [IGLayoutTestDataSource new];
self.collectionView = [[UICollectionView alloc] initWithFrame:testFrame collectionViewLayout:self.layout];
self.collectionView.dataSource = self.dataSource;
self.collectionView.delegate = self.dataSource;
[self.dataSource configCollectionView:self.collectionView];
}
- (void)tearDown {
[super tearDown];
self.collectionView = nil;
self.layout = nil;
self.dataSource = nil;
}
- (void)prepareWithData:(NSArray<IGLayoutTestSection *> *)data {
self.dataSource.sections = data;
[self.collectionView reloadData];
[self.collectionView layoutIfNeeded];
}
- (void)test_whenCreatingViaCoder_thatObjectIsValid {
XCTAssertNotNil([[IGListCollectionViewLayout alloc] initWithCoder:[NSCoder new]]);
}
- (void)test_whenApplyingSameBoundsValue_thatLayoutIsntInvalidated {
[self setUpWithStickyHeaders:YES topInset:0];
[self prepareWithData:nil];
XCTAssertFalse([self.layout shouldInvalidateLayoutForBoundsChange:self.collectionView.bounds]);
}
- (void)test_whenApplyingInvalidatedSectionLogic_thatMinimumInvalidatedSectionIsCorrect {
[self setUpWithStickyHeaders:YES topInset:0];
[self prepareWithData:nil];
[self.layout didModifySection:NSNotFound];
[self.layout didModifySection:0];
[self.layout didModifySection:NSNotFound];
}
- (void)test_whenEmptyData_thatContentSizeZero {
[self setUpWithStickyHeaders:YES topInset:0];
[self prepareWithData:nil];
// check so that nil messaging doesn't default size to 0
XCTAssertEqual(self.layout.collectionView, self.collectionView);
XCTAssertTrue(CGSizeEqualToSize(CGSizeZero, self.collectionView.contentSize));
}
- (void)test_whenSectionDataIsEmpty_thatStickyHeaderStillShow {
[self setUpWithStickyHeaders:YES showHeaderWhenEmpty:YES];
[self prepareWithData:@[[[IGLayoutTestSection alloc] initWithInsets:UIEdgeInsetsZero
lineSpacing:0
interitemSpacing:0
headerHeight:10
footerHeight:0
items:nil],
[[IGLayoutTestSection alloc] initWithInsets:UIEdgeInsetsZero
lineSpacing:0
interitemSpacing:0
headerHeight:20
footerHeight:0
items:nil],
[[IGLayoutTestSection alloc] initWithInsets:UIEdgeInsetsZero
lineSpacing:0
interitemSpacing:0
headerHeight:30
footerHeight:0
items:nil]]];
IGAssertEqualFrame([self headerForSection:0].frame, 0, 0, 100, 10);
IGAssertEqualFrame([self headerForSection:1].frame, 0, 10, 100, 20);
IGAssertEqualFrame([self headerForSection:2].frame, 0, 30, 100, 30);
}
- (void)test_whenSectionDataIsEmpty_thatStickyHeaderShouldBeHidden {
[self setUpWithStickyHeaders:YES showHeaderWhenEmpty:NO];
[self prepareWithData:@[[[IGLayoutTestSection alloc] initWithInsets:UIEdgeInsetsZero
lineSpacing:0
interitemSpacing:0
headerHeight:10
footerHeight:0
items:@[
[[IGLayoutTestItem alloc] initWithSize:(CGSize) {85, 10}]
]],
[[IGLayoutTestSection alloc] initWithInsets:UIEdgeInsetsZero
lineSpacing:0
interitemSpacing:0
headerHeight:20
footerHeight:0
items:nil],
[[IGLayoutTestSection alloc] initWithInsets:UIEdgeInsetsZero
lineSpacing:0
interitemSpacing:0
headerHeight:20
footerHeight:0
items:@[
[[IGLayoutTestItem alloc] initWithSize:(CGSize) {85, 10}],
[[IGLayoutTestItem alloc] initWithSize:(CGSize) {85, 20}],
]]
]];
IGAssertEqualFrame([self headerForSection:0].frame, 0, 0, 100, 10);
IGAssertEqualFrame([self headerForSection:1].frame, 0, 0, 0, 0);
IGAssertEqualFrame([self headerForSection:2].frame, 0, 20, 100, 20);
}
- (void)test_whenLayingOutCellsVertically_withHeaderHeight_withLineSpacing_withInsets_thatFramesCorrect {
[self setUpWithStickyHeaders:NO topInset:0];
const CGFloat headerHeight = 10;
const CGFloat lineSpacing = 10;
const UIEdgeInsets insets = UIEdgeInsetsMake(10, 10, 5, 5);
[self prepareWithData:@[
[[IGLayoutTestSection alloc] initWithInsets:insets
lineSpacing:lineSpacing
interitemSpacing:0
headerHeight:headerHeight
footerHeight:0
items:@[
[[IGLayoutTestItem alloc] initWithSize:(CGSize) {85, 10}],
[[IGLayoutTestItem alloc] initWithSize:(CGSize) {85, 20}],
]],
[[IGLayoutTestSection alloc] initWithInsets:insets
lineSpacing:lineSpacing
interitemSpacing:0
headerHeight:headerHeight
footerHeight:0
items:@[
[[IGLayoutTestItem alloc] initWithSize:(CGSize) {85, 30}],
]],
]];
XCTAssertEqual(self.collectionView.contentSize.height, 120);
IGAssertEqualFrame([self headerForSection:0].frame, 10, 10, 85, 10);
IGAssertEqualFrame([self cellForSection:0 item:0].frame, 10, 20, 85, 10);
IGAssertEqualFrame([self cellForSection:0 item:1].frame, 10, 40, 85, 20);
IGAssertEqualFrame([self headerForSection:1].frame, 10, 75, 85, 10);
IGAssertEqualFrame([self cellForSection:1 item:0].frame, 10, 85, 85, 30);
}
- (void)test_whenLayingOutCellsVertically_withFooterHeight_withLineSpacing_withInsets_thatFramesCorrect {
[self setUpWithStickyHeaders:NO topInset:0 testFrame:CGRectMake(0, 0, 100, 150)];
const CGFloat footerHeight = 10;
const CGFloat lineSpacing = 10;
const UIEdgeInsets insets = UIEdgeInsetsMake(10, 10, 5, 5);
[self prepareWithData:@[
[[IGLayoutTestSection alloc] initWithInsets:insets
lineSpacing:lineSpacing
interitemSpacing:0
headerHeight:0
footerHeight:footerHeight
items:@[
[[IGLayoutTestItem alloc] initWithSize:(CGSize) {85, 10}],
[[IGLayoutTestItem alloc] initWithSize:(CGSize) {85, 20}],
]],
[[IGLayoutTestSection alloc] initWithInsets:insets
lineSpacing:lineSpacing
interitemSpacing:0
headerHeight:0
footerHeight:footerHeight
items:@[
[[IGLayoutTestItem alloc] initWithSize:(CGSize) {85, 30}],
]],
]];
XCTAssertEqual(self.collectionView.contentSize.height, 120);
IGAssertEqualFrame([self cellForSection:0 item:0].frame, 10, 10, 85, 10);
IGAssertEqualFrame([self cellForSection:0 item:1].frame, 10, 30, 85, 20);
IGAssertEqualFrame([self footerForSection:0].frame, 10, 50, 85, 10);
IGAssertEqualFrame([self cellForSection:1 item:0].frame, 10, 75, 85, 30);
IGAssertEqualFrame([self footerForSection:1].frame, 10, 105, 85, 10);
}
- (void)test_whenLayingOutCellsVertically_withHeaderHeight_withFooterHeight_withLineSpacing_withInsets_thatFramesCorrect {
[self setUpWithStickyHeaders:NO topInset:0 testFrame:CGRectMake(0, 0, 100, 150)];
const CGFloat headerHeight = 10;
const CGFloat footerHeight = 10;
const CGFloat lineSpacing = 10;
const UIEdgeInsets insets = UIEdgeInsetsMake(10, 10, 5, 5);
[self prepareWithData:@[
[[IGLayoutTestSection alloc] initWithInsets:insets
lineSpacing:lineSpacing
interitemSpacing:0
headerHeight:headerHeight
footerHeight:footerHeight
items:@[
[[IGLayoutTestItem alloc] initWithSize:(CGSize) {85, 10}],
[[IGLayoutTestItem alloc] initWithSize:(CGSize) {85, 20}],
]],
[[IGLayoutTestSection alloc] initWithInsets:insets
lineSpacing:lineSpacing
interitemSpacing:0
headerHeight:headerHeight
footerHeight:footerHeight
items:@[
[[IGLayoutTestItem alloc] initWithSize:(CGSize) {85, 30}],
]],
]];
XCTAssertEqual(self.collectionView.contentSize.height, 140);
IGAssertEqualFrame([self headerForSection:0].frame, 10, 10, 85, 10);
IGAssertEqualFrame([self cellForSection:0 item:0].frame, 10, 20, 85, 10);
IGAssertEqualFrame([self cellForSection:0 item:1].frame, 10, 40, 85, 20);
IGAssertEqualFrame([self footerForSection:0].frame, 10, 60, 85, 10);
IGAssertEqualFrame([self headerForSection:1].frame, 10, 85, 85, 10);
IGAssertEqualFrame([self cellForSection:1 item:0].frame, 10, 95, 85, 30);
IGAssertEqualFrame([self footerForSection:1].frame, 10, 125, 85, 10);
}
- (void)test_whenLayingOutCellsHorizontally_withHeaderHeight_withLineSpacing_withInsets_thatFramesCorrect {
[self setUpWithStickyHeaders:NO scrollDirection:UICollectionViewScrollDirectionHorizontal topInset:0 stretchToEdge:NO testFrame:kTestFrame];
const CGFloat headerHeight = 10;
const CGFloat lineSpacing = 10;
const UIEdgeInsets insets = UIEdgeInsetsMake(10, 10, 5, 5);
[self prepareWithData:@[
[[IGLayoutTestSection alloc] initWithInsets:insets
lineSpacing:lineSpacing
interitemSpacing:0
headerHeight:headerHeight
footerHeight:0
items:@[
[[IGLayoutTestItem alloc] initWithSize:(CGSize) {45, 10}],
[[IGLayoutTestItem alloc] initWithSize:(CGSize) {45, 20}],
]],
[[IGLayoutTestSection alloc] initWithInsets:insets
lineSpacing:lineSpacing
interitemSpacing:0
headerHeight:headerHeight
footerHeight:0
items:@[
[[IGLayoutTestItem alloc] initWithSize:(CGSize) {45, 30}],
]],
]];
XCTAssertEqual(self.collectionView.contentSize.width, 140);
IGAssertEqualFrame([self headerForSection:0].frame, 10, 10, 10, 85);
IGAssertEqualFrame([self cellForSection:0 item:0].frame, 20, 10, 45, 10);
IGAssertEqualFrame([self cellForSection:0 item:1].frame, 20, 20, 45, 20);
IGAssertEqualFrame([self headerForSection:1].frame, 80, 10, 10, 85);
IGAssertEqualFrame([self cellForSection:1 item:0].frame, 90, 10, 45, 30);
}
- (void)test_whenLayingOutCellsHorizontally_withFooterHeight_withLineSpacing_withInsets_thatFramesCorrect {
[self setUpWithStickyHeaders:NO scrollDirection:UICollectionViewScrollDirectionHorizontal topInset:0 stretchToEdge:NO testFrame:kTestFrame];
const CGFloat footerHeight = 10;
const CGFloat lineSpacing = 10;
const UIEdgeInsets insets = UIEdgeInsetsMake(10, 10, 5, 5);
[self prepareWithData:@[
[[IGLayoutTestSection alloc] initWithInsets:insets
lineSpacing:lineSpacing
interitemSpacing:0
headerHeight:0
footerHeight:footerHeight
items:@[
[[IGLayoutTestItem alloc] initWithSize:(CGSize) {45, 10}],
[[IGLayoutTestItem alloc] initWithSize:(CGSize) {45, 20}],
]],
[[IGLayoutTestSection alloc] initWithInsets:insets
lineSpacing:lineSpacing
interitemSpacing:0
headerHeight:0
footerHeight:footerHeight
items:@[
[[IGLayoutTestItem alloc] initWithSize:(CGSize) {45, 30}],
]],
]];
XCTAssertEqual(self.collectionView.contentSize.width, 75);
IGAssertEqualFrame([self footerForSection:0].frame, 60, 10, 10, 85);
IGAssertEqualFrame([self cellForSection:0 item:0].frame, 10, 10, 45, 10);
IGAssertEqualFrame([self cellForSection:0 item:1].frame, 10, 20, 45, 20);
IGAssertEqualFrame([self footerForSection:1].frame, 60, 10, 10, 85);
IGAssertEqualFrame([self cellForSection:1 item:0].frame, 10, 55, 45, 30);
}
- (void)test_whenUsingStickyHeaders_withSimulatedScrolling_thatYPositionsAdjusted {
[self setUpWithStickyHeaders:YES topInset:10];
[self prepareWithData:@[
[[IGLayoutTestSection alloc] initWithInsets:UIEdgeInsetsZero
lineSpacing:0
interitemSpacing:0
headerHeight:10
footerHeight:0
items:@[
[[IGLayoutTestItem alloc] initWithSize:(CGSize) {100, 20}],
[[IGLayoutTestItem alloc] initWithSize:(CGSize) {100, 20}],
]],
[[IGLayoutTestSection alloc] initWithInsets:UIEdgeInsetsZero
lineSpacing:0
interitemSpacing:0
headerHeight:10
footerHeight:0
items:@[
[[IGLayoutTestItem alloc] initWithSize:(CGSize) {100, 30}],
[[IGLayoutTestItem alloc] initWithSize:(CGSize) {100, 30}],
[[IGLayoutTestItem alloc] initWithSize:(CGSize) {100, 30}],
]],
]];
// scroll header 0 halfway
self.collectionView.contentOffset = CGPointMake(0, 5);
[self.collectionView layoutIfNeeded];
IGAssertEqualFrame([self headerForSection:0].frame, 0, 15, 100, 10);
IGAssertEqualFrame([self headerForSection:1].frame, 0, 50, 100, 10);
// scroll header 0 off and 1 up
self.collectionView.contentOffset = CGPointMake(0, 45);
[self.collectionView layoutIfNeeded];
IGAssertEqualFrame([self headerForSection:0].frame, 0, 40, 100, 10);
IGAssertEqualFrame([self headerForSection:1].frame, 0, 55, 100, 10);
}
- (void)test_whenUsingStickyHeaders_withSimulatedHorizontalScrolling_thatXPositionsAdjusted {
[self setUpWithStickyHeaders:YES scrollDirection:UICollectionViewScrollDirectionHorizontal topInset:10 stretchToEdge:NO testFrame:kTestFrame];
[self prepareWithData:@[
[[IGLayoutTestSection alloc] initWithInsets:UIEdgeInsetsZero
lineSpacing:0
interitemSpacing:0
headerHeight:10
footerHeight:0
items:@[
[[IGLayoutTestItem alloc] initWithSize:(CGSize) {20, 100}],
[[IGLayoutTestItem alloc] initWithSize:(CGSize) {20, 100}],
]],
[[IGLayoutTestSection alloc] initWithInsets:UIEdgeInsetsZero
lineSpacing:0
interitemSpacing:0
headerHeight:10
footerHeight:0
items:@[
[[IGLayoutTestItem alloc] initWithSize:(CGSize) {30, 100}],
[[IGLayoutTestItem alloc] initWithSize:(CGSize) {30, 100}],
[[IGLayoutTestItem alloc] initWithSize:(CGSize) {30, 100}],
]],
]];
// scroll header 0 halfway
self.collectionView.contentOffset = CGPointMake(5, 0);
[self.collectionView layoutIfNeeded];
IGAssertEqualFrame([self headerForSection:0].frame, 15, 0, 10, 100);
IGAssertEqualFrame([self headerForSection:1].frame, 50, 0, 10, 100);
// scroll header 0 off and 1 left
self.collectionView.contentOffset = CGPointMake(45, 0);
[self.collectionView layoutIfNeeded];
IGAssertEqualFrame([self headerForSection:0].frame, 40, 0, 10, 100);
IGAssertEqualFrame([self headerForSection:1].frame, 55, 0, 10, 100);
}
- (void)test_whenAdjustingTopYInset_withVaryingHeaderHeights_thatYPositionsUpdated {
[self setUpWithStickyHeaders:YES topInset:10];
[self prepareWithData:@[
[[IGLayoutTestSection alloc] initWithInsets:UIEdgeInsetsZero
lineSpacing:0
interitemSpacing:0
headerHeight:10
footerHeight:0
items:@[
[[IGLayoutTestItem alloc] initWithSize:(CGSize) {100, 10}],
[[IGLayoutTestItem alloc] initWithSize:(CGSize) {100, 20}],
]],
[[IGLayoutTestSection alloc] initWithInsets:UIEdgeInsetsZero
lineSpacing:0
interitemSpacing:0
headerHeight:10
footerHeight:0
items:@[
[[IGLayoutTestItem alloc] initWithSize:(CGSize) {100, 30}],
[[IGLayoutTestItem alloc] initWithSize:(CGSize) {100, 40}],
[[IGLayoutTestItem alloc] initWithSize:(CGSize) {100, 50}],
]],
]];
// scroll header 0 off and 1 up
self.collectionView.contentOffset = CGPointMake(0, 35);
[self.collectionView layoutIfNeeded];
IGAssertEqualFrame([self headerForSection:0].frame, 0, 30, 100, 10);
IGAssertEqualFrame([self headerForSection:1].frame, 0, 45, 100, 10);
self.layout.stickyHeaderYOffset = -10;
[self.collectionView layoutIfNeeded];
IGAssertEqualFrame([self headerForSection:0].frame, 0, 30, 100, 10);
IGAssertEqualFrame([self headerForSection:1].frame, 0, 40, 100, 10);
self.layout.stickyHeaderYOffset = 10;
[self.collectionView layoutIfNeeded];
IGAssertEqualFrame([self headerForSection:0].frame, 0, 30, 100, 10);
IGAssertEqualFrame([self headerForSection:1].frame, 0, 55, 100, 10);
}
- (void)test_whenItemsSmallerThanContainerWidth_with0Insets_with0LineSpacing_with0Interitem_thatItemsFitSameRow {
[self setUpWithStickyHeaders:NO topInset:0];
[self prepareWithData:@[
[[IGLayoutTestSection alloc] initWithInsets:UIEdgeInsetsZero
lineSpacing:0
interitemSpacing:0
headerHeight:0
footerHeight:0
items:@[
[[IGLayoutTestItem alloc] initWithSize:(CGSize) {33, 33}],
[[IGLayoutTestItem alloc] initWithSize:(CGSize) {33, 33}],
[[IGLayoutTestItem alloc] initWithSize:(CGSize) {33, 33}],
]],
[[IGLayoutTestSection alloc] initWithInsets:UIEdgeInsetsZero
lineSpacing:0
interitemSpacing:0
headerHeight:0
footerHeight:0
items:@[
[[IGLayoutTestItem alloc] initWithSize:(CGSize) {33, 33}],
]],
]];
XCTAssertEqual(self.collectionView.contentSize.height, 66);
IGAssertEqualFrame([self cellForSection:0 item:0].frame, 0, 0, 33, 33);
IGAssertEqualFrame([self cellForSection:0 item:1].frame, 33, 0, 33, 33);
IGAssertEqualFrame([self cellForSection:0 item:2].frame, 66, 0, 33, 33);
IGAssertEqualFrame([self cellForSection:1 item:0].frame, 0, 33, 33, 33);
}
- (void)test_whenItemsSmallerThanContainerWidth_withHalfPointItemSpacing_with0Insets_with0LineSpacing_thatItemsFitSameRow {
[self setUpWithStickyHeaders:NO topInset:0];
[self prepareWithData:@[
[[IGLayoutTestSection alloc] initWithInsets:UIEdgeInsetsZero
lineSpacing:0
interitemSpacing:0.5
headerHeight:0
footerHeight:0
items:@[
[[IGLayoutTestItem alloc] initWithSize:(CGSize) {33, 33}],
[[IGLayoutTestItem alloc] initWithSize:(CGSize) {33, 33}],
[[IGLayoutTestItem alloc] initWithSize:(CGSize) {33, 33}],
]],
]];
XCTAssertEqual(self.collectionView.contentSize.height, 33);
IGAssertEqualFrame([self cellForSection:0 item:0].frame, 0, 0, 33, 33);
const CGRect rect = IGListRectIntegralScaled(CGRectMake(33.5, 0, 33, 33));
IGAssertEqualFrame([self cellForSection:0 item:1].frame, rect.origin.x, rect.origin.y, rect.size.width, rect.size.height);
IGAssertEqualFrame([self cellForSection:0 item:2].frame, 67, 0, 33, 33);
}
- (void)test_whenItemsLargerThanContainerHeight_withHorizontalScrolling_with5PointItemSpacing_with0Insets_with10PointLineSpacing_thatItemsBumpToNewColumn {
[self setUpWithStickyHeaders:NO scrollDirection:UICollectionViewScrollDirectionHorizontal topInset:0 stretchToEdge:NO testFrame:kTestFrame];
[self prepareWithData:@[
[[IGLayoutTestSection alloc] initWithInsets:UIEdgeInsetsZero
lineSpacing:10
interitemSpacing:5
headerHeight:0
footerHeight:0
items:@[
[[IGLayoutTestItem alloc] initWithSize:(CGSize) {33, 33}],
[[IGLayoutTestItem alloc] initWithSize:(CGSize) {33, 33}],
[[IGLayoutTestItem alloc] initWithSize:(CGSize) {33, 33}],
]],
]];
XCTAssertEqual(self.collectionView.contentSize.width, 76);
IGAssertEqualFrame([self cellForSection:0 item:0].frame, 0, 0, 33, 33);
IGAssertEqualFrame([self cellForSection:0 item:1].frame, 0, 38, 33, 33);
IGAssertEqualFrame([self cellForSection:0 item:2].frame, 43, 0, 33, 33);
}
- (void)test_whenSectionsSmallerThanContainerWidth_withVerticalScrolling_with0ItemSpacing_with0Insets_with0LineSpacing_thatSectionsFitSameRow {
[self setUpWithStickyHeaders:NO topInset:0];
[self prepareWithData:@[
[[IGLayoutTestSection alloc] initWithInsets:UIEdgeInsetsZero
lineSpacing:0
interitemSpacing:0
headerHeight:0
footerHeight:0
items:@[
[[IGLayoutTestItem alloc] initWithSize:(CGSize) {33, 33}],
]],
[[IGLayoutTestSection alloc] initWithInsets:UIEdgeInsetsZero
lineSpacing:0
interitemSpacing:0
headerHeight:0
footerHeight:0
items:@[
[[IGLayoutTestItem alloc] initWithSize:(CGSize) {33, 33}],
]],
[[IGLayoutTestSection alloc] initWithInsets:UIEdgeInsetsZero
lineSpacing:0
interitemSpacing:0
headerHeight:0
footerHeight:0
items:@[
[[IGLayoutTestItem alloc] initWithSize:(CGSize) {33, 33}],
]],
]];
XCTAssertEqual(self.collectionView.contentSize.height, 33);
IGAssertEqualFrame([self cellForSection:0 item:0].frame, 0, 0, 33, 33);
IGAssertEqualFrame([self cellForSection:1 item:0].frame, 33, 0, 33, 33);
IGAssertEqualFrame([self cellForSection:2 item:0].frame, 66, 0, 33, 33);
}
- (void)test_whenSectionsSmallerThanContainerHeight_withHorizontalScrolling_with0ItemSpacing_with0Insets_with0LineSpacing_thatSectionsFitSameColumn {
[self setUpWithStickyHeaders:NO scrollDirection:UICollectionViewScrollDirectionHorizontal topInset:0 stretchToEdge:NO testFrame:kTestFrame];
[self prepareWithData:@[
[[IGLayoutTestSection alloc] initWithInsets:UIEdgeInsetsZero lineSpacing:0
interitemSpacing:0
headerHeight:0
footerHeight:0
items:@[
[[IGLayoutTestItem alloc] initWithSize:(CGSize) {33, 33}],
]],
[[IGLayoutTestSection alloc] initWithInsets:UIEdgeInsetsZero lineSpacing:0
interitemSpacing:0
headerHeight:0
footerHeight:0
items:@[
[[IGLayoutTestItem alloc] initWithSize:(CGSize) {33, 33}],
]],
[[IGLayoutTestSection alloc] initWithInsets:UIEdgeInsetsZero lineSpacing:0
interitemSpacing:0
headerHeight:0
footerHeight:0
items:@[
[[IGLayoutTestItem alloc] initWithSize:(CGSize) {33, 33}],
]],
]];
XCTAssertEqual(self.collectionView.contentSize.width, 33);
IGAssertEqualFrame([self cellForSection:0 item:0].frame, 0, 0, 33, 33);
IGAssertEqualFrame([self cellForSection:1 item:0].frame, 0, 33, 33, 33);
IGAssertEqualFrame([self cellForSection:2 item:0].frame, 0, 66, 33, 33);
}
- (void)test_whenSectionsSmallerThanContainerWidth_withHalfPointSpacing_with0Insets_with0LineSpacing_thatSectionsFitSameRow {
[self setUpWithStickyHeaders:NO topInset:0];
[self prepareWithData:@[
[[IGLayoutTestSection alloc] initWithInsets:UIEdgeInsetsZero
lineSpacing:0
interitemSpacing:0.5
headerHeight:0
footerHeight:0
items:@[
[[IGLayoutTestItem alloc] initWithSize:(CGSize) {33, 33}],
]],
[[IGLayoutTestSection alloc] initWithInsets:UIEdgeInsetsZero
lineSpacing:0
interitemSpacing:0.5
headerHeight:0
footerHeight:0
items:@[
[[IGLayoutTestItem alloc] initWithSize:(CGSize) {33, 33}],
]],
[[IGLayoutTestSection alloc] initWithInsets:UIEdgeInsetsZero
lineSpacing:0
interitemSpacing:0.5
headerHeight:0
footerHeight:0
items:@[
[[IGLayoutTestItem alloc] initWithSize:(CGSize) {33, 33}],
]],
]];
XCTAssertEqual(self.collectionView.contentSize.height, 33);
IGAssertEqualFrame([self cellForSection:0 item:0].frame, 0, 0, 33, 33);
const CGRect rect = IGListRectIntegralScaled(CGRectMake(33.5, 0, 33, 33));
IGAssertEqualFrame([self cellForSection:1 item:0].frame, rect.origin.x, rect.origin.y, rect.size.width, rect.size.height);
IGAssertEqualFrame([self cellForSection:2 item:0].frame, 67, 0, 33, 33);
}
- (void)test_whenSectionsSmallerThanContainerWidth_with0ItemSpacing_withMiddleItemHasInsets_with0LineSpacing_thatNextSectionSnapsBelow {
[self setUpWithStickyHeaders:NO topInset:0];
[self prepareWithData:@[
[[IGLayoutTestSection alloc] initWithInsets:UIEdgeInsetsZero
lineSpacing:0
interitemSpacing:0
headerHeight:0
footerHeight:0
items:@[
[[IGLayoutTestItem alloc] initWithSize:(CGSize) {33, 33}],
]],
[[IGLayoutTestSection alloc] initWithInsets:UIEdgeInsetsMake(10, 10, 10, 10)
lineSpacing:0
interitemSpacing:0
headerHeight:0
footerHeight:0
items:@[
[[IGLayoutTestItem alloc] initWithSize:(CGSize) {13, 50}],
]],
[[IGLayoutTestSection alloc] initWithInsets:UIEdgeInsetsZero
lineSpacing:0
interitemSpacing:0
headerHeight:0
footerHeight:0
items:@[
[[IGLayoutTestItem alloc] initWithSize:(CGSize) {33, 33}],
]],
[[IGLayoutTestSection alloc] initWithInsets:UIEdgeInsetsZero
lineSpacing:0
interitemSpacing:0
headerHeight:0
footerHeight:0
items:@[
[[IGLayoutTestItem alloc] initWithSize:(CGSize) {33, 33}],
]],
]];
XCTAssertEqual(self.collectionView.contentSize.height, 103);
IGAssertEqualFrame([self cellForSection:0 item:0].frame, 0, 0, 33, 33);
IGAssertEqualFrame([self cellForSection:1 item:0].frame, 43, 10, 13, 50);
IGAssertEqualFrame([self cellForSection:2 item:0].frame, 66, 0, 33, 33);
IGAssertEqualFrame([self cellForSection:3 item:0].frame, 0, 70, 33, 33);
}
- (void)test_whenSectionBustingRow_thatNewlineAppliesSectionInset {
[self setUpWithStickyHeaders:NO topInset:0];
[self prepareWithData:@[
[[IGLayoutTestSection alloc] initWithInsets:UIEdgeInsetsZero
lineSpacing:0
interitemSpacing:0
headerHeight:0
footerHeight:0
items:@[
[[IGLayoutTestItem alloc] initWithSize:(CGSize) {33, 33}],
]],
[[IGLayoutTestSection alloc] initWithInsets:UIEdgeInsetsMake(10, 10, 5, 5)
lineSpacing:0
interitemSpacing:0
headerHeight:0
footerHeight:0
items:@[
[[IGLayoutTestItem alloc] initWithSize:(CGSize) {85, 50}],
]],
]];
XCTAssertEqual(self.collectionView.contentSize.height, 98);
IGAssertEqualFrame([self cellForSection:0 item:0].frame, 0, 0, 33, 33);
IGAssertEqualFrame([self cellForSection:1 item:0].frame, 10, 43, 85, 50);
}
- (void)test_whenSectionsSmallerThanWidth_withSectionHeader_thatHeaderCausesNewline {
[self setUpWithStickyHeaders:NO topInset:0];
[self prepareWithData:@[
[[IGLayoutTestSection alloc] initWithInsets:UIEdgeInsetsZero
lineSpacing:0
interitemSpacing:0
headerHeight:0
footerHeight:0
items:@[
[[IGLayoutTestItem alloc] initWithSize:(CGSize) {33, 33}],
]],
[[IGLayoutTestSection alloc] initWithInsets:UIEdgeInsetsZero
lineSpacing:0
interitemSpacing:0
headerHeight:10
footerHeight:0
items:@[
[[IGLayoutTestItem alloc] initWithSize:(CGSize) {33, 33}],
]],
]];
XCTAssertEqual(self.collectionView.contentSize.height, 76);
IGAssertEqualFrame([self cellForSection:0 item:0].frame, 0, 0, 33, 33);
IGAssertEqualFrame([self cellForSection:1 item:0].frame, 0, 43, 33, 33);
}
- (void)test_whenSectionsSmallerThanHeight_withHorizontalScrolling_withSectionHeader_thatHeaderCausesNewline {
[self setUpWithStickyHeaders:NO scrollDirection:UICollectionViewScrollDirectionHorizontal topInset:0 stretchToEdge:NO testFrame:kTestFrame];
[self prepareWithData:@[
[[IGLayoutTestSection alloc] initWithInsets:UIEdgeInsetsZero
lineSpacing:0
interitemSpacing:0
headerHeight:0
footerHeight:0
items:@[
[[IGLayoutTestItem alloc] initWithSize:(CGSize) {33, 33}],
]],
[[IGLayoutTestSection alloc] initWithInsets:UIEdgeInsetsZero
lineSpacing:0
interitemSpacing:0
headerHeight:10
footerHeight:0
items:@[
[[IGLayoutTestItem alloc] initWithSize:(CGSize) {33, 33}],
]],
]];
XCTAssertEqual(self.collectionView.contentSize.width, 76);
IGAssertEqualFrame([self cellForSection:0 item:0].frame, 0, 0, 33, 33);
IGAssertEqualFrame([self cellForSection:1 item:0].frame, 43, 0, 33, 33);
}
- (void)test_whenBatchItemUpdates_withHeaderHeight_withLineSpacing_withInsets_thatLayoutCorrectAfterUpdates {
[self setUpWithStickyHeaders:NO topInset:0];
const CGFloat headerHeight = 10;
const CGFloat lineSpacing = 10;
const UIEdgeInsets insets = UIEdgeInsetsMake(10, 10, 5, 5);
// making the view bigger so that we can check all cell frames
self.collectionView.frame = CGRectMake(0, 0, 100, 400);
[self prepareWithData:@[
[[IGLayoutTestSection alloc] initWithInsets:insets lineSpacing:lineSpacing
interitemSpacing:0
headerHeight:headerHeight
footerHeight:0
items:@[
[[IGLayoutTestItem alloc] initWithSize:(CGSize) {85, 10}],
[[IGLayoutTestItem alloc] initWithSize:(CGSize) {85, 20}],
]],
[[IGLayoutTestSection alloc] initWithInsets:insets lineSpacing:lineSpacing
interitemSpacing:0
headerHeight:headerHeight
footerHeight:0
items:@[
[[IGLayoutTestItem alloc] initWithSize:(CGSize) {85, 30}],
]],
[[IGLayoutTestSection alloc] initWithInsets:insets lineSpacing:lineSpacing
interitemSpacing:0
headerHeight:headerHeight
footerHeight:0
items:@[
[[IGLayoutTestItem alloc] initWithSize:(CGSize) {85, 60}],
]],
[[IGLayoutTestSection alloc] initWithInsets:insets lineSpacing:lineSpacing
interitemSpacing:0
headerHeight:headerHeight
footerHeight:0
items:@[
[[IGLayoutTestItem alloc] initWithSize:(CGSize) {85, 40}],
]],
]];
XCTestExpectation *expectation = [self expectationWithDescription:NSStringFromSelector(_cmd)];
[self.collectionView performBatchUpdates:^{
self.dataSource.sections = @[
[[IGLayoutTestSection alloc] initWithInsets:insets
lineSpacing:lineSpacing
interitemSpacing:0
headerHeight:headerHeight
footerHeight:0
items:@[
[[IGLayoutTestItem alloc] initWithSize:(CGSize) {85, 30}], // reloaded
// deleted
]],
// moved from section 3 to 1
[[IGLayoutTestSection alloc] initWithInsets:insets
lineSpacing:lineSpacing
interitemSpacing:0
headerHeight:headerHeight
footerHeight:0
items:@[
[[IGLayoutTestItem alloc] initWithSize:(CGSize) {85, 40}],
]],
// deleted section 2
[[IGLayoutTestSection alloc] initWithInsets:insets
lineSpacing:lineSpacing
interitemSpacing:0
headerHeight:headerHeight
footerHeight:0
items:@[
[[IGLayoutTestItem alloc] initWithSize:(CGSize) {85, 30}],
[[IGLayoutTestItem alloc] initWithSize:(CGSize) {85, 10}], // inserted
]],
// inserted
[[IGLayoutTestSection alloc] initWithInsets:insets
lineSpacing:lineSpacing
interitemSpacing:0
headerHeight:headerHeight
footerHeight:0
items:@[
[[IGLayoutTestItem alloc] initWithSize:(CGSize) {85, 10}],
[[IGLayoutTestItem alloc] initWithSize:(CGSize) {85, 20}],
]],
];
[self.collectionView deleteSections:[NSIndexSet indexSetWithIndex:2]];
[self.collectionView insertSections:[NSIndexSet indexSetWithIndex:3]];
[self.collectionView moveSection:3 toSection:1];
[self.collectionView reloadItemsAtIndexPaths:@[genIndexPath(0, 0)]];
[self.collectionView deleteItemsAtIndexPaths:@[genIndexPath(0, 1)]];
[self.collectionView insertItemsAtIndexPaths:@[genIndexPath(2, 1)]];
} completion:^(BOOL finished) {
[self.collectionView layoutIfNeeded];
[expectation fulfill];
XCTAssertEqual(self.collectionView.contentSize.height, 260);
IGAssertEqualFrame([self headerForSection:0].frame, 10, 10, 85, 10);
IGAssertEqualFrame([self cellForSection:0 item:0].frame, 10, 20, 85, 30);
IGAssertEqualFrame([self headerForSection:1].frame, 10, 65, 85, 10);
IGAssertEqualFrame([self cellForSection:1 item:0].frame, 10, 75, 85, 40);
IGAssertEqualFrame([self headerForSection:2].frame, 10, 130, 85, 10);
IGAssertEqualFrame([self cellForSection:2 item:0].frame, 10, 140, 85, 30);
IGAssertEqualFrame([self cellForSection:2 item:1].frame, 10, 180, 85, 10);
IGAssertEqualFrame([self headerForSection:3].frame, 10, 205, 85, 10);
IGAssertEqualFrame([self cellForSection:3 item:0].frame, 10, 215, 85, 10);
IGAssertEqualFrame([self cellForSection:3 item:1].frame, 10, 235, 85, 20);
}];
[self waitForExpectationsWithTimeout:30 handler:^(NSError * _Nullable error) {
XCTAssertNil(error);
}];
}
- (void)test_whenQueryingLayoutAttributes_withLotsOfCells_thatExactFramesFetched {
[self setUpWithStickyHeaders:NO topInset:0];
NSMutableArray *items = [NSMutableArray new];
for (NSInteger i = 0; i < 1000; i++) {
[items addObject:[[IGLayoutTestItem alloc] initWithSize:(CGSize) {100, 20}]];
}
[self prepareWithData:@[
[[IGLayoutTestSection alloc] initWithInsets:UIEdgeInsetsZero
lineSpacing:0
interitemSpacing:0
headerHeight:0
footerHeight:0
items:items]
]];
XCTAssertEqual([self.layout layoutAttributesForElementsInRect:CGRectMake(0, 500, 100, 100)].count, 5);
XCTAssertEqual([self.layout layoutAttributesForElementsInRect:CGRectMake(0, 0, 100, 1000)].count, 50);
XCTAssertEqual([self.layout layoutAttributesForElementsInRect:CGRectMake(0, 250, 100, 100)].count, 6);
XCTAssertEqual([self.layout layoutAttributesForElementsInRect:CGRectMake(0, 250, 100, 1)].count, 1);
}
- (void)test_whenSecondItemDoesntIntersectRect_thatOtherAttributesExist {
[self setUpWithStickyHeaders:NO topInset:0];
NSMutableArray *data = [NSMutableArray new];
for (NSInteger i = 0; i < 6; i++) {
[data addObject:[[IGLayoutTestSection alloc] initWithInsets:UIEdgeInsetsZero
lineSpacing:0
interitemSpacing:0
headerHeight:0
footerHeight:0
items:@[
[[IGLayoutTestItem alloc] initWithSize:(CGSize) {50, 100}],
[[IGLayoutTestItem alloc] initWithSize:(CGSize) {50, 10}],
]]];
}
[self prepareWithData:data];
NSArray *attributes = [self.layout layoutAttributesForElementsInRect:CGRectMake(0, 50, 100, 100)];
NSArray *paths = [[attributes valueForKeyPath:@"indexPath"] sortedArrayUsingSelector:@selector(compare:)];
NSArray *expectation = @[
genIndexPath(0, 0),
genIndexPath(1, 0),
genIndexPath(1, 1),
];
// should include 2 of the 100-height items and one of the 10-height
XCTAssertEqualObjects(paths, expectation);
}
- (void)test_whenTwoConsecutiveItemsDontIntersectRect_thatOtherAttributesExist {
[self setUpWithStickyHeaders:NO topInset:0];
NSMutableArray *data = [NSMutableArray new];
for (NSInteger i = 0; i < 6; i++) {
[data addObject:[[IGLayoutTestSection alloc] initWithInsets:UIEdgeInsetsZero
lineSpacing:0
interitemSpacing:0
headerHeight:0
footerHeight:0
items:@[
[[IGLayoutTestItem alloc] initWithSize:(CGSize) {30, 100}],
[[IGLayoutTestItem alloc] initWithSize:(CGSize) {30, 10}],
[[IGLayoutTestItem alloc] initWithSize:(CGSize) {30, 10}],
]]];
}
[self prepareWithData:data];
NSArray *attributes = [self.layout layoutAttributesForElementsInRect:CGRectMake(0, 50, 100, 100)];
NSArray *paths = [[attributes valueForKeyPath:@"indexPath"] sortedArrayUsingSelector:@selector(compare:)];
NSArray *expectation = @[
genIndexPath(0, 0),
genIndexPath(1, 0),
genIndexPath(1, 1),
genIndexPath(1, 2),
];
// should include 2 of the 100-height items and two of the 10-height
XCTAssertEqualObjects(paths, expectation);
}
- (void)test_whenChangingBoundsSize_withItemsThatNewlineAfterChange_thatLayoutShiftsItems {
[self setUpWithStickyHeaders:NO topInset:0];
[self prepareWithData:@[
[[IGLayoutTestSection alloc] initWithInsets:UIEdgeInsetsZero
lineSpacing:0
interitemSpacing:0
headerHeight:0
footerHeight:0
items:@[
[[IGLayoutTestItem alloc] initWithSize:(CGSize) {33, 33}],
]],
[[IGLayoutTestSection alloc] initWithInsets:UIEdgeInsetsZero
lineSpacing:0
interitemSpacing:0
headerHeight:0
footerHeight:0
items:@[
[[IGLayoutTestItem alloc] initWithSize:(CGSize) {33, 33}],
]],
[[IGLayoutTestSection alloc] initWithInsets:UIEdgeInsetsZero
lineSpacing:0
interitemSpacing:0
headerHeight:0
footerHeight:0
items:@[
[[IGLayoutTestItem alloc] initWithSize:(CGSize) {33, 33}],
]],
]];
XCTAssertEqual(self.collectionView.contentSize.height, 33);
IGAssertEqualFrame([self cellForSection:0 item:0].frame, 0, 0, 33, 33);
IGAssertEqualFrame([self cellForSection:1 item:0].frame, 33, 0, 33, 33);
IGAssertEqualFrame([self cellForSection:2 item:0].frame, 66, 0, 33, 33);
// can no longer fit 3 items in one section
self.collectionView.frame = CGRectMake(0, 0, 70, 100);
[self.collectionView layoutIfNeeded];
XCTAssertEqual(self.collectionView.contentSize.height, 66);
IGAssertEqualFrame([self cellForSection:0 item:0].frame, 0, 0, 33, 33);
IGAssertEqualFrame([self cellForSection:1 item:0].frame, 33, 0, 33, 33);
IGAssertEqualFrame([self cellForSection:2 item:0].frame, 0, 33, 33, 33);
}
- (void)test_whenCollectionViewContentInset_withFullWidthItems_thatItemsPinchedIn {
[self setUpWithStickyHeaders:NO topInset:0];
self.collectionView.contentInset = UIEdgeInsetsMake(0, 30, 0, 30);
[self prepareWithData:@[
[[IGLayoutTestSection alloc] initWithInsets:UIEdgeInsetsZero
lineSpacing:0
interitemSpacing:0
headerHeight:10
footerHeight:0
items:@[
[[IGLayoutTestItem alloc] initWithSize:(CGSize) {40, 10}],
[[IGLayoutTestItem alloc] initWithSize:(CGSize) {40, 20}],
]],
]];
XCTAssertEqual(self.collectionView.contentSize.height, 40);
IGAssertEqualFrame([self headerForSection:0].frame, 0, 0, 40, 10);
IGAssertEqualFrame([self cellForSection:0 item:0].frame, 0, 10, 40, 10);
IGAssertEqualFrame([self cellForSection:0 item:1].frame, 0, 20, 40, 20);
}
- (void)test_whenItemsAddedWidthSmallerThanWidth_DifferenceSmallerThanEpsilon {
[self setUpWithStickyHeaders:NO topInset:0 stretchToEdge:YES];
const CGSize size = CGSizeMake(33, 33);
[self prepareWithData:@[
[[IGLayoutTestSection alloc] initWithInsets:UIEdgeInsetsZero
lineSpacing:0
interitemSpacing:0
headerHeight:0
footerHeight:0
items:@[
[[IGLayoutTestItem alloc] initWithSize:size],
[[IGLayoutTestItem alloc] initWithSize:size],
[[IGLayoutTestItem alloc] initWithSize:size],
]],
]];
IGAssertEqualFrame([self cellForSection:0 item:0].frame, 0, 0, 33, 33);
IGAssertEqualFrame([self cellForSection:0 item:1].frame, 33, 0, 33, 33);
IGAssertEqualFrame([self cellForSection:0 item:2].frame, 66, 0, 34, 33);
}
- (void)test_whenItemsAddedWidthSmallerThanWidth_DifferenceBiggerThanEpsilon {
[self setUpWithStickyHeaders:NO topInset:0 stretchToEdge:YES];
[self prepareWithData:@[
[[IGLayoutTestSection alloc] initWithInsets:UIEdgeInsetsZero
lineSpacing:0
interitemSpacing:0
headerHeight:0
footerHeight:0
items:@[
[[IGLayoutTestItem alloc] initWithSize:CGSizeMake(33, 33)],
[[IGLayoutTestItem alloc] initWithSize:CGSizeMake(65, 33)],
]],
]];
IGAssertEqualFrame([self cellForSection:0 item:0].frame, 0, 0, 33, 33);
IGAssertEqualFrame([self cellForSection:0 item:1].frame, 33, 0, 65, 33);
}
- (void)test_whenItemsAddedWithBiggerThanWidth_DifferenceSmallerThanEpsilon {
[self setUpWithStickyHeaders:NO topInset:0];
[self prepareWithData:@[
[[IGLayoutTestSection alloc] initWithInsets:UIEdgeInsetsZero
lineSpacing:0
interitemSpacing:0
headerHeight:0
footerHeight:0
items:@[
[[IGLayoutTestItem alloc] initWithSize:CGSizeMake(50, 50)],
[[IGLayoutTestItem alloc] initWithSize:CGSizeMake(51, 50)],
]],
]];
IGAssertEqualFrame([self cellForSection:0 item:0].frame, 0, 0, 50, 50);
IGAssertEqualFrame([self cellForSection:0 item:1].frame, 50, 0, 51, 50);
}
- (void)test_whenItemsAddedWithBiggerThanWidth_DifferenceBiggerThanEpsilon {
[self setUpWithStickyHeaders:NO topInset:0];
[self prepareWithData:@[
[[IGLayoutTestSection alloc] initWithInsets:UIEdgeInsetsZero
lineSpacing:0
interitemSpacing:0
headerHeight:0
footerHeight:0
items:@[
[[IGLayoutTestItem alloc] initWithSize:CGSizeMake(50, 50)],
[[IGLayoutTestItem alloc] initWithSize:CGSizeMake(52, 50)],
]],
]];
IGAssertEqualFrame([self cellForSection:0 item:0].frame, 0, 0, 50, 50);
IGAssertEqualFrame([self cellForSection:0 item:1].frame, 0, 50, 52, 50);
}
- (void)test_ {
[self setUpWithStickyHeaders:NO topInset:0];
self.collectionView.frame = CGRectMake(0, 0, 414, 736);
NSMutableArray *data = [NSMutableArray new];
for (NSInteger i = 0; i < 6; i++) {
[data addObject:[[IGLayoutTestSection alloc] initWithInsets:UIEdgeInsetsMake(1, 1, 1, 1)
lineSpacing:0
interitemSpacing:0
headerHeight:0
footerHeight:0
items:@[
[[IGLayoutTestItem alloc] initWithSize:(CGSize) {136, 136}],
]]];
}
[self prepareWithData:data];
XCTAssertEqual(self.collectionView.contentSize.height, 276);
IGAssertEqualFrame([self cellForSection:0 item:0].frame, 1, 1, 136, 136);
IGAssertEqualFrame([self cellForSection:1 item:0].frame, 139, 1, 136, 136);
IGAssertEqualFrame([self cellForSection:2 item:0].frame, 277, 1, 136, 136);
IGAssertEqualFrame([self cellForSection:3 item:0].frame, 1, 139, 136, 136);
IGAssertEqualFrame([self cellForSection:4 item:0].frame, 139, 139, 136, 136);
IGAssertEqualFrame([self cellForSection:5 item:0].frame, 277, 139, 136, 136);
}
- (void)test_whenQueryingAttributes_withSectionOOB_thatReturnsNil {
[self setUpWithStickyHeaders:NO topInset:0 stretchToEdge:YES];
[self prepareWithData:@[
[[IGLayoutTestSection alloc] initWithInsets:UIEdgeInsetsZero
lineSpacing:0
interitemSpacing:0
headerHeight:0
footerHeight:0
items:@[
[[IGLayoutTestItem alloc] initWithSize:CGSizeMake(33, 33)],
[[IGLayoutTestItem alloc] initWithSize:CGSizeMake(65, 33)],
]],
]];
XCTAssertNil([self.layout layoutAttributesForItemAtIndexPath:genIndexPath(4, 0)]);
}
- (void)test_whenQueryingAttributes_withItemOOB_thatReturnsNil {
[self setUpWithStickyHeaders:NO topInset:0 stretchToEdge:YES];
[self prepareWithData:@[
[[IGLayoutTestSection alloc] initWithInsets:UIEdgeInsetsZero
lineSpacing:0
interitemSpacing:0
headerHeight:0
footerHeight:0
items:@[
[[IGLayoutTestItem alloc] initWithSize:CGSizeMake(33, 33)],
[[IGLayoutTestItem alloc] initWithSize:CGSizeMake(65, 33)],
]],
]];
XCTAssertNil([self.layout layoutAttributesForItemAtIndexPath:genIndexPath(0, 4)]);
}
- (void)test_whenQueryingSupplementaryAttributes_withSizeEmpty_thatReturnsNil {
[self setUpWithStickyHeaders:NO topInset:0 stretchToEdge:YES];
[self prepareWithData:@[
[[IGLayoutTestSection alloc] initWithInsets:UIEdgeInsetsZero
lineSpacing:0
interitemSpacing:0
headerHeight:0
footerHeight:0
items:@[
[[IGLayoutTestItem alloc] initWithSize:CGSizeMake(33, 33)],
]],
]];
XCTAssertNil([self.layout layoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionHeader atIndexPath:genIndexPath(0, 0)]);
XCTAssertNil([self.layout layoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionFooter atIndexPath:genIndexPath(0, 0)]);
}
- (void)test_whenUpdatingSizes_thatLayoutUpdates {
[self setUpWithStickyHeaders:NO topInset:0];
[self prepareWithData:@[
[[IGLayoutTestSection alloc] initWithInsets:UIEdgeInsetsZero
lineSpacing:0
interitemSpacing:0
headerHeight:0
footerHeight:0
items:@[
[[IGLayoutTestItem alloc] initWithSize:CGSizeMake(10, 10)],
[[IGLayoutTestItem alloc] initWithSize:CGSizeMake(10, 10)],
]],
]];
IGAssertEqualFrame([self cellForSection:0 item:0].frame, 0, 0, 10, 10);
IGAssertEqualFrame([self cellForSection:0 item:1].frame, 10, 0, 10, 10);
[self prepareWithData:@[
[[IGLayoutTestSection alloc] initWithInsets:UIEdgeInsetsZero
lineSpacing:0
interitemSpacing:0
headerHeight:0
footerHeight:0
items:@[
[[IGLayoutTestItem alloc] initWithSize:CGSizeMake(20, 20)],
[[IGLayoutTestItem alloc] initWithSize:CGSizeMake(20, 20)],
[[IGLayoutTestItem alloc] initWithSize:CGSizeMake(20, 20)],
]],
]];
IGAssertEqualFrame([self cellForSection:0 item:0].frame, 0, 0, 20, 20);
IGAssertEqualFrame([self cellForSection:0 item:1].frame, 20, 0, 20, 20);
IGAssertEqualFrame([self cellForSection:0 item:2].frame, 40, 0, 20, 20);
}
- (void)test_whenMarkingASectionAsUpdated_thatLayoutUpdates {
[self setUpWithStickyHeaders:NO topInset:0];
[self prepareWithData:@[
[[IGLayoutTestSection alloc] initWithInsets:UIEdgeInsetsZero
lineSpacing:0
interitemSpacing:0
headerHeight:0
footerHeight:0
items:@[
[[IGLayoutTestItem alloc] initWithSize:CGSizeMake(10, 10)],
[[IGLayoutTestItem alloc] initWithSize:CGSizeMake(10, 10)],
]],
]];
IGAssertEqualFrame([self cellForSection:0 item:0].frame, 0, 0, 10, 10);
IGAssertEqualFrame([self cellForSection:0 item:1].frame, 10, 0, 10, 10);
[self.layout didModifySection:1];
[self.layout prepareLayout];
IGAssertEqualFrame([self cellForSection:0 item:0].frame, 0, 0, 10, 10);
IGAssertEqualFrame([self cellForSection:0 item:1].frame, 10, 0, 10, 10);
}
#pragma mark - Internal debugging
- (void)test_withDelegateNameDebugger_thatReturnedNamesAreValid {
[self setUpWithStickyHeaders:NO topInset:0];
// Test with the regular delegate
XCTAssertTrue([[self.layout _classNameForDelegate:(id)self.collectionView.delegate
sectionIndex:0]
isEqualToString:@"IGLayoutTestDataSource"]);
// Test with a proxy providing a new adapter
IGListAdapter *adapter = [[IGListAdapter alloc] initWithUpdater:[IGListAdapterUpdater new] viewController:nil];
IGListAdapterProxy *proxy = [[IGListAdapterProxy alloc] initWithCollectionViewTarget:self.collectionView.delegate
scrollViewTarget:nil
interceptor:adapter];
XCTAssertNil([self.layout _classNameForDelegate:(id)proxy sectionIndex:0]);
// Test with a proxy with an invalid adapter
IGListAdapterProxy *invalidProxy = [[IGListAdapterProxy alloc] initWithCollectionViewTarget:self.collectionView.delegate
scrollViewTarget:nil
interceptor:(id)[NSObject new]];
XCTAssertNil([self.layout _classNameForDelegate:(id)invalidProxy sectionIndex:0]);
}
- (void)test_withSupplementalViewAttributes_thatOOBErrorsAreHandled {
[self setUpWithStickyHeaders:NO topInset:0];
XCTAssertNil([self.layout layoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionHeader
atIndexPath:[NSIndexPath indexPathForItem:10 inSection:10]]);
}
@end