mirror of
https://github.com/material-components/material-components-ios.git
synced 2026-02-20 08:27:32 +08:00
311 lines
14 KiB
Objective-C
311 lines
14 KiB
Objective-C
// Copyright 2017-present the Material Components for iOS authors. All Rights Reserved.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
#import <XCTest/XCTest.h>
|
|
#import "MDCCollectionViewFlowLayout.h"
|
|
|
|
@interface FakeUICollectionViewUpdateItem : UICollectionViewUpdateItem {
|
|
NSIndexPath *_indexPathBeforeUpdate;
|
|
NSIndexPath *_indexPathAfterUpdate;
|
|
UICollectionUpdateAction _updateAction;
|
|
}
|
|
@end
|
|
|
|
@implementation FakeUICollectionViewUpdateItem
|
|
|
|
- (void)setIndexPathBeforeUpdate:(NSIndexPath *)indexPath {
|
|
_indexPathBeforeUpdate = indexPath;
|
|
}
|
|
|
|
- (NSIndexPath *)indexPathBeforeUpdate {
|
|
return _indexPathBeforeUpdate;
|
|
}
|
|
|
|
- (void)setIndexPathAfterUpdate:(NSIndexPath *)indexPath {
|
|
_indexPathAfterUpdate = indexPath;
|
|
}
|
|
|
|
- (NSIndexPath *)indexPathAfterUpdate {
|
|
return _indexPathAfterUpdate;
|
|
}
|
|
|
|
- (void)setUpdateAction:(UICollectionUpdateAction)updateAction {
|
|
_updateAction = updateAction;
|
|
}
|
|
|
|
- (UICollectionUpdateAction)updateAction {
|
|
return _updateAction;
|
|
}
|
|
|
|
@end
|
|
|
|
@interface MDCCollectionViewFlowLayoutTests : XCTestCase <UICollectionViewDataSource>
|
|
|
|
@end
|
|
|
|
@implementation MDCCollectionViewFlowLayoutTests
|
|
|
|
- (void)testPrepareForCollectionViewUpdatesInsertSection {
|
|
if (@available(iOS 15, *)) {
|
|
} else if (@available(iOS 14.5, *)) {
|
|
// TODO(b/204249546): Evaluate why this test crashes on iOS 14.5.
|
|
return;
|
|
}
|
|
|
|
// Given
|
|
MDCCollectionViewFlowLayout *layout = [[MDCCollectionViewFlowLayout alloc] init];
|
|
|
|
UICollectionView *collectionView = [[UICollectionView alloc] initWithFrame:CGRectZero
|
|
collectionViewLayout:layout];
|
|
collectionView.dataSource = self;
|
|
NSMutableArray<UICollectionViewUpdateItem *> *updates = [NSMutableArray array];
|
|
FakeUICollectionViewUpdateItem *section1Update = [[FakeUICollectionViewUpdateItem alloc] init];
|
|
[section1Update setIndexPathBeforeUpdate:nil];
|
|
[section1Update setIndexPathAfterUpdate:[NSIndexPath indexPathForItem:NSNotFound inSection:1]];
|
|
section1Update.updateAction = UICollectionUpdateActionInsert;
|
|
[updates addObject:section1Update];
|
|
|
|
// When
|
|
[layout prepareForCollectionViewUpdates:[updates copy]];
|
|
|
|
// Then
|
|
UICollectionViewLayoutAttributes *section1Attributes = [layout
|
|
initialLayoutAttributesForAppearingItemAtIndexPath:[NSIndexPath indexPathForItem:NSNotFound
|
|
inSection:1]];
|
|
if (@available(iOS 15, *)) {
|
|
// TODO(b/201656993): Evaluate why this behavior is different on iOS 15+.
|
|
XCTAssertNil(section1Attributes);
|
|
} else {
|
|
XCTAssertNotNil(section1Attributes,
|
|
@"Section 1 has an insert so the attributes should be non-nil.");
|
|
}
|
|
|
|
XCTAssertEqual(0, section1Attributes.alpha);
|
|
XCTAssertTrue(CGRectEqualToRect(CGRectZero, section1Attributes.bounds),
|
|
@"The bounds should be the zero rect.\nReceived: %@",
|
|
NSStringFromCGRect(section1Attributes.bounds));
|
|
if (@available(iOS 15, *)) {
|
|
// TODO(b/201656993): Evaluate why this behavior is different on iOS 15+.
|
|
} else {
|
|
XCTAssertTrue(
|
|
CGAffineTransformEqualToTransform(CGAffineTransformIdentity, section1Attributes.transform),
|
|
@"The transform should be the transform because the attributes have zero-height "
|
|
@"bounds.\nIdentity: %@\nReceived: %@",
|
|
NSStringFromCGAffineTransform(CGAffineTransformIdentity),
|
|
NSStringFromCGAffineTransform(section1Attributes.transform));
|
|
}
|
|
|
|
UICollectionViewLayoutAttributes *section0Attributes = [layout
|
|
initialLayoutAttributesForAppearingItemAtIndexPath:[NSIndexPath indexPathForItem:NSNotFound
|
|
inSection:0]];
|
|
XCTAssertNil(section0Attributes, @"Section 0 has no inserts so the attributes should be nil.");
|
|
section1Attributes = [layout
|
|
finalLayoutAttributesForDisappearingItemAtIndexPath:[NSIndexPath indexPathForItem:NSNotFound
|
|
inSection:1]];
|
|
XCTAssertNil(section1Attributes);
|
|
section0Attributes = [layout
|
|
finalLayoutAttributesForDisappearingItemAtIndexPath:[NSIndexPath indexPathForItem:NSNotFound
|
|
inSection:0]];
|
|
XCTAssertNil(section0Attributes);
|
|
}
|
|
|
|
- (void)testPrepareForCollectionViewUpdatesInsertItem {
|
|
if (@available(iOS 15, *)) {
|
|
} else if (@available(iOS 14.5, *)) {
|
|
// TODO(b/204249546): Evaluate why this test crashes on iOS 14.5.
|
|
return;
|
|
}
|
|
|
|
// Given
|
|
MDCCollectionViewFlowLayout *layout = [[MDCCollectionViewFlowLayout alloc] init];
|
|
|
|
UICollectionView *collectionView = [[UICollectionView alloc] initWithFrame:CGRectZero
|
|
collectionViewLayout:layout];
|
|
collectionView.dataSource = self;
|
|
NSMutableArray<UICollectionViewUpdateItem *> *updates = [NSMutableArray array];
|
|
FakeUICollectionViewUpdateItem *section0Update = [[FakeUICollectionViewUpdateItem alloc] init];
|
|
[section0Update setIndexPathBeforeUpdate:nil];
|
|
[section0Update setIndexPathAfterUpdate:[NSIndexPath indexPathForItem:0 inSection:0]];
|
|
section0Update.updateAction = UICollectionUpdateActionInsert;
|
|
[updates addObject:section0Update];
|
|
|
|
// When
|
|
[layout prepareForCollectionViewUpdates:[updates copy]];
|
|
|
|
// Then
|
|
UICollectionViewLayoutAttributes *section1Attributes =
|
|
[layout initialLayoutAttributesForAppearingItemAtIndexPath:[NSIndexPath indexPathForItem:1
|
|
inSection:1]];
|
|
XCTAssertNotNil(section1Attributes,
|
|
@"Section 1 has an insert so the attributes should be non-nil.");
|
|
XCTAssertEqual(1, section1Attributes.alpha);
|
|
XCTAssertTrue(CGRectEqualToRect(CGRectZero, section1Attributes.bounds),
|
|
@"The bounds should be the zero rect.\nReceived: %@",
|
|
NSStringFromCGRect(section1Attributes.bounds));
|
|
XCTAssertTrue(
|
|
CGAffineTransformEqualToTransform(CGAffineTransformIdentity, section1Attributes.transform),
|
|
@"The transform should be the transform because the attributes have zero-height "
|
|
@"bounds.\nIdentity: %@\nReceived: %@",
|
|
NSStringFromCGAffineTransform(CGAffineTransformIdentity),
|
|
NSStringFromCGAffineTransform(section1Attributes.transform));
|
|
|
|
UICollectionViewLayoutAttributes *section0Attributes =
|
|
[layout initialLayoutAttributesForAppearingItemAtIndexPath:[NSIndexPath indexPathForItem:0
|
|
inSection:0]];
|
|
XCTAssertNotNil(section0Attributes,
|
|
@"Section 0 has an insert so the attributes should be non-nil.");
|
|
XCTAssertEqual(0, section0Attributes.alpha);
|
|
XCTAssertTrue(CGRectEqualToRect(CGRectZero, section0Attributes.bounds),
|
|
@"The bounds should be the zero rect.\nReceived: %@",
|
|
NSStringFromCGRect(section0Attributes.bounds));
|
|
XCTAssertTrue(
|
|
CGAffineTransformEqualToTransform(CGAffineTransformIdentity, section0Attributes.transform),
|
|
@"The transform should be the transform because the attributes have zero-height "
|
|
@"bounds.\nIdentity: %@\nReceived: %@",
|
|
NSStringFromCGAffineTransform(CGAffineTransformIdentity),
|
|
NSStringFromCGAffineTransform(section0Attributes.transform));
|
|
|
|
section1Attributes =
|
|
[layout finalLayoutAttributesForDisappearingItemAtIndexPath:[NSIndexPath indexPathForItem:0
|
|
inSection:1]];
|
|
XCTAssertNil(section1Attributes);
|
|
section0Attributes =
|
|
[layout finalLayoutAttributesForDisappearingItemAtIndexPath:[NSIndexPath indexPathForItem:0
|
|
inSection:0]];
|
|
XCTAssertNil(section0Attributes);
|
|
}
|
|
|
|
- (void)testPrepareForCollectionViewUpdatesDeleteSection {
|
|
if (@available(iOS 15, *)) {
|
|
} else if (@available(iOS 14.5, *)) {
|
|
// TODO(b/204249546): Evaluate why this test crashes on iOS 14.5.
|
|
return;
|
|
}
|
|
|
|
// Given
|
|
MDCCollectionViewFlowLayout *layout = [[MDCCollectionViewFlowLayout alloc] init];
|
|
UICollectionView *collectionView = [[UICollectionView alloc] initWithFrame:CGRectZero
|
|
collectionViewLayout:layout];
|
|
collectionView.dataSource = self;
|
|
NSMutableArray<UICollectionViewUpdateItem *> *updates = [NSMutableArray array];
|
|
FakeUICollectionViewUpdateItem *section1Update = [[FakeUICollectionViewUpdateItem alloc] init];
|
|
[section1Update setIndexPathBeforeUpdate:[NSIndexPath indexPathForItem:NSNotFound inSection:1]];
|
|
[section1Update setIndexPathAfterUpdate:nil];
|
|
section1Update.updateAction = UICollectionUpdateActionDelete;
|
|
[updates addObject:section1Update];
|
|
|
|
// When
|
|
[layout prepareForCollectionViewUpdates:[updates copy]];
|
|
|
|
// Then
|
|
UICollectionViewLayoutAttributes *section1Attributes = [layout
|
|
initialLayoutAttributesForAppearingItemAtIndexPath:[NSIndexPath indexPathForItem:NSNotFound
|
|
inSection:1]];
|
|
XCTAssertNil(section1Attributes, @"Section 1 has no inserts so the attributes should be nil.");
|
|
UICollectionViewLayoutAttributes *section0Attributes = [layout
|
|
initialLayoutAttributesForAppearingItemAtIndexPath:[NSIndexPath indexPathForItem:NSNotFound
|
|
inSection:0]];
|
|
XCTAssertNil(section0Attributes, @"Section 0 has no inserts so the attributes should be nil.");
|
|
section1Attributes = [layout
|
|
finalLayoutAttributesForDisappearingItemAtIndexPath:[NSIndexPath indexPathForItem:NSNotFound
|
|
inSection:1]];
|
|
XCTAssertNil(section1Attributes);
|
|
section0Attributes = [layout
|
|
finalLayoutAttributesForDisappearingItemAtIndexPath:[NSIndexPath indexPathForItem:NSNotFound
|
|
inSection:0]];
|
|
XCTAssertNil(section0Attributes);
|
|
}
|
|
|
|
- (void)testPrepareForCollectionViewUpdatesDeleteItem {
|
|
if (@available(iOS 15, *)) {
|
|
} else if (@available(iOS 14.5, *)) {
|
|
// TODO(b/204249546): Evaluate why this test crashes on iOS 14.5.
|
|
return;
|
|
}
|
|
|
|
// Given
|
|
MDCCollectionViewFlowLayout *layout = [[MDCCollectionViewFlowLayout alloc] init];
|
|
UICollectionView *collectionView = [[UICollectionView alloc] initWithFrame:CGRectZero
|
|
collectionViewLayout:layout];
|
|
collectionView.dataSource = self;
|
|
NSMutableArray<UICollectionViewUpdateItem *> *updates = [NSMutableArray array];
|
|
FakeUICollectionViewUpdateItem *section1Update = [[FakeUICollectionViewUpdateItem alloc] init];
|
|
[section1Update setIndexPathBeforeUpdate:[NSIndexPath indexPathForItem:1 inSection:1]];
|
|
[section1Update setIndexPathAfterUpdate:nil];
|
|
section1Update.updateAction = UICollectionUpdateActionDelete;
|
|
[updates addObject:section1Update];
|
|
|
|
// When
|
|
[layout prepareForCollectionViewUpdates:[updates copy]];
|
|
|
|
// Then
|
|
UICollectionViewLayoutAttributes *section1Attributes =
|
|
[layout initialLayoutAttributesForAppearingItemAtIndexPath:[NSIndexPath indexPathForItem:1
|
|
inSection:1]];
|
|
XCTAssertNotNil(section1Attributes,
|
|
@"Section 1 has a delete so the attributes should be non-nil.");
|
|
XCTAssertEqual(1, section1Attributes.alpha);
|
|
XCTAssertTrue(CGRectEqualToRect(CGRectZero, section1Attributes.bounds),
|
|
@"The bounds should be the zero rect.\nReceived: %@",
|
|
NSStringFromCGRect(section1Attributes.bounds));
|
|
XCTAssertTrue(
|
|
CGAffineTransformEqualToTransform(CGAffineTransformIdentity, section1Attributes.transform),
|
|
@"The transform should be the transform because the attributes have zero-height "
|
|
@"bounds.\nIdentity: %@\nReceived: %@",
|
|
NSStringFromCGAffineTransform(CGAffineTransformIdentity),
|
|
NSStringFromCGAffineTransform(section1Attributes.transform));
|
|
UICollectionViewLayoutAttributes *section0Attributes =
|
|
[layout initialLayoutAttributesForAppearingItemAtIndexPath:[NSIndexPath indexPathForItem:1
|
|
inSection:0]];
|
|
XCTAssertNotNil(section0Attributes,
|
|
@"Section 0 has a delete so the attributes should be non-nil.");
|
|
XCTAssertEqual(1, section0Attributes.alpha);
|
|
XCTAssertTrue(CGRectEqualToRect(CGRectZero, section0Attributes.bounds),
|
|
@"The bounds should be the zero rect.\nReceived: %@",
|
|
NSStringFromCGRect(section0Attributes.bounds));
|
|
XCTAssertTrue(
|
|
CGAffineTransformEqualToTransform(CGAffineTransformIdentity, section0Attributes.transform),
|
|
@"The transform should be the transform because the attributes have zero-height "
|
|
@"bounds.\nIdentity: %@\nReceived: %@",
|
|
NSStringFromCGAffineTransform(CGAffineTransformIdentity),
|
|
NSStringFromCGAffineTransform(section0Attributes.transform));
|
|
section1Attributes =
|
|
[layout finalLayoutAttributesForDisappearingItemAtIndexPath:[NSIndexPath indexPathForItem:1
|
|
inSection:1]];
|
|
XCTAssertNil(section1Attributes);
|
|
section0Attributes =
|
|
[layout finalLayoutAttributesForDisappearingItemAtIndexPath:[NSIndexPath indexPathForItem:1
|
|
inSection:0]];
|
|
XCTAssertNil(section0Attributes);
|
|
}
|
|
|
|
#pragma mark - <UICollectionViewDataSource>
|
|
|
|
// Never called in these tests
|
|
- (UICollectionViewCell *)collectionView:(UICollectionView *)cv
|
|
cellForItemAtIndexPath:(nonnull NSIndexPath *)indexPath {
|
|
return nil;
|
|
}
|
|
|
|
- (NSInteger)collectionView:(UICollectionView *)collectionView
|
|
numberOfItemsInSection:(NSInteger)section {
|
|
return 2;
|
|
}
|
|
|
|
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
|
|
return 2;
|
|
}
|
|
|
|
@end
|